diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 00000000000..df78cb33ddb --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,13 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "powershell": { + "version": "7.4.2", + "commands": [ + "pwsh" + ], + "rollForward": false + } + } +} \ No newline at end of file diff --git a/.editorconfig b/.editorconfig index dc501fa7b92..25222e51eb7 100644 --- a/.editorconfig +++ b/.editorconfig @@ -108,6 +108,8 @@ dotnet_diagnostic.IDE0250.severity = suggestion dotnet_diagnostic.IDE0260.severity = suggestion # Use nameof dotnet_diagnostic.IDE0280.severity = error +# Collection initialization can be simplified +dotnet_diagnostic.IDE0305.severity = silent csharp_style_var_when_type_is_apparent = true csharp_style_var_elsewhere = true diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/30-bug_report.md similarity index 93% rename from .github/ISSUE_TEMPLATE/bug_report.md rename to .github/ISSUE_TEMPLATE/30-bug_report.md index cfd2a875377..1ecbae46119 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/30-bug_report.md @@ -10,7 +10,6 @@ assignees: '' [//]: # "This description supports Markdown syntax. There's a cheatsheet here: https://guides.github.com/features/mastering-markdown/" [//]: # "These lines are comments, for letting you know what you should be writing. You can delete them or leave them in." [//]: # "Also, please don't waste your time writing until you've checked for similar Issues. Remember to check closed Issues too!" -[//]: # "One more thing: if you're on Linux, please comment on #1430 instead of opening an issue so we don't annoy the other devs." ### Summary [//]: # "Briefly describe what's broken. Include relevant details: loaded core, loaded rom's hash, open tools, running scripts... You can embed a screenshot if it's easier to show the bug, but if you need more than one please put them at the end." diff --git a/.github/ISSUE_TEMPLATE/core_port_request.md b/.github/ISSUE_TEMPLATE/70-core_port_request.md similarity index 100% rename from .github/ISSUE_TEMPLATE/core_port_request.md rename to .github/ISSUE_TEMPLATE/70-core_port_request.md diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index e4265f15ded..f7b4cbf3c35 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -3,9 +3,6 @@ contact_links: - name: "BEFORE OPENING AN ISSUE: Search for duplicates" url: "https://github.com/TASVideos/BizHawk/issues?q=is:issue+" about: "Use `is:issue ` to find open or closed issues that might be similar to your problem. (Clicking this option takes you back to the issue tracker index.)" - - name: "Report issues with the Linux port" - url: "https://github.com/TASVideos/BizHawk/issues/1430" - about: "Linux users: please comment here, on #1430, instead of opening a new issue." - name: "Chat with us on IRC" url: "https://matrix.to/#/#bizhawk:libera.chat" about: "Joins #bizhawk on Libera Chat with your browser. Please be patient as there isn't always somebody online." diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index aecf8c6d982..73fef2b9557 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -7,4 +7,4 @@ [//]: # "Apart from the mandatory license signature, these tasks are optional, but doing them could save reviewers some time and get the PR merged sooner." Check if completed: - [ ] I have run any relevant test suites -- [ ] I, the committer, have read the [licensing terms for contributors](https://github.com/TASEmulators/BizHawk/blob/master/contributing.md#copyrights-and-licensing) (last updated 2024-03-20) and am compliant +- [ ] I, the committer, have read the [licensing terms for contributors](https://github.com/TASEmulators/BizHawk/blob/master/contributing.md#copyrights-and-licensing) (last updated 2024-06-22) and am compliant diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000000..d8d5534f00e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,78 @@ +on: [push, pull_request, workflow_dispatch] +name: Build and test main solution + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + analyzer-build: + name: Build solution with analyzers + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install .NET 8 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: "8" + + - name: Debug build with analyzers + run: Dist/BuildDebug.sh -warnaserror -p:RunAnalyzersDuringBuild=true + + - name: Release build with analyzers + run: Dist/BuildRelease.sh -warnaserror -p:RunAnalyzersDuringBuild=true + + test: + name: Test + runs-on: ${{matrix.os.fullname}} + strategy: + fail-fast: false + matrix: + os: + - { prettyname: Windows, fullname: windows-latest } + - { prettyname: Linux, fullname: ubuntu-latest } + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install .NET 8 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: "8" + + - name: Test + run: dotnet test BizHawk.sln -c Release -p:ContinuousIntegrationBuild=true + shell: pwsh + + package: + name: Build and package output + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install .NET 8 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: "8" + + - name: Build solution + run: Dist/BuildRelease.sh + + - name: Package (Linux) + run: Dist/Package.sh + - name: Upload Linux dev build + uses: actions/upload-artifact@v4 + with: + name: BizHawk-dev-linux + path: packaged_output + + - name: Package (Windows) + run: Dist/Package.sh windows-x64 + - name: Upload Windows dev build + uses: actions/upload-artifact@v4 + with: + name: BizHawk-dev-windows + path: packaged_output diff --git a/.github/workflows/make.yml b/.github/workflows/make.yml new file mode 100644 index 00000000000..d97f56737f6 --- /dev/null +++ b/.github/workflows/make.yml @@ -0,0 +1,157 @@ +name: Build Emulation Cores + +on: + pull_request: + branches: [ "master" ] + paths: [ "waterbox/**" ] + push: + branches: [ "master" ] + paths: [ "waterbox/**" ] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + CC: clang-18 + +jobs: + + build-waterbox: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Installing clang 18 + run: wget https://apt.llvm.org/llvm.sh; + chmod u+x llvm.sh; + sudo ./llvm.sh 18; + clang-18 --version; + - name: Getting submodule(s) + working-directory: ./waterbox/ + run: git submodule update --init musl + - name: Building musl + working-directory: ./waterbox/musl + run: ./wbox_configure.sh; + ./wbox_build.sh; + - name: Building libcxx + working-directory: ./waterbox/libcxx + run: ./do-everything.sh + - name: Building nyma + working-directory: ./waterbox/nyma + run: ./build-and-install-zlib.sh + - name: Uploading compiled waterbox + uses: actions/upload-artifact@v4 + with: + name: compiled-waterbox + path: waterbox/sysroot + + build-waterboxed-cores: + runs-on: ubuntu-latest + needs: build-waterbox + steps: + - uses: actions/checkout@v4 + - name: Getting submodule(s) + working-directory: ./waterbox/ + run: git submodule update --init snes9x; + git submodule update --init melon/melonDS; + git submodule update --init nyma/mednafen; + git submodule update --init ares64/ares/thirdparty/angrylion-rdp; + git submodule update --init gpgx/Genesis-Plus-GX; + git submodule update --init ../submodules/sameboy/libsameboy; + git submodule update --init uae/libretro-uae; + - name: Download compiled waterbox + uses: actions/download-artifact@v4 + with: + name: compiled-waterbox + path: waterbox/sysroot + - name: Installing clang 18 + run: wget https://apt.llvm.org/llvm.sh; + chmod u+x llvm.sh; + sudo ./llvm.sh 18; + clang-18 --version; + - name: Giving execution permission to compiler + working-directory: ./waterbox/sysroot + run: chmod u+x bin/* + - name: Building cores + working-directory: ./waterbox/ + run: ./make-all-cores.sh install + - name: Upload waterbox cores + uses: actions/upload-artifact@v4 + with: + name: waterbox-cores + path: | + Assets/dll/ares64_interpreter.wbx.zst + Assets/dll/ares64_recompiler.wbx.zst + Assets/dll/bsnes.wbx.zst + Assets/dll/faust.wbx.zst + Assets/dll/gpgx.wbx.zst + Assets/dll/hyper.wbx.zst + Assets/dll/libsnes.wbx.zst + Assets/dll/melonDS.wbx.zst + Assets/dll/ngp.wbx.zst + Assets/dll/pcfx.wbx.zst + Assets/dll/picodrive.wbx.zst + Assets/dll/puae.wbx.zst + Assets/dll/shock.wbx.zst + Assets/dll/snes9x.wbx.zst + Assets/dll/ss.wbx.zst + Assets/dll/tic80.wbx.zst + Assets/dll/turbo.wbx.zst + Assets/dll/uzem.wbx.zst + Assets/dll/vb.wbx.zst + Assets/dll/virtualjaguar.wbx.zst + + build-mame: + runs-on: ubuntu-latest + needs: build-waterbox + steps: + - uses: actions/checkout@v4 + - name: Getting submodule(s) + working-directory: ./waterbox/ + run: git submodule update --init mame-arcade/mame + - name: Download compiled waterbox + uses: actions/download-artifact@v4 + with: + name: compiled-waterbox + path: waterbox/sysroot + - name: Installing clang 18 + run: wget https://apt.llvm.org/llvm.sh; + chmod u+x llvm.sh; + sudo ./llvm.sh 18; + clang-18 --version; + - name: Giving execution permission to compiler + working-directory: ./waterbox/sysroot + run: chmod u+x bin/* + - name: Build emulibc + working-directory: ./waterbox/emulibc + run: make -j4 + - name: Build libco + working-directory: ./waterbox/libco + run: make -j4 + - name: Building MAME + working-directory: ./waterbox/mame-arcade + run: make -j4 install + - name: Upload mame core + uses: actions/upload-artifact@v4 + with: + name: mame-core + path: | + Assets/dll/libmamearcade.wbx.zst + + build-quickernes: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Getting submodule(s) + working-directory: ./quicknes + run: git submodule update --recursive --init core + - name: Building QuickerNES core (Linux) + working-directory: ./quicknes/make + run: make -j4; make install + - name: Upload quicknes core + uses: actions/upload-artifact@v4 + with: + name: quicknes-core + path: | + Assets/dll/libquicknes.so diff --git a/.gitignore b/.gitignore index 451d48dd25c..9eb2979ed82 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ UpgradeLog.htm *.opendb /Dist/*.zip +/Dist/git_hooks/*.local.ps1 # mupen64plus-win32-deps is a submodule, so ignores should be in that repo /libmupen64plus/mupen64plus-win32-deps/SDL-1.2.14/docs diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b9f226cbdbb..02932b6d4b8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -201,8 +201,7 @@ run_tests: - job: build_asms_release artifacts: false script: - - Dist/BuildDebug.sh # populate output - - Dist/BuildTestRelease.sh -v normal + - Dist/BuildTestRelease.sh -v normal -p:TestProjTargetFrameworkOverride=net8.0 stage: test .disabled_job_sast: diff --git a/.gitmodules b/.gitmodules index ab074719fad..c4e67fcbd80 100644 --- a/.gitmodules +++ b/.gitmodules @@ -28,9 +28,6 @@ [submodule "submodules/gambatte"] path = submodules/gambatte url = https://github.com/pokemon-speedrunning/gambatte-core.git -[submodule "waterbox/llvm-project"] - path = waterbox/llvm-project - url = https://github.com/llvm/llvm-project.git [submodule "submodules/libdarm"] path = submodules/libdarm url = https://github.com/jbremer/darm.git @@ -81,3 +78,7 @@ path = waterbox/stella/core url = https://github.com/TASEmulators/stella.git branch = tasvideos-1 +[submodule "waterbox/uae/libretro-uae"] + path = waterbox/uae/libretro-uae + url = https://github.com/TASEmulators/libretro-uae.git + branch = wbx diff --git a/.global.editorconfig.ini b/.global.editorconfig.ini index 644864e0f78..9f7e7ba2ebd 100644 --- a/.global.editorconfig.ini +++ b/.global.editorconfig.ini @@ -14,6 +14,8 @@ dotnet_diagnostic.BHI1004.severity = error dotnet_diagnostic.BHI1005.severity = error # Do not discard local variables dotnet_diagnostic.BHI1006.severity = error +# Don't use target-typed new for throw expressions +dotnet_diagnostic.BHI1007.severity = suggestion # Don't call this.GetType() in sealed type, use typeof operator dotnet_diagnostic.BHI1100.severity = error # Don't call this.GetType(), use typeof operator (or replace subtype check with better encapsulation) @@ -22,6 +24,13 @@ dotnet_diagnostic.BHI1101.severity = error dotnet_diagnostic.BHI1102.severity = error # Don't call typeof(T).ToString(), use nameof operator or typeof(T).FullName dotnet_diagnostic.BHI1103.severity = error +# Don't use ^= (XOR-assign) for inverting the value of booleans +dotnet_diagnostic.BHI1104.severity = error +# Brackets of collection expression should be separated with spaces +dotnet_diagnostic.BHI1110.severity = warning +# Expression-bodied member should be flowed to next line correctly +dotnet_diagnostic.BHI1120.severity = silent + # Check result of IDictionary.TryGetValue, or discard it if default(T) is desired dotnet_diagnostic.BHI1200.severity = error # Call to FirstOrDefault when elements are of a value type; FirstOrNull may have been intended @@ -176,7 +185,7 @@ dotnet_diagnostic.MA0038.severity = silent # Do not write your own certificate validation method dotnet_diagnostic.MA0039.severity = error # Flow the cancellation token -dotnet_diagnostic.MA0040.severity = silent +dotnet_diagnostic.MA0040.severity = error # Make property static dotnet_diagnostic.MA0041.severity = silent # Do not use blocking calls in an async method @@ -184,7 +193,7 @@ dotnet_diagnostic.MA0042.severity = error # Use nameof operator in ArgumentException dotnet_diagnostic.MA0043.severity = error # Remove useless ToString call -dotnet_diagnostic.MA0044.severity = silent +dotnet_diagnostic.MA0044.severity = warning # Do not use blocking call in a sync method (need to make containing method async) dotnet_diagnostic.MA0045.severity = silent # Use EventHandler to declare events @@ -210,13 +219,13 @@ dotnet_diagnostic.MA0055.severity = silent # Do not call overridable members in constructor dotnet_diagnostic.MA0056.severity = silent # Class name should end with 'Attribute' -dotnet_diagnostic.MA0057.severity = silent +dotnet_diagnostic.MA0057.severity = error # Class name should end with 'Exception' dotnet_diagnostic.MA0058.severity = error # Class name should end with 'EventArgs' dotnet_diagnostic.MA0059.severity = silent # The value returned by Stream.Read/Stream.ReadAsync is not used -dotnet_diagnostic.MA0060.severity = silent +dotnet_diagnostic.MA0060.severity = error # Method overrides should not change parameter defaults dotnet_diagnostic.MA0061.severity = silent # Non-flags enums should not be marked with "FlagsAttribute" @@ -236,7 +245,7 @@ dotnet_diagnostic.MA0068.severity = error # Non-constant static fields should not be visible dotnet_diagnostic.MA0069.severity = silent # Obsolete attributes should include explanations -dotnet_diagnostic.MA0070.severity = silent +dotnet_diagnostic.MA0070.severity = warning # Avoid using redundant else dotnet_diagnostic.MA0071.severity = silent # Do not throw from a finally block @@ -252,7 +261,7 @@ dotnet_diagnostic.MA0076.severity = silent # A class that provides Equals(T) should implement IEquatable dotnet_diagnostic.MA0077.severity = error # Use 'Cast' instead of 'Select' to cast -dotnet_diagnostic.MA0078.severity = silent +dotnet_diagnostic.MA0078.severity = error # Flow the cancellation token using .WithCancellation() dotnet_diagnostic.MA0079.severity = error # Use a cancellation token using .WithCancellation() @@ -276,9 +285,9 @@ dotnet_diagnostic.MA0088.severity = error # Optimize string method usage dotnet_diagnostic.MA0089.severity = error # Remove empty else/finally block -dotnet_diagnostic.MA0090.severity = silent +dotnet_diagnostic.MA0090.severity = warning # Sender should be 'this' for instance events -dotnet_diagnostic.MA0091.severity = silent +dotnet_diagnostic.MA0091.severity = error # Sender should be 'null' for static events dotnet_diagnostic.MA0092.severity = error # EventArgs should not be null @@ -304,7 +313,7 @@ dotnet_diagnostic.MA0102.severity = silent # Use SequenceEqual instead of equality operator dotnet_diagnostic.MA0103.severity = error # Do not create a type with a name from the BCL -dotnet_diagnostic.MA0104.severity = silent +dotnet_diagnostic.MA0104.severity = error # Use the lambda parameters instead of using a closure dotnet_diagnostic.MA0105.severity = error # Avoid closure by using an overload with the 'factoryArgument' parameter @@ -317,6 +326,26 @@ dotnet_diagnostic.MA0108.severity = error dotnet_diagnostic.MA0109.severity = silent # Use the Regex source generator dotnet_diagnostic.MA0110.severity = error +# Use 'Count > 0' instead of 'Any()' +dotnet_diagnostic.MA0112.severity = silent +# Raw String contains an implicit end of line character (if you compile on Windows you may get CRLFs in string literals) +dotnet_diagnostic.MA0136.severity = warning +# Both if and else branch have identical code +dotnet_diagnostic.MA0140.severity = warning +# Use pattern matching instead of inequality operators for null check +dotnet_diagnostic.MA0141.severity = silent +# Use pattern matching instead of equality operators for null check +dotnet_diagnostic.MA0142.severity = silent +# Use pattern matching instead of equality operators for discrete value +dotnet_diagnostic.MA0148.severity = silent +# Use pattern matching instead of inequality operators for discrete value +dotnet_diagnostic.MA0149.severity = silent +# Do not use async void methods +dotnet_diagnostic.MA0155.severity = error +# Use 'Async' suffix when a method returns IAsyncEnumerable +dotnet_diagnostic.MA0156.severity = error +# Do not use 'Async' suffix when a method does not return IAsyncEnumerable +dotnet_diagnostic.MA0157.severity = error ## Menees.Analyzers rules @@ -344,6 +373,8 @@ dotnet_diagnostic.MEN013.severity = silent dotnet_diagnostic.MEN014.severity = warning # Use Preferred Terms dotnet_diagnostic.MEN015.severity = silent +# Use object-oriented methods instead of top-level statements +dotnet_diagnostic.MEN016.severity = silent ## StyleCop spacing rules @@ -515,7 +546,7 @@ dotnet_diagnostic.SA1503.severity = silent # Opening braces should not be followed by blank line dotnet_diagnostic.SA1505.severity = silent # Element documentation headers should not be followed by blank line -dotnet_diagnostic.SA1506.severity = silent +dotnet_diagnostic.SA1506.severity = warning # Code should not contain multiple blank lines in a row dotnet_diagnostic.SA1507.severity = silent # Closing braces should not be preceded by blank line @@ -529,13 +560,13 @@ dotnet_diagnostic.SA1512.severity = silent # Closing brace should be followed by blank line dotnet_diagnostic.SA1513.severity = silent # Element documentation header should be preceded by blank line -dotnet_diagnostic.SA1514.severity = silent +dotnet_diagnostic.SA1514.severity = warning # Single-line comment should be preceded by blank line dotnet_diagnostic.SA1515.severity = silent # Elements should be separated by blank line dotnet_diagnostic.SA1516.severity = silent # Code should not contain blank lines at start of file -dotnet_diagnostic.SA1517.severity = silent +dotnet_diagnostic.SA1517.severity = warning # Use line endings correctly at end of file dotnet_diagnostic.SA1518.severity = silent # Braces should not be omitted from multi-line child statement @@ -552,11 +583,11 @@ dotnet_diagnostic.SA1610.severity = silent # Element parameter documentation should match element parameters dotnet_diagnostic.SA1612.severity = silent # Element parameter documentation should have text -dotnet_diagnostic.SA1614.severity = silent +dotnet_diagnostic.SA1614.severity = warning # Element return value documentation should have text -dotnet_diagnostic.SA1616.severity = silent +dotnet_diagnostic.SA1616.severity = warning # Generic type parameter documentation should have text -dotnet_diagnostic.SA1622.severity = silent +dotnet_diagnostic.SA1622.severity = warning # Property summary documentation should match accessors dotnet_diagnostic.SA1623.severity = silent # Element documentation should not be copied and pasted diff --git a/Assets/EmuHawkMono.sh b/Assets/EmuHawkMono.sh index 13c50ea8669..0666196b79d 100755 --- a/Assets/EmuHawkMono.sh +++ b/Assets/EmuHawkMono.sh @@ -18,7 +18,6 @@ fi export LD_LIBRARY_PATH="$PWD/dll:$PWD:$libpath" export MONO_CRASH_NOFILE=1 export MONO_WINFORMS_XIM_STYLE=disabled # see https://bugzilla.xamarin.com/show_bug.cgi?id=28047#c9 -export BIZHAWK_INT_SYSLIB_PATH="$libpath" if [ "$1" = "--mono-no-redirect" ]; then # printf "(passing --mono-no-redirect is no longer necessary)\n" #TODO uncomment later shift diff --git a/Assets/Lua/Genesis/The Adventures of Batman and Robin.lua b/Assets/Lua/Genesis/The Adventures of Batman and Robin.lua new file mode 100644 index 00000000000..e1ab58912f7 --- /dev/null +++ b/Assets/Lua/Genesis/The Adventures of Batman and Robin.lua @@ -0,0 +1,430 @@ +-- The Adventures of Batman and Robin +-- 2013-2024, feos and r57shell + +-- GLOBALS -- +MsgTable = {} +MsgTime = 16 +MsgOffs = 24 +MsgCutoff = 60 +RNGcount = 0 +SpawnCount = 0 +SpawnDelay = 0 +SpawnX = 0 +SpawnY = 0 +Enemies = 0 +Items = 0 +Hearts = 0 + +-- SHORTCUTS -- +rb = memory.read_u8 +rbs = memory.read_s8 +rw = memory.read_u16_be +rws = memory.read_s16_be +rl = memory.read_u32_be +rls = memory.read_s32_be +rex = event.onmemoryexecute +getr= emu.getregister +box = gui.drawBox +text= gui.pixelText +line= gui.drawLine + +memory.usememorydomain("M68K BUS") +userdata.set("SpawnCount", 0) +userdata.set("SpawnOpac", 192) + +function ToSigned16(num) + if num > 32768 then + num = num - (2 * 32768) + return num + else return num + end +end + +function FitX(x, text) + local length = 0 + if text ~= nil then length = string.len(text)*5 end + if x < 0 then x = 0 + elseif x+length > 319 then x = 319-length end + return x +end + +function FitY(y) + if y < 0 then y = 0 + elseif y > 210 then y = 210 end + return y +end + +function GetCam() + xcam = rws(0xFFDFC4) + if rb(0xFFFFF6) == 50 then + ycam = rws(0xFFDFE0)-20 + else + ycam = 0 + end +end + +function EnemyPos(Base) + GetCam() + x1 = rws(Base + 0x12) - xcam + y1 = rws(Base + 0x14) - ycam + x2 = rws(Base + 0x16) - xcam + y2 = rws(Base + 0x18) - ycam + hp = rws(Base + 0x1E) +end + +function PlayerPos() + local sbase1 = rw(0xFFAD5C) + 0xFF0000 + local sbase2 = rw(0xFFADB6) + 0xFF0000 + p1speedx = rls(sbase1 + 0x18) / 0x10000 + p1speedy = rls(sbase1 + 0x1C) / 0x10000 + p2speedx = rls(sbase2 + 0x18) / 0x10000 + p2speedy = rls(sbase2 + 0x1C) / 0x10000 + LIFT = rw(0xFF9024) +end + +function HandleMsgTable(clear) + for i = 1, #MsgTable do + if clear then + MsgTable[i] = nil + end + if MsgTable[i] then + GetCam() + if MsgTable[i].y_ > MsgCutoff then + MsgY1 = 0 + MsgY2 = 6 + else + MsgY1 = 203 + MsgY2 = 203 + end + line(i * MsgOffs + 3, MsgY2, + MsgTable[i].x_ - xcam, MsgTable[i].y_, + 0xFF0000 + (MsgTable[i].timer_ << 28)) + text(i * MsgOffs , MsgY1, MsgTable[i].damage_, "red") + MsgTable[i].timer_ = MsgTable[i].timer_ - 1 + if MsgTable[i].timer_ <= 0 then + MsgTable[i] = nil + end + end + end +end + +function HandleDamage() + local damage = getr("M68K D0") & 0xFFFF + local base = getr("M68K A2") & 0xFFFFFF +-- print(string.format("%X", getr("M68K PC"))) + EnemyPos(base) + unit = { + timer_ = MsgTime, + damage_ = damage, + x_ = x1 + xcam, + y_ = y1 + } + for i = 1, 200 do + if MsgTable[i] == nil then + MsgTable[i] = unit + break + end + end +end + +function Collision() + GetCam() + local a0 = getr("M68K A0") & 0xFFFFFF + local a6 = getr("M68K A6") & 0xFFFFFF + local wx1 = ToSigned16(getr("M68K D4") & 0xFFFF) - xcam + local wy1 = ToSigned16(getr("M68K D5") & 0xFFFF) - ycam + local wx2 = ToSigned16(getr("M68K D6") & 0xFFFF) - xcam + local wy2 = ToSigned16(getr("M68K D7") & 0xFFFF) - ycam + local id = rw(a6 + 2) + local damage = rw(a6 + 0x12) +-- text(wx2 + 2, wy1 + 1, string.format("%X",a6)) + if damage == 0 then + damage = rw(a0 + 0x34) + end + if DamageHitbox then + box(wx1, wy1, wx2, wy2, 0xFFFF0000) + text(wx1 + 2, wy1 + 1, damage) + else + box(wx1, wy1, wx2, wy2, 0xFFFFFF00) + if id == 0x53B4 then Hearts = Hearts + 1 end + end +end + +function InRange(var, num1, num2) + if var >= num1 and var <= num2 + then return true + end +end + +function Item() + GetCam() + local a6 = getr("M68K A6") & 0xFFFFFF + local x = rw(a6 + 0x3E) - xcam + local y = rw(a6 + 0x42) + local code = rb(a6 + 0x19) + if InRange(code, 0, 1) then return + elseif InRange(code, 7, 19) then item = "Amo" -- ammo + elseif InRange(code, 21, 23) then item = "Cha" -- fast charge + elseif InRange(code, 24, 26) then item = "Bom" -- bomb + elseif InRange(code, 27, 29) then item = "Lif" -- life + elseif InRange(code, 30, 47) then item = "HiP" -- hearts + else item = tostring(code) + end + text(x-7, y, string.format("%s" , item ), "yellow") +-- text(x-7, y, string.format("\n%X", a6+0x19), "yellow") +end + +function Hitbox(address) + local i = 0 + local base = rw(address) + while (base ~= 0) do + base = base + 0xFF0000 + if rw(base + 2) == 0 then break end + EnemyPos(base) + if address == 0xFFDEB2 then + box(x1, y1, x2, y2, 0xFF00FF00) + elseif address == 0xFFDEBA then + box(x1, y1, x2, y2, 0xFF00FFFF) + text(FitX(x1, hp) + 2, FitY(y1) + 1, hp, 0xFFFF00FF) + -- if x2 < 0 then text(x1 + 2, y2 - 7, "x:" .. x1 ) end + -- if x1 >= 320 then text(x1 + 2, y2 - 7, "x:" .. x1 - 320) end + -- if y2 < 0 then text(x2 + 2, y2 - 7, "y:" .. y2 ) end + local offtext = "" + if x2 < 0 then offtext = offtext .. "x:" .. x1 end + if x1 >= 320 then offtext = offtext .. "x:" .. x1 - 320 end + if y2 < 0 then offtext = offtext .. "y:" .. y2 end + if y2 >= 224 then offtext = offtext .. "y:" .. y2 - 224 end + if offtext ~= "" then + text(FitX(x1, offtext), FitY(y1) - 7, offtext) + end + end + base = rw(base + 2) + i = i + 1 + if i > 400 then break end + end +end + +function Objects() + local level = rw(0xFFFFF5) + if level ~= 818 and level ~= 1026 then return end + Enemies = 0 + Items = 0 + GetCam() + local base = 0xFFAD54 + for i=0,100 do + local link = rw (base+ 6) + local ptr1 = rw (base+0x0A)+0xFF0000 + local ptr2 = rl (ptr1+0x2A) + local delay = rl(base+0x2E) >> 8 + local x = rws(base+0x3E) + local xsub = rb (base+0x40) + local y = rws(base+0x42) + local ysub = rb (base+0x44) + local hp = rw (base+0x52) + -- local code = rw (ptr2) + if base > 0 then + if ptr2 == 0x27DEE -- helicopter black + or ptr2 == 0x27F9C -- helicopter red + or ptr2 == 0x2804E -- plane black + or ptr2 == 0x28134 -- helicopter green + or ptr2 == 0x282B8 -- plane red + or ptr2 == 0x2860A -- missile + or ptr2 == 0x28DD2 -- helicopter red phase 1 + or ptr2 == 0x28E08 -- helicopter red phase 2 + then + Enemies = Enemies + 1 + elseif ptr2 == 0x13326 + or ptr2 == 0x13BDE + then + Items = Items + 1 + else + -- text(x - xcam, y - ycam, string.format("%X", ptr2), "green") + end + if delay > 0 and delay < 1000 then + SpawnDelay = delay + -- print(string.format("%X: %X", base+0x2E, delay)) + end + end + base = link + 0xFF0000 + local a5 = rl(base) + if a5 == 0x88BE then return end + end +end + +function Spawns() + local level = rw(0xFFFFF5) + if level ~= 818 and level ~= 1026 then return end + local base = getr("M68K A6") & 0xFFFFFF + local ptr1 = rw(base+0x0A) + 0xFF0000 + local ptr2 = rl(ptr1+0x2A) + local code = rw(ptr2) + local text = "" + SpawnX = rws(base+0x3E) - xcam + SpawnY = rws(base+0x42) - ycam + + if ptr2 == 0x3A6E2 then text = "HOMING" + elseif ptr2 == 0x3A5C6 then text = "SCROLLING" + elseif ptr2 == 0x3A81E then text = "LONG 1" + elseif ptr2 == 0x3A778 then text = "LONG 2" + else text = "UNKNOWN" + end + + if code ~= 0xAE6 -- drone + and code ~= 0xAF2 -- mini-missile + and code ~= 0x2384 -- item + then + userdata.set("SpawnOpac", 192) + userdata.set("SpawnCount", userdata.get("SpawnCount") + 1) + -- print(string.format("%02d - %X - %s", userdata.get("SpawnCount"), ptr2, text)) + end +end + +function CalculateDelay() + local d0 = getr("M68K D0") >> 8 + local d1 = getr("M68K D1") >> 8 + print(string.format("Random spawn delay: %d + %d", d1, d0)) +end + +function PredictItem(rng) + rng = rng & 0xFFFF + local a2 = 0x29B78 + local d0 = 0 + local carry = rw(a2) > rng + a2 = a2 + 2 + if carry then + a2 = a2 + 2 + while rw(a2) > rng do + a2 = a2 + 4 + end + a2 = a2 + 2 + end + a2 = a2 + rw(a2) + 2 + if a2 == 0x29BBA then a2 = 0 end + return rw(a2) & 0xFF +end + +function RNGroll(seed1, seed2) -- subroutine $995C + local d0 = seed1 + local d1 = seed2 + d1 = (d1 << 1) | (d1 >> 31) -- ROL.L #1,D1 + d1 = ((d1 & 0xFFFF) ~ d0) | (d1 & 0xFFFF0000) -- EOR.W D0,D1 + d1 = ((d1 & 0xFFFF) << 16) | (d1 >> 16) -- SWAP.W D1 + d0 = (d1 ~ d0) & 0xFFFF -- EOR.W D1,D0 + d0 = ((d0 << 1) & 0xFFFF) | ((d0 << 1) >> 16) -- ROL.W #1,D0 + d1 = ((d1 & 0xFFFF) ~ d0) | (d1 & 0xFFFF0000) -- EOR.W D0,D1 + d1 = ((d1 & 0xFFFF) << 16) | (d1 >> 16) -- SWAP.W D1 + d0 = ((d1 & 0xFFFF) ~ d0) -- EOR.W D1,D0 + return {(d0 & 0xFFFF), d1} +end + +function ItemPrediction() + local RNG1 = rw (0xFFF5FC) + local RNG2 = rl (0xFFF5FE) + local RNG = RNGroll(RNG1, RNG2) + local RNG = RNGroll(RNG[1], RNG[2]) + local item = PredictItem(RNG[1]) + gui.text(0, 170, string.format("%2X", item),"yellow") +end + +function Main() + local color0 = "yellow" + local color1 = "yellow" + local color2 = "yellow" + local base1 = 0xFFAD54 + local base2 = 0xFFADAE +-- local hp1 = rw (0xFFF654) +-- local life1 = rw (0xFFF644) + local level = rw (0xFFFFF5) + local X1 = rw (base1 + 0x3E) + local X1sub = rb (base1 + 0x40) + local Y1 = rws(base1 + 0x42) + local Y1sub = rb (base1 + 0x44) + local X2 = rw (base2 + 0x3E) + local X2sub = rb (base2 + 0x40) + local Y2 = rws(base2 + 0x42) + local Y2sub = rb (base2 + 0x44) + local RNG1 = rw (0xFFF5FC) +-- local RNG2 = rl (0xFFF5FE) + local Weapon1 = rb (0xFFF67B) + local Weapon2 = rb (0xFFF6BB) + local Charge1 = (rw(0xFFF658) - 0x2800) / -0x80 + local Charge2 = (rw(0xFFF698) - 0x2800) / -0x80 + local ScreenLock = rw (0xFFDFC0) + if Charge1 <= 0 then Charge1 = 0 color1 = "red" end + if Charge2 <= 0 then Charge2 = 0 color2 = "red" end + if RNGcount > 1 then color0 = "red" end + HandleMsgTable() + PlayerPos() + Objects() + if level == 818 or level == 1026 then + line(30, 42, SpawnX, SpawnY, 0x00FF00 + (userdata.get("SpawnOpac") << 24)) + text( 0, 35, string.format("Obj: %d", userdata.get("SpawnCount")), 0xFF00FF00) + text( 0, 49, string.format("%d %d %s", Enemies, Items, Hearts/2)) + if SpawnDelay > 0 and SpawnDelay < 1000 then + text(0, 42, string.format("Del: %d", SpawnDelay), "yellow") + end + end + text( 1, 217, string.format("RNG:%X" , RNG1)) + text( 40, 217, string.format("Lock:%d" , ScreenLock)) + text( 81, 210, string.format("Pos: %d.%d\nSpd: %.5f", X1, X1sub, p1speedx)) + text(137, 210, string.format("/ %d.%d\n/ %.5f" , Y1, Y1sub, p1speedy)) + text( 80, 22, string.format("%2.0f" , Charge1), color1) +-- text(235, 20, string.format("%2.0f" , Charge2), color2) + text( 34, 217, string.format("%d" , RNGcount), color0) + text(180, 217, string.format("%2d" , Weapon1+1), "yellow") +-- text(300, 217, string.format("%2d" , Weapon2+1), "yellow") +-- text(203, 210, string.format("Pos: %d.%d\nSpd: %.5f", X2, X2sub, p2speedx), 0xFF00FF00) +-- text(260, 210, string.format("/ %d.%d\n/ %.5f" , Y2, Y2sub, p2speedy), 0xFF00FF00) + Hitbox(0xFFDEB2) + Hitbox(0xFFDEBA) + RNGcount = 0 + + if rb(0xFF4633) == 5 then + text(143,3,string.format(" %2d", LIFT), 0xFFFF00FF, clear) + end + + DER = rw(0xFFAEA0) + text(135,3,string.format(" %2d", DER), 0xFFFF00FF, clear) + +-- emu.frameadvance() +-- gui.clearGraphics() +end + +event.onframeend(function() + local spawnOpac = userdata.get("SpawnOpac") - 4 + if spawnOpac < 0 then spawnOpac = 0 end + userdata.set("SpawnOpac", spawnOpac) + Main() +end) + +event.onframestart(function() + SpawnDelay1 = 0 + SpawnDelay2 = 0 + Hearts = 0 + ItemPrediction() +end) + +event.onloadstate(function() + Enemies = 0 + Items = 0 + Hearts = 0 + SpawnCount = 0 + return HandleMsgTable(1) +end) + +rex(function() DamageHitbox = false end , 0x375A, "DamageHitbox-") +rex(function() DamageHitbox = true end , 0x375E, "DamageHitbox+") +rex(function() DamageHitbox = false end , 0x3768, "DamageHitbox-") +rex(function() DamageHitbox = true end , 0x376C, "DamageHitbox+") +rex(function() DamageHitbox = false end , 0x65C4, "DamageHitbox-") +rex(function() DamageHitbox = true end , 0x65C8, "DamageHitbox+") +rex(CalculateDelay , 0x6ADE, "Delay") +rex(function() RNGcount = RNGcount + 1 end, 0x995C, "RNGcount++") +rex(Item , 0x4738, "Item") +rex(Item , 0x4534, "Item") +rex(Spawns , 0x8DE6, "Spawns") +rex(Spawns , 0x8DCE, "Spawns") +rex(Collision , 0x8C9A, "Collision") +rex(HandleDamage , 0x1085A, "MeeleeDamage") +rex(HandleDamage , 0x10CBA, "WeaponDamage") +rex(HandleDamage , 0x10CC4, "WeaponDamage") \ No newline at end of file diff --git a/Assets/Shaders/BizHawk/BizScanlines.glsl b/Assets/Shaders/BizHawk/BizScanlines.glsl index b96461956ef..2423cb9d6b2 100644 --- a/Assets/Shaders/BizHawk/BizScanlines.glsl +++ b/Assets/Shaders/BizHawk/BizScanlines.glsl @@ -1,13 +1,15 @@ -//Yeah, I'm sorry this uses really old non-generic attributes -//that's just how old this code is; support on ancient graphics cards is helpful - #ifdef VERTEX -uniform mat4 modelViewProj; +uniform mat4 MVPMatrix; + +in vec4 VertexCoord; +in vec2 TexCoord; + +out vec2 vTex; void main() { - gl_Position = modelViewProj * gl_Vertex; - gl_TexCoord[0] = gl_MultiTexCoord0; + gl_Position = MVPMatrix * VertexCoord; + vTex = TexCoord; } #endif @@ -17,15 +19,16 @@ void main() uniform float uIntensity; uniform sampler2D s_p; -uniform vec2 output_size; +in vec2 vTex; + +out vec4 FragColor; void main() { - vec2 vTex = gl_TexCoord[0].xy; - vec4 temp = texture2D(s_p,vTex); + vec4 temp = texture(s_p,vTex); vec2 wpos = gl_FragCoord.xy; if(floor(wpos.y/2.0) != floor(wpos.y)/2.0) temp.rgb *= uIntensity; - gl_FragColor = temp; + FragColor = temp; } #endif \ No newline at end of file diff --git a/Assets/Shaders/BizHawk/BizScanlines.hlsl b/Assets/Shaders/BizHawk/BizScanlines.hlsl index 96979e7b29b..64bf9f9f9ca 100644 --- a/Assets/Shaders/BizHawk/BizScanlines.hlsl +++ b/Assets/Shaders/BizHawk/BizScanlines.hlsl @@ -1,23 +1,25 @@ void main_vertex ( - float4 position : POSITION, - float2 tex : TEXCOORD0, + float4 position : POSITION, + float2 tex : TEXCOORD0, - uniform float4x4 modelViewProj, + uniform float4x4 modelViewProj, - out float4 oPosition : POSITION, - out float2 oTexcoord : TEXCOORD0 + out float4 oPosition : POSITION, + out float2 oTex0 : TEXCOORD0, + out float oTex1 : TEXCOORD1 ) { oPosition = mul(modelViewProj, position); - oTexcoord = tex; + oTex0 = tex; + oTex1 = position.y; } uniform float uIntensity; -float4 main_fragment (in float2 texcoord : TEXCOORD0, in float2 wpos : VPOS, uniform sampler2D s_p : TEXUNIT0) : COLOR +float4 main_fragment (in float4 vpos : POSITION, in float2 tex0 : TEXCOORD0, in float tex1 : TEXCOORD1, uniform sampler2D s_p : TEXUNIT0) : COLOR { - float4 temp = tex2D(s_p,texcoord); - if(floor(wpos.y/2) != floor(wpos.y)/2) temp.rgb *= uIntensity; + float4 temp = tex2D(s_p, tex0); + if (floor(tex1 / 2) != floor(tex1) / 2) temp.rgb *= uIntensity; return temp; } diff --git a/Assets/Shaders/BizHawk/bicubic-fast.hlsl b/Assets/Shaders/BizHawk/bicubic-fast.hlsl index db7b9fbbb49..f04219da303 100644 --- a/Assets/Shaders/BizHawk/bicubic-fast.hlsl +++ b/Assets/Shaders/BizHawk/bicubic-fast.hlsl @@ -46,13 +46,14 @@ struct input float2 video_size; float2 texture_size; float2 output_size; - float frame_count; - float frame_direction; + float frame_count; + float frame_direction; float frame_rotation; }; -struct out_vertex { +struct out_vertex +{ float2 texCoord : TEXCOORD0; float4 t1 : TEXCOORD1; float4 t2 : TEXCOORD2; @@ -65,26 +66,29 @@ struct out_vertex { }; /* VERTEX_SHADER */ -out_vertex main_vertex +void main_vertex ( float4 position : POSITION, - out float4 oPosition : POSITION, float2 texCoord1 : TEXCOORD0, - uniform float4x4 modelViewProj, - uniform input IN + uniform float4x4 modelViewProj, + uniform input IN, + + out float4 oPosition : POSITION, + out out_vertex oVAR ) { float2 ps = float2(1.0/IN.texture_size.x, 1.0/IN.texture_size.y); float dx = ps.x; float dy = ps.y; - oPosition = mul(modelViewProj, position); + oPosition = mul(modelViewProj, position); // This line fix a bug in ATI cards. float2 tex = texCoord1 + float2(0.0000001, 0.0000001); - out_vertex OUT = { + out_vertex OUT = + { tex, float4(tex,tex) + float4( -dx, -dy, 0.0, -dy), float4(tex,tex) + float4( dx, -dy, 2.0*dx, -dy), @@ -96,57 +100,54 @@ out_vertex main_vertex tex + float2(2.0*dx, 2.0*dy) }; - - return OUT; + oVAR = OUT; } -float4 main_fragment(in out_vertex VAR, uniform sampler2D s_p : TEXUNIT0, uniform input IN) : COLOR +float4 main_fragment(in float4 vpos : POSITION, in out_vertex VAR, uniform sampler2D s_p : TEXUNIT0, uniform input IN) : COLOR { - - float2 fp = frac(VAR.texCoord*IN.texture_size); - float3 c00 = tex2D(s_p, VAR.t1.xy).xyz; - float3 c01 = tex2D(s_p, VAR.t1.zw).xyz; - float3 c02 = tex2D(s_p, VAR.t2.xy).xyz; - float3 c03 = tex2D(s_p, VAR.t2.zw).xyz; - float3 c10 = tex2D(s_p, VAR.t3.xy).xyz; - float3 c11 = tex2D(s_p, VAR.texCoord).xyz; - float3 c12 = tex2D(s_p, VAR.t3.zw).xyz; - float3 c13 = tex2D(s_p, VAR.t4.xy).xyz; - float3 c20 = tex2D(s_p, VAR.t4.zw).xyz; - float3 c21 = tex2D(s_p, VAR.t5.xy).xyz; - float3 c22 = tex2D(s_p, VAR.t5.zw).xyz; - float3 c23 = tex2D(s_p, VAR.t6.xy).xyz; - float3 c30 = tex2D(s_p, VAR.t6.zw).xyz; - float3 c31 = tex2D(s_p, VAR.t7.xy).xyz; - float3 c32 = tex2D(s_p, VAR.t7.zw).xyz; - float3 c33 = tex2D(s_p, VAR.t8.xy).xyz; - - - float4x4 red_matrix = float4x4(c00.x, c01.x, c02.x, c03.x, - c10.x, c11.x, c12.x, c13.x, - c20.x, c21.x, c22.x, c23.x, - c30.x, c31.x, c32.x, c33.x); - - float4x4 green_matrix = float4x4(c00.y, c01.y, c02.y, c03.y, - c10.y, c11.y, c12.y, c13.y, - c20.y, c21.y, c22.y, c23.y, - c30.y, c31.y, c32.y, c33.y); - - float4x4 blue_matrix = float4x4(c00.z, c01.z, c02.z, c03.z, - c10.z, c11.z, c12.z, c13.z, - c20.z, c21.z, c22.z, c23.z, - c30.z, c31.z, c32.z, c33.z); - - - float4x1 invX_Px = mul(invX, float4x1(fp.x*fp.x*fp.x, fp.x*fp.x, fp.x, 1.0)); - float1x4 Py_invY = mul(float1x4(fp.y*fp.y*fp.y, fp.y*fp.y, fp.y, 1.0), invY); - - - float red = mul(Py_invY, mul( red_matrix, invX_Px)); - float green = mul(Py_invY, mul(green_matrix, invX_Px)); - float blue = mul(Py_invY, mul( blue_matrix, invX_Px)); - - return float4(red, green, blue, 1.0); + float2 fp = frac(VAR.texCoord*IN.texture_size); + float3 c00 = tex2D(s_p, VAR.t1.xy).xyz; + float3 c01 = tex2D(s_p, VAR.t1.zw).xyz; + float3 c02 = tex2D(s_p, VAR.t2.xy).xyz; + float3 c03 = tex2D(s_p, VAR.t2.zw).xyz; + float3 c10 = tex2D(s_p, VAR.t3.xy).xyz; + float3 c11 = tex2D(s_p, VAR.texCoord).xyz; + float3 c12 = tex2D(s_p, VAR.t3.zw).xyz; + float3 c13 = tex2D(s_p, VAR.t4.xy).xyz; + float3 c20 = tex2D(s_p, VAR.t4.zw).xyz; + float3 c21 = tex2D(s_p, VAR.t5.xy).xyz; + float3 c22 = tex2D(s_p, VAR.t5.zw).xyz; + float3 c23 = tex2D(s_p, VAR.t6.xy).xyz; + float3 c30 = tex2D(s_p, VAR.t6.zw).xyz; + float3 c31 = tex2D(s_p, VAR.t7.xy).xyz; + float3 c32 = tex2D(s_p, VAR.t7.zw).xyz; + float3 c33 = tex2D(s_p, VAR.t8.xy).xyz; + + + float4x4 red_matrix = float4x4(c00.x, c01.x, c02.x, c03.x, + c10.x, c11.x, c12.x, c13.x, + c20.x, c21.x, c22.x, c23.x, + c30.x, c31.x, c32.x, c33.x); + + float4x4 green_matrix = float4x4(c00.y, c01.y, c02.y, c03.y, + c10.y, c11.y, c12.y, c13.y, + c20.y, c21.y, c22.y, c23.y, + c30.y, c31.y, c32.y, c33.y); + + float4x4 blue_matrix = float4x4(c00.z, c01.z, c02.z, c03.z, + c10.z, c11.z, c12.z, c13.z, + c20.z, c21.z, c22.z, c23.z, + c30.z, c31.z, c32.z, c33.z); + + + float4x1 invX_Px = mul(invX, float4x1(fp.x*fp.x*fp.x, fp.x*fp.x, fp.x, 1.0)); + float1x4 Py_invY = mul(float1x4(fp.y*fp.y*fp.y, fp.y*fp.y, fp.y, 1.0), invY); + + + float red = mul(Py_invY, mul( red_matrix, invX_Px)); + float green = mul(Py_invY, mul(green_matrix, invX_Px)); + float blue = mul(Py_invY, mul( blue_matrix, invX_Px)); + + return float4(red, green, blue, 1.0); } - diff --git a/Assets/Shaders/BizHawk/bicubic-normal.hlsl b/Assets/Shaders/BizHawk/bicubic-normal.hlsl index 81aa180deb5..34ab1c165e6 100644 --- a/Assets/Shaders/BizHawk/bicubic-normal.hlsl +++ b/Assets/Shaders/BizHawk/bicubic-normal.hlsl @@ -33,35 +33,32 @@ http://www.gnu.org/copyleft/gpl.html /* Default Vertex shader */ void main_vertex ( - float4 position : POSITION, - //float4 color : COLOR, - float2 texCoord1 : TEXCOORD0, + float4 position : POSITION, + float2 texCoord1 : TEXCOORD0, - uniform float4x4 modelViewProj, + uniform float4x4 modelViewProj, - out float4 oPosition : POSITION, - //out float4 oColor : COLOR, - out float2 otexCoord : TEXCOORD - ) + out float4 oPosition : POSITION, + out float2 otexCoord : TEXCOORD +) { - oPosition = mul(modelViewProj, position); - //oColor = color; - otexCoord = texCoord1; + oPosition = mul(modelViewProj, position); + otexCoord = texCoord1; } struct output { - float4 color : COLOR; + float4 color : COLOR; }; struct input { - float2 video_size; - float2 texture_size; - float2 output_size; - float frame_count; - float frame_direction; - float frame_rotation; + float2 video_size; + float2 texture_size; + float2 output_size; + float frame_count; + float frame_direction; + float frame_rotation; }; float weight(float x) @@ -123,11 +120,11 @@ float3 line_run(float ypos, float4 xpos, float4 linetaps, uniform sampler2D s_p) } -output main_fragment (float2 tex : TEXCOORD0, uniform input IN, uniform sampler2D s_p : TEXUNIT0) +output main_fragment (in float4 vpos : POSITION, float2 tex : TEXCOORD0, uniform input IN, uniform sampler2D s_p : TEXUNIT0) { - float2 stepxy = float2(1.0/IN.texture_size.x, 1.0/IN.texture_size.y); - float2 pos = tex.xy + stepxy * 0.5; - float2 f = frac(pos / stepxy); + float2 stepxy = float2(1.0/IN.texture_size.x, 1.0/IN.texture_size.y); + float2 pos = tex.xy + stepxy * 0.5; + float2 f = frac(pos / stepxy); float4 linetaps = weight4(1.0 - f.x); float4 columntaps = weight4(1.0 - f.y); @@ -140,12 +137,11 @@ output main_fragment (float2 tex : TEXCOORD0, uniform input IN, uniform sampler2 float4 xpos = float4(xystart.x, xystart.x + stepxy.x, xystart.x + stepxy.x * 2.0, xystart.x + stepxy.x * 3.0); -// final sum and weight normalization - output OUT; - OUT.color = float4(line_run(xystart.y , xpos, linetaps, s_p) * columntaps.r + - line_run(xystart.y + stepxy.y , xpos, linetaps, s_p) * columntaps.g + - line_run(xystart.y + stepxy.y * 2.0, xpos, linetaps, s_p) * columntaps.b + - line_run(xystart.y + stepxy.y * 3.0, xpos, linetaps, s_p) * columntaps.a,1); + // final sum and weight normalization + output OUT; + OUT.color = float4(line_run(xystart.y , xpos, linetaps, s_p) * columntaps.r + + line_run(xystart.y + stepxy.y , xpos, linetaps, s_p) * columntaps.g + + line_run(xystart.y + stepxy.y * 2.0, xpos, linetaps, s_p) * columntaps.b + + line_run(xystart.y + stepxy.y * 3.0, xpos, linetaps, s_p) * columntaps.a,1); return OUT; } - diff --git a/Assets/Shaders/BizHawk/bsnes-gamma.glsl b/Assets/Shaders/BizHawk/bsnes-gamma.glsl index 085eb8a3b9c..24b9e7c4a52 100644 --- a/Assets/Shaders/BizHawk/bsnes-gamma.glsl +++ b/Assets/Shaders/BizHawk/bsnes-gamma.glsl @@ -8,12 +8,17 @@ // Shader that replicates gamma-ramp of bSNES/Higan. #ifdef VERTEX -uniform mat4 modelViewProj; +uniform mat4 MVPMatrix; + +in vec4 VertexCoord; +in vec2 TexCoord; + +out vec2 vTex; void main() { - gl_Position = modelViewProj * gl_Vertex; - gl_TexCoord[0] = gl_MultiTexCoord0; + gl_Position = MVPMatrix * VertexCoord; + vTex = TexCoord; } #endif @@ -22,6 +27,10 @@ void main() uniform sampler2D s_p; +in vec2 vTex; + +out vec4 FragColor; + // Tweakables. #define saturation 1.0 #define gamma 1.5 @@ -38,10 +47,10 @@ vec3 grayscale(vec3 col) void main() { - vec3 res = texture2D(s_p,gl_TexCoord[0].xy).xyz; + vec3 res = texture(s_p,vTex).xyz; res = mix(grayscale(res), res, saturation); // Apply saturation res = pow(res, vec3(gamma,gamma,gamma)); // Apply gamma - gl_FragColor = vec4(clamp(res * luminance,0.0,1.0), 1.0); + FragColor = vec4(clamp(res * luminance,0.0,1.0), 1.0); } #endif diff --git a/Assets/Shaders/BizHawk/bsnes-gamma.hlsl b/Assets/Shaders/BizHawk/bsnes-gamma.hlsl index 03f2c3bfe6b..6abcf6ce2f9 100644 --- a/Assets/Shaders/BizHawk/bsnes-gamma.hlsl +++ b/Assets/Shaders/BizHawk/bsnes-gamma.hlsl @@ -9,16 +9,17 @@ void main_vertex ( - float4 position : POSITION, - out float4 oPosition : POSITION, - uniform float4x4 modelViewProj, + float4 position : POSITION, + float2 tex : TEXCOORD, - float2 tex : TEXCOORD, - out float2 oTex : TEXCOORD + uniform float4x4 modelViewProj, + + out float4 oPosition : POSITION, + out float2 oTex : TEXCOORD ) { - oPosition = mul(modelViewProj, position); - oTex = tex; + oPosition = mul(modelViewProj, position); + oTex = tex; } // Tweakables. @@ -34,7 +35,7 @@ float3 grayscale(float3 col) return float3(v,v,v); } -float4 main_fragment(float2 tex : TEXCOORD, uniform sampler2D s0 : TEXUNIT0) : COLOR +float4 main_fragment(in float4 vpos : POSITION, in float2 tex : TEXCOORD, uniform sampler2D s0 : TEXUNIT0) : COLOR { float3 res = tex2D(s0, tex).xyz; res = lerp(grayscale(res), res, saturation); // Apply saturation diff --git a/Assets/Shaders/BizHawk/hq2x.glsl b/Assets/Shaders/BizHawk/hq2x.glsl index 6a3d1652bd3..5bb54b62bcd 100644 --- a/Assets/Shaders/BizHawk/hq2x.glsl +++ b/Assets/Shaders/BizHawk/hq2x.glsl @@ -1,6 +1,3 @@ -//Yeah, I'm sorry this uses really old non-generic attributes -//that's just how old this code is; support on ancient graphics cards is helpful - uniform struct { vec2 video_size; @@ -9,26 +6,31 @@ uniform struct } IN; #ifdef VERTEX -uniform mat4 modelViewProj; +uniform mat4 MVPMatrix; + +in vec4 VertexCoord; +in vec2 TexCoord; + +out vec2 coords[9]; void main() { - gl_Position = modelViewProj * gl_Vertex; + gl_Position = MVPMatrix * VertexCoord; vec2 texsize = IN.texture_size; vec2 delta = 0.5 / texsize; float dx = delta.x; float dy = delta.y; - gl_TexCoord[0].xy = gl_MultiTexCoord0.xy + vec2(-dx, -dy); - gl_TexCoord[1].xy = gl_MultiTexCoord0.xy + vec2(-dx, 0.0); - gl_TexCoord[2].xy = gl_MultiTexCoord0.xy + vec2(-dx, dy); - gl_TexCoord[3].xy = gl_MultiTexCoord0.xy + vec2(0.0, -dy); - gl_TexCoord[4].xy = gl_MultiTexCoord0.xy + vec2(0.0, 0.0); - gl_TexCoord[5].xy = gl_MultiTexCoord0.xy + vec2(0.0, dy); - gl_TexCoord[6].xy = gl_MultiTexCoord0.xy + vec2(dx, -dy); - gl_TexCoord[7].xy = gl_MultiTexCoord0.xy + vec2(dx, 0); - gl_TexCoord[7].zw = gl_MultiTexCoord0.xy + vec2(dx, dy); + coords[0] = TexCoord + vec2(-dx, -dy); + coords[1] = TexCoord + vec2(-dx, 0.0); + coords[2] = TexCoord + vec2(-dx, dy); + coords[3] = TexCoord + vec2(0.0, -dy); + coords[4] = TexCoord + vec2(0.0, 0.0); + coords[5] = TexCoord + vec2(0.0, dy); + coords[6] = TexCoord + vec2(dx, -dy); + coords[7] = TexCoord + vec2(dx, 0); + coords[8] = TexCoord + vec2(dx, dy); } #endif @@ -37,6 +39,10 @@ void main() uniform sampler2D s_p; +in vec2 coords[9]; + +out vec4 FragColor; + const float mx = 0.325; // start smoothing wt. const float k = -0.250; // wt. decrease factor const float max_w = 0.25; // max filter weigth @@ -45,15 +51,15 @@ const float lum_add = 0.25; // effects smoothing void main() { - vec3 c00 = texture2D(s_p, gl_TexCoord[0].xy).xyz; - vec3 c01 = texture2D(s_p, gl_TexCoord[1].xy).xyz; - vec3 c02 = texture2D(s_p, gl_TexCoord[2].xy).xyz; - vec3 c10 = texture2D(s_p, gl_TexCoord[3].xy).xyz; - vec3 c11 = texture2D(s_p, gl_TexCoord[4].xy).xyz; - vec3 c12 = texture2D(s_p, gl_TexCoord[5].xy).xyz; - vec3 c20 = texture2D(s_p, gl_TexCoord[6].xy).xyz; - vec3 c21 = texture2D(s_p, gl_TexCoord[7].xy).xyz; - vec3 c22 = texture2D(s_p, gl_TexCoord[7].zw).xyz; + vec3 c00 = texture(s_p, coords[0]).xyz; + vec3 c01 = texture(s_p, coords[1]).xyz; + vec3 c02 = texture(s_p, coords[2]).xyz; + vec3 c10 = texture(s_p, coords[3]).xyz; + vec3 c11 = texture(s_p, coords[4]).xyz; + vec3 c12 = texture(s_p, coords[5]).xyz; + vec3 c20 = texture(s_p, coords[6]).xyz; + vec3 c21 = texture(s_p, coords[7]).xyz; + vec3 c22 = texture(s_p, coords[8]).xyz; vec3 dt = vec3(1.0,1.0,1.0); float md1 = dot(abs(c00 - c22), dt); @@ -78,7 +84,7 @@ void main() w3 = clamp(lc1 * dot(abs(c11 - c12), dt) + mx, min_w, max_w); w4 = clamp(lc2 * dot(abs(c11 - c01), dt) + mx, min_w, max_w); - gl_FragColor = vec4(w1 * c10 + w2 * c21 + w3 * c12 + w4 * c01 + (1.0 - w1 - w2 - w3 - w4) * c11, 1.0); + FragColor = vec4(w1 * c10 + w2 * c21 + w3 * c12 + w4 * c01 + (1.0 - w1 - w2 - w3 - w4) * c11, 1.0); } #endif \ No newline at end of file diff --git a/Assets/Shaders/BizHawk/hq2x.hlsl b/Assets/Shaders/BizHawk/hq2x.hlsl index 98b7e6f640a..c8ce877a96a 100644 --- a/Assets/Shaders/BizHawk/hq2x.hlsl +++ b/Assets/Shaders/BizHawk/hq2x.hlsl @@ -1,51 +1,51 @@ struct tex_coords { - float2 c00 : TEXCOORD0; - float2 c01 : TEXCOORD1; - float2 c02 : TEXCOORD2; - float2 c10 : TEXCOORD3; - float2 c11 : TEXCOORD4; - float2 c12 : TEXCOORD5; - float2 c20 : TEXCOORD6; - float2 c21 : TEXCOORD7; - float2 c22 : COLOR0; + float2 c00 : TEXCOORD0; + float2 c01 : TEXCOORD1; + float2 c02 : TEXCOORD2; + float2 c10 : TEXCOORD3; + float2 c11 : TEXCOORD4; + float2 c12 : TEXCOORD5; + float2 c20 : TEXCOORD6; + float2 c21 : TEXCOORD7; + float2 c22 : COLOR0; }; struct input { - float2 video_size; - float2 texture_size; - float2 output_size; + float2 video_size; + float2 texture_size; + float2 output_size; }; void main_vertex ( - float4 position : POSITION, - out float4 oPosition : POSITION, - uniform float4x4 modelViewProj, + float4 position : POSITION, + float2 tex : TEXCOORD0, - float2 tex : TEXCOORD0, + uniform float4x4 modelViewProj, + uniform input IN, - uniform input IN, - out tex_coords coords + out float4 oPosition : POSITION, + out tex_coords coords ) { - oPosition = mul(modelViewProj, position); + oPosition = mul(modelViewProj, position); - float2 texsize = IN.texture_size; - float2 delta = 0.5 / texsize; - float dx = delta.x; - float dy = delta.y; + float2 texsize = IN.texture_size; + float2 delta = 0.5 / texsize; + float dx = delta.x; + float dy = delta.y; - coords.c00 = tex + float2(-dx, -dy); - coords.c01 = tex + float2(-dx, 0.0); - coords.c02 = tex + float2(-dx, dy); - coords.c10 = tex + float2(0.0, -dy); - coords.c11 = tex + float2(0.0, 0.0); - coords.c12 = tex + float2(0.0, dy); - coords.c20 = tex + float2(dx, -dy); - coords.c21 = tex + float2(dx, 0); - coords.c22 = tex + float2(dx, dy); + coords.c00 = tex + float2(-dx, -dy); + coords.c01 = tex + float2(-dx, 0.0); + coords.c02 = tex + float2(-dx, dy); + coords.c10 = tex + float2(0.0, -dy); + coords.c11 = tex + float2(0.0, 0.0); + coords.c12 = tex + float2(0.0, dy); + coords.c20 = tex + float2(dx, -dy); + coords.c21 = tex + float2(dx, 0); + coords.c22 = tex + float2(dx, dy); } static const float mx = 0.325; // start smoothing wt. @@ -54,40 +54,40 @@ static const float max_w = 0.25; // max filter weigth static const float min_w = -0.05; // min filter weigth static const float lum_add = 0.25; // effects smoothing -float4 main_fragment (in tex_coords co, uniform sampler2D s_p : TEXUNIT0) : COLOR +float4 main_fragment (in float4 vpos : POSITION, in tex_coords co, uniform sampler2D s_p : TEXUNIT0) : COLOR { - float3 c00 = tex2D(s_p, co.c00).xyz; - float3 c01 = tex2D(s_p, co.c01).xyz; - float3 c02 = tex2D(s_p, co.c02).xyz; - float3 c10 = tex2D(s_p, co.c10).xyz; - float3 c11 = tex2D(s_p, co.c11).xyz; - float3 c12 = tex2D(s_p, co.c12).xyz; - float3 c20 = tex2D(s_p, co.c20).xyz; - float3 c21 = tex2D(s_p, co.c21).xyz; - float3 c22 = tex2D(s_p, co.c22).xyz; - float3 dt = float3(1.0,1.0,1.0); + float3 c00 = tex2D(s_p, co.c00).xyz; + float3 c01 = tex2D(s_p, co.c01).xyz; + float3 c02 = tex2D(s_p, co.c02).xyz; + float3 c10 = tex2D(s_p, co.c10).xyz; + float3 c11 = tex2D(s_p, co.c11).xyz; + float3 c12 = tex2D(s_p, co.c12).xyz; + float3 c20 = tex2D(s_p, co.c20).xyz; + float3 c21 = tex2D(s_p, co.c21).xyz; + float3 c22 = tex2D(s_p, co.c22).xyz; + float3 dt = float3(1.0,1.0,1.0); - float md1 = dot(abs(c00 - c22), dt); - float md2 = dot(abs(c02 - c20), dt); + float md1 = dot(abs(c00 - c22), dt); + float md2 = dot(abs(c02 - c20), dt); - float w1 = dot(abs(c22 - c11), dt) * md2; - float w2 = dot(abs(c02 - c11), dt) * md1; - float w3 = dot(abs(c00 - c11), dt) * md2; - float w4 = dot(abs(c20 - c11), dt) * md1; + float w1 = dot(abs(c22 - c11), dt) * md2; + float w2 = dot(abs(c02 - c11), dt) * md1; + float w3 = dot(abs(c00 - c11), dt) * md2; + float w4 = dot(abs(c20 - c11), dt) * md1; - float t1 = w1 + w3; - float t2 = w2 + w4; - float ww = max(t1, t2) + 0.0001; + float t1 = w1 + w3; + float t2 = w2 + w4; + float ww = max(t1, t2) + 0.0001; - c11 = (w1 * c00 + w2 * c20 + w3 * c22 + w4 * c02 + ww * c11) / (t1 + t2 + ww); + c11 = (w1 * c00 + w2 * c20 + w3 * c22 + w4 * c02 + ww * c11) / (t1 + t2 + ww); - float lc1 = k / (0.12 * dot(c10 + c12 + c11, dt) + lum_add); - float lc2 = k / (0.12 * dot(c01 + c21 + c11, dt) + lum_add); + float lc1 = k / (0.12 * dot(c10 + c12 + c11, dt) + lum_add); + float lc2 = k / (0.12 * dot(c01 + c21 + c11, dt) + lum_add); - w1 = clamp(lc1 * dot(abs(c11 - c10), dt) + mx, min_w, max_w); - w2 = clamp(lc2 * dot(abs(c11 - c21), dt) + mx, min_w, max_w); - w3 = clamp(lc1 * dot(abs(c11 - c12), dt) + mx, min_w, max_w); - w4 = clamp(lc2 * dot(abs(c11 - c01), dt) + mx, min_w, max_w); + w1 = clamp(lc1 * dot(abs(c11 - c10), dt) + mx, min_w, max_w); + w2 = clamp(lc2 * dot(abs(c11 - c21), dt) + mx, min_w, max_w); + w3 = clamp(lc1 * dot(abs(c11 - c12), dt) + mx, min_w, max_w); + w4 = clamp(lc2 * dot(abs(c11 - c01), dt) + mx, min_w, max_w); - return float4(w1 * c10 + w2 * c21 + w3 * c12 + w4 * c01 + (1.0 - w1 - w2 - w3 - w4) * c11, 1.0); + return float4(w1 * c10 + w2 * c21 + w3 * c12 + w4 * c01 + (1.0 - w1 - w2 - w3 - w4) * c11, 1.0); } diff --git a/Assets/Shaders/retroizer/retroizer.glsl b/Assets/Shaders/retroizer/retroizer.glsl index 224305d4752..f6c985df2d1 100644 --- a/Assets/Shaders/retroizer/retroizer.glsl +++ b/Assets/Shaders/retroizer/retroizer.glsl @@ -6,17 +6,19 @@ //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// -//Yeah, I'm sorry this uses really old non-generic attributes -//that's just how old this code is; support on ancient graphics cards is helpful - #ifdef VERTEX -uniform mat4 modelViewProj; +uniform mat4 MVPMatrix; + +in vec4 VertexCoord; +in vec2 TexCoord; + +out vec2 vTexcoord; void main() { - gl_Position = modelViewProj * gl_Vertex; - gl_TexCoord[0] = gl_MultiTexCoord0; + gl_Position = MVPMatrix * VertexCoord; + vTexcoord = TexCoord; } #endif //VERTEX @@ -34,6 +36,10 @@ uniform float Time; uniform sampler2D s_p; +in vec2 vTexcoord; + +out vec4 FragColor; + float saturate(float x) { return max(0, min(1, x)); @@ -122,13 +128,13 @@ float expow(vec2 value, float exponent) { // MultiSampling for ghosting effect vec3 GhostSample(vec2 t, float latency) { - vec3 Out = texture2D(s_p,t).rgb; + vec3 Out = texture(s_p,t).rgb; float Weight = 1.0f; vec2 Direction = vec2(-latency,0.0f); for(int i=1; i < GhostNumSamples; i++) { float curweight = pow(1.0f-(float(i)/GhostNumSamples),1.0f/SignalLatencyAttenuation); - Out += GhostLatencyIntensity * curweight * texture2D(s_p,saturate(t+(1.0f-curweight)*Direction)).xyz; + Out += GhostLatencyIntensity * curweight * texture(s_p,saturate(t+(1.0f-curweight)*Direction)).xyz; Weight += GhostLatencyIntensity * curweight; } return Out/Weight; @@ -142,7 +148,7 @@ vec3 Bloom(vec2 t, vec2 r) { for(int i = 0; i < 5; i++) { vec2 offset = vec2(BloomPositions[i],BloomPositions[j]) / r; - Out += texture2D(s_p, t + offset).rgb * BloomWeights[i*5+j]; + Out += texture(s_p, t + offset).rgb * BloomWeights[i*5+j]; } return pow(Out, vec3(BloomExponent,BloomExponent,BloomExponent)) * BloomIntensity; } @@ -160,7 +166,7 @@ vec3 TVEffect(vec2 in_Position, vec2 FakeResolution, float Time) { #ifdef GHOST_SAMPLING vec3 latencyweight = vec3(0.0f,0.0f,0.0f); for(int i=1; i < GhostNumSamples; i++) { - latencyweight += texture2D(s_p, ScreenPos + vec2(1.0f/FakeResolution.x,0.0f)).xyz; + latencyweight += texture(s_p, ScreenPos + vec2(1.0f/FakeResolution.x,0.0f)).xyz; } vec3 LatencyRGB = SignalLatencyRGB * (1.0-(latencyweight/GhostNumSamples)); @@ -168,9 +174,9 @@ vec3 TVEffect(vec2 in_Position, vec2 FakeResolution, float Time) { vec3 SMP_Green = GhostSample((ScreenPos) + ((vec2(ColorFringeIntensity,0.0f))/FakeResolution),LatencyRGB.y).xyz; vec3 SMP_Blue = GhostSample((ScreenPos) + ((vec2(ColorFringeIntensity*2.0f,0.0f))/FakeResolution),LatencyRGB.z).xyz; #else - vec3 SMP_Red = texture2D(s_p, (ScreenPos)).xyz; - vec3 SMP_Green = texture2D(s_p, (ScreenPos) + ((vec2(ColorFringeIntensity,0.0f))/FakeResolution)).xyz; - vec3 SMP_Blue = texture2D(s_p, (ScreenPos) + ((vec2(ColorFringeIntensity*2.0f,0.0f))/FakeResolution)).xyz; + vec3 SMP_Red = texture(s_p, (ScreenPos)).xyz; + vec3 SMP_Green = texture(s_p, (ScreenPos) + ((vec2(ColorFringeIntensity,0.0f))/FakeResolution)).xyz; + vec3 SMP_Blue = texture(s_p, (ScreenPos) + ((vec2(ColorFringeIntensity*2.0f,0.0f))/FakeResolution)).xyz; #endif #ifdef BLOOM @@ -203,7 +209,7 @@ vec3 TVEffect(vec2 in_Position, vec2 FakeResolution, float Time) { ); // Non-Pixelated Image - vec3 ImageRGB = texture2D(s_p, ScreenPos).xyz; + vec3 ImageRGB = texture(s_p, ScreenPos).xyz; return mix(ImageRGB, PixelRGB, FakePixelEffectBlend) * mask; } @@ -211,8 +217,8 @@ vec3 TVEffect(vec2 in_Position, vec2 FakeResolution, float Time) { void main() { vec4 color = vec4(1.0f,1.0f,1.0f,1.0f); - color.xyz = TVEffect(gl_TexCoord[0].xy, IN.texture_size, Time); - gl_FragColor = color; + color.xyz = TVEffect(vTexcoord, IN.texture_size, Time); + FragColor = color; } #endif \ No newline at end of file diff --git a/Assets/Shaders/retroizer/retroizer.hlsl b/Assets/Shaders/retroizer/retroizer.hlsl index c0757707440..9db88a67e6a 100644 --- a/Assets/Shaders/retroizer/retroizer.hlsl +++ b/Assets/Shaders/retroizer/retroizer.hlsl @@ -1,4 +1,3 @@ - //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// //// @@ -9,26 +8,25 @@ struct input { - float2 video_size; - float2 texture_size; - float2 output_size; - + float2 video_size; + float2 texture_size; + float2 output_size; }; void main_vertex ( - float4 position : POSITION, - out float4 oPosition : POSITION, - uniform float4x4 modelViewProj, + float4 position : POSITION, + float2 tex : TEXCOORD0, - float2 tex : TEXCOORD, + uniform float4x4 modelViewProj, + uniform input IN, - uniform input IN, - out float2 oTexcoord : TEXCOORD, - out float2 oFakeResolution : TEXCOORD1 + out float4 oPosition : POSITION, + out float2 oTexcoord : TEXCOORD0, + out float2 oFakeResolution : TEXCOORD1 ) { - oPosition = mul(modelViewProj, position); + oPosition = mul(modelViewProj, position); oTexcoord = tex; oFakeResolution = IN.texture_size; } @@ -39,105 +37,112 @@ void main_vertex //// EFFECT CONSTANTS : TWEAK THEM! //// - // Size of the border effect - static const float2 OverscanMaskHardness = {12.0f ,12.0f }; - // Attenuation of the border effect - static const float OverscanMaskPower = 4.0f; - // Intensity of the border effect - static const float OverscanIntensity = 0.96f; - - // Intensity of the TV Corners (round-ness) deformation - static const float TVDeformInstensity = 0.02f; - + // Size of the border effect + static const float2 OverscanMaskHardness = {12.0f ,12.0f }; + // Attenuation of the border effect + static const float OverscanMaskPower = 4.0f; + // Intensity of the border effect + static const float OverscanIntensity = 0.96f; + + // Intensity of the TV Corners (round-ness) deformation + static const float TVDeformInstensity = 0.02f; + + + // How much R, G and B are offset : default is -0.333 pixels in fake-pixel-space + static const float ColorFringeIntensity = -0.666; + // How much luminosity is output by a fake-pixel + static const float FakePixelMaskGain = 0.75f; + // How much luminosity is output between fake-pixels (adds to the fake-pixel value) + static const float FakePixelMaskOffset = 0.55f; + // How sharp will appear the pixels (Horizontal Sharpness, Vertical Sharpness A.K.A Scanlines) + static const float2 FakePixelMaskPower = {0.150f ,2.0f }; + // Scanline Off Sync (Slides one line out of two) + static const float ScanlineOffSync = 0.25; + // Base Brightness + static const float BaseBrightness = 0.55f; - // How much R, G and B are offset : default is -0.333 pixels in fake-pixel-space - static const float ColorFringeIntensity = -0.666; - // How much luminosity is output by a fake-pixel - static const float FakePixelMaskGain = 0.75f; - // How much luminosity is output between fake-pixels (adds to the fake-pixel value) - static const float FakePixelMaskOffset = 0.55f; - // How sharp will appear the pixels (Horizontal Sharpness, Vertical Sharpness A.K.A Scanlines) - static const float2 FakePixelMaskPower = {0.150f ,2.0f }; - // Scanline Off Sync (Slides one line out of two) - static const float ScanlineOffSync = 0.25; - // Base Brightness - static const float BaseBrightness = 0.55f; - - // How much the Fake-Pixel effect is Active (0.0 = normal image, 1.0 = full FakePixel Effect) - static const float FakePixelEffectBlend = 0.95f; - - // Ghost Sampling : enable define to activate - #define GHOST_SAMPLING; - - static const float GhostLatencyIntensity = 0.03f; - // Number of samples (higer is slower) - static const int GhostNumSamples = 32; - // Latency of the RGB Signal (per-signal, in screen width percentage) - static const float3 SignalLatencyRGB = {0.184f,0.08f,0.0624f}; - // Attenuation of the ghosting latency - static const float SignalLatencyAttenuation = 1.0f; - - // Bloom : enable define to activate - #define BLOOM; - static const float BloomIntensity = 0.75f; - static const float BloomExponent = 1.00f; - static const float BloomWeights[5][5] = - { - {0.003765, 0.015019, 0.023792, 0.015019, 0.003765}, - {0.015019, 0.059912, 0.094907, 0.059912, 0.015019}, - {0.023792, 0.094907, 0.150342, 0.094907, 0.023792}, - {0.015019, 0.059912, 0.094907, 0.059912, 0.015019}, - {0.003765, 0.015019, 0.023792, 0.015019, 0.003765} - }; - static const float BloomPositions[5] = { -2, -1, 0 , 1 , 2}; - + // How much the Fake-Pixel effect is Active (0.0 = normal image, 1.0 = full FakePixel Effect) + static const float FakePixelEffectBlend = 0.95f; + + // Ghost Sampling : enable define to activate + #define GHOST_SAMPLING; + + static const float GhostLatencyIntensity = 0.03f; + // Number of samples (higer is slower) + static const int GhostNumSamples = 32; + // Latency of the RGB Signal (per-signal, in screen width percentage) + static const float3 SignalLatencyRGB = {0.184f,0.08f,0.0624f}; + // Attenuation of the ghosting latency + static const float SignalLatencyAttenuation = 1.0f; + + // Bloom : enable define to activate + #define BLOOM; + + static const float BloomIntensity = 0.75f; + static const float BloomExponent = 1.00f; + static const float BloomWeights[5][5] = + { + {0.003765, 0.015019, 0.023792, 0.015019, 0.003765}, + {0.015019, 0.059912, 0.094907, 0.059912, 0.015019}, + {0.023792, 0.094907, 0.150342, 0.094907, 0.023792}, + {0.015019, 0.059912, 0.094907, 0.059912, 0.015019}, + {0.003765, 0.015019, 0.023792, 0.015019, 0.003765} + }; + static const float BloomPositions[5] = { -2, -1, 0 , 1 , 2}; //// //// //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// -float expow(float value, float exponent) { +float expow(float value, float exponent) +{ return lerp(1.0f,pow(value,max(exponent,1.0f)),saturate(exponent)); } //the code that calls expow() carefully builds float2 for some reason and calls this only to have it implicitly thrown away (which is a warning) //so this was added to get rid of the warning -float expow(float2 value, float2 exponent) { +float expow(float2 value, float2 exponent) +{ return lerp(1.0f,pow(value,max(exponent,1.0f)),saturate(exponent)).x; } // MultiSampling for ghosting effect -float3 GhostSample(sampler2D s, float2 t, float latency) { - +float3 GhostSample(sampler2D s, float2 t, float latency) +{ float3 Out = tex2D(s,t); float Weight = 1.0f; float2 Direction = float2(-latency,0.0f); - for(int i=1; i < GhostNumSamples; i++) { - float curweight = pow(1.0f-((float)i/GhostNumSamples),1.0f/SignalLatencyAttenuation); + for(int i=1; i < GhostNumSamples; i++) + { + float curweight = pow(1.0f-((float)i/GhostNumSamples),1.0f/SignalLatencyAttenuation); Out += GhostLatencyIntensity * curweight * tex2D(s,saturate(t+(1.0f-curweight)*Direction)).xyz; Weight += GhostLatencyIntensity * curweight; } + return Out/Weight; } // MultiSampling for ghosting effect -float3 Bloom(sampler2D s, float2 t, float2 r) { - +float3 Bloom(sampler2D s, float2 t, float2 r) +{ float3 Out = float3(0,0,0); for(int j = 0; j < 5; j++) + { for(int i = 0; i < 5; i++) { float2 offset = float2(BloomPositions[i],BloomPositions[j]) / r; Out += tex2D(s, t + offset).rgb * BloomWeights[i][j]; } + } + return pow(Out, BloomExponent) * BloomIntensity; } // Compositing of the TV Emulation -float3 TVEffect(float2 in_Position, float2 FakeResolution, sampler2D Texture, float Time) { - +float3 TVEffect(float2 in_Position, float2 FakeResolution, sampler2D Texture, float Time) +{ // TV Deformation float2 ScreenPos = in_Position + dot(in_Position-0.5f,in_Position-0.5f)*(in_Position-0.5f)* TVDeformInstensity; @@ -147,9 +152,11 @@ float3 TVEffect(float2 in_Position, float2 FakeResolution, sampler2D Texture, fl // Sampling 3 Images biased to simulate TV RGB Offset #ifdef GHOST_SAMPLING float3 latencyweight = float3(0.0f,0.0f,0.0f); - for(int i=1; i < GhostNumSamples; i++) { + for(int i=1; i < GhostNumSamples; i++) + { latencyweight += tex2D(Texture, ScreenPos + float2(1.0f/FakeResolution.x,0.0f)).xyz; - } + } + float3 LatencyRGB = SignalLatencyRGB * (1.0-(latencyweight/GhostNumSamples)); float3 SMP_Red = GhostSample(Texture, (ScreenPos),LatencyRGB.x).xyz; @@ -183,24 +190,22 @@ float3 TVEffect(float2 in_Position, float2 FakeResolution, sampler2D Texture, fl float PixelMaskB = expow(saturate(4*frac(ScreenPos.x*FakeResolution.x+float2(ColorFringeIntensity*2.0f,0.0f))*(1.0f-frac(ScreenPos.x*FakeResolution.x+float2(ColorFringeIntensity*2.0f,0.0f)))),FakePixelMaskPower.x); float PixelMaskScanline = pow(saturate(4*frac(ScreenPos.y*FakeResolution.y)*(1.0f-frac(ScreenPos.y*FakeResolution.y))),FakePixelMaskPower.y); - float3 PixelRGB = float3 ( - ((PixelMaskR*PixelMaskScanline * FakePixelMaskGain)+FakePixelMaskOffset) * SMP_Red.x , - ((PixelMaskG*PixelMaskScanline * FakePixelMaskGain)+FakePixelMaskOffset) * SMP_Green.y , - ((PixelMaskB*PixelMaskScanline * FakePixelMaskGain)+FakePixelMaskOffset) * SMP_Blue.z - ); + float3 PixelRGB = float3(((PixelMaskR*PixelMaskScanline * FakePixelMaskGain)+FakePixelMaskOffset) * SMP_Red.x, + ((PixelMaskG*PixelMaskScanline * FakePixelMaskGain)+FakePixelMaskOffset) * SMP_Green.y, + ((PixelMaskB*PixelMaskScanline * FakePixelMaskGain)+FakePixelMaskOffset) * SMP_Blue.z); // Non-Pixelated Image float3 ImageRGB = tex2D(Texture, ScreenPos).xyz; return lerp(ImageRGB, PixelRGB, FakePixelEffectBlend) * mask; - + //return float3(PixelMaskR*PixelMaskScanline,PixelMaskG*PixelMaskScanline,PixelMaskB*PixelMaskScanline); } float4 main_fragment ( - in float2 TexCoord : TEXCOORD, + in float4 vpos : POSITION, + in float2 TexCoord : TEXCOORD0, in float2 FakeResolution : TEXCOORD1, - in float2 wpos : WPOS, uniform sampler2D s_p : TEXUNIT0, uniform float Time ) : COLOR diff --git a/Assets/dll/7z.dll b/Assets/dll/7z.dll deleted file mode 100644 index be29515b795..00000000000 Binary files a/Assets/dll/7z.dll and /dev/null differ diff --git a/Assets/dll/SDL2.dll b/Assets/dll/SDL2.dll index dc2a30a0c0d..6b2458fe5ae 100644 Binary files a/Assets/dll/SDL2.dll and b/Assets/dll/SDL2.dll differ diff --git a/Assets/dll/ares64_interpreter.wbx.zst b/Assets/dll/ares64_interpreter.wbx.zst index 14a13797ff8..8a13eada308 100644 Binary files a/Assets/dll/ares64_interpreter.wbx.zst and b/Assets/dll/ares64_interpreter.wbx.zst differ diff --git a/Assets/dll/ares64_recompiler.wbx.zst b/Assets/dll/ares64_recompiler.wbx.zst index 4dc8291d075..53d50d2c0dd 100644 Binary files a/Assets/dll/ares64_recompiler.wbx.zst and b/Assets/dll/ares64_recompiler.wbx.zst differ diff --git a/Assets/dll/chd_capi.dll b/Assets/dll/chd_capi.dll index d83b00b8381..f0f9692f96d 100644 Binary files a/Assets/dll/chd_capi.dll and b/Assets/dll/chd_capi.dll differ diff --git a/Assets/dll/cimgui.dll b/Assets/dll/cimgui.dll new file mode 100644 index 00000000000..a40b346f2cd Binary files /dev/null and b/Assets/dll/cimgui.dll differ diff --git a/Assets/dll/gpgx.wbx.zst b/Assets/dll/gpgx.wbx.zst index 40903b6b931..3ce5849e0e0 100644 Binary files a/Assets/dll/gpgx.wbx.zst and b/Assets/dll/gpgx.wbx.zst differ diff --git a/Assets/dll/libSDL2.so b/Assets/dll/libSDL2.so index 695005ea179..e74a4cee5f8 100755 Binary files a/Assets/dll/libSDL2.so and b/Assets/dll/libSDL2.so differ diff --git a/Assets/dll/libcimgui.so b/Assets/dll/libcimgui.so new file mode 100644 index 00000000000..d4b8c270e61 Binary files /dev/null and b/Assets/dll/libcimgui.so differ diff --git a/Assets/dll/libgambatte.dll b/Assets/dll/libgambatte.dll index 894ebf93a6f..654f402698f 100644 Binary files a/Assets/dll/libgambatte.dll and b/Assets/dll/libgambatte.dll differ diff --git a/Assets/dll/libgcc_s_seh-1.dll b/Assets/dll/libgcc_s_seh-1.dll index 12a362ad9da..df7e7815d0a 100644 Binary files a/Assets/dll/libgcc_s_seh-1.dll and b/Assets/dll/libgcc_s_seh-1.dll differ diff --git a/Assets/dll/libquicknes.dll b/Assets/dll/libquicknes.dll index 3e92763ffe8..779b225aa06 100644 Binary files a/Assets/dll/libquicknes.dll and b/Assets/dll/libquicknes.dll differ diff --git a/Assets/dll/libquicknes.so b/Assets/dll/libquicknes.so index 39ff5fc1044..79c668b2ef8 100755 Binary files a/Assets/dll/libquicknes.so and b/Assets/dll/libquicknes.so differ diff --git a/Assets/dll/libstdc++-6.dll b/Assets/dll/libstdc++-6.dll index 65fe81f0daa..53193c267f6 100644 Binary files a/Assets/dll/libstdc++-6.dll and b/Assets/dll/libstdc++-6.dll differ diff --git a/Assets/dll/libwaterboxhost.so b/Assets/dll/libwaterboxhost.so index 1b201844e76..f87c4b4e9cd 100644 Binary files a/Assets/dll/libwaterboxhost.so and b/Assets/dll/libwaterboxhost.so differ diff --git a/Assets/dll/libwinpthread-1.dll b/Assets/dll/libwinpthread-1.dll index e25834ad644..d452132fe38 100644 Binary files a/Assets/dll/libwinpthread-1.dll and b/Assets/dll/libwinpthread-1.dll differ diff --git a/Assets/dll/melonDS.wbx.zst b/Assets/dll/melonDS.wbx.zst index 15c1b21c670..a390639b189 100644 Binary files a/Assets/dll/melonDS.wbx.zst and b/Assets/dll/melonDS.wbx.zst differ diff --git a/Assets/dll/mupen64plus.dll b/Assets/dll/mupen64plus.dll index 5ecc047b978..1bc2bcc28ef 100644 Binary files a/Assets/dll/mupen64plus.dll and b/Assets/dll/mupen64plus.dll differ diff --git a/Assets/dll/puae.wbx.zst b/Assets/dll/puae.wbx.zst new file mode 100644 index 00000000000..04123a73b57 Binary files /dev/null and b/Assets/dll/puae.wbx.zst differ diff --git a/Assets/dll/tic80.wbx.zst b/Assets/dll/tic80.wbx.zst index a17b980ba03..fb8864f7986 100644 Binary files a/Assets/dll/tic80.wbx.zst and b/Assets/dll/tic80.wbx.zst differ diff --git a/Assets/dll/uzem.wbx.zst b/Assets/dll/uzem.wbx.zst index 230ce1f6504..ef54b43404f 100644 Binary files a/Assets/dll/uzem.wbx.zst and b/Assets/dll/uzem.wbx.zst differ diff --git a/Assets/dll/waterboxhost.dll b/Assets/dll/waterboxhost.dll index 0a8cf71cde0..92083586f58 100644 Binary files a/Assets/dll/waterboxhost.dll and b/Assets/dll/waterboxhost.dll differ diff --git a/BizHawk.sln b/BizHawk.sln index 1955f548fd9..2067752ffe5 100644 --- a/BizHawk.sln +++ b/BizHawk.sln @@ -29,8 +29,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BizHawk.Bizware.Graphics", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BizHawk.Bizware.Graphics.Controls", "src\BizHawk.Bizware.Graphics.Controls\BizHawk.Bizware.Graphics.Controls.csproj", "{3D050D35-B57D-4D14-BE0F-FD63552DADB0}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BizHawk.Bizware.BizwareGL", "src\BizHawk.Bizware.BizwareGL\BizHawk.Bizware.BizwareGL.csproj", "{658BB7AA-74A1-496F-A6AA-B7D3DD9C7CBE}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BizHawk.BizInvoke", "src\BizHawk.BizInvoke\BizHawk.BizInvoke.csproj", "{E5D76DC1-84A8-47AF-BE25-E76F06D2FBBC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BizHawk.WinForms.Controls", "src\BizHawk.WinForms.Controls\BizHawk.WinForms.Controls.csproj", "{B5A2214B-3CB0-48C4-8DB1-98B38D48AC4A}" @@ -89,10 +87,6 @@ Global {3D050D35-B57D-4D14-BE0F-FD63552DADB0}.Debug|Any CPU.Build.0 = Debug|Any CPU {3D050D35-B57D-4D14-BE0F-FD63552DADB0}.Release|Any CPU.ActiveCfg = Release|Any CPU {3D050D35-B57D-4D14-BE0F-FD63552DADB0}.Release|Any CPU.Build.0 = Release|Any CPU - {658BB7AA-74A1-496F-A6AA-B7D3DD9C7CBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {658BB7AA-74A1-496F-A6AA-B7D3DD9C7CBE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {658BB7AA-74A1-496F-A6AA-B7D3DD9C7CBE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {658BB7AA-74A1-496F-A6AA-B7D3DD9C7CBE}.Release|Any CPU.Build.0 = Release|Any CPU {E5D76DC1-84A8-47AF-BE25-E76F06D2FBBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E5D76DC1-84A8-47AF-BE25-E76F06D2FBBC}.Debug|Any CPU.Build.0 = Debug|Any CPU {E5D76DC1-84A8-47AF-BE25-E76F06D2FBBC}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/Common.props b/Common.props index 75784b774c6..3a18589e5aa 100644 --- a/Common.props +++ b/Common.props @@ -16,9 +16,10 @@ prompt strict $(TargetFramework.StartsWith("net4")) - 10.0 + true + 12.0 true - SA0001 + $(NoWarn);CS1591;SA0001 enable AnyCPU true diff --git a/Directory.Packages.props b/Directory.Packages.props index 8adc668cec2..d9e3da72c2e 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,37 +3,43 @@ - - - - + + + + + + + - + - - + + - + + + + diff --git a/Dist/Package.sh b/Dist/Package.sh index df065aee4de..8ac01132213 100755 --- a/Dist/Package.sh +++ b/Dist/Package.sh @@ -11,12 +11,11 @@ cd "$targetDir" if [ "$1" = "windows-x64" ]; then rm -f "EmuHawkMono.sh" cd "dll" - rm -f "libchd_capi.so" "libe_sqlite3.so" "libSDL2.so" "OpenTK.dll.config" \ - "libbizlynx.dll.so" "libbizswan.dll.so" "libblip_buf.so" "libbizhash.so" "libdarm.so" "libemu83.so" "libencore.so" "libfwunpack.so" "libgambatte.so" "libLibretroBridge.so" "libquicknes.so" "librcheevos.so" "libsameboy.so" "libmgba.dll.so" "libMSXHawk.so" "libwaterboxhost.so" + rm -f *.so else find . -type f -name "*.sh" -exec chmod +x {} \; # installed with -m644 but needs to be 755 cd "dll" - rm -f "chd_capi.dll" "e_sqlite3.dll" "lua54.dll" "SDL2.dll" \ + rm -f "chd_capi.dll" "cimgui.dll" "e_sqlite3.dll" "lua54.dll" "SDL2.dll" \ "mupen64plus-audio-bkm.dll" "mupen64plus-input-bkm.dll" "mupen64plus-rsp-cxd4-sse2.dll" "mupen64plus-rsp-hle.dll" "mupen64plus-video-angrylion-rdp.dll" "mupen64plus-video-glide64.dll" "mupen64plus-video-glide64mk2.dll" "mupen64plus-video-GLideN64.dll" "mupen64plus-video-rice.dll" "mupen64plus.dll" "octoshock.dll" \ "bizlynx.dll" "bizswan.dll" "blip_buf.dll" "libbizhash.dll" "libdarm.dll" "libemu83.dll" "encore.dll" "libfwunpack.dll" "libgambatte.dll" "libLibretroBridge.dll" "libquicknes.dll" "librcheevos.dll" "libsameboy.dll" "mgba.dll" "MSXHawk.dll" "waterboxhost.dll" fi diff --git a/Dist/deps.nix b/Dist/deps.nix index 47f594c2c26..d38bc09d591 100644 --- a/Dist/deps.nix +++ b/Dist/deps.nix @@ -6,44 +6,56 @@ (fetchNuGet { pname = "DotNetAnalyzers.DocumentationAnalyzers"; version = "1.0.0-beta.59"; sha256 = "03kllr1f52jq5a0b1fa2s57yz1bp0awh36n4dk679nqgbg6m8flj"; }) (fetchNuGet { pname = "DotNetAnalyzers.DocumentationAnalyzers.Unstable"; version = "1.0.0.59"; sha256 = "1491q3rby0ysm2bszr33r9h48wk4bz3bz748ziz8p2rklcqrhn5f"; }) (fetchNuGet { pname = "Google.FlatBuffers"; version = "23.5.26"; sha256 = "1yly6bjaqwpyh3f367wa8cr6pdwwpvan5q97xg55r1lfvpbbv51a"; }) - (fetchNuGet { pname = "JunitXml.TestLogger"; version = "3.0.124"; sha256 = "1s70k74bkw0fhfkylak289c2s7l6vijz7n5j64qyw7bjzncqs4n7"; }) - (fetchNuGet { pname = "Menees.Analyzers"; version = "3.0.10"; sha256 = "1fgkr4x8cnjmn6xj106g1y5smc49x9qkmb8c42nx7sqg3lzwqpgb"; }) - (fetchNuGet { pname = "Meziantou.Analyzer"; version = "2.0.33"; sha256 = "0lyi217pijxh7jw5xg47ks5r32s77g0xlw9nf42vjbmczfmhk23d"; }) - (fetchNuGet { pname = "Microsoft.ApplicationInsights"; version = "2.21.0"; sha256 = "1q034jbqkxb8lddkd0ijp0wp0ymnnf3bg2mjpay027zv7jswnc4x"; }) + (fetchNuGet { pname = "ImGui.NET"; version = "1.90.6.1"; sha256 = "1v1zzlpz3g2h7azqqqhfcwssx9vminnb5pl9880jw28mfk5si1q8"; }) + (fetchNuGet { pname = "JunitXml.TestLogger"; version = "3.1.12"; sha256 = "1571rs2zpd7az5wp0bklx1h3pac388awlwhz70k0p0vv44h0v5jc"; }) + (fetchNuGet { pname = "Menees.Analyzers"; version = "3.2.2"; sha256 = "0zd7hh5xilm1svnz4dcvgryixkmsncdszzimy3fvz2xbs06cpksb"; }) + (fetchNuGet { pname = "Meziantou.Analyzer"; version = "2.0.159"; sha256 = "0ybck0h871hdb7lfv52f73a1y1v2nrlvbvbmy2ws5nbd0xacjvww"; }) + (fetchNuGet { pname = "Microsoft.ApplicationInsights"; version = "2.22.0"; sha256 = "0h5qkhmazlvwvjmxxj9pp2404rmvk55yf6npwcmlskv9mgfkli4r"; }) (fetchNuGet { pname = "Microsoft.Bcl.AsyncInterfaces"; version = "8.0.0"; sha256 = "0z4jq5prnxyb4p3163yxx35znpd2msjd8hw8ysmv4ah90f5sd9gm"; }) (fetchNuGet { pname = "Microsoft.Bcl.HashCode"; version = "1.1.1"; sha256 = "0xwfph92p92d8hgrdiaka4cazqsjpg4ywfxfx6qbk3939f29kzl0"; }) - (fetchNuGet { pname = "Microsoft.CodeCoverage"; version = "17.8.0"; sha256 = "173wjadp3gan4x2jfjchngnc4ca4mb95h1sbb28jydfkfw0z1zvj"; }) + (fetchNuGet { pname = "Microsoft.CodeCoverage"; version = "17.10.0"; sha256 = "0s0v7jmrq85n356xv7zixvwa4z94fszjcr5vll8x4im1a2lp00f9"; }) (fetchNuGet { pname = "Microsoft.CSharp"; version = "4.7.0"; sha256 = "0gd67zlw554j098kabg887b5a6pq9kzavpa3jjy5w53ccjzjfy8j"; }) (fetchNuGet { pname = "Microsoft.Data.Sqlite.Core"; version = "8.0.4"; sha256 = "03i9b45n2vnsv4wdsk6qvjzj1ga2hcli168liyrqfa87l54skckd"; }) (fetchNuGet { pname = "Microsoft.DotNet.PlatformAbstractions"; version = "3.1.6"; sha256 = "0b9myd7gqbpaw9pkd2bx45jhik9mwj0f1ss57sk2cxmag2lkdws5"; }) (fetchNuGet { pname = "Microsoft.Extensions.DependencyModel"; version = "8.0.0"; sha256 = "02jnx23hm1vid3yd9pw4gghzn6qkgdl5xfc5r0zrcxdax70rsh5a"; }) - (fetchNuGet { pname = "Microsoft.NET.Test.Sdk"; version = "17.8.0"; sha256 = "1syvl3g0hbrcgfi9rq6pld8s8hqqww4dflf1lxn59ccddyyx0gmv"; }) + (fetchNuGet { pname = "Microsoft.NET.Test.Sdk"; version = "17.10.0"; sha256 = "13g8fwl09li8fc71nk13dgkb7gahd4qhamyg2xby7am63nlchhdf"; }) (fetchNuGet { pname = "Microsoft.NETCore.Platforms"; version = "1.1.0"; sha256 = "08vh1r12g6ykjygq5d3vq09zylgb84l63k49jc4v8faw9g93iqqm"; }) + (fetchNuGet { pname = "Microsoft.NETCore.Targets"; version = "1.1.0"; sha256 = "193xwf33fbm0ni3idxzbr5fdq3i2dlfgihsac9jj7whj0gd902nh"; }) (fetchNuGet { pname = "Microsoft.NETFramework.ReferenceAssemblies"; version = "1.0.3"; sha256 = "0hc4d4d4358g5192mf8faijwk0bpf9pjwcfd3h85sr67j0zhj6hl"; }) (fetchNuGet { pname = "Microsoft.NETFramework.ReferenceAssemblies.net48"; version = "1.0.3"; sha256 = "18h4265rn5dy5d1igddsz1ilygcyyj4id4cn2qsr3sz7722k8zla"; }) - (fetchNuGet { pname = "Microsoft.Testing.Extensions.Telemetry"; version = "1.0.2"; sha256 = "00psv2mvynd2bz8xnzvqvb32qr33glqxg4ni5j91b93k84yjy5ma"; }) - (fetchNuGet { pname = "Microsoft.Testing.Extensions.TrxReport.Abstractions"; version = "1.0.2"; sha256 = "09yn3hi9npgi8rs2vyfyzcl8vbfa1lqcl6lgpymw5d7lg0hc511w"; }) - (fetchNuGet { pname = "Microsoft.Testing.Extensions.VSTestBridge"; version = "1.0.2"; sha256 = "0c65fsc23xxw648xh83sjcmrn9hvs9q58l5lb36wflvaajbsjf2r"; }) - (fetchNuGet { pname = "Microsoft.Testing.Platform"; version = "1.0.2"; sha256 = "0bq46f4v2r4nzwly7g0dsakyc1lcql9nh85sp59d1fwzaknf1n94"; }) - (fetchNuGet { pname = "Microsoft.Testing.Platform.MSBuild"; version = "1.0.2"; sha256 = "1vjqrpqjx3z1irqgy0ckmkgyvrzqqqcikxs36q6gadyj643ra1c5"; }) + (fetchNuGet { pname = "Microsoft.Testing.Extensions.Telemetry"; version = "1.2.1"; sha256 = "1a6hyd3szjjpjkbr0ncfria0x2qijv3lwr4drhxm15xamfy23azw"; }) + (fetchNuGet { pname = "Microsoft.Testing.Extensions.TrxReport.Abstractions"; version = "1.2.1"; sha256 = "19309m0b9cjy1642m99ipjvr6gxq6qb008bam3l10m1mz8m81j31"; }) + (fetchNuGet { pname = "Microsoft.Testing.Extensions.VSTestBridge"; version = "1.2.1"; sha256 = "1bly8375zng21yjbfdi08c14lgapngv06p1dlzbryimxicqzxixx"; }) + (fetchNuGet { pname = "Microsoft.Testing.Platform"; version = "1.2.1"; sha256 = "0zlbqmvdb1vxnvmxh6lk65mz57c7mz6dqb1s8in0cfww8kxg058k"; }) + (fetchNuGet { pname = "Microsoft.Testing.Platform.MSBuild"; version = "1.2.1"; sha256 = "07674xnhc84h36pvzswx6ibjy0bgfi2bxhqm1zyq9fidmim0ch07"; }) (fetchNuGet { pname = "Microsoft.TestPlatform.ObjectModel"; version = "17.5.0"; sha256 = "0qkjyf3ky6xpjg5is2sdsawm99ka7fzgid2bvpglwmmawqgm8gls"; }) - (fetchNuGet { pname = "Microsoft.TestPlatform.ObjectModel"; version = "17.8.0"; sha256 = "0b0i7lmkrcfvim8i3l93gwqvkhhhfzd53fqfnygdqvkg6np0cg7m"; }) - (fetchNuGet { pname = "Microsoft.TestPlatform.TestHost"; version = "17.8.0"; sha256 = "0f5jah93kjkvxwmhwb78lw11m9pkkq9fvf135hpymmmpxqbdh97q"; }) - (fetchNuGet { pname = "Microsoft.Win32.SystemEvents"; version = "6.0.0"; sha256 = "0c6pcj088g1yd1vs529q3ybgsd2vjlk5y1ic6dkmbhvrp5jibl9p"; }) - (fetchNuGet { pname = "MSTest"; version = "3.2.2"; sha256 = "19pkywdlmgccv2ri52gbpb3pgci1ymb2ba5qhyp9j19vks6gf6cj"; }) - (fetchNuGet { pname = "MSTest.Analyzers"; version = "3.2.2"; sha256 = "1ap7imbqxmz2namgli796pxj91gyn01k6xxnllldpwwbxpd0ijgd"; }) - (fetchNuGet { pname = "MSTest.TestAdapter"; version = "3.2.2"; sha256 = "14nrxg1cd3lzaxw7zz8z91168sgnsf1xxnrpdy7wkd6ggk22hi19"; }) - (fetchNuGet { pname = "MSTest.TestFramework"; version = "3.2.2"; sha256 = "0igdrjr300bqz5lnibf9vl8pkaky1l27f889gza3a9xs83mpd06p"; }) + (fetchNuGet { pname = "MSTest"; version = "3.4.3"; sha256 = "070avma2zdxdpn23a9chgz9n1kglxh8nbb1g2ggzk3xxi5sdjj0n"; }) + (fetchNuGet { pname = "MSTest.Analyzers"; version = "3.4.3"; sha256 = "14a6rzh4cvaf9bw63qlxw242fbmk4agyx9qgl19swpciqcaq7pxi"; }) + (fetchNuGet { pname = "MSTest.TestAdapter"; version = "3.4.3"; sha256 = "0hsslndnfyb6shgkmgy10f1c9p6b47ry20zr2l1msagmkrk49s5q"; }) + (fetchNuGet { pname = "MSTest.TestFramework"; version = "3.4.3"; sha256 = "0hviglzfv16dd3aczny455sy1k0rikzd5w34smfpjyxc0wqx6xvp"; }) (fetchNuGet { pname = "NETStandard.Library"; version = "2.0.3"; sha256 = "1fn9fxppfcg4jgypp2pmrpr6awl3qz1xmnri0cygpkwvyx27df1y"; }) (fetchNuGet { pname = "Newtonsoft.Json"; version = "13.0.3"; sha256 = "0xrwysmrn4midrjal8g2hr1bbg38iyisl0svamb11arqws4w2bw7"; }) (fetchNuGet { pname = "NuGet.Frameworks"; version = "5.11.0"; sha256 = "0wv26gq39hfqw9md32amr5771s73f5zn1z9vs4y77cgynxr73s4z"; }) - (fetchNuGet { pname = "NuGet.Frameworks"; version = "6.5.0"; sha256 = "0s37d1p4md0k6d4cy6sq36f2dgkd9qfbzapxhkvi8awwh0vrynhj"; }) (fetchNuGet { pname = "Nullable"; version = "1.3.1"; sha256 = "0hwrr4q22c0i056dqy3v431rxjv7md910ihz0pjsi16qxsbpw7p7"; }) (fetchNuGet { pname = "PolySharp"; version = "1.14.1"; sha256 = "1gfpxlzmcip2zbmmgs2yfib8k53c0fp34lxwsyy46w5y47wp7a4p"; }) + (fetchNuGet { pname = "PowerShell"; version = "7.4.2"; sha256 = "17nrp0spddhmalbxy7m5s1926b597x7zl9d50il2w115y5cggbf0"; }) (fetchNuGet { pname = "ppy.SDL2-CS"; version = "1.0.630-alpha"; sha256 = "0jrf70jrz976b49ac0ygfy9qph2w7fnbfrqv0g0x7hlpaip33ra8"; }) + (fetchNuGet { pname = "runtime.any.System.Runtime"; version = "4.3.0"; sha256 = "1cqh1sv3h5j7ixyb7axxbdkqx6cxy00p4np4j91kpm492rf4s25b"; }) + (fetchNuGet { pname = "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "16rnxzpk5dpbbl1x354yrlsbvwylrq456xzpsha1n9y3glnhyx9d"; }) + (fetchNuGet { pname = "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0hkg03sgm2wyq8nqk6dbm9jh5vcq57ry42lkqdmfklrw89lsmr59"; }) + (fetchNuGet { pname = "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0c2p354hjx58xhhz7wv6div8xpi90sc6ibdm40qin21bvi7ymcaa"; }) + (fetchNuGet { pname = "runtime.native.System"; version = "4.3.0"; sha256 = "15hgf6zaq9b8br2wi1i3x0zvmk410nlmsmva9p0bbg73v6hml5k4"; }) + (fetchNuGet { pname = "runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "18pzfdlwsg2nb1jjjjzyb5qlgy6xjxzmhnfaijq5s2jw3cm3ab97"; }) + (fetchNuGet { pname = "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0qyynf9nz5i7pc26cwhgi8j62ps27sqmf78ijcfgzab50z9g8ay3"; }) + (fetchNuGet { pname = "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "1klrs545awhayryma6l7g2pvnp9xy4z0r1i40r80zb45q3i9nbyf"; }) + (fetchNuGet { pname = "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0zcxjv5pckplvkg0r6mw3asggm7aqzbdjimhvsasb0cgm59x09l3"; }) + (fetchNuGet { pname = "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "0vhynn79ih7hw7cwjazn87rm9z9fj0rvxgzlab36jybgcpcgphsn"; }) + (fetchNuGet { pname = "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "160p68l2c7cqmyqjwxydcvgw7lvl1cr0znkw8fp24d1by9mqc8p3"; }) + (fetchNuGet { pname = "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "15zrc8fgd8zx28hdghcj5f5i34wf3l6bq5177075m2bc2j34jrqy"; }) + (fetchNuGet { pname = "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl"; version = "4.3.0"; sha256 = "1p4dgxax6p7rlgj4q73k73rslcnz4wdcv8q2flg1s8ygwcm58ld5"; }) + (fetchNuGet { pname = "runtime.unix.System.Private.Uri"; version = "4.3.0"; sha256 = "1jx02q6kiwlvfksq1q9qr17fj78y5v6mwsszav4qcz9z25d5g6vk"; }) + (fetchNuGet { pname = "runtime.unix.System.Runtime.Extensions"; version = "4.3.0"; sha256 = "0pnxxmm8whx38dp6yvwgmh22smknxmqs5n513fc7m4wxvs1bvi4p"; }) (fetchNuGet { pname = "SharpCompress"; version = "0.31.0"; sha256 = "01az7amjkxjbya5rdcqwxzrh2d3kybf1gsd3617rsxvvxadyra1r"; }) - (fetchNuGet { pname = "SharpDX"; version = "4.2.0"; sha256 = "1hvg44sicvcby4kfgxmbj1y0cz8ybddas4hkiw8smyh00822cw8i"; }) - (fetchNuGet { pname = "SharpDX.Direct3D9"; version = "4.2.0"; sha256 = "051b7rvmh4phy6id6jyk3n4f8jmfir77i5kcgmfgvppkdvfj15gn"; }) (fetchNuGet { pname = "SharpGen.Runtime"; version = "2.0.0-beta.13"; sha256 = "1250z6sa9ghf84czlkzvaysb29c0n229z1f0vh5qls89akrkl7h8"; }) (fetchNuGet { pname = "SharpGen.Runtime.COM"; version = "2.0.0-beta.13"; sha256 = "1lmv3jp2g7mgy9j23pd3j0wr3p89qiq8v6c6qxqf688izyni1166"; }) (fetchNuGet { pname = "Silk.NET.Core"; version = "2.21.0"; sha256 = "0z24vczhivzszs28sw92kr9zlx3mxcic3lka8lig2zs6dl5591hg"; }) @@ -52,28 +64,34 @@ (fetchNuGet { pname = "Silk.NET.OpenAL.Extensions.Creative"; version = "2.21.0"; sha256 = "1mxm4ijml6hn833wzin7kyya22ix4jp9ribvmks84ci69nkqqw5g"; }) (fetchNuGet { pname = "Silk.NET.OpenAL.Extensions.Enumeration"; version = "2.21.0"; sha256 = "0km4g1msf50bfjcrb0pl3mxvxly0ffks66629i5gwgnyn86niljl"; }) (fetchNuGet { pname = "Silk.NET.OpenAL.Extensions.EXT"; version = "2.21.0"; sha256 = "048n34rzzqy6khr23vs1pm325fnzzydn23a12mwb5s854p1lyp20"; }) - (fetchNuGet { pname = "Silk.NET.OpenGL.Legacy"; version = "2.21.0"; sha256 = "0qsyc17nv0givdc0iychi34sy36ww1x8nmvlm1p54n6qpbv6w5ml"; }) + (fetchNuGet { pname = "Silk.NET.OpenGL"; version = "2.21.0"; sha256 = "1p0ll5g3y2565vqffnlhfrskrh4rglhdvij45xfi9qj01mzpnkzc"; }) + (fetchNuGet { pname = "Silk.NET.WGL"; version = "2.21.0"; sha256 = "09yxzw65xr4r9h8iny5nllbll8jqm6bhr6vc10a272c6b6if1ynj"; }) + (fetchNuGet { pname = "Silk.NET.WGL.Extensions.NV"; version = "2.21.0"; sha256 = "07qyj53y7j3xsnxkdbi24saj535ma7d7swl9h2b70afma5z4f452"; }) (fetchNuGet { pname = "SQLitePCLRaw.core"; version = "2.1.6"; sha256 = "1w8zsgz2w2q0a9cw9cl1rzrpv48a04nhyq67ywan6xlgknds65a7"; }) (fetchNuGet { pname = "SQLitePCLRaw.core"; version = "2.1.8"; sha256 = "1j67fs6qznkcsfnf2z2571vks1c0bhg4nzcbh8i286rz77hk9gcg"; }) (fetchNuGet { pname = "SQLitePCLRaw.provider.e_sqlite3"; version = "2.1.8"; sha256 = "12x7z1i13571fbiddvp8bzhyxvvvwwd2wwd7c8kd11hpkfza0kbq"; }) - (fetchNuGet { pname = "StyleCop.Analyzers"; version = "1.2.0-beta.435"; sha256 = "0dirz0av24ds2k7hgpss15y4wlhwlzz22qdjvkq0n3g3sxcckrsy"; }) - (fetchNuGet { pname = "StyleCop.Analyzers.Unstable"; version = "1.2.0.435"; sha256 = "1jv4ha4y2c9922n21yf2dvfkmi8qfa8z28gk5zsqdyck08izp9mh"; }) + (fetchNuGet { pname = "StyleCop.Analyzers"; version = "1.2.0-beta.556"; sha256 = "1x91v0x6w5s7xm85d5mipv0kah2j3r7ypyidpr9rrggrr90iidpp"; }) + (fetchNuGet { pname = "StyleCop.Analyzers.Unstable"; version = "1.2.0.556"; sha256 = "0ryaqhj1k71q3yh1ag1288y90ylv05w844win68pvybbmznjjnk9"; }) + (fetchNuGet { pname = "System.Buffers"; version = "4.4.0"; sha256 = "183f8063w8zqn99pv0ni0nnwh7fgx46qzxamwnans55hhs2l0g19"; }) (fetchNuGet { pname = "System.Buffers"; version = "4.5.1"; sha256 = "04kb1mdrlcixj9zh1xdi5as0k0qi8byr5mi3p3jcxx72qz93s2y3"; }) (fetchNuGet { pname = "System.Collections.Immutable"; version = "8.0.0"; sha256 = "0z53a42zjd59zdkszcm7pvij4ri5xbb8jly9hzaad9khlf69bcqp"; }) (fetchNuGet { pname = "System.ComponentModel.Annotations"; version = "5.0.0"; sha256 = "021h7x98lblq9avm1bgpa4i31c2kgsa7zn4sqhxf39g087ar756j"; }) (fetchNuGet { pname = "System.Diagnostics.DiagnosticSource"; version = "5.0.0"; sha256 = "0phd2qizshjvglhzws1jd0cq4m54gscz4ychzr3x6wbgl4vvfrga"; }) (fetchNuGet { pname = "System.Drawing.Common"; version = "6.0.0"; sha256 = "02n8rzm58dac2np8b3xw8ychbvylja4nh6938l5k2fhyn40imlgz"; }) + (fetchNuGet { pname = "System.Drawing.Primitives"; version = "4.3.0"; sha256 = "0p03zhbzf1cylfsia8bj55rpmj1c0nkxl9zmva8kjx4xq5s812sv"; }) (fetchNuGet { pname = "System.IO"; version = "4.3.0"; sha256 = "05l9qdrzhm4s5dixmx68kxwif4l99ll5gqmh7rqgw554fx0agv5f"; }) (fetchNuGet { pname = "System.Memory"; version = "4.5.5"; sha256 = "08jsfwimcarfzrhlyvjjid61j02irx6xsklf32rv57x2aaikvx0h"; }) (fetchNuGet { pname = "System.Net.Http"; version = "4.3.4"; sha256 = "0kdp31b8819v88l719j6my0yas6myv9d1viql3qz5577mv819jhl"; }) (fetchNuGet { pname = "System.Numerics.Vectors"; version = "4.4.0"; sha256 = "0rdvma399070b0i46c4qq1h2yvjj3k013sqzkilz4bz5cwmx1rba"; }) (fetchNuGet { pname = "System.Numerics.Vectors"; version = "4.5.0"; sha256 = "1kzrj37yzawf1b19jq0253rcs8hsq1l2q8g69d7ipnhzb0h97m59"; }) + (fetchNuGet { pname = "System.Private.Uri"; version = "4.3.0"; sha256 = "04r1lkdnsznin0fj4ya1zikxiqr0h6r6a1ww2dsm60gqhdrf0mvx"; }) (fetchNuGet { pname = "System.Reflection.Emit"; version = "4.7.0"; sha256 = "121l1z2ypwg02yz84dy6gr82phpys0njk7yask3sihgy214w43qp"; }) (fetchNuGet { pname = "System.Reflection.Emit.ILGeneration"; version = "4.7.0"; sha256 = "0l8jpxhpgjlf1nkz5lvp61r4kfdbhr29qi8aapcxn3izd9wd0j8r"; }) (fetchNuGet { pname = "System.Reflection.Metadata"; version = "1.6.0"; sha256 = "1wdbavrrkajy7qbdblpbpbalbdl48q3h34cchz24gvdgyrlf15r4"; }) (fetchNuGet { pname = "System.Resources.Extensions"; version = "7.0.0"; sha256 = "0d5gk5g5qqkwa728jwx9yabgjvgywsy6k8r5vgqv2dmlvjrqflb4"; }) (fetchNuGet { pname = "System.Runtime"; version = "4.3.0"; sha256 = "066ixvgbf2c929kgknshcxqj6539ax7b9m570cp8n179cpfkapz7"; }) (fetchNuGet { pname = "System.Runtime.CompilerServices.Unsafe"; version = "6.0.0"; sha256 = "0qm741kh4rh57wky16sq4m0v05fxmkjjr87krycf5vp9f0zbahbc"; }) + (fetchNuGet { pname = "System.Runtime.Extensions"; version = "4.3.0"; sha256 = "1ykp3dnhwvm48nap8q23893hagf665k0kn3cbgsqpwzbijdcgc60"; }) (fetchNuGet { pname = "System.Runtime.InteropServices.RuntimeInformation"; version = "4.0.0"; sha256 = "0glmvarf3jz5xh22iy3w9v3wyragcm4hfdr17v90vs7vcrm7fgp6"; }) (fetchNuGet { pname = "System.Security.Cryptography.Algorithms"; version = "4.3.0"; sha256 = "03sq183pfl5kp7gkvq77myv7kbpdnq3y0xj7vi4q1kaw54sny0ml"; }) (fetchNuGet { pname = "System.Security.Cryptography.Encoding"; version = "4.3.0"; sha256 = "1jr6w70igqn07k5zs1ph6xja97hxnb3mqbspdrff6cvssgrixs32"; }) @@ -86,7 +104,10 @@ (fetchNuGet { pname = "System.ValueTuple"; version = "4.5.0"; sha256 = "00k8ja51d0f9wrq4vv5z2jhq8hy31kac2rg0rv06prylcybzl8cy"; }) (fetchNuGet { pname = "Ultz.Bcl.Half"; version = "1.0.0"; sha256 = "1a77c7iv1ngldhrjk5j5gijaanmq5k26lqg99symrcmn90dmcxkf"; }) (fetchNuGet { pname = "Ultz.Bcl.Half.Fallback"; version = "1.0.0"; sha256 = "1c34rv9dc81sp53gvcqnfr69ncf4fi2vq07cj1hixaf7wmd32k14"; }) + (fetchNuGet { pname = "Vortice.D3DCompiler"; version = "2.4.2"; sha256 = "07wdz77cb4c0f4bzzkd7fzkfl5jx6m6mnddpxgab8a95ryv60xrd"; }) + (fetchNuGet { pname = "Vortice.Direct3D11"; version = "2.4.2"; sha256 = "18zyx9srbszah9hk8fkc1iws0hb5137gd77xi0qq9gx1nb62lkl5"; }) (fetchNuGet { pname = "Vortice.DirectX"; version = "2.4.2"; sha256 = "11yjyvyz922z1ygl8gxmdym3918df12nl7xxry4pdjpl8is33qic"; }) + (fetchNuGet { pname = "Vortice.DXGI"; version = "2.4.2"; sha256 = "17vsnm9ca6nqk3f1dfpfvd6i6fp8x8v41bn65rchrzwcv1zzi6pz"; }) (fetchNuGet { pname = "Vortice.Mathematics"; version = "1.4.25"; sha256 = "0vl6g087disxyzskvkbnwym74s47lkza0ly3nk4y0y88zibcggrj"; }) (fetchNuGet { pname = "Vortice.MediaFoundation"; version = "2.4.2"; sha256 = "0nk8r564w8x791nqn5457jcq0gj7v6k5v1mziisqy4945byjxcdl"; }) (fetchNuGet { pname = "Vortice.XAudio2"; version = "2.4.2"; sha256 = "0iwnaa0jdl3782k9i9j2c0s7lyxjky1ph6i8dv12w3ym2p19h3qc"; }) diff --git a/Dist/git_hook_shim.sh b/Dist/git_hook_shim.sh new file mode 100755 index 00000000000..102fc9b662a --- /dev/null +++ b/Dist/git_hook_shim.sh @@ -0,0 +1,12 @@ +#!/bin/sh +kind="$(basename "$0")" +pwsh="$(command -v pwsh)" +if [ -z "$pwsh" ]; then pwsh="$(command -v dotnet) pwsh"; fi +if ! ("$pwsh" -v >/dev/null 2>/dev/null); then + printf "pwsh not found in PATH; skipping %s hook\n" "$kind" + exit 0 +fi +if [ -e "./Dist/git_hooks/$kind.ps1" ]; then + "$pwsh" "./Dist/git_hooks/$kind.ps1" "$@" || exit $? + if [ -e "./Dist/git_hooks/$kind.local.ps1" ]; then "$pwsh" "./Dist/git_hooks/$kind.local.ps1" "$@" || exit $?; fi +fi diff --git a/Dist/git_hooks/commit-msg.ps1 b/Dist/git_hooks/commit-msg.ps1 new file mode 100755 index 00000000000..8350f4c73d5 --- /dev/null +++ b/Dist/git_hooks/commit-msg.ps1 @@ -0,0 +1,13 @@ +#!/usr/bin/env -S pwsh +$msg = Get-Content $args[0] -TotalCount 1 # this commit hook is always passed the commit message scratch file's path, so read the first line of that +if ($msg -Match "^fix(?:ed|es)? #\d+$") { + echo "An issue reference alone is not a suitable commit message. Vetoed." + exit 1 +} +if ($msg.Length -lt 20) { # arbitrary + if ($msg.Length -lt 8) { # semi-arbitrary; I figured "Fix typo" would be the shortest reasonable message --yoshi + echo "Your commit message is too short. Vetoed." + exit 1 + } + echo "Your commit message is a bit short. Do you have more to add? (If you included a longer description already, ignore this.)" +} diff --git a/Dist/historical.nix b/Dist/historical.nix index a1cc3138e07..2c360c5ccae 100644 --- a/Dist/historical.nix +++ b/Dist/historical.nix @@ -78,7 +78,7 @@ sed 's/$(git rev-parse --verify HEAD || printf "0000000000000000000000000000000000000000")/'"$shortHash"'/' \ -i $out/Dist/.InvokeCLIOnMainSln.sh ''; - hashPostPatching = "sha256-g6U0B+wY5uosP5WyNFKylBRX9kq+zM6H+f05egYqcAQ="; + hashPostPatching = "sha512-7/uvlkR+OxwxErrp0BK+B7ZURp58p8B581lv5iAZgO3Lr6e92kTptypLt7pmqZdZrrsSmuCphNuRfHu0BZeg0A=="; dotnet-sdk = dotnet-sdk_6; }; info-2_9 = { @@ -87,7 +87,7 @@ postFetch = '' commitCount=20208 '' + pre-2_9_1-no-git-patch + from-2_6_2-through-2_9-no-git-patch; - hashPostPatching = "sha256-gDLStqpRGxTlXip+FKWj/O7sQElBNjQK8HpjZbXsrC0="; + hashPostPatching = "sha512-KJvzpLyzoqLbQsGvWeC2gTWg7871jUToAVMLkI1zm2Ju5+5K5sqhrzwjK/Oxwg8HMCegqIvM9qeM2TdYYuwc6g=="; dotnet-sdk = dotnet-sdk_6; }; info-2_8 = { @@ -96,7 +96,7 @@ postFetch = '' commitCount=19337 '' + pre-2_9_1-no-git-patch + from-2_6_2-through-2_9-no-git-patch; - hashPostPatching = "sha256-TfxAA8QkyImau0MxCdbTWFKneXZwpXYPIB+iN9z+Unk="; + hashPostPatching = "sha512-kumq3rM86vDT/4W9GioOJ6j2SAEAnyNB7eH2TcPoQGSyxkCmngIyG/yRRY4zYzRLukgEcqM/PiTzBuZxJTNKcQ=="; dotnet-sdk = dotnet-sdk_6; }; info-2_7 = { @@ -105,7 +105,7 @@ postFetch = '' commitCount=19020 '' + pre-2_9_1-no-git-patch + from-2_6_2-through-2_9-no-git-patch; - hashPostPatching = "sha256-IX8WmNU+gEY8Vh6OAC3XogiGSmAfdAks4HPJVt4K/4w="; + hashPostPatching = "sha512-24/2zMd+Y02jO5XqQLqIZG5pAqO1TC+1ZMuhsO6xYQRTcDFHu2Rq6k0fiCiaoMpac1ymwOS/5bY/x/2e8Eqc/A=="; dotnet-sdk = dotnet-sdk_5; }; info-2_6_3 = { @@ -114,7 +114,7 @@ postFetch = '' commitCount=18925 '' + pre-2_9_1-no-git-patch + from-2_6_2-through-2_9-no-git-patch; - hashPostPatching = "sha256-2+r35rVDNYQ1sKffjSph+bsSWRtz1v3jgDqAi5WrhKo="; + hashPostPatching = "sha512-oSxazA8cjN6CkVahye3SExEiV+yvkhskDNJA+++fTQcRWaiPlbBb1LtLjH+YuyCyLqgJ25Wi38VgyPwhO4QKOA=="; dotnet-sdk = dotnet-sdk_5; }; info-2_6_2 = { @@ -123,7 +123,7 @@ postFetch = '' commitCount=18704 '' + pre-2_9_1-no-git-patch + from-2_6_2-through-2_9-no-git-patch; - hashPostPatching = "sha256-TPf2lFI4PrswoPFQAKrr9vQPHQ9Qi5afgPSyJEErKuo="; + hashPostPatching = "sha512-W79FBXhboUPwUreeIiTJ38grdcNuphzMFDKvV5StPj8kwwf/RoSw7kyK+/hXN5wFcobd48TnbRFVm36Upfuvmg=="; dotnet-sdk = dotnet-sdk_5; }; info-2_6_1 = { @@ -132,7 +132,7 @@ postFetch = '' commitCount=18467 '' + pre-2_9_1-no-git-patch; - hashPostPatching = "sha256-2+zIlHIENzakZGxjSGfA0owFRr5K2u5EagxTbnKeVsw="; + hashPostPatching = "sha512-qZjdISAxXmOSUQ3h7NVOvA2N7ezC7io8NGUWPNpoUVM+YzkHa/aBdxN5VniWid2N7m/nmfeQA69nmJi7HtkY+w=="; dotnet-sdk = dotnet-sdk_5; }; info-2_6 = { @@ -141,7 +141,7 @@ postFetch = '' commitCount=18376 '' + pre-2_9_1-no-git-patch; - hashPostPatching = "sha256-kswmNENYxumQlJdUKRQcb5Ni5+aXUqKxEnJ8jX5OHQ0="; + hashPostPatching = "sha512-K1XafghDr64MW0fnw5uujsHLrJhxNMcj4Ptin4HT4+cEHg6WN59oNcI5Hsml6xn5u6cRBqHmcugIfYXEK1/g5g=="; dotnet-sdk = dotnet-sdk_5; }; # if you want to get these building from source, start by changing `releasesEmuHawkInstallables` in `default.nix` so the attrs are actually exposed @@ -210,6 +210,7 @@ in { hasAssetsInOutput = !isVersionAtLeast "2.6.1" version; hasFFmpegPatch_e68a49aa5 = isVersionAtLeast "2.9.2" version; # with e68a49aa5, downloading *and running* FFmpeg finally works; TODO use FFmpeg from Nixpkgs since it's a stable version (4.4.1) hasMiscTypeCheckerPatch_6afb3be98 = isVersionAtLeast "2.6.2" version; + mainAppFilename = "EmuHawk.exe"; # for emuhawk-mono-wrapper launch script neededExtraManagedDeps = neededExtraManagedDepsApprox; needsLibGLVND = false; # true iff not using nixGL (i.e. on NixOS) AND using the OpenGL renderer (the default option) needsSDL = isVersionAtLeast "2.9.2" version; @@ -224,7 +225,11 @@ in { testProjectNeedsCIEnvVar = !isVersionAtLeast "2.8" version; # platform-specific tests don't run "in CI" because they assume Arch filesystem conventions (on Linux)--before 908d4519c, `-p:ContinuousIntegrationBuild=true` wasn't respected but `GITLAB_CI` was versionProjNeedsDoubleBuild = !isVersionAtLeast "2.9.1" version; #TODO warn about missing/broken features when eval'ing older releases - } // hawkSourceInfo; + } // hawkSourceInfo // { + frontendPackageFlavour = if (hawkSourceInfo.frontendPackageFlavour or null) == null + then "NixHawk" + else hawkSourceInfo.frontendPackageFlavour; + }; /** to be passed to `splitReleaseArtifact` */ releaseArtifactInfos = lib.mapAttrs' (releaseFrag: value: { @@ -243,55 +248,55 @@ in { { "2_9_1" = { stripRoot = false; - hashPrePatching = "sha256-5aKUbNStQ89hnfaxv7MTQ+1qDfy+QNMyLS5WUTdhue4="; + hashPrePatching = "sha512-VX+TlQoCWCNj76HpCXmDsS7SQly+/QeYCnu170+8kF6Y6cZkjMmILQxaC9XfTchVb/zFGMr/8gfgcZToOFZUeQ=="; # NAR checksum; gzip archive is SHA512:BEC7E558963416B3749EF558BC682D1A874A43DF8FE3083224EC7C4C0326CDFEA662EF5C604EEA7C1743D2EEB13656CCF749F0CDB3A413F4985C4B305A95E742 }; "2_9" = { - hashPrePatching = "sha256-gE0iu2L2yvC6dxBcv9Facm8RKPp9dseD7fAH3fnaZsY="; + hashPrePatching = "sha512-hywOvKqygQM4CTER4DFftXuND1eNsux46KuG/QWcEEwzJZ50MSOFHDj59YR+MalWAZ6CvtK4YG5JVENlpXWEdA=="; # NAR checksum; gzip archive is SHA512:A501F7A7DF2B75B00AD242D2DD8246B3B6CC165A2F903A7F1345DD900B30F3C6E0E9DA09DF2565402E8B1F34F3DBC432D3B4569282394C72C46AA348D0D439C2 }; "2_8" = { stripRoot = false; - hashPrePatching = "sha256-IRbhI22l30OPn8zJ4HPemjWUohUvZStlEYKnV7RArFA="; + hashPrePatching = "sha512-T1snCNq0Zfp2yKjoIH1nQJWxA1Ve5AWYWl7izPJNG3BesxIvrTsPMwqtCFdqmss9jjE3aKnPVdjceu1xXDNUYw=="; # NAR checksum; gzip archive is SHA512:A9FFBCD914CA1843372F50DE7C022107E65B8DED3BC61F04D584A7C5342AD83321A22B9F066A8872431181BCC8DE605827911B0C67511C5A2D4E75910C85D1A6 }; "2_7" = { - hashPrePatching = "sha256-rc9Tk5Pc4p6YR33cowB9W01iRl8FYgAI/V1CHc+pL5E="; + hashPrePatching = "sha512-tvldUoaZNV2LaudrGmSLy6VJEuGWLJjRjEYNTuYz8AgLY6006YmaRAjXRIceC04kkPblRGbJ7o4NqAcFdoJ5aQ=="; # NAR checksum; gzip archive is SHA512:9436264AA9CF44AE580A14570EE5B7C39A252A76363118633942D410EE2E5B47F81E1BF5F16030651F9EF63EE503F58AB8F434997F9A43669DFE30D0BD215F47 }; "2_6_3" = { stripRoot = false; - hashPrePatching = "sha256-gCHySfNOjqazbQDqk5lKJIYmPI6onqcaVDwuY8Ud2ns="; + hashPrePatching = "sha512-X4fyit9A9r172lyBtFGjfR2gFQIKU1oRhyupSKuGQnUujk9hYAhUfL6uuQIRu+08oJ7/pQGwlKojMBbC3QaEMg=="; # NAR checksum; gzip archive is SHA512:E16289170DC6013456EB8BCA82B6B911A92732F8DD06B096023B90B4902AA0B99606DD7F652164D5746914414D4C7A9CCE54C2888226BF77CC9887A39BA0D08D }; "2_6_2" = { - hashPrePatching = "sha256-tlnF/ZQOkLMbiEV2BqhxzQ/KixGZ30+LgOUoHvpv13s="; + hashPrePatching = "sha512-nfNCoAa1buug4pvltayzMEC8btjtx80sZZ1275L4Bqy3N9r1ZEGnx6p1M/UZPbpNtUd0jdU0ZawlAdTnxaMvVg=="; # NAR checksum; zip archive is SHA512:8751A2229D9E500A3F3A283CE24AE62F8F911507F5FDBE25AA41F31AC5026CF89433C89DC766864439A17531543829E4B43BC4D3B311F5A80B4DF0605BBD9627 }; "2_6_1" = { - hashPrePatching = "sha256-Ou4NbRo7Gh0HWviXSEHtp0PpsGDdYsN8yhR0/gQy3rY="; + hashPrePatching = "sha512-8VDjpfBHPIz18T+YymrqQkQUw25mvyUdUSQAwlsLS4ZDkg3F3qQPvSzTIavakv31gJeIweZN8Pcnw0cAkWFytw=="; # NAR checksum; zip archive is SHA512:84F0D14F8BA3AEFFE1E8A8F34BA3955629C12C6B39D34E939B14A1A30362B1BE8C7C3A29E3C75072A2D1661926607C058364ECC4E7C8F2D25EDB110182BA901C }; "2_6" = { - hashPrePatching = "sha256-AHP1mgedC9wUq+YAJD0gM4Lrl0H0UkrWyifEDC9KLog="; + hashPrePatching = "sha512-DsDkIOhsYz/XHIMCol0cLg8aPDLxo5twBfEFhkpsDVSY2dhqp+VZ5wExkz7tbypaqO52KePQlaVtGmE7mPkI9g=="; # NAR checksum; zip archive is SHA512:6F3760E71103681A0F05845D0ADADD7B55C10A57D0AC44606A5B2B88E0435DAE70129F3FFCEF9AC3794FB471196ADE78CCEE7E304DF6447EFC0D271D51ED10AB }; "2_5_2" = { - hashPrePatching = "sha256-vurAHOSWwpHZ96cLnRvb6wR+6dvTVKgoqUvlU4Qyp3g="; + hashPrePatching = "sha512-YTGC1xK7fYhyIcoF/4wqlossfRmNgQyGlXxqzn67zpTiqiidQcW5N+XXB6maZ7Yv2TOArZJmBlRpQNIPxAildg=="; # NAR checksum; zip archive is SHA512:9E4CDF5E2E311CA5AD5750B91EA5163D8E727813F9A88200D80013657C45B33B0A51112FD5816DEBE264B99B1244B8555C0F8B9ECCFC6F87C45E67BBD1C28B06 }; "2_5_1" = { - hashPrePatching = "sha256-tB6UXQPFHPIhV5bERkv/kAktyMn3dnlI4nzIwXO9imQ="; + hashPrePatching = "sha512-DStLgwHDaHpe3ddKSHChU6i70gfZiVaAYm+aRrov7BvLndGamYGD2AM77sV9uSgQ0DJlfYTH2TTrp2uhD7uPkg=="; # NAR checksum; zip archive is SHA512:8DDE88D72704027AD810E1B41AB6950AA5BF4A2FA93AAB7F06CDFF878CC65EE7673E1691AFEB8385F37D2035DFCBC686674EB7AF4AC279F934C46131DA56F721 }; "2_5" = { url = "https://github.com/TASEmulators/BizHawk/releases/download/2.5/BizHawk-2.5.0.zip"; - hashPrePatching = "sha256-OPuNxgHWYBCw6gkkllir0U9z+ZF3K8K2o24W00MWgLk="; + hashPrePatching = "sha512-+lMzqhCZHk3SqLeXGXvbuDURrn5nwnw9p79kqH2ywxb4t6KVJPcSvoPi90ByeUgxmoog1H2pWAkufJPN5c6kQw=="; # NAR checksum; zip archive is SHA512:CB35924402932F13F3ED7159BD5991C58790287C856DB6958F41B631A36C345C5DDEA5249D75560AE608C2900C939579FB395989939F99BF11B4B3B9E2E671AE }; "2_4_2" = { - hashPrePatching = "sha256-0ZunzBTO4O+B89N5PI0+AeVFBhe9shEtCANsYJBVdaY="; + hashPrePatching = "sha512-waqbTSdE4sjDtZc0h61CgzlJ9AUj5RxvkpPnhgJm8V/RYuWkaE6Kvg0i7ul1q46sFTn3nI/+cfWt9Af0s44EzA=="; # NAR checksum; zip archive is SHA512:EA4B8451E461B11BFC1962333ABE7FBB38F3D10CBE0BBF30AB250798FC281CC2C43807AEFFD352AB61DCF889B761AC8394BD095F37F5F22506B634FA529E4DE0 }; "2_4_1" = { - hashPrePatching = "sha256-uORUDsPh7ePRzB69wqKW65Cch35Fjg34Q0aa7Vcf+dA="; + hashPrePatching = "sha512-q8Ot2oTSU3adweTBBDZrWEre5FFEKMdWRRG39MbicJFN5zR1gpg3duRgE+AW36PUL8KXtNDeLypDnHQjxWmkLA=="; # NAR checksum; zip archive is SHA512:B0DEB73C155D60487F6E77F29B247B15F441E01782820DD42D22916CCF24F73B5AA95AF6A1BFED9B982984CDD06E83AEC2A21D61584EDADF4E8C8B763CD8BD27 }; "2_4" = { - hashPrePatching = "sha256-vgocYt0Wo5LSLxHF5W1aFi2xqkklMYhZP4zHOIFbCb0="; + hashPrePatching = "sha512-Uq+0zzMT8WbgZeriMOfQriWX5JYw2u7yycze/h6mE3Ofc31+vbhrIBXZrkK/ZDXRl5bGEpiBTdItswFSez6IGQ=="; # NAR checksum; zip archive is SHA512:34CB1E7FB300391341BA9C0BDEB87FCE93800A5B90EC971850F88B72C408E0C97AC62BD12DC1BAFBF7A5A15566BEA6726445C167832987477654BB535B69F408 }; "2_3_3" = { - hashPrePatching = "sha256-kLPNpnggnrc7TgA6NCC0P/tkFiUgTHVyKPdUz0UX1EE="; + hashPrePatching = "sha512-V2yYsjGsUkCdLTJ6qdsmCbe1MmgkjdA3yIzb9JE1Cahn9A32Kek/t5cqDwmSA82chpffsBXk3qMLfUfsRTaLgg=="; # NAR checksum; zip archive is SHA512:CF83E1357EEFB8BDF1542850D66D8007D620E4050B5715DC83F4A921D36CE9CE47D0D13C5D85F2B0FF8318D2877EEC2F63B931BD47417A81A538327AF927DA3E }; "2_3_2" = { - hashPrePatching = "sha256-x2DwrzBkPAGhlov/eU/VwXuHVP/Rv0o7pZptmsSQLJU="; + hashPrePatching = "sha512-WQpoK0M+ew44JE688w7O8gUfYdzTisJhy2dn7o31mNLA6+CmPnFY5h91fpipB50ZOLzfJLSSEH5v1lbujK3nZA=="; # NAR checksum; zip archive is SHA512:67E8C7E57E735E7319647A35FB09C504240D7BC885EB8D753554FC3E4A2A61AF6A91C07DCF8BF45006F5044DF6E98A8073BA61F14B4C7BCB1B25D5A9B630D817 }; # older releases won't pass prereq checker w/o WINE libs, relevant change was https://github.com/TASEmulators/BizHawk/commit/27a4062ea22e5cb4a81628580ce47fec7a2709a5#diff-aff17d6fcf6169cad48e9c8d08145b0de360e874aa8ffee0ea66e636cccda39f }; diff --git a/Dist/install_git_hooks.ps1 b/Dist/install_git_hooks.ps1 new file mode 100755 index 00000000000..370bc20171d --- /dev/null +++ b/Dist/install_git_hooks.ps1 @@ -0,0 +1,20 @@ +#!/usr/bin/env pwsh +$targetDir = "$PSScriptRoot/../.git/hooks" +if (Test-Path $targetDir -PathType Container) { # is Git repo + $PSCommandFilename = Split-Path $PSCommandPath -Leaf + $shimChecksum = (Get-FileHash "$PSScriptRoot/git_hook_shim.sh").Hash + foreach ($f in Get-ChildItem "$PSScriptRoot/git_hooks") { + $hook = Split-Path $f -LeafBase + $target = Join-Path $targetDir $hook + if (!(Test-Path $target -PathType Leaf)) { # target file doesn't exist + echo "[$PSCommandFilename] creating Git hook $hook" + Copy-Item "$PSScriptRoot/git_hook_shim.sh" $target + #TODO use symlinks on Linux + } elseif ((Get-FileHash $target).Hash -ne $shimChecksum) { # files differ + $head = Get-Content $target -TotalCount 3 + echo "[$PSCommandFilename] found existing Git hook $hook, please resolve conflict manually (ignore if checking out older commits)" + exit 1 + } + # else no-op + } +} diff --git a/Dist/launch-scripts.nix b/Dist/launch-scripts.nix index f1516966021..2e1b7c0be55 100644 --- a/Dist/launch-scripts.nix +++ b/Dist/launch-scripts.nix @@ -66,8 +66,9 @@ in writeShellScript "emuhawk-mono-wrapper" '' set -e - if [ ! -e "$BIZHAWK_HOME/EmuHawk.exe" ]; then - printf "no such file: %s\n" "$BIZHAWK_HOME/EmuHawk.exe" + mainAppPath="$BIZHAWK_HOME/${bizhawkAssemblies.hawkSourceInfo.mainAppFilename}" + if [ ! -e "$mainAppPath" ]; then + printf "no such file: %s\n" "$mainAppPath" exit 1 fi @@ -87,8 +88,7 @@ fi printf "(capturing output in %s/EmuHawkMono_last*.txt)\n" "$PWD" >&2 exec '${redirectOutputToFiles}' EmuHawkMono_laststdout.txt EmuHawkMono_laststderr.txt \ - '${lib.getBin bizhawkAssemblies.mono}/bin/mono' \ - "$BIZHAWK_HOME/EmuHawk.exe" --config=config.json "$@" + '${lib.getBin bizhawkAssemblies.mono}/bin/mono' "$mainAppPath" --config=config.json "$@" ''; in { inherit emuhawk; diff --git a/Dist/nix_expr_usage_docs.md b/Dist/nix_expr_usage_docs.md index c4d5ebe03db..a2045f74c92 100644 --- a/Dist/nix_expr_usage_docs.md +++ b/Dist/nix_expr_usage_docs.md @@ -39,7 +39,9 @@ Nix functions and data: - `buildExtraManagedDepsFor` - `buildUnmanagedDepsFor` - `depsForHistoricalRelease` +- `IDEs` - `launchScriptsForLocalBuild` +- `populateHawkSourceInfo` - `releaseTagSourceInfos` - `splitReleaseArtifact` @@ -49,7 +51,7 @@ There are a few parameters you can tweak without writing a full Nix expression: - `--argstr buildConfig Debug` builds the BizHawk solution in Debug configuration. - `--argstr extraDefines "CoolFeatureFlag"` adds to ``. - `--arg initConfig {}` can be used to set up keybinds and such, though you probably won't want to use `--arg` for that. -- Check the source for the full list. +- Check [the source](default.nix) for the full list. Every installable can also be used with `nix-shell`. Omitting `-A` is the same as `nix-shell -A emuhawk-latest`. + Exe + + + + + + + + + + + + diff --git a/ExternalProjects/BizHawk.AnalyzersTests/Properties/AssemblyInfo.cs b/ExternalProjects/BizHawk.AnalyzersTests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..ae411c7a1b9 --- /dev/null +++ b/ExternalProjects/BizHawk.AnalyzersTests/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)] diff --git a/ExternalProjects/BizHawk.AnalyzersTests/run_tests_debug.sh b/ExternalProjects/BizHawk.AnalyzersTests/run_tests_debug.sh new file mode 100755 index 00000000000..6bb3fec83e7 --- /dev/null +++ b/ExternalProjects/BizHawk.AnalyzersTests/run_tests_debug.sh @@ -0,0 +1,2 @@ +#!/bin/sh +cd "$(dirname "$(realpath "$0")")" && ./.run_tests_with_configuration.sh "Debug" "$@" diff --git a/ExternalProjects/BizHawk.AnalyzersTests/run_tests_release.sh b/ExternalProjects/BizHawk.AnalyzersTests/run_tests_release.sh new file mode 100755 index 00000000000..ef5dbe332c2 --- /dev/null +++ b/ExternalProjects/BizHawk.AnalyzersTests/run_tests_release.sh @@ -0,0 +1,2 @@ +#!/bin/sh +cd "$(dirname "$(realpath "$0")")" && ./.run_tests_with_configuration.sh "Release" "$@" diff --git a/ExternalProjects/BizHawk.SrcGen.ReflectionCache/ReflectionCacheGenerator.cs b/ExternalProjects/BizHawk.SrcGen.ReflectionCache/ReflectionCacheGenerator.cs index 7170b791e8a..81e2d903184 100644 --- a/ExternalProjects/BizHawk.SrcGen.ReflectionCache/ReflectionCacheGenerator.cs +++ b/ExternalProjects/BizHawk.SrcGen.ReflectionCache/ReflectionCacheGenerator.cs @@ -77,7 +77,7 @@ public static class ReflectionCache {{ private const string EMBED_PREFIX = ""{nSpace}.""; - private static Type[]? _types; + private static Type[]? _types = null; private static readonly Assembly Asm = typeof({nSpace}.ReflectionCache).Assembly; @@ -88,17 +88,19 @@ public static class ReflectionCache public static IEnumerable EmbeddedResourceList(string extraPrefix) {{ var fullPrefix = EMBED_PREFIX + extraPrefix; - return Asm.GetManifestResourceNames().Where(s => s.StartsWith(fullPrefix, StringComparison.Ordinal)).Select(s => s.RemovePrefix(fullPrefix)); + return Asm.GetManifestResourceNames().Where(s => s.StartsWithOrdinal(fullPrefix)) // seems redundant with `RemovePrefix`, but we only want these in the final list + .Select(s => s.RemovePrefix(fullPrefix)); }} public static IEnumerable EmbeddedResourceList() - => EmbeddedResourceList(string.Empty); + => EmbeddedResourceList(string.Empty); // can't be simplified to `Asm.GetManifestResourceNames` call /// not found public static Stream EmbeddedResourceStream(string embedPath) {{ var fullPath = EMBED_PREFIX + embedPath; - return Asm.GetManifestResourceStream(fullPath) ?? throw new ArgumentException($""resource at {{fullPath}} not found"", nameof(embedPath)); + return Asm.GetManifestResourceStream(fullPath) + ?? throw new ArgumentException(paramName: nameof(embedPath), message: $""resource at {{fullPath}} not found""); }} }} }} diff --git a/ExternalProjects/BizHawk.SrcGen.SettingsUtil/DefaultSetterGenerator.cs b/ExternalProjects/BizHawk.SrcGen.SettingsUtil/DefaultSetterGenerator.cs index ff81f112d88..bfb95e166ec 100644 --- a/ExternalProjects/BizHawk.SrcGen.SettingsUtil/DefaultSetterGenerator.cs +++ b/ExternalProjects/BizHawk.SrcGen.SettingsUtil/DefaultSetterGenerator.cs @@ -99,7 +99,7 @@ public static partial class SettingsUtil if (cds.AttributeLists.SelectMany(e => e.Attributes) .Any(e => e.Name.NormalizeWhitespace().ToFullString() == "CoreSettings")) { - var symbol = semanticModel.GetDeclaredSymbol(cds); + var symbol = semanticModel.GetDeclaredSymbol(cds, context.CancellationToken); if (symbol is not null) // probably never happens? { CreateDefaultSetter(source, symbol); diff --git a/ExternalProjects/BizHawk.SrcGen.VersionInfo/VersionInfoGenerator.cs b/ExternalProjects/BizHawk.SrcGen.VersionInfo/VersionInfoGenerator.cs index 62dcb4ff451..d9deaeabe2a 100644 --- a/ExternalProjects/BizHawk.SrcGen.VersionInfo/VersionInfoGenerator.cs +++ b/ExternalProjects/BizHawk.SrcGen.VersionInfo/VersionInfoGenerator.cs @@ -49,7 +49,7 @@ public void Execute(GeneratorExecutionContext context) var rev = ExecuteGitWithArguments($"-C {projectDir} rev-list HEAD --count") ?? string.Empty; var branch = ExecuteGitWithArguments($"-C {projectDir} rev-parse --abbrev-ref HEAD") ?? "master"; - var shortHash = ExecuteGitWithArguments($"-C {projectDir} log -1 --format=\"%h\"") ?? "000000000"; + var hash = ExecuteGitWithArguments($"-C {projectDir} log -1 --format=\"%H\"") ?? "0000000000000000000000000000000000000000"; // Generated source code string source = $@"namespace BizHawk.Common @@ -58,7 +58,8 @@ public static partial class VersionInfo {{ public const string SVN_REV = ""{rev}""; public const string GIT_BRANCH = ""{branch}""; - public const string GIT_SHORTHASH = ""{shortHash}""; + public const string GIT_HASH = ""{hash}""; + public const string GIT_SHORTHASH = ""{hash.Substring(startIndex: 0, length: 9)}""; }} }} "; diff --git a/ExternalProjects/NLua/NLua.csproj b/ExternalProjects/NLua/NLua.csproj index a01032d2efd..0355705fc3c 100644 --- a/ExternalProjects/NLua/NLua.csproj +++ b/ExternalProjects/NLua/NLua.csproj @@ -22,12 +22,12 @@ - $(NoWarn);IDE0005 + $(NoWarn);IDE0005;SA1514;SA1614;SA1616 disable true - + diff --git a/ExternalProjects/PcxFileTypePlugin.HawkQuantizer/OctreeQuantizer.cs b/ExternalProjects/PcxFileTypePlugin.HawkQuantizer/OctreeQuantizer.cs index 5b597c35f26..38fd81b0019 100644 --- a/ExternalProjects/PcxFileTypePlugin.HawkQuantizer/OctreeQuantizer.cs +++ b/ExternalProjects/PcxFileTypePlugin.HawkQuantizer/OctreeQuantizer.cs @@ -435,10 +435,7 @@ public void ConstructPalette(List palette, ref int paletteIndex) // Loop through children looking for leaves for (int index = 0; index < 8; index++) { - if (null != _children[index]) - { - _children[index].ConstructPalette(palette, ref paletteIndex); - } + _children[index]?.ConstructPalette(palette, ref paletteIndex); } } } diff --git a/ExternalProjects/SDL2/CMakeLists.txt b/ExternalProjects/SDL2/CMakeLists.txt index 78f357a1dfb..64e4f527540 100644 --- a/ExternalProjects/SDL2/CMakeLists.txt +++ b/ExternalProjects/SDL2/CMakeLists.txt @@ -9,7 +9,7 @@ project(SDL2-BizHawk C CXX) # set(SDL_ATOMIC ON) # Used in HIDAPI (and disabling it just makes it emulate atomics rather than use intrinsics) set(SDL_AUDIO OFF) set(SDL_VIDEO ON) # Used in mupen64plus + OpenGL/D3D9 display methods -set(SDL_RENDER OFF) +set(SDL_RENDER ON) # We use the software renderer for GDI+ImGui 2D rendering set(SDL_EVENTS ON) # Implied by SDL_VIDEO and SDL_JOYSTICK set(SDL_JOYSTICK ON) # Used for our SDL2 input adapter set(SDL_HAPTIC OFF) @@ -69,6 +69,7 @@ set(SDL_DIRECTFB OFF) set(SDL_DUMMYVIDEO OFF) set(SDL_RPI OFF) set(SDL_RENDER_D3D OFF) +set(SDL_RENDER_METAL OFF) set(SDL_VIVANTE OFF) set(SDL_VULKAN OFF) set(SDL_KMSDRM OFF) @@ -120,7 +121,7 @@ if(WIN32) target_compile_options(usb PRIVATE -w) endif() - set_target_properties(usb PROPERTIES VERSION 1.0.26) + set_target_properties(usb PROPERTIES VERSION 1.0.27) target_include_directories(usb BEFORE PUBLIC libusb/libusb PRIVATE libusb/msvc diff --git a/ExternalProjects/SDL2/SDL b/ExternalProjects/SDL2/SDL index 8f14dc69987..0805990668b 160000 --- a/ExternalProjects/SDL2/SDL +++ b/ExternalProjects/SDL2/SDL @@ -1 +1 @@ -Subproject commit 8f14dc699877c8b059e67d30431c91b91e0299f0 +Subproject commit 0805990668bdf92f4602520c9b7fed6edd90b448 diff --git a/ExternalProjects/SDL2/libusb b/ExternalProjects/SDL2/libusb index 4239bc3a500..d52e355daa0 160000 --- a/ExternalProjects/SDL2/libusb +++ b/ExternalProjects/SDL2/libusb @@ -1 +1 @@ -Subproject commit 4239bc3a50014b8e6a5a2a59df1fff3b7469543b +Subproject commit d52e355daa09f17ce64819122cb067b8a2ee0d4b diff --git a/ExternalProjects/TestromSuiteReportProcessor/.gitignore b/ExternalProjects/TestromSuiteReportProcessor/.gitignore new file mode 100644 index 00000000000..4c7473dedd6 --- /dev/null +++ b/ExternalProjects/TestromSuiteReportProcessor/.gitignore @@ -0,0 +1,2 @@ +/bin +/obj diff --git a/ExternalProjects/TestromSuiteReportProcessor/Program.cs b/ExternalProjects/TestromSuiteReportProcessor/Program.cs new file mode 100644 index 00000000000..8071121155c --- /dev/null +++ b/ExternalProjects/TestromSuiteReportProcessor/Program.cs @@ -0,0 +1,47 @@ +using System.Xml; + +using FailingCase = (string DispNameWithTestClass, string Stdout); + +if (args.Length < 1) { + Console.WriteLine("invoke as `dotnet run -- /path/to/proj.coverage.xml`"); + return; +} +FileInfo fi = new(args[0]); +if (!fi.Exists) throw new Exception("no such file"); +XmlDocument doc = new(); +doc.Load(fi.Open(FileMode.Open)); +if (doc.DocumentElement?.Name is not "testsuites") throw new Exception("not a dotnet test results file"); +var suite = doc.DocumentElement.FirstChild as XmlElement; +if (!(suite?.GetAttribute("name") ?? string.Empty).StartsWith("BizHawk.Tests.Testroms.", StringComparison.Ordinal)) throw new Exception("not for testroms project"); + +Dictionary> failuresByMessage = new(); +List GetListFor(string message) + => failuresByMessage.TryGetValue(message, out var l) ? l : (failuresByMessage[message] = new()); +static string NaiveSubstringAfter(string needle, string haystack) + => haystack.Substring(haystack.IndexOf(needle, StringComparison.Ordinal) + needle.Length); +foreach (var childNode in suite!) { + if (childNode is not XmlElement @case) continue; + if (@case.HasChildNodes && @case.Name is "testcase" && @case.FirstChild is XmlElement { Name: "failure"} fail) { + GetListFor(fail.GetAttribute("message")).Add(( + @case.GetAttribute("name").Replace(""", "\""), + NaiveSubstringAfter(needle: "Standard Output:", haystack: @case.InnerText) + )); + } +} + +foreach (var (message, failures) in failuresByMessage) { + if (message.Contains("screenshot contains correct value unexpectedly", StringComparison.Ordinal)) { + Console.WriteLine("drop these from known-bad:"); + foreach (var @case in failures) Console.WriteLine($"\t{@case.DispNameWithTestClass}"); + } else { + Console.WriteLine(message); + foreach (var (caseDisplayName, stdout) in failures) { + Console.WriteLine($"\t{caseDisplayName}"); + foreach (var line in stdout.Split('\n')) { + if (!string.IsNullOrWhiteSpace(line) && !line.Contains("not in DB", StringComparison.Ordinal)) { + Console.WriteLine($"\t\t{line.Trim()}"); + } + } + } + } +} diff --git a/ExternalProjects/TestromSuiteReportProcessor/TestromSuiteReportProcessor.csproj b/ExternalProjects/TestromSuiteReportProcessor/TestromSuiteReportProcessor.csproj new file mode 100644 index 00000000000..5b8fad6cf88 --- /dev/null +++ b/ExternalProjects/TestromSuiteReportProcessor/TestromSuiteReportProcessor.csproj @@ -0,0 +1,11 @@ + + + net8.0 + + + + true + enable + Exe + + diff --git a/ExternalProjects/iso-parser/ISOFile.cs b/ExternalProjects/iso-parser/ISOFile.cs index 4ebce8fbd46..13862830cd5 100644 --- a/ExternalProjects/iso-parser/ISOFile.cs +++ b/ExternalProjects/iso-parser/ISOFile.cs @@ -89,6 +89,7 @@ public ISOFile() /// /// The stream which we are using to parse the image. /// Should already be located at the start of the image. + /// will seek forward this number of sectors before reading public bool Parse(Stream s, int startSector = 16) { this.VolumeDescriptors = new List(); diff --git a/ExternalProjects/iso-parser/ISOParser.csproj b/ExternalProjects/iso-parser/ISOParser.csproj index 094f54bdcb6..f29a363a6cf 100644 --- a/ExternalProjects/iso-parser/ISOParser.csproj +++ b/ExternalProjects/iso-parser/ISOParser.csproj @@ -4,6 +4,7 @@ + $(NoWarn);MA0060;SA1514 disable diff --git a/ExternalProjects/libchd-rs-capi/build_release.bat b/ExternalProjects/libchd-rs-capi/build_release.bat index 66864f45293..05d411177ec 100644 --- a/ExternalProjects/libchd-rs-capi/build_release.bat +++ b/ExternalProjects/libchd-rs-capi/build_release.bat @@ -1,3 +1,10 @@ -@cargo b --release -@copy target\release\chd_capi.dll ..\..\Assets\dll -@copy target\release\chd_capi.dll ..\..\output\dll +:: To maintain Win7/8/8.1 compat for release builds, we must compile using the *-win7-windows-msvc target +:: This is a "Tier 3" target, which does not have prebuilt binaries (e.g. for standard library) available in rustup +:: The simplest way to use this target is to use the build-std argument, which builds the standard library +:: This requires the user to install the nightly toolchain (build-std is not in stable), then add the rust-src component +:: rustup toolchain install nightly-x86_64-pc-windows-msvc +:: rustup component add rust-src --toolchain nightly-x86_64-pc-windows-msvc +:: These don't need to be done for developer only builds (e.g. debug), only release builds need this +@cargo +nightly-x86_64-pc-windows-msvc b --release -Z build-std --target x86_64-win7-windows-msvc +@copy target\x86_64-win7-windows-msvc\release\chd_capi.dll ..\..\Assets\dll +@copy target\x86_64-win7-windows-msvc\release\chd_capi.dll ..\..\output\dll diff --git a/ExternalToolProjects/.run_with_tool.sh b/ExternalToolProjects/.run_with_tool.sh index 9d4b9848000..1337ede4024 100755 --- a/ExternalToolProjects/.run_with_tool.sh +++ b/ExternalToolProjects/.run_with_tool.sh @@ -1,2 +1,2 @@ #!/bin/sh -../../output/EmuHawkMono.sh --mono-no-redirect --open-ext-tool-dll=$(printf *.csproj | head -c-7) "$@" +../../output/EmuHawkMono.sh --open-ext-tool-dll=$(printf *.csproj | head -c-7) "$@" diff --git a/ExternalToolProjects/AutoGenConfig/ConfigEditorUIGenerators.cs b/ExternalToolProjects/AutoGenConfig/ConfigEditorUIGenerators.cs index ebf24cfafd2..3cae1bdb426 100644 --- a/ExternalToolProjects/AutoGenConfig/ConfigEditorUIGenerators.cs +++ b/ExternalToolProjects/AutoGenConfig/ConfigEditorUIGenerators.cs @@ -171,6 +171,7 @@ public sealed class ConfigEditorMetadata public readonly ComparisonColors ComparisonColors; + /// global cache /// default of uses public ConfigEditorMetadata(ConfigEditorCache cache, ComparisonColors? colors = null) { @@ -209,7 +210,7 @@ public abstract class ConfigPropEditorUIGen : IConfigPropEditor /// /// Default implementation didn't play nice with , so multiple behaviours are available for custom generators: - /// inherit from or instead. + /// inherit from or instead. /// protected abstract bool MatchesBaseline(TListed c, ConfigEditorMetadata metadata); @@ -273,12 +274,12 @@ public abstract class ConfigPropEditorUIGenRefT : ConfigPropEdi where TValue : class { /// - /// Checked in in the case where the baseline value is . - /// If its implementation returns , an exception will be thrown, otherwise ' implementation will be called with . + /// Checked in in the case where the baseline value is . + /// If its implementation returns , an exception will be thrown, otherwise ' implementation will be called with . /// protected abstract bool AllowNull { get; } - /// + /// protected override bool MatchesBaseline(TListed c, ConfigEditorMetadata metadata) => metadata.BaselineValues[c.Name] is TValue v ? TValueEquality(GetTValue(c), v) @@ -289,7 +290,7 @@ public abstract class ConfigPropEditorUIGenValT : ConfigPropEdi where TListed : Control where TValue : struct { - /// + /// protected override bool MatchesBaseline(TListed c, ConfigEditorMetadata metadata) => metadata.BaselineValues[c.Name] is TValue v ? TValueEquality(GetTValue(c), v) : throw new Exception(); } @@ -373,7 +374,7 @@ protected override FlowLayoutPanel GenerateControl(string nesting, PropertyInfo protected override string SerializeTValue(string? v) => v == null ? NULL_SERIALIZATION : $"\"{v}\""; - protected override bool TValueEquality(string? a, string? b) => string.Equals(a, b) || string.IsNullOrEmpty(a) && string.IsNullOrEmpty(b); + protected override bool TValueEquality(string? a, string? b) => a == b || string.IsNullOrEmpty(a) && string.IsNullOrEmpty(b); } public sealed class UnrepresentablePropEditorUIGen : ConfigPropEditorUIGen diff --git a/ExternalToolProjects/DATParser/CustomMainForm.cs b/ExternalToolProjects/DATParser/CustomMainForm.cs index 2aa33bdad89..539786ea156 100644 --- a/ExternalToolProjects/DATParser/CustomMainForm.cs +++ b/ExternalToolProjects/DATParser/CustomMainForm.cs @@ -3,7 +3,6 @@ using System.Windows.Forms; using BizHawk.Client.Common; -using BizHawk.Common; using BizHawk.Client.EmuHawk; namespace BizHawk.DATTool diff --git a/ExternalToolProjects/DATParser/DATConverter.cs b/ExternalToolProjects/DATParser/DATConverter.cs index 5ee0fb304ec..6f06d3a16ab 100644 --- a/ExternalToolProjects/DATParser/DATConverter.cs +++ b/ExternalToolProjects/DATParser/DATConverter.cs @@ -6,9 +6,6 @@ using System.Windows.Forms; using System.IO; -using BizHawk.Client.Common; -using BizHawk.Client.EmuHawk; - namespace BizHawk.DATTool { public partial class DATConverter : Form diff --git a/ExternalToolProjects/DATParser/DATParser.csproj b/ExternalToolProjects/DATParser/DATParser.csproj index 102b25d0efc..bd9b60e07fb 100644 --- a/ExternalToolProjects/DATParser/DATParser.csproj +++ b/ExternalToolProjects/DATParser/DATParser.csproj @@ -14,10 +14,10 @@ - True + True - SettingsSingleFileGenerator + SettingsSingleFileGenerator diff --git a/ExternalToolProjects/DATParser/DATParserBase.cs b/ExternalToolProjects/DATParser/DATParserBase.cs index e72a71d58fb..87de952efa2 100644 --- a/ExternalToolProjects/DATParser/DATParserBase.cs +++ b/ExternalToolProjects/DATParser/DATParserBase.cs @@ -1,5 +1,5 @@ #nullable disable - + using System; using System.Collections.Generic; using System.Text; @@ -53,13 +53,13 @@ protected void AppendCSVData(List data) { // hash sb.Append(d.HASH); - sb.Append("\t"); + sb.Append('\t'); // status sb.Append(d.Status); - sb.Append("\t"); + sb.Append('\t'); // name sb.Append(d.Name); - sb.Append("\t"); + sb.Append('\t'); // system sb.Append(d.System); @@ -89,37 +89,37 @@ protected void AppendCSVData(List data) // notes if (d.Notes != null) { - sb.Append("\t"); + sb.Append('\t'); sb.Append(d.Notes); } else if (cnt++ <= last) { - sb.Append("\t"); + sb.Append('\t'); } // metadata if (d.MetaData != null) { - sb.Append("\t"); + sb.Append('\t'); sb.Append(d.MetaData); } else if (cnt++ <= last) { - sb.Append("\t"); + sb.Append('\t'); } // region if (d.Region != null) { - sb.Append("\t"); + sb.Append('\t'); sb.Append(d.Region); } else if (cnt++ <= last) { - sb.Append("\t"); + sb.Append('\t'); } // force core if (d.ForcedCore != null) { - sb.Append("\t"); + sb.Append('\t'); sb.Append(d.ForcedCore); } @@ -137,8 +137,8 @@ public class GameDB // COL0: Hash public string SHA1 { get; set; } public string MD5 { get; set; } - public string CRC32 { get; set; } - // COL1: Status code indicator + public string CRC32 { get; set; } + // COL1: Status code indicator public string Status { get; set; } // COL2: Game title public string Name { get; set; } @@ -160,9 +160,9 @@ public string HASH { if (!string.IsNullOrWhiteSpace(SHA1)) return "SHA1:" + SHA1; - else if (!string.IsNullOrWhiteSpace(MD5)) - return "MD5:" + MD5; - else if (!string.IsNullOrWhiteSpace(CRC32)) + else if (!string.IsNullOrWhiteSpace(MD5)) + return "MD5:" + MD5; + else if (!string.IsNullOrWhiteSpace(CRC32)) return "CRC32:" + CRC32; throw new InvalidOperationException("No valid hash available?"); diff --git a/ExternalToolProjects/DATParser/NOINTROParser.cs b/ExternalToolProjects/DATParser/NOINTROParser.cs index 32a4e18a5b4..704a41fc3a6 100644 --- a/ExternalToolProjects/DATParser/NOINTROParser.cs +++ b/ExternalToolProjects/DATParser/NOINTROParser.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Xml.Linq; using System.Windows.Forms; +using BizHawk.Common.StringExtensions; namespace BizHawk.DATTool { @@ -69,9 +70,9 @@ public override string ParseDAT(string[] filePath) { GameDB item = new GameDB(); item.Name = g.Value; - item.SHA1 = g.Elements("rom").First().Attribute("sha1").Value.ToUpper(); - item.MD5 = g.Elements("rom").First().Attribute("md5").Value.ToUpper(); - item.CRC32 = g.Elements("rom").First().Attribute("crc").Value.ToUpper(); + item.SHA1 = g.Elements("rom").First().Attribute("sha1").Value.ToUpperInvariant(); + item.MD5 = g.Elements("rom").First().Attribute("md5").Value.ToUpperInvariant(); + item.CRC32 = g.Elements("rom").First().Attribute("crc").Value.ToUpperInvariant(); item.System = GameDB.GetSystemCode(SysType); ParseNOINTROFlags(item); @@ -99,7 +100,7 @@ public override string ParseDAT(string[] filePath) AddCommentBlock("Translated"); AppendCSVData(trans); - var good = working.Where(st => st.Status == "" || st.Status == null).OrderBy(na => na.Name).ToList(); + var good = working.Where(st => string.IsNullOrEmpty(st.Status)).OrderBy(na => na.Name).ToList(); AddCommentBlock("Believed Good"); AppendCSVData(good); } @@ -121,7 +122,7 @@ private void ParseNOINTROFlags(GameDB g) string a = RemoveUnneededOptions(nameString); // process data contained in () - string[] d = a.ToString().Split('(', ')'); + var d = a.Split('(', ')'); if (d.Length > 0) { @@ -146,7 +147,7 @@ private void ParseNOINTROFlags(GameDB g) string f = d[i].Trim(); // check for language - if (IsLanguageFlag(f) == true) + if (IsLanguageFlag(f)) { g.Notes = f; continue; @@ -155,26 +156,26 @@ private void ParseNOINTROFlags(GameDB g) // version - ignore // check development status (not currently implemented) - if (IsDevelopmenttStatus(f) == true) + if (IsDevelopmenttStatus(f)) { continue; } // check copyright status (not currently implemented) - if (IsCopyrightStatus(f) == true) + if (IsCopyrightStatus(f)) { continue; } // country flag(s) - if (IsCountryFlag(f) == true) + if (IsCountryFlag(f)) { g.Region = f; continue; } // language - if present add to notes - if (IsLanguageFlag(f) == true) + if (IsLanguageFlag(f)) { g.Notes = f; continue; @@ -207,14 +208,14 @@ private void ParseNOINTROFlags(GameDB g) if (e.Where(str => // bad dump - str == "b" || str.StartsWith("b ")).ToList().Count > 0) + str == "b" || str.StartsWithOrdinal("b ")).ToList().Count > 0) { // RomStatus.BadDump g.Status = "B"; } else if (e.Where(str => // BIOS - str == "BIOS" || str.StartsWith("BIOS ")).ToList().Count > 0) + str == "BIOS" || str.StartsWithOrdinal("BIOS ")).ToList().Count > 0) { // RomStatus.BIOS g.Status = "I"; @@ -259,7 +260,7 @@ public static bool IsLanguageFlag(string s) { foreach (var x in LC) { - if (s == x || s.StartsWith(x + ",") || s.EndsWith("," + x)) + if (s == x || s.StartsWithOrdinal(x + ",") || s.EndsWithOrdinal("," + x)) { b = true; break; @@ -286,7 +287,7 @@ public static bool IsCountryFlag(string s) { foreach (var x in CC) { - if (s == x || s.StartsWith(x) || s.EndsWith(x)) + if (s == x || s.StartsWithOrdinal(x) || s.EndsWithOrdinal(x)) { b = true; break; diff --git a/ExternalToolProjects/DATParser/TOSECParser.cs b/ExternalToolProjects/DATParser/TOSECParser.cs index 72f89051e4f..c10baed05c9 100644 --- a/ExternalToolProjects/DATParser/TOSECParser.cs +++ b/ExternalToolProjects/DATParser/TOSECParser.cs @@ -6,6 +6,8 @@ using System.Xml.Linq; using System.Windows.Forms; +using BizHawk.Common.StringExtensions; + namespace BizHawk.DATTool { public class TOSECParser : DATParser @@ -70,9 +72,9 @@ public override string ParseDAT(string[] filePath) { GameDB item = new GameDB(); item.Name = g.Value; - item.SHA1 = g.Elements("rom").First().Attribute("sha1").Value.ToUpper(); - item.MD5 = g.Elements("rom").First().Attribute("md5").Value.ToUpper(); - item.CRC32 = g.Elements("rom").First().Attribute("crc").Value.ToUpper(); + item.SHA1 = g.Elements("rom").First().Attribute("sha1").Value.ToUpperInvariant(); + item.MD5 = g.Elements("rom").First().Attribute("md5").Value.ToUpperInvariant(); + item.CRC32 = g.Elements("rom").First().Attribute("crc").Value.ToUpperInvariant(); item.System = GameDB.GetSystemCode(SysType); ParseTOSECFlags(item); @@ -104,7 +106,7 @@ public override string ParseDAT(string[] filePath) AddCommentBlock("Home Brew"); AppendCSVData(pd); - var good = working.Where(st => st.Status == "" || st.Status == null).OrderBy(na => na.Name).ToList(); + var good = working.Where(st => string.IsNullOrEmpty(st.Status)).OrderBy(na => na.Name).ToList(); AddCommentBlock("Believed Good"); AppendCSVData(good); } @@ -126,7 +128,7 @@ private void ParseTOSECFlags(GameDB g) string a = RemoveUnneededOptions(nameString); // process data contained in () - string[] d = a.ToString().Split('(', ')'); + var d = a.Split('(', ')'); if (d.Length > 0) { @@ -171,27 +173,27 @@ private void ParseTOSECFlags(GameDB g) } // country flag(s) - if (IsCountryFlag(f) == true) + if (IsCountryFlag(f)) { g.Region = f; continue; } // language - if present add to notes - if (IsLanguageFlag(f) == true) + if (IsLanguageFlag(f)) { g.Notes = f; continue; } // check copyright status (not currently implemented) - if (IsCopyrightStatus(f) == true) + if (IsCopyrightStatus(f)) { continue; } // check development status (not currently implemented) - if (IsDevelopmenttStatus(f) == true) + if (IsDevelopmenttStatus(f)) { continue; } @@ -225,28 +227,28 @@ private void ParseTOSECFlags(GameDB g) if (e.Where(str => // bad dump - str == "b" || str.StartsWith("b ") || + str == "b" || str.StartsWithOrdinal("b ") || // virus - str == "v" || str.StartsWith("v ") || + str == "v" || str.StartsWithOrdinal("v ") || // under dump - str == "u" || str.StartsWith("u ")).ToList().Count > 0) + str == "u" || str.StartsWithOrdinal("u ")).ToList().Count > 0) { // RomStatus.BadDump g.Status = "B"; } else if (e.Where(str => // cracked - str == "cr" || str.StartsWith("cr ") || + str == "cr" || str.StartsWithOrdinal("cr ") || // fixed - str == "f" || str.StartsWith("f ") || + str == "f" || str.StartsWithOrdinal("f ") || // hack - str == "h" || str.StartsWith("h ") || + str == "h" || str.StartsWithOrdinal("h ") || // modified - str == "m" || str.StartsWith("m ") || + str == "m" || str.StartsWithOrdinal("m ") || // pirated - str == "p" || str.StartsWith("p ") || + str == "p" || str.StartsWithOrdinal("p ") || // trained - str == "t" || str.StartsWith("t ") + str == "t" || str.StartsWithOrdinal("t ") ).ToList().Count > 0) { // RomStatus.Hack @@ -254,7 +256,7 @@ private void ParseTOSECFlags(GameDB g) } else if (e.Where(str => // over dump - str == "o" || str.StartsWith("o ")).ToList().Count > 0) + str == "o" || str.StartsWithOrdinal("o ")).ToList().Count > 0) { // RomStatus.Overdump g.Status = "O"; @@ -268,7 +270,7 @@ private void ParseTOSECFlags(GameDB g) } else if (e.Where(str => // translated - str == "tr" || str.StartsWith("tr ")).ToList().Count > 0) + str == "tr" || str.StartsWithOrdinal("tr ")).ToList().Count > 0) { // RomStatus.TranslatedRom g.Status = "T"; @@ -312,7 +314,7 @@ public static bool IsLanguageFlag(string s) { foreach (var x in LC) { - if (s == x || s.StartsWith(x) || s.EndsWith(x)) + if (s == x || s.StartsWithOrdinal(x) || s.EndsWithOrdinal(x)) { b = true; break; @@ -342,7 +344,7 @@ public static bool IsCountryFlag(string s) { foreach (var x in CC) { - if (s == x || s.StartsWith(x) || s.EndsWith(x)) + if (s == x || s.StartsWithOrdinal(x) || s.EndsWithOrdinal(x)) { b = true; break; diff --git a/ExternalToolProjects/DBMan/DB.cs b/ExternalToolProjects/DBMan/DB.cs index fb7451f5aa3..18f509a2580 100644 --- a/ExternalToolProjects/DBMan/DB.cs +++ b/ExternalToolProjects/DBMan/DB.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; +using BizHawk.Common.StringExtensions; using Community.CsharpSqlite.SQLiteClient; namespace BizHawk.DBManTool @@ -45,7 +45,7 @@ public string NameWithTheFlipped { get { - if (!Name.EndsWith(", The")) return Name; + if (!Name.EndsWithOrdinal(", The")) return Name; return "The "+Name.Substring(0, Name.Length-5); } } @@ -110,11 +110,11 @@ public class Game public static class DB { - public static List Roms = new List(); - public static List Games = new List(); - public static Dictionary GameMap = new Dictionary(); + public static List Roms { get; private set; } = new List(); + public static List Games { get; } = new List(); + public static Dictionary GameMap { get; } = new Dictionary(); - public static SqliteConnection Con; + public static SqliteConnection Con { get; set; } public static void LoadDbForSystem(string system) { @@ -455,4 +455,4 @@ public static void DeleteRom(Rom rom) cmd.Dispose(); } } -} \ No newline at end of file +} diff --git a/ExternalToolProjects/DBMan/DBMan.cs b/ExternalToolProjects/DBMan/DBMan.cs index 81345b1a8cc..8bb90031d60 100644 --- a/ExternalToolProjects/DBMan/DBMan.cs +++ b/ExternalToolProjects/DBMan/DBMan.cs @@ -1,13 +1,8 @@ #nullable disable using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; using System.Drawing; using System.IO; -using System.Linq; -using System.Text; using System.Windows.Forms; namespace BizHawk.DBManTool @@ -157,7 +152,7 @@ void cancelButton_Click(object sender, EventArgs e) void saveButton_Click(object sender, EventArgs e) { // Check if any changes were made - if (SelectedRom.New == false && RomChangesMade() == false) + if (!SelectedRom.New && !RomChangesMade()) return; int saveMode = 0; @@ -197,7 +192,7 @@ void saveButton_Click(object sender, EventArgs e) if (romListView.SelectedItems.Count > 0) { // Update the side listing - var romListItem = (ListViewItem)romListView.SelectedItems[0]; + var romListItem = romListView.SelectedItems[0]; romListItem.SubItems[0] = new ListViewItem.ListViewSubItem(romListItem, SelectedRom.DisplayName); romListItem.SubItems[1] = new ListViewItem.ListViewSubItem(romListItem, SelectedRom.Region); romListItem.SubItems[2] = new ListViewItem.ListViewSubItem(romListItem, SelectedRom.VersionTags); @@ -303,14 +298,14 @@ void exportGameDBToolStripMenuItem_Click(object sender, EventArgs e) string regionStr = ""; if (rom.Region != null) { - if (rom.Region.IndexOf("Japan") >= 0) regionStr += "J"; - if (rom.Region.IndexOf("USA") >= 0) regionStr += "U"; - if (rom.Region.IndexOf("Europe") >= 0) regionStr += "E"; - if (rom.Region.IndexOf("Brazil") >= 0) regionStr += "B"; - if (rom.Region.IndexOf("Taiwan") >= 0) regionStr += "T"; - if (rom.Region.IndexOf("Korea") >= 0) regionStr += "K"; - if (rom.Region.IndexOf("Australia") >= 0) regionStr += "Aus"; - if (rom.Region.IndexOf("World") >= 0) regionStr += "W"; + if (rom.Region.Contains("Japan")) regionStr += "J"; + if (rom.Region.Contains("USA")) regionStr += "U"; + if (rom.Region.Contains("Europe")) regionStr += "E"; + if (rom.Region.Contains("Brazil")) regionStr += "B"; + if (rom.Region.Contains("Taiwan")) regionStr += "T"; + if (rom.Region.Contains("Korea")) regionStr += "K"; + if (rom.Region.Contains("Australia")) regionStr += "Aus"; + if (rom.Region.Contains("World")) regionStr += "W"; } string romName = rom.NameWithTheFlipped; @@ -344,4 +339,4 @@ void deleteButton_Click(object sender, EventArgs e) loadRomsForSelectedSystem(); } } -} \ No newline at end of file +} diff --git a/ExternalToolProjects/DBMan/DirectoryScan.cs b/ExternalToolProjects/DBMan/DirectoryScan.cs index a91e4583ec0..ec73f97f604 100644 --- a/ExternalToolProjects/DBMan/DirectoryScan.cs +++ b/ExternalToolProjects/DBMan/DirectoryScan.cs @@ -18,7 +18,7 @@ public static List GetRomInfos(string path) foreach (var f in files) { - if (IsRomFile(f.Extension, f.Length) == false) + if (!IsRomFile(f.Extension, f.Length)) continue; romInfos.Add(RomHasher.Generate(f.FullName)); } @@ -56,11 +56,11 @@ public static void MergeRomInfosWithDatabase(IList roms) foreach (var rom in roms) { - if (RomInDatabase(rom.MD5) == false) + if (!RomInDatabase(rom.MD5)) { InsertRom(rom); - if (GameInDatabase(rom) == false) + if (!GameInDatabase(rom)) InsertGame(rom); } } diff --git a/ExternalToolProjects/DBMan/DiscHash.cs b/ExternalToolProjects/DBMan/DiscHash.cs index a9354d84308..3f0395542c8 100644 --- a/ExternalToolProjects/DBMan/DiscHash.cs +++ b/ExternalToolProjects/DBMan/DiscHash.cs @@ -1,20 +1,16 @@ #nullable disable using System; -using System.Runtime.InteropServices; using System.Threading.Tasks; -using System.Linq; using System.IO; using System.Collections.Generic; -using BizHawk.Common; using BizHawk.Emulation.DiscSystem; namespace BizHawk.DBManTool { class DiscHash { - static List FindExtensionsRecurse(string dir, string extUppercaseWithDot) { List ret = new List(); @@ -44,7 +40,6 @@ static List FindExtensionsRecurse(string dir, string extUppercaseWithDot public void Run(string[] args) { - string indir = null; string dpTemp = null; string fpOutfile = null; @@ -109,10 +104,10 @@ public void Run(string[] args) progress++; Console.WriteLine("{0}/{1} [{2}] {3}", progress, todo.Count, bizHashId, Path.GetFileNameWithoutExtension(fiCue)); outf.WriteLine("bizhash:{0} datahash:{1:X8} //{2}", bizHashId, redumpHash, name); - if (FoundHashes.ContainsKey(bizHashId)) + if (FoundHashes.TryGetValue(bizHashId, out string foundBizHashId)) { - Console.WriteLine("--> COLLISION WITH: {0}", FoundHashes[bizHashId]); - outf.WriteLine("--> COLLISION WITH: {0}", FoundHashes[bizHashId]); + Console.WriteLine("--> COLLISION WITH: {0}", foundBizHashId); + outf.WriteLine("--> COLLISION WITH: {0}", foundBizHashId); } else FoundHashes[bizHashId] = name; @@ -130,4 +125,4 @@ public void Run(string[] args) } //MyRun() } //class PsxRedump -} \ No newline at end of file +} diff --git a/ExternalToolProjects/DBMan/PsxDBJob.cs b/ExternalToolProjects/DBMan/PsxDBJob.cs index 9aad125d831..400e73e8e7e 100644 --- a/ExternalToolProjects/DBMan/PsxDBJob.cs +++ b/ExternalToolProjects/DBMan/PsxDBJob.cs @@ -3,15 +3,11 @@ using System; using System.Globalization; using System.IO; -using System.Xml; using System.Xml.Linq; using System.Collections.Generic; using System.Linq; -using System.Text; - using BizHawk.Common; -using BizHawk.Emulation.DiscSystem; namespace BizHawk.DBManTool { @@ -61,8 +57,7 @@ public void Run(string[] args) Console.WriteLine("merging"); foreach (var rr in rdpsx.Records) { - HashRecord hr; - if (!hashes.TryGetValue(rr.crc, out hr)) + if (!hashes.TryGetValue(rr.crc, out var hr)) continue; hr.matched = true; //correct name to redump current @@ -109,8 +104,8 @@ public void Load(string datpath) CRC32 spec_crc_calc = new() { Current = 0 }; //TODO is the current usage (invert initial state, don't invert final state) equivalent to only inverting the final state? --yoshi foreach (var rom in game.Elements("rom")) { - var ext = Path.GetExtension(rom.Attribute("name").Value).ToLower(); - if (ext == ".cue") continue; + var ext = Path.GetExtension(rom.Attribute("name").Value); + if (ext.Equals(".cue", StringComparison.OrdinalIgnoreCase)) continue; uint onecrc = uint.Parse(rom.Attribute("crc").Value, NumberStyles.HexNumber); int size = int.Parse(rom.Attribute("size").Value); spec_crc_calc.Incorporate(onecrc, size); @@ -125,4 +120,4 @@ public void Load(string datpath) } } } -} \ No newline at end of file +} diff --git a/ExternalToolProjects/DBMan/RomHasher.cs b/ExternalToolProjects/DBMan/RomHasher.cs index 2614d9ffc6d..dcdff196f3d 100644 --- a/ExternalToolProjects/DBMan/RomHasher.cs +++ b/ExternalToolProjects/DBMan/RomHasher.cs @@ -6,6 +6,7 @@ using System.Text; using BizHawk.Common; +using BizHawk.Common.StringExtensions; using BizHawk.Emulation.DiscSystem; namespace BizHawk.DBManTool @@ -48,7 +49,7 @@ static InitialRomInfo GenerateRomHashDirect(string file, byte[] filebytes) // Parse the filename to guess things about the rom var name = Path.GetFileNameWithoutExtension(fileInfo.Name); - if (name.StartsWith("[BIOS] ")) + if (name.StartsWithOrdinal("[BIOS] ")) name = name.Replace("[BIOS] ","") + " [BIOS]"; string modifiers = ""; @@ -62,7 +63,7 @@ static InitialRomInfo GenerateRomHashDirect(string file, byte[] filebytes) // parse out modifiers var mods = new List(); - modifiers = modifiers.Replace(")", ";").Replace("]",";"); + modifiers = modifiers.Replace(')', ';').Replace(']', ';'); modifiers = modifiers.Replace("(", "").Replace("[", ""); var m_ = modifiers.Split(';'); foreach (var mi in m_) @@ -78,7 +79,7 @@ static InitialRomInfo GenerateRomHashDirect(string file, byte[] filebytes) if (info.VersionTags.Length != 0) info.VersionTags += ";"; - switch (mi.ToLower()) + switch (mi.ToLowerInvariant()) { case "j": case "jp": @@ -260,4 +261,4 @@ static bool isDiscImage(string file) return false; } } -} \ No newline at end of file +} diff --git a/ExternalToolProjects/FakeTemporalAA/FakeTemporalAA.csproj b/ExternalToolProjects/FakeTemporalAA/FakeTemporalAA.csproj new file mode 100644 index 00000000000..f61ddc82c4e --- /dev/null +++ b/ExternalToolProjects/FakeTemporalAA/FakeTemporalAA.csproj @@ -0,0 +1,11 @@ + + + + + true + $(NoWarn);IDE0065;SA1200 + + + + + diff --git a/ExternalToolProjects/FakeTemporalAA/FakeTemporalAAToolForm.cs b/ExternalToolProjects/FakeTemporalAA/FakeTemporalAAToolForm.cs new file mode 100644 index 00000000000..df6aabb25ad --- /dev/null +++ b/ExternalToolProjects/FakeTemporalAA/FakeTemporalAAToolForm.cs @@ -0,0 +1,83 @@ +namespace BizHawk.Experiments.FakeTemporalAA; + +using System; + +using BizHawk.Bizware.Graphics; +using BizHawk.Client.Common; +using BizHawk.Client.EmuHawk; +using BizHawk.Emulation.Common; + +[ExternalTool(TOOL_NAME, Description = "Naively blends each frame with the previous")] +public sealed class FakeTemporalAAToolForm: ToolFormBase, IExternalToolForm +{ + private const string TOOL_NAME = "Fake Temporal Anti-aliasing"; + + private BitmapBuffer? _bbPrev = null; + + [RequiredService] + public IVideoProvider? _maybeVideoProvider { get; set; } + + public ApiContainer? _maybeAPIContainer { get; set; } + + private ApiContainer APIs + => _maybeAPIContainer!; + + protected override string WindowTitleStatic + => TOOL_NAME; + + public FakeTemporalAAToolForm() + => _ = _maybeVideoProvider; // used via ToolFormBase.MainForm + + private void ClearDrawingSurface() + => _maybeAPIContainer?.Gui?.WithSurface(DisplaySurfaceID.EmuCore, g => g.ClearGraphics(DisplaySurfaceID.EmuCore)); + + protected override void Dispose(bool disposing) + { + ClearDrawingSurface(); + base.Dispose(disposing); + } + + public override void Restart() + { + _bbPrev = null; + ClearDrawingSurface(); + } + + public override void UpdateValues(ToolFormUpdateType type) + { + const int OPACITY_MASK = 0xFF << 24; + static void Invert(Span buf) + { + for (var i = 0; i < buf.Length; i++) buf[i] = OPACITY_MASK | ~buf[i]; //TODO vectorise? + } + static int AverageXRGB(int c1, int c2) + { + //TODO can this be improved? + const int R_MASK = 0xFF0000; + const int G_MASK = 0xFF00; + const int B_MASK = 0xFF; + var r = (((c1 & R_MASK) + (c2 & R_MASK)) / 2) & R_MASK; + var g = (((c1 & G_MASK) + (c2 & G_MASK)) / 2) & G_MASK; + var b = (((c1 & B_MASK) + (c2 & B_MASK)) / 2) & B_MASK; + var c3 = r | g | b; + c3 &= ~OPACITY_MASK; + return OPACITY_MASK | c3; + } + if (type is not (ToolFormUpdateType.PreFrame or ToolFormUpdateType.FastPreFrame)) return; + + var bbCurrent = MainForm.MakeScreenshotImage(); + var spanCurrent = bbCurrent.AsSpan(); + Invert(spanCurrent); + if (_bbPrev is null) // initialisation + { + _bbPrev = bbCurrent; + return; + } + + var spanPrev = _bbPrev.AsSpan(); // was inverted before saving + for (var i = 0; i < spanCurrent.Length; i++) spanPrev[i] = AverageXRGB(spanPrev[i], spanCurrent[i]); + Invert(spanPrev); + APIs.Gui.WithSurface(DisplaySurfaceID.EmuCore, g => g.DrawImage(_bbPrev!.ToSysdrawingBitmap(), 0, 0, cache: false)); + _bbPrev = bbCurrent; + } +} diff --git a/ExternalToolProjects/FakeTemporalAA/build_debug.sh b/ExternalToolProjects/FakeTemporalAA/build_debug.sh new file mode 120000 index 00000000000..c2127aded12 --- /dev/null +++ b/ExternalToolProjects/FakeTemporalAA/build_debug.sh @@ -0,0 +1 @@ +../.build_debug.sh \ No newline at end of file diff --git a/ExternalToolProjects/FakeTemporalAA/build_release.sh b/ExternalToolProjects/FakeTemporalAA/build_release.sh new file mode 120000 index 00000000000..801b8e5998a --- /dev/null +++ b/ExternalToolProjects/FakeTemporalAA/build_release.sh @@ -0,0 +1 @@ +../.build_release.sh \ No newline at end of file diff --git a/ExternalToolProjects/FakeTemporalAA/run_with_tool.sh b/ExternalToolProjects/FakeTemporalAA/run_with_tool.sh new file mode 120000 index 00000000000..b7cf6138ab7 --- /dev/null +++ b/ExternalToolProjects/FakeTemporalAA/run_with_tool.sh @@ -0,0 +1 @@ +../.run_with_tool.sh \ No newline at end of file diff --git a/ExternalToolProjects/NET48ExternalToolForm.targets b/ExternalToolProjects/NET48ExternalToolForm.targets index f65ba71ec9c..822130c2c6d 100644 --- a/ExternalToolProjects/NET48ExternalToolForm.targets +++ b/ExternalToolProjects/NET48ExternalToolForm.targets @@ -8,6 +8,9 @@ + diff --git a/README.md b/README.md index f088ac2bd04..66fc682870a 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,13 @@ EmuHawk is a multi-system emulator written in C#. As well as quality-of-life fea A7800Hawk, Atari2600Hawk, C64Hawk, ColecoHawk, GBHawk, IntelliHawk, NesHawk, O2Hawk, PCEHawk, SMSHawk, TI83Hawk, VectrexHawk, and ZXHawk are bespoke emulation cores written in C#. MSXHawk is a bespoke emulation core written in C++. More info [below](#cores). [![(latest) release | GitHub](https://img.shields.io/github/release/TASEmulators/BizHawk.svg?logo=github&logoColor=333333&sort=semver&style=popout)](https://github.com/TASEmulators/BizHawk/releases/latest) -[![latest dev build | GitLab CI](https://img.shields.io/badge/latest_dev_build-GitLab_CI-orange.svg?logo=gitlab&style=popout)](https://gitlab.com/TASVideos/BizHawk/-/pipelines/master/latest) [![GitHub open issues counter](https://img.shields.io/github/issues-raw/TASEmulators/BizHawk.svg?logo=github&logoColor=333333&style=popout)](https://github.com/TASEmulators/BizHawk/issues) -[![built with nix](https://builtwithnix.org/badge.svg)](#nixnixos) +[![latest dev build (Windows) | GitHub Actions](https://img.shields.io/badge/latest_dev_build_(Windows)-GitHub_Actions-8250DF?logo=github&logoColor=333333&style=popout)](https://nightly.link/TASEmulators/BizHawk/workflows/ci/master/BizHawk-dev-windows.zip) +[![latest dev build (Linux) | GitHub Actions](https://img.shields.io/badge/latest_dev_build_(Linux)-GitHub_Actions-8250DF?logo=github&logoColor=333333&style=popout)](https://nightly.link/TASEmulators/BizHawk/workflows/ci/master/BizHawk-dev-linux.zip) +[![Build and test main solution](https://github.com/TASEmulators/BizHawk/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/TASEmulators/BizHawk/actions/workflows/ci.yml) + +[![reproducible via | Nix](https://img.shields.io/badge/reproducible_via-Nix-5277C3?logo=nixos&logoColor=7EBAE4&style=popout)](#nixnixos) [![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/5365/badge)](https://bestpractices.coreinfrastructure.org/projects/5365) --- @@ -113,7 +116,8 @@ Run `EmuHawk.exe` to start. If startup is blocked by a Windows SmartScreen dialo EmuHawk does have some prerequisites which it can't work without (it will let you know if they're missing). The list is [here](https://github.com/TASEmulators/BizHawk-Prereqs/blob/master/README), and we've made an all-in-one installer which you can get [here](https://github.com/TASEmulators/BizHawk-Prereqs/releases/latest). You should only have to run this once per machine, unless the changelog says we need something extra. -We will be following Microsoft in dropping support for old versions of Windows, that is, we reserve the right to ignore your problems unless you've updated to at least Win11 21H2 (initial release) or Win10 21H2. Read more on [MSDN](https://docs.microsoft.com/en-us/lifecycle/faq/windows). +We will be following Microsoft in dropping support for old versions of Windows, that is, we reserve the right to ignore your problems +unless you've updated to at least Win11 21H2 (initial release) or Win10 22H2. Read more on [MSDN](https://docs.microsoft.com/en-us/lifecycle/faq/windows). A "backport" release, [1.13.2](https://github.com/TASEmulators/BizHawk/releases/tag/1.13.2), is available for users of Windows XP, 7, or 8.1 32-bit. It has many bugs that will never be fixed and it doesn't have all the features of the later versions. @@ -159,22 +163,28 @@ Dev builds and a few recent releases can be built with Nix, either by cloning th See the [dedicated Nix usage readme](Dist/nix_expr_usage_docs.md) for what attributes are exposed. If you use a non-NixOS distro with Nix installed, you just need to add one argument and your host graphics drivers will be picked up thanks to nixGL. +You can also quickly get a development setup, including the .NET SDK and an IDE, with the provided `shell.nix`. See the [Nix-specific docs](Dist/nix_expr_usage_docs.md#ide-setup) for details. + [to top](#bizhawk) ### Development builds Development builds are made automatically whenever someone contributes. Because of this, we recommend using a release for work that requires stability (such as TASing), and only switching to a dev build if there's a specific change or addition you need. +[![recent dev builds | GitHub Actions](https://img.shields.io/badge/recent_dev_builds-GitHub_Actions-8250DF?logo=github&logoColor=333333&style=popout)](https://github.com/TASEmulators/BizHawk/actions/workflows/ci.yml) +[![latest dev build (Windows) | GitHub Actions](https://img.shields.io/badge/latest_dev_build_(Windows)-GitHub_Actions-8250DF?logo=github&logoColor=333333&style=popout)](https://nightly.link/TASEmulators/BizHawk/workflows/ci/master/BizHawk-dev-windows.zip) +[![latest dev build (Linux) | GitHub Actions](https://img.shields.io/badge/latest_dev_build_(Linux)-GitHub_Actions-8250DF?logo=github&logoColor=333333&style=popout)](https://nightly.link/TASEmulators/BizHawk/workflows/ci/master/BizHawk-dev-linux.zip) + [![recent dev builds | GitLab CI](https://img.shields.io/badge/recent_dev_builds-GitLab_CI-orange.svg?logo=gitlab&style=popout)](https://gitlab.com/TASVideos/BizHawk/-/pipelines) [![latest dev build | GitLab CI](https://img.shields.io/badge/latest_dev_build-GitLab_CI-orange.svg?logo=gitlab&style=popout)](https://gitlab.com/TASVideos/BizHawk/-/pipelines/master/latest) -> Note: Due to recent changes by AppVeyor, artifact downloads are no longer available. Use the GitLab CI artifacts. +Click one of the buttons above to download a dev build (they're also at the top of this readme). +- On the GitHub Actions page for a workflow run or job, click "Summary", then on the relevant download button under the "Artifacts" heading. +- On the GitLab CI page for a Pipeline, click "Jobs", then on the download button for the relevant `package_devbuild_*` job. (On the Pipelines list page, there's also a download button on each Pipeline. On a Job page, the download button is on the right.) -Click one of the buttons above to download a dev build (they're also at the top of this readme). AppVeyor uses Windows and GitLab CI uses Linux, but they work all the same. -* ~~On the AppVeyor page for a Build, click "Artifacts", then `BizHawk_Developer--#.zip`.~~ -* On the GitLab CI page for a Pipeline, click "Jobs", then the download button on the right under the heading "Package". (On the Pipelines list page, there's also a download button on each Pipeline—choose `package_devbuild_*:archive` there.) - -To find the dev builds for a specific commit, you can click the green checkmark next to it (in the [commit history](https://github.com/TASEmulators/BizHawk/commits/master), for example) for a dropdown, then click either "Details" link to go to AppVeyor/GitLab. +To find the dev builds for a specific commit, you can click the green checkmark next to it (in the [commit history](https://github.com/TASEmulators/BizHawk/commits/master), for example) +for a dropdown, then click the link for any GitHub Actions workflow. +(GitLab has a similar feature, but its Pipelines don't appear in GitHub's UI.) ## Building @@ -182,7 +192,7 @@ See the [contributor guidelines](https://github.com/TASEmulators/BizHawk/blob/ma tl;dr: - On Unix, run `Dist/BuildRelease.sh` (uses .NET SDK CLI). You can also use Rider or VS Code. -- On Windows, run in [VS2022](https://visualstudio.microsoft.com/vs/community). You can also use the command-line, Rider, or VS Code. +- On Windows, run in [VS2022](https://visualstudio.microsoft.com/vs/community). You can also use the command-line (`dotnet build BizHawk.sln`), Rider, or VS Code. [to top](#bizhawk) @@ -194,16 +204,7 @@ EmuHawk takes some command-line options which aren't well-documented; you might On Windows 8.1/10, it's easiest to use PowerShell for this. For example, to pass `--lua=C:\path\to\script.lua` as the first argument and `C:\path\to\rom.n64` as the second, navigate to the BizHawk install folder and run: ```pwsh -(New-Object System.Diagnostics.Process -Property @{StartInfo=(New-Object System.Diagnostics.ProcessStartInfo -Property @{FileName="$PWD\EmuHawk.exe";Arguments='"--lua=C:\path\to\script.lua" "C:\path\to\rom.n64"'})}).Start() -``` -Note: PowerShell's `cd` doesn't seem to change the CWD of child processes. Just open a shell from the install folder. Don't @ me. - -For char escaping tips you're on your own. It might help to split up the command so you can identify syntax errors: -```pwsh -$s = '"--lua=C:\path\to\script.lua" "C:\path\to\rom.n64"' -$startInfo = New-Object System.Diagnostics.ProcessStartInfo -Property @{FileName="$PWD\EmuHawk.exe";Arguments=$s} -$proc = New-Object System.Diagnostics.Process -Property @{StartInfo=$startInfo} -$proc.Start() +./EmuHawk.exe '--lua=C:\path\to\script.lua' 'C:\path\to\rom.n64' ``` On Linux, you can pass arguments to `EmuHawkMono.sh` as expected and they will be forwarded to `mono`. (You can also `export` env. vars.) All the arguments work as on Windows, with some caveats: @@ -352,7 +353,7 @@ Please don't bother core devs about these WIPs unless you're looking to contribu ## Support and troubleshooting A short [FAQ](https://tasvideos.org/Bizhawk/FAQ) is provided on the TASVideos wiki. If your problem is one of the many not answered there, and you can't find it in the [issue tracker search](https://github.com/TASEmulators/BizHawk/issues?q=is%3Aissue+PUT_ISSUE_KEYWORDS_HERE), you can try: -- `#emulation` on [the TASVideos Discord](https://discordapp.com/invite/GySG2b6) +- `#bizhawk` on [the TASVideos Discord](https://discordapp.com/invite/GySG2b6) - Also the more specialised channels `#tas-production` and `#scripting` (for Lua) on that server - For the .NET API, [the ApiHawk server](https://discord.gg/UPhN4um3px) - The [TASVideos forum for BizHawk](https://tasvideos.org/Forum/Subforum/64) diff --git a/References/BizHawk.Analyzer.dll b/References/BizHawk.Analyzer.dll index cefe7b12f31..600c82f8d9f 100644 Binary files a/References/BizHawk.Analyzer.dll and b/References/BizHawk.Analyzer.dll differ diff --git a/References/BizHawk.SrcGen.ReflectionCache.dll b/References/BizHawk.SrcGen.ReflectionCache.dll index 6c08fb3ce88..574c2bc02e0 100644 Binary files a/References/BizHawk.SrcGen.ReflectionCache.dll and b/References/BizHawk.SrcGen.ReflectionCache.dll differ diff --git a/References/BizHawk.SrcGen.SettingsUtil.dll b/References/BizHawk.SrcGen.SettingsUtil.dll index 926863c62bb..02a042e57e0 100644 Binary files a/References/BizHawk.SrcGen.SettingsUtil.dll and b/References/BizHawk.SrcGen.SettingsUtil.dll differ diff --git a/References/BizHawk.SrcGen.VersionInfo.dll b/References/BizHawk.SrcGen.VersionInfo.dll index 9934224fffb..87cdf9c34b8 100644 Binary files a/References/BizHawk.SrcGen.VersionInfo.dll and b/References/BizHawk.SrcGen.VersionInfo.dll differ diff --git a/References/ISOParser.dll b/References/ISOParser.dll index 46570e94afc..168c1ac10d6 100644 Binary files a/References/ISOParser.dll and b/References/ISOParser.dll differ diff --git a/References/PcxFileTypePlugin.HawkQuantizer.dll b/References/PcxFileTypePlugin.HawkQuantizer.dll index 0163d96cafd..1fef2d3f244 100644 Binary files a/References/PcxFileTypePlugin.HawkQuantizer.dll and b/References/PcxFileTypePlugin.HawkQuantizer.dll differ diff --git a/References/Virtu.dll b/References/Virtu.dll index effa151391c..d99870a539b 100644 Binary files a/References/Virtu.dll and b/References/Virtu.dll differ diff --git a/appveyor.yml b/appveyor.yml index 73aebc0e478..18ad8595e28 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,6 @@ version: 0.0.0.{build} branches: only: - - master image: Visual Studio 2022 assembly_info: patch: true diff --git a/contributing.md b/contributing.md index 6703f73c7d7..5f5471dac14 100644 --- a/contributing.md +++ b/contributing.md @@ -70,6 +70,7 @@ It's probably a good idea to get the .NET SDK, even if you're not working on a . - Linux - Install the .NET 8 SDK (package name is usually `dotnet-sdk-8.0`, see [full instructions](https://learn.microsoft.com/en-gb/dotnet/core/install/linux)). - VS Community isn't available for Linux, but Rider and VS Code are. + - Nix/NixOS users can get the .NET SDK ephemerally with the provided `shell.nix`. For IDE setup and more, see the [Nix-specific docs](Dist/nix_expr_usage_docs.md#ide-setup). - macOS - Note that EmuHawk does not currently support macOS. - Install the .NET 8 SDK [manually](https://learn.microsoft.com/en-gb/dotnet/core/install/macos) or with Homebrew. @@ -120,7 +121,8 @@ The source for EmuHawk, plus DiscoHawk and the supporting libraries, is in `/src EmuHawk's project file `/src/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj` includes the other projects [in a tree](https://gitlab.com/TASVideos/BizHawk/snippets/1886666), and they're all included in `/BizHawk.sln`. In VS2022, open `BizHawk.sln`, then select the "BizHawk.Client.EmuHawk | Release" configuration to build and run. -On the command-line, from root of the repo run `Dist/BuildRelease.sh` (Unix) or `Dist\QuickTestBuildAndPackage_Release.bat` (Windows). Run EmuHawk from `output` in the repo's root. +To build from the command-line on Windows, simply run `dotnet build BizHawk.sln` from the repository's root, and then `output\EmuHawk` will be available. Alternatively, you can run one of the existing build scripts that apply additional checks and configurations, such as `Dist\QuickTestBuildAndPackage_Release.bat`. +To build from the command-line on Unix, run `Dist/BuildRelease.sh`, and then `output/EmuHawkMono.sh` will be available. There are 2 build configurations. Besides `Release` there is `Debug`, which *does not run* bytecode optimisations, *does not remove* debugging symbols, *enables* additional logging and assertions, and *enables* some features. On Windows, a `Debug` executable will spawn a console window for stdout. Note there is also a "stronger" release build in the form of `VersionInfo.DeveloperBuild == false`, which is only used by GitLab CI for preparing a release (during `Dist/UpdateVersionInfoForRelease.sh`). @@ -321,5 +323,5 @@ See [Waterbox readme](https://github.com/TASEmulators/BizHawk/tree/master/waterb By contributing, you declare that any additions or changes either: - were authored by you and you are willing to license your contributions to us under the [project's license](https://github.com/TASEmulators/BizHawk/tree/master/LICENSE); or - were copied from a compatibly open-source, publicly-licensed source and are properly attributed, including licensing info. -> **Important** +> [!IMPORTANT] > We will **not** accept any contributions "authored" by GitHub Copilot or similar ML tools. diff --git a/default.nix b/default.nix index fbb9af2ba90..d73717466b8 100644 --- a/default.nix +++ b/default.nix @@ -1,7 +1,7 @@ { system ? builtins.currentSystem -, pkgs ? import (fetchTarball { - url = "https://github.com/NixOS/nixpkgs/archive/23.11.tar.gz"; - sha256 = "1ndiv385w1qyb3b18vw13991fzb9wg4cl21wglk89grsfsnra41k"; +, pkgs ? import (builtins.fetchTarball { + url = "https://github.com/NixOS/nixpkgs/archive/24.05.tar.gz"; + sha256 = "1lr1h35prqkd1mkmzriwlpvxcb34kmhc9dnr48gkm8hh089hifmx"; }) { inherit system; } , lib ? pkgs.lib , stdenv ? pkgs.stdenvNoCC @@ -31,22 +31,29 @@ in { , dotnet-sdk_6 ? pkgs.dotnet-sdk_6 , dotnet-sdk_5 ? let result = builtins.tryEval pkgs.dotnet-sdk_5; in if result.success then result.value - else (import (fetchTarball { - url = "https://github.com/NixOS/nixpkgs/archive/5234f4ce9340fffb705b908fff4896faeddb8a12^.tar.gz"; - sha256 = "0glawbqvvvbiz1gn7i1skhaqw96ilgdds6gzq7mj29kfk4vkzng1"; + else (import (fetchzip { + url = "https://github.com/NixOS/nixpkgs/archive/a8f575995434695a10b574d35ca51b0f26ae9049.tar.gz"; # commit immediately before .NET 5 was removed + hash = "sha512-3ysJjKK1lYV1r/zLohyuD1fiK+8TD3MMA3TrX9fb42nKqzfGGW62Aom7ltiyyxbVbBYOCXUy41Z5Y0j2VOxRKw=="; }) { inherit system; }).dotnet-sdk_5 , git ? pkgs.gitMinimal # only when building from-CWD (`-local`) # rundeps , coreutils ? pkgs.coreutils +, kate ? pkgs.kate.overrideAttrs (oldAttrs: { + patches = (oldAttrs.patches or []) ++ [ (fetchpatch { + url = "https://invent.kde.org/utilities/kate/-/commit/9ddf4f0c9eb3c26a0ab33c862d2b161bcbdc6a6e.patch"; # Fix name of OmniSharp LSP binary + hash = "sha256-a2KqoxuuVhfAQUJA3/yEQb1QCoa1JCvLz7BZZnSLnzI="; + }) ]; +}) , libgdiplus ? pkgs.libgdiplus , libGL ? pkgs.libGL , lua ? pkgs.lua54Packages.lua , mono ? null -, nixGLChannel ? (pkgs.nixgl or import (fetchTarball { +, nixGLChannel ? (pkgs.nixgl or import (fetchzip { url = "https://github.com/guibou/nixGL/archive/489d6b095ab9d289fe11af0219a9ff00fe87c7c5.tar.gz"; - sha256 = "03kwsz8mf0p1v1clz42zx8cmy6hxka0cqfbfasimbj858lyd930k"; + hash = "sha512-GvV707ftLvE0MCTfMJb/M86S2Nxf3vai+HPwq0QvJylmMBwliqYx/nW8X2ja2ruOHzaw3MXXmAxjnv5MMUn07w=="; }) { inherit system; }) , nixGL ? nixGLChannel.auto.nixGLDefault +, omnisharp-roslyn ? pkgs.omnisharp-roslyn #, nixVulkan ? nixGLChannel.auto.nixVulkanNvidia , openal ? pkgs.openal , SDL2 ? pkgs.SDL2 @@ -57,7 +64,6 @@ in { , debugPInvokes ? false # forwarded to Dist/launch-scripts.nix , debugDotnetHostCrashes ? false # forwarded to Dist/launch-scripts.nix , doCheck ? true # runs `Dist/BuildTest${buildConfig}.sh` -, emuhawkBuildFlavour ? "NixHawk" , extraDefines ? "" # added to ``, so ';'-separated , extraDotnetBuildFlags ? "" # currently passed to EVERY `dotnet build` and `dotnet test` invocation (and does not replace the flags for parallel compilation added by default) , forNixOS ? true @@ -104,20 +110,20 @@ in { releaseTagSourceInfos runCommand symlinkJoin writeShellScriptBin git libgdiplus libGL lua openal SDL2 udev zstd - buildConfig doCheck emuhawkBuildFlavour extraDefines extraDotnetBuildFlags; + buildConfig doCheck extraDefines extraDotnetBuildFlags; mono = if mono != null then mono # allow older Mono if set explicitly else if isVersionAtLeast "6.12.0.151" pkgs.mono.version then pkgs.mono else lib.trace "provided Mono too old, using Mono from Nixpkgs 23.05" - (import (fetchTarball { + (import (fetchzip { url = "https://github.com/NixOS/nixpkgs/archive/23.05.tar.gz"; - sha256 = "10wn0l08j9lgqcw8177nh2ljrnxdrpri7bp0g7nvrsn9rkawvlbf"; + hash = "sha512-REPJ9fRKxTefvh1d25MloT4bXJIfxI+1EvfVWq644Tzv+nuq2BmiGMiBNmBkyN9UT5fl2tdjqGliye3gZGaIGg=="; }) { inherit system; }).mono; monoBasic = fetchzip { url = "https://download.mono-project.com/repo/debian/pool/main/m/mono-basic/libmono-microsoft-visualbasic10.0-cil_4.7-0xamarin3+debian9b1_all.deb"; nativeBuildInputs = [ dpkg ]; - hash = "sha256-2m1FwpDxzqVXR6GUB3oFuTqIXCde/msb+tg8v6lIN6s="; + hash = "sha512-bPXbsVrViHAJz6PWuryo9HA6Nlv0bNqgc72pNKM/MUQM7JTUcfM0VDUzkz8vzXSqp/nt2LlAOIqIsS5D5iBIvQ=="; # tried and failed building from source, following https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=mono-basic }; }; @@ -155,7 +161,7 @@ in { ]; latestVersionFrag = lib.head releaseFrags; combined = pp // asmsFromReleaseArtifacts // releasesEmuHawkInstallables // { - inherit depsForHistoricalRelease releaseTagSourceInfos; + inherit depsForHistoricalRelease populateHawkSourceInfo releaseTagSourceInfos; bizhawkAssemblies = pp.buildAssembliesFor (fillTargetOSDifferences hawkSourceInfoDevBuild); "bizhawkAssemblies-${latestVersionFrag}" = pp.buildAssembliesFor (fillTargetOSDifferences releaseTagSourceInfos."info-${latestVersionFrag}"); @@ -172,6 +178,9 @@ in { bizhawkAssemblies = asmsFromReleaseArtifacts."bizhawkAssemblies-${latestVersionFrag}-bin"; }; emuhawk = emuhawk-local; + IDEs = { + kate = [ kate omnisharp-roslyn ]; + }; launchScriptsForLocalBuild = launchScriptsFor emuhawk-local.assemblies true; }; in combined // lib.listToAttrs (lib.concatLists (builtins.map diff --git a/libmupen64plus/mupen64plus-core/src/api/callbacks.c b/libmupen64plus/mupen64plus-core/src/api/callbacks.c index 4c903a33287..8a981030642 100644 --- a/libmupen64plus/mupen64plus-core/src/api/callbacks.c +++ b/libmupen64plus/mupen64plus-core/src/api/callbacks.c @@ -60,8 +60,8 @@ void DebugMessage(int level, const char *message, ...) if(level == M64MSG_ERROR) { - //trigger a vsync just to get out of frame advance - new_vi(); + //trigger a vsync just to get out of frame advance + new_vi(); WaitForSingleObject(rompausesem, INFINITE); } diff --git a/libmupen64plus/mupen64plus-core/src/api/vidext_sdl2_compat.h b/libmupen64plus/mupen64plus-core/src/api/vidext_sdl2_compat.h index 53da2bf49b5..e77feb60574 100644 --- a/libmupen64plus/mupen64plus-core/src/api/vidext_sdl2_compat.h +++ b/libmupen64plus/mupen64plus-core/src/api/vidext_sdl2_compat.h @@ -636,6 +636,11 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) /* If we're in OpenGL mode, just create a stub surface and we're done! */ if (flags & SDL_OPENGL) { + // make sure to set version/flag attributes, those might have been changed from the defaults + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0); SDL_VideoContext = SDL_GL_CreateContext(SDL_VideoWindow); if (!SDL_VideoContext) { return NULL; diff --git a/libmupen64plus/mupen64plus-core/src/main/rom.c b/libmupen64plus/mupen64plus-core/src/main/rom.c index d6bf6347719..459b8a7d9ce 100644 --- a/libmupen64plus/mupen64plus-core/src/main/rom.c +++ b/libmupen64plus/mupen64plus-core/src/main/rom.c @@ -125,7 +125,7 @@ m64p_error open_rom(const unsigned char* romimage, unsigned int size) char buffer[256]; unsigned char imagetype; int i; - m64p_handle CoreSection = NULL; + m64p_handle CoreSection = NULL; /* check input requirements */ if (rom != NULL) @@ -143,7 +143,18 @@ m64p_error open_rom(const unsigned char* romimage, unsigned int size) g_MemHasBeenBSwapped = 0; /* allocate new buffer for ROM and copy into this buffer */ rom_size = size; - rom = (unsigned char *) malloc(size); + + /* round rom size to the next power of 2 */ + while (rom_size & (rom_size - 1)) + { + rom_size |= rom_size >> 1; + rom_size++; + } + + if (rom_size == 0) + return M64ERR_INPUT_INVALID; + + rom = (unsigned char *) calloc(rom_size, sizeof(unsigned char)); if (rom == NULL) return M64ERR_NO_MEMORY; memcpy(rom, romimage, size); @@ -170,7 +181,7 @@ m64p_error open_rom(const unsigned char* romimage, unsigned int size) trim(ROM_PARAMS.headername); /* Remove trailing whitespace from ROM name. */ /* Look up this ROM in the .ini file and fill in goodname, etc */ - /* + /* if ((entry=ini_search_by_md5(digest)) != NULL || (entry=ini_search_by_crc(sl(ROM_HEADER.CRC1),sl(ROM_HEADER.CRC2))) != NULL) { @@ -190,16 +201,16 @@ m64p_error open_rom(const unsigned char* romimage, unsigned int size) ROM_SETTINGS.players = 0; ROM_SETTINGS.rumble = 0; } - */ + */ - strcpy(ROM_SETTINGS.goodname, ROM_PARAMS.headername); + strcpy(ROM_SETTINGS.goodname, ROM_PARAMS.headername); strcat(ROM_SETTINGS.goodname, " (unknown rom)"); - ROM_SETTINGS.savetype = 0; + ROM_SETTINGS.savetype = 0; if (ConfigOpenSection("Core", &CoreSection) == M64ERR_SUCCESS) { - ConfigSetDefaultInt(CoreSection, "SaveType", NONE, "The savetype for the game"); - ROM_SETTINGS.savetype = ConfigGetParamInt(CoreSection, "SaveType"); + ConfigSetDefaultInt(CoreSection, "SaveType", NONE, "The savetype for the game"); + ROM_SETTINGS.savetype = ConfigGetParamInt(CoreSection, "SaveType"); } ROM_SETTINGS.status = 0; diff --git a/libmupen64plus/mupen64plus-core/src/memory/dma.c b/libmupen64plus/mupen64plus-core/src/memory/dma.c index 5a539dc36ca..4ec3ac430c5 100644 --- a/libmupen64plus/mupen64plus-core/src/memory/dma.c +++ b/libmupen64plus/mupen64plus-core/src/memory/dma.c @@ -106,8 +106,8 @@ void dma_pi_read(void) { for (i=0; i < (pi_register.pi_rd_len_reg & 0xFFFFFF)+1; i++) { - sram[((pi_register.pi_cart_addr_reg-0x08000000)+i)^S8] = - ((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]; + sram[MASK_ADDR_U8(((pi_register.pi_cart_addr_reg-0x08000000)+i)^S8, sram)] = + ((unsigned char*)rdram)[MASK_ADDR_U8((pi_register.pi_dram_addr_reg+i)^S8, rdram)]; } sram_write_file(); @@ -145,8 +145,8 @@ void dma_pi_write(void) for (i=0; i<(int)(pi_register.pi_wr_len_reg & 0xFFFFFF)+1; i++) { - ((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]= - sram[(((pi_register.pi_cart_addr_reg-0x08000000)&0xFFFF)+i)^S8]; + ((unsigned char*)rdram)[MASK_ADDR_U8((pi_register.pi_dram_addr_reg+i)^S8, rdram)]= + sram[MASK_ADDR_U8((((pi_register.pi_cart_addr_reg-0x08000000)&0xFFFF)+i)^S8, sram)]; } flashram_info.use_flashram = -1; @@ -204,8 +204,8 @@ void dma_pi_write(void) unsigned long rdram_address1 = pi_register.pi_dram_addr_reg+i+0x80000000; unsigned long rdram_address2 = pi_register.pi_dram_addr_reg+i+0xa0000000; - ((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]= - rom[(((pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF)+i)^S8]; + ((unsigned char*)rdram)[MASK_ADDR_U8((pi_register.pi_dram_addr_reg+i)^S8, rdram)]= + rom[((((pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF)+i)^S8) & (rom_size - 1)]; if (!invalid_code[rdram_address1>>12]) { @@ -234,8 +234,8 @@ void dma_pi_write(void) { for (i=0; i<(int)longueur; i++) { - ((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]= - rom[(((pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF)+i)^S8]; + ((unsigned char*)rdram)[MASK_ADDR_U8((pi_register.pi_dram_addr_reg+i)^S8, rdram)]= + rom[MASK_ADDR_U8((((pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF)+i)^S8, rom)]; } } @@ -300,7 +300,7 @@ void dma_sp_write(void) for(j=0; j> 32); - rdram[pi_register.pi_dram_addr_reg/4+1] = (unsigned int)(flashram_info.status); + rdram[MASK_ADDR_U32(pi_register.pi_dram_addr_reg/4, rdram)] = (unsigned int)(flashram_info.status >> 32); + rdram[MASK_ADDR_U32(pi_register.pi_dram_addr_reg/4+1, rdram)] = (unsigned int)(flashram_info.status); break; case READ_MODE: for (i=0; i<(pi_register.pi_wr_len_reg & 0x0FFFFFF)+1; i++) { - ((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]= - flashram[(((pi_register.pi_cart_addr_reg-0x08000000)&0xFFFF)*2+i)^S8]; + ((unsigned char*)rdram)[MASK_ADDR_U8((pi_register.pi_dram_addr_reg+i)^S8, rdram)]= + flashram[MASK_ADDR_U8((((pi_register.pi_cart_addr_reg-0x08000000)&0xFFFF)*2+i)^S8, rdram)]; } break; default: diff --git a/libmupen64plus/mupen64plus-core/src/memory/memory.c b/libmupen64plus/mupen64plus-core/src/memory/memory.c index b33632b6748..41e8e10535b 100644 --- a/libmupen64plus/mupen64plus-core/src/memory/memory.c +++ b/libmupen64plus/mupen64plus-core/src/memory/memory.c @@ -139,7 +139,7 @@ void (*traceCB)(void) = NULL; //#define COUNT_WRITE_RDRAM_CALLS 1 #if defined( COUNT_WRITE_RDRAM_CALLS ) - int writerdram_count = 1; + int writerdram_count = 1; #endif int init_memory(int DoByteSwap) @@ -1765,8 +1765,8 @@ void read_rdramFBd(void) void write_rdram(void) { #if defined( COUNT_WRITE_RDRAM_CALLS ) - printf( "write_rdram, word=%i, count: %i", word, writerdram_count ); - writerdram_count++; + printf( "write_rdram, word=%i, count: %i", word, writerdram_count ); + writerdram_count++; #endif *((unsigned int *)(rdramb + (address & 0xFFFFFF))) = word; } @@ -1908,13 +1908,13 @@ void write_rdramregd(void) void read_rsp_mem(void) { if (*address_low < 0x1000) - { + { *rdword = *((unsigned int *)(SP_DMEMb + (*address_low))); - } + } else if (*address_low < 0x2000) - { + { *rdword = *((unsigned int *)(SP_IMEMb + (*address_low&0xFFF))); - } + } else read_nomem(); } @@ -1922,13 +1922,13 @@ void read_rsp_mem(void) void read_rsp_memb(void) { if (*address_low < 0x1000) - { + { *rdword = *(SP_DMEMb + (*address_low^S8)); - } + } else if (*address_low < 0x2000) - { + { *rdword = *(SP_IMEMb + ((*address_low&0xFFF)^S8)); - } + } else read_nomemb(); } @@ -1936,13 +1936,13 @@ void read_rsp_memb(void) void read_rsp_memh(void) { if (*address_low < 0x1000) - { + { *rdword = *((unsigned short *)(SP_DMEMb + (*address_low^S16))); - } + } else if (*address_low < 0x2000) - { + { *rdword = *((unsigned short *)(SP_IMEMb + ((*address_low&0xFFF)^S16))); - } + } else read_nomemh(); } @@ -1966,13 +1966,13 @@ void read_rsp_memd(void) void write_rsp_mem(void) { if (*address_low < 0x1000) - { + { *((unsigned int *)(SP_DMEMb + (*address_low))) = word; - } + } else if (*address_low < 0x2000) - { + { *((unsigned int *)(SP_IMEMb + (*address_low&0xFFF))) = word; - } + } else write_nomem(); } @@ -1980,13 +1980,13 @@ void write_rsp_mem(void) void write_rsp_memb(void) { if (*address_low < 0x1000) - { + { *(SP_DMEMb + (*address_low^S8)) = cpu_byte; - } + } else if (*address_low < 0x2000) - { + { *(SP_IMEMb + ((*address_low&0xFFF)^S8)) = cpu_byte; - } + } else write_nomemb(); } @@ -1994,13 +1994,13 @@ void write_rsp_memb(void) void write_rsp_memh(void) { if (*address_low < 0x1000) - { + { *((unsigned short *)(SP_DMEMb + (*address_low^S16))) = hword; - } + } else if (*address_low < 0x2000) - { + { *((unsigned short *)(SP_IMEMb + ((*address_low&0xFFF)^S16))) = hword; - } + } else write_nomemh(); } @@ -3665,7 +3665,7 @@ void write_pif(void) void write_pifb(void) { - if ((*address_low > 0x7FF) || (*address_low < 0x7C0)) + if ((*address_low > 0x7FF) || (*address_low < 0x7C0)) { DebugMessage(M64MSG_ERROR, "writing a byte in PIF at invalid address 0x%x", address); return; @@ -3741,14 +3741,13 @@ unsigned int *fast_mem_access(unsigned int address) address = virtual_to_physical_address(address, 2); if ((address & 0x1FFFFFFF) >= 0x10000000) - { - unsigned int ofs = ((address & 0x1FFFFFFF) - 0x10000000)/4; - if(ofs < rom_size/4) - return (unsigned int *)rom + ofs; - else { - return NULL; - } - } + { + unsigned int ofs = ((address & 0x1FFFFFFF) - 0x10000000)/4; + if (ofs < rom_size/4) + return (unsigned int *)rom + ofs; + else + return NULL; + } else if ((address & 0x1FFFFFFF) < 0x800000) return (unsigned int *)rdram + (address & 0x1FFFFFFF)/4; else if (address >= 0xa4000000 && address <= 0xa4001000) @@ -3761,5 +3760,5 @@ unsigned int *fast_mem_access(unsigned int address) EXPORT void CALL SetTraceCallback(void (*CB)(void)) { - traceCB = CB; + traceCB = CB; } \ No newline at end of file diff --git a/libmupen64plus/mupen64plus-core/src/memory/memory.h b/libmupen64plus/mupen64plus-core/src/memory/memory.h index d4be900a0ef..c2f61c64d17 100644 --- a/libmupen64plus/mupen64plus-core/src/memory/memory.h +++ b/libmupen64plus/mupen64plus-core/src/memory/memory.h @@ -26,6 +26,9 @@ #define TRACECB() if (traceCB) traceCB() +#define MASK_ADDR_U8(x, m) (x) & (sizeof(m) - 1) +#define MASK_ADDR_U32(x, m) (x) & (sizeof(m) / 4 - 1) + int init_memory(int DoByteSwap); void free_memory(void); #define read_word_in_memory() readmem[address>>16]() diff --git a/libmupen64plus/mupen64plus-core/src/memory/pif.c b/libmupen64plus/mupen64plus-core/src/memory/pif.c index 75badd677b8..b8911f0a901 100644 --- a/libmupen64plus/mupen64plus-core/src/memory/pif.c +++ b/libmupen64plus/mupen64plus-core/src/memory/pif.c @@ -91,7 +91,7 @@ static void eeprom_write_file(void) free(filename);*/ - saveramModified = 1; + saveramModified = 1; } /*static char *get_mempack_path(void) @@ -169,7 +169,7 @@ static void mempack_write_file(void) free(filename);*/ - saveramModified = 1; + saveramModified = 1; } //#define DEBUG_PIF @@ -302,15 +302,17 @@ static unsigned char mempack_crc(unsigned char *data) return CRC; } -static void internal_ReadController(int Control, unsigned char *Command) +static void internal_ReadController(int Control, unsigned char *Command, unsigned int Remaining) { + if (Remaining <= 2) return; + switch (Command[2]) { case 1: #ifdef DEBUG_PIF DebugMessage(M64MSG_INFO, "internal_ReadController() Channel %i Command 1 read buttons", Control); #endif - if (Controls[Control].Present) + if (Controls[Control].Present && Remaining > 6) { BUTTONS Keys; input.getKeys(Control, &Keys); @@ -324,7 +326,7 @@ static void internal_ReadController(int Control, unsigned char *Command) #ifdef DEBUG_PIF DebugMessage(M64MSG_INFO, "internal_ReadController() Channel %i Command 2 read controller pack (in Input plugin)", Control); #endif - if (Controls[Control].Present) + if (Controls[Control].Present && Remaining > 37) { if (Controls[Control].Plugin == PLUGIN_RAW) if (input.readController) @@ -335,7 +337,7 @@ static void internal_ReadController(int Control, unsigned char *Command) #ifdef DEBUG_PIF DebugMessage(M64MSG_INFO, "internal_ReadController() Channel %i Command 3 write controller pack (in Input plugin)", Control); #endif - if (Controls[Control].Present) + if (Controls[Control].Present && Remaining > 37) { if (Controls[Control].Plugin == PLUGIN_RAW) if (input.readController) @@ -345,8 +347,10 @@ static void internal_ReadController(int Control, unsigned char *Command) } } -static void internal_ControllerCommand(int Control, unsigned char *Command) +static void internal_ControllerCommand(int Control, unsigned char *Command, unsigned int Remaining) { + if (Remaining <= 2) return; + switch (Command[2]) { case 0x00: // read status @@ -356,7 +360,7 @@ static void internal_ControllerCommand(int Control, unsigned char *Command) #ifdef DEBUG_PIF DebugMessage(M64MSG_INFO, "internal_ControllerCommand() Channel %i Command %02x check pack present", Control, Command[2]); #endif - if (Controls[Control].Present) + if (Controls[Control].Present && Remaining > 5) { Command[3] = 0x05; Command[4] = 0x00; @@ -384,7 +388,7 @@ static void internal_ControllerCommand(int Control, unsigned char *Command) Command[1] |= 0x80; break; case 0x02: // read controller pack - if (Controls[Control].Present) + if (Controls[Control].Present && Remaining > 0x25) { switch (Controls[Control].Plugin) { @@ -434,7 +438,7 @@ static void internal_ControllerCommand(int Control, unsigned char *Command) Command[1] |= 0x80; break; case 0x03: // write controller pack - if (Controls[Control].Present) + if (Controls[Control].Present && Remaining > 0x25) { switch (Controls[Control].Plugin) { @@ -539,7 +543,7 @@ void update_pif_write(void) Controls[channel].RawData) input.controllerCommand(channel, &PIF_RAMb[i]); else - internal_ControllerCommand(channel, &PIF_RAMb[i]); + internal_ControllerCommand(channel, &PIF_RAMb[i], 0x40 - i); } else if (channel == 4) EepromCommand(&PIF_RAMb[i]); @@ -583,10 +587,33 @@ void update_pif_read(void) if (channel < 4) { if (Controls[channel].Present && - Controls[channel].RawData) - input.readController(channel, &PIF_RAMb[i]); + Controls[channel].RawData) + { + unsigned int remaining = 0x40 - i; + unsigned int needed = 3; + if (remaining > 2) + { + switch (PIF_RAMb[i + 2]) + { + case 0x00: + case 0xFF: + needed = 6; + break; + case 0x01: + needed = 7; + break; + case 0x02: + case 0x03: + needed = 38; + break; + } + } + + if (remaining >= needed) + input.readController(channel, &PIF_RAMb[i]); + } else - internal_ReadController(channel, &PIF_RAMb[i]); + internal_ReadController(channel, &PIF_RAMb[i], 0x40 - i); } i += PIF_RAMb[i] + (PIF_RAMb[(i+1)] & 0x3F) + 1; channel++; @@ -601,27 +628,27 @@ void update_pif_read(void) EXPORT void CALL init_saveram(void) { - eeprom_format(); - mempack_format(); - saveramModified = 0; + eeprom_format(); + mempack_format(); + saveramModified = 0; - flashram_format(); + flashram_format(); - sram_format(); + sram_format(); } EXPORT void CALL save_saveram(unsigned char * dest) { - memcpy(dest, eeprom, 0x800); - memcpy(dest + 0x800, mempack, 4 * 0x8000); - memcpy(dest + (0x800 + 4 * 0x8000), flashram, 0x20000); - memcpy(dest + (0x800 + 4 * 0x8000 + 0x20000), sram, 0x8000); + memcpy(dest, eeprom, 0x800); + memcpy(dest + 0x800, mempack, 4 * 0x8000); + memcpy(dest + (0x800 + 4 * 0x8000), flashram, 0x20000); + memcpy(dest + (0x800 + 4 * 0x8000 + 0x20000), sram, 0x8000); } EXPORT void CALL load_saveram(unsigned char * src) { - memcpy(eeprom, src, 0x800); - memcpy(mempack, src + 0x800, 4 * 0x8000); - memcpy(flashram, src + (0x800 + 4 * 0x8000), 0x20000); - memcpy(sram, src + (0x800 + 4 * 0x8000 + 0x20000), 0x8000); + memcpy(eeprom, src, 0x800); + memcpy(mempack, src + 0x800, 4 * 0x8000); + memcpy(flashram, src + (0x800 + 4 * 0x8000), 0x20000); + memcpy(sram, src + (0x800 + 4 * 0x8000 + 0x20000), 0x8000); } \ No newline at end of file diff --git a/libmupen64plus/mupen64plus-core/src/r4300/interupt.c b/libmupen64plus/mupen64plus-core/src/r4300/interupt.c index b9bb607e728..e3ca5e8d9e8 100644 --- a/libmupen64plus/mupen64plus-core/src/r4300/interupt.c +++ b/libmupen64plus/mupen64plus-core/src/r4300/interupt.c @@ -127,7 +127,7 @@ void add_interupt_event(int type, unsigned int delay) if (get_event(type)) { DebugMessage(M64MSG_WARNING, "two events of type 0x%x in interrupt queue", type); - return; + return; } if (q == NULL) @@ -384,7 +384,7 @@ void gen_interupt(void) #ifdef WITH_LIRC lircCheckInput(); #endif - SDL_PumpEvents(); + //SDL_PumpEvents(); refresh_stat(); @@ -397,7 +397,7 @@ void gen_interupt(void) // { //SDL_Delay(10); - SDL_PumpEvents(); + //SDL_PumpEvents(); #ifdef WITH_LIRC lircCheckInput(); #endif //WITH_LIRC @@ -405,7 +405,7 @@ void gen_interupt(void) //} new_vi(); - WaitForSingleObject(rompausesem, INFINITE); + WaitForSingleObject(rompausesem, INFINITE); if (vi_register.vi_v_sync == 0) vi_register.vi_delay = 500000; else vi_register.vi_delay = ((vi_register.vi_v_sync + 1)*1500); next_vi += vi_register.vi_delay; @@ -443,7 +443,7 @@ void gen_interupt(void) #ifdef WITH_LIRC lircCheckInput(); #endif //WITH_LIRC - SDL_PumpEvents(); + //SDL_PumpEvents(); PIF_RAMb[0x3F] = 0x0; remove_interupt_event(); MI_register.mi_intr_reg |= 0x02; diff --git a/quicknes/bizinterface.cpp b/quicknes/bizinterface.cpp index e72897ca772..8ed365acca1 100644 --- a/quicknes/bizinterface.cpp +++ b/quicknes/bizinterface.cpp @@ -5,12 +5,10 @@ #include #include -#ifdef _MSC_VER -#define EXPORT extern "C" __declspec(dllexport) -#elif __MINGW32__ -#define EXPORT extern "C" __declspec(dllexport) __attribute__((force_align_arg_pointer)) +#ifdef _WIN32 +#define QN_EXPORT extern "C" __declspec(dllexport) #else -#define EXPORT extern "C" __attribute__((force_align_arg_pointer)) +#define QN_EXPORT extern "C" __attribute__((visibility("default"))) #endif // Relevant defines for video output @@ -19,44 +17,45 @@ #define DEFAULT_HEIGHT 240 -EXPORT quickerNES::Emu *qn_new() +QN_EXPORT quickerNES::Emu *qn_new() { - // Zero intialized emulator to make super sure no side effects from previous data remains - auto ptr = calloc(1, sizeof(quickerNES::Emu)); - auto e = new (ptr) quickerNES::Emu(); + // Zero intialized emulator to make super sure no side effects from previous data remains + auto ptr = calloc(1, sizeof(quickerNES::Emu)); + auto e = new (ptr) quickerNES::Emu(); - // Creating video buffer - auto videoBuffer = (uint8_t *) malloc(VIDEO_BUFFER_SIZE); - e->set_pixels(videoBuffer, DEFAULT_WIDTH + 8); + // Creating video buffer + auto videoBuffer = (uint8_t *) malloc(VIDEO_BUFFER_SIZE); + e->set_pixels(videoBuffer, DEFAULT_WIDTH + 8); - return e; + return e; } -EXPORT void qn_delete(quickerNES::Emu *e) +QN_EXPORT void qn_delete(quickerNES::Emu *e) { - free(e->get_pixels_base_ptr()); - free(e); + free(e->get_pixels_base_ptr()); + e->~Emu(); // make sure to explicitly call the dtor + free(e); } -EXPORT const char *qn_loadines(quickerNES::Emu *e, const void *data, int length) +QN_EXPORT const char *qn_loadines(quickerNES::Emu *e, const void *data, int length) { - e->load_ines((const uint8_t*)data); - return 0; + e->load_ines((const uint8_t*)data); + return 0; } -EXPORT const char *qn_set_sample_rate(quickerNES::Emu *e, int rate) +QN_EXPORT const char *qn_set_sample_rate(quickerNES::Emu *e, int rate) { const char *ret = e->set_sample_rate(rate); if (!ret) e->set_equalizer(quickerNES::Emu::nes_eq); return ret; } -EXPORT const char *qn_emulate_frame(quickerNES::Emu *e, int pad1, int pad2) +QN_EXPORT const char *qn_emulate_frame(quickerNES::Emu *e, int pad1, int pad2) { return e->emulate_frame((uint32_t)pad1, (uint32_t)pad2); } -EXPORT void qn_blit(quickerNES::Emu *e, int32_t *dest, const int32_t *colors, int cropleft, int croptop, int cropright, int cropbottom) +QN_EXPORT void qn_blit(quickerNES::Emu *e, int32_t *dest, const int32_t *colors, int cropleft, int croptop, int cropright, int cropbottom) { // what is the point of the 256 color bitmap and the dynamic color allocation to it? // why not just render directly to a 512 color bitmap with static palette positions? @@ -81,17 +80,17 @@ EXPORT void qn_blit(quickerNES::Emu *e, int32_t *dest, const int32_t *colors, in } } -EXPORT const quickerNES::Emu::rgb_t *qn_get_default_colors() +QN_EXPORT const quickerNES::Emu::rgb_t *qn_get_default_colors() { return quickerNES::Emu::nes_colors; } -EXPORT int qn_get_joypad_read_count(quickerNES::Emu *e) +QN_EXPORT int qn_get_joypad_read_count(quickerNES::Emu *e) { return e->get_joypad_read_count(); } -EXPORT void qn_get_audio_info(quickerNES::Emu *e, int *sample_count, int *chan_count) +QN_EXPORT void qn_get_audio_info(quickerNES::Emu *e, int *sample_count, int *chan_count) { if (sample_count) *sample_count = e->frame().sample_count; @@ -99,17 +98,17 @@ EXPORT void qn_get_audio_info(quickerNES::Emu *e, int *sample_count, int *chan_c *chan_count = e->frame().chan_count; } -EXPORT int qn_read_audio(quickerNES::Emu *e, short *dest, int max_samples) +QN_EXPORT int qn_read_audio(quickerNES::Emu *e, short *dest, int max_samples) { return e->read_samples(dest, max_samples); } -EXPORT void qn_reset(quickerNES::Emu *e, int hard) +QN_EXPORT void qn_reset(quickerNES::Emu *e, int hard) { e->reset(hard); } -EXPORT const char *qn_state_size(quickerNES::Emu *e, int *size) +QN_EXPORT const char *qn_state_size(quickerNES::Emu *e, int *size) { jaffarCommon::serializer::Contiguous s; e->serializeState(s); @@ -117,44 +116,44 @@ EXPORT const char *qn_state_size(quickerNES::Emu *e, int *size) return 0; } -EXPORT const char *qn_state_save(quickerNES::Emu *e, void *dest, int size) +QN_EXPORT const char *qn_state_save(quickerNES::Emu *e, void *dest, int size) { jaffarCommon::serializer::Contiguous s(dest, size); e->serializeState(s); return 0; } -EXPORT const char *qn_state_load(quickerNES::Emu *e, const void *src, int size) +QN_EXPORT const char *qn_state_load(quickerNES::Emu *e, const void *src, int size) { jaffarCommon::deserializer::Contiguous d(src, size); e->deserializeState(d); return 0; } -EXPORT int qn_has_battery_ram(quickerNES::Emu *e) +QN_EXPORT int qn_has_battery_ram(quickerNES::Emu *e) { return e->has_battery_ram(); } -EXPORT const char *qn_battery_ram_size(quickerNES::Emu *e, int *size) +QN_EXPORT const char *qn_battery_ram_size(quickerNES::Emu *e, int *size) { *size = e->get_high_mem_size(); return 0; } -EXPORT const char *qn_battery_ram_save(quickerNES::Emu *e, void *dest, int size) +QN_EXPORT const char *qn_battery_ram_save(quickerNES::Emu *e, void *dest, int size) { memcpy(dest, e->high_mem(), size); return 0; } -EXPORT const char *qn_battery_ram_load(quickerNES::Emu *e, const void *src, int size) +QN_EXPORT const char *qn_battery_ram_load(quickerNES::Emu *e, const void *src, int size) { memcpy(e->high_mem(), src, size); return 0; } -EXPORT const char *qn_battery_ram_clear(quickerNES::Emu *e) +QN_EXPORT const char *qn_battery_ram_clear(quickerNES::Emu *e) { int size = 0; qn_battery_ram_size(e, &size); @@ -162,12 +161,12 @@ EXPORT const char *qn_battery_ram_clear(quickerNES::Emu *e) return 0; } -EXPORT void qn_set_sprite_limit(quickerNES::Emu *e, int n) +QN_EXPORT void qn_set_sprite_limit(quickerNES::Emu *e, int n) { e->set_sprite_mode((quickerNES::Emu::sprite_mode_t)n); } -EXPORT int qn_get_memory_area(quickerNES::Emu *e, int which, const void **data, int *size, int *writable, const char **name) +QN_EXPORT int qn_get_memory_area(quickerNES::Emu *e, int which, const void **data, int *size, int *writable, const char **name) { if (!data || !size || !writable || !name) return 0; @@ -226,22 +225,22 @@ EXPORT int qn_get_memory_area(quickerNES::Emu *e, int which, const void **data, } } -EXPORT unsigned char qn_peek_prgbus(quickerNES::Emu *e, int addr) +QN_EXPORT unsigned char qn_peek_prgbus(quickerNES::Emu *e, int addr) { return e->peek_prg(addr & 0xffff); } -EXPORT void qn_poke_prgbus(quickerNES::Emu *e, int addr, unsigned char val) +QN_EXPORT void qn_poke_prgbus(quickerNES::Emu *e, int addr, unsigned char val) { e->poke_prg(addr & 0xffff, val); } -EXPORT void qn_get_cpuregs(quickerNES::Emu *e, unsigned int *dest) +QN_EXPORT void qn_get_cpuregs(quickerNES::Emu *e, unsigned int *dest) { e->get_regs(dest); } -EXPORT const char *qn_get_mapper(quickerNES::Emu *e, int *number) +QN_EXPORT const char *qn_get_mapper(quickerNES::Emu *e, int *number) { int m = e->cart()->mapper_code(); if (number) @@ -306,33 +305,33 @@ EXPORT const char *qn_get_mapper(quickerNES::Emu *e, int *number) } } -EXPORT uint8_t qn_get_reg2000(quickerNES::Emu *e) +QN_EXPORT uint8_t qn_get_reg2000(quickerNES::Emu *e) { return e->get_ppu2000(); } -EXPORT uint8_t *qn_get_palmem(quickerNES::Emu *e) +QN_EXPORT uint8_t *qn_get_palmem(quickerNES::Emu *e) { return e->pal_mem(); } -EXPORT uint8_t *qn_get_oammem(quickerNES::Emu *e) +QN_EXPORT uint8_t *qn_get_oammem(quickerNES::Emu *e) { return e->pal_mem(); } -EXPORT uint8_t qn_peek_ppu(quickerNES::Emu *e, int addr) +QN_EXPORT uint8_t qn_peek_ppu(quickerNES::Emu *e, int addr) { return e->peek_ppu(addr); } -EXPORT void qn_peek_ppubus(quickerNES::Emu *e, uint8_t *dest) +QN_EXPORT void qn_peek_ppubus(quickerNES::Emu *e, uint8_t *dest) { for (int i = 0; i < 0x3000; i++) dest[i] = e->peek_ppu(i); } -EXPORT void qn_set_tracecb(quickerNES::Emu *e, void (*cb)(unsigned int *dest)) +QN_EXPORT void qn_set_tracecb(quickerNES::Emu *e, void (*cb)(unsigned int *dest)) { e->set_tracecb(cb); } diff --git a/quicknes/core b/quicknes/core index 74c1a73fe8b..027f63aee19 160000 --- a/quicknes/core +++ b/quicknes/core @@ -1 +1 @@ -Subproject commit 74c1a73fe8baf08ed02b66248b9bf12b4a77076c +Subproject commit 027f63aee19840ac1bf571a5d00d7758ca517220 diff --git a/quicknes/make/Makefile b/quicknes/make/Makefile index 981ef63b807..ea1ff46a278 100644 --- a/quicknes/make/Makefile +++ b/quicknes/make/Makefile @@ -2,18 +2,9 @@ CXX = g++ RM = rm CP = cp -MACHINE = $(shell $(CXX) -dumpmachine) -ifneq (,$(findstring i686,$(MACHINE))) - $(error 32 bit build no longer supported) -else ifneq (,$(findstring x86_64,$(MACHINE))) - ARCH = 64 -else - $(error Unknown arch) -endif - -CXXFLAGS_32 = -march=pentium4 -mtune=core2 -CXXFLAGS_64 = -CXXFLAGS = -Wall -I../core/source/quickerNES/core/ -I../core/extern/jaffarCommon/include -D__INLINE__=inline -O3 -Wfatal-errors -Werror -fomit-frame-pointer -flto -D_GNU_SOURCE -D_QUICKERNES_DETECT_JOYPAD_READS -D_QUICKERNES_ENABLE_TRACEBACK_SUPPORT $(CXXFLAGS_$(ARCH)) +CXXFLAGS = -I../core/source/quickerNES/core/ -I../core/extern/jaffarCommon/include -Wall -Wfatal-errors -Werror \ + -std=c++20 -O3 -fomit-frame-pointer -flto -fvisibility=internal -fvisibility-inlines-hidden \ + -D_GNU_SOURCE -D__INLINE__=inline -D_QUICKERNES_DETECT_JOYPAD_READS -D_QUICKERNES_ENABLE_TRACEBACK_SUPPORT # TODO: include these as options in the Makefile # -fprofile-generate @@ -26,12 +17,10 @@ else TARGET = libquicknes.dll endif -LDFLAGS_32 = -static -static-libgcc -static-libstdc++ -LDFLAGS_64 = -LDFLAGS = -shared $(LDFLAGS_$(ARCH)) $(CXXFLAGS) +LDFLAGS = -shared -s $(CXXFLAGS) -DEST_64 = ../../Assets/dll -DESTCOPY_64 = ../../output/dll +DEST = ../../Assets/dll +DESTCOPY = ../../output/dll SRCS = \ ../core/source/quickerNES/core/apu/vrc7/emu2413_state.cpp \ @@ -70,7 +59,7 @@ clean: $(RM) -f $(TARGET) install: - $(CP) $(TARGET) $(DEST_$(ARCH)) -ifneq ("$(wildcard $(DESTCOPY_$(ARCH)))", "") - $(CP) $(TARGET) $(DESTCOPY_$(ARCH)) + $(CP) $(TARGET) $(DEST) +ifneq ("$(wildcard $(DESTCOPY))", "") + $(CP) $(TARGET) $(DESTCOPY) endif diff --git a/quicknes/msvc/libquicknes.vcxproj b/quicknes/msvc/libquicknes.vcxproj index 04f38ded13c..51576de7e47 100644 --- a/quicknes/msvc/libquicknes.vcxproj +++ b/quicknes/msvc/libquicknes.vcxproj @@ -161,6 +161,7 @@ $(ProjectDir)\.. _WINDLL;%(PreprocessorDefinitions);_QUICKERNES_DETECT_JOYPAD_READS;_QUICKERNES_ENABLE_TRACEBACK_SUPPORT; true + stdcpp20 true @@ -180,6 +181,7 @@ $(ProjectDir)\.. _WINDLL;%(PreprocessorDefinitions);_QUICKERNES_DETECT_JOYPAD_READS;_QUICKERNES_ENABLE_TRACEBACK_SUPPORT; true + stdcpp20 true @@ -200,4 +202,4 @@ - + \ No newline at end of file diff --git a/shell.nix b/shell.nix index 0483f726136..d92ad497c25 100644 --- a/shell.nix +++ b/shell.nix @@ -5,6 +5,7 @@ , git-cola ? pkgs.git-cola , git ? pkgs.gitMinimal , nano ? pkgs.nano +, powershell ? pkgs.powershell , debugDotnetHostCrashes ? false # forwarded to Dist/launch-scripts.nix , debugPInvokes ? false # forwarded to Dist/launch-scripts.nix , forNixOS ? true @@ -12,18 +13,17 @@ , useNanoAndCola ? false , useVSCode ? false }: let - # thinking of exposing pre-configured IDEs from `default.nix` so they're available here avail = import ./. { inherit debugDotnetHostCrashes debugPInvokes forNixOS system; }; f = drv: mkShell { - packages = [ git ] + packages = [ git powershell ] ++ lib.optionals useNanoAndCola [ git-cola nano ] - ++ lib.optionals useKate [] #TODO + ++ lib.optionals useKate avail.IDEs.kate ++ lib.optionals useVSCode [] #TODO https://devblogs.microsoft.com/dotnet/csharp-dev-kit-now-generally-available/ https://learn.microsoft.com/en-us/training/modules/implement-visual-studio-code-debugging-tools/ ; inputsFrom = [ drv ]; shellHook = '' export BIZHAWKBUILD_HOME='${builtins.toString ./.}' - export BIZHAWK_HOME="$BIZHAWKBUILD_HOME/output" + export BIZHAWK_HOME="$BIZHAWKBUILD_HOME/output/" ldLibPath='${lib.makeLibraryPath drv.buildInputs}' # for running tests if [ -z "$LD_LIBRARY_PATH" ]; then export LD_LIBRARY_PATH="$ldLibPath" @@ -32,11 +32,14 @@ fi alias discohawk-monort-local='${avail.launchScriptsForLocalBuild.discohawk}' alias emuhawk-monort-local='${avail.launchScriptsForLocalBuild.emuhawk}' - pfx="$(realpath --relative-to="$PWD" "$BIZHAWKBUILD_HOME")/" - if [ "$pfx" = "./" ]; then pfx=""; fi - printf "%s\n%s\n" \ - "Run ''${pfx}Dist/Build{Debug,Release}.sh to build the solution. You may need to clean up with ''${pfx}Dist/CleanupBuildOutputDirs.sh." \ - "Once built, running {discohawk,emuhawk}-monort-local will pull from ''${pfx}output/* and use Mono from Nixpkgs." + case "$-" in *i*) + pfx="$(realpath --relative-to="$PWD" "$BIZHAWKBUILD_HOME")/" + if [ "$pfx" = "./" ]; then pfx=""; fi + printf "%s\n%s\n" \ + "Run ''${pfx}Dist/Build{Debug,Release}.sh to build the solution. You may need to clean up with ''${pfx}Dist/CleanupBuildOutputDirs.sh." \ + "Once built, running {discohawk,emuhawk}-monort-local will pull from ''${pfx}output/* and use Mono from Nixpkgs." + ;; + esac ''; }; shells = lib.pipe avail [ diff --git a/src/BizHawk.BizInvoke/BizInvokeUtilities.cs b/src/BizHawk.BizInvoke/BizInvokeUtilities.cs index 7ecd0d11bcb..6873145e902 100644 --- a/src/BizHawk.BizInvoke/BizInvokeUtilities.cs +++ b/src/BizHawk.BizInvoke/BizInvokeUtilities.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Reflection; using System.Reflection.Emit; diff --git a/src/BizHawk.BizInvoke/BizInvoker.cs b/src/BizHawk.BizInvoke/BizInvoker.cs index 5f6c6b5dd70..a1bc4a4d9ed 100644 --- a/src/BizHawk.BizInvoke/BizInvoker.cs +++ b/src/BizHawk.BizInvoke/BizInvoker.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -8,6 +7,7 @@ using BizHawk.Common; using BizHawk.Common.CollectionExtensions; +using BizHawk.Common.StringExtensions; namespace BizHawk.BizInvoke { @@ -83,10 +83,12 @@ public object Create(IImportResolver dll, IMonitor? monitor, ICallingConventionA /// How far into a class pointer the first field is. Different on mono and fw. /// private static readonly int ClassFieldOffset; + /// /// How far into a string pointer the first chair is. /// private static readonly int StringOffset; + /// /// How far into a value array type element 0 is. /// @@ -534,7 +536,7 @@ private static ParameterLoadInfo EmitParamterLoad(ILGenerator il, int idx, Type throw new NotImplementedException("Multidimensional arrays are not supported!"); } - if (type.Name.Contains('*')) + if (type.Name.ContainsOrdinal('*')) { throw new NotImplementedException("Only 0-based 1-dimensional arrays are supported!"); } diff --git a/src/BizHawk.BizInvoke/BizInvokerUtilities.cs b/src/BizHawk.BizInvoke/BizInvokerUtilities.cs index d59541c507b..b44865668dd 100644 --- a/src/BizHawk.BizInvoke/BizInvokerUtilities.cs +++ b/src/BizHawk.BizInvoke/BizInvokerUtilities.cs @@ -1,4 +1,3 @@ -using System; using System.Reflection; using System.Reflection.Emit; using System.Runtime.InteropServices; @@ -56,14 +55,12 @@ private class CF /// /// Computes the byte offset of the first field of any class relative to a class pointer. /// - /// public static int ComputeClassFirstFieldOffset() => ComputeFieldOffset(typeof(CF).GetField("FirstField")); /// /// Compute the byte offset of the first byte of string data (UTF16) relative to a pointer to the string. /// - /// public static int ComputeStringOffset() { var s = new string(Array.Empty()); @@ -79,7 +76,6 @@ public static int ComputeStringOffset() /// /// Compute the offset to the 0th element of an array of value types /// - /// public static int ComputeValueArrayElementOffset() { var arr = new int[4]; @@ -97,7 +93,6 @@ public static int ComputeValueArrayElementOffset() /// Compute the offset to the 0th element of an array of object types /// Slow, so cache it if you need it. /// - /// public static int ComputeObjectArrayElementOffset() { var obj = new object[4]; diff --git a/src/BizHawk.BizInvoke/CallingConventionAdapter.cs b/src/BizHawk.BizInvoke/CallingConventionAdapter.cs index 4303d6fcd20..c3e8ad6d5b7 100644 --- a/src/BizHawk.BizInvoke/CallingConventionAdapter.cs +++ b/src/BizHawk.BizInvoke/CallingConventionAdapter.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -25,27 +24,20 @@ public interface ICallingConventionAdapter /// managed wrapper involved. Called "arrival" because it is to be used when the foreign code is calling /// back into host code. /// - /// - IntPtr GetArrivalFunctionPointer(IntPtr p, ParameterInfo pp, object lifetime); + IntPtr GetArrivalFunctionPointer(IntPtr p, InvokerParameterInfo pp, object lifetime); /// /// Like Marshal.GetDelegateForFunctionPointer(), but wraps a thunk around the passed native pointer /// to adjust the calling convention appropriately /// - /// - /// - /// Delegate GetDelegateForFunctionPointer(IntPtr p, Type delegateType); + /// /// Like Marshal.GetDelegateForFunctionPointer(), but only the unmanaged thunk-to-thunk part, with no /// managed wrapper involved.static Called "departure" beause it is to be used when first leaving host /// code for foreign code. /// - /// - /// - /// - /// - IntPtr GetDepartureFunctionPointer(IntPtr p, ParameterInfo pp, object lifetime); + IntPtr GetDepartureFunctionPointer(IntPtr p, InvokerParameterInfo pp, object lifetime); } public static class CallingConventionAdapterExtensions @@ -55,19 +47,19 @@ public static T GetDelegateForFunctionPointer(this ICallingConventionAdapter => (T) a.GetDelegateForFunctionPointer(p, typeof(T)); } - public class ParameterInfo + public sealed class InvokerParameterInfo { public Type ReturnType { get; } public IReadOnlyList ParameterTypes { get; } - public ParameterInfo(Type returnType, IEnumerable parameterTypes) + public InvokerParameterInfo(Type returnType, IEnumerable parameterTypes) { ReturnType = returnType; ParameterTypes = parameterTypes.ToList().AsReadOnly(); } /// does not inherit - public ParameterInfo(Type delegateType) + public InvokerParameterInfo(Type delegateType) { if (!typeof(Delegate).IsAssignableFrom(delegateType)) { @@ -91,6 +83,7 @@ public interface ICallbackAdjuster /// any meaning to CallingConvention Adapter; it's just a unique key associated with the callback. /// IntPtr GetCallbackProcAddr(IntPtr exitPoint, int slot); + /// /// Returns a thunk over a departure point. /// @@ -101,13 +94,13 @@ public static class CallingConventionAdapters { private class NativeConvention : ICallingConventionAdapter { - public IntPtr GetArrivalFunctionPointer(IntPtr p, ParameterInfo pp, object lifetime) + public IntPtr GetArrivalFunctionPointer(IntPtr p, InvokerParameterInfo pp, object lifetime) => p; public Delegate GetDelegateForFunctionPointer(IntPtr p, Type delegateType) => Marshal.GetDelegateForFunctionPointer(p, delegateType); - public IntPtr GetDepartureFunctionPointer(IntPtr p, ParameterInfo pp, object lifetime) + public IntPtr GetDepartureFunctionPointer(IntPtr p, InvokerParameterInfo pp, object lifetime) => p; public IntPtr GetFunctionPointerForDelegate(Delegate d) @@ -136,7 +129,6 @@ public static ICallingConventionAdapter MakeWaterboxDepartureOnly(ICallbackAdjus /// This is very unsafe; any attempts by the guest to call syscalls will crash, and stack hygiene will be all wrong. /// DO NOT USE THIS. /// - /// public static ICallingConventionAdapter GetWaterboxUnsafeUnwrapped() => WaterboxAdapter.WaterboxWrapper; @@ -174,7 +166,7 @@ public WaterboxAdapter(IEnumerable? slots, ICallbackAdjuster waterboxH _waterboxHost = waterboxHost; } - public IntPtr GetArrivalFunctionPointer(IntPtr p, ParameterInfo pp, object lifetime) + public IntPtr GetArrivalFunctionPointer(IntPtr p, InvokerParameterInfo pp, object lifetime) { if (_slots == null) { @@ -200,7 +192,7 @@ public Delegate GetDelegateForFunctionPointer(IntPtr p, Type delegateType) return WaterboxWrapper.GetDelegateForFunctionPointer(p, delegateType); } - public IntPtr GetDepartureFunctionPointer(IntPtr p, ParameterInfo pp, object lifetime) + public IntPtr GetDepartureFunctionPointer(IntPtr p, InvokerParameterInfo pp, object lifetime) { p = _waterboxHost.GetCallinProcAddr(p); return WaterboxWrapper.GetDepartureFunctionPointer(p, pp, lifetime); @@ -289,7 +281,7 @@ private static void VerifyParameter(Type type) throw new NotSupportedException($"Unknown type {type}. Possibly supported?"); } - private static int VerifyDelegateSignature(ParameterInfo pp) + private static int VerifyDelegateSignature(InvokerParameterInfo pp) { VerifyParameter(pp.ReturnType); foreach (var ppp in pp.ParameterTypes) @@ -366,7 +358,7 @@ public IntPtr GetFunctionPointerForDelegate(Delegate d) } } - public IntPtr GetArrivalFunctionPointer(IntPtr p, ParameterInfo pp, object lifetime) + public IntPtr GetArrivalFunctionPointer(IntPtr p, InvokerParameterInfo pp, object lifetime) { lock (_sync) { @@ -391,7 +383,7 @@ public Delegate GetDelegateForFunctionPointer(IntPtr p, Type delegateType) } } - public IntPtr GetDepartureFunctionPointer(IntPtr p, ParameterInfo pp, object lifetime) + public IntPtr GetDepartureFunctionPointer(IntPtr p, InvokerParameterInfo pp, object lifetime) { lock (_sync) { diff --git a/src/BizHawk.Bizware.Audio/OpenALSoundOutput.cs b/src/BizHawk.Bizware.Audio/OpenALSoundOutput.cs index a33e5b5fdff..9b53deb798b 100644 --- a/src/BizHawk.Bizware.Audio/OpenALSoundOutput.cs +++ b/src/BizHawk.Bizware.Audio/OpenALSoundOutput.cs @@ -1,10 +1,10 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; using BizHawk.Client.Common; using BizHawk.Common; +using BizHawk.Common.IOExtensions; using Silk.NET.Core.Native; using Silk.NET.OpenAL; @@ -209,9 +209,7 @@ public void PlayWavFile(Stream wavFile, double volume) _wavSourceID = _al.GenSource(); _wavBufferID = _al.GenBuffer(); - var tempBuffer = new byte[wavStream.Length]; - wavStream.Read(tempBuffer); - + var tempBuffer = wavStream.ReadAllBytes(); if (wavStream.Format == SDL2WavStream.AudioFormat.S16MSB) { EndiannessUtils.MutatingByteSwap16(tempBuffer); diff --git a/src/BizHawk.Bizware.Audio/SDL2WavStream.cs b/src/BizHawk.Bizware.Audio/SDL2WavStream.cs index 030b6ece0b9..859f0bf78d6 100644 --- a/src/BizHawk.Bizware.Audio/SDL2WavStream.cs +++ b/src/BizHawk.Bizware.Audio/SDL2WavStream.cs @@ -1,9 +1,9 @@ -using System; using System.Buffers; using System.IO; using System.Runtime.InteropServices; using BizHawk.Common; +using BizHawk.Common.NumberExtensions; using static SDL2.SDL; @@ -92,17 +92,19 @@ public override void Flush() { } - public unsafe int Read(Span buffer) + public int Read(Span buffer) { if (_wav == IntPtr.Zero) { throw new ObjectDisposedException(nameof(SDL2WavStream)); } - var count = (int)Math.Min(buffer.Length, _len - _pos); - new ReadOnlySpan((void*)((nint)_wav + _pos), count).CopyTo(buffer); - _pos += (uint)count; - return count; + uint count = Math.Min((uint) buffer.Length, _len - _pos); + var countSigned = unchecked((int) count); // since `Span.Length` is at most `int.MaxValue`, so must `count` be + // really, these fields should just be widened to whatever they're used as, which seems to be s64, and asserted to be in 0.. - /// Represents a piece of 2d art. Not as versatile as a texture.. could have come from an atlas. So it comes with a boatload of constraints - /// - public class Art - { - // bleh, didnt mean to have this here, but I need it now - public Art(Texture2d tex) - { - BaseTexture = tex; - u1 = 1; - v1 = 1; - Width = tex.Width; - Height = tex.Height; - } - - public Art(ArtManager owner) - { - Owner = owner; - } - - public ArtManager Owner { get; } - public Texture2d BaseTexture { get; set; } - - public float Width, Height; - public float u0, v0, u1, v1; - - internal void Initialize() - { - //TBD - } - } -} \ No newline at end of file diff --git a/src/BizHawk.Bizware.BizwareGL/ArtManager.cs b/src/BizHawk.Bizware.BizwareGL/ArtManager.cs deleted file mode 100644 index 2fee78e871f..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/ArtManager.cs +++ /dev/null @@ -1,175 +0,0 @@ -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; - -namespace BizHawk.Bizware.BizwareGL -{ - /// - /// Load resources through here, and they can be grouped together, for purposes of batching and whatnot. - /// You can't use any of the returned Art resources until calling Close on the ArtManager - /// - public class ArtManager : IDisposable - { - public ArtManager(IGL owner) - { - Owner = owner; - Open(); - } - - public void Dispose() - { - // todo - } - - /// - /// Reopens this instance for further resource loading. Fails if it has been closed forever. - /// - public void Open() - { - AssertIsOpen(false); - if (IsClosedForever) - { - throw new InvalidOperationException($"{nameof(ArtManager)} instance has been closed forever!"); - } - - IsOpened = true; - } - - /// - /// Loads the given stream as an Art instance - /// - public Art LoadArt(Stream stream) - { - return LoadArtInternal(new BitmapBuffer(stream, new BitmapLoadOptions())); - } - - /// - /// Loads the given path as an Art instance. - /// - public Art LoadArt(string path) - { - using var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); - return LoadArtInternal(new BitmapBuffer(path, new BitmapLoadOptions())); - } - - private Art LoadArtInternal(BitmapBuffer tex) - { - AssertIsOpen(true); - - var a = new Art(this); - ArtLooseTextureAssociation.Add((a, tex)); - ManagedArts.Add(a); - - return a; - } - - /// - /// Closes this instance for for further resource loading. Will result in a texture atlasing operation. - /// If the close operation is forever, then internal backup copies of resources will be freed, but it can never be reopened. - /// This function may take some time to run, as it is - /// - public void Close(bool forever = true) - { - AssertIsOpen(true); - IsOpened = false; - IsClosedForever = forever; - - // first, cleanup old stuff - foreach (var tex in ManagedTextures) - { - tex.Dispose(); - } - ManagedTextures.Clear(); - - // prepare input for atlas process and perform atlas - // add 2 extra pixels for padding on all sides - var atlasItems = ArtLooseTextureAssociation - .Select(kvp => new TexAtlas.RectItem(kvp.Bitmap.Width + 2, kvp.Bitmap.Height + 2, kvp)) - .ToList(); - var results = TexAtlas.PackAtlas(atlasItems); - - // this isn't supported yet: - if (results.Count > 1) - throw new InvalidOperationException("Art files too big for atlas"); - - // prepare the output buffer - var bmpResult = new BitmapBuffer(results[0].Size); - - //for each item, copy it into the output buffer and set the tex parameters on them - for (var i = 0; i < atlasItems.Count; i++) - { - var item = results[0].Items[i]; - var (art, bitmap) = ((Art, BitmapBuffer)) item.Item; - var w = bitmap.Width; - var h = bitmap.Height; - var dx = item.X + 1; - var dy = item.Y + 1; - for (var y = 0; y < h; y++) - { - for (var x = 0; x < w; x++) - { - var pixel = bitmap.GetPixel(x, y); - bmpResult.SetPixel(x+dx,y+dy,pixel); - } - } - - var myDestWidth = (float)bmpResult.Width; - var myDestHeight = (float)bmpResult.Height; - - art.u0 = dx / myDestWidth; - art.v0 = dy / myDestHeight; - art.u1 = (dx + w) / myDestWidth; - art.v1 = (dy + h) / myDestHeight; - art.Width = w; - art.Height = h; - } - - //if we're closed forever, then forget all the original bitmaps - if (forever) - { - foreach (var tuple in ArtLooseTextureAssociation) tuple.Bitmap.Dispose(); - ArtLooseTextureAssociation.Clear(); - } - - //create a physical texture - var texture = Owner.LoadTexture(bmpResult); - ManagedTextures.Add(texture); - - //oops, we couldn't do this earlier. - foreach (var art in ManagedArts) - art.BaseTexture = texture; - } - - /// - /// Throws an exception if the instance is not open - /// - private void AssertIsOpen(bool state) - { - if (IsOpened != state) - { - throw new InvalidOperationException($"{nameof(ArtManager)} instance is not open!"); - } - } - - public IGL Owner { get; } - - public bool IsOpened { get; private set; } - public bool IsClosedForever { get; private set; } - - /// - /// This is used to remember the original bitmap sources for art files. Once the ArtManager is closed forever, this will be purged - /// - private readonly List<(Art Art, BitmapBuffer Bitmap)> ArtLooseTextureAssociation = new(); - - /// - /// Physical texture resources, which exist after this ArtManager has been closed - /// - private readonly List ManagedTextures = new(); - - /// - /// All the Arts managed by this instance - /// - private readonly List ManagedArts = new(); - } -} \ No newline at end of file diff --git a/src/BizHawk.Bizware.BizwareGL/AttributeInfo.cs b/src/BizHawk.Bizware.BizwareGL/AttributeInfo.cs deleted file mode 100644 index 16f72dc6b74..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/AttributeInfo.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace BizHawk.Bizware.BizwareGL -{ - public class AttributeInfo - { - public IntPtr Handle; - public string Name; - } -} \ No newline at end of file diff --git a/src/BizHawk.Bizware.BizwareGL/BizHawk.Bizware.BizwareGL.csproj b/src/BizHawk.Bizware.BizwareGL/BizHawk.Bizware.BizwareGL.csproj deleted file mode 100644 index 0b984476741..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/BizHawk.Bizware.BizwareGL.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - netstandard2.0 - - - - true - disable - - - - - - - - - - diff --git a/src/BizHawk.Bizware.BizwareGL/IGL.cs b/src/BizHawk.Bizware.BizwareGL/IGL.cs deleted file mode 100644 index cde696cc010..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/IGL.cs +++ /dev/null @@ -1,255 +0,0 @@ -using System; -using System.IO; -using System.Drawing; -using System.Numerics; - -namespace BizHawk.Bizware.BizwareGL -{ - - /// - /// This is a wrapper over OpenGL and direct3d to give a uniform interface - /// TODO - This really needs to be split up into an internal and a user interface. so many of the functions are made to support the smart wrappers - /// Maybe make a method that returns an interface used for advanced methods (and IGL_TK could implement that as well and just "return this:") - /// - /// NOTE: THIS SHOULD NOT BE ASSUMED TO BE THREAD SAFE! Make a new IGL if you want to use it in a new thread. I hope that will work... - /// - public interface IGL : IDisposable - { - /// HACK - EDispMethod DispMethodEnum { get; } - - /// - /// Clears the color buffer with the specified color - /// - void ClearColor(Color color); - - /// - /// compile a fragment shader. This is the simplified method. A more complex method may be added later which will accept multiple sources and preprocessor definitions independently - /// - Shader CreateFragmentShader(string source, string entry, bool required); - - /// - /// compile a vertex shader. This is the simplified method. A more complex method may be added later which will accept multiple sources and preprocessor definitions independently - /// - Shader CreateVertexShader(string source, string entry, bool required); - - /// - /// Creates a complete pipeline from the provided vertex and fragment shader handles - /// - Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, Shader fragmentShader, bool required, string memo); - - /// - /// Binds this pipeline as the current used for rendering - /// - void BindPipeline(Pipeline pipeline); - - /// - /// Sets a uniform sampler to use use the provided texture - /// - void SetPipelineUniformSampler(PipelineUniform uniform, Texture2d tex); - - /// - /// Sets a uniform value - /// - void SetPipelineUniformMatrix(PipelineUniform uniform, Matrix4x4 mat, bool transpose); - - /// - /// Sets a uniform value - /// - void SetPipelineUniformMatrix(PipelineUniform uniform, ref Matrix4x4 mat, bool transpose); - - /// - /// sets a uniform value - /// - void SetPipelineUniform(PipelineUniform uniform, Vector4 value); - - /// - /// sets a uniform value - /// - void SetPipelineUniform(PipelineUniform uniform, Vector2 value); - - /// - /// sets a uniform value - /// - void SetPipelineUniform(PipelineUniform uniform, float value); - - /// - /// sets uniform values - /// - void SetPipelineUniform(PipelineUniform uniform, Vector4[] values); - - /// - /// sets a uniform value - /// - void SetPipelineUniform(PipelineUniform uniform, bool value); - - /// - /// Begins a rendering scene; use before doing any draw calls, as per normal - /// - void BeginScene(); - - /// - /// Indicates end of scene rendering; use after all draw calls as per normal - /// - void EndScene(); - - /// - /// Draws based on the currently set pipeline - /// data contains vertexes based on the pipeline's VertexLayout - /// count is the vertex count - /// Vertexes must form triangle strips - /// - void Draw(IntPtr data, int count); - - /// - /// resolves the texture into a new BitmapBuffer - /// - BitmapBuffer ResolveTexture2d(Texture2d texture); - - void SetMinFilter(Texture2d texture, TextureMinFilter minFilter); - - void SetMagFilter(Texture2d texture, TextureMagFilter magFilter); - - /// - /// creates a vertex layout resource - /// - VertexLayout CreateVertexLayout(); - - /// - /// Enables normal (non-premultiplied) alpha blending. - /// - void EnableBlending(); - - /// - /// Disables blending (alpha values are copied from the source fragment) - /// - void DisableBlending(); - - /// - /// Creates a texture with the specified dimensions - /// TODO - pass in specifications somehow - /// - Texture2d CreateTexture(int width, int height); - - /// - /// In case you already have the texture ID (from an opengl emulator gpu core) you can get a Texture2d with it this way. - /// Otherwise, if this isn't an OpenGL frontend implementation, the core is expected to readback the texture for GetVideoBuffer() - /// - Texture2d WrapGLTexture2d(IntPtr glTexId, int width, int height); - - /// - /// Sets the clamp mode (for both uv) for the Texture2d. - /// The default is clamped=true. - /// - void SetTextureWrapMode(Texture2d tex, bool clamp); - - /// - /// Loads the texture with new data. This isn't supposed to be especially versatile, it just blasts a bitmap buffer into the texture - /// - void LoadTextureData(Texture2d tex, BitmapBuffer bmp); - - /// - /// Loads a texture from disk - /// - Texture2d LoadTexture(string path); - - /// - /// Loads a texture from the stream - /// - Texture2d LoadTexture(Stream stream); - - /// - /// Loads a texture from the BitmapBuffer - /// - Texture2d LoadTexture(BitmapBuffer buffer); - - /// - /// Loads a texture from the System.Drawing.Bitmap - /// - Texture2d LoadTexture(Bitmap bitmap); - - /// - /// sets the viewport (and scissor) according to the provided specifications - /// - void SetViewport(int x, int y, int width, int height); - - /// - /// sets the viewport (and scissor) according to the provided specifications - /// - void SetViewport(int width, int height); - -#if false // Unused and WinForms unavailable on .NET Standard - /// - /// sets the viewport (and scissor) according to the client area of the provided control - /// - void SetViewport(System.Windows.Forms.Control control); -#endif - - /// - /// sets the viewport (and scissor) according to the provided specifications - /// - void SetViewport(Size size); - - /// - /// generates a proper 2d othographic projection for the given destination size, suitable for use in a GUI - /// - Matrix4x4 CreateGuiProjectionMatrix(int w, int h); - - /// - /// generates a proper 2d othographic projection for the given destination size, suitable for use in a GUI - /// - Matrix4x4 CreateGuiProjectionMatrix(Size dims); - - /// - /// generates a proper view transform for a standard 2d ortho projection, including half-pixel jitter if necessary and - /// re-establishing of a normal 2d graphics top-left origin. suitable for use in a GUI - /// - Matrix4x4 CreateGuiViewMatrix(int w, int h, bool autoflip = true); - - /// - /// generates a proper view transform for a standard 2d ortho projection, including half-pixel jitter if necessary and - /// re-establishing of a normal 2d graphics top-left origin. suitable for use in a GUI - /// - Matrix4x4 CreateGuiViewMatrix(Size dims, bool autoflip = true); - - /// - /// Creates a render target. Only includes a color buffer. Pixel format control TBD - /// - RenderTarget CreateRenderTarget(int w, int h); - - /// - /// Binds a RenderTarget for current rendering - /// - void BindRenderTarget(RenderTarget rt); - - /// - /// Returns a string representing the API employed by this context - /// - string API { get; } - - /// - /// Frees the provided render target. Same as disposing the resource. - /// - void FreeRenderTarget(RenderTarget rt); - - /// - /// Frees the provided texture. Same as disposing the resource. - /// - void FreeTexture(Texture2d tex); - - /// - /// Frees the provided pipeline. Same as disposing the resource. - /// - void FreePipeline(Pipeline pipeline); - - /// - /// Frees the provided shader. For internal use only. - /// - void Internal_FreeShader(Shader shader); - - /// - /// Frees the provided vertex layout. For internal use only. - /// - void Internal_FreeVertexLayout(VertexLayout vertexLayout); - } -} diff --git a/src/BizHawk.Bizware.BizwareGL/IGuiRenderer.cs b/src/BizHawk.Bizware.BizwareGL/IGuiRenderer.cs deleted file mode 100644 index f3a77249715..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/IGuiRenderer.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using System.Drawing; -using System.Numerics; - -namespace BizHawk.Bizware.BizwareGL -{ - public interface IGuiRenderer : IDisposable - { - /// - /// Begins rendering - /// - void Begin(); - - void Begin(Size size); - - /// - /// begin rendering, initializing viewport and projections to the given dimensions - /// - void Begin(int width, int height); - - /// - /// draws the specified Art resource - /// - void Draw(Art art); - - /// - /// draws the specified Art resource with the specified offset. This could be tricky if youve applied other rotate or scale transforms first. - /// - void Draw(Art art, Vector2 pos); - - /// - /// draws the specified Art resource with the specified offset. This could be tricky if youve applied other rotate or scale transforms first. - /// - void Draw(Art art, float x, float y); - - /// - /// draws the specified Art resource with the specified offset, with the specified size. This could be tricky if youve applied other rotate or scale transforms first. - /// - void Draw(Art art, float x, float y, float width, float height); - - /// - /// draws the specified Texture with the specified offset, with the specified size. This could be tricky if youve applied other rotate or scale transforms first. - /// - void Draw(Texture2d art, float x, float y, float width, float height); - - /// - /// draws the specified texture2d resource. - /// - void Draw(Texture2d tex); - - /// - /// draws the specified texture2d resource. - /// - void Draw(Texture2d tex, float x, float y); - - /// - /// draws the specified Art resource with the given flip flags - /// - void DrawFlipped(Art art, bool xflip, bool yflip); - - /// - /// Draws a subrectangle from the provided texture. For advanced users only - /// - void DrawSubrect(Texture2d tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1); - - /// - /// Ends rendering - /// - void End(); - - /// - /// Use this, if you must do something sneaky to openGL without this GuiRenderer knowing. - /// It might be faster than End and Beginning again, and certainly prettier - /// - void Flush(); - - bool IsActive { get; } - - MatrixStack Modelview { get; set; } - - IGL Owner { get; } - - MatrixStack Projection { get; set; } - - void RectFill(float x, float y, float w, float h); - - void EnableBlending(); - - void DisableBlending(); - - /// - /// Sets the specified corner color (for the gradient effect) - /// - /// (x, y, z, w) is (r, g, b, a) - void SetCornerColor(int which, Vector4 color); - - /// - /// Sets all four corner colors at once - /// - /// (x, y, z, w) is (r, g, b, a) - void SetCornerColors(Vector4[] colors); - - /// - /// Restores the pipeline to the default - /// - void SetDefaultPipeline(); - - void SetModulateColor(Color color); - - void SetModulateColorWhite(); - - /// - /// Sets the pipeline for this GuiRenderer to use. We won't keep possession of it. - /// This pipeline must work in certain ways, which can be discerned by inspecting the built-in one - /// - void SetPipeline(Pipeline pipeline); - } -} diff --git a/src/BizHawk.Bizware.BizwareGL/Pipeline.cs b/src/BizHawk.Bizware.BizwareGL/Pipeline.cs deleted file mode 100644 index 92c0ecd02fe..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/Pipeline.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using System.Collections.Generic; - -using BizHawk.Common.CollectionExtensions; - -namespace BizHawk.Bizware.BizwareGL -{ - /// - /// WARNING! PLEASE SET THIS PIPELINE CURRENT BEFORE SETTING UNIFORMS IN IT! NOT TOO GREAT, I KNOW. - /// - public class Pipeline : IDisposable - { - public readonly string Memo; - - public Pipeline(IGL owner, object opaque, bool available, VertexLayout vertexLayout, IReadOnlyList uniforms, string memo) - { - Memo = memo; - Owner = owner; - Opaque = opaque; - VertexLayout = vertexLayout; - Available = available; - - // create the uniforms from the info list we got - if (!Available) - { - return; - } - - UniformsDictionary = new(this); - foreach (var ui in uniforms) - { - UniformsDictionary[ui.Name] = new(this); - } - - foreach (var ui in uniforms) - { - UniformsDictionary[ui.Name].AddUniformInfo(ui); - } - } - - /// - /// Allows us to create PipelineUniforms on the fly, in case a non-existing one has been requested. - /// Shader compilers will optimize out unused uniforms, and we wont have a record of it in the uniforms population loop - /// - private class UniformWorkingDictionary : Dictionary - { - public UniformWorkingDictionary(Pipeline owner) - { - Owner = owner; - } - - private Pipeline Owner; - public new PipelineUniform this[string key] - { -#if true - get => this.GetValueOrPut(key, static _ => new(null)); -#else - get => this.GetValueOrPut(key, static _ => new(new UniformInfo { Opaque = null })); -#endif - internal set => base[key] = value; - } - } - - private readonly UniformWorkingDictionary UniformsDictionary; - private IDictionary Uniforms => UniformsDictionary; - - public IEnumerable GetUniforms() => Uniforms.Values; - - public PipelineUniform TryGetUniform(string name) - { - _ = Uniforms.TryGetValue(name, out var ret); - return ret; - } - - public PipelineUniform this[string key] => UniformsDictionary[key]; - - public IGL Owner { get; } - public object Opaque { get; } - public VertexLayout VertexLayout { get; } - public bool Available { get; } - public string Errors { get; set; } - - public void Dispose() - { - Owner.FreePipeline(this); - } - } -} \ No newline at end of file diff --git a/src/BizHawk.Bizware.BizwareGL/PipelineUniform.cs b/src/BizHawk.Bizware.BizwareGL/PipelineUniform.cs deleted file mode 100644 index fb2464d80ec..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/PipelineUniform.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Numerics; - -namespace BizHawk.Bizware.BizwareGL -{ - /// - /// represents a pipeline uniform... - /// and one of those can represent multiple shader uniforms!! - /// - public class PipelineUniform - { - internal PipelineUniform(Pipeline owner) - { - Owner = owner; - } - - internal void AddUniformInfo(UniformInfo ui) - { - _uniformInfos.Add(ui); - } - - public IEnumerable UniformInfos => _uniformInfos; - - private readonly List _uniformInfos = new(); - - /// the first and only - /// more than one exists - public UniformInfo Sole - { - get - { - if (_uniformInfos.Count != 1) - { - throw new InvalidOperationException(); - } - - return _uniformInfos[0]; - } - } - - public Pipeline Owner { get; } - - public void Set(Matrix4x4 mat, bool transpose = false) - { - Owner?.Owner.SetPipelineUniformMatrix(this, mat, transpose); - } - - public void Set(Vector4 vec) - { - Owner?.Owner.SetPipelineUniform(this, vec); - } - - public void Set(Vector2 vec) - { - Owner?.Owner.SetPipelineUniform(this, vec); - } - - public void Set(float f) - { - Owner?.Owner.SetPipelineUniform(this, f); - } - - public void Set(Vector4[] vecs) - { - Owner?.Owner.SetPipelineUniform(this, vecs); - } - - public void Set(ref Matrix4x4 mat, bool transpose = false) - { - Owner?.Owner.SetPipelineUniformMatrix(this, ref mat, transpose); - } - - public void Set(bool value) - { - Owner?.Owner.SetPipelineUniform(this, value); - } - - public void Set(Texture2d tex) - { - Owner?.Owner.SetPipelineUniformSampler(this, tex); - } - } -} \ No newline at end of file diff --git a/src/BizHawk.Bizware.BizwareGL/RenderTarget.cs b/src/BizHawk.Bizware.BizwareGL/RenderTarget.cs deleted file mode 100644 index 8285cbbfb3a..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/RenderTarget.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; - -namespace BizHawk.Bizware.BizwareGL -{ - public class RenderTarget : IDisposable - { - public RenderTarget(IGL owner, object opaque, Texture2d tex) - { - Owner = owner; - Opaque = opaque; - Texture2d = tex; - } - - public override string ToString() - { - return $"GL RT: {Texture2d.Width}x{Texture2d.Height}"; - } - - public object Opaque { get; } - public IGL Owner { get; } - public Texture2d Texture2d { get; } - - public void Unbind() - { - Owner.BindRenderTarget(null); - } - - public void Bind() - { - Owner.BindRenderTarget(this); - } - - public void Dispose() - { - Owner.FreeRenderTarget(this); - } - } -} \ No newline at end of file diff --git a/src/BizHawk.Bizware.BizwareGL/RetroShader.cs b/src/BizHawk.Bizware.BizwareGL/RetroShader.cs deleted file mode 100644 index 2eb7f3446fb..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/RetroShader.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System; -using System.Drawing; -using System.Numerics; - -namespace BizHawk.Bizware.BizwareGL -{ - /// - /// Handles RetroArch's GLSL shader pass format - /// - public class RetroShader : IDisposable - { - // NOTE: we may need to overhaul uniform-setting infrastructure later. - // maybe samplers will need to be set by index and not by name (I think the specs don't dictate what the sampler must be named) - public RetroShader(IGL owner, string source, bool debug = false) - { - Owner = owner; - - VertexLayout = owner.CreateVertexLayout(); - VertexLayout.DefineVertexAttribute("position", 0, 4, VertexAttribPointerType.Float, AttribUsage.Position, false, 40, 0); - VertexLayout.DefineVertexAttribute("color", 1, 4, VertexAttribPointerType.Float, AttribUsage.Color0, false, 40, 16); //just dead weight, i have no idea why this is here. but some old HLSL compilers (used in bizhawk for various reasons) will want it to exist here since it exists in the vertex shader - VertexLayout.DefineVertexAttribute("tex", 2, 2, VertexAttribPointerType.Float, AttribUsage.Texcoord0, false, 40, 32); - VertexLayout.Close(); - - var vsSource = $"#define VERTEX\r\n{source}"; - var psSource = $"#define FRAGMENT\r\n{source}"; - var vs = owner.CreateVertexShader(vsSource, "main_vertex", debug); - var ps = owner.CreateFragmentShader(psSource, "main_fragment", debug); - Pipeline = Owner.CreatePipeline(VertexLayout, vs, ps, debug, "retro"); - - if (!Pipeline.Available) - { - Available = false; - return; - } - - // retroarch shaders will sometimes not have the right sampler name - // it's unclear whether we should bind to s_p or sampler0 - // lets bind to sampler0 in case we don't have s_p - sampler0 = Pipeline.TryGetUniform("s_p"); - if (sampler0 == null) - { - // sampler wasn't named correctly. this can happen on some retroarch shaders - foreach (var u in Pipeline.GetUniforms()) - { - if (u.Sole.IsSampler && u.Sole.SamplerIndex == 0) - { - sampler0 = u; - break; - } - } - } - - // if a sampler isn't available, we can't do much, although this does interfere with debugging (shaders just returning colors will malfunction) - Available = sampler0 != null; - } - - public bool Available { get; } - public string Errors => Pipeline.Errors; - - private readonly PipelineUniform sampler0; - - public void Dispose() - { - Pipeline.Dispose(); - VertexLayout.Release(); - } - - public void Bind() - { - // lame... - Owner.BindPipeline(Pipeline); - } - - public unsafe void Run(Texture2d tex, Size InputSize, Size OutputSize, bool flip) - { - // ack! make sure to set the pipeline before setting uniforms - Bind(); - - Pipeline["IN.video_size"].Set(new Vector2(InputSize.Width, InputSize.Height)); - Pipeline["IN.texture_size"].Set(new Vector2(tex.Width, tex.Height)); - Pipeline["IN.output_size"].Set(new Vector2(OutputSize.Width, OutputSize.Height)); - Pipeline["IN.frame_count"].Set(1); //todo - Pipeline["IN.frame_direction"].Set(1); //todo - - var Projection = Owner.CreateGuiProjectionMatrix(OutputSize); - var Modelview = Owner.CreateGuiViewMatrix(OutputSize); - var mat = Matrix4x4.Transpose(Modelview * Projection); - Pipeline["modelViewProj"].Set(mat, true); - - Owner.SetTextureWrapMode(tex, true); - - sampler0.Set(tex); - Owner.SetViewport(OutputSize); - - var time = DateTime.Now.Second + (float)DateTime.Now.Millisecond / 1000; - Pipeline["Time"].Set(time); - - var w = OutputSize.Width; - var h = OutputSize.Height; - - float v0, v1; - if (flip) - { - v0 = 1; - v1 = 0; - } - else - { - v0 = 0; - v1 = 1; - } - - var pData = stackalloc float[10 * 4]; - var i = 0; - pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 1; //topleft vert - pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //useless color - pData[i++] = 0; pData[i++] = v0; - pData[i++] = w; pData[i++] = 0; pData[i++] = 0; pData[i++] = 1; //topright vert - pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //useless color - pData[i++] = 1; pData[i++] = v0; - pData[i++] = 0; pData[i++] = h; pData[i++] = 0; pData[i++] = 1; //bottomleft vert - pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //useless color - pData[i++] = 0; pData[i++] = v1; - pData[i++] = w; pData[i++] = h; pData[i++] = 0; pData[i++] = 1; //bottomright vert - pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //useless color - pData[i++] = 1; pData[i] = v1; - - Owner.DisableBlending(); - Owner.Draw(new(pData), 4); - } - - public IGL Owner { get; } - - private readonly VertexLayout VertexLayout; - public readonly Pipeline Pipeline; - } -} \ No newline at end of file diff --git a/src/BizHawk.Bizware.BizwareGL/Shader.cs b/src/BizHawk.Bizware.BizwareGL/Shader.cs deleted file mode 100644 index 5e8b7ff587e..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/Shader.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace BizHawk.Bizware.BizwareGL -{ - /// - /// Represents an individual (fragment,vertex) shader. - /// It isn't IDisposable because it'll be lifecycle-managed by the IGL (disposed when all dependent pipelines are disposed) - /// But if you want to be sure to save it for later, use AddRef - /// - public class Shader - { - public Shader(IGL owner, object opaque, bool available) - { - Owner = owner; - Opaque = opaque; - Available = available; - Errors = ""; - } - - public IGL Owner { get; } - public object Opaque { get; } - public bool Available { get; private set; } - public string Errors { get; set; } - - private int RefCount; - - public void Release() - { - RefCount--; - if (RefCount <= 0) - { - Owner.Internal_FreeShader(this); - Available = false; - } - } - - public void AddRef() - { - RefCount++; - } - - } -} \ No newline at end of file diff --git a/src/BizHawk.Bizware.BizwareGL/TexAtlas.cs b/src/BizHawk.Bizware.BizwareGL/TexAtlas.cs deleted file mode 100644 index 501edee5e22..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/TexAtlas.cs +++ /dev/null @@ -1,298 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using System.Drawing; - -namespace BizHawk.Bizware.BizwareGL -{ - public static class TexAtlas - { - public class RectItem - { - public RectItem(int width, int height, object item) - { - Width = width; - Height = height; - Item = item; - } - - public int X, Y; - public int Width, Height; - public int TexIndex; - public object Item; - } - - private class TryFitParam - { - public TryFitParam(int _w, int _h) { this.w = _w; this.h = _h; } - public readonly int w; - public readonly int h; - public bool ok = true; - public readonly RectangleBinPack rbp = new RectangleBinPack(); - public readonly List nodes = new List(); - } - - public const int MaxSizeBits = 16; - - /// - /// packs the supplied RectItems into an atlas. Modifies the RectItems with x/y values of location in new atlas. - /// - public static IReadOnlyList<(Size Size, List Items)> PackAtlas(IEnumerable items) - { - static void AddAtlas(ICollection<(Size, List)> atlases, IEnumerable initItems) - { - List currentItems = new(initItems); - List remainItems = new(); - - TryFitParam tfpFinal; - while (true) - { - // this is where the texture size range is determined. - // we run this every time we make an atlas, in case we want to variably control the maximum texture output size. - // ALSO - we accumulate data in there, so we need to refresh it each time. ... lame. - var todoSizes = new List(); - for (var i = 3; i <= MaxSizeBits; i++) - { - for (var j = 3; j <= MaxSizeBits; j++) - { - var w = 1 << i; - var h = 1 << j; - var tfp = new TryFitParam(w, h); - todoSizes.Add(tfp); - } - } - - //run the packing algorithm on each potential size - Parallel.ForEach(todoSizes, (param) => - { - var rbp = new RectangleBinPack(); - rbp.Init(16384, 16384); - param.rbp.Init(param.w, param.h); - - // ReSharper disable once AccessToModifiedClosure - foreach (var ri in currentItems) - { - var node = param.rbp.Insert(ri.Width, ri.Height); - if (node == null) - { - param.ok = false; - } - else - { - node.ri = ri; - param.nodes.Add(node); - } - } - }); - - // find the best fit among the potential sizes that worked - var best = long.MaxValue; - tfpFinal = todoSizes[0]; - foreach (var tfp in todoSizes) - { - if (!tfp.ok) - { - continue; - } - - var area = tfp.w * (long) tfp.h; - if (area > best) - { - continue; // larger than best, not interested - } - - if (area == best) // same area, compare perimeter as tie-breaker (to create squares, which are nicer to look at) - { - if (tfp.w + tfp.h >= tfpFinal.w + tfpFinal.h) - { - continue; - } - } - - best = area; - tfpFinal = tfp; - } - - //did we find any fit? - if (best < long.MaxValue) - { - break; - } - - //nope - move an item to the remaining list and try again - remainItems.Add(currentItems[currentItems.Count - 1]); - currentItems.RemoveAt(currentItems.Count - 1); - } - - //we found a fit. setup this atlas in the result and drop the items into it - atlases.Add((new(tfpFinal.w, tfpFinal.h), new(currentItems))); - foreach (var item in currentItems) - { - var node = tfpFinal.nodes.Find(x => x.ri == item); - item.X = node.x; - item.Y = node.y; - item.TexIndex = atlases.Count - 1; - } - - //if we have any items left, we've got to run this again - if (remainItems.Count > 0) AddAtlas(atlases, remainItems); - } - - List<(Size, List)> atlases = new(); - AddAtlas(atlases, items); - if (atlases.Count > 1) Console.WriteLine($"Created animset with >1 texture ({atlases.Count} textures)"); - return atlases; - } - - // original file: RectangleBinPack.cpp - // author: Jukka Jylänki - private class RectangleBinPack - { - /** A node of a binary tree. Each node represents a rectangular area of the texture - we surface. Internal nodes store rectangles of used data, whereas leaf nodes track - rectangles of free space. All the rectangles stored in the tree are disjoint. */ - public class Node - { - // Left and right child. We don't really distinguish which is which, so these could - // as well be child1 and child2. - public Node left; - public Node right; - - // The top-left coordinate of the rectangle. - public int x; - public int y; - - // The dimension of the rectangle. - public int width; - public int height; - - public RectItem ri; - } - - /// Starts a new packing process to a bin of the given dimension. - public void Init(int width, int height) - { - binWidth = width; - binHeight = height; - root = new(); - root.left = root.right = null; - root.x = root.y = 0; - root.width = width; - root.height = height; - } - - - /// Inserts a new rectangle of the given size into the bin. - /// A pointer to the node that stores the newly added rectangle, or 0 if it didn't fit. - /// Running time is linear to the number of rectangles that have been already packed. - public Node Insert(int width, int height) - { - return Insert(root, width, height); - } - - /// Computes the ratio of used surface area. - private float Occupancy() - { - var totalSurfaceArea = binWidth * binHeight; - var usedSurfaceArea = UsedSurfaceArea(root); - - return (float)usedSurfaceArea / totalSurfaceArea; - } - - private Node root; - - // The total size of the bin we started with. - private int binWidth; - private int binHeight; - - /// The surface area used by the subtree rooted at node. - private static int UsedSurfaceArea(Node node) - { - if (node.left != null || node.right != null) - { - var usedSurfaceArea = node.width * node.height; - if (node.left != null) - usedSurfaceArea += UsedSurfaceArea(node.left); - if (node.right != null) - usedSurfaceArea += UsedSurfaceArea(node.right); - - return usedSurfaceArea; - } - - // This is a leaf node, it doesn't constitute to the total surface area. - return 0; - } - - - /// Inserts a new rectangle in the subtree rooted at the given node. - private static Node Insert(Node node, int width, int height) - { - - // If this node is an internal node, try both leaves for possible space. - // (The rectangle in an internal node stores used space, the leaves store free space) - if (node.left != null || node.right != null) - { - if (node.left != null) - { - var newNode = Insert(node.left, width, height); - if (newNode != null) - return newNode; - } - if (node.right != null) - { - var newNode = Insert(node.right, width, height); - if (newNode != null) - return newNode; - } - return null; // Didn't fit into either subtree! - } - - // This node is a leaf, but can we fit the new rectangle here? - if (width > node.width || height > node.height) - return null; // Too bad, no space. - - // The new cell will fit, split the remaining space along the shorter axis, - // that is probably more optimal. - var w = node.width - width; - var h = node.height - height; - node.left = new(); - node.right = new(); - if (w <= h) // Split the remaining space in horizontal direction. - { - node.left.x = node.x + width; - node.left.y = node.y; - node.left.width = w; - node.left.height = height; - - node.right.x = node.x; - node.right.y = node.y + height; - node.right.width = node.width; - node.right.height = h; - } - else // Split the remaining space in vertical direction. - { - node.left.x = node.x; - node.left.y = node.y + height; - node.left.width = width; - node.left.height = h; - - node.right.x = node.x + width; - node.right.y = node.y; - node.right.width = w; - node.right.height = node.height; - } - // Note that as a result of the above, it can happen that node.left or node.right - // is now a degenerate (zero area) rectangle. No need to do anything about it, - // like remove the nodes as "unnecessary" since they need to exist as children of - // this node (this node can't be a leaf anymore). - - // This node is now a non-leaf, so shrink its area - it now denotes - // *occupied* space instead of free space. Its children spawn the resulting - // area of free space. - node.width = width; - node.height = height; - return node; - } - } - } -} diff --git a/src/BizHawk.Bizware.BizwareGL/Texture2d.cs b/src/BizHawk.Bizware.BizwareGL/Texture2d.cs deleted file mode 100644 index 3040ce0a109..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/Texture2d.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.Drawing; - -namespace BizHawk.Bizware.BizwareGL -{ - /// - /// A full-scale 2D texture, with mip levels and everything. - /// In OpenGL tradition, this encapsulates the sampler state, as well, which is equal parts annoying and convenient - /// - public class Texture2d : IDisposable - { - /// - /// resolves the texture into a new BitmapBuffer - /// - public BitmapBuffer Resolve() - { - return Owner.ResolveTexture2d(this); - } - - public void Dispose() - { - Owner.FreeTexture(this); - Opaque = null; - } - - public Texture2d(IGL owner, object opaque, int width, int height) - { - Owner = owner; - Opaque = opaque; - Width = width; - Height = height; - } - - public override string ToString() - { - return $"GL Tex: {Width}x{Height}"; - } - - public void LoadFrom(BitmapBuffer buffer) - { - } - - public void SetMinFilter(TextureMinFilter minFilter) => Owner.SetMinFilter(this, minFilter); - - public void SetMagFilter(TextureMagFilter magFilter) => Owner.SetMagFilter(this, magFilter); - - public void SetFilterLinear() - { - SetMinFilter(TextureMinFilter.Linear); - SetMagFilter(TextureMagFilter.Linear); - } - - public void SetFilterNearest() - { - SetMinFilter(TextureMinFilter.Nearest); - SetMagFilter(TextureMagFilter.Nearest); - } - - public IGL Owner { get; } - public object Opaque { get; private set; } - - // note.. this was a lame idea. convenient, but weird. lets just change this back to ints. - public float Width { get; } - public float Height { get; } - - public int IntWidth => (int)Width; - public int IntHeight => (int)Height; - public Rectangle Rectangle => new(0, 0, IntWidth, IntHeight); - public Size Size => new(IntWidth, IntHeight); - - /// - /// opengl sucks, man. seriously, screw this (textures from render targets are upside down) - /// (couldn't we fix it up in the matrices somewhere?) - /// - public bool IsUpsideDown; - } -} \ No newline at end of file diff --git a/src/BizHawk.Bizware.BizwareGL/UniformInfo.cs b/src/BizHawk.Bizware.BizwareGL/UniformInfo.cs deleted file mode 100644 index 3d749b62932..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/UniformInfo.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace BizHawk.Bizware.BizwareGL -{ - public class UniformInfo - { - public object Opaque; - public string Name; - public int SamplerIndex; - public bool IsSampler; - } -} \ No newline at end of file diff --git a/src/BizHawk.Bizware.BizwareGL/VertexLayout.cs b/src/BizHawk.Bizware.BizwareGL/VertexLayout.cs deleted file mode 100644 index 6da0e46d3b2..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/VertexLayout.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using BizHawk.Common; - -namespace BizHawk.Bizware.BizwareGL -{ - /// - /// Represents a vertex layout, really a kind of a peer of the vertex and fragment shaders. - /// It isn't IDisposable because it'll be lifecycle-managed by the IGL (disposed when all dependent pipelines are disposed) - /// But if you want to be sure to save it for later, use AddRef - /// - public class VertexLayout - { - public VertexLayout(IGL owner, object opaque) - { - Owner = owner; - Opaque = opaque; - Items = new(); - } - - public object Opaque { get; } - public IGL Owner { get; } - - private int RefCount; - - public void Release() - { - RefCount--; - if (RefCount <= 0) - { - Owner.Internal_FreeVertexLayout(this); - } - } - - public void AddRef() - { - RefCount++; - } - - /// already closed (by call to ) - public void DefineVertexAttribute(string name, int index, int components, VertexAttribPointerType attribType, AttribUsage usage, bool normalized, int stride, int offset = 0) - { - if (Closed) - { - throw new InvalidOperationException("Type is Closed and is now immutable."); - } - - Items[index] = new() { Name = name, Components = components, AttribType = attribType, Usage = usage, Normalized = normalized, Stride = stride, Offset = offset }; - } - - /// - /// finishes this VertexLayout and renders it immutable - /// - public void Close() - { - Closed = true; - } - - public class LayoutItem - { - public string Name { get; internal set; } - public int Components { get; internal set; } - public VertexAttribPointerType AttribType { get; internal set; } - public bool Normalized { get; internal set; } - public int Stride { get; internal set; } - public int Offset { get; internal set; } - public AttribUsage Usage { get; internal set; } - } - - public class LayoutItemWorkingDictionary : WorkingDictionary - { - public new LayoutItem this[int key] - { - get => base[key]; - internal set => base[key] = value; - } - } - - public LayoutItemWorkingDictionary Items { get; } - private bool Closed; - - } -} \ No newline at end of file diff --git a/src/BizHawk.Bizware.BizwareGL/enums/TextureMagFilter.cs b/src/BizHawk.Bizware.BizwareGL/enums/TextureMagFilter.cs deleted file mode 100644 index 73ddfedc612..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/enums/TextureMagFilter.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace BizHawk.Bizware.BizwareGL -{ - public enum TextureMagFilter - { - Nearest = 0x2600, - Linear = 0x2601, - LinearDetailSgis = 0x8097, - LinearDetailAlphaSgis = 0x8098, - LinearDetailColorSgis = 0x8099, - LinearSharpenSgis = 0x80AD, - LinearSharpenAlphaSgis = 0x80AE, - LinearSharpenColorSgis = 0x80AF, - Filter4Sgis = 0x8146, - PixelTexGenQCeilingSgix = 0x8184, - PixelTexGenQRoundSgix = 0x8185, - PixelTexGenQFloorSgix = 0x8186, - } -} diff --git a/src/BizHawk.Bizware.BizwareGL/enums/TextureMinFilter.cs b/src/BizHawk.Bizware.BizwareGL/enums/TextureMinFilter.cs deleted file mode 100644 index 749a9f238e8..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/enums/TextureMinFilter.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace BizHawk.Bizware.BizwareGL -{ - public enum TextureMinFilter - { - Nearest = 0x2600, - Linear = 0x2601, - NearestMipmapNearest = 0x2700, - LinearMipmapNearest = 0x2701, - NearestMipmapLinear = 0x2702, - LinearMipmapLinear = 0x2703, - Filter4Sgis = 0x8146, - LinearClipmapLinearSgix = 0x8170, - PixelTexGenQCeilingSgix = 0x8184, - PixelTexGenQRoundSgix = 0x8185, - PixelTexGenQFloorSgix = 0x8186, - NearestClipmapNearestSgix = 0x844D, - NearestClipmapLinearSgix = 0x844E, - LinearClipmapNearestSgix = 0x844F, - } -} diff --git a/src/BizHawk.Bizware.BizwareGL/enums/VertexAttribPointerType.cs b/src/BizHawk.Bizware.BizwareGL/enums/VertexAttribPointerType.cs deleted file mode 100644 index af3794fe098..00000000000 --- a/src/BizHawk.Bizware.BizwareGL/enums/VertexAttribPointerType.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace BizHawk.Bizware.BizwareGL -{ - public enum VertexAttribPointerType - { - Byte = 0x1400, - UnsignedByte = 0x1401, - Short = 0x1402, - UnsignedShort = 0x1403, - Int = 0x1404, - UnsignedInt = 0x1405, - Float = 0x1406, - Double = 0x140A, - HalfFloat = 0x140B, - Fixed = 0x140C, - UnsignedInt2101010Rev = 0x8368, - UnsignedInt10F11F11FRev = 0x8C3B, - Int2101010Rev = 0x8D9F, - } -} diff --git a/src/BizHawk.Bizware.Graphics.Controls/BizHawk.Bizware.Graphics.Controls.csproj b/src/BizHawk.Bizware.Graphics.Controls/BizHawk.Bizware.Graphics.Controls.csproj index afa42186c55..a5062d60206 100644 --- a/src/BizHawk.Bizware.Graphics.Controls/BizHawk.Bizware.Graphics.Controls.csproj +++ b/src/BizHawk.Bizware.Graphics.Controls/BizHawk.Bizware.Graphics.Controls.csproj @@ -6,9 +6,10 @@ true disable + true - + diff --git a/src/BizHawk.Bizware.Graphics.Controls/Controls/D3D9Control.cs b/src/BizHawk.Bizware.Graphics.Controls/Controls/D3D11Control.cs similarity index 60% rename from src/BizHawk.Bizware.Graphics.Controls/Controls/D3D9Control.cs rename to src/BizHawk.Bizware.Graphics.Controls/Controls/D3D11Control.cs index 73e66e89b75..863f9424b5f 100644 --- a/src/BizHawk.Bizware.Graphics.Controls/Controls/D3D9Control.cs +++ b/src/BizHawk.Bizware.Graphics.Controls/Controls/D3D11Control.cs @@ -1,17 +1,16 @@ -using System; using System.Windows.Forms; namespace BizHawk.Bizware.Graphics.Controls { - internal sealed class D3D9Control : GraphicsControl + internal sealed class D3D11Control : GraphicsControl { - private readonly Func _createSwapChain; - private D3D9SwapChain _swapChain; - private bool Vsync; + private readonly Func _createSwapChain; + private D3D11SwapChain _swapChain; + private bool Vsync, AllowsTearing; - private D3D9SwapChain.ControlParameters ControlParameters => new(Handle, Width, Height, Vsync); + private D3D11SwapChain.ControlParameters ControlParameters => new(Handle, Width, Height, Vsync, AllowsTearing); - public D3D9Control(Func createSwapChain) + public D3D11Control(Func createSwapChain) { _createSwapChain = createSwapChain; @@ -41,20 +40,19 @@ protected override void OnResize(EventArgs e) _swapChain.Refresh(ControlParameters); } + public override void AllowTearing(bool state) + => AllowsTearing = state; + public override void SetVsync(bool state) - { - if (Vsync != state) - { - Vsync = state; - _swapChain.Refresh(ControlParameters); - } - } + => Vsync = state; public override void Begin() - => _swapChain.SetBackBuffer(); + { + } public override void End() - => _swapChain.SetBackBuffer(); + { + } public override void SwapBuffers() => _swapChain.PresentBuffer(ControlParameters); diff --git a/src/BizHawk.Bizware.Graphics.Controls/Controls/GDIPlusControl.cs b/src/BizHawk.Bizware.Graphics.Controls/Controls/GDIPlusControl.cs index de5e4124276..1bbb4810a29 100644 --- a/src/BizHawk.Bizware.Graphics.Controls/Controls/GDIPlusControl.cs +++ b/src/BizHawk.Bizware.Graphics.Controls/Controls/GDIPlusControl.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; @@ -9,23 +8,33 @@ namespace BizHawk.Bizware.Graphics.Controls { internal sealed class GDIPlusControl : GraphicsControl { - public GDIPlusControl(Func, GDIPlusRenderTarget> createControlRenderTarget) + /// + /// The render target for rendering to this control + /// + private readonly GDIPlusControlRenderTarget _renderTarget; + + public GDIPlusControl(Func, GDIPlusControlRenderTarget> createControlRenderTarget) { - RenderTarget = createControlRenderTarget(GetControlRenderContext); + _renderTarget = createControlRenderTarget(GetControlRenderContext); SetStyle(ControlStyles.UserPaint, true); - SetStyle(ControlStyles.OptimizedDoubleBuffer, true); SetStyle(ControlStyles.Opaque, true); SetStyle(ControlStyles.UserMouse, true); + DoubleBuffered = true; } private (SDGraphics Graphics, Rectangle Rectangle) GetControlRenderContext() - => (CreateGraphics(), ClientRectangle); + { + var graphics = CreateGraphics(); + graphics.CompositingMode = CompositingMode.SourceCopy; + graphics.CompositingQuality = CompositingQuality.HighSpeed; + return (graphics, ClientRectangle); + } - /// - /// The render target for rendering to this control - /// - private GDIPlusRenderTarget RenderTarget { get; } + public override void AllowTearing(bool state) + { + // not controllable + } public override void SetVsync(bool state) { @@ -33,30 +42,32 @@ public override void SetVsync(bool state) } public override void Begin() - => RenderTarget.CreateGraphics(); + { + } public override void End() { } - protected override void OnResize(EventArgs e) + protected override void OnHandleCreated(EventArgs e) { - base.OnResize(e); - RenderTarget.CreateGraphics(); + base.OnHandleCreated(e); + _renderTarget.CreateGraphics(); } - public override void SwapBuffers() + protected override void OnHandleDestroyed(EventArgs e) { - if (RenderTarget.BufferedGraphics == null) - { - return; - } + base.OnHandleDestroyed(e); + _renderTarget.Dispose(); + } - using var g = CreateGraphics(); - // not sure we had proof we needed this but it cant hurt - g.CompositingMode = CompositingMode.SourceCopy; - g.CompositingQuality = CompositingQuality.HighSpeed; - RenderTarget.BufferedGraphics.Render(g); + protected override void OnResize(EventArgs e) + { + base.OnResize(e); + _renderTarget.CreateGraphics(); } + + public override void SwapBuffers() + => _renderTarget.BufferedGraphics?.Render(_renderTarget.ControlGraphics); } -} \ No newline at end of file +} diff --git a/src/BizHawk.Bizware.Graphics.Controls/Controls/OpenGLControl.cs b/src/BizHawk.Bizware.Graphics.Controls/Controls/OpenGLControl.cs index 3edc4984909..c3d62a6e7f7 100644 --- a/src/BizHawk.Bizware.Graphics.Controls/Controls/OpenGLControl.cs +++ b/src/BizHawk.Bizware.Graphics.Controls/Controls/OpenGLControl.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Common; @@ -7,10 +6,13 @@ namespace BizHawk.Bizware.Graphics.Controls { internal sealed class OpenGLControl : GraphicsControl { - public SDL2OpenGLContext Context { get; private set; } + private readonly Action _initGLState; + private SDL2OpenGLContext _context; - public OpenGLControl() + public OpenGLControl(Action initGLState) { + _initGLState = initGLState; + // according to OpenTK, these are the styles we want to set SetStyle(ControlStyles.Opaque, true); SetStyle(ControlStyles.UserPaint, true); @@ -41,14 +43,15 @@ protected override CreateParams CreateParams protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); - Context = new(Handle, 3, 0, false, false); + _context = new(Handle, 3, 2, true); + _initGLState(); } protected override void OnHandleDestroyed(EventArgs e) { base.OnHandleDestroyed(e); - Context.Dispose(); - Context = null; + _context.Dispose(); + _context = null; } private void MakeContextCurrent() @@ -58,36 +61,37 @@ private void MakeContextCurrent() throw new ObjectDisposedException(nameof(OpenGLControl)); } - if (Context is null) + if (_context is null) { CreateControl(); } else { - Context.MakeContextCurrent(); + _context.MakeContextCurrent(); } } - public override void SetVsync(bool state) + public override void AllowTearing(bool state) { - MakeContextCurrent(); - Context.SetVsync(state); + // not controllable } - public override void Begin() + public override void SetVsync(bool state) { MakeContextCurrent(); + _context.SetVsync(state); } + public override void Begin() + => MakeContextCurrent(); + public override void End() - { - SDL2OpenGLContext.MakeNoneCurrent(); - } + => SDL2OpenGLContext.MakeNoneCurrent(); public override void SwapBuffers() { MakeContextCurrent(); - Context.SwapBuffers(); + _context.SwapBuffers(); } } -} \ No newline at end of file +} diff --git a/src/BizHawk.Client.EmuHawk/GraphicsImplementations/RetainedGraphicsControl.cs b/src/BizHawk.Bizware.Graphics.Controls/Controls/RetainedGraphicsControl.cs similarity index 70% rename from src/BizHawk.Client.EmuHawk/GraphicsImplementations/RetainedGraphicsControl.cs rename to src/BizHawk.Bizware.Graphics.Controls/Controls/RetainedGraphicsControl.cs index 660850859c3..14515add78d 100644 --- a/src/BizHawk.Client.EmuHawk/GraphicsImplementations/RetainedGraphicsControl.cs +++ b/src/BizHawk.Bizware.Graphics.Controls/Controls/RetainedGraphicsControl.cs @@ -1,10 +1,6 @@ using System.Windows.Forms; -using BizHawk.Bizware.BizwareGL; -using BizHawk.Bizware.Graphics; -using BizHawk.Bizware.Graphics.Controls; - -namespace BizHawk.Client.EmuHawk +namespace BizHawk.Bizware.Graphics.Controls { /// /// Adapts a GraphicsControl to gain the power of remembering what was drawn to it, and keeping it presented in response to Paint events @@ -16,6 +12,20 @@ public RetainedGraphicsControl(IGL gl) _gl = gl; _graphicsControl = GraphicsControlFactory.CreateGraphicsControl(gl); _guiRenderer = new(gl); + + SetStyle(ControlStyles.Opaque, true); + SetStyle(ControlStyles.UserPaint, true); + SetStyle(ControlStyles.AllPaintingInWmPaint, true); + SetStyle(ControlStyles.UserMouse, true); + + _graphicsControl.Dock = DockStyle.Fill; + _graphicsControl.MouseDoubleClick += (_, e) => OnMouseDoubleClick(e); + _graphicsControl.MouseClick += (_, e) => OnMouseClick(e); + _graphicsControl.MouseEnter += (_, e) => OnMouseEnter(e); + _graphicsControl.MouseLeave += (_, e) => OnMouseLeave(e); + _graphicsControl.MouseMove += (_, e) => OnMouseMove(e); + _graphicsControl.Paint += (_, e) => OnPaint(e); + Controls.Add(_graphicsControl); } /// @@ -41,7 +51,7 @@ public bool Retain private readonly IGL _gl; private readonly GraphicsControl _graphicsControl; - private RenderTarget _rt; + private IRenderTarget _rt; private readonly GuiRenderer _guiRenderer; protected override void OnPaint(PaintEventArgs e) @@ -53,6 +63,9 @@ protected override void OnPaint(PaintEventArgs e) _graphicsControl.End(); } + public override void AllowTearing(bool state) + => _graphicsControl.AllowTearing(state); + public override void SetVsync(bool state) => _graphicsControl.SetVsync(state); @@ -73,7 +86,7 @@ public override void End() { if (_retain) { - _rt.Unbind(); + _gl.BindDefaultRenderTarget(); } _graphicsControl.End(); @@ -89,7 +102,7 @@ public override void SwapBuffers() } // if we're retaining, then we cant draw until we unbind! its semantically a bit odd, but we expect users to call SwapBuffers() before end, so we cant unbind in End() even thoug hit makes a bit more sense. - _rt.Unbind(); + _gl.BindDefaultRenderTarget(); Draw(); } @@ -102,9 +115,9 @@ private void Draw() _guiRenderer.Begin(Width, Height); _guiRenderer.DisableBlending(); - _guiRenderer.Draw(_rt.Texture2d); + _guiRenderer.Draw(_rt); _guiRenderer.End(); _graphicsControl.SwapBuffers(); } } -} \ No newline at end of file +} diff --git a/src/BizHawk.Bizware.Graphics.Controls/GraphicsControl.cs b/src/BizHawk.Bizware.Graphics.Controls/GraphicsControl.cs index fb32cb464b7..4215bdf67cc 100644 --- a/src/BizHawk.Bizware.Graphics.Controls/GraphicsControl.cs +++ b/src/BizHawk.Bizware.Graphics.Controls/GraphicsControl.cs @@ -4,13 +4,20 @@ namespace BizHawk.Bizware.Graphics.Controls { public abstract class GraphicsControl : Control { + /// + /// Allows the control to tear when out of vsync + /// Only relevant for D3D11Control currently + /// + public abstract void AllowTearing(bool state); + /// /// Sets whether presentation operations on this control will vsync /// public abstract void SetVsync(bool state); /// - /// Swaps the buffers for this control + /// Swaps the buffers for this control. + /// Be aware, the owner IGL's current render target is undefined after calling this /// public abstract void SwapBuffers(); diff --git a/src/BizHawk.Bizware.Graphics.Controls/GraphicsControlFactory.cs b/src/BizHawk.Bizware.Graphics.Controls/GraphicsControlFactory.cs index 05f11ce9a4f..54214a041f9 100644 --- a/src/BizHawk.Bizware.Graphics.Controls/GraphicsControlFactory.cs +++ b/src/BizHawk.Bizware.Graphics.Controls/GraphicsControlFactory.cs @@ -1,7 +1,3 @@ -using System; - -using BizHawk.Bizware.BizwareGL; - namespace BizHawk.Bizware.Graphics.Controls { /// @@ -13,8 +9,8 @@ public static GraphicsControl CreateGraphicsControl(IGL gl) { GraphicsControl ret = gl switch { - IGL_OpenGL => new OpenGLControl(), - IGL_D3D9 d3d9 => new D3D9Control(d3d9.CreateSwapChain), + IGL_OpenGL openGL => new OpenGLControl(openGL.InitGLState), + IGL_D3D11 d3d11 => new D3D11Control(d3d11.CreateSwapChain), IGL_GDIPlus gdiPlus => new GDIPlusControl(gdiPlus.CreateControlRenderTarget), _ => throw new InvalidOperationException() }; diff --git a/src/BizHawk.Bizware.BizwareGL/AttribUsage.cs b/src/BizHawk.Bizware.Graphics/AttribUsage.cs similarity index 55% rename from src/BizHawk.Bizware.BizwareGL/AttribUsage.cs rename to src/BizHawk.Bizware.Graphics/AttribUsage.cs index 414022d96df..5e5b0dfb71e 100644 --- a/src/BizHawk.Bizware.BizwareGL/AttribUsage.cs +++ b/src/BizHawk.Bizware.Graphics/AttribUsage.cs @@ -1,10 +1,9 @@ -namespace BizHawk.Bizware.BizwareGL +namespace BizHawk.Bizware.Graphics { public enum AttribUsage { - Unspecified, Position, Color0, Texcoord0, Texcoord1, } -} \ No newline at end of file +} diff --git a/src/BizHawk.Bizware.BizwareGL/BitmapBuffer.cs b/src/BizHawk.Bizware.Graphics/BitmapBuffer.cs similarity index 89% rename from src/BizHawk.Bizware.BizwareGL/BitmapBuffer.cs rename to src/BizHawk.Bizware.Graphics/BitmapBuffer.cs index 7e03c06cde8..8bcb1ce2fbc 100644 --- a/src/BizHawk.Bizware.BizwareGL/BitmapBuffer.cs +++ b/src/BizHawk.Bizware.Graphics/BitmapBuffer.cs @@ -1,15 +1,16 @@ // TODO - introduce Trim for ArtManager // TODO - add a small buffer reuse manager.. small images can be stored in larger buffers which we happen to have held. use a timer to wait to free it until some time has passed -using System; using System.Diagnostics; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; -using System.Runtime.InteropServices; using System.IO; +using System.Runtime.InteropServices; -namespace BizHawk.Bizware.BizwareGL +using SDGraphics = System.Drawing.Graphics; + +namespace BizHawk.Bizware.Graphics { /// /// a software-based bitmap, way easier (and faster) to use than .net's built-in bitmap. @@ -33,6 +34,10 @@ public unsafe class BitmapBuffer : IDisposable private GCHandle CurrLockHandle; private BitmapData CurrLock; + /// same as (A8R8G8B8) + public Span AsSpan() + => Pixels; + /// already locked /// TODO add read/write semantic, for wraps public BitmapData LockBits() @@ -212,19 +217,24 @@ public BitmapBuffer Trim(out int xofs, out int yofs) return new(0, 0); } - var w = maxx - minx + 1; - var h = maxy - miny + 1; - var bbRet = new BitmapBuffer(w, h); - for (var y = 0; y < h; y++) - { - for (var x = 0; x < w; x++) - { - bbRet.SetPixel(x, y, GetPixel(x + minx, y + miny)); - } - } - xofs = minx; yofs = miny; + return Copy(region: new(x: minx, y: miny, width: maxx - minx + 1, height: maxy - miny + 1)); + } + + public BitmapBuffer Copy() + => new(width: Width, height: Height, pixels: Pixels.AsSpan().ToArray()); + + /// TODO surely there's a better implementation --yoshi + public BitmapBuffer Copy(Rectangle region) + { + BitmapBuffer bbRet = new(region.Size); + var miny = region.Top; + var minx = region.Left; + for (int y = 0, h = region.Height; y < h; y++) for (int x = 0, w = region.Width; x < w; x++) + { + bbRet.SetPixel(x, y, GetPixel(x + minx, y + miny)); + } return bbRet; } @@ -534,6 +544,8 @@ private static int NextHigher(int k) return candidate; } + public bool SequenceEqual(BitmapBuffer other) + => Width == other.Width && Height == other.Height && AsSpan().SequenceEqual(other.AsSpan()); /// /// Dumps this BitmapBuffer to a new System.Drawing.Bitmap @@ -559,7 +571,7 @@ public void ToSysdrawingBitmap(Bitmap bmp) { if (WrappedBitmap != null) { - using var g = Graphics.FromImage(bmp); + using var g = SDGraphics.FromImage(bmp); g.CompositingMode = CompositingMode.SourceCopy; g.CompositingQuality = CompositingQuality.HighSpeed; g.DrawImageUnscaled(WrappedBitmap, 0, 0); @@ -567,7 +579,7 @@ public void ToSysdrawingBitmap(Bitmap bmp) } //note: we lock it as 32bpp even if the bitmap is 24bpp so we can write to it more conveniently. - var bmpdata = bmp.LockBits(new(0, 0, Width, Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); + var bmpdata = bmp.LockBits(new(0, 0, Width, Height), ImageLockMode.WriteOnly, HasAlpha ? PixelFormat.Format32bppArgb : PixelFormat.Format32bppRgb); if (bmpdata.Stride == bmpdata.Width * 4) { diff --git a/src/BizHawk.Bizware.BizwareGL/BitmapLoadOptions.cs b/src/BizHawk.Bizware.Graphics/BitmapLoadOptions.cs similarity index 93% rename from src/BizHawk.Bizware.BizwareGL/BitmapLoadOptions.cs rename to src/BizHawk.Bizware.Graphics/BitmapLoadOptions.cs index d8168e075c0..58778ea6c61 100644 --- a/src/BizHawk.Bizware.BizwareGL/BitmapLoadOptions.cs +++ b/src/BizHawk.Bizware.Graphics/BitmapLoadOptions.cs @@ -1,7 +1,6 @@ -using System; using System.Drawing; -namespace BizHawk.Bizware.BizwareGL +namespace BizHawk.Bizware.Graphics { public class BitmapLoadOptions { diff --git a/src/BizHawk.Bizware.Graphics/BizHawk.Bizware.Graphics.csproj b/src/BizHawk.Bizware.Graphics/BizHawk.Bizware.Graphics.csproj index 805c9754c8e..267244effbe 100644 --- a/src/BizHawk.Bizware.Graphics/BizHawk.Bizware.Graphics.csproj +++ b/src/BizHawk.Bizware.Graphics/BizHawk.Bizware.Graphics.csproj @@ -8,9 +8,15 @@ disable - - + + + + + + - + + + diff --git a/src/BizHawk.Bizware.Graphics/D3D11/D3D11GLInterop.cs b/src/BizHawk.Bizware.Graphics/D3D11/D3D11GLInterop.cs new file mode 100644 index 00000000000..7e16b3d5167 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/D3D11/D3D11GLInterop.cs @@ -0,0 +1,294 @@ +using Silk.NET.Core.Contexts; +using Silk.NET.OpenGL; +using Silk.NET.WGL.Extensions.NV; + +using Vortice.Direct3D; +using Vortice.Direct3D11; +using Vortice.DXGI; + +using BizHawk.Common.StringExtensions; + +using static SDL2.SDL; + +namespace BizHawk.Bizware.Graphics +{ + internal sealed class D3D11GLInterop : IDisposable + { + public static readonly bool IsAvailable; + + // we use glCopyImageSubData in order to copy an external gl texture to our wrapped gl texture + // this is only guaranteed for GL 4.3 however, so we want to handle grabbing the ARB_copy_image or NV_copy_image extension variants + private static IntPtr GetGLProcAddress(string proc) + { + var ret = SDL2OpenGLContext.GetGLProcAddress(proc); + if (ret == IntPtr.Zero && proc == "glCopyImageSubData") + { + // note that both core and ARB_copy_image use the same proc name + // however, NV_copy_image uses a different name + ret = SDL2OpenGLContext.GetGLProcAddress("glCopyImageSubDataNV"); + } + + return ret; + } + + private static readonly GL GL; + private static readonly NVDXInterop NVDXInterop; + + private enum Vendor + { + Nvida, + Amd, + Intel, + Unknown + } + + static D3D11GLInterop() + { + using (new SavedOpenGLContext()) + { + try + { + // from Kronos: + // "WGL function retrieval does require an active, current context. However, the use of WGL functions do not. + // Therefore, you can destroy the context after querying all of the WGL extension functions." + + // from Microsoft: + // "The extension function addresses are unique for each pixel format. + // All rendering contexts of a given pixel format share the same extension function addresses." + + var (majorVersion, minorVersion) = OpenGLVersion.SupportsVersion(4, 3) ? (4, 3) : (2, 1); + using var glContext = new SDL2OpenGLContext(majorVersion, minorVersion, true); + + GL = GL.GetApi(GetGLProcAddress); + if (GL.CurrentVTable.Load("glCopyImageSubData") == IntPtr.Zero + || GL.CurrentVTable.Load("glGenTextures") == IntPtr.Zero + || GL.CurrentVTable.Load("glDeleteTextures") == IntPtr.Zero) + { + return; + } + + // note: Silk.NET's WGL.IsExtensionPresent function seems to be bugged and just results in NREs... + NVDXInterop = new(new LamdaNativeContext(SDL2OpenGLContext.GetGLProcAddress)); + if (NVDXInterop.CurrentVTable.Load("wglDXOpenDeviceNV") == IntPtr.Zero + || NVDXInterop.CurrentVTable.Load("wglDXCloseDeviceNV") == IntPtr.Zero + || NVDXInterop.CurrentVTable.Load("wglDXRegisterObjectNV") == IntPtr.Zero + || NVDXInterop.CurrentVTable.Load("wglDXUnregisterObjectNV") == IntPtr.Zero + || NVDXInterop.CurrentVTable.Load("wglDXLockObjectsNV") == IntPtr.Zero + || NVDXInterop.CurrentVTable.Load("wglDXUnlockObjectsNV") == IntPtr.Zero) + { + return; + } + + var glVendor = GL.GetStringS(StringName.Vendor); + var vendor = Vendor.Unknown; + switch (glVendor) + { + case "NVIDIA Corporation": + vendor = Vendor.Nvida; + break; + case "ATI Technologies Inc." or "Advanced Micro Devices, Inc.": + vendor = Vendor.Amd; + break; + default: + { + if (glVendor.Contains("Intel", StringComparison.Ordinal)) + { + vendor = Vendor.Intel; + } + + break; + } + } + + // using these NVDXInterop functions shouldn't need a context active (see above Kronos comment) + // however, some buggy drivers will end up failing if we don't have a context + // explicitly make no context active to catch these buggy drivers + SDL2OpenGLContext.MakeNoneCurrent(); + + ID3D11Device device = null; + var dxInteropDevice = IntPtr.Zero; + try + { + D3D11.D3D11CreateDevice( + adapter: null, + DriverType.Hardware, + DeviceCreationFlags.BgraSupport, + null!, + out device, + out var context).CheckError(); + context.Dispose(); + + // try to not use this extension if the D3D11 device is using different GPUs + // some buggy drivers will end up crashing if these mismatch + // presumingly hybrid GPU PCs just have an Intel card and an AMD or NVIDIA card + // so just checking if vendors match should suffice + using var dxgiDevice = device.QueryInterface(); + using var adapter = dxgiDevice.GetAdapter(); + var vendorId = adapter.Description.VendorId; + switch (vendorId) + { + // match against vendor ids + case 0x10DE when vendor == Vendor.Nvida: + case 0x1002 when vendor == Vendor.Amd: + case 0x8086 when vendor == Vendor.Intel: + break; + // for now, don't even try for unknown vendors + default: + return; + } + + unsafe + { + dxInteropDevice = NVDXInterop.DxopenDevice((void*)device.NativePointer); + } + + // TODO: test interop harder? + IsAvailable = dxInteropDevice != IntPtr.Zero; + } + finally + { + if (dxInteropDevice != IntPtr.Zero) + { + NVDXInterop.DxcloseDevice(dxInteropDevice); + } + + device?.Dispose(); + + if (!IsAvailable) + { + GL?.Dispose(); + GL = null; + NVDXInterop?.Dispose(); + NVDXInterop = null; + } + } + } + catch + { + // ignored + } + } + } + + private readonly D3D11Resources _resources; + private ID3D11Device Device => _resources.Device; + + private IntPtr _dxInteropDevice; + private IntPtr _lastGLContext; + private D3D11Texture2D _wrappedGLTexture; + private IntPtr _wrappedGLTexInteropHandle; + private uint _wrappedGLTexID; + + public D3D11GLInterop(D3D11Resources resources) + { + _resources = resources; + try + { + OpenInteropDevice(); + } + catch + { + Dispose(); + throw; + } + } + + public void OpenInteropDevice() + { + unsafe + { + _dxInteropDevice = NVDXInterop.DxopenDevice((void*)Device.NativePointer); + } + + if (_dxInteropDevice == IntPtr.Zero) + { + throw new InvalidOperationException("Failed to open DX interop device"); + } + } + + public D3D11Texture2D WrapGLTexture(int glTexId, int width, int height) + { + var glContext = SDL_GL_GetCurrentContext(); + if (glContext == IntPtr.Zero) + { + // can't do much without a context... + return null; + } + + if (_lastGLContext != glContext) + { + DestroyWrappedTexture(hasActiveContext: false); + _lastGLContext = glContext; + } + + if (_wrappedGLTexture == null || _wrappedGLTexture.Width != width || _wrappedGLTexture.Height != height) + { + DestroyWrappedTexture(hasActiveContext: true); + CreateWrappedTexture(width, height); + } + + unsafe + { + var wrappedGLTexInteropHandle = _wrappedGLTexInteropHandle; + NVDXInterop.DxlockObjects(hDevice: _dxInteropDevice, 1, &wrappedGLTexInteropHandle); + + GL.CopyImageSubData((uint)glTexId, CopyImageSubDataTarget.Texture2D, 0, 0, 0, 0, + _wrappedGLTexID, CopyImageSubDataTarget.Texture2D, 0, 0, 0, 0, (uint)width, (uint)height, 1); + + NVDXInterop.DxunlockObjects(hDevice: _dxInteropDevice, 1, &wrappedGLTexInteropHandle); + } + + return _wrappedGLTexture; + } + + private void CreateWrappedTexture(int width, int height) + { + _wrappedGLTexID = GL.GenTexture(); + _wrappedGLTexture = new(_resources, BindFlags.ShaderResource, ResourceUsage.Default, CpuAccessFlags.None, width, height, wrapped: true); + unsafe + { + _wrappedGLTexInteropHandle = NVDXInterop.DxregisterObject( + hDevice: _dxInteropDevice, + dxObject: (void*)_wrappedGLTexture.Texture.NativePointer, + name: _wrappedGLTexID, + type: (NV)GLEnum.Texture2D, + access: NV.AccessWriteDiscardNV); + } + } + + private void DestroyWrappedTexture(bool hasActiveContext = false) + { + if (_wrappedGLTexInteropHandle != IntPtr.Zero) + { + NVDXInterop.DxunregisterObject(_dxInteropDevice, _wrappedGLTexInteropHandle); + _wrappedGLTexInteropHandle = IntPtr.Zero; + } + + // this gl tex id is owned by the external context, which might be unavailable + // if it's unavailable, we assume that context was just destroyed + // therefore, assume the texture was already destroy in that case + if (hasActiveContext && _wrappedGLTexID != 0) + { + GL.DeleteTexture(_wrappedGLTexID); + } + + _wrappedGLTexID = 0; + + _wrappedGLTexture?.Dispose(); + _wrappedGLTexture = null; + } + + public void Dispose() + { + DestroyWrappedTexture(hasActiveContext: false); + + if (_dxInteropDevice != IntPtr.Zero) + { + NVDXInterop.DxcloseDevice(_dxInteropDevice); + _dxInteropDevice = IntPtr.Zero; + } + + _lastGLContext = IntPtr.Zero; + } + } +} diff --git a/src/BizHawk.Bizware.Graphics/D3D11/D3D11Pipeline.cs b/src/BizHawk.Bizware.Graphics/D3D11/D3D11Pipeline.cs new file mode 100644 index 00000000000..b41766a4b86 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/D3D11/D3D11Pipeline.cs @@ -0,0 +1,420 @@ +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Runtime.InteropServices; + +using BizHawk.Common; +using BizHawk.Common.CollectionExtensions; +using BizHawk.Common.StringExtensions; + +using Vortice.D3DCompiler; +using Vortice.Direct3D; +using Vortice.Direct3D11; +using Vortice.Direct3D11.Shader; +using Vortice.DXGI; + +namespace BizHawk.Bizware.Graphics +{ + internal class D3D11Pipeline : IPipeline + { + private readonly D3D11Resources _resources; + private ID3D11Device Device => _resources.Device; + private ID3D11DeviceContext Context => _resources.Context; + private ID3D11SamplerState PointSamplerState => _resources.PointSamplerState; + private ID3D11SamplerState LinearSamplerState => _resources.LinearSamplerState; + + private readonly ReadOnlyMemory _vsBytecode, _psBytecode; + private readonly InputElementDescription[] _inputElements; + + public ID3D11InputLayout VertexInputLayout; + public readonly int VertexStride; + + public ID3D11Buffer VertexBuffer; + public int VertexBufferCount; + + public ID3D11Buffer IndexBuffer; + public int IndexBufferCount; + + private readonly record struct D3D11Uniform(IntPtr VariablePointer, int VariableSize, D3D11PendingBuffer PB); + + private readonly Dictionary _vsUniforms = new(); + private readonly Dictionary _psUniforms = new(); + + private readonly Dictionary _vsSamplers = new(); + private readonly Dictionary _psSamplers = new(); + + public class D3D11PendingBuffer + { + public IntPtr VSPendingBuffer, PSPendingBuffer; + public int VSBufferSize, PSBufferSize; + public bool VSBufferDirty, PSBufferDirty; + } + + public readonly D3D11PendingBuffer[] PendingBuffers = new D3D11PendingBuffer[ID3D11DeviceContext.CommonShaderConstantBufferSlotCount]; + public readonly ID3D11Buffer[] VSConstantBuffers = new ID3D11Buffer[ID3D11DeviceContext.CommonShaderConstantBufferSlotCount]; + public readonly ID3D11Buffer[] PSConstantBuffers = new ID3D11Buffer[ID3D11DeviceContext.CommonShaderConstantBufferSlotCount]; + + public ID3D11VertexShader VS; + public ID3D11PixelShader PS; + + private static ReadOnlyMemory CompileShader(PipelineCompileArgs.ShaderCompileArgs compileArgs, string profile, FeatureLevel featureLevel) + { + profile += featureLevel switch + { + FeatureLevel.Level_9_1 or FeatureLevel.Level_9_2 => "_4_0_level_9_1", + FeatureLevel.Level_9_3 => "_4_0_level_9_3", + _ => "_4_0", + }; + + // note: we use D3D9-like shaders for legacy reasons, so we need the backwards compat flag + // TODO: remove D3D9 syntax from shaders + return Compiler.Compile( + shaderSource: compileArgs.Source, + entryPoint: compileArgs.Entry, + sourceName: null!, // this is safe to be null + profile: profile, + shaderFlags: ShaderFlags.OptimizationLevel3 | ShaderFlags.EnableBackwardsCompatibility); + } + + public D3D11Pipeline(D3D11Resources resources, PipelineCompileArgs compileArgs) + { + _resources = resources; + + try + { + _vsBytecode = CompileShader(compileArgs.VertexShaderArgs, "vs", _resources.DeviceFeatureLevel); + _psBytecode = CompileShader(compileArgs.FragmentShaderArgs, "ps", _resources.DeviceFeatureLevel); + + _inputElements = new InputElementDescription[compileArgs.VertexLayout.Count]; + for (var i = 0; i < compileArgs.VertexLayout.Count; i++) + { + var item = compileArgs.VertexLayout[i]; + + var semanticName = item.Usage switch + { + AttribUsage.Position => "POSITION", + AttribUsage.Color0 => "COLOR", + AttribUsage.Texcoord0 or AttribUsage.Texcoord1 => "TEXCOORD", + _ => throw new InvalidOperationException() + }; + + var format = item.Components switch + { + 1 => Format.R32_Float, + 2 => Format.R32G32_Float, + 3 => Format.R32G32B32_Float, + 4 => item.Integer ? Format.B8G8R8A8_UNorm : Format.R32G32B32A32_Float, + _ => throw new InvalidOperationException() + }; + + _inputElements[i] = new(semanticName, item.Usage == AttribUsage.Texcoord1 ? 1 : 0, format, item.Offset, 0); + } + + VertexStride = compileArgs.VertexLayoutStride; + + using var vsRefl = Compiler.Reflect(_vsBytecode.Span); + using var psRefl = Compiler.Reflect(_psBytecode.Span); + foreach (var refl in new[] { vsRefl, psRefl }) + { + var isVs = refl == vsRefl; + var reflCbs = refl.ConstantBuffers; + var todo = new Queue<(string, int, string, int, ID3D11ShaderReflectionType)>(); + for (var i = 0; i < reflCbs.Length; i++) + { + var cbDesc = reflCbs[i].Description; + var bd = new BufferDescription((cbDesc.Size + 15) & ~15, BindFlags.ConstantBuffer, ResourceUsage.Dynamic, CpuAccessFlags.Write); + PendingBuffers[i] ??= new(); + if (isVs) + { + VSConstantBuffers[i] = Device.CreateBuffer(bd); + PendingBuffers[i].VSPendingBuffer = Marshal.AllocCoTaskMem(cbDesc.Size); + PendingBuffers[i].VSBufferSize = cbDesc.Size; + } + else + { + PSConstantBuffers[i] = Device.CreateBuffer(bd); + PendingBuffers[i].PSPendingBuffer = Marshal.AllocCoTaskMem(cbDesc.Size); + PendingBuffers[i].PSBufferSize = cbDesc.Size; + } + + var prefix = cbDesc.Name.RemovePrefix('$'); + prefix = prefix is "Params" or "Globals" ? "" : $"{prefix}."; + foreach (var reflVari in reflCbs[i].Variables) + { + var reflVariDesc = reflVari.Description; + todo.Enqueue((prefix, i, reflVariDesc.Name, reflVariDesc.StartOffset, reflVari.VariableType)); + } + } + + while (todo.Count != 0) + { + var (prefix, pbIndex, reflVariName, reflVariOffset, reflVariType) = todo.Dequeue(); + var reflVariTypeDesc = reflVariType.Description; + if (reflVariTypeDesc.MemberCount > 0) + { + prefix = $"{prefix}{reflVariName}."; + for (var i = 0; i < reflVariTypeDesc.MemberCount; i++) + { + var memberName = reflVariType.GetMemberTypeName(i); + var memberType = reflVariType.GetMemberTypeByIndex(i); + var memberOffset = memberType.Description.Offset; + todo.Enqueue((prefix, pbIndex, memberName, reflVariOffset + memberOffset, memberType)); + } + + continue; + } + + if (reflVariTypeDesc.Type is not (ShaderVariableType.Bool or ShaderVariableType.Float)) + { + // unsupported type + continue; + } + + reflVariName = $"{prefix}{reflVariName}"; + var reflVariSize = 4 * reflVariTypeDesc.ColumnCount * reflVariTypeDesc.RowCount; + if (isVs) + { + var reflVariPtr = PendingBuffers[pbIndex].VSPendingBuffer + reflVariOffset; + _vsUniforms.Add(reflVariName, new(reflVariPtr, reflVariSize, PendingBuffers[pbIndex])); + } + else + { + var reflVariPtr = PendingBuffers[pbIndex].PSPendingBuffer + reflVariOffset; + _psUniforms.Add(reflVariName, new(reflVariPtr, reflVariSize, PendingBuffers[pbIndex])); + } + } + + foreach (var resource in refl.BoundResources) + { + if (resource.Type == ShaderInputType.Sampler) + { + var samplerName = resource.Name.RemovePrefix('$'); + var samplerIndex = resource.BindPoint; + if (isVs) + { + _vsSamplers.Add(samplerName, samplerIndex); + } + else + { + _psSamplers.Add(samplerName, samplerIndex); + } + } + } + } + + CreatePipeline(); + _resources.Pipelines.Add(this); + } + catch + { + DestroyPipeline(); + throw; + } + } + + public void Dispose() + { + DestroyPipeline(); + DestroyPendingBuffers(); + _resources.Pipelines.Remove(this); + } + + public void CreatePipeline() + { + VertexInputLayout = Device.CreateInputLayout(_inputElements, _vsBytecode.Span); + + for (var i = 0; i < ID3D11DeviceContext.CommonShaderConstantBufferSlotCount; i++) + { + var pb = PendingBuffers[i]; + if (pb == null) + { + break; + } + + if (pb.VSBufferSize > 0) + { + var bd = new BufferDescription(pb.VSBufferSize, BindFlags.ConstantBuffer, ResourceUsage.Dynamic, CpuAccessFlags.Write); + VSConstantBuffers[i] = Device.CreateBuffer(bd); + pb.VSBufferDirty = true; + } + + if (pb.PSBufferSize > 0) + { + var bd = new BufferDescription(pb.PSBufferSize, BindFlags.ConstantBuffer, ResourceUsage.Dynamic, CpuAccessFlags.Write); + PSConstantBuffers[i] = Device.CreateBuffer(bd); + pb.PSBufferDirty = true; + } + } + + VS = Device.CreateVertexShader(_vsBytecode.Span); + PS = Device.CreatePixelShader(_psBytecode.Span); + } + + public void DestroyPipeline() + { + VertexInputLayout?.Dispose(); + VertexInputLayout = null; + VertexBuffer?.Dispose(); + VertexBuffer = null; + VertexBufferCount = 0; + IndexBuffer?.Dispose(); + IndexBuffer = null; + IndexBufferCount = 0; + + for (var i = 0; i < ID3D11DeviceContext.CommonShaderConstantBufferSlotCount; i++) + { + VSConstantBuffers[i]?.Dispose(); + VSConstantBuffers[i] = null; + PSConstantBuffers[i]?.Dispose(); + PSConstantBuffers[i] = null; + } + + VS?.Dispose(); + VS = null; + PS?.Dispose(); + PS = null; + } + + public void DestroyPendingBuffers() + { + for (var i = 0; i < ID3D11DeviceContext.CommonShaderConstantBufferSlotCount; i++) + { + if (PendingBuffers[i] == null) + { + break; + } + + Marshal.FreeCoTaskMem(PendingBuffers[i].VSPendingBuffer); + Marshal.FreeCoTaskMem(PendingBuffers[i].PSPendingBuffer); + PendingBuffers[i] = null; + } + } + + public void SetVertexData(IntPtr data, int count) + { + if (VertexBufferCount < count) + { + VertexBuffer?.Dispose(); + var bd = new BufferDescription( count * VertexStride, BindFlags.VertexBuffer, ResourceUsage.Dynamic, CpuAccessFlags.Write); + VertexBuffer = Device.CreateBuffer(in bd, data); + VertexBufferCount = count; + Context.IASetVertexBuffer(0, VertexBuffer, VertexStride); + } + else + { + var mappedVb = Context.Map(VertexBuffer, MapMode.WriteDiscard); + try + { + Util.UnsafeSpanFromPointer(ptr: data, length: count * VertexStride) + .CopyTo(Util.UnsafeSpanFromPointer(ptr: mappedVb.DataPointer, length: VertexBufferCount * VertexStride)); + } + finally + { + Context.Unmap(VertexBuffer); + } + } + } + + public void SetIndexData(IntPtr data, int count) + { + if (IndexBufferCount < count) + { + IndexBuffer?.Dispose(); + var bd = new BufferDescription(count * 2, BindFlags.IndexBuffer, ResourceUsage.Dynamic, CpuAccessFlags.Write); + IndexBuffer = Device.CreateBuffer(in bd, data); + IndexBufferCount = count; + Context.IASetIndexBuffer(IndexBuffer, Format.R16_UInt, 0); + } + else + { + var mappedIb = Context.Map(IndexBuffer, MapMode.WriteDiscard); + try + { + Util.UnsafeSpanFromPointer(ptr: data, length: count * 2) + .CopyTo(Util.UnsafeSpanFromPointer(ptr: mappedIb.DataPointer, length: IndexBufferCount * 2)); + } + finally + { + Context.Unmap(IndexBuffer); + } + } + } + + public bool HasUniformSampler(string name) + { + return _vsSamplers.ContainsKey(name) + || _psSamplers.ContainsKey(name); + } + + public string GetUniformSamplerName(int index) + { + var sampler = _psSamplers.AsEnumerable().FirstOrNull(s => s.Value == index) + ?? _vsSamplers.AsEnumerable().FirstOrNull(s => s.Value == index); + + return sampler?.Key; + } + + public void SetUniformSampler(string name, ITexture2D tex) + { + if (tex == null) + { + return; + } + + var d3d11Tex = (D3D11Texture2D)tex; + var sampler = d3d11Tex.LinearFiltering ? LinearSamplerState : PointSamplerState; + + if (_vsSamplers.TryGetValue(name, out var vsSamplerIndex)) + { + Context.VSSetSampler(vsSamplerIndex, sampler); + Context.VSSetShaderResource(vsSamplerIndex, d3d11Tex.SRV); + } + + if (_psSamplers.TryGetValue(name, out var psSamplerIndex)) + { + Context.PSSetSampler(psSamplerIndex, sampler); + Context.PSSetShaderResource(psSamplerIndex, d3d11Tex.SRV); + } + } + + private unsafe void SetUniform(string name, void* valPtr, int valSize) + { + if (_vsUniforms.TryGetValue(name, out var vsUniform)) + { + Buffer.MemoryCopy(valPtr, (void*)vsUniform.VariablePointer, vsUniform.VariableSize, valSize); + vsUniform.PB.VSBufferDirty = true; + } + + if (_psUniforms.TryGetValue(name, out var psUniform)) + { + Buffer.MemoryCopy(valPtr, (void*)psUniform.VariablePointer, psUniform.VariableSize, valSize); + psUniform.PB.PSBufferDirty = true; + } + } + + public void SetUniformMatrix(string name, Matrix4x4 mat, bool transpose) + => SetUniformMatrix(name, ref mat, transpose); + + public unsafe void SetUniformMatrix(string name, ref Matrix4x4 mat, bool transpose) + { + var m = transpose ? Matrix4x4.Transpose(mat) : mat; + SetUniform(name, &m, sizeof(Matrix4x4)); + } + + public unsafe void SetUniform(string name, Vector4 value) + => SetUniform(name, &value, sizeof(Vector4)); + + public unsafe void SetUniform(string name, Vector2 value) + => SetUniform(name, &value, sizeof(Vector2)); + + public unsafe void SetUniform(string name, float value) + => SetUniform(name, &value, sizeof(float)); + + public unsafe void SetUniform(string name, bool value) + { + // note: HLSL bool is 4 bytes large + var b = value ? 1 : 0; + SetUniform(name, &b, sizeof(int)); + } + } +} diff --git a/src/BizHawk.Bizware.Graphics/D3D11/D3D11RenderTarget.cs b/src/BizHawk.Bizware.Graphics/D3D11/D3D11RenderTarget.cs new file mode 100644 index 00000000000..fef57551811 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/D3D11/D3D11RenderTarget.cs @@ -0,0 +1,38 @@ +using Vortice.Direct3D11; +using Vortice.DXGI; + +namespace BizHawk.Bizware.Graphics +{ + internal sealed class D3D11RenderTarget : D3D11Texture2D, IRenderTarget + { + public ID3D11RenderTargetView RTV; + + public D3D11RenderTarget(D3D11Resources resources, int width, int height) + : base(resources, BindFlags.ShaderResource | BindFlags.RenderTarget, ResourceUsage.Default, CpuAccessFlags.None, width, height) + { + } + + public override void CreateTexture() + { + base.CreateTexture(); + var rtvd = new RenderTargetViewDescription(RenderTargetViewDimension.Texture2D, Format.B8G8R8A8_UNorm); + RTV = Device.CreateRenderTargetView(Texture, rtvd); + } + + public override void DestroyTexture() + { + RTV?.Dispose(); + RTV = null; + base.DestroyTexture(); + } + + public void Bind() + { + Context.OMSetRenderTargets(RTV); + _resources.CurRenderTarget = this; + } + + public override string ToString() + => $"D3D11 RenderTarget: {Width}x{Height}"; + } +} diff --git a/src/BizHawk.Bizware.Graphics/D3D11/D3D11Resources.cs b/src/BizHawk.Bizware.Graphics/D3D11/D3D11Resources.cs new file mode 100644 index 00000000000..416b2309a08 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/D3D11/D3D11Resources.cs @@ -0,0 +1,187 @@ +using System.Collections.Generic; + +using Vortice.Direct3D; +using Vortice.Direct3D11; +using Vortice.DXGI; + +namespace BizHawk.Bizware.Graphics +{ + /// + /// Encapsules all D3D11 resources + /// This is mainly needed as we need to be able to recreate these resources + /// Due to possibly getting a device reset/lost (e.g. from hibernation) + /// + internal sealed class D3D11Resources : IDisposable + { + public ID3D11Device Device; + public ID3D11DeviceContext Context; + public IDXGIFactory1 Factory1; + public IDXGIFactory2 Factory2; + public ID3D11BlendState BlendNormalState; + public ID3D11BlendState BlendAlphaState; + public ID3D11BlendState BlendDisableState; + public ID3D11SamplerState PointSamplerState; + public ID3D11SamplerState LinearSamplerState; + public ID3D11RasterizerState RasterizerState; + + public FeatureLevel DeviceFeatureLevel; + public int MaxTextureDimension; + public bool PresentAllowTearing; + + public D3D11RenderTarget CurRenderTarget; + public D3D11Pipeline CurPipeline; + + public readonly HashSet Textures = [ ]; + public readonly HashSet Pipelines = [ ]; + + public void CreateResources() + { + try + { +#if false + // use this to debug D3D11 calls + // note the debug layer requires extra steps to use: https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-devices-layers#debug-layer + // also debug output will only be present with a "native debugger" attached (pure managed debugger can't see this output) + var creationFlags = DeviceCreationFlags.Singlethreaded | DeviceCreationFlags.BgraSupport | DeviceCreationFlags.Debug; +#else + // IGL is not thread safe, so let's not bother making this implementation thread safe + var creationFlags = DeviceCreationFlags.Singlethreaded | DeviceCreationFlags.BgraSupport; +#endif + + // GL interop doesn't support the single threaded flag + if (D3D11GLInterop.IsAvailable) + { + creationFlags &= ~DeviceCreationFlags.Singlethreaded; + } + + D3D11.D3D11CreateDevice( + adapter: null, + DriverType.Hardware, + creationFlags, + null!, // this is safe to be null + out Device, + out Context).CheckError(); + + using var dxgiDevice = Device.QueryInterface(); + dxgiDevice.MaximumFrameLatency = 1; + + using var adapter = dxgiDevice.GetAdapter(); + Factory1 = adapter.GetParent(); + // we want IDXGIFactory2 for CreateSwapChainForHwnd + // however, it's not guaranteed to be available (only available in Win8+ or Win7 with the Platform Update) + Factory2 = Factory1.QueryInterfaceOrNull(); + + using var factory5 = Factory1.QueryInterfaceOrNull(); + PresentAllowTearing = factory5?.PresentAllowTearing ?? false; + + var bd = default(BlendDescription); + bd.AlphaToCoverageEnable = false; + bd.IndependentBlendEnable = false; + bd.RenderTarget[0].BlendEnable = true; + bd.RenderTarget[0].SourceBlend = Blend.SourceAlpha; + bd.RenderTarget[0].DestinationBlend = Blend.InverseSourceAlpha; + bd.RenderTarget[0].BlendOperation = BlendOperation.Add; + bd.RenderTarget[0].SourceBlendAlpha = Blend.One; + bd.RenderTarget[0].DestinationBlendAlpha = Blend.InverseSourceAlpha; + bd.RenderTarget[0].BlendOperationAlpha = BlendOperation.Add; + bd.RenderTarget[0].RenderTargetWriteMask = ColorWriteEnable.All; + BlendNormalState = Device.CreateBlendState(bd); + + bd.RenderTarget[0].SourceBlend = Blend.One; + bd.RenderTarget[0].DestinationBlend = Blend.Zero; + BlendAlphaState = Device.CreateBlendState(bd); + + bd.RenderTarget[0].BlendEnable = false; + BlendDisableState = Device.CreateBlendState(bd); + + PointSamplerState = Device.CreateSamplerState(SamplerDescription.PointClamp); + LinearSamplerState = Device.CreateSamplerState(SamplerDescription.LinearClamp); + + DeviceFeatureLevel = Device.FeatureLevel; + + MaxTextureDimension = DeviceFeatureLevel switch + { + FeatureLevel.Level_9_1 or FeatureLevel.Level_9_2 => 2048, + FeatureLevel.Level_9_3 => 4096, + FeatureLevel.Level_10_0 or FeatureLevel.Level_10_1 => 8192, + _ => ID3D11Resource.MaximumTexture2DSize, + }; + + var rd = new RasterizerDescription + { + CullMode = CullMode.None, + FillMode = FillMode.Solid, + ScissorEnable = true, + DepthClipEnable = DeviceFeatureLevel is FeatureLevel.Level_9_1 or FeatureLevel.Level_9_2 or FeatureLevel.Level_9_3, + }; + + RasterizerState = Device.CreateRasterizerState(rd); + + foreach (var tex2d in Textures) + { + tex2d.CreateTexture(); + } + } + catch + { + Dispose(); + throw; + } + } + + public void DestroyResources() + { + foreach (var tex2d in Textures) + { + tex2d.DestroyTexture(); + } + + foreach (var pipeline in Pipelines) + { + pipeline.DestroyPipeline(); + } + + CurRenderTarget = null; + CurPipeline = null; + + LinearSamplerState?.Dispose(); + LinearSamplerState = null; + PointSamplerState?.Dispose(); + PointSamplerState = null; + + RasterizerState?.Dispose(); + RasterizerState = null; + + BlendNormalState?.Dispose(); + BlendNormalState = null; + BlendAlphaState?.Dispose(); + BlendAlphaState = null; + BlendDisableState?.Dispose(); + BlendDisableState = null; + + Context?.Dispose(); + Context = null; + Device?.Dispose(); + Device = null; + + Factory2?.Dispose(); + Factory2 = null; + + Factory1?.Dispose(); + Factory1 = null; + } + + public void Dispose() + { + DestroyResources(); + Textures.Clear(); + + foreach (var pipeline in Pipelines) + { + pipeline.DestroyPendingBuffers(); + } + + Pipelines.Clear(); + } + } +} diff --git a/src/BizHawk.Bizware.Graphics/D3D11/D3D11SwapChain.cs b/src/BizHawk.Bizware.Graphics/D3D11/D3D11SwapChain.cs new file mode 100644 index 00000000000..52754936c3a --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/D3D11/D3D11SwapChain.cs @@ -0,0 +1,134 @@ +using Vortice.Direct3D11; +using Vortice.DXGI; + +using DXGIResultCode = Vortice.DXGI.ResultCode; + +namespace BizHawk.Bizware.Graphics +{ + public sealed class D3D11SwapChain : IDisposable + { + public readonly struct ControlParameters + { + public readonly IntPtr Handle; + public readonly int Width; + public readonly int Height; + public readonly bool Vsync; + public readonly bool AllowsTearing; + + public ControlParameters(IntPtr handle, int width, int height, bool vsync, bool allowsTearing) + { + Handle = handle; + Width = Math.Max(width, 1); + Height = Math.Max(height, 1); + Vsync = vsync; + AllowsTearing = allowsTearing; + } + } + + internal class SwapChainResources : IDisposable + { + public ID3D11Device Device; + public ID3D11DeviceContext Context; + public ID3D11DeviceContext1 Context1; + public ID3D11Texture2D BackBufferTexture; + public ID3D11RenderTargetView RTV; + public IDXGISwapChain SwapChain; + public bool HasFlipModel; + public bool AllowsTearing; + + public void Dispose() + { + // Device/Context not owned by this class + Device = null; + Context = null; + Context1?.Dispose(); + Context1 = null; + RTV?.Dispose(); + RTV = null; + BackBufferTexture?.Dispose(); + BackBufferTexture = null; + SwapChain?.Dispose(); + SwapChain = null; + } + } + + private static readonly SharpGen.Runtime.Result D3DDDIERR_DEVICEREMOVED = new(2289436784UL); + + private readonly SwapChainResources _resources; + private readonly Action _resetDeviceCallback; + + private ID3D11Device Device => _resources.Device; + private ID3D11DeviceContext Context => _resources.Context; + private ID3D11DeviceContext1 Context1 => _resources.Context1; + private ID3D11Texture2D BackBufferTexture => _resources.BackBufferTexture; + private ID3D11RenderTargetView RTV => _resources.RTV; + private IDXGISwapChain SwapChain => _resources.SwapChain; + private bool HasFlipModel => _resources.HasFlipModel; + private bool AllowsTearing => _resources.AllowsTearing; + + internal D3D11SwapChain(SwapChainResources resources, Action resetDeviceCallback) + { + _resources = resources; + _resetDeviceCallback = resetDeviceCallback; + } + + public void Dispose() + => _resources.Dispose(); + + public void PresentBuffer(ControlParameters cp) + { + Context.OMSetRenderTargets(RTV); + + PresentFlags presentFlags; + if (cp.Vsync || !HasFlipModel) + { + presentFlags = PresentFlags.None; + } + else + { + presentFlags = cp.AllowsTearing && AllowsTearing ? PresentFlags.AllowTearing : PresentFlags.DoNotWait; + } + + var result = SwapChain.Present(cp.Vsync ? 1 : 0, presentFlags); + if (result == DXGIResultCode.DeviceReset + || result == DXGIResultCode.DeviceRemoved + || result == D3DDDIERR_DEVICEREMOVED) + { + _resetDeviceCallback(cp); + } + + // optimization hint to the GPU (note: not always available, needs Win8+ or Win7 with the Platform Update) + Context1?.DiscardView(RTV); + } + + public void Refresh(ControlParameters cp) + { + // must be released in order to resize these buffers + RTV.Dispose(); + _resources.RTV = null; + BackBufferTexture.Dispose(); + _resources.BackBufferTexture = null; + + var result = SwapChain.ResizeBuffers( + bufferCount: 2, + cp.Width, + cp.Height, + Format.B8G8R8A8_UNorm, + AllowsTearing ? SwapChainFlags.AllowTearing : SwapChainFlags.None); + + if (result == DXGIResultCode.DeviceReset + || result == DXGIResultCode.DeviceRemoved + || result == D3DDDIERR_DEVICEREMOVED) + { + _resetDeviceCallback(cp); + } + else + { + result.CheckError(); + _resources.BackBufferTexture = SwapChain.GetBuffer(0); + var rtvd = new RenderTargetViewDescription(RenderTargetViewDimension.Texture2D, Format.B8G8R8A8_UNorm); + _resources.RTV = Device.CreateRenderTargetView(BackBufferTexture, rtvd); + } + } + } +} diff --git a/src/BizHawk.Bizware.Graphics/D3D11/D3D11Texture2D.cs b/src/BizHawk.Bizware.Graphics/D3D11/D3D11Texture2D.cs new file mode 100644 index 00000000000..80c3b3ad446 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/D3D11/D3D11Texture2D.cs @@ -0,0 +1,175 @@ +using System.Collections.Generic; +using System.Runtime.InteropServices; + +using Vortice.Direct3D; +using Vortice.Direct3D11; +using Vortice.DXGI; + +namespace BizHawk.Bizware.Graphics +{ + internal class D3D11Texture2D : ITexture2D + { + protected readonly D3D11Resources _resources; + private readonly BindFlags _bindFlags; + private readonly ResourceUsage _usage; + private readonly CpuAccessFlags _cpuAccessFlags; + + protected ID3D11Device Device => _resources.Device; + protected ID3D11DeviceContext Context => _resources.Context; + private HashSet Textures => _resources.Textures; + + private ID3D11Texture2D StagingTexture; + + public ID3D11Texture2D Texture; + public ID3D11ShaderResourceView SRV; + public bool LinearFiltering; + + public int Width { get; } + public int Height { get; } + public bool IsUpsideDown { get; } + + public D3D11Texture2D(D3D11Resources resources, BindFlags bindFlags, ResourceUsage usage, CpuAccessFlags cpuAccessFlags, int width, int height, bool wrapped = false) + { + _resources = resources; + _bindFlags = bindFlags; + _usage = usage; + _cpuAccessFlags = cpuAccessFlags; + Width = width; + Height = height; + IsUpsideDown = wrapped; + // ReSharper disable once VirtualMemberCallInConstructor + CreateTexture(); + Textures.Add(this); + } + + public void Dispose() + { + DestroyTexture(); + Textures.Remove(this); + } + + public virtual void CreateTexture() + { + // wrapped textures are R8G8B8A8 rather than B8G8R8A8... + var format = IsUpsideDown ? Format.R8G8B8A8_UNorm : Format.B8G8R8A8_UNorm; + Texture = Device.CreateTexture2D( + format, + Width, + Height, + mipLevels: 1, + bindFlags: _bindFlags, + usage: _usage, + cpuAccessFlags: _cpuAccessFlags); + + var srvd = new ShaderResourceViewDescription(ShaderResourceViewDimension.Texture2D, format, mostDetailedMip: 0, mipLevels: 1); + SRV = Device.CreateShaderResourceView(Texture, srvd); + } + + public virtual void DestroyTexture() + { + SRV?.Dispose(); + SRV = null; + Texture?.Dispose(); + Texture = null; + StagingTexture?.Dispose(); + StagingTexture = null; + } + + public BitmapBuffer Resolve() + { + StagingTexture ??= Device.CreateTexture2D( + Format.B8G8R8A8_UNorm, + Width, + Height, + mipLevels: 1, + bindFlags: BindFlags.None, + usage: ResourceUsage.Staging, + cpuAccessFlags: CpuAccessFlags.Read); + + Context.CopyResource(StagingTexture, Texture); + + try + { + var srcSpan = Context.MapReadOnly(StagingTexture); + var pixels = new int[Width * Height]; + var dstSpan = MemoryMarshal.AsBytes(pixels.AsSpan()); + + if (srcSpan.Length == dstSpan.Length) + { + srcSpan.CopyTo(dstSpan); + } + else + { + int srcStart = 0, dstStart = 0; + int srcStride = srcSpan.Length / Height, dstStride = Width * sizeof(int); + for (var i = 0; i < Height; i++) + { + srcSpan.Slice(srcStart, dstStride) + .CopyTo(dstSpan.Slice(dstStart, dstStride)); + srcStart += srcStride; + dstStart += dstStride; + } + } + + return new(Width, Height, pixels); + } + finally + { + Context.Unmap(StagingTexture, 0); + } + } + + public unsafe void LoadFrom(BitmapBuffer buffer) + { + if (buffer.Width != Width || buffer.Height != Height) + { + throw new InvalidOperationException("BitmapBuffer dimensions do not match texture dimensions"); + } + + if ((_cpuAccessFlags & CpuAccessFlags.Write) == 0) + { + throw new InvalidOperationException("This texture cannot be written by the CPU"); + } + + var bmpData = buffer.LockBits(); + try + { + var srcSpan = new ReadOnlySpan(bmpData.Scan0.ToPointer(), bmpData.Stride * buffer.Height); + var mappedTex = Context.Map(Texture, 0, 0, MapMode.WriteDiscard); + + if (srcSpan.Length == mappedTex.Length) + { + srcSpan.CopyTo(mappedTex); + } + else + { + // D3D11 sometimes has weird pitches (seen with 3DS) + int srcStart = 0, dstStart = 0; + int srcStride = bmpData.Stride, dstStride = mappedTex.Length / buffer.Height; + var height = buffer.Height; + for (var i = 0; i < height; i++) + { + srcSpan.Slice(srcStart, srcStride) + .CopyTo(mappedTex.Slice(dstStart, dstStride)); + srcStart += srcStride; + dstStart += dstStride; + } + } + } + finally + { + Context.Unmap(Texture, 0); + buffer.UnlockBits(bmpData); + } + } + + public void SetFilterLinear() + => LinearFiltering = true; + + public void SetFilterNearest() + => LinearFiltering = false; + + public override string ToString() + => $"D3D11 Texture2D: {Width}x{Height}"; + } +} diff --git a/src/BizHawk.Bizware.Graphics/D3D11/IGL_D3D11.cs b/src/BizHawk.Bizware.Graphics/D3D11/IGL_D3D11.cs new file mode 100644 index 00000000000..bcc76f8d8f3 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/D3D11/IGL_D3D11.cs @@ -0,0 +1,316 @@ +using System.Drawing; +using System.Numerics; + +using Vortice.Direct3D; +using Vortice.Direct3D11; +using Vortice.DXGI; + +using BizHawk.Common; + +namespace BizHawk.Bizware.Graphics +{ + /// + /// Direct3D11 implementation of the BizwareGL.IGL interface + /// + public sealed class IGL_D3D11 : IGL + { + public EDispMethod DispMethodEnum => EDispMethod.D3D11; + + // D3D11 resources + // these might need to be thrown out and recreated if the device is lost + private readonly D3D11Resources _resources; + + private ID3D11Device Device => _resources.Device; + private ID3D11DeviceContext Context => _resources.Context; + private IDXGIFactory1 Factory1 => _resources.Factory1; + private IDXGIFactory2 Factory2 => _resources.Factory2; + private ID3D11BlendState BlendNormalState => _resources.BlendNormalState; + private ID3D11BlendState BlendAlphaState => _resources.BlendAlphaState; + private ID3D11BlendState BlendDisableState => _resources.BlendDisableState; + private ID3D11RasterizerState RasterizerState => _resources.RasterizerState; + + private bool PresentAllowTearing => _resources.PresentAllowTearing; + + private D3D11RenderTarget CurRenderTarget => _resources.CurRenderTarget; + private D3D11Pipeline CurPipeline => _resources.CurPipeline; + + private D3D11SwapChain.SwapChainResources _controlSwapChain; + private readonly D3D11GLInterop _glInterop; + + public IGL_D3D11() + { + if (OSTailoredCode.IsUnixHost) + { + throw new NotSupportedException("D3D11 is Windows only"); + } + + _resources = new(); + _resources.CreateResources(); + + if (D3D11GLInterop.IsAvailable) + { + _glInterop = new(_resources); + } + } + + private IDXGISwapChain CreateDXGISwapChain(D3D11SwapChain.ControlParameters cp) + { + IDXGISwapChain ret; + + if (Factory2 is null) + { + // no Factory2, probably on Windows 7 without the Platform Update + // we can assume a simple legacy format is needed here + var sd = default(SwapChainDescription); + sd.BufferDescription = new( + width: cp.Width, + height: cp.Height, + refreshRate: new(0, 0), + format: Format.B8G8R8A8_UNorm); + sd.SampleDescription = SampleDescription.Default; + sd.BufferUsage = Usage.RenderTargetOutput; + sd.BufferCount = 2; + sd.OutputWindow = cp.Handle; + sd.Windowed = true; + sd.SwapEffect = SwapEffect.Discard; + sd.Flags = SwapChainFlags.None; + + ret = Factory1.CreateSwapChain(Device, sd); + } + else + { + // this is the optimal swapchain model + // note however it requires windows 10+ + // a less optimal model will end up being used in case this fails + var sd = new SwapChainDescription1( + width: cp.Width, + height: cp.Height, + format: Format.B8G8R8A8_UNorm, + stereo: false, + swapEffect: SwapEffect.FlipDiscard, + bufferUsage: Usage.RenderTargetOutput, + bufferCount: 2, + scaling: Scaling.Stretch, + alphaMode: AlphaMode.Ignore, + flags: PresentAllowTearing ? SwapChainFlags.AllowTearing : SwapChainFlags.None); + + try + { + ret = Factory2.CreateSwapChainForHwnd(Device, cp.Handle, sd); + } + catch + { + try + { + // FlipSequential is supported on Win8+ + sd.SwapEffect = SwapEffect.FlipSequential; + ret = Factory2.CreateSwapChainForHwnd(Device, cp.Handle, sd); + } + catch + { + sd.SwapEffect = SwapEffect.Discard; + sd.Flags = SwapChainFlags.None; + ret = Factory2.CreateSwapChainForHwnd(Device, cp.Handle, sd); + } + } + } + + // don't allow DXGI to snoop alt+enter and such + using var parentFactory = ret.GetParent(); + parentFactory.MakeWindowAssociation(cp.Handle, WindowAssociationFlags.IgnoreAll); + return ret; + } + + private void ResetDevice(D3D11SwapChain.ControlParameters cp) + { + _controlSwapChain.Dispose(); + Context.Flush(); // important to immediately dispose of the swapchain (if it's still around, we can't recreate it) + + _glInterop?.Dispose(); + _resources.DestroyResources(); + _resources.CreateResources(); + _glInterop?.OpenInteropDevice(); + + var swapChain = CreateDXGISwapChain(cp); + var bbTex = swapChain.GetBuffer(0); + var bbRtvd = new RenderTargetViewDescription(RenderTargetViewDimension.Texture2D, Format.B8G8R8A8_UNorm); + var rtv = Device.CreateRenderTargetView(bbTex, bbRtvd); + var swapChainDesc = swapChain.Description; + + _controlSwapChain.Device = Device; + _controlSwapChain.Context = Context; + _controlSwapChain.Context1 = Context.QueryInterfaceOrNull(); + _controlSwapChain.BackBufferTexture = bbTex; + _controlSwapChain.RTV = rtv; + _controlSwapChain.SwapChain = swapChain; + _controlSwapChain.HasFlipModel = swapChainDesc.SwapEffect is SwapEffect.FlipSequential or SwapEffect.FlipDiscard; + _controlSwapChain.AllowsTearing = (swapChainDesc.Flags & SwapChainFlags.AllowTearing) != 0; + } + + public D3D11SwapChain CreateSwapChain(D3D11SwapChain.ControlParameters cp) + { + if (_controlSwapChain != null) + { + throw new InvalidOperationException($"{nameof(IGL_D3D11)} can only have 1 control swap chain"); + } + + var swapChain = CreateDXGISwapChain(cp); + var bbTex = swapChain.GetBuffer(0); + var rtvd = new RenderTargetViewDescription(RenderTargetViewDimension.Texture2D, Format.B8G8R8A8_UNorm); + var rtv = Device.CreateRenderTargetView(bbTex, rtvd); + var swapChainDesc = swapChain.Description; + + _controlSwapChain = new() + { + Device = Device, + Context = Context, + Context1 = Context.QueryInterfaceOrNull(), + BackBufferTexture = bbTex, + RTV = rtv, + SwapChain = swapChain, + HasFlipModel = swapChainDesc.SwapEffect is SwapEffect.FlipSequential or SwapEffect.FlipDiscard, + AllowsTearing = (swapChainDesc.Flags & SwapChainFlags.AllowTearing) != 0, + }; + + return new(_controlSwapChain, ResetDevice); + } + + public void Dispose() + { + _controlSwapChain.Dispose(); + _resources.Dispose(); + } + + public int MaxTextureDimension => _resources.MaxTextureDimension; + + public void ClearColor(Color color) + => Context.ClearRenderTargetView(CurRenderTarget?.RTV ?? _controlSwapChain.RTV, new(color.R, color.B, color.G, color.A)); + + public void EnableBlendNormal() + => Context.OMSetBlendState(BlendNormalState); + + public void EnableBlendAlpha() + => Context.OMSetBlendState(BlendAlphaState); + + public void DisableBlending() + => Context.OMSetBlendState(BlendDisableState); + + public IPipeline CreatePipeline(PipelineCompileArgs compileArgs) + => new D3D11Pipeline(_resources, compileArgs); + + public void BindPipeline(IPipeline pipeline) + { + var d3d11Pipeline = (D3D11Pipeline)pipeline; + _resources.CurPipeline = d3d11Pipeline; + + if (d3d11Pipeline == null) + { + // unbind? i don't know + return; + } + + Context.VSSetShader(d3d11Pipeline.VS); + Context.PSSetShader(d3d11Pipeline.PS); + + Context.VSSetConstantBuffers(0, d3d11Pipeline.VSConstantBuffers); + Context.PSSetConstantBuffers(0, d3d11Pipeline.PSConstantBuffers); + + Context.VSUnsetSamplers(0, ID3D11DeviceContext.CommonShaderSamplerSlotCount); + Context.VSUnsetShaderResources(0, ID3D11DeviceContext.CommonShaderSamplerSlotCount); + Context.PSUnsetSamplers(0, ID3D11DeviceContext.CommonShaderSamplerSlotCount); + Context.PSUnsetShaderResources(0, ID3D11DeviceContext.CommonShaderSamplerSlotCount); + + Context.IASetInputLayout(d3d11Pipeline.VertexInputLayout); + Context.IASetVertexBuffer(0, d3d11Pipeline.VertexBuffer, d3d11Pipeline.VertexStride); + Context.IASetIndexBuffer(d3d11Pipeline.IndexBuffer, Format.R16_UInt, 0); + + // not sure if this applies to the current pipeline or all pipelines + // just set it every time to be safe + Context.RSSetState(RasterizerState); + } + + public ITexture2D CreateTexture(int width, int height) + => new D3D11Texture2D(_resources, BindFlags.ShaderResource, ResourceUsage.Dynamic, CpuAccessFlags.Write, width, height); + + public ITexture2D WrapGLTexture2D(int glTexId, int width, int height) + => _glInterop?.WrapGLTexture(glTexId, width, height); + + public Matrix4x4 CreateGuiProjectionMatrix(int width, int height) + { + var ret = Matrix4x4.Identity; + ret.M11 = 2.0f / width; + ret.M22 = 2.0f / height; + return ret; + } + + public Matrix4x4 CreateGuiViewMatrix(int width, int height, bool autoFlip) + { + var ret = Matrix4x4.Identity; + ret.M22 = -1.0f; + ret.M41 = width * -0.5f; + ret.M42 = height * 0.5f; + + // auto-flipping isn't needed on D3D + return ret; + } + + public void SetViewport(int x, int y, int width, int height) + { + Context.RSSetViewport(x, y, width, height); + Context.RSSetScissorRect(x, y, width, height); + } + + public IRenderTarget CreateRenderTarget(int width, int height) + => new D3D11RenderTarget(_resources, width, height); + + public void BindDefaultRenderTarget() + { + _resources.CurRenderTarget = null; + Context.OMSetRenderTargets(_controlSwapChain.RTV); + } + + private void UpdateConstantBuffers() + { + for (var i = 0; i < ID3D11DeviceContext.CommonShaderConstantBufferSlotCount; i++) + { + var pb = CurPipeline.PendingBuffers[i]; + if (pb == null) + { + break; + } + + if (pb.VSBufferDirty) + { + var vsCb = Context.Map(CurPipeline.VSConstantBuffers[i], MapMode.WriteDiscard); + Util.UnsafeSpanFromPointer(ptr: pb.VSPendingBuffer, length: pb.VSBufferSize) + .CopyTo(Util.UnsafeSpanFromPointer(ptr: vsCb.DataPointer, length: pb.VSBufferSize)); + Context.Unmap(CurPipeline.VSConstantBuffers[i]); + pb.VSBufferDirty = false; + } + + if (pb.PSBufferDirty) + { + var psCb = Context.Map(CurPipeline.PSConstantBuffers[i], MapMode.WriteDiscard); + Util.UnsafeSpanFromPointer(ptr: pb.PSPendingBuffer, length: pb.PSBufferSize) + .CopyTo(Util.UnsafeSpanFromPointer(ptr: psCb.DataPointer, length: pb.PSBufferSize)); + Context.Unmap(CurPipeline.PSConstantBuffers[i]); + pb.PSBufferDirty = false; + } + } + } + + public void Draw(int vertexCount) + { + UpdateConstantBuffers(); + Context.IASetPrimitiveTopology(PrimitiveTopology.TriangleStrip); + Context.Draw(vertexCount, 0); + } + + public void DrawIndexed(int indexCount, int indexStart, int vertexStart) + { + UpdateConstantBuffers(); + Context.IASetPrimitiveTopology(PrimitiveTopology.TriangleList); + Context.DrawIndexed(indexCount, indexStart, vertexStart); + } + } +} diff --git a/src/BizHawk.Bizware.Graphics/D3D9/D3D9SwapChain.cs b/src/BizHawk.Bizware.Graphics/D3D9/D3D9SwapChain.cs deleted file mode 100644 index 77e494317f1..00000000000 --- a/src/BizHawk.Bizware.Graphics/D3D9/D3D9SwapChain.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; - -using SharpDX; -using SharpDX.Direct3D9; - -namespace BizHawk.Bizware.Graphics -{ - public sealed class D3D9SwapChain : IDisposable - { - public readonly struct ControlParameters - { - public readonly IntPtr Handle; - public readonly int Width; - public readonly int Height; - public readonly bool Vsync; - - public ControlParameters(IntPtr handle, int width, int height, bool vsync) - { - Handle = handle; - Width = Math.Max(width, 1); - Height = Math.Max(height, 1); - Vsync = vsync; - } - } - - private const int D3DERR_DEVICELOST = unchecked((int)0x88760868); - - private readonly Device _device; - private readonly Func _resetDeviceCallback; - private readonly Func _resetSwapChainCallback; - - private SwapChain _swapChain; - - internal D3D9SwapChain(Device device, SwapChain swapChain, - Func resetDeviceCallback, Func resetSwapChainCallback) - { - _device = device; - _swapChain = swapChain; - _resetDeviceCallback = resetDeviceCallback; - _resetSwapChainCallback = resetSwapChainCallback; - } - - public void Dispose() - { - _swapChain?.Dispose(); - _swapChain = null; - } - - public void SetBackBuffer() - { - using var surface = _swapChain.GetBackBuffer(0); - _device.SetRenderTarget(0, surface); - _device.DepthStencilSurface = null; - } - - public void PresentBuffer(ControlParameters cp) - { - SetBackBuffer(); - - try - { - _swapChain.Present(Present.None); - } - catch (SharpDXException ex) - { - if (ex.ResultCode.Code == D3DERR_DEVICELOST) - { - _swapChain = _resetDeviceCallback(cp); - } - } - } - - public void Refresh(ControlParameters cp) - => _swapChain = _resetSwapChainCallback(cp); - } -} diff --git a/src/BizHawk.Bizware.Graphics/D3D9/IGL_D3D9.cs b/src/BizHawk.Bizware.Graphics/D3D9/IGL_D3D9.cs deleted file mode 100644 index c4c239fa284..00000000000 --- a/src/BizHawk.Bizware.Graphics/D3D9/IGL_D3D9.cs +++ /dev/null @@ -1,839 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.IO; -using System.Linq; -using System.Numerics; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Threading; - -using BizHawk.Bizware.BizwareGL; -using BizHawk.Common; -using BizHawk.Common.StringExtensions; - -using SharpDX.Direct3D9; - -using static SDL2.SDL; - -// todo - do a better job selecting shader model? base on caps somehow? try several and catch compilation exceptions (yuck, exceptions) -namespace BizHawk.Bizware.Graphics -{ - /// - /// Direct3D9 implementation of the BizwareGL.IGL interface - /// - public sealed class IGL_D3D9 : IGL - { - public EDispMethod DispMethodEnum => EDispMethod.D3D9; - - private const int D3DERR_DEVICENOTRESET = unchecked((int)0x88760869); - - private Device _device; - private SwapChain _controlSwapchain; - - private IntPtr _offscreenSdl2Window; - private IntPtr OffscreenNativeWindow; - - // rendering state - private Pipeline _currPipeline; - - // misc state - private readonly HashSet _renderTargets = new(); - - public string API => "D3D9"; - - static IGL_D3D9() - { - if (SDL_Init(SDL_INIT_VIDEO) != 0) - { - throw new($"Failed to init SDL video, SDL error: {SDL_GetError()}"); - } - } - - public IGL_D3D9() - { - if (OSTailoredCode.IsUnixHost) - { - throw new NotSupportedException("D3D9 is Windows only"); - } - - // make an 'offscreen context' so we can at least do things without having to create a window - _offscreenSdl2Window = SDL_CreateWindow(null, 0, 0, 1, 1, SDL_WindowFlags.SDL_WINDOW_HIDDEN); - if (_offscreenSdl2Window == IntPtr.Zero) - { - throw new($"Failed to create offscreen SDL window, SDL error: {SDL_GetError()}"); - } - - // get the native window handle - var wminfo = default(SDL_SysWMinfo); - SDL_GetVersion(out wminfo.version); - SDL_GetWindowWMInfo(_offscreenSdl2Window, ref wminfo); - if (wminfo.subsystem != SDL_SYSWM_TYPE.SDL_SYSWM_WINDOWS) - { - throw new($"SDL_SysWMinfo did not report SDL_SYSWM_WINDOWS? Something went wrong... SDL error: {SDL_GetError()}"); - } - - OffscreenNativeWindow = wminfo.info.win.window; - - CreateDevice(); - } - - public void AlternateVsyncPass(int pass) - { - while (true) - { - var status = _device.GetRasterStatus(0); - if (status.InVBlank && pass == 0) return; // wait for vblank to begin - if (!status.InVBlank && pass == 1) return; // wait for vblank to end - // STOP! think you can use System.Threading.SpinWait? No, it's way too slow. - // (on my system, the vblank is something like 24 of 1074 scanlines @ 60hz ~= 0.35ms which is an awfully small window to nail) - } - } - - private void CreateDevice() - { - // this object is only used for creating a device, it's not needed afterwards - using var d3d9 = new Direct3D(); - - var pp = MakePresentParameters(); - - var flags = (d3d9.GetDeviceCaps(0, DeviceType.Hardware).DeviceCaps & DeviceCaps.HWTransformAndLight) != 0 - ? CreateFlags.HardwareVertexProcessing - : CreateFlags.SoftwareVertexProcessing; - - flags |= CreateFlags.FpuPreserve; - _device = new(d3d9, 0, DeviceType.Hardware, pp.DeviceWindowHandle, flags, pp); - } - - private PresentParameters MakePresentParameters() - { - return new() - { - BackBufferCount = 1, - SwapEffect = SwapEffect.Discard, - DeviceWindowHandle = OffscreenNativeWindow, - Windowed = true, - PresentationInterval = PresentInterval.Immediate, - }; - } - - private static PresentParameters MakePresentParameters(D3D9SwapChain.ControlParameters cp) - { - return new() - { - BackBufferWidth = cp.Width, - BackBufferHeight = cp.Height, - BackBufferFormat = Format.X8R8G8B8, - BackBufferCount = 2, - SwapEffect = SwapEffect.Discard, - DeviceWindowHandle = cp.Handle, - Windowed = true, - PresentationInterval = cp.Vsync ? PresentInterval.One : PresentInterval.Immediate - }; - } - - private SwapChain ResetDevice(D3D9SwapChain.ControlParameters cp) - { - SuspendRenderTargets(); - _controlSwapchain.Dispose(); - - var pp = MakePresentParameters(); - - while (true) - { - var result = _device.TestCooperativeLevel(); - if (result.Success) - { - break; - } - - if (result.Code == D3DERR_DEVICENOTRESET) - { - try - { - _device.Reset(pp); - break; - } - catch - { - // ignored - } - } - - Thread.Sleep(100); - } - - ResumeRenderTargets(); - - pp = MakePresentParameters(cp); - _controlSwapchain = new(_device, pp); - return _controlSwapchain; - } - - private SwapChain ResetSwapChain(D3D9SwapChain.ControlParameters cp) - { - _controlSwapchain.Dispose(); - - var pp = MakePresentParameters(cp); - _controlSwapchain = new(_device, pp); - return _controlSwapchain; - } - - public D3D9SwapChain CreateSwapChain(D3D9SwapChain.ControlParameters cp) - { - if (_controlSwapchain != null) - { - throw new InvalidOperationException($"{nameof(IGL_D3D9)} can only have 1 control swap chain"); - } - - var pp = MakePresentParameters(cp); - _controlSwapchain = new(_device, pp); - return new(_device, _controlSwapchain, ResetDevice, ResetSwapChain); - } - - public void Dispose() - { - if (_device != null) - { - _device.Dispose(); - _device = null; - } - - if (_offscreenSdl2Window != IntPtr.Zero) - { - SDL_DestroyWindow(_offscreenSdl2Window); - _offscreenSdl2Window = OffscreenNativeWindow = IntPtr.Zero; - } - - _controlSwapchain = null; - } - - public void ClearColor(Color color) - => _device.Clear(ClearFlags.Target, color.ToSharpDXColor(), 0.0f, 0); - - public void FreeTexture(Texture2d tex) - { - var tw = (TextureWrapper)tex.Opaque; - tw.Texture.Dispose(); - } - - private class ShaderWrapper // Disposable fields cleaned up by Internal_FreeShader - { - public ShaderBytecode Bytecode; - public VertexShader VS; - public PixelShader PS; - public Shader IGLShader; - } - - /// is and compilation error occurred - public Shader CreateFragmentShader(string source, string entry, bool required) - { - try - { - var sw = new ShaderWrapper(); - - // ShaderFlags.EnableBackwardsCompatibility - used this once upon a time (please leave a note about why) - var result = ShaderBytecode.Compile( - shaderSource: source, - entryPoint: entry, - profile: "ps_3_0", - shaderFlags: ShaderFlags.UseLegacyD3DX9_31Dll); - - sw.PS = new(_device, result); - sw.Bytecode = result; - - var s = new Shader(this, sw, true); - sw.IGLShader = s; - - return s; - } - catch (Exception ex) - { - if (required) - { - throw; - } - - return new(this, null, false) { Errors = ex.ToString() }; - } - } - - /// is and compilation error occurred - public Shader CreateVertexShader(string source, string entry, bool required) - { - try - { - var sw = new ShaderWrapper(); - - var result = ShaderBytecode.Compile( - shaderSource: source, - entryPoint: entry, - profile: "vs_3_0", - shaderFlags: ShaderFlags.UseLegacyD3DX9_31Dll); - - sw.VS = new(_device, result); - sw.Bytecode = result; - - var s = new Shader(this, sw, true); - sw.IGLShader = s; - - return s; - } - catch (Exception ex) - { - if (required) - { - throw; - } - - return new(this, null, false) { Errors = ex.ToString() }; - } - } - - public void EnableBlending() - { - _device.SetRenderState(RenderState.AlphaBlendEnable, true); - _device.SetRenderState(RenderState.SeparateAlphaBlendEnable, true); - - _device.SetRenderState(RenderState.BlendOperation, BlendOperation.Add); - _device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha); - _device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha); - - _device.SetRenderState(RenderState.BlendOperationAlpha, BlendOperation.Add); - _device.SetRenderState(RenderState.SourceBlendAlpha, Blend.One); - _device.SetRenderState(RenderState.DestinationBlendAlpha, Blend.Zero); - } - - public void DisableBlending() - => _device.SetRenderState(RenderState.AlphaBlendEnable, false); - - /// - /// is and either or is unavailable (their property is ), or - /// one of 's items has an unsupported value in , , or - /// - public Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, Shader fragmentShader, bool required, string memo) - { - if (!vertexShader.Available || !fragmentShader.Available) - { - var errors = $"Vertex Shader:\r\n {vertexShader.Errors} \r\n-------\r\nFragment Shader:\r\n{fragmentShader.Errors}"; - if (required) - { - throw new InvalidOperationException($"Couldn't build required GL pipeline:\r\n{errors}"); - } - - return new(this, null, false, null, null, null) { Errors = errors }; - } - - var ves = new VertexElement[vertexLayout.Items.Count + 1]; - var stride = 0; - foreach (var (i, item) in vertexLayout.Items) - { - DeclarationType declType; - // ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault - switch (item.AttribType) - { - case VertexAttribPointerType.Float: - declType = item.Components switch - { - 1 => DeclarationType.Float1, - 2 => DeclarationType.Float2, - 3 => DeclarationType.Float3, - 4 => DeclarationType.Float4, - _ => throw new InvalidOperationException() - }; - stride += 4 * item.Components; - break; - default: - throw new NotSupportedException(); - } - - DeclarationUsage usage; - byte usageIndex = 0; - // ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault - switch (item.Usage) - { - case AttribUsage.Position: - usage = DeclarationUsage.Position; - break; - case AttribUsage.Texcoord0: - usage = DeclarationUsage.TextureCoordinate; - break; - case AttribUsage.Texcoord1: - usage = DeclarationUsage.TextureCoordinate; - usageIndex = 1; - break; - case AttribUsage.Color0: - usage = DeclarationUsage.Color; - break; - default: - throw new NotSupportedException(); - } - - ves[i] = new(0, (short)item.Offset, declType, DeclarationMethod.Default, usage, usageIndex); - } - - // must be placed at the end - ves[vertexLayout.Items.Count] = VertexElement.VertexDeclarationEnd; - - var pw = new PipelineWrapper - { - VertexDeclaration = new(_device, ves), - VertexShader = (ShaderWrapper)vertexShader.Opaque, - FragmentShader = (ShaderWrapper)fragmentShader.Opaque, - VertexStride = stride - }; - - // scan uniforms from reflection - var uniforms = new List(); - var vsct = pw.VertexShader.Bytecode.ConstantTable; - var psct = pw.FragmentShader.Bytecode.ConstantTable; - foreach (var ct in new[] { vsct, psct }) - { - var todo = new Queue<(string, EffectHandle)>(); - var n = ct.Description.Constants; - for (var i = 0; i < n; i++) - { - var handle = ct.GetConstant(null, i); - todo.Enqueue((string.Empty, handle)); - } - - while (todo.Count != 0) - { - var (prefix, handle) = todo.Dequeue(); - var descr = ct.GetConstantDescription(handle); - - // Console.WriteLine($"D3D UNIFORM: {descr.Name}"); - - if (descr.StructMembers != 0) - { - var newPrefix = $"{prefix}{descr.Name}."; - for (var j = 0; j < descr.StructMembers; j++) - { - var subHandle = ct.GetConstant(handle, j); - todo.Enqueue((newPrefix, subHandle)); - } - - continue; - } - - var ui = new UniformInfo(); - var uw = new UniformWrapper(); - - ui.Opaque = uw; - var name = prefix + descr.Name; - - // uniforms done through the entry point signature have $ in their names which isn't helpful, so get rid of that - name = name.RemovePrefix('$'); - - ui.Name = name; - uw.EffectHandle = handle; - uw.CT = ct; - - if (descr.Type == ParameterType.Sampler2D) - { - ui.IsSampler = true; - ui.SamplerIndex = descr.RegisterIndex; - } - - uniforms.Add(ui); - } - } - - return new(this, pw, true, vertexLayout, uniforms, memo); - } - - public void FreePipeline(Pipeline pipeline) - { - // unavailable pipelines will have no opaque - if (pipeline.Opaque is not PipelineWrapper pw) - { - return; - } - - pw.VertexDeclaration.Dispose(); - pw.FragmentShader.IGLShader.Release(); - pw.VertexShader.IGLShader.Release(); - } - - public void Internal_FreeShader(Shader shader) - { - var sw = (ShaderWrapper)shader.Opaque; - sw.Bytecode.Dispose(); - sw.PS?.Dispose(); - sw.VS?.Dispose(); - } - - private class UniformWrapper - { - public EffectHandle EffectHandle; - public ConstantTable CT; - } - - private class PipelineWrapper // Disposable fields cleaned up by FreePipeline - { - public VertexDeclaration VertexDeclaration; - public ShaderWrapper VertexShader, FragmentShader; - public int VertexStride; - } - - private class TextureWrapper - { - public Texture Texture; - public TextureAddress WrapClamp = TextureAddress.Clamp; - public TextureFilter MinFilter = TextureFilter.Point, MagFilter = TextureFilter.Point; - } - - public VertexLayout CreateVertexLayout() - => new(this, null); - - public void Internal_FreeVertexLayout(VertexLayout layout) - { - } - - public void BindPipeline(Pipeline pipeline) - { - _currPipeline = pipeline; - - if (pipeline == null) - { - // unbind? i don't know - return; - } - - var pw = (PipelineWrapper)pipeline.Opaque; - _device.PixelShader = pw.FragmentShader.PS; - _device.VertexShader = pw.VertexShader.VS; - _device.VertexDeclaration = pw.VertexDeclaration; - } - - public void SetPipelineUniform(PipelineUniform uniform, bool value) - { - foreach (var ui in uniform.UniformInfos) - { - var uw = (UniformWrapper)ui.Opaque; - uw.CT.SetValue(_device, uw.EffectHandle, value); - } - } - - public void SetPipelineUniformMatrix(PipelineUniform uniform, Matrix4x4 mat, bool transpose) - => SetPipelineUniformMatrix(uniform, ref mat, transpose); - - public void SetPipelineUniformMatrix(PipelineUniform uniform, ref Matrix4x4 mat, bool transpose) - { - foreach (var ui in uniform.UniformInfos) - { - var uw = (UniformWrapper)ui.Opaque; - uw.CT.SetValue(_device, uw.EffectHandle, mat.ToSharpDXMatrix(!transpose)); - } - } - - public void SetPipelineUniform(PipelineUniform uniform, Vector4 value) - { - foreach (var ui in uniform.UniformInfos) - { - var uw = (UniformWrapper)ui.Opaque; - uw.CT.SetValue(_device, uw.EffectHandle, value.ToSharpDXVector4()); - } - } - - public void SetPipelineUniform(PipelineUniform uniform, Vector2 value) - { - foreach (var ui in uniform.UniformInfos) - { - var uw = (UniformWrapper)ui.Opaque; - uw.CT.SetValue(_device, uw.EffectHandle, value.ToSharpDXVector2()); - } - } - - public void SetPipelineUniform(PipelineUniform uniform, float value) - { - foreach (var ui in uniform.UniformInfos) - { - var uw = (UniformWrapper)ui.Opaque; - uw.CT.SetValue(_device, uw.EffectHandle, value); - } - } - - public void SetPipelineUniform(PipelineUniform uniform, Vector4[] values) - { - var v = Array.ConvertAll(values, v => v.ToSharpDXVector4()); - foreach (var ui in uniform.UniformInfos) - { - var uw = (UniformWrapper)ui.Opaque; - uw.CT.SetValue(_device, uw.EffectHandle, v); - } - } - - public void SetPipelineUniformSampler(PipelineUniform uniform, Texture2d tex) - { - if (uniform.Owner == null) - { - return; // uniform was optimized out - } - - var tw = (TextureWrapper)tex.Opaque; - foreach (var ui in uniform.UniformInfos) - { - if (!ui.IsSampler) - { - throw new InvalidOperationException("Uniform was not a texture/sampler"); - } - - _device.SetTexture(ui.SamplerIndex, tw.Texture); - - _device.SetSamplerState(ui.SamplerIndex, SamplerState.AddressU, (int)tw.WrapClamp); - _device.SetSamplerState(ui.SamplerIndex, SamplerState.AddressV, (int)tw.WrapClamp); - _device.SetSamplerState(ui.SamplerIndex, SamplerState.MinFilter, (int)tw.MinFilter); - _device.SetSamplerState(ui.SamplerIndex, SamplerState.MagFilter, (int)tw.MagFilter); - } - } - - public void SetTextureWrapMode(Texture2d tex, bool clamp) - { - var tw = (TextureWrapper)tex.Opaque; - tw.WrapClamp = clamp ? TextureAddress.Clamp : TextureAddress.Wrap; - } - - public void SetMinFilter(Texture2d texture, TextureMinFilter minFilter) - => ((TextureWrapper)texture.Opaque).MinFilter = minFilter == TextureMinFilter.Linear - ? TextureFilter.Linear - : TextureFilter.Point; - - public void SetMagFilter(Texture2d texture, TextureMagFilter magFilter) - => ((TextureWrapper)texture.Opaque).MagFilter = magFilter == TextureMagFilter.Linear - ? TextureFilter.Linear - : TextureFilter.Point; - - public Texture2d LoadTexture(Bitmap bitmap) - { - using var bmp = new BitmapBuffer(bitmap, new()); - return LoadTexture(bmp); - } - - public Texture2d LoadTexture(Stream stream) - { - using var bmp = new BitmapBuffer(stream, new()); - return LoadTexture(bmp); - } - - public Texture2d CreateTexture(int width, int height) - { - var tex = new Texture(_device, width, height, 1, Usage.None, Format.A8R8G8B8, Pool.Managed); - var tw = new TextureWrapper { Texture = tex }; - var ret = new Texture2d(this, tw, width, height); - return ret; - } - - public Texture2d WrapGLTexture2d(IntPtr glTexId, int width, int height) - { - // only used for OpenGL - return null; - } - - /// GDI+ call returned unexpected data - public unsafe void LoadTextureData(Texture2d tex, BitmapBuffer bmp) - { - var tw = (TextureWrapper)tex.Opaque; - var bmpData = bmp.LockBits(); - - try - { - var dr = tw.Texture.LockRectangle(0, LockFlags.None); - - // TODO - do we need to handle odd sizes, weird pitches here? - if (bmp.Width * 4 != bmpData.Stride || bmpData.Stride != dr.Pitch) - { - throw new InvalidOperationException(); - } - - var srcSpan = new ReadOnlySpan(bmpData.Scan0.ToPointer(), bmpData.Stride * bmp.Height); - var dstSpan = new Span(dr.DataPointer.ToPointer(), dr.Pitch * bmp.Height); - srcSpan.CopyTo(dstSpan); - } - finally - { - tw.Texture.UnlockRectangle(0); - bmp.UnlockBits(bmpData); - } - } - - public Texture2d LoadTexture(BitmapBuffer bmp) - { - var ret = CreateTexture(bmp.Width, bmp.Height); - LoadTextureData(ret, bmp); - return ret; - } - - /// Vortice call returned unexpected data - public BitmapBuffer ResolveTexture2d(Texture2d tex) - { - // TODO - lazy create and cache resolving target in RT - using var target = new Texture(_device, tex.IntWidth, tex.IntHeight, 1, Usage.None, Format.A8R8G8B8, Pool.SystemMemory); - var tw = (TextureWrapper)tex.Opaque; - - using var rtSurf = tw.Texture.GetSurfaceLevel(0); - using var dstSurf = target.GetSurfaceLevel(0); - _device.GetRenderTargetData(rtSurf, dstSurf); - - try - { - var dr = target.LockRectangle(0, LockFlags.ReadOnly); - - if (dr.Pitch != tex.IntWidth * 4) - { - throw new InvalidOperationException(); - } - - var pixels = new int[tex.IntWidth * tex.IntHeight]; - Marshal.Copy(dr.DataPointer, pixels, 0, tex.IntWidth * tex.IntHeight); - return new(tex.IntWidth, tex.IntHeight, pixels); - } - finally - { - target.UnlockRectangle(0); - } - } - - public Texture2d LoadTexture(string path) - { - using var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); - return LoadTexture(fs); - } - - public Matrix4x4 CreateGuiProjectionMatrix(int w, int h) - { - return CreateGuiProjectionMatrix(new(w, h)); - } - - public Matrix4x4 CreateGuiViewMatrix(int w, int h, bool autoFlip) - { - return CreateGuiViewMatrix(new(w, h), autoFlip); - } - - public Matrix4x4 CreateGuiProjectionMatrix(Size dims) - { - var ret = Matrix4x4.Identity; - ret.M11 = 2.0f / dims.Width; - ret.M22 = 2.0f / dims.Height; - return ret; - } - - public Matrix4x4 CreateGuiViewMatrix(Size dims, bool autoFlip) - { - var ret = Matrix4x4.Identity; - ret.M22 = -1.0f; - ret.M41 = -dims.Width * 0.5f - 0.5f; - ret.M42 = dims.Height * 0.5f + 0.5f; - - // auto-flipping isn't needed on D3D - return ret; - } - - public void SetViewport(int x, int y, int width, int height) - { - _device.Viewport = new() { X = x, Y = y, Width = width, Height = height, MinDepth = 0, MaxDepth = 1 }; - _device.ScissorRect = new(x, y, x + width, y + height); - } - - public void SetViewport(int width, int height) - { - SetViewport(0, 0, width, height); - } - - public void SetViewport(Size size) - { - SetViewport(size.Width, size.Height); - } - - public void FreeRenderTarget(RenderTarget rt) - { - var tw = (TextureWrapper)rt.Texture2d.Opaque; - tw.Texture.Dispose(); - tw.Texture = null; - _renderTargets.Remove(rt); - } - - public RenderTarget CreateRenderTarget(int w, int h) - { - var tw = new TextureWrapper { Texture = CreateRenderTargetTexture(w, h) }; - var tex = new Texture2d(this, tw, w, h); - var rt = new RenderTarget(this, tw, tex); - _renderTargets.Add(rt); - return rt; - } - - private Texture CreateRenderTargetTexture(int w, int h) - => new(_device, w, h, 1, Usage.RenderTarget, Format.A8R8G8B8, Pool.Default); - - private void SuspendRenderTargets() - { - foreach (var tw in _renderTargets.Select(tex => (TextureWrapper)tex.Opaque)) - { - tw.Texture.Dispose(); - tw.Texture = null; - } - } - - private void ResumeRenderTargets() - { - foreach (var rt in _renderTargets) - { - var tw = (TextureWrapper)rt.Opaque; - tw.Texture = CreateRenderTargetTexture(rt.Texture2d.IntWidth, rt.Texture2d.IntHeight); - } - } - - public void BindRenderTarget(RenderTarget rt) - { - if (rt == null) - { - using var bb = _controlSwapchain.GetBackBuffer(0); - _device.SetRenderTarget(0, bb); - _device.DepthStencilSurface = null; - return; - } - - // dispose doesn't seem necessary for reset here... - var tw = (TextureWrapper)rt.Opaque; - using var texSurface = tw.Texture.GetSurfaceLevel(0); - _device.SetRenderTarget(0, texSurface); - _device.DepthStencilSurface = null; - } - - private delegate void DrawPrimitiveUPDelegate(Device device, PrimitiveType primitiveType, int primitiveCount, IntPtr vertexStreamZeroDataRef, int vertexStreamZeroStride); - - private static readonly Lazy _drawPrimitiveUP = new(() => - { - var mi = typeof(Device).GetMethod("DrawPrimitiveUP", BindingFlags.Instance | BindingFlags.NonPublic); - return (DrawPrimitiveUPDelegate)Delegate.CreateDelegate(typeof(DrawPrimitiveUPDelegate), mi!); - }); - - private void DrawPrimitiveUP(PrimitiveType primitiveType, int primitiveCount, IntPtr vertexStreamZeroDataRef, int vertexStreamZeroStride) - => _drawPrimitiveUP.Value(_device, primitiveType, primitiveCount, vertexStreamZeroDataRef, vertexStreamZeroStride); - - public void Draw(IntPtr data, int count) - { - var pw = (PipelineWrapper)_currPipeline.Opaque; - - // this is stupid, sharpdx only public exposes DrawUserPrimatives - // why is this bad? it takes in an array of T - // and uses the size of T to determine stride - // since stride for us is just completely variable, this is no good - // DrawPrimitiveUP is internal so we have to use this hack to use it directly - - DrawPrimitiveUP(PrimitiveType.TriangleStrip, count - 2, data, pw.VertexStride); - } - - public void BeginScene() - { - _device.BeginScene(); - _device.SetRenderState(RenderState.CullMode, Cull.None); - _device.SetRenderState(RenderState.ZEnable, false); - _device.SetRenderState(RenderState.ZWriteEnable, false); - _device.SetRenderState(RenderState.Lighting, false); - } - - public void EndScene() - => _device.EndScene(); - } -} diff --git a/src/BizHawk.Bizware.Graphics/D3D9/SharpDXExtensions.cs b/src/BizHawk.Bizware.Graphics/D3D9/SharpDXExtensions.cs deleted file mode 100644 index ee650588a62..00000000000 --- a/src/BizHawk.Bizware.Graphics/D3D9/SharpDXExtensions.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Drawing; -using System.Numerics; - -using SharpDX.Mathematics.Interop; - -namespace BizHawk.Bizware.Graphics -{ - internal static class SharpDXExtensions - { - // SharpDX RawMatrix and Numerics Matrix4x4 are identical in structure - public static RawMatrix ToSharpDXMatrix(this Matrix4x4 m, bool transpose) - { - // Transpose call could be inlined to reduce 2 sets of copies to 1 - if (transpose) - { - m = Matrix4x4.Transpose(m); - } - - return new() - { - M11 = m.M11, M12 = m.M12, M13 = m.M13, M14 = m.M14, - M21 = m.M21, M22 = m.M22, M23 = m.M23, M24 = m.M24, - M31 = m.M31, M32 = m.M32, M33 = m.M33, M34 = m.M34, - M41 = m.M41, M42 = m.M42, M43 = m.M43, M44 = m.M44 - }; - } - - public static RawVector2 ToSharpDXVector2(this Vector2 v) - => new(v.X, v.Y); - - public static RawVector4 ToSharpDXVector4(this Vector4 v) - => new(v.X, v.Y, v.Z, v.W); - - public static RawColorBGRA ToSharpDXColor(this Color c) - => new(c.B, c.G, c.R, c.A); - } -} diff --git a/src/BizHawk.Bizware.BizwareGL/EDispMethod.cs b/src/BizHawk.Bizware.Graphics/EDispMethod.cs similarity index 57% rename from src/BizHawk.Bizware.BizwareGL/EDispMethod.cs rename to src/BizHawk.Bizware.Graphics/EDispMethod.cs index 81211d49c8b..e9150a049d9 100644 --- a/src/BizHawk.Bizware.BizwareGL/EDispMethod.cs +++ b/src/BizHawk.Bizware.Graphics/EDispMethod.cs @@ -1,9 +1,9 @@ -namespace BizHawk.Bizware.BizwareGL +namespace BizHawk.Bizware.Graphics { public enum EDispMethod { OpenGL = 0, GdiPlus = 1, - D3D9 = 2 + D3D11 = 2, } } diff --git a/src/BizHawk.Bizware.BizwareGL/Extensions/DrawingExtensions.cs b/src/BizHawk.Bizware.Graphics/Extensions/DrawingExtensions.cs similarity index 59% rename from src/BizHawk.Bizware.BizwareGL/Extensions/DrawingExtensions.cs rename to src/BizHawk.Bizware.Graphics/Extensions/DrawingExtensions.cs index c683d0a1875..fca9107a66e 100644 --- a/src/BizHawk.Bizware.BizwareGL/Extensions/DrawingExtensions.cs +++ b/src/BizHawk.Bizware.Graphics/Extensions/DrawingExtensions.cs @@ -1,6 +1,7 @@ using System.Drawing; +using System.Numerics; -namespace BizHawk.Bizware.BizwareGL.DrawingExtensions +namespace BizHawk.Bizware.Graphics { public static class DrawingExtensions { @@ -9,5 +10,8 @@ public static void Deconstruct(this Size size, out int width, out int height) width = size.Width; height = size.Height; } + + public static Vector2 ToVector(this Point point) + => new(point.X, point.Y); } } diff --git a/src/BizHawk.Bizware.Graphics/Extensions/IGLExtensions.cs b/src/BizHawk.Bizware.Graphics/Extensions/IGLExtensions.cs new file mode 100644 index 00000000000..171beb789aa --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/Extensions/IGLExtensions.cs @@ -0,0 +1,81 @@ +using System.IO; +using System.Drawing; +using System.Numerics; + +namespace BizHawk.Bizware.Graphics +{ + public static class IGLExtensions + { + public static IGuiRenderer CreateGuiRenderer(this IGL gl) + => gl is IGL_GDIPlus gdipImpl + ? new GDIPlusGuiRenderer(gdipImpl) + : new GuiRenderer(gl); + + public static I2DRenderer Create2DRenderer(this IGL gl, ImGuiResourceCache resourceCache) + => gl is IGL_GDIPlus gdipImpl + ? new SDLImGui2DRenderer(gdipImpl, resourceCache) + : new ImGui2DRenderer(gl, resourceCache); + + /// + /// Loads a texture from disk + /// + public static ITexture2D LoadTexture(this IGL igl, string path) + { + using var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); + return igl.LoadTexture(fs); + } + + /// + /// Loads a texture from the stream + /// + public static ITexture2D LoadTexture(this IGL igl, Stream stream) + { + using var bmp = new BitmapBuffer(stream, new()); + return igl.LoadTexture(bmp); + } + + /// + /// Loads a texture from the System.Drawing.Bitmap + /// + public static ITexture2D LoadTexture(this IGL igl, Bitmap bitmap) + { + using var bmp = new BitmapBuffer(bitmap, new()); + return igl.LoadTexture(bmp); + } + + /// + /// Loads a texture from the BitmapBuffer + /// + public static ITexture2D LoadTexture(this IGL igl, BitmapBuffer buffer) + { + var ret = igl.CreateTexture(buffer.Width, buffer.Height); + ret.LoadFrom(buffer); + return ret; + } + + /// + /// Sets the viewport (and scissor) according to the provided specifications + /// + public static void SetViewport(this IGL igl, int width, int height) + => igl.SetViewport(0, 0, width, height); + + /// + /// Sets the viewport (and scissor) according to the provided specifications + /// + public static void SetViewport(this IGL igl, Size size) + => igl.SetViewport(0, 0, size.Width, size.Height); + + /// + /// Generates a proper 2d othographic projection for the given destination size, suitable for use in a GUI + /// + public static Matrix4x4 CreateGuiProjectionMatrix(this IGL igl, Size dims) + => igl.CreateGuiProjectionMatrix(dims.Width, dims.Height); + + /// + /// Generates a proper view transform for a standard 2d ortho projection, including half-pixel jitter if necessary and + /// re-establishing of a normal 2d graphics top-left origin. suitable for use in a GUI + /// + public static Matrix4x4 CreateGuiViewMatrix(this IGL igl, Size dims, bool autoflip = true) + => igl.CreateGuiViewMatrix(dims.Width, dims.Height, autoflip); + } +} diff --git a/src/BizHawk.Bizware.Graphics/Extensions/IGuiRendererExtensions.cs b/src/BizHawk.Bizware.Graphics/Extensions/IGuiRendererExtensions.cs new file mode 100644 index 00000000000..56840e32a05 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/Extensions/IGuiRendererExtensions.cs @@ -0,0 +1,47 @@ +using System.Drawing; + +namespace BizHawk.Bizware.Graphics +{ + public static class IGuiRendererExtensions + { + /// + /// Begin rendering, initializing viewport and projections to the given dimensions + /// + public static void Begin(this IGuiRenderer guiRenderer, Size size) + => guiRenderer.Begin(size.Width, size.Height); + + /// + /// Draws the specified texture2d resource. + /// + public static void Draw(this IGuiRenderer guiRenderer, ITexture2D tex) + => guiRenderer.Draw(tex, 0, 0, tex.Width, tex.Height); + + /// + /// Draws the specified texture2d resource with the specified offset. + /// + public static void Draw(this IGuiRenderer guiRenderer, ITexture2D tex, float x, float y) + => guiRenderer.Draw(tex, x, y, tex.Width, tex.Height); + + /// + /// Draws the specified Texture with the specified offset and the specified size. This could be tricky if youve applied other rotate or scale transforms first. + /// + public static void Draw(this IGuiRenderer guiRenderer, ITexture2D tex, float x, float y, float width, float height) + { + const float u0 = 0, u1 = 1; + float v0, v1; + + if (tex.IsUpsideDown) + { + v0 = 1; + v1 = 0; + } + else + { + v0 = 0; + v1 = 1; + } + + guiRenderer.DrawSubrect(tex, x, y, width, height, u0, v0, u1, v1); + } + } +} diff --git a/src/BizHawk.Bizware.Graphics/Extensions/ITexture2DExtensions.cs b/src/BizHawk.Bizware.Graphics/Extensions/ITexture2DExtensions.cs new file mode 100644 index 00000000000..b1c604d0f46 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/Extensions/ITexture2DExtensions.cs @@ -0,0 +1,13 @@ +using System.Drawing; + +namespace BizHawk.Bizware.Graphics +{ + public static class ITexture2DExtensions + { + public static Rectangle GetRectangle(this ITexture2D texture2D) + => new(0, 0, texture2D.Width, texture2D.Height); + + public static Size GetSize(this ITexture2D texture2D) + => new(texture2D.Width, texture2D.Height); + } +} diff --git a/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusControlRenderTarget.cs b/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusControlRenderTarget.cs new file mode 100644 index 00000000000..20b4730c746 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusControlRenderTarget.cs @@ -0,0 +1,36 @@ +using System.Drawing; + +using SDGraphics = System.Drawing.Graphics; + +namespace BizHawk.Bizware.Graphics +{ + public sealed class GDIPlusControlRenderTarget : IDisposable + { + private readonly Func<(SDGraphics, Rectangle)> _getControlRenderContext; + private BufferedGraphicsContext _bufferedGraphicsContext = new(); + + public SDGraphics ControlGraphics; + public BufferedGraphics BufferedGraphics; + + internal GDIPlusControlRenderTarget(Func<(SDGraphics Graphics, Rectangle Rectangle)> getControlRenderContext) + => _getControlRenderContext = getControlRenderContext; + + public void Dispose() + { + ControlGraphics?.Dispose(); + ControlGraphics = null; + BufferedGraphics?.Dispose(); + BufferedGraphics = null; + _bufferedGraphicsContext?.Dispose(); + _bufferedGraphicsContext = null; + } + + public void CreateGraphics() + { + ControlGraphics?.Dispose(); + BufferedGraphics?.Dispose(); + (ControlGraphics, var r) = _getControlRenderContext(); + BufferedGraphics = _bufferedGraphicsContext.Allocate(ControlGraphics, r); + } + } +} diff --git a/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusRenderTarget.cs b/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusRenderTarget.cs index 56aa376e9a6..71476c7371a 100644 --- a/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusRenderTarget.cs +++ b/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusRenderTarget.cs @@ -1,63 +1,30 @@ -using System; -using System.Drawing; - -using BizHawk.Bizware.BizwareGL; - using SDGraphics = System.Drawing.Graphics; namespace BizHawk.Bizware.Graphics { - public class GDIPlusRenderTarget : IDisposable + internal sealed class GDIPlusRenderTarget : GDIPlusTexture2D, IRenderTarget { - internal GDIPlusRenderTarget(Func getBufferedGraphicsContext, - Func<(SDGraphics Graphics, Rectangle Rectangle)> getControlRenderContext = null) + private readonly IGL_GDIPlus _gdiPlus; + public SDGraphics TextureGraphics; + + internal GDIPlusRenderTarget(IGL_GDIPlus gdiPlus, int width, int height) + : base(width, height) { - _getBufferedGraphicsContext = getBufferedGraphicsContext; - _getControlRenderContext = getControlRenderContext; + _gdiPlus = gdiPlus; + TextureGraphics = SDGraphics.FromImage(SDBitmap); } - public void Dispose() + public override void Dispose() { - if (_getControlRenderContext != null) - { - CurGraphics?.Dispose(); - } - - BufferedGraphics?.Dispose(); + TextureGraphics?.Dispose(); + TextureGraphics = null; + base.Dispose(); } - private readonly Func _getBufferedGraphicsContext; - - /// - /// get Graphics and Rectangle from a control, if any - /// - private readonly Func<(SDGraphics, Rectangle)> _getControlRenderContext; + public void Bind() + => _gdiPlus.CurRenderTarget = this; - /// - /// the offscreen render target, if that's what this is representing - /// - public RenderTarget Target; - - public SDGraphics CurGraphics; - public BufferedGraphics BufferedGraphics; - - public void CreateGraphics() - { - Rectangle r; - if (_getControlRenderContext != null) - { - (CurGraphics, r) = _getControlRenderContext(); - } - else - { - var gtex = (GDIPlusTexture)Target.Texture2d.Opaque; - CurGraphics?.Dispose(); - CurGraphics = SDGraphics.FromImage(gtex.SDBitmap); - r = Target.Texture2d.Rectangle; - } - - BufferedGraphics?.Dispose(); - BufferedGraphics = _getBufferedGraphicsContext().Allocate(CurGraphics, r); - } + public override string ToString() + => $"GDI+ RenderTarget: {Width}x{Height}"; } } diff --git a/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusTexture.cs b/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusTexture.cs deleted file mode 100644 index d0726fdb497..00000000000 --- a/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusTexture.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Drawing; - -using BizHawk.Bizware.BizwareGL; - -namespace BizHawk.Bizware.Graphics -{ - public class GDIPlusTexture : IDisposable - { - public Bitmap SDBitmap; - public TextureMinFilter MinFilter = TextureMinFilter.Nearest; - public TextureMagFilter MagFilter = TextureMagFilter.Nearest; - - public void Dispose() - { - SDBitmap?.Dispose(); - SDBitmap = null; - } - } -} diff --git a/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusTexture2D.cs b/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusTexture2D.cs new file mode 100644 index 00000000000..97654fea32e --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusTexture2D.cs @@ -0,0 +1,50 @@ +using System.Drawing; +using System.Drawing.Imaging; + +namespace BizHawk.Bizware.Graphics +{ + internal class GDIPlusTexture2D : ITexture2D + { + public Bitmap SDBitmap; + public bool LinearFiltering; + + public int Width { get; } + public int Height { get; } + public bool IsUpsideDown => false; + + public GDIPlusTexture2D(int width, int height) + { + Width = width; + Height = height; + SDBitmap = new(width, height, PixelFormat.Format32bppArgb); + } + + public virtual void Dispose() + { + SDBitmap?.Dispose(); + SDBitmap = null; + } + + public BitmapBuffer Resolve() + { + var blo = new BitmapLoadOptions + { + AllowWrap = false // must be an independent resource + }; + + return new(SDBitmap, blo); + } + + public void LoadFrom(BitmapBuffer buffer) + => buffer.ToSysdrawingBitmap(SDBitmap); + + public void SetFilterLinear() + => LinearFiltering = true; + + public void SetFilterNearest() + => LinearFiltering = false; + + public override string ToString() + => $"GDI+ Texture2D: {Width}x{Height}"; + } +} diff --git a/src/BizHawk.Bizware.Graphics/GDIPlus/IGL_GDIPlus.cs b/src/BizHawk.Bizware.Graphics/GDIPlus/IGL_GDIPlus.cs index 12672eebc88..1a6dcb9bc40 100644 --- a/src/BizHawk.Bizware.Graphics/GDIPlus/IGL_GDIPlus.cs +++ b/src/BizHawk.Bizware.Graphics/GDIPlus/IGL_GDIPlus.cs @@ -1,44 +1,40 @@ -using System; -using System.IO; using System.Drawing; using System.Drawing.Drawing2D; -using System.Drawing.Imaging; using System.Numerics; -using BizHawk.Bizware.BizwareGL; - using SDGraphics = System.Drawing.Graphics; -//TODO - maybe a layer to cache Graphics parameters (notably, filtering) ? namespace BizHawk.Bizware.Graphics { public class IGL_GDIPlus : IGL { + private GDIPlusControlRenderTarget _controlRenderTarget; + + internal GDIPlusRenderTarget CurRenderTarget; + public EDispMethod DispMethodEnum => EDispMethod.GdiPlus; public void Dispose() { - BufferedGraphicsContext.Dispose(); } + // maximum bitmap size doesn't seem to be well defined... we'll just use D3D11's maximum size + public int MaxTextureDimension => 16384; + + internal SDGraphics GetCurrentGraphics() + => CurRenderTarget?.TextureGraphics ?? _controlRenderTarget.BufferedGraphics.Graphics; + public void ClearColor(Color color) => GetCurrentGraphics().Clear(color); - public string API => "GDIPLUS"; - - public void FreeTexture(Texture2d tex) + public void EnableBlendNormal() { - var gtex = (GDIPlusTexture)tex.Opaque; - gtex.Dispose(); + var g = GetCurrentGraphics(); + g.CompositingMode = CompositingMode.SourceOver; + g.CompositingQuality = CompositingQuality.Default; } - public Shader CreateFragmentShader(string source, string entry, bool required) - => null; - - public Shader CreateVertexShader(string source, string entry, bool required) - => null; - - public void EnableBlending() + public void EnableBlendAlpha() { var g = GetCurrentGraphics(); g.CompositingMode = CompositingMode.SourceOver; @@ -52,242 +48,57 @@ public void DisableBlending() g.CompositingQuality = CompositingQuality.HighSpeed; } - public Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, Shader fragmentShader, bool required, string memo) - { - return null; - } - - public void FreePipeline(Pipeline pipeline) - { - } - - public VertexLayout CreateVertexLayout() - => new(this, null); - - public void Internal_FreeVertexLayout(VertexLayout layout) - { - } - - public void SetTextureWrapMode(Texture2d tex, bool clamp) - { - } - - public void Draw(IntPtr data, int count) - { - } - - public void BindPipeline(Pipeline pipeline) - { - - } - - public void Internal_FreeShader(Shader shader) - { - } - - public void SetPipelineUniform(PipelineUniform uniform, bool value) - { - } - - public void SetPipelineUniformMatrix(PipelineUniform uniform, Matrix4x4 mat, bool transpose) - { - } - - public void SetPipelineUniformMatrix(PipelineUniform uniform, ref Matrix4x4 mat, bool transpose) - { - } - - public void SetPipelineUniform(PipelineUniform uniform, Vector4 value) - { - } - - public void SetPipelineUniform(PipelineUniform uniform, Vector2 value) - { - } + public IPipeline CreatePipeline(PipelineCompileArgs compileArgs) + => throw new NotSupportedException("GDI+ does not support pipelines"); - public void SetPipelineUniform(PipelineUniform uniform, float value) + public void BindPipeline(IPipeline pipeline) { } - public void SetPipelineUniform(PipelineUniform uniform, Vector4[] values) + public void Draw(int vertexCount) { } - public void SetPipelineUniformSampler(PipelineUniform uniform, Texture2d tex) + public void DrawIndexed(int indexCount, int indexStart, int vertexStart) { } - public void SetMinFilter(Texture2d texture, TextureMinFilter minFilter) - => ((GDIPlusTexture) texture.Opaque).MinFilter = minFilter; - - public void SetMagFilter(Texture2d texture, TextureMagFilter magFilter) - => ((GDIPlusTexture) texture.Opaque).MagFilter = magFilter; + public ITexture2D CreateTexture(int width, int height) + => new GDIPlusTexture2D(width, height); - public Texture2d LoadTexture(Bitmap bitmap) - { - var sdBitmap = (Bitmap)bitmap.Clone(); - var gtex = new GDIPlusTexture { SDBitmap = sdBitmap }; - return new(this, gtex, bitmap.Width, bitmap.Height); - } - - public Texture2d LoadTexture(Stream stream) - { - using var bmp = new BitmapBuffer(stream, new()); - return LoadTexture(bmp); - } - - public Texture2d CreateTexture(int width, int height) + // only used for OpenGL + public ITexture2D WrapGLTexture2D(int glTexId, int width, int height) => null; - public Texture2d WrapGLTexture2d(IntPtr glTexId, int width, int height) - { - // only used for OpenGL - return null; - } + // see CreateGuiViewMatrix for more + public Matrix4x4 CreateGuiProjectionMatrix(int width, int height) + => Matrix4x4.Identity; - public void LoadTextureData(Texture2d tex, BitmapBuffer bmp) - { - var gtex = (GDIPlusTexture)tex.Opaque; - bmp.ToSysdrawingBitmap(gtex.SDBitmap); - } - - public Texture2d LoadTexture(BitmapBuffer bmp) - { - // definitely needed (by TextureFrugalizer at least) - var sdBitmap = bmp.ToSysdrawingBitmap(); - var gtex = new GDIPlusTexture { SDBitmap = sdBitmap }; - return new(this, gtex, bmp.Width, bmp.Height); - } - - public BitmapBuffer ResolveTexture2d(Texture2d tex) - { - var gtex = (GDIPlusTexture)tex.Opaque; - var blow = new BitmapLoadOptions - { - AllowWrap = false // must be an independent resource - }; - - var bb = new BitmapBuffer(gtex.SDBitmap, blow); - return bb; - } - - public Texture2d LoadTexture(string path) - { - using var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); - return LoadTexture(fs); - } - - public Matrix4x4 CreateGuiProjectionMatrix(int w, int h) - { - return CreateGuiProjectionMatrix(new(w, h)); - } - - public Matrix4x4 CreateGuiViewMatrix(int w, int h, bool autoFlip) - { - return CreateGuiViewMatrix(new(w, h), autoFlip); - } - - public Matrix4x4 CreateGuiProjectionMatrix(Size dims) - { - // see CreateGuiViewMatrix for more - return Matrix4x4.Identity; - } - - public Matrix4x4 CreateGuiViewMatrix(Size dims, bool autoFlip) - { - // on account of gdi+ working internally with a default view exactly like we want, we don't need to setup a new one here - // furthermore, we _cant_, without inverting the GuiView and GuiProjection before drawing, to completely undo it - // this might be feasible, but its kind of slow and annoying and worse, seemingly numerically unstable - return Matrix4x4.Identity; - } + // on account of gdi+ working internally with a default view exactly like we want, we don't need to setup a new one here + // furthermore, we _cant_, without inverting the GuiView and GuiProjection before drawing, to completely undo it + // this might be feasible, but its kind of slow and annoying and worse, seemingly numerically unstable + public Matrix4x4 CreateGuiViewMatrix(int width, int height, bool autoFlip) + => Matrix4x4.Identity; public void SetViewport(int x, int y, int width, int height) { } - public void SetViewport(int width, int height) - { - } + public IRenderTarget CreateRenderTarget(int width, int height) + => new GDIPlusRenderTarget(this, width, height); - public void SetViewport(Size size) - { - SetViewport(size.Width, size.Height); - } + public void BindDefaultRenderTarget() + => CurRenderTarget = null; - public void BeginScene() - { - } - - public void EndScene() - { - // maybe an inconsistent semantic with other implementations.. - // but accomplishes the needed goal of getting the current RT to render - BindRenderTarget(null); - } - - public void FreeRenderTarget(RenderTarget rt) - { - var grt = (GDIPlusRenderTarget)rt.Opaque; - grt.Dispose(); - } - - public RenderTarget CreateRenderTarget(int w, int h) - { - var gtex = new GDIPlusTexture - { - SDBitmap = new(w, h, PixelFormat.Format32bppArgb) - }; - var tex = new Texture2d(this, gtex, w, h); - - var grt = new GDIPlusRenderTarget(() => BufferedGraphicsContext); - var rt = new RenderTarget(this, grt, tex); - grt.Target = rt; - return rt; - } - - public void BindRenderTarget(RenderTarget rt) - { - if (_currOffscreenGraphics != null) - { - _currOffscreenGraphics.Dispose(); - _currOffscreenGraphics = null; - } - - if (rt == null) - { - // null means to use the default RT for the current control - CurrentRenderTarget = _controlRenderTarget; - } - else - { - var gtex = (GDIPlusTexture)rt.Texture2d.Opaque; - CurrentRenderTarget = (GDIPlusRenderTarget)rt.Opaque; - _currOffscreenGraphics = SDGraphics.FromImage(gtex.SDBitmap); - } - } - - private GDIPlusRenderTarget _controlRenderTarget; - - public GDIPlusRenderTarget CreateControlRenderTarget(Func<(SDGraphics Graphics, Rectangle Rectangle)> getControlRenderContext) + public GDIPlusControlRenderTarget CreateControlRenderTarget(Func<(SDGraphics Graphics, Rectangle Rectangle)> getControlRenderContext) { if (_controlRenderTarget != null) { throw new InvalidOperationException($"{nameof(IGL_GDIPlus)} can only have one control render target"); } - _controlRenderTarget = new(() => BufferedGraphicsContext, getControlRenderContext); + _controlRenderTarget = new(getControlRenderContext); return _controlRenderTarget; } - - private SDGraphics _currOffscreenGraphics; - - public SDGraphics GetCurrentGraphics() - { - return _currOffscreenGraphics ?? CurrentRenderTarget.BufferedGraphics.Graphics; - } - - public GDIPlusRenderTarget CurrentRenderTarget; - - public readonly BufferedGraphicsContext BufferedGraphicsContext = new(); } } diff --git a/src/BizHawk.Bizware.Graphics/ImGuiResourceCache.cs b/src/BizHawk.Bizware.Graphics/ImGuiResourceCache.cs new file mode 100644 index 00000000000..aac5be832e4 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/ImGuiResourceCache.cs @@ -0,0 +1,185 @@ +using System.Collections.Generic; +using System.Drawing; + +namespace BizHawk.Bizware.Graphics +{ + /// + /// Shared resource cache for the ImGui 2D renderer + /// This allows multiple ImGui renderers to share the same cache + /// + public sealed class ImGuiResourceCache + { + private readonly IGL _igl; + + internal readonly IPipeline Pipeline; + internal readonly Dictionary TextureCache = [ ]; + internal readonly Dictionary BrushCache = [ ]; + + public ImGuiResourceCache(IGL igl) + { + _igl = igl; + if (igl.DispMethodEnum is EDispMethod.OpenGL or EDispMethod.D3D11) + { + string psProgram, vsProgram; + + // ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault + switch (igl.DispMethodEnum) + { + case EDispMethod.D3D11: + vsProgram = ImGuiVertexShader_d3d11; + psProgram = ImGuiPixelShader_d3d11; + break; + case EDispMethod.OpenGL: + vsProgram = ImGuiVertexShader_gl; + psProgram = ImGuiPixelShader_gl; + break; + default: + throw new InvalidOperationException(); + } + + var vertexLayoutItems = new PipelineCompileArgs.VertexLayoutItem[3]; + vertexLayoutItems[0] = new("aPosition", 2, 0, AttribUsage.Position); + vertexLayoutItems[1] = new("aTexcoord", 2, 8, AttribUsage.Texcoord0); + vertexLayoutItems[2] = new("aColor", 4, 16, AttribUsage.Color0, Integer: true); + + var compileArgs = new PipelineCompileArgs( + vertexLayoutItems, + vertexShaderArgs: new(vsProgram, "vsmain"), + fragmentShaderArgs: new(psProgram, "psmain"), + fragmentOutputName: "FragColor"); + Pipeline = igl.CreatePipeline(compileArgs); + + igl.BindPipeline(Pipeline); + SetTexture(null); + igl.BindPipeline(null); + } + } + + internal void SetProjection(int width, int height) + { + var projection = _igl.CreateGuiViewMatrix(width, height) * _igl.CreateGuiProjectionMatrix(width, height); + Pipeline.SetUniformMatrix("um44Projection", projection); + } + + internal void SetTexture(ITexture2D texture2D) + { + Pipeline.SetUniform("uSamplerEnable", texture2D != null); + Pipeline.SetUniformSampler("uSampler0", texture2D); + } + + public void Dispose() + { + foreach (var cachedTex in TextureCache.Values) + { + cachedTex.Dispose(); + } + + foreach (var cachedBrush in BrushCache.Values) + { + cachedBrush.Dispose(); + } + + TextureCache.Clear(); + BrushCache.Clear(); + Pipeline?.Dispose(); + } + + public void ClearTextureCache() + { + foreach (var cachedTex in TextureCache.Values) + { + cachedTex.Dispose(); + } + + TextureCache.Clear(); + } + + public const string ImGuiVertexShader_d3d11 = @" +//vertex shader uniforms +float4x4 um44Projection; + +struct VS_INPUT +{ + float2 aPosition : POSITION; + float2 aTexcoord : TEXCOORD0; + float4 aColor : COLOR0; +}; + +struct VS_OUTPUT +{ + float4 vPosition : SV_POSITION; + float2 vTexcoord0 : TEXCOORD0; + float4 vColor0 : COLOR0; +}; + +VS_OUTPUT vsmain(VS_INPUT src) +{ + VS_OUTPUT dst; + float4 temp = float4(src.aPosition,0,1); + dst.vPosition = mul(um44Projection, temp); + dst.vTexcoord0 = src.aTexcoord; + dst.vColor0 = src.aColor; + return dst; +} +"; + + public const string ImGuiPixelShader_d3d11 = @" +//pixel shader uniforms +bool uSamplerEnable; +Texture2D uTexture0; +sampler uSampler0; + +struct PS_INPUT +{ + float4 vPosition : SV_POSITION; + float2 vTexcoord0 : TEXCOORD0; + float4 vColor0 : COLOR0; +}; + +float4 psmain(PS_INPUT src) : SV_Target +{ + float4 temp = src.vColor0; + if(uSamplerEnable) temp *= uTexture0.Sample(uSampler0,src.vTexcoord0); + return temp; +} +"; + + public const string ImGuiVertexShader_gl = @" +//opengl 3.2 +#version 150 +uniform mat4 um44Projection; + +in vec2 aPosition; +in vec2 aTexcoord; +in vec4 aColor; + +out vec2 vTexcoord0; +out vec4 vColor0; + +void main() +{ + vec4 temp = vec4(aPosition,0,1); + gl_Position = um44Projection * temp; + vTexcoord0 = aTexcoord; + vColor0 = aColor; +}"; + + public const string ImGuiPixelShader_gl = @" +//opengl 3.2 +#version 150 +uniform bool uSamplerEnable; +uniform sampler2D uSampler0; + +in vec2 vTexcoord0; +in vec4 vColor0; + +out vec4 FragColor; + +void main() +{ + vec4 temp = vColor0; + if(uSamplerEnable) temp *= texture(uSampler0, vTexcoord0); + FragColor = temp; +}"; + } +} diff --git a/src/BizHawk.Bizware.Graphics/Interfaces/I2DRenderer.cs b/src/BizHawk.Bizware.Graphics/Interfaces/I2DRenderer.cs new file mode 100644 index 00000000000..3d667e23621 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/Interfaces/I2DRenderer.cs @@ -0,0 +1,67 @@ +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Text; + +namespace BizHawk.Bizware.Graphics +{ + /// + /// Interface for 2D rendering, similar to System.Drawing's Graphics + /// Semantically, this must be able to be called at any point + /// This means batching MUST occur + /// As in this case IGL resources can only be used in the ctor, Dispose(), and Render() + /// + public interface I2DRenderer : IDisposable + { + /// + /// Renders any pending draw calls. + /// Returns the result as an ITexture2D. + /// Internally, this may change the bound render target, pipeline, viewport/scissor, and blending state. + /// If this is important, rebind them after calling this. + /// Any rendering occurs after clearing the target texture. + /// If nothing needs to be rendered and the size does not change, the contents are preserved + /// + ITexture2D Render(int width, int height); + + /// + /// Clears any pending draw calls. + /// This will also insert a command to clear the target texture. + /// + void Clear(); + + /// + /// Discards any pending draw calls. + /// Similar to Clear(), except this won't insert a command to clear the target texture + /// + void Discard(); + + CompositingMode CompositingMode { set; } + + void DrawBezier(Color color, Point pt1, Point pt2, Point pt3, Point pt4); + + void DrawBeziers(Color color, Point[] points); + + void DrawRectangle(Color color, int x, int y, int width, int height); + + void FillRectangle(Color color, int x, int y, int width, int height); + + void DrawEllipse(Color color, int x, int y, int width, int height); + + void FillEllipse(Color color, int x, int y, int width, int height); + + void DrawImage(Bitmap bitmap, int x, int y); + + void DrawImage(Bitmap bitmap, Rectangle destRect, int srcX, int srcY, int srcWidth, int srcHeight, bool cache); + + void DrawLine(Color color, int x1, int y1, int x2, int y2); + + void DrawPie(Color color, int x, int y, int width, int height, int startAngle, int sweepAngle); + + void FillPie(Color color, int x, int y, int width, int height, int startAngle, int sweepAngle); + + void DrawPolygon(Color color, Point[] points); + + void FillPolygon(Color color, Point[] points); + + void DrawString(string s, Font font, Color color, float x, float y, StringFormat format = null, TextRenderingHint textRenderingHint = TextRenderingHint.SystemDefault); + } +} diff --git a/src/BizHawk.Bizware.Graphics/Interfaces/IGL.cs b/src/BizHawk.Bizware.Graphics/Interfaces/IGL.cs new file mode 100644 index 00000000000..b08b6c48364 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/Interfaces/IGL.cs @@ -0,0 +1,107 @@ +using System.Drawing; +using System.Numerics; + +namespace BizHawk.Bizware.Graphics +{ + /// + /// This is a wrapper over OpenGL and Direct3D11 to give a uniform interface + /// NOTE: THIS SHOULD NOT BE ASSUMED TO BE THREAD SAFE! Make a new IGL if you want to use it in a new thread. I hope that will work... + /// + public interface IGL : IDisposable + { + /// + /// Returns the display method represented by this IGL + /// + EDispMethod DispMethodEnum { get; } + + /// + /// Returns the maximum size any dimension of a texture may have + /// This should be set on init, and therefore shouldn't need a graphics context active... + /// + int MaxTextureDimension { get; } + + /// + /// Creates a texture with the specified dimensions + /// The texture will use a clamping address mode and nearest neighbor filtering by default + /// + ITexture2D CreateTexture(int width, int height); + + /// + /// In case you already have the texture ID (from an OpenGL emulator gpu core) you can get an ITexture2D with it this way. + /// Otherwise, if this isn't an OpenGL frontend implementation, the core is expected to readback the texture for GetVideoBuffer() + /// + ITexture2D WrapGLTexture2D(int glTexId, int width, int height); + + /// + /// Creates a render target. Only includes a color buffer, and will always be in byte order BGRA (i.e. little endian ARGB) + /// This may unbind a previously bound render target + /// + IRenderTarget CreateRenderTarget(int width, int height); + + /// + /// Binds the IGL's default render target (i.e. to the IGL's control) + /// This implicitly unbinds any previously bound IRenderTarget + /// + void BindDefaultRenderTarget(); + + /// + /// Clears the currently bound render target with the specified color + /// + void ClearColor(Color color); + + /// + /// Creates a complete pipeline + /// + IPipeline CreatePipeline(PipelineCompileArgs compileArgs); + + /// + /// Binds this pipeline as the current used for rendering + /// + void BindPipeline(IPipeline pipeline); + + /// + /// Enables normal (non-premultiplied) alpha blending. + /// + void EnableBlendNormal(); + + /// + /// Enables alpha blending (non-alpha values are copied from the source fragment). + /// This mimics GDI+ blending + /// + void EnableBlendAlpha(); + + /// + /// Disables blending (alpha values are copied from the source fragment) + /// + void DisableBlending(); + + /// + /// Sets the viewport (and scissor) according to the provided specifications + /// + void SetViewport(int x, int y, int width, int height); + + /// + /// Non-indexed drawing for the currently set pipeline/render target + /// Vertexes must form triangle strips + /// + void Draw(int vertexCount); + + /// + /// Indexed drawing for the currently set pipeline/render target + /// Indexes must be 16 bits each + /// Vertexes must form triangle lists + /// + void DrawIndexed(int indexCount, int indexStart, int vertexStart); + + /// + /// Generates a proper 2D othographic projection for the given destination size, suitable for use in a GUI + /// + Matrix4x4 CreateGuiProjectionMatrix(int width, int height); + + /// + /// Generates a proper view transform for a standard 2D othographic projection, including half-pixel jitter if necessary + /// and re-establishing of a normal 2D graphics top-left origin. Suitable for use in a GUI + /// + Matrix4x4 CreateGuiViewMatrix(int width, int height, bool autoflip = true); + } +} diff --git a/src/BizHawk.Bizware.Graphics/Interfaces/IGuiRenderer.cs b/src/BizHawk.Bizware.Graphics/Interfaces/IGuiRenderer.cs new file mode 100644 index 00000000000..f3e467e918d --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/Interfaces/IGuiRenderer.cs @@ -0,0 +1,68 @@ +using System.Drawing; +using System.Numerics; + +namespace BizHawk.Bizware.Graphics +{ + public interface IGuiRenderer : IDisposable + { + /// + /// Begin rendering, initializing viewport and projections to the given dimensions + /// + void Begin(int width, int height); + + /// + /// Draws a subrectangle from the provided texture. For advanced users only + /// + void DrawSubrect(ITexture2D tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1); + + /// + /// Ends rendering + /// + void End(); + + /// + /// Use this, if you must do something sneaky to OpenGL without this GuiRenderer knowing. + /// It might be faster than End and Beginning again, and certainly prettier + /// + void Flush(); + + bool IsActive { get; } + + MatrixStack ModelView { get; set; } + + IGL Owner { get; } + + MatrixStack Projection { get; set; } + + void EnableBlending(); + + void DisableBlending(); + + /// + /// Sets the specified corner color (for the gradient effect) + /// + /// (x, y, z, w) is (r, g, b, a) + void SetCornerColor(int which, Vector4 color); + + /// + /// Sets all four corner colors at once + /// + /// (x, y, z, w) is (r, g, b, a) + void SetCornerColors(Vector4[] colors); + + /// + /// Restores the pipeline to the default + /// + void SetDefaultPipeline(); + + void SetModulateColor(Color color); + + void SetModulateColorWhite(); + + /// + /// Sets the pipeline for this GuiRenderer to use. We won't keep possession of it. + /// This pipeline must work in certain ways, which can be discerned by inspecting the built-in one + /// + void SetPipeline(IPipeline pipeline); + } +} diff --git a/src/BizHawk.Bizware.Graphics/Interfaces/IPipeline.cs b/src/BizHawk.Bizware.Graphics/Interfaces/IPipeline.cs new file mode 100644 index 00000000000..c86a31bc303 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/Interfaces/IPipeline.cs @@ -0,0 +1,56 @@ +using System.Numerics; + +namespace BizHawk.Bizware.Graphics +{ + public interface IPipeline : IDisposable + { + /// + /// Sets vertex data for this pipeline + /// + void SetVertexData(IntPtr data, int count); + + /// + /// Sets index data for this pipeline + /// + void SetIndexData(IntPtr data, int count); + + bool HasUniformSampler(string name); + + string GetUniformSamplerName(int index); + + /// + /// Sets a uniform sampler to use use the provided texture + /// + void SetUniformSampler(string name, ITexture2D tex); + + /// + /// Sets a uniform value + /// + void SetUniformMatrix(string name, Matrix4x4 mat, bool transpose = false); + + /// + /// Sets a uniform value + /// + void SetUniformMatrix(string name, ref Matrix4x4 mat, bool transpose = false); + + /// + /// Sets a uniform value + /// + void SetUniform(string name, Vector4 value); + + /// + /// Sets a uniform value + /// + void SetUniform(string name, Vector2 value); + + /// + /// Sets a uniform value + /// + void SetUniform(string name, float value); + + /// + /// Sets a uniform value + /// + void SetUniform(string name, bool value); + } +} diff --git a/src/BizHawk.Bizware.Graphics/Interfaces/IRenderTarget.cs b/src/BizHawk.Bizware.Graphics/Interfaces/IRenderTarget.cs new file mode 100644 index 00000000000..59515f433ce --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/Interfaces/IRenderTarget.cs @@ -0,0 +1,15 @@ +namespace BizHawk.Bizware.Graphics +{ + /// + /// A render target, essentially just a 2D texture which can be written as if it was a window + /// As this is effectively a texture, it inherits ITexture2D + /// However, note that semantically the CPU shouldn't be writing to a render target, so LoadFrom might not work! + /// + public interface IRenderTarget : ITexture2D + { + /// + /// Binds this render target + /// + void Bind(); + } +} diff --git a/src/BizHawk.Bizware.Graphics/Interfaces/ITexture2D.cs b/src/BizHawk.Bizware.Graphics/Interfaces/ITexture2D.cs new file mode 100644 index 00000000000..134bad7432d --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/Interfaces/ITexture2D.cs @@ -0,0 +1,37 @@ +namespace BizHawk.Bizware.Graphics +{ + /// + /// A full-scale 2D texture, with mip levels and everything. + /// In OpenGL tradition, this encapsulates the sampler state, as well, which is equal parts annoying and convenient + /// + public interface ITexture2D : IDisposable + { + int Width { get; } + int Height { get; } + + /// + /// OpenGL wrapped textures from IGLTextureProvider will be upside down + /// + bool IsUpsideDown { get; } + + /// + /// Resolves the texture into a new BitmapBuffer + /// + BitmapBuffer Resolve(); + + /// + /// Loads the texture with new data. This isn't supposed to be especially versatile, it just blasts a bitmap buffer into the texture + /// + void LoadFrom(BitmapBuffer buffer); + + /// + /// Sets the texture's filtering mode to linear + /// + void SetFilterLinear(); + + /// + /// Sets the texture's filtering mode to nearest neighbor + /// + void SetFilterNearest(); + } +} diff --git a/src/BizHawk.Bizware.BizwareGL/MatrixStack.cs b/src/BizHawk.Bizware.Graphics/MatrixStack.cs similarity index 94% rename from src/BizHawk.Bizware.BizwareGL/MatrixStack.cs rename to src/BizHawk.Bizware.Graphics/MatrixStack.cs index b6b0f25372a..35483aa4437 100644 --- a/src/BizHawk.Bizware.BizwareGL/MatrixStack.cs +++ b/src/BizHawk.Bizware.Graphics/MatrixStack.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Numerics; -namespace BizHawk.Bizware.BizwareGL +namespace BizHawk.Bizware.Graphics { // note: the sense of these matrices, as well as pre- and post- multiplying may be all mixed up. // conceptually here is how we should be working, in the example of spinning a sprite in place diff --git a/src/BizHawk.Bizware.Graphics/OpenGL/IGL_OpenGL.cs b/src/BizHawk.Bizware.Graphics/OpenGL/IGL_OpenGL.cs index c94e48e8dc3..cff3942fed0 100644 --- a/src/BizHawk.Bizware.Graphics/OpenGL/IGL_OpenGL.cs +++ b/src/BizHawk.Bizware.Graphics/OpenGL/IGL_OpenGL.cs @@ -1,35 +1,12 @@ -// regarding binding and vertex arrays: -// http://stackoverflow.com/questions/8704801/glvertexattribpointer-clarification -// http://stackoverflow.com/questions/9536973/oes-vertex-array-object-and-client-state -// http://www.opengl.org/wiki/Vertex_Specification - -// etc -// glBindAttribLocation (programID, 0, "vertexPosition_modelspace"); - -using System; -using System.Collections.Generic; -using System.Diagnostics; using System.Drawing; -using System.IO; -using System.Linq; using System.Numerics; -using BizHawk.Bizware.BizwareGL; -using BizHawk.Common; - -using Silk.NET.OpenGL.Legacy; - -using BizShader = BizHawk.Bizware.BizwareGL.Shader; - -using BizTextureMagFilter = BizHawk.Bizware.BizwareGL.TextureMagFilter; -using BizTextureMinFilter = BizHawk.Bizware.BizwareGL.TextureMinFilter; - -using GLVertexAttribPointerType = Silk.NET.OpenGL.Legacy.VertexAttribPointerType; +using Silk.NET.OpenGL; namespace BizHawk.Bizware.Graphics { /// - /// OpenGL implementation of the BizwareGL.IGL interface + /// OpenGL implementation of the IGL interface /// public class IGL_OpenGL : IGL { @@ -38,633 +15,133 @@ public class IGL_OpenGL : IGL private readonly GL GL; // rendering state - private Pipeline _currPipeline; - private RenderTarget _currRenderTarget; - - public string API => "OPENGL"; + private OpenGLPipeline _curPipeline; + internal bool DefaultRenderTargetBound; - // this IGL either requires at least OpenGL 3.0 - public static bool Available => OpenGLVersion.SupportsVersion(3, 0); + // this IGL either requires at least OpenGL 3.2 + public static bool Available => OpenGLVersion.SupportsVersion(3, 2); public IGL_OpenGL() { if (!Available) { - throw new InvalidOperationException("OpenGL 3.0 is required and unavailable"); + throw new InvalidOperationException("OpenGL 3.2 is required and unavailable"); } GL = GL.GetApi(SDL2OpenGLContext.GetGLProcAddress); } - public void BeginScene() - { - } + public void Dispose() + => GL.Dispose(); - public void EndScene() + /// + /// Should be called once the GL context is created + /// + public void InitGLState() { - } + GL.GetInteger(GetPName.MaxTextureSize, out var maxTextureDimension); + if (maxTextureDimension == 0) + { + throw new($"Failed to get max texture size, GL error: {GL.GetError()}"); + } - public void Dispose() - { - GL.Dispose(); + MaxTextureDimension = maxTextureDimension; } + public int MaxTextureDimension { get; private set; } + public void ClearColor(Color color) { GL.ClearColor(color); GL.Clear(ClearBufferMask.ColorBufferBit); } - public void FreeTexture(Texture2d tex) + public void EnableBlendNormal() { - GL.DeleteTexture((uint)tex.Opaque); - } - - public BizShader CreateFragmentShader(string source, string entry, bool required) - { - return CreateShader(ShaderType.FragmentShader, source, required); - } - - public BizShader CreateVertexShader(string source, string entry, bool required) - { - return CreateShader(ShaderType.VertexShader, source, required); + GL.Enable(EnableCap.Blend); + GL.BlendEquation(GLEnum.FuncAdd); + GL.BlendFuncSeparate(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha, BlendingFactor.One, BlendingFactor.OneMinusSrcAlpha); } - public void EnableBlending() + public void EnableBlendAlpha() { GL.Enable(EnableCap.Blend); GL.BlendEquation(GLEnum.FuncAdd); - GL.BlendFuncSeparate(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha, BlendingFactor.One, BlendingFactor.Zero); + GL.BlendFuncSeparate(BlendingFactor.One, BlendingFactor.Zero, BlendingFactor.One, BlendingFactor.OneMinusSrcAlpha); } public void DisableBlending() => GL.Disable(EnableCap.Blend); - private class ShaderWrapper - { - public uint sid; - } - - private class PipelineWrapper - { - public uint pid; - public BizShader FragmentShader, VertexShader; - public List SamplerLocs; - } - - /// - /// is and either or is unavailable (their property is ), or - /// glLinkProgram call did not produce expected result - /// - public Pipeline CreatePipeline(VertexLayout vertexLayout, BizShader vertexShader, BizShader fragmentShader, bool required, string memo) + public IPipeline CreatePipeline(PipelineCompileArgs compileArgs) { - // if the shaders aren't available, the pipeline isn't either - if (!vertexShader.Available || !fragmentShader.Available) - { - var errors = $"Vertex Shader:\r\n {vertexShader.Errors} \r\n-------\r\nFragment Shader:\r\n{fragmentShader.Errors}"; - if (required) - { - throw new InvalidOperationException($"Couldn't build required GL pipeline:\r\n{errors}"); - } - - return new(this, null, false, null, null, null) { Errors = errors }; - } - - var success = true; - - var vsw = (ShaderWrapper)vertexShader.Opaque; - var fsw = (ShaderWrapper)fragmentShader.Opaque; - - var pid = GL.CreateProgram(); - GL.AttachShader(pid, vsw.sid); - GL.AttachShader(pid, fsw.sid); - _ = GL.GetError(); - - GL.LinkProgram(pid); - - var errcode = (ErrorCode)GL.GetError(); - var resultLog = GL.GetProgramInfoLog(pid); - - if (errcode != ErrorCode.NoError) - { - if (required) - { - throw new InvalidOperationException($"Error creating pipeline (error returned from glLinkProgram): {errcode}\r\n\r\n{resultLog}"); - } - - success = false; - } - - GL.GetProgram(pid, GLEnum.LinkStatus, out var linkStatus); - if (linkStatus == 0) - { - if (required) - { - throw new InvalidOperationException($"Error creating pipeline (link status false returned from glLinkProgram): \r\n\r\n{resultLog}"); - } - - success = false; -#if DEBUG - resultLog = GL.GetProgramInfoLog(pid); - Util.DebugWriteLine(resultLog); -#endif - } - - // need to work on validation. apparently there are some weird caveats to glValidate which make it complicated and possibly excuses (barely) the intel drivers' dysfunctional operation - // "A sampler points to a texture unit used by fixed function with an incompatible target" - // - // info: - // http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgram.xml - // This function mimics the validation operation that OpenGL implementations must perform when rendering commands are issued while programmable shaders are part of current state. - // glValidateProgram checks to see whether the executables contained in program can execute given the current OpenGL state - // This function is typically useful only during application development. - // - // So, this is no big deal. we shouldn't be calling validate right now anyway. - // conclusion: glValidate is very complicated and is of virtually no use unless your draw calls are returning errors and you want to know why - // _ = GL.GetError(); - // GL.ValidateProgram(pid); - // errcode = (ErrorCode)GL.GetError(); - // resultLog = GL.GetProgramInfoLog(pid); - // if (errcode != ErrorCode.NoError) - // throw new InvalidOperationException($"Error creating pipeline (error returned from glValidateProgram): {errcode}\r\n\r\n{resultLog}"); - // GL.GetProgram(pid, GetProgramParameterName.ValidateStatus, out var validateStatus); - // if (validateStatus == 0) - // throw new InvalidOperationException($"Error creating pipeline (validateStatus status false returned from glValidateProgram): \r\n\r\n{resultLog}"); - - // set the program to active, in case we need to set sampler uniforms on it - GL.UseProgram(pid); - -#if false - //get all the attributes (not needed) - var attributes = new List(); - GL.GetProgram(pid, GLEnum.ActiveAttributes, out var nAttributes); - for (uint i = 0; i < nAttributes; i++) - { - GL.GetActiveAttrib(pid, i, 1024, out _, out _, out AttributeType _, out string name); - attributes.Add(new() { Handle = new(i), Name = name }); - } -#endif - - // get all the uniforms - var uniforms = new List(); - GL.GetProgram(pid, GLEnum.ActiveUniforms, out var nUniforms); - var samplers = new List(); - - for (uint i = 0; i < nUniforms; i++) + try { - GL.GetActiveUniform(pid, i, 1024, out _, out _, out UniformType type, out string name); - var loc = GL.GetUniformLocation(pid, name); - - var ui = new UniformInfo { Name = name, Opaque = loc }; - - if (type == UniformType.Sampler2D) - { - ui.IsSampler = true; - ui.SamplerIndex = samplers.Count; - ui.Opaque = loc | (samplers.Count << 24); - samplers.Add(loc); - } - - uniforms.Add(ui); + return new OpenGLPipeline(GL, compileArgs); } - - // deactivate the program, so we don't accidentally use it - GL.UseProgram(0); - - if (!vertexShader.Available) success = false; - if (!fragmentShader.Available) success = false; - - var pw = new PipelineWrapper { pid = pid, VertexShader = vertexShader, FragmentShader = fragmentShader, SamplerLocs = samplers }; - - return new(this, pw, success, vertexLayout, uniforms, memo); - } - - public void FreePipeline(Pipeline pipeline) - { - // unavailable pipelines will have no opaque - if (pipeline.Opaque is not PipelineWrapper pw) + finally { - return; + BindPipeline(null); } - - GL.DeleteProgram(pw.pid); - - pw.FragmentShader.Release(); - pw.VertexShader.Release(); } - public void Internal_FreeShader(BizShader shader) + public void BindPipeline(IPipeline pipeline) { - var sw = (ShaderWrapper)shader.Opaque; - GL.DeleteShader(sw.sid); - } + _curPipeline = (OpenGLPipeline)pipeline; - /// . is - public void BindPipeline(Pipeline pipeline) - { - _currPipeline = pipeline; - - if (pipeline == null) + if (_curPipeline == null) { + GL.BindVertexArray(0); + GL.BindBuffer(GLEnum.ArrayBuffer, 0); + GL.BindBuffer(GLEnum.ElementArrayBuffer, 0); GL.UseProgram(0); + _curPipeline = null; return; } - if (!pipeline.Available) - { - throw new InvalidOperationException("Attempt to bind unavailable pipeline"); - } - - var pw = (PipelineWrapper)pipeline.Opaque; - GL.UseProgram(pw.pid); - - // this is dumb and confusing, but we have to bind physical sampler numbers to sampler variables. - for (var i = 0; i < pw.SamplerLocs.Count; i++) - { - GL.Uniform1(pw.SamplerLocs[i], i); - } - } - - private class VertexLayoutWrapper - { - public uint vao; - public uint vbo; - public int bufferLen; - } - - public VertexLayout CreateVertexLayout() - { - var vlw = new VertexLayoutWrapper() - { - vao = GL.GenVertexArray(), - vbo = GL.GenBuffer(), - bufferLen = 0, - }; - - return new(this, vlw); - } - - public void Internal_FreeVertexLayout(VertexLayout vl) - { - var vlw = (VertexLayoutWrapper)vl.Opaque; - GL.DeleteVertexArray(vlw.vao); - GL.DeleteBuffer(vlw.vbo); - } - - private void BindTexture2d(Texture2d tex) - { - GL.BindTexture(TextureTarget.Texture2D, (uint)tex.Opaque); - } - - public void SetTextureWrapMode(Texture2d tex, bool clamp) - { - BindTexture2d(tex); - - var mode = clamp ? TextureWrapMode.ClampToEdge : TextureWrapMode.Repeat; - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)mode); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)mode); - } - - private void LegacyBindArrayData(VertexLayout vertexLayout, IntPtr pData) - { - // DEPRECATED CRAP USED, NEEDED FOR ANCIENT SHADERS - // ALSO THIS IS WHY LEGACY PACKAGE IS USED AS NON-LEGACY DOESN'T HAVE THESE - // TODO: REMOVE NEED FOR THIS -#pragma warning disable CS0618 -#pragma warning disable CS0612 - - // disable all the client states.. a lot of overhead right now, to be sure - - GL.DisableClientState(EnableCap.VertexArray); - GL.DisableClientState(EnableCap.ColorArray); - - for (var i = 1; i >= 0; i--) - { - GL.ClientActiveTexture(TextureUnit.Texture0 + i); - GL.DisableClientState(EnableCap.TextureCoordArray); - } - - unsafe - { - foreach (var (_, item) in vertexLayout.Items) - { - switch (item.Usage) - { - case AttribUsage.Position: - GL.EnableClientState(EnableCap.VertexArray); - GL.VertexPointer(item.Components, VertexPointerType.Float, (uint)item.Stride, (pData + item.Offset).ToPointer()); - break; - case AttribUsage.Texcoord0: - GL.ClientActiveTexture(TextureUnit.Texture0); - GL.EnableClientState(EnableCap.TextureCoordArray); - GL.TexCoordPointer(item.Components, TexCoordPointerType.Float, (uint)item.Stride, (pData + item.Offset).ToPointer()); - break; - case AttribUsage.Texcoord1: - GL.ClientActiveTexture(TextureUnit.Texture1); - GL.EnableClientState(EnableCap.TextureCoordArray); - GL.TexCoordPointer(item.Components, TexCoordPointerType.Float, (uint)item.Stride, (pData + item.Offset).ToPointer()); - GL.ClientActiveTexture(TextureUnit.Texture0); - break; - case AttribUsage.Color0: - break; - case AttribUsage.Unspecified: - default: - throw new InvalidOperationException(); - } - } - } -#pragma warning restore CS0618 -#pragma warning restore CS0612 - } - - public void Draw(IntPtr data, int count) - { - if (_currPipeline == null) - { - throw new InvalidOperationException($"Tried to {nameof(Draw)} without pipeline!"); - } - - var vertexLayout = _currPipeline.VertexLayout; - - if (_currPipeline.Memo != "xgui") - { - LegacyBindArrayData(vertexLayout, data); - GL.DrawArrays(PrimitiveType.TriangleStrip, 0, (uint)count); - return; - } - - var vlw = (VertexLayoutWrapper)vertexLayout.Opaque; - GL.BindVertexArray(vlw.vao); - GL.BindBuffer(GLEnum.ArrayBuffer, vlw.vbo); - - var stride = vertexLayout.Items[0].Stride; - Debug.Assert(vertexLayout.Items.All(i => i.Value.Stride == stride)); - - unsafe - { - var vertexes = new ReadOnlySpan(data.ToPointer(), count * stride); - - // BufferData reallocs and BufferSubData doesn't, so only use the former if size changes - if (vertexes.Length != vlw.bufferLen) - { - GL.BufferData(GLEnum.ArrayBuffer, vertexes, GLEnum.DynamicDraw); - } - else - { - // I tried to do a CRC check to avoid BufferSubData calls, actually hurts performance - GL.BufferSubData(GLEnum.ArrayBuffer, 0, vertexes); - } - - vlw.bufferLen = vertexes.Length; - - foreach (var (i, item) in vertexLayout.Items) - { - GL.VertexAttribPointer( - (uint)i, - item.Components, - (GLVertexAttribPointerType)item.AttribType, // these are the same enum - item.Normalized, - (uint)item.Stride, - (void*)item.Offset); - GL.EnableVertexAttribArray((uint)i); - } - } - - GL.DrawArrays(PrimitiveType.TriangleStrip, 0, (uint)count); - - foreach (var (i, _) in vertexLayout.Items) - { - GL.DisableVertexAttribArray((uint)i); - } - - GL.BindBuffer(GLEnum.ArrayBuffer, 0); - GL.BindVertexArray(0); - } - - public void SetPipelineUniform(PipelineUniform uniform, bool value) - { - GL.Uniform1((int)uniform.Sole.Opaque, value ? 1 : 0); - } - - public unsafe void SetPipelineUniformMatrix(PipelineUniform uniform, Matrix4x4 mat, bool transpose) - { - GL.UniformMatrix4((int)uniform.Sole.Opaque, 1, transpose, (float*)&mat); - } - - public unsafe void SetPipelineUniformMatrix(PipelineUniform uniform, ref Matrix4x4 mat, bool transpose) - { - fixed (Matrix4x4* pMat = &mat) - { - GL.UniformMatrix4((int)uniform.Sole.Opaque, 1, transpose, (float*)pMat); - } - } - - public void SetPipelineUniform(PipelineUniform uniform, Vector4 value) - { - GL.Uniform4((int)uniform.Sole.Opaque, value.X, value.Y, value.Z, value.W); - } - - public void SetPipelineUniform(PipelineUniform uniform, Vector2 value) - { - GL.Uniform2((int)uniform.Sole.Opaque, value.X, value.Y); - } - - public void SetPipelineUniform(PipelineUniform uniform, float value) - { - if (uniform.Owner == null) - { - return; // uniform was optimized out - } - - GL.Uniform1((int)uniform.Sole.Opaque, value); - } - - public unsafe void SetPipelineUniform(PipelineUniform uniform, Vector4[] values) - { - fixed (Vector4* pValues = &values[0]) - { - GL.Uniform4((int)uniform.Sole.Opaque, (uint)values.Length, (float*)pValues); - } - } - - public void SetPipelineUniformSampler(PipelineUniform uniform, Texture2d tex) - { - var n = (int)uniform.Sole.Opaque >> 24; - - // set the sampler index into the uniform first - GL.ActiveTexture(TextureUnit.Texture0 + n); - - // now bind the texture - GL.BindTexture(TextureTarget.Texture2D, (uint)tex.Opaque); - } - - public void SetMinFilter(Texture2d texture, BizTextureMinFilter minFilter) - { - BindTexture2d(texture); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)minFilter); - } - - public void SetMagFilter(Texture2d texture, BizTextureMagFilter magFilter) - { - BindTexture2d(texture); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)magFilter); + GL.BindVertexArray(_curPipeline.VAO); + GL.BindBuffer(GLEnum.ArrayBuffer, _curPipeline.VBO); + GL.BindBuffer(GLEnum.ElementArrayBuffer, _curPipeline.IBO); + GL.UseProgram(_curPipeline.PID); } - public Texture2d LoadTexture(Bitmap bitmap) - { - using var bmp = new BitmapBuffer(bitmap, new()); - return LoadTexture(bmp); - } + public void Draw(int vertexCount) + => GL.DrawArrays(PrimitiveType.TriangleStrip, 0, (uint)vertexCount); - public Texture2d LoadTexture(Stream stream) - { - using var bmp = new BitmapBuffer(stream, new()); - return LoadTexture(bmp); - } + public unsafe void DrawIndexed(int indexCount, int indexStart, int vertexStart) + => GL.DrawElementsBaseVertex(PrimitiveType.Triangles, (uint)indexCount, DrawElementsType.UnsignedShort, (void*)(indexStart * 2), vertexStart); - public Texture2d CreateTexture(int width, int height) - { - var id = GL.GenTexture(); - return new(this, id, width, height); - } + public ITexture2D CreateTexture(int width, int height) + => new OpenGLTexture2D(GL, width, height); - public Texture2d WrapGLTexture2d(IntPtr glTexId, int width, int height) - { - return new(this, (uint)glTexId.ToInt32(), width, height) { IsUpsideDown = true }; - } - - public unsafe void LoadTextureData(Texture2d tex, BitmapBuffer bmp) - { - var bmpData = bmp.LockBits(); - try - { - GL.BindTexture(TextureTarget.Texture2D, (uint)tex.Opaque); - GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, (uint)bmp.Width, (uint)bmp.Height, PixelFormat.Bgra, PixelType.UnsignedByte, bmpData.Scan0.ToPointer()); - } - finally - { - bmp.UnlockBits(bmpData); - } - } - - public void FreeRenderTarget(RenderTarget rt) - { - rt.Texture2d.Dispose(); - GL.DeleteFramebuffer((uint)rt.Opaque); - } + public ITexture2D WrapGLTexture2D(int glTexId, int width, int height) + => new OpenGLTexture2D(GL, (uint)glTexId, width, height); /// framebuffer creation unsuccessful - public unsafe RenderTarget CreateRenderTarget(int w, int h) - { - // create a texture for it - var texId = GL.GenTexture(); - var tex = new Texture2d(this, texId, w, h); - - GL.BindTexture(TextureTarget.Texture2D, texId); - GL.TexImage2D(TextureTarget.Texture2D, 0, InternalFormat.Rgba8, (uint)w, (uint)h, 0, PixelFormat.Bgra, PixelType.UnsignedByte, null); - tex.SetMagFilter(BizTextureMagFilter.Nearest); - tex.SetMinFilter(BizTextureMinFilter.Nearest); - - // create the FBO - var fbId = GL.GenFramebuffer(); - GL.BindFramebuffer(FramebufferTarget.Framebuffer, fbId); - - // bind the tex to the FBO - GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, texId, 0); - - // do something, I guess say which color buffers are used by the framebuffer - GL.DrawBuffer(DrawBufferMode.ColorAttachment0); - - if ((FramebufferStatus)GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferStatus.Complete) - { - throw new InvalidOperationException($"Error creating framebuffer (at {nameof(GL.CheckFramebufferStatus)})"); - } - - // since we're done configuring unbind this framebuffer, to return to the default - GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); - - return new(this, fbId, tex); - } + public IRenderTarget CreateRenderTarget(int width, int height) + => new OpenGLRenderTarget(this, GL, width, height); - public void BindRenderTarget(RenderTarget rt) + public void BindDefaultRenderTarget() { - _currRenderTarget = rt; - if (rt == null) - { - GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); - } - else - { - GL.BindFramebuffer(FramebufferTarget.Framebuffer, (uint)rt.Opaque); - } - } - - public unsafe Texture2d LoadTexture(BitmapBuffer bmp) - { - Texture2d ret; - var id = GL.GenTexture(); - try - { - ret = new(this, id, bmp.Width, bmp.Height); - GL.BindTexture(TextureTarget.Texture2D, id); - // picking a color order that matches doesnt seem to help, any. maybe my driver is accelerating it, or maybe it isnt a big deal. but its something to study on another day - GL.TexImage2D(TextureTarget.Texture2D, 0, InternalFormat.Rgba, (uint)bmp.Width, (uint)bmp.Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero.ToPointer()); - LoadTextureData(ret, bmp); - } - catch - { - GL.DeleteTexture(id); - throw; - } - - // set default filtering... its safest to do this always - ret.SetFilterNearest(); - - return ret; - } - - public unsafe BitmapBuffer ResolveTexture2d(Texture2d tex) - { - // note - this is dangerous since it changes the bound texture. could we save it? - BindTexture2d(tex); - var bb = new BitmapBuffer(tex.IntWidth, tex.IntHeight); - var bmpdata = bb.LockBits(); - GL.GetTexImage(TextureTarget.Texture2D, 0, PixelFormat.Bgra, PixelType.UnsignedByte, bmpdata.Scan0.ToPointer()); - bb.UnlockBits(bmpdata); - return bb; - } - - public Texture2d LoadTexture(string path) - { - using var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); - return LoadTexture(fs); - } - - public Matrix4x4 CreateGuiProjectionMatrix(int w, int h) - { - return CreateGuiProjectionMatrix(new(w, h)); - } - - public Matrix4x4 CreateGuiViewMatrix(int w, int h, bool autoflip) - { - return CreateGuiViewMatrix(new(w, h), autoflip); + GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); + DefaultRenderTargetBound = true; } - public Matrix4x4 CreateGuiProjectionMatrix(Size dims) + public Matrix4x4 CreateGuiProjectionMatrix(int width, int height) { var ret = Matrix4x4.Identity; - ret.M11 = 2.0f / dims.Width; - ret.M22 = 2.0f / dims.Height; + ret.M11 = 2.0f / width; + ret.M22 = 2.0f / height; return ret; } - public Matrix4x4 CreateGuiViewMatrix(Size dims, bool autoflip) + public Matrix4x4 CreateGuiViewMatrix(int width, int height, bool autoflip) { var ret = Matrix4x4.Identity; ret.M22 = -1.0f; - ret.M41 = dims.Width * -0.5f; - ret.M42 = dims.Height * 0.5f; - if (autoflip && _currRenderTarget is not null) // flip as long as we're not a final render target + ret.M41 = width * -0.5f; + ret.M42 = height * 0.5f; + if (autoflip && !DefaultRenderTargetBound) // flip as long as we're not a final render target { ret.M22 = 1.0f; ret.M42 *= -1; @@ -679,99 +156,5 @@ public void SetViewport(int x, int y, int width, int height) GL.Scissor(x, y, (uint)width, (uint)height); // hack for mupen[rice]+intel: at least the rice plugin leaves the scissor rectangle scrambled, and we're trying to run it in the main graphics context for intel // BUT ALSO: new specifications.. viewport+scissor make sense together } - - public void SetViewport(int width, int height) - { - SetViewport(0, 0, width, height); - } - - public void SetViewport(Size size) - { - SetViewport(size.Width, size.Height); - } - - private BizShader CreateShader(ShaderType type, string source, bool required) - { - var sw = new ShaderWrapper(); - var info = string.Empty; - - _ = GL.GetError(); - var sid = GL.CreateShader(type); - var ok = CompileShaderSimple(sid, source, required); - if (!ok) - { - GL.GetShaderInfoLog(sid, out info); - GL.DeleteShader(sid); - sid = 0; - } - - var ret = new BizShader(this, sw, ok) - { - Errors = info - }; - - sw.sid = sid; - - return ret; - } - - private bool CompileShaderSimple(uint sid, string source, bool required) - { - var success = true; - - var errcode = (ErrorCode)GL.GetError(); - if (errcode != ErrorCode.NoError) - { - if (required) - { - throw new InvalidOperationException($"Error compiling shader (from previous operation) {errcode}"); - } - - success = false; - } - - GL.ShaderSource(sid, source); - - errcode = (ErrorCode)GL.GetError(); - if (errcode != ErrorCode.NoError) - { - if (required) - { - throw new InvalidOperationException($"Error compiling shader ({nameof(GL.ShaderSource)}) {errcode}"); - } - - success = false; - } - - GL.CompileShader(sid); - - errcode = (ErrorCode)GL.GetError(); - var resultLog = GL.GetShaderInfoLog(sid); - if (errcode != ErrorCode.NoError) - { - var message = $"Error compiling shader ({nameof(GL.CompileShader)}) {errcode}\r\n\r\n{resultLog}"; - if (required) - { - throw new InvalidOperationException(message); - } - - Console.WriteLine(message); - success = false; - } - - GL.GetShader(sid, ShaderParameterName.CompileStatus, out var n); - - if (n == 0) - { - if (required) - { - throw new InvalidOperationException($"Error compiling shader ({nameof(GL.GetShader)})\r\n\r\n{resultLog}"); - } - - success = false; - } - - return success; - } } } diff --git a/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLPipeline.cs b/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLPipeline.cs new file mode 100644 index 00000000000..64397a0d98c --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLPipeline.cs @@ -0,0 +1,314 @@ +using System.Collections.Generic; +using System.Linq; +using System.Numerics; + +using Silk.NET.OpenGL; + +using BizHawk.Common; +using BizHawk.Common.CollectionExtensions; + +namespace BizHawk.Bizware.Graphics +{ + internal class OpenGLPipeline : IPipeline + { + private readonly GL GL; + + public readonly uint VAO; + public readonly uint VBO; + + public readonly int VertexStride; + public int VertexBufferLen; + + public readonly uint IBO; + public int IndexBufferLen; + + public readonly uint VertexSID; + public readonly uint FragmentSID; + + public readonly uint PID; + private readonly Dictionary _uniforms = new(); + private readonly Dictionary _samplers = new(); + + private uint CompileShader(string source, ShaderType type) + { + var sid = GL.CreateShader(type); + + try + { + var errcode = (ErrorCode)GL.GetError(); + if (errcode != ErrorCode.NoError) + { + throw new InvalidOperationException($"Error compiling shader (from previous operation) {errcode}"); + } + + GL.ShaderSource(sid, source); + + errcode = (ErrorCode)GL.GetError(); + if (errcode != ErrorCode.NoError) + { + throw new InvalidOperationException($"Error compiling shader ({nameof(GL.ShaderSource)}) {errcode}"); + } + + GL.CompileShader(sid); + + errcode = (ErrorCode)GL.GetError(); + var resultLog = GL.GetShaderInfoLog(sid); + if (errcode != ErrorCode.NoError) + { + throw new InvalidOperationException( $"Error compiling shader ({nameof(GL.CompileShader)}) {errcode}\r\n\r\n{resultLog}"); + } + + GL.GetShader(sid, ShaderParameterName.CompileStatus, out var n); + + if (n == 0) + { + throw new InvalidOperationException($"Error compiling shader ({nameof(GL.GetShader)})\r\n\r\n{resultLog}"); + } + + return sid; + } + catch + { + GL.DeleteShader(sid); + throw; + } + } + + public OpenGLPipeline(GL gl, PipelineCompileArgs compileArgs) + { + GL = gl; + + try + { + VAO = GL.GenVertexArray(); + VBO = GL.GenBuffer(); + VertexStride = compileArgs.VertexLayoutStride; + + IBO = GL.GenBuffer(); + + _ = GL.GetError(); + VertexSID = CompileShader(compileArgs.VertexShaderArgs.Source, ShaderType.VertexShader); + FragmentSID = CompileShader(compileArgs.FragmentShaderArgs.Source, ShaderType.FragmentShader); + + PID = GL.CreateProgram(); + GL.AttachShader(PID, VertexSID); + GL.AttachShader(PID, FragmentSID); + + GL.BindVertexArray(VAO); // used by EnableVertexAttribArray + GL.BindBuffer(GLEnum.ArrayBuffer, VBO); // used by VertexAttribPointer + unsafe + { + for (var i = 0; i < compileArgs.VertexLayout.Count; i++) + { + var item = compileArgs.VertexLayout[i]; + var attribIndex = (uint)i; + GL.BindAttribLocation(PID, attribIndex, item.Name); + GL.EnableVertexAttribArray(attribIndex); + GL.VertexAttribPointer( + attribIndex, + item.Integer ? (int)GLEnum.Bgra : item.Components, + item.Integer ? VertexAttribPointerType.UnsignedByte : VertexAttribPointerType.Float, + normalized: item.Integer, + (uint)VertexStride, + (void*)item.Offset); + } + } + + GL.BindFragDataLocation(PID, 0, compileArgs.FragmentOutputName); + + _ = GL.GetError(); + GL.LinkProgram(PID); + + var errcode = (ErrorCode)GL.GetError(); + var resultLog = GL.GetProgramInfoLog(PID); + + if (errcode != ErrorCode.NoError) + { + throw new InvalidOperationException($"Error creating pipeline (error returned from ({nameof(GL.LinkProgram)}): {errcode}\r\n\r\n{resultLog}"); + } + + GL.GetProgram(PID, GLEnum.LinkStatus, out var linkStatus); + + if (linkStatus == 0) + { + throw new InvalidOperationException($"Error creating pipeline (link status false returned from {nameof(GL.GetProgram)}): \r\n\r\n{resultLog}"); + } + + // need to work on validation. apparently there are some weird caveats to glValidate which make it complicated and possibly excuses (barely) the intel drivers' dysfunctional operation + // "A sampler points to a texture unit used by fixed function with an incompatible target" + // + // info: + // http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgram.xml + // This function mimics the validation operation that OpenGL implementations must perform when rendering commands are issued while programmable shaders are part of current state. + // glValidateProgram checks to see whether the executables contained in program can execute given the current OpenGL state + // This function is typically useful only during application development. + // + // So, this is no big deal. we shouldn't be calling validate right now anyway. + // conclusion: glValidate is very complicated and is of virtually no use unless your draw calls are returning errors and you want to know why +#if false + _ = GL.GetError(); + GL.ValidateProgram(PID); + errcode = (ErrorCode)GL.GetError(); + resultLog = GL.GetProgramInfoLog(PID); + if (errcode != ErrorCode.NoError) + { + throw new InvalidOperationException($"Error creating pipeline (error returned from {nameof(GL.ValidateProgram)}): {errcode}\r\n\r\n{resultLog}"); + } + + GL.GetProgram(PID, GLEnum.ValidateStatus, out var validateStatus); + if (validateStatus == 0) + { + throw new InvalidOperationException($"Error creating pipeline (validateStatus status false returned from glValidateProgram): \r\n\r\n{resultLog}"); + } +#endif + // set the program to active, in case we need to set sampler uniforms on it + GL.UseProgram(PID); + + // get all the uniforms + GL.GetProgram(PID, GLEnum.ActiveUniforms, out var numUniforms); + + for (uint i = 0; i < numUniforms; i++) + { + GL.GetActiveUniform(PID, i, 1024, out _, out _, out UniformType type, out string name); + var loc = GL.GetUniformLocation(PID, name); + + // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault + switch (type) + { + case UniformType.Bool: + case UniformType.Float: + case UniformType.FloatVec2: + case UniformType.FloatVec3: + case UniformType.FloatVec4: + case UniformType.FloatMat4: + _uniforms.Add(name, loc); + break; + case UniformType.Sampler2D: + // this is dumb and confusing, but we have to bind physical sampler numbers to sampler variables + var bindPoint = _samplers.Count; + GL.Uniform1(loc, bindPoint); + _samplers.Add(name, bindPoint); + break; + } + } + } + catch + { + Dispose(); + throw; + } + } + + public void Dispose() + { + GL.DeleteProgram(PID); + + GL.DeleteShader(VertexSID); + GL.DeleteShader(FragmentSID); + + GL.DeleteVertexArray(VAO); + GL.DeleteBuffer(VBO); + } + + public void SetVertexData(IntPtr data, int count) + { + ReadOnlySpan vertexes = Util.UnsafeSpanFromPointer(ptr: data, length: count * VertexStride); + // BufferData reallocs and BufferSubData doesn't, so only use the former if we need to grow the buffer + if (vertexes.Length > VertexBufferLen) + { + GL.BufferData(GLEnum.ArrayBuffer, vertexes, GLEnum.DynamicDraw); + VertexBufferLen = vertexes.Length; + } + else + { + GL.BufferSubData(GLEnum.ArrayBuffer, 0, vertexes); + } + } + + public void SetIndexData(IntPtr data, int count) + { + ReadOnlySpan indexes = Util.UnsafeSpanFromPointer(ptr: data, length: count * 2); + if (indexes.Length > IndexBufferLen) + { + GL.BufferData(GLEnum.ElementArrayBuffer, indexes, GLEnum.DynamicDraw); + IndexBufferLen = indexes.Length; + } + else + { + GL.BufferSubData(GLEnum.ElementArrayBuffer, 0, indexes); + } + } + + public bool HasUniformSampler(string name) + => _samplers.ContainsKey(name); + + public string GetUniformSamplerName(int index) + { + var sampler = _samplers.AsEnumerable().FirstOrNull(s => s.Value == index); + return sampler?.Key; + } + + public void SetUniformSampler(string name, ITexture2D tex) + { + if (tex == null) + { + return; + } + + if (_samplers.TryGetValue(name, out var sampler)) + { + var oglTex = (OpenGLTexture2D)tex; + GL.ActiveTexture(TextureUnit.Texture0 + sampler); + GL.BindTexture(TextureTarget.Texture2D, oglTex.TexID); + } + } + + public void SetUniformMatrix(string name, Matrix4x4 mat, bool transpose) + => SetUniformMatrix(name, ref mat, transpose); + + public unsafe void SetUniformMatrix(string name, ref Matrix4x4 mat, bool transpose) + { + if (_uniforms.TryGetValue(name, out var uid)) + { + fixed (Matrix4x4* p = &mat) + { + GL.UniformMatrix4(uid, 1, transpose, (float*)p); + } + } + } + + public unsafe void SetUniform(string name, Vector4 value) + { + if (_uniforms.TryGetValue(name, out var uid)) + { + GL.Uniform4(uid, 1, (float*)&value); + } + } + + public unsafe void SetUniform(string name, Vector2 value) + { + if (_uniforms.TryGetValue(name, out var uid)) + { + GL.Uniform2(uid, 1, (float*)&value); + } + } + + public unsafe void SetUniform(string name, float value) + { + if (_uniforms.TryGetValue(name, out var uid)) + { + GL.Uniform1(uid, 1, &value); + } + } + + public unsafe void SetUniform(string name, bool value) + { + if (_uniforms.TryGetValue(name, out var uid)) + { + // note: GLSL bool is 4 bytes large + var b = value ? 1 : 0; + GL.Uniform1(uid, 1, &b); + } + } + } +} diff --git a/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLRenderTarget.cs b/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLRenderTarget.cs new file mode 100644 index 00000000000..106ad52c728 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLRenderTarget.cs @@ -0,0 +1,50 @@ +using Silk.NET.OpenGL; + +namespace BizHawk.Bizware.Graphics +{ + internal sealed class OpenGLRenderTarget : OpenGLTexture2D, IRenderTarget + { + private readonly IGL_OpenGL _openGL; + private readonly GL GL; + + public readonly uint FBO; + + public OpenGLRenderTarget(IGL_OpenGL openGL, GL gl, int width, int height) + : base(gl, width, height) + { + _openGL = openGL; + GL = gl; + + // create the FBO + FBO = GL.GenFramebuffer(); + Bind(); + + // bind the tex to the FBO + GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, TexID, 0); + + // do something, I guess say which color buffers are used by the framebuffer + GL.DrawBuffer(DrawBufferMode.ColorAttachment0); + + if ((FramebufferStatus)GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferStatus.Complete) + { + Dispose(); + throw new InvalidOperationException($"Error creating framebuffer (at {nameof(GL.CheckFramebufferStatus)})"); + } + } + + public override void Dispose() + { + GL.DeleteFramebuffer(FBO); + base.Dispose(); + } + + public void Bind() + { + GL.BindFramebuffer(FramebufferTarget.Framebuffer, FBO); + _openGL.DefaultRenderTargetBound = false; + } + + public override string ToString() + => $"OpenGL RenderTarget: {Width}x{Height}"; + } +} diff --git a/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLTexture2D.cs b/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLTexture2D.cs new file mode 100644 index 00000000000..b91ab6e70cf --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLTexture2D.cs @@ -0,0 +1,95 @@ +using Silk.NET.OpenGL; + +namespace BizHawk.Bizware.Graphics +{ + internal class OpenGLTexture2D : ITexture2D + { + private readonly GL GL; + public readonly uint TexID; + + public int Width { get; } + public int Height { get; } + public bool IsUpsideDown { get; } + + public OpenGLTexture2D(GL gl, int width, int height) + { + GL = gl; + TexID = GL.GenTexture(); + + GL.BindTexture(TextureTarget.Texture2D, TexID); + unsafe + { + GL.TexImage2D(TextureTarget.Texture2D, 0, InternalFormat.Rgba8, (uint)width, (uint)height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, null); + } + + // sensible defaults + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); + + Width = width; + Height = height; + IsUpsideDown = false; + } + + public OpenGLTexture2D(GL gl, uint texID, int width, int height) + { + GL = gl; + TexID = texID; + Width = width; + Height = height; + IsUpsideDown = true; + } + + public virtual void Dispose() + => GL.DeleteTexture(TexID); + + public unsafe BitmapBuffer Resolve() + { + GL.BindTexture(TextureTarget.Texture2D, TexID); + + var pixels = new int[Width * Height]; + fixed (int* p = pixels) + { + GL.GetTexImage(TextureTarget.Texture2D, 0, PixelFormat.Bgra, PixelType.UnsignedByte, p); + } + + return new(Width, Height, pixels); + } + + public unsafe void LoadFrom(BitmapBuffer buffer) + { + if (buffer.Width != Width || buffer.Height != Height) + { + throw new InvalidOperationException("BitmapBuffer dimensions do not match texture dimensions"); + } + + var bmpData = buffer.LockBits(); + try + { + GL.BindTexture(TextureTarget.Texture2D, TexID); + GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, (uint)buffer.Width, (uint)buffer.Height, PixelFormat.Bgra, PixelType.UnsignedByte, bmpData.Scan0.ToPointer()); + } + finally + { + buffer.UnlockBits(bmpData); + } + } + + public void SetFilterLinear() + { + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); + } + + public void SetFilterNearest() + { + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); + } + + public override string ToString() + => $"OpenGL Texture2D: {Width}x{Height}"; + } +} diff --git a/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLVersion.cs b/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLVersion.cs index e1c0114a14d..d9a0b14a17b 100644 --- a/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLVersion.cs +++ b/src/BizHawk.Bizware.Graphics/OpenGL/OpenGLVersion.cs @@ -1,10 +1,8 @@ -using System; using System.Collections.Generic; -using BizHawk.Common.CollectionExtensions; -using Silk.NET.OpenGL.Legacy; +using Silk.NET.OpenGL; -using static SDL2.SDL; +using BizHawk.Common.CollectionExtensions; namespace BizHawk.Bizware.Graphics { @@ -13,22 +11,6 @@ namespace BizHawk.Bizware.Graphics /// public static class OpenGLVersion { - private readonly ref struct SavedOpenGLContext - { - private readonly IntPtr _sdlWindow, _glContext; - - public SavedOpenGLContext() - { - _sdlWindow = SDL_GL_GetCurrentWindow(); - _glContext = SDL_GL_GetCurrentContext(); - } - - public void Dispose() - { - _ = SDL_GL_MakeCurrent(_sdlWindow, _glContext); - } - } - private static readonly IDictionary _glSupport = new Dictionary(); private static int PackGLVersion(int major, int minor) @@ -40,7 +22,7 @@ private static bool CheckVersion(int requestedMajor, int requestedMinor) { try { - using (new SDL2OpenGLContext(requestedMajor, requestedMinor, true, false)) + using (new SDL2OpenGLContext(requestedMajor, requestedMinor, true)) { using var gl = GL.GetApi(SDL2OpenGLContext.GetGLProcAddress); var versionString = gl.GetStringS(StringName.Version); @@ -61,4 +43,4 @@ public static bool SupportsVersion(int major, int minor) => _glSupport.GetValueOrPut(PackGLVersion(major, minor), static version => CheckVersion(version / 10, version % 10)); } -} \ No newline at end of file +} diff --git a/src/BizHawk.Bizware.Graphics/OpenGL/SDL2OpenGLContext.cs b/src/BizHawk.Bizware.Graphics/OpenGL/SDL2OpenGLContext.cs index 202351851c9..89c3ad5cc91 100644 --- a/src/BizHawk.Bizware.Graphics/OpenGL/SDL2OpenGLContext.cs +++ b/src/BizHawk.Bizware.Graphics/OpenGL/SDL2OpenGLContext.cs @@ -1,10 +1,8 @@ // #define DEBUG_OPENGL -using System; - #if DEBUG_OPENGL using System.Runtime.InteropServices; -using Silk.NET.OpenGL.Legacy; +using Silk.NET.OpenGL; #endif using static SDL2.SDL; @@ -30,17 +28,6 @@ static SDL2OpenGLContext() throw new($"Could not load default OpenGL library! SDL Error: {SDL_GetError()}"); } - // set some sensible defaults - SDL_GL_ResetAttributes(); - if (SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_RED_SIZE, 8) is not 0 - || SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_GREEN_SIZE, 8) is not 0 - || SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_BLUE_SIZE, 8) is not 0 - || SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_ALPHA_SIZE, 0) is not 0 - || SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_DOUBLEBUFFER, 1) is not 0) - { - throw new($"Could not set GL attributes! SDL Error: {SDL_GetError()}"); - } - // we will be turning a foreign window into an SDL window // we need this so it knows that it is capable of using OpenGL functions SDL_SetHint(SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL, "1"); @@ -58,8 +45,19 @@ private static void DebugCallback(GLEnum source, GLEnum type, int id, GLEnum sev private IntPtr _sdlWindow; private IntPtr _glContext; - private void CreateContext(int majorVersion, int minorVersion, bool coreProfile, bool forwardCompatible) + private void CreateContext(int majorVersion, int minorVersion, bool coreProfile, bool shareContext) { + // set some sensible defaults + SDL_GL_ResetAttributes(); + if (SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_RED_SIZE, 8) is not 0 + || SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_GREEN_SIZE, 8) is not 0 + || SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_BLUE_SIZE, 8) is not 0 + || SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_ALPHA_SIZE, 0) is not 0 + || SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_DOUBLEBUFFER, 1) is not 0) + { + throw new($"Could not set GL attributes! SDL Error: {SDL_GetError()}"); + } + if (SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_CONTEXT_MAJOR_VERSION, majorVersion) != 0) { throw new($"Could not set GL Major Version! SDL Error: {SDL_GetError()}"); @@ -70,13 +68,6 @@ private void CreateContext(int majorVersion, int minorVersion, bool coreProfile, throw new($"Could not set GL Minor Version! SDL Error: {SDL_GetError()}"); } - // TODO: Debug flag / debug callback with DEBUG build - if (SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_CONTEXT_FLAGS, forwardCompatible - ? (int)SDL_GLcontext.SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG : 0) != 0) - { - throw new($"Could not set GL Context Flags! SDL Error: {SDL_GetError()}"); - } - #if DEBUG_OPENGL if (SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_CONTEXT_FLAGS, (int)SDL_GLcontext.SDL_GL_CONTEXT_DEBUG_FLAG) != 0) { @@ -93,6 +84,11 @@ private void CreateContext(int majorVersion, int minorVersion, bool coreProfile, throw new($"Could not set GL profile! SDL Error: {SDL_GetError()}"); } + if (SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_SHARE_WITH_CURRENT_CONTEXT, shareContext ? 1 : 0) != 0) + { + throw new($"Could not set share context attribute! SDL Error: {SDL_GetError()}"); + } + _glContext = SDL_GL_CreateContext(_sdlWindow); if (_glContext == IntPtr.Zero) { @@ -111,7 +107,7 @@ private void CreateContext(int majorVersion, int minorVersion, bool coreProfile, #endif } - public SDL2OpenGLContext(IntPtr nativeWindowhandle, int majorVersion, int minorVersion, bool coreProfile, bool forwardCompatible) + public SDL2OpenGLContext(IntPtr nativeWindowhandle, int majorVersion, int minorVersion, bool coreProfile) { _sdlWindow = SDL_CreateWindowFrom(nativeWindowhandle); if (_sdlWindow == IntPtr.Zero) @@ -120,15 +116,10 @@ public SDL2OpenGLContext(IntPtr nativeWindowhandle, int majorVersion, int minorV } // Controls are not shared, they are the sharees - if (SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 0) != 0) - { - throw new($"Could not set share context attribute! SDL Error: {SDL_GetError()}"); - } - - CreateContext(majorVersion, minorVersion, coreProfile, forwardCompatible); + CreateContext(majorVersion, minorVersion, coreProfile, shareContext: false); } - public SDL2OpenGLContext(int majorVersion, int minorVersion, bool coreProfile, bool forwardCompatible) + public SDL2OpenGLContext(int majorVersion, int minorVersion, bool coreProfile) { _sdlWindow = SDL_CreateWindow(null, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1, 1, SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL_WindowFlags.SDL_WINDOW_HIDDEN); @@ -139,12 +130,7 @@ public SDL2OpenGLContext(int majorVersion, int minorVersion, bool coreProfile, b // offscreen contexts are shared (as we want to send texture from it over to our control's context) // make sure to set the current graphics control context before creating this context - if (SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1) != 0) - { - throw new($"Could not set share context attribute! SDL Error: {SDL_GetError()}"); - } - - CreateContext(majorVersion, minorVersion, coreProfile, forwardCompatible); + CreateContext(majorVersion, minorVersion, coreProfile, shareContext: true); } public void Dispose() diff --git a/src/BizHawk.Bizware.Graphics/OpenGL/SavedOpenGLContext.cs b/src/BizHawk.Bizware.Graphics/OpenGL/SavedOpenGLContext.cs new file mode 100644 index 00000000000..fb02200b1c1 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/OpenGL/SavedOpenGLContext.cs @@ -0,0 +1,21 @@ +using static SDL2.SDL; + +namespace BizHawk.Bizware.Graphics +{ + /// + /// Helper ref struct for tempoarily saving the current OpenGL context and restoring it + /// + public readonly ref struct SavedOpenGLContext + { + private readonly IntPtr _sdlWindow, _glContext; + + public SavedOpenGLContext() + { + _sdlWindow = SDL_GL_GetCurrentWindow(); + _glContext = SDL_GL_GetCurrentContext(); + } + + public void Dispose() + => _ = SDL_GL_MakeCurrent(_sdlWindow, _glContext); + } +} diff --git a/src/BizHawk.Bizware.Graphics/PipelineCompileArgs.cs b/src/BizHawk.Bizware.Graphics/PipelineCompileArgs.cs new file mode 100644 index 00000000000..76a5c4b29d9 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/PipelineCompileArgs.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; + +namespace BizHawk.Bizware.Graphics +{ + /// + /// Defines arguments for compiling a pipeline + /// + public class PipelineCompileArgs + { + /// + /// Defines an item within a vertex layout + /// This is currently restricted to to either 4 byte floats, or a 32 bit unsigned normalized integer type + /// If this is a 32 bit unsigned normalized type, it must have 4 components + /// + /// Name of the item + /// Number of components in the item (e.g. float2 has 2 components). Only 1-4 components is valid (unless Integer is true, then only 4 is valid) + /// Byte offset within the vertex buffer to the item + /// Semantic usage + /// Indicates if this uses an integer rather than a float + public readonly record struct VertexLayoutItem(string Name, int Components, int Offset, AttribUsage Usage, bool Integer = false); + + /// + /// Defines arguments for compiling a shader + /// This currently assumes the native shader format + /// + /// Source code for the shader + /// Entrypoint for this shader + public readonly record struct ShaderCompileArgs(string Source, string Entry); + + internal readonly IReadOnlyList VertexLayout; + internal readonly int VertexLayoutStride; + internal readonly ShaderCompileArgs VertexShaderArgs; + internal readonly ShaderCompileArgs FragmentShaderArgs; + internal readonly string FragmentOutputName; + + public PipelineCompileArgs(IReadOnlyList vertexLayoutItems, + ShaderCompileArgs vertexShaderArgs, ShaderCompileArgs fragmentShaderArgs, + string fragmentOutputName) + { + VertexLayout = vertexLayoutItems; + + foreach (var item in VertexLayout) + { + if (item.Components is < 1 or > 4) + { + throw new InvalidOperationException("A vertex layout item must have 1-4 components"); + } + + if (item.Integer && item.Components != 4) + { + throw new InvalidOperationException("A vertex layout integer item must have 4 components"); + } + + VertexLayoutStride += item.Integer ? 4 : item.Components * 4; + } + + VertexShaderArgs = vertexShaderArgs; + FragmentShaderArgs = fragmentShaderArgs; + FragmentOutputName = fragmentOutputName; + } + } +} diff --git a/src/BizHawk.Bizware.Graphics/Renderers/GDIPlusGuiRenderer.cs b/src/BizHawk.Bizware.Graphics/Renderers/GDIPlusGuiRenderer.cs index 25d0fa66e25..dfd621c31bf 100644 --- a/src/BizHawk.Bizware.Graphics/Renderers/GDIPlusGuiRenderer.cs +++ b/src/BizHawk.Bizware.Graphics/Renderers/GDIPlusGuiRenderer.cs @@ -1,13 +1,10 @@ // this is full of bugs probably, related to state from old rendering sessions being all messed up. its only barely good enough to work at all -using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Numerics; -using BizHawk.Bizware.BizwareGL; - using SDGraphics = System.Drawing.Graphics; namespace BizHawk.Bizware.Graphics @@ -28,9 +25,7 @@ public GDIPlusGuiRenderer(IGL_GDIPlus gdi) }; public void SetCornerColor(int which, Vector4 color) - { - CornerColors[which] = color; - } + => CornerColors[which] = color; /// does not have exactly 4 elements public void SetCornerColors(Vector4[] colors) @@ -49,11 +44,9 @@ public void SetCornerColors(Vector4[] colors) } public void Dispose() - { - CurrentImageAttributes?.Dispose(); - } + => CurrentImageAttributes?.Dispose(); - public void SetPipeline(Pipeline pipeline) + public void SetPipeline(IPipeline pipeline) { } @@ -62,9 +55,7 @@ public void SetDefaultPipeline() } public void SetModulateColorWhite() - { - SetModulateColor(Color.White); - } + => SetModulateColor(Color.White); private ImageAttributes CurrentImageAttributes; @@ -96,51 +87,34 @@ public void SetModulateColor(Color color) } public void EnableBlending() - { - Owner.EnableBlending(); - } + => Owner.EnableBlendNormal(); public void DisableBlending() - { - Owner.DisableBlending(); - } + => Owner.DisableBlending(); - private MatrixStack _Projection, _Modelview; + private MatrixStack _projection, _modelView; public MatrixStack Projection { - get => _Projection; + get => _projection; set { - _Projection = value; - _Projection.IsDirty = true; + _projection = value; + _projection.IsDirty = true; } } - public MatrixStack Modelview + public MatrixStack ModelView { - get => _Modelview; + get => _modelView; set { - _Modelview = value; - _Modelview.IsDirty = true; + _modelView = value; + _modelView.IsDirty = true; } } - public void Begin(Size size) - { - Begin(size.Width, size.Height); - } - public void Begin(int width, int height) - { - Begin(); - - Projection = Owner.CreateGuiProjectionMatrix(width, height); - Modelview = Owner.CreateGuiViewMatrix(width, height); - } - - public void Begin() { // uhhmmm I want to throw an exception if its already active, but its annoying. IsActive = true; @@ -148,8 +122,11 @@ public void Begin() CurrentImageAttributes?.Dispose(); CurrentImageAttributes = new(); - Modelview?.Clear(); + ModelView?.Clear(); Projection?.Clear(); + + Projection = Owner.CreateGuiProjectionMatrix(width, height); + ModelView = Owner.CreateGuiViewMatrix(width, height); } public void Flush() @@ -170,22 +147,15 @@ public void End() CurrentImageAttributes = null; } - public void RectFill(float x, float y, float w, float h) - { - } - - public void DrawSubrect(Texture2d tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1) + public void DrawSubrect(ITexture2D tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1) { - var gtex = (GDIPlusTexture)tex.Opaque; var g = _gdi.GetCurrentGraphics(); - PrepDraw(g, tex); - SetupMatrix(g); + var tex2d = (GDIPlusTexture2D)tex; + // TODO - we can support bicubic for the final presentation... + g.InterpolationMode = tex2d.LinearFiltering ? InterpolationMode.Bilinear : InterpolationMode.NearestNeighbor; - var x0 = u0 * tex.Width; - var y0 = v0 * tex.Height; - var x1 = u1 * tex.Width; - var y1 = v1 * tex.Height; + SetupMatrix(g); PointF[] destPoints = { @@ -194,90 +164,24 @@ public void DrawSubrect(Texture2d tex, float x, float y, float w, float h, float new(x, y + h), }; - g.DrawImage(gtex.SDBitmap, destPoints, new(x0, y0, x1 - x0, y1 - y0), GraphicsUnit.Pixel, CurrentImageAttributes); - g.Transform = new(); // .Reset() doesnt work? - } - - public void Draw(Art art) { DrawInternal(art, 0, 0, art.Width, art.Height, false, false); } - public void Draw(Art art, float x, float y) { DrawInternal(art, x, y, art.Width, art.Height, false, false); } - public void Draw(Art art, float x, float y, float width, float height) { DrawInternal(art, x, y, width, height, false, false); } - public void Draw(Art art, Vector2 pos) { DrawInternal(art, pos.X, pos.Y, art.Width, art.Height, false, false); } - public void Draw(Texture2d tex) { DrawInternal(tex, 0, 0, tex.Width, tex.Height); } - public void Draw(Texture2d tex, float x, float y) { DrawInternal(tex, x, y, tex.Width, tex.Height); } - public void DrawFlipped(Art art, bool xflip, bool yflip) { DrawInternal(art, 0, 0, art.Width, art.Height, xflip, yflip); } - - public void Draw(Texture2d art, float x, float y, float width, float height) - { - DrawInternal(art, x, y, width, height); - } - - private static void PrepDraw(SDGraphics g, Texture2d tex) - { - var tw = (GDIPlusTexture)tex.Opaque; - - // TODO - we can support bicubic for the final presentation... - if ((int)tw.MagFilter != (int)tw.MinFilter) - { - throw new InvalidOperationException($"{nameof(tw)}.{nameof(tw.MagFilter)} != {nameof(tw)}.{nameof(tw.MinFilter)}"); - } + var x0 = u0 * tex.Width; + var y0 = v0 * tex.Height; + var x1 = u1 * tex.Width; + var y1 = v1 * tex.Height; - g.InterpolationMode = tw.MagFilter switch - { - TextureMagFilter.Linear => InterpolationMode.Bilinear, - TextureMagFilter.Nearest => InterpolationMode.NearestNeighbor, - _ => g.InterpolationMode - }; + g.PixelOffsetMode = PixelOffsetMode.Half; + g.DrawImage(tex2d.SDBitmap, destPoints, new(x0, y0, x1 - x0, y1 - y0), GraphicsUnit.Pixel, CurrentImageAttributes); + g.Transform = new(); // .Reset() doesnt work? } private void SetupMatrix(SDGraphics g) { // projection is always identity, so who cares i guess // var mat = Projection.Top * Modelview.Top; - var mat = Modelview.Top; + var mat = ModelView.Top; g.Transform = new(mat.M11, mat.M12, mat.M21, mat.M22, mat.M41, mat.M42); } - private void DrawInternal(Art art, float x, float y, float w, float h) - { - DrawInternal(art.BaseTexture, x, y, w, h, art.u0, art.v0, art.u1, art.v1); - } - - private void DrawInternal(Texture2d tex, float x, float y, float w, float h) - { - DrawInternal(tex, x, y, w, h, 0, 0, 1, 1); - } - - private void DrawInternal(Texture2d tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1) - { - var g = _gdi.GetCurrentGraphics(); - PrepDraw(g, tex); - - SetupMatrix(g); - - PointF[] destPoints = - { - new(x, y), - new(x+w, y), - new(x, y+h), - }; - - var sx = tex.Width * u0; - var sy = tex.Height * v0; - var sx2 = tex.Width * u1; - var sy2 = tex.Height * v1; - var sw = sx2 - sx; - var sh = sy2 - sy; - - var gtex = (GDIPlusTexture)tex.Opaque; - g.PixelOffsetMode = PixelOffsetMode.Half; - g.DrawImage(gtex.SDBitmap, destPoints, new(sx, sy, sw, sh), GraphicsUnit.Pixel, CurrentImageAttributes); - g.Transform = new(); // .Reset() doesn't work ? ? - } - - private static void DrawInternal(Art art, float x, float y, float w, float h, bool fx, bool fy) - { - } - public bool IsActive { get; private set; } public IGL Owner => _gdi; diff --git a/src/BizHawk.Bizware.Graphics/Renderers/GuiRenderer.cs b/src/BizHawk.Bizware.Graphics/Renderers/GuiRenderer.cs index 0d5df3a2bf3..e9781a46f5b 100644 --- a/src/BizHawk.Bizware.Graphics/Renderers/GuiRenderer.cs +++ b/src/BizHawk.Bizware.Graphics/Renderers/GuiRenderer.cs @@ -1,50 +1,53 @@ //http://stackoverflow.com/questions/6893302/decode-rgb-value-to-single-float-without-bit-shift-in-glsl -using System; using System.Drawing; using System.Numerics; -using BizHawk.Bizware.BizwareGL; - namespace BizHawk.Bizware.Graphics { /// /// A simple renderer useful for rendering GUI stuff. /// When doing GUI rendering, run everything through here (if you need a GL feature not done through here, run it through here first) - /// Call Begin, then draw, then End, and don't use other Renderers or GL calls in the meantime, unless you know what you're doing. + /// Call Begin, then Draw, then End, and don't use other Renderers or GL calls in the meantime, unless you know what you're doing. /// This can perform batching (well.. maybe not yet), which is occasionally necessary for drawing large quantities of things. /// - public class GuiRenderer : IDisposable, IGuiRenderer + public class GuiRenderer : IGuiRenderer { public GuiRenderer(IGL owner) { Owner = owner; - VertexLayout = owner.CreateVertexLayout(); - VertexLayout.DefineVertexAttribute("aPosition", 0, 2, VertexAttribPointerType.Float, AttribUsage.Position, false, 32); - VertexLayout.DefineVertexAttribute("aTexcoord", 1, 2, VertexAttribPointerType.Float, AttribUsage.Texcoord0, false, 32, 8); - VertexLayout.DefineVertexAttribute("aColor", 2, 4, VertexAttribPointerType.Float, AttribUsage.Texcoord1, false, 32, 16); - VertexLayout.Close(); - - _Projection = new(); - _Modelview = new(); + _projection = new(); + _modelView = new(); string psProgram, vsProgram; - if (owner.API == "D3D9") - { - vsProgram = DefaultShader_d3d9; - psProgram = DefaultShader_d3d9; - } - else + // ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault + switch (owner.DispMethodEnum) { - vsProgram = DefaultVertexShader_gl; - psProgram = DefaultPixelShader_gl; + case EDispMethod.D3D11: + vsProgram = DefaultVertexShader_d3d11; + psProgram = DefaultPixelShader_d3d11; + break; + case EDispMethod.OpenGL: + vsProgram = DefaultVertexShader_gl; + psProgram = DefaultPixelShader_gl; + break; + default: + throw new InvalidOperationException(); } - var vs = Owner.CreateVertexShader(vsProgram, "vsmain", true); - var ps = Owner.CreateFragmentShader(psProgram, "psmain", true); - CurrPipeline = DefaultPipeline = Owner.CreatePipeline(VertexLayout, vs, ps, true, "xgui"); + var vertexLayoutItems = new PipelineCompileArgs.VertexLayoutItem[3]; + vertexLayoutItems[0] = new("aPosition", 2, 0, AttribUsage.Position); + vertexLayoutItems[1] = new("aTexcoord", 2, 8, AttribUsage.Texcoord0); + vertexLayoutItems[2] = new("aColor", 4, 16, AttribUsage.Texcoord1); + + var compileArgs = new PipelineCompileArgs( + vertexLayoutItems, + vertexShaderArgs: new(vsProgram, "vsmain"), + fragmentShaderArgs: new(psProgram, "psmain"), + fragmentOutputName: "FragColor"); + CurrPipeline = DefaultPipeline = Owner.CreatePipeline(compileArgs); } private readonly Vector4[] CornerColors = @@ -57,15 +60,20 @@ public GuiRenderer(IGL owner) public void SetCornerColor(int which, Vector4 color) { - Flush(); //don't really need to flush with current implementation. we might as well roll modulate color into it too. + Flush(); // don't really need to flush with current implementation. we might as well roll modulate color into it too. CornerColors[which] = color; } /// does not have exactly 4 elements public void SetCornerColors(Vector4[] colors) { - Flush(); //don't really need to flush with current implementation. we might as well roll modulate color into it too. - if (colors.Length != 4) throw new ArgumentException("array must be size 4", nameof(colors)); + Flush(); // don't really need to flush with current implementation. we might as well roll modulate color into it too. + + if (colors.Length != 4) + { + throw new ArgumentException("array must be size 4", nameof(colors)); + } + for (var i = 0; i < 4; i++) { CornerColors[i] = colors[i]; @@ -73,22 +81,19 @@ public void SetCornerColors(Vector4[] colors) } public void Dispose() - { - DefaultPipeline.Dispose(); - VertexLayout.Release(); - } + => DefaultPipeline.Dispose(); /// is - public void SetPipeline(Pipeline pipeline) + public void SetPipeline(IPipeline pipeline) { if (IsActive) + { throw new InvalidOperationException("Can't change pipeline while renderer is running!"); + } Flush(); CurrPipeline = pipeline; - // clobber state cache - sTexture = null; // save the modulate color? user beware, I guess, for now. } @@ -105,13 +110,13 @@ public void SetModulateColorWhite() public void SetModulateColor(Color color) { Flush(); - CurrPipeline["uModulateColor"].Set(new Vector4(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, color.A / 255.0f)); + CurrPipeline.SetUniform("uModulateColor", new Vector4(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, color.A / 255.0f)); } public void EnableBlending() { Flush(); - Owner.EnableBlending(); + Owner.EnableBlendNormal(); } public void DisableBlending() @@ -120,43 +125,30 @@ public void DisableBlending() Owner.DisableBlending(); } - private MatrixStack _Projection, _Modelview; + private MatrixStack _projection, _modelView; + public MatrixStack Projection { - get => _Projection; + get => _projection; set { - _Projection = value; - _Projection.IsDirty = true; + _projection = value; + _projection.IsDirty = true; } } - public MatrixStack Modelview + + public MatrixStack ModelView { - get => _Modelview; + get => _modelView; set { - _Modelview = value; - _Modelview.IsDirty = true; + _modelView = value; + _modelView.IsDirty = true; } } - public void Begin(Size size) - { - Begin(size.Width, size.Height); - } - - public void Begin(int width, int height) - { - Begin(); - - Projection = Owner.CreateGuiViewMatrix(width, height) * Owner.CreateGuiProjectionMatrix(width, height); - Modelview.Clear(); - - Owner.SetViewport(width, height); - } - /// no pipeline set (need to call ) - public void Begin() + public void Begin(int width, int height) { // uhhmmm I want to throw an exception if its already active, but its annoying. @@ -169,14 +161,17 @@ public void Begin() Owner.BindPipeline(CurrPipeline); Owner.DisableBlending(); - //clear state cache - sTexture = null; - CurrPipeline["uSamplerEnable"].Set(false); - Modelview.Clear(); + // clear state cache + CurrPipeline.SetUniform("uSamplerEnable", false); + ModelView.Clear(); Projection.Clear(); SetModulateColorWhite(); - } + Projection = Owner.CreateGuiViewMatrix(width, height) * Owner.CreateGuiProjectionMatrix(width, height); + ModelView.Clear(); + + Owner.SetViewport(width, height); + } public void Flush() { @@ -194,133 +189,27 @@ public void End() IsActive = false; } - public void RectFill(float x, float y, float w, float h) - { - PrepDrawSubrectInternal(null); - EmitRectangleInternal(x, y, w, h, 0, 0, 0, 0); - } - - - public void DrawSubrect(Texture2d tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1) - { - DrawSubrectInternal(tex, x, y, w, h, u0, v0, u1, v1); - } - - public void Draw(Art art) - { - DrawInternal(art, 0, 0, art.Width, art.Height, false, false); - } - - public void Draw(Art art, float x, float y) + public void DrawSubrect(ITexture2D tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1) { - DrawInternal(art, x, y, art.Width, art.Height, false, false); - } - - public void Draw(Art art, float x, float y, float width, float height) - { - DrawInternal(art, x, y, width, height, false, false); - } - - public void Draw(Art art, Vector2 pos) - { - DrawInternal(art, pos.X, pos.Y, art.Width, art.Height, false, false); - } - - public void Draw(Texture2d tex) - { - DrawInternal(tex, 0, 0, tex.Width, tex.Height); - } - - public void Draw(Texture2d tex, float x, float y) - { - DrawInternal(tex, x, y, tex.Width, tex.Height); - } - - public void DrawFlipped(Art art, bool xflip, bool yflip) - { - DrawInternal(art, 0, 0, art.Width, art.Height, xflip, yflip); - } - - public void Draw(Texture2d art, float x, float y, float width, float height) - { - DrawInternal(art, x, y, width, height); - } - - private void DrawInternal(Texture2d tex, float x, float y, float w, float h) - { - var art = new Art((ArtManager)null) - { - Width = w, - Height = h - }; - - art.u0 = art.v0 = 0; - art.u1 = art.v1 = 1; - art.BaseTexture = tex; - - DrawInternal(art, x, y, w, h, false, tex.IsUpsideDown); + PrepDrawSubrectInternal(tex); + EmitRectangleInternal(x, y, w, h, u0, v0, u1, v1); } - private unsafe void DrawInternal(Art art, float x, float y, float w, float h, bool fx, bool fy) + private void PrepDrawSubrectInternal(ITexture2D tex) { - float u0, v0, u1, v1; - - if (fx) - { - u0 = art.u1; - u1 = art.u0; - } - else - { - u0 = art.u0; - u1 = art.u1; - } - - if (fy) - { - v0 = art.v1; - v1 = art.v0; - } - else - { - v0 = art.v0; - v1 = art.v1; - } + CurrPipeline.SetUniformSampler("uSampler0", tex); + CurrPipeline.SetUniform("uSamplerEnable", tex != null); - var data = stackalloc float[32] + if (_projection.IsDirty) { - x, y, u0, v0, - CornerColors[0].X, CornerColors[0].Y, CornerColors[0].Z, CornerColors[0].W, - x + w, y, u1, v0, - CornerColors[1].X, CornerColors[1].Y, CornerColors[1].Z, CornerColors[1].W, - x, y + h, u0, v1, - CornerColors[2].X, CornerColors[2].Y, CornerColors[2].Z, CornerColors[2].W, - x + w, y + h, u1, v1, - CornerColors[3].X, CornerColors[3].Y, CornerColors[3].Z, CornerColors[3].W, - }; - - PrepDrawSubrectInternal(art.BaseTexture); - Owner.Draw(new(data), 4); - } - - private void PrepDrawSubrectInternal(Texture2d tex) - { - if (sTexture != tex) - { - sTexture = tex; - CurrPipeline["uSampler0"].Set(tex); - CurrPipeline["uSamplerEnable"].Set(tex != null); + CurrPipeline.SetUniformMatrix("um44Projection", ref _projection.Top); + _projection.IsDirty = false; } - if (_Projection.IsDirty) - { - CurrPipeline["um44Projection"].Set(ref _Projection.Top); - _Projection.IsDirty = false; - } - if (_Modelview.IsDirty) + if (_modelView.IsDirty) { - CurrPipeline["um44Modelview"].Set(ref _Modelview.Top); - _Modelview.IsDirty = false; + CurrPipeline.SetUniformMatrix("um44Modelview", ref _modelView.Top); + _modelView.IsDirty = false; } } @@ -360,37 +249,23 @@ private unsafe void EmitRectangleInternal(float x, float y, float w, float h, fl pData[30] = CornerColors[3].Z; pData[31] = CornerColors[3].W; - Owner.Draw(new(pData), 4); - } - - private void DrawSubrectInternal(Texture2d tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1) - { - PrepDrawSubrectInternal(tex); - EmitRectangleInternal(x, y, w, h, u0, v0, u1, v1); + CurrPipeline.SetVertexData(new(pData), 4); + Owner.Draw(4); } public bool IsActive { get; private set; } public IGL Owner { get; } - private readonly VertexLayout VertexLayout; - private Pipeline CurrPipeline; - private readonly Pipeline DefaultPipeline; - - // state cache - private Texture2d sTexture; + private IPipeline CurrPipeline; + private readonly IPipeline DefaultPipeline; // shaders are hand-coded for each platform to make sure they stay as fast as possible - public const string DefaultShader_d3d9 = @" + public const string DefaultVertexShader_d3d11 = @" //vertex shader uniforms float4x4 um44Modelview, um44Projection; float4 uModulateColor; -//pixel shader uniforms -bool uSamplerEnable; -texture2D texture0, texture1; -sampler uSampler0 = sampler_state { Texture = (texture0); }; - struct VS_INPUT { float2 aPosition : POSITION; @@ -400,13 +275,7 @@ struct VS_INPUT struct VS_OUTPUT { - float4 vPosition : POSITION; - float2 vTexcoord0 : TEXCOORD0; - float4 vCornerColor : COLOR0; -}; - -struct PS_INPUT -{ + float4 vPosition : SV_POSITION; float2 vTexcoord0 : TEXCOORD0; float4 vCornerColor : COLOR0; }; @@ -420,27 +289,41 @@ VS_OUTPUT vsmain(VS_INPUT src) dst.vCornerColor = src.aColor * uModulateColor; return dst; } +"; -float4 psmain(PS_INPUT src) : COLOR + public const string DefaultPixelShader_d3d11 = @" +//pixel shader uniforms +bool uSamplerEnable; +Texture2D texture0; +sampler uSampler0; + +struct PS_INPUT +{ + float4 vPosition : SV_POSITION; + float2 vTexcoord0 : TEXCOORD0; + float4 vCornerColor : COLOR0; +}; + +float4 psmain(PS_INPUT src) : SV_Target { float4 temp = src.vCornerColor; - if(uSamplerEnable) temp *= tex2D(uSampler0,src.vTexcoord0); + if(uSamplerEnable) temp *= texture0.Sample(uSampler0,src.vTexcoord0); return temp; } "; public const string DefaultVertexShader_gl = @" -//opengl 2.0 ~ 2004 -#version 110 +//opengl 3.2 +#version 150 uniform mat4 um44Modelview, um44Projection; uniform vec4 uModulateColor; -attribute vec2 aPosition; -attribute vec2 aTexcoord; -attribute vec4 aColor; +in vec2 aPosition; +in vec2 aTexcoord; +in vec4 aColor; -varying vec2 vTexcoord0; -varying vec4 vCornerColor; +out vec2 vTexcoord0; +out vec4 vCornerColor; void main() { @@ -451,20 +334,22 @@ void main() }"; public const string DefaultPixelShader_gl = @" -//opengl 2.0 ~ 2004 -#version 110 +//opengl 3.2 +#version 150 uniform bool uSamplerEnable; uniform sampler2D uSampler0; -varying vec2 vTexcoord0; -varying vec4 vCornerColor; +in vec2 vTexcoord0; +in vec4 vCornerColor; + +out vec4 FragColor; void main() { vec4 temp = vCornerColor; - if(uSamplerEnable) temp *= texture2D(uSampler0,vTexcoord0); - gl_FragColor = temp; + if(uSamplerEnable) temp *= texture(uSampler0,vTexcoord0); + FragColor = temp; }"; } -} \ No newline at end of file +} diff --git a/src/BizHawk.Bizware.Graphics/Renderers/ImGui2DRenderer.cs b/src/BizHawk.Bizware.Graphics/Renderers/ImGui2DRenderer.cs new file mode 100644 index 00000000000..32f115eb4a5 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/Renderers/ImGui2DRenderer.cs @@ -0,0 +1,552 @@ +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.Drawing.Text; +using System.Numerics; +using System.Runtime.InteropServices; + +using ImGuiNET; + +using BizHawk.Common; +using BizHawk.Common.CollectionExtensions; + +using SDGraphics = System.Drawing.Graphics; + +namespace BizHawk.Bizware.Graphics +{ + /// + /// Wraps ImGui to create a simple 2D renderer + /// + internal class ImGui2DRenderer : I2DRenderer + { + // ImDrawListSharedData is defined in imgui_internal.h, and therefore it is not exposed in ImGuiNET + // we want to use it directly however, and cimgui does give exports for it + + [StructLayout(LayoutKind.Sequential)] + private struct ImDrawListSharedData + { + public Vector2 TexUvWhitePixel; + public IntPtr Font; + public float FontSize; + public float CurveTessellationTol; + // other fields are present, but we don't care about them + } + + [DllImport("cimgui", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + private static extern unsafe ImDrawListSharedData* ImDrawListSharedData_ImDrawListSharedData(); + + [DllImport("cimgui", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + private static extern unsafe void ImDrawListSharedData_SetCircleTessellationMaxError(ImDrawListSharedData* self, float max_error); + + private static readonly unsafe ImDrawListSharedData* _drawListSharedData; + + static ImGui2DRenderer() + { + unsafe + { + _drawListSharedData = ImDrawListSharedData_ImDrawListSharedData(); + // values taken from default ImGuiStyle + _drawListSharedData->CurveTessellationTol = 1.25f; + ImDrawListSharedData_SetCircleTessellationMaxError(_drawListSharedData, 0.3f); + } + } + + private readonly HashSet _gcHandles = [ ]; + + protected virtual float RenderThickness => 1; + + protected readonly IGL _igl; + protected readonly ImGuiResourceCache _resourceCache; + protected ImDrawListPtr _imGuiDrawList; + protected bool _hasDrawStringCommand; + protected bool _hasClearPending; + protected Bitmap _stringOutput; + protected SDGraphics _stringGraphics; + protected IRenderTarget _renderTarget; + + public ImGui2DRenderer(IGL igl, ImGuiResourceCache resourceCache) + { + _igl = igl; + _resourceCache = resourceCache; + + unsafe + { + _imGuiDrawList = ImGuiNative.ImDrawList_ImDrawList((IntPtr)_drawListSharedData); + } + + _pendingBlendEnable = true; + ResetDrawList(); + } + + public void Dispose() + { + ClearGCHandles(); + _renderTarget?.Dispose(); + _renderTarget = null; + _stringGraphics?.Dispose(); + _stringGraphics = null; + _stringOutput?.Dispose(); + _stringOutput = null; + _imGuiDrawList.Destroy(); + _imGuiDrawList = IntPtr.Zero; + } + + private void ClearStringOutput() + { + var bmpData = _stringOutput.LockBits(new(0, 0, _stringOutput.Width, _stringOutput.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); + Util.UnsafeSpanFromPointer(ptr: bmpData.Scan0, length: bmpData.Stride * bmpData.Height).Clear(); + _stringOutput.UnlockBits(bmpData); + } + + private void ClearGCHandles() + { + foreach (var gcHandle in _gcHandles) + { + switch (gcHandle.Target) + { + // we can't actually dispose this, as the bitmap might still be cached within GuiApi + // it doesn't matter too much, as the finalizer would also dispose this, so no memory leaks will occur +#if false + case ImGuiUserTexture userTexture: + // only dispose anything not cached somewhere + if (userTexture.Bitmap != _stringOutput + && !_resourceCache.TextureCache.ContainsKey(userTexture.Bitmap)) + { + userTexture.Bitmap.Dispose(); + } + break; +#endif + case DrawStringArgs args: + args.Font.Dispose(); + break; + } + + gcHandle.Free(); + } + + _gcHandles.Clear(); + } + + private void ResetDrawList() + { + ClearGCHandles(); + _imGuiDrawList._ResetForNewFrame(); + _imGuiDrawList.Flags |= ImDrawListFlags.AllowVtxOffset; + _hasDrawStringCommand = false; + EnableBlending = _pendingBlendEnable; + } + + protected class ImGuiUserTexture + { + public Bitmap Bitmap; + public bool WantCache; + } + + protected class DrawStringArgs + { + public string Str; + public Font Font; + public Color Color; + public float X, Y; + public StringFormat Format; + public TextRenderingHint TextRenderingHint; + } + + protected enum DrawCallbackId + { + None, + DisableBlending, + EnableBlendAlpha, + EnableBlendNormal, + DrawString, + } + + protected virtual void RenderInternal(int width, int height) + { + if (EnableBlending) + { + _igl.EnableBlendAlpha(); + } + else + { + _igl.DisableBlending(); + } + + _igl.BindPipeline(_resourceCache.Pipeline); + _resourceCache.SetProjection(width, height); + + if (_imGuiDrawList.VtxBuffer.Size > 0) + { + _resourceCache.Pipeline.SetVertexData(_imGuiDrawList.VtxBuffer.Data, _imGuiDrawList.VtxBuffer.Size); + } + + if (_imGuiDrawList.IdxBuffer.Size > 0) + { + _resourceCache.Pipeline.SetIndexData(_imGuiDrawList.IdxBuffer.Data, _imGuiDrawList.IdxBuffer.Size); + } + + var cmdBuffer = _imGuiDrawList.CmdBuffer; + for (var i = 0; i < cmdBuffer.Size; i++) + { + var cmd = cmdBuffer[i]; + var callbackId = (DrawCallbackId)cmd.UserCallback; + switch (callbackId) + { + case DrawCallbackId.None: + { + var texId = cmd.GetTexID(); + ITexture2D tempTex = null; + if (texId != IntPtr.Zero) + { + var userTex = (ImGuiUserTexture)GCHandle.FromIntPtr(texId).Target!; + if (userTex.WantCache && _resourceCache.TextureCache.TryGetValue(userTex.Bitmap, out var cachedTexture)) + { + _resourceCache.SetTexture(cachedTexture); + } + else + { + tempTex = _igl.LoadTexture(userTex.Bitmap); + _resourceCache.SetTexture(tempTex); + if (userTex.WantCache) + { + _resourceCache.TextureCache.Add(userTex.Bitmap, tempTex); + tempTex = null; + } + } + } + else + { + _resourceCache.SetTexture(null); + } + + _igl.DrawIndexed((int)cmd.ElemCount, (int)cmd.IdxOffset, (int)cmd.VtxOffset); + tempTex?.Dispose(); + break; + } + case DrawCallbackId.DisableBlending: + _igl.DisableBlending(); + break; + case DrawCallbackId.EnableBlendAlpha: + _igl.EnableBlendAlpha(); + break; + case DrawCallbackId.EnableBlendNormal: + _igl.EnableBlendNormal(); + break; + case DrawCallbackId.DrawString: + { + var stringArgs = (DrawStringArgs)GCHandle.FromIntPtr(cmd.UserCallbackData).Target!; + var brush = _resourceCache.BrushCache.GetValueOrPutNew1(stringArgs.Color); + _stringGraphics.TextRenderingHint = stringArgs.TextRenderingHint; + _stringGraphics.DrawString(stringArgs.Str, stringArgs.Font, brush, stringArgs.X, stringArgs.Y, stringArgs.Format); + break; + } + default: + throw new InvalidOperationException(); + } + } + } + + public ITexture2D Render(int width, int height) + { + var needsRender = _imGuiDrawList.VtxBuffer.Size > 0 || _imGuiDrawList.IdxBuffer.Size > 0 || _hasDrawStringCommand; + var needsClear = needsRender || _hasClearPending; + if (_renderTarget == null || _renderTarget.Width != width || _renderTarget.Height != height) + { + _renderTarget?.Dispose(); + _renderTarget = _igl.CreateRenderTarget(width, height); + needsClear = true; + } + + if (_hasDrawStringCommand + && (_stringOutput == null + || _stringOutput.Width != width + || _stringOutput.Height != height)) + { + _stringGraphics?.Dispose(); + _stringOutput?.Dispose(); + _stringOutput = new(width, height, PixelFormat.Format32bppArgb); + _stringGraphics = SDGraphics.FromImage(_stringOutput); + } + + _renderTarget.Bind(); + _igl.SetViewport(width, height); + + if (needsClear) + { + _igl.ClearColor(Color.FromArgb(0)); + _hasClearPending = false; + } + + if (needsRender) + { + if (_hasDrawStringCommand) + { + ClearStringOutput(); + // synthesize an add image command for our string bitmap + if (!_pendingBlendEnable) + { + // always normal blend the string (it covers the entire image, if it was alpha that'd obscure everything else) + _imGuiDrawList.AddCallback((IntPtr)DrawCallbackId.EnableBlendNormal, IntPtr.Zero); + } + DrawImage(_stringOutput, 0, 0); + } + + _imGuiDrawList._PopUnusedDrawCmd(); + RenderInternal(width, height); + ResetDrawList(); + } + + return _renderTarget; + } + + public void Clear() + { + ResetDrawList(); + _hasClearPending = true; + } + + public void Discard() + => ResetDrawList(); + + protected bool EnableBlending { get; private set; } + private bool _pendingBlendEnable; + + public CompositingMode CompositingMode + { + set + { + switch (_pendingBlendEnable) + { + // CompositingMode.SourceCopy means disable blending + case true when value == CompositingMode.SourceCopy: + _imGuiDrawList.AddCallback((IntPtr)DrawCallbackId.DisableBlending, IntPtr.Zero); + _pendingBlendEnable = false; + break; + // CompositingMode.SourceOver means enable blending + case false when value == CompositingMode.SourceOver: + _imGuiDrawList.AddCallback((IntPtr)DrawCallbackId.EnableBlendAlpha, IntPtr.Zero); + _pendingBlendEnable = true; + break; + } + } + } + + public void DrawBezier(Color color, Point pt1, Point pt2, Point pt3, Point pt4) + { + _imGuiDrawList.AddBezierCubic( + p1: pt1.ToVector(), + p2: pt2.ToVector(), + p3: pt3.ToVector(), + p4: pt4.ToVector(), + col: (uint)color.ToArgb(), + thickness: RenderThickness); + } + + public void DrawBeziers(Color color, Point[] points) + { + if (points.Length < 4 || (points.Length - 1) % 3 != 0) + { + throw new InvalidOperationException("Invalid number of points"); + } + + var startPt = points[0]; + var col = (uint)color.ToArgb(); + for (var i = 1; i < points.Length; i += 3) + { + _imGuiDrawList.AddBezierCubic( + p1: startPt.ToVector(), + p2: points[i + 0].ToVector(), + p3: points[i + 1].ToVector(), + p4: points[i + 2].ToVector(), + col: col, + thickness: RenderThickness); + startPt = points[i + 2]; + } + } + + public void DrawRectangle(Color color, int x, int y, int width, int height) + { + // we don't use AddRect as we want to avoid double drawing at the corners + // as that produces artifacts with alpha blending + + // keep in mind width/height include the beginning pixel + // e.g. a 1x1 rect has the same coordinate for all corners, so you don't + 1, you + 1 - 1 + var right = x + width - 1; + var bottom = y + height - 1; + + // top left to top right + DrawLine(color, x, y, right, y); + // top right (and 1 pixel down) to bottom right + DrawLine(color, right, y + 1, right, bottom); + // bottom right (and 1 pixel left) to bottom left + DrawLine(color, right - 1, bottom, x, bottom); + // bottom left (and 1 pixel up) to top left (and 1 pixel down) + DrawLine(color, x, bottom - 1, x, y + 1); + } + + public void FillRectangle(Color color, int x, int y, int width, int height) + { + _imGuiDrawList.AddRectFilled( + p_min: new(x, y), + p_max: new(x + width, y + height), + col: (uint)color.ToArgb()); + } + + public void DrawEllipse(Color color, int x, int y, int width, int height) + { + var radius = new Vector2(width / 2.0f, height / 2.0f); + _imGuiDrawList.AddEllipse( + center: new(x + radius.X, y + radius.Y), + radius: radius, + col: (uint)color.ToArgb(), + rot: 0, + num_segments: 0, + RenderThickness); + } + + public void FillEllipse(Color color, int x, int y, int width, int height) + { + var radius = new Vector2(width / 2.0f, height / 2.0f); + _imGuiDrawList.AddEllipseFilled( + center: new(x + radius.X, y + radius.Y), + radius: radius, + col: (uint)color.ToArgb()); + } + + public void DrawImage(Bitmap image, int x, int y) + { + // use normal blending for images + if (_pendingBlendEnable) + { + _imGuiDrawList.AddCallback((IntPtr)DrawCallbackId.EnableBlendNormal, IntPtr.Zero); + } + + var texture = new ImGuiUserTexture { Bitmap = image, WantCache = false }; + var handle = GCHandle.Alloc(texture, GCHandleType.Normal); + _gcHandles.Add(handle); + _imGuiDrawList.AddImage( + user_texture_id: GCHandle.ToIntPtr(handle), + p_min: new(x, y), + p_max: new(x + image.Width, y + image.Height)); + + if (_pendingBlendEnable) + { + _imGuiDrawList.AddCallback((IntPtr)DrawCallbackId.EnableBlendAlpha, IntPtr.Zero); + } + } + + public void DrawImage(Bitmap image, Rectangle destRect, int srcX, int srcY, int srcWidth, int srcHeight, bool cache) + { + // use normal blending for images + if (_pendingBlendEnable) + { + _imGuiDrawList.AddCallback((IntPtr)DrawCallbackId.EnableBlendNormal, IntPtr.Zero); + } + + var texture = new ImGuiUserTexture { Bitmap = image, WantCache = cache }; + var handle = GCHandle.Alloc(texture, GCHandleType.Normal); + _gcHandles.Add(handle); + var imgWidth = (float)image.Width; + var imgHeight = (float)image.Height; + _imGuiDrawList.AddImage( + user_texture_id: GCHandle.ToIntPtr(handle), + p_min: new(destRect.Left, destRect.Top), + p_max: new(destRect.Right, destRect.Bottom), + uv_min: new(srcX / imgWidth, srcY / imgHeight), + uv_max: new((srcX + srcWidth) / imgWidth, (srcY + srcHeight) / imgHeight)); + + if (_pendingBlendEnable) + { + _imGuiDrawList.AddCallback((IntPtr)DrawCallbackId.EnableBlendAlpha, IntPtr.Zero); + } + } + + public void DrawLine(Color color, int x1, int y1, int x2, int y2) + { + var p1 = new Vector2(x1, y1); + var p2 = new Vector2(x2, y2); + + if (p1.X > p2.X) + { + p1.X += 0.5f; + } + else + { + p2.X += 0.5f; + } + + if (p1.Y > p2.Y) + { + p1.Y += 0.5f; + } + else + { + p2.Y += 0.5f; + } + + _imGuiDrawList.AddLine( + p1: p1, + p2: p2, + col: (uint)color.ToArgb(), + thickness: RenderThickness); + } + + public void DrawPie(Color color, int x, int y, int width, int height, int startAngle, int sweepAngle) + { + var radius = new Vector2(width / 2.0f, height / 2.0f); + var center = new Vector2(x + radius.X, y + radius.Y); + var aMin = (float)(Math.PI / 180 * startAngle); + var aMax = (float)(Math.PI / 180 * (startAngle + sweepAngle)); + _imGuiDrawList.PathEllipticalArcTo(center, radius, 0, aMin, aMax); + _imGuiDrawList.PathLineTo(center); + _imGuiDrawList.PathStroke((uint)color.ToArgb(), ImDrawFlags.Closed, RenderThickness); + } + + public void FillPie(Color color, int x, int y, int width, int height, int startAngle, int sweepAngle) + { + var radius = new Vector2(width / 2.0f, height / 2.0f); + var center = new Vector2(x + radius.X, y + radius.Y); + var aMin = (float)(Math.PI / 180 * startAngle); + var aMax = (float)(Math.PI / 180 * (startAngle + sweepAngle)); + _imGuiDrawList.PathEllipticalArcTo(center, radius, 0, aMin, aMax); + _imGuiDrawList.PathLineTo(center); + _imGuiDrawList.PathFillConvex((uint)color.ToArgb()); + } + + public unsafe void DrawPolygon(Color color, Point[] points) + { + var vectorPoints = Array.ConvertAll(points, static p => new Vector2(p.X + 0.5f, p.Y + 0.5f)); + fixed (Vector2* p = vectorPoints) + { + _imGuiDrawList.AddPolyline( + points: ref *p, + num_points: vectorPoints.Length, + col: (uint)color.ToArgb(), + flags: ImDrawFlags.Closed, + thickness: RenderThickness); + } + } + + public unsafe void FillPolygon(Color color, Point[] points) + { + var vectorPoints = Array.ConvertAll(points, static p => new Vector2(p.X + 0.5f, p.Y + 0.5f)); + fixed (Vector2* p = vectorPoints) + { + _imGuiDrawList.AddConcavePolyFilled( + points: ref *p, + num_points: vectorPoints.Length, + col: (uint)color.ToArgb()); + } + } + + public void DrawString(string s, Font font, Color color, float x, float y, StringFormat format, TextRenderingHint textRenderingHint) + { + var stringArgs = new DrawStringArgs { Str = s, Font = font, Color = color, X = x, Y = y, Format = format, TextRenderingHint = textRenderingHint }; + var handle = GCHandle.Alloc(stringArgs, GCHandleType.Normal); + _gcHandles.Add(handle); + _imGuiDrawList.AddCallback((IntPtr)DrawCallbackId.DrawString, GCHandle.ToIntPtr(handle)); + _hasDrawStringCommand = true; + } + } +} diff --git a/src/BizHawk.Bizware.Graphics/Renderers/SDLImGui2DRenderer.cs b/src/BizHawk.Bizware.Graphics/Renderers/SDLImGui2DRenderer.cs new file mode 100644 index 00000000000..cc91ed98830 --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/Renderers/SDLImGui2DRenderer.cs @@ -0,0 +1,190 @@ +using System.Drawing.Imaging; +using System.Runtime.InteropServices; + +using ImGuiNET; + +using BizHawk.Common.CollectionExtensions; + +using static SDL2.SDL; + +namespace BizHawk.Bizware.Graphics +{ + /// + /// Wraps SDL2's software rendering with an ImGui 2D renderer + /// Used for the GDI+ IGL, which doesn't understand vertexes and such + /// + internal class SDLImGui2DRenderer : ImGui2DRenderer + { + // SDL's software renderer sometimes doesn't fill in shapes all the way with a thickness of 1 + // a thickness of 2 seems to suffice however + protected override float RenderThickness => 2.0f; + + public SDLImGui2DRenderer(IGL_GDIPlus gdiPlus, ImGuiResourceCache resourceCache) + : base(gdiPlus, resourceCache) + { + _ = gdiPlus; // this backend must use the GDI+ display method, as it assumes IRenderTarget is an GDIPlusRenderTarget + } + + private readonly ref struct SDLSurface + { + public readonly IntPtr Surface; + + public SDLSurface(BitmapData bmpData) + { + Surface = SDL_CreateRGBSurfaceWithFormatFrom( + bmpData.Scan0, bmpData.Width, bmpData.Height, 8, bmpData.Stride, SDL_PIXELFORMAT_ABGR8888); + if (Surface == IntPtr.Zero) + { + throw new($"Failed to create SDL surface, SDL error: {SDL_GetError()}"); + } + } + + public void Dispose() + => SDL_FreeSurface(Surface); + } + + private readonly ref struct SDLSoftwareRenderer + { + public readonly IntPtr Renderer; + + public SDLSoftwareRenderer(SDLSurface surface) + { + Renderer = SDL_CreateSoftwareRenderer(surface.Surface); + if (Renderer == IntPtr.Zero) + { + throw new($"Failed to create SDL software renderer, SDL error: {SDL_GetError()}"); + } + } + + public void Dispose() + => SDL_DestroyRenderer(Renderer); + } + + // SDL2-CS import expects float[]/int[]'s instead of raw pointers :( + [DllImport("SDL2", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + private static extern int SDL_RenderGeometryRaw( + IntPtr renderer, + IntPtr texture, + IntPtr xy, + int xy_stride, + IntPtr color, + int color_stride, + IntPtr uv, + int uv_stride, + int num_vertices, + IntPtr indices, + int num_indices, + int size_indices + ); + + private static unsafe void RenderCommand(IntPtr sdlRenderer, IntPtr sdlTexture, ImDrawListPtr cmdList, ImDrawCmdPtr cmd) + { + var vtxBuffer = (ImDrawVert*)cmdList.VtxBuffer.Data; + var idxBuffer = (ushort*)cmdList.IdxBuffer.Data; + var vtx = &vtxBuffer![cmd.VtxOffset]; + _ = SDL_RenderGeometryRaw( + renderer: sdlRenderer, + texture: sdlTexture, + xy: (IntPtr)(&vtx->pos), + xy_stride: sizeof(ImDrawVert), + color: (IntPtr)(&vtx->col), + color_stride: sizeof(ImDrawVert), + uv: (IntPtr)(&vtx->uv), + uv_stride: sizeof(ImDrawVert), + num_vertices: (int)(cmdList.VtxBuffer.Size - cmd.VtxOffset), + indices: (IntPtr)(&idxBuffer![cmd.IdxOffset]), + num_indices: (int)cmd.ElemCount, + size_indices: sizeof(ushort) + ); + } + + protected override void RenderInternal(int width, int height) + { + var rt = (GDIPlusRenderTarget)_renderTarget; + var bmpData = rt.SDBitmap.LockBits(rt.GetRectangle(), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); + try + { + using var surface = new SDLSurface(bmpData); + using var renderer = new SDLSoftwareRenderer(surface); + var sdlRenderer = renderer.Renderer; + + _ = SDL_SetRenderDrawBlendMode(sdlRenderer, EnableBlending + ? SDL_BlendMode.SDL_BLENDMODE_BLEND + : SDL_BlendMode.SDL_BLENDMODE_NONE); + + var rect = new SDL_Rect { x = 0, y = 0, w = width, h = height }; + _ = SDL_RenderSetViewport(sdlRenderer, ref rect); + _ = SDL_RenderSetClipRect(sdlRenderer, IntPtr.Zero); + + var cmdBuffer = _imGuiDrawList.CmdBuffer; + for (var i = 0; i < cmdBuffer.Size; i++) + { + var cmd = cmdBuffer[i]; + var callbackId = (DrawCallbackId)cmd.UserCallback; + switch (callbackId) + { + case DrawCallbackId.None: + { + var texId = cmd.GetTexID(); + if (texId != IntPtr.Zero) + { + var userTex = (ImGuiUserTexture)GCHandle.FromIntPtr(texId).Target!; + var texBmpData = userTex.Bitmap.LockBits( + new(0, 0, userTex.Bitmap.Width, userTex.Bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); + try + { + using var texSurf = new SDLSurface(texBmpData); + var sdlTex = SDL_CreateTextureFromSurface(sdlRenderer, texSurf.Surface); + if (sdlTex == IntPtr.Zero) + { + throw new($"Failed to create SDL texture from surface, SDL error: {SDL_GetError()}"); + } + + try + { + RenderCommand(sdlRenderer, sdlTex, _imGuiDrawList, cmd); + } + finally + { + SDL_DestroyTexture(sdlTex); + } + } + finally + { + userTex.Bitmap.UnlockBits(texBmpData); + } + } + else + { + RenderCommand(sdlRenderer, IntPtr.Zero, _imGuiDrawList, cmd); + } + + break; + } + case DrawCallbackId.DisableBlending: + _ = SDL_SetRenderDrawBlendMode(sdlRenderer, SDL_BlendMode.SDL_BLENDMODE_NONE); + break; + case DrawCallbackId.EnableBlendAlpha: + case DrawCallbackId.EnableBlendNormal: + _ = SDL_SetRenderDrawBlendMode(sdlRenderer, SDL_BlendMode.SDL_BLENDMODE_BLEND); + break; + case DrawCallbackId.DrawString: + { + var stringArgs = (DrawStringArgs)GCHandle.FromIntPtr(cmd.UserCallbackData).Target!; + var brush = _resourceCache.BrushCache.GetValueOrPutNew1(stringArgs.Color); + _stringGraphics.TextRenderingHint = stringArgs.TextRenderingHint; + _stringGraphics.DrawString(stringArgs.Str, stringArgs.Font, brush, stringArgs.X, stringArgs.Y, stringArgs.Format); + break; + } + default: + throw new InvalidOperationException(); + } + } + } + finally + { + rt.SDBitmap.UnlockBits(bmpData); + } + } + } +} diff --git a/src/BizHawk.Bizware.BizwareGL/StringRenderer.cs b/src/BizHawk.Bizware.Graphics/Renderers/StringRenderer.cs similarity index 57% rename from src/BizHawk.Bizware.BizwareGL/StringRenderer.cs rename to src/BizHawk.Bizware.Graphics/Renderers/StringRenderer.cs index 21f423b0edf..dcec79f05bd 100644 --- a/src/BizHawk.Bizware.BizwareGL/StringRenderer.cs +++ b/src/BizHawk.Bizware.Graphics/Renderers/StringRenderer.cs @@ -1,14 +1,13 @@ -//http://www.angelcode.com/products/bmfont/ -//http://cyotek.com/blog/angelcode-bitmap-font-parsing-using-csharp +// https://www.angelcode.com/products/bmfont/ +// https://devblog.cyotek.com/post/angelcode-bitmap-font-parsing-using-csharp -using System; using System.Collections.Generic; using System.Drawing; using System.IO; using Cyotek.Drawing.BitmapFont; -namespace BizHawk.Bizware.BizwareGL +namespace BizHawk.Bizware.Graphics { public class StringRenderer : IDisposable { @@ -19,10 +18,24 @@ public StringRenderer(IGL owner, Stream xml, params Stream[] textures) FontInfo.LoadXml(xml); // load textures - for (var i=0; i TexturePages = new(); + private List TexturePages = [ ]; + private readonly Dictionary CharTexCoords = [ ]; + + private record TexCoords(float U0, float V0, float U1, float V1); } -} \ No newline at end of file +} diff --git a/src/BizHawk.Bizware.Graphics/RetroShader.cs b/src/BizHawk.Bizware.Graphics/RetroShader.cs new file mode 100644 index 00000000000..6859a17c54f --- /dev/null +++ b/src/BizHawk.Bizware.Graphics/RetroShader.cs @@ -0,0 +1,163 @@ +using System.Drawing; +using System.Numerics; + +namespace BizHawk.Bizware.Graphics +{ + /// + /// Handles RetroArch's GLSL shader pass format + /// + public class RetroShader : IDisposable + { + // NOTE: we may need to overhaul uniform-setting infrastructure later. + // maybe samplers will need to be set by index and not by name (I think the specs don't dictate what the sampler must be named) + public RetroShader(IGL owner, string source, bool debug = false) + { + Owner = owner; + + var vertexLayoutItems = new PipelineCompileArgs.VertexLayoutItem[3]; + // note: vertex input names don't matter for HLSL, only for GLSL do they matter + // inversely, semantic usage doesn't matter for GLSL, only for HLSL do they matter + vertexLayoutItems[0] = new("VertexCoord", 4, 0, AttribUsage.Position); + vertexLayoutItems[1] = new("COLOR", 4, 16, AttribUsage.Color0); // just dead weight, i have no idea why this is here. but some old HLSL compilers (used in bizhawk for various reasons) will want it to exist here since it exists in the vertex shader + vertexLayoutItems[2] = new("TexCoord", 2, 32, AttribUsage.Texcoord0); + + string vsSource, psSource; + if (owner.DispMethodEnum == EDispMethod.OpenGL) + { + // versions must be specified first, even before defines + vsSource = "#version 150\r\n"; + psSource = "#version 150\r\n"; + } + else + { + vsSource = ""; + psSource = ""; + } + + vsSource += $"#define VERTEX\r\n{source}"; + psSource += $"#define FRAGMENT\r\n{source}"; + + var compileArgs = new PipelineCompileArgs( + vertexLayoutItems, + vertexShaderArgs: new(vsSource, "main_vertex"), + fragmentShaderArgs: new(psSource, "main_fragment"), + fragmentOutputName: "FragColor"); + + try + { + Pipeline = Owner.CreatePipeline(compileArgs); + } + catch (Exception ex) + { + if (!debug) + { + Errors = ex.Message; + return; + } + + throw; + } + + // retroarch shaders will sometimes not have the right sampler name + // it's unclear whether we should bind to s_p or sampler0 + // lets bind to sampler0 in case we don't have s_p + sampler0 = Pipeline.HasUniformSampler("s_p") ? "s_p" : Pipeline.GetUniformSamplerName(0); + + // if a sampler isn't available, we can't do much, although this does interfere with debugging (shaders just returning colors will malfunction) + Available = sampler0 != null; + } + + public bool Available { get; } + public string Errors { get; } + + private readonly string sampler0; + + public void Dispose() + { + Pipeline.Dispose(); + } + + public void Bind() + { + // lame... + Owner.BindPipeline(Pipeline); + } + + public unsafe void Run(ITexture2D tex, Size InputSize, Size OutputSize, bool flip) + { + // ack! make sure to set the pipeline before setting uniforms + Bind(); + + var videoSize = new Vector2(InputSize.Width, InputSize.Height); + var texSize = new Vector2(tex.Width, tex.Height); + var outputSize = new Vector2(OutputSize.Width, OutputSize.Height); + + // cg struct based IN + Pipeline.SetUniform("IN.video_size", videoSize); + Pipeline.SetUniform("IN.texture_size", texSize); + Pipeline.SetUniform("IN.output_size", outputSize); + Pipeline.SetUniform("IN.frame_count", 1); //todo + Pipeline.SetUniform("IN.frame_direction", 1); //todo + + // cg2glsl based IN + Pipeline.SetUniform("VideoSize", videoSize); + Pipeline.SetUniform("TextureSize", texSize); + Pipeline.SetUniform("OutputSize", outputSize); + Pipeline.SetUniform("FrameCount", 1); //todo + Pipeline.SetUniform("FrameDirection", 1); //todo + + var projection = Owner.CreateGuiProjectionMatrix(OutputSize); + var modelView = Owner.CreateGuiViewMatrix(OutputSize); + var mat = modelView * projection; + // cg based projection matrix + Pipeline.SetUniformMatrix("modelViewProj", ref mat); + // cg2glsl based projection matrix + Pipeline.SetUniformMatrix("MVPMatrix", ref mat); + + Pipeline.SetUniformSampler(sampler0, tex); + Owner.SetViewport(OutputSize); + + var time = DateTime.Now.Second + (float)DateTime.Now.Millisecond / 1000; + Pipeline.SetUniform("Time", time); + + var w = OutputSize.Width; + var h = OutputSize.Height; + + float v0, v1; + if (flip) + { + v0 = 1; + v1 = 0; + } + else + { + v0 = 0; + v1 = 1; + } + + var pData = stackalloc float[10 * 4]; + var i = 0; + pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 1; //topleft vert + pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //useless color + pData[i++] = 0; pData[i++] = v0; + pData[i++] = w; pData[i++] = 0; pData[i++] = 0; pData[i++] = 1; //topright vert + pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //useless color + pData[i++] = 1; pData[i++] = v0; + pData[i++] = 0; pData[i++] = h; pData[i++] = 0; pData[i++] = 1; //bottomleft vert + pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //useless color + pData[i++] = 0; pData[i++] = v1; + pData[i++] = w; pData[i++] = h; pData[i++] = 0; pData[i++] = 1; //bottomright vert + pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //useless color + pData[i++] = 1; pData[i] = v1; + + Pipeline.SetVertexData(new(pData), 4); + + Owner.DisableBlending(); + Owner.Draw(4); + } + + public IGL Owner { get; } + + public readonly IPipeline Pipeline; + } +} \ No newline at end of file diff --git a/src/BizHawk.Bizware.Input/KeyInput/IKeyInput.cs b/src/BizHawk.Bizware.Input/KeyInput/IKeyInput.cs index 176aef89499..b261394adff 100644 --- a/src/BizHawk.Bizware.Input/KeyInput/IKeyInput.cs +++ b/src/BizHawk.Bizware.Input/KeyInput/IKeyInput.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using BizHawk.Client.Common; diff --git a/src/BizHawk.Bizware.Input/KeyInput/KeyInputFactory.cs b/src/BizHawk.Bizware.Input/KeyInput/KeyInputFactory.cs index 7bba5f37e79..881f7ae2013 100644 --- a/src/BizHawk.Bizware.Input/KeyInput/KeyInputFactory.cs +++ b/src/BizHawk.Bizware.Input/KeyInput/KeyInputFactory.cs @@ -1,7 +1,5 @@ #nullable enable -using System; - using BizHawk.Common; namespace BizHawk.Bizware.Input diff --git a/src/BizHawk.Bizware.Input/KeyInput/RawKeyInput.cs b/src/BizHawk.Bizware.Input/KeyInput/RawKeyInput.cs index 02821ce0399..c9372ba3e26 100644 --- a/src/BizHawk.Bizware.Input/KeyInput/RawKeyInput.cs +++ b/src/BizHawk.Bizware.Input/KeyInput/RawKeyInput.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Bizware.Input/KeyInput/X11KeyInput.cs b/src/BizHawk.Bizware.Input/KeyInput/X11KeyInput.cs index 6e9097608e2..f744bfdc1de 100644 --- a/src/BizHawk.Bizware.Input/KeyInput/X11KeyInput.cs +++ b/src/BizHawk.Bizware.Input/KeyInput/X11KeyInput.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Bizware.Input/OSTailoredKeyInputAdapter.cs b/src/BizHawk.Bizware.Input/OSTailoredKeyInputAdapter.cs index 7e3ca364e3f..33a601f5926 100644 --- a/src/BizHawk.Bizware.Input/OSTailoredKeyInputAdapter.cs +++ b/src/BizHawk.Bizware.Input/OSTailoredKeyInputAdapter.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Bizware.Input/SDL2/SDL2Gamepad.cs b/src/BizHawk.Bizware.Input/SDL2/SDL2Gamepad.cs index c94eb182e4a..73bab822ab3 100644 --- a/src/BizHawk.Bizware.Input/SDL2/SDL2Gamepad.cs +++ b/src/BizHawk.Bizware.Input/SDL2/SDL2Gamepad.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using static SDL2.SDL; diff --git a/src/BizHawk.Bizware.Input/SDL2/SDL2InputAdapter.cs b/src/BizHawk.Bizware.Input/SDL2/SDL2InputAdapter.cs index 82fe0a66438..297a735bc0f 100644 --- a/src/BizHawk.Bizware.Input/SDL2/SDL2InputAdapter.cs +++ b/src/BizHawk.Bizware.Input/SDL2/SDL2InputAdapter.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Bizware.Test/BizHawk.Bizware.Test.csproj b/src/BizHawk.Bizware.Test/BizHawk.Bizware.Test.csproj index 4af484e8fa5..c7f64502970 100644 --- a/src/BizHawk.Bizware.Test/BizHawk.Bizware.Test.csproj +++ b/src/BizHawk.Bizware.Test/BizHawk.Bizware.Test.csproj @@ -2,14 +2,21 @@ net48 - + - $(DefineConstants);EXE_PROJECT $(ProjectDir)bin + + Exe + + + WinExe + - + + + diff --git a/src/BizHawk.Bizware.Test/Program.cs b/src/BizHawk.Bizware.Test/Program.cs index b713017ab7b..2fc5b1acba9 100644 --- a/src/BizHawk.Bizware.Test/Program.cs +++ b/src/BizHawk.Bizware.Test/Program.cs @@ -1,33 +1,16 @@ -using System; using System.Drawing; using System.IO; using System.Linq; -using System.Reflection; using System.Threading; using System.Windows.Forms; -using BizHawk.Bizware.BizwareGL; using BizHawk.Bizware.Graphics; -using BizHawk.Client.EmuHawk; +using BizHawk.Bizware.Graphics.Controls; namespace BizHawk.Bizware.Test { public static class Program { - static Program() - { - AppDomain.CurrentDomain.AssemblyResolve += (_, args) => - { - lock (AppDomain.CurrentDomain) - { - var firstAsm = Array.Find(AppDomain.CurrentDomain.GetAssemblies(), asm => asm.FullName == args.Name); - if (firstAsm is not null) return firstAsm; - var guessFilename = Path.Combine(AppContext.BaseDirectory, "dll", $"{new AssemblyName(args.Name).Name}.dll"); - return File.Exists(guessFilename) ? Assembly.LoadFile(guessFilename) : null; - } - }; - } - public static void Main() => RunTest(); private sealed class TestForm : Form @@ -46,13 +29,14 @@ public TestForm() private static void RunTest() { - IGL igl = new IGL_OpenGL(2, 0, false); - ArtManager am = new(igl); - var testArts = typeof(Program).Assembly.GetManifestResourceNames().Where(s => s.Contains("flame")) - .Select(s => am.LoadArt(ReflectionCache.EmbeddedResourceStream(s.Substring(21)))) // ReflectionCache adds back the prefix + IGL igl = new IGL_OpenGL(); + // graphics control must be made right away to create the OpenGL context + RetainedGraphicsControl? c = new(igl) { Dock = DockStyle.Fill, BackColor = Color.Black }; + + var testTexs = typeof(Program).Assembly.GetManifestResourceNames().Where(s => s.Contains("flame")) + .Select(s => igl.LoadTexture(ReflectionCache.EmbeddedResourceStream(s[21..]))) // ReflectionCache adds back the prefix .ToList(); - var smile = am.LoadArt(ReflectionCache.EmbeddedResourceStream("TestImages.smile.png")); - am.Close(); + var smile = igl.LoadTexture(ReflectionCache.EmbeddedResourceStream("TestImages.smile.png"))!; StringRenderer sr; using (var xml = ReflectionCache.EmbeddedResourceStream("TestImages.courier16px.fnt")) using (var tex = ReflectionCache.EmbeddedResourceStream("TestImages.courier16px_0.png")) @@ -61,8 +45,6 @@ private static void RunTest() } GuiRenderer gr = new(igl); - - RetainedGraphicsControl? c = new(igl) { Dock = DockStyle.Fill }; TestForm tf = new() { Controls = { c } }; tf.FormClosing += (_, _) => { @@ -81,26 +63,24 @@ private static void RunTest() // create a render target var rt = igl.CreateRenderTarget(60, 60); rt.Bind(); - igl.SetClearColor(Color.Blue); - igl.Clear(ClearBufferMask.ColorBufferBit); + igl.ClearColor(Color.Blue); gr.Begin(60, 60); gr.Draw(smile); gr.End(); - rt.Unbind(); + igl.BindDefaultRenderTarget(); - var rttex2d = igl.LoadTexture(rt.Texture2d.Resolve()); + var rttex2d = igl.LoadTexture(rt.Resolve())!; // test retroarch shader var rt2 = igl.CreateRenderTarget(240, 240); rt2.Bind(); - igl.SetClearColor(Color.CornflowerBlue); - igl.Clear(ClearBufferMask.ColorBufferBit); + igl.ClearColor(Color.CornflowerBlue); RetroShader shader; using (var stream = ReflectionCache.EmbeddedResourceStream("TestImages.4xSoft.glsl")) { shader = new(igl, new StreamReader(stream).ReadToEnd()); } - igl.SetBlendState(igl.BlendNoneCopy); + igl.DisableBlending(); shader.Run(rttex2d, new Size(60, 60), new Size(240, 240), true); var running = true; @@ -118,38 +98,37 @@ private static void RunTest() { c.Begin(); - igl.SetClearColor(Color.Red); - igl.Clear(ClearBufferMask.ColorBufferBit); + igl.ClearColor(Color.Red); - var frame = (int) (DateTime.Now - start).TotalSeconds % testArts.Count; + var frame = (int) (DateTime.Now - start).TotalSeconds % testTexs.Count; gr.Begin(c.ClientSize.Width, c.ClientSize.Height); - gr.SetBlendState(igl.BlendNormal); + gr.EnableBlending(); gr.SetModulateColor(Color.Green); - gr.RectFill(250, 0, 16, 16); + gr.DrawSubrect(null, 250, 0, 16, 16, 0, 0, 1, 1); - gr.SetBlendState(igl.BlendNoneCopy); + gr.DisableBlending(); gr.Draw(rttex2d, 0, 20); - gr.SetBlendState(igl.BlendNormal); + gr.EnableBlending(); sr.RenderString(gr, 0, 0, "?? fps"); gr.SetModulateColor(Color.FromArgb(255, 255, 255, 255)); gr.SetCornerColor(0, new(1.0f, 0.0f, 0.0f, 1.0f)); - gr.Draw(rt2.Texture2d, 0, 0); + gr.Draw(rt2, 0, 0); gr.SetCornerColor(0, new(1.0f, 1.0f, 1.0f, 1.0f)); gr.SetModulateColorWhite(); - gr.Modelview.Translate((float) Math.Sin(wobble / 360.0f) * 50, 0); - gr.Modelview.Translate(100, 100); - gr.Modelview.Push(); - gr.Modelview.Translate(testArts[frame].Width, 0); - gr.Modelview.Scale(-1, 1); + gr.ModelView.Translate((float) Math.Sin(wobble / 360.0f) * 50, 0); + gr.ModelView.Translate(100, 100); + gr.ModelView.Push(); + gr.ModelView.Translate(testTexs[frame].Width, 0); + gr.ModelView.Scale(-1, 1); wobble++; gr.SetModulateColor(Color.Yellow); - gr.DrawFlipped(testArts[frame], true, false); + gr.DrawSubrect(testTexs[frame], 0, 0, testTexs[frame].Width, testTexs[frame].Height, 1, 0, 0, 1); gr.SetModulateColorWhite(); - gr.Modelview.Pop(); - gr.SetBlendState(igl.BlendNormal); + gr.ModelView.Pop(); + gr.EnableBlending(); gr.Draw(smile); gr.End(); diff --git a/src/BizHawk.Client.Common/Api/ApiContainer.cs b/src/BizHawk.Client.Common/Api/ApiContainer.cs index 065a0e122c3..d8f1d37e7c6 100644 --- a/src/BizHawk.Client.Common/Api/ApiContainer.cs +++ b/src/BizHawk.Client.Common/Api/ApiContainer.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; namespace BizHawk.Client.Common @@ -18,10 +17,6 @@ public IEmuClientApi EmuClient public IEmulationApi Emulation => Get(); // requires IEmulator - [Obsolete("use Emulation")] - public IGameInfoApi GameInfo - => Get(); - public IGuiApi Gui => Get(); // requires IEmulator diff --git a/src/BizHawk.Client.Common/Api/ApiInjector.cs b/src/BizHawk.Client.Common/Api/ApiInjector.cs index 7fa0c877ce2..353d3e03a2c 100644 --- a/src/BizHawk.Client.Common/Api/ApiInjector.cs +++ b/src/BizHawk.Client.Common/Api/ApiInjector.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using BizHawk.Common.ReflectionExtensions; diff --git a/src/BizHawk.Client.Common/Api/BasicApiProvider.cs b/src/BizHawk.Client.Common/Api/BasicApiProvider.cs index d20e8970588..1b01a466def 100644 --- a/src/BizHawk.Client.Common/Api/BasicApiProvider.cs +++ b/src/BizHawk.Client.Common/Api/BasicApiProvider.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Client.Common/Api/BizHawkExternalToolUsage.cs b/src/BizHawk.Client.Common/Api/BizHawkExternalToolUsage.cs index 937a96a91fa..719ad474642 100644 --- a/src/BizHawk.Client.Common/Api/BizHawkExternalToolUsage.cs +++ b/src/BizHawk.Client.Common/Api/BizHawkExternalToolUsage.cs @@ -9,10 +9,12 @@ public enum BizHawkExternalToolUsage : short /// General usage, works even with null emulator /// Global = 0, + /// /// Specific to an emulator (NES,SNES,etc...) /// EmulatorSpecific = 1, + /// /// Specific to a Game /// diff --git a/src/BizHawk.Client.Common/Api/BizHawkSystemIdToCoreSystemEnumConverter.cs b/src/BizHawk.Client.Common/Api/BizHawkSystemIdToCoreSystemEnumConverter.cs deleted file mode 100644 index 4776ff0de6c..00000000000 --- a/src/BizHawk.Client.Common/Api/BizHawkSystemIdToCoreSystemEnumConverter.cs +++ /dev/null @@ -1,150 +0,0 @@ -using System; -using System.Globalization; - -using BizHawk.Emulation.Common; - -namespace BizHawk.Client.Common -{ - /// - /// This class holds a converter for BizHawk SystemId (which is a simple - /// It allows you to convert it to a value and vice versa - /// - /// I made it this way just in case one day we need it for WPF (DependencyProperty binding). Just uncomment :IValueConverter implementation - /// I didn't implemented it because of mono compatibility - /// - public sealed class BizHawkSystemIdToEnumConverter //:IValueConverter - { - /// - /// Convert BizHawk SystemId to value - /// - /// you want to convert - /// The type of the binding target property - /// The converter parameter to use; null in our case - /// The culture to use in the converter - /// A that is equivalent to BizHawk SystemId - /// Thrown when SystemId hasn't been found - public object Convert(object value, Type targetType, object parameter, CultureInfo cultureInfo) - { - return (string) value switch - { - VSystemID.Raw.AppleII => CoreSystem.AppleII, - VSystemID.Raw.A26 => CoreSystem.Atari2600, - VSystemID.Raw.A78 => CoreSystem.Atari7800, - VSystemID.Raw.Arcade => CoreSystem.Arcade, - VSystemID.Raw.Coleco => CoreSystem.ColecoVision, - VSystemID.Raw.C64 => CoreSystem.Commodore64, - VSystemID.Raw.GBL => CoreSystem.GameBoyLink, - VSystemID.Raw.GB => CoreSystem.GameBoy, - VSystemID.Raw.GBA => CoreSystem.GameBoyAdvance, - VSystemID.Raw.GEN => CoreSystem.Genesis, - VSystemID.Raw.INTV => CoreSystem.Intellivision, - VSystemID.Raw.Libretro => CoreSystem.Libretro, - VSystemID.Raw.Lynx => CoreSystem.Lynx, - VSystemID.Raw.SMS => CoreSystem.MasterSystem, - VSystemID.Raw.NDS => CoreSystem.NintendoDS, - VSystemID.Raw.NES => CoreSystem.NES, - VSystemID.Raw.N64 => CoreSystem.Nintendo64, - VSystemID.Raw.NULL => CoreSystem.Null, - VSystemID.Raw.PCE => CoreSystem.PCEngine, - VSystemID.Raw.PCECD => CoreSystem.PCEngine, - VSystemID.Raw.SGX => CoreSystem.PCEngine, - VSystemID.Raw.PSX => CoreSystem.Playstation, - VSystemID.Raw.SAT => CoreSystem.Saturn, - VSystemID.Raw.SNES => CoreSystem.SNES, - VSystemID.Raw.TI83 => CoreSystem.TI83, - VSystemID.Raw.VEC => CoreSystem.Vectrex, - VSystemID.Raw.WSWAN => CoreSystem.WonderSwan, - VSystemID.Raw.ZXSpectrum => CoreSystem.ZXSpectrum, - VSystemID.Raw.AmstradCPC => CoreSystem.AmstradCPC, - VSystemID.Raw.GGL => CoreSystem.GGL, - VSystemID.Raw.ChannelF => CoreSystem.ChannelF, - VSystemID.Raw.O2 => CoreSystem.Odyssey2, - VSystemID.Raw.MSX => CoreSystem.MSX, - VSystemID.Raw.VB => CoreSystem.VirtualBoy, - VSystemID.Raw.NGP => CoreSystem.NeoGeoPocket, - VSystemID.Raw.SGB => CoreSystem.SuperGameBoy, - VSystemID.Raw.UZE => CoreSystem.UzeBox, - VSystemID.Raw.PCFX => CoreSystem.PcFx, - _ => throw new InvalidOperationException($"{value} is missing in convert list") - }; - } - - - /// - /// Convert BizHawk SystemId to value - /// - /// you want to convert - /// A that is equivalent to BizHawk SystemId - /// Thrown when SystemId hasn't been found - public CoreSystem Convert(string value) - { - return (CoreSystem)Convert(value, null, null, CultureInfo.CurrentCulture); - } - - - /// - /// Convert a value to BizHawk SystemId - /// - /// you want to convert - /// The type of the binding target property - /// The converter parameter to use; null in our case - /// The culture to use in the converter - /// A that is used by BizHawk SystemId - /// Thrown when hasn't been found - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo cultureInfo) - { - return (CoreSystem) value switch - { - CoreSystem.AppleII => VSystemID.Raw.AppleII, - CoreSystem.Atari2600 => VSystemID.Raw.A26, - CoreSystem.Atari7800 => VSystemID.Raw.A78, - CoreSystem.Arcade => VSystemID.Raw.Arcade, - CoreSystem.ChannelF => VSystemID.Raw.ChannelF, - CoreSystem.ColecoVision => VSystemID.Raw.Coleco, - CoreSystem.Commodore64 => VSystemID.Raw.C64, - CoreSystem.GameBoyLink => VSystemID.Raw.GBL, - CoreSystem.GameBoy => VSystemID.Raw.GB, - CoreSystem.GameBoyAdvance => VSystemID.Raw.GBA, - CoreSystem.Genesis => VSystemID.Raw.GEN, - CoreSystem.GGL => VSystemID.Raw.GGL, - CoreSystem.Intellivision => VSystemID.Raw.INTV, - CoreSystem.Libretro => VSystemID.Raw.Libretro, - CoreSystem.Lynx => VSystemID.Raw.Lynx, - CoreSystem.MasterSystem => VSystemID.Raw.SMS, - CoreSystem.MSX => VSystemID.Raw.MSX, - CoreSystem.NeoGeoPocket => VSystemID.Raw.NGP, - CoreSystem.NES => VSystemID.Raw.NES, - CoreSystem.Nintendo64 => VSystemID.Raw.N64, - CoreSystem.NintendoDS => VSystemID.Raw.NDS, - CoreSystem.Null => VSystemID.Raw.NULL, - CoreSystem.PCEngine => VSystemID.Raw.PCE, - CoreSystem.PcFx => VSystemID.Raw.PCFX, - CoreSystem.Playstation => VSystemID.Raw.PSX, - CoreSystem.Saturn => VSystemID.Raw.SAT, - CoreSystem.SNES => VSystemID.Raw.SNES, - CoreSystem.SuperGameBoy => VSystemID.Raw.SGB, - CoreSystem.TI83 => VSystemID.Raw.TI83, - CoreSystem.UzeBox => VSystemID.Raw.UZE, - CoreSystem.Vectrex => VSystemID.Raw.VEC, - CoreSystem.VirtualBoy => VSystemID.Raw.VB, - CoreSystem.WonderSwan => VSystemID.Raw.WSWAN, - CoreSystem.ZXSpectrum => VSystemID.Raw.ZXSpectrum, - CoreSystem.AmstradCPC => VSystemID.Raw.AmstradCPC, - CoreSystem.Odyssey2 => VSystemID.Raw.O2, - _ => throw new InvalidOperationException($"{value} is missing in convert list") - }; - } - - - /// - /// Convert a value to BizHawk SystemId - /// - /// you want to convert - /// A that is used by BizHawk SystemId - /// Thrown when hasn't been found - public string ConvertBack(CoreSystem value) - { - return (string)ConvertBack(value, null, null, CultureInfo.CurrentCulture); - } - } -} diff --git a/src/BizHawk.Client.Common/Api/Classes/EmuClientApi.cs b/src/BizHawk.Client.Common/Api/Classes/EmuClientApi.cs index a1c4aa63c2a..47320ea4b7e 100644 --- a/src/BizHawk.Client.Common/Api/Classes/EmuClientApi.cs +++ b/src/BizHawk.Client.Common/Api/Classes/EmuClientApi.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.IO; using BizHawk.Emulation.Common; @@ -56,6 +55,7 @@ public EmuClientApi(Action logCallback, IMainFormForApi mainForm, Displa public int BufferWidth() => VideoProvider.BufferWidth; +#pragma warning disable MA0091 // passing through `sender` is intentional private void CallBeforeQuickLoad(object sender, BeforeQuickLoadEventArgs args) => BeforeQuickLoad?.Invoke(sender, args); @@ -70,6 +70,7 @@ private void CallStateLoaded(object sender, StateLoadedEventArgs args) private void CallStateSaved(object sender, StateSavedEventArgs args) => StateSaved?.Invoke(sender, args); +#pragma warning restore MA0091 public void ClearAutohold() => _mainForm.ClearHolds(); @@ -90,7 +91,7 @@ public void Dispose() public void DoFrameAdvance() { - _mainForm.FrameAdvance(); + _mainForm.FrameAdvance(discardApiHawkSurfaces: false); // we're rendering, so we don't want to discard _mainForm.StepRunLoop_Throttle(); _mainForm.Render(); } @@ -121,7 +122,8 @@ public void FrameSkip(int numFrames) public int GetTargetScanlineIntensity() => _config.TargetScanlineFilterIntensity; - public int GetWindowSize() => _config.TargetZoomFactors[Emulator.SystemId]; + public int GetWindowSize() + => _config.GetWindowScaleFor(Emulator.SystemId); public void InvisibleEmulation(bool invisible) => _mainForm.InvisibleEmulation = invisible; @@ -138,7 +140,7 @@ public bool LoadState(string name) suppressOSD: false); public bool OpenRom(string path) - => _mainForm.LoadRom(path, new LoadRomArgs { OpenAdvanced = OpenAdvancedSerializer.ParseWithLegacy(path) }); + => _mainForm.LoadRom(path, new LoadRomArgs(new OpenAdvanced_OpenRom(path))); public void Pause() => _mainForm.PauseEmulator(); @@ -194,7 +196,7 @@ public void SetWindowSize(int size) { if (size == 1 || size == 2 || size == 3 || size == 4 || size == 5 || size == 10) { - _config.TargetZoomFactors[Emulator.SystemId] = size; + _config.SetWindowScaleFor(Emulator.SystemId, size); _mainForm.FrameBufferResized(); _displayManager.OSD.AddMessage($"Window size set to {size}x"); } diff --git a/src/BizHawk.Client.Common/Api/Classes/EmulationApi.cs b/src/BizHawk.Client.Common/Api/Classes/EmulationApi.cs index a7b43629806..bfb898071dd 100644 --- a/src/BizHawk.Client.Common/Api/Classes/EmulationApi.cs +++ b/src/BizHawk.Client.Common/Api/Classes/EmulationApi.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; diff --git a/src/BizHawk.Client.Common/Api/Classes/GameInfoApi.cs b/src/BizHawk.Client.Common/Api/Classes/GameInfoApi.cs deleted file mode 100644 index 6e6dedc5f01..00000000000 --- a/src/BizHawk.Client.Common/Api/Classes/GameInfoApi.cs +++ /dev/null @@ -1,36 +0,0 @@ -#nullable enable - -using System; -using System.Collections.Generic; - -using BizHawk.Common; -using BizHawk.Emulation.Common; - -namespace BizHawk.Client.Common -{ - [Obsolete("use IEmulationApi")] - public sealed class GameInfoApi : IGameInfoApi - { - [OptionalService] - public IBoardInfo? _boardInfo { get; set; } - - private readonly IGameInfo? _game; - - public GameInfoApi(IGameInfo? game) - => _game = game; - - public string GetBoardType() - => _boardInfo?.BoardName ?? string.Empty; - - public IGameInfo? GetGameInfo() - => _game; - - public IReadOnlyDictionary GetOptions() - { - var options = new Dictionary(); - if (_game == null) return options; - foreach (var (k, v) in ((GameInfo) _game).GetOptions()) options[k] = v; - return options; - } - } -} diff --git a/src/BizHawk.Client.Common/Api/Classes/GuiApi.cs b/src/BizHawk.Client.Common/Api/Classes/GuiApi.cs index 272e38214c1..d3344ea5b82 100644 --- a/src/BizHawk.Client.Common/Api/Classes/GuiApi.cs +++ b/src/BizHawk.Client.Common/Api/Classes/GuiApi.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; @@ -6,6 +5,7 @@ using System.Drawing.Text; using System.IO; +using BizHawk.Bizware.Graphics; using BizHawk.Common.CollectionExtensions; using BizHawk.Emulation.Common; @@ -25,15 +25,9 @@ public sealed class GuiApi : IGuiApi private readonly DisplayManagerBase _displayManager; - private readonly Dictionary _imageCache = new Dictionary(); + private readonly Dictionary _imageCache = new(); - private readonly Bitmap _nullGraphicsBitmap = new Bitmap(1, 1); - - private readonly Dictionary _pens = new Dictionary(); - - private readonly Dictionary _solidBrushes = new Dictionary(); - - private ImageAttributes _attributes = new ImageAttributes(); + private readonly Bitmap _nullGraphicsBitmap = new(1, 1); private CompositingMode _compositingMode = CompositingMode.SourceOver; @@ -43,19 +37,12 @@ public sealed class GuiApi : IGuiApi private int _defaultPixelFont = 1; // = "gens" - private Color? _defaultTextBackground = Color.FromArgb(128, 0, 0, 0); - - private IDisplaySurface _clientSurface; - - private IDisplaySurface _GUISurface; + private Color _defaultTextBackground = Color.FromArgb(128, 0, 0, 0); private (int Left, int Top, int Right, int Bottom) _padding = (0, 0, 0, 0); - private DisplaySurfaceID? _usingSurfaceID = null; - - public bool EnableLuaAutolockHack = false; - - public bool HasGUISurface => _GUISurface != null; + private DisplaySurfaceID? _usingSurfaceID; + public bool HasGUISurface => true; public GuiApi(Action logCallback, DisplayManagerBase displayManager) { @@ -63,90 +50,36 @@ public GuiApi(Action logCallback, DisplayManagerBase displayManager) _displayManager = displayManager; } - private SolidBrush GetBrush(Color color) - => _solidBrushes.GetValueOrPutNew1(color); - - private Pen GetPen(Color color) - => _pens.GetValueOrPutNew1(color); - - private Graphics GetGraphics(DisplaySurfaceID? surfaceID) + private I2DRenderer Get2DRenderer(DisplaySurfaceID? surfaceID) { - var g = GetRelevantSurface(surfaceID)?.GetGraphics() ?? Graphics.FromImage(_nullGraphicsBitmap); - return g; + var nnID = surfaceID ?? _usingSurfaceID ?? throw new Exception(); + return _displayManager.GetApiHawk2DRenderer(nnID); } public void ToggleCompositingMode() => _compositingMode = (CompositingMode) (1 - (int) _compositingMode); // enum has two members, 0 and 1 - public ImageAttributes GetAttributes() => _attributes; + public ImageAttributes GetAttributes() => null; - public void SetAttributes(ImageAttributes a) => _attributes = a; - - private IDisplaySurface GetRelevantSurface(DisplaySurfaceID? surfaceID) + public void SetAttributes(ImageAttributes a) { - var nnID = surfaceID ?? _usingSurfaceID ?? throw new Exception(); - void ThisIsTheLuaAutolockHack() - { - try - { - UnlockSurface(nnID); - LockSurface(nnID); - } - catch (InvalidOperationException ex) - { - LogCallback(ex.ToString()); - } - } - switch (nnID) - { - case DisplaySurfaceID.EmuCore: - if (_GUISurface == null && EnableLuaAutolockHack) ThisIsTheLuaAutolockHack(); - return _GUISurface; - case DisplaySurfaceID.Client: - if (_clientSurface == null && EnableLuaAutolockHack) ThisIsTheLuaAutolockHack(); - return _clientSurface; - default: - throw new Exception(); - } } - private void LockSurface(DisplaySurfaceID surfaceID) + public void WithSurface(DisplaySurfaceID surfaceID, Action drawingCallsFunc) { - switch (surfaceID) + _usingSurfaceID = surfaceID; + try { - case DisplaySurfaceID.EmuCore: - if (_GUISurface != null) throw new InvalidOperationException("attempt to lock surface without unlocking previous"); - _GUISurface = _displayManager.LockApiHawkSurface(surfaceID, clear: true); - break; - case DisplaySurfaceID.Client: - if (_clientSurface != null) throw new InvalidOperationException("attempt to lock surface without unlocking previous"); - _clientSurface = _displayManager.LockApiHawkSurface(surfaceID, clear: true); - break; - default: - throw new ArgumentException(message: "not a valid enum member", paramName: nameof(surfaceID)); + drawingCallsFunc(this); } - } - - private void UnlockSurface(DisplaySurfaceID surfaceID) - { - switch (surfaceID) + finally { - case DisplaySurfaceID.EmuCore: - if (_GUISurface != null) _displayManager.UnlockApiHawkSurface(_GUISurface); - _GUISurface = null; - break; - case DisplaySurfaceID.Client: - if (_clientSurface != null) _displayManager.UnlockApiHawkSurface(_clientSurface); - _clientSurface = null; - break; - default: - throw new ArgumentException(message: "not a valid enum member", paramName: nameof(surfaceID)); + _usingSurfaceID = null; } } public void WithSurface(DisplaySurfaceID surfaceID, Action drawingCallsFunc) { - LockSurface(surfaceID); _usingSurfaceID = surfaceID; try { @@ -155,27 +88,9 @@ public void WithSurface(DisplaySurfaceID surfaceID, Action drawingCallsFunc) finally { _usingSurfaceID = null; - UnlockSurface(surfaceID); - } - } - - public readonly ref struct LuaAutoUnlockHack - { - private readonly GuiApi _guiApi; - - internal LuaAutoUnlockHack(GuiApi guiApi) - => _guiApi = guiApi; - - public void Dispose() - { - _guiApi.UnlockSurface(DisplaySurfaceID.EmuCore); - _guiApi.UnlockSurface(DisplaySurfaceID.Client); } } - public LuaAutoUnlockHack ThisIsTheLuaAutoUnlockHack() - => new(this); - public void DrawNew(string name, bool clear) { switch (name) @@ -204,7 +119,7 @@ public void DrawNew(string name, bool clear) public void AddMessage(string message, int? duration = null) => _displayManager.OSD.AddMessage(message, duration); - public void ClearGraphics(DisplaySurfaceID? surfaceID = null) => GetRelevantSurface(surfaceID).Clear(); + public void ClearGraphics(DisplaySurfaceID? surfaceID = null) => Get2DRenderer(surfaceID).Clear(); public void ClearText() => _displayManager.OSD.ClearGuiText(); @@ -212,7 +127,7 @@ public void AddMessage(string message, int? duration = null) public void SetDefaultBackgroundColor(Color color) => _defaultBackground = color; - public Color? GetDefaultTextBackground() => _defaultTextBackground; + public Color GetDefaultTextBackground() => _defaultTextBackground; public void SetDefaultTextBackground(Color color) => _defaultTextBackground = color; @@ -238,9 +153,9 @@ public void DrawBezier(Point p1, Point p2, Point p3, Point p4, Color? color = nu { try { - using var g = GetGraphics(surfaceID); - g.CompositingMode = _compositingMode; - g.DrawBezier(GetPen(color ?? _defaultForeground), p1, p2, p3, p4); + var r = Get2DRenderer(surfaceID); + r.CompositingMode = _compositingMode; + r.DrawBezier(color ?? _defaultForeground, p1, p2, p3, p4); } catch (Exception) { @@ -252,9 +167,9 @@ public void DrawBeziers(Point[] points, Color? color = null, DisplaySurfaceID? s { try { - using var g = GetGraphics(surfaceID); - g.CompositingMode = _compositingMode; - g.DrawBeziers(GetPen(color ?? _defaultForeground), points); + var r = Get2DRenderer(surfaceID); + r.CompositingMode = _compositingMode; + r.DrawBeziers(color ?? _defaultForeground, points); } catch (Exception) { @@ -266,33 +181,24 @@ public void DrawBox(int x, int y, int x2, int y2, Color? line = null, Color? bac { try { - float w; - if (x < x2) - { - w = x2 - x; - } - else - { - x2 = x - x2; - x -= x2; - w = Math.Max(x2, 0.1f); - } - float h; - if (y < y2) + if (x > x2) { - h = y2 - y; + (x, x2) = (x2, x); } - else + + if (y > y2) { - y2 = y - y2; - y -= y2; - h = Math.Max(y2, 0.1f); + (y, y2) = (y2, y); } - using var g = GetGraphics(surfaceID); - g.CompositingMode = _compositingMode; - g.DrawRectangle(GetPen(line ?? _defaultForeground), x, y, w, h); + + var w = x2 - x + 1; + var h = y2 - y + 1; + + var r = Get2DRenderer(surfaceID); + r.CompositingMode = _compositingMode; + r.DrawRectangle(line ?? _defaultForeground, x, y, w, h); var bg = background ?? _defaultBackground; - if (bg != null) g.FillRectangle(GetBrush(bg.Value), x + 1, y + 1, Math.Max(w - 1, 0), Math.Max(h - 1, 0)); + if (bg != null) r.FillRectangle(bg.Value, x + 1, y + 1, Math.Max(w - 2, 0), Math.Max(h - 2, 0)); } catch (Exception) { @@ -304,11 +210,13 @@ public void DrawEllipse(int x, int y, int width, int height, Color? line = null, { try { - using var g = GetGraphics(surfaceID); + var r = Get2DRenderer(surfaceID); var bg = background ?? _defaultBackground; - if (bg != null) g.FillEllipse(GetBrush(bg.Value), x, y, width, height); - g.CompositingMode = _compositingMode; - g.DrawEllipse(GetPen(line ?? _defaultForeground), x, y, width, height); + // GDI+ had an off by one here, we increment width and height to preserve backwards compatibility + width++; height++; + if (bg != null) r.FillEllipse(bg.Value, x, y, width, height); + r.CompositingMode = _compositingMode; + r.DrawEllipse(line ?? _defaultForeground, x, y, width, height); } catch (Exception) { @@ -325,15 +233,14 @@ public void DrawIcon(string path, int x, int y, int? width = null, int? height = AddMessage($"File not found: {path}"); return; } - using var g = GetGraphics(surfaceID); - g.CompositingMode = _compositingMode; - g.DrawIcon( - width != null && height != null - ? new Icon(path, width.Value, height.Value) - : new Icon(path), - x, - y - ); + + var icon = width != null && height != null + ? new Icon(path, width.Value, height.Value) + : new Icon(path); + + var r = Get2DRenderer(surfaceID); + r.CompositingMode = _compositingMode; + r.DrawImage(icon.ToBitmap(), x, y); } catch (Exception) { @@ -343,19 +250,19 @@ public void DrawIcon(string path, int x, int y, int? width = null, int? height = public void DrawImage(Image img, int x, int y, int? width = null, int? height = null, bool cache = true, DisplaySurfaceID? surfaceID = null) { - using var g = GetGraphics(surfaceID); - g.CompositingMode = _compositingMode; - g.DrawImage( - img, + var r = Get2DRenderer(surfaceID); + r.CompositingMode = _compositingMode; + r.DrawImage( + new(img), new Rectangle(x, y, width ?? img.Width, height ?? img.Height), 0, 0, img.Width, img.Height, - GraphicsUnit.Pixel, - _attributes + cache: false // caching is meaningless here ); } + public void DrawImage(string path, int x, int y, int? width = null, int? height = null, bool cache = true, DisplaySurfaceID? surfaceID = null) { if (!File.Exists(path)) @@ -363,44 +270,44 @@ public void DrawImage(string path, int x, int y, int? width = null, int? height LogCallback($"File not found: {path}"); return; } - using var g = GetGraphics(surfaceID); + if (!_imageCache.TryGetValue(path, out var img)) { - img = Image.FromFile(path); + img = new(Image.FromFile(path)); if (cache) _imageCache[path] = img; } - g.CompositingMode = _compositingMode; - g.DrawImage( + + var r = Get2DRenderer(surfaceID); + r.CompositingMode = _compositingMode; + r.DrawImage( img, new Rectangle(x, y, width ?? img.Width, height ?? img.Height), 0, 0, img.Width, img.Height, - GraphicsUnit.Pixel, - _attributes + cache ); } public void ClearImageCache() { - foreach (var image in _imageCache) image.Value.Dispose(); _imageCache.Clear(); + _displayManager.ClearApiHawkTextureCache(); } public void DrawImageRegion(Image img, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int? dest_width = null, int? dest_height = null, DisplaySurfaceID? surfaceID = null) { - using var g = GetGraphics(surfaceID); - g.CompositingMode = _compositingMode; - g.DrawImage( - img, + var r = Get2DRenderer(surfaceID); + r.CompositingMode = _compositingMode; + r.DrawImage( + new(img), new Rectangle(dest_x, dest_y, dest_width ?? source_width, dest_height ?? source_height), source_x, source_y, source_width, source_height, - GraphicsUnit.Pixel, - _attributes + cache: false ); } @@ -411,25 +318,25 @@ public void DrawImageRegion(string path, int source_x, int source_y, int source_ LogCallback($"File not found: {path}"); return; } - using var g = GetGraphics(surfaceID); - g.CompositingMode = _compositingMode; - g.DrawImage( - _imageCache.GetValueOrPut(path, Image.FromFile), + + var r = Get2DRenderer(surfaceID); + r.CompositingMode = _compositingMode; + r.DrawImage( + _imageCache.GetValueOrPut(path, static i => new(Image.FromFile(i))), new Rectangle(dest_x, dest_y, dest_width ?? source_width, dest_height ?? source_height), source_x, source_y, source_width, source_height, - GraphicsUnit.Pixel, - _attributes + cache: true ); } public void DrawLine(int x1, int y1, int x2, int y2, Color? color = null, DisplaySurfaceID? surfaceID = null) { - using var g = GetGraphics(surfaceID); - g.CompositingMode = _compositingMode; - g.DrawLine(GetPen(color ?? _defaultForeground), x1, y1, x2, y2); + var r = Get2DRenderer(surfaceID); + r.CompositingMode = _compositingMode; + r.DrawLine(color ?? _defaultForeground, x1, y1, x2, y2); } public void DrawAxis(int x, int y, int size, Color? color = null, DisplaySurfaceID? surfaceID = null) @@ -440,19 +347,21 @@ public void DrawAxis(int x, int y, int size, Color? color = null, DisplaySurface public void DrawPie(int x, int y, int width, int height, int startangle, int sweepangle, Color? line = null, Color? background = null, DisplaySurfaceID? surfaceID = null) { - using var g = GetGraphics(surfaceID); - g.CompositingMode = _compositingMode; + var r = Get2DRenderer(surfaceID); + r.CompositingMode = _compositingMode; var bg = background ?? _defaultBackground; - if (bg != null) g.FillPie(GetBrush(bg.Value), x, y, width, height, startangle, sweepangle); - g.DrawPie(GetPen(line ?? _defaultForeground), x + 1, y + 1, width - 1, height - 1, startangle, sweepangle); + // GDI+ had an off by one here, we increment width and height to preserve backwards compatibility + width++; height++; + if (bg != null) r.FillPie(bg.Value, x, y, width, height, startangle, sweepangle); + r.DrawPie(line ?? _defaultForeground, x + 1, y + 1, width - 1, height - 1, startangle, sweepangle); } public void DrawPixel(int x, int y, Color? color = null, DisplaySurfaceID? surfaceID = null) { try { - using var g = GetGraphics(surfaceID); - g.DrawLine(GetPen(color ?? _defaultForeground), x, y, x + 0.1F, y); + var r = Get2DRenderer(surfaceID); + r.DrawLine(color ?? _defaultForeground, x, y, x, y); } catch (Exception) { @@ -464,10 +373,10 @@ public void DrawPolygon(Point[] points, Color? line = null, Color? background = { try { - using var g = GetGraphics(surfaceID); - g.DrawPolygon(GetPen(line ?? _defaultForeground), points); + var r = Get2DRenderer(surfaceID); + r.DrawPolygon(line ?? _defaultForeground, points); var bg = background ?? _defaultBackground; - if (bg != null) g.FillPolygon(GetBrush(bg.Value), points); + if (bg != null) r.FillPolygon(bg.Value, points); } catch (Exception) { @@ -477,12 +386,14 @@ public void DrawPolygon(Point[] points, Color? line = null, Color? background = public void DrawRectangle(int x, int y, int width, int height, Color? line = null, Color? background = null, DisplaySurfaceID? surfaceID = null) { - using var g = GetGraphics(surfaceID); - var w = Math.Max(width, 0.1F); - var h = Math.Max(height, 0.1F); - g.DrawRectangle(GetPen(line ?? _defaultForeground), x, y, w, h); + var r = Get2DRenderer(surfaceID); + var w = Math.Max(width, 1); + var h = Math.Max(height, 1); + // GDI+ had an off by one here, we increment width and height to preserve backwards compatibility + w++; h++; + r.DrawRectangle(line ?? _defaultForeground, x, y, w, h); var bg = background ?? _defaultBackground; - if (bg != null) g.FillRectangle(GetBrush(bg.Value), x + 1, y + 1, Math.Max(w - 1, 0), Math.Max(h - 1, 0)); + if (bg != null) r.FillRectangle(bg.Value, x + 1, y + 1, Math.Max(w - 2, 0), Math.Max(h - 2, 0)); } public void DrawString(int x, int y, string message, Color? forecolor = null, Color? backcolor = null, int? fontsize = null, string fontfamily = null, string fontstyle = null, string horizalign = null, string vertalign = null, DisplaySurfaceID? surfaceID = null) @@ -500,7 +411,7 @@ public void DrawString(int x, int y, string message, Color? forecolor = null, Co _ => FontStyle.Regular }; - using var g = GetGraphics(surfaceID); + using var g = Graphics.FromImage(_nullGraphicsBitmap); // The text isn't written out using GenericTypographic, so measuring it using GenericTypographic seemed to make it worse. // And writing it out with GenericTypographic just made it uglier. :p @@ -535,17 +446,17 @@ public void DrawString(int x, int y, string message, Color? forecolor = null, Co break; } + var r = Get2DRenderer(surfaceID); var bg = backcolor ?? _defaultBackground; if (bg != null) { - var brush = GetBrush(bg.Value); for (var xd = -1; xd <= 1; xd++) for (var yd = -1; yd <= 1; yd++) { - g.DrawString(message, font, brush, x + xd, y + yd); + r.DrawString(message, font, bg.Value, x + xd, y + yd); } } - g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; - g.DrawString(message, font, GetBrush(forecolor ?? _defaultForeground), x, y); + + r.DrawString(message, font, forecolor ?? _defaultForeground, x, y, textRenderingHint: TextRenderingHint.SingleBitPerPixelGridFit); } catch (Exception) { @@ -594,12 +505,14 @@ public void PixelText( index = _defaultPixelFont; break; } - using var g = GetGraphics(surfaceID); + + using var g = Graphics.FromImage(_nullGraphicsBitmap); var font = new Font(_displayManager.CustomFonts.Families[index], 8, FontStyle.Regular, GraphicsUnit.Pixel); var sizeOfText = g.MeasureString(message, font, width: 0, PixelTextFormat).ToSize(); - if (backcolor.HasValue) g.FillRectangle(GetBrush(backcolor.Value), new Rectangle(new Point(x, y), sizeOfText + new Size(1, 0))); - g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; - g.DrawString(message, font, GetBrush(forecolor ?? _defaultForeground), x + 1, y, PixelTextFormat); + + var r = Get2DRenderer(surfaceID); + if (backcolor.HasValue) r.FillRectangle(backcolor.Value, x, y, sizeOfText.Width + 2, sizeOfText.Height); + r.DrawString(message, font, forecolor ?? _defaultForeground, x + 1, y, PixelTextFormat, TextRenderingHint.SingleBitPerPixelGridFit); } catch (Exception) { @@ -632,17 +545,11 @@ public void Text(int x, int y, string message, Color? forecolor = null, string a y -= oy; } - var pos = new MessagePosition{ X = x, Y = y, Anchor = (MessagePosition.AnchorType)a }; + var pos = new MessagePosition { X = x, Y = y, Anchor = (MessagePosition.AnchorType)a }; _displayManager.OSD.AddGuiText(message, pos, Color.Black, forecolor ?? Color.White); } public void Dispose() - { - UnlockSurface(DisplaySurfaceID.EmuCore); - UnlockSurface(DisplaySurfaceID.Client); - foreach (var brush in _solidBrushes.Values) brush.Dispose(); - foreach (var brush in _pens.Values) brush.Dispose(); - ClearImageCache(); - } + => ClearImageCache(); } } diff --git a/src/BizHawk.Client.Common/Api/Classes/JoypadApi.cs b/src/BizHawk.Client.Common/Api/Classes/JoypadApi.cs index 91b6aebb3d7..e9e6113b7e9 100644 --- a/src/BizHawk.Client.Common/Api/Classes/JoypadApi.cs +++ b/src/BizHawk.Client.Common/Api/Classes/JoypadApi.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; diff --git a/src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs b/src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs index 5ce463ff57e..f20daba70af 100644 --- a/src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs +++ b/src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs @@ -1,8 +1,8 @@ -using System; using System.Collections.Generic; using System.Linq; using BizHawk.Common; +using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Client.Common @@ -188,7 +188,8 @@ private void WriteUnsigned(long addr, uint value, int size, string domain = null public IReadOnlyCollection GetMemoryDomainList() => DomainList.Select(static domain => domain.Name).ToList(); - public uint GetMemoryDomainSize(string name = null) => (uint) NamedDomainOrCurrent(name).Size; + public uint GetMemoryDomainSize(string name) + => (uint) NamedDomainOrCurrent(name).Size; public string GetCurrentMemoryDomain() => Domain.Name; @@ -287,7 +288,7 @@ public float ReadFloat(long addr, string domain = null) LogCallback($"Warning: Attempted read {addr} outside memory size of {d.Size}"); return default; } - return BitConverter.ToSingle(BitConverter.GetBytes(d.PeekUint(addr, _isBigEndian)), 0); + return NumberExtensions.ReinterpretAsF32(d.PeekUint(addr, _isBigEndian)); } public void WriteFloat(long addr, double value, string domain = null) @@ -303,7 +304,7 @@ public void WriteFloat(long addr, double value, string domain = null) LogCallback($"Warning: Attempted write {addr} outside memory size of {d.Size}"); return; } - d.PokeUint(addr, BitConverter.ToUInt32(BitConverter.GetBytes((float) value), 0), _isBigEndian); + d.PokeUint(addr, NumberExtensions.ReinterpretAsUInt32((float) value), _isBigEndian); } public int ReadS8(long addr, string domain = null) => (sbyte) ReadUnsigned(addr, 1, domain); diff --git a/src/BizHawk.Client.Common/Api/Classes/MemorySaveStateApi.cs b/src/BizHawk.Client.Common/Api/Classes/MemorySaveStateApi.cs index d8a89a29a2d..9b2b42cc1c8 100644 --- a/src/BizHawk.Client.Common/Api/Classes/MemorySaveStateApi.cs +++ b/src/BizHawk.Client.Common/Api/Classes/MemorySaveStateApi.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.Common/Api/Classes/MovieApi.cs b/src/BizHawk.Client.Common/Api/Classes/MovieApi.cs index 972c6d83910..5665a52c7d3 100644 --- a/src/BizHawk.Client.Common/Api/Classes/MovieApi.cs +++ b/src/BizHawk.Client.Common/Api/Classes/MovieApi.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -56,7 +55,7 @@ public string GetInputAsMnemonic(int frame) return lg.GenerateLogEntry(); } - public void Save(string filename = null) + public void Save(string filename) { if (_movieSession.Movie.NotActive()) { @@ -66,7 +65,7 @@ public void Save(string filename = null) if (!string.IsNullOrEmpty(filename)) { filename += $".{_movieSession.Movie.PreferredExtension}"; - if (new FileInfo(filename).Exists) + if (File.Exists(filename)) { LogCallback($"File {filename} already exists, will not overwrite"); return; diff --git a/src/BizHawk.Client.Common/Api/Classes/SQLiteApi.cs b/src/BizHawk.Client.Common/Api/Classes/SQLiteApi.cs index 4e07a8d9684..215e0777582 100644 --- a/src/BizHawk.Client.Common/Api/Classes/SQLiteApi.cs +++ b/src/BizHawk.Client.Common/Api/Classes/SQLiteApi.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; @@ -52,7 +51,7 @@ public string OpenDatabase(string name) return "Database Opened Successfully"; } - public string WriteCommand(string query = null) + public string WriteCommand(string query) { if (string.IsNullOrWhiteSpace(query)) return "query is empty"; if (_dbConnection == null) return "Database not open."; @@ -72,7 +71,7 @@ public string WriteCommand(string query = null) return result; } - public object ReadCommand(string query = null) + public object ReadCommand(string query) { if (string.IsNullOrWhiteSpace(query)) return "query is empty"; if (_dbConnection == null) return "Database not open."; diff --git a/src/BizHawk.Client.Common/Api/Classes/SaveStateApi.cs b/src/BizHawk.Client.Common/Api/Classes/SaveStateApi.cs index 88cfdf48b1a..9bbe860e9c5 100644 --- a/src/BizHawk.Client.Common/Api/Classes/SaveStateApi.cs +++ b/src/BizHawk.Client.Common/Api/Classes/SaveStateApi.cs @@ -1,4 +1,3 @@ -using System; using System.IO; namespace BizHawk.Client.Common diff --git a/src/BizHawk.Client.Common/Api/Classes/UserDataApi.cs b/src/BizHawk.Client.Common/Api/Classes/UserDataApi.cs index 91e1d0e45fa..a2bf2a5863b 100644 --- a/src/BizHawk.Client.Common/Api/Classes/UserDataApi.cs +++ b/src/BizHawk.Client.Common/Api/Classes/UserDataApi.cs @@ -1,20 +1,26 @@ -using System; using System.Collections.Generic; using System.Linq; +#if NET5_0_OR_GREATER +using KeyCollectionType = System.Collections.Generic.IReadOnlySet; +#else +using KeyCollectionType = System.Collections.Generic.IReadOnlyCollection; +#endif + namespace BizHawk.Client.Common { public sealed class UserDataApi : IUserDataApi { private readonly IMovieSession _movieSession; -#if NET6_0 - public IReadOnlySet Keys - => throw new NotImplementedException(); -#else - public IReadOnlyCollection Keys - => _movieSession.UserBag.Keys.ToList(); -#endif + public KeyCollectionType Keys + { + get + { + ICollection keys = _movieSession.UserBag.Keys; + return (keys as KeyCollectionType) ?? keys.ToList(); + } + } public UserDataApi(IMovieSession movieSession) => _movieSession = movieSession; diff --git a/src/BizHawk.Client.Common/Api/ClientWebSocketWrapper.cs b/src/BizHawk.Client.Common/Api/ClientWebSocketWrapper.cs index 9f754573936..65c774dffc4 100644 --- a/src/BizHawk.Client.Common/Api/ClientWebSocketWrapper.cs +++ b/src/BizHawk.Client.Common/Api/ClientWebSocketWrapper.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Net.WebSockets; using System.Text; using System.Threading; @@ -18,7 +17,9 @@ public struct ClientWebSocketWrapper public ClientWebSocketWrapper(Uri uri, CancellationToken? cancellationToken = null) { _w = new ClientWebSocket(); +#pragma warning disable MA0040 // Analyzer not smart enough to recognise this _w.ConnectAsync(uri, cancellationToken ?? CancellationToken.None).Wait(); +#pragma warning restore MA0040 } /// calls diff --git a/src/BizHawk.Client.Common/Api/CoreSystem.cs b/src/BizHawk.Client.Common/Api/CoreSystem.cs deleted file mode 100644 index c35e36f73a3..00000000000 --- a/src/BizHawk.Client.Common/Api/CoreSystem.cs +++ /dev/null @@ -1,45 +0,0 @@ -namespace BizHawk.Client.Common -{ - /// - /// Enumeration of each system emulated by BizHawk - /// - public enum CoreSystem - { - Null = 0, - TI83, - AppleII, - Commodore64, - Atari2600, - Atari7800, - Lynx, - ColecoVision, - Intellivision, - GameBoy, - GameBoyLink, - GameBoyAdvance, - NintendoDS, - Nintendo64, - NES, - SNES, - PCEngine, - Genesis, - Saturn, - MasterSystem, - Playstation, - WonderSwan, - Libretro, - VirtualBoy, - Vectrex, - NeoGeoPocket, - ZXSpectrum, - AmstradCPC, - GGL, - ChannelF, - Odyssey2, - Arcade, - MSX, - SuperGameBoy, - UzeBox, - PcFx - } -} diff --git a/src/BizHawk.Client.Common/Api/DisplaySurfaceID.cs b/src/BizHawk.Client.Common/Api/DisplaySurfaceID.cs index 4358fc3f5f0..e0b69803cd5 100644 --- a/src/BizHawk.Client.Common/Api/DisplaySurfaceID.cs +++ b/src/BizHawk.Client.Common/Api/DisplaySurfaceID.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Diagnostics.CodeAnalysis; namespace BizHawk.Client.Common @@ -15,7 +14,7 @@ public enum DisplaySurfaceID : int public static class DisplaySurfaceIDParser { #pragma warning disable BHI1005 // switching on string, possibly from user input, ArgumentException is correct here - [return: NotNullIfNotNull("str")] + [return: NotNullIfNotNull(nameof(str))] public static DisplaySurfaceID? Parse(string? str) => str?.ToLowerInvariant() switch { null => null, // this makes it easy to cascade the "remembered" value diff --git a/src/BizHawk.Client.Common/Api/ExternalToolAttributes.cs b/src/BizHawk.Client.Common/Api/ExternalToolAttributes.cs index 59c8b9ecfe1..c725a8f2f60 100644 --- a/src/BizHawk.Client.Common/Api/ExternalToolAttributes.cs +++ b/src/BizHawk.Client.Common/Api/ExternalToolAttributes.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.Linq; @@ -9,6 +8,7 @@ namespace BizHawk.Client.Common { +#pragma warning disable MA0057 // oops, should have called these `*Attribute`, too late now --yoshi public static class ExternalToolApplicability { /// This class is not deprecated, do not remove it. @@ -55,33 +55,6 @@ public override bool NotApplicableTo(string romHash, string? sysID) => sysID != _sysID || !_romHashes.Contains(romHash); } - [AttributeUsage(AttributeTargets.Class)] - [Obsolete("renamed RomWhitelist-->RomList")] - public sealed class RomWhitelist : ExternalToolApplicabilityAttributeBase - { - private readonly IList _romHashes; - - private readonly string _sysID; - - [Obsolete("replace CoreSystem with string from VSystemID.Raw")] - public RomWhitelist(CoreSystem system, params string[] romHashes) - : this(SystemIdConverter.ConvertBack(system), romHashes) {} - - public RomWhitelist(string sysID, params string[] romHashes) - { - if (sysID is VSystemID.Raw.NULL) throw new ArgumentException("there are no roms for the NULL system", nameof(sysID)); - if (!romHashes.All(NumericStringExtensions.IsHex)) throw new ArgumentException("misformatted hash", nameof(romHashes)); - _romHashes = romHashes.ToList(); - _sysID = sysID; - } - - public override bool NotApplicableTo(string sysID) - => sysID != _sysID; - - public override bool NotApplicableTo(string romHash, string? sysID) - => sysID != _sysID || !_romHashes.Contains(romHash); - } - [AttributeUsage(AttributeTargets.Class)] public sealed class SingleRom : ExternalToolApplicabilityAttributeBase { @@ -89,10 +62,6 @@ public sealed class SingleRom : ExternalToolApplicabilityAttributeBase private readonly string _sysID; - [Obsolete("replace CoreSystem with string from VSystemID.Raw")] - public SingleRom(CoreSystem system, string romHash) - : this(SystemIdConverter.ConvertBack(system), romHash) {} - public SingleRom(string sysID, string romHash) { if (sysID is VSystemID.Raw.NULL) throw new ArgumentException("there are no roms for the NULL system", nameof(sysID)); @@ -113,10 +82,6 @@ public sealed class SingleSystem : ExternalToolApplicabilityAttributeBase { private readonly string _sysID; - [Obsolete("replace CoreSystem with string from VSystemID.Raw")] - public SingleSystem(CoreSystem system) - : this(SystemIdConverter.ConvertBack(system)) {} - public SingleSystem(string sysID) => _sysID = sysID; @@ -130,14 +95,13 @@ public override bool NotApplicableTo(string romHash, string? sysID) public abstract class ExternalToolApplicabilityAttributeBase : Attribute { - protected static readonly BizHawkSystemIdToEnumConverter SystemIdConverter = new(); - public abstract bool NotApplicableTo(string sysID); public abstract bool NotApplicableTo(string romHash, string? sysID); public class DuplicateException : Exception {} } +#pragma warning disable MA0057 [AttributeUsage(AttributeTargets.Class)] public sealed class ExternalToolAttribute : Attribute diff --git a/src/BizHawk.Client.Common/Api/HttpCommunication.cs b/src/BizHawk.Client.Common/Api/HttpCommunication.cs index 1270b8d058c..63a4571f27e 100644 --- a/src/BizHawk.Client.Common/Api/HttpCommunication.cs +++ b/src/BizHawk.Client.Common/Api/HttpCommunication.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; diff --git a/src/BizHawk.Client.Common/Api/IExternalApiProvider.cs b/src/BizHawk.Client.Common/Api/IExternalApiProvider.cs index 2842c9f0d22..72011391b67 100644 --- a/src/BizHawk.Client.Common/Api/IExternalApiProvider.cs +++ b/src/BizHawk.Client.Common/Api/IExternalApiProvider.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; namespace BizHawk.Client.Common diff --git a/src/BizHawk.Client.Common/Api/Interfaces/IEmuClientApi.cs b/src/BizHawk.Client.Common/Api/Interfaces/IEmuClientApi.cs index 55e95cd7811..94c13562a35 100644 --- a/src/BizHawk.Client.Common/Api/Interfaces/IEmuClientApi.cs +++ b/src/BizHawk.Client.Common/Api/Interfaces/IEmuClientApi.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; namespace BizHawk.Client.Common diff --git a/src/BizHawk.Client.Common/Api/Interfaces/IGameInfoApi.cs b/src/BizHawk.Client.Common/Api/Interfaces/IGameInfoApi.cs deleted file mode 100644 index b08c03bd35b..00000000000 --- a/src/BizHawk.Client.Common/Api/Interfaces/IGameInfoApi.cs +++ /dev/null @@ -1,19 +0,0 @@ -#nullable enable - -using System; -using System.Collections.Generic; - -using BizHawk.Emulation.Common; - -namespace BizHawk.Client.Common -{ - [Obsolete("use IEmulationApi")] - public interface IGameInfoApi : IExternalApi - { - string GetBoardType(); - - IGameInfo? GetGameInfo(); - - IReadOnlyDictionary GetOptions(); - } -} diff --git a/src/BizHawk.Client.Common/Api/Interfaces/IGuiApi.cs b/src/BizHawk.Client.Common/Api/Interfaces/IGuiApi.cs index e10e1eb65e9..a2c3311037a 100644 --- a/src/BizHawk.Client.Common/Api/Interfaces/IGuiApi.cs +++ b/src/BizHawk.Client.Common/Api/Interfaces/IGuiApi.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Drawing.Imaging; @@ -7,18 +6,24 @@ namespace BizHawk.Client.Common public interface IGuiApi : IDisposable, IExternalApi { void ToggleCompositingMode(); + + [Obsolete("No longer supported, returns null always.")] ImageAttributes GetAttributes(); + [Obsolete("No longer supported, no-op.")] void SetAttributes(ImageAttributes a); + void WithSurface(DisplaySurfaceID surfaceID, Action drawingCallsFunc); + + [Obsolete("use the other overload e.g. `APIs.Gui.WithSurface(..., gui => { gui.DrawLine(...); });`")] void WithSurface(DisplaySurfaceID surfaceID, Action drawingCallsFunc); - [Obsolete] + [Obsolete("No longer supported, no-op.")] void DrawNew(string name, bool clear = true); - [Obsolete] + [Obsolete("No longer supported, no-op.")] void DrawFinish(); - [Obsolete] + [Obsolete("Always true")] bool HasGUISurface { get; } void SetPadding(int all); @@ -32,7 +37,7 @@ public interface IGuiApi : IDisposable, IExternalApi void ClearText(); void SetDefaultForegroundColor(Color color); void SetDefaultBackgroundColor(Color color); - Color? GetDefaultTextBackground(); + Color GetDefaultTextBackground(); void SetDefaultTextBackground(Color color); void SetDefaultPixelFont(string fontfamily); void DrawBezier(Point p1, Point p2, Point p3, Point p4, Color? color = null, DisplaySurfaceID? surfaceID = null); diff --git a/src/BizHawk.Client.Common/Api/Interfaces/IInputApi.cs b/src/BizHawk.Client.Common/Api/Interfaces/IInputApi.cs index 6a1ffe9c88f..442bfa8f4f0 100644 --- a/src/BizHawk.Client.Common/Api/Interfaces/IInputApi.cs +++ b/src/BizHawk.Client.Common/Api/Interfaces/IInputApi.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Client.Common @@ -18,7 +17,7 @@ public interface IInputApi : IExternalApi /// See for keyboard key names, though some are overridden by (check the source). /// /// - [Obsolete] + [Obsolete($"consider using {nameof(GetPressedButtons)}/{nameof(GetPressedAxes)}/{nameof(GetMouse)}")] Dictionary Get(); /// diff --git a/src/BizHawk.Client.Common/Api/Interfaces/IToolApi.cs b/src/BizHawk.Client.Common/Api/Interfaces/IToolApi.cs index 924384f155a..842afee7bbc 100644 --- a/src/BizHawk.Client.Common/Api/Interfaces/IToolApi.cs +++ b/src/BizHawk.Client.Common/Api/Interfaces/IToolApi.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Client.Common diff --git a/src/BizHawk.Client.Common/Api/Interfaces/IUserDataApi.cs b/src/BizHawk.Client.Common/Api/Interfaces/IUserDataApi.cs index 497aff23b24..00993cc5d9d 100644 --- a/src/BizHawk.Client.Common/Api/Interfaces/IUserDataApi.cs +++ b/src/BizHawk.Client.Common/Api/Interfaces/IUserDataApi.cs @@ -4,7 +4,7 @@ namespace BizHawk.Client.Common { public interface IUserDataApi : IExternalApi { -#if NET6_0 +#if NET5_0_OR_GREATER IReadOnlySet Keys { get; } #else IReadOnlyCollection Keys { get; } diff --git a/src/BizHawk.Client.Common/Api/MemoryMappedFiles.cs b/src/BizHawk.Client.Common/Api/MemoryMappedFiles.cs index 669f0ce024f..ff1249563b8 100644 --- a/src/BizHawk.Client.Common/Api/MemoryMappedFiles.cs +++ b/src/BizHawk.Client.Common/Api/MemoryMappedFiles.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO.MemoryMappedFiles; using System.Text; diff --git a/src/BizHawk.Client.Common/Api/SocketServer.cs b/src/BizHawk.Client.Common/Api/SocketServer.cs index ba8e7b7e64c..aa56b8955fe 100644 --- a/src/BizHawk.Client.Common/Api/SocketServer.cs +++ b/src/BizHawk.Client.Common/Api/SocketServer.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Net; using System.Net.Sockets; @@ -24,7 +23,7 @@ public static byte[] PrefixWithLength(byte[] payload) private readonly Func _takeScreenshotCallback; - private (string HostIP, int Port) _targetAddr; + private (string HostIP, ushort Port) _targetAddr; public bool Connected { get; private set; } @@ -38,7 +37,7 @@ public string IP } } - public int Port + public ushort Port { get => _targetAddr.Port; set @@ -48,7 +47,7 @@ public int Port } } - public (string HostIP, int Port) TargetAddress + public (string HostIP, ushort Port) TargetAddress { get => _targetAddr; set @@ -66,7 +65,7 @@ public int Port public bool Successful { get; private set; } - public SocketServer(Func takeScreenshotCallback, ProtocolType protocol, string ip, int port) + public SocketServer(Func takeScreenshotCallback, ProtocolType protocol, string ip, ushort port) { _protocol = protocol; ReinitSocket(out _soc); diff --git a/src/BizHawk.Client.Common/Api/WebSocketServer.cs b/src/BizHawk.Client.Common/Api/WebSocketServer.cs index da6a34a5100..be68f7c51d6 100644 --- a/src/BizHawk.Client.Common/Api/WebSocketServer.cs +++ b/src/BizHawk.Client.Common/Api/WebSocketServer.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Threading; namespace BizHawk.Client.Common diff --git a/src/BizHawk.Client.Common/ArgParser.cs b/src/BizHawk.Client.Common/ArgParser.cs index 0d8350edd3e..73297b5e3bc 100644 --- a/src/BizHawk.Client.Common/ArgParser.cs +++ b/src/BizHawk.Client.Common/ArgParser.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.Linq; using System.IO; @@ -37,7 +36,7 @@ public static void ParseArguments(out ParsedCLIFlags parsed, string[] args) bool? startFullscreen = null; string? luaScript = null; bool? luaConsole = null; - int? socketPort = null; + ushort? socketPort = null; string? socketIP = null; string? mmfFilename = null; string? urlGet = null; @@ -79,20 +78,17 @@ public static void ParseArguments(out ParsedCLIFlags parsed, string[] args) } else if (argDowncased.StartsWithOrdinal("--dump-type=")) { + // ignored unless `--dump-name` also passed cmdDumpType = argDowncased.Substring(argDowncased.IndexOf('=') + 1); } else if (argDowncased.StartsWithOrdinal("--dump-frames=")) { + // comma-separated list of integers, indices of frames which should be included in the A/V dump (encoding) string list = argDowncased.Substring(argDowncased.IndexOf('=') + 1); - string[] items = list.Split(','); - currAviWriterFrameList = new HashSet(); - foreach (string item in items) - { - currAviWriterFrameList.Add(int.Parse(item)); - } - + currAviWriterFrameList = new(); + currAviWriterFrameList.AddRange(list.Split(',').Select(int.Parse)); // automatically set dump length to maximum frame - autoDumpLength = currAviWriterFrameList.Order().Last(); + autoDumpLength = currAviWriterFrameList.Max(); } else if (argDowncased.StartsWithOrdinal("--version")) { @@ -100,6 +96,7 @@ public static void ParseArguments(out ParsedCLIFlags parsed, string[] args) } else if (argDowncased.StartsWithOrdinal("--dump-name=")) { + // ignored unless `--dump-type` also passed cmdDumpName = arg.Substring(arg.IndexOf('=') + 1); } else if (argDowncased.StartsWithOrdinal("--dump-length=")) @@ -123,6 +120,7 @@ public static void ParseArguments(out ParsedCLIFlags parsed, string[] args) else if (argDowncased.StartsWithOrdinal("--lua=")) { luaScript = arg.Substring(arg.IndexOf('=') + 1); + // implies `--luaconsole` luaConsole = true; } else if (argDowncased.StartsWithOrdinal("--luaconsole")) @@ -131,15 +129,18 @@ public static void ParseArguments(out ParsedCLIFlags parsed, string[] args) } else if (argDowncased.StartsWithOrdinal("--socket_port=")) { - var port = int.TryParse(argDowncased.Substring(argDowncased.IndexOf('=') + 1), out var i1) ? i1 : default; + // must be paired with `--socket_ip` + var port = ushort.TryParse(arg.Substring(14), out var i1) ? i1 : (ushort) 0; if (port > 0) socketPort = port; } else if (argDowncased.StartsWithOrdinal("--socket_ip=")) { + // must be paired with `--socket_port` socketIP = argDowncased.Substring(argDowncased.IndexOf('=') + 1); } else if (argDowncased.StartsWithOrdinal("--socket_udp")) { + // ignored unless `--socket_ip --socket_port` also passed socketProtocol = ProtocolType.Udp; } else if (argDowncased.StartsWithOrdinal("--mmf=")) @@ -156,6 +157,8 @@ public static void ParseArguments(out ParsedCLIFlags parsed, string[] args) } else if (argDowncased.StartsWithOrdinal("--audiosync=")) { + // `true` is the only truthy value, all else falsey + // if not set, uses remembered state from config audiosync = argDowncased.Substring(argDowncased.IndexOf('=') + 1) == "true"; } else if (argDowncased.StartsWithOrdinal("--open-ext-tool-dll=")) @@ -167,6 +170,10 @@ public static void ParseArguments(out ParsedCLIFlags parsed, string[] args) } else if (argDowncased.StartsWithOrdinal("--userdata=")) { + // pairs in the format `k1:v1;k2:v2` (mind your shell escape sequences) + // if the value is `true`/`false` it's interpreted as a boolean, + // if it's a valid 32-bit signed integer e.g. `-1234` it's interpreted as such, if it's a valid 32-bit float e.g. `12.34` it's interpreted as such, + // else it's interpreted as a string userdataUnparsedPairs = new(); foreach (var s in arg.Substring(11).Split(';')) { @@ -184,7 +191,7 @@ public static void ParseArguments(out ParsedCLIFlags parsed, string[] args) var httpAddresses = urlGet == null && urlPost == null ? ((string?, string?)?) null // don't bother : (urlGet, urlPost); - (string, int)? socketAddress; + (string, ushort)? socketAddress; if (socketIP == null && socketPort == null) { socketAddress = null; // don't bother diff --git a/src/BizHawk.Client.Common/BitmapBufferVideoProvider.cs b/src/BizHawk.Client.Common/BitmapBufferVideoProvider.cs index 260cbb4db84..6c9e07ff58f 100644 --- a/src/BizHawk.Client.Common/BitmapBufferVideoProvider.cs +++ b/src/BizHawk.Client.Common/BitmapBufferVideoProvider.cs @@ -1,7 +1,5 @@ -using System; - +using BizHawk.Bizware.Graphics; using BizHawk.Emulation.Common; -using BizHawk.Bizware.BizwareGL; namespace BizHawk.Client.Common { diff --git a/src/BizHawk.Client.Common/BizHawk.Client.Common.csproj b/src/BizHawk.Client.Common/BizHawk.Client.Common.csproj index 526ece94b26..2cf384f1edf 100644 --- a/src/BizHawk.Client.Common/BizHawk.Client.Common.csproj +++ b/src/BizHawk.Client.Common/BizHawk.Client.Common.csproj @@ -12,8 +12,9 @@ + - + diff --git a/src/BizHawk.Client.Common/BreakpointList.cs b/src/BizHawk.Client.Common/BreakpointList.cs index b43df421ae7..3b135b3ffbf 100644 --- a/src/BizHawk.Client.Common/BreakpointList.cs +++ b/src/BizHawk.Client.Common/BreakpointList.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.Common/Controller.cs b/src/BizHawk.Client.Common/Controller.cs index df66988c532..e359e2349a1 100644 --- a/src/BizHawk.Client.Common/Controller.cs +++ b/src/BizHawk.Client.Common/Controller.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; @@ -148,10 +147,7 @@ public void Overrides(OverrideAdapter controller) _axes[button] = controller.AxisValue(button); } - foreach (var button in controller.InversedButtons) - { - _buttons[button] ^= true; - } + foreach (var button in controller.InversedButtons) _buttons[button] = !_buttons[button]; } public void BindMulti(string button, string controlString) diff --git a/src/BizHawk.Client.Common/DialogControllerExtensions.cs b/src/BizHawk.Client.Common/DialogControllerExtensions.cs index ef1ad31d50f..768dd0a6e26 100644 --- a/src/BizHawk.Client.Common/DialogControllerExtensions.cs +++ b/src/BizHawk.Client.Common/DialogControllerExtensions.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; namespace BizHawk.Client.Common diff --git a/src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs b/src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs index 706d613035a..01927e2522e 100644 --- a/src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs +++ b/src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs @@ -1,7 +1,6 @@ // TODO // we could flag textures as 'actually' render targets (keep a reference to the render target?) which could allow us to convert between them more quickly in some cases -using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Text; @@ -9,11 +8,9 @@ using System.Numerics; using System.Runtime.InteropServices; -using BizHawk.Bizware.BizwareGL; -using BizHawk.Bizware.BizwareGL.DrawingExtensions; +using BizHawk.Bizware.Graphics; using BizHawk.Client.Common.FilterManager; using BizHawk.Client.Common.Filters; -using BizHawk.Common.CollectionExtensions; using BizHawk.Common.PathExtensions; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Consoles.Nintendo.N3DS; @@ -29,23 +26,23 @@ namespace BizHawk.Client.Common /// public abstract class DisplayManagerBase : IDisposable { - private static DisplaySurface CreateDisplaySurface(int w, int h) => new(w, h); - protected class DisplayManagerRenderTargetProvider : IRenderTargetProvider { - private readonly Func _callback; + private readonly Func _callback; - RenderTarget IRenderTargetProvider.Get(Size size) + public IRenderTarget Get(Size size) { return _callback(size); } - public DisplayManagerRenderTargetProvider(Func callback) + public DisplayManagerRenderTargetProvider(Func callback) { _callback = callback; } } + public const int DEFAULT_DPI = 96; + public OSDManager OSD { get; } protected Config GlobalConfig; @@ -67,9 +64,6 @@ protected DisplayManagerBase( _gl = gl; _renderer = renderer; - // it's sort of important for these to be initialized to something nonzero - _currEmuWidth = _currEmuHeight = 1; - _videoTextureFrugalizer = new(_gl); _shaderChainFrugalizers = new RenderTargetFrugalizer[16]; // hacky hardcoded limit.. need some other way to manage these @@ -88,7 +82,7 @@ protected DisplayManagerBase( LoadCustomFont(fceux); } - if (dispMethod is EDispMethod.OpenGL or EDispMethod.D3D9) + if (dispMethod is EDispMethod.OpenGL or EDispMethod.D3D11) { var fiHq2x = new FileInfo(Path.Combine(PathUtils.ExeDirectoryPath, "Shaders/BizHawk/hq2x.cgp")); if (fiHq2x.Exists) @@ -102,7 +96,7 @@ protected DisplayManagerBase( using var stream = fiScanlines.OpenRead(); _shaderChainScanlines = new(_gl, new(stream), Path.Combine(PathUtils.ExeDirectoryPath, "Shaders/BizHawk")); } - var bicubicPath = dispMethod == EDispMethod.D3D9 ? "Shaders/BizHawk/bicubic-normal.cgp" : "Shaders/BizHawk/bicubic-fast.cgp"; + var bicubicPath = dispMethod is EDispMethod.D3D11 ? "Shaders/BizHawk/bicubic-normal.cgp" : "Shaders/BizHawk/bicubic-fast.cgp"; var fiBicubic = new FileInfo(Path.Combine(PathUtils.ExeDirectoryPath, bicubicPath)); if (fiBicubic.Exists) { @@ -111,10 +105,9 @@ protected DisplayManagerBase( } } - _apiHawkSurfaceSets[DisplaySurfaceID.EmuCore] = new(CreateDisplaySurface); - _apiHawkSurfaceSets[DisplaySurfaceID.Client] = new(CreateDisplaySurface); - _apiHawkSurfaceFrugalizers[DisplaySurfaceID.EmuCore] = new(_gl); - _apiHawkSurfaceFrugalizers[DisplaySurfaceID.Client] = new(_gl); + _imGuiResourceCache = new ImGuiResourceCache(_gl); + _apiHawkIDTo2DRenderer.Add(DisplaySurfaceID.EmuCore, _gl.Create2DRenderer(_imGuiResourceCache)); + _apiHawkIDTo2DRenderer.Add(DisplaySurfaceID.Client, _gl.Create2DRenderer(_imGuiResourceCache)); RefreshUserShader(); } @@ -141,11 +134,14 @@ public void Dispose() ActivateOpenGLContext(); _videoTextureFrugalizer.Dispose(); - foreach (var f in _apiHawkSurfaceFrugalizers.Values) + + foreach (var r in _apiHawkIDTo2DRenderer.Values) { - f.Dispose(); + r.Dispose(); } + _imGuiResourceCache.Dispose(); + foreach (var f in _shaderChainFrugalizers) { f?.Dispose(); @@ -170,12 +166,6 @@ public void Dispose() // layer resources protected FilterProgram _currentFilterProgram; - /// - /// these variables will track the dimensions of the last frame's (or the next frame? this is confusing) emulator native output size - /// THIS IS OLD JUNK. I should get rid of it, I think. complex results from the last filter ingestion should be saved instead. - /// - private int _currEmuWidth, _currEmuHeight; - /// /// additional pixels added at the unscaled level for the use of lua drawing. essentially increases the input video provider dimensions /// @@ -193,8 +183,6 @@ public void Dispose() private readonly TextureFrugalizer _videoTextureFrugalizer; - private readonly Dictionary _apiHawkSurfaceFrugalizers = new(); - protected readonly RenderTargetFrugalizer[] _shaderChainFrugalizers; private readonly RetroShaderChain _shaderChainHq2X; @@ -263,7 +251,7 @@ public void RefreshUserShader() private FilterProgram BuildDefaultChain(Size chainInSize, Size chainOutSize, bool includeOSD, bool includeUserFilters) { // select user special FX shader chain - var selectedChainProperties = new Dictionary(); + KeyValuePair[] selectedChainProperties = null; RetroShaderChain selectedChain = null; switch (GlobalConfig.TargetDisplayFilter) { @@ -272,7 +260,7 @@ private FilterProgram BuildDefaultChain(Size chainInSize, Size chainOutSize, boo break; case 2 when _shaderChainScanlines is { Available: true }: selectedChain = _shaderChainScanlines; - selectedChainProperties["uIntensity"] = 1.0f - GlobalConfig.TargetScanlineFilterIntensity / 256.0f; + selectedChainProperties = [ new("uIntensity", 1.0f - GlobalConfig.TargetScanlineFilterIntensity / 256.0f) ]; break; case 3 when _shaderChainUser is { Available: true }: selectedChain = _shaderChainUser; @@ -317,6 +305,10 @@ private FilterProgram BuildDefaultChain(Size chainInSize, Size chainOutSize, boo if (size.Width < 1) size.Width = 1; if (size.Height < 1) size.Height = 1; + // if either of the dimensions exceed the maximum size of a texture, we need to constrain them + size.Width = Math.Min(size.Width, _gl.MaxTextureDimension); + size.Height = Math.Min(size.Height, _gl.MaxTextureDimension); + var fPadding = new FinalPresentation(size); chain.AddFilter(fPadding, "padding"); fPadding.Config_PadOnly = true; @@ -390,7 +382,7 @@ private FilterProgram BuildDefaultChain(Size chainInSize, Size chainOutSize, boo return chain; } - private static void AppendRetroShaderChain(FilterProgram program, string name, RetroShaderChain retroChain, Dictionary properties) + private static void AppendRetroShaderChain(FilterProgram program, string name, RetroShaderChain retroChain, KeyValuePair[] properties) { for (var i = 0; i < retroChain.Passes.Length; i++) { @@ -403,16 +395,9 @@ private static void AppendRetroShaderChain(FilterProgram program, string name, R private void AppendApiHawkLayer(FilterProgram chain, DisplaySurfaceID surfaceID) { - var luaNativeSurface = _apiHawkSurfaceSets[surfaceID].GetCurrent(); - if (luaNativeSurface == null) - { - return; - } - - var luaNativeTexture = _apiHawkSurfaceFrugalizers[surfaceID].Get(luaNativeSurface); - var fLuaLayer = new LuaLayer(); - fLuaLayer.SetTexture(luaNativeTexture); - chain.AddFilter(fLuaLayer, surfaceID.GetName()); + var apiHawkRenderer = _apiHawkIDTo2DRenderer[surfaceID]; + var fApiHawkLayer = new ApiHawkLayer(apiHawkRenderer); + chain.AddFilter(fApiHawkLayer, surfaceID.GetName()); } protected abstract Point GraphicsControlPointToClient(Point p); @@ -456,6 +441,8 @@ public Point TransformPoint(Point p) protected abstract Size GetGraphicsControlSize(); + protected abstract int GetGraphicsControlDpi(); + /// /// This will receive an emulated output frame from an IVideoProvider and run it through the complete frame processing pipeline /// Then it will stuff it into the bound PresentationPanel. @@ -503,6 +490,7 @@ public BitmapBuffer RenderOffscreen(IVideoProvider videoProvider, bool includeOS UpdateSourceInternal(job); return job.OffscreenBb; } + /// /// Does the display process to an offscreen buffer, suitable for a Lua-inclusive movie. /// @@ -791,20 +779,25 @@ private FilterProgram UpdateSourceInternal(JobInfo job) vw += padding.Horizontal; vh += padding.Vertical; - //in case the user requested so much padding that the dimensions are now negative, just turn it to something small. + // in case the user requested so much padding that the dimensions are now negative, just turn it to something small. if (vw < 1) vw = 1; if (vh < 1) vh = 1; + // if either of the dimensions exceed the maximum size of a texture, we need to constrain them + vw = Math.Min(vw, _gl.MaxTextureDimension); + vh = Math.Min(vh, _gl.MaxTextureDimension); + BitmapBuffer bb = null; - Texture2d videoTexture = null; + ITexture2D videoTexture = null; if (!simulate) { - if (videoProvider is IGLTextureProvider glTextureProvider && _gl.DispMethodEnum == EDispMethod.OpenGL) + if (videoProvider is IGLTextureProvider glTextureProvider) { // FYI: this is a million years from happening on n64, since it's all geriatric non-FBO code - videoTexture = _gl.WrapGLTexture2d(new(glTextureProvider.GetGLTexture()), bufferWidth, bufferHeight); + videoTexture = _gl.WrapGLTexture2D(glTextureProvider.GetGLTexture(), bufferWidth, bufferHeight); } - else + + if (videoTexture == null) { // wrap the VideoProvider data in a BitmapBuffer (no point to refactoring that many IVideoProviders) bb = new(bufferWidth, bufferHeight, videoProvider.GetVideoBuffer()); @@ -812,16 +805,9 @@ private FilterProgram UpdateSourceInternal(JobInfo job) //now, acquire the data sent from the videoProvider into a texture videoTexture = _videoTextureFrugalizer.Get(bb); - - // lets not use this. lets define BizwareGL to make clamp by default (TBD: check opengl) - // _gl.SetTextureWrapMode(videoTexture, true); } } - // record the size of what we received, since lua and stuff is gonna want to draw onto it - _currEmuWidth = bufferWidth; - _currEmuHeight = bufferHeight; - //build the default filter chain and set it up with services filters will need var chainInsize = new Size(bufferWidth, bufferHeight); @@ -829,6 +815,8 @@ private FilterProgram UpdateSourceInternal(JobInfo job) filterProgram.GuiRenderer = _renderer; filterProgram.GL = _gl; + filterProgram.ControlDpi = GetGraphicsControlDpi(); + //setup the source image filter var fInput = (SourceImage)filterProgram["input"]; fInput.Texture = videoTexture; @@ -865,10 +853,8 @@ private FilterProgram UpdateSourceInternal(JobInfo job) public void Blank() { ActivateGraphicsControlContext(); - _gl.BeginScene(); - _gl.BindRenderTarget(null); + _gl.BindDefaultRenderTarget(); _gl.ClearColor(Color.Black); - _gl.EndScene(); SwapBuffersOfGraphicsControl(); } @@ -876,27 +862,20 @@ protected virtual void UpdateSourceDrawingWork(JobInfo job) { if (!job.Offscreen) throw new InvalidOperationException(); - // begin rendering on this context - // should this have been done earlier? - // do i need to check this on an intel video card to see if running excessively is a problem? (it used to be in the FinalTarget command below, shouldn't be a problem) - //GraphicsControl.Begin(); // CRITICAL POINT for yabause+GL - //TODO - auto-create and age these (and dispose when old) var rtCounter = 0; // ReSharper disable once AccessToModifiedClosure _currentFilterProgram.RenderTargetProvider = new DisplayManagerRenderTargetProvider(size => _shaderChainFrugalizers[rtCounter++].Get(size)); - _gl.BeginScene(); RunFilterChainSteps(ref rtCounter, out var rtCurr, out _); - _gl.EndScene(); - job.OffscreenBb = rtCurr.Texture2d.Resolve(); + job.OffscreenBb = rtCurr.Resolve(); job.OffscreenBb.DiscardAlpha(); } - protected void RunFilterChainSteps(ref int rtCounter, out RenderTarget rtCurr, out bool inFinalTarget) + protected void RunFilterChainSteps(ref int rtCounter, out IRenderTarget rtCurr, out bool inFinalTarget) { - Texture2d texCurr = null; + ITexture2D texCurr = null; rtCurr = null; inFinalTarget = false; foreach (var step in _currentFilterProgram.Program) switch (step.Type) @@ -917,7 +896,7 @@ protected void RunFilterChainSteps(ref int rtCounter, out RenderTarget rtCurr, o break; case FilterProgram.ProgramStepType.FinalTarget: _currentFilterProgram.CurrRenderTarget = rtCurr = null; - _gl.BindRenderTarget(rtCurr); + _gl.BindDefaultRenderTarget(); inFinalTarget = true; break; default: @@ -931,7 +910,7 @@ private void LoadCustomFont(Stream fontStream) try { var fontData = new byte[fontStream.Length]; - fontStream.Read(fontData, 0, (int)fontStream.Length); + _ = fontStream.Read(fontData, 0, (int)fontStream.Length); Marshal.Copy(fontData, 0, data, (int)fontStream.Length); CustomFonts.AddMemoryFont(data, fontData.Length); } @@ -942,87 +921,34 @@ private void LoadCustomFont(Stream fontStream) } } - private readonly Dictionary _apiHawkIDToSurface = new(); - - /// Can't this just be a prop of ? --yoshi - private readonly Dictionary _apiHawkSurfaceToID = new(); - - private readonly Dictionary> _apiHawkSurfaceSets = new(); + private readonly ImGuiResourceCache _imGuiResourceCache; + private readonly Dictionary _apiHawkIDTo2DRenderer = new(); /// - /// Peeks a locked lua surface, or returns null if it isn't locked + /// Gets an ApiHawk 2D renderer, suitable for drawing with Gui/lua apis and such + /// The size of this surface might change between different calls + /// Implicitly, if the size changes the surface will be cleared /// - public IDisplaySurface PeekApiHawkLockedSurface(DisplaySurfaceID surfaceID) - => _apiHawkIDToSurface.TryGetValue(surfaceID, out var surface) ? surface : null; - - public IDisplaySurface LockApiHawkSurface(DisplaySurfaceID surfaceID, bool clear) - { - if (_apiHawkIDToSurface.ContainsKey(surfaceID)) - { - throw new InvalidOperationException($"ApiHawk/Lua surface is already locked: {surfaceID.GetName()}"); - } - - var sdss = _apiHawkSurfaceSets.GetValueOrPut(surfaceID, static _ => new(CreateDisplaySurface)); - - // placeholder logic for more abstracted surface definitions from filter chain - var (currNativeWidth, currNativeHeight) = GetPanelNativeSize(); - currNativeWidth += ClientExtraPadding.Left + ClientExtraPadding.Right; - currNativeHeight += ClientExtraPadding.Top + ClientExtraPadding.Bottom; - - var (width, height) = surfaceID switch - { - DisplaySurfaceID.EmuCore => (GameExtraPadding.Left + _currEmuWidth + GameExtraPadding.Right, GameExtraPadding.Top + _currEmuHeight + GameExtraPadding.Bottom), - DisplaySurfaceID.Client => (currNativeWidth, currNativeHeight), - _ => throw new InvalidOperationException() - }; - - IDisplaySurface ret = sdss.AllocateSurface(width, height, clear); - _apiHawkIDToSurface[surfaceID] = ret; - _apiHawkSurfaceToID[ret] = surfaceID; - return ret; - } + public I2DRenderer GetApiHawk2DRenderer(DisplaySurfaceID surfaceID) + => _apiHawkIDTo2DRenderer[surfaceID]; public void ClearApiHawkSurfaces() { - foreach (var kvp in _apiHawkSurfaceSets) + foreach (var renderer in _apiHawkIDTo2DRenderer.Values) { - try - { - if (PeekApiHawkLockedSurface(kvp.Key) == null) - { - var surfLocked = LockApiHawkSurface(kvp.Key, true); - if (surfLocked != null) - { - UnlockApiHawkSurface(surfLocked); - } - } - - _apiHawkSurfaceSets[kvp.Key].SetPending(null); - } - catch (InvalidOperationException) - { - // ignored - } + renderer.Clear(); } } - /// unlocks this IDisplaySurface which had better have been locked as a lua surface - /// already unlocked - public void UnlockApiHawkSurface(IDisplaySurface surface) + public void DiscardApiHawkSurfaces() { - if (surface is not DisplaySurface dispSurfaceImpl) - { - throw new ArgumentException("don't mix " + nameof(IDisplaySurface) + " implementations!", nameof(surface)); - } - - if (!_apiHawkSurfaceToID.TryGetValue(dispSurfaceImpl, out var surfaceID)) + foreach (var renderer in _apiHawkIDTo2DRenderer.Values) { - throw new InvalidOperationException("Surface was not locked as a lua surface"); + renderer.Discard(); } - - _apiHawkSurfaceToID.Remove(dispSurfaceImpl); - _apiHawkIDToSurface.Remove(surfaceID); - _apiHawkSurfaceSets[surfaceID].SetPending(dispSurfaceImpl); } + + public void ClearApiHawkTextureCache() + => _imGuiResourceCache.ClearTextureCache(); } } diff --git a/src/BizHawk.Client.Common/DisplayManager/DisplaySurface.cs b/src/BizHawk.Client.Common/DisplayManager/DisplaySurface.cs deleted file mode 100644 index e170efdbf0b..00000000000 --- a/src/BizHawk.Client.Common/DisplayManager/DisplaySurface.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Drawing; -using System.Drawing.Imaging; - -namespace BizHawk.Client.Common -{ - /// - /// This is a wrapper for a Bitmap. - /// It should be phased out, in favor of BitmapBuffer and Texture2d's - /// - public unsafe class DisplaySurface : IDisplaySurface - { - private const PixelFormat Format = PixelFormat.Format32bppArgb; - - private Bitmap _bmp; - - public void Clear() - { - var bmpData = _bmp.LockBits(new(0, 0, Width, Height), ImageLockMode.WriteOnly, Format); - new Span((void*)bmpData.Scan0, bmpData.Stride * bmpData.Height).Clear(); - _bmp.UnlockBits(bmpData); - } - - public Bitmap PeekBitmap() - { - return _bmp; - } - - public Graphics GetGraphics() - { - return Graphics.FromImage(_bmp); - } - - public DisplaySurface(int width, int height) - { - // can't create a bitmap with zero dimensions, so for now, just bump it up to one - if (width == 0) - { - width = 1; - } - - if (height == 0) - { - height = 1; - } - - Width = width; - Height = height; - - _bmp = new Bitmap(Width, Height, Format); - } - - public int Width { get; } - public int Height { get; } - - public void Dispose() - { - _bmp?.Dispose(); - _bmp = null; - } - } - -} diff --git a/src/BizHawk.Client.Common/DisplayManager/FilterManager.cs b/src/BizHawk.Client.Common/DisplayManager/FilterManager.cs index b2cea63311d..e0ab617a9fc 100644 --- a/src/BizHawk.Client.Common/DisplayManager/FilterManager.cs +++ b/src/BizHawk.Client.Common/DisplayManager/FilterManager.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using System.Collections.Generic; using System.Drawing; @@ -7,7 +6,7 @@ using BizHawk.Client.Common.Filters; -using BizHawk.Bizware.BizwareGL; +using BizHawk.Bizware.Graphics; namespace BizHawk.Client.Common.FilterManager { @@ -38,15 +37,15 @@ public SurfaceState(SurfaceFormat surfaceFormat, SurfaceDisposition surfaceDispo public interface IRenderTargetProvider { - RenderTarget Get(Size size); + IRenderTarget Get(Size size); } public class FilterProgram { private readonly Dictionary _filterNameIndex = new(); - public readonly IList Filters = new List(); - public readonly IList Program = new List(); + public readonly List Filters = new(); + public readonly List Program = new(); public BaseFilter this[string name] { @@ -69,9 +68,13 @@ public enum ProgramStepType public IGL GL; public IRenderTargetProvider RenderTargetProvider; - public RenderTarget CurrRenderTarget; + public IRenderTarget CurrRenderTarget; - public RenderTarget GetTempTarget(int width, int height) + // DPI / 96.0 indicates the display scaling + // this is mainly relevant for OSD + public int ControlDpi; + + public IRenderTarget GetTempTarget(int width, int height) { return RenderTargetProvider.Get(new(width, height)); } @@ -290,4 +293,4 @@ public void Compile(string channel, Size inSize, Size outsize, bool finalTarget) } } } -} \ No newline at end of file +} diff --git a/src/BizHawk.Client.Common/DisplayManager/Filters/BaseFilter.cs b/src/BizHawk.Client.Common/DisplayManager/Filters/BaseFilter.cs index d625c3b00a7..5e5a918a786 100644 --- a/src/BizHawk.Client.Common/DisplayManager/Filters/BaseFilter.cs +++ b/src/BizHawk.Client.Common/DisplayManager/Filters/BaseFilter.cs @@ -2,7 +2,7 @@ using System.Drawing; using System.Numerics; -using BizHawk.Bizware.BizwareGL; +using BizHawk.Bizware.Graphics; using BizHawk.Client.Common.FilterManager; // Here's how to make a filter: @@ -41,7 +41,7 @@ public virtual void SetInputFormat(string channel, SurfaceState state) { } - public Dictionary Parameters = new(); + public KeyValuePair[] Parameters { get; set; } public bool IsNop { get; protected set; } @@ -74,7 +74,7 @@ public virtual Vector2 TransformPoint(string channel, Vector2 point) return point; } - public void SetInput(Texture2d tex) + public void SetInput(ITexture2D tex) { InputTexture = tex; } @@ -83,18 +83,18 @@ public virtual void Run() { } - public Texture2d GetOutput() + public ITexture2D GetOutput() => _outputTexture; // filter actions - protected void YieldOutput(Texture2d tex) + protected void YieldOutput(ITexture2D tex) { _outputTexture = tex; } protected FilterProgram FilterProgram; - protected Texture2d InputTexture; - private Texture2d _outputTexture; + protected ITexture2D InputTexture; + private ITexture2D _outputTexture; /// /// Indicate a 'RenderTarget' disposition if you want to draw directly to the input @@ -111,7 +111,7 @@ protected IOSurfaceInfo DeclareOutput(SurfaceDisposition disposition = SurfaceDi } // TODO - why a different param order than DeclareOutput? - protected RenderTarget GetTempTarget(int width, int height) + protected IRenderTarget GetTempTarget(int width, int height) { return FilterProgram.GetTempTarget(width, height); } diff --git a/src/BizHawk.Client.Common/DisplayManager/Filters/Gui.cs b/src/BizHawk.Client.Common/DisplayManager/Filters/Gui.cs index 6ba485b4305..1d7d0802181 100644 --- a/src/BizHawk.Client.Common/DisplayManager/Filters/Gui.cs +++ b/src/BizHawk.Client.Common/DisplayManager/Filters/Gui.cs @@ -1,8 +1,7 @@ -using System; using System.Drawing; using System.Numerics; -using BizHawk.Bizware.BizwareGL; +using BizHawk.Bizware.Graphics; using BizHawk.Client.Common.FilterManager; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Consoles.Nintendo.N3DS; @@ -452,9 +451,22 @@ public override void Initialize() public override void SetInputFormat(string channel, SurfaceState state) { - var outputSize = state.SurfaceFormat.Size; - outputSize.Width *= Scale; - outputSize.Height *= Scale; + var inputSize = state.SurfaceFormat.Size; + var outputSize = new Size(inputSize.Width * Scale, inputSize.Height * Scale); + var maxTexDimension = FilterProgram.GL.MaxTextureDimension; + while (outputSize.Width > maxTexDimension || outputSize.Height > maxTexDimension) + { + outputSize.Width -= inputSize.Width; + outputSize.Height -= inputSize.Height; + Scale--; + } + + // this hopefully never happens + if (outputSize.Width == 0 || outputSize.Height == 0) + { + throw new InvalidOperationException("Prescale input was too large for a texture"); + } + var ss = new SurfaceState(new(outputSize), SurfaceDisposition.RenderTarget); DeclareOutput(ss, channel); } @@ -464,7 +476,7 @@ public override void Run() var outSize = FindOutput().SurfaceFormat.Size; FilterProgram.GuiRenderer.Begin(outSize); FilterProgram.GuiRenderer.DisableBlending(); - FilterProgram.GuiRenderer.Modelview.Scale(Scale); + FilterProgram.GuiRenderer.ModelView.Scale(Scale); FilterProgram.GuiRenderer.Draw(InputTexture); FilterProgram.GuiRenderer.End(); } @@ -519,15 +531,19 @@ public override void Run() { FilterProgram.GuiRenderer.Begin(OutputSize); // hope this didn't change FilterProgram.GuiRenderer.DisableBlending(); - FilterProgram.GuiRenderer.Modelview.Scale(XIS,YIS); + FilterProgram.GuiRenderer.ModelView.Scale(XIS,YIS); FilterProgram.GuiRenderer.Draw(InputTexture); FilterProgram.GuiRenderer.End(); } } - /// More accurately, ApiHawkLayer, since the gui Lua library is delegated. - public class LuaLayer : BaseFilter + public class ApiHawkLayer : BaseFilter { + private readonly I2DRenderer _renderer; + + public ApiHawkLayer(I2DRenderer renderer) + => _renderer = renderer; + public override void Initialize() { DeclareInput(SurfaceDisposition.RenderTarget); @@ -538,19 +554,26 @@ public override void SetInputFormat(string channel, SurfaceState state) DeclareOutput(state); } - private Texture2d _texture; - - public void SetTexture(Texture2d tex) - { - _texture = tex; - } - public override void Run() { var outSize = FindOutput().SurfaceFormat.Size; + + var output = _renderer.Render(outSize.Width, outSize.Height); + + // render target might have changed when rendering, rebind the filter chain's target + var rt = FilterProgram.CurrRenderTarget; + if (rt == null) + { + FilterProgram.GL.BindDefaultRenderTarget(); + } + else + { + rt.Bind(); + } + FilterProgram.GuiRenderer.Begin(outSize); FilterProgram.GuiRenderer.EnableBlending(); - FilterProgram.GuiRenderer.Draw(_texture); + FilterProgram.GuiRenderer.Draw(output); FilterProgram.GuiRenderer.End(); } } @@ -589,9 +612,10 @@ public override void Run() } var size = FindInput().SurfaceFormat.Size; - + FilterProgram.GuiRenderer.Begin(size.Width, size.Height); - var blitter = new OSDBlitter(_font, FilterProgram.GuiRenderer, new(0, 0, size.Width, size.Height)); + var scale = FilterProgram.ControlDpi / 96.0F; + var blitter = new OSDBlitter(_font, FilterProgram.GuiRenderer, new(0, 0, size.Width, size.Height), scale); FilterProgram.GuiRenderer.EnableBlending(); _manager.DrawScreenInfo(blitter); _manager.DrawMessages(blitter); @@ -603,24 +627,27 @@ private class OSDBlitter : IBlitter private readonly StringRenderer _font; private readonly IGuiRenderer _renderer; - public OSDBlitter(StringRenderer font, IGuiRenderer renderer, Rectangle clipBounds) + public OSDBlitter(StringRenderer font, IGuiRenderer renderer, Rectangle clipBounds, float scale) { _font = font; _renderer = renderer; ClipBounds = clipBounds; + Scale = scale; } public void DrawString(string s, Color color, float x, float y) { _renderer.SetModulateColor(color); - _font.RenderString(_renderer, x, y, s); + _font.RenderString(_renderer, x, y, s, Scale); _renderer.SetModulateColorWhite(); } public SizeF MeasureString(string s) - => _font.Measure(s); + => _font.Measure(s, Scale); public Rectangle ClipBounds { get; } + + public float Scale { get; } } } -} \ No newline at end of file +} diff --git a/src/BizHawk.Client.Common/DisplayManager/Filters/Retro.cs b/src/BizHawk.Client.Common/DisplayManager/Filters/Retro.cs index 3ea9f51b307..eb482750982 100644 --- a/src/BizHawk.Client.Common/DisplayManager/Filters/Retro.cs +++ b/src/BizHawk.Client.Common/DisplayManager/Filters/Retro.cs @@ -2,7 +2,6 @@ // https://github.com/Themaister/Emulator-Shader-Pack/blob/master/Cg/README // https://github.com/libretro/common-shaders/ -using System; using System.Collections.Generic; using System.Drawing; using System.Globalization; @@ -10,12 +9,12 @@ using System.Numerics; using System.Text.RegularExpressions; -using BizHawk.Client.Common.FilterManager; - -using BizHawk.Bizware.BizwareGL; +using BizHawk.Bizware.Graphics; using BizHawk.Common; using BizHawk.Common.StringExtensions; +using BizHawk.Client.Common.FilterManager; + namespace BizHawk.Client.Common.Filters { public class RetroShaderChain : IDisposable @@ -45,9 +44,9 @@ public RetroShaderChain(IGL owner, RetroShaderPreset preset, string baseDirector Passes = preset.Passes.ToArray(); Errors = string.Empty; - if (owner.API is not ("OPENGL" or "D3D9")) + if (owner.DispMethodEnum is not (EDispMethod.OpenGL or EDispMethod.D3D11)) { - Errors = $"Unsupported API {owner.API}"; + Errors = $"Unsupported Display Method {owner.DispMethodEnum}"; return; } @@ -67,11 +66,12 @@ public RetroShaderChain(IGL owner, RetroShaderPreset preset, string baseDirector if (!File.Exists(path)) { - path = owner.API switch + // ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault + path = owner.DispMethodEnum switch { - "OPENGL" => Path.ChangeExtension(path, ".glsl"), - "D3D9" => Path.ChangeExtension(path, ".hlsl"), - _ => throw new InvalidOperationException(), + EDispMethod.OpenGL => Path.ChangeExtension(path, ".glsl"), + EDispMethod.D3D11 => Path.ChangeExtension(path, ".hlsl"), + _ => throw new InvalidOperationException() }; } } @@ -346,12 +346,9 @@ public override void Run() // apply all parameters to this shader.. even if it was meant for other shaders. kind of lame. if (Parameters != null) { - foreach (var (k, v) in Parameters) + foreach (var (k, value) in Parameters) { - if (v is float value) - { - shader.Pipeline[k].Set(value); - } + shader.Pipeline.SetUniform(k, value); } } @@ -365,7 +362,7 @@ public override void Run() InputTexture.SetFilterNearest(); } - _rsc.Shaders[_rsi].Run(input, input.Size, _outputSize, InputTexture.IsUpsideDown); + _rsc.Shaders[_rsi].Run(input, input.GetSize(), _outputSize, InputTexture.IsUpsideDown); // maintain invariant.. i think. InputTexture.SetFilterNearest(); diff --git a/src/BizHawk.Client.Common/DisplayManager/Filters/Utils.cs b/src/BizHawk.Client.Common/DisplayManager/Filters/Utils.cs index 9dfa70aacb0..69ad542ae1b 100644 --- a/src/BizHawk.Client.Common/DisplayManager/Filters/Utils.cs +++ b/src/BizHawk.Client.Common/DisplayManager/Filters/Utils.cs @@ -1,6 +1,6 @@ using System.Drawing; -using BizHawk.Bizware.BizwareGL; +using BizHawk.Bizware.Graphics; using BizHawk.Client.Common.FilterManager; namespace BizHawk.Client.Common.Filters @@ -14,7 +14,7 @@ public SourceImage(Size size) private readonly Size _size; - public Texture2d Texture { get; set; } + public ITexture2D Texture { get; set; } public override void Run() { @@ -71,7 +71,7 @@ public override void SetInputFormat(string channel, SurfaceState state) public override void Run() { - YieldOutput(FilterProgram.CurrRenderTarget.Texture2d); + YieldOutput(FilterProgram.CurrRenderTarget); } } } \ No newline at end of file diff --git a/src/BizHawk.Client.Common/DisplayManager/IBlitter.cs b/src/BizHawk.Client.Common/DisplayManager/IBlitter.cs index 47db7c2f5e8..5f23f8ce0f3 100644 --- a/src/BizHawk.Client.Common/DisplayManager/IBlitter.cs +++ b/src/BizHawk.Client.Common/DisplayManager/IBlitter.cs @@ -14,5 +14,7 @@ public interface IBlitter SizeF MeasureString(string s); Rectangle ClipBounds { get; } + + public float Scale { get; } } } diff --git a/src/BizHawk.Client.Common/DisplayManager/IDisplaySurface.cs b/src/BizHawk.Client.Common/DisplayManager/IDisplaySurface.cs deleted file mode 100644 index ccbb4947489..00000000000 --- a/src/BizHawk.Client.Common/DisplayManager/IDisplaySurface.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Drawing; - -namespace BizHawk.Client.Common -{ - public interface IDisplaySurface : IDisposable - { - int Height { get; } - - int Width { get; } - - void Clear(); - - /// a used to render to this surface; be sure to dispose it! - Graphics GetGraphics(); - - Bitmap PeekBitmap(); - } -} diff --git a/src/BizHawk.Client.Common/DisplayManager/OSDManager.cs b/src/BizHawk.Client.Common/DisplayManager/OSDManager.cs index 11d930cd4e6..5c0890c7717 100644 --- a/src/BizHawk.Client.Common/DisplayManager/OSDManager.cs +++ b/src/BizHawk.Client.Common/DisplayManager/OSDManager.cs @@ -1,8 +1,8 @@ -using System; using System.Linq; using System.Text; using System.Drawing; using System.Collections.Generic; + using BizHawk.Emulation.Common; namespace BizHawk.Client.Common @@ -36,17 +36,18 @@ public void UpdateGlobals(Config config, IEmulator emulator) public Color FixedMessagesColor => Color.FromArgb(_config.MessagesColor); public Color FixedAlertMessageColor => Color.FromArgb(_config.AlertMessageColor); - private PointF GetCoordinates(IBlitter g, MessagePosition position, string message) + + + private static PointF GetCoordinates(IBlitter g, MessagePosition position, string message) { var size = g.MeasureString(message); - float x = position.Anchor.IsLeft() - ? position.X - : g.ClipBounds.Width - position.X - size.Width; + var x = position.Anchor.IsLeft() + ? position.X * g.Scale + : g.ClipBounds.Width - position.X * g.Scale - size.Width; - float y = position.Anchor.IsTop() - ? position.Y - : g.ClipBounds.Height - position.Y - size.Height; - + var y = position.Anchor.IsTop() + ? position.Y * g.Scale + : g.ClipBounds.Height - position.Y * g.Scale - size.Height; return new PointF(x, y); } @@ -78,9 +79,9 @@ private string MakeFrameCounter() return _emulator.Frame.ToString(); } - private readonly List _messages = new List(5); - private readonly List _guiTextList = new List(); - private readonly List _ramWatchList = new List(); + private readonly List _messages = new(5); + private readonly List _guiTextList = [ ]; + private readonly List _ramWatchList = [ ]; public void AddMessage(string message, int? duration = null) => _messages.Add(new() { @@ -89,9 +90,7 @@ public void AddMessage(string message, int? duration = null) }); public void ClearRamWatches() - { - _ramWatchList.Clear(); - } + => _ramWatchList.Clear(); public void AddRamWatch(string message, MessagePosition pos, Color backGround, Color foreColor) { @@ -116,9 +115,7 @@ public void AddGuiText(string message, MessagePosition pos, Color backGround, Co } public void ClearGuiText() - { - _guiTextList.Clear(); - } + => _guiTextList.Clear(); private void DrawMessage(IBlitter g, UIMessage message, int yOffset) { @@ -140,10 +137,10 @@ public void DrawMessages(IBlitter g) { if (_config.StackOSDMessages) { - int line = 1; - for (int i = _messages.Count - 1; i >= 0; i--, line++) + var line = 1; + for (var i = _messages.Count - 1; i >= 0; i--, line++) { - int yOffset = (line - 1) * 18; + var yOffset = (int)Math.Round((line - 1) * 18 * g.Scale); if (!_config.Messages.Anchor.IsTop()) { yOffset = 0 - yOffset; @@ -154,7 +151,7 @@ public void DrawMessages(IBlitter g) } else { - var message = _messages[_messages.Count - 1]; + var message = _messages[^1]; DrawMessage(g, message, 0); } } @@ -175,14 +172,10 @@ public void DrawMessages(IBlitter g) } public string InputStrMovie() - { - return MakeStringFor(_movieSession.MovieController, cache: true); - } + => MakeStringFor(_movieSession.MovieController, cache: true); public string InputStrImmediate() - { - return MakeStringFor(_inputManager.AutofireStickyXorAdapter, cache: true); - } + => MakeStringFor(_inputManager.AutofireStickyXorAdapter, cache: true); public string InputPrevious() { @@ -235,10 +228,8 @@ public string MakeRerecordCount() : ""; } - private void DrawOsdMessage(IBlitter g, string message, Color color, float x, float y) - { - g.DrawString(message, color, x, y); - } + private static void DrawOsdMessage(IBlitter g, string message, Color color, float x, float y) + => g.DrawString(message, color, x, y); /// /// Display all screen info objects like fps, frame counter, lag counter, and input display @@ -247,7 +238,7 @@ public void DrawScreenInfo(IBlitter g) { if (_config.DisplayFrameCounter && !_emulator.IsNull()) { - string message = MakeFrameCounter(); + var message = MakeFrameCounter(); var point = GetCoordinates(g, _config.FrameCounter, message); DrawOsdMessage(g, message, Color.FromArgb(_config.MessagesColor), point.X, point.Y); @@ -266,14 +257,14 @@ public void DrawScreenInfo(IBlitter g) { var input = InputStrMovie(); var point = GetCoordinates(g, _config.InputDisplay, input); - Color c = Color.FromArgb(_config.MovieInput); + var c = Color.FromArgb(_config.MovieInput); g.DrawString(input, c, point.X, point.Y); } if (!moviePlaying) // TODO: message config -- allow setting of "mixed", and "auto" { var previousColor = Color.FromArgb(_config.LastInputColor); - Color immediateColor = Color.FromArgb(_config.MessagesColor); + var immediateColor = Color.FromArgb(_config.MessagesColor); var autoColor = Color.Pink; var changedColor = Color.PeachPuff; @@ -325,7 +316,7 @@ public void DrawScreenInfo(IBlitter g) if (_config.DisplayRerecordCount) { - string rerecordCount = MakeRerecordCount(); + var rerecordCount = MakeRerecordCount(); var point = GetCoordinates(g, _config.ReRecordCounter, rerecordCount); DrawOsdMessage(g, rerecordCount, FixedMessagesColor, point.X, point.Y); } @@ -334,12 +325,12 @@ public void DrawScreenInfo(IBlitter g) { var sb = new StringBuilder("Held: "); - foreach (string sticky in _inputManager.StickyXorAdapter.CurrentStickies) + foreach (var sticky in _inputManager.StickyXorAdapter.CurrentStickies) { sb.Append(sticky).Append(' '); } - foreach (string autoSticky in _inputManager.AutofireStickyXorAdapter.CurrentStickies) + foreach (var autoSticky in _inputManager.AutofireStickyXorAdapter.CurrentStickies) { sb .Append("Auto-") @@ -363,4 +354,4 @@ public void DrawScreenInfo(IBlitter g) } } } -} \ No newline at end of file +} diff --git a/src/BizHawk.Client.Common/DisplayManager/RenderTargetFrugalizer.cs b/src/BizHawk.Client.Common/DisplayManager/RenderTargetFrugalizer.cs index f824969c568..2bf34c9630b 100644 --- a/src/BizHawk.Client.Common/DisplayManager/RenderTargetFrugalizer.cs +++ b/src/BizHawk.Client.Common/DisplayManager/RenderTargetFrugalizer.cs @@ -1,8 +1,7 @@ -using System; using System.Drawing; using System.Collections.Generic; -using BizHawk.Bizware.BizwareGL; +using BizHawk.Bizware.Graphics; namespace BizHawk.Client.Common { @@ -30,26 +29,26 @@ public void Dispose() private void ResetList() { - _currentRenderTargets = new List { null, null }; + _currentRenderTargets = new List { null, null }; } private readonly IGL _gl; - private List _currentRenderTargets; + private List _currentRenderTargets; - public RenderTarget Get(Size dimensions) + public IRenderTarget Get(Size dimensions) { return Get(dimensions.Width, dimensions.Height); } - public RenderTarget Get(int width, int height) + public IRenderTarget Get(int width, int height) { //get the current entry - RenderTarget currentRenderTarget = _currentRenderTargets[0]; + var currentRenderTarget = _currentRenderTargets[0]; //check if its rotten and needs recreating if (currentRenderTarget == null - || currentRenderTarget.Texture2d.IntWidth != width - || currentRenderTarget.Texture2d.IntHeight != height) + || currentRenderTarget.Width != width + || currentRenderTarget.Height != height) { // needs recreating. be sure to kill the old one... currentRenderTarget?.Dispose(); diff --git a/src/BizHawk.Client.Common/DisplayManager/SimpleGDIPDisplayManager.cs b/src/BizHawk.Client.Common/DisplayManager/SimpleGDIPDisplayManager.cs new file mode 100644 index 00000000000..f91f9d55a41 --- /dev/null +++ b/src/BizHawk.Client.Common/DisplayManager/SimpleGDIPDisplayManager.cs @@ -0,0 +1,44 @@ +#nullable enable + +using System.Drawing; + +using BizHawk.Bizware.Graphics; +using BizHawk.Emulation.Common; + +namespace BizHawk.Client.Common +{ + public sealed class SimpleGDIPDisplayManager : DisplayManagerBase + { + private SimpleGDIPDisplayManager(Config config, IEmulator emuCore, IGL_GDIPlus glImpl) + : base( + config, + emuCore, + inputManager: null, + movieSession: null, + EDispMethod.GdiPlus, + glImpl, + new GDIPlusGuiRenderer(glImpl)) + {} + + public SimpleGDIPDisplayManager(Config config, IEmulator emuCore, Func<(int Width, int Height)> getVirtualSize) + : this(config, emuCore, new IGL_GDIPlus()) {} + + protected override void ActivateGraphicsControlContext() {} + + public override void ActivateOpenGLContext() {} + + protected override int GetGraphicsControlDpi() + => DisplayManagerBase.DEFAULT_DPI; + + protected override Size GetGraphicsControlSize() + => throw new NotImplementedException(); + + public override Size GetPanelNativeSize() + => throw new NotImplementedException(); + + protected override Point GraphicsControlPointToClient(Point p) + => throw new NotImplementedException(); + + protected override void SwapBuffersOfGraphicsControl() {} + } +} diff --git a/src/BizHawk.Client.Common/DisplayManager/SwappableDisplaySurfaceSet.cs b/src/BizHawk.Client.Common/DisplayManager/SwappableDisplaySurfaceSet.cs deleted file mode 100644 index 17b2d6ad13d..00000000000 --- a/src/BizHawk.Client.Common/DisplayManager/SwappableDisplaySurfaceSet.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace BizHawk.Client.Common -{ - /// - /// encapsulates thread-safe concept of pending/current display surfaces, reusing buffers where matching - /// sizes are available and keeping them cleaned up when they don't seem like they'll need to be used anymore - /// - public class SwappableDisplaySurfaceSet - where T : class, IDisplaySurface - { - private readonly Func _createDispSurface; - - private T _pending, _current; - private bool _isPending; - private readonly Queue _releasedSurfaces = new(); - - public SwappableDisplaySurfaceSet(Func createDispSurface) => _createDispSurface = createDispSurface; - - /// - /// retrieves a surface with the specified size, reusing an old buffer if available and clearing if requested - /// - public T AllocateSurface(int width, int height, bool needsClear = true) - { - for (; ; ) - { - T trial; - lock (this) - { - if (_releasedSurfaces.Count == 0) break; - trial = _releasedSurfaces.Dequeue(); - } - if (trial.Width == width && trial.Height == height) - { - if (needsClear) - { - trial.Clear(); - } - - return trial; - } - - trial.Dispose(); - } - - return _createDispSurface(width, height); - } - - /// - /// sets the provided buffer as pending. takes control of the supplied buffer - /// - public void SetPending(T newPending) - { - lock (this) - { - if (_pending != null) _releasedSurfaces.Enqueue(_pending); - _pending = newPending; - _isPending = true; - } - } - - public void ReleaseSurface(T surface) - { - lock (this) _releasedSurfaces.Enqueue(surface); - } - - /// - /// returns the current buffer, making the most recent pending buffer (if there is such) as the new current first. - /// - public T GetCurrent() - { - lock (this) - { - if (_isPending) - { - if (_current != null) _releasedSurfaces.Enqueue(_current); - _current = _pending; - _pending = null; - _isPending = false; - } - } - - return _current; - } - } -} \ No newline at end of file diff --git a/src/BizHawk.Client.Common/DisplayManager/TextureFrugalizer.cs b/src/BizHawk.Client.Common/DisplayManager/TextureFrugalizer.cs index a084d8f5068..37788a8cec0 100644 --- a/src/BizHawk.Client.Common/DisplayManager/TextureFrugalizer.cs +++ b/src/BizHawk.Client.Common/DisplayManager/TextureFrugalizer.cs @@ -1,11 +1,11 @@ -using System; using System.Collections.Generic; -using BizHawk.Bizware.BizwareGL; + +using BizHawk.Bizware.Graphics; namespace BizHawk.Client.Common { /// - /// Recycles a pair of temporary textures (in case double-buffering helps any) to contain a BitmapBuffer's or DisplaySurface's contents, as long as the dimensions match. + /// Recycles a pair of temporary textures (in case double-buffering helps any) to contain a BitmapBuffer's contents, as long as the dimensions match. /// When the dimensions don't match, a new one will be allocated /// public class TextureFrugalizer : IDisposable @@ -28,27 +28,22 @@ public void Dispose() private void ResetList() { - _currentTextures = new List { null, null }; + _currentTextures = new List { null, null }; } private readonly IGL _gl; - private List _currentTextures; + private List _currentTextures; - public Texture2d Get(IDisplaySurface ds) - { - using var bb = new BitmapBuffer(ds.PeekBitmap(), new BitmapLoadOptions()); - return Get(bb); - } - public Texture2d Get(BitmapBuffer bb) + public ITexture2D Get(BitmapBuffer bb) { //get the current entry - Texture2d currentTexture = _currentTextures[0]; + var currentTexture = _currentTextures[0]; // TODO - its a bit cruddy here that we don't respect the current texture HasAlpha condition (in fact, there's no such concept) // we might need to deal with that in the future to fix some bugs. //check if its rotten and needs recreating - if (currentTexture == null || currentTexture.IntWidth != bb.Width || currentTexture.IntHeight != bb.Height) + if (currentTexture == null || currentTexture.Width != bb.Width || currentTexture.Height != bb.Height) { //needs recreating. be sure to kill the old one... currentTexture?.Dispose(); @@ -58,7 +53,7 @@ public Texture2d Get(BitmapBuffer bb) else { //its good! just load in the data - _gl.LoadTextureData(currentTexture, bb); + currentTexture.LoadFrom(bb); } //now shuffle the buffers diff --git a/src/BizHawk.Client.Common/DisplayManager/UIMessage.cs b/src/BizHawk.Client.Common/DisplayManager/UIMessage.cs index 2cbf8ee9b21..c4e6a2b8fa5 100644 --- a/src/BizHawk.Client.Common/DisplayManager/UIMessage.cs +++ b/src/BizHawk.Client.Common/DisplayManager/UIMessage.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Client.Common { public class UIMessage diff --git a/src/BizHawk.Client.Common/EventTypes.cs b/src/BizHawk.Client.Common/EventTypes.cs index c9b4bfae8f0..83a3fc60b90 100644 --- a/src/BizHawk.Client.Common/EventTypes.cs +++ b/src/BizHawk.Client.Common/EventTypes.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Client.Common { /// diff --git a/src/BizHawk.Client.Common/ExceptionClasses.cs b/src/BizHawk.Client.Common/ExceptionClasses.cs index c63eeff6e26..534e978e62f 100644 --- a/src/BizHawk.Client.Common/ExceptionClasses.cs +++ b/src/BizHawk.Client.Common/ExceptionClasses.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Client.Common { public class MoviePlatformMismatchException : InvalidOperationException diff --git a/src/BizHawk.Client.Common/FrameworkZipWriter.cs b/src/BizHawk.Client.Common/FrameworkZipWriter.cs index 48bdfdd8033..a90755dd84c 100644 --- a/src/BizHawk.Client.Common/FrameworkZipWriter.cs +++ b/src/BizHawk.Client.Common/FrameworkZipWriter.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.IO.Compression; @@ -32,7 +31,9 @@ public FrameworkZipWriter(string path, int compressionLevel) public void WriteItem(string name, Action callback, bool zstdCompress) { - using var stream = _archive.CreateEntry(name, _level).Open(); + // don't compress with deflate if we're already compressing with zstd + // this won't produce meaningful compression, and would just be a timesink + using var stream = _archive.CreateEntry(name, zstdCompress ? CompressionLevel.NoCompression : _level).Open(); if (zstdCompress) { diff --git a/src/BizHawk.Client.Common/HostCapabilityDetector.cs b/src/BizHawk.Client.Common/HostCapabilityDetector.cs index feb4914c491..ae16e0bd781 100644 --- a/src/BizHawk.Client.Common/HostCapabilityDetector.cs +++ b/src/BizHawk.Client.Common/HostCapabilityDetector.cs @@ -1,15 +1,13 @@ -using System; - using BizHawk.Common; namespace BizHawk.Client.Common { public static class HostCapabilityDetector { - private static readonly Lazy _hasD3D9 = new(() => + private static readonly Lazy _hasD3D11 = new(() => { if (OSTailoredCode.IsUnixHost) return false; - var p = OSTailoredCode.LinkedLibManager.LoadOrZero("d3dx9_43.dll"); + var p = OSTailoredCode.LinkedLibManager.LoadOrZero("d3d11.dll"); if (p == IntPtr.Zero) return false; OSTailoredCode.LinkedLibManager.FreeByPtr(p); return true; @@ -37,7 +35,7 @@ public static class HostCapabilityDetector return false; }); - public static bool HasD3D9 => _hasD3D9.Value; + public static bool HasD3D11 => _hasD3D11.Value; public static bool HasXAudio2 => _hasXAudio2.Value; } } diff --git a/src/BizHawk.Client.Common/IMainFormForApi.cs b/src/BizHawk.Client.Common/IMainFormForApi.cs index 343aeff4ce6..e3354b3a7fe 100644 --- a/src/BizHawk.Client.Common/IMainFormForApi.cs +++ b/src/BizHawk.Client.Common/IMainFormForApi.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using BizHawk.Emulation.Common; @@ -52,7 +51,7 @@ public interface IMainFormForApi bool FlushSaveRAM(bool autosave = false); /// only referenced from EmuClientApi - void FrameAdvance(); + void FrameAdvance(bool discardApiHawkSurfaces = true); void FrameBufferResized(); diff --git a/src/BizHawk.Client.Common/IZipWriter.cs b/src/BizHawk.Client.Common/IZipWriter.cs index 71d1cda6f2a..fa1de4e6513 100644 --- a/src/BizHawk.Client.Common/IZipWriter.cs +++ b/src/BizHawk.Client.Common/IZipWriter.cs @@ -1,4 +1,3 @@ -using System; using System.IO; namespace BizHawk.Client.Common diff --git a/src/BizHawk.Client.Common/LoadRomArgs.cs b/src/BizHawk.Client.Common/LoadRomArgs.cs index 72794622d78..fdffb47a0ca 100644 --- a/src/BizHawk.Client.Common/LoadRomArgs.cs +++ b/src/BizHawk.Client.Common/LoadRomArgs.cs @@ -1,8 +1,9 @@ namespace BizHawk.Client.Common { - public class LoadRomArgs + public sealed class LoadRomArgs(IOpenAdvanced ioa, bool? deterministic = null) { - public bool? Deterministic { get; set; } - public IOpenAdvanced OpenAdvanced { get; set; } + public readonly bool? Deterministic = deterministic; + + public readonly IOpenAdvanced OpenAdvanced = ioa; } } diff --git a/src/BizHawk.Client.Common/OpenAdvanced.cs b/src/BizHawk.Client.Common/OpenAdvanced.cs index 394a100fd17..a33b5cb1de2 100644 --- a/src/BizHawk.Client.Common/OpenAdvanced.cs +++ b/src/BizHawk.Client.Common/OpenAdvanced.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Common.StringExtensions; @@ -44,7 +43,7 @@ public static IOpenAdvanced ParseWithLegacy(string text) { return text.StartsWith('*') ? Deserialize(text.Substring(1)) - : new OpenAdvanced_OpenRom { Path = text }; + : new OpenAdvanced_OpenRom(text); } private static IOpenAdvanced Deserialize(string text) @@ -152,6 +151,12 @@ public class OpenAdvanced_OpenRom : IOpenAdvanced public string DisplayName => Path; public string SimplePath => Path; + public OpenAdvanced_OpenRom() {} + + public OpenAdvanced_OpenRom(string path) + : this() + => Path = path; + public void Deserialize(string str) { Path = str; diff --git a/src/BizHawk.Client.Common/ParsedCLIFlags.cs b/src/BizHawk.Client.Common/ParsedCLIFlags.cs index d2f0c0338f4..489585ea292 100644 --- a/src/BizHawk.Client.Common/ParsedCLIFlags.cs +++ b/src/BizHawk.Client.Common/ParsedCLIFlags.cs @@ -35,7 +35,7 @@ public readonly struct ParsedCLIFlags public readonly bool luaConsole; - public readonly (string IP, int Port)? SocketAddress; + public readonly (string IP, ushort Port)? SocketAddress; public readonly ProtocolType SocketProtocol; @@ -66,7 +66,7 @@ public ParsedCLIFlags( bool startFullscreen, string? luaScript, bool luaConsole, - (string IP, int Port)? socketAddress, + (string IP, ushort Port)? socketAddress, string? mmfFilename, (string? UrlGet, string? UrlPost)? httpAddresses, bool? audiosync, diff --git a/src/BizHawk.Client.Common/QuickBmpFile.cs b/src/BizHawk.Client.Common/QuickBmpFile.cs index 4e7d18136d7..76af7364f59 100644 --- a/src/BizHawk.Client.Common/QuickBmpFile.cs +++ b/src/BizHawk.Client.Common/QuickBmpFile.cs @@ -1,4 +1,4 @@ -using System; +using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; @@ -95,11 +95,13 @@ private static unsafe byte[] GetBytes(object o) private static unsafe T GetObject(Stream s) { - byte[] tmp = new byte[Marshal.SizeOf(typeof(T))]; - s.Read(tmp, 0, tmp.Length); + var t = typeof(T); + byte[] tmp = new byte[Marshal.SizeOf(t)]; + var bytesRead = s.Read(tmp, offset: 0, count: tmp.Length); + Debug.Assert(bytesRead == tmp.Length, $"reached end-of-file while reading {t.Name}"); fixed (byte* p = tmp) { - return (T)Marshal.PtrToStructure((IntPtr)p, typeof(T)); + return (T) Marshal.PtrToStructure((IntPtr) p, t); } } @@ -185,7 +187,7 @@ public static unsafe void Copy(IVideoProvider src, IVideoProvider dst) { if (src.BufferWidth == dst.BufferWidth && src.BufferHeight == dst.BufferHeight) { - Array.Copy(src.GetVideoBuffer(), dst.GetVideoBuffer(), src.GetVideoBuffer().Length); + Array.Copy(src.GetVideoBuffer(), dst.GetVideoBuffer(), src.BufferWidth * src.BufferHeight); } else { @@ -248,7 +250,8 @@ public static unsafe bool Load(IVideoProvider v, Stream s) int inH = bi.biHeight; byte[] src = new byte[inW * inH * 4]; - s.Read(src, 0, src.Length); + var bytesRead = s.Read(src, offset: 0, count: src.Length); + Debug.Assert(bytesRead == src.Length, "reached end-of-file while reading .bmp"); if (v is LoadedBMP) { var l = v as LoadedBMP; diff --git a/src/BizHawk.Client.Common/RecentFiles.cs b/src/BizHawk.Client.Common/RecentFiles.cs index 041cd971774..5f37582d1b0 100644 --- a/src/BizHawk.Client.Common/RecentFiles.cs +++ b/src/BizHawk.Client.Common/RecentFiles.cs @@ -1,13 +1,10 @@ -using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; namespace BizHawk.Client.Common { - [JsonObject] - public class RecentFiles : IEnumerable + public class RecentFiles { // ReSharper disable once FieldCanBeMadeReadOnly.Local private List recentlist; @@ -43,7 +40,6 @@ public RecentFiles(int max) public string this[int index] => recentlist.Any() ? recentlist[index] : ""; public IEnumerator GetEnumerator() => recentlist.GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public void Clear() { @@ -78,8 +74,6 @@ public bool Remove(string newFile) } public void ToggleAutoLoad() - { - AutoLoad ^= true; - } + => AutoLoad = !AutoLoad; } } diff --git a/src/BizHawk.Client.Common/RomGame.cs b/src/BizHawk.Client.Common/RomGame.cs index f7e75d2102b..fb9a7d5f6d5 100644 --- a/src/BizHawk.Client.Common/RomGame.cs +++ b/src/BizHawk.Client.Common/RomGame.cs @@ -1,4 +1,4 @@ -using System; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Threading; @@ -81,7 +81,7 @@ public RomGame(HawkFile file, string patch) // assume we have a header of that size. Otherwise, assume it's just all rom. // Other 'recognized' header sizes may need to be added. int headerOffset = fileLength % BankSize; - if (headerOffset.In(0, 128, 512) == false) + if (!headerOffset.In(0, 128, 512)) { Console.WriteLine("ROM was not a multiple of 1024 bytes, and not a recognized header size: {0}. Assume it's purely ROM data.", headerOffset); headerOffset = 0; @@ -94,7 +94,8 @@ public RomGame(HawkFile file, string patch) // read the entire file into FileData. FileData = new byte[fileLength]; stream.Position = 0; - stream.Read(FileData, 0, fileLength); + var bytesRead = stream.Read(FileData, offset: 0, count: fileLength); + Debug.Assert(bytesRead == fileLength, "failed to read whole rom stream"); string SHA1_check = SHA1Checksum.ComputePrefixedHex(FileData); diff --git a/src/BizHawk.Client.Common/RomLoader.cs b/src/BizHawk.Client.Common/RomLoader.cs index 009f11ceb18..b686365d61f 100644 --- a/src/BizHawk.Client.Common/RomLoader.cs +++ b/src/BizHawk.Client.Common/RomLoader.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; @@ -347,7 +346,7 @@ private void LoadM3U(string path, CoreComm nextComm, HawkFile file, string force var discs = m3u.Entries .Select(e => e.Path) .Where(p => Disc.IsValidExtension(Path.GetExtension(p))) - .Select(path => (p: path, d: DiscExtensions.CreateAnyType(path, str => DoLoadErrorCallback(str, "???", LoadErrorType.DiscError)))) + .Select(p => (p, d: DiscExtensions.CreateAnyType(p, str => DoLoadErrorCallback(str, "???", LoadErrorType.DiscError)))) .Where(a => a.d != null) .Select(a => (IDiscAsset)new DiscAsset { @@ -356,7 +355,7 @@ private void LoadM3U(string path, CoreComm nextComm, HawkFile file, string force DiscName = Path.GetFileNameWithoutExtension(a.p) }) .ToList(); - if (m3u.Entries.Count == 0) + if (discs.Count == 0) throw new InvalidOperationException("Couldn't load any contents of the M3U as discs"); game = MakeGameFromDisc(discs[0].DiscData, Path.GetExtension(m3u.Entries[0].Path), discs[0].DiscName); @@ -875,6 +874,8 @@ private static class RomFileExtensions public static readonly IReadOnlyCollection A78 = new[] { "a78" }; + public static readonly IReadOnlyCollection Amiga = new[] { "adf", "adz", "dms", "fdi", "hdf", "ipf", "lha" }; + public static readonly IReadOnlyCollection AppleII = new[] { "dsk", "do", "po" }; public static readonly IReadOnlyCollection Arcade = new[] { "zip", "7z", "chd" }; @@ -934,6 +935,7 @@ private static class RomFileExtensions public static readonly IReadOnlyCollection AutoloadFromArchive = Array.Empty() .Concat(A26) .Concat(A78) + .Concat(Amiga) .Concat(AppleII) .Concat(C64) .Concat(Coleco) @@ -1004,6 +1006,7 @@ private static class RomFileExtensions new FilesystemFilter("Vectrex", RomFileExtensions.VEC), new FilesystemFilter("MSX", RomFileExtensions.MSX), new FilesystemFilter("Arcade", RomFileExtensions.Arcade), + new FilesystemFilter("Amiga", RomFileExtensions.Amiga), FilesystemFilter.EmuHawkSaveStates) { CombinedEntryDesc = "Everything", diff --git a/src/BizHawk.Client.Common/SaveSlotManager.cs b/src/BizHawk.Client.Common/SaveSlotManager.cs index 96bfa3221ea..5760e218015 100644 --- a/src/BizHawk.Client.Common/SaveSlotManager.cs +++ b/src/BizHawk.Client.Common/SaveSlotManager.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Common; @@ -32,7 +31,7 @@ public void Update(IEmulator emulator, IMovie movie, string saveStatePrefix) else { var file = new FileInfo($"{saveStatePrefix}.QuickSave{i % 10}.State"); - if (file.Directory != null && file.Directory.Exists == false) + if (file.Directory != null && !file.Directory.Exists) { file.Directory.Create(); } @@ -68,7 +67,7 @@ public void ClearRedoList() public void ToggleRedo(IMovie movie, int slot) { - if (slot is >= 1 and <= 10 && movie is not ITasMovie) _redo[slot - 1] ^= true; + if (slot is >= 1 and <= 10 && movie is not ITasMovie) _redo[slot - 1] = !_redo[slot - 1]; } public bool IsRedo(IMovie movie, int slot) diff --git a/src/BizHawk.Client.Common/SharpCompressArchiveFile.cs b/src/BizHawk.Client.Common/SharpCompressArchiveFile.cs index 13f0c4112b2..c00b47a5c2e 100644 --- a/src/BizHawk.Client.Common/SharpCompressArchiveFile.cs +++ b/src/BizHawk.Client.Common/SharpCompressArchiveFile.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/BizHawk.Client.Common/SharpCompressDearchivalMethod.cs b/src/BizHawk.Client.Common/SharpCompressDearchivalMethod.cs index dd4143bf513..e9947515389 100644 --- a/src/BizHawk.Client.Common/SharpCompressDearchivalMethod.cs +++ b/src/BizHawk.Client.Common/SharpCompressDearchivalMethod.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.IO; @@ -41,7 +40,7 @@ public bool CheckSignature(string fileName, out int offset, out bool isExecutabl // looking for magic bytes fs.Seek(0x101, SeekOrigin.Begin); var buffer = new byte[8]; - fs.Read(buffer, 0, 8); + _ = fs.Read(buffer, offset: 0, count: buffer.Length); // if stream is too short, the next check will catch it var s = buffer.BytesToHexString(); if (s == "7573746172003030" || s == "7573746172202000") return true; // "ustar\000" (libarchive's bsdtar) or "ustar \0" (GNU Tar) @@ -70,7 +69,7 @@ public bool CheckSignature(Stream fileStream, string? filenameHint) var seekPos = fileStream.Position; fileStream.Seek(0x101, SeekOrigin.Begin); var buffer = new byte[8]; - fileStream.Read(buffer, 0, 8); + _ = fileStream.Read(buffer, offset: 0, count: buffer.Length); // if stream is too short, the next check will catch it fileStream.Seek(seekPos, SeekOrigin.Begin); var s = buffer.BytesToHexString(); if (s == "7573746172003030" || s == "7573746172202000") return true; // "ustar\000" (libarchive's bsdtar) or "ustar \0" (GNU Tar) diff --git a/src/BizHawk.Client.Common/Sound/Interfaces/ISoundOutput.cs b/src/BizHawk.Client.Common/Sound/Interfaces/ISoundOutput.cs index 4add3d63e9a..827273aee9c 100644 --- a/src/BizHawk.Client.Common/Sound/Interfaces/ISoundOutput.cs +++ b/src/BizHawk.Client.Common/Sound/Interfaces/ISoundOutput.cs @@ -1,4 +1,3 @@ -using System; using System.IO; namespace BizHawk.Client.Common diff --git a/src/BizHawk.Client.Common/Sound/Output/DummySoundOutput.cs b/src/BizHawk.Client.Common/Sound/Output/DummySoundOutput.cs index 2ddf2386c47..96d33cb109c 100644 --- a/src/BizHawk.Client.Common/Sound/Output/DummySoundOutput.cs +++ b/src/BizHawk.Client.Common/Sound/Output/DummySoundOutput.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using System.IO; diff --git a/src/BizHawk.Client.Common/Sound/Utilities/BufferedAsync.cs b/src/BizHawk.Client.Common/Sound/Utilities/BufferedAsync.cs index 14795ab8978..ac66dc95616 100644 --- a/src/BizHawk.Client.Common/Sound/Utilities/BufferedAsync.cs +++ b/src/BizHawk.Client.Common/Sound/Utilities/BufferedAsync.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.Common/Sound/Utilities/SoundOutputProvider.cs b/src/BizHawk.Client.Common/Sound/Utilities/SoundOutputProvider.cs index d46e901eb89..4f0d374397c 100644 --- a/src/BizHawk.Client.Common/Sound/Utilities/SoundOutputProvider.cs +++ b/src/BizHawk.Client.Common/Sound/Utilities/SoundOutputProvider.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Client.Common/Sound/Utilities/SyncToAsyncProvider.cs b/src/BizHawk.Client.Common/Sound/Utilities/SyncToAsyncProvider.cs index bd311de14c3..7a5365df824 100644 --- a/src/BizHawk.Client.Common/Sound/Utilities/SyncToAsyncProvider.cs +++ b/src/BizHawk.Client.Common/Sound/Utilities/SyncToAsyncProvider.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Client.Common diff --git a/src/BizHawk.Client.Common/XmlGame.cs b/src/BizHawk.Client.Common/XmlGame.cs index 9684da4443e..19ffd70af3d 100644 --- a/src/BizHawk.Client.Common/XmlGame.cs +++ b/src/BizHawk.Client.Common/XmlGame.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/BizHawk.Client.Common/cheats/GameSharkDecoder.cs b/src/BizHawk.Client.Common/cheats/GameSharkDecoder.cs index 2ddbe54c89a..c842db3512d 100644 --- a/src/BizHawk.Client.Common/cheats/GameSharkDecoder.cs +++ b/src/BizHawk.Client.Common/cheats/GameSharkDecoder.cs @@ -1,7 +1,7 @@ -using System; using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; +#pragma warning disable MA0089 namespace BizHawk.Client.Common.cheats { public class GameSharkDecoder @@ -90,7 +90,7 @@ private static IDecodeResult Gen(string code) { // Problem: I don't know what the Non-FF Style codes are. // TODO: Fix that. - if (code.StartsWithOrdinal("FF") == false) + if (!code.StartsWithOrdinal("FF")) { return new InvalidCheatCode("This Action Replay Code, is not yet supported."); } @@ -143,3 +143,4 @@ private static IDecodeResult Snes(string code) } } } +#pragma warning restore MA0089 diff --git a/src/BizHawk.Client.Common/cheats/GbGameSharkDecoder.cs b/src/BizHawk.Client.Common/cheats/GbGameSharkDecoder.cs index 14750d9b17d..9454a01a90f 100644 --- a/src/BizHawk.Client.Common/cheats/GbGameSharkDecoder.cs +++ b/src/BizHawk.Client.Common/cheats/GbGameSharkDecoder.cs @@ -1,4 +1,3 @@ -using System; using System.Globalization; namespace BizHawk.Client.Common.cheats diff --git a/src/BizHawk.Client.Common/cheats/GbGgGameGenieDecoder.cs b/src/BizHawk.Client.Common/cheats/GbGgGameGenieDecoder.cs index 5433d57fe8b..0f471a8d653 100644 --- a/src/BizHawk.Client.Common/cheats/GbGgGameGenieDecoder.cs +++ b/src/BizHawk.Client.Common/cheats/GbGgGameGenieDecoder.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common.NumberExtensions; using BizHawk.Common.StringExtensions; diff --git a/src/BizHawk.Client.Common/cheats/GbaGameSharkDecoder.cs b/src/BizHawk.Client.Common/cheats/GbaGameSharkDecoder.cs index 6b94b732f9b..b65d3f42a4c 100644 --- a/src/BizHawk.Client.Common/cheats/GbaGameSharkDecoder.cs +++ b/src/BizHawk.Client.Common/cheats/GbaGameSharkDecoder.cs @@ -1,7 +1,7 @@ -using System; using System.Globalization; using System.Linq; +#pragma warning disable MA0089 namespace BizHawk.Client.Common.cheats { // TODO: @@ -95,3 +95,4 @@ private static string GetLast(string str, int length) } } } +#pragma warning restore MA0089 diff --git a/src/BizHawk.Client.Common/cheats/GenesisActionReplayDecoder.cs b/src/BizHawk.Client.Common/cheats/GenesisActionReplayDecoder.cs index ee61b0a9351..a8b4856004c 100644 --- a/src/BizHawk.Client.Common/cheats/GenesisActionReplayDecoder.cs +++ b/src/BizHawk.Client.Common/cheats/GenesisActionReplayDecoder.cs @@ -1,6 +1,6 @@ -using System; using System.Globalization; +#pragma warning disable MA0089 namespace BizHawk.Client.Common.cheats { // TODO: validate string and throw @@ -51,3 +51,4 @@ public static IDecodeResult Decode(string code) } } } +#pragma warning restore MA0089 diff --git a/src/BizHawk.Client.Common/cheats/GenesisGameGenieDecoder.cs b/src/BizHawk.Client.Common/cheats/GenesisGameGenieDecoder.cs index 290db9c097c..3ee7bc2eaa4 100644 --- a/src/BizHawk.Client.Common/cheats/GenesisGameGenieDecoder.cs +++ b/src/BizHawk.Client.Common/cheats/GenesisGameGenieDecoder.cs @@ -1,6 +1,6 @@ -using System; using System.Collections.Generic; +#pragma warning disable MA0089 namespace BizHawk.Client.Common.cheats { public static class GenesisGameGenieDecoder @@ -85,3 +85,4 @@ public static IDecodeResult Decode(string code) } } } +#pragma warning restore MA0089 diff --git a/src/BizHawk.Client.Common/cheats/N64GameSharkDecoder.cs b/src/BizHawk.Client.Common/cheats/N64GameSharkDecoder.cs index 2d42fcc523a..de6a7c4da45 100644 --- a/src/BizHawk.Client.Common/cheats/N64GameSharkDecoder.cs +++ b/src/BizHawk.Client.Common/cheats/N64GameSharkDecoder.cs @@ -1,6 +1,6 @@ -using System; using System.Globalization; +#pragma warning disable MA0089 namespace BizHawk.Client.Common.cheats { // TODO: support comparison cheat codes @@ -66,3 +66,4 @@ public static IDecodeResult Decode(string code) } } } +#pragma warning restore MA0089 diff --git a/src/BizHawk.Client.Common/cheats/NesGameGenieDecoder.cs b/src/BizHawk.Client.Common/cheats/NesGameGenieDecoder.cs index 1f5a25bb4b7..85656d4be45 100644 --- a/src/BizHawk.Client.Common/cheats/NesGameGenieDecoder.cs +++ b/src/BizHawk.Client.Common/cheats/NesGameGenieDecoder.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Client.Common.cheats diff --git a/src/BizHawk.Client.Common/cheats/PsxGameSharkDecoder.cs b/src/BizHawk.Client.Common/cheats/PsxGameSharkDecoder.cs index 3298a37227a..d5dbfd25548 100644 --- a/src/BizHawk.Client.Common/cheats/PsxGameSharkDecoder.cs +++ b/src/BizHawk.Client.Common/cheats/PsxGameSharkDecoder.cs @@ -1,6 +1,6 @@ -using System; using System.Globalization; +#pragma warning disable MA0089 namespace BizHawk.Client.Common.cheats { // TODO: cheats support comparison type, so we could support a lot more codes, by having Compare and Type properties and parsing @@ -57,3 +57,4 @@ public static IDecodeResult Decode(string code) } } } +#pragma warning restore MA0089 diff --git a/src/BizHawk.Client.Common/cheats/SaturnGameSharkDecoder.cs b/src/BizHawk.Client.Common/cheats/SaturnGameSharkDecoder.cs index 06fd4355471..19c00f73eea 100644 --- a/src/BizHawk.Client.Common/cheats/SaturnGameSharkDecoder.cs +++ b/src/BizHawk.Client.Common/cheats/SaturnGameSharkDecoder.cs @@ -1,6 +1,6 @@ -using System; using System.Globalization; +#pragma warning disable MA0089 namespace BizHawk.Client.Common.cheats { public static class SaturnGameSharkDecoder @@ -44,3 +44,4 @@ public static IDecodeResult Decode(string code) } } } +#pragma warning restore MA0089 diff --git a/src/BizHawk.Client.Common/cheats/SmsActionReplayDecoder.cs b/src/BizHawk.Client.Common/cheats/SmsActionReplayDecoder.cs index c3ef9867a52..55baef56390 100644 --- a/src/BizHawk.Client.Common/cheats/SmsActionReplayDecoder.cs +++ b/src/BizHawk.Client.Common/cheats/SmsActionReplayDecoder.cs @@ -1,6 +1,6 @@ -using System; using System.Globalization; +#pragma warning disable MA0089 namespace BizHawk.Client.Common.cheats { public static class SmsActionReplayDecoder @@ -28,3 +28,4 @@ public static IDecodeResult Decode(string code) } } } +#pragma warning restore MA0089 diff --git a/src/BizHawk.Client.Common/cheats/SnesActionReplayDecoder.cs b/src/BizHawk.Client.Common/cheats/SnesActionReplayDecoder.cs index 08098a0a9e1..0d1d1d04cfd 100644 --- a/src/BizHawk.Client.Common/cheats/SnesActionReplayDecoder.cs +++ b/src/BizHawk.Client.Common/cheats/SnesActionReplayDecoder.cs @@ -1,4 +1,3 @@ -using System; using System.Globalization; namespace BizHawk.Client.Common.cheats diff --git a/src/BizHawk.Client.Common/cheats/SnesGameGenieDecoder.cs b/src/BizHawk.Client.Common/cheats/SnesGameGenieDecoder.cs index 24e12e8e80f..e5e97ae5acc 100644 --- a/src/BizHawk.Client.Common/cheats/SnesGameGenieDecoder.cs +++ b/src/BizHawk.Client.Common/cheats/SnesGameGenieDecoder.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Client.Common.cheats diff --git a/src/BizHawk.Client.Common/config/Config.cs b/src/BizHawk.Client.Common/config/Config.cs index 69acf219b1a..128927b2c7d 100644 --- a/src/BizHawk.Client.Common/config/Config.cs +++ b/src/BizHawk.Client.Common/config/Config.cs @@ -1,9 +1,9 @@ -using System; using System.Collections.Generic; using System.IO; -using BizHawk.Bizware.BizwareGL; +using BizHawk.Bizware.Graphics; using BizHawk.Common; +using BizHawk.Common.CollectionExtensions; using BizHawk.Common.PathExtensions; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores; @@ -18,38 +18,53 @@ public class Config public static string ControlDefaultPath => Path.Combine(PathUtils.ExeDirectoryPath, "defctrl.json"); /// - /// AppliesTo[0] is used as the group label, and + /// CoreNames[0] is the default (out-of-the-box) core.
+ /// AppliesTo are concatenated to make the submenu's label, and /// Config.PreferredCores[AppliesTo[0]] (lookup on global instance) determines which option is shown as checked.
/// The order within submenus and the order of the submenus themselves are determined by the declaration order here. ///
public static readonly IReadOnlyList<(string[] AppliesTo, string[] CoreNames)> CorePickerUIData = new List<(string[], string[])> { - (new[] { VSystemID.Raw.A26 }, - new[] { CoreNames.Stella, CoreNames.Atari2600Hawk }), - (new[] { VSystemID.Raw.GB, VSystemID.Raw.GBC }, - new[] { CoreNames.Gambatte, CoreNames.Sameboy, CoreNames.GbHawk, CoreNames.SubGbHawk }), - (new[] { VSystemID.Raw.GBL }, - new[] { CoreNames.GambatteLink, CoreNames.GBHawkLink, CoreNames.GBHawkLink3x, CoreNames.GBHawkLink4x }), - (new[] { VSystemID.Raw.SGB }, - new[] { CoreNames.Gambatte, CoreNames.Bsnes115, CoreNames.SubBsnes115, CoreNames.Bsnes }), - (new[] { VSystemID.Raw.GEN }, - new[] { CoreNames.Gpgx, CoreNames.PicoDrive }), - (new[] { VSystemID.Raw.N64 }, - new[] { CoreNames.Mupen64Plus, CoreNames.Ares64 }), - (new[] { VSystemID.Raw.NES }, - new[] { CoreNames.QuickNes, CoreNames.NesHawk, CoreNames.SubNesHawk }), - (new[] { VSystemID.Raw.PCE, VSystemID.Raw.PCECD, VSystemID.Raw.SGX, VSystemID.Raw.SGXCD }, - new[] { CoreNames.TurboNyma, CoreNames.HyperNyma, CoreNames.PceHawk }), - (new[] { VSystemID.Raw.PSX }, - new[] { CoreNames.Nymashock, CoreNames.Octoshock }), - (new[] { VSystemID.Raw.SMS, VSystemID.Raw.GG, VSystemID.Raw.SG }, - new[] { CoreNames.Gpgx, CoreNames.SMSHawk }), - (new[] { VSystemID.Raw.SNES }, - new[] { CoreNames.Snes9X, CoreNames.Bsnes115, CoreNames.SubBsnes115, CoreNames.Faust, CoreNames.Bsnes }), - (new[] { VSystemID.Raw.TI83 }, - new[] { CoreNames.Emu83, CoreNames.TI83Hawk }), + ([ VSystemID.Raw.A26 ], + [ CoreNames.Stella, CoreNames.Atari2600Hawk ]), + ([ VSystemID.Raw.Satellaview ], + [ CoreNames.Bsnes115, CoreNames.SubBsnes115 ]), + ([ VSystemID.Raw.GB, VSystemID.Raw.GBC ], + [ CoreNames.Gambatte, CoreNames.Sameboy, CoreNames.GbHawk, CoreNames.SubGbHawk ]), + ([ VSystemID.Raw.GBL ], + [ CoreNames.GambatteLink, CoreNames.GBHawkLink, CoreNames.GBHawkLink3x, CoreNames.GBHawkLink4x ]), + ([ VSystemID.Raw.SGB ], + [ CoreNames.Gambatte, CoreNames.Bsnes115, CoreNames.SubBsnes115, CoreNames.Bsnes ]), + ([ VSystemID.Raw.GEN ], + [ CoreNames.Gpgx, CoreNames.PicoDrive ]), + ([ VSystemID.Raw.N64 ], + [ CoreNames.Mupen64Plus, CoreNames.Ares64 ]), + ([ VSystemID.Raw.NES ], + [ CoreNames.QuickNes, CoreNames.NesHawk, CoreNames.SubNesHawk ]), + ([ VSystemID.Raw.PCE, VSystemID.Raw.PCECD, VSystemID.Raw.SGX, VSystemID.Raw.SGXCD ], + [ CoreNames.TurboNyma, CoreNames.HyperNyma, CoreNames.PceHawk ]), + ([ VSystemID.Raw.PSX ], + [ CoreNames.Nymashock, CoreNames.Octoshock ]), + ([ VSystemID.Raw.SMS, VSystemID.Raw.GG, VSystemID.Raw.SG ], + [ CoreNames.Gpgx, CoreNames.SMSHawk ]), + ([ VSystemID.Raw.SNES ], + [ CoreNames.Snes9X, CoreNames.Bsnes115, CoreNames.SubBsnes115, CoreNames.Faust, CoreNames.Bsnes ]), + ([ VSystemID.Raw.TI83 ], + [ CoreNames.Emu83, CoreNames.TI83Hawk ]), + }; + public static Dictionary GenDefaultCorePreferences() + { + Dictionary dict = new(); + foreach (var (appliesTo, coreNames) in CorePickerUIData) + { + var defaultCore = coreNames[0]; + foreach (var sysID in appliesTo) dict[sysID] = defaultCore; + } + return dict; + } + public Config() { if (AllTrollers.Count == 0 @@ -98,7 +113,20 @@ public void ResolveDefaults() public bool StackOSDMessages { get; set; } = true; - public ZoomFactors TargetZoomFactors { get; set; } = new ZoomFactors(); + private Dictionary TargetZoomFactors { get; set; } = new() + { + [VSystemID.Raw.GB] = 3, + [VSystemID.Raw.GBA] = 3, + [VSystemID.Raw.GBC] = 3, + [VSystemID.Raw.N64] = 1, + [VSystemID.Raw.WSWAN] = 3, + }; + + public int GetWindowScaleFor(string sysID) + => TargetZoomFactors.GetValueOrPut(sysID, static _ => 2); + + public void SetWindowScaleFor(string sysID, int windowScale) + => TargetZoomFactors[sysID] = windowScale; // choose between 0 and 256 public int TargetScanlineFilterIntensity { get; set; } = 128; @@ -188,9 +216,9 @@ public void ResolveDefaults() public bool VSync { get; set; } /// - /// Tries to use an alternate vsync mechanism, for video cards that just can't do it right + /// Allows non-vsync'd video to tear, this is needed for VFR monitors reportedly /// - public bool DispAlternateVsync { get; set; } + public bool DispAllowTearing { get; set; } // Display options public bool DisplayFps { get; set; } @@ -222,7 +250,7 @@ public void ResolveDefaults() public int DispPrescale { get; set; } = 1; - public EDispMethod DispMethod { get; set; } = HostCapabilityDetector.HasD3D9 && !OSTailoredCode.IsWine ? EDispMethod.D3D9 : EDispMethod.OpenGL; + public EDispMethod DispMethod { get; set; } = HostCapabilityDetector.HasD3D11 && !OSTailoredCode.IsWine ? EDispMethod.D3D11 : EDispMethod.OpenGL; public int DispChromeFrameWindowed { get; set; } = 2; public bool DispChromeStatusBarWindowed { get; set; } = true; @@ -370,22 +398,7 @@ public void ResolveDefaults() public bool GbAsSgb { get; set; } public string LibretroCore { get; set; } - public Dictionary PreferredCores = new() - { - [VSystemID.Raw.NES] = CoreNames.QuickNes, - [VSystemID.Raw.SNES] = CoreNames.Snes9X, - [VSystemID.Raw.N64] = CoreNames.Mupen64Plus, - [VSystemID.Raw.GB] = CoreNames.Gambatte, - [VSystemID.Raw.GBC] = CoreNames.Gambatte, - [VSystemID.Raw.GBL] = CoreNames.GambatteLink, - [VSystemID.Raw.SGB] = CoreNames.Gambatte, - [VSystemID.Raw.PCE] = CoreNames.TurboNyma, - [VSystemID.Raw.PCECD] = CoreNames.TurboNyma, - [VSystemID.Raw.SGX] = CoreNames.TurboNyma, - [VSystemID.Raw.SGXCD] = CoreNames.TurboNyma, - [VSystemID.Raw.PSX] = CoreNames.Nymashock, - [VSystemID.Raw.TI83] = CoreNames.Emu83, - }; + public Dictionary PreferredCores = GenDefaultCorePreferences(); public bool DontTryOtherCores { get; set; } diff --git a/src/BizHawk.Client.Common/config/ConfigExtensions.cs b/src/BizHawk.Client.Common/config/ConfigExtensions.cs index db982d0d3aa..17176e6e436 100644 --- a/src/BizHawk.Client.Common/config/ConfigExtensions.cs +++ b/src/BizHawk.Client.Common/config/ConfigExtensions.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; @@ -40,8 +39,6 @@ private static object Deserialize(JToken j, Type type) /// /// Returns the core settings for a core /// - /// - /// /// null if no settings were saved, or there was an error deserializing public static object GetCoreSettings(this Config config, Type coreType, Type settingsType) { @@ -62,9 +59,7 @@ public static TSetting GetCoreSettings(this Config config) /// /// saves the core settings for a core /// - /// /// null to remove settings for that core instead - /// public static void PutCoreSettings(this Config config, object o, Type coreType) { if (o != null) @@ -80,8 +75,6 @@ public static void PutCoreSettings(this Config config, object o, Type coreType) /// /// Returns the core syncsettings for a core /// - /// - /// /// null if no settings were saved, or there was an error deserializing public static object GetCoreSyncSettings(this Config config, Type coreType, Type syncSettingsType) { @@ -102,9 +95,7 @@ public static TSync GetCoreSyncSettings(this Config config) /// /// saves the core syncsettings for a core /// - /// /// null to remove settings for that core instead - /// public static void PutCoreSyncSettings(this Config config, object o, Type coreType) { if (o != null) diff --git a/src/BizHawk.Client.Common/config/ConfigGroupingStructAttribute.cs b/src/BizHawk.Client.Common/config/ConfigGroupingStructAttribute.cs index 7711d10ed33..bf70e5caf75 100644 --- a/src/BizHawk.Client.Common/config/ConfigGroupingStructAttribute.cs +++ b/src/BizHawk.Client.Common/config/ConfigGroupingStructAttribute.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Client.Common { [AttributeUsage(AttributeTargets.Field)] diff --git a/src/BizHawk.Client.Common/config/ConfigPersistAttribute.cs b/src/BizHawk.Client.Common/config/ConfigPersistAttribute.cs index 7931c2f9a28..03839199183 100644 --- a/src/BizHawk.Client.Common/config/ConfigPersistAttribute.cs +++ b/src/BizHawk.Client.Common/config/ConfigPersistAttribute.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Client.Common { /// Indicates that a property is to be saved to config for persistence. diff --git a/src/BizHawk.Client.Common/config/ConfigService.cs b/src/BizHawk.Client.Common/config/ConfigService.cs index 310790ac32c..fda1ba59ed8 100644 --- a/src/BizHawk.Client.Common/config/ConfigService.cs +++ b/src/BizHawk.Client.Common/config/ConfigService.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Reflection; @@ -41,7 +40,7 @@ public static bool IsFromSameVersion(string filepath, out string msg) const string MSGFMT_PRE_2_3_3 = "Your config file ({0}) is corrupted, or is from an older version of EmuHawk, predating 2.3.3 (this is {1}). It may fail to load."; const string MSGFMT_PRE_2_5 = "Your config file ({0}) is corrupted, or is from an older version of EmuHawk, predating 2.5 (this is {1}). It may fail to load."; - if (!new FileInfo(filepath).Exists) + if (!File.Exists(filepath)) { msg = null; return true; diff --git a/src/BizHawk.Client.Common/config/ConfigSettingsAdapter.cs b/src/BizHawk.Client.Common/config/ConfigSettingsAdapter.cs index 7fcaa9d36f0..32556717e3e 100644 --- a/src/BizHawk.Client.Common/config/ConfigSettingsAdapter.cs +++ b/src/BizHawk.Client.Common/config/ConfigSettingsAdapter.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Linq; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.Common/config/EditorUIGeneratorAttribute.cs b/src/BizHawk.Client.Common/config/EditorUIGeneratorAttribute.cs index df67338ec83..b8a78f24c24 100644 --- a/src/BizHawk.Client.Common/config/EditorUIGeneratorAttribute.cs +++ b/src/BizHawk.Client.Common/config/EditorUIGeneratorAttribute.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Client.Common { [AttributeUsage(AttributeTargets.Property)] diff --git a/src/BizHawk.Client.Common/config/PathEntryCollection.cs b/src/BizHawk.Client.Common/config/PathEntryCollection.cs index c2dec1d2c77..cba2e3a97cf 100644 --- a/src/BizHawk.Client.Common/config/PathEntryCollection.cs +++ b/src/BizHawk.Client.Common/config/PathEntryCollection.cs @@ -1,5 +1,3 @@ -using System; -using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; @@ -12,8 +10,7 @@ namespace BizHawk.Client.Common { - [JsonObject] - public class PathEntryCollection : IEnumerable + public class PathEntryCollection { private static readonly string COMBINED_SYSIDS_GB = string.Join("_", VSystemID.Raw.GB, VSystemID.Raw.GBC, VSystemID.Raw.SGB); @@ -24,6 +21,7 @@ public class PathEntryCollection : IEnumerable private static readonly Dictionary _displayNameLookup = new() { [GLOBAL] = "Global", + [VSystemID.Raw.Amiga] = "Amiga", [VSystemID.Raw.Arcade] = "Arcade", [VSystemID.Raw.INTV] = "Intellivision", [VSystemID.Raw.NES] = "NES", @@ -74,14 +72,14 @@ private static PathEntry CheatsEntryFor(string sysID) => new(sysID, "Cheats", Path.Combine(".", "Cheats")); private static IEnumerable CommonEntriesFor(string sysID, string basePath, bool omitSaveRAM = false) - { - yield return BaseEntryFor(sysID, basePath); - yield return ROMEntryFor(sysID); - yield return SavestatesEntryFor(sysID); - if (!omitSaveRAM) yield return SaveRAMEntryFor(sysID); - yield return ScreenshotsEntryFor(sysID); - yield return CheatsEntryFor(sysID); - } + => [ + BaseEntryFor(sysID, basePath), + ROMEntryFor(sysID), + SavestatesEntryFor(sysID), + ..(omitSaveRAM ? [ ] : new[] { SaveRAMEntryFor(sysID) }), + ScreenshotsEntryFor(sysID), + CheatsEntryFor(sysID), + ]; public static string GetDisplayNameFor(string sysID) => _displayNameLookup.GetValueOrPut(sysID, static s => s + " (INTERIM)"); @@ -120,9 +118,6 @@ public PathEntryCollection() : this(new List(Defaults.Value)) {} public bool UseRecentForRoms { get; set; } public string LastRomPath { get; set; } = "."; - public IEnumerator GetEnumerator() => Paths.GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public PathEntry this[string system, string type] => Paths.Find(p => p.IsSystem(system) && p.Type == type) ?? TryGetDebugPath(system, type); @@ -198,6 +193,8 @@ public void ResolveWithDefaults() CommonEntriesFor(VSystemID.Raw.Sega32X, basePath: Path.Combine(".", "32X")), + CommonEntriesFor(VSystemID.Raw.Amiga, basePath: Path.Combine(".", "Amiga")), + CommonEntriesFor(VSystemID.Raw.A26, basePath: Path.Combine(".", "Atari 2600"), omitSaveRAM: true), CommonEntriesFor(VSystemID.Raw.A78, basePath: Path.Combine(".", "Atari 7800")), diff --git a/src/BizHawk.Client.Common/config/PathEntryCollectionExtensions.cs b/src/BizHawk.Client.Common/config/PathEntryCollectionExtensions.cs index 9ae93cdf6a9..79e6c069aef 100644 --- a/src/BizHawk.Client.Common/config/PathEntryCollectionExtensions.cs +++ b/src/BizHawk.Client.Common/config/PathEntryCollectionExtensions.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Common; using BizHawk.Common.PathExtensions; @@ -181,6 +180,12 @@ public static string ToolsAbsolutePath(this PathEntryCollection collection) return collection.AbsolutePathFor(path, null); } + public static string ExternalToolsAbsolutePath(this PathEntryCollection collection) + { + var path = collection[PathEntryCollection.GLOBAL, "External Tools"].Path; + return collection.AbsolutePathFor(path, null); + } + public static string MultiDiskAbsolutePath(this PathEntryCollection collection) { var path = collection.ResolveToolsPath(collection[PathEntryCollection.GLOBAL, "Multi-Disk Bundles"].Path); diff --git a/src/BizHawk.Client.Common/config/RestoreDefaultsAttribute.cs b/src/BizHawk.Client.Common/config/RestoreDefaultsAttribute.cs index bdfcd53dda2..c891c6fc556 100644 --- a/src/BizHawk.Client.Common/config/RestoreDefaultsAttribute.cs +++ b/src/BizHawk.Client.Common/config/RestoreDefaultsAttribute.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Client.Common { /// Indicates which method of an is to be called when the generated Restore Defaults menu item is clicked. diff --git a/src/BizHawk.Client.Common/config/ToolDialogSettings.cs b/src/BizHawk.Client.Common/config/ToolDialogSettings.cs index 5c2304af1ba..39f44327aca 100644 --- a/src/BizHawk.Client.Common/config/ToolDialogSettings.cs +++ b/src/BizHawk.Client.Common/config/ToolDialogSettings.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Client.Common/config/ZoomFactors.cs b/src/BizHawk.Client.Common/config/ZoomFactors.cs deleted file mode 100644 index bf5572142c7..00000000000 --- a/src/BizHawk.Client.Common/config/ZoomFactors.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Collections.Generic; - -namespace BizHawk.Client.Common -{ - public class ZoomFactors : Dictionary - { - public new int this[string index] - { - get - { - if (!ContainsKey(index)) - { - Add(index, 2); - } - - return base[index]; - } - - set => base[index] = value; - } - } -} diff --git a/src/BizHawk.Client.Common/controllers/AutofireController.cs b/src/BizHawk.Client.Common/controllers/AutofireController.cs index 854562f323d..dd739accc55 100644 --- a/src/BizHawk.Client.Common/controllers/AutofireController.cs +++ b/src/BizHawk.Client.Common/controllers/AutofireController.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; @@ -65,7 +64,7 @@ public void LatchFromPhysical(IController controller) { foreach (var boundBtn in v) { - if (_buttons[k] == false && controller.IsPressed(boundBtn)) + if (!_buttons[k] && controller.IsPressed(boundBtn)) { _buttonStarts[k] = _emulator.Frame; } diff --git a/src/BizHawk.Client.Common/controllers/ClickyVirtualPadController.cs b/src/BizHawk.Client.Common/controllers/ClickyVirtualPadController.cs index 2c39ea71228..991507e94d1 100644 --- a/src/BizHawk.Client.Common/controllers/ClickyVirtualPadController.cs +++ b/src/BizHawk.Client.Common/controllers/ClickyVirtualPadController.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.Common/display/IInputDisplayGenerator.cs b/src/BizHawk.Client.Common/display/IInputDisplayGenerator.cs index ef6c1cdf2a7..a0f84b99f47 100644 --- a/src/BizHawk.Client.Common/display/IInputDisplayGenerator.cs +++ b/src/BizHawk.Client.Common/display/IInputDisplayGenerator.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/BizHawk.Client.Common/input/HostInputAdapter.cs b/src/BizHawk.Client.Common/input/HostInputAdapter.cs index a9c884d0805..4198544a250 100644 --- a/src/BizHawk.Client.Common/input/HostInputAdapter.cs +++ b/src/BizHawk.Client.Common/input/HostInputAdapter.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; namespace BizHawk.Client.Common diff --git a/src/BizHawk.Client.Common/input/InputEvent.cs b/src/BizHawk.Client.Common/input/InputEvent.cs index dd7a7d3572d..bfb2017f92d 100644 --- a/src/BizHawk.Client.Common/input/InputEvent.cs +++ b/src/BizHawk.Client.Common/input/InputEvent.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.Text; @@ -62,7 +61,8 @@ public LogicalButton(string button, uint modifiers, Func> public override readonly bool Equals(object? obj) => obj is not null && (LogicalButton) obj == this; //TODO safe type check? - public override readonly int GetHashCode() => Button.GetHashCode() ^ Modifiers.GetHashCode(); + public override readonly int GetHashCode() + => HashCode.Combine(Button, Modifiers); public override readonly string ToString() { diff --git a/src/BizHawk.Client.Common/inputAdapters/InputManager.cs b/src/BizHawk.Client.Common/inputAdapters/InputManager.cs index edf2174518b..12d9f01f21a 100644 --- a/src/BizHawk.Client.Common/inputAdapters/InputManager.cs +++ b/src/BizHawk.Client.Common/inputAdapters/InputManager.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; @@ -11,7 +10,9 @@ namespace BizHawk.Client.Common // user -> Input -> ActiveController -> UDLR -> StickyXORPlayerInputAdapter -> TurboAdapter(TBD) -> Lua(?TBD?) -> .. // .. -> MovieInputSourceAdapter -> (MovieSession) -> MovieOutputAdapter -> ControllerOutput(1) -> Game // (1)->Input Display +#pragma warning disable MA0104 // unlikely to conflict with System.Windows.Input.InputManager public class InputManager +#pragma warning restore MA0104 { // the original source controller, bound to the user, sort of the "input" port for the chain, i think public Controller ActiveController { get; private set; } diff --git a/src/BizHawk.Client.Common/inputAdapters/OverrideAdapter.cs b/src/BizHawk.Client.Common/inputAdapters/OverrideAdapter.cs index d4dee4e1423..e554e3ef016 100644 --- a/src/BizHawk.Client.Common/inputAdapters/OverrideAdapter.cs +++ b/src/BizHawk.Client.Common/inputAdapters/OverrideAdapter.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.Common/lua/CommonLibs/ClientLuaLibrary.cs b/src/BizHawk.Client.Common/lua/CommonLibs/ClientLuaLibrary.cs index 05188fe2813..e72d1504476 100644 --- a/src/BizHawk.Client.Common/lua/CommonLibs/ClientLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/CommonLibs/ClientLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Diagnostics; using System.Drawing; diff --git a/src/BizHawk.Client.Common/lua/CommonLibs/CommLuaLibrary.cs b/src/BizHawk.Client.Common/lua/CommonLibs/CommLuaLibrary.cs index bc44d08d1cb..db050266a2d 100644 --- a/src/BizHawk.Client.Common/lua/CommonLibs/CommLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/CommonLibs/CommLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; @@ -93,7 +92,7 @@ public void SocketServerSetIp(string ip) } [LuaMethod("socketServerSetPort", "sets the port of the Lua socket server")] - public void SocketServerSetPort(int port) + public void SocketServerSetPort(ushort port) { CheckSocketServer(); APIs.Comm.Sockets.Port = port; diff --git a/src/BizHawk.Client.Common/lua/CommonLibs/EmulationLuaLibrary.cs b/src/BizHawk.Client.Common/lua/CommonLibs/EmulationLuaLibrary.cs index 879e741a397..189419e1d32 100644 --- a/src/BizHawk.Client.Common/lua/CommonLibs/EmulationLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/CommonLibs/EmulationLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using NLua; diff --git a/src/BizHawk.Client.Common/lua/CommonLibs/GameInfoLuaLibrary.cs b/src/BizHawk.Client.Common/lua/CommonLibs/GameInfoLuaLibrary.cs index 66a97e9e78e..d9b38b8271d 100644 --- a/src/BizHawk.Client.Common/lua/CommonLibs/GameInfoLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/CommonLibs/GameInfoLuaLibrary.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; using NLua; diff --git a/src/BizHawk.Client.Common/lua/CommonLibs/GuiLuaLibrary.cs b/src/BizHawk.Client.Common/lua/CommonLibs/GuiLuaLibrary.cs index ac7f6a5ba0f..b308e5ffd09 100644 --- a/src/BizHawk.Client.Common/lua/CommonLibs/GuiLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/CommonLibs/GuiLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Linq; @@ -21,6 +20,7 @@ private DisplaySurfaceID UseOrFallback(string surfaceName) => DisplaySurfaceIDParser.Parse(surfaceName) ?? _rememberedSurfaceID; #pragma warning disable CS0612 +#pragma warning disable CS0618 [LuaDeprecatedMethod] [LuaMethod("DrawNew", "Changes drawing target to the specified lua surface name. This may clobber any previous drawing to this surface (pass false if you don't want it to)")] public void DrawNew(string name, bool? clear = true) @@ -31,6 +31,7 @@ public void DrawNew(string name, bool? clear = true) public void DrawFinish() => APIs.Gui.DrawFinish(); #pragma warning restore CS0612 +#pragma warning restore CS0618 [LuaMethodExample("gui.addmessage( \"Some message\" );")] [LuaMethod("addmessage", "Adds a message to the OSD's message area")] @@ -92,7 +93,7 @@ public void DrawBezier( } catch (Exception) { - return; + // ignored } } @@ -232,7 +233,7 @@ public void DrawPolygon( } catch (Exception) { - return; + // ignored } } @@ -249,7 +250,7 @@ public void DrawRectangle( => APIs.Gui.DrawRectangle(x, y, width, height, _th.SafeParseColor(line), _th.SafeParseColor(background), surfaceID: UseOrFallback(surfaceName)); [LuaMethodExample("gui.drawString( 16, 32, \"Some message\", 0x7F0000FF, 0x00007FFF, 8, \"Arial Narrow\", \"bold\", \"center\", \"middle\" );")] - [LuaMethod("drawString", "Draws the given message in the emulator screen space (like all draw functions) at the given x,y coordinates and the given color. The default color is white. A fontfamily can be specified and is monospace generic if none is specified (font family options are the same as the .NET FontFamily class). The fontsize default is 12. The default font style is regular. Font style options are regular, bold, italic, strikethrough, underline. Horizontal alignment options are left (default), center, or right. Vertical alignment options are bottom (default), middle, or top. Alignment options specify which ends of the text will be drawn at the x and y coordinates. For pixel-perfect font look, make sure to disable aspect ratio correction.")] + [LuaMethod("drawString", "Draws the given message in the emulator screen space (like all draw functions) at the given x,y coordinates and the given color. The default color is white. A fontfamily can be specified and is monospace generic if none is specified (font family options are the same as the .NET FontFamily class). The fontsize default is 12. The default font style is regular. Font style options are regular, bold, italic, strikethrough, underline. Horizontal alignment options are left (default), center, or right. Vertical alignment options are bottom (default), middle, or top. Alignment options specify which ends of the text will be drawn at the x and y coordinates. For pixel-perfect font look, make sure to disable aspect ratio correction. Note that all text drawing occurs after all other drawing occurs (e.g. after gui.drawRectangle() regardless of call order).")] public void DrawString( int x, int y, @@ -304,7 +305,7 @@ public void DrawText( surfaceName: surfaceName); [LuaMethodExample("gui.pixelText( 16, 32, \"Some message\", 0x7F0000FF, 0x00007FFF, \"Arial Narrow\" );")] - [LuaMethod("pixelText", "Draws the given message in the emulator screen space (like all draw functions) at the given x,y coordinates and the given color. The default color is white. Two font families are available, \"fceux\" and \"gens\" (or \"0\" and \"1\" respectively), both are monospace and have the same size as in the emulators they've been taken from. If no font family is specified, it uses \"gens\" font, unless that's overridden via gui.defaultPixelFont()")] + [LuaMethod("pixelText", "Draws the given message in the emulator screen space (like all draw functions) at the given x,y coordinates and the given color. The default color is white. Two font families are available, \"fceux\" and \"gens\" (or \"0\" and \"1\" respectively), both are monospace and have the same size as in the emulators they've been taken from. If no font family is specified, it uses \"gens\" font, unless that's overridden via gui.defaultPixelFont(). Note that all text drawing occurs after all other drawing occurs (e.g. after gui.drawRectangle() regardless of call order).")] public void PixelText( int x, int y, @@ -313,10 +314,10 @@ public void PixelText( [LuaColorParam] object backcolor = null, string fontfamily = null, string surfaceName = null) - => APIs.Gui.PixelText(x, y, message, _th.SafeParseColor(forecolor), _th.SafeParseColor(backcolor) ?? APIs.Gui.GetDefaultTextBackground().Value, fontfamily, surfaceID: UseOrFallback(surfaceName)); + => APIs.Gui.PixelText(x, y, message, _th.SafeParseColor(forecolor), _th.SafeParseColor(backcolor) ?? APIs.Gui.GetDefaultTextBackground(), fontfamily, surfaceID: UseOrFallback(surfaceName)); [LuaMethodExample("gui.text( 16, 32, \"Some message\", 0x7F0000FF, \"bottomleft\" );")] - [LuaMethod("text", "Displays the given text on the screen at the given coordinates. Optional Foreground color. The optional anchor flag anchors the text to one of the four corners. Anchor flag parameters: topleft, topright, bottomleft, bottomright")] + [LuaMethod("text", "Displays the given text on the screen at the given coordinates. Optional Foreground color. The optional anchor flag anchors the text to one of the four corners. Anchor flag parameters: topleft, topright, bottomleft, bottomright. This function is generally much faster than other text drawing functions, at the cost of customization. Note that all text drawing occurs after all other drawing occurs (e.g. after gui.drawRectangle() regardless of call order).")] public void Text( int x, int y, diff --git a/src/BizHawk.Client.Common/lua/CommonLibs/InputLuaLibrary.cs b/src/BizHawk.Client.Common/lua/CommonLibs/InputLuaLibrary.cs index d22308d5742..b6d016f66f5 100644 --- a/src/BizHawk.Client.Common/lua/CommonLibs/InputLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/CommonLibs/InputLuaLibrary.cs @@ -1,5 +1,3 @@ -using System; - using NLua; namespace BizHawk.Client.Common @@ -11,12 +9,12 @@ public InputLuaLibrary(ILuaLibraries luaLibsImpl, ApiContainer apiContainer, Act public override string Name => "input"; -#pragma warning disable CS0612 [LuaMethodExample("local buttons_down = input.get();\nlocal is_b_down = buttons_down[\"B\"];\nif is_b_down and not was_b_down then console.writeline(\"B pressed\"); end\nwas_b_down = is_b_down;")] [LuaMethod("get", "Returns a dict-like table of key/button names (of host). Only pressed buttons will appear (with a value of {{true}}); unpressed buttons are omitted. Includes gamepad axes ({{!axis.isNeutral}}, with sticks as 4 \"buttons\" suffixed {{\"Up\"}}/{{\"Down\"}}/{{\"Left\"}}/{{\"Right\"}}). Includes mouse buttons, but not axes (cursor position and wheel rotation). Unlike {{getmouse}}, these have the names {{\"WMouse L\"}}, {{\"WMouse R\"}}, {{\"WMouse C\"}}, {{\"WMouse 1\"}}, and {{\"WMouse 2\"}} for LMB, RMB, MMB, Mouse4, and Mouse5, respectively.")] public LuaTable Get() +#pragma warning disable CS0618 // the ApiHawk equivalent of this function is warn-level deprecated; Lua can't and shouldn't make that distinction => _th.DictToTable(APIs.Input.Get()); -#pragma warning restore CS0612 +#pragma warning restore CS0618 [LuaMethodExample("local mouse_buttons_down = input.getmouse();\nlocal is_m3_down = mouse_buttons_down[\"Middle\"];\nif is_m3_down and not was_m3_down then console.writeline(\"M3 pressed\"); end\nwas_m3_down = is_m3_down;")] [LuaMethod("getmouse", "Returns a lua table of the mouse X/Y coordinates and button states. Table keys are X, Y, Left, Middle, Right, XButton1, XButton2, Wheel.")] diff --git a/src/BizHawk.Client.Common/lua/CommonLibs/JoypadLuaLibrary.cs b/src/BizHawk.Client.Common/lua/CommonLibs/JoypadLuaLibrary.cs index 27799327c3d..5e75a9aaef3 100644 --- a/src/BizHawk.Client.Common/lua/CommonLibs/JoypadLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/CommonLibs/JoypadLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using NLua; diff --git a/src/BizHawk.Client.Common/lua/CommonLibs/MemoryLuaLibrary.cs b/src/BizHawk.Client.Common/lua/CommonLibs/MemoryLuaLibrary.cs index 945b378b127..a7523c196fd 100644 --- a/src/BizHawk.Client.Common/lua/CommonLibs/MemoryLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/CommonLibs/MemoryLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; diff --git a/src/BizHawk.Client.Common/lua/CommonLibs/MemorySavestateLuaLibrary.cs b/src/BizHawk.Client.Common/lua/CommonLibs/MemorySavestateLuaLibrary.cs index 58f9cec115b..08789b65fb7 100644 --- a/src/BizHawk.Client.Common/lua/CommonLibs/MemorySavestateLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/CommonLibs/MemorySavestateLuaLibrary.cs @@ -1,5 +1,3 @@ -using System; - // ReSharper disable UnusedMember.Global // ReSharper disable UnusedAutoPropertyAccessor.Local namespace BizHawk.Client.Common diff --git a/src/BizHawk.Client.Common/lua/CommonLibs/MovieLuaLibrary.cs b/src/BizHawk.Client.Common/lua/CommonLibs/MovieLuaLibrary.cs index aa8699816b7..b2060e62ba4 100644 --- a/src/BizHawk.Client.Common/lua/CommonLibs/MovieLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/CommonLibs/MovieLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using NLua; diff --git a/src/BizHawk.Client.Common/lua/CommonLibs/SQLiteLuaLibrary.cs b/src/BizHawk.Client.Common/lua/CommonLibs/SQLiteLuaLibrary.cs index 9ac0170f491..be2d2294947 100644 --- a/src/BizHawk.Client.Common/lua/CommonLibs/SQLiteLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/CommonLibs/SQLiteLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; diff --git a/src/BizHawk.Client.Common/lua/CommonLibs/SaveStateLuaLibrary.cs b/src/BizHawk.Client.Common/lua/CommonLibs/SaveStateLuaLibrary.cs index edca18f644e..926b3d38b5b 100644 --- a/src/BizHawk.Client.Common/lua/CommonLibs/SaveStateLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/CommonLibs/SaveStateLuaLibrary.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Client.Common { public sealed class SaveStateLuaLibrary : LuaLibraryBase diff --git a/src/BizHawk.Client.Common/lua/CommonLibs/UserDataLuaLibrary.cs b/src/BizHawk.Client.Common/lua/CommonLibs/UserDataLuaLibrary.cs index 13739df691f..f24185f39f5 100644 --- a/src/BizHawk.Client.Common/lua/CommonLibs/UserDataLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/CommonLibs/UserDataLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; diff --git a/src/BizHawk.Client.Common/lua/EnvironmentSandbox.cs b/src/BizHawk.Client.Common/lua/EnvironmentSandbox.cs index 3f201935e92..668475b7e07 100644 --- a/src/BizHawk.Client.Common/lua/EnvironmentSandbox.cs +++ b/src/BizHawk.Client.Common/lua/EnvironmentSandbox.cs @@ -1,5 +1,3 @@ -using System; - // TODO - kill this file (or renew the concept as distinct from the LuaSandbox?) namespace BizHawk.Client.Common { diff --git a/src/BizHawk.Client.Common/lua/ILuaLibraries.cs b/src/BizHawk.Client.Common/lua/ILuaLibraries.cs index 2a36e2df454..c4e1ea10789 100644 --- a/src/BizHawk.Client.Common/lua/ILuaLibraries.cs +++ b/src/BizHawk.Client.Common/lua/ILuaLibraries.cs @@ -1,5 +1,3 @@ -using System; - using NLua; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.Common/lua/INamedLuaFunction.cs b/src/BizHawk.Client.Common/lua/INamedLuaFunction.cs index 1d38ee67f9f..412e0bb27d0 100644 --- a/src/BizHawk.Client.Common/lua/INamedLuaFunction.cs +++ b/src/BizHawk.Client.Common/lua/INamedLuaFunction.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Client.Common diff --git a/src/BizHawk.Client.Common/lua/LuaAttributes.cs b/src/BizHawk.Client.Common/lua/LuaAttributes.cs index 27ded63dbcd..acd24a12173 100644 --- a/src/BizHawk.Client.Common/lua/LuaAttributes.cs +++ b/src/BizHawk.Client.Common/lua/LuaAttributes.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Client.Common { [AttributeUsage(AttributeTargets.Parameter)] diff --git a/src/BizHawk.Client.Common/lua/LuaFileList.cs b/src/BizHawk.Client.Common/lua/LuaFileList.cs index 689a16e88e9..1ad8d64fa73 100644 --- a/src/BizHawk.Client.Common/lua/LuaFileList.cs +++ b/src/BizHawk.Client.Common/lua/LuaFileList.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Text; diff --git a/src/BizHawk.Client.Common/lua/LuaFunctionList.cs b/src/BizHawk.Client.Common/lua/LuaFunctionList.cs index 7e20aa4e6ee..c9640c655ae 100644 --- a/src/BizHawk.Client.Common/lua/LuaFunctionList.cs +++ b/src/BizHawk.Client.Common/lua/LuaFunctionList.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Client.Common/lua/LuaHelperLibs/BitLuaLibrary.cs b/src/BizHawk.Client.Common/lua/LuaHelperLibs/BitLuaLibrary.cs index f4620df8b11..99424486739 100644 --- a/src/BizHawk.Client.Common/lua/LuaHelperLibs/BitLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/LuaHelperLibs/BitLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.Buffers.Binary; using System.ComponentModel; diff --git a/src/BizHawk.Client.Common/lua/LuaHelperLibs/EventsLuaLibrary.cs b/src/BizHawk.Client.Common/lua/LuaHelperLibs/EventsLuaLibrary.cs index 4c5226fd4a6..f6b669670ae 100644 --- a/src/BizHawk.Client.Common/lua/LuaHelperLibs/EventsLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/LuaHelperLibs/EventsLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.ComponentModel; diff --git a/src/BizHawk.Client.Common/lua/LuaHelperLibs/GenesisLuaLibrary.cs b/src/BizHawk.Client.Common/lua/LuaHelperLibs/GenesisLuaLibrary.cs index b20db31a893..830000d97d5 100644 --- a/src/BizHawk.Client.Common/lua/LuaHelperLibs/GenesisLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/LuaHelperLibs/GenesisLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.Common/lua/LuaHelperLibs/MainMemoryLuaLibrary.cs b/src/BizHawk.Client.Common/lua/LuaHelperLibs/MainMemoryLuaLibrary.cs index 5c012bd8bf2..c1866470f2f 100644 --- a/src/BizHawk.Client.Common/lua/LuaHelperLibs/MainMemoryLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/LuaHelperLibs/MainMemoryLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Linq; diff --git a/src/BizHawk.Client.Common/lua/LuaHelperLibs/NDSLuaLibrary.cs b/src/BizHawk.Client.Common/lua/LuaHelperLibs/NDSLuaLibrary.cs index 9dbe89c6979..0a4fda66e95 100644 --- a/src/BizHawk.Client.Common/lua/LuaHelperLibs/NDSLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/LuaHelperLibs/NDSLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using BizHawk.Emulation.Cores.Consoles.Nintendo.NDS; diff --git a/src/BizHawk.Client.Common/lua/LuaHelperLibs/NESLuaLibrary.cs b/src/BizHawk.Client.Common/lua/LuaHelperLibs/NESLuaLibrary.cs index 33bc9a7e1a7..e6ca79882ad 100644 --- a/src/BizHawk.Client.Common/lua/LuaHelperLibs/NESLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/LuaHelperLibs/NESLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using BizHawk.Emulation.Cores.Nintendo.NES; diff --git a/src/BizHawk.Client.Common/lua/LuaHelperLibs/SNESLuaLibrary.cs b/src/BizHawk.Client.Common/lua/LuaHelperLibs/SNESLuaLibrary.cs index 139d96f7c9b..0bfa8be5636 100644 --- a/src/BizHawk.Client.Common/lua/LuaHelperLibs/SNESLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/LuaHelperLibs/SNESLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using BizHawk.Emulation.Cores.Nintendo.SNES; diff --git a/src/BizHawk.Client.Common/lua/LuaHelperLibs/StringLuaLibrary.cs b/src/BizHawk.Client.Common/lua/LuaHelperLibs/StringLuaLibrary.cs index c70b37a1940..f4d33059906 100644 --- a/src/BizHawk.Client.Common/lua/LuaHelperLibs/StringLuaLibrary.cs +++ b/src/BizHawk.Client.Common/lua/LuaHelperLibs/StringLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Linq; using BizHawk.Common.StringExtensions; diff --git a/src/BizHawk.Client.Common/lua/LuaLibraryBase.cs b/src/BizHawk.Client.Common/lua/LuaLibraryBase.cs index 40e52e5fc06..805c07f2da2 100644 --- a/src/BizHawk.Client.Common/lua/LuaLibraryBase.cs +++ b/src/BizHawk.Client.Common/lua/LuaLibraryBase.cs @@ -1,4 +1,3 @@ -using System; using System.Threading; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.Common/lua/LuaSandbox.cs b/src/BizHawk.Client.Common/lua/LuaSandbox.cs index e1f5a203d0a..666b8911c30 100644 --- a/src/BizHawk.Client.Common/lua/LuaSandbox.cs +++ b/src/BizHawk.Client.Common/lua/LuaSandbox.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.CompilerServices; using BizHawk.Common; using NLua; diff --git a/src/BizHawk.Client.Common/lua/NLuaTableHelper.cs b/src/BizHawk.Client.Common/lua/NLuaTableHelper.cs index 0ef2ddab795..67d60b0e412 100644 --- a/src/BizHawk.Client.Common/lua/NLuaTableHelper.cs +++ b/src/BizHawk.Client.Common/lua/NLuaTableHelper.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Globalization; diff --git a/src/BizHawk.Client.Common/lua/NamedLuaFunction.cs b/src/BizHawk.Client.Common/lua/NamedLuaFunction.cs index d24657083cd..cea0c4542d5 100644 --- a/src/BizHawk.Client.Common/lua/NamedLuaFunction.cs +++ b/src/BizHawk.Client.Common/lua/NamedLuaFunction.cs @@ -1,4 +1,3 @@ -using System; using NLua; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.Common/movie/BasicMovieInfo.cs b/src/BizHawk.Client.Common/movie/BasicMovieInfo.cs index 82361ffc242..f0ee4774877 100644 --- a/src/BizHawk.Client.Common/movie/BasicMovieInfo.cs +++ b/src/BizHawk.Client.Common/movie/BasicMovieInfo.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -146,8 +145,7 @@ public virtual string FirmwareHash public bool Load() { - var file = new FileInfo(Filename); - if (!file.Exists) + if (!File.Exists(Filename)) { return false; } @@ -223,19 +221,6 @@ protected virtual void LoadFields(ZipStateLoader bl) Subtitles.Sort(); }); - - bl.GetLump(BinaryStateLump.Subtitles, abort: false, tr => - { - while (tr.ReadLine() is string line) - { - if (!string.IsNullOrWhiteSpace(line)) - { - Subtitles.AddFromString(line); - } - } - - Subtitles.Sort(); - }); } private void LoadFramecount(ZipStateLoader bl) diff --git a/src/BizHawk.Client.Common/movie/MovieConversionExtensions.cs b/src/BizHawk.Client.Common/movie/MovieConversionExtensions.cs index f42c10f0f7e..8ec5bf7fdf1 100644 --- a/src/BizHawk.Client.Common/movie/MovieConversionExtensions.cs +++ b/src/BizHawk.Client.Common/movie/MovieConversionExtensions.cs @@ -295,7 +295,7 @@ public static void PopulateWithDefaultHeaderValues( movie.HeaderEntries.Add(HeaderKeys.VsyncAttoseconds, mame.VsyncAttoseconds.ToString()); } - if (emulator is ICycleTiming) + if (emulator.HasCycleTiming()) { movie.HeaderEntries.Add(HeaderKeys.CycleCount, "0"); movie.HeaderEntries.Add(HeaderKeys.ClockRate, "0"); diff --git a/src/BizHawk.Client.Common/movie/MovieService.cs b/src/BizHawk.Client.Common/movie/MovieService.cs index a7f43490f6c..5568e401bad 100644 --- a/src/BizHawk.Client.Common/movie/MovieService.cs +++ b/src/BizHawk.Client.Common/movie/MovieService.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Globalization; using System.Linq; diff --git a/src/BizHawk.Client.Common/movie/MovieSession.cs b/src/BizHawk.Client.Common/movie/MovieSession.cs index 7f06fdfb642..d1a748fe11d 100644 --- a/src/BizHawk.Client.Common/movie/MovieSession.cs +++ b/src/BizHawk.Client.Common/movie/MovieSession.cs @@ -1,7 +1,8 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; + +using BizHawk.Common.PathExtensions; using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; @@ -59,11 +60,6 @@ public IMovieController GenerateMovieController(ControllerDefinition definition return new Bk2Controller("", definition ?? MovieController.Definition); } - public void SetMovieController(ControllerDefinition definition) - { - MovieController = GenerateMovieController(definition); - } - public void HandleFrameBefore() { if (Movie.NotActive()) @@ -187,50 +183,49 @@ public bool HandleLoadState(TextReader reader) return true; } - /// is and . does not match . - public void QueueNewMovie(IMovie movie, bool record, string systemId, IDictionary preferredCores) + /// . does not match . + public void QueueNewMovie( + IMovie movie, + string systemId, + string loadedRomHash, + PathEntryCollection pathEntries, + IDictionary preferredCores) { - if (movie.IsActive() && movie.Changes) + if (movie.SystemID != systemId) { - movie.Save(); - } - - if (!record) // The semantics of record is that we are starting a new movie, and even wiping a pre-existing movie with the same path, but non-record means we are loading an existing movie into playback mode - { - movie.Load(); - - if (movie.SystemID != systemId) - { - throw new MoviePlatformMismatchException( - $"Movie system Id ({movie.SystemID}) does not match the currently loaded platform ({systemId}), unable to load"); - } + throw new MoviePlatformMismatchException( + $"Movie system Id ({movie.SystemID}) does not match the currently loaded platform ({systemId}), unable to load"); } - if (!record) + if (!(string.IsNullOrEmpty(movie.Hash) || loadedRomHash.Equals(movie.Hash, StringComparison.Ordinal)) + && movie is TasMovie tasproj) { - if (string.IsNullOrWhiteSpace(movie.Core)) + var result = _dialogParent.ModalMessageBox2( + caption: "Discard GreenZone?", + text: $"The TAStudio project {movie.Filename.MakeRelativeTo(pathEntries.MovieAbsolutePath())} appears to be for a different game than the one that's loaded.\n" + + "Choose \"No\" to continue anyway, which may lead to an invalid savestate being loaded.\n" + + "Choose \"Yes\" to discard the GreenZone (savestate history). This is safer, and at worst you'll only need to watch through the whole movie."); + //TODO add abort option + if (result) { - PopupMessage(preferredCores.TryGetValue(systemId, out var coreName) - ? $"No core specified in the movie file, using the preferred core {coreName} instead." - : "No core specified in the movie file, using the default core instead."); - } - else - { - var keys = preferredCores.Keys.ToList(); - foreach (var k in keys) - { - preferredCores[k] = movie.Core; - } + tasproj.TasSession.UpdateValues(frame: 0, currentBranch: tasproj.TasSession.CurrentBranch); // wtf is this API --yoshi + tasproj.InvalidateEntireGreenzone(); } } - if (record) // This is a hack really, we need to set the movie to its proper state so that it will be considered active later + if (string.IsNullOrWhiteSpace(movie.Core)) { - movie.SwitchToRecord(); + PopupMessage(preferredCores.TryGetValue(systemId, out var coreName) + ? $"No core specified in the movie file, using the preferred core {coreName} instead." + : "No core specified in the movie file, using the default core instead."); } else { - movie.SwitchToPlay(); + var keys = preferredCores.Keys.ToList(); + foreach (var k in keys) + { + preferredCores[k] = movie.Core; + } } _queuedMovie = movie; @@ -307,15 +302,17 @@ public void ConvertToTasProj() Movie.SwitchToPlay(); } - public IMovie Get(string path) + public IMovie Get(string path, bool loadMovie) { // TODO: change IMovies to take HawkFiles only and not path - if (Path.GetExtension(path)?.EndsWithOrdinal("tasproj") ?? false) - { - return new TasMovie(this, path); - } + IMovie movie = Path.GetExtension(path)?.EndsWithOrdinal("tasproj") is true + ? new TasMovie(this, path) + : new Bk2Movie(this, path); - return new Bk2Movie(this, path); + if (loadMovie) + movie.Load(); + + return movie; } public void PopupMessage(string message) => _dialogParent.ModalMessageBox(message, "Warning", EMsgBoxIcon.Warning); @@ -344,25 +341,59 @@ private void LatchInputToLog() private void HandlePlaybackEnd() { - if (Movie.IsAtEnd() && (Movie.Emulator is ICycleTiming cycleCore)) +#if false // invariants given by single call-site + Debug.Assert(Movie.IsPlaying()); + Debug.Assert(Movie.Emulator.Frame >= Movie.InputLogLength); +#endif + if (Movie.IsAtEnd() && Movie.Emulator.HasCycleTiming()) { - long coreValue = cycleCore.CycleCount; - bool movieHasValue = Movie.HeaderEntries.TryGetValue(HeaderKeys.CycleCount, out string movieValueStr); - - long movieValue = movieHasValue ? Convert.ToInt64(movieValueStr) : 0; - var valuesMatch = movieValue == coreValue; - - if (!movieHasValue || !valuesMatch) + const string WINDOW_TITLE_MISMATCH = "Cycle count mismatch"; + const string WINDOW_TITLE_MISSING = "Cycle count not yet saved"; + const string PFX_MISSING = "The cycle count (running time) hasn't been saved into this movie yet.\n"; + const string ERR_MSG_MISSING_READONLY = PFX_MISSING + "The movie was loaded in read-only mode. To add the cycle count, load it in read-write mode and play to the end again."; + const string ERR_MSG_MISSING_CONFIRM = PFX_MISSING + "Add it now?"; + const string PFX_MISMATCH = "The cycle count (running time) saved into this movie ({0}) doesn't match the measured count ({1}) here at the end.\n"; + const string ERR_FMT_STR_MISMATCH_READONLY = PFX_MISMATCH + "The movie was loaded in read-only mode. To correct the cycle count, load it in read-write mode and play to the end again."; + const string ERR_FMT_STR_MISMATCH_CONFIRM = PFX_MISMATCH + "Correct it now?"; + var coreValue = Movie.Emulator.AsCycleTiming().CycleCount; + if (!Movie.HeaderEntries.TryGetValue(HeaderKeys.CycleCount, out var movieValueStr) + || !long.TryParse(movieValueStr, out var movieValue)) { - var previousState = !movieHasValue - ? $"The movie is currently missing a cycle count." - : $"The cycle count in the movie ({movieValue}) doesn't match the current value."; - // TODO: Ideally, this would be a Yes/No MessageBox that saves when "Yes" is pressed. - PopupMessage($"The end of the movie has been reached.\n\n{previousState}\n\nSave the movie to update to the current cycle count ({coreValue})."); + if (ReadOnly) + { + //TODO this would be annoying to encounter; detect the missing field when playback starts instead --yoshi + _dialogParent.ModalMessageBox( + caption: WINDOW_TITLE_MISSING, + text: ERR_MSG_MISSING_READONLY, + icon: EMsgBoxIcon.Info); + } + else if (_dialogParent.ModalMessageBox2( + caption: WINDOW_TITLE_MISSING, + text: ERR_MSG_MISSING_CONFIRM, + icon: EMsgBoxIcon.Question)) + { + Movie.SetCycleValues(); + } + } + else if (coreValue != movieValue) + { + if (ReadOnly) + { + //TODO this would be annoying to encounter; detect the missing field when playback starts instead --yoshi + _dialogParent.ModalMessageBox( + caption: WINDOW_TITLE_MISMATCH, + text: string.Format(ERR_FMT_STR_MISMATCH_READONLY, movieValue, coreValue), + icon: EMsgBoxIcon.Warning); + } + else if (_dialogParent.ModalMessageBox2( + caption: WINDOW_TITLE_MISMATCH, + text: string.Format(ERR_FMT_STR_MISMATCH_CONFIRM, movieValue, coreValue), + icon: EMsgBoxIcon.Question)) + { + Movie.SetCycleValues(); + } } } - - // TODO: mainform callback to update on mode change switch (Settings.MovieEndAction) { case MovieEndAction.Stop: diff --git a/src/BizHawk.Client.Common/movie/PlatformFrameRates.cs b/src/BizHawk.Client.Common/movie/PlatformFrameRates.cs index 773f7d87851..a7f11def234 100644 --- a/src/BizHawk.Client.Common/movie/PlatformFrameRates.cs +++ b/src/BizHawk.Client.Common/movie/PlatformFrameRates.cs @@ -72,10 +72,10 @@ public static class PlatformFrameRates ["ZXSpectrum_PAL"] = 50.080128205, ["AmstradCPC_PAL"] = 50.08012820512821, - ["UZE"] = 60.016319939602, + ["UZE"] = 1125000.0 / 18733.0, // = 8 * 315000000 / 88 / 1820 / 262 ≈ 60.05444936742646666 ["VEC"] = 50, - ["O2"] = 89478485 / 1495643, // 59.8260982065907439141559850846 - ["O2_PAL"] = 89478485 / 1800319, // 49.70146124103561646574857011 + ["O2"] = 89478485.0 / 1495643, // 59.8260982065907439141559850846 + ["O2_PAL"] = 89478485.0 / 1800319, // 49.70146124103561646574857011 ["TIC80"] = 60, }; diff --git a/src/BizHawk.Client.Common/movie/bk2/Bk2Controller.cs b/src/BizHawk.Client.Common/movie/bk2/Bk2Controller.cs index 59c95297c6c..122fdc75ce9 100755 --- a/src/BizHawk.Client.Common/movie/bk2/Bk2Controller.cs +++ b/src/BizHawk.Client.Common/movie/bk2/Bk2Controller.cs @@ -1,5 +1,5 @@ -using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using BizHawk.Common; @@ -14,16 +14,11 @@ internal class Bk2Controller : IMovieController private readonly Bk2ControllerDefinition _type; - private IList _controlsOrdered; + private IReadOnlyList _controlsOrdered; - private IList ControlsOrdered => _controlsOrdered ??= _type.OrderedControlsFlat - .Select(c => new ControlMap - { - Name = c, - IsBool = _type.BoolButtons.Contains(c), - IsAxis = _type.Axes.ContainsKey(c) - }) - .ToList(); + private IReadOnlyList ControlsOrdered + => _controlsOrdered + ??= _type.OrderedControlsFlat.Select(name => new ControlMap(name, _type)).ToArray(); public IInputDisplayGenerator InputDisplayGenerator { get; set; } = null; @@ -84,32 +79,30 @@ public void SetFromSticky(IStickyAdapter controller) public void SetFromMnemonic(string mnemonic) { - if (!string.IsNullOrWhiteSpace(mnemonic)) + if (string.IsNullOrWhiteSpace(mnemonic)) return; + var iterator = 0; + + foreach (var key in ControlsOrdered) { - var iterator = 0; + while (mnemonic[iterator] == '|') iterator++; - foreach (var key in ControlsOrdered) + if (key.IsBool) { - while (mnemonic[iterator] == '|') iterator++; - - if (key.IsBool) - { - _myBoolButtons[key.Name] = mnemonic[iterator] != '.'; - iterator++; - } - else if (key.IsAxis) - { - var commaIndex = mnemonic.IndexOf(',', iterator); -#if NET6_0_OR_GREATER - var val = int.Parse(mnemonic.AsSpan(start: iterator, length: commaIndex - iterator)); + _myBoolButtons[key.Name] = mnemonic[iterator] != '.'; + iterator++; + } + else if (key.IsAxis) + { + var commaIndex = mnemonic.IndexOf(',', iterator); +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER + var val = int.Parse(mnemonic.AsSpan(start: iterator, length: commaIndex - iterator)); #else - var axisValueString = mnemonic.Substring(startIndex: iterator, length: commaIndex - iterator); - var val = int.Parse(axisValueString); + var axisValueString = mnemonic.Substring(startIndex: iterator, length: commaIndex - iterator); + var val = int.Parse(axisValueString); #endif - _myAxisControls[key.Name] = val; + _myAxisControls[key.Name] = val; - iterator = commaIndex + 1; - } + iterator = commaIndex + 1; } } } @@ -124,11 +117,27 @@ public void SetAxis(string buttonName, int value) _myAxisControls[buttonName] = value; } - private class ControlMap + private readonly struct ControlMap { - public string Name { get; set; } - public bool IsBool { get; set; } - public bool IsAxis { get; set; } + public readonly bool IsAxis; + + public readonly bool IsBool; + + public readonly string Name; + + public ControlMap(string name, bool isButton, bool isAxis) + { + Debug.Assert(isButton ^ isAxis, "axis conflicts with button of the same name?"); + Name = name; + IsBool = isButton; + IsAxis = isAxis; + } + + public ControlMap(string name, ControllerDefinition def) + : this( + name: name, + isButton: def.BoolButtons.Contains(name), + isAxis: def.Axes.ContainsKey(name)) {} } private class Bk2ControllerDefinition : ControllerDefinition diff --git a/src/BizHawk.Client.Common/movie/bk2/Bk2LogEntryGenerator.cs b/src/BizHawk.Client.Common/movie/bk2/Bk2LogEntryGenerator.cs index a91e029ddb6..87bd730ff60 100644 --- a/src/BizHawk.Client.Common/movie/bk2/Bk2LogEntryGenerator.cs +++ b/src/BizHawk.Client.Common/movie/bk2/Bk2LogEntryGenerator.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -51,12 +50,11 @@ public Bk2LogEntryGenerator(string systemId, IController source) /// documentation of the meaning of the mnemonics and not to be used to /// enforce the mnemonic values ///
- public string GenerateLogKey() + public static string GenerateLogKey(ControllerDefinition definition) { var sb = new StringBuilder(); - sb.Append("LogKey:"); - foreach (var group in _source.Definition.ControlsOrdered.Where(static c => c.Count is not 0)) + foreach (var group in definition.ControlsOrdered.Where(static c => c.Count is not 0)) { sb.Append('#'); foreach (var button in group) diff --git a/src/BizHawk.Client.Common/movie/bk2/Bk2MnemonicLookup.cs b/src/BizHawk.Client.Common/movie/bk2/Bk2MnemonicLookup.cs index 13f2ab41194..24b5a9254d6 100644 --- a/src/BizHawk.Client.Common/movie/bk2/Bk2MnemonicLookup.cs +++ b/src/BizHawk.Client.Common/movie/bk2/Bk2MnemonicLookup.cs @@ -210,6 +210,7 @@ public static string LookupAxis(string button, string systemId) ["Cursor"] = 'c', ["Turbo"] = 't', ["Toggle Multitap"] = 't', + ["Offscreen"] = 'o', ["B0"] = '0', ["B1"] = '1', @@ -716,6 +717,75 @@ public static string LookupAxis(string button, string systemId) ["F11"] = '1', ["F12"] = '2', }, + [VSystemID.Raw.Amiga] = new() + { + ["L"] = 'L', + ["R"] = 'R', + ["NP 0"] = '0', + ["NP 1"] = '1', + ["NP 2"] = '2', + ["NP 3"] = '3', + ["NP 4"] = '4', + ["NP 5"] = '5', + ["NP 6"] = '6', + ["NP 7"] = '7', + ["NP 8"] = '8', + ["NP 9"] = '9', + ["NP Add"] = '+', + ["NP Delete"] = 'd', + ["NP Div"] = '/', + ["NP Enter"] = 'e', + ["NP Left Paren"] = '(', + ["NP Mul"] = '*', + ["NP Right Paren"] = ')', + ["NP Sub"] = '-', + ["Backquote"] = '`', + ["Backslash"] = '\\', + ["Backspace"] = 'b', + ["Caps Lock"] = 'c', + ["Comma"] = ',', + ["Ctrl"] = 'c', + ["Delete"] = 'd', + ["Down"] = 'D', + ["Equal"] = '=', + ["Escape"] = 'e', + ["Help"] = 'h', + ["Left"] = 'L', + ["Left Alt"] = 'a', + ["Left Amiga"] = 'A', + ["Left Bracket"] = '[', + ["Left Shift"] = 's', + ["Less"] = '<', + ["Minus"] = '-', + ["Number Sign"] = '#', + ["Period"] = '.', + ["Quote"] = '\"', + ["Return"] = 'r', + ["Right"] = 'R', + ["Right Alt"] = 'a', + ["Right Amiga"] = 'A', + ["Right Bracket"] = ']', + ["Right Shift"] = 's', + ["Semicolon"] = ';', + ["Slash"] = '/', + ["Space"] = '_', + ["Tab"] = 't', + ["Up"] = 'U', + ["Joystick Button 1"] = '1', + ["Joystick Button 2"] = '2', + ["Joystick Button 3"] = '3', + ["Joystick Up"] = 'U', + ["Joystick Down"] = 'D', + ["Joystick Left"] = 'L', + ["Joystick Right"] = 'R', + ["Mouse Left Button"] = 'l', + ["Mouse Middle Button"] = 'm', + ["Mouse Right Button"] = 'r', + ["Eject"] = '^', + ["Insert"] = 'v', + ["Next Drive"] = '}', + ["Next Slot"] = '>', + } }; private static readonly Dictionary BaseAxisLookupTable = new Dictionary diff --git a/src/BizHawk.Client.Common/movie/bk2/Bk2Movie.IO.cs b/src/BizHawk.Client.Common/movie/bk2/Bk2Movie.IO.cs index 3f5d53e0d7b..8ac524dde69 100644 --- a/src/BizHawk.Client.Common/movie/bk2/Bk2Movie.IO.cs +++ b/src/BizHawk.Client.Common/movie/bk2/Bk2Movie.IO.cs @@ -1,4 +1,3 @@ -using System; using System.Globalization; using System.IO; @@ -23,7 +22,7 @@ public void SaveBackup() } var backupName = Filename; - backupName = backupName.Insert(Filename.LastIndexOf(".", StringComparison.Ordinal), $".{DateTime.Now:yyyy-MM-dd HH.mm.ss}"); + backupName = backupName.Insert(Filename.LastIndexOf('.'), $".{DateTime.Now:yyyy-MM-dd HH.mm.ss}"); backupName = Path.Combine(Session.BackupDirectory, Path.GetFileName(backupName)); Write(backupName, isBackup: true); @@ -49,12 +48,13 @@ protected virtual void Write(string fn, bool isBackup = false) } } - private void SetCycleValues() + public void SetCycleValues() //TODO IEmulator should not be an instance prop of movies, it should be passed in to every call (i.e. from MovieService) --yoshi { // The saved cycle value will only be valid if the end of the movie has been emulated. if (this.IsAtEnd()) { - if (Emulator is ICycleTiming cycleCore) + var cycleCore = Emulator.AsCycleTiming(); + if (cycleCore != null) { Header[HeaderKeys.CycleCount] = cycleCore.CycleCount.ToString(); Header[HeaderKeys.ClockRate] = cycleCore.ClockRate.ToString(CultureInfo.InvariantCulture); diff --git a/src/BizHawk.Client.Common/movie/bk2/Bk2Movie.InputLog.cs b/src/BizHawk.Client.Common/movie/bk2/Bk2Movie.InputLog.cs index 9b407f3d494..7ad80e361bf 100644 --- a/src/BizHawk.Client.Common/movie/bk2/Bk2Movie.InputLog.cs +++ b/src/BizHawk.Client.Common/movie/bk2/Bk2Movie.InputLog.cs @@ -13,15 +13,8 @@ public partial class Bk2Movie public void WriteInputLog(TextWriter writer) { writer.WriteLine("[Input]"); - if (string.IsNullOrEmpty(LogKey)) - { - var lg = LogGeneratorInstance(Session.MovieController); - writer.WriteLine(lg.GenerateLogKey()); - } - else - { - writer.WriteLine($"LogKey:{LogKey}"); - } + writer.Write("LogKey:"); + writer.WriteLine(string.IsNullOrEmpty(LogKey) ? Bk2LogEntryGenerator.GenerateLogKey(Session.MovieController.Definition) : LogKey); foreach (var record in Log) { @@ -142,6 +135,12 @@ public bool CheckTimeLines(TextReader reader, out string errorMessage) stateFrame = newLog.Count; // In case the frame count failed to parse, revert to using the entire state input log } + if (stateFrame > newLog.Count) + { + errorMessage = $"Savestate has invalid frame number {stateFrame} (expected maximum {newLog.Count})"; + return false; + } + if (Log.Count < stateFrame) { if (this.IsFinished()) diff --git a/src/BizHawk.Client.Common/movie/bk2/StringLogs.cs b/src/BizHawk.Client.Common/movie/bk2/StringLogs.cs index 3a4cf026725..c2c3649012f 100644 --- a/src/BizHawk.Client.Common/movie/bk2/StringLogs.cs +++ b/src/BizHawk.Client.Common/movie/bk2/StringLogs.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; using System.IO; diff --git a/src/BizHawk.Client.Common/movie/import/BkmImport.cs b/src/BizHawk.Client.Common/movie/import/BkmImport.cs index 76996cf838a..8d2cf60546b 100644 --- a/src/BizHawk.Client.Common/movie/import/BkmImport.cs +++ b/src/BizHawk.Client.Common/movie/import/BkmImport.cs @@ -13,6 +13,8 @@ protected override void RunImport() for (var i = 0; i < bkm.InputLogLength; i++) { + // TODO: this is currently broken because Result.Movie.Emulator is no longer getting set, + // however using that was sketchy anyway because it relied on the currently loaded core for import var input = bkm.GetInputState(i, Result.Movie.Emulator.ControllerDefinition, bkm.Header[HeaderKeys.Platform]); Result.Movie.AppendFrame(input); } diff --git a/src/BizHawk.Client.Common/movie/import/DsmImport.cs b/src/BizHawk.Client.Common/movie/import/DsmImport.cs index d2831687dfd..803ed13b955 100644 --- a/src/BizHawk.Client.Common/movie/import/DsmImport.cs +++ b/src/BizHawk.Client.Common/movie/import/DsmImport.cs @@ -1,4 +1,3 @@ -using System; using System.Globalization; using System.Linq; using BizHawk.Common; diff --git a/src/BizHawk.Client.Common/movie/import/FcmImport.cs b/src/BizHawk.Client.Common/movie/import/FcmImport.cs index 7e3946c1cf0..b09a220402b 100644 --- a/src/BizHawk.Client.Common/movie/import/FcmImport.cs +++ b/src/BizHawk.Client.Common/movie/import/FcmImport.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Text; diff --git a/src/BizHawk.Client.Common/movie/import/Fm2Import.cs b/src/BizHawk.Client.Common/movie/import/Fm2Import.cs index 95a7d3d918e..db28f9bd2e8 100644 --- a/src/BizHawk.Client.Common/movie/import/Fm2Import.cs +++ b/src/BizHawk.Client.Common/movie/import/Fm2Import.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Common.BufferExtensions; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.Common/movie/import/FmvImport.cs b/src/BizHawk.Client.Common/movie/import/FmvImport.cs index 1b86bf00d24..ed23ef5d130 100644 --- a/src/BizHawk.Client.Common/movie/import/FmvImport.cs +++ b/src/BizHawk.Client.Common/movie/import/FmvImport.cs @@ -5,7 +5,6 @@ namespace BizHawk.Client.Common.movie.import { - // ReSharper disable once UnusedMember.Global /// For Famtasia's .fmv format [ImporterFor("Famtasia", ".fmv")] internal class FmvImport : MovieImporter diff --git a/src/BizHawk.Client.Common/movie/import/IMovieImport.cs b/src/BizHawk.Client.Common/movie/import/IMovieImport.cs index b3a5e8576b4..86040687369 100644 --- a/src/BizHawk.Client.Common/movie/import/IMovieImport.cs +++ b/src/BizHawk.Client.Common/movie/import/IMovieImport.cs @@ -1,7 +1,7 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text.RegularExpressions; using BizHawk.Common; @@ -96,8 +96,8 @@ private string PromptForRom(MatchesMovieHash matchesMovieHash) using var rom = new HawkFile(result); if (rom.IsArchive) rom.BindFirst(); var romData = (ReadOnlySpan) rom.ReadAllBytes(); - if (romData.Length % 1024 == 512) - romData = romData.Slice(512, romData.Length - 512); + int headerBytes = romData.Length % 1024; // assume that all roms have sizes divisible by 1024, and any rest is header + romData = romData[headerBytes..]; if (matchesMovieHash(romData)) return SHA1Checksum.ComputeDigestHex(romData); @@ -122,22 +122,11 @@ protected static string ParseHeader(string line, string headerName) return str.Trim(); } + private static readonly Regex WhitespacePattern = new(@"\s+"); + // Reduce all whitespace to single spaces. protected static string SingleSpaces(string line) - { - line = line.Replace("\t", " "); - line = line.Replace("\n", " "); - line = line.Replace("\r", " "); - line = line.Replace("\r\n", " "); - string prev; - do - { - prev = line; - line = line.Replace(" ", " "); - } - while (prev != line); - return line; - } + => WhitespacePattern.Replace(line, " "); // Ends the string where a NULL character is found. protected static string NullTerminated(string str) diff --git a/src/BizHawk.Client.Common/movie/import/LsmvImport.cs b/src/BizHawk.Client.Common/movie/import/LsmvImport.cs index f05c6099bc5..95352984d6d 100644 --- a/src/BizHawk.Client.Common/movie/import/LsmvImport.cs +++ b/src/BizHawk.Client.Common/movie/import/LsmvImport.cs @@ -1,9 +1,9 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Text; + using BizHawk.Common.IOExtensions; using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; @@ -12,16 +12,19 @@ namespace BizHawk.Client.Common.movie.import { - // ReSharper disable once UnusedMember.Global /// For lsnes' .lsmv format [ImporterFor("LSNES", ".lsmv")] internal class LsmvImport : MovieImporter { private static readonly byte[] Zipheader = { 0x50, 0x4b, 0x03, 0x04 }; - private BsnesControllers _controllers; private int _playerCount; - // hacky variable; just exists because if subframe input is used, the previous frame needs to be marked subframe aware - private SimpleController _previousControllers; + private SimpleController _controller; + private SimpleController _emptyController; + + private readonly string[][] _lsnesGamepadButtons = Enumerable.Range(1, 8) + .Select(player => new[] { "B", "Y", "Select", "Start", "Up", "Down", "Left", "Right", "A", "X", "L", "R" } + .Select(button => $"P{player} {button}").ToArray()) + .ToArray(); protected override void RunImport() { @@ -31,7 +34,7 @@ protected override void RunImport() using var fs = new FileStream(SourceFile.FullName, FileMode.Open, FileAccess.Read); { byte[] data = new byte[4]; - fs.Read(data, 0, 4); + _ = fs.Read(data, offset: 0, count: data.Length); // if stream is too short, the next check will catch it if (!data.SequenceEqual(Zipheader)) { Result.Errors.Add("This is not a zip file."); @@ -80,9 +83,13 @@ protected override void RunImport() _ => BsnesApi.BSNES_INPUT_DEVICE.Gamepad }; } - _controllers = new BsnesControllers(ss, true); - Result.Movie.LogKey = new Bk2LogEntryGenerator("SNES", new Bk2Controller(_controllers.Definition)).GenerateLogKey(); - _playerCount = _controllers.Definition.PlayerCount; + + ControllerDefinition controllerDefinition = new BsnesControllers(ss, true).Definition; + _emptyController = new SimpleController(controllerDefinition); + _controller = new SimpleController(controllerDefinition); + _playerCount = controllerDefinition.PlayerCount; + + Result.Movie.LogKey = Bk2LogEntryGenerator.GenerateLogKey(controllerDefinition); foreach (var item in zip.Entries) { @@ -166,7 +173,7 @@ protected override void RunImport() // Insert an empty frame in lsmv snes movies // see https://github.com/TASEmulators/BizHawk/issues/721 - Result.Movie.AppendFrame(EmptyLmsvFrame()); + // note: this is done inside ImportTextFrame already using (var reader = new StringReader(input)) { while(reader.ReadLine() is string line) @@ -176,7 +183,7 @@ protected override void RunImport() ImportTextFrame(line); } } - Result.Movie.AppendFrame(_previousControllers); + Result.Movie.AppendFrame(_controller); } else if (item.FullName.StartsWithOrdinal("moviesram.")) { @@ -265,22 +272,8 @@ protected override void RunImport() Result.Movie.SyncSettingsJson = ConfigService.SaveWithType(ss); } - private IController EmptyLmsvFrame() - { - SimpleController emptyController = new(_controllers.Definition); - - foreach (var button in emptyController.Definition.BoolButtons) - { - emptyController[button] = false; - } - - return emptyController; - } - private void ImportTextFrame(string line) { - SimpleController controllers = new(_controllers.Definition); - // Split up the sections of the frame. string[] sections = line.Split('|'); @@ -288,7 +281,8 @@ private void ImportTextFrame(string line) if (sections.Length != 0) { string flags = sections[0]; - if (flags[0] != 'F' && _previousControllers != null) _previousControllers["Subframe"] = true; + _controller["Subframe"] = flags[0] != 'F'; + Result.Movie.AppendFrame(_controller); // need to append the subframe input to the previous frame reset = flags[1] != '.'; flags = SingleSpaces(flags.Substring(2)); string[] splitFlags = flags.Split(' '); @@ -302,13 +296,13 @@ private void ImportTextFrame(string line) delay = 0; } + _controller.AcceptNewAxis("Reset Instruction", delay); if (delay != 0) { - controllers.AcceptNewAxis("Reset Instruction", delay); Result.Warnings.Add("Delayed reset may be mistimed."); // lsnes doesn't count some instructions that our bsnes version does } - controllers["Reset"] = reset; + _controller["Reset"] = reset; } // LSNES frames don't start or end with a |. @@ -318,12 +312,10 @@ private void ImportTextFrame(string line) { if (player > _playerCount) break; - IReadOnlyList buttons = controllers.Definition.ControlsOrdered[player]; + IReadOnlyList buttons = _controller.Definition.ControlsOrdered[player]; if (buttons[0].EndsWithOrdinal("Up")) // hack to identify gamepad / multitap which have a different button order in bizhawk compared to lsnes { - buttons = new[] { "B", "Y", "Select", "Start", "Up", "Down", "Left", "Right", "A", "X", "L", "R" } - .Select(button => $"P{player} {button}") - .ToList(); + buttons = _lsnesGamepadButtons[player - 1]; } // Only consider lines that have the right number of buttons if (sections[player].Length == buttons.Count) @@ -331,18 +323,12 @@ private void ImportTextFrame(string line) for (int button = 0; button < buttons.Count; button++) { // Consider the button pressed so long as its spot is not occupied by a ".". - controllers[buttons[button]] = sections[player][button] != '.'; + _controller[buttons[button]] = sections[player][button] != '.'; } } } - // Convert the data for the controllers to a mnemonic and add it as a frame. - if (_previousControllers != null) - Result.Movie.AppendFrame(_previousControllers); - - if (reset) Result.Movie.AppendFrame(EmptyLmsvFrame()); - - _previousControllers = controllers; + if (reset) Result.Movie.AppendFrame(_emptyController); } private static string ImportTextSubtitle(string line) diff --git a/src/BizHawk.Client.Common/movie/import/Mc2Import.cs b/src/BizHawk.Client.Common/movie/import/Mc2Import.cs index edf9fc3f586..c7ee709fa4d 100644 --- a/src/BizHawk.Client.Common/movie/import/Mc2Import.cs +++ b/src/BizHawk.Client.Common/movie/import/Mc2Import.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.PCEngine; diff --git a/src/BizHawk.Client.Common/movie/import/MmvImport.cs b/src/BizHawk.Client.Common/movie/import/MmvImport.cs index 7e05ebb6980..0185d78abf1 100644 --- a/src/BizHawk.Client.Common/movie/import/MmvImport.cs +++ b/src/BizHawk.Client.Common/movie/import/MmvImport.cs @@ -5,7 +5,6 @@ namespace BizHawk.Client.Common.movie.import { - // ReSharper disable once UnusedMember.Global /// For Dega's .mmv format [ImporterFor("Dega", ".mmv")] internal class MmvImport : MovieImporter diff --git a/src/BizHawk.Client.Common/movie/import/MovieImport.cs b/src/BizHawk.Client.Common/movie/import/MovieImport.cs index 1b0fe10c18e..29f53f670bf 100644 --- a/src/BizHawk.Client.Common/movie/import/MovieImport.cs +++ b/src/BizHawk.Client.Common/movie/import/MovieImport.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.IO; diff --git a/src/BizHawk.Client.Common/movie/import/SmvImport.cs b/src/BizHawk.Client.Common/movie/import/SmvImport.cs index b6889eb760e..9a050b92f03 100644 --- a/src/BizHawk.Client.Common/movie/import/SmvImport.cs +++ b/src/BizHawk.Client.Common/movie/import/SmvImport.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Linq; using System.Text; @@ -9,7 +8,6 @@ namespace BizHawk.Client.Common.movie.import { - // ReSharper disable once UnusedMember.Global /// For Snes9x's .smv format [ImporterFor("Snes9x", ".smv")] internal class SmvImport : MovieImporter @@ -190,9 +188,10 @@ is used (and MOVIE_SYNC_DATA_EXISTS is set), 0 bytes otherwise. Result.Movie.HeaderEntries[HeaderKeys.GameName] = gameName; } - var _controllers = new Snes9xControllers(ss); - Result.Movie.LogKey = new Bk2LogEntryGenerator("SNES", new Bk2Controller(_controllers.ControllerDefinition)).GenerateLogKey(); - SimpleController controllers = new(_controllers.ControllerDefinition); + ControllerDefinition definition = new Snes9xControllers(ss).ControllerDefinition; + SimpleController controllers = new(definition); + + Result.Movie.LogKey = Bk2LogEntryGenerator.GenerateLogKey(definition); r.BaseStream.Position = firstFrameOffset; /* diff --git a/src/BizHawk.Client.Common/movie/import/YmvImport.cs b/src/BizHawk.Client.Common/movie/import/YmvImport.cs index 20c1b39b899..0572c2b0b49 100644 --- a/src/BizHawk.Client.Common/movie/import/YmvImport.cs +++ b/src/BizHawk.Client.Common/movie/import/YmvImport.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.Common/movie/import/bkm/BkmControllerAdapter.cs b/src/BizHawk.Client.Common/movie/import/bkm/BkmControllerAdapter.cs index 6734a7b62e8..d20c8259dc7 100644 --- a/src/BizHawk.Client.Common/movie/import/bkm/BkmControllerAdapter.cs +++ b/src/BizHawk.Client.Common/movie/import/bkm/BkmControllerAdapter.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; diff --git a/src/BizHawk.Client.Common/movie/import/bkm/BkmMovie.cs b/src/BizHawk.Client.Common/movie/import/bkm/BkmMovie.cs index b70c152c265..e098f4ff57d 100644 --- a/src/BizHawk.Client.Common/movie/import/bkm/BkmMovie.cs +++ b/src/BizHawk.Client.Common/movie/import/bkm/BkmMovie.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; @@ -43,7 +42,7 @@ public bool Load() { var file = new FileInfo(Filename); - if (file.Exists == false) + if (!file.Exists) { Loaded = false; return false; @@ -84,4 +83,4 @@ public bool Load() return true; } } -} \ No newline at end of file +} diff --git a/src/BizHawk.Client.Common/movie/interfaces/IBasicMovieInfo.cs b/src/BizHawk.Client.Common/movie/interfaces/IBasicMovieInfo.cs index fd2fa02ef51..f02ed54a452 100644 --- a/src/BizHawk.Client.Common/movie/interfaces/IBasicMovieInfo.cs +++ b/src/BizHawk.Client.Common/movie/interfaces/IBasicMovieInfo.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Client.Common diff --git a/src/BizHawk.Client.Common/movie/interfaces/IMovie.cs b/src/BizHawk.Client.Common/movie/interfaces/IMovie.cs index 3ccefb589be..045d183ecfc 100644 --- a/src/BizHawk.Client.Common/movie/interfaces/IMovie.cs +++ b/src/BizHawk.Client.Common/movie/interfaces/IMovie.cs @@ -84,6 +84,9 @@ public interface IMovie : IBasicMovieInfo ///
void Save(); + /// updates the and headers from the currently loaded core + void SetCycleValues(); + /// /// Writes the input log directly to the stream, bypassing the need to load it all into ram as a string /// @@ -212,6 +215,7 @@ public static FilesystemFilterSet GetFSFilterSet(this IMovie/*?*/ movie) public static bool IsFinished(this IMovie movie) => movie?.Mode == MovieMode.Finished; public static bool IsPlayingOrFinished(this IMovie movie) => movie?.Mode == MovieMode.Play || movie?.Mode == MovieMode.Finished; public static bool IsPlayingOrRecording(this IMovie movie) => movie?.Mode == MovieMode.Play || movie?.Mode == MovieMode.Record; + /// /// Emulation is currently right after the movie's last input frame, /// but no further frames have been emulated. diff --git a/src/BizHawk.Client.Common/movie/interfaces/IMovieSession.cs b/src/BizHawk.Client.Common/movie/interfaces/IMovieSession.cs index e245c12a614..8ba18108a54 100644 --- a/src/BizHawk.Client.Common/movie/interfaces/IMovieSession.cs +++ b/src/BizHawk.Client.Common/movie/interfaces/IMovieSession.cs @@ -54,17 +54,6 @@ public interface IMovieSession /// IMovieController GenerateMovieController(ControllerDefinition definition = null); - /// - /// Hack only used for TAStudio when starting a new movie - /// This is due to needing to save a "dummy" default.tasproj - /// This dummy file's initial save bypasses the normal queue/run - /// new movie code (which normally sets the controller), although - /// once it saves it goes through the normal queue/run code anyway. - /// TODO: Stop relying on this dummy file so we do not need this ugly hack - /// - /// current IEmulator ControllerDefinition - void SetMovieController(ControllerDefinition definition); - void HandleFrameBefore(); void HandleFrameAfter(); void HandleSaveState(TextWriter writer); @@ -77,7 +66,12 @@ public interface IMovieSession /// When initializing a movie, it will be stored until Rom loading processes have been completed, then it will be moved to the Movie property /// If an existing movie is still active, it will remain in the Movie property while the new movie is queued ///
- void QueueNewMovie(IMovie movie, bool record, string systemId, IDictionary preferredCores); + void QueueNewMovie( + IMovie movie, + string systemId, + string loadedRomHash, + PathEntryCollection pathEntries, + IDictionary preferredCores); /// /// Sets the Movie property with the QueuedMovie, clears the queued movie, and starts the new movie @@ -94,7 +88,11 @@ public interface IMovieSession /// void ConvertToTasProj(); - IMovie Get(string path); + /// + /// Create a new (Tas)Movie with the given path as filename. If is true, + /// will also attempt to load an existing movie from . + /// + IMovie Get(string path, bool loadMovie = false); string BackupDirectory { get; set; } diff --git a/src/BizHawk.Client.Common/movie/interfaces/ITasMovie.cs b/src/BizHawk.Client.Common/movie/interfaces/ITasMovie.cs index d538d1d11b6..ad334117e9f 100644 --- a/src/BizHawk.Client.Common/movie/interfaces/ITasMovie.cs +++ b/src/BizHawk.Client.Common/movie/interfaces/ITasMovie.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; diff --git a/src/BizHawk.Client.Common/movie/tasproj/IStateManager.cs b/src/BizHawk.Client.Common/movie/tasproj/IStateManager.cs index 042e01cfe93..aba852c3347 100644 --- a/src/BizHawk.Client.Common/movie/tasproj/IStateManager.cs +++ b/src/BizHawk.Client.Common/movie/tasproj/IStateManager.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using BizHawk.Emulation.Common; @@ -42,20 +41,13 @@ public interface IStateManager : IDisposable /// Get a nearby state. The returned frame must be less than or equal to the passed frame. /// This may not fail; the StateManager strongly holds a frame 0 state to ensure there's always a possible result. ///
- /// /// This stream may be consumed only once, and before any other calls to statemanager occur KeyValuePair GetStateClosestToFrame(int frame); - /// - /// Returns the total number of states currently held by the state manager - /// - /// + /// the total number of states currently held by the state manager int Count { get; } - /// - /// Returns the most recent frame number that the state manager possesses - /// - /// + /// the most recent frame number that the state manager possesses int Last { get; } /// @@ -72,7 +64,6 @@ public interface IStateManager : IDisposable /// Enables the instance to be used. An instance of should not /// be useable until this method is called /// - /// void Engage(byte[] frameZeroState); } } diff --git a/src/BizHawk.Client.Common/movie/tasproj/StateDictionary.cs b/src/BizHawk.Client.Common/movie/tasproj/StateDictionary.cs index ffdb67fa1da..820edc0f430 100644 --- a/src/BizHawk.Client.Common/movie/tasproj/StateDictionary.cs +++ b/src/BizHawk.Client.Common/movie/tasproj/StateDictionary.cs @@ -1,7 +1,8 @@ -using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.IO; +using System.Linq; using BizHawk.Common; namespace BizHawk.Client.Common @@ -16,7 +17,8 @@ public byte[] this[int key] { byte[] bytes = new byte[_streams[key].Length]; _streams[key].Seek(0, SeekOrigin.Begin); - _streams[key].Read(bytes, 0, bytes.Length); + var bytesRead = _streams[key].Read(bytes, offset: 0, count: bytes.Length); + Debug.Assert(bytesRead == bytes.Length, "reached end-of-file while reading state"); return bytes; } set => SetState(key, new MemoryStream(value)); @@ -85,10 +87,7 @@ public void CopyTo(KeyValuePair[] array, int arrayIndex) } public IEnumerator> GetEnumerator() - { - foreach (var kvp in _streams) - yield return new KeyValuePair(kvp.Key, this[kvp.Key]); - } + => _streams.Select(kvp => new KeyValuePair(kvp.Key, this[kvp.Key])).GetEnumerator(); public bool Remove(int key) { diff --git a/src/BizHawk.Client.Common/movie/tasproj/TasBranch.cs b/src/BizHawk.Client.Common/movie/tasproj/TasBranch.cs index 9e476bbde4c..56cb358f213 100644 --- a/src/BizHawk.Client.Common/movie/tasproj/TasBranch.cs +++ b/src/BizHawk.Client.Common/movie/tasproj/TasBranch.cs @@ -1,9 +1,10 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; + using Newtonsoft.Json; -using BizHawk.Bizware.BizwareGL; + +using BizHawk.Bizware.Graphics; using BizHawk.Common.IOExtensions; namespace BizHawk.Client.Common diff --git a/src/BizHawk.Client.Common/movie/tasproj/TasMovie.Editing.cs b/src/BizHawk.Client.Common/movie/tasproj/TasMovie.Editing.cs index a4e6d8ef131..95cb6022543 100644 --- a/src/BizHawk.Client.Common/movie/tasproj/TasMovie.Editing.cs +++ b/src/BizHawk.Client.Common/movie/tasproj/TasMovie.Editing.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; @@ -32,7 +31,7 @@ public override void RecordFrame(int frame, IController source) if (this.IsRecording()) { TasStateManager.InvalidateAfter(frame); - GreenzoneInvalidated(frame + 1); + GreenzoneInvalidated(frame); } if (frame != 0) diff --git a/src/BizHawk.Client.Common/movie/tasproj/TasMovie.History.cs b/src/BizHawk.Client.Common/movie/tasproj/TasMovie.History.cs index bc2401f70f5..d0ade6460e9 100644 --- a/src/BizHawk.Client.Common/movie/tasproj/TasMovie.History.cs +++ b/src/BizHawk.Client.Common/movie/tasproj/TasMovie.History.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Client.Common/movie/tasproj/TasMovie.IO.cs b/src/BizHawk.Client.Common/movie/tasproj/TasMovie.IO.cs index c8260c9ee52..816f5fec140 100644 --- a/src/BizHawk.Client.Common/movie/tasproj/TasMovie.IO.cs +++ b/src/BizHawk.Client.Common/movie/tasproj/TasMovie.IO.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Linq; @@ -100,23 +99,13 @@ private void LoadTasprojExtras(ZipStateLoader bl) if (GetClientSettingsOnLoad != null) { - string clientSettings = ""; bl.GetLump(BinaryStateLump.ClientSettings, abort: false, tr => { - string line; - while ((line = tr.ReadLine()) != null) - { - if (!string.IsNullOrWhiteSpace(line)) - { - clientSettings = line; - } - } - }); + string clientSettings = tr.ReadToEnd(); - if (!string.IsNullOrWhiteSpace(clientSettings)) - { - GetClientSettingsOnLoad(clientSettings); - } + if (!string.IsNullOrEmpty(clientSettings)) + GetClientSettingsOnLoad(clientSettings); + }); } bl.GetLump(BinaryStateLump.VerificationLog, abort: false, tr => @@ -145,6 +134,7 @@ private void LoadTasprojExtras(ZipStateLoader bl) try { TasSession = JsonConvert.DeserializeObject(json); + Branches.Current = TasSession.CurrentBranch; } catch { @@ -152,7 +142,7 @@ private void LoadTasprojExtras(ZipStateLoader bl) } }); - ZwinderStateManagerSettings settings = new ZwinderStateManagerSettings(); + var settings = new ZwinderStateManagerSettings(); bl.GetLump(BinaryStateLump.StateHistorySettings, abort: false, tr => { var json = tr.ReadToEnd(); @@ -166,11 +156,11 @@ private void LoadTasprojExtras(ZipStateLoader bl) } }); - bl.GetLump(BinaryStateLump.StateHistory, abort: false, br => + TasStateManager?.Dispose(); + var hasHistory = bl.GetLump(BinaryStateLump.StateHistory, abort: false, br => { try { - TasStateManager?.Dispose(); TasStateManager = ZwinderStateManager.Create(br, settings, IsReserved); } catch @@ -184,6 +174,20 @@ private void LoadTasprojExtras(ZipStateLoader bl) Session.PopupMessage("State history was corrupted, clearing and working with a fresh history."); } }); + + if (!hasHistory) + { + try + { + TasStateManager = new ZwinderStateManager(settings, IsReserved); + } + catch + { + TasStateManager = new ZwinderStateManager( + Session.Settings.DefaultTasStateManagerSettings, + IsReserved); + } + } } } } diff --git a/src/BizHawk.Client.Common/movie/tasproj/TasMovie.cs b/src/BizHawk.Client.Common/movie/tasproj/TasMovie.cs index f3101ab9e82..3edc922e8f3 100644 --- a/src/BizHawk.Client.Common/movie/tasproj/TasMovie.cs +++ b/src/BizHawk.Client.Common/movie/tasproj/TasMovie.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; @@ -135,7 +134,7 @@ private void InvalidateAfter(int frame) { var anyLagInvalidated = LagLog.RemoveFrom(frame); var anyStateInvalidated = TasStateManager.InvalidateAfter(frame); - GreenzoneInvalidated(frame + 1); + GreenzoneInvalidated(frame); if (anyLagInvalidated || anyStateInvalidated) { Changes = true; @@ -149,6 +148,8 @@ private void InvalidateAfter(int frame) } } + public void InvalidateEntireGreenzone() + => InvalidateAfter(0); private (int Frame, IMovieController Controller) _displayCache = (-1, new Bk2Controller("", NullController.Instance.Definition)); @@ -310,7 +311,7 @@ public void LoadBranch(TasBranch branch) if (BindMarkersToInput) // pretty critical not to erase them { - Markers = branch.Markers; + Markers = branch.Markers.DeepClone(); } Changes = true; diff --git a/src/BizHawk.Client.Common/movie/tasproj/TasMovieMarker.cs b/src/BizHawk.Client.Common/movie/tasproj/TasMovieMarker.cs index 1fe16aa3db5..dcc0cee8ad5 100644 --- a/src/BizHawk.Client.Common/movie/tasproj/TasMovieMarker.cs +++ b/src/BizHawk.Client.Common/movie/tasproj/TasMovieMarker.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; @@ -127,7 +126,7 @@ public override string ToString() public void Add(TasMovieMarker item, bool skipHistory) { - var existingItem = this.FirstOrDefault(m => m.Frame == item.Frame); + var existingItem = Find(m => m.Frame == item.Frame); if (existingItem != null) { if (existingItem.Message != item.Message) @@ -335,7 +334,7 @@ public bool IsMarker(int frame) public TasMovieMarker Get(int frame) { - return this.FirstOrDefault(m => m == frame); + return Find(m => m == frame); } public void ShiftAt(int frame, int offset) diff --git a/src/BizHawk.Client.Common/movie/tasproj/ZwinderStateManager.cs b/src/BizHawk.Client.Common/movie/tasproj/ZwinderStateManager.cs index b854ca401fb..c44ffac2ba8 100644 --- a/src/BizHawk.Client.Common/movie/tasproj/ZwinderStateManager.cs +++ b/src/BizHawk.Client.Common/movie/tasproj/ZwinderStateManager.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/BizHawk.Client.Common/rewind/IRewinder.cs b/src/BizHawk.Client.Common/rewind/IRewinder.cs index 578ae37f670..25df1fb8023 100644 --- a/src/BizHawk.Client.Common/rewind/IRewinder.cs +++ b/src/BizHawk.Client.Common/rewind/IRewinder.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Client.Common { public interface IRewinder : IDisposable @@ -12,6 +10,7 @@ public interface IRewinder : IDisposable bool Active { get; } void Capture(int frame); + /// /// Rewind 1 or 2 saved frames, avoiding frameToAvoid if possible. /// diff --git a/src/BizHawk.Client.Common/rewind/ZeldaWinder.cs b/src/BizHawk.Client.Common/rewind/ZeldaWinder.cs index af6b8db8b24..d1cc2653399 100644 --- a/src/BizHawk.Client.Common/rewind/ZeldaWinder.cs +++ b/src/BizHawk.Client.Common/rewind/ZeldaWinder.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Threading.Tasks; using BizHawk.Common; diff --git a/src/BizHawk.Client.Common/rewind/ZwinderBuffer.cs b/src/BizHawk.Client.Common/rewind/ZwinderBuffer.cs index 079ebf418de..c98286fbd0a 100644 --- a/src/BizHawk.Client.Common/rewind/ZwinderBuffer.cs +++ b/src/BizHawk.Client.Common/rewind/ZwinderBuffer.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -86,10 +85,7 @@ public void Dispose() ///
public int Count => (_nextStateIndex - _firstStateIndex) & STATEMASK; - /// - /// total number of bytes used - /// - /// + /// total number of bytes used public long Used => Count == 0 ? 0 : (_states[HeadStateIndex].Start @@ -97,10 +93,7 @@ public void Dispose() - _states[_firstStateIndex].Start ) & _sizeMask; - /// - /// Total size of the _buffer - /// - /// + /// Total size of the buffer public long Size { get; } private readonly long _sizeMask; @@ -283,8 +276,6 @@ internal StateInformation(ZwinderBuffer parent, int index) /// Retrieve information about a state from 0..Count - 1. /// The information contained within is valid only until the collection is modified. ///
- /// - /// public StateInformation GetState(int index) { if ((uint) index >= (uint) Count) throw new ArgumentOutOfRangeException(paramName: nameof(index), index, message: "index out of range"); @@ -294,7 +285,6 @@ public StateInformation GetState(int index) /// /// Invalidate states from GetState(index) on to the end of the buffer, so that Count == index afterwards /// - /// public void InvalidateEnd(int index) { if ((uint) index > (uint) Count) // intentionally allows index == Count (e.g. clearing an empty buffer) diff --git a/src/BizHawk.Client.Common/savestates/BinaryStateLump.cs b/src/BizHawk.Client.Common/savestates/BinaryStateLump.cs index 547756add21..ff73d2faab0 100644 --- a/src/BizHawk.Client.Common/savestates/BinaryStateLump.cs +++ b/src/BizHawk.Client.Common/savestates/BinaryStateLump.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Reflection; diff --git a/src/BizHawk.Client.Common/savestates/SavestateFile.cs b/src/BizHawk.Client.Common/savestates/SavestateFile.cs index d277d8d1049..a2af4d74a1f 100644 --- a/src/BizHawk.Client.Common/savestates/SavestateFile.cs +++ b/src/BizHawk.Client.Common/savestates/SavestateFile.cs @@ -1,9 +1,9 @@ -using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; -using BizHawk.Bizware.BizwareGL; +using BizHawk.Bizware.Graphics; using BizHawk.Common; using BizHawk.Emulation.Common; @@ -71,31 +71,19 @@ public void Create(string filename, SaveStateConfig config) if (config.SaveScreenshot && _videoProvider != null) { - var buff = _videoProvider.GetVideoBuffer(); - if (buff.Length == 1) + var outWidth = _videoProvider.BufferWidth; + var outHeight = _videoProvider.BufferHeight; + + // if buffer is too big, scale down screenshot + if (!config.NoLowResLargeScreenshots && outWidth * outHeight >= config.BigScreenshotSize) { - // is a hacky opengl texture ID. can't handle this now! - // need to discuss options - // 1. cores must be able to provide a pixels VideoProvider in addition to a texture ID, on command (not very hard overall but interface changing and work per core) - // 2. SavestateManager must be setup with a mechanism for resolving texture IDs (even less work, but sloppy) - // There are additional problems with AVWriting. They depend on VideoProvider providing pixels. + outWidth /= 2; + outHeight /= 2; } - else - { - int outWidth = _videoProvider.BufferWidth; - int outHeight = _videoProvider.BufferHeight; - // if buffer is too big, scale down screenshot - if (!config.NoLowResLargeScreenshots && buff.Length >= config.BigScreenshotSize) - { - outWidth /= 2; - outHeight /= 2; - } - - using (new SimpleTime("Save Framebuffer")) - { - bs.PutLump(BinaryStateLump.Framebuffer, s => QuickBmpFile.Save(_videoProvider, s, outWidth, outHeight)); - } + using (new SimpleTime("Save Framebuffer")) + { + bs.PutLump(BinaryStateLump.Framebuffer, s => QuickBmpFile.Save(_videoProvider, s, outWidth, outHeight)); } } @@ -104,6 +92,7 @@ public void Create(string filename, SaveStateConfig config) bs.PutLump(BinaryStateLump.Input, tw => { + Debug.Assert(_movieSession.Movie.FrameCount >= _emulator.Frame, $"Tried to create a savestate at frame {_emulator.Frame}, but only got a log of length {_movieSession.Movie.FrameCount}!"); // this never should have been a core's responsibility tw.WriteLine("Frame {0}", _emulator.Frame); _movieSession.HandleSaveState(tw); @@ -216,13 +205,13 @@ private static void PopulateFramebuffer(BinaryReader br, IVideoProvider videoPro } catch { - var buff = videoProvider.GetVideoBuffer(); + var vb = videoProvider.GetVideoBuffer(); + var vbLen = videoProvider.BufferWidth * videoProvider.BufferHeight; try { - for (int i = 0; i < buff.Length; i++) + for (var i = 0; i < vbLen; i++) { - int j = br.ReadInt32(); - buff[i] = j; + vb[i] = br.ReadInt32(); } } catch (EndOfStreamException) diff --git a/src/BizHawk.Client.Common/savestates/ZipStateLoader.cs b/src/BizHawk.Client.Common/savestates/ZipStateLoader.cs index b7141e839fd..06462dfbd86 100644 --- a/src/BizHawk.Client.Common/savestates/ZipStateLoader.cs +++ b/src/BizHawk.Client.Common/savestates/ZipStateLoader.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; @@ -79,7 +78,7 @@ public static ZipStateLoader LoadAndDetect(string filename, bool isMovieLoad = f using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read)) { byte[] data = new byte[4]; - fs.Read(data, 0, 4); + _ = fs.Read(data, offset: 0, count: data.Length); // if stream is too short, the next check will catch it if (!data.SequenceEqual(Zipheader)) { return null; diff --git a/src/BizHawk.Client.Common/savestates/ZipStateSaver.cs b/src/BizHawk.Client.Common/savestates/ZipStateSaver.cs index a2b05e9e1c4..7cd3db218b4 100644 --- a/src/BizHawk.Client.Common/savestates/ZipStateSaver.cs +++ b/src/BizHawk.Client.Common/savestates/ZipStateSaver.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Common; diff --git a/src/BizHawk.Client.Common/tools/Cheat.cs b/src/BizHawk.Client.Common/tools/Cheat.cs index e91f720b02d..fc64c3242b1 100644 --- a/src/BizHawk.Client.Common/tools/Cheat.cs +++ b/src/BizHawk.Client.Common/tools/Cheat.cs @@ -149,7 +149,7 @@ public void Toggle(bool handleChange = true) { if (!IsSeparator) { - _enabled ^= true; + _enabled = !_enabled; if (handleChange) { Changes(); diff --git a/src/BizHawk.Client.Common/tools/CheatList.cs b/src/BizHawk.Client.Common/tools/CheatList.cs index 0d92d13823b..861529a0608 100644 --- a/src/BizHawk.Client.Common/tools/CheatList.cs +++ b/src/BizHawk.Client.Common/tools/CheatList.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; using System.Globalization; @@ -242,7 +241,7 @@ public void SaveOnClose() } else if (!_cheatList.Any() && !string.IsNullOrWhiteSpace(CurrentFileName)) { - new FileInfo(CurrentFileName).Delete(); + File.Delete(CurrentFileName); _config.Recent.Remove(CurrentFileName); } } @@ -286,13 +285,13 @@ public bool SaveFile(string path) sb .Append(cheat.AddressStr).Append('\t') .Append(cheat.ValueStr).Append('\t') - .Append(cheat.Compare?.ToString() ?? "N").Append('\t') + .Append(cheat.Compare is null ? "N" : cheat.CompareStr).Append('\t') .Append(cheat.Domain != null ? cheat.Domain.Name : "").Append('\t') .Append(cheat.Enabled ? '1' : '0').Append('\t') .Append(cheat.Name).Append('\t') .Append(cheat.SizeAsChar).Append('\t') .Append(cheat.TypeAsChar).Append('\t') - .Append((cheat.BigEndian ?? false) ? '1' : '0').Append('\t') + .Append(cheat.BigEndian is true ? '1' : '0').Append('\t') .Append(cheat.ComparisonType).Append('\t') .AppendLine(); @@ -316,7 +315,7 @@ public bool SaveFile(string path) public bool Load(IMemoryDomains domains, string path, bool append) { var file = new FileInfo(path); - if (file.Exists == false) + if (!file.Exists) { return false; } diff --git a/src/BizHawk.Client.Common/tools/RamSearchEngine/Extensions.cs b/src/BizHawk.Client.Common/tools/RamSearchEngine/Extensions.cs index fce21969733..d4b1f381595 100644 --- a/src/BizHawk.Client.Common/tools/RamSearchEngine/Extensions.cs +++ b/src/BizHawk.Client.Common/tools/RamSearchEngine/Extensions.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using BizHawk.Emulation.Common; @@ -7,43 +6,22 @@ namespace BizHawk.Client.Common.RamSearchEngine { internal static class Extensions { - public static float ToFloat(this long val) - { - var bytes = BitConverter.GetBytes((int)val); - return BitConverter.ToSingle(bytes, 0); - } - public static IEnumerable ToBytes(this IEnumerable addresses, SearchEngineSettings settings) - => settings.IsDetailed() - ? addresses.ToDetailedBytes(settings.Domain) - : addresses.ToBytes(settings.Domain); + => addresses.ToDetailedBytes(settings.Domain); public static IEnumerable ToWords(this IEnumerable addresses, SearchEngineSettings settings) - => settings.IsDetailed() - ? addresses.ToDetailedWords(settings.Domain, settings.BigEndian) - : addresses.ToWords(settings.Domain, settings.BigEndian); + => addresses.ToDetailedWords(settings.Domain, settings.BigEndian); public static IEnumerable ToDWords(this IEnumerable addresses, SearchEngineSettings settings) - => settings.IsDetailed() - ? addresses.ToDetailedDWords(settings.Domain, settings.BigEndian) - : addresses.ToDWords(settings.Domain, settings.BigEndian); - - private static IEnumerable ToBytes(this IEnumerable addresses, MemoryDomain domain) - => addresses.Select(a => new MiniByteWatch(domain, a)); + => addresses.ToDetailedDWords(settings.Domain, settings.BigEndian); private static IEnumerable ToDetailedBytes(this IEnumerable addresses, MemoryDomain domain) - => addresses.Select(a => new MiniByteWatchDetailed(domain, a)); - - private static IEnumerable ToWords(this IEnumerable addresses, MemoryDomain domain, bool bigEndian) - => addresses.Select(a => new MiniWordWatch(domain, a, bigEndian)); + => addresses.Select(a => new MiniByteWatch(domain, a)); private static IEnumerable ToDetailedWords(this IEnumerable addresses, MemoryDomain domain, bool bigEndian) - => addresses.Select(a => new MiniWordWatchDetailed(domain, a, bigEndian)); - - private static IEnumerable ToDWords(this IEnumerable addresses, MemoryDomain domain, bool bigEndian) - => addresses.Select(a => new MiniDWordWatch(domain, a, bigEndian)); + => addresses.Select(a => new MiniWordWatch(domain, a, bigEndian)); private static IEnumerable ToDetailedDWords(this IEnumerable addresses, MemoryDomain domain, bool bigEndian) - => addresses.Select(a => new MiniDWordWatchDetailed(domain, a, bigEndian)); + => addresses.Select(a => new MiniDWordWatch(domain, a, bigEndian)); } } diff --git a/src/BizHawk.Client.Common/tools/RamSearchEngine/IMiniWatch.cs b/src/BizHawk.Client.Common/tools/RamSearchEngine/IMiniWatch.cs index 1bd7b869669..05162aa1572 100644 --- a/src/BizHawk.Client.Common/tools/RamSearchEngine/IMiniWatch.cs +++ b/src/BizHawk.Client.Common/tools/RamSearchEngine/IMiniWatch.cs @@ -4,130 +4,172 @@ namespace BizHawk.Client.Common.RamSearchEngine { /// /// Represents a Ram address for watching in the - /// With the minimal details necessary for searching /// internal interface IMiniWatch { long Address { get; } - long Previous { get; } // do not store sign extended variables in here. - void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian); + uint Previous { get; } + uint Current { get; } + int ChangeCount { get; } + void ClearChangeCount(); + void SetPreviousToCurrent(); bool IsValid(MemoryDomain domain); + void Update(PreviousType type, MemoryDomain domain, bool bigEndian); } internal sealed class MiniByteWatch : IMiniWatch { public long Address { get; } + private byte _previous; + private byte _current; public MiniByteWatch(MemoryDomain domain, long addr) { Address = addr; - _previous = GetByte(Address, domain); + _previous = _current = GetByte(domain); } - public long Previous => _previous; - - public bool IsValid(MemoryDomain domain) + public void SetPreviousToCurrent() { - return IsValid(Address, domain); + _previous = _current; } - public void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian) - { - _previous = GetByte(Address, domain); - } + public uint Previous => _previous; + public uint Current => _current; - public static bool IsValid(long address, MemoryDomain domain) - { - return address < domain.Size; - } + public int ChangeCount { get; private set; } - public static byte GetByte(long address, MemoryDomain domain) + public void Update(PreviousType type, MemoryDomain domain, bool bigEndian) { - if (!IsValid(address, domain)) + var newValue = GetByte(domain); + + if (newValue != _current) { - return 0; + ChangeCount++; + if (type == PreviousType.LastChange) + { + _previous = _current; + } } - return domain.PeekByte(address); + if (type == PreviousType.LastFrame) + _previous = _current; + + _current = newValue; + } + + public void ClearChangeCount() => ChangeCount = 0; + + public bool IsValid(MemoryDomain domain) => Address < domain.Size; + + public byte GetByte(MemoryDomain domain) + { + return IsValid(domain) ? domain.PeekByte(Address) : (byte)0; } } internal sealed class MiniWordWatch : IMiniWatch { public long Address { get; } + private ushort _previous; + private ushort _current; public MiniWordWatch(MemoryDomain domain, long addr, bool bigEndian) { Address = addr; - _previous = GetUshort(Address, domain, bigEndian); + _previous = _current = GetUshort(domain, bigEndian); } - public long Previous => _previous; - - public void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian) + public void SetPreviousToCurrent() { - _previous = GetUshort(Address, domain, bigEndian); + _previous = _current; } - public bool IsValid(MemoryDomain domain) - { - return IsValid(Address, domain); - } + public uint Previous => _previous; + public uint Current => _current; - public static bool IsValid(long address, MemoryDomain domain) - { - return address < (domain.Size - 1); - } + public int ChangeCount { get; private set; } - public static ushort GetUshort(long address, MemoryDomain domain, bool bigEndian) + public void Update(PreviousType type, MemoryDomain domain, bool bigEndian) { - if (!IsValid(address, domain)) + var newValue = GetUshort(domain, bigEndian); + + if (newValue != _current) { - return 0; + ChangeCount++; + if (type == PreviousType.LastChange) + { + _previous = _current; + } } - return domain.PeekUshort(address, bigEndian); + if (type == PreviousType.LastFrame) + _previous = _current; + + _current = newValue; + } + + public void ClearChangeCount() => ChangeCount = 0; + + public bool IsValid(MemoryDomain domain) => Address < domain.Size - 1; + + private ushort GetUshort(MemoryDomain domain, bool bigEndian) + { + return IsValid(domain) ? domain.PeekUshort(Address, bigEndian) : (ushort)0; } } internal sealed class MiniDWordWatch : IMiniWatch { public long Address { get; } + private uint _previous; + private uint _current; public MiniDWordWatch(MemoryDomain domain, long addr, bool bigEndian) { Address = addr; - _previous = GetUint(Address, domain, bigEndian); + _previous = _current = GetUint(domain, bigEndian); } - public long Previous => _previous; - - public void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian) + public void SetPreviousToCurrent() { - _previous = GetUint(Address, domain, bigEndian); + _previous = _current; } - public bool IsValid(MemoryDomain domain) - { - return IsValid(Address, domain); - } + public uint Previous => _previous; + public uint Current => _current; - public static bool IsValid(long address, MemoryDomain domain) - { - return address < (domain.Size - 3); - } + public int ChangeCount { get; private set; } - public static uint GetUint(long address, MemoryDomain domain, bool bigEndian) + public void Update(PreviousType type, MemoryDomain domain, bool bigEndian) { - if (!IsValid(address, domain)) + var newValue = GetUint(domain, bigEndian); + + if (newValue != _current) { - return 0; + ChangeCount++; + if (type == PreviousType.LastChange) + { + _previous = _current; + } } - return domain.PeekUint(address, bigEndian); + if (type == PreviousType.LastFrame) + _previous = _current; + + _current = newValue; + } + + public void ClearChangeCount() => ChangeCount = 0; + + public bool IsValid(MemoryDomain domain) => Address < domain.Size - 3; + + private uint GetUint(MemoryDomain domain, bool bigEndian) + { + return IsValid(domain) ? domain.PeekUint(Address, bigEndian) : 0; } } } diff --git a/src/BizHawk.Client.Common/tools/RamSearchEngine/IMiniWatchDetails.cs b/src/BizHawk.Client.Common/tools/RamSearchEngine/IMiniWatchDetails.cs deleted file mode 100644 index 024eae8d78a..00000000000 --- a/src/BizHawk.Client.Common/tools/RamSearchEngine/IMiniWatchDetails.cs +++ /dev/null @@ -1,183 +0,0 @@ -using BizHawk.Emulation.Common; - -namespace BizHawk.Client.Common.RamSearchEngine -{ - /// - /// Represents a but with added details - /// to do change tracking. These types add more information but at a cost of - /// having to poll the ram address on every update - /// - internal interface IMiniWatchDetails : IMiniWatch - { - int ChangeCount { get; } - - void ClearChangeCount(); - void Update(PreviousType type, MemoryDomain domain, bool bigEndian); - } - - internal sealed class MiniByteWatchDetailed : IMiniWatchDetails - { - public long Address { get; } - - private byte _previous; - private byte _prevFrame; - - public MiniByteWatchDetailed(MemoryDomain domain, long addr) - { - Address = addr; - SetPreviousToCurrent(domain, false); - } - - public void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian) - { - _previous = _prevFrame = MiniByteWatch.GetByte(Address, domain); - } - - public long Previous => _previous; - - public int ChangeCount { get; private set; } - - public void Update(PreviousType type, MemoryDomain domain, bool bigEndian) - { - var value = MiniByteWatch.GetByte(Address, domain); - - if (value != _prevFrame) - { - ChangeCount++; - } - - switch (type) - { - case PreviousType.Original: - case PreviousType.LastSearch: - break; - case PreviousType.LastFrame: - _previous = _prevFrame; - break; - case PreviousType.LastChange: - if (_prevFrame != value) - { - _previous = _prevFrame; - } - - break; - } - - _prevFrame = value; - } - - public void ClearChangeCount() => ChangeCount = 0; - - public bool IsValid(MemoryDomain domain) => MiniByteWatch.IsValid(Address, domain); - } - - internal sealed class MiniWordWatchDetailed : IMiniWatchDetails - { - public long Address { get; } - - private ushort _previous; - private ushort _prevFrame; - - public MiniWordWatchDetailed(MemoryDomain domain, long addr, bool bigEndian) - { - Address = addr; - SetPreviousToCurrent(domain, bigEndian); - } - - public void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian) - { - _previous = _prevFrame = MiniWordWatch.GetUshort(Address, domain, bigEndian); - } - - public long Previous => _previous; - - public int ChangeCount { get; private set; } - - public void Update(PreviousType type, MemoryDomain domain, bool bigEndian) - { - var value = MiniWordWatch.GetUshort(Address, domain, bigEndian); - if (value != Previous) - { - ChangeCount++; - } - - switch (type) - { - case PreviousType.Original: - case PreviousType.LastSearch: - break; - case PreviousType.LastFrame: - _previous = _prevFrame; - break; - case PreviousType.LastChange: - if (_prevFrame != value) - { - _previous = _prevFrame; - } - - break; - } - - _prevFrame = value; - } - - public void ClearChangeCount() => ChangeCount = 0; - - public bool IsValid(MemoryDomain domain) => MiniWordWatch.IsValid(Address, domain); - } - - internal sealed class MiniDWordWatchDetailed : IMiniWatchDetails - { - public long Address { get; } - - private uint _previous; - private uint _prevFrame; - - public MiniDWordWatchDetailed(MemoryDomain domain, long addr, bool bigEndian) - { - Address = addr; - SetPreviousToCurrent(domain, bigEndian); - } - - public void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian) - { - _previous = _prevFrame = MiniDWordWatch.GetUint(Address, domain, bigEndian); - } - - public long Previous => (int)_previous; - - public int ChangeCount { get; private set; } - - public void Update(PreviousType type, MemoryDomain domain, bool bigEndian) - { - var value = MiniDWordWatch.GetUint(Address, domain, bigEndian); - if (value != Previous) - { - ChangeCount++; - } - - switch (type) - { - case PreviousType.Original: - case PreviousType.LastSearch: - break; - case PreviousType.LastFrame: - _previous = _prevFrame; - break; - case PreviousType.LastChange: - if (_prevFrame != value) - { - _previous = _prevFrame; - } - - break; - } - - _prevFrame = value; - } - - public void ClearChangeCount() => ChangeCount = 0; - - public bool IsValid(MemoryDomain domain) => MiniDWordWatch.IsValid(Address, domain); - } -} diff --git a/src/BizHawk.Client.Common/tools/RamSearchEngine/RamSearchEngine.cs b/src/BizHawk.Client.Common/tools/RamSearchEngine/RamSearchEngine.cs index 7de28c64c73..5039a292b4a 100644 --- a/src/BizHawk.Client.Common/tools/RamSearchEngine/RamSearchEngine.cs +++ b/src/BizHawk.Client.Common/tools/RamSearchEngine/RamSearchEngine.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; @@ -6,18 +5,17 @@ using BizHawk.Common.CollectionExtensions; using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; +using static BizHawk.Common.NumberExtensions.NumberExtensions; -// ReSharper disable PossibleInvalidCastExceptionInForeachLoop namespace BizHawk.Client.Common.RamSearchEngine { public class RamSearchEngine { private Compare _compareTo = Compare.Previous; - private IMiniWatch[] _watchList = Array.Empty(); + private IMiniWatch[] _watchList = [ ]; private readonly SearchEngineSettings _settings; - private readonly UndoHistory> _history = new UndoHistory>(true, new List()); //TODO use IList instead of IEnumerable and stop calling `.ToArray()` (i.e. cloning) on reads and writes? - private bool _isSorted = true; // Tracks whether or not the array is sorted by address, if it is, binary search can be used for finding watches + private readonly UndoHistory> _history = new(true, [ ]); //TODO use IList instead of IEnumerable and stop calling `.ToArray()` (i.e. cloning) on reads and writes? public RamSearchEngine(SearchEngineSettings settings, IMemoryDomains memoryDomains) { @@ -33,7 +31,7 @@ public RamSearchEngine(SearchEngineSettings settings, IMemoryDomains memoryDomai }; } - public RamSearchEngine(SearchEngineSettings settings, IMemoryDomains memoryDomains, Compare compareTo, long? compareValue, int? differentBy) + public RamSearchEngine(SearchEngineSettings settings, IMemoryDomains memoryDomains, Compare compareTo, uint? compareValue, uint? differentBy) : this(settings, memoryDomains) { _compareTo = compareTo; @@ -53,55 +51,19 @@ public void Start() long listSize = domain.Size / stepSize - (int)_settings.Size + stepSize; _watchList = new IMiniWatch[listSize]; - - using (Domain.EnterExit()) + using var @lock = Domain.EnterExit(); + switch (_settings.Size) { - switch (_settings.Size) - { - default: - case WatchSize.Byte: - for (int i = 0; i < domain.Size; i++) - { - if (_settings.IsDetailed()) - { - _watchList[i] = new MiniByteWatchDetailed(domain, i); - } - else - { - _watchList[i] = new MiniByteWatch(domain, i); - } - } - - break; - case WatchSize.Word: - for (int i = 0; i < listSize; i++) - { - if (_settings.IsDetailed()) - { - _watchList[i] = new MiniWordWatchDetailed(domain, i * stepSize, _settings.BigEndian); - } - else - { - _watchList[i] = new MiniWordWatch(domain, i * stepSize, _settings.BigEndian); - } - } - - break; - case WatchSize.DWord: - for (int i = 0; i < listSize; i++) - { - if (_settings.IsDetailed()) - { - _watchList[i] = new MiniDWordWatchDetailed(domain, i * stepSize, _settings.BigEndian); - } - else - { - _watchList[i] = new MiniDWordWatch(domain, i * stepSize, _settings.BigEndian); - } - } - - break; - } + default: + case WatchSize.Byte: + for (var i = 0; i < _watchList.Length; i++) _watchList[i] = new MiniByteWatch(domain, i); + break; + case WatchSize.Word: + for (var i = 0; i < _watchList.Length; i++) _watchList[i] = new MiniWordWatch(domain, i * stepSize, _settings.BigEndian); + break; + case WatchSize.DWord: + for (var i = 0; i < _watchList.Length; i++) _watchList[i] = new MiniDWordWatch(domain, i * stepSize, _settings.BigEndian); + break; } } @@ -118,12 +80,14 @@ public void Start() "", 0, _watchList[index].Previous, - _settings.IsDetailed() ? ((IMiniWatchDetails)_watchList[index]).ChangeCount : 0); + _settings.IsDetailed() ? _watchList[index].ChangeCount : 0); - public int DoSearch() + public int DoSearch(bool updatePrevious) { int before = _watchList.Length; + Update(updatePrevious); + using (Domain.EnterExit()) { _watchList = _compareTo switch @@ -135,11 +99,6 @@ public int DoSearch() Compare.Difference => CompareDifference(_watchList).ToArray(), _ => ComparePrevious(_watchList).ToArray() }; - - if (_settings.PreviousType == PreviousType.LastSearch) - { - SetPreviousToCurrent(); - } } if (UndoEnabled) @@ -150,11 +109,11 @@ public int DoSearch() return before - _watchList.Length; } - public bool Preview(long address) + public bool Preview(int index) { - var listOfOne = Enumerable.Repeat(_isSorted - ? _watchList.BinarySearch(w => w.Address, address) - : _watchList.FirstOrDefault(w => w.Address == address), 1); + var addressWatch = _watchList[index]; + addressWatch.Update(PreviousType.Original, _settings.Domain, _settings.BigEndian); + IMiniWatch[] listOfOne = [ addressWatch ]; return _compareTo switch { @@ -190,24 +149,22 @@ public Compare CompareTo } } - public long? CompareValue { get; set; } + public uint? CompareValue { get; set; } public ComparisonOperator Operator { get; set; } - // zero 07-sep-2014 - this isn't ideal. but don't bother changing it (to a long, for instance) until it can support floats. maybe store it as a double here. - public int? DifferentBy { get; set; } + /// + /// zero 07-sep-2014 - this isn't ideal. but don't bother changing it (to a long, for instance) until it can support floats. maybe store it as a double here.
+ /// it already supported floats by way of reinterpret-cast, it just wasn't implemented correctly on this side --yoshi + ///
+ public uint? DifferentBy { get; set; } - public void Update() + public void Update(bool updatePrevious) { - if (_settings.IsDetailed()) + using var @lock = _settings.Domain.EnterExit(); + foreach (var watch in _watchList) { - using (_settings.Domain.EnterExit()) - { - foreach (IMiniWatchDetails watch in _watchList) - { - watch.Update(_settings.PreviousType, _settings.Domain, _settings.BigEndian); - } - } + watch.Update(updatePrevious ? _settings.PreviousType : PreviousType.Original, _settings.Domain, _settings.BigEndian); } } @@ -215,30 +172,20 @@ public void Update() public void SetEndian(bool bigEndian) => _settings.BigEndian = bigEndian; - /// is and is - public void SetPreviousType(PreviousType type) - { - if (_settings.IsFastMode() && type == PreviousType.LastFrame) - { - throw new InvalidOperationException(); - } + public void SetPreviousType(PreviousType type) => _settings.PreviousType = type; - _settings.PreviousType = type; - } + public void SetMode(SearchMode mode) => _settings.Mode = mode; public void SetPreviousToCurrent() { - Array.ForEach(_watchList, w => w.SetPreviousToCurrent(_settings.Domain, _settings.BigEndian)); + Array.ForEach(_watchList, static w => w.SetPreviousToCurrent()); } public void ClearChangeCounts() { - if (_settings.IsDetailed()) + foreach (var watch in _watchList) { - foreach (var watch in _watchList.Cast()) - { - watch.ClearChangeCount(); - } + watch.ClearChangeCount(); } } @@ -284,36 +231,26 @@ public void AddRange(IEnumerable addresses, bool append) }; _watchList = (append ? _watchList.Concat(list) : list).ToArray(); - _isSorted = false; //TODO can this be smarter, such as by inserting instead of appending? } public void Sort(string column, bool reverse) { - _isSorted = column == WatchList.Address && !reverse; switch (column) { case WatchList.Address: _watchList = _watchList.OrderBy(w => w.Address, reverse).ToArray(); break; case WatchList.Value: - _watchList = _watchList.OrderBy(w => GetValue(w.Address), reverse).ToArray(); + _watchList = _watchList.OrderBy(w => w.Current, reverse).ToArray(); break; case WatchList.Prev: _watchList = _watchList.OrderBy(w => w.Previous, reverse).ToArray(); break; case WatchList.ChangesCol: - if (_settings.IsDetailed()) - { - _watchList = _watchList - .Cast() - .OrderBy(w => w.ChangeCount, reverse) - .Cast() - .ToArray(); - } - + _watchList = _watchList.OrderBy(w => w.ChangeCount, reverse).ToArray(); break; case WatchList.Diff: - _watchList = _watchList.OrderBy(w => GetValue(w.Address) - w.Previous, reverse).ToArray(); + _watchList = _watchList.OrderBy(w => w.Current - w.Previous, reverse).ToArray(); break; } } @@ -356,247 +293,224 @@ public int Redo() private IEnumerable ComparePrevious(IEnumerable watchList) { + if (_settings.Type is not WatchDisplayType.Float) + { + switch (Operator) + { + default: + case ComparisonOperator.Equal: + return watchList.Where(w => SignExtendAsNeeded(w.Current) == SignExtendAsNeeded(w.Previous)); + case ComparisonOperator.NotEqual: + return watchList.Where(w => SignExtendAsNeeded(w.Current) != SignExtendAsNeeded(w.Previous)); + case ComparisonOperator.GreaterThan: + return watchList.Where(w => SignExtendAsNeeded(w.Current) > SignExtendAsNeeded(w.Previous)); + case ComparisonOperator.GreaterThanEqual: + return watchList.Where(w => SignExtendAsNeeded(w.Current) >= SignExtendAsNeeded(w.Previous)); + case ComparisonOperator.LessThan: + return watchList.Where(w => SignExtendAsNeeded(w.Current) < SignExtendAsNeeded(w.Previous)); + case ComparisonOperator.LessThanEqual: + return watchList.Where(w => SignExtendAsNeeded(w.Current) <= SignExtendAsNeeded(w.Previous)); + case ComparisonOperator.DifferentBy: + if (DifferentBy is not uint differentBy) throw new InvalidOperationException(); + return watchList.Where(w => + differentBy == Math.Abs(SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous))); + } + } switch (Operator) { default: case ComparisonOperator.Equal: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => GetValue(w.Address).ToFloat().HawkFloatEquality(w.Previous.ToFloat())) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) == SignExtendAsNeeded(w.Previous)); + return watchList.Where(w => ReinterpretAsF32(w.Current).HawkFloatEquality(ReinterpretAsF32(w.Previous))); case ComparisonOperator.NotEqual: - return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) != SignExtendAsNeeded(w.Previous)); + return watchList.Where(w => !ReinterpretAsF32(w.Current).HawkFloatEquality(ReinterpretAsF32(w.Previous))); case ComparisonOperator.GreaterThan: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => GetValue(w.Address).ToFloat() > w.Previous.ToFloat()) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) > SignExtendAsNeeded(w.Previous)); + return watchList.Where(w => ReinterpretAsF32(w.Current) > ReinterpretAsF32(w.Previous)); case ComparisonOperator.GreaterThanEqual: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => GetValue(w.Address).ToFloat() >= w.Previous.ToFloat()) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) >= SignExtendAsNeeded(w.Previous)); - + return watchList.Where(w => + { + var val = ReinterpretAsF32(w.Current); + var prev = ReinterpretAsF32(w.Previous); + return val > prev || val.HawkFloatEquality(prev); + }); case ComparisonOperator.LessThan: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => GetValue(w.Address).ToFloat() < w.Previous.ToFloat()) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) < SignExtendAsNeeded(w.Previous)); + return watchList.Where(w => ReinterpretAsF32(w.Current) < ReinterpretAsF32(w.Previous)); case ComparisonOperator.LessThanEqual: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => GetValue(w.Address).ToFloat() <= w.Previous.ToFloat()) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) <= SignExtendAsNeeded(w.Previous)); - case ComparisonOperator.DifferentBy: - if (DifferentBy.HasValue) - { - var differentBy = DifferentBy.Value; - if (_settings.Type == WatchDisplayType.Float) - { - return watchList.Where(w => (GetValue(w.Address).ToFloat() + differentBy).HawkFloatEquality(w.Previous.ToFloat()) - || (GetValue(w.Address).ToFloat() - differentBy).HawkFloatEquality(w.Previous.ToFloat())); - } - - return watchList.Where(w => - { - long val = SignExtendAsNeeded(GetValue(w.Address)); - long prev = SignExtendAsNeeded(w.Previous); - return val + differentBy == prev - || val - differentBy == prev; - }); - } - else + return watchList.Where(w => { - throw new InvalidOperationException(); - } + var val = ReinterpretAsF32(w.Current); + var prev = ReinterpretAsF32(w.Previous); + return val < prev || val.HawkFloatEquality(prev); + }); + case ComparisonOperator.DifferentBy: + if (DifferentBy is not uint differentBy) throw new InvalidOperationException(); + var differentByF = ReinterpretAsF32(differentBy); + return watchList.Where(w => Math.Abs(ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous)) + .HawkFloatEquality(differentByF)); } } private IEnumerable CompareSpecificValue(IEnumerable watchList) { - if (CompareValue.HasValue) + if (CompareValue is not uint compareValue) throw new InvalidOperationException(); + if (_settings.Type is not WatchDisplayType.Float) { - var compareValue = CompareValue.Value; switch (Operator) { default: case ComparisonOperator.Equal: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => GetValue(w.Address).ToFloat().HawkFloatEquality(compareValue.ToFloat())) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) == SignExtendAsNeeded(compareValue)); + return watchList.Where(w => SignExtendAsNeeded(w.Current) == SignExtendAsNeeded(compareValue)); case ComparisonOperator.NotEqual: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => !GetValue(w.Address).ToFloat().HawkFloatEquality(compareValue.ToFloat())) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) != SignExtendAsNeeded(compareValue)); + return watchList.Where(w => SignExtendAsNeeded(w.Current) != SignExtendAsNeeded(compareValue)); case ComparisonOperator.GreaterThan: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => GetValue(w.Address).ToFloat() > compareValue.ToFloat()) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) > SignExtendAsNeeded(compareValue)); + return watchList.Where(w => SignExtendAsNeeded(w.Current) > SignExtendAsNeeded(compareValue)); case ComparisonOperator.GreaterThanEqual: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => GetValue(w.Address).ToFloat() >= compareValue.ToFloat()) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) >= SignExtendAsNeeded(compareValue)); + return watchList.Where(w => SignExtendAsNeeded(w.Current) >= SignExtendAsNeeded(compareValue)); case ComparisonOperator.LessThan: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => GetValue(w.Address).ToFloat() < compareValue.ToFloat()) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) < SignExtendAsNeeded(compareValue)); - + return watchList.Where(w => SignExtendAsNeeded(w.Current) < SignExtendAsNeeded(compareValue)); case ComparisonOperator.LessThanEqual: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => GetValue(w.Address).ToFloat() <= compareValue.ToFloat()) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) <= SignExtendAsNeeded(compareValue)); - + return watchList.Where(w => SignExtendAsNeeded(w.Current) <= SignExtendAsNeeded(compareValue)); case ComparisonOperator.DifferentBy: - if (DifferentBy.HasValue) - { - var differentBy = DifferentBy.Value; - if (_settings.Type == WatchDisplayType.Float) - { - return watchList.Where(w => (GetValue(w.Address).ToFloat() + differentBy).HawkFloatEquality(compareValue) - || (GetValue(w.Address).ToFloat() - differentBy).HawkFloatEquality(compareValue)); - } - - return watchList.Where(w - => SignExtendAsNeeded(GetValue(w.Address)) + differentBy == compareValue - || SignExtendAsNeeded(GetValue(w.Address)) - differentBy == compareValue); - } - - throw new InvalidOperationException(); + if (DifferentBy is not uint differentBy) throw new InvalidOperationException(); + return watchList.Where(w => + differentBy == Math.Abs(SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(compareValue))); } } - - throw new InvalidOperationException(); + var compareValueF = ReinterpretAsF32(compareValue); + switch (Operator) + { + default: + case ComparisonOperator.Equal: + return watchList.Where(w => ReinterpretAsF32(w.Current).HawkFloatEquality(compareValueF)); + case ComparisonOperator.NotEqual: + return watchList.Where(w => !ReinterpretAsF32(w.Current).HawkFloatEquality(compareValueF)); + case ComparisonOperator.GreaterThan: + return watchList.Where(w => ReinterpretAsF32(w.Current) > compareValueF); + case ComparisonOperator.GreaterThanEqual: + return watchList.Where(w => + { + var val = ReinterpretAsF32(w.Current); + return val > compareValueF || val.HawkFloatEquality(compareValueF); + }); + case ComparisonOperator.LessThan: + return watchList.Where(w => ReinterpretAsF32(w.Current) < compareValueF); + case ComparisonOperator.LessThanEqual: + return watchList.Where(w => + { + var val = ReinterpretAsF32(w.Current); + return val < compareValueF || val.HawkFloatEquality(compareValueF); + }); + case ComparisonOperator.DifferentBy: + if (DifferentBy is not uint differentBy) throw new InvalidOperationException(); + var differentByF = ReinterpretAsF32(differentBy); + return watchList.Where(w => Math.Abs(ReinterpretAsF32(w.Current) - compareValueF) + .HawkFloatEquality(differentByF)); + } } private IEnumerable CompareSpecificAddress(IEnumerable watchList) { - if (CompareValue.HasValue) + if (CompareValue is not uint compareValue) throw new InvalidOperationException(); + switch (Operator) { - var compareValue = CompareValue.Value; - switch (Operator) - { - default: - case ComparisonOperator.Equal: - return watchList.Where(w => w.Address == compareValue); - case ComparisonOperator.NotEqual: - return watchList.Where(w => w.Address != compareValue); - case ComparisonOperator.GreaterThan: - return watchList.Where(w => w.Address > compareValue); - case ComparisonOperator.GreaterThanEqual: - return watchList.Where(w => w.Address >= compareValue); - case ComparisonOperator.LessThan: - return watchList.Where(w => w.Address < compareValue); - case ComparisonOperator.LessThanEqual: - return watchList.Where(w => w.Address <= compareValue); - case ComparisonOperator.DifferentBy: - if (DifferentBy.HasValue) - { - return watchList.Where(w => w.Address + DifferentBy.Value == compareValue - || w.Address - DifferentBy.Value == compareValue); - } - - throw new InvalidOperationException(); - } + default: + case ComparisonOperator.Equal: + return watchList.Where(w => w.Address == compareValue); + case ComparisonOperator.NotEqual: + return watchList.Where(w => w.Address != compareValue); + case ComparisonOperator.GreaterThan: + return watchList.Where(w => w.Address > compareValue); + case ComparisonOperator.GreaterThanEqual: + return watchList.Where(w => w.Address >= compareValue); + case ComparisonOperator.LessThan: + return watchList.Where(w => w.Address < compareValue); + case ComparisonOperator.LessThanEqual: + return watchList.Where(w => w.Address <= compareValue); + case ComparisonOperator.DifferentBy: + if (DifferentBy is not uint differentBy) throw new InvalidOperationException(); + return watchList.Where(w => Math.Abs(w.Address - compareValue) == differentBy); } - - throw new InvalidOperationException(); } private IEnumerable CompareChanges(IEnumerable watchList) { - if (_settings.IsDetailed() && CompareValue.HasValue) + if (CompareValue is not uint compareValue) throw new InvalidOperationException(); + switch (Operator) { - var compareValue = CompareValue.Value; - switch (Operator) - { - default: - case ComparisonOperator.Equal: - return watchList - .Cast() - .Where(w => w.ChangeCount == compareValue); - case ComparisonOperator.NotEqual: - return watchList - .Cast() - .Where(w => w.ChangeCount != compareValue); - case ComparisonOperator.GreaterThan: - return watchList - .Cast() - .Where(w => w.ChangeCount > compareValue); - case ComparisonOperator.GreaterThanEqual: - return watchList - .Cast() - .Where(w => w.ChangeCount >= compareValue); - case ComparisonOperator.LessThan: - return watchList - .Cast() - .Where(w => w.ChangeCount < compareValue); - case ComparisonOperator.LessThanEqual: - return watchList - .Cast() - .Where(w => w.ChangeCount <= compareValue); - case ComparisonOperator.DifferentBy: - if (DifferentBy.HasValue) - { - return watchList - .Cast() - .Where(w => w.ChangeCount + DifferentBy.Value == compareValue - || w.ChangeCount - DifferentBy.Value == compareValue); - } - - throw new InvalidOperationException(); - } + default: + case ComparisonOperator.Equal: + return watchList.Where(w => w.ChangeCount == compareValue); + case ComparisonOperator.NotEqual: + return watchList.Where(w => w.ChangeCount != compareValue); + case ComparisonOperator.GreaterThan: + return watchList.Where(w => w.ChangeCount > compareValue); + case ComparisonOperator.GreaterThanEqual: + return watchList.Where(w => w.ChangeCount >= compareValue); + case ComparisonOperator.LessThan: + return watchList.Where(w => w.ChangeCount < compareValue); + case ComparisonOperator.LessThanEqual: + return watchList.Where(w => w.ChangeCount <= compareValue); + case ComparisonOperator.DifferentBy: + if (DifferentBy is not uint differentBy) throw new InvalidOperationException(); + return watchList.Where(w => Math.Abs(w.ChangeCount - compareValue) == differentBy); } - - throw new InvalidCastException(); } private IEnumerable CompareDifference(IEnumerable watchList) { - if (CompareValue.HasValue) + if (CompareValue is not uint compareValue) throw new InvalidCastException(); //TODO typo for IOE? + if (_settings.Type is not WatchDisplayType.Float) { - var compareValue = CompareValue.Value; switch (Operator) { default: case ComparisonOperator.Equal: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => (GetValue(w.Address).ToFloat() - w.Previous.ToFloat()).HawkFloatEquality(compareValue)) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) == compareValue); + return watchList.Where(w => SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous) == compareValue); case ComparisonOperator.NotEqual: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => !(GetValue(w.Address).ToFloat() - w.Previous.ToFloat()).HawkFloatEquality(compareValue)) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) != compareValue); + return watchList.Where(w => SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous) != compareValue); case ComparisonOperator.GreaterThan: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => GetValue(w.Address).ToFloat() - w.Previous.ToFloat() > compareValue) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) > compareValue); + return watchList.Where(w => SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous) > compareValue); case ComparisonOperator.GreaterThanEqual: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => GetValue(w.Address).ToFloat() - w.Previous.ToFloat() >= compareValue) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) >= compareValue); + return watchList.Where(w => SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous) >= compareValue); case ComparisonOperator.LessThan: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => GetValue(w.Address).ToFloat() - w.Previous.ToFloat() < compareValue) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) < compareValue); + return watchList.Where(w => SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous) < compareValue); case ComparisonOperator.LessThanEqual: - return _settings.Type == WatchDisplayType.Float - ? watchList.Where(w => GetValue(w.Address).ToFloat() - w.Previous.ToFloat() <= compareValue) - : watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) <= compareValue); + return watchList.Where(w => SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous) <= compareValue); case ComparisonOperator.DifferentBy: - if (DifferentBy.HasValue) - { - var differentBy = DifferentBy.Value; - if (_settings.Type == WatchDisplayType.Float) - { - return watchList.Where(w => (GetValue(w.Address).ToFloat() - w.Previous.ToFloat() + differentBy).HawkFloatEquality(compareValue) - || (GetValue(w.Address).ToFloat() - w.Previous.ToFloat() - differentBy).HawkFloatEquality(w.Previous)); - } - - return watchList.Where(w - => SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) + differentBy == compareValue - || SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) - differentBy == compareValue); - } - - throw new InvalidOperationException(); + if (DifferentBy is not uint differentBy) throw new InvalidOperationException(); + return watchList.Where(w => + differentBy == Math.Abs(Math.Abs(SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous)) - compareValue)); } } - - throw new InvalidCastException(); + var compareValueF = ReinterpretAsF32(compareValue); + switch (Operator) + { + default: + case ComparisonOperator.Equal: + return watchList.Where(w => (ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous)).HawkFloatEquality(compareValueF)); + case ComparisonOperator.NotEqual: + return watchList.Where(w => !(ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous)).HawkFloatEquality(compareValueF)); + case ComparisonOperator.GreaterThan: + return watchList.Where(w => ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous) > compareValueF); + case ComparisonOperator.GreaterThanEqual: + return watchList.Where(w => + { + var diff = ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous); + return diff > compareValueF || diff.HawkFloatEquality(compareValueF); + }); + case ComparisonOperator.LessThan: + return watchList.Where(w => ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous) < compareValueF); + case ComparisonOperator.LessThanEqual: + return watchList.Where(w => + { + var diff = ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous); + return diff < compareValueF || diff.HawkFloatEquality(compareValueF); + }); + case ComparisonOperator.DifferentBy: + if (DifferentBy is not uint differentBy) throw new InvalidOperationException(); + var differentByF = ReinterpretAsF32(differentBy); + return watchList.Where(w => Math.Abs(ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous) - compareValueF) + .HawkFloatEquality(differentByF)); + } } private long SignExtendAsNeeded(long val) @@ -615,24 +529,12 @@ private long SignExtendAsNeeded(long val) }; } - private long GetValue(long addr) - { - // do not return sign extended variables from here. - return _settings.Size switch - { - WatchSize.Byte => MiniByteWatch.GetByte(addr, Domain), - WatchSize.Word => MiniWordWatch.GetUshort(addr, Domain, _settings.BigEndian), - WatchSize.DWord => MiniDWordWatch.GetUint(addr, Domain, _settings.BigEndian), - _ => MiniByteWatch.GetByte(addr, Domain) - }; - } - private bool CanDoCompareType(Compare compareType) { return _settings.Mode switch { SearchMode.Detailed => true, - SearchMode.Fast => (compareType != Compare.Changes), + SearchMode.Fast => compareType != Compare.Changes, _ => true }; } diff --git a/src/BizHawk.Client.Common/tools/RamSearchEngine/SearchEngineSettings.cs b/src/BizHawk.Client.Common/tools/RamSearchEngine/SearchEngineSettings.cs index 5323c745f7d..9944a901291 100644 --- a/src/BizHawk.Client.Common/tools/RamSearchEngine/SearchEngineSettings.cs +++ b/src/BizHawk.Client.Common/tools/RamSearchEngine/SearchEngineSettings.cs @@ -8,28 +8,25 @@ public SearchEngineSettings(IMemoryDomains memoryDomains, bool useUndoHistory) { BigEndian = memoryDomains.MainMemory.EndianType == MemoryDomain.Endian.Big; Size = (WatchSize)memoryDomains.MainMemory.WordSize; - Type = WatchDisplayType.Unsigned; Mode = memoryDomains.MainMemory.Size > 1024 * 1024 ? SearchMode.Fast : SearchMode.Detailed; Domain = memoryDomains.MainMemory; - CheckMisAligned = false; - PreviousType = PreviousType.LastSearch; UseUndoHistory = useUndoHistory; } /*Require restart*/ - public SearchMode Mode { get; set; } public MemoryDomain Domain { get; set; } public WatchSize Size { get; set; } public bool CheckMisAligned { get; set; } /*Can be changed mid-search*/ - public WatchDisplayType Type { get; set; } + public WatchDisplayType Type { get; set; } = WatchDisplayType.Unsigned; public bool BigEndian { get; set; } - public PreviousType PreviousType { get; set; } + public PreviousType PreviousType { get; set; } = PreviousType.LastFrame; public bool UseUndoHistory { get; set; } + public SearchMode Mode { get; set; } } public static class SearchEngineSettingsExtensions diff --git a/src/BizHawk.Client.Common/tools/Watch/ByteWatch.cs b/src/BizHawk.Client.Common/tools/Watch/ByteWatch.cs index d9189bcd200..cafc967053b 100644 --- a/src/BizHawk.Client.Common/tools/Watch/ByteWatch.cs +++ b/src/BizHawk.Client.Common/tools/Watch/ByteWatch.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Globalization; using BizHawk.Emulation.Common; @@ -36,16 +35,12 @@ internal ByteWatch(MemoryDomain domain, long address, WatchDisplayType type, boo /// /// Gets an enumeration of that are valid for a /// - public static IEnumerable ValidTypes - { - get - { - yield return WatchDisplayType.Unsigned; - yield return WatchDisplayType.Signed; - yield return WatchDisplayType.Hex; - yield return WatchDisplayType.Binary; - } - } + public static IEnumerable ValidTypes { get; } = [ + WatchDisplayType.Unsigned, + WatchDisplayType.Signed, + WatchDisplayType.Hex, + WatchDisplayType.Binary, + ]; /// /// Get a list a that can be used for this diff --git a/src/BizHawk.Client.Common/tools/Watch/DWordWatch.cs b/src/BizHawk.Client.Common/tools/Watch/DWordWatch.cs index 6c9645ba5e2..f02d906d429 100644 --- a/src/BizHawk.Client.Common/tools/Watch/DWordWatch.cs +++ b/src/BizHawk.Client.Common/tools/Watch/DWordWatch.cs @@ -1,6 +1,6 @@ -using System; using System.Collections.Generic; using System.Globalization; +using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Client.Common @@ -36,19 +36,15 @@ internal DWordWatch(MemoryDomain domain, long address, WatchDisplayType type, bo /// /// Gets a list of for a /// - public static IEnumerable ValidTypes - { - get - { - yield return WatchDisplayType.Unsigned; - yield return WatchDisplayType.Signed; - yield return WatchDisplayType.Hex; - yield return WatchDisplayType.Binary; - yield return WatchDisplayType.FixedPoint_20_12; - yield return WatchDisplayType.FixedPoint_16_16; - yield return WatchDisplayType.Float; - } - } + public static IEnumerable ValidTypes { get; } = [ + WatchDisplayType.Unsigned, + WatchDisplayType.Signed, + WatchDisplayType.Hex, + WatchDisplayType.Binary, + WatchDisplayType.FixedPoint_20_12, + WatchDisplayType.FixedPoint_16_16, + WatchDisplayType.Float, + ]; /// /// Get a list of that can be used for a @@ -84,7 +80,7 @@ public override bool Poke(string value) WatchDisplayType.Hex => uint.Parse(value, NumberStyles.HexNumber), WatchDisplayType.FixedPoint_20_12 => (uint)(double.Parse(value, NumberFormatInfo.InvariantInfo) * 4096.0), WatchDisplayType.FixedPoint_16_16 => (uint)(double.Parse(value, NumberFormatInfo.InvariantInfo) * 65536.0), - WatchDisplayType.Float => BitConverter.ToUInt32(BitConverter.GetBytes(float.Parse(value, NumberFormatInfo.InvariantInfo)), 0), + WatchDisplayType.Float => NumberExtensions.ReinterpretAsUInt32(float.Parse(value, NumberFormatInfo.InvariantInfo)), _ => 0 }; @@ -133,8 +129,7 @@ public string FormatValue(uint val) { string FormatFloat() { - var bytes = BitConverter.GetBytes(val); - var _float = BitConverter.ToSingle(bytes, 0); + var _float = NumberExtensions.ReinterpretAsF32(val); return _float.ToString(NumberFormatInfo.InvariantInfo); } diff --git a/src/BizHawk.Client.Common/tools/Watch/PreviousType.cs b/src/BizHawk.Client.Common/tools/Watch/PreviousType.cs index 7e9e5c03d64..2c65a5a3224 100644 --- a/src/BizHawk.Client.Common/tools/Watch/PreviousType.cs +++ b/src/BizHawk.Client.Common/tools/Watch/PreviousType.cs @@ -2,9 +2,8 @@ { public enum PreviousType { - Original = 0, - LastSearch = 1, - LastFrame = 2, - LastChange = 3 + Original, + LastFrame, + LastChange, } } diff --git a/src/BizHawk.Client.Common/tools/Watch/SeparatorWatch.cs b/src/BizHawk.Client.Common/tools/Watch/SeparatorWatch.cs index 81de10f3817..b78e31694a1 100644 --- a/src/BizHawk.Client.Common/tools/Watch/SeparatorWatch.cs +++ b/src/BizHawk.Client.Common/tools/Watch/SeparatorWatch.cs @@ -34,9 +34,7 @@ public static SeparatorWatch NewSeparatorWatch(string description) /// /// WatchDisplayType.Separator nothing else public override IEnumerable AvailableTypes() - { - yield return WatchDisplayType.Separator; - } + => [ WatchDisplayType.Separator ]; /// /// Ignore that stuff diff --git a/src/BizHawk.Client.Common/tools/Watch/Watch.cs b/src/BizHawk.Client.Common/tools/Watch/Watch.cs index a43a2f64c31..fbf45fb264f 100644 --- a/src/BizHawk.Client.Common/tools/Watch/Watch.cs +++ b/src/BizHawk.Client.Common/tools/Watch/Watch.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Globalization; using System.Linq; diff --git a/src/BizHawk.Client.Common/tools/Watch/WatchList/WatchList.cs b/src/BizHawk.Client.Common/tools/Watch/WatchList/WatchList.cs index ee418b04619..b4b3be63899 100644 --- a/src/BizHawk.Client.Common/tools/Watch/WatchList/WatchList.cs +++ b/src/BizHawk.Client.Common/tools/Watch/WatchList/WatchList.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; using System.Globalization; @@ -149,7 +148,7 @@ public void Insert(int index, Watch watch) /// public void InsertRange(int index, IEnumerable collection) { -#if NET6_0 +#if NET6_0_OR_GREATER if (collection.TryGetNonEnumeratedCount(out var n) && n is 0) return; #else if (collection is ICollection hasCount && hasCount.Count is 0) return; @@ -376,7 +375,7 @@ public bool SaveAs(FileInfo file) private bool LoadFile(string path, bool append) { var file = new FileInfo(path); - if (file.Exists == false) + if (!file.Exists) { return false; } diff --git a/src/BizHawk.Client.Common/tools/Watch/WatchList/WatchNoteComparer.cs b/src/BizHawk.Client.Common/tools/Watch/WatchList/WatchNoteComparer.cs index 3d0259b45a2..7541ab26a65 100644 --- a/src/BizHawk.Client.Common/tools/Watch/WatchList/WatchNoteComparer.cs +++ b/src/BizHawk.Client.Common/tools/Watch/WatchList/WatchNoteComparer.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Client.Common diff --git a/src/BizHawk.Client.Common/tools/Watch/WordWatch.cs b/src/BizHawk.Client.Common/tools/Watch/WordWatch.cs index 4317a4436fb..7dfaa071462 100644 --- a/src/BizHawk.Client.Common/tools/Watch/WordWatch.cs +++ b/src/BizHawk.Client.Common/tools/Watch/WordWatch.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Globalization; using BizHawk.Emulation.Common; @@ -36,17 +35,13 @@ internal WordWatch(MemoryDomain domain, long address, WatchDisplayType type, boo /// /// Gets an Enumeration of s that are valid for a /// - public static IEnumerable ValidTypes - { - get - { - yield return WatchDisplayType.Unsigned; - yield return WatchDisplayType.Signed; - yield return WatchDisplayType.Hex; - yield return WatchDisplayType.Binary; - yield return WatchDisplayType.FixedPoint_12_4; - } - } + public static IEnumerable ValidTypes { get; } = [ + WatchDisplayType.Unsigned, + WatchDisplayType.Signed, + WatchDisplayType.Hex, + WatchDisplayType.Binary, + WatchDisplayType.FixedPoint_12_4, + ]; /// /// Get a list a that can be used for this diff --git a/src/BizHawk.Client.DiscoHawk/About.cs b/src/BizHawk.Client.DiscoHawk/About.cs index 38c7a0708a4..ab9829a4b4a 100644 --- a/src/BizHawk.Client.DiscoHawk/About.cs +++ b/src/BizHawk.Client.DiscoHawk/About.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; namespace BizHawk.Client.DiscoHawk diff --git a/src/BizHawk.Client.DiscoHawk/BizHawk.Client.DiscoHawk.csproj b/src/BizHawk.Client.DiscoHawk/BizHawk.Client.DiscoHawk.csproj index 60ba414b0a4..95f68f935f1 100755 --- a/src/BizHawk.Client.DiscoHawk/BizHawk.Client.DiscoHawk.csproj +++ b/src/BizHawk.Client.DiscoHawk/BizHawk.Client.DiscoHawk.csproj @@ -6,9 +6,9 @@ discohawk.ico disable + true - diff --git a/src/BizHawk.Client.DiscoHawk/MainDiscoForm.cs b/src/BizHawk.Client.DiscoHawk/MainDiscoForm.cs index c26bf3b1576..dc8e489852c 100644 --- a/src/BizHawk.Client.DiscoHawk/MainDiscoForm.cs +++ b/src/BizHawk.Client.DiscoHawk/MainDiscoForm.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.Client.DiscoHawk/Program.cs b/src/BizHawk.Client.DiscoHawk/Program.cs index 826a1675172..cd4ed36bee3 100644 --- a/src/BizHawk.Client.DiscoHawk/Program.cs +++ b/src/BizHawk.Client.DiscoHawk/Program.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using System.Reflection; using System.Collections.Generic; diff --git a/src/BizHawk.Client.DiscoHawk/app.config b/src/BizHawk.Client.DiscoHawk/app.config index d4050983520..2c0f5590f09 100644 --- a/src/BizHawk.Client.DiscoHawk/app.config +++ b/src/BizHawk.Client.DiscoHawk/app.config @@ -1,3 +1,3 @@ - + diff --git a/src/BizHawk.Client.EmuHawk/AVOut/AVSync.cs b/src/BizHawk.Client.EmuHawk/AVOut/AVSync.cs index 51a509095d1..22252dc2762 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/AVSync.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/AVSync.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Client.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs b/src/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs index 2c8aab2847d..24a84bf05fa 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs @@ -1,6 +1,5 @@ #if AVI_SUPPORT #pragma warning disable SA1129 -using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; @@ -125,7 +124,7 @@ private class VideoCopy : IVideoProvider public VideoCopy(IVideoProvider c) { - _vb = (int[])c.GetVideoBuffer().Clone(); + _vb = c.GetVideoBufferCopy(); BufferWidth = c.BufferWidth; BufferHeight = c.BufferHeight; BackgroundColor = c.BackgroundColor; diff --git a/src/BizHawk.Client.EmuHawk/AVOut/BmpVideoProvder.cs b/src/BizHawk.Client.EmuHawk/AVOut/BmpVideoProvder.cs index 367c3b33cd9..88f52219bd6 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/BmpVideoProvder.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/BmpVideoProvder.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Client.EmuHawk/AVOut/FFmpegDownloaderForm.cs b/src/BizHawk.Client.EmuHawk/AVOut/FFmpegDownloaderForm.cs index d11feae8c59..e95488cdcc4 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/FFmpegDownloaderForm.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/FFmpegDownloaderForm.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Linq; using System.Threading; diff --git a/src/BizHawk.Client.EmuHawk/AVOut/FFmpegWriter.cs b/src/BizHawk.Client.EmuHawk/AVOut/FFmpegWriter.cs index 84bb23a1367..5704493bb3f 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/FFmpegWriter.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/FFmpegWriter.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Text; @@ -196,7 +195,7 @@ public void AddFrame(IVideoProvider source) var video = source.GetVideoBuffer(); try { - _muxer.WriteVideoFrame(video); + _muxer.WriteVideoFrame(video.AsSpan(0, _width * _height)); } catch { diff --git a/src/BizHawk.Client.EmuHawk/AVOut/FFmpegWriterForm.cs b/src/BizHawk.Client.EmuHawk/AVOut/FFmpegWriterForm.cs index b5f4b131fa3..2ab7a6e34e2 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/FFmpegWriterForm.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/FFmpegWriterForm.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Windows.Forms; using BizHawk.Client.Common; @@ -51,7 +50,7 @@ public static FormatPreset[] GetPresets(string customCommand) "-c:a pcm_s16le -c:v utvideo -pred median -pix_fmt gbrp -f avi", false, "avi"), new FormatPreset("AVI Lossless FFV1", "Lossless FFV1 video and uncompressed audio in an AVI container. Compatible with AVISource(), if ffmpeg based decoder is installed. Slow, but high compression.", "-c:a pcm_s16le -c:v ffv1 -pix_fmt bgr0 -level 1 -g 1 -coder 1 -context 1 -f avi", false, "avi"), - new FormatPreset("AVI Lossless AVC", "Lossless AVC video and uncompressed audio in an AVI container. High speed and compression, compatible with AVISource(). Seeking may be unstable.", + new FormatPreset("AVI Lossless AVC", "Lossless AVC video and uncompressed audio in an AVI container. High speed and compression, compatible with AVISource() if x264vfw or ffmpeg based decoder is installed. Seeking may be unstable.", "-c:a pcm_s16le -c:v libx264rgb -qp 0 -preset ultrafast -g 10 -pix_fmt rgb24 -f avi", false, "avi"), new FormatPreset("AVI Uncompressed", "Uncompressed video and audio in an AVI container. Very large, don't use!", "-c:a pcm_s16le -c:v rawvideo -f avi", false, "avi"), diff --git a/src/BizHawk.Client.EmuHawk/AVOut/GifWriter.cs b/src/BizHawk.Client.EmuHawk/AVOut/GifWriter.cs index e9e97f70b0a..d4f6710a67c 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/GifWriter.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/GifWriter.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Drawing; diff --git a/src/BizHawk.Client.EmuHawk/AVOut/GifWriterForm.cs b/src/BizHawk.Client.EmuHawk/AVOut/GifWriterForm.cs index 02ae1da861e..ef07809d143 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/GifWriterForm.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/GifWriterForm.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/AVOut/IVideoWriter.cs b/src/BizHawk.Client.EmuHawk/AVOut/IVideoWriter.cs index 9d964fd0820..743649930ea 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/IVideoWriter.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/IVideoWriter.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; @@ -29,12 +28,14 @@ public interface IVideoWriter : IDisposable /// bool UsesVideo { get; } - // why no OpenFile(IEnumerator) ? - // different video writers may have different ideas of how and why splitting is to occur /// /// opens a recording stream /// set a video codec token first. /// + /// + /// why no OpenFile(IEnumerator<string>)? + /// different video writers may have different ideas of how and why splitting is to occur + /// void OpenFile(string baseName); /// @@ -101,38 +102,24 @@ public interface IVideoWriter : IDisposable } [AttributeUsage(AttributeTargets.Class)] - public sealed class VideoWriterAttribute : Attribute + public sealed class VideoWriterAttribute(string shortName, string name, string description) : Attribute { - public string ShortName { get; } - public string Name { get; } - public string Description { get; } - - public VideoWriterAttribute(string shortName, string name, string description) - { - ShortName = shortName; - Name = name; - Description = description; - } + public string ShortName { get; } = shortName; + public string Name { get; } = name; + public string Description { get; } = description; } - public class VideoWriterInfo + public class VideoWriterInfo(VideoWriterAttribute attribs, Type type) { - private static readonly Type[] CTOR_TYPES_A = { typeof(IDialogParent) }; + private static readonly Type[] CTOR_TYPES_A = [ typeof(IDialogParent) ]; - public VideoWriterAttribute Attribs { get; } - private readonly Type _type; - - public VideoWriterInfo(VideoWriterAttribute attribs, Type type) - { - _type = type; - Attribs = attribs; - } + public VideoWriterAttribute Attribs { get; } = attribs; /// parent for if the user is shown config dialog public IVideoWriter Create(IDialogParent dialogParent) => (IVideoWriter) ( - _type.GetConstructor(CTOR_TYPES_A) - ?.Invoke(new object[] { dialogParent }) - ?? Activator.CreateInstance(_type)); + type.GetConstructor(CTOR_TYPES_A) + ?.Invoke([ dialogParent ]) + ?? Activator.CreateInstance(type)); public override string ToString() => Attribs.Name; } @@ -142,11 +129,12 @@ public IVideoWriter Create(IDialogParent dialogParent) => (IVideoWriter) ( /// public static class VideoWriterInventory { - private static readonly Dictionary VideoWriters = new Dictionary(); + private static readonly Dictionary VideoWriters = [ ]; + private static readonly VideoWriterInfo[] VideoWritersOrdered; static VideoWriterInventory() { - foreach (var t in EmuHawk.ReflectionCache.Types) + foreach (var t in ReflectionCache.Types) { if (!t.IsInterface && typeof(IVideoWriter).IsAssignableFrom(t) @@ -157,9 +145,24 @@ static VideoWriterInventory() VideoWriters.Add(a.ShortName, new VideoWriterInfo(a, t)); } } + + // we want to keep the FFmpeg writer as the first item + var ffmpegShortName = typeof(FFmpegWriter) + .GetCustomAttributes(typeof(VideoWriterAttribute), false) + .Cast() + .First() + .ShortName; + + var videoWriters = VideoWriters.Values.ToList(); + var ffmpegWriter = videoWriters.Find(vwi => vwi.Attribs.ShortName == ffmpegShortName); + videoWriters.Remove(ffmpegWriter); + VideoWritersOrdered = videoWriters + .OrderBy(vwi => vwi.Attribs.Name) + .Prepend(ffmpegWriter) + .ToArray(); } - public static IEnumerable GetAllWriters() => VideoWriters.Values; + public static IEnumerable GetAllWriters() => VideoWritersOrdered; /// /// find an IVideoWriter by its short name diff --git a/src/BizHawk.Client.EmuHawk/AVOut/ImageSequenceWriter.cs b/src/BizHawk.Client.EmuHawk/AVOut/ImageSequenceWriter.cs index 3139a7b802c..f0bf9bf6993 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/ImageSequenceWriter.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/ImageSequenceWriter.cs @@ -1,8 +1,7 @@ -using System; using System.IO; using System.Drawing.Imaging; -using BizHawk.Bizware.BizwareGL; +using BizHawk.Bizware.Graphics; using BizHawk.Client.Common; using BizHawk.Common.PathExtensions; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/AVOut/JMDForm.cs b/src/BizHawk.Client.EmuHawk/AVOut/JMDForm.cs index 1a0d961044b..0904bc6b9f0 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/JMDForm.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/JMDForm.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; namespace BizHawk.Client.EmuHawk diff --git a/src/BizHawk.Client.EmuHawk/AVOut/JMDWriter.cs b/src/BizHawk.Client.EmuHawk/AVOut/JMDWriter.cs index 4ec8f34b8dd..8d0800ebf1d 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/JMDWriter.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/JMDWriter.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; @@ -624,6 +623,7 @@ public void OpenFile(string baseName) } // some of this code is copied from AviWriter... not sure how if at all it should be abstracted + /// /// blocking thread safe queue, used for communication between main program and file writing thread /// diff --git a/src/BizHawk.Client.EmuHawk/AVOut/NutMuxer.cs b/src/BizHawk.Client.EmuHawk/AVOut/NutMuxer.cs index 66a65e220c4..159fd9cd35c 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/NutMuxer.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/NutMuxer.cs @@ -1,8 +1,8 @@ -using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Numerics; +using System.Runtime.InteropServices; namespace BizHawk.Client.EmuHawk { @@ -539,15 +539,15 @@ public void WriteData(Stream dest) /// raw video data; if length 0, write EOR /// internal error, possible A/V desync /// already written EOR - public void WriteVideoFrame(int[] video) + public void WriteVideoFrame(ReadOnlySpan video) { if (_videoDone) throw new InvalidOperationException("Can't write data after end of relevance!"); if (_audioQueue.Count > 5) throw new Exception("A/V Desync?"); - int dataLen = video.Length * sizeof(int); - byte[] data = _bufferPool.GetBufferAtLeast(dataLen); - Buffer.BlockCopy(video, 0, data, 0, dataLen); + var dataLen = video.Length * sizeof(int); + var data = _bufferPool.GetBufferAtLeast(dataLen); + MemoryMarshal.AsBytes(video).CopyTo(data.AsSpan(0, dataLen)); if (dataLen == 0) { _videoDone = true; @@ -644,12 +644,12 @@ public void Finish() { if (!_videoDone) { - WriteVideoFrame(Array.Empty()); + WriteVideoFrame([ ]); } if (!_audioDone) { - WriteAudioFrame(Array.Empty()); + WriteAudioFrame([ ]); } // flush any remaining queued packets diff --git a/src/BizHawk.Client.EmuHawk/AVOut/NutWriter.cs b/src/BizHawk.Client.EmuHawk/AVOut/NutWriter.cs index 39c8f463702..08734b59b18 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/NutWriter.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/NutWriter.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Client.Common; @@ -76,7 +75,7 @@ public void AddFrame(IVideoProvider source) SetVideoParameters(source.BufferWidth, source.BufferHeight); } - _current.WriteVideoFrame(source.GetVideoBuffer()); + _current.WriteVideoFrame(source.GetVideoBuffer().AsSpan(0, _width * _height)); } public void AddSamples(short[] samples) diff --git a/src/BizHawk.Client.EmuHawk/AVOut/SynclessRecorder.cs b/src/BizHawk.Client.EmuHawk/AVOut/SynclessRecorder.cs index 169924ee1e3..7dc76f9606a 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/SynclessRecorder.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/SynclessRecorder.cs @@ -1,11 +1,10 @@ -using System; using System.IO; using System.Collections.Generic; using System.Drawing.Imaging; using System.Text; using BizHawk.Emulation.Common; -using BizHawk.Bizware.BizwareGL; +using BizHawk.Bizware.Graphics; using BizHawk.Client.Common; using BizHawk.Common.PathExtensions; diff --git a/src/BizHawk.Client.EmuHawk/AVOut/SynclessRecordingTools.cs b/src/BizHawk.Client.EmuHawk/AVOut/SynclessRecordingTools.cs index 8945f95b6eb..d6e5d4c4a46 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/SynclessRecordingTools.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/SynclessRecordingTools.cs @@ -1,11 +1,11 @@ -using System; using System.IO; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; -using BizHawk.Bizware.BizwareGL; +using BizHawk.Bizware.Graphics; using BizHawk.Client.Common; +using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Client.EmuHawk @@ -50,13 +50,9 @@ public void Run() string framesDir = ""; foreach (var line in lines) { - int idx = line.IndexOf('='); - string key = line[..idx]; - string value = line[(idx + 1)..]; - if (key == "framesdir") - { - framesDir = value; - } + const string KEY = "framesdir="; + if (line.StartsWithOrdinal(KEY)) framesDir = line.Substring(startIndex: KEY.Length); + // and continue } _mFramesDirectory = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(_mSynclessConfigFile)), framesDir); diff --git a/src/BizHawk.Client.EmuHawk/AVOut/VideoWriterChooserForm.cs b/src/BizHawk.Client.EmuHawk/AVOut/VideoWriterChooserForm.cs index 587d21854f3..6f97451cd82 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/VideoWriterChooserForm.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/VideoWriterChooserForm.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/AVOut/WavWriter.cs b/src/BizHawk.Client.EmuHawk/AVOut/WavWriter.cs index beed6ac85b6..57b238ed351 100644 --- a/src/BizHawk.Client.EmuHawk/AVOut/WavWriter.cs +++ b/src/BizHawk.Client.EmuHawk/AVOut/WavWriter.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Text; using System.IO; diff --git a/src/BizHawk.Client.EmuHawk/Api/ApiManager.cs b/src/BizHawk.Client.EmuHawk/Api/ApiManager.cs index 3eed6c02135..cdac3bd3e44 100644 --- a/src/BizHawk.Client.EmuHawk/Api/ApiManager.cs +++ b/src/BizHawk.Client.EmuHawk/Api/ApiManager.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -97,7 +96,6 @@ public static ApiContainer RestartLua( { _luaContainer?.Dispose(); _luaContainer = Register(serviceProvider, logCallback, mainForm, displayManager, inputManager, movieSession, toolManager, config, emulator, game); - ((GuiApi) _luaContainer.Gui).EnableLuaAutolockHack = true; return _luaContainer; } } diff --git a/src/BizHawk.Client.EmuHawk/Api/Libraries/ToolApi.cs b/src/BizHawk.Client.EmuHawk/Api/Libraries/ToolApi.cs index b46073ee063..8f3d87d9b32 100644 --- a/src/BizHawk.Client.EmuHawk/Api/Libraries/ToolApi.cs +++ b/src/BizHawk.Client.EmuHawk/Api/Libraries/ToolApi.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/ArchiveChooser.cs b/src/BizHawk.Client.EmuHawk/ArchiveChooser.cs index 16cda64e098..3a95e417836 100644 --- a/src/BizHawk.Client.EmuHawk/ArchiveChooser.cs +++ b/src/BizHawk.Client.EmuHawk/ArchiveChooser.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Collections.Generic; using System.Linq; @@ -136,7 +135,7 @@ private void StartMatching(TextBox tb, Action func) catch (ArgumentException ex) { string errMsg = ex.Message; - errMsg = errMsg[(errMsg.IndexOf('-') + 2)..]; + errMsg = errMsg.Substring(startIndex: errMsg.IndexOf('-') + 2); // Balloon is bugged on first invocation _errorBalloon.Show($"Error parsing RegEx: {errMsg}", tb); diff --git a/src/BizHawk.Client.EmuHawk/BizBox.Designer.cs b/src/BizHawk.Client.EmuHawk/BizBox.Designer.cs index 560e88b544e..bd72bd337ab 100644 --- a/src/BizHawk.Client.EmuHawk/BizBox.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/BizBox.Designer.cs @@ -180,7 +180,6 @@ private void InitializeComponent() this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "About EmuHawk"; this.Load += new System.EventHandler(this.BizBox_Load); - this.Shown += new System.EventHandler(this.BizBox_Shown); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); diff --git a/src/BizHawk.Client.EmuHawk/BizBox.cs b/src/BizHawk.Client.EmuHawk/BizBox.cs index 5c337c5fee2..6926ea7aae0 100644 --- a/src/BizHawk.Client.EmuHawk/BizBox.cs +++ b/src/BizHawk.Client.EmuHawk/BizBox.cs @@ -1,27 +1,22 @@ -using System; using System.Diagnostics; using System.Linq; using System.Windows.Forms; using BizHawk.Client.EmuHawk.Properties; using BizHawk.Common; -using BizHawk.Common.IOExtensions; using BizHawk.Emulation.Cores; namespace BizHawk.Client.EmuHawk { public partial class BizBox : Form { - private static readonly byte[] _bizBoxSound = ReflectionCache.EmbeddedResourceStream("Resources.nothawk.wav").ReadAllBytes(); - private readonly Action _playWavFileCallback; - - public BizBox(Action playWavFileCallback) + public BizBox(Action/*?*/ playNotHawkCallSFX = null) { InitializeComponent(); Icon = Resources.Logo; pictureBox1.Image = Resources.CorpHawk; btnCopyHash.Image = Resources.Duplicate; - _playWavFileCallback = playWavFileCallback; + if (playNotHawkCallSFX is not null) Shown += (_, _) => playNotHawkCallSFX(); } private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) @@ -38,23 +33,9 @@ private void OK_Click(object sender, EventArgs e) private void BizBox_Load(object sender, EventArgs e) { DeveloperBuildLabel.Visible = VersionInfo.DeveloperBuild; - -#if true //TODO prepare for re-adding x86 and adding ARM/RISC-V - const string targetArch = "x64"; -#else - var targetArch = IntPtr.Size is 8 ? "x64" : "x86"; -#endif -#if DEBUG - const string buildConfig = "Debug"; -#else - const string buildConfig = "Release"; -#endif - VersionLabel.Text = $"Version {VersionInfo.MainVersion}"; - VersionLabel.Text += VersionInfo.DeveloperBuild - ? $" — dev build ({buildConfig}, {targetArch})" - : $" ({targetArch})"; + VersionLabel.Text = VersionInfo.GetFullVersionDetails(); DateLabel.Text = VersionInfo.ReleaseDate; - + (linkLabel2.Text, linkLabel2.Tag) = VersionInfo.GetGitCommitLink(); foreach (var core in CoreInventory.Instance.SystemsFlat.Where(core => core.CoreAttr.Released) .OrderByDescending(core => core.Name.ToLowerInvariant())) { @@ -63,26 +44,15 @@ private void BizBox_Load(object sender, EventArgs e) Dock = DockStyle.Top }); } - - linkLabel2.Text = $"Commit :{VersionInfo.GIT_BRANCH}@{VersionInfo.GIT_SHORTHASH}"; } - private void BizBox_Shown(object sender, EventArgs e) - => _playWavFileCallback(_bizBoxSound); - private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) - { - Process.Start($"https://github.com/TASEmulators/BizHawk/commit/{VersionInfo.GIT_SHORTHASH}"); - } + => Process.Start((string) ((Control) sender).Tag); private void btnCopyHash_Click(object sender, EventArgs e) - { - Clipboard.SetText(VersionInfo.GIT_SHORTHASH); - } + => Clipboard.SetText(VersionInfo.GIT_HASH); private void linkLabel3_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) - { - Process.Start("https://github.com/TASEmulators/BizHawk/graphs/contributors"); - } + => Process.Start(VersionInfo.BizHawkContributorsListURI); } } diff --git a/src/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj b/src/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj index ee281732fc7..7338784c6ad 100755 --- a/src/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj +++ b/src/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj @@ -9,10 +9,10 @@ app.manifest disable None + true - @@ -40,7 +40,6 @@ - @@ -262,8 +261,6 @@ - - diff --git a/src/BizHawk.Client.EmuHawk/CoreFeatureAnalysis.cs b/src/BizHawk.Client.EmuHawk/CoreFeatureAnalysis.cs index 011bd0228a0..6442d1299ab 100644 --- a/src/BizHawk.Client.EmuHawk/CoreFeatureAnalysis.cs +++ b/src/BizHawk.Client.EmuHawk/CoreFeatureAnalysis.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/ClipboardEventTextBox.cs b/src/BizHawk.Client.EmuHawk/CustomControls/ClipboardEventTextBox.cs new file mode 100644 index 00000000000..a2ff671c345 --- /dev/null +++ b/src/BizHawk.Client.EmuHawk/CustomControls/ClipboardEventTextBox.cs @@ -0,0 +1,94 @@ +using System.Windows.Forms; +using BizHawk.Common; + +namespace BizHawk.Client.EmuHawk.CustomControls +{ + public class ClipboardEventTextBox : TextBox + { + protected override void WndProc(ref Message m) + { + // WM_PASTE is also sent when pasting through the OS context menu, but doesn't work on Mono + const int WM_PASTE = 0x302; + + if (m.Msg is WM_PASTE && !OSTailoredCode.IsUnixHost) + { + if (OnPasteInternal()) + { + return; + } + } + + base.WndProc(ref m); + } + + protected override bool ProcessCmdKey(ref Message m, Keys keyData) + { + if (!ReadOnly && OSTailoredCode.IsUnixHost && keyData is (Keys.Control | Keys.V) or (Keys.Shift | Keys.Insert)) + { + return OnPasteInternal(); + } + + return base.ProcessCmdKey(ref m, keyData); + } + + /// if regular paste handling should be prevented. + private bool OnPasteInternal() + { + bool containsText; + string text; + + try + { + containsText = Clipboard.ContainsText(); + text = containsText ? Clipboard.GetText() : string.Empty; + } + catch (Exception) + { + // Clipboard is busy? No idea if this ever happens in practice + return true; + } + + var args = new PasteEventArgs(containsText, text); + OnPaste(args); + return args.Handled; + } + + protected virtual void OnPaste(PasteEventArgs e) + { } + + /// + /// Paste at selected position without exceeding the limit. + /// The pasted string will be truncated if necessary. + /// + /// + /// Does not raise . + /// + public void PasteWithMaxLength(string text) + { + if (MaxLength > 0) + { + var availableLength = MaxLength - TextLength + SelectionLength; + if (text.Length > availableLength) + { + text = text.Substring(startIndex: 0, length: availableLength); + } + } + Paste(text); + } + + protected sealed class PasteEventArgs : EventArgs + { + public bool ContainsText { get; } + public string Text { get; } + + /// Prevents regular paste handling if set to . + public bool Handled { get; set; } + + public PasteEventArgs(bool containsText, string text) + { + ContainsText = containsText; + Text = text; + } + } + } +} diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/GdiPlusRenderer.cs b/src/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/GdiPlusRenderer.cs index f585ddc41ec..e12d3448352 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/GdiPlusRenderer.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/GdiPlusRenderer.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; namespace BizHawk.Client.EmuHawk.CustomControls diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/IControlRenderer.cs b/src/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/IControlRenderer.cs index fb78f4f6e38..bc5afe44634 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/IControlRenderer.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/ControlRenderer/IControlRenderer.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; namespace BizHawk.Client.EmuHawk.CustomControls diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/ExceptionBox.cs b/src/BizHawk.Client.EmuHawk/CustomControls/ExceptionBox.cs index 212691c413a..917aa67199c 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/ExceptionBox.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/ExceptionBox.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/FolderBrowserDialogEx.cs b/src/BizHawk.Client.EmuHawk/CustomControls/FolderBrowserDialogEx.cs index 47e5bb28552..e8cd6f42051 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/FolderBrowserDialogEx.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/FolderBrowserDialogEx.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Runtime.InteropServices; using System.Threading; diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/HexTextBox.cs b/src/BizHawk.Client.EmuHawk/CustomControls/HexTextBox.cs index 8a8d13e5213..4573ddd4822 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/HexTextBox.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/HexTextBox.cs @@ -1,7 +1,6 @@ -using System; using System.Globalization; using System.Windows.Forms; - +using BizHawk.Client.EmuHawk.CustomControls; using BizHawk.Common.StringExtensions; using BizHawk.Common.NumberExtensions; @@ -11,11 +10,11 @@ namespace BizHawk.Client.EmuHawk public interface INumberBox { bool Nullable { get; } - int? ToRawInt(); - void SetFromRawInt(int? rawInt); + uint? ToRawUInt(); + void SetFromRawUInt(uint? rawUInt); } - public class HexTextBox : TextBox, INumberBox + public class HexTextBox : ClipboardEventTextBox, INumberBox { private string _addressFormatStr = ""; private long? _maxSize; @@ -86,7 +85,7 @@ protected override void OnKeyDown(KeyEventArgs e) { if (Text.IsHex() && !string.IsNullOrEmpty(_addressFormatStr)) { - var val = (uint)ToRawInt(); + var val = ToRawUInt(); if (val == GetMax()) { @@ -104,7 +103,7 @@ protected override void OnKeyDown(KeyEventArgs e) { if (Text.IsHex() && !string.IsNullOrEmpty(_addressFormatStr)) { - var val = (uint)ToRawInt(); + var val = ToRawUInt(); if (val == 0) { val = (uint)GetMax(); // int to long todo @@ -135,7 +134,19 @@ protected override void OnTextChanged(EventArgs e) base.OnTextChanged(e); } - public int? ToRawInt() + protected override void OnPaste(PasteEventArgs e) + { + if (e.ContainsText) + { + string text = e.Text.CleanHex(); + PasteWithMaxLength(text); + e.Handled = true; + } + + base.OnPaste(e); + } + + public uint? ToRawUInt() { if (string.IsNullOrWhiteSpace(Text)) { @@ -147,10 +158,10 @@ protected override void OnTextChanged(EventArgs e) return 0; } - return int.Parse(Text, NumberStyles.HexNumber); + return uint.Parse(Text, NumberStyles.HexNumber); } - public void SetFromRawInt(int? val) + public void SetFromRawUInt(uint? val) { Text = val.HasValue ? string.Format(_addressFormatStr, val) : ""; } @@ -219,7 +230,7 @@ protected override void OnKeyDown(KeyEventArgs e) { if (Text.IsHex()) { - var val = (uint)ToRawInt(); + var val = ToRawUInt().Value; if (val == uint.MaxValue) { val = 0; @@ -236,7 +247,7 @@ protected override void OnKeyDown(KeyEventArgs e) { if (Text.IsHex()) { - var val = (uint)ToRawInt(); + var val = ToRawUInt().Value; if (val == 0) { @@ -268,7 +279,7 @@ protected override void OnTextChanged(EventArgs e) base.OnTextChanged(e); } - public int? ToRawInt() + public uint? ToRawUInt() { if (string.IsNullOrWhiteSpace(Text) || !Text.IsHex()) { @@ -280,10 +291,10 @@ protected override void OnTextChanged(EventArgs e) return 0; } - return (int)uint.Parse(Text); + return uint.Parse(Text); } - public void SetFromRawInt(int? val) + public void SetFromRawUInt(uint? val) { Text = val?.ToString() ?? ""; } diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/Cell.cs b/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/Cell.cs index bae344b07f7..d401076bea0 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/Cell.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/Cell.cs @@ -1,4 +1,5 @@ -using System; +#nullable enable + using System.Diagnostics; using BizHawk.Common; @@ -11,8 +12,9 @@ namespace BizHawk.Client.EmuHawk /// public sealed class Cell : IComparable, IEquatable { - public RollColumn Column { get; internal set; } - public int? RowIndex { get; internal set; } + public RollColumn? Column { get; internal set; } = null; + + public int? RowIndex { get; internal set; } = null; public Cell() { } @@ -25,30 +27,30 @@ public Cell(Cell cell) public int CompareTo(Cell other) => SortCell.Compare(this, other); - public bool Equals(Cell other) + public bool Equals(Cell? other) => other is not null && Column?.Name == other.Column?.Name && RowIndex == other.RowIndex; - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is Cell other && Equals(other); public override int GetHashCode() { - return Column.GetHashCode() + RowIndex.GetHashCode(); + return Column!.GetHashCode() + RowIndex.GetHashCode(); } public override string ToString() => $"Cell(r: {RowIndex?.ToString() ?? "null"}, c: \"{Column?.Name ?? "(no column)"}\")"; - public static bool operator ==(Cell a, Cell b) + public static bool operator ==(Cell? a, Cell? b) => a is null ? b is null : a.Equals(b); - public static bool operator !=(Cell a, Cell b) + public static bool operator !=(Cell? a, Cell? b) => a is null ? b is not null : !a.Equals(b); } internal static class SortCell { - public static int Compare(Cell c1, Cell c2) + public static int Compare(Cell? c1, Cell? c2) { if (c1 is null && c2 is null) { @@ -65,9 +67,9 @@ public static int Compare(Cell c1, Cell c2) return -1; } - if (c1.RowIndex.HasValue) + if (c1.RowIndex is not null) { - if (c2.RowIndex.HasValue) + if (c2.RowIndex is not null) { int row = c1.RowIndex.Value.CompareTo(c2.RowIndex.Value); return row == 0 @@ -78,12 +80,12 @@ public static int Compare(Cell c1, Cell c2) return 1; } - if (c2.RowIndex.HasValue) + if (c2.RowIndex is not null) { return -1; } - return string.CompareOrdinal(c1.Column.Name, c2.Column.Name); + return string.CompareOrdinal(c1.Column!.Name, c2.Column!.Name); } } @@ -119,9 +121,7 @@ public bool IncludesRow(int rowIndex) public static class CellExtensions { - public static bool IsDataCell(this Cell cell) - { - return cell != null && cell.RowIndex != null && cell.Column != null; - } + public static bool IsDataCell(this Cell? cell) + => cell is { RowIndex: not null, Column: not null }; } } diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/ColumnType.cs b/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/ColumnType.cs index 4e5fac6af6d..aa2e2757d87 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/ColumnType.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/ColumnType.cs @@ -1,4 +1,6 @@ -namespace BizHawk.Client.EmuHawk +#nullable enable + +namespace BizHawk.Client.EmuHawk { /// /// Specifies the type of column of a diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.Drawing.cs b/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.Drawing.cs index 4d7371bc52f..5b7c6c0ad6d 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.Drawing.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.Drawing.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -104,7 +103,7 @@ private void CalculateHorizontalColumnPositions(List visibleColumns) private void DrawColumnDrag(List visibleColumns) { - if (!(_columnDown?.Width > 0) + if (_columnDown is not { Width: > 0 } || !_columnDownMoved || !_currentX.HasValue || !_currentY.HasValue @@ -139,28 +138,27 @@ private void DrawColumnDrag(List visibleColumns) private void DrawCellDrag(List visibleColumns) { - if (_draggingCell?.RowIndex != null - && _draggingCell.Column.Width > 0 + if (_draggingCell is { RowIndex: int targetRow, Column: { Width: > 0 } targetCol } && _currentX.HasValue && _currentY.HasValue) { var text = ""; int offsetX = 0; int offsetY = 0; - QueryItemText?.Invoke(_draggingCell.RowIndex.Value, _draggingCell.Column, out text, ref offsetX, ref offsetY); + QueryItemText?.Invoke(targetRow, targetCol, out text, ref offsetX, ref offsetY); Color bgColor = _backColor; - QueryItemBkColor?.Invoke(_draggingCell.RowIndex.Value, _draggingCell.Column, ref bgColor); + QueryItemBkColor?.Invoke(targetRow, targetCol, ref bgColor); int columnHeight = CellHeight; if (HorizontalOrientation) { - int columnIndex = visibleColumns.IndexOf(_draggingCell.Column); + var columnIndex = visibleColumns.IndexOf(targetCol); columnHeight = GetHColHeight(columnIndex); } - int x1 = _currentX.Value - (_draggingCell.Column.Width / 2); + var x1 = _currentX.Value - targetCol.Width / 2; int y1 = _currentY.Value - (columnHeight / 2); - int x2 = x1 + _draggingCell.Column.Width; + var x2 = x1 + targetCol.Width; int y2 = y1 + columnHeight; _renderer.SetBrush(bgColor); @@ -410,7 +408,7 @@ private void DrawColumnBg(List visibleColumns, Rectangle rect) int top = GetHColTop(i) - _vBar.Value; int height = GetHColHeight(i); - _renderer.SetBrush(CurrentCell.Column.Emphasis + _renderer.SetBrush(CurrentCell.Column!.Emphasis ? SystemColors.Highlight.Add(0x00222222) : SystemColors.Highlight); @@ -433,7 +431,7 @@ private void DrawColumnBg(List visibleColumns, Rectangle rect) int left = column.Left - _hBar.Value; int width = column.Right - _hBar.Value - left; - _renderer.SetBrush(CurrentCell.Column.Emphasis + _renderer.SetBrush(CurrentCell.Column!.Emphasis ? SystemColors.Highlight.Add(0x00550000) : SystemColors.Highlight); @@ -448,7 +446,7 @@ private void DrawColumnBg(List visibleColumns, Rectangle rect) // Draw Gridlines and background colors using QueryItemBkColor. private void DrawBg(List visibleColumns, Rectangle rect, int firstVisibleRow, int lastVisibleRow) { - if (QueryItemBkColor != null) + if (QueryItemBkColor is not null || QueryRowBkColor is not null) { DoBackGroundCallback(visibleColumns, rect, firstVisibleRow, lastVisibleRow); } @@ -564,7 +562,7 @@ private void DrawCellBG(Color color, Cell cell, List visibleColumns, return; } - int columnIndex = visibleColumns.IndexOf(cell.Column); + var columnIndex = visibleColumns.IndexOf(cell.Column!); w = CellWidth - 1; y = GetHColTop(columnIndex) - _vBar.Value + 1; h = GetHColHeight(columnIndex) - 1; @@ -577,7 +575,7 @@ private void DrawCellBG(Color color, Cell cell, List visibleColumns, return; } - x = cell.Column.Left - _hBar.Value + 1; + x = cell.Column!.Left - _hBar.Value + 1; w = cell.Column.Width - 1; h = CellHeight - 1; } diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.cs b/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.cs index 79507d64e31..e0d34f50492 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; @@ -57,8 +56,9 @@ public override Color ForeColor private int[] _horizontalColumnTops; // Updated on paint, contains one extra item to allow inference of last column height - private RollColumn _columnDown; - private RollColumn _columnResizing; + private RollColumn/*?*/ _columnDown; + + private RollColumn/*?*/ _columnResizing; private int? _currentX; private int? _currentY; @@ -81,12 +81,14 @@ public override Color ForeColor /// Gets or sets a value indicating whether or not the control will respond to right-click events with a context menu /// [Category("Behavior")] + [DefaultValue(true)] public bool AllowRightClickSelection { get; set; } = true; /// /// Gets or sets a value indicating whether or not Home and End will navigate to the beginning or end of the list /// [Category("Behavior")] + [DefaultValue(true)] public bool AllowMassNavigationShortcuts { get; set; } = true; [Category("Behavior")] @@ -177,13 +179,14 @@ protected override void OnDoubleClick(EventArgs e) } else { - var maxLength = CurrentCell.Column.Text?.Length ?? 0; + var col = CurrentCell.Column!; + var maxLength = col.Text.Length; for (int i = 0; i < RowCount; i++) { string text = ""; int offSetX = 0, offSetY = 0; - QueryItemText?.Invoke(i, CurrentCell.Column, out text, ref offSetX, ref offSetY); + QueryItemText?.Invoke(i, col, out text, ref offSetX, ref offSetY); if (text.Length > maxLength) { maxLength = text.Length; @@ -191,7 +194,7 @@ protected override void OnDoubleClick(EventArgs e) } var newWidth = (maxLength * _charSize.Width) + (CellWidthPadding * 2); - CurrentCell.Column.Width = (int)newWidth; + col.Width = (int) newWidth; _columns.ColumnsChanged(); Refresh(); } @@ -206,14 +209,14 @@ protected override void OnDoubleClick(EventArgs e) /// [DefaultValue(3)] [Category("Behavior")] - public int CellWidthPadding { get; set; } + public int CellWidthPadding { get; set; } = 3; /// /// Gets or sets the amount of top and bottom padding on the text inside a cell /// [DefaultValue(1)] [Category("Behavior")] - public int CellHeightPadding { get; set; } + public int CellHeightPadding { get; set; } = 1; /// /// Gets or sets a value indicating whether grid lines are displayed around cells @@ -379,7 +382,7 @@ private void FastDraw() /// Gets or sets a value indicating whether pressing page up/down will cause /// the current selection to change /// - [DefaultValue(false)] + [DefaultValue(true)] [Category("Behavior")] public bool ChangeSelectionWhenPaging { get; set; } = true; @@ -535,24 +538,26 @@ public CellEventArgs(Cell oldCell, Cell newCell) public class ColumnClickEventArgs { - public ColumnClickEventArgs(RollColumn column) + public ColumnClickEventArgs(RollColumn/*?*/ column) { Column = column; } - public RollColumn Column { get; } + public RollColumn/*?*/ Column { get; } } + /// this is only used in TAStudio, which ignores the args param completely public class ColumnReorderedEventArgs { - public ColumnReorderedEventArgs(int oldDisplayIndex, int newDisplayIndex, RollColumn column) + public ColumnReorderedEventArgs(int oldDisplayIndex, int newDisplayIndex, RollColumn/*?*/ column) { Column = column; OldDisplayIndex = oldDisplayIndex; NewDisplayIndex = newDisplayIndex; } - public RollColumn Column { get; } + public RollColumn/*?*/ Column { get; } + public int OldDisplayIndex { get; } public int NewDisplayIndex { get; } } @@ -792,7 +797,6 @@ private int LastVisibleRow } // Small jump, more accurate - var range = 0.RangeTo(_lagFrames[VisibleRows - halfRow]); int lastVisible = LastFullyVisibleRow; do { @@ -808,7 +812,7 @@ private int LastVisibleRow SetLagFramesArray(); lastVisible = LastFullyVisibleRow; } - while (!range.Contains(lastVisible - value) && FirstVisibleRow != 0); + while ((lastVisible - value < 0 || _lagFrames[VisibleRows - halfRow] < lastVisible - value) && FirstVisibleRow != 0); } _programmaticallyChangingRow = false; PointMouseToNewCell(); @@ -972,21 +976,15 @@ public bool IsRowSelected(int rowIndex) public IEnumerable GenerateContextMenuItems() { - if (Rotatable) + if (!Rotatable) return [ ]; + var rotate = new ToolStripMenuItem { - yield return new ToolStripSeparator(); - - var rotate = new ToolStripMenuItem - { - Name = "RotateMenuItem", - Text = "Rotate", - ShortcutKeyDisplayString = RotateHotkeyStr - }; - - rotate.Click += (o, ev) => { HorizontalOrientation ^= true; }; - - yield return rotate; - } + Name = "RotateMenuItem", + Text = "Rotate", + ShortcutKeyDisplayString = RotateHotkeyStr + }; + rotate.Click += (_, _) => HorizontalOrientation = !HorizontalOrientation; + return [ new ToolStripSeparator(), rotate ]; } public string RotateHotkeyStr => "Ctrl+Shift+F"; @@ -1156,7 +1154,7 @@ protected override void OnMouseDown(MouseEventArgs e) { // do marker drag here } - else if (ModifierKeys == Keys.Shift && CurrentCell.Column.Type == ColumnType.Text) + else if (ModifierKeys is Keys.Shift && CurrentCell.Column! is { Type: ColumnType.Text } col) { if (_selectedItems.Count is not 0) { @@ -1188,7 +1186,6 @@ protected override void OnMouseDown(MouseEventArgs e) additionEndExcl = targetRow + 1; } } - var col = CurrentCell.Column; for (var i = additionStart; i < additionEndExcl; i++) SelectCell(new() { RowIndex = i, Column = col }); } } @@ -1202,7 +1199,7 @@ protected override void OnMouseDown(MouseEventArgs e) SelectCell(CurrentCell); } } - else if (ModifierKeys == Keys.Control && CurrentCell.Column.Type == ColumnType.Text) + else if (ModifierKeys is Keys.Control && CurrentCell.Column!.Type is ColumnType.Text) { SelectCell(CurrentCell, toggle: true); } @@ -1331,17 +1328,19 @@ protected override void OnMouseWheel(MouseEventArgs e) } } +#pragma warning disable MA0091 // passing through `sender` is intentional private void DoRightMouseScroll(object sender, MouseEventArgs e) { RightMouseScrolled?.Invoke(sender, e); } +#pragma warning restore MA0091 - private void ColumnClickEvent(RollColumn column) + private void ColumnClickEvent(RollColumn/*?*/ column) { ColumnClick?.Invoke(this, new ColumnClickEventArgs(column)); } - private void ColumnRightClickEvent(RollColumn column) + private void ColumnRightClickEvent(RollColumn/*?*/ column) { ColumnRightClick?.Invoke(this, new ColumnClickEventArgs(column)); } @@ -1366,10 +1365,7 @@ protected override void OnKeyDown(KeyEventArgs e) } else if (e.IsCtrlShift(Keys.F)) { - if (Rotatable) - { - HorizontalOrientation ^= true; - } + if (Rotatable) HorizontalOrientation = !HorizontalOrientation; } // Scroll else if (e.IsPressed(Keys.PageUp)) @@ -1599,7 +1595,7 @@ private void CellChanged(Cell newCell) PointedCellChanged(this, new CellEventArgs(_lastCell, CurrentCell)); } - if (CurrentCell?.Column != null && CurrentCell.RowIndex.HasValue) + if (CurrentCell?.Column is not null) { _hoverTimer.Start(); } @@ -1616,6 +1612,7 @@ private void VerticalBar_ValueChanged(object sender, EventArgs e) Refresh(); } +#pragma warning disable MA0091 // unorthodox, but I think this is sound --yoshi if (_horizontalOrientation) { ColumnScroll?.Invoke(_hBar, e); @@ -1624,6 +1621,7 @@ private void VerticalBar_ValueChanged(object sender, EventArgs e) { RowScroll?.Invoke(_vBar, e); } +#pragma warning restore MA0091 } private void HorizontalBar_ValueChanged(object sender, EventArgs e) @@ -1633,6 +1631,7 @@ private void HorizontalBar_ValueChanged(object sender, EventArgs e) Refresh(); } +#pragma warning disable MA0091 // unorthodox, but I think this is sound --yoshi if (_horizontalOrientation) { RowScroll?.Invoke(_hBar, e); @@ -1641,6 +1640,7 @@ private void HorizontalBar_ValueChanged(object sender, EventArgs e) { ColumnScroll?.Invoke(_vBar, e); } +#pragma warning restore MA0091 } private void ColumnChangedCallback() @@ -1654,13 +1654,15 @@ private void ColumnChangedCallback() private void DoColumnReorder() { - if (_columnDown != CurrentCell.Column) + if (_columnDown! != CurrentCell.Column!) { var oldIndex = _columns.IndexOf(_columnDown); var newIndex = _columns.IndexOf(CurrentCell.Column); ColumnReordered?.Invoke(this, new ColumnReorderedEventArgs(oldIndex, newIndex, _columnDown)); + //TODO surely this only works properly in one direction? + // also the event is "...Reordered"--past tense--so it should be called AFTER the change --yoshi _columns.Remove(_columnDown); _columns.Insert(newIndex, _columnDown); } @@ -1883,7 +1885,7 @@ private Cell CalculatePointedCell(int x, int y) /// /// The pixel coordinate. /// RollColumn object that contains the pixel coordinate or null if none exists. - private RollColumn ColumnAtPixel(int pixel) + private RollColumn/*?*/ ColumnAtPixel(int pixel) { if (_horizontalOrientation) { @@ -1943,13 +1945,11 @@ private int GetHColBottom(int index) => // The height of a column cell in Vertical Orientation. private int ColumnHeight => CellHeight + 2; - // The width of a cell in Horizontal Orientation. Only can be changed by changing the Font or CellPadding. - private int CellWidth { get; set; } + // The width of a cell in Horizontal Orientation. + private int CellWidth => (int)_charSize.Width + CellWidthPadding * 4; // Double the padding for horizontal because it looks better - /// - /// Gets or sets a value indicating the height of a cell in Vertical Orientation. Only can be changed by changing the Font or CellPadding. - /// - private int CellHeight { get; set; } = 8; + // The height of a cell in Vertical Orientation. + private int CellHeight => (int)_charSize.Height + CellHeightPadding * 2; /// /// Call when _charSize, MaxCharactersInHorizontal, or CellPadding is changed. @@ -1962,12 +1962,8 @@ private void UpdateCellSize() // Measure width change to ignore extra padding at start/end var size1 = _renderer.MeasureString("A", Font); var size2 = _renderer.MeasureString("AA", Font); - _charSize = new SizeF(size2.Width - size1.Width, size1.Height); // TODO make this a property so changing it updates other values. + _charSize = new SizeF(size2.Width - size1.Width, size1.Height); } - - // TODO: Should we round instead of truncate? - CellHeight = (int)_charSize.Height + (CellHeightPadding * 2); - CellWidth = (int)_charSize.Width + (CellWidthPadding * 4); // Double the padding for horizontal because it looks better if (_columns.VisibleColumns.Any()) { diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/RollColumn.cs b/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/RollColumn.cs index fb1f50aaa8b..78bd394f735 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/RollColumn.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/RollColumn.cs @@ -1,4 +1,6 @@ -namespace BizHawk.Client.EmuHawk +#nullable enable + +namespace BizHawk.Client.EmuHawk { public class RollColumn { diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/RollColumns.cs b/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/RollColumns.cs index b87491914c7..fe4a2128c9d 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/RollColumns.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/InputRoll/RollColumns.cs @@ -1,4 +1,5 @@ -using System; +#nullable enable + using System.Collections.Generic; using System.Linq; @@ -6,11 +7,12 @@ namespace BizHawk.Client.EmuHawk { public class RollColumns : List { - public RollColumn this[string name] => this.SingleOrDefault(column => column.Name == name); + public RollColumn? this[string name] + => this.SingleOrDefault(column => column.Name == name); public IEnumerable VisibleColumns => this.Where(c => c.Visible); - public Action ChangedCallback { get; set; } + public Action? ChangedCallback { get; set; } = null; // TODO: this shouldn't be exposed. But in order to not expose it, each RollColumn must have a change callback, and all property changes must call it, it is quicker and easier to just call this when needed public void ColumnsChanged() diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/InputWidget.cs b/src/BizHawk.Client.EmuHawk/CustomControls/InputWidget.cs index a0a5e7f322f..e13426272e1 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/InputWidget.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/InputWidget.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/MsgBox.cs b/src/BizHawk.Client.EmuHawk/CustomControls/MsgBox.cs index 1350eaa8923..13345782cbf 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/MsgBox.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/MsgBox.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/RepeatButton.cs b/src/BizHawk.Client.EmuHawk/CustomControls/RepeatButton.cs index 45e6d84f6e6..30c2eb0693c 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/RepeatButton.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/RepeatButton.cs @@ -1,10 +1,11 @@ -using System; using System.Windows.Forms; namespace BizHawk.Client.EmuHawk { // http://www.codeproject.com/Articles/2130/NET-port-of-Joe-s-AutoRepeat-Button-class +#pragma warning disable MA0104 // unlikely to conflict with System.Windows.Controls.Primitives.RepeatButton public class RepeatButton : Button +#pragma warning restore MA0104 { private readonly Timer _mTimer; private bool _down; diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/ScreenshotForm.cs b/src/BizHawk.Client.EmuHawk/CustomControls/ScreenshotForm.cs index e89ecd8dc78..6cb92e775c4 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/ScreenshotForm.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/ScreenshotForm.cs @@ -1,8 +1,7 @@ -using System; using System.Drawing; using System.Windows.Forms; -using BizHawk.Bizware.BizwareGL; +using BizHawk.Bizware.Graphics; namespace BizHawk.Client.EmuHawk { diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/ViewportPanel.cs b/src/BizHawk.Client.EmuHawk/CustomControls/ViewportPanel.cs index 1ef784db64b..01f22098aad 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/ViewportPanel.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/ViewportPanel.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Threading; using System.Drawing; diff --git a/src/BizHawk.Client.EmuHawk/DialogControllerWinFormsExtensions.cs b/src/BizHawk.Client.EmuHawk/DialogControllerWinFormsExtensions.cs index 6982b5450fd..281ed362d73 100644 --- a/src/BizHawk.Client.EmuHawk/DialogControllerWinFormsExtensions.cs +++ b/src/BizHawk.Client.EmuHawk/DialogControllerWinFormsExtensions.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Windows.Forms; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/DisplayManager/DisplayManager.cs b/src/BizHawk.Client.EmuHawk/DisplayManager/DisplayManager.cs index 802bc31b0dc..69eeea9b3ab 100644 --- a/src/BizHawk.Client.EmuHawk/DisplayManager/DisplayManager.cs +++ b/src/BizHawk.Client.EmuHawk/DisplayManager/DisplayManager.cs @@ -1,10 +1,10 @@ -using System; using System.Diagnostics; using System.Drawing; -using BizHawk.Bizware.BizwareGL; +using BizHawk.Bizware.Graphics; using BizHawk.Bizware.Graphics.Controls; using BizHawk.Client.Common; +using BizHawk.Common; using BizHawk.Emulation.Common; namespace BizHawk.Client.EmuHawk @@ -31,7 +31,7 @@ public DisplayManager( IGL gl, PresentationPanel presentationPanel, Func getIsSecondaryThrottlingDisabled) - : base(config, emulator, inputManager, movieSession, gl.DispMethodEnum, gl, gl.CreateRenderer()) + : base(config, emulator, inputManager, movieSession, gl.DispMethodEnum, gl, gl.CreateGuiRenderer()) { _presentationPanel = presentationPanel; _getIsSecondaryThrottlingDisabled = getIsSecondaryThrottlingDisabled; @@ -51,14 +51,18 @@ public override void ActivateOpenGLContext() public override Size GetPanelNativeSize() => _presentationPanel.NativeSize; + protected override int GetGraphicsControlDpi() + => OSTailoredCode.IsUnixHost ? DisplayManagerBase.DEFAULT_DPI : GraphicsControlDpi; + + // DeviceDpi is not available under mono, so we need to have this access wrapped in a separate function + private int GraphicsControlDpi => _graphicsControl.DeviceDpi; + protected override Point GraphicsControlPointToClient(Point p) => _graphicsControl.PointToClient(p); protected override void SwapBuffersOfGraphicsControl() => _graphicsControl.SwapBuffers(); protected override void UpdateSourceDrawingWork(JobInfo job) { - bool alternateVsync = false; - if (!job.Offscreen) { //apply the vsync setting (should probably try to avoid repeating this) @@ -73,12 +77,9 @@ protected override void UpdateSourceDrawingWork(JobInfo job) vsync = false; //for now, it's assumed that the presentation panel is the main window, but that may not always be true - if (vsync && GlobalConfig.DispAlternateVsync && GlobalConfig.VSyncThrottle && _gl.DispMethodEnum is EDispMethod.D3D9) - { - alternateVsync = true; - //unset normal vsync if we've chosen the alternate vsync - vsync = false; - } + + // no cost currently to just always call this... + _graphicsControl.AllowTearing(GlobalConfig.DispAllowTearing); //TODO - whats so hard about triple buffering anyway? just enable it always, and change api to SetVsync(enable,throttle) //maybe even SetVsync(enable,throttlemethod) or just SetVsync(enable,throttle,advanced) @@ -96,40 +97,26 @@ protected override void UpdateSourceDrawingWork(JobInfo job) } } - // begin rendering on this context - // should this have been done earlier? - // do i need to check this on an intel video card to see if running excessively is a problem? (it used to be in the FinalTarget command below, shouldn't be a problem) - //GraphicsControl.Begin(); // CRITICAL POINT for yabause+GL - //TODO - auto-create and age these (and dispose when old) int rtCounter = 0; - _currentFilterProgram.RenderTargetProvider = new DisplayManagerRenderTargetProvider(size => _shaderChainFrugalizers[rtCounter++].Get(size)); - _gl.BeginScene(); RunFilterChainSteps(ref rtCounter, out var rtCurr, out var inFinalTarget); - _gl.EndScene(); if (job.Offscreen) { - job.OffscreenBb = rtCurr.Texture2d.Resolve(); + job.OffscreenBb = rtCurr.Resolve(); job.OffscreenBb.DiscardAlpha(); return; } Debug.Assert(inFinalTarget); - // wait for vsync to begin - if (alternateVsync) ((dynamic) _gl).AlternateVsyncPass(0); - // present and conclude drawing _graphicsControl.SwapBuffers(); - // wait for vsync to end - if (alternateVsync) ((dynamic) _gl).AlternateVsyncPass(1); - // nope. don't do this. workaround for slow context switching on intel GPUs. just switch to another context when necessary before doing anything - // presentationPanel.GraphicsControl.End(); + // _graphicsControl.End(); } } } diff --git a/src/BizHawk.Client.EmuHawk/EmuHawkUtil.cs b/src/BizHawk.Client.EmuHawk/EmuHawkUtil.cs index bf792836f84..70c339dfb17 100644 --- a/src/BizHawk.Client.EmuHawk/EmuHawkUtil.cs +++ b/src/BizHawk.Client.EmuHawk/EmuHawkUtil.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Security.Principal; @@ -15,7 +14,7 @@ public static class EmuHawkUtil /// http://stackoverflow.com/questions/139010/how-to-resolve-a-lnk-in-c-sharp public static string ResolveShortcut(string filename) { - if (OSTailoredCode.IsUnixHost || filename.Contains("|") + if (OSTailoredCode.IsUnixHost || HawkFile.PathContainsPipe(filename) || !".lnk".Equals(Path.GetExtension(filename), StringComparison.OrdinalIgnoreCase)) { return filename; // archive internal files are never shortcuts (and choke when analyzing any further) diff --git a/src/BizHawk.Client.EmuHawk/Extensions/ControlExtensions.cs b/src/BizHawk.Client.EmuHawk/Extensions/ControlExtensions.cs index 29069fd3ffb..13de37f6cb3 100644 --- a/src/BizHawk.Client.EmuHawk/Extensions/ControlExtensions.cs +++ b/src/BizHawk.Client.EmuHawk/Extensions/ControlExtensions.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; diff --git a/src/BizHawk.Client.EmuHawk/Extensions/ToolExtensions.cs b/src/BizHawk.Client.EmuHawk/Extensions/ToolExtensions.cs index e394e6940f6..677ba79c0fb 100644 --- a/src/BizHawk.Client.EmuHawk/Extensions/ToolExtensions.cs +++ b/src/BizHawk.Client.EmuHawk/Extensions/ToolExtensions.cs @@ -1,7 +1,7 @@ -using System; using System.IO; using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Windows.Forms; using BizHawk.Common; @@ -190,7 +190,7 @@ public static ToolStripItem[] RecentMenu( Text = recent.Frozen ? "&Unfreeze" : "&Freeze", Image = recent.Frozen ? Properties.Resources.Unfreeze : Properties.Resources.Freeze }; - freezeItem.Click += (o, ev) => recent.Frozen ^= true; + freezeItem.Click += (_, _) => recent.Frozen = !recent.Frozen; items.Add(freezeItem); if (!noAutoload) @@ -239,8 +239,7 @@ public static void HandleLoadError(this RecentFiles recent, IMainFormForTools ma } public static IEnumerable MenuItems(this IMemoryDomains domains, Action setCallback, string selected = "", int? maxSize = null) - { - foreach (var domain in domains) + => domains.Select(domain => { var name = domain.Name; var item = new ToolStripMenuItem @@ -250,9 +249,7 @@ public static IEnumerable MenuItems(this IMemoryDomains domains, Checked = name == selected }; item.Click += (o, ev) => setCallback(name); - - yield return item; - } - } + return item; + }); } } diff --git a/src/BizHawk.Client.EmuHawk/FormBase.cs b/src/BizHawk.Client.EmuHawk/FormBase.cs index 0ad36d7c951..a0ca4c8b31e 100644 --- a/src/BizHawk.Client.EmuHawk/FormBase.cs +++ b/src/BizHawk.Client.EmuHawk/FormBase.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/GraphicsImplementations/IGLExtensions.cs b/src/BizHawk.Client.EmuHawk/GraphicsImplementations/IGLExtensions.cs deleted file mode 100644 index e470f4550dc..00000000000 --- a/src/BizHawk.Client.EmuHawk/GraphicsImplementations/IGLExtensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using BizHawk.Bizware.BizwareGL; -using BizHawk.Bizware.Graphics; - -namespace BizHawk.Client.EmuHawk -{ - public static class IGLExtensions - { - public static IGuiRenderer CreateRenderer(this IGL gl) - => gl is IGL_GDIPlus gdipImpl - ? new GDIPlusGuiRenderer(gdipImpl) - : new GuiRenderer(gl); // This implementation doesn't seem to require any OpenGL-specific (or D3D-specific) behaviour; can it be used with IGL_GdiPlus too? If so, is GDIPlusGuiRenderer only kept around because it's faster? --yoshi - } -} diff --git a/src/BizHawk.Client.EmuHawk/GraphicsImplementations/OpenGLProvider.cs b/src/BizHawk.Client.EmuHawk/GraphicsImplementations/OpenGLProvider.cs index 117e66c71fc..b4793c7e8d4 100644 --- a/src/BizHawk.Client.EmuHawk/GraphicsImplementations/OpenGLProvider.cs +++ b/src/BizHawk.Client.EmuHawk/GraphicsImplementations/OpenGLProvider.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Bizware.Graphics; using BizHawk.Emulation.Common; @@ -13,8 +11,8 @@ public class OpenGLProvider : IOpenGLProvider public bool SupportsGLVersion(int major, int minor) => OpenGLVersion.SupportsVersion(major, minor); - public object RequestGLContext(int major, int minor, bool coreProfile, bool forwardCompatible) - => new SDL2OpenGLContext(major, minor, coreProfile, forwardCompatible); + public object RequestGLContext(int major, int minor, bool coreProfile) + => new SDL2OpenGLContext(major, minor, coreProfile); public void ReleaseGLContext(object context) => ((SDL2OpenGLContext)context).Dispose(); diff --git a/src/BizHawk.Client.EmuHawk/IMainFormForTools.cs b/src/BizHawk.Client.EmuHawk/IMainFormForTools.cs index 34414c5243f..d2ba2bd5eda 100644 --- a/src/BizHawk.Client.EmuHawk/IMainFormForTools.cs +++ b/src/BizHawk.Client.EmuHawk/IMainFormForTools.cs @@ -1,6 +1,4 @@ -using System; - -using BizHawk.Bizware.BizwareGL; +using BizHawk.Bizware.Graphics; using BizHawk.Client.Common; using BizHawk.Emulation.Common; @@ -56,7 +54,7 @@ public interface IMainFormForTools : IDialogController bool EnsureCoreIsAccurate(); /// only referenced from - void FrameAdvance(); + void FrameAdvance(bool discardApiHawkSurfaces = true); /// only referenced from void FrameBufferResized(); @@ -78,9 +76,6 @@ public interface IMainFormForTools : IDialogController bool BlockFrameAdvance { get; set; } - /// only referenced from - void RelinquishControl(IControlMainform master); - /// only referenced from void SeekFrameAdvance(); @@ -88,9 +83,6 @@ public interface IMainFormForTools : IDialogController bool StartNewMovie(IMovie movie, bool record); - /// only referenced from - void TakeBackControl(); - /// only referenced from void Throttle(); diff --git a/src/BizHawk.Client.EmuHawk/Input/Input.cs b/src/BizHawk.Client.EmuHawk/Input/Input.cs index 223fd1eaf4d..06f45a19727 100644 --- a/src/BizHawk.Client.EmuHawk/Input/Input.cs +++ b/src/BizHawk.Client.EmuHawk/Input/Input.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Collections.Generic; using System.Threading; @@ -27,7 +26,9 @@ public void ControlInputFocus(Control c, ClientInputFocus types, bool wants) private readonly HashSet _wantingMouseFocus = new HashSet(); - public static Input Instance { get; set; } +#pragma warning disable CA2211 // public field + public static Input Instance; +#pragma warning restore CA2211 private readonly Thread _updateThread; @@ -131,6 +132,9 @@ private void HandleButton(string button, bool newState, ClientInputFocus source) private void HandleAxis(string axis, int newValue) { + if (ShouldSwallow(MainFormInputAllowedCallback(false), ClientInputFocus.Pad)) + return; + if (_trackDeltas) _axisDeltas[axis] += Math.Abs(newValue - _axisValues[axis]); _axisValues[axis] = newValue; } @@ -248,9 +252,9 @@ private void UpdateThreadProc() foreach (var ie in _newEvents) { //events are swallowed in some cases: - if ((ie.LogicalButton.Modifiers & LogicalButton.MASK_ALT) is not 0U && ShouldSwallow(MainFormInputAllowedCallback(true), ie)) + if ((ie.LogicalButton.Modifiers & LogicalButton.MASK_ALT) is not 0U && ShouldSwallow(MainFormInputAllowedCallback(true), ie.Source)) continue; - if (ie.EventType == InputEventType.Press && ShouldSwallow(allowInput, ie)) + if (ie.EventType == InputEventType.Press && ShouldSwallow(allowInput, ie.Source)) continue; EnqueueEvent(ie); @@ -261,13 +265,13 @@ private void UpdateThreadProc() } //lock(this) //arbitrary selection of polling frequency: - Thread.Sleep(10); + Thread.Sleep(2); } } - private static bool ShouldSwallow(AllowInput allowInput, InputEvent inputEvent) + private static bool ShouldSwallow(AllowInput allowInput, ClientInputFocus inputFocus) { - return allowInput == AllowInput.None || (allowInput == AllowInput.OnlyController && inputEvent.Source != ClientInputFocus.Pad); + return allowInput == AllowInput.None || (allowInput == AllowInput.OnlyController && inputFocus != ClientInputFocus.Pad); } public void StartListeningForAxisEvents() @@ -324,7 +328,7 @@ public string GetNextBindEvent(ref InputEvent lastPress) { InputEvent ie = DequeueEvent(); - if (ShouldSwallow(allowInput, ie)) continue; + if (ShouldSwallow(allowInput, ie.Source)) continue; if (ie.EventType == InputEventType.Press) { diff --git a/src/BizHawk.Client.EmuHawk/JumpLists.cs b/src/BizHawk.Client.EmuHawk/JumpLists.cs index ed8b927c408..5780494e415 100644 --- a/src/BizHawk.Client.EmuHawk/JumpLists.cs +++ b/src/BizHawk.Client.EmuHawk/JumpLists.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Reflection; diff --git a/src/BizHawk.Client.EmuHawk/LogWindow.cs b/src/BizHawk.Client.EmuHawk/LogWindow.cs index 8f417a4c602..320ef5a317e 100644 --- a/src/BizHawk.Client.EmuHawk/LogWindow.cs +++ b/src/BizHawk.Client.EmuHawk/LogWindow.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.IO; diff --git a/src/BizHawk.Client.EmuHawk/MainForm.Debug.cs b/src/BizHawk.Client.EmuHawk/MainForm.Debug.cs index 65726907520..d003932c463 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.Debug.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.Debug.cs @@ -41,6 +41,14 @@ private void AddDebugMenu() }, Text = "Firmware", }, + new ToolStripMenuItemEx + { + DropDownItems = + { + rcHashDebugItem, + }, + Text = "RCheevos", + }, new ToolStripSeparatorEx(), new DebugVSystemMenuItem(VSystemID.Raw.GB, VSystemID.Raw.GBC) { @@ -62,15 +70,6 @@ private void AddDebugMenu() new DebugVSystemChildItem(N64VideoSettingsFuzzToolForm.TOOL_NAME, OpenTool), }, }, - new ToolStripSeparatorEx(), - new ToolStripMenuItemEx - { - DropDownItems = - { - rcHashDebugItem, - }, - Text = "RCheevos", - }, }, Image = Resources.Bug, Text = "&Debug Utilities", diff --git a/src/BizHawk.Client.EmuHawk/MainForm.Designer.cs b/src/BizHawk.Client.EmuHawk/MainForm.Designer.cs index 871c1f1d043..94a10c2699f 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.Designer.cs @@ -57,7 +57,6 @@ private void InitializeComponent() this.toolStripSeparator21 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.AutoloadLastSlotMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.SaveSlotSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.SelectSlot0MenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.SelectSlot1MenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.SelectSlot2MenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.SelectSlot3MenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -67,6 +66,7 @@ private void InitializeComponent() this.SelectSlot7MenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.SelectSlot8MenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.SelectSlot9MenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.SelectSlot0MenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.PreviousSlotMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.NextSlotMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.toolStripSeparator5 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); @@ -134,6 +134,7 @@ private void InitializeComponent() this.toolStripMenuItem4 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.DisplayStatusBarMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.DisplayMessagesMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.toolStripSeparator8 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.DisplayLogWindowMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.ConfigSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.ControllersMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -205,9 +206,9 @@ private void InitializeComponent() this.GameSharkConverterMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.toolStripSeparator29 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.MultiDiskBundlerFileMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.BatchRunnerMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.ExternalToolMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.dummyExternalTool = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.BatchRunnerMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.RetroAchievementsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.StartRetroAchievementsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.NESSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -259,14 +260,14 @@ private void InitializeComponent() this.ColecoUseSGMMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.N64SubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.N64PluginSettingsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.Ares64SubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.Ares64SettingsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.N64ControllerSettingsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.toolStripSeparator23 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.N64CircularAnalogRangeMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.Ares64CircularAnalogRangeMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.MupenStyleLagMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.N64ExpansionSlotMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.Ares64SubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.Ares64SettingsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.Ares64CircularAnalogRangeMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.GBLSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.GBLsettingsToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.AppleSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -372,7 +373,7 @@ private void InitializeComponent() this.ShowMenuContextMenuSeparator = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.ShowMenuContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.timerMouseIdle = new System.Windows.Forms.Timer(this.components); - this.toolStripSeparator8 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); + this.toolStripSeparator25 = new System.Windows.Forms.ToolStripSeparator(); this.MainformMenu.SuspendLayout(); this.MainStatusBar.SuspendLayout(); this.MainFormContextMenu.SuspendLayout(); @@ -381,28 +382,28 @@ private void InitializeComponent() // MainformMenu // this.MainformMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.FileSubMenu, - this.EmulationSubMenu, - this.ViewSubMenu, - this.ConfigSubMenu, - this.ToolsSubMenu, - this.NESSubMenu, - this.TI83SubMenu, - this.A7800SubMenu, - this.GBSubMenu, - this.PSXSubMenu, - this.SNESSubMenu, - this.ColecoSubMenu, - this.N64SubMenu, - this.Ares64SubMenu, - this.GBLSubMenu, - this.AppleSubMenu, - this.C64SubMenu, - this.IntvSubMenu, - this.zXSpectrumToolStripMenuItem, - this.GenericCoreSubMenu, - this.amstradCPCToolStripMenuItem, - this.HelpSubMenu}); + this.FileSubMenu, + this.EmulationSubMenu, + this.ViewSubMenu, + this.ConfigSubMenu, + this.ToolsSubMenu, + this.NESSubMenu, + this.TI83SubMenu, + this.A7800SubMenu, + this.GBSubMenu, + this.PSXSubMenu, + this.SNESSubMenu, + this.ColecoSubMenu, + this.N64SubMenu, + this.Ares64SubMenu, + this.GBLSubMenu, + this.AppleSubMenu, + this.C64SubMenu, + this.IntvSubMenu, + this.zXSpectrumToolStripMenuItem, + this.GenericCoreSubMenu, + this.amstradCPCToolStripMenuItem, + this.HelpSubMenu}); this.MainformMenu.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.Flow; this.MainformMenu.TabIndex = 0; this.MainformMenu.MenuActivate += new System.EventHandler(this.MainformMenu_MenuActivate); @@ -411,21 +412,21 @@ private void InitializeComponent() // FileSubMenu // this.FileSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.OpenRomMenuItem, - this.RecentRomSubMenu, - this.OpenAdvancedMenuItem, - this.CloseRomMenuItem, - this.toolStripMenuItem1, - this.SaveStateSubMenu, - this.LoadStateSubMenu, - this.SaveSlotSubMenu, - this.SaveRAMSubMenu, - this.toolStripMenuItem2, - this.MovieSubMenu, - this.AVSubMenu, - this.ScreenshotSubMenu, - this.toolStripSeparator4, - this.ExitMenuItem}); + this.OpenRomMenuItem, + this.RecentRomSubMenu, + this.OpenAdvancedMenuItem, + this.CloseRomMenuItem, + this.toolStripMenuItem1, + this.SaveStateSubMenu, + this.LoadStateSubMenu, + this.SaveSlotSubMenu, + this.SaveRAMSubMenu, + this.toolStripMenuItem2, + this.MovieSubMenu, + this.AVSubMenu, + this.ScreenshotSubMenu, + this.toolStripSeparator4, + this.ExitMenuItem}); this.FileSubMenu.Text = "&File"; this.FileSubMenu.DropDownOpened += new System.EventHandler(this.FileSubMenu_DropDownOpened); // @@ -437,7 +438,7 @@ private void InitializeComponent() // RecentRomSubMenu // this.RecentRomSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripSeparator3}); + this.toolStripSeparator3}); this.RecentRomSubMenu.Text = "&Recent ROM"; this.RecentRomSubMenu.DropDownOpened += new System.EventHandler(this.RecentRomMenuItem_DropDownOpened); // @@ -454,20 +455,20 @@ private void InitializeComponent() // SaveStateSubMenu // this.SaveStateSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.SaveState1MenuItem, - this.SaveState2MenuItem, - this.SaveState3MenuItem, - this.SaveState4MenuItem, - this.SaveState5MenuItem, - this.SaveState6MenuItem, - this.SaveState7MenuItem, - this.SaveState8MenuItem, - this.SaveState9MenuItem, - this.SaveState0MenuItem, - this.toolStripSeparator6, - this.SaveNamedStateMenuItem, - this.toolStripSeparator24, - this.AutosaveLastSlotMenuItem}); + this.SaveState1MenuItem, + this.SaveState2MenuItem, + this.SaveState3MenuItem, + this.SaveState4MenuItem, + this.SaveState5MenuItem, + this.SaveState6MenuItem, + this.SaveState7MenuItem, + this.SaveState8MenuItem, + this.SaveState9MenuItem, + this.SaveState0MenuItem, + this.toolStripSeparator6, + this.SaveNamedStateMenuItem, + this.toolStripSeparator24, + this.AutosaveLastSlotMenuItem}); this.SaveStateSubMenu.Text = "&Save State"; this.SaveStateSubMenu.DropDownOpened += new System.EventHandler(this.SaveStateSubMenu_DropDownOpened); // @@ -528,27 +529,26 @@ private void InitializeComponent() // // AutosaveLastSlotMenuItem // - this.AutosaveLastSlotMenuItem.Name = "AutosaveLastSlotMenuItem"; this.AutosaveLastSlotMenuItem.Text = "Autosave Last Slot"; this.AutosaveLastSlotMenuItem.Click += new System.EventHandler(this.AutosaveLastSlotMenuItem_Click); // // LoadStateSubMenu // this.LoadStateSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.LoadState1MenuItem, - this.LoadState2MenuItem, - this.LoadState3MenuItem, - this.LoadState4MenuItem, - this.LoadState5MenuItem, - this.LoadState6MenuItem, - this.LoadState7MenuItem, - this.LoadState8MenuItem, - this.LoadState9MenuItem, - this.LoadState0MenuItem, - this.toolStripSeparator7, - this.LoadNamedStateMenuItem, - this.toolStripSeparator21, - this.AutoloadLastSlotMenuItem}); + this.LoadState1MenuItem, + this.LoadState2MenuItem, + this.LoadState3MenuItem, + this.LoadState4MenuItem, + this.LoadState5MenuItem, + this.LoadState6MenuItem, + this.LoadState7MenuItem, + this.LoadState8MenuItem, + this.LoadState9MenuItem, + this.LoadState0MenuItem, + this.toolStripSeparator7, + this.LoadNamedStateMenuItem, + this.toolStripSeparator21, + this.AutoloadLastSlotMenuItem}); this.LoadStateSubMenu.Text = "&Load State"; this.LoadStateSubMenu.DropDownOpened += new System.EventHandler(this.LoadStateSubMenu_DropDownOpened); // @@ -615,29 +615,24 @@ private void InitializeComponent() // SaveSlotSubMenu // this.SaveSlotSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.SelectSlot1MenuItem, - this.SelectSlot2MenuItem, - this.SelectSlot3MenuItem, - this.SelectSlot4MenuItem, - this.SelectSlot5MenuItem, - this.SelectSlot6MenuItem, - this.SelectSlot7MenuItem, - this.SelectSlot8MenuItem, - this.SelectSlot9MenuItem, - this.SelectSlot0MenuItem, - this.PreviousSlotMenuItem, - this.NextSlotMenuItem, - this.toolStripSeparator5, - this.SaveToCurrentSlotMenuItem, - this.LoadCurrentSlotMenuItem}); + this.SelectSlot1MenuItem, + this.SelectSlot2MenuItem, + this.SelectSlot3MenuItem, + this.SelectSlot4MenuItem, + this.SelectSlot5MenuItem, + this.SelectSlot6MenuItem, + this.SelectSlot7MenuItem, + this.SelectSlot8MenuItem, + this.SelectSlot9MenuItem, + this.SelectSlot0MenuItem, + this.PreviousSlotMenuItem, + this.NextSlotMenuItem, + this.toolStripSeparator5, + this.SaveToCurrentSlotMenuItem, + this.LoadCurrentSlotMenuItem}); this.SaveSlotSubMenu.Text = "Save S&lot"; this.SaveSlotSubMenu.DropDownOpened += new System.EventHandler(this.SaveSlotSubMenu_DropDownOpened); // - // SelectSlot0MenuItem - // - this.SelectSlot0MenuItem.Text = "Select Slot 10"; - this.SelectSlot0MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); - // // SelectSlot1MenuItem // this.SelectSlot1MenuItem.Text = "Select Slot 1"; @@ -683,6 +678,11 @@ private void InitializeComponent() this.SelectSlot9MenuItem.Text = "Select Slot 9"; this.SelectSlot9MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); // + // SelectSlot0MenuItem + // + this.SelectSlot0MenuItem.Text = "Select Slot 10"; + this.SelectSlot0MenuItem.Click += new System.EventHandler(this.SelectSlotMenuItems_Click); + // // PreviousSlotMenuItem // this.PreviousSlotMenuItem.Text = "Previous Slot"; @@ -706,7 +706,7 @@ private void InitializeComponent() // SaveRAMSubMenu // this.SaveRAMSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.FlushSaveRAMMenuItem}); + this.FlushSaveRAMMenuItem}); this.SaveRAMSubMenu.Text = "Save &RAM"; this.SaveRAMSubMenu.DropDownOpened += new System.EventHandler(this.SaveRamSubMenu_DropDownOpened); // @@ -718,21 +718,22 @@ private void InitializeComponent() // MovieSubMenu // this.MovieSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ReadonlyMenuItem, - this.toolStripSeparator15, - this.RecentMovieSubMenu, - this.RecordMovieMenuItem, - this.PlayMovieMenuItem, - this.StopMovieMenuItem, - this.PlayFromBeginningMenuItem, - this.ImportMoviesMenuItem, - this.SaveMovieMenuItem, - this.SaveMovieAsMenuItem, - this.StopMovieWithoutSavingMenuItem, - this.toolStripSeparator14, - this.AutomaticallyBackupMoviesMenuItem, - this.FullMovieLoadstatesMenuItem, - this.MovieEndSubMenu}); + this.ReadonlyMenuItem, + this.toolStripSeparator15, + this.RecentMovieSubMenu, + this.RecordMovieMenuItem, + this.PlayMovieMenuItem, + this.StopMovieMenuItem, + this.PlayFromBeginningMenuItem, + this.SaveMovieMenuItem, + this.SaveMovieAsMenuItem, + this.StopMovieWithoutSavingMenuItem, + this.toolStripSeparator25, + this.ImportMoviesMenuItem, + this.toolStripSeparator14, + this.AutomaticallyBackupMoviesMenuItem, + this.FullMovieLoadstatesMenuItem, + this.MovieEndSubMenu}); this.MovieSubMenu.Text = "&Movie"; this.MovieSubMenu.DropDownOpened += new System.EventHandler(this.MovieSubMenu_DropDownOpened); // @@ -744,7 +745,7 @@ private void InitializeComponent() // RecentMovieSubMenu // this.RecentMovieSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripSeparator16}); + this.toolStripSeparator16}); this.RecentMovieSubMenu.Text = "Recent"; this.RecentMovieSubMenu.DropDownOpened += new System.EventHandler(this.RecentMovieSubMenu_DropDownOpened); // @@ -801,10 +802,10 @@ private void InitializeComponent() // MovieEndSubMenu // this.MovieEndSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.MovieEndFinishMenuItem, - this.MovieEndRecordMenuItem, - this.MovieEndStopMenuItem, - this.MovieEndPauseMenuItem}); + this.MovieEndFinishMenuItem, + this.MovieEndRecordMenuItem, + this.MovieEndStopMenuItem, + this.MovieEndPauseMenuItem}); this.MovieEndSubMenu.Text = "On Movie End"; this.MovieEndSubMenu.DropDownOpened += new System.EventHandler(this.MovieEndSubMenu_DropDownOpened); // @@ -831,13 +832,13 @@ private void InitializeComponent() // AVSubMenu // this.AVSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.RecordAVMenuItem, - this.ConfigAndRecordAVMenuItem, - this.StopAVIMenuItem, - this.toolStripSeparator19, - this.CaptureOSDMenuItem, - this.CaptureLuaMenuItem, - this.SynclessRecordingMenuItem}); + this.RecordAVMenuItem, + this.ConfigAndRecordAVMenuItem, + this.StopAVIMenuItem, + this.toolStripSeparator19, + this.CaptureOSDMenuItem, + this.CaptureLuaMenuItem, + this.SynclessRecordingMenuItem}); this.AVSubMenu.Text = "&AVI/WAV"; this.AVSubMenu.DropDownOpened += new System.EventHandler(this.AVSubMenu_DropDownOpened); // @@ -866,7 +867,7 @@ private void InitializeComponent() // this.CaptureLuaMenuItem.CheckOnClick = true; this.CaptureLuaMenuItem.Name = "CaptureLuaMenuItem"; - this.CaptureLuaMenuItem.Size = new System.Drawing.Size(225, 22); + this.CaptureLuaMenuItem.Size = new System.Drawing.Size(232, 22); this.CaptureLuaMenuItem.Text = "Capture Lua"; this.CaptureLuaMenuItem.Click += new System.EventHandler(this.CaptureLuaMenuItem_Click); // @@ -877,12 +878,12 @@ private void InitializeComponent() // ScreenshotSubMenu // this.ScreenshotSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ScreenshotMenuItem, - this.ScreenshotAsMenuItem, - this.ScreenshotClipboardMenuItem, - this.ScreenshotClientClipboardMenuItem, - this.toolStripSeparator20, - this.ScreenshotCaptureOSDMenuItem1}); + this.ScreenshotMenuItem, + this.ScreenshotAsMenuItem, + this.ScreenshotClipboardMenuItem, + this.ScreenshotClientClipboardMenuItem, + this.toolStripSeparator20, + this.ScreenshotCaptureOSDMenuItem1}); this.ScreenshotSubMenu.Text = "Scree&nshot"; this.ScreenshotSubMenu.DropDownOpening += new System.EventHandler(this.ScreenshotSubMenu_DropDownOpening); // @@ -920,13 +921,13 @@ private void InitializeComponent() // EmulationSubMenu // this.EmulationSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.PauseMenuItem, - this.RebootCoreMenuItem, - this.toolStripSeparator1, - this.SoftResetMenuItem, - this.HardResetMenuItem, - this.EmulatorMenuSeparator2, - this.LoadedCoreNameMenuItem}); + this.PauseMenuItem, + this.RebootCoreMenuItem, + this.toolStripSeparator1, + this.SoftResetMenuItem, + this.HardResetMenuItem, + this.EmulatorMenuSeparator2, + this.LoadedCoreNameMenuItem}); this.EmulationSubMenu.Text = "&Emulation"; this.EmulationSubMenu.DropDownOpened += new System.EventHandler(this.EmulationMenuItem_DropDownOpened); // @@ -958,20 +959,20 @@ private void InitializeComponent() // ViewSubMenu // this.ViewSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.WindowSizeSubMenu, - this.SwitchToFullscreenMenuItem, - this.toolStripSeparator2, - this.DisplayFPSMenuItem, - this.DisplayFrameCounterMenuItem, - this.DisplayLagCounterMenuItem, - this.DisplayInputMenuItem, - this.DisplayRerecordCountMenuItem, - this.DisplaySubtitlesMenuItem, - this.toolStripMenuItem4, - this.DisplayStatusBarMenuItem, - this.DisplayMessagesMenuItem, - this.toolStripSeparator8, - this.DisplayLogWindowMenuItem}); + this.WindowSizeSubMenu, + this.SwitchToFullscreenMenuItem, + this.toolStripSeparator2, + this.DisplayFPSMenuItem, + this.DisplayFrameCounterMenuItem, + this.DisplayLagCounterMenuItem, + this.DisplayInputMenuItem, + this.DisplayRerecordCountMenuItem, + this.DisplaySubtitlesMenuItem, + this.toolStripMenuItem4, + this.DisplayStatusBarMenuItem, + this.DisplayMessagesMenuItem, + this.toolStripSeparator8, + this.DisplayLogWindowMenuItem}); this.ViewSubMenu.Text = "&View"; this.ViewSubMenu.DropDownOpened += new System.EventHandler(this.ViewSubMenu_DropDownOpened); // @@ -1033,27 +1034,27 @@ private void InitializeComponent() // ConfigSubMenu // this.ConfigSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ControllersMenuItem, - this.HotkeysMenuItem, - this.DisplayConfigMenuItem, - this.SoundMenuItem, - this.PathsMenuItem, - this.FirmwaresMenuItem, - this.MessagesMenuItem, - this.AutofireMenuItem, - this.RewindOptionsMenuItem, - this.extensionsToolStripMenuItem, - this.ClientOptionsMenuItem, - this.ProfilesMenuItem, - this.toolStripSeparator9, - this.SpeedSkipSubMenu, - this.KeyPrioritySubMenu, - this.CoresSubMenu, - this.toolStripSeparator10, - this.SaveConfigMenuItem, - this.SaveConfigAsMenuItem, - this.LoadConfigMenuItem, - this.LoadConfigFromMenuItem}); + this.ControllersMenuItem, + this.HotkeysMenuItem, + this.DisplayConfigMenuItem, + this.SoundMenuItem, + this.PathsMenuItem, + this.FirmwaresMenuItem, + this.MessagesMenuItem, + this.AutofireMenuItem, + this.RewindOptionsMenuItem, + this.extensionsToolStripMenuItem, + this.ClientOptionsMenuItem, + this.ProfilesMenuItem, + this.toolStripSeparator9, + this.SpeedSkipSubMenu, + this.KeyPrioritySubMenu, + this.CoresSubMenu, + this.toolStripSeparator10, + this.SaveConfigMenuItem, + this.SaveConfigAsMenuItem, + this.LoadConfigMenuItem, + this.LoadConfigFromMenuItem}); this.ConfigSubMenu.Text = "&Config"; this.ConfigSubMenu.DropDownOpened += new System.EventHandler(this.ConfigSubMenu_DropDownOpened); // @@ -1120,23 +1121,23 @@ private void InitializeComponent() // SpeedSkipSubMenu // this.SpeedSkipSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ClockThrottleMenuItem, - this.AudioThrottleMenuItem, - this.VsyncThrottleMenuItem, - this.toolStripSeparator27, - this.VsyncEnabledMenuItem, - this.toolStripMenuItem3, - this.miUnthrottled, - this.MinimizeSkippingMenuItem, - this.NeverSkipMenuItem, - this.toolStripMenuItem17, - this.toolStripMenuItem5, - this.Speed50MenuItem, - this.Speed75MenuItem, - this.Speed100MenuItem, - this.Speed150MenuItem, - this.Speed200MenuItem, - this.Speed400MenuItem}); + this.ClockThrottleMenuItem, + this.AudioThrottleMenuItem, + this.VsyncThrottleMenuItem, + this.toolStripSeparator27, + this.VsyncEnabledMenuItem, + this.toolStripMenuItem3, + this.miUnthrottled, + this.MinimizeSkippingMenuItem, + this.NeverSkipMenuItem, + this.toolStripMenuItem17, + this.toolStripMenuItem5, + this.Speed50MenuItem, + this.Speed75MenuItem, + this.Speed100MenuItem, + this.Speed150MenuItem, + this.Speed200MenuItem, + this.Speed400MenuItem}); this.SpeedSkipSubMenu.Text = "Speed/Skip"; this.SpeedSkipSubMenu.DropDownOpened += new System.EventHandler(this.FrameSkipMenuItem_DropDownOpened); // @@ -1178,15 +1179,15 @@ private void InitializeComponent() // toolStripMenuItem17 // this.toolStripMenuItem17.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.Frameskip1MenuItem, - this.Frameskip2MenuItem, - this.Frameskip3MenuItem, - this.Frameskip4MenuItem, - this.Frameskip5MenuItem, - this.Frameskip6MenuItem, - this.Frameskip7MenuItem, - this.Frameskip8MenuItem, - this.Frameskip9MenuItem}); + this.Frameskip1MenuItem, + this.Frameskip2MenuItem, + this.Frameskip3MenuItem, + this.Frameskip4MenuItem, + this.Frameskip5MenuItem, + this.Frameskip6MenuItem, + this.Frameskip7MenuItem, + this.Frameskip8MenuItem, + this.Frameskip9MenuItem}); this.toolStripMenuItem17.Text = "Skip 1..9"; // // Frameskip1MenuItem @@ -1267,9 +1268,9 @@ private void InitializeComponent() // KeyPrioritySubMenu // this.KeyPrioritySubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.BothHkAndControllerMenuItem, - this.InputOverHkMenuItem, - this.HkOverInputMenuItem}); + this.BothHkAndControllerMenuItem, + this.InputOverHkMenuItem, + this.HkOverInputMenuItem}); this.KeyPrioritySubMenu.Text = "Key Priority"; this.KeyPrioritySubMenu.DropDownOpened += new System.EventHandler(this.KeyPriorityMenuItem_DropDownOpened); // @@ -1315,27 +1316,27 @@ private void InitializeComponent() // ToolsSubMenu // this.ToolsSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ToolBoxMenuItem, - this.toolStripSeparator12, - this.RamWatchMenuItem, - this.RamSearchMenuItem, - this.LuaConsoleMenuItem, - this.TAStudioMenuItem, - this.HexEditorMenuItem, - this.TraceLoggerMenuItem, - this.DebuggerMenuItem, - this.CodeDataLoggerMenuItem, - this.MacroToolMenuItem, - this.VirtualPadMenuItem, - this.BasicBotMenuItem, - this.toolStripSeparator11, - this.CheatsMenuItem, - this.GameSharkConverterMenuItem, - this.toolStripSeparator29, - this.MultiDiskBundlerFileMenuItem, - this.BatchRunnerMenuItem, - this.ExternalToolMenuItem, - this.RetroAchievementsMenuItem}); + this.ToolBoxMenuItem, + this.toolStripSeparator12, + this.RamWatchMenuItem, + this.RamSearchMenuItem, + this.LuaConsoleMenuItem, + this.TAStudioMenuItem, + this.HexEditorMenuItem, + this.TraceLoggerMenuItem, + this.DebuggerMenuItem, + this.CodeDataLoggerMenuItem, + this.MacroToolMenuItem, + this.VirtualPadMenuItem, + this.BasicBotMenuItem, + this.toolStripSeparator11, + this.CheatsMenuItem, + this.GameSharkConverterMenuItem, + this.toolStripSeparator29, + this.MultiDiskBundlerFileMenuItem, + this.BatchRunnerMenuItem, + this.ExternalToolMenuItem, + this.RetroAchievementsMenuItem}); this.ToolsSubMenu.Text = "&Tools"; this.ToolsSubMenu.DropDownOpened += new System.EventHandler(this.ToolsSubMenu_DropDownOpened); // @@ -1399,17 +1400,6 @@ private void InitializeComponent() this.BasicBotMenuItem.Text = "Basic Bot"; this.BasicBotMenuItem.Click += new System.EventHandler(this.BasicBotMenuItem_Click); // - // RetroAchievementsMenuItem - // - this.RetroAchievementsMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - StartRetroAchievementsMenuItem}); - this.RetroAchievementsMenuItem.Text = "&RetroAchievements"; - // - // StartRetroAchievementsMenuItem - // - this.StartRetroAchievementsMenuItem.Text = "&Start RetroAchievements"; - this.StartRetroAchievementsMenuItem.Click += new System.EventHandler(this.StartRetroAchievementsMenuItem_Click); - // // CheatsMenuItem // this.CheatsMenuItem.Text = "Cheats"; @@ -1425,10 +1415,16 @@ private void InitializeComponent() this.MultiDiskBundlerFileMenuItem.Text = "Multi-disk Bundler"; this.MultiDiskBundlerFileMenuItem.Click += new System.EventHandler(this.MultidiskBundlerMenuItem_Click); // + // BatchRunnerMenuItem + // + this.BatchRunnerMenuItem.Text = "Batch Runner..."; + this.BatchRunnerMenuItem.Visible = false; + this.BatchRunnerMenuItem.Click += new System.EventHandler(this.BatchRunnerMenuItem_Click); + // // ExternalToolMenuItem // this.ExternalToolMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.dummyExternalTool}); + this.dummyExternalTool}); this.ExternalToolMenuItem.Text = "External Tool"; this.ExternalToolMenuItem.DropDownOpening += new System.EventHandler(this.ExternalToolMenuItem_DropDownOpening); // @@ -1436,28 +1432,33 @@ private void InitializeComponent() // this.dummyExternalTool.Text = "None"; // - // BatchRunnerMenuItem + // RetroAchievementsMenuItem // - this.BatchRunnerMenuItem.Text = "Batch Runner..."; - this.BatchRunnerMenuItem.Visible = false; - this.BatchRunnerMenuItem.Click += new System.EventHandler(this.BatchRunnerMenuItem_Click); + this.RetroAchievementsMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.StartRetroAchievementsMenuItem}); + this.RetroAchievementsMenuItem.Text = "&RetroAchievements"; + // + // StartRetroAchievementsMenuItem + // + this.StartRetroAchievementsMenuItem.Text = "&Start RetroAchievements"; + this.StartRetroAchievementsMenuItem.Click += new System.EventHandler(this.StartRetroAchievementsMenuItem_Click); // // NESSubMenu // this.NESSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.NESPPUViewerMenuItem, - this.NESNametableViewerMenuItem, - this.MusicRipperMenuItem, - this.toolStripSeparator17, - this.NesControllerSettingsMenuItem, - this.NESGraphicSettingsMenuItem, - this.NESSoundChannelsMenuItem, - this.VSSettingsMenuItem, - this.MovieSettingsMenuItem, - this.toolStripSeparator22, - this.FDSControlsMenuItem, - this.VSControlsMenuItem, - this.BarcodeReaderMenuItem}); + this.NESPPUViewerMenuItem, + this.NESNametableViewerMenuItem, + this.MusicRipperMenuItem, + this.toolStripSeparator17, + this.NesControllerSettingsMenuItem, + this.NESGraphicSettingsMenuItem, + this.NESSoundChannelsMenuItem, + this.VSSettingsMenuItem, + this.MovieSettingsMenuItem, + this.toolStripSeparator22, + this.FDSControlsMenuItem, + this.VSControlsMenuItem, + this.BarcodeReaderMenuItem}); this.NESSubMenu.Text = "&NES"; this.NESSubMenu.DropDownOpened += new System.EventHandler(this.NesSubMenu_DropDownOpened); // @@ -1504,7 +1505,7 @@ private void InitializeComponent() // FDSControlsMenuItem // this.FDSControlsMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.FdsEjectDiskMenuItem}); + this.FdsEjectDiskMenuItem}); this.FDSControlsMenuItem.Text = "FDS Controls"; this.FDSControlsMenuItem.DropDownOpened += new System.EventHandler(this.FdsControlsMenuItem_DropDownOpened); // @@ -1516,9 +1517,9 @@ private void InitializeComponent() // VSControlsMenuItem // this.VSControlsMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.VSInsertCoinP1MenuItem, - this.VSInsertCoinP2MenuItem, - this.VSServiceSwitchMenuItem}); + this.VSInsertCoinP1MenuItem, + this.VSInsertCoinP2MenuItem, + this.VSServiceSwitchMenuItem}); this.VSControlsMenuItem.Text = "VS Controls"; // // VSInsertCoinP1MenuItem @@ -1544,10 +1545,10 @@ private void InitializeComponent() // TI83SubMenu // this.TI83SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.KeypadMenuItem, - this.LoadTIFileMenuItem, - this.toolStripSeparator13, - this.paletteToolStripMenuItem}); + this.KeypadMenuItem, + this.LoadTIFileMenuItem, + this.toolStripSeparator13, + this.paletteToolStripMenuItem}); this.TI83SubMenu.Text = "TI83"; // // KeypadMenuItem @@ -1568,8 +1569,8 @@ private void InitializeComponent() // A7800SubMenu // this.A7800SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.A7800ControllerSettingsMenuItem, - this.A7800FilterSettingsMenuItem}); + this.A7800ControllerSettingsMenuItem, + this.A7800FilterSettingsMenuItem}); this.A7800SubMenu.Text = "&A7800"; this.A7800SubMenu.DropDownOpened += new System.EventHandler(this.A7800SubMenu_DropDownOpened); // @@ -1586,11 +1587,11 @@ private void InitializeComponent() // GBSubMenu // this.GBSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.GBcoreSettingsToolStripMenuItem, - this.SameBoyColorChooserMenuItem, - this.toolStripSeparator28, - this.GBGPUViewerMenuItem, - this.GBPrinterViewerMenuItem}); + this.GBcoreSettingsToolStripMenuItem, + this.SameBoyColorChooserMenuItem, + this.toolStripSeparator28, + this.GBGPUViewerMenuItem, + this.GBPrinterViewerMenuItem}); this.GBSubMenu.Text = "&GB"; // // GBcoreSettingsToolStripMenuItem @@ -1616,10 +1617,10 @@ private void InitializeComponent() // PSXSubMenu // this.PSXSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.PSXControllerSettingsMenuItem, - this.PSXOptionsMenuItem, - this.PSXDiscControlsMenuItem, - this.PSXHashDiscsToolStripMenuItem}); + this.PSXControllerSettingsMenuItem, + this.PSXOptionsMenuItem, + this.PSXDiscControlsMenuItem, + this.PSXHashDiscsToolStripMenuItem}); this.PSXSubMenu.Text = "PSX"; this.PSXSubMenu.DropDownOpened += new System.EventHandler(this.PsxSubMenu_DropDownOpened); // @@ -1646,10 +1647,10 @@ private void InitializeComponent() // SNESSubMenu // this.SNESSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.SNESControllerConfigurationMenuItem, - this.toolStripSeparator18, - this.SnesGfxDebuggerMenuItem, - this.SnesOptionsMenuItem}); + this.SNESControllerConfigurationMenuItem, + this.toolStripSeparator18, + this.SnesGfxDebuggerMenuItem, + this.SnesOptionsMenuItem}); this.SNESSubMenu.Text = "&SNES"; this.SNESSubMenu.DropDownOpened += new System.EventHandler(this.SnesSubMenu_DropDownOpened); // @@ -1671,10 +1672,10 @@ private void InitializeComponent() // ColecoSubMenu // this.ColecoSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ColecoControllerSettingsMenuItem, - this.toolStripSeparator35, - this.ColecoSkipBiosMenuItem, - this.ColecoUseSGMMenuItem}); + this.ColecoControllerSettingsMenuItem, + this.toolStripSeparator35, + this.ColecoSkipBiosMenuItem, + this.ColecoUseSGMMenuItem}); this.ColecoSubMenu.Text = "&Coleco"; this.ColecoSubMenu.DropDownOpened += new System.EventHandler(this.ColecoSubMenu_DropDownOpened); // @@ -1696,12 +1697,12 @@ private void InitializeComponent() // N64SubMenu // this.N64SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.N64PluginSettingsMenuItem, - this.N64ControllerSettingsMenuItem, - this.toolStripSeparator23, - this.N64CircularAnalogRangeMenuItem, - this.MupenStyleLagMenuItem, - this.N64ExpansionSlotMenuItem}); + this.N64PluginSettingsMenuItem, + this.N64ControllerSettingsMenuItem, + this.toolStripSeparator23, + this.N64CircularAnalogRangeMenuItem, + this.MupenStyleLagMenuItem, + this.N64ExpansionSlotMenuItem}); this.N64SubMenu.Text = "N64"; this.N64SubMenu.DropDownOpened += new System.EventHandler(this.N64SubMenu_DropDownOpened); // @@ -1733,8 +1734,8 @@ private void InitializeComponent() // Ares64SubMenu // this.Ares64SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.Ares64SettingsMenuItem, - this.Ares64CircularAnalogRangeMenuItem}); + this.Ares64SettingsMenuItem, + this.Ares64CircularAnalogRangeMenuItem}); this.Ares64SubMenu.Text = "N64"; this.Ares64SubMenu.DropDownOpened += new System.EventHandler(this.Ares64SubMenu_DropDownOpened); // @@ -1751,7 +1752,7 @@ private void InitializeComponent() // GBLSubMenu // this.GBLSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.GBLsettingsToolStripMenuItem}); + this.GBLsettingsToolStripMenuItem}); this.GBLSubMenu.Text = "&GB Link"; // // GBLsettingsToolStripMenuItem @@ -1762,15 +1763,15 @@ private void InitializeComponent() // AppleSubMenu // this.AppleSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.AppleDisksSubMenu, - this.settingsToolStripMenuItem1}); + this.AppleDisksSubMenu, + this.settingsToolStripMenuItem1}); this.AppleSubMenu.Text = "Apple"; this.AppleSubMenu.DropDownOpened += new System.EventHandler(this.AppleSubMenu_DropDownOpened); // // AppleDisksSubMenu // this.AppleDisksSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripSeparator31}); + this.toolStripSeparator31}); this.AppleDisksSubMenu.Text = "Disks"; this.AppleDisksSubMenu.DropDownOpened += new System.EventHandler(this.AppleDisksSubMenu_DropDownOpened); // @@ -1782,15 +1783,15 @@ private void InitializeComponent() // C64SubMenu // this.C64SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.C64DisksSubMenu, - this.C64SettingsMenuItem}); + this.C64DisksSubMenu, + this.C64SettingsMenuItem}); this.C64SubMenu.Text = "&C64"; this.C64SubMenu.DropDownOpened += new System.EventHandler(this.C64SubMenu_DropDownOpened); // // C64DisksSubMenu // this.C64DisksSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripSeparator36}); + this.toolStripSeparator36}); this.C64DisksSubMenu.Text = "Disks"; this.C64DisksSubMenu.DropDownOpened += new System.EventHandler(this.C64DisksSubMenu_DropDownOpened); // @@ -1802,7 +1803,7 @@ private void InitializeComponent() // IntvSubMenu // this.IntvSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.IntVControllerSettingsMenuItem}); + this.IntVControllerSettingsMenuItem}); this.IntvSubMenu.Text = "&Intv"; this.IntvSubMenu.DropDownOpened += new System.EventHandler(this.IntVSubMenu_DropDownOpened); // @@ -1814,11 +1815,11 @@ private void InitializeComponent() // zXSpectrumToolStripMenuItem // this.zXSpectrumToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ZXSpectrumCoreEmulationSettingsMenuItem, - this.ZXSpectrumControllerConfigurationMenuItem, - this.ZXSpectrumAudioSettingsMenuItem, - this.ZXSpectrumNonSyncSettingsMenuItem, - this.ZXSpectrumMediaMenuItem}); + this.ZXSpectrumCoreEmulationSettingsMenuItem, + this.ZXSpectrumControllerConfigurationMenuItem, + this.ZXSpectrumAudioSettingsMenuItem, + this.ZXSpectrumNonSyncSettingsMenuItem, + this.ZXSpectrumMediaMenuItem}); this.zXSpectrumToolStripMenuItem.Text = "ZX Spectrum"; // // ZXSpectrumCoreEmulationSettingsMenuItem @@ -1844,16 +1845,16 @@ private void InitializeComponent() // ZXSpectrumMediaMenuItem // this.ZXSpectrumMediaMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ZXSpectrumTapesSubMenu, - this.ZXSpectrumDisksSubMenu, - this.ZXSpectrumExportSnapshotMenuItemMenuItem}); + this.ZXSpectrumTapesSubMenu, + this.ZXSpectrumDisksSubMenu, + this.ZXSpectrumExportSnapshotMenuItemMenuItem}); this.ZXSpectrumMediaMenuItem.Text = "Media"; this.ZXSpectrumMediaMenuItem.DropDownOpened += new System.EventHandler(this.ZXSpectrumMediaMenuItem_DropDownOpened); // // ZXSpectrumTapesSubMenu // this.ZXSpectrumTapesSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.zxt1ToolStripMenuItem}); + this.zxt1ToolStripMenuItem}); this.ZXSpectrumTapesSubMenu.Text = "Tapes"; this.ZXSpectrumTapesSubMenu.DropDownOpened += new System.EventHandler(this.ZXSpectrumTapesSubMenu_DropDownOpened); // @@ -1864,7 +1865,7 @@ private void InitializeComponent() // ZXSpectrumDisksSubMenu // this.ZXSpectrumDisksSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.zxt2ToolStripMenuItem}); + this.zxt2ToolStripMenuItem}); this.ZXSpectrumDisksSubMenu.Text = "Disks"; this.ZXSpectrumDisksSubMenu.DropDownOpened += new System.EventHandler(this.ZXSpectrumDisksSubMenu_DropDownOpened); // @@ -1884,10 +1885,10 @@ private void InitializeComponent() // amstradCPCToolStripMenuItem // this.amstradCPCToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.amstradCPCCoreEmulationSettingsToolStripMenuItem, - this.AmstradCPCAudioSettingsToolStripMenuItem, - this.AmstradCPCNonSyncSettingsToolStripMenuItem, - this.AmstradCPCMediaToolStripMenuItem}); + this.amstradCPCCoreEmulationSettingsToolStripMenuItem, + this.AmstradCPCAudioSettingsToolStripMenuItem, + this.AmstradCPCNonSyncSettingsToolStripMenuItem, + this.AmstradCPCMediaToolStripMenuItem}); this.amstradCPCToolStripMenuItem.Text = "Amstrad CPC"; // // amstradCPCCoreEmulationSettingsToolStripMenuItem @@ -1908,15 +1909,15 @@ private void InitializeComponent() // AmstradCPCMediaToolStripMenuItem // this.AmstradCPCMediaToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.AmstradCPCTapesSubMenu, - this.AmstradCPCDisksSubMenu}); + this.AmstradCPCTapesSubMenu, + this.AmstradCPCDisksSubMenu}); this.AmstradCPCMediaToolStripMenuItem.Text = "Media"; this.AmstradCPCMediaToolStripMenuItem.DropDownOpened += new System.EventHandler(this.AmstradCpcMediaMenuItem_DropDownOpened); // // AmstradCPCTapesSubMenu // this.AmstradCPCTapesSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.cpct1ToolStripMenuItem}); + this.cpct1ToolStripMenuItem}); this.AmstradCPCTapesSubMenu.Text = "Tapes"; this.AmstradCPCTapesSubMenu.DropDownOpened += new System.EventHandler(this.AmstradCpcTapesSubMenu_DropDownOpened); // @@ -1927,7 +1928,7 @@ private void InitializeComponent() // AmstradCPCDisksSubMenu // this.AmstradCPCDisksSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.cpcd1ToolStripMenuItem}); + this.cpcd1ToolStripMenuItem}); this.AmstradCPCDisksSubMenu.Text = "Disks"; this.AmstradCPCDisksSubMenu.DropDownOpened += new System.EventHandler(this.AmstradCpcDisksSubMenu_DropDownOpened); // @@ -1938,10 +1939,10 @@ private void InitializeComponent() // HelpSubMenu // this.HelpSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.OnlineHelpMenuItem, - this.ForumsMenuItem, - this.FeaturesMenuItem, - this.AboutMenuItem}); + this.OnlineHelpMenuItem, + this.ForumsMenuItem, + this.FeaturesMenuItem, + this.AboutMenuItem}); this.HelpSubMenu.Text = "&Help"; this.HelpSubMenu.DropDownOpened += new System.EventHandler(this.HelpSubMenu_DropDownOpened); // @@ -1972,30 +1973,30 @@ private void InitializeComponent() // MainStatusBar // this.MainStatusBar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.DumpStatusButton, - this.EmuStatus, - this.PlayRecordStatusButton, - this.PauseStatusButton, - this.RebootStatusBarIcon, - this.AVIStatusLabel, - this.LedLightStatusLabel, - this.SaveSlotsStatusLabel, - this.Slot1StatusButton, - this.Slot2StatusButton, - this.Slot3StatusButton, - this.Slot4StatusButton, - this.Slot5StatusButton, - this.Slot6StatusButton, - this.Slot7StatusButton, - this.Slot8StatusButton, - this.Slot9StatusButton, - this.Slot0StatusButton, - this.CheatStatusButton, - this.KeyPriorityStatusLabel, - this.CoreNameStatusBarButton, - this.ProfileFirstBootLabel, - this.LinkConnectStatusBarButton, - this.UpdateNotification}); + this.DumpStatusButton, + this.EmuStatus, + this.PlayRecordStatusButton, + this.PauseStatusButton, + this.RebootStatusBarIcon, + this.AVIStatusLabel, + this.LedLightStatusLabel, + this.SaveSlotsStatusLabel, + this.Slot1StatusButton, + this.Slot2StatusButton, + this.Slot3StatusButton, + this.Slot4StatusButton, + this.Slot5StatusButton, + this.Slot6StatusButton, + this.Slot7StatusButton, + this.Slot8StatusButton, + this.Slot9StatusButton, + this.Slot0StatusButton, + this.CheatStatusButton, + this.KeyPriorityStatusLabel, + this.CoreNameStatusBarButton, + this.ProfileFirstBootLabel, + this.LinkConnectStatusBarButton, + this.UpdateNotification}); this.MainStatusBar.Location = new System.Drawing.Point(0, 386); this.MainStatusBar.Name = "MainStatusBar"; this.MainStatusBar.ShowItemToolTips = true; @@ -2158,31 +2159,31 @@ private void InitializeComponent() // MainFormContextMenu // this.MainFormContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.OpenRomContextMenuItem, - this.LoadLastRomContextMenuItem, - this.StopAVContextMenuItem, - this.ContextSeparator_AfterROM, - this.RecordMovieContextMenuItem, - this.PlayMovieContextMenuItem, - this.RestartMovieContextMenuItem, - this.StopMovieContextMenuItem, - this.LoadLastMovieContextMenuItem, - this.BackupMovieContextMenuItem, - this.StopNoSaveContextMenuItem, - this.ViewSubtitlesContextMenuItem, - this.AddSubtitleContextMenuItem, - this.ViewCommentsContextMenuItem, - this.SaveMovieContextMenuItem, - this.SaveMovieAsContextMenuItem, - this.ContextSeparator_AfterMovie, - this.UndoSavestateContextMenuItem, - this.ContextSeparator_AfterUndo, - this.ConfigContextMenuItem, - this.ScreenshotContextMenuItem, - this.CloseRomContextMenuItem, - this.ClearSRAMContextMenuItem, - this.ShowMenuContextMenuSeparator, - this.ShowMenuContextMenuItem}); + this.OpenRomContextMenuItem, + this.LoadLastRomContextMenuItem, + this.StopAVContextMenuItem, + this.ContextSeparator_AfterROM, + this.RecordMovieContextMenuItem, + this.PlayMovieContextMenuItem, + this.RestartMovieContextMenuItem, + this.StopMovieContextMenuItem, + this.LoadLastMovieContextMenuItem, + this.BackupMovieContextMenuItem, + this.StopNoSaveContextMenuItem, + this.ViewSubtitlesContextMenuItem, + this.AddSubtitleContextMenuItem, + this.ViewCommentsContextMenuItem, + this.SaveMovieContextMenuItem, + this.SaveMovieAsContextMenuItem, + this.ContextSeparator_AfterMovie, + this.UndoSavestateContextMenuItem, + this.ContextSeparator_AfterUndo, + this.ConfigContextMenuItem, + this.ScreenshotContextMenuItem, + this.CloseRomContextMenuItem, + this.ClearSRAMContextMenuItem, + this.ShowMenuContextMenuSeparator, + this.ShowMenuContextMenuItem}); this.MainFormContextMenu.Name = "contextMenuStrip1"; this.MainFormContextMenu.Size = new System.Drawing.Size(217, 490); this.MainFormContextMenu.Closing += new System.Windows.Forms.ToolStripDropDownClosingEventHandler(this.MainFormContextMenu_Closing); @@ -2271,20 +2272,20 @@ private void InitializeComponent() // ConfigContextMenuItem // this.ConfigContextMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripMenuItem6, - this.toolStripMenuItem7, - this.toolStripMenuItem8, - this.toolStripMenuItem9, - this.toolStripMenuItem10, - this.toolStripMenuItem11, - this.toolStripMenuItem12, - this.toolStripMenuItem13, - this.toolStripMenuItem14, - this.toolStripMenuItem15, - this.customizeToolStripMenuItem, - this.toolStripSeparator30, - this.toolStripMenuItem66, - this.toolStripMenuItem67}); + this.toolStripMenuItem6, + this.toolStripMenuItem7, + this.toolStripMenuItem8, + this.toolStripMenuItem9, + this.toolStripMenuItem10, + this.toolStripMenuItem11, + this.toolStripMenuItem12, + this.toolStripMenuItem13, + this.toolStripMenuItem14, + this.toolStripMenuItem15, + this.customizeToolStripMenuItem, + this.toolStripSeparator30, + this.toolStripMenuItem66, + this.toolStripMenuItem67}); this.ConfigContextMenuItem.Text = "Config"; // // toolStripMenuItem6 @@ -2378,6 +2379,11 @@ private void InitializeComponent() this.timerMouseIdle.Interval = 2000; this.timerMouseIdle.Tick += new System.EventHandler(this.TimerMouseIdle_Tick); // + // toolStripSeparator25 + // + this.toolStripSeparator25.Name = "toolStripSeparator25"; + this.toolStripSeparator25.Size = new System.Drawing.Size(228, 6); + // // MainForm // this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; @@ -2758,7 +2764,8 @@ private void InitializeComponent() private BizHawk.WinForms.Controls.ToolStripMenuItemEx AmstradCPCNonSyncSettingsToolStripMenuItem; private BizHawk.WinForms.Controls.ToolStripSeparatorEx toolStripSeparator8; private System.Windows.Forms.ToolStripMenuItem CaptureLuaMenuItem; - private System.Windows.Forms.ToolStripMenuItem AutosaveLastSlotMenuItem; private ToolStripSeparatorEx toolStripSeparator24; + private ToolStripMenuItemEx AutosaveLastSlotMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator25; } } diff --git a/src/BizHawk.Client.EmuHawk/MainForm.Events.cs b/src/BizHawk.Client.EmuHawk/MainForm.Events.cs index 3d394ba46a8..5fb9121a172 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.Events.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.Events.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; @@ -13,59 +12,6 @@ using BizHawk.Common; using BizHawk.Common.PathExtensions; using BizHawk.Emulation.Common; -using BizHawk.Emulation.Cores; -using BizHawk.Emulation.Cores.Arcades.MAME; -using BizHawk.Emulation.Cores.Atari.A7800Hawk; -using BizHawk.Emulation.Cores.Atari.Atari2600; -using BizHawk.Emulation.Cores.Atari.Jaguar; -using BizHawk.Emulation.Cores.Atari.Lynx; -using BizHawk.Emulation.Cores.Calculators.Emu83; -using BizHawk.Emulation.Cores.Calculators.TI83; -using BizHawk.Emulation.Cores.ColecoVision; -using BizHawk.Emulation.Cores.Computers.AmstradCPC; -using BizHawk.Emulation.Cores.Computers.AppleII; -using BizHawk.Emulation.Cores.Computers.Commodore64; -using BizHawk.Emulation.Cores.Computers.MSX; -using BizHawk.Emulation.Cores.Computers.SinclairSpectrum; -using BizHawk.Emulation.Cores.Computers.TIC80; -using BizHawk.Emulation.Cores.Consoles.Belogic; -using BizHawk.Emulation.Cores.Consoles.ChannelF; -using BizHawk.Emulation.Cores.Consoles.NEC.PCE; -using BizHawk.Emulation.Cores.Consoles.NEC.PCFX; -using BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64; -using BizHawk.Emulation.Cores.Consoles.Nintendo.Faust; -using BizHawk.Emulation.Cores.Consoles.Nintendo.N3DS; -using BizHawk.Emulation.Cores.Consoles.Nintendo.NDS; -using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES; -using BizHawk.Emulation.Cores.Consoles.Nintendo.VB; -using BizHawk.Emulation.Cores.Consoles.O2Hawk; -using BizHawk.Emulation.Cores.Consoles.Sega.gpgx; -using BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive; -using BizHawk.Emulation.Cores.Consoles.Sega.Saturn; -using BizHawk.Emulation.Cores.Consoles.SNK; -using BizHawk.Emulation.Cores.Consoles.Vectrex; -using BizHawk.Emulation.Cores.Intellivision; -using BizHawk.Emulation.Cores.Libretro; -using BizHawk.Emulation.Cores.Nintendo.BSNES; -using BizHawk.Emulation.Cores.Nintendo.Gameboy; -using BizHawk.Emulation.Cores.Nintendo.GBA; -using BizHawk.Emulation.Cores.Nintendo.GBHawk; -using BizHawk.Emulation.Cores.Nintendo.GBHawkLink; -using BizHawk.Emulation.Cores.Nintendo.GBHawkLink3x; -using BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x; -using BizHawk.Emulation.Cores.Nintendo.N64; -using BizHawk.Emulation.Cores.Nintendo.NES; -using BizHawk.Emulation.Cores.Nintendo.Sameboy; -using BizHawk.Emulation.Cores.Nintendo.SNES; -using BizHawk.Emulation.Cores.Nintendo.SNES9X; -using BizHawk.Emulation.Cores.Nintendo.SubGBHawk; -using BizHawk.Emulation.Cores.Nintendo.SubNESHawk; -using BizHawk.Emulation.Cores.PCEngine; -using BizHawk.Emulation.Cores.Sega.GGHawkLink; -using BizHawk.Emulation.Cores.Sega.MasterSystem; -using BizHawk.Emulation.Cores.Sony.PSX; -using BizHawk.Emulation.Cores.Waterbox; -using BizHawk.Emulation.Cores.WonderSwan; using BizHawk.WinForms.Controls; namespace BizHawk.Client.EmuHawk @@ -82,13 +28,6 @@ public partial class MainForm AppendAllFilesEntry = false, }; - private static readonly FilesystemFilterSet TI83ProgramFilesFSFilterSet = new(new FilesystemFilter("TI-83 Program Files", new[] { "83p", "8xp" })); - - private static readonly FilesystemFilterSet ZXStateFilesFSFilterSet = new(new FilesystemFilter("ZX-State files", new[] { "szx" })) - { - AppendAllFilesEntry = false, - }; - private void FileSubMenu_DropDownOpened(object sender, EventArgs e) { SaveStateSubMenu.Enabled = @@ -99,9 +38,7 @@ private void FileSubMenu_DropDownOpened(object sender, EventArgs e) OpenRomMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Open ROM"]; CloseRomMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Close ROM"]; - MovieSubMenu.Enabled = - CloseRomMenuItem.Enabled = - !Emulator.IsNull(); + CloseRomMenuItem.Enabled = !Emulator.IsNull(); var hasSaveRam = Emulator.HasSaveRam(); bool needBold = hasSaveRam && Emulator.AsSaveRam().SaveRamModified; @@ -232,14 +169,13 @@ private void MovieSubMenu_DropDownOpened(object sender, EventArgs e) SaveMovieMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Save Movie"]; PlayMovieMenuItem.Enabled - = ImportMoviesMenuItem.Enabled + = RecordMovieMenuItem.Enabled = RecentMovieSubMenu.Enabled - = !Tools.IsLoaded(); + = !Emulator.IsNull() && !Tools.IsLoaded(); // Record movie dialog should not be opened while in need of a reboot, // Otherwise the wrong sync settings could be set for the recording movie and cause crashes - RecordMovieMenuItem.Enabled = !Tools.IsLoaded() - && RebootStatusBarIcon.Visible == false; + RecordMovieMenuItem.Enabled &= !RebootStatusBarIcon.Visible; PlayFromBeginningMenuItem.Enabled = MovieSession.Movie.IsActive() && !Tools.IsLoaded(); } @@ -303,30 +239,25 @@ private void OpenAdvancedMenuItem_Click(object sender, EventArgs e) if (oac.Result == AdvancedRomLoaderType.LibretroLaunchNoGame) { - var argsNoGame = new LoadRomArgs - { - OpenAdvanced = new OpenAdvanced_LibretroNoGame(Config.LibretroCore) - }; - _ = LoadRom(string.Empty, argsNoGame); + _ = LoadRom(string.Empty, new LoadRomArgs(new OpenAdvanced_LibretroNoGame(Config.LibretroCore))); return; } - var args = new LoadRomArgs(); - - var filter = RomLoader.RomFilter; - + IOpenAdvanced ioa; + FilesystemFilterSet filter; if (oac.Result == AdvancedRomLoaderType.LibretroLaunchGame) { - args.OpenAdvanced = new OpenAdvanced_Libretro(); + ioa = new OpenAdvanced_Libretro(); filter = oac.SuggestedExtensionFilter!; } else if (oac.Result == AdvancedRomLoaderType.ClassicLaunchGame) { - args.OpenAdvanced = new OpenAdvanced_OpenRom(); + ioa = new OpenAdvanced_OpenRom(); + filter = RomLoader.RomFilter; } else if (oac.Result == AdvancedRomLoaderType.MameLaunchGame) { - args.OpenAdvanced = new OpenAdvanced_MAME(); + ioa = new OpenAdvanced_MAME(); filter = MAMERomsFSFilterSet; } else @@ -341,7 +272,7 @@ private void OpenAdvancedMenuItem_Click(object sender, EventArgs e) if (result is null) return; FileInfo file = new(result); Config.PathEntries.LastRomPath = file.DirectoryName; - _ = LoadRom(file.FullName, args); + _ = LoadRom(file.FullName, new LoadRomArgs(ioa)); } private void CloseRomMenuItem_Click(object sender, EventArgs e) @@ -362,13 +293,10 @@ private void QuickLoadstateMenuItem_Click(object sender, EventArgs e) private void LoadNamedStateMenuItem_Click(object sender, EventArgs e) => LoadStateAs(); private void AutoloadLastSlotMenuItem_Click(object sender, EventArgs e) - { - Config.AutoLoadLastSaveSlot ^= true; - } + => Config.AutoLoadLastSaveSlot = !Config.AutoLoadLastSaveSlot; + private void AutosaveLastSlotMenuItem_Click(object sender, EventArgs e) - { - Config.AutoSaveLastSaveSlot ^= true; - } + => Config.AutoSaveLastSaveSlot = !Config.AutoSaveLastSaveSlot; private void SelectSlotMenuItems_Click(object sender, EventArgs e) { @@ -513,14 +441,10 @@ private void StopMovieWithoutSavingMenuItem_Click(object sender, EventArgs e) } private void AutomaticMovieBackupMenuItem_Click(object sender, EventArgs e) - { - Config.Movies.EnableBackupMovies ^= true; - } + => Config.Movies.EnableBackupMovies = !Config.Movies.EnableBackupMovies; private void FullMovieLoadstatesMenuItem_Click(object sender, EventArgs e) - { - Config.Movies.VBAStyleMovieLoadState ^= true; - } + => Config.Movies.VBAStyleMovieLoadState = !Config.Movies.VBAStyleMovieLoadState; private void MovieEndFinishMenuItem_Click(object sender, EventArgs e) { @@ -604,9 +528,7 @@ private void ScreenshotClientClipboardMenuItem_Click(object sender, EventArgs e) } private void ScreenshotCaptureOSDMenuItem_Click(object sender, EventArgs e) - { - Config.ScreenshotCaptureOsd ^= true; - } + => Config.ScreenshotCaptureOsd = !Config.ScreenshotCaptureOsd; private void ExitMenuItem_Click(object sender, EventArgs e) { @@ -692,15 +614,16 @@ private void ViewSubMenu_DropDownOpened(object sender, EventArgs e) private void WindowSizeSubMenu_DropDownOpened(object sender, EventArgs e) { + var windowScale = Config.GetWindowScaleFor(Emulator.SystemId); foreach (ToolStripMenuItem item in WindowSizeSubMenu.DropDownItems) { - item.Checked = Config.TargetZoomFactors[Emulator.SystemId] == (int) item.Tag; + item.Checked = (int) item.Tag == windowScale; } } private void WindowSize_Click(object sender, EventArgs e) { - Config.TargetZoomFactors[Emulator.SystemId] = (int) ((ToolStripMenuItem) sender).Tag; + Config.SetWindowScaleFor(Emulator.SystemId, (int) ((ToolStripMenuItem) sender).Tag); FrameBufferResized(); } @@ -730,25 +653,19 @@ private void DisplayInputMenuItem_Click(object sender, EventArgs e) } private void DisplayRerecordsMenuItem_Click(object sender, EventArgs e) - { - Config.DisplayRerecordCount ^= true; - } + => Config.DisplayRerecordCount = !Config.DisplayRerecordCount; private void DisplaySubtitlesMenuItem_Click(object sender, EventArgs e) - { - Config.DisplaySubtitles ^= true; - } + => Config.DisplaySubtitles = !Config.DisplaySubtitles; private void DisplayStatusBarMenuItem_Click(object sender, EventArgs e) { - Config.DispChromeStatusBarWindowed ^= true; + Config.DispChromeStatusBarWindowed = !Config.DispChromeStatusBarWindowed; SetStatusBar(); } private void DisplayMessagesMenuItem_Click(object sender, EventArgs e) - { - Config.DisplayMessages ^= true; - } + => Config.DisplayMessages = !Config.DisplayMessages; private void DisplayLogWindowMenuItem_Click(object sender, EventArgs e) { @@ -961,7 +878,7 @@ private void ProfilesMenuItem_Click(object sender, EventArgs e) private void ClockThrottleMenuItem_Click(object sender, EventArgs e) { - Config.ClockThrottle ^= true; + Config.ClockThrottle = !Config.ClockThrottle; if (Config.ClockThrottle) { var old = Config.SoundThrottle; @@ -984,7 +901,7 @@ private void ClockThrottleMenuItem_Click(object sender, EventArgs e) private void AudioThrottleMenuItem_Click(object sender, EventArgs e) { - Config.SoundThrottle ^= true; + Config.SoundThrottle = !Config.SoundThrottle; RewireSound(); if (Config.SoundThrottle) { @@ -1002,7 +919,7 @@ private void AudioThrottleMenuItem_Click(object sender, EventArgs e) private void VsyncThrottleMenuItem_Click(object sender, EventArgs e) { - Config.VSyncThrottle ^= true; + Config.VSyncThrottle = !Config.VSyncThrottle; _presentationPanel.Resized = true; if (Config.VSyncThrottle) { @@ -1026,7 +943,7 @@ private void VsyncThrottleMenuItem_Click(object sender, EventArgs e) private void VsyncEnabledMenuItem_Click(object sender, EventArgs e) { - Config.VSync ^= true; + Config.VSync = !Config.VSync; if (!Config.VSyncThrottle) // when vsync throttle is on, vsync is forced to on, so no change to make here { _presentationPanel.Resized = true; @@ -1040,14 +957,12 @@ private void UnthrottledMenuItem_Click(object sender, EventArgs e) private void ToggleUnthrottled() { - Config.Unthrottled ^= true; + Config.Unthrottled = !Config.Unthrottled; ThrottleMessage(); } private void MinimizeSkippingMenuItem_Click(object sender, EventArgs e) - { - Config.AutoMinimizeSkipping ^= true; - } + => Config.AutoMinimizeSkipping = !Config.AutoMinimizeSkipping; private void NeverSkipMenuItem_Click(object sender, EventArgs e) { Config.FrameSkip = 0; FrameSkipMessage(); } private void Frameskip1MenuItem_Click(object sender, EventArgs e) { Config.FrameSkip = 1; FrameSkipMessage(); } @@ -1269,1211 +1184,256 @@ private void StartRetroAchievementsMenuItem_Click(object sender, EventArgs e) OpenRetroAchievements(); } - private void NesSubMenu_DropDownOpened(object sender, EventArgs e) - { - var boardName = Emulator.HasBoardInfo() ? Emulator.AsBoardInfo().BoardName : null; - FDSControlsMenuItem.Enabled = boardName == "FDS"; - - VSControlsMenuItem.Enabled = - VSSettingsMenuItem.Enabled = - (Emulator is NES nes && nes.IsVS) - || (Emulator is SubNESHawk sub && sub.IsVs); - - NESSoundChannelsMenuItem.Enabled = Tools.IsAvailable(); - MovieSettingsMenuItem.Enabled = Emulator is NES or SubNESHawk && MovieSession.Movie.NotActive(); - - NesControllerSettingsMenuItem.Enabled = Tools.IsAvailable() && MovieSession.Movie.NotActive(); + private DialogResult OpenGenericCoreConfigFor(string title) + where T : IEmulator + => GenericCoreConfig.DoDialogFor(this, GetSettingsAdapterFor(), title, isMovieActive: MovieSession.Movie.IsActive()); - BarcodeReaderMenuItem.Enabled = ServiceInjector.IsAvailable(Emulator.ServiceProvider, typeof(BarcodeEntry)); + private void OpenGenericCoreConfig() + => GenericCoreConfig.DoDialog(Emulator, this, isMovieActive: MovieSession.Movie.IsActive()); - MusicRipperMenuItem.Enabled = Tools.IsAvailable(); - } + private void GenericCoreSettingsMenuItem_Click(object sender, EventArgs e) + => OpenGenericCoreConfig(); - private void FdsControlsMenuItem_DropDownOpened(object sender, EventArgs e) + private void HelpSubMenu_DropDownOpened(object sender, EventArgs e) { - var boardName = Emulator.HasBoardInfo() ? Emulator.AsBoardInfo().BoardName : null; - FdsEjectDiskMenuItem.Enabled = boardName == "FDS"; - - while (FDSControlsMenuItem.DropDownItems.Count > 1) - { - FDSControlsMenuItem.DropDownItems.RemoveAt(1); - } - - string button; - for (int i = 0; Emulator.ControllerDefinition.BoolButtons.Contains(button = $"FDS Insert {i}"); i++) - { - var name = $"Disk {i / 2 + 1} Side {(char)(i % 2 + 'A')}"; - FdsInsertDiskMenuAdd($"Insert {name}", button, $"FDS {name} inserted."); - } + FeaturesMenuItem.Visible = VersionInfo.DeveloperBuild; } - private void NesPpuViewerMenuItem_Click(object sender, EventArgs e) + private void OnlineHelpMenuItem_Click(object sender, EventArgs e) { - Tools.Load(); + System.Diagnostics.Process.Start("https://tasvideos.org/BizHawk"); } - private void NesNametableViewerMenuItem_Click(object sender, EventArgs e) + private void ForumsMenuItem_Click(object sender, EventArgs e) { - Tools.Load(); + System.Diagnostics.Process.Start("https://tasvideos.org/Forum/Subforum/64"); } - private void MusicRipperMenuItem_Click(object sender, EventArgs e) + private void FeaturesMenuItem_Click(object sender, EventArgs e) { - Tools.Load(); + Tools.Load(); } - private DialogResult OpenNesHawkGraphicsSettingsDialog(ISettingsAdapter settable) + private void AboutMenuItem_Click(object sender, EventArgs e) { - using NESGraphicsConfig form = new(Config, this, settable); - return this.ShowDialogWithTempMute(form); + using BizBox form = new(() => Sound.PlayWavFile(Properties.Resources.GetNotHawkCallSFX(), atten: 1.0f)); + this.ShowDialogWithTempMute(form); } - private DialogResult OpenQuickNesGraphicsSettingsDialog(ISettingsAdapter settable) + private void MainFormContextMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e) { - using QuickNesConfig form = new(Config, DialogController, settable); - return this.ShowDialogWithTempMute(form); - } + MaybePauseFromMenuOpened(); - private void NesGraphicSettingsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch + OpenRomContextMenuItem.Visible = Emulator.IsNull() || _inFullscreen; + + bool showMenuVisible = _inFullscreen || !MainMenuStrip.Visible; // need to always be able to restore this as an emergency measure + + if (_argParser._chromeless) { - NES => OpenNesHawkGraphicsSettingsDialog(GetSettingsAdapterForLoadedCore()), - SubNESHawk => OpenNesHawkGraphicsSettingsDialog(GetSettingsAdapterForLoadedCore()), - QuickNES => OpenQuickNesGraphicsSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } + showMenuVisible = true; // I decided this was always possible in chrome-less mode, we'll see what they think + } - private void NesSoundChannelsMenuItem_Click(object sender, EventArgs e) - { - Tools.Load(); - } + var movieIsActive = MovieSession.Movie.IsActive(); - private DialogResult OpenNesHawkVSSettingsDialog(ISettingsAdapter settable) - { - using NesVsSettings form = new(settable); - return this.ShowDialogWithTempMute(form); - } + ShowMenuContextMenuItem.Visible = + ShowMenuContextMenuSeparator.Visible = + showMenuVisible; - private void VsSettingsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - NES { IsVS: true } => OpenNesHawkVSSettingsDialog(GetSettingsAdapterForLoadedCore()), - SubNESHawk { IsVs: true } => OpenNesHawkVSSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } + LoadLastRomContextMenuItem.Visible = Emulator.IsNull(); - private void FdsEjectDiskMenuItem_Click(object sender, EventArgs e) - { - if (!MovieSession.Movie.IsPlaying()) - { - InputManager.ClickyVirtualPadController.Click("FDS Eject"); - AddOnScreenMessage("FDS disk ejected."); - } - } + StopAVContextMenuItem.Visible = _currAviWriter != null; - private void VsInsertCoinP1MenuItem_Click(object sender, EventArgs e) - { - if (Emulator is NES nes && nes.IsVS - || Emulator is SubNESHawk sub && sub.IsVs) + ContextSeparator_AfterMovie.Visible = + ContextSeparator_AfterUndo.Visible = + ScreenshotContextMenuItem.Visible = + CloseRomContextMenuItem.Visible = + UndoSavestateContextMenuItem.Visible = + !Emulator.IsNull(); + + RecordMovieContextMenuItem.Visible = + PlayMovieContextMenuItem.Visible = + LoadLastMovieContextMenuItem.Visible = + !Emulator.IsNull() && !movieIsActive; + + RestartMovieContextMenuItem.Visible = + StopMovieContextMenuItem.Visible = + ViewSubtitlesContextMenuItem.Visible = + ViewCommentsContextMenuItem.Visible = + SaveMovieContextMenuItem.Visible = + SaveMovieAsContextMenuItem.Visible = + movieIsActive; + + BackupMovieContextMenuItem.Visible = movieIsActive; + + StopNoSaveContextMenuItem.Visible = movieIsActive && MovieSession.Movie.Changes; + + AddSubtitleContextMenuItem.Visible = !Emulator.IsNull() && movieIsActive && !MovieSession.ReadOnly; + + ConfigContextMenuItem.Visible = _inFullscreen; + + ClearSRAMContextMenuItem.Visible = File.Exists(Config.PathEntries.SaveRamAbsolutePath(Game, MovieSession.Movie)); + + ContextSeparator_AfterROM.Visible = OpenRomContextMenuItem.Visible || LoadLastRomContextMenuItem.Visible; + + LoadLastRomContextMenuItem.Enabled = !Config.RecentRoms.Empty; + LoadLastMovieContextMenuItem.Enabled = !Config.RecentMovies.Empty; + + if (movieIsActive) { - if (!MovieSession.Movie.IsPlaying()) + if (MovieSession.ReadOnly) + { + ViewSubtitlesContextMenuItem.Text = "View Subtitles"; + ViewCommentsContextMenuItem.Text = "View Comments"; + } + else { - InputManager.ClickyVirtualPadController.Click("Insert Coin P1"); - AddOnScreenMessage("P1 Coin Inserted"); + ViewSubtitlesContextMenuItem.Text = "Edit Subtitles"; + ViewCommentsContextMenuItem.Text = "Edit Comments"; } } - } - private void VsInsertCoinP2MenuItem_Click(object sender, EventArgs e) - { - if (Emulator is NES nes && nes.IsVS - || Emulator is SubNESHawk sub && sub.IsVs) + var file = new FileInfo($"{SaveStatePrefix()}.QuickSave{Config.SaveSlot % 10}.State.bak"); + + if (file.Exists) { - if (!MovieSession.Movie.IsPlaying()) + UndoSavestateContextMenuItem.Enabled = true; + if (_stateSlots.IsRedo(MovieSession.Movie, Config.SaveSlot)) + { + UndoSavestateContextMenuItem.Text = $"Redo Save to slot {Config.SaveSlot}"; + UndoSavestateContextMenuItem.Image = Properties.Resources.Redo; + } + else { - InputManager.ClickyVirtualPadController.Click("Insert Coin P2"); - AddOnScreenMessage("P2 Coin Inserted"); + UndoSavestateContextMenuItem.Text = $"Undo Save to slot {Config.SaveSlot}"; + UndoSavestateContextMenuItem.Image = Properties.Resources.Undo; } } + else + { + UndoSavestateContextMenuItem.Enabled = false; + UndoSavestateContextMenuItem.Text = "Undo Savestate"; + UndoSavestateContextMenuItem.Image = Properties.Resources.Undo; + } + + ShowMenuContextMenuItem.Text = MainMenuStrip.Visible ? "Hide Menu" : "Show Menu"; } - private void VsServiceSwitchMenuItem_Click(object sender, EventArgs e) + private void MainFormContextMenu_Closing(object sender, ToolStripDropDownClosingEventArgs e) + => MaybeUnpauseFromMenuClosed(); + + private void DisplayConfigMenuItem_Click(object sender, EventArgs e) { - if (Emulator is NES nes && nes.IsVS - || Emulator is SubNESHawk sub && sub.IsVs) + using DisplayConfig window = new(Config, DialogController, GL); + if (this.ShowDialogWithTempMute(window).IsOk()) { - if (!MovieSession.Movie.IsPlaying()) + DisplayManager.RefreshUserShader(); + FrameBufferResized(); + SynchChrome(); + if (window.NeedReset) { - InputManager.ClickyVirtualPadController.Click("Service Switch"); - AddOnScreenMessage("Service Switch Pressed"); + AddOnScreenMessage("Restart program for changed settings"); } } } - private DialogResult OpenNesHawkGamepadSettingsDialog(ISettingsAdapter settable) - { - using NesControllerSettings form = new(settable); - return this.ShowDialogWithTempMute(form); - } - - private DialogResult OpenQuickNesGamepadSettingsDialog(ISettingsAdapter settable) - => GenericCoreConfig.DoDialogFor( - this, - settable, - CoreNames.QuickNes + " Controller Settings", - isMovieActive: MovieSession.Movie.IsActive(), - ignoreSettings: true); + private void LoadLastRomContextMenuItem_Click(object sender, EventArgs e) + => LoadMostRecentROM(); - private void NesControllerSettingsMenuItem_Click(object sender, EventArgs e) + private void LoadMostRecentROM() { - _ = Emulator switch - { - NES => OpenNesHawkGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), - SubNESHawk => OpenNesHawkGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), - QuickNES => OpenQuickNesGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; + LoadRomFromRecent(Config.RecentRoms.MostRecent); } - private DialogResult OpenNesHawkAdvancedSettingsDialog(ISettingsAdapter settable, bool hasMapperProperties) + private void LoadLastMovieContextMenuItem_Click(object sender, EventArgs e) { - using NESSyncSettingsForm form = new(this, settable, hasMapperProperties: hasMapperProperties); - return this.ShowDialogWithTempMute(form); + LoadMoviesFromRecent(Config.RecentMovies.MostRecent); } - private void MovieSettingsMenuItem_Click(object sender, EventArgs e) + private void BackupMovieContextMenuItem_Click(object sender, EventArgs e) { - _ = Emulator switch - { - NES nesHawk => OpenNesHawkAdvancedSettingsDialog(GetSettingsAdapterForLoadedCore(), nesHawk.HasMapperProperties), - SubNESHawk subNESHawk => OpenNesHawkAdvancedSettingsDialog(GetSettingsAdapterForLoadedCore(), subNESHawk.HasMapperProperties), - _ => DialogResult.None - }; + MovieSession.Movie.SaveBackup(); + AddOnScreenMessage("Backup movie saved."); } - private void BarcodeReaderMenuItem_Click(object sender, EventArgs e) + private void ViewSubtitlesContextMenuItem_Click(object sender, EventArgs e) { - Tools.Load(); + if (MovieSession.Movie.NotActive()) return; + using EditSubtitlesForm form = new(this, MovieSession.Movie, Config.PathEntries, readOnly: MovieSession.ReadOnly); + this.ShowDialogWithTempMute(form); } - private void Ti83KeypadMenuItem_Click(object sender, EventArgs e) + private void AddSubtitleContextMenuItem_Click(object sender, EventArgs e) { - Tools.Load(); - } + // TODO: rethink this? + var subForm = new SubtitleMaker(); + subForm.DisableFrame(); - private void Ti83LoadTIFileMenuItem_Click(object sender, EventArgs e) - { - if (Emulator is not TI83 ti83) return; - var result = this.ShowFileOpenDialog( - discardCWDChange: true, - filter: TI83ProgramFilesFSFilterSet, - initDir: Config.PathEntries.RomAbsolutePath(Emulator.SystemId)); - if (result is null) return; - try - { - ti83.LinkPort.SendFileToCalc(File.OpenRead(result), true); - } - catch (IOException ex) + int index = -1; + var sub = new Subtitle(); + for (int i = 0; i < MovieSession.Movie.Subtitles.Count; i++) { - var message = - $"Invalid file format. Reason: {ex.Message} \nForce transfer? This may cause the calculator to crash."; - if (this.ShowMessageBox3(owner: null, message, "Upload Failed", EMsgBoxIcon.Question) == true) + sub = MovieSession.Movie.Subtitles[i]; + if (Emulator.Frame == sub.Frame) { - ti83.LinkPort.SendFileToCalc(File.OpenRead(result), false); + index = i; + break; } } - } - - private DialogResult OpenTI83PaletteSettingsDialog(ISettingsAdapter settable) - { - using TI83PaletteConfig form = new(settable); - return this.ShowDialogWithTempMute(form); - } - private void Ti83PaletteMenuItem_Click(object sender, EventArgs e) - { - var result = Emulator switch + if (index < 0) { - Emu83 => OpenTI83PaletteSettingsDialog(GetSettingsAdapterForLoadedCore()), - TI83 => OpenTI83PaletteSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - if (result.IsOk()) AddOnScreenMessage("Palette settings saved"); + sub = new Subtitle { Frame = Emulator.Frame }; + } + + subForm.Sub = sub; + if (!this.ShowDialogWithTempMute(subForm).IsOk()) return; + + if (index >= 0) MovieSession.Movie.Subtitles.RemoveAt(index); + MovieSession.Movie.Subtitles.Add(subForm.Sub); } - private void A7800SubMenu_DropDownOpened(object sender, EventArgs e) + private void ViewCommentsContextMenuItem_Click(object sender, EventArgs e) { - A7800ControllerSettingsMenuItem.Enabled - = A7800FilterSettingsMenuItem.Enabled - = MovieSession.Movie.NotActive(); + if (MovieSession.Movie.NotActive()) return; + using EditCommentsForm form = new(MovieSession.Movie, MovieSession.ReadOnly); + this.ShowDialogWithTempMute(form); } - private DialogResult OpenA7800HawkGamepadSettingsDialog(ISettingsAdapter settable) + private void UndoSavestateContextMenuItem_Click(object sender, EventArgs e) { - using A7800ControllerSettings form = new(settable); - return this.ShowDialogWithTempMute(form); + _stateSlots.SwapBackupSavestate(MovieSession.Movie, $"{SaveStatePrefix()}.QuickSave{Config.SaveSlot % 10}.State", Config.SaveSlot); + AddOnScreenMessage($"Save slot {Config.SaveSlot} restored."); } - private void A7800ControllerSettingsMenuItem_Click(object sender, EventArgs e) + private void ClearSramContextMenuItem_Click(object sender, EventArgs e) { - _ = Emulator switch - { - A7800Hawk => OpenA7800HawkGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; + CloseRom(clearSram: true); } - private DialogResult OpenA7800HawkFilterSettingsDialog(ISettingsAdapter settable) + private void ShowMenuContextMenuItem_Click(object sender, EventArgs e) { - using A7800FilterSettings form = new(settable); - return this.ShowDialogWithTempMute(form); + MainMenuStrip.Visible = !MainMenuStrip.Visible; + FrameBufferResized(); } - private void A7800FilterSettingsMenuItem_Click(object sender, EventArgs e) + private void DumpStatusButton_Click(object sender, EventArgs e) { - _ = Emulator switch + string details = Emulator.RomDetails(); + if (string.IsNullOrWhiteSpace(details)) { - A7800Hawk => OpenA7800HawkFilterSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } - - private DialogResult OpenGambatteSettingsDialog(ISettingsAdapter settable) - => GBPrefs.DoGBPrefsDialog(Config, this, Game, MovieSession, settable); - - private DialogResult OpenGBHawkSettingsDialog() - => OpenGenericCoreConfigFor(CoreNames.GbHawk + " Settings"); - - private DialogResult OpenSameBoySettingsDialog() - => OpenGenericCoreConfigFor(CoreNames.Sameboy + " Settings"); - - private DialogResult OpenSubGBHawkSettingsDialog() - => OpenGenericCoreConfigFor(CoreNames.SubGbHawk + " Settings"); + details = _defaultRomDetails; + } - private void GbCoreSettingsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch + if (!string.IsNullOrEmpty(details)) { - Gameboy => OpenGambatteSettingsDialog(GetSettingsAdapterForLoadedCore()), - GBHawk => OpenGBHawkSettingsDialog(), - Sameboy => OpenSameBoySettingsDialog(), - SubGBHawk => OpenSubGBHawkSettingsDialog(), - _ => DialogResult.None - }; + Tools.Load(); + ((LogWindow) Tools.Get()).ShowReport("Dump Status Report", details); + } } - private DialogResult OpenSameBoyPaletteSettingsDialog(ISettingsAdapter settable) - { - using SameBoyColorChooserForm form = new(Config, this, Game, settable); - return this.ShowDialogWithTempMute(form); - } + private readonly ScreenshotForm _screenshotTooltip = new(); - private void SameboyColorChooserMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - Sameboy => OpenSameBoyPaletteSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } - - private void GbGpuViewerMenuItem_Click(object sender, EventArgs e) - { - Tools.Load(); - } - - private void GbPrinterViewerMenuItem_Click(object sender, EventArgs e) - { - Tools.Load(); - } - - private void PsxSubMenu_DropDownOpened(object sender, EventArgs e) - { - PSXControllerSettingsMenuItem.Enabled = MovieSession.Movie.NotActive(); - } - - private DialogResult OpenOctoshockGamepadSettingsDialog(ISettingsAdapter settable) - { - using PSXControllerConfig form = new(settable); - return this.ShowDialogWithTempMute(form); - } - - private void PsxControllerSettingsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - Octoshock => OpenOctoshockGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } - - private DialogResult OpenOctoshockSettingsDialog(ISettingsAdapter settable, OctoshockDll.eVidStandard vidStandard, Size vidSize) - => PSXOptions.DoSettingsDialog(Config, this, settable, vidStandard, vidSize); - - private void PsxOptionsMenuItem_Click(object sender, EventArgs e) - { - var result = Emulator switch - { - Octoshock octoshock => OpenOctoshockSettingsDialog(GetSettingsAdapterForLoadedCore(), octoshock.SystemVidStandard, octoshock.CurrentVideoSize), - _ => DialogResult.None - }; - if (result.IsOk()) FrameBufferResized(); - } - - private void PsxDiscControlsMenuItem_Click(object sender, EventArgs e) - { - Tools.Load().ScrollToPadSchema("Console"); - } - - private void PsxHashDiscsMenuItem_Click(object sender, EventArgs e) - { - if (Emulator is not IRedumpDiscChecksumInfo psx) return; - using PSXHashDiscs form = new() { _psx = psx }; - this.ShowDialogWithTempMute(form); - } - - private void SnesSubMenu_DropDownOpened(object sender, EventArgs e) - { - SNESControllerConfigurationMenuItem.Enabled = MovieSession.Movie.NotActive(); - } - - private DialogResult OpenOldBSNESGamepadSettingsDialog(ISettingsAdapter settable) - { - using SNESControllerSettings form = new(settable); - return this.ShowDialogWithTempMute(form); - } - - private DialogResult OpenBSNESGamepadSettingsDialog(ISettingsAdapter settable) - { - using BSNESControllerSettings form = new(settable); - return this.ShowDialogWithTempMute(form); - } - - private void SNESControllerConfigurationMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - LibsnesCore => OpenOldBSNESGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), - BsnesCore => OpenBSNESGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), - SubBsnesCore => OpenBSNESGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } - - private void SnesGfxDebuggerMenuItem_Click(object sender, EventArgs e) - { - Tools.Load(); - } - - private DialogResult OpenOldBSNESSettingsDialog(ISettingsAdapter settable) - => SNESOptions.DoSettingsDialog(this, settable); - - private DialogResult OpenBSNESSettingsDialog(ISettingsAdapter settable) - => BSNESOptions.DoSettingsDialog(this, settable); - - private void SnesOptionsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - LibsnesCore => OpenOldBSNESSettingsDialog(GetSettingsAdapterForLoadedCore()), - BsnesCore => OpenBSNESSettingsDialog(GetSettingsAdapterForLoadedCore()), - SubBsnesCore => OpenBSNESSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } - - private void ColecoSubMenu_DropDownOpened(object sender, EventArgs e) - { - if (Emulator is ColecoVision coleco) - { - var ss = coleco.GetSyncSettings(); - ColecoSkipBiosMenuItem.Checked = ss.SkipBiosIntro; - ColecoUseSGMMenuItem.Checked = ss.UseSGM; - ColecoControllerSettingsMenuItem.Enabled = MovieSession.Movie.NotActive(); - } - } - - private void ColecoHawkSetSkipBIOSIntro(bool newValue, ISettingsAdapter settable) - { - var ss = (ColecoVision.ColecoSyncSettings) settable.GetSyncSettings(); - ss.SkipBiosIntro = newValue; - settable.PutCoreSyncSettings(ss); - } - - private void ColecoSkipBiosMenuItem_Click(object sender, EventArgs e) - { - if (Emulator is ColecoVision) ColecoHawkSetSkipBIOSIntro(!((ToolStripMenuItem) sender).Checked, GetSettingsAdapterForLoadedCore()); - } - - private void ColecoHawkSetSuperGameModule(bool newValue, ISettingsAdapter settable) - { - var ss = (ColecoVision.ColecoSyncSettings) settable.GetSyncSettings(); - ss.UseSGM = newValue; - settable.PutCoreSyncSettings(ss); - } - - private void ColecoUseSGMMenuItem_Click(object sender, EventArgs e) - { - if (Emulator is ColecoVision) ColecoHawkSetSuperGameModule(!((ToolStripMenuItem) sender).Checked, GetSettingsAdapterForLoadedCore()); - } - - private DialogResult OpenColecoHawkGamepadSettingsDialog(ISettingsAdapter settable) - { - using ColecoControllerSettings form = new(settable); - return this.ShowDialogWithTempMute(form); - } - - private void ColecoControllerSettingsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - ColecoVision => OpenColecoHawkGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } - - private void N64SubMenu_DropDownOpened(object sender, EventArgs e) - { - N64PluginSettingsMenuItem.Enabled = - N64ControllerSettingsMenuItem.Enabled = - N64ExpansionSlotMenuItem.Enabled = - MovieSession.Movie.NotActive(); - - N64CircularAnalogRangeMenuItem.Checked = Config.N64UseCircularAnalogConstraint; - - var s = ((N64)Emulator).GetSettings(); - MupenStyleLagMenuItem.Checked = s.UseMupenStyleLag; - - N64ExpansionSlotMenuItem.Checked = ((N64)Emulator).UsingExpansionSlot; - N64ExpansionSlotMenuItem.Enabled = !((N64)Emulator).IsOverridingUserExpansionSlotSetting; - } - - private DialogResult OpenMupen64PlusGraphicsSettingsDialog(ISettingsAdapter settable) - { - using N64VideoPluginConfig form = new(settable); - return this.ShowDialogWithTempMute(form); - } - - private void N64PluginSettingsMenuItem_Click(object sender, EventArgs e) - { - if (OpenMupen64PlusGraphicsSettingsDialog(GetSettingsAdapterFor()).IsOk() - && Emulator is not N64) // If it's loaded, the reboot required message will appear - { - AddOnScreenMessage("Plugin settings saved"); - } - } - - private DialogResult OpenMupen64PlusGamepadSettingsDialog(ISettingsAdapter settable) - { - using N64ControllersSetup form = new(settable); - return this.ShowDialogWithTempMute(form); - } - - private void N64ControllerSettingsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - N64 => OpenMupen64PlusGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } - - private void N64CircularAnalogRangeMenuItem_Click(object sender, EventArgs e) - { - Config.N64UseCircularAnalogConstraint ^= true; - } - - private static void Mupen64PlusSetMupenStyleLag(bool newValue, ISettingsAdapter settable) - { - var s = (N64Settings) settable.GetSettings(); - s.UseMupenStyleLag = newValue; - settable.PutCoreSettings(s); - } - - private void MupenStyleLagMenuItem_Click(object sender, EventArgs e) - => Mupen64PlusSetMupenStyleLag(!((ToolStripMenuItem) sender).Checked, GetSettingsAdapterForLoadedCore()); - - private void Mupen64PlusSetUseExpansionSlot(bool newValue, ISettingsAdapter settable) - { - var ss = (N64SyncSettings) settable.GetSyncSettings(); - ss.DisableExpansionSlot = !newValue; - settable.PutCoreSyncSettings(ss); - } - - private void N64ExpansionSlotMenuItem_Click(object sender, EventArgs e) - { - if (Emulator is N64) - { - Mupen64PlusSetUseExpansionSlot(!((ToolStripMenuItem) sender).Checked, GetSettingsAdapterForLoadedCore()); - FlagNeedsReboot(); - } - } - - private void Ares64SubMenu_DropDownOpened(object sender, EventArgs e) - => Ares64CircularAnalogRangeMenuItem.Checked = Config.N64UseCircularAnalogConstraint; - - private void Ares64SettingsMenuItem_Click(object sender, EventArgs e) - => OpenGenericCoreConfigFor(CoreNames.Ares64 + " Settings"); - - private DialogResult OpenGambatteLinkSettingsDialog(ISettingsAdapter settable) - => GBLPrefs.DoGBLPrefsDialog(Config, this, Game, MovieSession, settable); - - private void GblSettingsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - GambatteLink => OpenGambatteLinkSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } - - private DialogResult OpenGenericCoreConfigFor(string title) - where T : IEmulator - => GenericCoreConfig.DoDialogFor(this, GetSettingsAdapterFor(), title, isMovieActive: MovieSession.Movie.IsActive()); - - private void OpenGenericCoreConfig() - => GenericCoreConfig.DoDialog(Emulator, this, isMovieActive: MovieSession.Movie.IsActive()); - - private void GenericCoreSettingsMenuItem_Click(object sender, EventArgs e) - => OpenGenericCoreConfig(); - - private DialogResult OpenVirtuSettingsDialog() - => OpenGenericCoreConfigFor(CoreNames.Virtu + " Settings"); - - private void AppleIISettingsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - AppleII => OpenVirtuSettingsDialog(), - _ => DialogResult.None - }; - } - - private void AppleSubMenu_DropDownOpened(object sender, EventArgs e) - { - if (Emulator is AppleII a) - { - AppleDisksSubMenu.Enabled = a.DiskCount > 1; - } - } - - private void AppleDisksSubMenu_DropDownOpened(object sender, EventArgs e) - { - AppleDisksSubMenu.DropDownItems.Clear(); - - if (Emulator is AppleII appleII) - { - for (int i = 0; i < appleII.DiskCount; i++) - { - var menuItem = new ToolStripMenuItem - { - Name = $"Disk{i + 1}", - Text = $"Disk{i + 1}", - Checked = appleII.CurrentDisk == i - }; - - int dummy = i; - menuItem.Click += (o, ev) => - { - appleII.SetDisk(dummy); - }; - - AppleDisksSubMenu.DropDownItems.Add(menuItem); - } - } - } - - private void C64SubMenu_DropDownOpened(object sender, EventArgs e) - { - if (Emulator is C64 c64) - { - C64DisksSubMenu.Enabled = c64.DiskCount > 1; - } - } - - private void C64DisksSubMenu_DropDownOpened(object sender, EventArgs e) - { - C64DisksSubMenu.DropDownItems.Clear(); - - if (Emulator is C64 c64) - { - for (int i = 0; i < c64.DiskCount; i++) - { - var menuItem = new ToolStripMenuItem - { - Name = $"Disk{i + 1}", - Text = $"Disk{i + 1}", - Checked = c64.CurrentDisk == i - }; - - int dummy = i; - menuItem.Click += (o, ev) => - { - c64.SetDisk(dummy); - }; - - C64DisksSubMenu.DropDownItems.Add(menuItem); - } - } - } - - private DialogResult OpenC64HawkSettingsDialog() - => OpenGenericCoreConfigFor(CoreNames.C64Hawk + " Settings"); - - private void C64SettingsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - C64 => OpenC64HawkSettingsDialog(), - _ => DialogResult.None - }; - } - - private void IntVSubMenu_DropDownOpened(object sender, EventArgs e) - { - IntVControllerSettingsMenuItem.Enabled = MovieSession.Movie.NotActive(); - } - - private DialogResult OpenIntelliHawkGamepadSettingsDialog(ISettingsAdapter settable) - { - using IntvControllerSettings form = new(settable); - return this.ShowDialogWithTempMute(form); - } - - private void IntVControllerSettingsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - Intellivision => OpenIntelliHawkGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } - - private DialogResult OpenZXHawkGamepadSettingsDialog(ISettingsAdapter settable) - { - using ZxSpectrumJoystickSettings form = new(this, settable); - return this.ShowDialogWithTempMute(form); - } - - private void ZXSpectrumControllerConfigurationMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - ZXSpectrum => OpenZXHawkGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } - - private DialogResult OpenZXHawkSyncSettingsDialog(ISettingsAdapter settable) - { - using ZxSpectrumCoreEmulationSettings form = new(settable); - return this.ShowDialogWithTempMute(form); - } - - private void ZXSpectrumCoreEmulationSettingsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - ZXSpectrum => OpenZXHawkSyncSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } - - private DialogResult OpenZXHawkSettingsDialog(ISettingsAdapter settable) - { - using ZxSpectrumNonSyncSettings form = new(settable); - return this.ShowDialogWithTempMute(form); - } - - private void ZXSpectrumNonSyncSettingsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - ZXSpectrum => OpenZXHawkSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } - - private DialogResult OpenZXHawkAudioSettingsDialog(ISettingsAdapter settable) - { - using ZxSpectrumAudioSettings form = new(settable); - return this.ShowDialogWithTempMute(form); - } - - private void ZXSpectrumAudioSettingsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - ZXSpectrum => OpenZXHawkAudioSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } - - private void ZXSpectrumMediaMenuItem_DropDownOpened(object sender, EventArgs e) - { - if (Emulator is ZXSpectrum speccy) - { - ZXSpectrumTapesSubMenu.Enabled = speccy._tapeInfo.Count > 0; - ZXSpectrumDisksSubMenu.Enabled = speccy._diskInfo.Count > 0; - } - } - - private void ZXSpectrumTapesSubMenu_DropDownOpened(object sender, EventArgs e) - { - ZXSpectrumTapesSubMenu.DropDownItems.Clear(); - - List items = new(); - - if (Emulator is ZXSpectrum speccy) - { - var tapeMediaIndex = speccy._machine.TapeMediaIndex; - - for (int i = 0; i < speccy._tapeInfo.Count; i++) - { - string name = speccy._tapeInfo[i].Name; - - var menuItem = new ToolStripMenuItem - { - Name = $"{i}_{name}", - Text = $"{i}: {name}", - Checked = tapeMediaIndex == i - }; - - int dummy = i; - menuItem.Click += (o, ev) => - { - speccy._machine.TapeMediaIndex = dummy; - }; - - items.Add(menuItem); - } - } - - ZXSpectrumTapesSubMenu.DropDownItems.AddRange(items.ToArray()); - } - - private void ZXSpectrumDisksSubMenu_DropDownOpened(object sender, EventArgs e) - { - ZXSpectrumDisksSubMenu.DropDownItems.Clear(); - - List items = new(); - - if (Emulator is ZXSpectrum speccy) - { - var diskMediaIndex = speccy._machine.DiskMediaIndex; - - for (int i = 0; i < speccy._diskInfo.Count; i++) - { - string name = speccy._diskInfo[i].Name; - - var menuItem = new ToolStripMenuItem - { - Name = $"{i}_{name}", - Text = $"{i}: {name}", - Checked = diskMediaIndex == i - }; - - int dummy = i; - menuItem.Click += (o, ev) => - { - speccy._machine.DiskMediaIndex = dummy; - }; - - items.Add(menuItem); - } - } - - ZXSpectrumDisksSubMenu.DropDownItems.AddRange(items.ToArray()); - } - - private void ZXSpectrumExportSnapshotMenuItemMenuItem_Click(object sender, EventArgs e) - { - try - { - var result = this.ShowFileSaveDialog( - discardCWDChange: true, - fileExt: "szx", -// SupportMultiDottedExtensions = true, // I think this should be enabled globally if we're going to do it --yoshi - filter: ZXStateFilesFSFilterSet, - initDir: Config.PathEntries.ToolsAbsolutePath()); - if (result is not null) - { - var speccy = (ZXSpectrum)Emulator; - var snap = speccy.GetSZXSnapshot(); - File.WriteAllBytes(result, snap); - } - } - catch (Exception) - { - } - } - - private DialogResult OpenCPCHawkSyncSettingsDialog(ISettingsAdapter settable) - { - using AmstradCpcCoreEmulationSettings form = new(settable); - return this.ShowDialogWithTempMute(form); - } - - private void AmstradCpcCoreEmulationSettingsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - AmstradCPC => OpenCPCHawkSyncSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } - - private DialogResult OpenCPCHawkAudioSettingsDialog(ISettingsAdapter settable) - { - using AmstradCpcAudioSettings form = new(settable); - return this.ShowDialogWithTempMute(form); - } - - private void AmstradCpcAudioSettingsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - AmstradCPC => OpenCPCHawkAudioSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } - - private void AmstradCpcMediaMenuItem_DropDownOpened(object sender, EventArgs e) - { - if (Emulator is AmstradCPC cpc) - { - AmstradCPCTapesSubMenu.Enabled = cpc._tapeInfo.Count > 0; - AmstradCPCDisksSubMenu.Enabled = cpc._diskInfo.Count > 0; - } - } - - private void AmstradCpcTapesSubMenu_DropDownOpened(object sender, EventArgs e) - { - AmstradCPCTapesSubMenu.DropDownItems.Clear(); - - List items = new(); - - if (Emulator is AmstradCPC ams) - { - var tapeMediaIndex = ams._machine.TapeMediaIndex; - - for (int i = 0; i < ams._tapeInfo.Count; i++) - { - string name = ams._tapeInfo[i].Name; - - var menuItem = new ToolStripMenuItem - { - Name = $"{i}_{name}", - Text = $"{i}: {name}", - Checked = tapeMediaIndex == i - }; - - int dummy = i; - menuItem.Click += (o, ev) => - { - ams._machine.TapeMediaIndex = dummy; - }; - - items.Add(menuItem); - } - } - - AmstradCPCTapesSubMenu.DropDownItems.AddRange(items.ToArray()); - } - - private void AmstradCpcDisksSubMenu_DropDownOpened(object sender, EventArgs e) - { - AmstradCPCDisksSubMenu.DropDownItems.Clear(); - - List items = new(); - - if (Emulator is AmstradCPC ams) - { - var diskMediaIndex = ams._machine.DiskMediaIndex; - - for (int i = 0; i < ams._diskInfo.Count; i++) - { - string name = ams._diskInfo[i].Name; - - var menuItem = new ToolStripMenuItem - { - Name = $"{i}_{name}", - Text = $"{i}: {name}", - Checked = diskMediaIndex == i - }; - - int dummy = i; - menuItem.Click += (o, ev) => - { - ams._machine.DiskMediaIndex = dummy; - }; - - items.Add(menuItem); - } - } - - AmstradCPCDisksSubMenu.DropDownItems.AddRange(items.ToArray()); - } - - private DialogResult OpenCPCHawkSettingsDialog(ISettingsAdapter settable) - { - using AmstradCpcNonSyncSettings form = new(settable); - return this.ShowDialogWithTempMute(form); - } - - private void AmstradCpcNonSyncSettingsMenuItem_Click(object sender, EventArgs e) - { - _ = Emulator switch - { - AmstradCPC => OpenCPCHawkSettingsDialog(GetSettingsAdapterForLoadedCore()), - _ => DialogResult.None - }; - } - - private void HelpSubMenu_DropDownOpened(object sender, EventArgs e) - { - FeaturesMenuItem.Visible = VersionInfo.DeveloperBuild; - } - - private void OnlineHelpMenuItem_Click(object sender, EventArgs e) - { - System.Diagnostics.Process.Start("https://tasvideos.org/BizHawk"); - } - - private void ForumsMenuItem_Click(object sender, EventArgs e) - { - System.Diagnostics.Process.Start("https://tasvideos.org/Forum/Subforum/64"); - } - - private void FeaturesMenuItem_Click(object sender, EventArgs e) - { - Tools.Load(); - } - - private void AboutMenuItem_Click(object sender, EventArgs e) - { - using var form = new BizBox(b => Sound.PlayWavFile(new MemoryStream(b, false), 1)); - this.ShowDialogWithTempMute(form); - } - - private void MainFormContextMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e) - { - MaybePauseFromMenuOpened(); - - OpenRomContextMenuItem.Visible = Emulator.IsNull() || _inFullscreen; - - bool showMenuVisible = _inFullscreen || !MainMenuStrip.Visible; // need to always be able to restore this as an emergency measure - - if (_argParser._chromeless) - { - showMenuVisible = true; // I decided this was always possible in chrome-less mode, we'll see what they think - } - - var movieIsActive = MovieSession.Movie.IsActive(); - - ShowMenuContextMenuItem.Visible = - ShowMenuContextMenuSeparator.Visible = - showMenuVisible; - - LoadLastRomContextMenuItem.Visible = Emulator.IsNull(); - - StopAVContextMenuItem.Visible = _currAviWriter != null; - - ContextSeparator_AfterMovie.Visible = - ContextSeparator_AfterUndo.Visible = - ScreenshotContextMenuItem.Visible = - CloseRomContextMenuItem.Visible = - UndoSavestateContextMenuItem.Visible = - !Emulator.IsNull(); - - RecordMovieContextMenuItem.Visible = - PlayMovieContextMenuItem.Visible = - LoadLastMovieContextMenuItem.Visible = - !Emulator.IsNull() && !movieIsActive; - - RestartMovieContextMenuItem.Visible = - StopMovieContextMenuItem.Visible = - ViewSubtitlesContextMenuItem.Visible = - ViewCommentsContextMenuItem.Visible = - SaveMovieContextMenuItem.Visible = - SaveMovieAsContextMenuItem.Visible = - movieIsActive; - - BackupMovieContextMenuItem.Visible = movieIsActive; - - StopNoSaveContextMenuItem.Visible = movieIsActive && MovieSession.Movie.Changes; - - AddSubtitleContextMenuItem.Visible = !Emulator.IsNull() && movieIsActive && !MovieSession.ReadOnly; - - ConfigContextMenuItem.Visible = _inFullscreen; - - ClearSRAMContextMenuItem.Visible = File.Exists(Config.PathEntries.SaveRamAbsolutePath(Game, MovieSession.Movie)); - - ContextSeparator_AfterROM.Visible = OpenRomContextMenuItem.Visible || LoadLastRomContextMenuItem.Visible; - - LoadLastRomContextMenuItem.Enabled = !Config.RecentRoms.Empty; - LoadLastMovieContextMenuItem.Enabled = !Config.RecentMovies.Empty; - - if (movieIsActive) - { - if (MovieSession.ReadOnly) - { - ViewSubtitlesContextMenuItem.Text = "View Subtitles"; - ViewCommentsContextMenuItem.Text = "View Comments"; - } - else - { - ViewSubtitlesContextMenuItem.Text = "Edit Subtitles"; - ViewCommentsContextMenuItem.Text = "Edit Comments"; - } - } - - var file = new FileInfo($"{SaveStatePrefix()}.QuickSave{Config.SaveSlot % 10}.State.bak"); - - if (file.Exists) - { - UndoSavestateContextMenuItem.Enabled = true; - if (_stateSlots.IsRedo(MovieSession.Movie, Config.SaveSlot)) - { - UndoSavestateContextMenuItem.Text = $"Redo Save to slot {Config.SaveSlot}"; - UndoSavestateContextMenuItem.Image = Properties.Resources.Redo; - } - else - { - UndoSavestateContextMenuItem.Text = $"Undo Save to slot {Config.SaveSlot}"; - UndoSavestateContextMenuItem.Image = Properties.Resources.Undo; - } - } - else - { - UndoSavestateContextMenuItem.Enabled = false; - UndoSavestateContextMenuItem.Text = "Undo Savestate"; - UndoSavestateContextMenuItem.Image = Properties.Resources.Undo; - } - - ShowMenuContextMenuItem.Text = MainMenuStrip.Visible ? "Hide Menu" : "Show Menu"; - } - - private void MainFormContextMenu_Closing(object sender, ToolStripDropDownClosingEventArgs e) - => MaybeUnpauseFromMenuClosed(); - - private void DisplayConfigMenuItem_Click(object sender, EventArgs e) - { - using DisplayConfig window = new(Config, DialogController, GL); - if (this.ShowDialogWithTempMute(window).IsOk()) - { - DisplayManager.RefreshUserShader(); - FrameBufferResized(); - SynchChrome(); - if (window.NeedReset) - { - AddOnScreenMessage("Restart program for changed settings"); - } - } - } - - private void LoadLastRomContextMenuItem_Click(object sender, EventArgs e) - => LoadMostRecentROM(); - - private void LoadMostRecentROM() - { - LoadRomFromRecent(Config.RecentRoms.MostRecent); - } - - private void LoadLastMovieContextMenuItem_Click(object sender, EventArgs e) - { - LoadMoviesFromRecent(Config.RecentMovies.MostRecent); - } - - private void BackupMovieContextMenuItem_Click(object sender, EventArgs e) - { - MovieSession.Movie.SaveBackup(); - AddOnScreenMessage("Backup movie saved."); - } - - private void ViewSubtitlesContextMenuItem_Click(object sender, EventArgs e) - { - if (MovieSession.Movie.NotActive()) return; - using EditSubtitlesForm form = new(this, MovieSession.Movie, Config.PathEntries, readOnly: MovieSession.ReadOnly); - this.ShowDialogWithTempMute(form); - } - - private void AddSubtitleContextMenuItem_Click(object sender, EventArgs e) - { - // TODO: rethink this? - var subForm = new SubtitleMaker(); - subForm.DisableFrame(); - - int index = -1; - var sub = new Subtitle(); - for (int i = 0; i < MovieSession.Movie.Subtitles.Count; i++) - { - sub = MovieSession.Movie.Subtitles[i]; - if (Emulator.Frame == sub.Frame) - { - index = i; - break; - } - } - - if (index < 0) - { - sub = new Subtitle { Frame = Emulator.Frame }; - } - - subForm.Sub = sub; - if (!this.ShowDialogWithTempMute(subForm).IsOk()) return; - - if (index >= 0) MovieSession.Movie.Subtitles.RemoveAt(index); - MovieSession.Movie.Subtitles.Add(subForm.Sub); - } - - private void ViewCommentsContextMenuItem_Click(object sender, EventArgs e) - { - if (MovieSession.Movie.NotActive()) return; - using EditCommentsForm form = new(MovieSession.Movie, MovieSession.ReadOnly); - this.ShowDialogWithTempMute(form); - } - - private void UndoSavestateContextMenuItem_Click(object sender, EventArgs e) - { - _stateSlots.SwapBackupSavestate(MovieSession.Movie, $"{SaveStatePrefix()}.QuickSave{Config.SaveSlot % 10}.State", Config.SaveSlot); - AddOnScreenMessage($"Save slot {Config.SaveSlot} restored."); - } - - private void ClearSramContextMenuItem_Click(object sender, EventArgs e) - { - CloseRom(clearSram: true); - } - - private void ShowMenuContextMenuItem_Click(object sender, EventArgs e) - { - MainMenuStrip.Visible ^= true; - FrameBufferResized(); - } - - private void DumpStatusButton_Click(object sender, EventArgs e) - { - string details = Emulator.RomDetails(); - if (string.IsNullOrWhiteSpace(details)) - { - details = _defaultRomDetails; - } - - if (!string.IsNullOrEmpty(details)) - { - Tools.Load(); - ((LogWindow) Tools.Get()).ShowReport("Dump Status Report", details); - } - } - - private readonly ScreenshotForm _screenshotTooltip = new(); - - private void SlotStatusButtons_MouseEnter(object/*?*/ sender, EventArgs e) + private void SlotStatusButtons_MouseEnter(object/*?*/ sender, EventArgs e) { var slot = 10; if (sender == Slot1StatusButton) slot = 1; @@ -2560,8 +1520,9 @@ private void LinkConnectStatusBarButton_Click(object sender, EventArgs e) // toggle Link status (only outside of a movie session) if (!MovieSession.Movie.IsPlaying()) { - Emulator.AsLinkable().LinkConnected ^= true; - Console.WriteLine("Cable connect status to {0}", Emulator.AsLinkable().LinkConnected); + var core = Emulator.AsLinkable(); + core.LinkConnected = !core.LinkConnected; + Console.WriteLine($"Cable connect status to {core.LinkConnected}"); } } @@ -2670,351 +1631,5 @@ private static void FormDragEnter(object sender, DragEventArgs e) private void FormDragDrop(object sender, DragEventArgs e) => PathsFromDragDrop = (string[]) e.Data.GetData(DataFormats.FileDrop); - - private enum VSystemCategory : int - { - Consoles = 0, - Handhelds = 1, - PCs = 2, - Other = 3, - } - - private IReadOnlyCollection CreateCoreSettingsSubmenus(bool includeDupes = false) - { - static ToolStripMenuItemEx CreateSettingsItem(string text, EventHandler onClick) - { - ToolStripMenuItemEx menuItem = new() { Text = text }; - menuItem.Click += onClick; - return menuItem; - } - ToolStripMenuItemEx CreateGenericCoreConfigItem(string coreName) - where T : IEmulator - => CreateSettingsItem("Settings...", (_, _) => OpenGenericCoreConfigFor($"{coreName} Settings")); - ToolStripMenuItemEx CreateGenericNymaCoreConfigItem(string coreName, Func getCachedSettingsInfo) - where T : NymaCore - => CreateSettingsItem( - "Settings...", - (_, _) => GenericCoreConfig.DoNymaDialogFor( - this, - GetSettingsAdapterFor(), - $"{coreName} Settings", - getCachedSettingsInfo(CreateCoreComm()), - isMovieActive: MovieSession.Movie.IsActive())); - ToolStripMenuItemEx CreateCoreSubmenu(VSystemCategory cat, string coreName, params ToolStripItem[] items) - { - ToolStripMenuItemEx submenu = new() { Tag = cat, Text = coreName }; - submenu.DropDownItems.AddRange(items); - return submenu; - } - - List items = new(); - - // A7800Hawk - var a7800HawkGamepadSettingsItem = CreateSettingsItem("Controller Settings...", (_, _) => OpenA7800HawkGamepadSettingsDialog(GetSettingsAdapterFor())); - var a7800HawkFilterSettingsItem = CreateSettingsItem("Filter Settings...", (_, _) => OpenA7800HawkFilterSettingsDialog(GetSettingsAdapterFor())); - var a7800HawkSubmenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.A7800Hawk, a7800HawkGamepadSettingsItem, a7800HawkFilterSettingsItem); - a7800HawkSubmenu.DropDownOpened += (_, _) => a7800HawkGamepadSettingsItem.Enabled = a7800HawkFilterSettingsItem.Enabled = MovieSession.Movie.NotActive() || Emulator is not A7800Hawk; - items.Add(a7800HawkSubmenu); - - // Ares64 - var ares64AnalogConstraintItem = CreateSettingsItem("Circular Analog Range", N64CircularAnalogRangeMenuItem_Click); - var ares64Submenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Ares64, CreateGenericCoreConfigItem(CoreNames.Ares64)); - ares64Submenu.DropDownOpened += (_, _) => ares64AnalogConstraintItem.Checked = Config.N64UseCircularAnalogConstraint; - items.Add(ares64Submenu); - - // Atari2600Hawk - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Atari2600Hawk, CreateGenericCoreConfigItem(CoreNames.Atari2600Hawk))); - - // BSNES - var oldBSNESGamepadSettingsItem = CreateSettingsItem("Controller Configuration...", (_, _) => OpenOldBSNESGamepadSettingsDialog(GetSettingsAdapterFor())); - var oldBSNESSettingsItem = CreateSettingsItem("Options...", (_, _) => OpenOldBSNESSettingsDialog(GetSettingsAdapterFor())); - var oldBSNESSubmenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Bsnes, oldBSNESGamepadSettingsItem, oldBSNESSettingsItem); - oldBSNESSubmenu.DropDownOpened += (_, _) => oldBSNESGamepadSettingsItem.Enabled = MovieSession.Movie.NotActive() || Emulator is not LibsnesCore; - items.Add(oldBSNESSubmenu); - - // BSNESv115+ - var bsnesGamepadSettingsItem = CreateSettingsItem("Controller Configuration...", (_, _) => OpenBSNESGamepadSettingsDialog(GetSettingsAdapterFor())); - var bsnesSettingsItem = CreateSettingsItem("Options...", (_, _) => OpenBSNESSettingsDialog(GetSettingsAdapterFor())); - var bsnesSubmenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Bsnes115, bsnesGamepadSettingsItem, bsnesSettingsItem); - bsnesSubmenu.DropDownOpened += (_, _) => bsnesGamepadSettingsItem.Enabled = MovieSession.Movie.NotActive() || Emulator is not BsnesCore; - items.Add(bsnesSubmenu); - - // SubBSNESv115+ - var subBsnesGamepadSettingsItem = CreateSettingsItem("Controller Configuration...", (_, _) => OpenBSNESGamepadSettingsDialog(GetSettingsAdapterFor())); - var subBsnesSettingsItem = CreateSettingsItem("Options...", (_, _) => OpenBSNESSettingsDialog(GetSettingsAdapterFor())); - var subBsnesSubmenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.SubBsnes115, subBsnesGamepadSettingsItem, subBsnesSettingsItem); - subBsnesSubmenu.DropDownOpened += (_, _) => subBsnesGamepadSettingsItem.Enabled = MovieSession.Movie.NotActive() || Emulator is not SubBsnesCore; - items.Add(subBsnesSubmenu); - - // C64Hawk - items.Add(CreateCoreSubmenu(VSystemCategory.PCs, CoreNames.C64Hawk, CreateSettingsItem("Settings...", (_, _) => OpenC64HawkSettingsDialog()))); - - // ChannelFHawk - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.ChannelFHawk, CreateGenericCoreConfigItem(CoreNames.ChannelFHawk))); - - // Encore - items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.Encore, CreateGenericCoreConfigItem(CoreNames.Encore))); - - // ColecoHawk - var colecoHawkGamepadSettingsItem = CreateSettingsItem("Controller Settings...", (_, _) => OpenColecoHawkGamepadSettingsDialog(GetSettingsAdapterFor())); - var colecoHawkSkipBIOSItem = CreateSettingsItem("Skip BIOS intro (When Applicable)", (sender, _) => ColecoHawkSetSkipBIOSIntro(!((ToolStripMenuItem) sender).Checked, GetSettingsAdapterFor())); - var colecoHawkUseSGMItem = CreateSettingsItem("Use the Super Game Module", (sender, _) => ColecoHawkSetSuperGameModule(!((ToolStripMenuItem) sender).Checked, GetSettingsAdapterFor())); - var colecoHawkSubmenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.ColecoHawk, colecoHawkGamepadSettingsItem, colecoHawkSkipBIOSItem, colecoHawkUseSGMItem); - colecoHawkSubmenu.DropDownOpened += (_, _) => - { - var ss = (ColecoVision.ColecoSyncSettings) GetSettingsAdapterFor().GetSyncSettings(); - colecoHawkGamepadSettingsItem.Enabled = MovieSession.Movie.NotActive() || Emulator is not ColecoVision; - colecoHawkSkipBIOSItem.Checked = ss.SkipBiosIntro; - colecoHawkUseSGMItem.Checked = ss.UseSGM; - }; - items.Add(colecoHawkSubmenu); - - // CPCHawk - items.Add(CreateCoreSubmenu( - VSystemCategory.PCs, - CoreNames.CPCHawk, - CreateSettingsItem("Core Emulation Settings...", (_, _) => OpenCPCHawkSyncSettingsDialog(GetSettingsAdapterFor())), - CreateSettingsItem("Audio Settings...", (_, _) => OpenCPCHawkAudioSettingsDialog(GetSettingsAdapterFor())), - CreateSettingsItem("Non-Sync Settings...", (_, _) => OpenCPCHawkSettingsDialog(GetSettingsAdapterFor())))); - - // Cygne - items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.Cygne, CreateGenericCoreConfigItem(CoreNames.Cygne))); - - // Emu83 - items.Add(CreateCoreSubmenu(VSystemCategory.Other, CoreNames.Emu83, CreateSettingsItem("Palette...", (_, _) => OpenTI83PaletteSettingsDialog(GetSettingsAdapterFor())))); - - // Faust - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Faust, CreateGenericNymaCoreConfigItem(CoreNames.Faust, Faust.CachedSettingsInfo))); - - // Gambatte - items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.Gambatte, CreateSettingsItem("Settings...", (_, _) => OpenGambatteSettingsDialog(GetSettingsAdapterFor())))); - if (includeDupes) items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Gambatte, CreateSettingsItem("Settings...", (_, _) => OpenGambatteSettingsDialog(GetSettingsAdapterFor())))); - - // GambatteLink - items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.GambatteLink, CreateSettingsItem("Settings...", (_, _) => OpenGambatteLinkSettingsDialog(GetSettingsAdapterFor())))); - - // GBHawk - items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.GbHawk, CreateSettingsItem("Settings...", (_, _) => OpenGBHawkSettingsDialog()))); - - // GBHawkLink - items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.GBHawkLink, CreateGenericCoreConfigItem(CoreNames.GBHawkLink))); - - // GBHawkLink3x - items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.GBHawkLink3x, CreateGenericCoreConfigItem(CoreNames.GBHawkLink3x))); - - // GBHawkLink4x - items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.GBHawkLink4x, CreateGenericCoreConfigItem(CoreNames.GBHawkLink4x))); - - // GGHawkLink - items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.GGHawkLink, CreateGenericCoreConfigItem(CoreNames.GGHawkLink))); - - // Genplus-gx - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Gpgx, CreateGenericCoreConfigItem(CoreNames.Gpgx))); - - // Handy - items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.Handy, CreateGenericCoreConfigItem(CoreNames.Handy))); // as Handy doesn't implement `ISettable<,>`, this opens an empty `GenericCoreConfig`, which is dumb, but matches the existing behaviour - - // HyperNyma - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.HyperNyma, CreateGenericNymaCoreConfigItem(CoreNames.HyperNyma, HyperNyma.CachedSettingsInfo))); - - // IntelliHawk - var intelliHawkGamepadSettingsItem = CreateSettingsItem("Controller Settings...", (_, _) => OpenIntelliHawkGamepadSettingsDialog(GetSettingsAdapterFor())); - var intelliHawkSubmenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.IntelliHawk, intelliHawkGamepadSettingsItem); - intelliHawkSubmenu.DropDownOpened += (_, _) => intelliHawkGamepadSettingsItem.Enabled = MovieSession.Movie.NotActive() || Emulator is not Intellivision; - items.Add(intelliHawkSubmenu); - - // Libretro - items.Add(CreateCoreSubmenu( - VSystemCategory.Other, - CoreNames.Libretro, - CreateGenericCoreConfigItem(CoreNames.Libretro))); // as Libretro doesn't implement `ISettable<,>`, this opens an empty `GenericCoreConfig`, which is dumb, but matches the existing behaviour - - // MAME - var mameSettingsItem = CreateSettingsItem("Settings...", (_, _) => OpenGenericCoreConfig()); - var mameSubmenu = CreateCoreSubmenu(VSystemCategory.Other, CoreNames.MAME, mameSettingsItem); - mameSubmenu.DropDownOpened += (_, _) => mameSettingsItem.Enabled = Emulator is MAME; - items.Add(mameSubmenu); - - // melonDS - items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.MelonDS, CreateGenericCoreConfigItem(CoreNames.MelonDS))); - - // mGBA - items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.Mgba, CreateGenericCoreConfigItem(CoreNames.Mgba))); - - // MSXHawk - items.Add(CreateCoreSubmenu(VSystemCategory.PCs, CoreNames.MSXHawk, CreateGenericCoreConfigItem(CoreNames.MSXHawk))); - - // Mupen64Plus - var mupen64PlusGraphicsSettingsItem = CreateSettingsItem("Video Plugins...", N64PluginSettingsMenuItem_Click); - var mupen64PlusGamepadSettingsItem = CreateSettingsItem("Controller Settings...", (_, _) => OpenMupen64PlusGamepadSettingsDialog(GetSettingsAdapterFor())); - var mupen64PlusAnalogConstraintItem = CreateSettingsItem("Circular Analog Range", N64CircularAnalogRangeMenuItem_Click); - var mupen64PlusMupenStyleLagFramesItem = CreateSettingsItem("Mupen Style Lag Frames", (sender, _) => Mupen64PlusSetMupenStyleLag(!((ToolStripMenuItem) sender).Checked, GetSettingsAdapterFor())); - var mupen64PlusUseExpansionSlotItem = CreateSettingsItem("Use Expansion Slot", (sender, _) => Mupen64PlusSetUseExpansionSlot(!((ToolStripMenuItem) sender).Checked, GetSettingsAdapterFor())); - var mupen64PlusSubmenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Mupen64Plus, mupen64PlusGraphicsSettingsItem, mupen64PlusGamepadSettingsItem, mupen64PlusAnalogConstraintItem, mupen64PlusMupenStyleLagFramesItem, mupen64PlusUseExpansionSlotItem); - mupen64PlusSubmenu.DropDownOpened += (_, _) => - { - var settable = GetSettingsAdapterFor(); - var s = (N64Settings) settable.GetSettings(); - var isMovieActive = MovieSession.Movie.IsActive(); - var mupen64Plus = Emulator as N64; - var loadedCoreIsMupen64Plus = mupen64Plus is not null; - mupen64PlusGraphicsSettingsItem.Enabled = !loadedCoreIsMupen64Plus || !isMovieActive; - mupen64PlusGamepadSettingsItem.Enabled = !loadedCoreIsMupen64Plus || !isMovieActive; - mupen64PlusAnalogConstraintItem.Checked = Config.N64UseCircularAnalogConstraint; - mupen64PlusMupenStyleLagFramesItem.Checked = s.UseMupenStyleLag; - if (loadedCoreIsMupen64Plus) - { - mupen64PlusUseExpansionSlotItem.Checked = mupen64Plus.UsingExpansionSlot; - mupen64PlusUseExpansionSlotItem.Enabled = !mupen64Plus.IsOverridingUserExpansionSlotSetting; - } - else - { - mupen64PlusUseExpansionSlotItem.Checked = !((N64SyncSettings) settable.GetSyncSettings()).DisableExpansionSlot; - mupen64PlusUseExpansionSlotItem.Enabled = true; - } - }; - items.Add(mupen64PlusSubmenu); - - // NeoPop - items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.NeoPop, CreateGenericNymaCoreConfigItem(CoreNames.NeoPop, NeoGeoPort.CachedSettingsInfo))); - - // NesHawk - var nesHawkGamepadSettingsItem = CreateSettingsItem("Controller Settings...", (_, _) => OpenNesHawkGamepadSettingsDialog(GetSettingsAdapterFor())); - var nesHawkVSSettingsItem = CreateSettingsItem("VS Settings...", (_, _) => OpenNesHawkVSSettingsDialog(GetSettingsAdapterFor())); - var nesHawkAdvancedSettingsItem = CreateSettingsItem("Advanced Settings...", (_, _) => OpenNesHawkAdvancedSettingsDialog(GetSettingsAdapterFor(), Emulator is not NES nesHawk || nesHawk.HasMapperProperties)); - var nesHawkSubmenu = CreateCoreSubmenu( - VSystemCategory.Consoles, - CoreNames.NesHawk, - nesHawkGamepadSettingsItem, - CreateSettingsItem("Graphics Settings...", (_, _) => OpenNesHawkGraphicsSettingsDialog(GetSettingsAdapterFor())), - nesHawkVSSettingsItem, - nesHawkAdvancedSettingsItem); - nesHawkSubmenu.DropDownOpened += (_, _) => - { - var nesHawk = Emulator as NES; - var canEditSyncSettings = nesHawk is null || MovieSession.Movie.NotActive(); - nesHawkGamepadSettingsItem.Enabled = canEditSyncSettings && Tools.IsAvailable(); - nesHawkVSSettingsItem.Enabled = nesHawk?.IsVS is null or true; - nesHawkAdvancedSettingsItem.Enabled = canEditSyncSettings; - }; - items.Add(nesHawkSubmenu); - - // Nymashock - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Nymashock, CreateGenericNymaCoreConfigItem(CoreNames.Nymashock, Nymashock.CachedSettingsInfo))); - - // O2Hawk - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.O2Hawk, CreateGenericCoreConfigItem(CoreNames.O2Hawk))); - - // Octoshock - var octoshockGamepadSettingsItem = CreateSettingsItem("Controller / Memcard Settings...", (_, _) => OpenOctoshockGamepadSettingsDialog(GetSettingsAdapterFor())); - var octoshockSettingsItem = CreateSettingsItem("Options...", PsxOptionsMenuItem_Click); - // using init buffer sizes here (in practice, they don't matter here, but might as well) - var octoshockNTSCSettingsItem = CreateSettingsItem("Options (as NTSC)...", (_, _) => OpenOctoshockSettingsDialog(GetSettingsAdapterFor(), OctoshockDll.eVidStandard.NTSC, new(280, 240))); - var octoshockPALSettingsItem = CreateSettingsItem("Options (as PAL)...", (_, _) => OpenOctoshockSettingsDialog(GetSettingsAdapterFor(), OctoshockDll.eVidStandard.PAL, new(280, 288))); - var octoshockSubmenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Octoshock, octoshockGamepadSettingsItem, octoshockSettingsItem, octoshockNTSCSettingsItem, octoshockPALSettingsItem); - octoshockSubmenu.DropDownOpened += (_, _) => - { - var loadedCoreIsOctoshock = Emulator is Octoshock; - octoshockGamepadSettingsItem.Enabled = !loadedCoreIsOctoshock || MovieSession.Movie.NotActive(); - octoshockSettingsItem.Visible = loadedCoreIsOctoshock; - octoshockNTSCSettingsItem.Visible = octoshockPALSettingsItem.Visible = !loadedCoreIsOctoshock; - }; - items.Add(octoshockSubmenu); - - // PCEHawk - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.PceHawk, CreateGenericCoreConfigItem(CoreNames.PceHawk))); - - // PicoDrive - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.PicoDrive, CreateGenericCoreConfigItem(CoreNames.PicoDrive))); - - // QuickNes - var quickNesGamepadSettingsItem = CreateSettingsItem("Controller Settings...", (_, _) => OpenQuickNesGamepadSettingsDialog(GetSettingsAdapterFor())); - var quickNesSubmenu = CreateCoreSubmenu( - VSystemCategory.Consoles, - CoreNames.QuickNes, - quickNesGamepadSettingsItem, - CreateSettingsItem("Graphics Settings...", (_, _) => OpenQuickNesGraphicsSettingsDialog(GetSettingsAdapterFor()))); - quickNesSubmenu.DropDownOpened += (_, _) => quickNesGamepadSettingsItem.Enabled = (MovieSession.Movie.NotActive() || Emulator is not QuickNES) && Tools.IsAvailable(); - items.Add(quickNesSubmenu); - - // SameBoy - items.Add(CreateCoreSubmenu( - VSystemCategory.Handhelds, - CoreNames.Sameboy, - CreateSettingsItem("Settings...", (_, _) => OpenSameBoySettingsDialog()), - CreateSettingsItem("Choose Custom Palette...", (_, _) => OpenSameBoyPaletteSettingsDialog(GetSettingsAdapterFor())))); - - // Saturnus - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Saturnus, CreateGenericNymaCoreConfigItem(CoreNames.Saturnus, Saturnus.CachedSettingsInfo))); - - // SMSHawk - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.SMSHawk, CreateGenericCoreConfigItem(CoreNames.SMSHawk))); - if (includeDupes) items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.SMSHawk, CreateGenericCoreConfigItem(CoreNames.SMSHawk))); - - // Snes9x - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Snes9X, CreateGenericCoreConfigItem(CoreNames.Snes9X))); - - // SubGBHawk - items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.SubGbHawk, CreateSettingsItem("Settings...", (_, _) => OpenSubGBHawkSettingsDialog()))); - - // SubNESHawk - var subNESHawkGamepadSettingsItem = CreateSettingsItem("Controller Settings...", (_, _) => OpenNesHawkGamepadSettingsDialog(GetSettingsAdapterFor())); - var subNESHawkVSSettingsItem = CreateSettingsItem("VS Settings...", (_, _) => OpenNesHawkVSSettingsDialog(GetSettingsAdapterFor())); - var subNESHawkAdvancedSettingsItem = CreateSettingsItem("Advanced Settings...", (_, _) => OpenNesHawkAdvancedSettingsDialog(GetSettingsAdapterFor(), Emulator is not SubNESHawk subNESHawk || subNESHawk.HasMapperProperties)); - var subNESHawkSubmenu = CreateCoreSubmenu( - VSystemCategory.Consoles, - CoreNames.SubNesHawk, - subNESHawkGamepadSettingsItem, - CreateSettingsItem("Graphics Settings...", (_, _) => OpenNesHawkGraphicsSettingsDialog(GetSettingsAdapterFor())), - subNESHawkVSSettingsItem, - subNESHawkAdvancedSettingsItem); - subNESHawkSubmenu.DropDownOpened += (_, _) => - { - var subNESHawk = Emulator as SubNESHawk; - var canEditSyncSettings = subNESHawk is null || MovieSession.Movie.NotActive(); - subNESHawkGamepadSettingsItem.Enabled = canEditSyncSettings && Tools.IsAvailable(); - subNESHawkVSSettingsItem.Enabled = subNESHawk?.IsVs is null or true; - subNESHawkAdvancedSettingsItem.Enabled = canEditSyncSettings; - }; - items.Add(subNESHawkSubmenu); - - // TI83Hawk - items.Add(CreateCoreSubmenu(VSystemCategory.Other, CoreNames.TI83Hawk, CreateSettingsItem("Palette...", (_, _) => OpenTI83PaletteSettingsDialog(GetSettingsAdapterFor())))); - - // TIC80 - items.Add(CreateCoreSubmenu(VSystemCategory.PCs, CoreNames.TIC80, CreateGenericCoreConfigItem(CoreNames.TIC80))); - - // T. S. T. - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.TST, CreateGenericNymaCoreConfigItem(CoreNames.TST, Tst.CachedSettingsInfo))); - - // TurboNyma - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.TurboNyma, CreateGenericNymaCoreConfigItem(CoreNames.TurboNyma, TurboNyma.CachedSettingsInfo))); - - // uzem - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Uzem, CreateGenericCoreConfigItem(CoreNames.Uzem))); // as uzem doesn't implement `ISettable<,>`, this opens an empty `GenericCoreConfig`, which is dumb, but matches the existing behaviour - - // VectrexHawk - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.VectrexHawk, CreateGenericCoreConfigItem(CoreNames.VectrexHawk))); - - // Virtu - items.Add(CreateCoreSubmenu(VSystemCategory.PCs, CoreNames.Virtu, CreateSettingsItem("Settings...", (_, _) => OpenVirtuSettingsDialog()))); - - // Virtual Boyee - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.VirtualBoyee, CreateGenericNymaCoreConfigItem(CoreNames.VirtualBoyee, VirtualBoyee.CachedSettingsInfo))); - - // Virtual Jaguar - items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.VirtualJaguar, CreateGenericCoreConfigItem(CoreNames.VirtualJaguar))); - - // ZXHawk - items.Add(CreateCoreSubmenu( - VSystemCategory.PCs, - CoreNames.ZXHawk, - CreateSettingsItem("Core Emulation Settings...", (_, _) => OpenZXHawkSyncSettingsDialog(GetSettingsAdapterFor())), - CreateSettingsItem("Joystick Configuration...", (_, _) => OpenZXHawkGamepadSettingsDialog(GetSettingsAdapterFor())), - CreateSettingsItem("Audio Settings...", (_, _) => OpenZXHawkAudioSettingsDialog(GetSettingsAdapterFor())), - CreateSettingsItem("Non-Sync Settings...", (_, _) => OpenZXHawkSettingsDialog(GetSettingsAdapterFor())))); - - return items; - } } } diff --git a/src/BizHawk.Client.EmuHawk/MainForm.FileLoader.cs b/src/BizHawk.Client.EmuHawk/MainForm.FileLoader.cs index 3e094cdbb1b..8ff033e2dda 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.FileLoader.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.FileLoader.cs @@ -1,9 +1,7 @@ -using System; using System.IO; using System.Linq; using System.Collections.Generic; -using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Client.Common; using BizHawk.Common.PathExtensions; @@ -95,17 +93,11 @@ public bool LoadMovie(string filename, string archive = null) } return Tools.IsLoaded() ? Tools.TAStudio.LoadMovieFile(filename) - : StartNewMovie(MovieSession.Get(filename), false); + : StartNewMovie(MovieSession.Get(filename, true), false); } private bool LoadRom(string filename, string archive = null) - { - var args = new LoadRomArgs - { - OpenAdvanced = new OpenAdvanced_OpenRom {Path = filename} - }; - return LoadRom(filename, args); - } + => LoadRom(filename, new LoadRomArgs(new OpenAdvanced_OpenRom(filename))); private bool LoadStateFile(string filename, string archive = null) => LoadState(path: filename, userFriendlyStateName: Path.GetFileName(filename)); @@ -169,15 +161,12 @@ private void ProcessFileList(IEnumerable fileList, ref Dictionary getter, - Action setter) - { - if (Emulator is not Gameboy gb) return; - if (gb.DeterministicEmulation) - { - AddOnScreenMessage($"{name} cannot be toggled during movie recording."); - return; - } - var ss = gb.GetSyncSettings(); - var newState = !getter(ss); - setter(ss, newState); - gb.PutSyncSettings(ss); - AddOnScreenMessage($"{name} toggled {(newState ? "on" : "off")}"); - } switch (trigger) { @@ -113,7 +94,7 @@ void ToggleGambatteSyncSetting( ToggleBackgroundInput(); break; case "Toggle Menu": - MainMenuStrip.Visible ^= true; + ShowMenuContextMenuItem_Click(this, EventArgs.Empty); break; case "Volume Up": VolumeUp(); @@ -152,22 +133,21 @@ void ToggleGambatteSyncSetting( RebootCore(); break; case "Toggle Skip Lag Frame": - Config.SkipLagFrame ^= true; + Config.SkipLagFrame = !Config.SkipLagFrame; AddOnScreenMessage($"Skip Lag Frames toggled {(Config.SkipLagFrame ? "On" : "Off")}"); break; case "Toggle Key Priority": ToggleKeyPriority(); break; case "Toggle Messages": - Config.DisplayMessages ^= true; + DisplayMessagesMenuItem_Click(this, EventArgs.Empty); break; case "Toggle Display Nothing": // TODO: account for 1 when implemented Config.DispSpeedupFeatures = Config.DispSpeedupFeatures == 0 ? 2 : 0; break; case "Accept Background Input": - Config.AcceptBackgroundInput ^= true; - AddOnScreenMessage($"Accept Background Input toggled {(Config.AcceptBackgroundInput ? "On" : "Off")}"); + ToggleBackgroundInput(); break; // Save States @@ -297,16 +277,16 @@ void ToggleGambatteSyncSetting( // Tools case "RAM Watch": - Tools.LoadRamWatch(true); + RamWatchMenuItem_Click(this, EventArgs.Empty); break; case "RAM Search": - Tools.Load(); + RamSearchMenuItem_Click(this, EventArgs.Empty); break; case "Hex Editor": - Tools.Load(); + HexEditorMenuItem_Click(this, EventArgs.Empty); break; case "Trace Logger": - Tools.Load(); + TraceLoggerMenuItem_Click(this, EventArgs.Empty); break; case "Lua Console": OpenLuaConsole(); @@ -318,7 +298,7 @@ void ToggleGambatteSyncSetting( } break; case "Cheats": - Tools.Load(); + CheatsMenuItem_Click(this, EventArgs.Empty); break; case "Toggle All Cheats": var cheats = CheatList.Where(static c => !c.IsSeparator).ToList(); @@ -336,10 +316,10 @@ void ToggleGambatteSyncSetting( TAStudioMenuItem_Click(null, null); break; case "ToolBox": - Tools.Load(); + ToolBoxMenuItem_Click(this, EventArgs.Empty); break; case "Virtual Pad": - Tools.Load(); + VirtualPadMenuItem_Click(this, EventArgs.Empty); break; // RAM Search @@ -384,15 +364,18 @@ void ToggleGambatteSyncSetting( break; case "Toggle Follow Cursor": if (!Tools.IsLoaded()) return false; - Tools.TAStudio.TasPlaybackBox.FollowCursor ^= true; + var playbackBox = Tools.TAStudio.TasPlaybackBox; + playbackBox.FollowCursor = !playbackBox.FollowCursor; break; case "Toggle Auto-Restore": if (!Tools.IsLoaded()) return false; - Tools.TAStudio.TasPlaybackBox.AutoRestore ^= true; + var playbackBox1 = Tools.TAStudio.TasPlaybackBox; + playbackBox1.AutoRestore = !playbackBox1.AutoRestore; break; case "Toggle Turbo Seek": if (!Tools.IsLoaded()) return false; - Tools.TAStudio.TasPlaybackBox.TurboSeek ^= true; + var playbackBox2 = Tools.TAStudio.TasPlaybackBox; + playbackBox2.TurboSeek = !playbackBox2.TurboSeek; break; case "Undo": if (!Tools.IsLoaded()) return false; @@ -487,22 +470,13 @@ void ToggleGambatteSyncSetting( // GB case "GB Toggle BG": - ToggleGambatteSyncSetting( - "BG", - static ss => ss.DisplayBG, - static (ss, newState) => ss.DisplayBG = newState); + GB_ToggleBackgroundLayer(); break; case "GB Toggle Obj": - ToggleGambatteSyncSetting( - "OBJ", - static ss => ss.DisplayOBJ, - static (ss, newState) => ss.DisplayOBJ = newState); + GB_ToggleObjectLayer(); break; case "GB Toggle Window": - ToggleGambatteSyncSetting( - "WIN", - static ss => ss.DisplayWindow, - static (ss, newState) => ss.DisplayWindow = newState); + GB_ToggleWindowLayer(); break; // Analog @@ -533,66 +507,19 @@ void ToggleGambatteSyncSetting( // DS case "Next Screen Layout": - IncrementDSLayout(1); + NDS_IncrementLayout(1); break; case "Previous Screen Layout": - IncrementDSLayout(-1); + NDS_IncrementLayout(-1); break; case "Screen Rotate": - IncrementDSScreenRotate(); + NDS_IncrementScreenRotate(); break; } return true; } - private void IncrementDSScreenRotate() - { - if (Emulator is NDS ds) - { - var settings = ds.GetSettings(); - settings.ScreenRotation = settings.ScreenRotation switch - { - NDS.ScreenRotationKind.Rotate0 => settings.ScreenRotation = NDS.ScreenRotationKind.Rotate90, - NDS.ScreenRotationKind.Rotate90 => settings.ScreenRotation = NDS.ScreenRotationKind.Rotate180, - NDS.ScreenRotationKind.Rotate180 => settings.ScreenRotation = NDS.ScreenRotationKind.Rotate270, - NDS.ScreenRotationKind.Rotate270 => settings.ScreenRotation = NDS.ScreenRotationKind.Rotate0, - _ => settings.ScreenRotation - }; - ds.PutSettings(settings); - AddOnScreenMessage($"Screen rotation to {settings.ScreenRotation}"); - FrameBufferResized(); - } - } - - private void IncrementDSLayout(int delta) - { - bool decrement = delta == -1; - if (Emulator is NDS ds) - { - var settings = ds.GetSettings(); - var num = (int)settings.ScreenLayout; - if (decrement) - { - num--; - } - else - { - num++; - } - - var next = (NDS.ScreenLayoutKind)Enum.Parse(typeof(NDS.ScreenLayoutKind), num.ToString()); - if (typeof(NDS.ScreenLayoutKind).IsEnumDefined(next)) - { - settings.ScreenLayout = next; - - ds.PutSettings(settings); - AddOnScreenMessage($"Screen layout to {next}"); - FrameBufferResized(); - } - } - } - // Determines if the value is a hotkey that would be handled outside of the CheckHotkey method private bool IsInternalHotkey(string trigger) { diff --git a/src/BizHawk.Client.EmuHawk/MainForm.Movie.cs b/src/BizHawk.Client.EmuHawk/MainForm.Movie.cs index 6412e720124..a4e8564e7b4 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.Movie.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.Movie.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Windows.Forms; @@ -27,7 +26,12 @@ public bool StartNewMovie(IMovie movie, bool record) { try { - MovieSession.QueueNewMovie(movie, record, Emulator.SystemId, Config.PreferredCores); + MovieSession.QueueNewMovie( + movie, + systemId: Emulator.SystemId, + loadedRomHash: Game.Hash, + Config.PathEntries, + Config.PreferredCores); } catch (MoviePlatformMismatchException ex) { @@ -54,6 +58,7 @@ public bool StartNewMovie(IMovie movie, bool record) SetMainformMovieInfo(); + // turns out this was too late for .tasproj autoloading and restoring playback position (loads savestate but wasn't checking game match) if (string.IsNullOrEmpty(MovieSession.Movie.Hash)) { AddOnScreenMessage("Movie is missing hash, skipping hash check"); @@ -94,9 +99,9 @@ public void SetMainformMovieInfo() public void StopMovie(bool saveChanges = true) { - if (IsSlave && Master.WantsToControlStopMovie) + if (ToolControllingStopMovie is { } tool) { - Master.StopMovie(!saveChanges); + tool.StopMovie(!saveChanges); } else { @@ -107,7 +112,7 @@ public void StopMovie(bool saveChanges = true) public bool RestartMovie() { - if (IsSlave && Master.WantsToControlRestartMovie) return Master.RestartMovie(); + if (ToolControllingRestartMovie is { } tool) return tool.RestartMovie(); if (!MovieSession.Movie.IsActive()) return false; var success = StartNewMovie(MovieSession.Movie, false); if (success) AddOnScreenMessage("Replaying movie file in read-only mode"); @@ -116,15 +121,15 @@ public bool RestartMovie() private void ToggleReadOnly() { - if (IsSlave && Master.WantsToControlReadOnly) + if (ToolControllingReadOnly is { } tool) { - Master.ToggleReadOnly(); + tool.ToggleReadOnly(); } else { if (MovieSession.Movie.IsActive()) { - MovieSession.ReadOnly ^= true; + MovieSession.ReadOnly = !MovieSession.ReadOnly; AddOnScreenMessage(MovieSession.ReadOnly ? "Movie read-only mode" : "Movie read+write mode"); } else diff --git a/src/BizHawk.Client.EmuHawk/MainForm.VSystem.cs b/src/BizHawk.Client.EmuHawk/MainForm.VSystem.cs new file mode 100644 index 00000000000..7d0def6e14b --- /dev/null +++ b/src/BizHawk.Client.EmuHawk/MainForm.VSystem.cs @@ -0,0 +1,1521 @@ +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Runtime.CompilerServices; +using System.Windows.Forms; + +using BizHawk.Client.Common; +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores; +using BizHawk.Emulation.Cores.Arcades.MAME; +using BizHawk.Emulation.Cores.Atari.A7800Hawk; +using BizHawk.Emulation.Cores.Atari.Atari2600; +using BizHawk.Emulation.Cores.Atari.Jaguar; +using BizHawk.Emulation.Cores.Atari.Lynx; +using BizHawk.Emulation.Cores.Calculators.Emu83; +using BizHawk.Emulation.Cores.Calculators.TI83; +using BizHawk.Emulation.Cores.ColecoVision; +using BizHawk.Emulation.Cores.Computers.Amiga; +using BizHawk.Emulation.Cores.Computers.AmstradCPC; +using BizHawk.Emulation.Cores.Computers.AppleII; +using BizHawk.Emulation.Cores.Computers.Commodore64; +using BizHawk.Emulation.Cores.Computers.MSX; +using BizHawk.Emulation.Cores.Computers.SinclairSpectrum; +using BizHawk.Emulation.Cores.Computers.TIC80; +using BizHawk.Emulation.Cores.Consoles.Belogic; +using BizHawk.Emulation.Cores.Consoles.ChannelF; +using BizHawk.Emulation.Cores.Consoles.NEC.PCE; +using BizHawk.Emulation.Cores.Consoles.NEC.PCFX; +using BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64; +using BizHawk.Emulation.Cores.Consoles.Nintendo.Faust; +using BizHawk.Emulation.Cores.Consoles.Nintendo.N3DS; +using BizHawk.Emulation.Cores.Consoles.Nintendo.NDS; +using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES; +using BizHawk.Emulation.Cores.Consoles.Nintendo.VB; +using BizHawk.Emulation.Cores.Consoles.O2Hawk; +using BizHawk.Emulation.Cores.Consoles.SNK; +using BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive; +using BizHawk.Emulation.Cores.Consoles.Sega.Saturn; +using BizHawk.Emulation.Cores.Consoles.Sega.gpgx; +using BizHawk.Emulation.Cores.Consoles.Vectrex; +using BizHawk.Emulation.Cores.Intellivision; +using BizHawk.Emulation.Cores.Libretro; +using BizHawk.Emulation.Cores.Nintendo.BSNES; +using BizHawk.Emulation.Cores.Nintendo.GBA; +using BizHawk.Emulation.Cores.Nintendo.GBHawk; +using BizHawk.Emulation.Cores.Nintendo.GBHawkLink3x; +using BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x; +using BizHawk.Emulation.Cores.Nintendo.GBHawkLink; +using BizHawk.Emulation.Cores.Nintendo.Gameboy; +using BizHawk.Emulation.Cores.Nintendo.N64; +using BizHawk.Emulation.Cores.Nintendo.NES; +using BizHawk.Emulation.Cores.Nintendo.SNES9X; +using BizHawk.Emulation.Cores.Nintendo.SNES; +using BizHawk.Emulation.Cores.Nintendo.Sameboy; +using BizHawk.Emulation.Cores.Nintendo.SubGBHawk; +using BizHawk.Emulation.Cores.Nintendo.SubNESHawk; +using BizHawk.Emulation.Cores.PCEngine; +using BizHawk.Emulation.Cores.Sega.GGHawkLink; +using BizHawk.Emulation.Cores.Sega.MasterSystem; +using BizHawk.Emulation.Cores.Sony.PSX; +using BizHawk.Emulation.Cores.Waterbox; +using BizHawk.Emulation.Cores.WonderSwan; +using BizHawk.WinForms.Controls; + +namespace BizHawk.Client.EmuHawk +{ + public partial class MainForm + { + private DialogResult OpenA7800HawkGamepadSettingsDialog(ISettingsAdapter settable) + { + using A7800ControllerSettings form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private void A7800ControllerSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + A7800Hawk => OpenA7800HawkGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private DialogResult OpenA7800HawkFilterSettingsDialog(ISettingsAdapter settable) + { + using A7800FilterSettings form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private void A7800FilterSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + A7800Hawk => OpenA7800HawkFilterSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private void A7800SubMenu_DropDownOpened(object sender, EventArgs e) + => A7800ControllerSettingsMenuItem.Enabled = A7800FilterSettingsMenuItem.Enabled + = MovieSession.Movie.NotActive(); + + + + private void AppleDisksSubMenu_DropDownOpened(object sender, EventArgs e) + { + AppleDisksSubMenu.DropDownItems.Clear(); + if (Emulator is not AppleII appleII) return; + EventHandler clickHandler = (clickSender, _) => + { + if (!object.ReferenceEquals(appleII, Emulator)) return; + appleII.SetDisk((int) ((Control) clickSender).Tag); + }; + var selected = appleII.CurrentDisk; + for (int i = 0; i < appleII.DiskCount; i++) + { + ToolStripMenuItem menuItem = new() + { + Checked = i == selected, + Tag = i, + Text = $"Disk{i + 1}", + }; + menuItem.Click += clickHandler; + AppleDisksSubMenu.DropDownItems.Add(menuItem); + } + } + + private DialogResult OpenVirtuSettingsDialog() + => OpenGenericCoreConfigFor(CoreNames.Virtu + " Settings"); + + private void AppleIISettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + AppleII => OpenVirtuSettingsDialog(), + _ => DialogResult.None + }; + + private void AppleSubMenu_DropDownOpened(object sender, EventArgs e) + { + if (Emulator is not AppleII a) return; + AppleDisksSubMenu.Enabled = a.DiskCount > 1; + } + + + + private void C64DisksSubMenu_DropDownOpened(object sender, EventArgs e) + { + C64DisksSubMenu.DropDownItems.Clear(); + if (Emulator is not C64 c64) return; + EventHandler clickHandler = (clickSender, _) => + { + if (!object.ReferenceEquals(c64, Emulator)) return; + c64.SetDisk((int) ((Control) clickSender).Tag); + }; + var selected = c64.CurrentDisk; + for (int i = 0; i < c64.DiskCount; i++) + { + ToolStripMenuItem menuItem = new() + { + Checked = i == selected, + Tag = i, + Text = $"Disk{i + 1}", + }; + menuItem.Click += clickHandler; + C64DisksSubMenu.DropDownItems.Add(menuItem); + } + } + + private DialogResult OpenC64HawkSettingsDialog() + => OpenGenericCoreConfigFor(CoreNames.C64Hawk + " Settings"); + + private void C64SettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + C64 => OpenC64HawkSettingsDialog(), + _ => DialogResult.None + }; + + private void C64SubMenu_DropDownOpened(object sender, EventArgs e) + { + if (Emulator is not C64 c64) return; + C64DisksSubMenu.Enabled = c64.DiskCount > 1; + } + + + + private DialogResult OpenColecoHawkGamepadSettingsDialog(ISettingsAdapter settable) + { + using ColecoControllerSettings form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private void ColecoControllerSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + ColecoVision => OpenColecoHawkGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private void ColecoHawkSetSkipBIOSIntro(bool newValue, ISettingsAdapter settable) + { + var ss = (ColecoVision.ColecoSyncSettings) settable.GetSyncSettings(); + ss.SkipBiosIntro = newValue; + settable.PutCoreSyncSettings(ss); + } + + private void ColecoSkipBiosMenuItem_Click(object sender, EventArgs e) + { + if (Emulator is ColecoVision) ColecoHawkSetSkipBIOSIntro(!((ToolStripMenuItem) sender).Checked, GetSettingsAdapterForLoadedCore()); + } + + private void ColecoHawkSetSuperGameModule(bool newValue, ISettingsAdapter settable) + { + var ss = (ColecoVision.ColecoSyncSettings) settable.GetSyncSettings(); + ss.UseSGM = newValue; + settable.PutCoreSyncSettings(ss); + } + + private void ColecoUseSGMMenuItem_Click(object sender, EventArgs e) + { + if (Emulator is ColecoVision) ColecoHawkSetSuperGameModule(!((ToolStripMenuItem) sender).Checked, GetSettingsAdapterForLoadedCore()); + } + + private void ColecoSubMenu_DropDownOpened(object sender, EventArgs e) + { + if (Emulator is not ColecoVision coleco) return; + var ss = coleco.GetSyncSettings(); + ColecoSkipBiosMenuItem.Checked = ss.SkipBiosIntro; + ColecoUseSGMMenuItem.Checked = ss.UseSGM; + ColecoControllerSettingsMenuItem.Enabled = MovieSession.Movie.NotActive(); + } + + + + private DialogResult OpenCPCHawkSyncSettingsDialog(ISettingsAdapter settable) + { + using AmstradCpcCoreEmulationSettings form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private void AmstradCpcCoreEmulationSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + AmstradCPC => OpenCPCHawkSyncSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private DialogResult OpenCPCHawkAudioSettingsDialog(ISettingsAdapter settable) + { + using AmstradCpcAudioSettings form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private void AmstradCpcAudioSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + AmstradCPC => OpenCPCHawkAudioSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private DialogResult OpenCPCHawkSettingsDialog(ISettingsAdapter settable) + { + using AmstradCpcNonSyncSettings form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private void AmstradCpcNonSyncSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + AmstradCPC => OpenCPCHawkSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private void AmstradCpcTapesSubMenu_DropDownOpened(object sender, EventArgs e) + { + AmstradCPCTapesSubMenu.DropDownItems.Clear(); + if (Emulator is not AmstradCPC ams) return; + EventHandler clickHandler = (clickSender, _) => + { + if (!object.ReferenceEquals(ams, Emulator)) return; + ams._machine.TapeMediaIndex = (int) ((Control) clickSender).Tag; + }; + var tapeMediaIndex = ams._machine.TapeMediaIndex; + for (int i = 0; i < ams._tapeInfo.Count; i++) + { + ToolStripMenuItem menuItem = new() + { + Checked = i == tapeMediaIndex, + Tag = i, + Text = $"{i}: {ams._tapeInfo[i].Name}", + }; + menuItem.Click += clickHandler; + AmstradCPCTapesSubMenu.DropDownItems.Add(menuItem); + } + } + + private void AmstradCpcDisksSubMenu_DropDownOpened(object sender, EventArgs e) + { + AmstradCPCDisksSubMenu.DropDownItems.Clear(); + if (Emulator is not AmstradCPC ams) return; + EventHandler clickHandler = (clickSender, _) => + { + if (!object.ReferenceEquals(ams, Emulator)) return; + ams._machine.DiskMediaIndex = (int) ((Control) clickSender).Tag; + }; + var diskMediaIndex = ams._machine.DiskMediaIndex; + for (int i = 0; i < ams._diskInfo.Count; i++) + { + ToolStripMenuItem menuItem = new() + { + Checked = i == diskMediaIndex, + Tag = i, + Text = $"{i}: {ams._diskInfo[i].Name}", + }; + menuItem.Click += clickHandler; + AmstradCPCDisksSubMenu.DropDownItems.Add(menuItem); + } + } + + private void AmstradCpcMediaMenuItem_DropDownOpened(object sender, EventArgs e) + { + if (Emulator is AmstradCPC cpc) + { + AmstradCPCTapesSubMenu.Enabled = cpc._tapeInfo.Count > 0; + AmstradCPCDisksSubMenu.Enabled = cpc._diskInfo.Count > 0; + } + } + + + + private DialogResult OpenGambatteSettingsDialog(ISettingsAdapter settable) + => GBPrefs.DoGBPrefsDialog(Config, this, Game, MovieSession, settable); + + private DialogResult OpenGBHawkSettingsDialog() + => OpenGenericCoreConfigFor(CoreNames.GbHawk + " Settings"); + + private DialogResult OpenSameBoySettingsDialog() + => OpenGenericCoreConfigFor(CoreNames.Sameboy + " Settings"); + + private DialogResult OpenSubGBHawkSettingsDialog() + => OpenGenericCoreConfigFor(CoreNames.SubGbHawk + " Settings"); + + private void GbCoreSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + Gameboy => OpenGambatteSettingsDialog(GetSettingsAdapterForLoadedCore()), + GBHawk => OpenGBHawkSettingsDialog(), + Sameboy => OpenSameBoySettingsDialog(), + SubGBHawk => OpenSubGBHawkSettingsDialog(), + _ => DialogResult.None + }; + + private DialogResult OpenSameBoyPaletteSettingsDialog(ISettingsAdapter settable) + { + using SameBoyColorChooserForm form = new(Config, this, Game, settable); + return this.ShowDialogWithTempMute(form); + } + + private void SameboyColorChooserMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + Sameboy => OpenSameBoyPaletteSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private void GbGpuViewerMenuItem_Click(object sender, EventArgs e) + => Tools.Load(); + + private void GbPrinterViewerMenuItem_Click(object sender, EventArgs e) + => Tools.Load(); + + private DialogResult OpenGambatteLinkSettingsDialog(ISettingsAdapter settable) + => GBLPrefs.DoGBLPrefsDialog(Config, this, Game, MovieSession, settable); + + private void GblSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + GambatteLink => OpenGambatteLinkSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void ToggleGambatteSyncSetting( + string name, + Func getter, + Action setter) + { + if (Emulator is not Gameboy gb) return; + if (gb.DeterministicEmulation) + { + AddOnScreenMessage($"{name} cannot be toggled during movie recording."); + return; + } + var ss = gb.GetSyncSettings(); + var newState = !getter(ss); + setter(ss, newState); + gb.PutSyncSettings(ss); + AddOnScreenMessage($"{name} toggled {(newState ? "on" : "off")}"); + } + + private void GB_ToggleBackgroundLayer() + => ToggleGambatteSyncSetting( + "BG", + static ss => ss.DisplayBG, + static (ss, newState) => ss.DisplayBG = newState); + + private void GB_ToggleObjectLayer() + => ToggleGambatteSyncSetting( + "OBJ", + static ss => ss.DisplayOBJ, + static (ss, newState) => ss.DisplayOBJ = newState); + + private void GB_ToggleWindowLayer() + => ToggleGambatteSyncSetting( + "WIN", + static ss => ss.DisplayWindow, + static (ss, newState) => ss.DisplayWindow = newState); + + + + private DialogResult OpenIntelliHawkGamepadSettingsDialog(ISettingsAdapter settable) + { + using IntvControllerSettings form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private void IntVControllerSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + Intellivision => OpenIntelliHawkGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private void IntVSubMenu_DropDownOpened(object sender, EventArgs e) + { + IntVControllerSettingsMenuItem.Enabled = MovieSession.Movie.NotActive(); + } + + + + private DialogResult OpenMupen64PlusGraphicsSettingsDialog(ISettingsAdapter settable) + { + using N64VideoPluginConfig form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private void N64PluginSettingsMenuItem_Click(object sender, EventArgs e) + { + if (OpenMupen64PlusGraphicsSettingsDialog(GetSettingsAdapterFor()).IsOk() + && Emulator is not N64) // If it's loaded, the reboot required message will appear + { + AddOnScreenMessage("Plugin settings saved"); + } + } + + private DialogResult OpenMupen64PlusGamepadSettingsDialog(ISettingsAdapter settable) + { + using N64ControllersSetup form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private void N64ControllerSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + N64 => OpenMupen64PlusGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private void N64CircularAnalogRangeMenuItem_Click(object sender, EventArgs e) + => Config.N64UseCircularAnalogConstraint = !Config.N64UseCircularAnalogConstraint; + + private static void Mupen64PlusSetMupenStyleLag(bool newValue, ISettingsAdapter settable) + { + var s = (N64Settings) settable.GetSettings(); + s.UseMupenStyleLag = newValue; + settable.PutCoreSettings(s); + } + + private void MupenStyleLagMenuItem_Click(object sender, EventArgs e) + => Mupen64PlusSetMupenStyleLag(!((ToolStripMenuItem) sender).Checked, GetSettingsAdapterForLoadedCore()); + + private void Mupen64PlusSetUseExpansionSlot(bool newValue, ISettingsAdapter settable) + { + var ss = (N64SyncSettings) settable.GetSyncSettings(); + ss.DisableExpansionSlot = !newValue; + settable.PutCoreSyncSettings(ss); + } + + private void N64ExpansionSlotMenuItem_Click(object sender, EventArgs e) + { + if (Emulator is not N64) return; + Mupen64PlusSetUseExpansionSlot(!((ToolStripMenuItem) sender).Checked, GetSettingsAdapterForLoadedCore()); + FlagNeedsReboot(); + } + + private void N64SubMenu_DropDownOpened(object sender, EventArgs e) + { + N64PluginSettingsMenuItem.Enabled = N64ControllerSettingsMenuItem.Enabled + = N64ExpansionSlotMenuItem.Enabled + = MovieSession.Movie.NotActive(); + N64CircularAnalogRangeMenuItem.Checked = Config.N64UseCircularAnalogConstraint; + var mupen = (N64) Emulator; + var s = mupen.GetSettings(); + MupenStyleLagMenuItem.Checked = s.UseMupenStyleLag; + N64ExpansionSlotMenuItem.Checked = mupen.UsingExpansionSlot; + N64ExpansionSlotMenuItem.Enabled = !mupen.IsOverridingUserExpansionSlotSetting; + } + + private void Ares64SettingsMenuItem_Click(object sender, EventArgs e) + => OpenGenericCoreConfigFor(CoreNames.Ares64 + " Settings"); + + private void Ares64SubMenu_DropDownOpened(object sender, EventArgs e) + => Ares64CircularAnalogRangeMenuItem.Checked = Config.N64UseCircularAnalogConstraint; + + + + private void NDS_IncrementScreenRotate() + { + if (Emulator is not NDS ds) return; + + var settings = ds.GetSettings(); + var next = settings.ScreenRotation switch + { + NDS.ScreenRotationKind.Rotate0 => NDS.ScreenRotationKind.Rotate90, + NDS.ScreenRotationKind.Rotate90 => NDS.ScreenRotationKind.Rotate180, + NDS.ScreenRotationKind.Rotate180 => NDS.ScreenRotationKind.Rotate270, + NDS.ScreenRotationKind.Rotate270 => NDS.ScreenRotationKind.Rotate0, + _ => settings.ScreenRotation + }; + settings.ScreenRotation = next; + ds.PutSettings(settings); + AddOnScreenMessage($"Screen rotation to {next}"); + FrameBufferResized(); + } + + private void NDS_IncrementLayout(int delta) + { + if (Emulator is not NDS ds) return; + + var settings = ds.GetSettings(); + var t = typeof(NDS.ScreenLayoutKind); + //TODO WTF is this --yoshi + var next = (NDS.ScreenLayoutKind) Enum.Parse(t, ((int) settings.ScreenLayout + delta).ToString()); + if (!t.IsEnumDefined(next)) return; + + settings.ScreenLayout = next; + ds.PutSettings(settings); + AddOnScreenMessage($"Screen layout to {next}"); + FrameBufferResized(); + } + + + + /// should this not be a separate sysID? --yoshi + private bool LoadedCoreIsNesHawkInVSMode + => Emulator is NES { IsVS: true } or SubNESHawk { IsVs: true }; + + private void NesPpuViewerMenuItem_Click(object sender, EventArgs e) + => Tools.Load(); + + private void NesNametableViewerMenuItem_Click(object sender, EventArgs e) + => Tools.Load(); + + private void MusicRipperMenuItem_Click(object sender, EventArgs e) + => Tools.Load(); + + private DialogResult OpenNesHawkGamepadSettingsDialog(ISettingsAdapter settable) + { + using NesControllerSettings form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private DialogResult OpenQuickNesGamepadSettingsDialog(ISettingsAdapter settable) + => GenericCoreConfig.DoDialogFor( + this, + settable, + CoreNames.QuickNes + " Controller Settings", + isMovieActive: MovieSession.Movie.IsActive(), + ignoreSettings: true); + + private void NesControllerSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + NES => OpenNesHawkGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), + SubNESHawk => OpenNesHawkGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), + QuickNES => OpenQuickNesGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private DialogResult OpenNesHawkGraphicsSettingsDialog(ISettingsAdapter settable) + { + using NESGraphicsConfig form = new(Config, this, settable); + return this.ShowDialogWithTempMute(form); + } + + private DialogResult OpenQuickNesGraphicsSettingsDialog(ISettingsAdapter settable) + { + using QuickNesConfig form = new(Config, DialogController, settable); + return this.ShowDialogWithTempMute(form); + } + + private void NesGraphicSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + NES => OpenNesHawkGraphicsSettingsDialog(GetSettingsAdapterForLoadedCore()), + SubNESHawk => OpenNesHawkGraphicsSettingsDialog(GetSettingsAdapterForLoadedCore()), + QuickNES => OpenQuickNesGraphicsSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private void NesSoundChannelsMenuItem_Click(object sender, EventArgs e) + => Tools.Load(); + + private DialogResult OpenNesHawkVSSettingsDialog(ISettingsAdapter settable) + { + using NesVsSettings form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private void VsSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + NES { IsVS: true } => OpenNesHawkVSSettingsDialog(GetSettingsAdapterForLoadedCore()), + SubNESHawk { IsVs: true } => OpenNesHawkVSSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private DialogResult OpenNesHawkAdvancedSettingsDialog(ISettingsAdapter settable, bool hasMapperProperties) + { + using NESSyncSettingsForm form = new(this, settable, hasMapperProperties: hasMapperProperties); + return this.ShowDialogWithTempMute(form); + } + + private void MovieSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + NES nesHawk => OpenNesHawkAdvancedSettingsDialog(GetSettingsAdapterForLoadedCore(), nesHawk.HasMapperProperties), + SubNESHawk subNESHawk => OpenNesHawkAdvancedSettingsDialog(GetSettingsAdapterForLoadedCore(), subNESHawk.HasMapperProperties), + _ => DialogResult.None + }; + + private void FdsEjectDiskMenuItem_Click(object sender, EventArgs e) + { + if (MovieSession.Movie.IsPlaying()) return; + InputManager.ClickyVirtualPadController.Click("FDS Eject"); + AddOnScreenMessage("FDS disk ejected."); + } + + private void FdsControlsMenuItem_DropDownOpened(object sender, EventArgs e) + { + var boardName = Emulator.HasBoardInfo() ? Emulator.AsBoardInfo().BoardName : null; + FdsEjectDiskMenuItem.Enabled = boardName == "FDS"; + while (FDSControlsMenuItem.DropDownItems.Count > 1) FDSControlsMenuItem.DropDownItems.RemoveAt(1); + string button; + for (int i = 0; Emulator.ControllerDefinition.BoolButtons.Contains(button = $"FDS Insert {i}"); i++) + { + var name = $"Disk {i / 2 + 1} Side {(char)(i % 2 + 'A')}"; + FdsInsertDiskMenuAdd($"Insert {name}", button, $"FDS {name} inserted."); + } + } + + private void VsInsertCoinP1MenuItem_Click(object sender, EventArgs e) + { + if (MovieSession.Movie.IsPlaying() || !LoadedCoreIsNesHawkInVSMode) return; + InputManager.ClickyVirtualPadController.Click("Insert Coin P1"); + AddOnScreenMessage("P1 Coin Inserted"); + } + + private void VsInsertCoinP2MenuItem_Click(object sender, EventArgs e) + { + if (MovieSession.Movie.IsPlaying() || !LoadedCoreIsNesHawkInVSMode) return; + InputManager.ClickyVirtualPadController.Click("Insert Coin P2"); + AddOnScreenMessage("P2 Coin Inserted"); + } + + private void VsServiceSwitchMenuItem_Click(object sender, EventArgs e) + { + if (MovieSession.Movie.IsPlaying() || !LoadedCoreIsNesHawkInVSMode) return; + InputManager.ClickyVirtualPadController.Click("Service Switch"); + AddOnScreenMessage("Service Switch Pressed"); + } + + private void BarcodeReaderMenuItem_Click(object sender, EventArgs e) + => Tools.Load(); + + private void NesSubMenu_DropDownOpened(object sender, EventArgs e) + { + var boardName = Emulator.HasBoardInfo() ? Emulator.AsBoardInfo().BoardName : null; + FDSControlsMenuItem.Enabled = boardName == "FDS"; + VSControlsMenuItem.Enabled = VSSettingsMenuItem.Enabled = LoadedCoreIsNesHawkInVSMode; + NESSoundChannelsMenuItem.Enabled = Tools.IsAvailable(); + MovieSettingsMenuItem.Enabled = Emulator is NES or SubNESHawk && MovieSession.Movie.NotActive(); + NesControllerSettingsMenuItem.Enabled = Tools.IsAvailable() && MovieSession.Movie.NotActive(); + BarcodeReaderMenuItem.Enabled = ServiceInjector.IsAvailable(Emulator.ServiceProvider, typeof(BarcodeEntry)); + MusicRipperMenuItem.Enabled = Tools.IsAvailable(); + } + + + + private DialogResult OpenOctoshockGamepadSettingsDialog(ISettingsAdapter settable) + { + using PSXControllerConfig form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private void PsxControllerSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + Octoshock => OpenOctoshockGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private DialogResult OpenOctoshockSettingsDialog(ISettingsAdapter settable, OctoshockDll.eVidStandard vidStandard, Size vidSize) + => PSXOptions.DoSettingsDialog(Config, this, settable, vidStandard, vidSize); + + private void PsxOptionsMenuItem_Click(object sender, EventArgs e) + { + var result = Emulator switch + { + Octoshock octoshock => OpenOctoshockSettingsDialog(GetSettingsAdapterForLoadedCore(), octoshock.SystemVidStandard, octoshock.CurrentVideoSize), + _ => DialogResult.None + }; + if (result.IsOk()) FrameBufferResized(); + } + + private void PsxDiscControlsMenuItem_Click(object sender, EventArgs e) + => Tools.Load().ScrollToPadSchema("Console"); + + private void PsxHashDiscsMenuItem_Click(object sender, EventArgs e) + { + if (Emulator is not IRedumpDiscChecksumInfo psx) return; + using PSXHashDiscs form = new() { _psx = psx }; + this.ShowDialogWithTempMute(form); + } + + private void PsxSubMenu_DropDownOpened(object sender, EventArgs e) + => PSXControllerSettingsMenuItem.Enabled = MovieSession.Movie.NotActive(); + + + + private DialogResult OpenOldBSNESGamepadSettingsDialog(ISettingsAdapter settable) + { + using SNESControllerSettings form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private DialogResult OpenBSNESGamepadSettingsDialog(ISettingsAdapter settable) + { + using BSNESControllerSettings form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private void SNESControllerConfigurationMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + LibsnesCore => OpenOldBSNESGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), + BsnesCore => OpenBSNESGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), + SubBsnesCore => OpenBSNESGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private void SnesGfxDebuggerMenuItem_Click(object sender, EventArgs e) + => Tools.Load(); + + private DialogResult OpenOldBSNESSettingsDialog(ISettingsAdapter settable) + => SNESOptions.DoSettingsDialog(this, settable); + + private DialogResult OpenBSNESSettingsDialog(ISettingsAdapter settable) + => BSNESOptions.DoSettingsDialog(this, settable); + + private void SnesOptionsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + LibsnesCore => OpenOldBSNESSettingsDialog(GetSettingsAdapterForLoadedCore()), + BsnesCore => OpenBSNESSettingsDialog(GetSettingsAdapterForLoadedCore()), + SubBsnesCore => OpenBSNESSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private void SnesSubMenu_DropDownOpened(object sender, EventArgs e) + => SNESControllerConfigurationMenuItem.Enabled = MovieSession.Movie.NotActive(); + + private void SNES_ToggleBg(int layer) + { + if (layer is < 1 or > 4) return; // should this throw? + bool result = false; + switch (Emulator) + { + case BsnesCore or SubBsnesCore: + { + var settingsProvider = Emulator.ServiceProvider + .GetService>(); + var s = settingsProvider.GetSettings(); + switch (layer) + { + case 1: + result = s.ShowBG1_0 = s.ShowBG1_1 = !s.ShowBG1_1; + break; + case 2: + result = s.ShowBG2_0 = s.ShowBG2_1 = !s.ShowBG2_1; + break; + case 3: + result = s.ShowBG3_0 = s.ShowBG3_1 = !s.ShowBG3_1; + break; + case 4: + result = s.ShowBG4_0 = s.ShowBG4_1 = !s.ShowBG4_1; + break; + } + settingsProvider.PutSettings(s); + break; + } + case LibsnesCore libsnes: + { + var s = libsnes.GetSettings(); + switch (layer) + { + case 1: + result = s.ShowBG1_0 = s.ShowBG1_1 = !s.ShowBG1_1; + break; + case 2: + result = s.ShowBG2_0 = s.ShowBG2_1 = !s.ShowBG2_1; + break; + case 3: + result = s.ShowBG3_0 = s.ShowBG3_1 = !s.ShowBG3_1; + break; + case 4: + result = s.ShowBG4_0 = s.ShowBG4_1 = !s.ShowBG4_1; + break; + } + libsnes.PutSettings(s); + break; + } + case Snes9x snes9X: + { + var s = snes9X.GetSettings(); + switch (layer) + { + case 1: + result = s.ShowBg0 = !s.ShowBg0; + break; + case 2: + result = s.ShowBg1 = !s.ShowBg1; + break; + case 3: + result = s.ShowBg2 = !s.ShowBg2; + break; + case 4: + result = s.ShowBg3 = !s.ShowBg3; + break; + } + snes9X.PutSettings(s); + break; + } + default: + return; + } + AddOnScreenMessage($"BG {layer} Layer {(result ? "On" : "Off")}"); + } + + private void SNES_ToggleObj(int layer) + { + if (layer is < 1 or > 4) return; // should this throw? + bool result = false; + if (Emulator is LibsnesCore bsnes) + { + var s = bsnes.GetSettings(); + result = layer switch + { + 1 => s.ShowOBJ_0 = !s.ShowOBJ_0, + 2 => s.ShowOBJ_1 = !s.ShowOBJ_1, + 3 => s.ShowOBJ_2 = !s.ShowOBJ_2, + 4 => s.ShowOBJ_3 = !s.ShowOBJ_3, + _ => result + }; + bsnes.PutSettings(s); + AddOnScreenMessage($"Obj {layer} Layer {(result ? "On" : "Off")}"); + } + else if (Emulator is Snes9x snes9X) + { + var s = snes9X.GetSettings(); + result = layer switch + { + 1 => s.ShowSprites0 = !s.ShowSprites0, + 2 => s.ShowSprites1 = !s.ShowSprites1, + 3 => s.ShowSprites2 = !s.ShowSprites2, + 4 => s.ShowSprites3 = !s.ShowSprites3, + _ => result + }; + snes9X.PutSettings(s); + AddOnScreenMessage($"Sprite {layer} Layer {(result ? "On" : "Off")}"); + } + else + { + return; + } + } + + + + private static readonly FilesystemFilterSet TI83ProgramFilesFSFilterSet = new(new FilesystemFilter("TI-83 Program Files", new[] { "83p", "8xp" })); + + private void Ti83KeypadMenuItem_Click(object sender, EventArgs e) + => Tools.Load(); + + private void Ti83LoadTIFileMenuItem_Click(object sender, EventArgs e) + { + if (Emulator is not TI83 ti83) return; + var result = this.ShowFileOpenDialog( + discardCWDChange: true, + filter: TI83ProgramFilesFSFilterSet, + initDir: Config.PathEntries.RomAbsolutePath(Emulator.SystemId)); + if (result is null) return; + try + { + ti83.LinkPort.SendFileToCalc(File.OpenRead(result), true); + return; + } + catch (IOException ex) + { + if (this.ShowMessageBox3( + owner: null, + icon: EMsgBoxIcon.Question, + caption: "Upload Failed", + text: $"Invalid file format. Reason: {ex.Message} \nForce transfer? This may cause the calculator to crash.") + is not true) + { + return; + } + } + ti83.LinkPort.SendFileToCalc(File.OpenRead(result), false); + } + + private DialogResult OpenTI83PaletteSettingsDialog(ISettingsAdapter settable) + { + using TI83PaletteConfig form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private void Ti83PaletteMenuItem_Click(object sender, EventArgs e) + { + var result = Emulator switch + { + Emu83 => OpenTI83PaletteSettingsDialog(GetSettingsAdapterForLoadedCore()), + TI83 => OpenTI83PaletteSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + if (result.IsOk()) AddOnScreenMessage("Palette settings saved"); + } + + + + private static readonly FilesystemFilterSet ZXStateFilesFSFilterSet = new(new FilesystemFilter("ZX-State files", new[] { "szx" })) + { + AppendAllFilesEntry = false, + }; + + private DialogResult OpenZXHawkSyncSettingsDialog(ISettingsAdapter settable) + { + using ZxSpectrumCoreEmulationSettings form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private void ZXSpectrumCoreEmulationSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + ZXSpectrum => OpenZXHawkSyncSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private DialogResult OpenZXHawkGamepadSettingsDialog(ISettingsAdapter settable) + { + using ZxSpectrumJoystickSettings form = new(this, settable); + return this.ShowDialogWithTempMute(form); + } + + private void ZXSpectrumControllerConfigurationMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + ZXSpectrum => OpenZXHawkGamepadSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private DialogResult OpenZXHawkAudioSettingsDialog(ISettingsAdapter settable) + { + using ZxSpectrumAudioSettings form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private void ZXSpectrumAudioSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + ZXSpectrum => OpenZXHawkAudioSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private DialogResult OpenZXHawkSettingsDialog(ISettingsAdapter settable) + { + using ZxSpectrumNonSyncSettings form = new(settable); + return this.ShowDialogWithTempMute(form); + } + + private void ZXSpectrumNonSyncSettingsMenuItem_Click(object sender, EventArgs e) + => _ = Emulator switch + { + ZXSpectrum => OpenZXHawkSettingsDialog(GetSettingsAdapterForLoadedCore()), + _ => DialogResult.None + }; + + private void ZXSpectrumTapesSubMenu_DropDownOpened(object sender, EventArgs e) + { + ZXSpectrumTapesSubMenu.DropDownItems.Clear(); + if (Emulator is not ZXSpectrum speccy) return; + EventHandler clickHandler = (clickSender, _) => + { + if (!object.ReferenceEquals(speccy, Emulator)) return; + speccy._machine.TapeMediaIndex = (int) ((Control) clickSender).Tag; + }; + var tapeMediaIndex = speccy._machine.TapeMediaIndex; + for (int i = 0; i < speccy._tapeInfo.Count; i++) + { + ToolStripMenuItem menuItem = new() + { + Checked = i == tapeMediaIndex, + Tag = i, + Text = $"{i}: {speccy._tapeInfo[i].Name}", + }; + menuItem.Click += clickHandler; + ZXSpectrumTapesSubMenu.DropDownItems.Add(menuItem); + } + } + + private void ZXSpectrumDisksSubMenu_DropDownOpened(object sender, EventArgs e) + { + ZXSpectrumDisksSubMenu.DropDownItems.Clear(); + if (Emulator is not ZXSpectrum speccy) return; + EventHandler clickHandler = (clickSender, _) => + { + if (!object.ReferenceEquals(speccy, Emulator)) return; + speccy._machine.DiskMediaIndex = (int) ((Control) clickSender).Tag; + }; + var diskMediaIndex = speccy._machine.DiskMediaIndex; + for (int i = 0; i < speccy._diskInfo.Count; i++) + { + ToolStripMenuItem menuItem = new() + { + Checked = i == diskMediaIndex, + Tag = i, + Text = $"{i}: {speccy._diskInfo[i].Name}", + }; + menuItem.Click += clickHandler; + ZXSpectrumDisksSubMenu.DropDownItems.Add(menuItem); + } + } + + private void ZXSpectrumExportSnapshotMenuItemMenuItem_Click(object sender, EventArgs e) + { + try + { + var result = this.ShowFileSaveDialog( + discardCWDChange: true, + fileExt: "szx", +// SupportMultiDottedExtensions = true, // I think this should be enabled globally if we're going to do it --yoshi + filter: ZXStateFilesFSFilterSet, + initDir: Config.PathEntries.ToolsAbsolutePath()); + if (result is not null) + { + var speccy = (ZXSpectrum)Emulator; + var snap = speccy.GetSZXSnapshot(); + File.WriteAllBytes(result, snap); + } + } + catch (Exception) + { + // ignored + } + } + + private void ZXSpectrumMediaMenuItem_DropDownOpened(object sender, EventArgs e) + { + if (Emulator is not ZXSpectrum speccy) return; + ZXSpectrumTapesSubMenu.Enabled = speccy._tapeInfo.Count > 0; + ZXSpectrumDisksSubMenu.Enabled = speccy._diskInfo.Count > 0; + } + + + + private enum VSystemCategory : int + { + Consoles = 0, + Handhelds = 1, + PCs = 2, + Other = 3, + } + + private IReadOnlyCollection CreateCoreSettingsSubmenus(bool includeDupes = false) + { + static ToolStripMenuItemEx CreateSettingsItem(string text, EventHandler onClick) + { + ToolStripMenuItemEx menuItem = new() { Text = text }; + menuItem.Click += onClick; + return menuItem; + } + ToolStripMenuItemEx CreateGenericCoreConfigItem(string coreName) + where T : IEmulator + => CreateSettingsItem("Settings...", (_, _) => OpenGenericCoreConfigFor($"{coreName} Settings")); + ToolStripMenuItemEx CreateGenericNymaCoreConfigItem(string coreName, Func getCachedSettingsInfo) + where T : NymaCore + => CreateSettingsItem( + "Settings...", + (_, _) => GenericCoreConfig.DoNymaDialogFor( + this, + GetSettingsAdapterFor(), + $"{coreName} Settings", + getCachedSettingsInfo(CreateCoreComm()), + isMovieActive: MovieSession.Movie.IsActive())); + ToolStripMenuItemEx CreateCoreSubmenu(VSystemCategory cat, string coreName, params ToolStripItem[] items) + { + ToolStripMenuItemEx submenu = new() { Tag = cat, Text = coreName }; + submenu.DropDownItems.AddRange(items); + return submenu; + } + + List items = new(); + + // A7800Hawk + var a7800HawkGamepadSettingsItem = CreateSettingsItem("Controller Settings...", (_, _) => OpenA7800HawkGamepadSettingsDialog(GetSettingsAdapterFor())); + var a7800HawkFilterSettingsItem = CreateSettingsItem("Filter Settings...", (_, _) => OpenA7800HawkFilterSettingsDialog(GetSettingsAdapterFor())); + var a7800HawkSubmenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.A7800Hawk, a7800HawkGamepadSettingsItem, a7800HawkFilterSettingsItem); + a7800HawkSubmenu.DropDownOpened += (_, _) => a7800HawkGamepadSettingsItem.Enabled = a7800HawkFilterSettingsItem.Enabled = MovieSession.Movie.NotActive() || Emulator is not A7800Hawk; + items.Add(a7800HawkSubmenu); + + // Ares64 + var ares64AnalogConstraintItem = CreateSettingsItem("Circular Analog Range", N64CircularAnalogRangeMenuItem_Click); + var ares64Submenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Ares64, CreateGenericCoreConfigItem(CoreNames.Ares64)); + ares64Submenu.DropDownOpened += (_, _) => ares64AnalogConstraintItem.Checked = Config.N64UseCircularAnalogConstraint; + items.Add(ares64Submenu); + + // Atari2600Hawk + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Atari2600Hawk, CreateGenericCoreConfigItem(CoreNames.Atari2600Hawk))); + + // BSNES + var oldBSNESGamepadSettingsItem = CreateSettingsItem("Controller Configuration...", (_, _) => OpenOldBSNESGamepadSettingsDialog(GetSettingsAdapterFor())); + var oldBSNESSettingsItem = CreateSettingsItem("Options...", (_, _) => OpenOldBSNESSettingsDialog(GetSettingsAdapterFor())); + var oldBSNESSubmenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Bsnes, oldBSNESGamepadSettingsItem, oldBSNESSettingsItem); + oldBSNESSubmenu.DropDownOpened += (_, _) => oldBSNESGamepadSettingsItem.Enabled = MovieSession.Movie.NotActive() || Emulator is not LibsnesCore; + items.Add(oldBSNESSubmenu); + + // BSNESv115+ + var bsnesGamepadSettingsItem = CreateSettingsItem("Controller Configuration...", (_, _) => OpenBSNESGamepadSettingsDialog(GetSettingsAdapterFor())); + var bsnesSettingsItem = CreateSettingsItem("Options...", (_, _) => OpenBSNESSettingsDialog(GetSettingsAdapterFor())); + var bsnesSubmenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Bsnes115, bsnesGamepadSettingsItem, bsnesSettingsItem); + bsnesSubmenu.DropDownOpened += (_, _) => bsnesGamepadSettingsItem.Enabled = MovieSession.Movie.NotActive() || Emulator is not BsnesCore; + items.Add(bsnesSubmenu); + + // SubBSNESv115+ + var subBsnesGamepadSettingsItem = CreateSettingsItem("Controller Configuration...", (_, _) => OpenBSNESGamepadSettingsDialog(GetSettingsAdapterFor())); + var subBsnesSettingsItem = CreateSettingsItem("Options...", (_, _) => OpenBSNESSettingsDialog(GetSettingsAdapterFor())); + var subBsnesSubmenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.SubBsnes115, subBsnesGamepadSettingsItem, subBsnesSettingsItem); + subBsnesSubmenu.DropDownOpened += (_, _) => subBsnesGamepadSettingsItem.Enabled = MovieSession.Movie.NotActive() || Emulator is not SubBsnesCore; + items.Add(subBsnesSubmenu); + + // C64Hawk + items.Add(CreateCoreSubmenu(VSystemCategory.PCs, CoreNames.C64Hawk, CreateSettingsItem("Settings...", (_, _) => OpenC64HawkSettingsDialog()))); + + // ChannelFHawk + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.ChannelFHawk, CreateGenericCoreConfigItem(CoreNames.ChannelFHawk))); + + // Encore + items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.Encore, CreateGenericCoreConfigItem(CoreNames.Encore))); + + // ColecoHawk + var colecoHawkGamepadSettingsItem = CreateSettingsItem("Controller Settings...", (_, _) => OpenColecoHawkGamepadSettingsDialog(GetSettingsAdapterFor())); + var colecoHawkSkipBIOSItem = CreateSettingsItem("Skip BIOS intro (When Applicable)", (sender, _) => ColecoHawkSetSkipBIOSIntro(!((ToolStripMenuItem) sender).Checked, GetSettingsAdapterFor())); + var colecoHawkUseSGMItem = CreateSettingsItem("Use the Super Game Module", (sender, _) => ColecoHawkSetSuperGameModule(!((ToolStripMenuItem) sender).Checked, GetSettingsAdapterFor())); + var colecoHawkSubmenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.ColecoHawk, colecoHawkGamepadSettingsItem, colecoHawkSkipBIOSItem, colecoHawkUseSGMItem); + colecoHawkSubmenu.DropDownOpened += (_, _) => + { + var ss = (ColecoVision.ColecoSyncSettings) GetSettingsAdapterFor().GetSyncSettings(); + colecoHawkGamepadSettingsItem.Enabled = MovieSession.Movie.NotActive() || Emulator is not ColecoVision; + colecoHawkSkipBIOSItem.Checked = ss.SkipBiosIntro; + colecoHawkUseSGMItem.Checked = ss.UseSGM; + }; + items.Add(colecoHawkSubmenu); + + // CPCHawk + items.Add(CreateCoreSubmenu( + VSystemCategory.PCs, + CoreNames.CPCHawk, + CreateSettingsItem("Core Emulation Settings...", (_, _) => OpenCPCHawkSyncSettingsDialog(GetSettingsAdapterFor())), + CreateSettingsItem("Audio Settings...", (_, _) => OpenCPCHawkAudioSettingsDialog(GetSettingsAdapterFor())), + CreateSettingsItem("Non-Sync Settings...", (_, _) => OpenCPCHawkSettingsDialog(GetSettingsAdapterFor())))); + + // Cygne + items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.Cygne, CreateGenericCoreConfigItem(CoreNames.Cygne))); + + // Emu83 + items.Add(CreateCoreSubmenu(VSystemCategory.Other, CoreNames.Emu83, CreateSettingsItem("Palette...", (_, _) => OpenTI83PaletteSettingsDialog(GetSettingsAdapterFor())))); + + // Faust + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Faust, CreateGenericNymaCoreConfigItem(CoreNames.Faust, Faust.CachedSettingsInfo))); + + // Gambatte + items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.Gambatte, CreateSettingsItem("Settings...", (_, _) => OpenGambatteSettingsDialog(GetSettingsAdapterFor())))); + if (includeDupes) items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Gambatte, CreateSettingsItem("Settings...", (_, _) => OpenGambatteSettingsDialog(GetSettingsAdapterFor())))); + + // GambatteLink + items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.GambatteLink, CreateSettingsItem("Settings...", (_, _) => OpenGambatteLinkSettingsDialog(GetSettingsAdapterFor())))); + + // GBHawk + items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.GbHawk, CreateSettingsItem("Settings...", (_, _) => OpenGBHawkSettingsDialog()))); + + // GBHawkLink + items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.GBHawkLink, CreateGenericCoreConfigItem(CoreNames.GBHawkLink))); + + // GBHawkLink3x + items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.GBHawkLink3x, CreateGenericCoreConfigItem(CoreNames.GBHawkLink3x))); + + // GBHawkLink4x + items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.GBHawkLink4x, CreateGenericCoreConfigItem(CoreNames.GBHawkLink4x))); + + // GGHawkLink + items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.GGHawkLink, CreateGenericCoreConfigItem(CoreNames.GGHawkLink))); + + // Genplus-gx + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Gpgx, CreateGenericCoreConfigItem(CoreNames.Gpgx))); + + // Handy + items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.Handy, CreateGenericCoreConfigItem(CoreNames.Handy))); // as Handy doesn't implement `ISettable<,>`, this opens an empty `GenericCoreConfig`, which is dumb, but matches the existing behaviour + + // HyperNyma + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.HyperNyma, CreateGenericNymaCoreConfigItem(CoreNames.HyperNyma, HyperNyma.CachedSettingsInfo))); + + // IntelliHawk + var intelliHawkGamepadSettingsItem = CreateSettingsItem("Controller Settings...", (_, _) => OpenIntelliHawkGamepadSettingsDialog(GetSettingsAdapterFor())); + var intelliHawkSubmenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.IntelliHawk, intelliHawkGamepadSettingsItem); + intelliHawkSubmenu.DropDownOpened += (_, _) => intelliHawkGamepadSettingsItem.Enabled = MovieSession.Movie.NotActive() || Emulator is not Intellivision; + items.Add(intelliHawkSubmenu); + + // Libretro + items.Add(CreateCoreSubmenu( + VSystemCategory.Other, + CoreNames.Libretro, + CreateGenericCoreConfigItem(CoreNames.Libretro))); // as Libretro doesn't implement `ISettable<,>`, this opens an empty `GenericCoreConfig`, which is dumb, but matches the existing behaviour + + // MAME + var mameSettingsItem = CreateSettingsItem("Settings...", (_, _) => OpenGenericCoreConfig()); + var mameSubmenu = CreateCoreSubmenu(VSystemCategory.Other, CoreNames.MAME, mameSettingsItem); + mameSubmenu.DropDownOpened += (_, _) => mameSettingsItem.Enabled = Emulator is MAME; + items.Add(mameSubmenu); + + // melonDS + items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.MelonDS, CreateGenericCoreConfigItem(CoreNames.MelonDS))); + + // mGBA + items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.Mgba, CreateGenericCoreConfigItem(CoreNames.Mgba))); + + // MSXHawk + items.Add(CreateCoreSubmenu(VSystemCategory.PCs, CoreNames.MSXHawk, CreateGenericCoreConfigItem(CoreNames.MSXHawk))); + + // Mupen64Plus + var mupen64PlusGraphicsSettingsItem = CreateSettingsItem("Video Plugins...", N64PluginSettingsMenuItem_Click); + var mupen64PlusGamepadSettingsItem = CreateSettingsItem("Controller Settings...", (_, _) => OpenMupen64PlusGamepadSettingsDialog(GetSettingsAdapterFor())); + var mupen64PlusAnalogConstraintItem = CreateSettingsItem("Circular Analog Range", N64CircularAnalogRangeMenuItem_Click); + var mupen64PlusMupenStyleLagFramesItem = CreateSettingsItem("Mupen Style Lag Frames", (sender, _) => Mupen64PlusSetMupenStyleLag(!((ToolStripMenuItem) sender).Checked, GetSettingsAdapterFor())); + var mupen64PlusUseExpansionSlotItem = CreateSettingsItem("Use Expansion Slot", (sender, _) => Mupen64PlusSetUseExpansionSlot(!((ToolStripMenuItem) sender).Checked, GetSettingsAdapterFor())); + var mupen64PlusSubmenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Mupen64Plus, mupen64PlusGraphicsSettingsItem, mupen64PlusGamepadSettingsItem, mupen64PlusAnalogConstraintItem, mupen64PlusMupenStyleLagFramesItem, mupen64PlusUseExpansionSlotItem); + mupen64PlusSubmenu.DropDownOpened += (_, _) => + { + var settable = GetSettingsAdapterFor(); + var s = (N64Settings) settable.GetSettings(); + var isMovieActive = MovieSession.Movie.IsActive(); + var mupen64Plus = Emulator as N64; + var loadedCoreIsMupen64Plus = mupen64Plus is not null; + mupen64PlusGraphicsSettingsItem.Enabled = !loadedCoreIsMupen64Plus || !isMovieActive; + mupen64PlusGamepadSettingsItem.Enabled = !loadedCoreIsMupen64Plus || !isMovieActive; + mupen64PlusAnalogConstraintItem.Checked = Config.N64UseCircularAnalogConstraint; + mupen64PlusMupenStyleLagFramesItem.Checked = s.UseMupenStyleLag; + if (loadedCoreIsMupen64Plus) + { + mupen64PlusUseExpansionSlotItem.Checked = mupen64Plus.UsingExpansionSlot; + mupen64PlusUseExpansionSlotItem.Enabled = !mupen64Plus.IsOverridingUserExpansionSlotSetting; + } + else + { + mupen64PlusUseExpansionSlotItem.Checked = !((N64SyncSettings) settable.GetSyncSettings()).DisableExpansionSlot; + mupen64PlusUseExpansionSlotItem.Enabled = true; + } + }; + items.Add(mupen64PlusSubmenu); + + // NeoPop + items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.NeoPop, CreateGenericNymaCoreConfigItem(CoreNames.NeoPop, NeoGeoPort.CachedSettingsInfo))); + + // NesHawk + var nesHawkGamepadSettingsItem = CreateSettingsItem("Controller Settings...", (_, _) => OpenNesHawkGamepadSettingsDialog(GetSettingsAdapterFor())); + var nesHawkVSSettingsItem = CreateSettingsItem("VS Settings...", (_, _) => OpenNesHawkVSSettingsDialog(GetSettingsAdapterFor())); + var nesHawkAdvancedSettingsItem = CreateSettingsItem("Advanced Settings...", (_, _) => OpenNesHawkAdvancedSettingsDialog(GetSettingsAdapterFor(), Emulator is not NES nesHawk || nesHawk.HasMapperProperties)); + var nesHawkSubmenu = CreateCoreSubmenu( + VSystemCategory.Consoles, + CoreNames.NesHawk, + nesHawkGamepadSettingsItem, + CreateSettingsItem("Graphics Settings...", (_, _) => OpenNesHawkGraphicsSettingsDialog(GetSettingsAdapterFor())), + nesHawkVSSettingsItem, + nesHawkAdvancedSettingsItem); + nesHawkSubmenu.DropDownOpened += (_, _) => + { + var nesHawk = Emulator as NES; + var canEditSyncSettings = nesHawk is null || MovieSession.Movie.NotActive(); + nesHawkGamepadSettingsItem.Enabled = canEditSyncSettings && Tools.IsAvailable(); + nesHawkVSSettingsItem.Enabled = nesHawk?.IsVS is null or true; + nesHawkAdvancedSettingsItem.Enabled = canEditSyncSettings; + }; + items.Add(nesHawkSubmenu); + + // Nymashock + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Nymashock, CreateGenericNymaCoreConfigItem(CoreNames.Nymashock, Nymashock.CachedSettingsInfo))); + + // O2Hawk + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.O2Hawk, CreateGenericCoreConfigItem(CoreNames.O2Hawk))); + + // Octoshock + var octoshockGamepadSettingsItem = CreateSettingsItem("Controller / Memcard Settings...", (_, _) => OpenOctoshockGamepadSettingsDialog(GetSettingsAdapterFor())); + var octoshockSettingsItem = CreateSettingsItem("Options...", PsxOptionsMenuItem_Click); + // using init buffer sizes here (in practice, they don't matter here, but might as well) + var octoshockNTSCSettingsItem = CreateSettingsItem("Options (as NTSC)...", (_, _) => OpenOctoshockSettingsDialog(GetSettingsAdapterFor(), OctoshockDll.eVidStandard.NTSC, new(280, 240))); + var octoshockPALSettingsItem = CreateSettingsItem("Options (as PAL)...", (_, _) => OpenOctoshockSettingsDialog(GetSettingsAdapterFor(), OctoshockDll.eVidStandard.PAL, new(280, 288))); + var octoshockSubmenu = CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Octoshock, octoshockGamepadSettingsItem, octoshockSettingsItem, octoshockNTSCSettingsItem, octoshockPALSettingsItem); + octoshockSubmenu.DropDownOpened += (_, _) => + { + var loadedCoreIsOctoshock = Emulator is Octoshock; + octoshockGamepadSettingsItem.Enabled = !loadedCoreIsOctoshock || MovieSession.Movie.NotActive(); + octoshockSettingsItem.Visible = loadedCoreIsOctoshock; + octoshockNTSCSettingsItem.Visible = octoshockPALSettingsItem.Visible = !loadedCoreIsOctoshock; + }; + items.Add(octoshockSubmenu); + + // PCEHawk + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.PceHawk, CreateGenericCoreConfigItem(CoreNames.PceHawk))); + + // PicoDrive + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.PicoDrive, CreateGenericCoreConfigItem(CoreNames.PicoDrive))); + + // PUAE + items.Add(CreateCoreSubmenu(VSystemCategory.PCs, CoreNames.PUAE, CreateGenericCoreConfigItem(CoreNames.PUAE))); + + // QuickNes + var quickNesGamepadSettingsItem = CreateSettingsItem("Controller Settings...", (_, _) => OpenQuickNesGamepadSettingsDialog(GetSettingsAdapterFor())); + var quickNesSubmenu = CreateCoreSubmenu( + VSystemCategory.Consoles, + CoreNames.QuickNes, + quickNesGamepadSettingsItem, + CreateSettingsItem("Graphics Settings...", (_, _) => OpenQuickNesGraphicsSettingsDialog(GetSettingsAdapterFor()))); + quickNesSubmenu.DropDownOpened += (_, _) => quickNesGamepadSettingsItem.Enabled = (MovieSession.Movie.NotActive() || Emulator is not QuickNES) && Tools.IsAvailable(); + items.Add(quickNesSubmenu); + + // SameBoy + items.Add(CreateCoreSubmenu( + VSystemCategory.Handhelds, + CoreNames.Sameboy, + CreateSettingsItem("Settings...", (_, _) => OpenSameBoySettingsDialog()), + CreateSettingsItem("Choose Custom Palette...", (_, _) => OpenSameBoyPaletteSettingsDialog(GetSettingsAdapterFor())))); + + // Saturnus + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Saturnus, CreateGenericNymaCoreConfigItem(CoreNames.Saturnus, Saturnus.CachedSettingsInfo))); + + // SMSHawk + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.SMSHawk, CreateGenericCoreConfigItem(CoreNames.SMSHawk))); + if (includeDupes) items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.SMSHawk, CreateGenericCoreConfigItem(CoreNames.SMSHawk))); + + // Snes9x + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Snes9X, CreateGenericCoreConfigItem(CoreNames.Snes9X))); + + // SubGBHawk + items.Add(CreateCoreSubmenu(VSystemCategory.Handhelds, CoreNames.SubGbHawk, CreateSettingsItem("Settings...", (_, _) => OpenSubGBHawkSettingsDialog()))); + + // SubNESHawk + var subNESHawkGamepadSettingsItem = CreateSettingsItem("Controller Settings...", (_, _) => OpenNesHawkGamepadSettingsDialog(GetSettingsAdapterFor())); + var subNESHawkVSSettingsItem = CreateSettingsItem("VS Settings...", (_, _) => OpenNesHawkVSSettingsDialog(GetSettingsAdapterFor())); + var subNESHawkAdvancedSettingsItem = CreateSettingsItem("Advanced Settings...", (_, _) => OpenNesHawkAdvancedSettingsDialog(GetSettingsAdapterFor(), Emulator is not SubNESHawk subNESHawk || subNESHawk.HasMapperProperties)); + var subNESHawkSubmenu = CreateCoreSubmenu( + VSystemCategory.Consoles, + CoreNames.SubNesHawk, + subNESHawkGamepadSettingsItem, + CreateSettingsItem("Graphics Settings...", (_, _) => OpenNesHawkGraphicsSettingsDialog(GetSettingsAdapterFor())), + subNESHawkVSSettingsItem, + subNESHawkAdvancedSettingsItem); + subNESHawkSubmenu.DropDownOpened += (_, _) => + { + var subNESHawk = Emulator as SubNESHawk; + var canEditSyncSettings = subNESHawk is null || MovieSession.Movie.NotActive(); + subNESHawkGamepadSettingsItem.Enabled = canEditSyncSettings && Tools.IsAvailable(); + subNESHawkVSSettingsItem.Enabled = subNESHawk?.IsVs is null or true; + subNESHawkAdvancedSettingsItem.Enabled = canEditSyncSettings; + }; + items.Add(subNESHawkSubmenu); + + // TI83Hawk + items.Add(CreateCoreSubmenu(VSystemCategory.Other, CoreNames.TI83Hawk, CreateSettingsItem("Palette...", (_, _) => OpenTI83PaletteSettingsDialog(GetSettingsAdapterFor())))); + + // TIC80 + items.Add(CreateCoreSubmenu(VSystemCategory.PCs, CoreNames.TIC80, CreateGenericCoreConfigItem(CoreNames.TIC80))); + + // T. S. T. + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.TST, CreateGenericNymaCoreConfigItem(CoreNames.TST, Tst.CachedSettingsInfo))); + + // TurboNyma + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.TurboNyma, CreateGenericNymaCoreConfigItem(CoreNames.TurboNyma, TurboNyma.CachedSettingsInfo))); + + // uzem + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.Uzem, CreateGenericCoreConfigItem(CoreNames.Uzem))); // as uzem doesn't implement `ISettable<,>`, this opens an empty `GenericCoreConfig`, which is dumb, but matches the existing behaviour + + // VectrexHawk + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.VectrexHawk, CreateGenericCoreConfigItem(CoreNames.VectrexHawk))); + + // Virtu + items.Add(CreateCoreSubmenu(VSystemCategory.PCs, CoreNames.Virtu, CreateSettingsItem("Settings...", (_, _) => OpenVirtuSettingsDialog()))); + + // Virtual Boyee + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.VirtualBoyee, CreateGenericNymaCoreConfigItem(CoreNames.VirtualBoyee, VirtualBoyee.CachedSettingsInfo))); + + // Virtual Jaguar + items.Add(CreateCoreSubmenu(VSystemCategory.Consoles, CoreNames.VirtualJaguar, CreateGenericCoreConfigItem(CoreNames.VirtualJaguar))); + + // ZXHawk + items.Add(CreateCoreSubmenu( + VSystemCategory.PCs, + CoreNames.ZXHawk, + CreateSettingsItem("Core Emulation Settings...", (_, _) => OpenZXHawkSyncSettingsDialog(GetSettingsAdapterFor())), + CreateSettingsItem("Joystick Configuration...", (_, _) => OpenZXHawkGamepadSettingsDialog(GetSettingsAdapterFor())), + CreateSettingsItem("Audio Settings...", (_, _) => OpenZXHawkAudioSettingsDialog(GetSettingsAdapterFor())), + CreateSettingsItem("Non-Sync Settings...", (_, _) => OpenZXHawkSettingsDialog(GetSettingsAdapterFor())))); + + return items; + } + + private void HandlePlatformMenus() + { + if (GenericCoreSubMenu.Visible) + { + var i = GenericCoreSubMenu.Text.IndexOf('&'); + if (i != -1) AvailableAccelerators.Add(GenericCoreSubMenu.Text[i + 1]); + } + GenericCoreSubMenu.Visible = false; + TI83SubMenu.Visible = false; + NESSubMenu.Visible = false; + GBSubMenu.Visible = false; + A7800SubMenu.Visible = false; + SNESSubMenu.Visible = false; + PSXSubMenu.Visible = false; + ColecoSubMenu.Visible = false; + N64SubMenu.Visible = false; + Ares64SubMenu.Visible = false; + GBLSubMenu.Visible = false; + AppleSubMenu.Visible = false; + C64SubMenu.Visible = false; + IntvSubMenu.Visible = false; + zXSpectrumToolStripMenuItem.Visible = false; + amstradCPCToolStripMenuItem.Visible = false; + + var sysID = Emulator.SystemId; + switch (sysID) + { + case VSystemID.Raw.NULL: + break; + case VSystemID.Raw.A78: + A7800SubMenu.Visible = true; + break; + case VSystemID.Raw.AmstradCPC: + amstradCPCToolStripMenuItem.Visible = true; + break; + case VSystemID.Raw.AppleII: + AppleSubMenu.Visible = true; + break; + case VSystemID.Raw.C64: + C64SubMenu.Visible = true; + break; + case VSystemID.Raw.Coleco: + ColecoSubMenu.Visible = true; + break; + case VSystemID.Raw.INTV: + IntvSubMenu.Visible = true; + break; + case VSystemID.Raw.N64 when Emulator is N64: + N64SubMenu.Visible = true; + break; + case VSystemID.Raw.N64 when Emulator is Ares64: + Ares64SubMenu.Visible = true; + break; + case VSystemID.Raw.NES: + NESSubMenu.Visible = true; + break; + case VSystemID.Raw.PSX when Emulator is Octoshock: + PSXSubMenu.Visible = true; + break; + case VSystemID.Raw.TI83: + TI83SubMenu.Visible = true; + LoadTIFileMenuItem.Visible = Emulator is TI83; + break; + case VSystemID.Raw.ZXSpectrum: + zXSpectrumToolStripMenuItem.Visible = true; + break; + case VSystemID.Raw.GBL when Emulator is GambatteLink: + GBLSubMenu.Visible = true; + break; + case VSystemID.Raw.GB: + case VSystemID.Raw.GBC: + case VSystemID.Raw.SGB when Emulator is Gameboy: + GBSubMenu.Visible = true; + SameBoyColorChooserMenuItem.Visible = Emulator is Sameboy { IsCGBMode: false }; // palette config only works in DMG mode + break; + case VSystemID.Raw.SNES when Emulator is LibsnesCore oldBSNES: // doesn't use "SGB" sysID, always "SNES" + SNESSubMenu.Text = oldBSNES.IsSGB ? "&SGB" : "&SNES"; + SNESSubMenu.Visible = true; + break; + case var _ when Emulator is BsnesCore or SubBsnesCore: + SNESSubMenu.Text = $"&{sysID}"; + SNESSubMenu.Visible = true; + break; + default: + DisplayDefaultCoreMenu(); + break; + } + } + } +} diff --git a/src/BizHawk.Client.EmuHawk/MainForm.cs b/src/BizHawk.Client.EmuHawk/MainForm.cs index 2cc5ff8fc05..24b393b9f5e 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; @@ -14,34 +13,27 @@ using System.Security.Principal; using System.IO.Pipes; +using BizHawk.Bizware.Graphics; + using BizHawk.Common; using BizHawk.Common.BufferExtensions; using BizHawk.Common.PathExtensions; using BizHawk.Common.StringExtensions; using BizHawk.Client.Common; -using BizHawk.Bizware.BizwareGL; using BizHawk.Emulation.Common; using BizHawk.Emulation.Common.Base_Implementations; using BizHawk.Emulation.Cores; using BizHawk.Emulation.Cores.Arcades.MAME; -using BizHawk.Emulation.Cores.Calculators.TI83; using BizHawk.Emulation.Cores.Computers.AppleII; using BizHawk.Emulation.Cores.Computers.Commodore64; -using BizHawk.Emulation.Cores.Consoles.NEC.PCE; -using BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64; using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES; using BizHawk.Emulation.Cores.Consoles.SNK; -using BizHawk.Emulation.Cores.Nintendo.BSNES; -using BizHawk.Emulation.Cores.Nintendo.Gameboy; using BizHawk.Emulation.Cores.Nintendo.GBA; using BizHawk.Emulation.Cores.Nintendo.N64; using BizHawk.Emulation.Cores.Nintendo.NES; -using BizHawk.Emulation.Cores.Nintendo.Sameboy; using BizHawk.Emulation.Cores.Nintendo.SNES; -using BizHawk.Emulation.Cores.Nintendo.SNES9X; -using BizHawk.Emulation.Cores.Sony.PSX; using BizHawk.Emulation.DiscSystem; @@ -88,31 +80,28 @@ ToolStripItem[] CreateWindowSizeFactorSubmenus() foreach (var (appliesTo, coreNames) in Config.CorePickerUIData) { - var groupLabel = appliesTo[0]; - var submenu = new ToolStripMenuItem { Text = groupLabel }; - void ClickHandler(object clickSender, EventArgs clickArgs) - { - var coreName = ((ToolStripMenuItem) clickSender).Text; - foreach (var system in appliesTo) - { - if (Emulator.SystemId == system && Emulator.Attributes().CoreName != coreName) FlagNeedsReboot(); - Config.PreferredCores[system] = coreName; - } - } + var submenu = new ToolStripMenuItem { Text = string.Join(" | ", appliesTo) }; submenu.DropDownItems.AddRange(coreNames.Select(coreName => { var entry = new ToolStripMenuItem { Text = coreName }; - entry.Click += ClickHandler; + entry.Click += (_, _) => + { + string currentCoreName = Emulator.Attributes().CoreName; + if (coreName != currentCoreName && coreNames.Contains(currentCoreName)) FlagNeedsReboot(); + foreach (string system in appliesTo) + Config.PreferredCores[system] = coreName; + }; return (ToolStripItem) entry; }).ToArray()); submenu.DropDownOpened += (openedSender, _1) => { - _ = Config.PreferredCores.TryGetValue(groupLabel, out var preferred); + _ = Config.PreferredCores.TryGetValue(appliesTo[0], out var preferred); if (!coreNames.Contains(preferred)) { // invalid --> default (doing this here rather than when reading config file to allow for hacked-in values, though I'm not sure if that could do anything at the moment --yoshi) var defaultCore = coreNames[0]; - Console.WriteLine($"setting preferred core for {groupLabel} etc. to {defaultCore} (was {preferred ?? "null"})"); - Config.PreferredCores[groupLabel] = preferred = defaultCore; + Console.WriteLine($"setting preferred core for {submenu.Text} to {defaultCore} (was {preferred ?? "null"})"); + preferred = defaultCore; + foreach (var sysID in appliesTo) Config.PreferredCores[sysID] = preferred; } foreach (ToolStripMenuItem entry in ((ToolStripMenuItem) openedSender).DropDownItems) entry.Checked = entry.Text == preferred; }; @@ -122,7 +111,7 @@ void ClickHandler(object clickSender, EventArgs clickArgs) var GBInSGBMenuItem = new ToolStripMenuItem { Text = "GB in SGB" }; GBInSGBMenuItem.Click += (_, _) => { - Config.GbAsSgb ^= true; + Config.GbAsSgb = !Config.GbAsSgb; if (Emulator.SystemId is VSystemID.Raw.GB or VSystemID.Raw.GBC or VSystemID.Raw.SGB) FlagNeedsReboot(); }; CoresSubMenu.DropDownItems.Add(GBInSGBMenuItem); @@ -142,7 +131,7 @@ void ClickHandler(object clickSender, EventArgs clickArgs) }; ToolStripMenuItemEx consolesCoreSettingsSubmenu = new() { Text = "For Consoles" }; ToolStripMenuItemEx handheldsCoreSettingsSubmenu = new() { Text = "For Handhelds" }; - ToolStripMenuItemEx pcsCoreSettingsSubmenu = new() { Text = "For PCs" }; + ToolStripMenuItemEx pcsCoreSettingsSubmenu = new() { Text = "For Computers" }; ToolStripMenuItemEx otherCoreSettingsSubmenu = new() { Text = "Other" }; foreach (var submenu in CreateCoreSettingsSubmenus(includeDupes: true).OrderBy(submenu => submenu.Text)) { @@ -492,7 +481,6 @@ void MainForm_MouseClick(object sender, MouseEventArgs e) UpdateKeyPriorityIcon(); // TODO GL - a lot of disorganized wiring-up here - // installed separately on Unix (via package manager or from https://developer.nvidia.com/cg-toolkit-download), look in $PATH _presentationPanel = new( Config, GL, @@ -641,9 +629,9 @@ _argParser.SocketAddress is var (socketIP, socketPort) if (_argParser.cmdRom != null) { // Commandline should always override auto-load - var ioa = OpenAdvancedSerializer.ParseWithLegacy(_argParser.cmdRom); - if (ioa is OpenAdvanced_OpenRom oaor) ioa = new OpenAdvanced_OpenRom { Path = oaor.Path.MakeAbsolute() }; // fixes #3224; should this be done for all the IOpenAdvanced types? --yoshi - _ = LoadRom(ioa.SimplePath, new LoadRomArgs { OpenAdvanced = ioa }); + OpenAdvanced_OpenRom ioa = new(_argParser.cmdRom); + if (ioa is OpenAdvanced_OpenRom oaor) ioa = new(oaor.Path.MakeAbsolute()); // fixes #3224; should this be done for all the IOpenAdvanced types? --yoshi + _ = LoadRom(ioa.SimplePath, new LoadRomArgs(ioa)); if (Game.IsNullInstance()) { ShowMessageBox(owner: null, $"Failed to load {_argParser.cmdRom} specified on commandline"); @@ -667,7 +655,7 @@ _argParser.SocketAddress is var (socketIP, socketPort) // If user picked a game, then do the commandline logic if (!Game.IsNullInstance()) { - var movie = MovieSession.Get(_argParser.cmdMovie); + var movie = MovieSession.Get(_argParser.cmdMovie, true); MovieSession.ReadOnly = true; // if user is dumping and didn't supply dump length, make it as long as the loaded movie @@ -702,7 +690,7 @@ _argParser.SocketAddress is var (socketIP, socketPort) { if (File.Exists(Config.RecentMovies.MostRecent)) { - StartNewMovie(MovieSession.Get(Config.RecentMovies.MostRecent), false); + StartNewMovie(MovieSession.Get(Config.RecentMovies.MostRecent, true), false); } else { @@ -791,9 +779,9 @@ _ when double.TryParse(v, out var d) => d, { // OSTailoredCode.WindowsVersion._11 when win10PlusVersion! < new Version(10, 0, 22621) => $"Quick reminder: Your copy of Windows 11 (build {win10PlusVersion.Build}) is no longer supported by Microsoft.\nEmuHawk will probably continue working, but please update to at least 21H2 for increased security.", OSTailoredCode.WindowsVersion._11 => null, - OSTailoredCode.WindowsVersion._10 when win10PlusVersion! < new Version(10, 0, 19044) => $"Quick reminder: Your copy of Windows 10 (build {win10PlusVersion.Build}) is no longer supported by Microsoft.\nEmuHawk will probably continue working, but please update to at least 21H2 for increased security.", + OSTailoredCode.WindowsVersion._10 when win10PlusVersion! < new Version(10, 0, 19045) => $"Quick reminder: Your copy of Windows 10 (build {win10PlusVersion.Build}) is no longer supported by Microsoft.\nEmuHawk will probably continue working, but please update to at least 22H2 for increased security.", OSTailoredCode.WindowsVersion._10 => null, - _ => $"Quick reminder: Windows {winVersion.ToString().RemovePrefix('_').Replace("_", ".")} is no longer supported by Microsoft.\nEmuHawk will probably continue working, but please get a new operating system for increased security (either Windows 10+ or a GNU+Linux distro)." + _ => $"Quick reminder: Windows {winVersion.ToString().RemovePrefix('_').Replace('_', '.')} is no longer supported by Microsoft.\nEmuHawk will probably continue working, but please get a new operating system for increased security (either Windows 10+ or a GNU+Linux distro)." }; if (message is not null) { @@ -878,9 +866,8 @@ public int ProgramRunLoop() } StepRunLoop_Core(); - StepRunLoop_Throttle(); - Render(); + StepRunLoop_Throttle(); // HACK: RAIntegration might peek at memory during messages // we need this to allow memory access here, otherwise it will deadlock @@ -903,11 +890,6 @@ public int ProgramRunLoop() { break; } - - if (Config.DispSpeedupFeatures != 0) - { - Thread.Sleep(0); - } } Shutdown(); @@ -1087,6 +1069,13 @@ private set public readonly ToolManager Tools; + private IControlMainform ToolControllingSavestates => Tools.FirstOrNull(tool => tool.WantsToControlSavestates); + private IControlMainform ToolControllingRewind => Tools.FirstOrNull(tool => tool.WantsToControlRewind); + private IControlMainform ToolControllingReboot => Tools.FirstOrNull(tool => tool.WantsToControlReboot); + private IControlMainform ToolControllingStopMovie => Tools.FirstOrNull(tool => tool.WantsToControlStopMovie); + private IControlMainform ToolControllingRestartMovie => Tools.FirstOrNull(tool => tool.WantsToControlRestartMovie); + private IControlMainform ToolControllingReadOnly => Tools.FirstOrNull(tool => tool.WantsToControlReadOnly); + private DisplayManager DisplayManager; private OSDManager OSD => DisplayManager.OSD; @@ -1114,6 +1103,8 @@ private Sound Sound public void CreateRewinder() { + if (ToolControllingRewind is not null) return; + Rewinder?.Dispose(); Rewinder = Emulator.HasSavestates() && Config.Rewind.Enabled && (!Emulator.AsStatable().AvoidRewind || Config.Rewind.AllowSlowStates) ? Config.Rewind.UseDelta @@ -1272,9 +1263,9 @@ private void ProcessInput( public bool RebootCore() { - if (IsSlave && Master.WantsToControlReboot) + if (ToolControllingReboot is { } tool) { - Master.RebootCore(); + tool.RebootCore(); return true; } else @@ -1298,7 +1289,7 @@ public void UnpauseEmulator() public void TogglePause() { - EmulatorPaused ^= true; + EmulatorPaused = !EmulatorPaused; SetPauseStatusBarIcon(); // TODO: have tastudio set a pause status change callback, or take control over pause @@ -1380,7 +1371,7 @@ public void FrameBufferResized() // run this entire thing exactly twice, since the first resize may adjust the menu stacking for (int i = 0; i < 2; i++) { - int zoom = Config.TargetZoomFactors[Emulator.SystemId]; + int zoom = Config.GetWindowScaleFor(Emulator.SystemId); var area = Screen.FromControl(this).WorkingArea; int borderWidth = Size.Width - _presentationPanel.Control.Size.Width; @@ -1609,128 +1600,6 @@ public void UpdateCheatStatus() } } - private void SNES_ToggleBg(int layer) - { - if (Emulator is not (BsnesCore or SubBsnesCore or LibsnesCore or Snes9x) || !1.RangeTo(4).Contains(layer)) - { - return; - } - - bool result = false; - switch (Emulator) - { - case BsnesCore or SubBsnesCore: - { - var settingsProvider = Emulator.ServiceProvider.GetService>(); - var s = settingsProvider.GetSettings(); - switch (layer) - { - case 1: - result = s.ShowBG1_0 = s.ShowBG1_1 ^= true; - break; - case 2: - result = s.ShowBG2_0 = s.ShowBG2_1 ^= true; - break; - case 3: - result = s.ShowBG3_0 = s.ShowBG3_1 ^= true; - break; - case 4: - result = s.ShowBG4_0 = s.ShowBG4_1 ^= true; - break; - } - - settingsProvider.PutSettings(s); - break; - } - case LibsnesCore libsnes: - { - var s = libsnes.GetSettings(); - switch (layer) - { - case 1: - result = s.ShowBG1_0 = s.ShowBG1_1 ^= true; - break; - case 2: - result = s.ShowBG2_0 = s.ShowBG2_1 ^= true; - break; - case 3: - result = s.ShowBG3_0 = s.ShowBG3_1 ^= true; - break; - case 4: - result = s.ShowBG4_0 = s.ShowBG4_1 ^= true; - break; - } - - libsnes.PutSettings(s); - break; - } - case Snes9x snes9X: - { - var s = snes9X.GetSettings(); - switch (layer) - { - case 1: - result = s.ShowBg0 ^= true; - break; - case 2: - result = s.ShowBg1 ^= true; - break; - case 3: - result = s.ShowBg2 ^= true; - break; - case 4: - result = s.ShowBg3 ^= true; - break; - } - - snes9X.PutSettings(s); - break; - } - } - - AddOnScreenMessage($"BG {layer} Layer {(result ? "On" : "Off")}"); - } - - private void SNES_ToggleObj(int layer) - { - if (!(Emulator is LibsnesCore || Emulator is Snes9x) || !1.RangeTo(4).Contains(layer)) - { - return; - } - - bool result = false; - if (Emulator is LibsnesCore bsnes) - { - var s = bsnes.GetSettings(); - result = layer switch - { - 1 => (s.ShowOBJ_0 ^= true), - 2 => (s.ShowOBJ_1 ^= true), - 3 => (s.ShowOBJ_2 ^= true), - 4 => (s.ShowOBJ_3 ^= true), - _ => result - }; - - bsnes.PutSettings(s); - AddOnScreenMessage($"Obj {layer} Layer {(result ? "On" : "Off")}"); - } - else if (Emulator is Snes9x snes9X) - { - var s = snes9X.GetSettings(); - result = layer switch - { - 1 => (s.ShowSprites0 ^= true), - 2 => (s.ShowSprites1 ^= true), - 3 => (s.ShowSprites2 ^= true), - 4 => (s.ShowSprites3 ^= true), - _ => result - }; - - snes9X.PutSettings(s); - AddOnScreenMessage($"Sprite {layer} Layer {(result ? "On" : "Off")}"); - } - } - public bool RunLibretroCoreChooser() { string initFileName = null; @@ -2112,95 +1981,6 @@ private void RewireSound() } } - private void HandlePlatformMenus() - { - if (GenericCoreSubMenu.Visible) - { - var i = GenericCoreSubMenu.Text.IndexOf('&'); - if (i != -1) AvailableAccelerators.Add(GenericCoreSubMenu.Text[i + 1]); - } - GenericCoreSubMenu.Visible = false; - TI83SubMenu.Visible = false; - NESSubMenu.Visible = false; - GBSubMenu.Visible = false; - A7800SubMenu.Visible = false; - SNESSubMenu.Visible = false; - PSXSubMenu.Visible = false; - ColecoSubMenu.Visible = false; - N64SubMenu.Visible = false; - Ares64SubMenu.Visible = false; - GBLSubMenu.Visible = false; - AppleSubMenu.Visible = false; - C64SubMenu.Visible = false; - IntvSubMenu.Visible = false; - zXSpectrumToolStripMenuItem.Visible = false; - amstradCPCToolStripMenuItem.Visible = false; - - var sysID = Emulator.SystemId; - switch (sysID) - { - case VSystemID.Raw.NULL: - break; - case VSystemID.Raw.A78: - A7800SubMenu.Visible = true; - break; - case VSystemID.Raw.AmstradCPC: - amstradCPCToolStripMenuItem.Visible = true; - break; - case VSystemID.Raw.AppleII: - AppleSubMenu.Visible = true; - break; - case VSystemID.Raw.C64: - C64SubMenu.Visible = true; - break; - case VSystemID.Raw.Coleco: - ColecoSubMenu.Visible = true; - break; - case VSystemID.Raw.INTV: - IntvSubMenu.Visible = true; - break; - case VSystemID.Raw.N64 when Emulator is N64: - N64SubMenu.Visible = true; - break; - case VSystemID.Raw.N64 when Emulator is Ares64: - Ares64SubMenu.Visible = true; - break; - case VSystemID.Raw.NES: - NESSubMenu.Visible = true; - break; - case VSystemID.Raw.PSX when Emulator is Octoshock: - PSXSubMenu.Visible = true; - break; - case VSystemID.Raw.TI83: - TI83SubMenu.Visible = true; - LoadTIFileMenuItem.Visible = Emulator is TI83; - break; - case VSystemID.Raw.ZXSpectrum: - zXSpectrumToolStripMenuItem.Visible = true; - break; - case VSystemID.Raw.GBL when Emulator is GambatteLink: - GBLSubMenu.Visible = true; - break; - case VSystemID.Raw.GB: - case VSystemID.Raw.GBC: - case VSystemID.Raw.SGB when Emulator is Gameboy: - GBSubMenu.Visible = true; - SameBoyColorChooserMenuItem.Visible = Emulator is Sameboy { IsCGBMode: false }; // palette config only works in DMG mode - break; - case VSystemID.Raw.SNES when Emulator is LibsnesCore oldBSNES: // doesn't use "SGB" sysID, always "SNES" - SNESSubMenu.Text = oldBSNES.IsSGB ? "&SGB" : "&SNES"; - SNESSubMenu.Visible = true; - break; - case var _ when Emulator is BsnesCore or SubBsnesCore: - SNESSubMenu.Text = $"&{sysID}"; - SNESSubMenu.Visible = true; - break; - default: - DisplayDefaultCoreMenu(); - break; - } - } - private static readonly IList SpecializedTools = ReflectionCache.Types .Where(static t => !t.IsAbstract && typeof(IToolForm).IsAssignableFrom(t) && t.GetCustomAttribute() is not null) @@ -2283,7 +2063,7 @@ private void LoadMoviesFromRecent(string path) { if (File.Exists(path)) { - var movie = MovieSession.Get(path); + var movie = MovieSession.Get(path, true); MovieSession.ReadOnly = true; StartNewMovie(movie, false); } @@ -2297,15 +2077,10 @@ private void LoadRomFromRecent(string rom) { var ioa = OpenAdvancedSerializer.ParseWithLegacy(rom); - var args = new LoadRomArgs - { - OpenAdvanced = ioa - }; - // if(ioa is this or that) - for more complex behaviour string romPath = ioa.SimplePath; - if (!LoadRom(romPath, args, out var failureIsFromAskSave)) + if (!LoadRom(romPath, new LoadRomArgs(ioa), out var failureIsFromAskSave)) { if (failureIsFromAskSave) AddOnScreenMessage("ROM loading cancelled; a tool had unsaved changes"); else if (ioa is OpenAdvanced_LibretroNoGame || File.Exists(romPath)) AddOnScreenMessage("ROM loading failed"); @@ -2405,7 +2180,7 @@ private void CheckMessages() // only check window messages a maximum of once per millisecond // this check is irrelvant for the 99% of cases where fps are <1k // but gives a slight fps boost in those scenarios - if ((currentTime - _lastMessageCheck).Milliseconds > 0) + if ((uint)(currentTime - _lastMessageCheck).Milliseconds > 0) { _lastMessageCheck = currentTime; Application.DoEvents(); @@ -2459,7 +2234,7 @@ private void AutohideCursor(bool hide) public BitmapBuffer MakeScreenshotImage() { - var ret = new BitmapBuffer(_currentVideoProvider.BufferWidth, _currentVideoProvider.BufferHeight, _currentVideoProvider.GetVideoBuffer().ToArray()); + var ret = new BitmapBuffer(_currentVideoProvider.BufferWidth, _currentVideoProvider.BufferHeight, _currentVideoProvider.GetVideoBufferCopy()); ret.DiscardAlpha(); return ret; } @@ -2476,6 +2251,7 @@ private void SaveSlotSelectedMessage() { if (Config.DispSpeedupFeatures == 0) { + DisplayManager.DiscardApiHawkSurfaces(); return; } @@ -2539,7 +2315,7 @@ private void OpenRom() initDir: Config.PathEntries.RomAbsolutePath(Emulator.SystemId)); if (result is null) return; var filePath = new FileInfo(result).FullName; - _ = LoadRom(filePath, new LoadRomArgs { OpenAdvanced = new OpenAdvanced_OpenRom { Path = filePath } }); + _ = LoadRom(filePath, new LoadRomArgs(new OpenAdvanced_OpenRom(filePath))); } private void CoreSyncSettings(object sender, RomLoader.SettingsLoadArgs e) @@ -2645,28 +2421,20 @@ private void SaveConfig(string path = "") } private void ToggleFps() - { - Config.DisplayFps ^= true; - } + => Config.DisplayFps = !Config.DisplayFps; private void ToggleFrameCounter() - { - Config.DisplayFrameCounter ^= true; - } + => Config.DisplayFrameCounter = !Config.DisplayFrameCounter; private void ToggleLagCounter() - { - Config.DisplayLagCounter ^= true; - } + => Config.DisplayLagCounter = !Config.DisplayLagCounter; private void ToggleInputDisplay() - { - Config.DisplayInput ^= true; - } + => Config.DisplayInput = !Config.DisplayInput; public void ToggleSound() { - Config.SoundEnabled ^= true; + Config.SoundEnabled = !Config.SoundEnabled; Sound.StopSound(); Sound.StartSound(); } @@ -2786,21 +2554,25 @@ public BitmapBuffer CaptureLua() private void IncreaseWindowSize() { - if (Config.TargetZoomFactors[Emulator.SystemId] < WINDOW_SCALE_MAX) + var windowScale = Config.GetWindowScaleFor(Emulator.SystemId); + if (windowScale < WINDOW_SCALE_MAX) { - Config.TargetZoomFactors[Emulator.SystemId]++; + windowScale++; + Config.SetWindowScaleFor(Emulator.SystemId, windowScale); } - AddOnScreenMessage($"Screensize set to {Config.TargetZoomFactors[Emulator.SystemId]}x"); + AddOnScreenMessage($"Screensize set to {windowScale}x"); FrameBufferResized(); } private void DecreaseWindowSize() { - if (Config.TargetZoomFactors[Emulator.SystemId] > 1) + var windowScale = Config.GetWindowScaleFor(Emulator.SystemId); + if (windowScale > 1) { - Config.TargetZoomFactors[Emulator.SystemId]--; + windowScale--; + Config.SetWindowScaleFor(Emulator.SystemId, windowScale); } - AddOnScreenMessage($"Screensize set to {Config.TargetZoomFactors[Emulator.SystemId]}x"); + AddOnScreenMessage($"Screensize set to {windowScale}x"); FrameBufferResized(); } @@ -2940,7 +2712,7 @@ private void UpdateKeyPriorityIcon() private void ToggleBackgroundInput() { - Config.AcceptBackgroundInput ^= true; + Config.AcceptBackgroundInput = !Config.AcceptBackgroundInput; AddOnScreenMessage($"Background Input {(Config.AcceptBackgroundInput ? "enabled" : "disabled")}"); } @@ -3068,16 +2840,21 @@ private void LoadConfigFile(string iniPath) _throttle.Step(Config, Sound, allowSleep: true, forceFrameSkip: -1); } - public void FrameAdvance() + public void FrameAdvance(bool discardApiHawkSurfaces) { PressFrameAdvance = true; StepRunLoop_Core(true); + if (discardApiHawkSurfaces) + { + DisplayManager.DiscardApiHawkSurfaces(); + } } public void SeekFrameAdvance() { PressFrameAdvance = true; StepRunLoop_Core(true); + DisplayManager.DiscardApiHawkSurfaces(); PressFrameAdvance = false; } @@ -3245,7 +3022,7 @@ private void StepRunLoop_Core(bool force = false) MovieSession.Movie.SwitchToRecord(); } - if (isRewinding && !IsRewindSlave && MovieSession.Movie.IsRecording()) + if (isRewinding && ToolControllingRewind is null && MovieSession.Movie.IsRecording()) { MovieSession.Movie.Truncate(Emulator.Frame); } @@ -4030,7 +3807,7 @@ private bool LoadRomInternal(string path, LoadRomArgs args, out bool failureIsFr ExtToolManager.BuildToolStrip(); - RomLoaded?.Invoke(null, EventArgs.Empty); + RomLoaded?.Invoke(this, EventArgs.Empty); return true; } else if (Emulator.IsNull()) @@ -4044,7 +3821,7 @@ private bool LoadRomInternal(string path, LoadRomArgs args, out bool failureIsFr else { // The ROM has been loaded by a recursive invocation of the LoadROM method. - RomLoaded?.Invoke(null, EventArgs.Empty); + RomLoaded?.Invoke(this, EventArgs.Empty); return true; } } @@ -4163,7 +3940,6 @@ public void CloseRom(bool clearSram = false) Emulator.Dispose(); Emulator = new NullEmulator(); Game = GameInfo.NullInstance; - CreateRewinder(); Tools.Restart(Config, Emulator, Game); RewireSound(); ClearHolds(); @@ -4236,25 +4012,6 @@ public void DisableRewind() Rewinder = null; } - // TODO: move me - public IControlMainform Master { get; private set; } - - private bool IsSlave => Master != null; - - private bool IsSavestateSlave => IsSlave && Master.WantsToControlSavestates; - - private bool IsRewindSlave => IsSlave && Master.WantsToControlRewind; - - public void RelinquishControl(IControlMainform master) - { - Master = master; - } - - public void TakeBackControl() - { - Master = null; - } - private int SlotToInt(string slot) { return int.Parse(slot.Substring(slot.Length - 1, 1)); @@ -4270,7 +4027,7 @@ private int SlotToInt(string slot) public bool LoadState(string path, string userFriendlyStateName, bool suppressOSD = false) // Move to client.common { if (!Emulator.HasSavestates()) return false; - if (IsSavestateSlave) return Master.LoadState(); + if (ToolControllingSavestates is { } tool) return tool.LoadState(); if (!new SavestateFile(Emulator, MovieSession, MovieSession.UserBag).Load(path, this)) { @@ -4299,7 +4056,7 @@ public bool LoadState(string path, string userFriendlyStateName, bool suppressOS //we don't want to analyze how to intermix movies, rewinding, and states //so purge rewind history when loading a state while doing a movie - if (!IsRewindSlave && MovieSession.Movie.IsActive()) + if (ToolControllingRewind is null && MovieSession.Movie.IsActive()) { Rewinder?.Clear(); } @@ -4325,7 +4082,7 @@ public bool LoadQuickSave(int slot, bool suppressOSD = false) } if (handled) return true; // not sure - if (IsSavestateSlave) return Master.LoadQuickSave(SlotToInt(quickSlotName)); + if (ToolControllingSavestates is { } tool) return tool.LoadQuickSave(SlotToInt(quickSlotName)); var path = $"{SaveStatePrefix()}.{quickSlotName}.State"; if (!File.Exists(path)) @@ -4344,9 +4101,15 @@ public void SaveState(string path, string userFriendlyStateName, bool fromLua = return; } - if (IsSavestateSlave) + if (ToolControllingSavestates is { } tool) + { + tool.SaveState(); + return; + } + + if (MovieSession.Movie.IsFinished()) { - Master.SaveState(); + OSD.AddMessage("Cannot savestate after movie end!"); return; } @@ -4397,9 +4160,9 @@ public void SaveQuickSave(int slot, bool suppressOSD = false, bool fromLua = fal return; } - if (IsSavestateSlave) + if (ToolControllingSavestates is { } tool) { - Master.SaveQuickSave(SlotToInt(quickSlotName)); + tool.SaveQuickSave(SlotToInt(quickSlotName)); return; } @@ -4447,13 +4210,17 @@ bool PromptToSwitchCore(string currentCore, string recommendedCore, Action disab return true; } - return Emulator switch + var currentCoreName = Emulator.Attributes().CoreName; + var recommendedCore = currentCoreName switch { - Snes9x => PromptToSwitchCore(CoreNames.Snes9X, CoreNames.Bsnes115, () => Config.PreferredCores[VSystemID.Raw.SNES] = CoreNames.Bsnes115), - QuickNES => PromptToSwitchCore(CoreNames.QuickNes, CoreNames.NesHawk, () => Config.PreferredCores[VSystemID.Raw.NES] = CoreNames.NesHawk), - HyperNyma => PromptToSwitchCore(CoreNames.HyperNyma, CoreNames.TurboNyma, () => Config.PreferredCores[VSystemID.Raw.PCE] = CoreNames.TurboNyma), - _ => true + CoreNames.Snes9X => CoreNames.Bsnes115, + CoreNames.QuickNes => CoreNames.NesHawk, + CoreNames.HyperNyma => CoreNames.TurboNyma, + _ => null }; + return recommendedCore is null + ? true + : PromptToSwitchCore(currentCoreName, recommendedCore, () => Config.PreferredCores[Emulator.SystemId] = recommendedCore); } private void SaveStateAs() @@ -4470,9 +4237,9 @@ private void SaveStateAs() Tools.TAStudio.NamedStatePending = true; } - if (IsSavestateSlave) + if (ToolControllingSavestates is { } tool) { - Master.SaveStateAs(); + tool.SaveStateAs(); return; } @@ -4500,7 +4267,7 @@ private void SaveStateAs() private bool LoadStateAs() { if (!Emulator.HasSavestates()) return false; - if (IsSavestateSlave) return Master.LoadStateAs(); + if (ToolControllingSavestates is { } tool) return tool.LoadStateAs(); var result = this.ShowFileOpenDialog( discardCWDChange: true, @@ -4513,9 +4280,9 @@ private bool LoadStateAs() private void SelectSlot(int slot) { if (!Emulator.HasSavestates()) return; - if (IsSavestateSlave) + if (ToolControllingSavestates is { } tool) { - var handled = Master.SelectSlot(slot); + bool handled = tool.SelectSlot(slot); if (handled) return; } Config.SaveSlot = slot; @@ -4526,9 +4293,9 @@ private void SelectSlot(int slot) private void PreviousSlot() { if (!Emulator.HasSavestates()) return; - if (IsSavestateSlave) + if (ToolControllingSavestates is { } tool) { - var handled = Master.PreviousSlot(); + bool handled = tool.PreviousSlot(); if (handled) return; } Config.SaveSlot--; @@ -4540,9 +4307,9 @@ private void PreviousSlot() private void NextSlot() { if (!Emulator.HasSavestates()) return; - if (IsSavestateSlave) + if (ToolControllingSavestates is { } tool) { - var handled = Master.NextSlot(); + bool handled = tool.NextSlot(); if (handled) return; } Config.SaveSlot++; @@ -4553,9 +4320,9 @@ private void NextSlot() private void CaptureRewind(bool suppressCaptureRewind) { - if (IsRewindSlave) + if (ToolControllingRewind is { } tool) { - Master.CaptureRewind(); + tool.CaptureRewind(); } else if (!suppressCaptureRewind && Rewinder?.Active == true) { @@ -4569,7 +4336,7 @@ private bool Rewind(ref bool runFrame, long currentTimestamp, out bool returnToR returnToRecording = false; - if (IsRewindSlave) + if (ToolControllingRewind is { } rewindTool) { if (InputManager.ClientControls["Rewind"] || PressRewind) { @@ -4608,7 +4375,7 @@ private bool Rewind(ref bool runFrame, long currentTimestamp, out bool returnToR if (isRewinding) { runFrame = Emulator.Frame > 1; // TODO: the master should be deciding this! - Master.Rewind(); + rewindTool.Rewind(); } } else diff --git a/src/BizHawk.Client.EmuHawk/OpenAdvancedChooser.cs b/src/BizHawk.Client.EmuHawk/OpenAdvancedChooser.cs index 99394c69ee1..fe35a40ae88 100644 --- a/src/BizHawk.Client.EmuHawk/OpenAdvancedChooser.cs +++ b/src/BizHawk.Client.EmuHawk/OpenAdvancedChooser.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Collections.Generic; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/PlatformChooser.cs b/src/BizHawk.Client.EmuHawk/PlatformChooser.cs index 92aa384cf4f..5a47d7b5eb7 100644 --- a/src/BizHawk.Client.EmuHawk/PlatformChooser.cs +++ b/src/BizHawk.Client.EmuHawk/PlatformChooser.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -74,8 +73,6 @@ private void OkBtn_Click(object sender, EventArgs e) } private void label4_Click(object sender, EventArgs e) - { - AlwaysCheckbox.Checked ^= true; - } + => AlwaysCheckbox.Checked = !AlwaysCheckbox.Checked; } } diff --git a/src/BizHawk.Client.EmuHawk/PresentationPanel.cs b/src/BizHawk.Client.EmuHawk/PresentationPanel.cs index 9cd9ba96c8b..443a3ea4cc6 100644 --- a/src/BizHawk.Client.EmuHawk/PresentationPanel.cs +++ b/src/BizHawk.Client.EmuHawk/PresentationPanel.cs @@ -1,9 +1,8 @@ -using System; using System.Drawing; using System.Windows.Forms; using BizHawk.Client.Common; -using BizHawk.Bizware.BizwareGL; +using BizHawk.Bizware.Graphics; using BizHawk.Bizware.Graphics.Controls; namespace BizHawk.Client.EmuHawk diff --git a/src/BizHawk.Client.EmuHawk/Program.cs b/src/BizHawk.Client.EmuHawk/Program.cs index a19063d780b..2b2c151dbc2 100644 --- a/src/BizHawk.Client.EmuHawk/Program.cs +++ b/src/BizHawk.Client.EmuHawk/Program.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using System.IO; using System.Collections.Generic; @@ -7,7 +6,6 @@ using System.Runtime.InteropServices; using System.Windows.Forms; -using BizHawk.Bizware.BizwareGL; using BizHawk.Bizware.Graphics; using BizHawk.Common; using BizHawk.Common.PathExtensions; @@ -108,7 +106,6 @@ private static int SubMain(string[] args) { BizInvoke.ReflectionCache.AsmVersion, Bizware.Audio.ReflectionCache.AsmVersion, - Bizware.BizwareGL.ReflectionCache.AsmVersion, Bizware.Graphics.ReflectionCache.AsmVersion, Bizware.Graphics.Controls.ReflectionCache.AsmVersion, Bizware.Input.ReflectionCache.AsmVersion, @@ -207,9 +204,9 @@ IGL TryInitIGL(EDispMethod dispMethod) // try to fallback on the faster option on Windows // if we're on a Unix platform, there's only 1 fallback here... 1 when OSTailoredCode.IsUnixHost => (EDispMethod.GdiPlus, "GDI+"), - 1 or 2 when !OSTailoredCode.IsUnixHost => dispMethod == EDispMethod.D3D9 + 1 or 2 when !OSTailoredCode.IsUnixHost => dispMethod == EDispMethod.D3D11 ? (EDispMethod.OpenGL, "OpenGL") - : (EDispMethod.D3D9, "Direct3D9"), + : (EDispMethod.D3D11, "Direct3D11"), _ => (EDispMethod.GdiPlus, "GDI+") }; @@ -217,7 +214,7 @@ IGL CheckRenderer(IGL gl) { try { - using (gl.CreateRenderer()) return gl; + using (gl.CreateGuiRenderer()) return gl; } catch (Exception ex) { @@ -229,7 +226,7 @@ IGL CheckRenderer(IGL gl) switch (dispMethod) { - case EDispMethod.D3D9: + case EDispMethod.D3D11: if (OSTailoredCode.IsUnixHost || OSTailoredCode.IsWine) { // possibly sharing config w/ Windows, assume the user wants the not-slow method (but don't change the config) @@ -237,12 +234,12 @@ IGL CheckRenderer(IGL gl) } try { - return CheckRenderer(new IGL_D3D9()); + return CheckRenderer(new IGL_D3D11()); } catch (Exception ex) { var (method, name) = ChooseFallback(); - new ExceptionBox(new Exception($"Initialization of Direct3D9 Display Method failed; falling back to {name}", ex)).ShowDialog(); + new ExceptionBox(new Exception($"Initialization of Direct3D11 Display Method failed; falling back to {name}", ex)).ShowDialog(); return TryInitIGL(initialConfig.DispMethod = method); } case EDispMethod.OpenGL: @@ -253,12 +250,16 @@ IGL CheckRenderer(IGL gl) new ExceptionBox(new Exception($"Initialization of OpenGL Display Method failed; falling back to {name}")).ShowDialog(); return TryInitIGL(initialConfig.DispMethod = method); } - var igl = new IGL_OpenGL(); // need to have a context active for checking renderer, will be disposed afterwards - using (new SDL2OpenGLContext(3, 0, false, false)) + using (new SDL2OpenGLContext(3, 2, true)) { - return CheckRenderer(igl); + using var testOpenGL = new IGL_OpenGL(); + testOpenGL.InitGLState(); + _ = CheckRenderer(testOpenGL); } + + // don't return the same IGL, we don't want the test context to be part of this IGL + return new IGL_OpenGL(); default: case EDispMethod.GdiPlus: // if this fails, we're screwed diff --git a/src/BizHawk.Client.EmuHawk/Properties/Resources.cs b/src/BizHawk.Client.EmuHawk/Properties/Resources.cs index c406b7c0743..2347a123bc8 100644 --- a/src/BizHawk.Client.EmuHawk/Properties/Resources.cs +++ b/src/BizHawk.Client.EmuHawk/Properties/Resources.cs @@ -1,5 +1,5 @@ -using System; using System.Drawing; +using System.IO; using System.Windows.Forms; namespace BizHawk.Client.EmuHawk.Properties @@ -211,5 +211,8 @@ internal static class Resources internal static readonly Bitmap YellowLeft = ReadEmbeddedBitmap("YellowLeft"); internal static readonly Bitmap YellowRight = ReadEmbeddedBitmap("YellowRight"); internal static readonly Bitmap YellowUp = ReadEmbeddedBitmap("YellowUp"); + + internal static Stream GetNotHawkCallSFX() + => EmuHawk.ReflectionCache.EmbeddedResourceStream("Resources.nothawk.wav"); } } diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/IRetroAchievements.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/IRetroAchievements.cs index 916cfed5b88..5e1803b6779 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/IRetroAchievements.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/IRetroAchievements.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Client.EmuHawk { public interface IRetroAchievements : IDisposable diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/LibRCheevos.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/LibRCheevos.cs index 7f31224df31..fc60ce2384d 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/LibRCheevos.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/LibRCheevos.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RAIntegration.Update.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RAIntegration.Update.cs index ad534ff985a..668df2be2da 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RAIntegration.Update.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RAIntegration.Update.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RAIntegration.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RAIntegration.cs index e292f253fa9..cd11e62906d 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RAIntegration.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RAIntegration.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Runtime.InteropServices; using System.Text; @@ -68,7 +67,11 @@ private void RebuildMenu() Checked = _getConfig().RAAutostart, CheckOnClick = true, }; - tsi.CheckedChanged += (_, _) => _getConfig().RAAutostart ^= true; + tsi.CheckedChanged += (_, _) => + { + var config = _getConfig(); + config.RAAutostart = !config.RAAutostart; + }; _raDropDownItems.Add(tsi); var tss = new ToolStripSeparator(); @@ -139,7 +142,7 @@ public RAIntegration( Marshal.Copy(name, 0, buffer, Math.Min(name.Length, 256)); }; _resetEmulator = () => _mainForm.RebootCore(); - _loadROM = path => _ = _mainForm.LoadRom(path, new() { OpenAdvanced = OpenAdvancedSerializer.ParseWithLegacy(path) }); + _loadROM = path => _ = _mainForm.LoadRom(path, new LoadRomArgs(new OpenAdvanced_OpenRom(path))); RA.InstallSharedFunctionsExt(_isActive, _unpause, _pause, _rebuildMenu, _estimateTitle, _resetEmulator, _loadROM); diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RAIntegrationDownloaderForm.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RAIntegrationDownloaderForm.cs index cbe3e517b87..db1a5485e86 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RAIntegrationDownloaderForm.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RAIntegrationDownloaderForm.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Threading; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RAInterface.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RAInterface.cs index 5d6e7186363..9251f4ba6a8 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RAInterface.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RAInterface.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.BizInvoke; diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Achievements.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Achievements.cs index cb42c735593..bd4fe51082c 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Achievements.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Achievements.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Text; @@ -148,14 +147,14 @@ private void ToggleUnofficialCheevos() { if (_gameData.GameID == 0) { - AllowUnofficialCheevos ^= true; + AllowUnofficialCheevos = !AllowUnofficialCheevos; return; } _activeModeUnlocksRequest.Wait(); DeactivateCheevos(HardcoreMode); - AllowUnofficialCheevos ^= true; + AllowUnofficialCheevos = !AllowUnofficialCheevos; ActivateCheevos(HardcoreMode); } diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Debug.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Debug.cs index a1054211eaa..72d03b4a90a 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Debug.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Debug.cs @@ -1,4 +1,3 @@ -using System; using System.Buffers; using System.IO; using System.Runtime.InteropServices; @@ -310,7 +309,7 @@ private static void InternalDebugHash(string path) { static string ResolvePath(string path) { - if (path.IndexOf('|') == -1 && Disc.IsValidExtension(Path.GetExtension(path))) + if (!HawkFile.PathContainsPipe(path) && Disc.IsValidExtension(Path.GetExtension(path))) { return path; // nothing to do in this case } @@ -342,7 +341,7 @@ static string ResolvePath(string path) static ConsoleID IdentifyConsole(string path) { - if (path.IndexOf('|') == -1 && Disc.IsValidExtension(Path.GetExtension(path))) + if (!HawkFile.PathContainsPipe(path) && Disc.IsValidExtension(Path.GetExtension(path))) { using var disc = DiscExtensions.CreateAnyType(path, Console.WriteLine); if (disc is null) diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.GameInfo.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.GameInfo.cs index c16955505cb..93fe4607e61 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.GameInfo.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.GameInfo.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.IO; diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Http.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Http.cs index b0ee101a5c9..34f8a39fa87 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Http.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Http.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; @@ -112,7 +111,7 @@ protected void InternalDoRequest(LibRCheevos.rc_error_t apiParamsResult, ref Lib ? HttpPost(request.URL, request.PostData, request.ContentType) : HttpGet(request.URL); - apiTask.ContinueWith(async t => + _ = apiTask.ContinueWith(async t => { var result = await t; if (result is null) // likely a timeout diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Leaderboards.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Leaderboards.cs index 48727a99a69..3128d2c9f1f 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Leaderboards.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Leaderboards.cs @@ -1,4 +1,3 @@ -using System; using System.Text; namespace BizHawk.Client.EmuHawk diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Login.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Login.cs index c54a4eefd07..0a8b16735ad 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Login.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Login.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Client.EmuHawk { public partial class RCheevos diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Ping.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Ping.cs index 868db73bdf1..e34615fe96a 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Ping.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Ping.cs @@ -1,4 +1,3 @@ -using System; using System.Text; namespace BizHawk.Client.EmuHawk diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Sound.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Sound.cs index bb7da1cf7cd..791b5a65b8a 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Sound.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Sound.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Common.PathExtensions; diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.cs index c86764d2b0d..a386aa4258e 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Linq; using System.Runtime.InteropServices; @@ -73,7 +72,11 @@ private void BuildMenu(ToolStripItemCollection raDropDownItems) Checked = _getConfig().RAAutostart, CheckOnClick = true, }; - autoStartRAItem.CheckedChanged += (_, _) => _getConfig().RAAutostart ^= true; + autoStartRAItem.CheckedChanged += (_, _) => + { + var config = _getConfig(); + config.RAAutostart = !config.RAAutostart; + }; raDropDownItems.Add(autoStartRAItem); var loginItem = new ToolStripMenuItem("Login") @@ -111,7 +114,7 @@ private void BuildMenu(ToolStripItemCollection raDropDownItems) Checked = CheevosActive, CheckOnClick = true }; - enableCheevosItem.CheckedChanged += (_, _) => CheevosActive ^= true; + enableCheevosItem.CheckedChanged += (_, _) => CheevosActive = !CheevosActive; raDropDownItems.Add(enableCheevosItem); var enableLboardsItem = new ToolStripMenuItem("Enable Leaderboards") @@ -120,7 +123,7 @@ private void BuildMenu(ToolStripItemCollection raDropDownItems) CheckOnClick = true, Enabled = HardcoreMode }; - enableLboardsItem.CheckedChanged += (_, _) => LBoardsActive ^= true; + enableLboardsItem.CheckedChanged += (_, _) => LBoardsActive = !LBoardsActive; raDropDownItems.Add(enableLboardsItem); var enableRichPresenceItem = new ToolStripMenuItem("Enable Rich Presence") @@ -128,7 +131,7 @@ private void BuildMenu(ToolStripItemCollection raDropDownItems) Checked = RichPresenceActive, CheckOnClick = true }; - enableRichPresenceItem.CheckedChanged += (_, _) => RichPresenceActive ^= true; + enableRichPresenceItem.CheckedChanged += (_, _) => RichPresenceActive = !RichPresenceActive; raDropDownItems.Add(enableRichPresenceItem); var enableHardcoreItem = new ToolStripMenuItem("Enable Hardcore Mode") @@ -138,8 +141,7 @@ private void BuildMenu(ToolStripItemCollection raDropDownItems) }; enableHardcoreItem.CheckedChanged += (_, _) => { - _hardcoreMode ^= true; - + _hardcoreMode = !_hardcoreMode; if (HardcoreMode) { _hardcoreMode = _mainForm.RebootCore(); // unset hardcore mode if we fail to reboot core somehow @@ -160,7 +162,7 @@ private void BuildMenu(ToolStripItemCollection raDropDownItems) Checked = EnableSoundEffects, CheckOnClick = true }; - enableSoundEffectsItem.CheckedChanged += (_, _) => EnableSoundEffects ^= true; + enableSoundEffectsItem.CheckedChanged += (_, _) => EnableSoundEffects = !EnableSoundEffects; raDropDownItems.Add(enableSoundEffectsItem); var enableUnofficialCheevosItem = new ToolStripMenuItem("Test Unofficial Achievements") @@ -283,7 +285,7 @@ public override void OnSaveState(string path) { var buffer = new byte[(int)size]; _lib.rc_runtime_serialize_progress(buffer, _runtime, IntPtr.Zero); - using var file = File.OpenWrite(path + ".rap"); + using var file = File.Create(path + ".rap"); file.Write(buffer, 0, buffer.Length); } } @@ -697,4 +699,4 @@ public override void OnFrameAdvance() #endif } } -} \ No newline at end of file +} diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevosAchievementForm.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevosAchievementForm.cs index b6e18facb12..e17ea086734 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevosAchievementForm.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevosAchievementForm.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevosAchievementListForm.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevosAchievementListForm.cs index f6a2c07b885..9dc2db82eb7 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevosAchievementListForm.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevosAchievementListForm.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevosLeaderboardListForm.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevosLeaderboardListForm.cs index 301f14d9303..c7fd886ede2 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevosLeaderboardListForm.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevosLeaderboardListForm.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevosLoginForm.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevosLoginForm.cs index c9c061ca96a..bb3c4865238 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevosLoginForm.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevosLoginForm.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.GameVerification.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.GameVerification.cs index dc3986945a7..21d9afbb97d 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.GameVerification.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.GameVerification.cs @@ -1,5 +1,5 @@ -using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; @@ -124,7 +124,7 @@ int GetFileSector(string filename, out int filesize) // end of the path has ; var end = exePath.IndexOf(';'); if (end < 0) break; - exePath = exePath[index..end]; + exePath = exePath.Substring(startIndex: index, length: end - index); } buffer.AddRange(Encoding.ASCII.GetBytes(exePath)); @@ -433,7 +433,8 @@ private bool GetNcchNormalKeysFunc(IntPtr primary_key_y, byte secondary_key_x_sl Marshal.Copy(optional_program_id, programIdBytes, 0, 8); var programId = BitConverter.ToUInt64(programIdBytes, 0); - using var seeddb = new BinaryReader(GetFirmware(new("3DS", "seeddb"))); + FirmwareID seeddbFWID = new("3DS", "seeddb"); + using BinaryReader seeddb = new(GetFirmware(seeddbFWID)); var count = seeddb.ReadUInt32(); seeddb.BaseStream.Seek(12, SeekOrigin.Current); // apparently some padding bytes before actual seeds for (long i = 0; i < count; i++) @@ -447,7 +448,8 @@ private bool GetNcchNormalKeysFunc(IntPtr primary_key_y, byte secondary_key_x_sl var sha256Input = new byte[32]; Marshal.Copy(primary_key_y, sha256Input, 0, 16); - seeddb.BaseStream.Read(sha256Input, 16, 16); + var bytesRead = seeddb.BaseStream.Read(sha256Input, offset: 16, count: 16); + Debug.Assert(bytesRead is 16, $"reached end-of-file while reading {seeddbFWID} firmware"); var sha256Digest = SHA256Checksum.Compute(sha256Input); var secondaryKeyYBytes = new byte[17]; diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.Hardcore.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.Hardcore.cs index df39963a8e4..906d7908f89 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.Hardcore.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.Hardcore.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.Memory.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.Memory.cs index 9933caa66d5..a14a394edeb 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.Memory.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.Memory.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; @@ -355,24 +354,23 @@ public ChanFMemFunctions(IDebuggable debuggable, MemoryDomain vram) // these consoles will use the entire system bus private static readonly ConsoleID[] UseFullSysBus = - { + [ ConsoleID.NES, ConsoleID.C64, ConsoleID.AmstradCPC, ConsoleID.Atari7800, - }; + ]; // these consoles will use the entire main memory domain private static readonly ConsoleID[] UseFullMainMem = - { - ConsoleID.PlayStation, ConsoleID.Lynx, ConsoleID.NeoGeoPocket, ConsoleID.Jaguar, + [ + ConsoleID.Amiga, ConsoleID.Lynx, ConsoleID.NeoGeoPocket, ConsoleID.Jaguar, ConsoleID.JaguarCD, ConsoleID.DS, ConsoleID.DSi, ConsoleID.AppleII, ConsoleID.Vectrex, ConsoleID.Tic80, ConsoleID.PCEngine, ConsoleID.Uzebox, ConsoleID.Nintendo3DS, - }; + ]; // these consoles will use part of the system bus at an offset private static readonly Dictionary UsePartialSysBus = new() { - [ConsoleID.Colecovision] = new[] { (0x6000u, 0x400u) }, - [ConsoleID.SG1000] = new[] { (0xC000u, 0x2000u), (0x2000u, 0x2000u), (0x8000u, 0x2000u) }, + [ConsoleID.SG1000] = [ (0xC000u, 0x2000u), (0x2000u, 0x2000u), (0x8000u, 0x2000u) ], }; // anything more complicated will be handled accordingly @@ -430,6 +428,10 @@ void TryAddDomain(string domain, uint? size = null, uint addressMangler = 0) TryAddDomain("Save RAM"); TryAddDomain("SRAM"); break; + case ConsoleID.PlayStation: + mfs.Add(new(domains["MainRAM"], 0, domains["MainRAM"].Size)); + mfs.Add(new(domains["DCache"], 0, domains["DCache"].Size)); + break; case ConsoleID.SNES: mfs.Add(new(domains["WRAM"], 0, domains["WRAM"].Size)); TryAddDomain("CARTRAM"); @@ -538,6 +540,11 @@ void TryAddDomain(string domain, uint? size = null, uint addressMangler = 0) mfs.Add(new(domains["Work Ram Low"], 0, domains["Work Ram Low"].Size, 1)); mfs.Add(new(domains["Work Ram High"], 0, domains["Work Ram High"].Size, 1)); break; + case ConsoleID.Colecovision: + mfs.Add(new(domains["Main RAM"], 0, domains["Main RAM"].Size)); + TryAddDomain("SGM Low RAM"); + TryAddDomain("SGM High RAM"); + break; case ConsoleID.Intellivision: // special case mfs.Add(new NullMemFunctions(0x80)); diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.cs index 8e7a5e4ee7f..a2c74b4bbd8 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RetroAchievements.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/RomStatusPicker.cs b/src/BizHawk.Client.EmuHawk/RomStatusPicker.cs index 8ba7eaa849b..1a846b35db4 100644 --- a/src/BizHawk.Client.EmuHawk/RomStatusPicker.cs +++ b/src/BizHawk.Client.EmuHawk/RomStatusPicker.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Client.EmuHawk.Properties; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/Sound/Sound.cs b/src/BizHawk.Client.EmuHawk/Sound/Sound.cs index 0ba3efc41de..43e359aca0f 100644 --- a/src/BizHawk.Client.EmuHawk/Sound/Sound.cs +++ b/src/BizHawk.Client.EmuHawk/Sound/Sound.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Threading; diff --git a/src/BizHawk.Client.EmuHawk/Throttle.cs b/src/BizHawk.Client.EmuHawk/Throttle.cs index a686550bf57..ce8c6bea8b9 100644 --- a/src/BizHawk.Client.EmuHawk/Throttle.cs +++ b/src/BizHawk.Client.EmuHawk/Throttle.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using System.Threading; diff --git a/src/BizHawk.Client.EmuHawk/ToolAttribute.cs b/src/BizHawk.Client.EmuHawk/ToolAttribute.cs index 1f22ffac895..77e19b7ce3c 100644 --- a/src/BizHawk.Client.EmuHawk/ToolAttribute.cs +++ b/src/BizHawk.Client.EmuHawk/ToolAttribute.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/UIHelper.cs b/src/BizHawk.Client.EmuHawk/UIHelper.cs index 72e851b3fdc..d9c3d4a48a9 100644 --- a/src/BizHawk.Client.EmuHawk/UIHelper.cs +++ b/src/BizHawk.Client.EmuHawk/UIHelper.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/UpdateChecker.cs b/src/BizHawk.Client.EmuHawk/UpdateChecker.cs index 045682a2c84..b1bff70609f 100644 --- a/src/BizHawk.Client.EmuHawk/UpdateChecker.cs +++ b/src/BizHawk.Client.EmuHawk/UpdateChecker.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Net; using System.Threading; diff --git a/src/BizHawk.Client.EmuHawk/app.config b/src/BizHawk.Client.EmuHawk/app.config index b30b4b86b17..cd26a46e517 100644 --- a/src/BizHawk.Client.EmuHawk/app.config +++ b/src/BizHawk.Client.EmuHawk/app.config @@ -1,13 +1,13 @@ - + - + - - - + + + diff --git a/src/BizHawk.Client.EmuHawk/app.manifest b/src/BizHawk.Client.EmuHawk/app.manifest index c86efcb5ad4..bda8c3b1b62 100644 --- a/src/BizHawk.Client.EmuHawk/app.manifest +++ b/src/BizHawk.Client.EmuHawk/app.manifest @@ -35,13 +35,10 @@ - true + system diff --git a/src/BizHawk.Client.EmuHawk/config/A7800/A7800ControllerSettings.cs b/src/BizHawk.Client.EmuHawk/config/A7800/A7800ControllerSettings.cs index 9e473f089ac..99ca124ea74 100644 --- a/src/BizHawk.Client.EmuHawk/config/A7800/A7800ControllerSettings.cs +++ b/src/BizHawk.Client.EmuHawk/config/A7800/A7800ControllerSettings.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/A7800/A7800FilterSettings.cs b/src/BizHawk.Client.EmuHawk/config/A7800/A7800FilterSettings.cs index 7386432e56a..dc616ba8c21 100644 --- a/src/BizHawk.Client.EmuHawk/config/A7800/A7800FilterSettings.cs +++ b/src/BizHawk.Client.EmuHawk/config/A7800/A7800FilterSettings.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/AmstradCPC/AmstradCPCAudioSettings.cs b/src/BizHawk.Client.EmuHawk/config/AmstradCPC/AmstradCPCAudioSettings.cs index 5e95e7f5c49..e863e116f9f 100644 --- a/src/BizHawk.Client.EmuHawk/config/AmstradCPC/AmstradCPCAudioSettings.cs +++ b/src/BizHawk.Client.EmuHawk/config/AmstradCPC/AmstradCPCAudioSettings.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/AmstradCPC/AmstradCPCCoreEmulationSettings.cs b/src/BizHawk.Client.EmuHawk/config/AmstradCPC/AmstradCPCCoreEmulationSettings.cs index 179c0146571..1ff73b119f2 100644 --- a/src/BizHawk.Client.EmuHawk/config/AmstradCPC/AmstradCPCCoreEmulationSettings.cs +++ b/src/BizHawk.Client.EmuHawk/config/AmstradCPC/AmstradCPCCoreEmulationSettings.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/AmstradCPC/AmstradCPCNonSyncSettings.cs b/src/BizHawk.Client.EmuHawk/config/AmstradCPC/AmstradCPCNonSyncSettings.cs index 644093431a9..3cddb8dbb17 100644 --- a/src/BizHawk.Client.EmuHawk/config/AmstradCPC/AmstradCPCNonSyncSettings.cs +++ b/src/BizHawk.Client.EmuHawk/config/AmstradCPC/AmstradCPCNonSyncSettings.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/AnalogRangeConfig.cs b/src/BizHawk.Client.EmuHawk/config/AnalogRangeConfig.cs index 1f4033ba8a7..c9a4e222c85 100644 --- a/src/BizHawk.Client.EmuHawk/config/AnalogRangeConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/AnalogRangeConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; @@ -122,7 +121,7 @@ protected override void OnMouseDown(MouseEventArgs e) } else if (e.Button == MouseButtons.Right) { - Radial ^= true; + Radial = !Radial; } base.OnMouseDown(e); diff --git a/src/BizHawk.Client.EmuHawk/config/AnalogRangeConfigControl.cs b/src/BizHawk.Client.EmuHawk/config/AnalogRangeConfigControl.cs index 2f2b0ee7c03..42a9ef44faa 100644 --- a/src/BizHawk.Client.EmuHawk/config/AnalogRangeConfigControl.cs +++ b/src/BizHawk.Client.EmuHawk/config/AnalogRangeConfigControl.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; namespace BizHawk.Client.EmuHawk diff --git a/src/BizHawk.Client.EmuHawk/config/AutofireConfig.cs b/src/BizHawk.Client.EmuHawk/config/AutofireConfig.cs index ed95eb83114..8458ddd66d1 100644 --- a/src/BizHawk.Client.EmuHawk/config/AutofireConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/AutofireConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/ColecoVision/ColecoControllerSettings.cs b/src/BizHawk.Client.EmuHawk/config/ColecoVision/ColecoControllerSettings.cs index bf7f4a2577b..3f023b08a18 100644 --- a/src/BizHawk.Client.EmuHawk/config/ColecoVision/ColecoControllerSettings.cs +++ b/src/BizHawk.Client.EmuHawk/config/ColecoVision/ColecoControllerSettings.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/ControllerConfig.cs b/src/BizHawk.Client.EmuHawk/config/ControllerConfig.cs index 50641fb9ec0..9b4ae668562 100644 --- a/src/BizHawk.Client.EmuHawk/config/ControllerConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/ControllerConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Client.EmuHawk/config/ControllerConfig/AnalogBindControl.cs b/src/BizHawk.Client.EmuHawk/config/ControllerConfig/AnalogBindControl.cs index d0d200456da..c84e8cb9bd1 100644 --- a/src/BizHawk.Client.EmuHawk/config/ControllerConfig/AnalogBindControl.cs +++ b/src/BizHawk.Client.EmuHawk/config/ControllerConfig/AnalogBindControl.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/ControllerConfig/ControllerConfigPanel.cs b/src/BizHawk.Client.EmuHawk/config/ControllerConfig/ControllerConfigPanel.cs index 7398d888455..27314a5713c 100644 --- a/src/BizHawk.Client.EmuHawk/config/ControllerConfig/ControllerConfigPanel.cs +++ b/src/BizHawk.Client.EmuHawk/config/ControllerConfig/ControllerConfigPanel.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/config/DisplayConfig.Designer.cs b/src/BizHawk.Client.EmuHawk/config/DisplayConfig.Designer.cs index cddc5b0da72..6ce2c780788 100644 --- a/src/BizHawk.Client.EmuHawk/config/DisplayConfig.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/config/DisplayConfig.Designer.cs @@ -81,9 +81,9 @@ private void InitializeComponent() this.label6 = new BizHawk.WinForms.Controls.LocLabelEx(); this.groupBox3 = new System.Windows.Forms.GroupBox(); this.label13 = new BizHawk.WinForms.Controls.LocLabelEx(); - this.cbAlternateVsync = new System.Windows.Forms.CheckBox(); + this.cbAllowTearing = new System.Windows.Forms.CheckBox(); this.label8 = new BizHawk.WinForms.Controls.LocLabelEx(); - this.rbD3D9 = new System.Windows.Forms.RadioButton(); + this.rbD3D11 = new System.Windows.Forms.RadioButton(); this.label7 = new BizHawk.WinForms.Controls.LocLabelEx(); this.rbGDIPlus = new System.Windows.Forms.RadioButton(); this.tpMisc = new System.Windows.Forms.TabPage(); @@ -633,9 +633,9 @@ private void InitializeComponent() // groupBox3 // this.groupBox3.Controls.Add(this.label13); - this.groupBox3.Controls.Add(this.cbAlternateVsync); + this.groupBox3.Controls.Add(this.cbAllowTearing); this.groupBox3.Controls.Add(this.label8); - this.groupBox3.Controls.Add(this.rbD3D9); + this.groupBox3.Controls.Add(this.rbD3D11); this.groupBox3.Controls.Add(this.label7); this.groupBox3.Controls.Add(this.rbGDIPlus); this.groupBox3.Controls.Add(this.label5); @@ -652,34 +652,34 @@ private void InitializeComponent() this.label13.Name = "label13"; this.label13.Text = resources.GetString("label13.Text"); this.label13.Click += new System.EventHandler(this.Label13_Click); - this.label13.DoubleClick += new System.EventHandler(this.Label13_Click); - // - // cbAlternateVsync - // - this.cbAlternateVsync.AutoSize = true; - this.cbAlternateVsync.Location = new System.Drawing.Point(28, 60); - this.cbAlternateVsync.Name = "cbAlternateVsync"; - this.cbAlternateVsync.Size = new System.Drawing.Size(15, 14); - this.cbAlternateVsync.TabIndex = 21; - this.cbAlternateVsync.UseVisualStyleBackColor = true; + this.label13.DoubleClick += new System.EventHandler(this.Label13_Click); + // + // cbAllowTearing + // + this.cbAllowTearing.AutoSize = true; + this.cbAllowTearing.Location = new System.Drawing.Point(28, 60); + this.cbAllowTearing.Name = "cbAllowTearing"; + this.cbAllowTearing.Size = new System.Drawing.Size(15, 14); + this.cbAllowTearing.TabIndex = 21; + this.cbAllowTearing.UseVisualStyleBackColor = true; // // label8 // this.label8.Location = new System.Drawing.Point(21, 30); this.label8.Name = "label8"; - this.label8.Text = " • Best compatibility\r\n • May have trouble with OpenGL-based cores (N64)\r\n"; - // - // rbD3D9 - // - this.rbD3D9.AutoSize = true; - this.rbD3D9.Checked = true; - this.rbD3D9.Location = new System.Drawing.Point(6, 10); - this.rbD3D9.Name = "rbD3D9"; - this.rbD3D9.Size = new System.Drawing.Size(73, 17); - this.rbD3D9.TabIndex = 19; - this.rbD3D9.TabStop = true; - this.rbD3D9.Text = "Direct3D9"; - this.rbD3D9.UseVisualStyleBackColor = true; + this.label8.Text = " • Best compatibility\r\n • May have decreased performance for OpenGL-based cores (NDS, 3DS)\r\n"; + // + // rbD3D11 + // + this.rbD3D11.AutoSize = true; + this.rbD3D11.Checked = true; + this.rbD3D11.Location = new System.Drawing.Point(6, 10); + this.rbD3D11.Name = "rbD3D11"; + this.rbD3D11.Size = new System.Drawing.Size(73, 17); + this.rbD3D11.TabIndex = 19; + this.rbD3D11.TabStop = true; + this.rbD3D11.Text = "Direct3D11"; + this.rbD3D11.UseVisualStyleBackColor = true; // // label7 // @@ -1050,7 +1050,7 @@ private void InitializeComponent() private System.Windows.Forms.RadioButton rbGDIPlus; private System.Windows.Forms.TabPage tpMisc; private BizHawk.WinForms.Controls.LocLabelEx label8; - private System.Windows.Forms.RadioButton rbD3D9; + private System.Windows.Forms.RadioButton rbD3D11; private System.Windows.Forms.TabPage tabPage1; private System.Windows.Forms.CheckBox cbStatusBarWindowed; private BizHawk.WinForms.Controls.LocLabelEx label9; @@ -1078,7 +1078,7 @@ private void InitializeComponent() private System.Windows.Forms.TextBox txtCustomARX; private System.Windows.Forms.CheckBox cbAutoPrescale; private BizHawk.WinForms.Controls.LocLabelEx label13; - private System.Windows.Forms.CheckBox cbAlternateVsync; + private System.Windows.Forms.CheckBox cbAllowTearing; private BizHawk.WinForms.Controls.LocLabelEx label1; private System.Windows.Forms.CheckBox cbFullscreenHacks; private System.Windows.Forms.Button btnDefaults; diff --git a/src/BizHawk.Client.EmuHawk/config/DisplayConfig.cs b/src/BizHawk.Client.EmuHawk/config/DisplayConfig.cs index cf25fcd9052..587cc15070a 100755 --- a/src/BizHawk.Client.EmuHawk/config/DisplayConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/DisplayConfig.cs @@ -1,9 +1,8 @@ -using System; using System.Globalization; using System.IO; using System.Windows.Forms; -using BizHawk.Bizware.BizwareGL; +using BizHawk.Bizware.Graphics; using BizHawk.Client.Common; using BizHawk.Client.Common.Filters; using BizHawk.Common; @@ -53,7 +52,7 @@ public DisplayConfig(Config config, IDialogController dialogController, IGL gl) cbFullscreenHacks.Checked = _config.DispFullscreenHacks; cbAutoPrescale.Checked = _config.DispAutoPrescale; - cbAlternateVsync.Checked = _config.DispAlternateVsync; + cbAllowTearing.Checked = _config.DispAllowTearing; if (_config.DispSpeedupFeatures == 2) rbDisplayFull.Checked = true; if (_config.DispSpeedupFeatures == 1) rbDisplayMinimal.Checked = true; @@ -63,7 +62,7 @@ public DisplayConfig(Config config, IDialogController dialogController, IGL gl) rbOpenGL.Checked = _config.DispMethod == EDispMethod.OpenGL; rbGDIPlus.Checked = _config.DispMethod == EDispMethod.GdiPlus; - rbD3D9.Checked = _config.DispMethod == EDispMethod.D3D9; + rbD3D11.Checked = _config.DispMethod == EDispMethod.D3D11; cbStatusBarWindowed.Checked = _config.DispChromeStatusBarWindowed; cbCaptionWindowed.Checked = _config.DispChromeCaptionWindowed; @@ -110,11 +109,11 @@ public DisplayConfig(Config config, IDialogController dialogController, IGL gl) RefreshAspectRatioOptions(); - if (!HostCapabilityDetector.HasD3D9) + if (!HostCapabilityDetector.HasD3D11) { - rbD3D9.Enabled = false; - rbD3D9.AutoCheck = false; - cbAlternateVsync.Enabled = false; + rbD3D11.Enabled = false; + rbD3D11.AutoCheck = false; + cbAllowTearing.Enabled = false; label13.Enabled = false; label8.Enabled = false; } @@ -146,7 +145,7 @@ private void BtnOk_Click(object sender, EventArgs e) _config.DispFullscreenHacks = cbFullscreenHacks.Checked; _config.DispAutoPrescale = cbAutoPrescale.Checked; - _config.DispAlternateVsync = cbAlternateVsync.Checked; + _config.DispAllowTearing = cbAllowTearing.Checked; _config.DispChromeStatusBarWindowed = cbStatusBarWindowed.Checked; _config.DispChromeCaptionWindowed = cbCaptionWindowed.Checked; @@ -228,8 +227,8 @@ private void BtnOk_Click(object sender, EventArgs e) _config.DispMethod = EDispMethod.OpenGL; if(rbGDIPlus.Checked) _config.DispMethod = EDispMethod.GdiPlus; - if(rbD3D9.Checked) - _config.DispMethod = EDispMethod.D3D9; + if(rbD3D11.Checked) + _config.DispMethod = EDispMethod.D3D11; if (int.TryParse(txtCropLeft.Text, out int dispCropLeft)) { @@ -367,9 +366,7 @@ private void LinkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs } private void Label13_Click(object sender, EventArgs e) - { - cbAlternateVsync.Checked ^= true; - } + => cbAllowTearing.Checked = !cbAllowTearing.Checked; private void BtnDefaults_Click(object sender, EventArgs e) { diff --git a/src/BizHawk.Client.EmuHawk/config/DisplayConfig.resx b/src/BizHawk.Client.EmuHawk/config/DisplayConfig.resx index 86fa78854a0..ae153eb520a 100644 --- a/src/BizHawk.Client.EmuHawk/config/DisplayConfig.resx +++ b/src/BizHawk.Client.EmuHawk/config/DisplayConfig.resx @@ -121,9 +121,9 @@ 17, 17 - Alternate VSync Method: Some GPUs have problems VSyncing. It seems -to manifest on full-screen windows. There will be hiccups when throttling -to VSync. Use this to try and solve it (busy loop; burns major CPU) + Allow Tearing: Allows fullscreen to tear when VSync is disabled. +This is required for variable frame rate (VFR) monitors to properly work. +Fast forward performance might decrease with tearing allowed. For Windows operating systems >= Vista, with diff --git a/src/BizHawk.Client.EmuHawk/config/EmuHawkOptions.Designer.cs b/src/BizHawk.Client.EmuHawk/config/EmuHawkOptions.Designer.cs index e528e2fd309..9c02b570396 100755 --- a/src/BizHawk.Client.EmuHawk/config/EmuHawkOptions.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/config/EmuHawkOptions.Designer.cs @@ -104,13 +104,15 @@ private void InitializeComponent() // // tabControl1 // - this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); + this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); this.tabControl1.Controls.Add(this.tabPage1); this.tabControl1.Controls.Add(this.tabPage3); - this.tabControl1.Location = new System.Drawing.Point(12, 12); + this.tabControl1.Location = new System.Drawing.Point(9, 12); this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; - this.tabControl1.Size = new System.Drawing.Size(394, 348); + this.tabControl1.Size = new System.Drawing.Size(400, 354); this.tabControl1.TabIndex = 2; // // tabPage1 @@ -129,7 +131,7 @@ private void InitializeComponent() this.tabPage1.Location = new System.Drawing.Point(4, 22); this.tabPage1.Name = "tabPage1"; this.tabPage1.Padding = new System.Windows.Forms.Padding(3); - this.tabPage1.Size = new System.Drawing.Size(386, 322); + this.tabPage1.Size = new System.Drawing.Size(392, 328); this.tabPage1.TabIndex = 0; this.tabPage1.Text = "General"; this.tabPage1.UseVisualStyleBackColor = true; @@ -137,7 +139,7 @@ private void InitializeComponent() // cbMergeLAndRModifierKeys // this.cbMergeLAndRModifierKeys.AutoSize = true; - this.cbMergeLAndRModifierKeys.Location = new System.Drawing.Point(7, 151); + this.cbMergeLAndRModifierKeys.Location = new System.Drawing.Point(7, 168); this.cbMergeLAndRModifierKeys.Name = "cbMergeLAndRModifierKeys"; this.cbMergeLAndRModifierKeys.Size = new System.Drawing.Size(320, 17); this.cbMergeLAndRModifierKeys.TabIndex = 29; @@ -147,7 +149,7 @@ private void InitializeComponent() // HandleAlternateKeyboardLayoutsCheckBox // this.HandleAlternateKeyboardLayoutsCheckBox.AutoSize = true; - this.HandleAlternateKeyboardLayoutsCheckBox.Location = new System.Drawing.Point(7, 128); + this.HandleAlternateKeyboardLayoutsCheckBox.Location = new System.Drawing.Point(7, 145); this.HandleAlternateKeyboardLayoutsCheckBox.Name = "HandleAlternateKeyboardLayoutsCheckBox"; this.HandleAlternateKeyboardLayoutsCheckBox.Size = new System.Drawing.Size(320, 17); this.HandleAlternateKeyboardLayoutsCheckBox.TabIndex = 26; @@ -159,14 +161,15 @@ private void InitializeComponent() this.NeverAskSaveCheckbox.AutoSize = true; this.NeverAskSaveCheckbox.Location = new System.Drawing.Point(6, 29); this.NeverAskSaveCheckbox.Name = "NeverAskSaveCheckbox"; - this.NeverAskSaveCheckbox.Size = new System.Drawing.Size(387, 17); + this.NeverAskSaveCheckbox.Size = new System.Drawing.Size(390, 17); this.NeverAskSaveCheckbox.TabIndex = 20; - this.NeverAskSaveCheckbox.Text = "When EmuHawk is closing, skip \"unsaved changes\" prompts and discard all"; + this.NeverAskSaveCheckbox.Text = "When EmuHawk is closing, skip \"unsaved changes\" prompts and discard all."; this.NeverAskSaveCheckbox.UseVisualStyleBackColor = true; // // label2 // this.label2.Location = new System.Drawing.Point(26, 112); + this.label2.MaximumSize = new System.Drawing.Size(380, 0); this.label2.Name = "label2"; this.label2.Text = "\"Eavesdrops\" on keyboard and gamepad input while other programs are focused."; // @@ -196,7 +199,7 @@ private void InitializeComponent() // this.label1.Location = new System.Drawing.Point(26, 72); this.label1.Name = "label1"; - this.label1.Text = "When this is set, the client will continue to run when it loses focus"; + this.label1.Text = "When this is set, the client will continue to run when it loses focus."; // // RunInBackgroundCheckbox // @@ -236,7 +239,7 @@ private void InitializeComponent() this.groupBox1.Controls.Add(this.StartFullScreenCheckbox); this.groupBox1.Controls.Add(this.label3); this.groupBox1.Controls.Add(this.SingleInstanceModeCheckbox); - this.groupBox1.Location = new System.Drawing.Point(6, 174); + this.groupBox1.Location = new System.Drawing.Point(6, 191); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(369, 133); this.groupBox1.TabIndex = 15; @@ -307,7 +310,7 @@ private void InitializeComponent() this.tabPage3.Controls.Add(this.BackupSRamCheckbox); this.tabPage3.Location = new System.Drawing.Point(4, 22); this.tabPage3.Name = "tabPage3"; - this.tabPage3.Size = new System.Drawing.Size(386, 322); + this.tabPage3.Size = new System.Drawing.Size(392, 322); this.tabPage3.TabIndex = 2; this.tabPage3.Text = "Advanced"; this.tabPage3.UseVisualStyleBackColor = true; @@ -354,7 +357,11 @@ private void InitializeComponent() // AutosaveSRAMtextBox // this.AutosaveSRAMtextBox.Location = new System.Drawing.Point(151, 33); - this.AutosaveSRAMtextBox.Maximum = new decimal(new int[] { 100000, 0, 0, 0 }); + this.AutosaveSRAMtextBox.Maximum = new decimal(new int[] { + 100000, + 0, + 0, + 0}); this.AutosaveSRAMtextBox.Name = "AutosaveSRAMtextBox"; this.AutosaveSRAMtextBox.Size = new System.Drawing.Size(50, 20); this.AutosaveSRAMtextBox.TabIndex = 5; @@ -412,7 +419,8 @@ private void InitializeComponent() // this.label6.Location = new System.Drawing.Point(27, 243); this.label6.Name = "label6"; - this.label6.Text = "Skips some integrity check exceptions in waterbox cores.\r\nUseful for romhackers. " + "Reboot core after changing.\r\nDon\'t bother reporting bugs if checked.\r\n"; + this.label6.Text = "Skips some integrity check exceptions in waterbox cores.\r\nUseful for romhackers. " + + "Reboot core after changing.\r\nDon\'t bother reporting bugs if checked.\r\n"; // // cbSkipWaterboxIntegrityChecks // @@ -428,7 +436,8 @@ private void InitializeComponent() // this.label5.Location = new System.Drawing.Point(27, 194); this.label5.Name = "label5"; - this.label5.Text = "Will prevent many Out Of Memory crashes during long movies.\r\nYou must restart the" + " program after changing this."; + this.label5.Text = "Will prevent many Out Of Memory crashes during long movies.\r\nYou must restart the" + + " program after changing this."; // // cbMoviesOnDisk // @@ -508,6 +517,7 @@ private void InitializeComponent() this.groupBox2.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.AutosaveSRAMtextBox)).EndInit(); this.ResumeLayout(false); + } #endregion diff --git a/src/BizHawk.Client.EmuHawk/config/EmuHawkOptions.cs b/src/BizHawk.Client.EmuHawk/config/EmuHawkOptions.cs index e27de1d189e..e3185f0eff2 100755 --- a/src/BizHawk.Client.EmuHawk/config/EmuHawkOptions.cs +++ b/src/BizHawk.Client.EmuHawk/config/EmuHawkOptions.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Client.Common; using BizHawk.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/FileExtensionPreferences.cs b/src/BizHawk.Client.EmuHawk/config/FileExtensionPreferences.cs index 6246efb6b8a..e8b852d778a 100644 --- a/src/BizHawk.Client.EmuHawk/config/FileExtensionPreferences.cs +++ b/src/BizHawk.Client.EmuHawk/config/FileExtensionPreferences.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/config/FileExtensionPreferencesPicker.cs b/src/BizHawk.Client.EmuHawk/config/FileExtensionPreferencesPicker.cs index e35051e7637..f4d31cec3b5 100644 --- a/src/BizHawk.Client.EmuHawk/config/FileExtensionPreferencesPicker.cs +++ b/src/BizHawk.Client.EmuHawk/config/FileExtensionPreferencesPicker.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/FirmwaresConfig.cs b/src/BizHawk.Client.EmuHawk/config/FirmwaresConfig.cs index 3ab096b0cba..d2e0771cf67 100644 --- a/src/BizHawk.Client.EmuHawk/config/FirmwaresConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/FirmwaresConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; @@ -62,6 +61,7 @@ public partial class FirmwaresConfig : Form, IDialogParent // Redundant with SystemLookup? Not so fast. That data drives things. This is one step abstracted. Don't be such a smart guy. Keep this redundant list up to date. private static readonly Dictionary SystemGroupNames = new Dictionary { + ["Amiga"] = "Amiga", ["NES"] = "NES", ["SNES"] = "SNES", ["BSX"] = "SNES+Satellaview", @@ -184,7 +184,7 @@ ListViewGroup AddGroup(string sysID) lvFirmwares.Groups.Add( key: sysID, headerText: SystemGroupNames.TryGetValue(sysID, out var name) ? name : "FIX ME (FirmwaresConfig.cs)"); - return lvFirmwares.Groups[^1]; + return lvFirmwares.Groups[lvFirmwares.Groups.Count - 1]; } // we'll use this font for displaying the hash, so they don't look all jagged in a long list @@ -591,7 +591,7 @@ private bool RunImportJobSingle(string basePath, string f, ref string errors) } string target = Path.Combine(basePath, fi.Name); - if (new FileInfo(target).Exists) + if (File.Exists(target)) { // compare the files, if they're the same. don't do anything if (File.ReadAllBytes(target).SequenceEqual(File.ReadAllBytes(f))) diff --git a/src/BizHawk.Client.EmuHawk/config/FirmwaresConfigInfo.cs b/src/BizHawk.Client.EmuHawk/config/FirmwaresConfigInfo.cs index 12708df3325..a9e834a1f95 100644 --- a/src/BizHawk.Client.EmuHawk/config/FirmwaresConfigInfo.cs +++ b/src/BizHawk.Client.EmuHawk/config/FirmwaresConfigInfo.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/GB/BmpView.cs b/src/BizHawk.Client.EmuHawk/config/GB/BmpView.cs index 5abe2db2665..077df58ebfe 100644 --- a/src/BizHawk.Client.EmuHawk/config/GB/BmpView.cs +++ b/src/BizHawk.Client.EmuHawk/config/GB/BmpView.cs @@ -1,6 +1,5 @@ //TODO - this is redundant with RetainedViewportPanel. Someone needs to reconcile the two. -using System; using System.ComponentModel; using System.Drawing.Imaging; using System.Drawing; diff --git a/src/BizHawk.Client.EmuHawk/config/GB/CGBColorChooserForm.cs b/src/BizHawk.Client.EmuHawk/config/GB/CGBColorChooserForm.cs index 58fba344835..ee111c42aba 100644 --- a/src/BizHawk.Client.EmuHawk/config/GB/CGBColorChooserForm.cs +++ b/src/BizHawk.Client.EmuHawk/config/GB/CGBColorChooserForm.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/GB/ColorChooserForm.cs b/src/BizHawk.Client.EmuHawk/config/GB/ColorChooserForm.cs index 4be0c56dd7a..fee089c44d7 100644 --- a/src/BizHawk.Client.EmuHawk/config/GB/ColorChooserForm.cs +++ b/src/BizHawk.Client.EmuHawk/config/GB/ColorChooserForm.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; @@ -192,7 +191,9 @@ public static int[] LoadPalFile(TextReader f) try { - lines.Add(line[..i], int.Parse(line[(i + 1)..])); + lines.Add( + line.Substring(startIndex: 0, length: i), + int.Parse(line.Substring(startIndex: i + 1))); } catch (FormatException) { @@ -302,7 +303,7 @@ private void Button6_Click(object sender, EventArgs e) var result = this.ShowFileOpenDialog( discardCWDChange: true, filter: FilesystemFilterSet.Palettes, - initDir: _config.PathEntries.ScreenshotAbsolutePathFor(VSystemID.Raw.GB)); + initDir: _config.PathEntries.PalettesAbsolutePathFor(VSystemID.Raw.GB)); if (result is not null) LoadColorFile(result, alert: true); } diff --git a/src/BizHawk.Client.EmuHawk/config/GB/GBPrefControl.cs b/src/BizHawk.Client.EmuHawk/config/GB/GBPrefControl.cs index e0989109ffa..a460aa03e2b 100644 --- a/src/BizHawk.Client.EmuHawk/config/GB/GBPrefControl.cs +++ b/src/BizHawk.Client.EmuHawk/config/GB/GBPrefControl.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/GB/SameBoyColorChooserForm.cs b/src/BizHawk.Client.EmuHawk/config/GB/SameBoyColorChooserForm.cs index 7f9c775af98..8aa70a0427d 100644 --- a/src/BizHawk.Client.EmuHawk/config/GB/SameBoyColorChooserForm.cs +++ b/src/BizHawk.Client.EmuHawk/config/GB/SameBoyColorChooserForm.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; @@ -162,7 +161,9 @@ public static int[] LoadPalFile(TextReader f) try { - lines.Add(line[..i], int.Parse(line[(i + 1)..])); + lines.Add( + line.Substring(startIndex: 0, length: i), + int.Parse(line.Substring(startIndex: i + 1))); } catch (FormatException) { @@ -264,7 +265,7 @@ private void Button6_Click(object sender, EventArgs e) var result = this.ShowFileOpenDialog( discardCWDChange: true, filter: FilesystemFilterSet.Palettes, - initDir: _config.PathEntries.ScreenshotAbsolutePathFor(VSystemID.Raw.GB)); + initDir: _config.PathEntries.PalettesAbsolutePathFor(VSystemID.Raw.GB)); if (result is not null) LoadColorFile(result, alert: true); } diff --git a/src/BizHawk.Client.EmuHawk/config/GenericCoreConfig.cs b/src/BizHawk.Client.EmuHawk/config/GenericCoreConfig.cs index e86eb9f7f83..9af2d7ed17d 100644 --- a/src/BizHawk.Client.EmuHawk/config/GenericCoreConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/GenericCoreConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/HotkeyConfig.Designer.cs b/src/BizHawk.Client.EmuHawk/config/HotkeyConfig.Designer.cs index e48900efd51..a7e520b520e 100644 --- a/src/BizHawk.Client.EmuHawk/config/HotkeyConfig.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/config/HotkeyConfig.Designer.cs @@ -42,10 +42,11 @@ private void InitializeComponent() this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); this.MiscButton = new BizHawk.Client.EmuHawk.MenuButton(); this.clearBtnContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); - this.clearAllToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.clearCurrentTabToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.restoreDefaultsToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.restoreDefaultsForCurrentTabToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator1 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); + this.clearAllToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.clearCurrentTabToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.HotkeyTabControl.SuspendLayout(); this.clearBtnContextMenu.SuspendLayout(); this.SuspendLayout(); @@ -163,11 +164,24 @@ private void InitializeComponent() // this.clearBtnContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.restoreDefaultsToolStripMenuItem, + this.restoreDefaultsForCurrentTabToolStripMenuItem, this.toolStripSeparator1, this.clearAllToolStripMenuItem, this.clearCurrentTabToolStripMenuItem}); this.clearBtnContextMenu.Name = "clearBtnContextMenu"; - this.clearBtnContextMenu.Size = new System.Drawing.Size(168, 76); + this.clearBtnContextMenu.Size = new System.Drawing.Size(224, 98); + // + // restoreDefaultsToolStripMenuItem + // + this.restoreDefaultsToolStripMenuItem.Text = "Restore Defaults"; + this.restoreDefaultsToolStripMenuItem.Click += new System.EventHandler(this.RestoreDefaultsToolStripMenuItem_Click); + // + // restoreDefaultsForCurrentTabToolStripMenuItem + // + this.restoreDefaultsForCurrentTabToolStripMenuItem.Name = "restoreDefaultsForCurrentTabToolStripMenuItem"; + this.restoreDefaultsForCurrentTabToolStripMenuItem.Size = new System.Drawing.Size(223, 22); + this.restoreDefaultsForCurrentTabToolStripMenuItem.Text = "Restore Current Tab Defaults"; + this.restoreDefaultsForCurrentTabToolStripMenuItem.Click += new System.EventHandler(this.RestoreDefaultsCurrentTabToolStripMenuItem_Click); // // clearAllToolStripMenuItem // @@ -179,11 +193,6 @@ private void InitializeComponent() this.clearCurrentTabToolStripMenuItem.Text = "Clear Current Tab"; this.clearCurrentTabToolStripMenuItem.Click += new System.EventHandler(this.ClearCurrentTabToolStripMenuItem_Click); // - // restoreDefaultsToolStripMenuItem - // - this.restoreDefaultsToolStripMenuItem.Text = "Restore Defaults"; - this.restoreDefaultsToolStripMenuItem.Click += new System.EventHandler(this.RestoreDefaultsToolStripMenuItem_Click); - // // HotkeyConfig // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -225,11 +234,12 @@ private void InitializeComponent() private BizHawk.WinForms.Controls.LocLabelEx label2; private BizHawk.WinForms.Controls.LocLabelEx label3; private System.Windows.Forms.ToolTip toolTip1; - private MenuButton MiscButton; + private BizHawk.Client.EmuHawk.MenuButton MiscButton; private System.Windows.Forms.ContextMenuStrip clearBtnContextMenu; private BizHawk.WinForms.Controls.ToolStripMenuItemEx clearAllToolStripMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx clearCurrentTabToolStripMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx restoreDefaultsToolStripMenuItem; private BizHawk.WinForms.Controls.ToolStripSeparatorEx toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem restoreDefaultsForCurrentTabToolStripMenuItem; } -} \ No newline at end of file +} diff --git a/src/BizHawk.Client.EmuHawk/config/HotkeyConfig.cs b/src/BizHawk.Client.EmuHawk/config/HotkeyConfig.cs index 3ea5af69f53..42d1098b5d3 100644 --- a/src/BizHawk.Client.EmuHawk/config/HotkeyConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/HotkeyConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -151,26 +150,23 @@ private void DoTabs() HotkeyTabControl.ResumeLayout(); } - private void Defaults() + private void Defaults(bool currentTabOnly) { - foreach (var w in InputWidgets) w.Bindings = HotkeyInfo.AllHotkeys[w.WidgetName].DefaultBinding; + var widgets = currentTabOnly ? HotkeyTabControl.SelectedTab.Controls.OfType() : InputWidgets; + + foreach (var w in widgets) + { + w.Bindings = HotkeyInfo.AllHotkeys[w.WidgetName].DefaultBinding; + } } private void ClearAll(bool currentTabOnly) { - if (currentTabOnly) + var widgets = currentTabOnly ? HotkeyTabControl.SelectedTab.Controls.OfType() : InputWidgets; + + foreach (var w in widgets) { - foreach (var w in InputWidgets) - { - w.Clear(); - } - } - else - { - foreach (var w in HotkeyTabControl.SelectedTab.Controls.OfType()) - { - w.Clear(); - } + w.Clear(); } } @@ -222,17 +218,22 @@ private void SearchBox_KeyDown(object sender, KeyEventArgs e) private void ClearAllToolStripMenuItem_Click(object sender, EventArgs e) { - ClearAll(true); + ClearAll(false); } private void ClearCurrentTabToolStripMenuItem_Click(object sender, EventArgs e) { - ClearAll(false); + ClearAll(true); } private void RestoreDefaultsToolStripMenuItem_Click(object sender, EventArgs e) { - Defaults(); + Defaults(false); + } + + private void RestoreDefaultsCurrentTabToolStripMenuItem_Click(object sender, EventArgs e) + { + Defaults(true); } } } diff --git a/src/BizHawk.Client.EmuHawk/config/INTV/IntvControllerSettings.cs b/src/BizHawk.Client.EmuHawk/config/INTV/IntvControllerSettings.cs index 33053418385..4f13594886c 100644 --- a/src/BizHawk.Client.EmuHawk/config/INTV/IntvControllerSettings.cs +++ b/src/BizHawk.Client.EmuHawk/config/INTV/IntvControllerSettings.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/InputCompositeWidget.cs b/src/BizHawk.Client.EmuHawk/config/InputCompositeWidget.cs index 0da03d1a3f9..9e851208372 100644 --- a/src/BizHawk.Client.EmuHawk/config/InputCompositeWidget.cs +++ b/src/BizHawk.Client.EmuHawk/config/InputCompositeWidget.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/Messages/ColorRow.cs b/src/BizHawk.Client.EmuHawk/config/Messages/ColorRow.cs index cb393343f13..341d852f9a3 100644 --- a/src/BizHawk.Client.EmuHawk/config/Messages/ColorRow.cs +++ b/src/BizHawk.Client.EmuHawk/config/Messages/ColorRow.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/Messages/MessageConfig.cs b/src/BizHawk.Client.EmuHawk/config/Messages/MessageConfig.cs index 73324f0b1cf..548db1dc0cc 100644 --- a/src/BizHawk.Client.EmuHawk/config/Messages/MessageConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/Messages/MessageConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/config/Messages/MessageEdit.cs b/src/BizHawk.Client.EmuHawk/config/Messages/MessageEdit.cs index fc3b868b4c7..6d212762daf 100644 --- a/src/BizHawk.Client.EmuHawk/config/Messages/MessageEdit.cs +++ b/src/BizHawk.Client.EmuHawk/config/Messages/MessageEdit.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/Messages/MessageRow.cs b/src/BizHawk.Client.EmuHawk/config/Messages/MessageRow.cs index 907f6398495..7744b6ff72c 100644 --- a/src/BizHawk.Client.EmuHawk/config/Messages/MessageRow.cs +++ b/src/BizHawk.Client.EmuHawk/config/Messages/MessageRow.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/N64/N64ControllerSettingControl.cs b/src/BizHawk.Client.EmuHawk/config/N64/N64ControllerSettingControl.cs index c2badf6a94a..f8e3fa0f948 100644 --- a/src/BizHawk.Client.EmuHawk/config/N64/N64ControllerSettingControl.cs +++ b/src/BizHawk.Client.EmuHawk/config/N64/N64ControllerSettingControl.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/N64/N64ControllersSetup.cs b/src/BizHawk.Client.EmuHawk/config/N64/N64ControllersSetup.cs index ea095f1a3e3..60b02fdce71 100644 --- a/src/BizHawk.Client.EmuHawk/config/N64/N64ControllersSetup.cs +++ b/src/BizHawk.Client.EmuHawk/config/N64/N64ControllersSetup.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/N64/N64VideoPluginconfig.cs b/src/BizHawk.Client.EmuHawk/config/N64/N64VideoPluginconfig.cs index 60b4626a227..d1dbf86d9c1 100644 --- a/src/BizHawk.Client.EmuHawk/config/N64/N64VideoPluginconfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/N64/N64VideoPluginconfig.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/NES/NESGraphicsConfig.cs b/src/BizHawk.Client.EmuHawk/config/NES/NESGraphicsConfig.cs index 42f31ebdd64..30d2bfd69fb 100644 --- a/src/BizHawk.Client.EmuHawk/config/NES/NESGraphicsConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/NES/NESGraphicsConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/NES/NESSoundConfig.cs b/src/BizHawk.Client.EmuHawk/config/NES/NESSoundConfig.cs index a0a08fe5c04..16c0fa4325c 100644 --- a/src/BizHawk.Client.EmuHawk/config/NES/NESSoundConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/NES/NESSoundConfig.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Cores.Nintendo.NES; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/NES/NESSyncSettingsForm.cs b/src/BizHawk.Client.EmuHawk/config/NES/NESSyncSettingsForm.cs index 2fbaae5f8be..c6ea8dbd7e5 100644 --- a/src/BizHawk.Client.EmuHawk/config/NES/NESSyncSettingsForm.cs +++ b/src/BizHawk.Client.EmuHawk/config/NES/NESSyncSettingsForm.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/NES/NESVSSettings.cs b/src/BizHawk.Client.EmuHawk/config/NES/NESVSSettings.cs index f640e4359a9..22a04903881 100644 --- a/src/BizHawk.Client.EmuHawk/config/NES/NESVSSettings.cs +++ b/src/BizHawk.Client.EmuHawk/config/NES/NESVSSettings.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/NES/NesControllerSettings.cs b/src/BizHawk.Client.EmuHawk/config/NES/NesControllerSettings.cs index b14c2e2661b..4de6b12d22e 100644 --- a/src/BizHawk.Client.EmuHawk/config/NES/NesControllerSettings.cs +++ b/src/BizHawk.Client.EmuHawk/config/NES/NesControllerSettings.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/NES/QuickNesConfig.cs b/src/BizHawk.Client.EmuHawk/config/NES/QuickNesConfig.cs index 63880cfeb29..816ae4ad191 100644 --- a/src/BizHawk.Client.EmuHawk/config/NES/QuickNesConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/NES/QuickNesConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/PSX/PSXControllerConfig.cs b/src/BizHawk.Client.EmuHawk/config/PSX/PSXControllerConfig.cs index ae182414846..00b8b74bdec 100644 --- a/src/BizHawk.Client.EmuHawk/config/PSX/PSXControllerConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/PSX/PSXControllerConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/PSX/PSXHashDiscs.cs b/src/BizHawk.Client.EmuHawk/config/PSX/PSXHashDiscs.cs index 597157fa1af..22f2600179d 100644 --- a/src/BizHawk.Client.EmuHawk/config/PSX/PSXHashDiscs.cs +++ b/src/BizHawk.Client.EmuHawk/config/PSX/PSXHashDiscs.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Client.EmuHawk diff --git a/src/BizHawk.Client.EmuHawk/config/PSX/PSXOptions.cs b/src/BizHawk.Client.EmuHawk/config/PSX/PSXOptions.cs index 0d14187246b..aa2b85f7492 100644 --- a/src/BizHawk.Client.EmuHawk/config/PSX/PSXOptions.cs +++ b/src/BizHawk.Client.EmuHawk/config/PSX/PSXOptions.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/PathConfig.cs b/src/BizHawk.Client.EmuHawk/config/PathConfig.cs index 5681de66021..ec237b8c23e 100644 --- a/src/BizHawk.Client.EmuHawk/config/PathConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/PathConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -42,7 +41,7 @@ private void LoadSettings() { RecentForROMs.Checked = _pathEntries.UseRecentForRoms; - DoTabs(_pathEntries.ToList(), _sysID); + DoTabs(_pathEntries.Paths, focusTabOfSystem: _sysID); DoRomToggle(); } @@ -135,7 +134,7 @@ void AddTabPageForSystem(string system, string systemDisplayName) tcMain.Visible = false; PathTabControl.TabPages.Clear(); - var systems = _pathEntries.Select(e => e.System).Distinct() // group entries by "system" (intentionally using instance field here, not parameter) + var systems = _pathEntries.Paths.Select(static e => e.System).Distinct() // group entries by "system" (intentionally using instance field here, not parameter) .Select(sys => (SysGroup: sys, DisplayName: PathEntryCollection.GetDisplayNameFor(sys))) .OrderBy(tuple => tuple.DisplayName) .ToList(); @@ -218,7 +217,7 @@ private void SaveSettings() foreach (var t in AllPathControls.OfType()) { - var pathEntry = _pathEntries.First(p => p.System == t.Parent.Name && p.Type == t.Name); + var pathEntry = _pathEntries.Paths.First(p => p.System == t.Parent.Name && p.Type == t.Name); pathEntry.Path = t.Text; } diff --git a/src/BizHawk.Client.EmuHawk/config/PathInfo.cs b/src/BizHawk.Client.EmuHawk/config/PathInfo.cs index a09e5987ea0..6e3d0f5cb2e 100644 --- a/src/BizHawk.Client.EmuHawk/config/PathInfo.cs +++ b/src/BizHawk.Client.EmuHawk/config/PathInfo.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; namespace BizHawk.Client.EmuHawk diff --git a/src/BizHawk.Client.EmuHawk/config/ProfileConfig.cs b/src/BizHawk.Client.EmuHawk/config/ProfileConfig.cs index 31827cea6d3..9f5e9dd7a4e 100644 --- a/src/BizHawk.Client.EmuHawk/config/ProfileConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/ProfileConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/RewindConfig.Designer.cs b/src/BizHawk.Client.EmuHawk/config/RewindConfig.Designer.cs index 4c8a67b34ca..e354bd02835 100755 --- a/src/BizHawk.Client.EmuHawk/config/RewindConfig.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/config/RewindConfig.Designer.cs @@ -567,7 +567,7 @@ private void InitializeComponent() this.MinimizeBox = false; this.Name = "RewindConfig"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "Rewind & Savestate Cofiguration"; + this.Text = "Rewind & Savestate Configuration"; this.Load += new System.EventHandler(this.RewindConfig_Load); ((System.ComponentModel.ISupportInitialize)(this.BufferSizeUpDown)).EndInit(); this.groupBox4.ResumeLayout(false); diff --git a/src/BizHawk.Client.EmuHawk/config/RewindConfig.cs b/src/BizHawk.Client.EmuHawk/config/RewindConfig.cs index cf292a97602..003df64f52e 100755 --- a/src/BizHawk.Client.EmuHawk/config/RewindConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/RewindConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/SNES/BSNESControllerConfig.cs b/src/BizHawk.Client.EmuHawk/config/SNES/BSNESControllerConfig.cs index 3c3f55f54b7..af157dc432d 100644 --- a/src/BizHawk.Client.EmuHawk/config/SNES/BSNESControllerConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/SNES/BSNESControllerConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/SNES/BSNESOptions.cs b/src/BizHawk.Client.EmuHawk/config/SNES/BSNESOptions.cs index b130ab9b94e..9c64c457e6c 100644 --- a/src/BizHawk.Client.EmuHawk/config/SNES/BSNESOptions.cs +++ b/src/BizHawk.Client.EmuHawk/config/SNES/BSNESOptions.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/SNES/SNESControllerConfig.cs b/src/BizHawk.Client.EmuHawk/config/SNES/SNESControllerConfig.cs index 5401ff2e2dc..9b5ac6c3351 100644 --- a/src/BizHawk.Client.EmuHawk/config/SNES/SNESControllerConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/SNES/SNESControllerConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/SNES/SNESOptions.cs b/src/BizHawk.Client.EmuHawk/config/SNES/SNESOptions.cs index c430972c077..a68370707ba 100644 --- a/src/BizHawk.Client.EmuHawk/config/SNES/SNESOptions.cs +++ b/src/BizHawk.Client.EmuHawk/config/SNES/SNESOptions.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/SoundConfig.cs b/src/BizHawk.Client.EmuHawk/config/SoundConfig.cs index ecb21bf661c..08d6043a2b3 100644 --- a/src/BizHawk.Client.EmuHawk/config/SoundConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/SoundConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/TI83/TI83PaletteConfig.cs b/src/BizHawk.Client.EmuHawk/config/TI83/TI83PaletteConfig.cs index 559e0a55eb9..65dc26a589c 100644 --- a/src/BizHawk.Client.EmuHawk/config/TI83/TI83PaletteConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/TI83/TI83PaletteConfig.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/config/ZXSpectrum/ZXSpectrumAudioSettings.cs b/src/BizHawk.Client.EmuHawk/config/ZXSpectrum/ZXSpectrumAudioSettings.cs index ad5e108ed4a..543c94ee73f 100644 --- a/src/BizHawk.Client.EmuHawk/config/ZXSpectrum/ZXSpectrumAudioSettings.cs +++ b/src/BizHawk.Client.EmuHawk/config/ZXSpectrum/ZXSpectrumAudioSettings.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/ZXSpectrum/ZXSpectrumCoreEmulationSettings.cs b/src/BizHawk.Client.EmuHawk/config/ZXSpectrum/ZXSpectrumCoreEmulationSettings.cs index 026e5cf9e2a..f3a28fec856 100644 --- a/src/BizHawk.Client.EmuHawk/config/ZXSpectrum/ZXSpectrumCoreEmulationSettings.cs +++ b/src/BizHawk.Client.EmuHawk/config/ZXSpectrum/ZXSpectrumCoreEmulationSettings.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/ZXSpectrum/ZXSpectrumJoystickSettings.cs b/src/BizHawk.Client.EmuHawk/config/ZXSpectrum/ZXSpectrumJoystickSettings.cs index 2acc1ab7eff..98a54c33dce 100644 --- a/src/BizHawk.Client.EmuHawk/config/ZXSpectrum/ZXSpectrumJoystickSettings.cs +++ b/src/BizHawk.Client.EmuHawk/config/ZXSpectrum/ZXSpectrumJoystickSettings.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/config/ZXSpectrum/ZXSpectrumNonSyncSettings.cs b/src/BizHawk.Client.EmuHawk/config/ZXSpectrum/ZXSpectrumNonSyncSettings.cs index d5fc7789c6b..e90c4997a9e 100644 --- a/src/BizHawk.Client.EmuHawk/config/ZXSpectrum/ZXSpectrumNonSyncSettings.cs +++ b/src/BizHawk.Client.EmuHawk/config/ZXSpectrum/ZXSpectrumNonSyncSettings.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/debug/DebugMenuItems.cs b/src/BizHawk.Client.EmuHawk/debug/DebugMenuItems.cs index 186db4d76da..b87977a3cc0 100644 --- a/src/BizHawk.Client.EmuHawk/debug/DebugMenuItems.cs +++ b/src/BizHawk.Client.EmuHawk/debug/DebugMenuItems.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/debug/FirmwareAutopatchDebugToolForm.cs b/src/BizHawk.Client.EmuHawk/debug/FirmwareAutopatchDebugToolForm.cs index 3768ab1f408..8afb7168fa1 100644 --- a/src/BizHawk.Client.EmuHawk/debug/FirmwareAutopatchDebugToolForm.cs +++ b/src/BizHawk.Client.EmuHawk/debug/FirmwareAutopatchDebugToolForm.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -23,7 +22,7 @@ protected override string WindowTitleStatic public FirmwareAutopatchDebugToolForm() { static string LabelFragment(string hash) - => $"{hash[..8]}... {FirmwareDatabase.FirmwareFilesByHash[hash].RecommendedName}"; + => $"{hash.Substring(startIndex: 0, length: 8)}... {FirmwareDatabase.FirmwareFilesByHash[hash].RecommendedName}"; List<(string Label, FirmwarePatchOption PatchOption)> patches = FirmwareDatabase.AllPatches .Select(static fpo => ($"{LabelFragment(fpo.BaseHash)} --> {LabelFragment(fpo.TargetHash)}", fpo)).ToList(); patches.Sort(static (a, b) => string.CompareOrdinal(a.Label, b.Label)); diff --git a/src/BizHawk.Client.EmuHawk/debug/N64RomByteswapToolForm.cs b/src/BizHawk.Client.EmuHawk/debug/N64RomByteswapToolForm.cs index 5154b2ba896..b3b58a4af76 100644 --- a/src/BizHawk.Client.EmuHawk/debug/N64RomByteswapToolForm.cs +++ b/src/BizHawk.Client.EmuHawk/debug/N64RomByteswapToolForm.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.IO; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/debug/N64VideoSettingsFuzzToolForm.cs b/src/BizHawk.Client.EmuHawk/debug/N64VideoSettingsFuzzToolForm.cs index 5de980f9ab4..f5086659d3d 100644 --- a/src/BizHawk.Client.EmuHawk/debug/N64VideoSettingsFuzzToolForm.cs +++ b/src/BizHawk.Client.EmuHawk/debug/N64VideoSettingsFuzzToolForm.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.Linq; using System.Reflection; diff --git a/src/BizHawk.Client.EmuHawk/movie/EditCommentsForm.Designer.cs b/src/BizHawk.Client.EmuHawk/movie/EditCommentsForm.Designer.cs index 397735db0e1..dad44911976 100644 --- a/src/BizHawk.Client.EmuHawk/movie/EditCommentsForm.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/movie/EditCommentsForm.Designer.cs @@ -109,6 +109,7 @@ private void InitializeComponent() this.Name = "EditCommentsForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Edit Comments"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.OnClosed); this.Load += new System.EventHandler(this.EditCommentsForm_Load); ((System.ComponentModel.ISupportInitialize)(this.CommentGrid)).EndInit(); this.ResumeLayout(false); diff --git a/src/BizHawk.Client.EmuHawk/movie/EditCommentsForm.cs b/src/BizHawk.Client.EmuHawk/movie/EditCommentsForm.cs index 40107cfca99..aa2dba3ca89 100644 --- a/src/BizHawk.Client.EmuHawk/movie/EditCommentsForm.cs +++ b/src/BizHawk.Client.EmuHawk/movie/EditCommentsForm.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Linq; using System.Windows.Forms; @@ -12,13 +11,15 @@ public partial class EditCommentsForm : Form private readonly bool _readOnly; private string _lastHeaderClicked; private bool _sortReverse; + private readonly bool _dispose; - public EditCommentsForm(IMovie movie, bool readOnly) + public EditCommentsForm(IMovie movie, bool readOnly, bool disposeOnClose = false) { _movie = movie; _readOnly = readOnly; _lastHeaderClicked = ""; _sortReverse = false; + _dispose = disposeOnClose; InitializeComponent(); Icon = Properties.Resources.TAStudioIcon; @@ -99,5 +100,13 @@ private void SortColumn(DataGridViewColumn e) _sortReverse = !_sortReverse; CommentGrid.Refresh(); } + + private void OnClosed(object sender, FormClosedEventArgs e) + { + if (_dispose && _movie is ITasMovie tasMovie) + { + tasMovie.Dispose(); + } + } } } diff --git a/src/BizHawk.Client.EmuHawk/movie/EditSubtitlesForm.Designer.cs b/src/BizHawk.Client.EmuHawk/movie/EditSubtitlesForm.Designer.cs index 4f86c3962ca..704c97eb7c7 100644 --- a/src/BizHawk.Client.EmuHawk/movie/EditSubtitlesForm.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/movie/EditSubtitlesForm.Designer.cs @@ -199,6 +199,7 @@ private void InitializeComponent() this.Name = "EditSubtitlesForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Edit Subtitles"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.OnClosed); this.Load += new System.EventHandler(this.EditSubtitlesForm_Load); ((System.ComponentModel.ISupportInitialize)(this.SubGrid)).EndInit(); this.ResumeLayout(false); diff --git a/src/BizHawk.Client.EmuHawk/movie/EditSubtitlesForm.cs b/src/BizHawk.Client.EmuHawk/movie/EditSubtitlesForm.cs index 17c351be9ef..0a6db6506f7 100644 --- a/src/BizHawk.Client.EmuHawk/movie/EditSubtitlesForm.cs +++ b/src/BizHawk.Client.EmuHawk/movie/EditSubtitlesForm.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.IO; using System.Windows.Forms; @@ -17,14 +16,16 @@ public partial class EditSubtitlesForm : Form, IDialogParent private readonly IMovie _selectedMovie; private readonly bool _readOnly; + private readonly bool _dispose; public IDialogController DialogController { get; } - public EditSubtitlesForm(IDialogController dialogController, IMovie movie, PathEntryCollection pathEntries, bool readOnly) + public EditSubtitlesForm(IDialogController dialogController, IMovie movie, PathEntryCollection pathEntries, bool readOnly, bool disposeOnClose = false) { _pathEntries = pathEntries; _selectedMovie = movie; _readOnly = readOnly; + _dispose = disposeOnClose; DialogController = dialogController; InitializeComponent(); Icon = Properties.Resources.TAStudioIcon; @@ -271,5 +272,13 @@ private void SubGrid_CellContentClick(object sender, DataGridViewCellEventArgs e } } } + + private void OnClosed(object sender, FormClosedEventArgs e) + { + if (_dispose && _selectedMovie is ITasMovie tasMovie) + { + tasMovie.Dispose(); + } + } } } diff --git a/src/BizHawk.Client.EmuHawk/movie/PlayMovie.cs b/src/BizHawk.Client.EmuHawk/movie/PlayMovie.cs index f65b3d6fa9e..7a01d3aca38 100644 --- a/src/BizHawk.Client.EmuHawk/movie/PlayMovie.cs +++ b/src/BizHawk.Client.EmuHawk/movie/PlayMovie.cs @@ -1,4 +1,3 @@ -using System; using System.Threading.Tasks; using System.Collections.Generic; using System.ComponentModel; @@ -102,7 +101,7 @@ private void Run() var indices = MovieView.SelectedIndices; if (indices.Count > 0) // Import file if necessary { - var movie = _movieSession.Get(_movieList[MovieView.SelectedIndices[0]].Filename); + var movie = _movieSession.Get(_movieList[MovieView.SelectedIndices[0]].Filename, true); _mainForm.StartNewMovie(movie, false); } } @@ -164,7 +163,7 @@ private IBasicMovieInfo LoadMovieInfo(HawkFile hf, bool force) // Don't do this from browse if (movie.Hash == _game.Hash - || _config.PlayMovieMatchHash == false || force) + || !_config.PlayMovieMatchHash || force) { return movie; } @@ -523,10 +522,8 @@ private void CommentsBtn_Click(object sender, EventArgs e) if (indices.Count > 0) { // TODO this will allocate unnecessary memory when this movie is a TasMovie due to TasStateManager - var movie = _movieSession.Get(_movieList[MovieView.SelectedIndices[0]].Filename); - movie.Load(); - // TODO movie should be disposed if movie is ITasMovie - var form = new EditCommentsForm(movie, _movieSession.ReadOnly); + var movie = _movieSession.Get(_movieList[MovieView.SelectedIndices[0]].Filename, true); + var form = new EditCommentsForm(movie, readOnly: false, disposeOnClose: true); form.Show(); } } @@ -537,11 +534,9 @@ private void SubtitlesBtn_Click(object sender, EventArgs e) if (indices.Count > 0) { // TODO this will allocate unnecessary memory when this movie is a TasMovie due to TasStateManager - var movie = _movieSession.Get(_movieList[MovieView.SelectedIndices[0]].Filename); - movie.Load(); - // TODO movie should be disposed if movie is ITasMovie - using EditSubtitlesForm s = new(DialogController, movie, _config.PathEntries, readOnly: true); - s.Show(); + var movie = _movieSession.Get(_movieList[MovieView.SelectedIndices[0]].Filename, true); + var form = new EditSubtitlesForm(DialogController, movie, _config.PathEntries, readOnly: false, disposeOnClose: true); + form.Show(); } } @@ -598,7 +593,7 @@ private void Ok_Click(object sender, EventArgs e) if (StopOnFrameCheckbox.Checked) { if (LastFrameCheckbox.Checked) _mainForm.PauseOnFrame = _movieSession.Movie.InputLogLength; - else if (StopOnFrameTextBox.ToRawInt() is int i) _mainForm.PauseOnFrame = i; + else if (StopOnFrameTextBox.ToRawUInt() is uint i) _mainForm.PauseOnFrame = (int)i; } Close(); } diff --git a/src/BizHawk.Client.EmuHawk/movie/RecordMovie.cs b/src/BizHawk.Client.EmuHawk/movie/RecordMovie.cs index 467a048a430..439772bb13d 100644 --- a/src/BizHawk.Client.EmuHawk/movie/RecordMovie.cs +++ b/src/BizHawk.Client.EmuHawk/movie/RecordMovie.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.IO; using System.Windows.Forms; @@ -251,7 +250,7 @@ private void Ok_Click(object sender, EventArgs e) movieToRecord.SavestateFramebuffer = Array.Empty(); if (_emulator.HasVideoProvider()) { - movieToRecord.SavestateFramebuffer = (int[])_emulator.AsVideoProvider().GetVideoBuffer().Clone(); + movieToRecord.SavestateFramebuffer = _emulator.AsVideoProvider().GetVideoBufferCopy(); } } else if (StartFromCombo.SelectedItem.ToString() is START_FROM_SAVERAM && _emulator.HasSaveRam()) @@ -267,7 +266,6 @@ private void Ok_Click(object sender, EventArgs e) _game, _firmwareManager, AuthorBox.Text ?? _config.DefaultAuthor); - movieToRecord.Save(); _mainForm.StartNewMovie(movieToRecord, true); _config.UseDefaultAuthor = DefaultAuthorCheckBox.Checked; diff --git a/src/BizHawk.Client.EmuHawk/movie/SubtitleMaker.cs b/src/BizHawk.Client.EmuHawk/movie/SubtitleMaker.cs index 621b808f527..6adfae395b5 100644 --- a/src/BizHawk.Client.EmuHawk/movie/SubtitleMaker.cs +++ b/src/BizHawk.Client.EmuHawk/movie/SubtitleMaker.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/tools/BasicBot/BasicBot.cs b/src/BizHawk.Client.EmuHawk/tools/BasicBot/BasicBot.cs index fd4b67794d9..bb9a77c0514 100644 --- a/src/BizHawk.Client.EmuHawk/tools/BasicBot/BasicBot.cs +++ b/src/BizHawk.Client.EmuHawk/tools/BasicBot/BasicBot.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; @@ -388,9 +387,7 @@ private void MemoryDomainsMenuItem_DropDownOpened(object sender, EventArgs e) => MemoryDomainsMenuItem.ReplaceDropDownItems(MemoryDomains.MenuItems(SetMemoryDomain, _currentDomain.Name).ToArray()); private void BigEndianMenuItem_Click(object sender, EventArgs e) - { - _bigEndian ^= true; - } + => _bigEndian = !_bigEndian; private void DataSizeMenuItem_DropDownOpened(object sender, EventArgs e) { @@ -415,9 +412,7 @@ private void FourByteMenuItem_Click(object sender, EventArgs e) } private void TurboWhileBottingMenuItem_Click(object sender, EventArgs e) - { - Settings.TurboWhenBotting ^= true; - } + => Settings.TurboWhenBotting = !Settings.TurboWhenBotting; private void RunBtn_Click(object sender, EventArgs e) { @@ -1301,9 +1296,7 @@ private void HelpToolStripMenuItem_Click(object sender, EventArgs e) } private void InvisibleEmulationCheckBox_CheckedChanged(object sender, EventArgs e) - { - Settings.InvisibleEmulation ^= true; - } + => Settings.InvisibleEmulation = !Settings.InvisibleEmulation; private void MaximizeAddressBox_TextChanged(object sender, EventArgs e) { diff --git a/src/BizHawk.Client.EmuHawk/tools/BasicBot/BotControlsRow.cs b/src/BizHawk.Client.EmuHawk/tools/BasicBot/BotControlsRow.cs index d444b2c0110..3766dc01cf1 100644 --- a/src/BizHawk.Client.EmuHawk/tools/BasicBot/BotControlsRow.cs +++ b/src/BizHawk.Client.EmuHawk/tools/BasicBot/BotControlsRow.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; namespace BizHawk.Client.EmuHawk diff --git a/src/BizHawk.Client.EmuHawk/tools/BatchRun.cs b/src/BizHawk.Client.EmuHawk/tools/BatchRun.cs index bef6713fb2f..9477f35a953 100644 --- a/src/BizHawk.Client.EmuHawk/tools/BatchRun.cs +++ b/src/BizHawk.Client.EmuHawk/tools/BatchRun.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Windows.Forms; using System.Threading; diff --git a/src/BizHawk.Client.EmuHawk/tools/BatchRunner.cs b/src/BizHawk.Client.EmuHawk/tools/BatchRunner.cs index 5e5e8f89aa5..4a97ce94116 100644 --- a/src/BizHawk.Client.EmuHawk/tools/BatchRunner.cs +++ b/src/BizHawk.Client.EmuHawk/tools/BatchRunner.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using BizHawk.Common; @@ -145,7 +144,7 @@ private void LoadOne(string f) return; } - if (result == false) + if (!result) { _current.Status = Result.EStatus.FalseOnLoad; _results.Add(_current); diff --git a/src/BizHawk.Client.EmuHawk/tools/CDL.cs b/src/BizHawk.Client.EmuHawk/tools/CDL.cs index 798a9bbc3c0..1f054552704 100644 --- a/src/BizHawk.Client.EmuHawk/tools/CDL.cs +++ b/src/BizHawk.Client.EmuHawk/tools/CDL.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.IO; using System.Windows.Forms; @@ -576,18 +575,12 @@ private void TsbExportText_Click(object sender, EventArgs e) } private void MiAutoSave_Click(object sender, EventArgs e) - { - CDLAutoSave ^= true; - } + => CDLAutoSave = !CDLAutoSave; private void MiAutoStart_Click(object sender, EventArgs e) - { - CDLAutoStart ^= true; - } + => CDLAutoStart = !CDLAutoStart; private void MiAutoResume_Click(object sender, EventArgs e) - { - CDLAutoResume ^= true; - } + => CDLAutoResume = !CDLAutoResume; } } diff --git a/src/BizHawk.Client.EmuHawk/tools/CDL.designer.cs b/src/BizHawk.Client.EmuHawk/tools/CDL.designer.cs index 6aec80e3b2b..eb2ef3a6b31 100644 --- a/src/BizHawk.Client.EmuHawk/tools/CDL.designer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/CDL.designer.cs @@ -30,7 +30,7 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.menuStrip1 = new MenuStripEx(); + this.menuStrip1 = new BizHawk.WinForms.Controls.MenuStripEx(); this.FileSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.NewMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.OpenMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -41,18 +41,18 @@ private void InitializeComponent() this.noneToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.miAutoStart = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.miAutoSave = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.miAutoResume = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.toolStripSeparator2 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.ClearMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.DisassembleMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.toolStrip1 = new ToolStripEx(); + this.toolStrip1 = new BizHawk.WinForms.Controls.ToolStripEx(); this.tsbLoggingActive = new System.Windows.Forms.ToolStripButton(); this.toolStripSeparator3 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.tsbViewUpdate = new System.Windows.Forms.ToolStripButton(); this.tsbViewStyle = new System.Windows.Forms.ToolStripComboBox(); this.toolStripSeparator4 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.tsbExportText = new System.Windows.Forms.ToolStripButton(); - this.lvCDL = new InputRoll(); - this.miAutoResume = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.lvCDL = new BizHawk.Client.EmuHawk.InputRoll(); this.menuStrip1.SuspendLayout(); this.toolStrip1.SuspendLayout(); this.SuspendLayout(); @@ -132,6 +132,11 @@ private void InitializeComponent() this.miAutoSave.Text = "Auto-Save"; this.miAutoSave.Click += new System.EventHandler(this.MiAutoSave_Click); // + // miAutoResume + // + this.miAutoResume.Text = "Auto-Resume"; + this.miAutoResume.Click += new System.EventHandler(this.MiAutoResume_Click); + // // ClearMenuItem // this.ClearMenuItem.Text = "&Clear"; @@ -161,7 +166,7 @@ private void InitializeComponent() this.tsbLoggingActive.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; this.tsbLoggingActive.ImageTransparentColor = System.Drawing.Color.Magenta; this.tsbLoggingActive.Name = "tsbLoggingActive"; - this.tsbLoggingActive.Size = new System.Drawing.Size(41, 22); + this.tsbLoggingActive.Size = new System.Drawing.Size(44, 22); this.tsbLoggingActive.Text = "Active"; this.tsbLoggingActive.CheckedChanged += new System.EventHandler(this.TsbLoggingActive_CheckedChanged); // @@ -173,7 +178,7 @@ private void InitializeComponent() this.tsbViewUpdate.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; this.tsbViewUpdate.ImageTransparentColor = System.Drawing.Color.Magenta; this.tsbViewUpdate.Name = "tsbViewUpdate"; - this.tsbViewUpdate.Size = new System.Drawing.Size(46, 22); + this.tsbViewUpdate.Size = new System.Drawing.Size(49, 22); this.tsbViewUpdate.Text = "Update"; // // tsbViewStyle @@ -191,29 +196,30 @@ private void InitializeComponent() // this.tsbExportText.ImageTransparentColor = System.Drawing.Color.Magenta; this.tsbExportText.Name = "tsbExportText"; - this.tsbExportText.Size = new System.Drawing.Size(87, 22); + this.tsbExportText.Size = new System.Drawing.Size(78, 22); this.tsbExportText.Text = "To Clipboard"; this.tsbExportText.Click += new System.EventHandler(this.TsbExportText_Click); // // lvCDL // - this.lvCDL.CellWidthPadding = 3; + this.lvCDL.AllowColumnReorder = false; + this.lvCDL.AllowColumnResize = true; + this.lvCDL.AllowMassNavigationShortcuts = true; + this.lvCDL.AllowRightClickSelection = true; + this.lvCDL.AlwaysScroll = false; + this.lvCDL.CellHeightPadding = 0; this.lvCDL.Dock = System.Windows.Forms.DockStyle.Fill; this.lvCDL.FullRowSelect = true; - this.lvCDL.GridLines = true; - this.lvCDL.RowCount = 0; + this.lvCDL.HorizontalOrientation = false; + this.lvCDL.LetKeysModifySelection = false; this.lvCDL.Location = new System.Drawing.Point(0, 49); this.lvCDL.Name = "lvCDL"; + this.lvCDL.RowCount = 0; + this.lvCDL.ScrollSpeed = 0; + this.lvCDL.SeekingCutoffInterval = 0; this.lvCDL.Size = new System.Drawing.Size(992, 323); this.lvCDL.TabIndex = 9; - this.lvCDL.AllowColumnReorder = false; - this.lvCDL.AllowColumnResize = true; - this.lvCDL.QueryItemText += new InputRoll.QueryItemTextHandler(this.LvCDL_QueryItemText); - // - // miAutoResume - // - this.miAutoResume.Text = "Auto-Resume"; - this.miAutoResume.Click += new System.EventHandler(this.MiAutoResume_Click); + this.lvCDL.QueryItemText += new BizHawk.Client.EmuHawk.InputRoll.QueryItemTextHandler(this.LvCDL_QueryItemText); // // CDL // diff --git a/src/BizHawk.Client.EmuHawk/tools/Cheats/CheatEdit.cs b/src/BizHawk.Client.EmuHawk/tools/Cheats/CheatEdit.cs index 8f1e470b1d3..040e2a10a1a 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Cheats/CheatEdit.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Cheats/CheatEdit.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Windows.Forms; @@ -94,7 +93,7 @@ private void SetFormToCheat() CheckFormState(); if (!_cheat.Compare.HasValue) { - CompareBox.Text = ""; // Necessary hack until WatchValueBox.ToRawInt() becomes nullable + CompareBox.Text = ""; // Necessary hack until WatchValueBox.ToRawUInt() becomes nullable } _loading = false; @@ -133,7 +132,7 @@ private void SetFormToDefault() SetTypeSelected(WatchDisplayType.Hex); CheckFormState(); - CompareBox.Text = ""; // TODO: A needed hack until WatchValueBox.ToRawInt() becomes nullable + CompareBox.Text = ""; // TODO: A needed hack until WatchValueBox.ToRawUInt() becomes nullable _loading = false; } @@ -311,7 +310,7 @@ public void ClearForm() public Cheat GetCheat() { var domain = MemoryDomains[DomainDropDown.SelectedItem.ToString()]!; - var address = AddressBox.ToRawInt().Value; + var address = AddressBox.ToRawUInt().Value; if (address < domain.Size) { var watch = Watch.GenerateWatch( @@ -334,11 +333,11 @@ public Cheat GetCheat() _ => Cheat.CompareType.None }; - var compare = CompareBox.ToRawInt(); + var compare = CompareBox.ToRawUInt(); return new Cheat( watch, - value: ValueBox.ToRawInt().Value, - compare: compare, + value: (int)ValueBox.ToRawUInt().Value, + compare: (int?)compare, enabled: true, comparisonType); } diff --git a/src/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.Designer.cs b/src/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.Designer.cs index a3d533e3a12..8a37d682d0a 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.Designer.cs @@ -31,13 +31,13 @@ protected override void Dispose(bool disposing) private void InitializeComponent() { this.components = new System.ComponentModel.Container(); - this.CheatListView = new InputRoll(); + this.CheatListView = new BizHawk.Client.EmuHawk.InputRoll(); this.CheatsContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); this.ToggleContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.RemoveContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.DisableAllContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.ViewInHexEditorContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.CheatsMenu = new MenuStripEx(); + this.CheatsMenu = new BizHawk.WinForms.Controls.MenuStripEx(); this.FileSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.NewMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.OpenMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -62,7 +62,7 @@ private void InitializeComponent() this.AlwaysLoadCheatsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.AutoSaveCheatsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.DisableCheatsOnLoadMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.toolStrip1 = new ToolStripEx(); + this.toolStrip1 = new BizHawk.WinForms.Controls.ToolStripEx(); this.NewToolBarItem = new System.Windows.Forms.ToolStripButton(); this.OpenToolBarItem = new System.Windows.Forms.ToolStripButton(); this.SaveToolBarItem = new System.Windows.Forms.ToolStripButton(); @@ -86,20 +86,25 @@ private void InitializeComponent() // // CheatListView // - this.CheatListView.CellWidthPadding = 3; this.CheatListView.AllowColumnReorder = true; this.CheatListView.AllowColumnResize = true; - this.CheatListView.MultiSelect = true; this.CheatListView.AllowDrop = true; + this.CheatListView.AllowMassNavigationShortcuts = true; + this.CheatListView.AllowRightClickSelection = true; + this.CheatListView.AlwaysScroll = false; this.CheatListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); + this.CheatListView.CellHeightPadding = 0; this.CheatListView.ContextMenuStrip = this.CheatsContextMenu; this.CheatListView.FullRowSelect = true; - this.CheatListView.GridLines = true; - this.CheatListView.RowCount = 0; + this.CheatListView.HorizontalOrientation = false; + this.CheatListView.LetKeysModifySelection = false; this.CheatListView.Location = new System.Drawing.Point(12, 72); this.CheatListView.Name = "CheatListView"; + this.CheatListView.RowCount = 0; + this.CheatListView.ScrollSpeed = 0; + this.CheatListView.SeekingCutoffInterval = 0; this.CheatListView.Size = new System.Drawing.Size(414, 321); this.CheatListView.TabIndex = 1; this.CheatListView.ColumnClick += new BizHawk.Client.EmuHawk.InputRoll.ColumnClickEventHandler(this.CheatListView_ColumnClick); @@ -117,7 +122,7 @@ private void InitializeComponent() this.DisableAllContextMenuItem, this.ViewInHexEditorContextMenuItem}); this.CheatsContextMenu.Name = "contextMenuStrip1"; - this.CheatsContextMenu.Size = new System.Drawing.Size(170, 92); + this.CheatsContextMenu.Size = new System.Drawing.Size(171, 92); this.CheatsContextMenu.Opening += new System.ComponentModel.CancelEventHandler(this.CheatsContextMenu_Opening); // // ToggleContextMenuItem @@ -247,15 +252,15 @@ private void InitializeComponent() // // ToggleMenuItem // - this.ToggleMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Enter))); this.ToggleMenuItem.ShortcutKeyDisplayString = "Ctrl + Enter"; + this.ToggleMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Return))); this.ToggleMenuItem.Text = "&Toggle"; this.ToggleMenuItem.Click += new System.EventHandler(this.ToggleMenuItem_Click); // // DisableAllCheatsMenuItem // - this.DisableAllCheatsMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Back))); this.DisableAllCheatsMenuItem.ShortcutKeyDisplayString = "Ctrl + Backspace"; + this.DisableAllCheatsMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Back))); this.DisableAllCheatsMenuItem.Text = "Disable all"; this.DisableAllCheatsMenuItem.Click += new System.EventHandler(this.DisableAllCheatsMenuItem_Click); // @@ -374,7 +379,7 @@ private void InitializeComponent() this.LoadGameGenieToolbarItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; this.LoadGameGenieToolbarItem.ImageTransparentColor = System.Drawing.Color.Magenta; this.LoadGameGenieToolbarItem.Name = "LoadGameGenieToolbarItem"; - this.LoadGameGenieToolbarItem.Size = new System.Drawing.Size(75, 22); + this.LoadGameGenieToolbarItem.Size = new System.Drawing.Size(94, 22); this.LoadGameGenieToolbarItem.Text = "Code Converter"; this.LoadGameGenieToolbarItem.ToolTipText = "Open the Cheat Code Converter"; this.LoadGameGenieToolbarItem.Click += new System.EventHandler(this.OpenGameGenieEncoderDecoderMenuItem_Click); diff --git a/src/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.cs b/src/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.cs index 93377ddebb6..0c6ed44be97 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; @@ -451,7 +450,7 @@ private void MoveDownMenuItem_Click(object sender, EventArgs e) { var indices = SelectedIndices.ToList(); if (indices.Count == 0 - || indices[^1] == MainForm.CheatList.Count - 1) // at end already + || indices[indices.Count - 1] == MainForm.CheatList.Count - 1) // at end already { return; } @@ -506,19 +505,13 @@ private void SettingsSubMenu_DropDownOpened(object sender, EventArgs e) } private void AlwaysLoadCheatsMenuItem_Click(object sender, EventArgs e) - { - Config.Cheats.LoadFileByGame ^= true; - } + => Config.Cheats.LoadFileByGame = !Config.Cheats.LoadFileByGame; private void AutoSaveCheatsMenuItem_Click(object sender, EventArgs e) - { - Config.Cheats.AutoSaveOnClose ^= true; - } + => Config.Cheats.AutoSaveOnClose = !Config.Cheats.AutoSaveOnClose; private void CheatsOnOffLoadMenuItem_Click(object sender, EventArgs e) - { - Config.Cheats.DisableOnLoad ^= true; - } + => Config.Cheats.DisableOnLoad = !Config.Cheats.DisableOnLoad; [RestoreDefaults] private void RestoreDefaults() @@ -566,7 +559,7 @@ private void CheatListView_SelectedIndexChanged(object sender, EventArgs e) private void CheatListView_ColumnClick(object sender, InputRoll.ColumnClickEventArgs e) { - var column = e.Column; + var column = e.Column!; if (column.Name != _sortedColumn) { _sortReverse = false; @@ -575,7 +568,7 @@ private void CheatListView_ColumnClick(object sender, InputRoll.ColumnClickEvent MainForm.CheatList.Sort(column.Name, _sortReverse); _sortedColumn = column.Name; - _sortReverse ^= true; + _sortReverse = !_sortReverse; GeneralUpdate(); } diff --git a/src/BizHawk.Client.EmuHawk/tools/Debugger/AddBreakpointDialog.cs b/src/BizHawk.Client.EmuHawk/tools/Debugger/AddBreakpointDialog.cs index eec013cd2a0..08930db061d 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Debugger/AddBreakpointDialog.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Debugger/AddBreakpointDialog.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Emulation.Common; @@ -101,13 +100,13 @@ public MemoryCallbackType BreakType public uint Address { - get => (uint)AddressBox.ToRawInt().Value & AddressMask; + get => AddressBox.ToRawUInt().Value & AddressMask; set => AddressBox.SetFromLong(value & AddressMask); } public uint AddressMask { - get => (uint)AddressMaskBox.ToRawInt().Value; + get => AddressMaskBox.ToRawUInt().Value; set => AddressMaskBox.SetFromLong(value); } diff --git a/src/BizHawk.Client.EmuHawk/tools/Debugger/BreakpointControl.cs b/src/BizHawk.Client.EmuHawk/tools/Debugger/BreakpointControl.cs index 41a84b0ee3c..cf352002333 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Debugger/BreakpointControl.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Debugger/BreakpointControl.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -219,11 +218,7 @@ private void BreakpointView_ItemActivate(object sender, EventArgs e) var items = EditableItems.ToList(); if (items.Any()) { - foreach (var item in items) - { - item.Active ^= true; - } - + foreach (var item in items) item.Active = !item.Active; BreakpointView.VirtualListSize = _breakpoints.Count; UpdateBreakpointRemoveButton(); UpdateStatsLabel(); @@ -246,11 +241,7 @@ private void UpdateStatsLabel() private void ToggleButton_Click(object sender, EventArgs e) { - foreach (var item in SelectedItems) - { - item.Active ^= true; - } - + foreach (var item in SelectedItems) item.Active = !item.Active; BreakpointView.VirtualListSize = _breakpoints.Count; UpdateStatsLabel(); } diff --git a/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Designer.cs b/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Designer.cs index 90d95e063c5..72e93c48aa2 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Designer.cs @@ -30,321 +30,320 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - this.menuStrip1 = new BizHawk.WinForms.Controls.MenuStripEx(); - this.fileToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.DebugSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.StepIntoMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.StepOverMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.StepOutMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.toolStripSeparator1 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); - this.RefreshMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.RegistersGroupBox = new System.Windows.Forms.GroupBox(); - this.RegisterPanel = new BizHawk.Client.EmuHawk.RegisterBoxControl(); - this.BreakpointsGroupBox = new System.Windows.Forms.GroupBox(); - this.BreakPointControl1 = new BizHawk.Client.EmuHawk.BreakpointControl(); - this.DisassemblerBox = new System.Windows.Forms.GroupBox(); - this.ToPCBtn = new System.Windows.Forms.Button(); - this.label1 = new BizHawk.WinForms.Controls.LocLabelEx(); - this.DisassemblerView = new BizHawk.Client.EmuHawk.InputRoll(); - this.DisassemblerContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); - this.AddBreakpointContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.StepOutBtn = new System.Windows.Forms.Button(); - this.StepIntoBtn = new System.Windows.Forms.Button(); - this.StepOverBtn = new System.Windows.Forms.Button(); - this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); - this.SeekToBtn = new System.Windows.Forms.Button(); - this.SeekToBox = new BizHawk.Client.EmuHawk.HexTextBox(); - this.CancelSeekBtn = new System.Windows.Forms.Button(); - this.RunBtn = new System.Windows.Forms.Button(); - this.menuStrip1.SuspendLayout(); - this.RegistersGroupBox.SuspendLayout(); - this.BreakpointsGroupBox.SuspendLayout(); - this.DisassemblerBox.SuspendLayout(); - this.DisassemblerContextMenu.SuspendLayout(); - this.SuspendLayout(); - // - // menuStrip1 - // - this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.components = new System.ComponentModel.Container(); + this.menuStrip1 = new BizHawk.WinForms.Controls.MenuStripEx(); + this.fileToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.DebugSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.StepIntoMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.StepOverMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.StepOutMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.toolStripSeparator1 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); + this.RefreshMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.RegistersGroupBox = new System.Windows.Forms.GroupBox(); + this.RegisterPanel = new BizHawk.Client.EmuHawk.RegisterBoxControl(); + this.BreakpointsGroupBox = new System.Windows.Forms.GroupBox(); + this.BreakPointControl1 = new BizHawk.Client.EmuHawk.BreakpointControl(); + this.DisassemblerBox = new System.Windows.Forms.GroupBox(); + this.ToPCBtn = new System.Windows.Forms.Button(); + this.label1 = new BizHawk.WinForms.Controls.LocLabelEx(); + this.DisassemblerView = new BizHawk.Client.EmuHawk.InputRoll(); + this.DisassemblerContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); + this.AddBreakpointContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.StepOutBtn = new System.Windows.Forms.Button(); + this.StepIntoBtn = new System.Windows.Forms.Button(); + this.StepOverBtn = new System.Windows.Forms.Button(); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.SeekToBtn = new System.Windows.Forms.Button(); + this.SeekToBox = new BizHawk.Client.EmuHawk.HexTextBox(); + this.CancelSeekBtn = new System.Windows.Forms.Button(); + this.RunBtn = new System.Windows.Forms.Button(); + this.menuStrip1.SuspendLayout(); + this.RegistersGroupBox.SuspendLayout(); + this.BreakpointsGroupBox.SuspendLayout(); + this.DisassemblerBox.SuspendLayout(); + this.DisassemblerContextMenu.SuspendLayout(); + this.SuspendLayout(); + // + // menuStrip1 + // + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.fileToolStripMenuItem, this.DebugSubMenu}); - this.menuStrip1.TabIndex = 1; - // - // fileToolStripMenuItem - // - this.fileToolStripMenuItem.Text = "&File"; - // - // DebugSubMenu - // - this.DebugSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.menuStrip1.TabIndex = 1; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.Text = "&File"; + // + // DebugSubMenu + // + this.DebugSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.StepIntoMenuItem, this.StepOverMenuItem, this.StepOutMenuItem, this.toolStripSeparator1, this.RefreshMenuItem}); - this.DebugSubMenu.Text = "&Debug"; - // - // StepIntoMenuItem - // - this.StepIntoMenuItem.Enabled = false; - this.StepIntoMenuItem.ShortcutKeyDisplayString = "F11"; - this.StepIntoMenuItem.Text = "Step &Into"; - this.StepIntoMenuItem.Click += new System.EventHandler(this.StepIntoMenuItem_Click); - // - // StepOverMenuItem - // - this.StepOverMenuItem.Enabled = false; - this.StepOverMenuItem.ShortcutKeyDisplayString = "F10"; - this.StepOverMenuItem.Text = "Step O&ver"; - this.StepOverMenuItem.Click += new System.EventHandler(this.StepOverMenuItem_Click); - // - // StepOutMenuItem - // - this.StepOutMenuItem.Enabled = false; - this.StepOutMenuItem.ShortcutKeyDisplayString = "Shift+F11"; - this.StepOutMenuItem.Text = "Step Ou&t"; - this.StepOutMenuItem.Click += new System.EventHandler(this.StepOutMenuItem_Click); - // - // RefreshMenuItem - // - this.RefreshMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F5; - this.RefreshMenuItem.Text = "Refresh"; - this.RefreshMenuItem.Click += new System.EventHandler(this.RefreshMenuItem_Click); - // - // RegistersGroupBox - // - this.RegistersGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.DebugSubMenu.Text = "&Debug"; + // + // StepIntoMenuItem + // + this.StepIntoMenuItem.Enabled = false; + this.StepIntoMenuItem.ShortcutKeyDisplayString = "F11"; + this.StepIntoMenuItem.Text = "Step &Into"; + this.StepIntoMenuItem.Click += new System.EventHandler(this.StepIntoMenuItem_Click); + // + // StepOverMenuItem + // + this.StepOverMenuItem.Enabled = false; + this.StepOverMenuItem.ShortcutKeyDisplayString = "F10"; + this.StepOverMenuItem.Text = "Step O&ver"; + this.StepOverMenuItem.Click += new System.EventHandler(this.StepOverMenuItem_Click); + // + // StepOutMenuItem + // + this.StepOutMenuItem.Enabled = false; + this.StepOutMenuItem.ShortcutKeyDisplayString = "Shift+F11"; + this.StepOutMenuItem.Text = "Step Ou&t"; + this.StepOutMenuItem.Click += new System.EventHandler(this.StepOutMenuItem_Click); + // + // RefreshMenuItem + // + this.RefreshMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F5; + this.RefreshMenuItem.Text = "Refresh"; + this.RefreshMenuItem.Click += new System.EventHandler(this.RefreshMenuItem_Click); + // + // RegistersGroupBox + // + this.RegistersGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.RegistersGroupBox.Controls.Add(this.RegisterPanel); - this.RegistersGroupBox.Location = new System.Drawing.Point(425, 27); - this.RegistersGroupBox.Name = "RegistersGroupBox"; - this.RegistersGroupBox.Size = new System.Drawing.Size(330, 234); - this.RegistersGroupBox.TabIndex = 8; - this.RegistersGroupBox.TabStop = false; - this.RegistersGroupBox.Text = "Registers"; - // - // RegisterPanel - // - this.RegisterPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + this.RegistersGroupBox.Controls.Add(this.RegisterPanel); + this.RegistersGroupBox.Location = new System.Drawing.Point(425, 27); + this.RegistersGroupBox.Name = "RegistersGroupBox"; + this.RegistersGroupBox.Size = new System.Drawing.Size(330, 234); + this.RegistersGroupBox.TabIndex = 8; + this.RegistersGroupBox.TabStop = false; + this.RegistersGroupBox.Text = "Registers"; + // + // RegisterPanel + // + this.RegisterPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.RegisterPanel.AutoScroll = true; - this.RegisterPanel.Core = null; - this.RegisterPanel.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204))); - this.RegisterPanel.Location = new System.Drawing.Point(8, 19); - this.RegisterPanel.Name = "RegisterPanel"; - this.RegisterPanel.ParentDebugger = null; - this.RegisterPanel.Size = new System.Drawing.Size(316, 209); - this.RegisterPanel.TabIndex = 0; - // - // BreakpointsGroupBox - // - this.BreakpointsGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + this.RegisterPanel.AutoScroll = true; + this.RegisterPanel.Core = null; + this.RegisterPanel.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204))); + this.RegisterPanel.Location = new System.Drawing.Point(8, 19); + this.RegisterPanel.Name = "RegisterPanel"; + this.RegisterPanel.ParentDebugger = null; + this.RegisterPanel.Size = new System.Drawing.Size(316, 209); + this.RegisterPanel.TabIndex = 0; + // + // BreakpointsGroupBox + // + this.BreakpointsGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.BreakpointsGroupBox.Controls.Add(this.BreakPointControl1); - this.BreakpointsGroupBox.Location = new System.Drawing.Point(425, 267); - this.BreakpointsGroupBox.Name = "BreakpointsGroupBox"; - this.BreakpointsGroupBox.Size = new System.Drawing.Size(239, 281); - this.BreakpointsGroupBox.TabIndex = 9; - this.BreakpointsGroupBox.TabStop = false; - this.BreakpointsGroupBox.Text = "Breakpoints"; - // - // BreakPointControl1 - // - this.BreakPointControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + this.BreakpointsGroupBox.Controls.Add(this.BreakPointControl1); + this.BreakpointsGroupBox.Location = new System.Drawing.Point(425, 267); + this.BreakpointsGroupBox.Name = "BreakpointsGroupBox"; + this.BreakpointsGroupBox.Size = new System.Drawing.Size(239, 281); + this.BreakpointsGroupBox.TabIndex = 9; + this.BreakpointsGroupBox.TabStop = false; + this.BreakpointsGroupBox.Text = "Breakpoints"; + // + // BreakPointControl1 + // + this.BreakPointControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.BreakPointControl1.Core = null; - this.BreakPointControl1.Location = new System.Drawing.Point(8, 19); - this.BreakPointControl1.MainForm = null; - this.BreakPointControl1.Mcs = null; - this.BreakPointControl1.MemoryDomains = null; - this.BreakPointControl1.Name = "BreakPointControl1"; - this.BreakPointControl1.ParentDebugger = null; - this.BreakPointControl1.Size = new System.Drawing.Size(225, 256); - this.BreakPointControl1.TabIndex = 0; - // - // DisassemblerBox - // - this.DisassemblerBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + this.BreakPointControl1.Core = null; + this.BreakPointControl1.Location = new System.Drawing.Point(8, 19); + this.BreakPointControl1.MainForm = null; + this.BreakPointControl1.Mcs = null; + this.BreakPointControl1.MemoryDomains = null; + this.BreakPointControl1.Name = "BreakPointControl1"; + this.BreakPointControl1.ParentDebugger = null; + this.BreakPointControl1.Size = new System.Drawing.Size(225, 256); + this.BreakPointControl1.TabIndex = 0; + // + // DisassemblerBox + // + this.DisassemblerBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left))); - this.DisassemblerBox.Controls.Add(this.ToPCBtn); - this.DisassemblerBox.Controls.Add(this.label1); - this.DisassemblerBox.Controls.Add(this.DisassemblerView); - this.DisassemblerBox.Location = new System.Drawing.Point(12, 27); - this.DisassemblerBox.Name = "DisassemblerBox"; - this.DisassemblerBox.Size = new System.Drawing.Size(407, 521); - this.DisassemblerBox.TabIndex = 7; - this.DisassemblerBox.TabStop = false; - this.DisassemblerBox.Text = "Disassembler"; - // - // ToPCBtn - // - this.ToPCBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.ToPCBtn.Location = new System.Drawing.Point(351, 13); - this.ToPCBtn.Name = "ToPCBtn"; - this.ToPCBtn.Size = new System.Drawing.Size(50, 23); - this.ToPCBtn.TabIndex = 3; - this.ToPCBtn.Text = "To PC"; - this.ToPCBtn.UseVisualStyleBackColor = true; - this.ToPCBtn.Click += new System.EventHandler(this.ToPCBtn_Click); - // - // label1 - // - this.label1.Location = new System.Drawing.Point(6, 51); - this.label1.Name = "label1"; - this.label1.Text = "Cpu: Use \'[\' or \']\' to change address, hold \'shift\' for speed."; - // - // DisassemblerView - // - this.DisassemblerView.AllowColumnReorder = false; - this.DisassemblerView.AllowColumnResize = true; - this.DisassemblerView.AllowMassNavigationShortcuts = true; - this.DisassemblerView.AllowRightClickSelection = true; - this.DisassemblerView.AlwaysScroll = false; - this.DisassemblerView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + this.DisassemblerBox.Controls.Add(this.ToPCBtn); + this.DisassemblerBox.Controls.Add(this.label1); + this.DisassemblerBox.Controls.Add(this.DisassemblerView); + this.DisassemblerBox.Location = new System.Drawing.Point(12, 27); + this.DisassemblerBox.Name = "DisassemblerBox"; + this.DisassemblerBox.Size = new System.Drawing.Size(407, 521); + this.DisassemblerBox.TabIndex = 7; + this.DisassemblerBox.TabStop = false; + this.DisassemblerBox.Text = "Disassembler"; + // + // ToPCBtn + // + this.ToPCBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ToPCBtn.Location = new System.Drawing.Point(351, 13); + this.ToPCBtn.Name = "ToPCBtn"; + this.ToPCBtn.Size = new System.Drawing.Size(50, 23); + this.ToPCBtn.TabIndex = 3; + this.ToPCBtn.Text = "To PC"; + this.ToPCBtn.UseVisualStyleBackColor = true; + this.ToPCBtn.Click += new System.EventHandler(this.ToPCBtn_Click); + // + // label1 + // + this.label1.Location = new System.Drawing.Point(6, 51); + this.label1.Name = "label1"; + this.label1.Text = "Cpu: Use \'[\' or \']\' to change address, hold \'shift\' for speed."; + // + // DisassemblerView + // + this.DisassemblerView.AllowColumnReorder = false; + this.DisassemblerView.AllowColumnResize = true; + this.DisassemblerView.AllowMassNavigationShortcuts = true; + this.DisassemblerView.AllowRightClickSelection = true; + this.DisassemblerView.AlwaysScroll = false; + this.DisassemblerView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.DisassemblerView.CellHeightPadding = 0; - this.DisassemblerView.ChangeSelectionWhenPaging = true; - this.DisassemblerView.ContextMenuStrip = this.DisassemblerContextMenu; - this.DisassemblerView.Font = new System.Drawing.Font("Courier New", 8F); - this.DisassemblerView.FullRowSelect = true; - this.DisassemblerView.HorizontalOrientation = false; - this.DisassemblerView.LetKeysModifySelection = false; - this.DisassemblerView.Location = new System.Drawing.Point(6, 67); - this.DisassemblerView.Name = "DisassemblerView"; - this.DisassemblerView.RowCount = 0; - this.DisassemblerView.ScrollSpeed = 0; - this.DisassemblerView.SeekingCutoffInterval = 0; - this.DisassemblerView.Size = new System.Drawing.Size(395, 448); - this.DisassemblerView.TabIndex = 1; - this.DisassemblerView.SizeChanged += new System.EventHandler(this.DisassemblerView_SizeChanged); - this.DisassemblerView.KeyDown += new System.Windows.Forms.KeyEventHandler(this.DisassemblerView_KeyDown); - // - // DisassemblerContextMenu - // - this.DisassemblerContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.DisassemblerView.CellHeightPadding = 0; + this.DisassemblerView.ContextMenuStrip = this.DisassemblerContextMenu; + this.DisassemblerView.Font = new System.Drawing.Font("Courier New", 8F); + this.DisassemblerView.FullRowSelect = true; + this.DisassemblerView.HorizontalOrientation = false; + this.DisassemblerView.LetKeysModifySelection = false; + this.DisassemblerView.Location = new System.Drawing.Point(6, 67); + this.DisassemblerView.Name = "DisassemblerView"; + this.DisassemblerView.RowCount = 0; + this.DisassemblerView.ScrollSpeed = 0; + this.DisassemblerView.SeekingCutoffInterval = 0; + this.DisassemblerView.Size = new System.Drawing.Size(395, 448); + this.DisassemblerView.TabIndex = 1; + this.DisassemblerView.SizeChanged += new System.EventHandler(this.DisassemblerView_SizeChanged); + this.DisassemblerView.KeyDown += new System.Windows.Forms.KeyEventHandler(this.DisassemblerView_KeyDown); + // + // DisassemblerContextMenu + // + this.DisassemblerContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.AddBreakpointContextMenuItem}); - this.DisassemblerContextMenu.Name = "DisassemblerContextMenu"; - this.DisassemblerContextMenu.Size = new System.Drawing.Size(157, 26); - this.DisassemblerContextMenu.Opening += new System.ComponentModel.CancelEventHandler(this.DisassemblerContextMenu_Opening); - // - // AddBreakpointContextMenuItem - // - this.AddBreakpointContextMenuItem.Text = "Add Breakpoint"; - this.AddBreakpointContextMenuItem.Click += new System.EventHandler(this.AddBreakpointContextMenuItem_Click); - // - // StepOutBtn - // - this.StepOutBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.StepOutBtn.Enabled = false; - this.StepOutBtn.Location = new System.Drawing.Point(680, 519); - this.StepOutBtn.Name = "StepOutBtn"; - this.StepOutBtn.Size = new System.Drawing.Size(75, 23); - this.StepOutBtn.TabIndex = 10; - this.StepOutBtn.Text = "Step Out"; - this.StepOutBtn.UseVisualStyleBackColor = true; - this.StepOutBtn.Click += new System.EventHandler(this.StepOutMenuItem_Click); - // - // StepIntoBtn - // - this.StepIntoBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.StepIntoBtn.Enabled = false; - this.StepIntoBtn.Location = new System.Drawing.Point(680, 461); - this.StepIntoBtn.Name = "StepIntoBtn"; - this.StepIntoBtn.Size = new System.Drawing.Size(75, 23); - this.StepIntoBtn.TabIndex = 11; - this.StepIntoBtn.Text = "Step Into"; - this.StepIntoBtn.UseVisualStyleBackColor = true; - this.StepIntoBtn.Click += new System.EventHandler(this.StepIntoMenuItem_Click); - // - // StepOverBtn - // - this.StepOverBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.StepOverBtn.Enabled = false; - this.StepOverBtn.Location = new System.Drawing.Point(680, 490); - this.StepOverBtn.Name = "StepOverBtn"; - this.StepOverBtn.Size = new System.Drawing.Size(75, 23); - this.StepOverBtn.TabIndex = 12; - this.StepOverBtn.Text = "Step Over"; - this.StepOverBtn.UseVisualStyleBackColor = true; - this.StepOverBtn.Click += new System.EventHandler(this.StepOverMenuItem_Click); - // - // SeekToBtn - // - this.SeekToBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.SeekToBtn.Location = new System.Drawing.Point(680, 267); - this.SeekToBtn.Name = "SeekToBtn"; - this.SeekToBtn.Size = new System.Drawing.Size(75, 23); - this.SeekToBtn.TabIndex = 13; - this.SeekToBtn.Text = "Seek To:"; - this.SeekToBtn.UseVisualStyleBackColor = true; - this.SeekToBtn.Click += new System.EventHandler(this.SeekToBtn_Click); - // - // SeekToBox - // - this.SeekToBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.SeekToBox.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper; - this.SeekToBox.Location = new System.Drawing.Point(680, 297); - this.SeekToBox.Name = "SeekToBox"; - this.SeekToBox.Nullable = false; - this.SeekToBox.Size = new System.Drawing.Size(75, 20); - this.SeekToBox.TabIndex = 14; - // - // CancelSeekBtn - // - this.CancelSeekBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.CancelSeekBtn.Location = new System.Drawing.Point(680, 323); - this.CancelSeekBtn.Name = "CancelSeekBtn"; - this.CancelSeekBtn.Size = new System.Drawing.Size(75, 23); - this.CancelSeekBtn.TabIndex = 15; - this.CancelSeekBtn.Text = "Cancel"; - this.CancelSeekBtn.UseVisualStyleBackColor = true; - this.CancelSeekBtn.Click += new System.EventHandler(this.CancelSeekBtn_Click); - // - // RunBtn - // - this.RunBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.RunBtn.Location = new System.Drawing.Point(680, 432); - this.RunBtn.Name = "RunBtn"; - this.RunBtn.Size = new System.Drawing.Size(75, 23); - this.RunBtn.TabIndex = 16; - this.RunBtn.Text = "Run"; - this.RunBtn.UseVisualStyleBackColor = true; - this.RunBtn.Click += new System.EventHandler(this.RunBtn_Click); - // - // GenericDebugger - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(767, 560); - this.Controls.Add(this.RunBtn); - this.Controls.Add(this.CancelSeekBtn); - this.Controls.Add(this.SeekToBox); - this.Controls.Add(this.SeekToBtn); - this.Controls.Add(this.StepOverBtn); - this.Controls.Add(this.StepIntoBtn); - this.Controls.Add(this.StepOutBtn); - this.Controls.Add(this.BreakpointsGroupBox); - this.Controls.Add(this.RegistersGroupBox); - this.Controls.Add(this.DisassemblerBox); - this.Controls.Add(this.menuStrip1); - this.MainMenuStrip = this.menuStrip1; - this.Name = "GenericDebugger"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.GenericDebugger_MouseMove); - this.menuStrip1.ResumeLayout(false); - this.menuStrip1.PerformLayout(); - this.RegistersGroupBox.ResumeLayout(false); - this.BreakpointsGroupBox.ResumeLayout(false); - this.DisassemblerBox.ResumeLayout(false); - this.DisassemblerBox.PerformLayout(); - this.DisassemblerContextMenu.ResumeLayout(false); - this.ResumeLayout(false); - this.PerformLayout(); + this.DisassemblerContextMenu.Name = "DisassemblerContextMenu"; + this.DisassemblerContextMenu.Size = new System.Drawing.Size(157, 26); + this.DisassemblerContextMenu.Opening += new System.ComponentModel.CancelEventHandler(this.DisassemblerContextMenu_Opening); + // + // AddBreakpointContextMenuItem + // + this.AddBreakpointContextMenuItem.Text = "Add Breakpoint"; + this.AddBreakpointContextMenuItem.Click += new System.EventHandler(this.AddBreakpointContextMenuItem_Click); + // + // StepOutBtn + // + this.StepOutBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.StepOutBtn.Enabled = false; + this.StepOutBtn.Location = new System.Drawing.Point(680, 519); + this.StepOutBtn.Name = "StepOutBtn"; + this.StepOutBtn.Size = new System.Drawing.Size(75, 23); + this.StepOutBtn.TabIndex = 10; + this.StepOutBtn.Text = "Step Out"; + this.StepOutBtn.UseVisualStyleBackColor = true; + this.StepOutBtn.Click += new System.EventHandler(this.StepOutMenuItem_Click); + // + // StepIntoBtn + // + this.StepIntoBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.StepIntoBtn.Enabled = false; + this.StepIntoBtn.Location = new System.Drawing.Point(680, 461); + this.StepIntoBtn.Name = "StepIntoBtn"; + this.StepIntoBtn.Size = new System.Drawing.Size(75, 23); + this.StepIntoBtn.TabIndex = 11; + this.StepIntoBtn.Text = "Step Into"; + this.StepIntoBtn.UseVisualStyleBackColor = true; + this.StepIntoBtn.Click += new System.EventHandler(this.StepIntoMenuItem_Click); + // + // StepOverBtn + // + this.StepOverBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.StepOverBtn.Enabled = false; + this.StepOverBtn.Location = new System.Drawing.Point(680, 490); + this.StepOverBtn.Name = "StepOverBtn"; + this.StepOverBtn.Size = new System.Drawing.Size(75, 23); + this.StepOverBtn.TabIndex = 12; + this.StepOverBtn.Text = "Step Over"; + this.StepOverBtn.UseVisualStyleBackColor = true; + this.StepOverBtn.Click += new System.EventHandler(this.StepOverMenuItem_Click); + // + // SeekToBtn + // + this.SeekToBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.SeekToBtn.Location = new System.Drawing.Point(680, 267); + this.SeekToBtn.Name = "SeekToBtn"; + this.SeekToBtn.Size = new System.Drawing.Size(75, 23); + this.SeekToBtn.TabIndex = 13; + this.SeekToBtn.Text = "Seek To:"; + this.SeekToBtn.UseVisualStyleBackColor = true; + this.SeekToBtn.Click += new System.EventHandler(this.SeekToBtn_Click); + // + // SeekToBox + // + this.SeekToBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.SeekToBox.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper; + this.SeekToBox.Location = new System.Drawing.Point(680, 297); + this.SeekToBox.Name = "SeekToBox"; + this.SeekToBox.Nullable = false; + this.SeekToBox.Size = new System.Drawing.Size(75, 20); + this.SeekToBox.TabIndex = 14; + // + // CancelSeekBtn + // + this.CancelSeekBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.CancelSeekBtn.Location = new System.Drawing.Point(680, 323); + this.CancelSeekBtn.Name = "CancelSeekBtn"; + this.CancelSeekBtn.Size = new System.Drawing.Size(75, 23); + this.CancelSeekBtn.TabIndex = 15; + this.CancelSeekBtn.Text = "Cancel"; + this.CancelSeekBtn.UseVisualStyleBackColor = true; + this.CancelSeekBtn.Click += new System.EventHandler(this.CancelSeekBtn_Click); + // + // RunBtn + // + this.RunBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.RunBtn.Location = new System.Drawing.Point(680, 432); + this.RunBtn.Name = "RunBtn"; + this.RunBtn.Size = new System.Drawing.Size(75, 23); + this.RunBtn.TabIndex = 16; + this.RunBtn.Text = "Run"; + this.RunBtn.UseVisualStyleBackColor = true; + this.RunBtn.Click += new System.EventHandler(this.RunBtn_Click); + // + // GenericDebugger + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(767, 560); + this.Controls.Add(this.RunBtn); + this.Controls.Add(this.CancelSeekBtn); + this.Controls.Add(this.SeekToBox); + this.Controls.Add(this.SeekToBtn); + this.Controls.Add(this.StepOverBtn); + this.Controls.Add(this.StepIntoBtn); + this.Controls.Add(this.StepOutBtn); + this.Controls.Add(this.BreakpointsGroupBox); + this.Controls.Add(this.RegistersGroupBox); + this.Controls.Add(this.DisassemblerBox); + this.Controls.Add(this.menuStrip1); + this.MainMenuStrip = this.menuStrip1; + this.Name = "GenericDebugger"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.GenericDebugger_MouseMove); + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.RegistersGroupBox.ResumeLayout(false); + this.BreakpointsGroupBox.ResumeLayout(false); + this.DisassemblerBox.ResumeLayout(false); + this.DisassemblerBox.PerformLayout(); + this.DisassemblerContextMenu.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); } diff --git a/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Disassembler.cs b/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Disassembler.cs index 0841ce7b4fd..e412bc55aad 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Disassembler.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.Disassembler.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.IToolForm.cs b/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.IToolForm.cs index 38231ba2076..12ab32d6476 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.IToolForm.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.IToolForm.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Client.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.cs b/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.cs index 2b4b3fba8e3..9a991d001d3 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Linq; using System.Windows.Forms; @@ -119,7 +118,7 @@ Control GenCPUPicker() var pc = PCRegister; SeekToBox.Nullable = false; SeekToBox.SetHexProperties((long)Math.Pow(2, pc.BitSize)); - SeekToBox.SetFromRawInt(0); + SeekToBox.SetFromRawUInt(0); } else { @@ -264,7 +263,7 @@ public void DisableCancelSeekBtn() private void SeekToBtn_Click(object sender, EventArgs e) { CancelSeekBtn.Enabled = true; - var pcVal = (uint)(SeekToBox.ToRawInt() ?? 0); + var pcVal = SeekToBox.ToRawUInt() ?? 0; var pcBitSize = PCRegister.BitSize; BreakPointControl1.RemoveCurrentSeek(); diff --git a/src/BizHawk.Client.EmuHawk/tools/Debugger/RegisterBoxControl.cs b/src/BizHawk.Client.EmuHawk/tools/Debugger/RegisterBoxControl.cs index 79e3e77a714..58a51878b29 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Debugger/RegisterBoxControl.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Debugger/RegisterBoxControl.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Linq; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/tools/ExternalToolManager.cs b/src/BizHawk.Client.EmuHawk/tools/ExternalToolManager.cs index a69010e1f53..ac3203783db 100644 --- a/src/BizHawk.Client.EmuHawk/tools/ExternalToolManager.cs +++ b/src/BizHawk.Client.EmuHawk/tools/ExternalToolManager.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.IO; @@ -89,7 +88,7 @@ public void Restart(Config config) DirectoryMonitor.Created -= DirectoryMonitor_Created; DirectoryMonitor.Dispose(); } - var path = _config.PathEntries[PathEntryCollection.GLOBAL, "External Tools"].Path; + var path = _config.PathEntries.ExternalToolsAbsolutePath(); if (Directory.Exists(path)) { DirectoryMonitor = new FileSystemWatcher(path, "*.dll") @@ -123,7 +122,7 @@ internal void BuildToolStrip() { ToolStripMenuItem/*?*/ Fail(string reason) { - Console.WriteLine($"ignoring /{fileName.MakeRelativeTo(DirectoryMonitor.Path).RemovePrefix("./")} as {reason}"); + Console.WriteLine($"ignoring /{fileName.MakeRelativeTo(Path.GetFullPath(DirectoryMonitor.Path)).RemovePrefix("./")} as {reason}"); return null; } if (fileName == null) throw new Exception(); @@ -135,12 +134,7 @@ internal void BuildToolStrip() try { if (!OSTailoredCode.IsUnixHost) MotWHack.RemoveMOTW(fileName); -#if DEBUG var externalToolFile = Assembly.LoadFrom(fileName); -#else - var asmBytes = File.ReadAllBytes(fileName); - var externalToolFile = Assembly.Load(asmBytes); -#endif if (!externalToolFile.GetReferencedAssemblies().Any(static name => name.Name.StartsWithOrdinal("BizHawk."))) { return Fail("it doesn't reference a BizHawk assembly"); @@ -154,9 +148,15 @@ internal void BuildToolStrip() if (applicabilityAttrs.Count > 1) throw new ExternalToolApplicabilityAttributeBase.DuplicateException(); var toolAttribute = allAttrs.OfType().First(); + item.Text = toolAttribute.Name; if (toolAttribute.LoadAssemblyFiles != null) { - foreach (var depFilename in toolAttribute.LoadAssemblyFiles) Assembly.LoadFrom($"{_config.PathEntries[PathEntryCollection.GLOBAL, "External Tools"].Path}/{depFilename}"); + foreach (var depFilename in toolAttribute.LoadAssemblyFiles) + { + var depFilePath = Path.Combine(_config.PathEntries.ExternalToolsAbsolutePath(), depFilename); + Console.WriteLine($"preloading assembly {depFilePath} requested by ext. tool {toolAttribute.Name}"); + Assembly.LoadFrom(depFilePath); + } } item.Image = null; // no errors, remove error icon @@ -166,13 +166,12 @@ internal void BuildToolStrip() var rawIcon = externalToolFile.GetManifestResourceStream(embeddedIconAttr.ResourcePath); if (rawIcon != null) item.Image = new Bitmap(rawIcon); } - item.Text = toolAttribute.Name; MenuItemInfo menuItemInfo = new( this, #if DEBUG asmChecksum: string.Empty, #else - asmChecksum: SHA1Checksum.ComputePrefixedHex(asmBytes), + asmChecksum: SHA1Checksum.ComputePrefixedHex(File.ReadAllBytes(fileName)), #endif asmFilename: fileName, entryPointTypeName: entryPoint.FullName); diff --git a/src/BizHawk.Client.EmuHawk/tools/GB/GBGPUView.cs b/src/BizHawk.Client.EmuHawk/tools/GB/GBGPUView.cs index 0bbc3578229..048aa51207f 100644 --- a/src/BizHawk.Client.EmuHawk/tools/GB/GBGPUView.cs +++ b/src/BizHawk.Client.EmuHawk/tools/GB/GBGPUView.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Drawing.Imaging; using System.Text; @@ -44,6 +43,7 @@ private IGameboyCommon Gb /// Whether the tiles are being drawn with the sprite or bg palettes /// private bool _tilesPalIsSprite; + /// /// How far (in bytes, I guess?) we should offset into the tiles palette /// diff --git a/src/BizHawk.Client.EmuHawk/tools/GB/GBPrinterView.cs b/src/BizHawk.Client.EmuHawk/tools/GB/GBPrinterView.cs index fb28f76afd4..a22c649ed99 100644 --- a/src/BizHawk.Client.EmuHawk/tools/GB/GBPrinterView.cs +++ b/src/BizHawk.Client.EmuHawk/tools/GB/GBPrinterView.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/tools/GBA/GBAGPUView.cs b/src/BizHawk.Client.EmuHawk/tools/GBA/GBAGPUView.cs index baa9643efd7..7ae099cd4df 100644 --- a/src/BizHawk.Client.EmuHawk/tools/GBA/GBAGPUView.cs +++ b/src/BizHawk.Client.EmuHawk/tools/GBA/GBAGPUView.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/tools/GBA/MobileDetailView.cs b/src/BizHawk.Client.EmuHawk/tools/GBA/MobileDetailView.cs index 740f1b9bc84..03cf8c7ca56 100644 --- a/src/BizHawk.Client.EmuHawk/tools/GBA/MobileDetailView.cs +++ b/src/BizHawk.Client.EmuHawk/tools/GBA/MobileDetailView.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; namespace BizHawk.Client.EmuHawk diff --git a/src/BizHawk.Client.EmuHawk/tools/GameShark.cs b/src/BizHawk.Client.EmuHawk/tools/GameShark.cs index 85053377279..1310e86f12c 100644 --- a/src/BizHawk.Client.EmuHawk/tools/GameShark.cs +++ b/src/BizHawk.Client.EmuHawk/tools/GameShark.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/tools/Genesis/VDPViewer.cs b/src/BizHawk.Client.EmuHawk/tools/Genesis/VDPViewer.cs index e1dfa026e5b..8fd24fd3672 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Genesis/VDPViewer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Genesis/VDPViewer.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; using System.Drawing.Imaging; diff --git a/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexColor.cs b/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexColor.cs index b52d5bf6571..1f33915efba 100644 --- a/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexColor.cs +++ b/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexColor.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; namespace BizHawk.Client.EmuHawk diff --git a/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.Designer.cs b/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.Designer.cs index cad33f5aa90..cb3c8f8543e 100644 --- a/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.Designer.cs @@ -429,6 +429,7 @@ private void InitializeComponent() // this.HexScrollBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Right))); + this.HexScrollBar.Dock = System.Windows.Forms.DockStyle.Right; this.HexScrollBar.LargeChange = 16; this.HexScrollBar.Location = new System.Drawing.Point(544, 16); this.HexScrollBar.Name = "HexScrollBar"; diff --git a/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs b/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs index df99162fc7e..03a06fdaa33 100644 --- a/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs +++ b/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; @@ -353,7 +352,7 @@ public void FindNext(string value, bool wrap) GoToAddress(found); _findStr = search; } - else if (wrap == false) + else if (!wrap) { FindPrev(value, true); // Search the opposite direction if not found } @@ -400,7 +399,7 @@ public void FindPrev(string value, bool wrap) GoToAddress(found); _findStr = search; } - else if (wrap == false) + else if (!wrap) { FindPrev(value, true); // Search the opposite direction if not found } @@ -854,6 +853,7 @@ private void FreezeHighlighted() return; } + var cheats = new List(); if (_highlightedAddress >= 0) { var watch = Watch.GenerateWatch( @@ -863,14 +863,13 @@ private void FreezeHighlighted() Common.WatchDisplayType.Hex, BigEndian); - MainForm.CheatList.Add(new Cheat( + cheats.Add(new Cheat( watch, watch.Value)); } if (_secondaryHighlightedAddresses.Any()) { - var cheats = new List(); foreach (var address in _secondaryHighlightedAddresses) { var watch = Watch.GenerateWatch( @@ -884,10 +883,10 @@ private void FreezeHighlighted() watch, watch.Value)); } - - MainForm.CheatList.AddRange(cheats); } + MainForm.CheatList.AddRange(cheats); + MemoryViewerBox.Refresh(); } @@ -1395,10 +1394,7 @@ private string MakeCopyExportString(bool export) } // and add HighlightedAddress if present - if (_highlightedAddress.HasValue) - { - addresses[^1] = _highlightedAddress.Value; - } + if (_highlightedAddress is long l) addresses[addresses.Length - 1] = l; // these need to be sorted. it's not just for HighlightedAddress, _secondaryHighlightedAddresses can even be jumbled Array.Sort(addresses); @@ -1578,7 +1574,7 @@ private void DataSizeDWordMenuItem_Click(object sender, EventArgs e) private void BigEndianMenuItem_Click(object sender, EventArgs e) { - BigEndian ^= true; + BigEndian = !BigEndian; GeneralUpdate(); } diff --git a/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexFind.cs b/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexFind.cs index f48a8a1f801..816c2542f52 100644 --- a/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexFind.cs +++ b/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexFind.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/tools/InputPrompt.cs b/src/BizHawk.Client.EmuHawk/tools/InputPrompt.cs index 595e5c7b3c9..c2820d6c27e 100644 --- a/src/BizHawk.Client.EmuHawk/tools/InputPrompt.cs +++ b/src/BizHawk.Client.EmuHawk/tools/InputPrompt.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/ConsoleLuaLibrary.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/ConsoleLuaLibrary.cs index 49eaf2437ad..30226056cef 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/ConsoleLuaLibrary.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/ConsoleLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Text; diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/FormsLuaLibrary.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/FormsLuaLibrary.cs index 4e1cb7b2211..f2102da01a1 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/FormsLuaLibrary.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/FormsLuaLibrary.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs index 0f6eb5f0534..f2bb6d35f27 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Linq; @@ -26,7 +25,7 @@ public TAStudioLuaLibrary(ILuaLibraries luaLibsImpl, ApiContainer apiContainer, public override string Name => "tastudio"; - private TAStudio Tastudio => Tools.Get() as TAStudio; + private TAStudio Tastudio => Tools.TAStudio; private struct PendingChanges { @@ -328,6 +327,7 @@ public void ApplyInputChanges() Tastudio.CurrentTasMovie.SetAxisState(_changeList[i].Frame, _changeList[i].Button, _changeList[i].ValueAxis); break; } + Tastudio.RefreshForInputChange(_changeList[i].Frame); break; case LuaChangeTypes.InsertFrames: Tastudio.InsertNumFrames(_changeList[i].Frame, _changeList[i].Number); @@ -341,7 +341,6 @@ public void ApplyInputChanges() } } _changeList.Clear(); - Tastudio.Refresh(); Tastudio.JumpToGreenzone(); Tastudio.DoAutoRestore(); } @@ -543,7 +542,7 @@ public void ClearIconCache() } [LuaMethodExample("tastudio.ongreenzoneinvalidated( function( currentindex )\r\n\tconsole.log( \"Called whenever the greenzone is invalidated.\" );\r\nend );")] - [LuaMethod("ongreenzoneinvalidated", "Called whenever the greenzone is invalidated. Your callback can have 1 parameter, which will be the index of the first row that was invalidated.")] + [LuaMethod("ongreenzoneinvalidated", "Called whenever the greenzone is invalidated. Your callback can have 1 parameter, which will be the index of the last row before the invalidated ones.")] public void OnGreenzoneInvalidated(LuaFunction luaf) { if (Engaged()) diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaAutocompleteInstaller.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaAutocompleteInstaller.cs index 95df15dd123..871129c17d9 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaAutocompleteInstaller.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaAutocompleteInstaller.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaButton.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaButton.cs index fd1f578b934..0c0a6477f12 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaButton.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaButton.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; namespace BizHawk.Client.EmuHawk diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaCanvas.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaCanvas.cs index 6da3fcc0d5c..e089d4dde2a 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaCanvas.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaCanvas.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaCheckbox.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaCheckbox.cs index 5f61da99931..7353f40e360 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaCheckbox.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaCheckbox.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; namespace BizHawk.Client.EmuHawk diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs index aed4b760598..5ed96ca6669 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; @@ -132,6 +131,7 @@ public LuaConsole() Settings.Columns = LuaListView.AllColumns; DisplayManager.ClearApiHawkSurfaces(); + DisplayManager.ClearApiHawkTextureCache(); ResetDrawSurfacePadding(); ClearFileWatches(); LuaImp?.Close(); @@ -386,7 +386,7 @@ private void RemoveAllLuaFiles() { while (LuaImp.ScriptList.Count > 0) { - RemoveLuaFile(LuaImp.ScriptList[^1]); + RemoveLuaFile(LuaImp.ScriptList[LuaImp.ScriptList.Count - 1]); } } @@ -949,6 +949,7 @@ private void RemoveScriptMenuItem_Click(object sender, EventArgs e) UpdateDialog(); DisplayManager.ClearApiHawkSurfaces(); + DisplayManager.ClearApiHawkTextureCache(); DisplayManager.OSD.ClearGuiText(); if (!LuaImp.ScriptList.Any(static lf => !lf.IsSeparator)) ResetDrawSurfacePadding(); // just removed last script, reset padding } @@ -1028,7 +1029,7 @@ private void MoveDownMenuItem_Click(object sender, EventArgs e) { var indices = LuaListView.SelectedRows.ToList(); if (indices.Count == 0 - || indices[^1] == LuaImp.ScriptList.Count - 1) // at end already + || indices[indices.Count - 1] == LuaImp.ScriptList.Count - 1) // at end already { return; } @@ -1095,19 +1096,14 @@ private void OptionsSubMenu_DropDownOpened(object sender, EventArgs e) } private void DisableScriptsOnLoadMenuItem_Click(object sender, EventArgs e) - { - Settings.DisableLuaScriptsOnLoad ^= true; - } + => Settings.DisableLuaScriptsOnLoad = !Settings.DisableLuaScriptsOnLoad; private void ToggleAllIfNoneSelectedMenuItem_Click(object sender, EventArgs e) - { - Settings.ToggleAllIfNoneSelected ^= true; - } + => Settings.ToggleAllIfNoneSelected = !Settings.ToggleAllIfNoneSelected; private void ReloadWhenScriptFileChangesMenuItem_Click(object sender, EventArgs e) { - Settings.ReloadOnScriptFileChange ^= true; - + Settings.ReloadOnScriptFileChange = !Settings.ReloadOnScriptFileChange; if (Settings.ReloadOnScriptFileChange) { AddFileWatches(); @@ -1318,7 +1314,7 @@ private void OutputBox_KeyDown(object sender, KeyEventArgs e) /// private void LuaListView_ColumnClick(object sender, InputRoll.ColumnClickEventArgs e) { - var columnToSort = e.Column.Name; + var columnToSort = e.Column!.Name; var luaListTemp = new List(); if (columnToSort != _lastColumnSorted) { @@ -1333,7 +1329,7 @@ private void LuaListView_ColumnClick(object sender, InputRoll.ColumnClickEventAr var split = words[0].Split(Path.DirectorySeparatorChar); luaListTemp.Add(LuaImp.ScriptList[i]); - luaListTemp[i].Name = split[^1]; + luaListTemp[i].Name = split[split.Length - 1]; } // Script, Path diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaFunctionsForm.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaFunctionsForm.cs index 877135034df..aa379733b95 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaFunctionsForm.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaFunctionsForm.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -100,11 +99,7 @@ public int Column get => _column; set { - if (_column == value) - { - Descending ^= true; - } - + if (_column == value) Descending = !Descending; _column = value; } } diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs index 1393e8ac867..0490799b8f8 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; @@ -205,8 +204,6 @@ public void Restart( public void CallSaveStateEvent(string name) { - using var luaAutoUnlockHack = GuiAPI.ThisIsTheLuaAutoUnlockHack(); - try { foreach (var lf in RegisteredFunctions.Where(static l => l.Event == NamedLuaFunction.EVENT_TYPE_SAVESTATE).ToList()) @@ -222,8 +219,6 @@ public void CallSaveStateEvent(string name) public void CallLoadStateEvent(string name) { - using var luaAutoUnlockHack = GuiAPI.ThisIsTheLuaAutoUnlockHack(); - try { foreach (var lf in RegisteredFunctions.Where(static l => l.Event == NamedLuaFunction.EVENT_TYPE_LOADSTATE).ToList()) @@ -241,8 +236,6 @@ public void CallFrameBeforeEvent() { if (IsUpdateSupressed) return; - using var luaAutoUnlockHack = GuiAPI.ThisIsTheLuaAutoUnlockHack(); - try { foreach (var lf in RegisteredFunctions.Where(static l => l.Event == NamedLuaFunction.EVENT_TYPE_PREFRAME).ToList()) @@ -260,8 +253,6 @@ public void CallFrameAfterEvent() { if (IsUpdateSupressed) return; - using var luaAutoUnlockHack = GuiAPI.ThisIsTheLuaAutoUnlockHack(); - try { foreach (var lf in RegisteredFunctions.Where(static l => l.Event == NamedLuaFunction.EVENT_TYPE_POSTFRAME).ToList()) @@ -277,8 +268,6 @@ public void CallFrameAfterEvent() public void CallExitEvent(LuaFile lf) { - using var luaAutoUnlockHack = GuiAPI.ThisIsTheLuaAutoUnlockHack(); - foreach (var exitCallback in RegisteredFunctions .Where(l => l.Event == NamedLuaFunction.EVENT_TYPE_ENGINESTOP && (l.LuaFile.Path == lf.Path || ReferenceEquals(l.LuaFile.Thread, lf.Thread))) @@ -340,7 +329,6 @@ public void ExecuteString(string command) public (bool WaitForFrame, bool Terminated) ResumeScript(LuaFile lf) { _currThread = lf.Thread; - using var luaAutoUnlockHack = GuiAPI.ThisIsTheLuaAutoUnlockHack(); try { diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaPictureBox.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaPictureBox.cs index 91e7118690c..d65423972ff 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaPictureBox.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaPictureBox.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaRegisteredFunctionsList.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaRegisteredFunctionsList.cs index 844c5fb4d13..99183dfa584 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaRegisteredFunctionsList.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaRegisteredFunctionsList.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Linq; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaWinform.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaWinform.cs index 91647177054..2d4afe8129c 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaWinform.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaWinform.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Windows.Forms; using NLua; diff --git a/src/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.ButtonSelect.cs b/src/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.ButtonSelect.cs index dc5beeaabdc..2987ef22a8f 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.ButtonSelect.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.ButtonSelect.cs @@ -1,7 +1,8 @@ -using System; using System.Drawing; using System.Windows.Forms; +using BizHawk.Client.Common; + namespace BizHawk.Client.EmuHawk { public partial class MacroInputTool @@ -47,9 +48,8 @@ private void ButtonBox_CheckedChanged(object sender, EventArgs e) s.Refresh(); // Update the selected zone's key - var lg = MovieSession.Movie.LogGeneratorInstance(MovieSession.MovieController); - string key = lg.GenerateLogKey(); - key = key.Replace("LogKey:", "").Replace("#", ""); + string key = Bk2LogEntryGenerator.GenerateLogKey(MovieSession.MovieController.Definition); + key = key.Replace("#", ""); foreach (var box in _buttonBoxes) { @@ -58,10 +58,7 @@ private void ButtonBox_CheckedChanged(object sender, EventArgs e) key = key.Replace($"{box.Text}|", ""); } } - - key = key[..^1]; - - SelectedZone.InputKey = key; + SelectedZone.InputKey = key.Substring(startIndex: 0, length: key.Length - 1); // drop final char } private void PositionBoxes() @@ -91,4 +88,4 @@ private void MacroInputTool_Resize(object sender, EventArgs e) PositionBoxes(); } } -} \ No newline at end of file +} diff --git a/src/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.cs b/src/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.cs index 3823a2d81b7..2c330313cad 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Macros/MacroInput.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; @@ -97,7 +96,7 @@ public override void Restart() public override bool AskSaveChanges() { - if (_unsavedZones.Count == 0 || IsDisposed) + if (_unsavedZones.Count == 0) { return true; } diff --git a/src/BizHawk.Client.EmuHawk/tools/Macros/MovieZone.cs b/src/BizHawk.Client.EmuHawk/tools/Macros/MovieZone.cs index 6dc2f0b5814..0146f6d6632 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Macros/MovieZone.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Macros/MovieZone.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.IO; @@ -20,15 +19,13 @@ public class MovieZone public MovieZone(IEmulator emulator, ToolManager tools, IMovieSession movieSession, int start, int length, string key = "") : this(emulator, tools, movieSession) { - var lg = movieSession.Movie.LogGeneratorInstance(movieSession.MovieController); - if (key == "") { - key = lg.GenerateLogKey(); + key = Bk2LogEntryGenerator.GenerateLogKey(movieSession.MovieController.Definition); } - key = key.Replace("LogKey:", "").Replace("#", ""); - key = key[..^1]; + key = key.Replace("#", ""); + key = key.Substring(startIndex: 0, length: key.Length - 1); // drop last char _inputKey = key; Length = length; @@ -38,10 +35,9 @@ public MovieZone(IEmulator emulator, ToolManager tools, IMovieSession movieSessi InitController(_inputKey); var logGenerator = movieSession.Movie.LogGeneratorInstance(_controller); - logGenerator.GenerateLogEntry(); // Reference and create all buttons. - string movieKey = logGenerator.GenerateLogKey().Replace("LogKey:", "").Replace("#", ""); - movieKey = movieKey[..^1]; + string movieKey = Bk2LogEntryGenerator.GenerateLogKey(_controller.Definition).Replace("#", ""); + movieKey = movieKey.Substring(startIndex: 0, length: movieKey.Length - 1); // drop last char if (key == movieKey) { for (int i = 0; i < length; i++) @@ -236,10 +232,9 @@ public MovieZone(string fileName, IDialogController dialogController, IEmulator // If the LogKey contains buttons/controls not accepted by the emulator, // tell the user and display the macro's controller name and player count _inputKey = readText[0]; - var lg = _movieSession.Movie.LogGeneratorInstance(_movieSession.MovieController); - string key = lg.GenerateLogKey(); - key = key.Replace("LogKey:", "").Replace("#", ""); - key = key[..^1]; + string key = Bk2LogEntryGenerator.GenerateLogKey(_movieSession.MovieController.Definition); + key = key.Replace("#", ""); + key = key.Substring(startIndex: 0, length: key.Length - 1); // drop last char string[] emuKeys = key.Split('|'); string[] macroKeys = _inputKey.Split('|'); foreach (var macro in macroKeys) diff --git a/src/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.Designer.cs b/src/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.Designer.cs index 657b81adf1a..1a132d701c2 100644 --- a/src/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.Designer.cs @@ -111,7 +111,8 @@ private void InitializeComponent() // // FileSelectorPanel // - this.FileSelectorPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + this.FileSelectorPanel.AllowDrop = true; + this.FileSelectorPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.FileSelectorPanel.AutoScroll = true; @@ -120,6 +121,8 @@ private void InitializeComponent() this.FileSelectorPanel.Name = "FileSelectorPanel"; this.FileSelectorPanel.Size = new System.Drawing.Size(486, 214); this.FileSelectorPanel.TabIndex = 12; + this.FileSelectorPanel.DragDrop += new System.Windows.Forms.DragEventHandler(this.OnDragDrop); + this.FileSelectorPanel.DragEnter += new System.Windows.Forms.DragEventHandler(this.OnDragEnter); // // AddButton // @@ -191,7 +194,6 @@ private void InitializeComponent() this.MainMenuStrip = this.MultiDiskMenuStrip; this.Name = "MultiDiskBundler"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Load += new System.EventHandler(this.MultiGameCreator_Load); this.grpName.ResumeLayout(false); this.grpName.PerformLayout(); this.ResumeLayout(false); diff --git a/src/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs b/src/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs index 4842cc1f865..8b0da9721e3 100644 --- a/src/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs +++ b/src/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.IO; @@ -8,6 +7,7 @@ using BizHawk.Emulation.Common; using BizHawk.Client.Common; +using BizHawk.Common; using BizHawk.Common.PathExtensions; using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Cores.Sega.MasterSystem; @@ -32,8 +32,8 @@ public MultiDiskBundler() { InitializeComponent(); Icon = ToolIcon; - SystemDropDown.Items.AddRange(new[] - { + SystemDropDown.Items.AddRange([ + VSystemID.Raw.Amiga, VSystemID.Raw.AmstradCPC, VSystemID.Raw.AppleII, VSystemID.Raw.Arcade, @@ -49,20 +49,18 @@ public MultiDiskBundler() VSystemID.Raw.SAT, VSystemID.Raw.TI83, VSystemID.Raw.ZXSpectrum, - }); + ]); } - private void MultiGameCreator_Load(object sender, EventArgs e) => Restart(); - public override void Restart() { FileSelectorPanel.Controls.Clear(); AddButton_Click(null, null); AddButton_Click(null, null); - if (!Game.IsNullInstance() && !MainForm.CurrentlyOpenRom.EndsWithOrdinal(".xml")) + if (!Game.IsNullInstance()) { - if (MainForm.CurrentlyOpenRom.Contains("|")) + if (HawkFile.PathContainsPipe(MainForm.CurrentlyOpenRom)) { var pieces = MainForm.CurrentlyOpenRom.Split('|'); @@ -70,10 +68,19 @@ public override void Restart() var filename = Path.ChangeExtension(pieces[1], ".xml"); NameBox.Text = Path.Combine(directory, filename); + FileSelectors.First().Path = MainForm.CurrentlyOpenRom; } else { NameBox.Text = Path.ChangeExtension(MainForm.CurrentlyOpenRom, ".xml"); + if (MainForm.CurrentlyOpenRom.EndsWithOrdinal(".xml")) + { + PopulateFromXmlFile(MainForm.CurrentlyOpenRom); + } + else + { + FileSelectors.First().Path = MainForm.CurrentlyOpenRom; + } } if (SystemDropDown.Items.Contains(Emulator.SystemId)) @@ -84,9 +91,37 @@ public override void Restart() { SystemDropDown.SelectedItem = VSystemID.Raw.GGL; } + } + } - FileSelectors.First().Path = MainForm.CurrentlyOpenRom; - Recalculate(); + private void PopulateFromXmlFile(string xmlPath) + { + try + { + var xmlGame = XmlGame.Create(new HawkFile(xmlPath)); + AddFiles(xmlGame.AssetFullPaths); + } + catch + { + // something went wrong while parsing the given xml path... just don't populate anything then + } + } + + private void AddFiles(IList filePaths) + { + var existingEmptyControls = FileSelectors.Count(fileSelector => string.IsNullOrEmpty(fileSelector.Path)); + for (int i = existingEmptyControls; i < filePaths.Count; i++) + { + AddButton_Click(null, null); + } + + var fileSelectors = FileSelectors.ToArray(); + int currentFileSelector = 0; + foreach (string filePath in filePaths) + { + while (currentFileSelector < fileSelectors.Length && !string.IsNullOrEmpty(fileSelectors[currentFileSelector].Path)) + currentFileSelector++; + fileSelectors[currentFileSelector].Path = filePath; } } @@ -130,9 +165,7 @@ private void SaveRunButton_Click(object sender, EventArgs e) DialogResult = DialogResult.OK; Close(); - - var lra = new LoadRomArgs { OpenAdvanced = new OpenAdvanced_OpenRom { Path = fileInfo.FullName } }; - _ = MainForm.LoadRom(fileInfo.FullName, lra); + _ = MainForm.LoadRom(fileInfo.FullName, new LoadRomArgs(new OpenAdvanced_OpenRom(fileInfo.FullName))); } private void AddButton_Click(object sender, EventArgs e) @@ -163,23 +196,11 @@ private void AddButton_Click(object sender, EventArgs e) private void btnRemove_Click(object sender, EventArgs e) { - //ToDo: - //Make this better? - //We need to have i at 1 and not zero because Controls Count doesn't start at zero (sort of) - var i = 1; - //For Each Control box we have, loop - foreach (Control ctrl in FileSelectorPanel.Controls) + if (FileSelectorPanel.Controls.Count > 0) { - //if we are at the last box, then remove it. - if ((i == FileSelectorPanel.Controls.Count)) - { - ctrl.Dispose(); - } - //One to our looper - i++; + FileSelectorPanel.Controls[^1].Dispose(); + Recalculate(); } - - Recalculate(); } private void FileSelector_NameChanged(object sender, EventArgs e) @@ -216,21 +237,32 @@ private bool Recalculate() throw new Exception("System Id can not be blank"); } - var basePath = Path.GetDirectoryName(name.SubstringBefore('|')); - if (string.IsNullOrEmpty(basePath)) - { - var fileInfo = new FileInfo(name); - basePath = Path.GetDirectoryName(fileInfo.FullName); - } + var basePath = Path.GetDirectoryName(Path.GetFullPath(name.SubstringBefore('|'))); _currentXml = new XElement("BizHawk-XMLGame", new XAttribute("System", system), new XAttribute("Name", Path.GetFileNameWithoutExtension(name)), new XElement("LoadAssets", - names.Select(n => new XElement( - "Asset", - new XAttribute("FileName", PathExtensions.GetRelativePath(basePath, n)) - )) + names.Select(n => + { + string currentRomPath = Path.GetFullPath(n); + string fileName; + + try + { + fileName = PathExtensions.GetRelativePath(basePath, currentRomPath)!; + } + catch (ArgumentException) + { + // if a relative path cannot be constructed, use an absolute path + fileName = currentRomPath; + } + + return new XElement( + "Asset", + new XAttribute("FileName", fileName) + ); + }) ) ); @@ -284,5 +316,26 @@ private void SystemDropDown_SelectedIndexChanged(object sender, EventArgs e) { Recalculate(); } + + private void OnDragDrop(object sender, DragEventArgs e) + { + string[] droppedFiles = (string[])e.Data.GetData(DataFormats.FileDrop); + if (droppedFiles is null) return; + + string xmlPath = droppedFiles.FirstOrDefault(path => path.EndsWith(".xml", StringComparison.OrdinalIgnoreCase)); + if (xmlPath is not null) + { + PopulateFromXmlFile(xmlPath); + } + else + { + AddFiles(droppedFiles); + } + } + + private void OnDragEnter(object sender, DragEventArgs e) + { + e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : DragDropEffects.None; + } } } diff --git a/src/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskFileSelector.cs b/src/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskFileSelector.cs index 93fd91cc6db..1f1bee18e02 100644 --- a/src/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskFileSelector.cs +++ b/src/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskFileSelector.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Windows.Forms; @@ -27,11 +26,6 @@ public string Path public event EventHandler NameChanged; - private void HandleLabelTextChanged(object sender, EventArgs e) - { - OnNameChanged(EventArgs.Empty); - } - public MultiDiskFileSelector(IDialogController dialogController, PathEntryCollection pathEntries, Func getLoadedRomNameCallback, Func getSystemNameCallback) { @@ -40,7 +34,6 @@ public MultiDiskFileSelector(IDialogController dialogController, PathEntryCollec _getLoadedRomNameCallback = getLoadedRomNameCallback; _getSystemNameCallback = getSystemNameCallback; InitializeComponent(); - PathBox.TextChanged += HandleLabelTextChanged; } protected virtual void OnNameChanged(EventArgs e) diff --git a/src/BizHawk.Client.EmuHawk/tools/NES/BarcodeEntry.cs b/src/BizHawk.Client.EmuHawk/tools/NES/BarcodeEntry.cs index e58ede885ac..6b5bfbbae6a 100644 --- a/src/BizHawk.Client.EmuHawk/tools/NES/BarcodeEntry.cs +++ b/src/BizHawk.Client.EmuHawk/tools/NES/BarcodeEntry.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using BizHawk.Emulation.Cores.Nintendo.NES; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Client.EmuHawk/tools/NES/NESMusicRipper.cs b/src/BizHawk.Client.EmuHawk/tools/NES/NESMusicRipper.cs index c3e84c8d4e7..6a6c9aefcc7 100644 --- a/src/BizHawk.Client.EmuHawk/tools/NES/NESMusicRipper.cs +++ b/src/BizHawk.Client.EmuHawk/tools/NES/NESMusicRipper.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.IO; diff --git a/src/BizHawk.Client.EmuHawk/tools/NES/NESNameTableViewer.cs b/src/BizHawk.Client.EmuHawk/tools/NES/NESNameTableViewer.cs index 10077e0ec66..404f72f12a3 100644 --- a/src/BizHawk.Client.EmuHawk/tools/NES/NESNameTableViewer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/NES/NESNameTableViewer.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms; @@ -163,7 +162,7 @@ private unsafe void Generate(bool now = false) return; } - if (now == false && _emu.Frame % RefreshRate.Value != 0) + if (!now && _emu.Frame % RefreshRate.Value != 0) { return; } diff --git a/src/BizHawk.Client.EmuHawk/tools/NES/NESPPU.cs b/src/BizHawk.Client.EmuHawk/tools/NES/NESPPU.cs index 871e025ed32..5918435672b 100644 --- a/src/BizHawk.Client.EmuHawk/tools/NES/NESPPU.cs +++ b/src/BizHawk.Client.EmuHawk/tools/NES/NESPPU.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms; @@ -805,9 +804,7 @@ private void NesPPU_FormClosed(object sender, FormClosedEventArgs e) private readonly byte[] _chrRomCache = new byte[8192]; private void ChrROMTileViewerToolStripMenuItem_Click(object sender, EventArgs e) - { - ChrRomView ^= true; - } + => ChrRomView = !ChrRomView; private void CalculateFormSize() { diff --git a/src/BizHawk.Client.EmuHawk/tools/PCE/PCEBGViewer.cs b/src/BizHawk.Client.EmuHawk/tools/PCE/PCEBGViewer.cs index e0e2ba993f2..c21bf8530e9 100644 --- a/src/BizHawk.Client.EmuHawk/tools/PCE/PCEBGViewer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/PCE/PCEBGViewer.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/tools/PCE/PCESoundDebugger.cs b/src/BizHawk.Client.EmuHawk/tools/PCE/PCESoundDebugger.cs index b880c6aa5e0..edf80338169 100644 --- a/src/BizHawk.Client.EmuHawk/tools/PCE/PCESoundDebugger.cs +++ b/src/BizHawk.Client.EmuHawk/tools/PCE/PCESoundDebugger.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.IO; using System.IO.Compression; diff --git a/src/BizHawk.Client.EmuHawk/tools/PCE/PCETileViewer.cs b/src/BizHawk.Client.EmuHawk/tools/PCE/PCETileViewer.cs index ef69543b23f..4e35095f4b5 100644 --- a/src/BizHawk.Client.EmuHawk/tools/PCE/PCETileViewer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/PCE/PCETileViewer.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms; diff --git a/src/BizHawk.Client.EmuHawk/tools/SMS/VDPViewer.cs b/src/BizHawk.Client.EmuHawk/tools/SMS/VDPViewer.cs index c35b2b20c56..6d402ffa410 100644 --- a/src/BizHawk.Client.EmuHawk/tools/SMS/VDPViewer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/SMS/VDPViewer.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; using System.Drawing.Imaging; diff --git a/src/BizHawk.Client.EmuHawk/tools/SNES/SNESGraphicsDebugger.cs b/src/BizHawk.Client.EmuHawk/tools/SNES/SNESGraphicsDebugger.cs index 2e872daac0c..71858075f23 100644 --- a/src/BizHawk.Client.EmuHawk/tools/SNES/SNESGraphicsDebugger.cs +++ b/src/BizHawk.Client.EmuHawk/tools/SNES/SNESGraphicsDebugger.cs @@ -22,7 +22,6 @@ //hiding the tab control headers.. once this design gets solid, ill get rid of them //http://www.mostthingsweb.com/2011/01/hiding-tab-headers-on-a-tabcontrol-in-c/ -using System; using System.Collections; using System.Collections.Generic; using System.Drawing; @@ -1377,14 +1376,10 @@ private void lblEnPrio1_Click(object sender, EventArgs e) } private void lblEnPrio2_Click(object sender, EventArgs e) - { - checkEN2_OBJ.Checked ^= true; - } + => checkEN2_OBJ.Checked = !checkEN2_OBJ.Checked; private void lblEnPrio3_Click(object sender, EventArgs e) - { - checkEN3_OBJ.Checked ^= true; - } + => checkEN3_OBJ.Checked = !checkEN3_OBJ.Checked; } //class SNESGraphicsDebugger } //namespace BizHawk.Client.EmuHawk diff --git a/src/BizHawk.Client.EmuHawk/tools/SpecializedToolAttribute.cs b/src/BizHawk.Client.EmuHawk/tools/SpecializedToolAttribute.cs index 278040f3ade..1fa429dd2cc 100644 --- a/src/BizHawk.Client.EmuHawk/tools/SpecializedToolAttribute.cs +++ b/src/BizHawk.Client.EmuHawk/tools/SpecializedToolAttribute.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Client.Common; namespace BizHawk.Client.EmuHawk diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.Designer.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.Designer.cs index a00a8cd9473..3e9c3ef9d9f 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.Designer.cs @@ -142,23 +142,18 @@ private void InitializeComponent() // this.BranchView.AllowColumnReorder = false; this.BranchView.AllowColumnResize = false; - this.BranchView.AllowMassNavigationShortcuts = true; - this.BranchView.AllowRightClickSelection = true; this.BranchView.AlwaysScroll = false; this.BranchView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.BranchView.CellWidthPadding = 3; this.BranchView.CellHeightPadding = 0; this.BranchView.ChangeSelectionWhenPaging = false; this.BranchView.ContextMenuStrip = this.BranchesContextMenu; this.BranchView.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.BranchView.FullRowSelect = true; - this.BranchView.GridLines = true; this.BranchView.HorizontalOrientation = false; this.BranchView.LetKeysModifySelection = false; this.BranchView.Location = new System.Drawing.Point(6, 19); - this.BranchView.MultiSelect = true; this.BranchView.Name = "BranchView"; this.BranchView.RowCount = 0; this.BranchView.ScrollSpeed = 1; diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs index 15c5cb1416e..49786f5a371 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Drawing; using System.IO; @@ -481,8 +480,11 @@ public void SelectBranchExternal(bool next) { if (SelectedBranch == null) { - Select(Branches.Current, true); - BranchView.Refresh(); + if (Branches.Current != -1) + { + Select(Branches.Current, true); + BranchView.Refresh(); + } return; } @@ -593,8 +595,7 @@ private void BranchView_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { - if (BranchView.CurrentCell.IsDataCell() - && BranchView.CurrentCell.Column.Name == BranchNumberColumnName) + if (BranchView.CurrentCell is { RowIndex: not null, Column.Name: BranchNumberColumnName }) { BranchView.DragCurrentCell(); } diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.resx b/src/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.resx index 5af3536e76c..b72db1b6d3f 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.resx +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.resx @@ -123,4 +123,7 @@ 23, 17 + + 185, 17 + \ No newline at end of file diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/FramesPrompt.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/FramesPrompt.cs index 25127ef6d06..be350c264f4 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/FramesPrompt.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/FramesPrompt.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; namespace BizHawk.Client.EmuHawk @@ -18,7 +17,7 @@ public FramesPrompt(string headMessage, string bodyMessage) this.label1.Text = bodyMessage; } - public int Frames => NumFramesBox.ToRawInt() ?? 0; + public int Frames => (int)(NumFramesBox.ToRawUInt() ?? 0); private void FramesPrompt_Load(object sender, EventArgs e) { diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/GreenzoneSettings.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/GreenzoneSettings.cs index e23c7b61465..168e5f02f83 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/GreenzoneSettings.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/GreenzoneSettings.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/HeaderEditor.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/HeaderEditor.cs index 9952d940136..b0f5c86aa1e 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/HeaderEditor.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/HeaderEditor.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/MarkerControl.Designer.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/MarkerControl.Designer.cs index a141eecbd77..26ba57905ef 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/MarkerControl.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/MarkerControl.Designer.cs @@ -62,7 +62,7 @@ private void InitializeComponent() this.toolStripSeparator1, this.RemoveMarkerToolStripMenuItem}); this.MarkerContextMenu.Name = "MarkerContextMenu"; - this.MarkerContextMenu.Size = new System.Drawing.Size(119, 120); + this.MarkerContextMenu.Size = new System.Drawing.Size(196, 142); this.MarkerContextMenu.Opening += new System.ComponentModel.CancelEventHandler(this.MarkerContextMenu_Opening); // // JumpToMarkerToolStripMenuItem @@ -181,14 +181,11 @@ private void InitializeComponent() // this.MarkerView.AllowColumnReorder = false; this.MarkerView.AllowColumnResize = false; - this.MarkerView.AllowMassNavigationShortcuts = true; - this.MarkerView.AllowRightClickSelection = true; this.MarkerView.AlwaysScroll = false; this.MarkerView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.MarkerView.CellHeightPadding = 0; - this.MarkerView.ChangeSelectionWhenPaging = true; this.MarkerView.ContextMenuStrip = this.MarkerContextMenu; this.MarkerView.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.MarkerView.FullRowSelect = true; diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/MarkerControl.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/MarkerControl.cs index 04ce5d603f2..fa0a5aaf2d9 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/MarkerControl.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/MarkerControl.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/MarkerControl.resx b/src/BizHawk.Client.EmuHawk/tools/TAStudio/MarkerControl.resx index cabd6fd3861..1e64cf29690 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/MarkerControl.resx +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/MarkerControl.resx @@ -123,4 +123,7 @@ 168, 17 + + 168, 17 + \ No newline at end of file diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/PatternsForm.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/PatternsForm.cs index 3d992848ceb..3ed4f51e6a4 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/PatternsForm.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/PatternsForm.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Globalization; using System.Windows.Forms; @@ -302,7 +301,7 @@ private void GetPattern() { if (p[i] == lastValue) { - _counts[^1]++; + _counts[_counts.Count - 1]++; } else { @@ -335,7 +334,7 @@ private void GetPattern() { if (p[i] == lastValue) { - _counts[^1]++; + _counts[_counts.Count - 1]++; } else { diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/PlaybackBox.Designer.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/PlaybackBox.Designer.cs index 8b2042936e6..aedb8d24380 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/PlaybackBox.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/PlaybackBox.Designer.cs @@ -137,7 +137,7 @@ private void InitializeComponent() this.PauseButton.Name = "PauseButton"; this.PauseButton.Size = new System.Drawing.Size(38, 23); this.PauseButton.TabIndex = 2; - this.PauseButton.Text = "| |"; + this.PauseButton.Text = "> ||"; this.toolTip1.SetToolTip(this.PauseButton, "Middle Mouse Button"); this.PauseButton.UseVisualStyleBackColor = true; this.PauseButton.Click += new System.EventHandler(this.PauseButton_Click); diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/PlaybackBox.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/PlaybackBox.cs index 1a92e5633ae..defe37d0293 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/PlaybackBox.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/PlaybackBox.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Windows.Forms; @@ -96,26 +95,19 @@ private void NextMarkerButton_Click(object sender, EventArgs e) private void TurboSeekCheckbox_CheckedChanged(object sender, EventArgs e) { - if (!_loading) - { - Tastudio.Config.TurboSeek ^= true; - } + if (!_loading) Tastudio.Config.TurboSeek = !Tastudio.Config.TurboSeek; } private void AutoRestoreCheckbox_CheckedChanged(object sender, EventArgs e) { - if (!_loading) - { - Tastudio.Settings.AutoRestoreLastPosition ^= true; - } + if (!_loading) Tastudio.Settings.AutoRestoreLastPosition = !Tastudio.Settings.AutoRestoreLastPosition; } private void FollowCursorCheckbox_CheckedChanged(object sender, EventArgs e) { if (!_loading) { - Tastudio.Settings.FollowCursor ^= true; - + Tastudio.Settings.FollowCursor = !Tastudio.Settings.FollowCursor; if (Tastudio.Settings.FollowCursor) { Tastudio.SetVisibleFrame(); @@ -126,7 +118,7 @@ private void FollowCursorCheckbox_CheckedChanged(object sender, EventArgs e) private void RecordingModeCheckbox_MouseClick(object sender, MouseEventArgs e) { - RecordingMode ^= true; + RecordingMode = !RecordingMode; Tastudio.WasRecording = RecordingMode; // hard reset at manual click and hotkey } diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Callbacks.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Callbacks.cs index a9dff4b5ec4..637837fbac7 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Callbacks.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Callbacks.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; namespace BizHawk.Client.EmuHawk diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Designer.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Designer.cs index f3262bef953..f08812e9117 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Designer.cs @@ -31,7 +31,7 @@ protected override void Dispose(bool disposing) private void InitializeComponent() { this.components = new System.ComponentModel.Container(); - this.TASMenu = new MenuStripEx(); + this.TASMenu = new BizHawk.WinForms.Controls.MenuStripEx(); this.FileSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.NewTASMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.NewFromSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -83,6 +83,7 @@ private void InitializeComponent() this.SetMaxUndoLevelsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.SetBranchCellHoverIntervalMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.SetSeekingCutoffIntervalMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.CopyIncludesFrameNoMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.toolStripSeparator26 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.autosaveToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.SetAutosaveIntervalMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -112,6 +113,7 @@ private void InitializeComponent() this.customPatternToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.setpToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.setCustomsToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.SetFontMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.MetaSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.HeaderMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.StateHistorySettingsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -129,11 +131,11 @@ private void InitializeComponent() this.toolStripSeparator12 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.hideWasLagFramesToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.iconsToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.ColorSettingsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.DenoteStatesWithIconsToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.DenoteStatesWithBGColorToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.DenoteMarkersWithIconsToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.DenoteMarkersWithBGColorToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.ColorSettingsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.toolStripSeparator23 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.followCursorToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.alwaysScrollToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -153,7 +155,7 @@ private void InitializeComponent() this.toolStripSeparator10 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.EnableTooltipsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.TasView = new BizHawk.Client.EmuHawk.InputRoll(); - this.TasStatusStrip = new StatusStripEx(); + this.TasStatusStrip = new BizHawk.WinForms.Controls.StatusStripEx(); this.MessageStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); this.ProgressBar = new System.Windows.Forms.ToolStripProgressBar(); this.toolStripStatusLabel2 = new System.Windows.Forms.ToolStripStatusLabel(); @@ -191,8 +193,7 @@ private void InitializeComponent() this.BookMarkControl = new BizHawk.Client.EmuHawk.BookmarksBranchesBox(); this.BranchesMarkersSplit = new System.Windows.Forms.SplitContainer(); this.MainVertialSplit = new System.Windows.Forms.SplitContainer(); - this.SetFontMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.CopyIncludesFrameNoMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); this.TASMenu.SuspendLayout(); this.TasStatusStrip.SuspendLayout(); this.RightClickMenu.SuspendLayout(); @@ -347,7 +348,7 @@ private void InitializeComponent() this.DeleteFramesMenuItem, this.CloneFramesMenuItem, this.CloneFramesXTimesMenuItem, - this.InsertNumFramesMenuItem, + this.InsertNumFramesMenuItem, this.toolStripSeparator6, this.TruncateMenuItem, this.ClearGreenzoneMenuItem, @@ -503,7 +504,7 @@ private void InitializeComponent() this.AutopauseAtEndOfMovieMenuItem, this.sepToolStripMenuItem, this.autoHoldFireToolStripMenuItem, - this.SetFontMenuItem}); + this.SetFontMenuItem}); this.ConfigSubMenu.Text = "&Config"; this.ConfigSubMenu.DropDownOpened += new System.EventHandler(this.ConfigSubMenu_DropDownOpened); // @@ -523,6 +524,11 @@ private void InitializeComponent() this.SetSeekingCutoffIntervalMenuItem.Visible = false; this.SetSeekingCutoffIntervalMenuItem.Click += new System.EventHandler(this.SetSeekingCutoffIntervalMenuItem_Click); // + // CopyIncludesFrameNoMenuItem + // + this.CopyIncludesFrameNoMenuItem.Text = "Include Frame No. When Copying Row(s)"; + this.CopyIncludesFrameNoMenuItem.Click += new System.EventHandler(this.CopyIncludesFrameNoMenuItem_Click); + // // autosaveToolStripMenuItem // this.autosaveToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -659,6 +665,11 @@ private void InitializeComponent() this.setCustomsToolStripMenuItem.Text = "Set Customs..."; this.setCustomsToolStripMenuItem.Click += new System.EventHandler(this.SetCustomsMenuItem_Click); // + // SetFontMenuItem + // + this.SetFontMenuItem.Text = "Set Font"; + this.SetFontMenuItem.Click += new System.EventHandler(this.SetFontMenuItem_Click); + // // MetaSubMenu // this.MetaSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -771,11 +782,6 @@ private void InitializeComponent() this.iconsToolStripMenuItem.Text = "Icons"; this.iconsToolStripMenuItem.DropDownOpened += new System.EventHandler(this.IconsMenuItem_DropDownOpened); // - // ColorSettingsMenuItem - // - this.ColorSettingsMenuItem.Text = "Edit TAStudio Colors..."; - this.ColorSettingsMenuItem.Click += new System.EventHandler(this.ColorSettingsMenuItem_Click); - // // DenoteStatesWithIconsToolStripMenuItem // this.DenoteStatesWithIconsToolStripMenuItem.CheckOnClick = true; @@ -800,6 +806,11 @@ private void InitializeComponent() this.DenoteMarkersWithBGColorToolStripMenuItem.Text = "Denote Markers With BG Color"; this.DenoteMarkersWithBGColorToolStripMenuItem.Click += new System.EventHandler(this.DenoteMarkersWithBGColorToolStripMenuItem_Click); // + // ColorSettingsMenuItem + // + this.ColorSettingsMenuItem.Text = "Edit TAStudio Colors..."; + this.ColorSettingsMenuItem.Click += new System.EventHandler(this.ColorSettingsMenuItem_Click); + // // followCursorToolStripMenuItem // this.followCursorToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -886,28 +897,23 @@ private void InitializeComponent() this.EnableTooltipsMenuItem.Text = "&Enable Tooltips"; // // TasView - // - this.TasView.ChangeSelectionWhenPaging = false; - this.TasView.InputPaintingMode = true; - this.TasView.CellWidthPadding = 3; - this.TasView.GridLines = true; - this.TasView.AllowMassNavigationShortcuts = false; + // this.TasView.AllowColumnReorder = false; this.TasView.AllowColumnResize = false; + this.TasView.AllowMassNavigationShortcuts = false; this.TasView.AllowRightClickSelection = false; this.TasView.AlwaysScroll = false; this.TasView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.TasView.CellHeightPadding = 0; + this.TasView.ChangeSelectionWhenPaging = false; this.TasView.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.TasView.FullRowSelect = true; - this.TasView.HideWasLagFrames = false; this.TasView.HorizontalOrientation = false; - this.TasView.LagFramesToHide = 0; + this.TasView.InputPaintingMode = true; this.TasView.LetKeysModifySelection = true; this.TasView.Location = new System.Drawing.Point(3, 0); - this.TasView.MultiSelect = true; this.TasView.Name = "TasView"; this.TasView.Rotatable = true; this.TasView.RowCount = 0; @@ -942,7 +948,7 @@ private void InitializeComponent() // MessageStatusLabel // this.MessageStatusLabel.Name = "MessageStatusLabel"; - this.MessageStatusLabel.Size = new System.Drawing.Size(95, 17); + this.MessageStatusLabel.Size = new System.Drawing.Size(103, 17); this.MessageStatusLabel.Text = "TAStudio engaged"; // // ProgressBar @@ -953,7 +959,7 @@ private void InitializeComponent() // toolStripStatusLabel2 // this.toolStripStatusLabel2.Name = "toolStripStatusLabel2"; - this.toolStripStatusLabel2.Size = new System.Drawing.Size(277, 17); + this.toolStripStatusLabel2.Size = new System.Drawing.Size(269, 17); this.toolStripStatusLabel2.Spring = true; // // SplicerStatusLabel @@ -977,7 +983,7 @@ private void InitializeComponent() this.MarkerControl.Dock = System.Windows.Forms.DockStyle.Fill; this.MarkerControl.Location = new System.Drawing.Point(0, 0); this.MarkerControl.Name = "MarkerControl"; - this.MarkerControl.Size = new System.Drawing.Size(200, 224); + this.MarkerControl.Size = new System.Drawing.Size(200, 225); this.MarkerControl.TabIndex = 6; this.MarkerControl.Tastudio = null; // @@ -1004,7 +1010,7 @@ private void InitializeComponent() this.DeleteFramesContextMenuItem, this.CloneContextMenuItem, this.CloneXTimesContextMenuItem, - this.InsertNumFramesContextMenuItem, + this.InsertNumFramesContextMenuItem, this.toolStripSeparator18, this.TruncateContextMenuItem, this.BranchContextMenuItem, @@ -1012,7 +1018,7 @@ private void InitializeComponent() this.StartNewProjectFromNowMenuItem, this.StartANewProjectFromSaveRamMenuItem}); this.RightClickMenu.Name = "RightClickMenu"; - this.RightClickMenu.Size = new System.Drawing.Size(243, 480); + this.RightClickMenu.Size = new System.Drawing.Size(253, 502); this.RightClickMenu.Opened += new System.EventHandler(this.RightClickMenu_Opened); // // SetMarkersContextMenuItem @@ -1133,7 +1139,7 @@ private void InitializeComponent() this.BookMarkControl.Name = "BookMarkControl"; this.BookMarkControl.RemovedCallback = null; this.BookMarkControl.SavedCallback = null; - this.BookMarkControl.Size = new System.Drawing.Size(200, 184); + this.BookMarkControl.Size = new System.Drawing.Size(200, 183); this.BookMarkControl.TabIndex = 8; this.BookMarkControl.Tastudio = null; // @@ -1154,7 +1160,7 @@ private void InitializeComponent() // this.BranchesMarkersSplit.Panel2.Controls.Add(this.MarkerControl); this.BranchesMarkersSplit.Size = new System.Drawing.Size(200, 412); - this.BranchesMarkersSplit.SplitterDistance = 184; + this.BranchesMarkersSplit.SplitterDistance = 183; this.BranchesMarkersSplit.TabIndex = 9; this.BranchesMarkersSplit.SplitterMoved += new System.Windows.Forms.SplitterEventHandler(this.BranchesMarkersSplit_SplitterMoved); // @@ -1180,16 +1186,6 @@ private void InitializeComponent() this.MainVertialSplit.TabIndex = 10; this.MainVertialSplit.SplitterMoved += new System.Windows.Forms.SplitterEventHandler(this.MainVerticalSplit_SplitterMoved); // - // SetFontMenuItem - // - this.SetFontMenuItem.Text = "Set Font"; - this.SetFontMenuItem.Click += new System.EventHandler(this.SetFontMenuItem_Click); - // - // CopyIncludesFrameNoMenuItem - // - this.CopyIncludesFrameNoMenuItem.Text = "Include Frame No. When Copying Row(s)"; - this.CopyIncludesFrameNoMenuItem.Click += new System.EventHandler(this.CopyIncludesFrameNoMenuItem_Click); - // // TAStudio // this.AllowDrop = true; @@ -1390,5 +1386,6 @@ private void InitializeComponent() private BizHawk.WinForms.Controls.ToolStripMenuItemEx LoadBranchOnDoubleclickMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx SetFontMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx CopyIncludesFrameNoMenuItem; + private System.Windows.Forms.ToolTip toolTip1; } } \ No newline at end of file diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.IControlMainForm.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.IControlMainForm.cs index f4451d97e16..c35d8baaf78 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.IControlMainForm.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.IControlMainForm.cs @@ -68,7 +68,7 @@ public void StopMovie(bool suppressSave) } } - public bool WantsToControlRewind => true; + public bool WantsToControlRewind { get; private set; } = true; public void CaptureRewind() { @@ -113,13 +113,7 @@ public bool RestartMovie() return success; } - public bool WantsToControlReboot { get; private set; } = true; - - public void RebootCore() - { - WantsToControlReboot = false; - NewTasMenuItem_Click(null, null); - WantsToControlReboot = true; - } + public bool WantsToControlReboot => false; + public void RebootCore() => throw new NotSupportedException("This should never be called"); } } diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.IToolForm.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.IToolForm.cs index 39cfc1317dd..b96f29d3d92 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.IToolForm.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.IToolForm.cs @@ -94,7 +94,7 @@ protected override void FastUpdateAfter() public override void Restart() { - if (!IsHandleCreated || IsDisposed) + if (!IsActive) { return; } @@ -106,18 +106,16 @@ public override void Restart() if (CurrentTasMovie != null) { - if (Game.Hash != CurrentTasMovie.Hash) + bool loadRecent = Game.Hash == CurrentTasMovie.Hash && CurrentTasMovie.Filename == Settings.RecentTas.MostRecent; + TastudioStopMovie(); + // try to load the most recent movie if it matches the currently loaded movie + if (loadRecent) { - TastudioStopMovie(); - TasView.AllColumns.Clear(); - StartNewTasMovie(); - SetUpColumns(); - TasView.Refresh(); + LoadMostRecentOrStartNew(); } else { - TastudioStopMovie(); - LoadMostRecentOrStartNew(); + StartNewTasMovie(); } } } diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs index bd1bdcddcf6..ecb8060e02a 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.ListView.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Linq; using System.Windows.Forms; @@ -370,7 +369,7 @@ private void TasView_ColumnClick(object sender, InputRoll.ColumnClickEventArgs e { if (TasView.AnyRowsSelected) { - var columnName = e.Column.Name; + var columnName = e.Column!.Name; if (columnName == FrameColumnName) { @@ -379,7 +378,7 @@ private void TasView_ColumnClick(object sender, InputRoll.ColumnClickEventArgs e else if (columnName != CursorColumnName) { var frame = TasView.AnyRowsSelected ? TasView.FirstSelectedRowIndex : 0; - string buttonName = TasView.CurrentCell.Column.Name; + var buttonName = TasView.CurrentCell.Column!.Name; if (ControllerType.BoolButtons.Contains(buttonName)) { @@ -424,8 +423,9 @@ private void TasView_ColumnClick(object sender, InputRoll.ColumnClickEventArgs e private void TasView_ColumnRightClick(object sender, InputRoll.ColumnClickEventArgs e) { - e.Column.Emphasis ^= true; - UpdateAutoFire(e.Column.Name, e.Column.Emphasis); + var col = e.Column!; + col.Emphasis = !col.Emphasis; + UpdateAutoFire(col.Name, col.Emphasis); TasView.Refresh(); } @@ -542,13 +542,9 @@ private void TasView_MouseDown(object sender, MouseEventArgs e) return; } - if (TasView.CurrentCell?.RowIndex == null || TasView.CurrentCell.Column == null) - { - return; - } + if (TasView.CurrentCell is not { RowIndex: int frame, Column: RollColumn targetCol }) return; - int frame = TasView.CurrentCell.RowIndex.Value; - string buttonName = TasView.CurrentCell.Column.Name; + var buttonName = targetCol.Name; WasRecording = CurrentTasMovie.IsRecording() || WasRecording; if (e.Button == MouseButtons.Left) @@ -592,12 +588,12 @@ private void TasView_MouseDown(object sender, MouseEventArgs e) } } - if (TasView.CurrentCell.Column.Name == CursorColumnName) + if (targetCol.Name is CursorColumnName) { _startCursorDrag = true; - GoToFrame(TasView.CurrentCell.RowIndex.Value, false, false, true); + GoToFrame(frame, fromLua: false, fromRewinding: false, OnLeftMouseDown: true); } - else if (TasView.CurrentCell.Column.Name == FrameColumnName) + else if (targetCol.Name is FrameColumnName) { if (ModifierKeys == Keys.Alt && CurrentTasMovie.Markers.IsMarker(frame)) { @@ -610,7 +606,7 @@ private void TasView_MouseDown(object sender, MouseEventArgs e) _selectionDragState = TasView.IsRowSelected(frame); } } - else if (TasView.CurrentCell.Column.Type != ColumnType.Text) // User changed input + else if (targetCol.Type is not ColumnType.Text) // User changed input { _playbackInterrupted = !MainForm.EmulatorPaused; MainForm.PauseEmulator(); @@ -628,11 +624,11 @@ private void TasView_MouseDown(object sender, MouseEventArgs e) var altOrShift4State = ModifierKeys & (Keys.Alt | Keys.Shift); if (altOrShift4State is Keys.Alt || (applyPatternToPaintedInputToolStripMenuItem.Checked - && (!onlyOnAutoFireColumnsToolStripMenuItem.Checked || TasView.CurrentCell.Column.Emphasis))) + && (!onlyOnAutoFireColumnsToolStripMenuItem.Checked || targetCol.Emphasis))) { BoolPatterns[ControllerType.BoolButtons.IndexOf(buttonName)].Reset(); _patternPaint = true; - _startRow = TasView.CurrentCell.RowIndex.Value; + _startRow = frame; _boolPaintState = !CurrentTasMovie.BoolIsPressed(frame, buttonName); } else if (altOrShift4State is Keys.Shift) @@ -670,7 +666,7 @@ private void TasView_MouseDown(object sender, MouseEventArgs e) { CurrentTasMovie.ChangeLog.BeginNewBatch($"Paint Bool {buttonName} from frame {frame}"); - CurrentTasMovie.ToggleBoolState(TasView.CurrentCell.RowIndex.Value, buttonName); + CurrentTasMovie.ToggleBoolState(frame, buttonName); _boolPaintState = CurrentTasMovie.BoolIsPressed(frame, buttonName); _triggerAutoRestore = true; TastudioPlayMode(true); @@ -687,7 +683,7 @@ private void TasView_MouseDown(object sender, MouseEventArgs e) _axisPaintState = CurrentTasMovie.GetAxisState(frame, buttonName); if (applyPatternToPaintedInputToolStripMenuItem.Checked && (!onlyOnAutoFireColumnsToolStripMenuItem.Checked - || TasView.CurrentCell.Column.Emphasis)) + || targetCol.Emphasis)) { AxisPatterns[ControllerType.Axes.IndexOf(buttonName)].Reset(); CurrentTasMovie.SetAxisState(frame, buttonName, AxisPatterns[ControllerType.Axes.IndexOf(buttonName)].GetNextValue()); @@ -727,7 +723,7 @@ private void TasView_MouseDown(object sender, MouseEventArgs e) } else if (e.Button == MouseButtons.Right) { - if (TasView.CurrentCell.Column.Name == FrameColumnName && frame < CurrentTasMovie.InputLogLength) + if (targetCol.Name is FrameColumnName && frame < CurrentTasMovie.InputLogLength) { _rightClickControl = (ModifierKeys | Keys.Control) == ModifierKeys; _rightClickShift = (ModifierKeys | Keys.Shift) == ModifierKeys; @@ -908,14 +904,11 @@ private void TasView_MouseWheel(object sender, MouseEventArgs e) private void TasView_MouseDoubleClick(object sender, MouseEventArgs e) { - if (TasView.CurrentCell.Column == null) - { - return; - } + if (TasView.CurrentCell.Column is not { Name: var columnName }) return; if (e.Button == MouseButtons.Left) { - if (!AxisEditingMode && TasView.CurrentCell is { RowIndex: not null, Column.Name: FrameColumnName }) + if (!AxisEditingMode && TasView.CurrentCell.RowIndex is not null && columnName is FrameColumnName) { var existingMarker = CurrentTasMovie.Markers.FirstOrDefault(m => m.Frame == TasView.CurrentCell.RowIndex.Value); @@ -942,10 +935,9 @@ private void TasView_MouseDoubleClick(object sender, MouseEventArgs e) private void TasView_PointedCellChanged(object sender, InputRoll.CellEventArgs e) { - // TODO: If NewCell is null, it indicates that there was a mouse leave scenario, we may want to account for that - // For now return if a null because this happens OnEnter which doesn't have any of the below behaviors yet - if (e.OldCell?.Column == null || e.OldCell?.RowIndex == null - || e.NewCell?.Column == null || e.NewCell?.RowIndex == null) + toolTip1.SetToolTip(TasView, null); + + if (e.NewCell.RowIndex is null) { return; } @@ -957,7 +949,7 @@ private void TasView_PointedCellChanged(object sender, InputRoll.CellEventArgs e if (_paintingMinFrame >= 0) { - _paintingMinFrame = Math.Min(_paintingMinFrame, e.NewCell?.RowIndex ?? 0); + _paintingMinFrame = Math.Min(_paintingMinFrame, e.NewCell.RowIndex.Value); } // skip rerecord counting on drawing entirely, mouse down is enough @@ -967,7 +959,7 @@ private void TasView_PointedCellChanged(object sender, InputRoll.CellEventArgs e int startVal, endVal; int frame = e.NewCell.RowIndex.Value; - if (e.OldCell.RowIndex.Value < e.NewCell.RowIndex.Value) + if (e.OldCell.RowIndex < e.NewCell.RowIndex) { startVal = e.OldCell.RowIndex.Value; endVal = e.NewCell.RowIndex.Value; @@ -979,7 +971,7 @@ private void TasView_PointedCellChanged(object sender, InputRoll.CellEventArgs e else { startVal = e.NewCell.RowIndex.Value; - endVal = e.OldCell.RowIndex.Value; + endVal = e.OldCell.RowIndex ?? e.NewCell.RowIndex.Value; if(_patternPaint) { endVal = _startRow; @@ -994,7 +986,8 @@ private void TasView_PointedCellChanged(object sender, InputRoll.CellEventArgs e { for (var i = startVal; i <= endVal; i++) { - TasView.SelectRow(i, _selectionDragState); + if (!TasView.IsRowSelected(i)) + TasView.SelectRow(i, _selectionDragState); if (AxisEditingMode && (ModifierKeys == Keys.Control || ModifierKeys == Keys.Shift)) { if (_selectionDragState) @@ -1319,7 +1312,7 @@ public void EditAnalogProgrammatically(KeyEventArgs e) else if (e.KeyCode == Keys.OemMinus || e.KeyCode == Keys.Subtract) { _axisTypedValue = _axisTypedValue.StartsWith('-') - ? _axisTypedValue[1..] + ? _axisTypedValue.Substring(startIndex: 1) : $"-{_axisTypedValue}"; } else if (e.KeyCode == Keys.Back) @@ -1329,7 +1322,7 @@ public void EditAnalogProgrammatically(KeyEventArgs e) _axisTypedValue = value.ToString(NumberFormatInfo.InvariantInfo); } - _axisTypedValue = _axisTypedValue[..^1]; + _axisTypedValue = _axisTypedValue.Substring(startIndex: 0, length: _axisTypedValue.Length - 1); // drop last char if (_axisTypedValue == "" || _axisTypedValue == "-") { value = 0f; diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs index ea28187008b..7304fb8d4ac 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.MenuItems.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Linq; using System.Text; @@ -22,9 +21,6 @@ public partial class TAStudio private void FileSubMenu_DropDownOpened(object sender, EventArgs e) { - ToBk2MenuItem.Enabled = !string.IsNullOrWhiteSpace(CurrentTasMovie.Filename) - && CurrentTasMovie.Filename != DefaultTasProjName(); - saveSelectionToMacroToolStripMenuItem.Enabled = placeMacroAtSelectionToolStripMenuItem.Enabled = recentMacrosToolStripMenuItem.Enabled = @@ -50,7 +46,7 @@ private void StartNewProjectFromNowMenuItem_Click(object sender, EventArgs e) Emulator.Frame, StatableEmulator.CloneSavestate()); MainForm.PauseEmulator(); - LoadFile(new FileInfo(newProject.Filename), true); + LoadMovie(newProject, true); } } @@ -62,20 +58,14 @@ private void StartANewProjectFromSaveRamMenuItem_Click(object sender, EventArgs GoToFrame(TasView.AnyRowsSelected ? TasView.FirstSelectedRowIndex : 0); var newProject = CurrentTasMovie.ConvertToSaveRamAnchoredMovie(saveRam); MainForm.PauseEmulator(); - LoadFile(new FileInfo(newProject.Filename), true); + LoadMovie(newProject, true); } } private void RecentSubMenu_DropDownOpened(object sender, EventArgs e) => RecentSubMenu.ReplaceDropDownItems(Settings.RecentTas.RecentMenu(this, DummyLoadProject, "Project")); - private void NewTasMenuItem_Click(object sender, EventArgs e) - { - var prev = WantsToControlReboot; - WantsToControlReboot = false; - StartNewTasMovie(); - WantsToControlReboot = prev; - } + private void NewTasMenuItem_Click(object sender, EventArgs e) => StartNewTasMovie(); private void OpenTasMenuItem_Click(object sender, EventArgs e) { @@ -100,8 +90,7 @@ public bool LoadMovieFile(string filename, bool askToSave = true) if (askToSave && !AskSaveChanges()) return false; if (filename.EndsWithOrdinal(MovieService.TasMovieExtension)) { - LoadFileWithFallback(filename); - return true; //TODO should this return false if it fell back to a new project? + return LoadFileWithFallback(filename); } if (filename.EndsWithOrdinal(MovieService.StandardMovieExtension)) { @@ -113,18 +102,8 @@ public bool LoadMovieFile(string filename, bool askToSave = true) { return false; } - _initializing = true; // Starting a new movie causes a core reboot - WantsToControlReboot = false; - _engaged = false; - MainForm.StartNewMovie(MovieSession.Get(filename), false); - ConvertCurrentMovieToTasproj(); - _initializing = false; - var success = StartNewMovieWrapper(CurrentTasMovie); - _engaged = true; - WantsToControlReboot = true; - SetUpColumns(); - UpdateWindowTitle(); - return success; //TODO is this correct? + + return LoadFileWithFallback(filename); } DialogController.ShowMessageBox( caption: "Movie load error", @@ -255,48 +234,45 @@ private void RecentMacrosMenuItem_DropDownOpened(object sender, EventArgs e) private void ToBk2MenuItem_Click(object sender, EventArgs e) { + // TODO: can we deduplicate this logic somehow? The same code with minimal changes is copy pasted like 4 times _autosaveTimer.Stop(); - - if (Emulator is Emulation.Cores.Nintendo.SubNESHawk.SubNESHawk - || Emulator is Emulation.Cores.Nintendo.Gameboy.Gameboy - || Emulator is Emulation.Cores.Nintendo.SubGBHawk.SubGBHawk) + + if (Emulator.HasCycleTiming()) { DialogController.ShowMessageBox("This core requires emulation to be on the last frame when writing the movie, otherwise movie length will appear incorrect.\nTAStudio can't handle this, so Export BK2, play it to the end, and then Save Movie.", "Warning", EMsgBoxIcon.Warning); } - var bk2 = CurrentTasMovie.ToBk2(); - MessageStatusLabel.Text = "Exporting to .bk2..."; - Cursor = Cursors.WaitCursor; - Update(); - string exportResult = " not exported."; - var file = new FileInfo(bk2.Filename); - if (file.Exists) - { - var result = MainForm.DoWithTempMute(() => MessageBox.Show( - "Overwrite Existing File?", - "Tastudio", - MessageBoxButtons.YesNoCancel, - MessageBoxIcon.Question, - MessageBoxDefaultButton.Button3)); - if (result == DialogResult.Yes) - { - bk2.Save(); - exportResult = " exported."; - } + string filename = CurrentTasMovie.Filename; + if (string.IsNullOrWhiteSpace(filename) || filename == DefaultTasProjName()) + { + filename = SuggestedTasProjName(); } - else + + var fileInfo = new FileInfo(Path.ChangeExtension(filename, Bk2Movie.Extension)); + if (fileInfo.Exists) { + fileInfo = SaveFileDialog(currentFile: fileInfo.Name, path: Config!.PathEntries.MovieAbsolutePath(), new FilesystemFilterSet(FilesystemFilter.BizHawkMovies), this); + } + + if (fileInfo is not null) + { + MessageStatusLabel.Text = "Exporting to .bk2..."; + Cursor = Cursors.WaitCursor; + var bk2 = CurrentTasMovie.ToBk2(); + bk2.Filename = fileInfo.FullName; bk2.Save(); - exportResult = " exported."; + MessageStatusLabel.Text = $"{bk2.Name} exported."; + Cursor = Cursors.Default; + } + else + { + MessageStatusLabel.Text = "bk2 export cancelled."; } if (Settings.AutosaveInterval > 0) { _autosaveTimer.Start(); } - - MessageStatusLabel.Text = bk2.Name + exportResult; - Cursor = Cursors.Default; } private void EditSubMenu_DropDownOpened(object sender, EventArgs e) @@ -468,7 +444,7 @@ private void PasteMenuItem_Click(object sender, EventArgs e) { _tasClipboard.Clear(); int linesToPaste = lines.Length; - if (lines[^1] == "") linesToPaste--; + if (lines[lines.Length - 1].Length is 0) linesToPaste--; for (int i = 0; i < linesToPaste; i++) { var line = ControllerFromMnemonicStr(lines[i]); @@ -510,7 +486,7 @@ private void PasteInsertMenuItem_Click(object sender, EventArgs e) { _tasClipboard.Clear(); int linesToPaste = lines.Length; - if (lines[^1] == "") linesToPaste--; + if (lines[lines.Length - 1].Length is 0) linesToPaste--; for (int i = 0; i < linesToPaste; i++) { var line = ControllerFromMnemonicStr(lines[i]); @@ -892,9 +868,7 @@ private void SetSeekingCutoffIntervalMenuItem_Click(object sender, EventArgs e) } private void CopyIncludesFrameNoMenuItem_Click(object sender, EventArgs e) - { - Settings.CopyIncludesFrameNo ^= true; - } + => Settings.CopyIncludesFrameNo = !Settings.CopyIncludesFrameNo; private void SetAutosaveIntervalMenuItem_Click(object sender, EventArgs e) { @@ -919,19 +893,13 @@ private void SetAutosaveIntervalMenuItem_Click(object sender, EventArgs e) } private void AutosaveAsBk2MenuItem_Click(object sender, EventArgs e) - { - Settings.AutosaveAsBk2 ^= true; - } + => Settings.AutosaveAsBk2 = !Settings.AutosaveAsBk2; private void AutosaveAsBackupFileMenuItem_Click(object sender, EventArgs e) - { - Settings.AutosaveAsBackupFile ^= true; - } + => Settings.AutosaveAsBackupFile = !Settings.AutosaveAsBackupFile; private void BackupPerFileSaveMenuItem_Click(object sender, EventArgs e) - { - Settings.BackupPerFileSave ^= true; - } + => Settings.BackupPerFileSave = !Settings.BackupPerFileSave; private void ApplyPatternToPaintedInputMenuItem_CheckedChanged(object sender, EventArgs e) { @@ -939,9 +907,7 @@ private void ApplyPatternToPaintedInputMenuItem_CheckedChanged(object sender, Ev } private void SingleClickAxisEditMenuItem_Click(object sender, EventArgs e) - { - Settings.SingleClickAxisEdit ^= true; - } + => Settings.SingleClickAxisEdit = !Settings.SingleClickAxisEdit; private void BindMarkersToInputMenuItem_Click(object sender, EventArgs e) { @@ -949,14 +915,10 @@ private void BindMarkersToInputMenuItem_Click(object sender, EventArgs e) } private void EmptyNewMarkerNotesMenuItem_Click(object sender, EventArgs e) - { - Settings.EmptyMarkers ^= true; - } + => Settings.EmptyMarkers = !Settings.EmptyMarkers; private void AutoPauseAtEndMenuItem_Click(object sender, EventArgs e) - { - Settings.AutoPause ^= true; - } + => Settings.AutoPause = !Settings.AutoPause; private void AutoHoldMenuItem_CheckedChanged(object sender, EventArgs e) { @@ -1009,14 +971,10 @@ private void SetCustomsMenuItem_Click(object sender, EventArgs e) } private void OldControlSchemeForBranchesMenuItem_Click(object sender, EventArgs e) - { - Settings.OldControlSchemeForBranches ^= true; - } + => Settings.OldControlSchemeForBranches = !Settings.OldControlSchemeForBranches; private void LoadBranchOnDoubleClickMenuItem_Click(object sender, EventArgs e) - { - Settings.LoadBranchOnDoubleClick ^= true; - } + => Settings.LoadBranchOnDoubleClick = !Settings.LoadBranchOnDoubleClick; private void HeaderMenuItem_Click(object sender, EventArgs e) { @@ -1114,7 +1072,7 @@ private void FollowCursorMenuItem_DropDownOpened(object sender, EventArgs e) private void RotateMenuItem_Click(object sender, EventArgs e) { - TasView.HorizontalOrientation ^= true; + TasView.HorizontalOrientation = !TasView.HorizontalOrientation; CurrentTasMovie.FlagChanges(); } @@ -1126,9 +1084,7 @@ private void HideLagFramesX_Click(object sender, EventArgs e) } private void HideWasLagFramesMenuItem_Click(object sender, EventArgs e) - { - TasView.HideWasLagFrames ^= true; - } + => TasView.HideWasLagFrames = !TasView.HideWasLagFrames; private void AlwaysScrollMenuItem_Click(object sender, EventArgs e) { @@ -1311,7 +1267,7 @@ private void SetUpToolStripColumns() { foreach (ToolStripMenuItem menuItem in dummyObject1.DropDownItems) { - menuItem.Checked ^= true; + menuItem.Checked = !menuItem.Checked; } CurrentTasMovie.FlagChanges(); diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Navigation.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Navigation.cs index ac0cf5d8a8d..f86bf776b9e 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Navigation.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Navigation.cs @@ -59,7 +59,7 @@ public void GoToFrame(int frame, bool fromLua = false, bool fromRewinding = fals var lastState = GetPriorStateForFramebuffer(frame); if (lastState.Key > Emulator.Frame) { - LoadState(lastState); + LoadState(lastState, true); } StartSeeking(frame); diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs index 6d92f56d58d..d6b98e77660 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.IO; @@ -153,6 +152,13 @@ public TAStudio() BookMarkControl.SavedCallback = BranchSaved; BookMarkControl.RemovedCallback = BranchRemoved; TasView.MouseLeave += TAStudio_MouseLeave; + TasView.CellHovered += (_, e) => + { + if (e.NewCell.RowIndex is null) + { + toolTip1.Show(e.NewCell.Column!.Name, TasView, PointToClient(Cursor.Position)); + } + }; } private void Tastudio_Load(object sender, EventArgs e) @@ -204,11 +210,7 @@ private void Tastudio_Load(object sender, EventArgs e) private void LoadMostRecentOrStartNew() { - if (!LoadFile(new(Settings.RecentTas.MostRecent))) - { - TasView.AllColumns.Clear(); - StartNewTasMovie(); - } + LoadFileWithFallback(Settings.RecentTas.MostRecent); } private bool Engage() @@ -255,7 +257,7 @@ private bool Engage() // Start Scenario 2: A tasproj is already active else if (MovieSession.Movie.IsActive() && MovieSession.Movie is ITasMovie) { - bool result = LoadFile(new FileInfo(CurrentTasMovie.Filename), gotoFrame: Emulator.Frame); + bool result = LoadMovie(CurrentTasMovie, gotoFrame: Emulator.Frame); if (!result) { TasView.AllColumns.Clear(); @@ -285,7 +287,6 @@ private bool Engage() MainForm.AddOnScreenMessage("TAStudio engaged"); SetTasMovieCallbacks(CurrentTasMovie); UpdateWindowTitle(); - MainForm.RelinquishControl(this); _originalEndAction = Config.Movies.MovieEndAction; MainForm.DisableRewind(); Config.Movies.MovieEndAction = MovieEndAction.Record; @@ -449,17 +450,16 @@ private void SetupBoolPatterns() BoolPatterns[i] = new AutoPatternBool(1, 1); } - BoolPatterns[^2] = new AutoPatternBool(1, 0); - BoolPatterns[^1] = new AutoPatternBool( - Config.AutofireOn, Config.AutofireOff); + BoolPatterns[BoolPatterns.Length - 2] = new(1, 0); + BoolPatterns[BoolPatterns.Length - 1] = new(Config.AutofireOn, Config.AutofireOff); for (int i = fStart; i < AxisPatterns.Length - 2; i++) { AxisPatterns[i] = new AutoPatternAxis(new[] { 1 }); } - AxisPatterns[^2] = new AutoPatternAxis(new[] { 1 }); - AxisPatterns[^1] = new AutoPatternAxis(1, Config.AutofireOn, 0, Config.AutofireOff); + AxisPatterns[AxisPatterns.Length - 2] = new([ 1 ]); + AxisPatterns[AxisPatterns.Length - 1] = new(1, Config.AutofireOn, 0, Config.AutofireOff); SetUpToolStripColumns(); } @@ -521,26 +521,18 @@ private void ConvertCurrentMovieToTasproj() CurrentTasMovie.PropertyChanged += TasMovie_OnPropertyChanged; } - private bool LoadFile(FileInfo file, bool startsFromSavestate = false, int gotoFrame = 0) + private bool LoadMovie(ITasMovie tasMovie, bool startsFromSavestate = false, int gotoFrame = 0) { - if (!file.Exists) - { - Settings.RecentTas.HandleLoadError(MainForm, file.FullName); - return false; - } - _engaged = false; - var newMovie = (ITasMovie)MovieSession.Get(file.FullName); - newMovie.BindMarkersToInput = Settings.BindMarkersToInput; - newMovie.GreenzoneInvalidated = GreenzoneInvalidated; + tasMovie.BindMarkersToInput = Settings.BindMarkersToInput; + tasMovie.GreenzoneInvalidated = GreenzoneInvalidated; - if (!HandleMovieLoadStuff(newMovie)) + if (!HandleMovieLoadStuff(tasMovie)) { return false; } _engaged = true; - Settings.RecentTas.Add(newMovie.Filename); // only add if it did load if (startsFromSavestate) { @@ -566,7 +558,6 @@ private bool LoadFile(FileInfo file, bool startsFromSavestate = false, int gotoF SetUpToolStripColumns(); CurrentTasMovie.PropertyChanged += TasMovie_OnPropertyChanged; - CurrentTasMovie.Branches.Current = CurrentTasMovie.TasSession.CurrentBranch; BookMarkControl.UpdateTextColumnWidth(); MarkerControl.UpdateTextColumnWidth(); // clear all selections @@ -603,14 +594,8 @@ private void StartNewTasMovie() Config.DefaultAuthor); SetTasMovieCallbacks(tasMovie); - MovieSession.SetMovieController(Emulator.ControllerDefinition); // hack, see interface comment - tasMovie.ClearChanges(); // Don't ask to save changes here. - tasMovie.Save(); + tasMovie.ClearChanges(); _ = HandleMovieLoadStuff(tasMovie); - // let's not keep this longer than we actually need - // the user will be prompted to enter a proper name - // when they want to save - File.Delete(tasMovie.Filename); // clear all selections TasView.DeselectAll(); @@ -624,7 +609,6 @@ private void StartNewTasMovie() private bool HandleMovieLoadStuff(ITasMovie movie) { WantsToControlStopMovie = false; - WantsToControlReboot = false; var result = StartNewMovieWrapper(movie); if (!result) @@ -633,10 +617,8 @@ private bool HandleMovieLoadStuff(ITasMovie movie) } WantsToControlStopMovie = true; - WantsToControlReboot = true; CurrentTasMovie.ChangeLog.Clear(); - CurrentTasMovie.ClearChanges(); UpdateWindowTitle(); MessageStatusLabel.Text = $"{Path.GetFileName(CurrentTasMovie.Filename)} loaded."; @@ -673,16 +655,35 @@ private void DummyLoadProject(string path) } } - private void LoadFileWithFallback(string path) + private bool LoadFileWithFallback(string path) { - var result = LoadFile(new FileInfo(path)); - if (!result) + bool movieLoadSucceeded = false; + + if (!File.Exists(path)) + { + Settings.RecentTas.HandleLoadError(MainForm, path); + } + else + { + var movie = MovieSession.Get(path, loadMovie: false); + // we can't load the movie yet, we need to set the callbacks first... + if (movie is ITasMovie pendingTasMovie) + { + SetTasMovieCallbacks(pendingTasMovie); + } + + movie.Load(); + var tasMovie = movie as ITasMovie ?? movie.ToTasMovie(); + movieLoadSucceeded = LoadMovie(tasMovie); + } + + if (!movieLoadSucceeded) { - TasView.AllColumns.Clear(); - WantsToControlReboot = false; StartNewTasMovie(); _engaged = true; } + + return movieLoadSucceeded; } private void DummyLoadMacro(string path) @@ -701,7 +702,7 @@ private void DummyLoadMacro(string path) private void TastudioToggleReadOnly() { - TasPlaybackBox.RecordingMode ^= true; + TasPlaybackBox.RecordingMode = !TasPlaybackBox.RecordingMode; WasRecording = TasPlaybackBox.RecordingMode; // hard reset at manual click and hotkey } @@ -737,8 +738,8 @@ private void Disengage() _engaged = false; MainForm.PauseOnFrame = null; MainForm.AddOnScreenMessage("TAStudio disengaged"); - MainForm.TakeBackControl(); Config.Movies.MovieEndAction = _originalEndAction; + WantsToControlRewind = false; MainForm.EnableRewind(true); MainForm.SetMainformMovieInfo(); } @@ -885,6 +886,14 @@ public void RefreshDialog(bool refreshTasView = true, bool refreshBranches = tru } } + public void RefreshForInputChange(int firstChangedFrame) + { + if (TasView.IsPartiallyVisible(firstChangedFrame) || firstChangedFrame < TasView.FirstVisibleRow) + { + RefreshDialog(); + } + } + private void SetTasViewRowCount() { TasView.RowCount = CurrentTasMovie.InputLogLength + 1; @@ -933,14 +942,14 @@ private void StartAtNearestFrameAndEmulate(int frame, bool fromLua, bool fromRew var closestState = GetPriorStateForFramebuffer(frame); if (closestState.Value.Length > 0 && (frame < Emulator.Frame || closestState.Key > Emulator.Frame)) { - LoadState(closestState); + LoadState(closestState, true); } closestState.Value.Dispose(); if (fromLua) { bool wasPaused = MainForm.EmulatorPaused; - + // why not use this? because I'm not letting the form freely run. it all has to be under this loop. // i could use this and then poll StepRunLoop_Core() repeatedly, but.. that's basically what I'm doing // PauseOnFrame = frame; @@ -981,7 +990,7 @@ private void StartAtNearestFrameAndEmulate(int frame, bool fromLua, bool fromRew } } - public void LoadState(KeyValuePair state) + public void LoadState(KeyValuePair state, bool discardApiHawkSurfaces = false) { StatableEmulator.LoadStateBinary(new BinaryReader(state.Value)); @@ -991,6 +1000,10 @@ public void LoadState(KeyValuePair state) } UpdateTools(); + if (discardApiHawkSurfaces) + { + DisplayManager.DiscardApiHawkSurfaces(); + } } public void AddBranchExternal() => BookMarkControl.AddBranchExternal(); @@ -1056,7 +1069,7 @@ public void InsertNumFrames(int insertionFrame, int numberOfFrames) } else { - RefreshDialog(); + RefreshForInputChange(insertionFrame); } } } @@ -1077,7 +1090,7 @@ public void DeleteFrames(int beginningFrame, int numberOfFrames) } else { - RefreshDialog(); + RefreshForInputChange(beginningFrame); } } } @@ -1092,7 +1105,7 @@ public void ClearFrames(int beginningFrame, int numberOfFrames) { CurrentTasMovie.ClearFrame(i); } - + if (needsToRollback) { GoToLastEmulatedFrameIfNecessary(beginningFrame); @@ -1100,7 +1113,7 @@ public void ClearFrames(int beginningFrame, int numberOfFrames) } else { - RefreshDialog(); + RefreshForInputChange(beginningFrame); } } } @@ -1148,6 +1161,7 @@ private void TAStudio_DragDrop(object sender, DragEventArgs e) private void TAStudio_MouseLeave(object sender, EventArgs e) { + toolTip1.SetToolTip(TasView, null); DoTriggeredAutoRestoreIfNeeded(); } diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.resx b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.resx index 13e8b473992..2de40e63762 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.resx +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.resx @@ -126,4 +126,7 @@ 249, 17 + + 388, 17 + \ No newline at end of file diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudioColorSettingsForm.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudioColorSettingsForm.cs index fe1ba124803..8b36a18cda3 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudioColorSettingsForm.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudioColorSettingsForm.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/UndoHistoryForm.Designer.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/UndoHistoryForm.Designer.cs index ef20a8fdadb..39a8adb9a1d 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/UndoHistoryForm.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/UndoHistoryForm.Designer.cs @@ -40,7 +40,7 @@ private void InitializeComponent() this.AutoScrollCheck = new System.Windows.Forms.CheckBox(); this.MaxStepsNum = new System.Windows.Forms.NumericUpDown(); this.label1 = new BizHawk.WinForms.Controls.LocLabelEx(); - this.HistoryView = new InputRoll(); + this.HistoryView = new BizHawk.Client.EmuHawk.InputRoll(); this.RightClickMenu.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.MaxStepsNum)).BeginInit(); this.SuspendLayout(); @@ -149,21 +149,28 @@ private void InitializeComponent() // // HistoryView // + this.HistoryView.AllowColumnReorder = false; + this.HistoryView.AllowColumnResize = false; + this.HistoryView.AlwaysScroll = false; this.HistoryView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.HistoryView.RowCount = 0; + this.HistoryView.CellHeightPadding = 0; + this.HistoryView.CellWidthPadding = 0; + this.HistoryView.FullRowSelect = true; + this.HistoryView.HorizontalOrientation = false; + this.HistoryView.LetKeysModifySelection = false; this.HistoryView.Location = new System.Drawing.Point(10, 10); this.HistoryView.MultiSelect = false; this.HistoryView.Name = "HistoryView"; + this.HistoryView.RowCount = 0; + this.HistoryView.ScrollSpeed = 0; + this.HistoryView.SeekingCutoffInterval = 0; this.HistoryView.Size = new System.Drawing.Size(369, 213); this.HistoryView.TabIndex = 2; this.HistoryView.DoubleClick += new System.EventHandler(this.HistoryView_DoubleClick); this.HistoryView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.HistoryView_MouseDown); this.HistoryView.MouseUp += new System.Windows.Forms.MouseEventHandler(this.HistoryView_MouseUp); - this.HistoryView.AllowColumnReorder = false; - this.HistoryView.AllowColumnResize = false; - this.HistoryView.FullRowSelect = true; // // UndoHistoryForm // diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/UndoHistoryForm.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/UndoHistoryForm.cs index 7b7cc8b0e75..0d048a4eebb 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/UndoHistoryForm.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/UndoHistoryForm.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/tools/TI83/TI83KeyPad.cs b/src/BizHawk.Client.EmuHawk/tools/TI83/TI83KeyPad.cs index abde7acedd0..7facceb6e13 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TI83/TI83KeyPad.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TI83/TI83KeyPad.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using BizHawk.Client.Common; @@ -115,8 +114,7 @@ private void OptionsSubMenu_DropDownOpened(object sender, EventArgs e) private void ShowHotkeysMenuItem_Click(object sender, EventArgs e) { - TI83ToolTips ^= true; - + TI83ToolTips = !TI83ToolTips; if (TI83ToolTips) { SetToolTips(); diff --git a/src/BizHawk.Client.EmuHawk/tools/ToolBox.cs b/src/BizHawk.Client.EmuHawk/tools/ToolBox.cs index ebdb1452023..09223503fd6 100644 --- a/src/BizHawk.Client.EmuHawk/tools/ToolBox.cs +++ b/src/BizHawk.Client.EmuHawk/tools/ToolBox.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/tools/ToolFormBase.cs b/src/BizHawk.Client.EmuHawk/tools/ToolFormBase.cs index 5916ae9ec75..810db9f53dc 100644 --- a/src/BizHawk.Client.EmuHawk/tools/ToolFormBase.cs +++ b/src/BizHawk.Client.EmuHawk/tools/ToolFormBase.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/tools/ToolManager.cs b/src/BizHawk.Client.EmuHawk/tools/ToolManager.cs index af79645601d..0d34bfa7286 100644 --- a/src/BizHawk.Client.EmuHawk/tools/ToolManager.cs +++ b/src/BizHawk.Client.EmuHawk/tools/ToolManager.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Globalization; @@ -473,6 +472,24 @@ public IToolForm Get() where T : class, IToolForm return Load(false); } + /// + /// Returns the first tool of type that fulfills the given condition + /// + /// The condition to check for + /// Type of tools to check + public T FirstOrNull(Predicate condition) where T : class + { + foreach (var tool in _tools) // not bothering to copy here since `condition` is expected to have no side-effects + { + if (tool.IsActive && tool is T specialTool && condition(specialTool)) + { + return specialTool; + } + } + + return null; + } + /// /// returns the instance of , regardless of whether it's loaded,
/// but doesn't create and load a new instance if it's not found @@ -482,7 +499,7 @@ public IToolForm Get() where T : class, IToolForm /// you may pass any class or interface /// public IToolForm/*?*/ LazyGet(Type toolType) - => _tools.Find(t => toolType.IsAssignableFrom(t.GetType())); + => _tools.Find(toolType.IsInstanceOfType); internal static readonly IDictionary IconAndNameCache = new Dictionary { @@ -577,7 +594,7 @@ public void Restart(Config config, IEmulator emulator, IGameInfo game) var unavailable = new List(); - foreach (var tool in _tools) + foreach (var tool in _tools.ToArray()) // copy because a tool may open another { SetBaseProperties(tool); if (ServiceInjector.UpdateServices(_emulator.ServiceProvider, tool) @@ -616,9 +633,7 @@ public bool AskSave() return true; } - return _tools - .Select(tool => tool.AskSaveChanges()) - .All(result => result); + return _tools.TrueForAll(tool => !tool.IsActive || tool.AskSaveChanges()); } /// @@ -647,8 +662,19 @@ public void Close(Type toolType) public void Close() { - _tools.ForEach(t => t.Close()); + var toolsCopy = _tools.ToArray(); _tools.Clear(); + foreach (var t in toolsCopy) + { + try + { + t.Close(); + } + catch (Exception e) + { + Console.WriteLine($"caught while calling Form.Close on tool: {e}"); + } + } } /// @@ -722,7 +748,7 @@ private IToolForm CreateInstance(Type toolType, string dllPath, string toolTypeN public void UpdateToolsBefore() { - foreach (var tool in _tools) + foreach (var tool in _tools.ToArray()) // copy because a tool may open another { if (tool.IsActive) { @@ -733,7 +759,7 @@ public void UpdateToolsBefore() public void UpdateToolsAfter() { - foreach (var tool in _tools) + foreach (var tool in _tools.ToArray()) // copy because a tool may open another { if (tool.IsActive) { @@ -744,7 +770,7 @@ public void UpdateToolsAfter() public void FastUpdateBefore() { - foreach (var tool in _tools) + foreach (var tool in _tools.ToArray()) // copy because a tool may open another { if (tool.IsActive) { @@ -755,7 +781,7 @@ public void FastUpdateBefore() public void FastUpdateAfter() { - foreach (var tool in _tools) + foreach (var tool in _tools.ToArray()) // copy because a tool may open another { if (tool.IsActive) { @@ -850,7 +876,7 @@ public string GenerateDefaultCheatFilename() var path = _config.PathEntries.CheatsAbsolutePath(_game.System); var f = new FileInfo(path); - if (f.Directory != null && f.Directory.Exists == false) + if (f.Directory != null && !f.Directory.Exists) { f.Directory.Create(); } diff --git a/src/BizHawk.Client.EmuHawk/tools/TraceLogger.Designer.cs b/src/BizHawk.Client.EmuHawk/tools/TraceLogger.Designer.cs index d38cba1a8cd..f8d3181d1f3 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TraceLogger.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TraceLogger.Designer.cs @@ -32,12 +32,12 @@ private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.TracerBox = new System.Windows.Forms.GroupBox(); - this.TraceView = new InputRoll(); + this.TraceView = new BizHawk.Client.EmuHawk.InputRoll(); this.TraceContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); this.CopyContextMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.SelectAllContextMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.ClearContextMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.menuStrip1 = new MenuStripEx(); + this.menuStrip1 = new BizHawk.WinForms.Controls.MenuStripEx(); this.FileSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.SaveLogMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.EditSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -46,6 +46,7 @@ private void InitializeComponent() this.ClearMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.OptionsSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.MaxLinesMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.SegmentSizeMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.groupBox2 = new System.Windows.Forms.GroupBox(); this.OpenLogFile = new System.Windows.Forms.Button(); this.BrowseBox = new System.Windows.Forms.Button(); @@ -53,7 +54,6 @@ private void InitializeComponent() this.ToFileRadio = new System.Windows.Forms.RadioButton(); this.ToWindowRadio = new System.Windows.Forms.RadioButton(); this.LoggingEnabled = new System.Windows.Forms.CheckBox(); - this.SegmentSizeMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.TracerBox.SuspendLayout(); this.TraceContextMenu.SuspendLayout(); this.menuStrip1.SuspendLayout(); @@ -75,21 +75,27 @@ private void InitializeComponent() // // TraceView // + this.TraceView.AllowColumnReorder = false; + this.TraceView.AllowColumnResize = true; + this.TraceView.AlwaysScroll = false; this.TraceView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); + this.TraceView.CellHeightPadding = 0; + this.TraceView.CellWidthPadding = 0; this.TraceView.ContextMenuStrip = this.TraceContextMenu; this.TraceView.Font = new System.Drawing.Font("Courier New", 8F); this.TraceView.FullRowSelect = true; - this.TraceView.GridLines = true; - this.TraceView.RowCount = 0; + this.TraceView.HorizontalOrientation = false; + this.TraceView.LetKeysModifySelection = false; this.TraceView.Location = new System.Drawing.Point(8, 18); this.TraceView.Name = "TraceView"; + this.TraceView.RowCount = 0; + this.TraceView.ScrollSpeed = 0; + this.TraceView.SeekingCutoffInterval = 0; this.TraceView.Size = new System.Drawing.Size(603, 414); this.TraceView.TabIndex = 4; this.TraceView.TabStop = false; - this.TraceView.AllowColumnResize = true; - this.TraceView.AllowColumnReorder = false; // // TraceContextMenu // @@ -175,6 +181,11 @@ private void InitializeComponent() this.MaxLinesMenuItem.Text = "&Set Max Lines..."; this.MaxLinesMenuItem.Click += new System.EventHandler(this.MaxLinesMenuItem_Click); // + // SegmentSizeMenuItem + // + this.SegmentSizeMenuItem.Text = "Set Segment Size..."; + this.SegmentSizeMenuItem.Click += new System.EventHandler(this.SegmentSizeMenuItem_Click); + // // groupBox2 // this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) @@ -262,11 +273,6 @@ private void InitializeComponent() this.LoggingEnabled.UseVisualStyleBackColor = true; this.LoggingEnabled.CheckedChanged += new System.EventHandler(this.LoggingEnabled_CheckedChanged); // - // SegmentSizeMenuItem - // - this.SegmentSizeMenuItem.Text = "Set Segment Size..."; - this.SegmentSizeMenuItem.Click += new System.EventHandler(this.SegmentSizeMenuItem_Click); - // // TraceLogger // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); diff --git a/src/BizHawk.Client.EmuHawk/tools/TraceLogger.cs b/src/BizHawk.Client.EmuHawk/tools/TraceLogger.cs index f8eb6a11e91..932b71b065f 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TraceLogger.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TraceLogger.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; diff --git a/src/BizHawk.Client.EmuHawk/tools/VirtualPads/VirtualPad.cs b/src/BizHawk.Client.EmuHawk/tools/VirtualPads/VirtualPad.cs index 3104ab2cf44..ae9b254f698 100644 --- a/src/BizHawk.Client.EmuHawk/tools/VirtualPads/VirtualPad.cs +++ b/src/BizHawk.Client.EmuHawk/tools/VirtualPads/VirtualPad.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/tools/VirtualPads/VirtualpadsTool.cs b/src/BizHawk.Client.EmuHawk/tools/VirtualPads/VirtualpadsTool.cs index d4969112b6c..06a05a219db 100644 --- a/src/BizHawk.Client.EmuHawk/tools/VirtualPads/VirtualpadsTool.cs +++ b/src/BizHawk.Client.EmuHawk/tools/VirtualPads/VirtualpadsTool.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -225,9 +224,7 @@ private void ClearAllMenuItem_Click(object sender, EventArgs e) } private void StickyMenuItem_Click(object sender, EventArgs e) - { - StickyPads ^= true; - } + => StickyPads = !StickyPads; private void PadBoxContextMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e) { @@ -245,8 +242,6 @@ private void OptionsSubMenu_DropDownOpened(object sender, EventArgs e) } private void ClearClearsAnalogInputMenuItem_Click(object sender, EventArgs e) - { - ClearAlsoClearsAnalog ^= true; - } + => ClearAlsoClearsAnalog = !ClearAlsoClearsAnalog; } } diff --git a/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadAnalogButton.cs b/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadAnalogButton.cs index 36e2e7fab5e..e5f3fc4deeb 100644 --- a/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadAnalogButton.cs +++ b/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadAnalogButton.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadAnalogStick.cs b/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadAnalogStick.cs index 76baba50fb5..a7c1ed973fa 100644 --- a/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadAnalogStick.cs +++ b/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadAnalogStick.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Windows.Forms; using BizHawk.Emulation.Common; @@ -101,7 +100,7 @@ void UnsetLastFocusedNUD(object sender, EventArgs eventArgs) _inputManager.StickyXorAdapter, name, RangeX, - !string.IsNullOrEmpty(secondaryName) ? secondaryName : Name.Replace("X", "Y"), + string.IsNullOrEmpty(secondaryName) ? Name.Replace('X', 'Y') : secondaryName, RangeY ); diff --git a/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadButton.cs b/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadButton.cs index 72c7eced5fe..7d620da1a41 100644 --- a/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadButton.cs +++ b/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadButton.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using System.Drawing; @@ -83,7 +82,7 @@ protected override void WndProc(ref Message m) if (!ReadOnly) { RightClicked = true; - Checked ^= true; + Checked = !Checked; } return; case 0x0205: // WM_RBUTTONUP @@ -136,7 +135,7 @@ protected override void OnCheckedChanged(EventArgs e) { InputManager.AutofireStickyXorAdapter.SetSticky(Name, Checked); - if (Checked == false) + if (!Checked) { Clear(); } @@ -145,7 +144,7 @@ protected override void OnCheckedChanged(EventArgs e) { InputManager.StickyXorAdapter.SetSticky(Name, Checked); - if (Checked == false) + if (!Checked) { Clear(); } diff --git a/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadDiscManager.cs b/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadDiscManager.cs index 13516d0fd4e..ed467df4bb6 100644 --- a/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadDiscManager.cs +++ b/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadDiscManager.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Windows.Forms; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadTargetScreen.cs b/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadTargetScreen.cs index 6f29e3ee88f..26130f31f4c 100644 --- a/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadTargetScreen.cs +++ b/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/VirtualPadTargetScreen.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using System.Windows.Forms; using BizHawk.Client.Common; diff --git a/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/components/AnalogStickPanel.cs b/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/components/AnalogStickPanel.cs index 40d6d1d638e..84f26da6ac8 100644 --- a/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/components/AnalogStickPanel.cs +++ b/src/BizHawk.Client.EmuHawk/tools/VirtualPads/controls/components/AnalogStickPanel.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; @@ -108,6 +107,7 @@ private void Rerange() /// min + (max - i) == max - (i - min) == min + max - i /// private int MaybeReversedInX(int i) => _reverseX ? _rangeX.Start + _rangeX.EndInclusive - i : i; + /// private int MaybeReversedInY(int i) => _reverseY ? i : _rangeY.Start + _rangeY.EndInclusive - i; diff --git a/src/BizHawk.Client.EmuHawk/tools/Watch/RamPoke.cs b/src/BizHawk.Client.EmuHawk/tools/Watch/RamPoke.cs index eebd9a43472..5d6847c9012 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Watch/RamPoke.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Watch/RamPoke.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Client.EmuHawk/tools/Watch/RamSearch.Designer.cs b/src/BizHawk.Client.EmuHawk/tools/Watch/RamSearch.Designer.cs index 48569a72780..c3b22d4f262 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Watch/RamSearch.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Watch/RamSearch.Designer.cs @@ -31,8 +31,9 @@ protected override void Dispose(bool disposing) private void InitializeComponent() { this.components = new System.ComponentModel.Container(); + this.SearchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.TotalSearchLabel = new BizHawk.WinForms.Controls.LocLabelEx(); - this.WatchListView = new InputRoll(); + this.WatchListView = new BizHawk.Client.EmuHawk.InputRoll(); this.ListViewContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); this.DoSearchContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.NewSearchContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -46,7 +47,7 @@ private void InitializeComponent() this.ViewInHexEditorContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.ContextMenuSeparator3 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.ClearPreviewContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.RamSearchMenu = new MenuStripEx(); + this.RamSearchMenu = new BizHawk.WinForms.Controls.MenuStripEx(); this.fileToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.OpenMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.SaveMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -71,7 +72,6 @@ private void InitializeComponent() this.DisplayTypeSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.toolStripSeparator1 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.DefinePreviousValueSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.Previous_LastSearchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.PreviousFrameMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.Previous_OriginalMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.Previous_LastChangeMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -88,6 +88,7 @@ private void InitializeComponent() this.AddToRamWatchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.PokeAddressMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.FreezeAddressMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.SelectAllMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.toolStripSeparator13 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.ClearUndoMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.SettingsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); @@ -111,7 +112,7 @@ private void InitializeComponent() this.SpecificAddressRadio = new System.Windows.Forms.RadioButton(); this.SpecificValueRadio = new System.Windows.Forms.RadioButton(); this.PreviousValueRadio = new System.Windows.Forms.RadioButton(); - this.toolStrip1 = new ToolStripEx(); + this.toolStrip1 = new BizHawk.WinForms.Controls.ToolStripEx(); this.DoSearchToolButton = new System.Windows.Forms.ToolStripButton(); this.toolStripSeparator10 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); this.NewSearchToolButton = new System.Windows.Forms.ToolStripButton(); @@ -143,8 +144,6 @@ private void InitializeComponent() this.label1 = new BizHawk.WinForms.Controls.LocLabelEx(); this.label2 = new BizHawk.WinForms.Controls.LocLabelEx(); this.DisplayTypeDropdown = new System.Windows.Forms.ComboBox(); - this.SelectAllMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.SearchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.ListViewContextMenu.SuspendLayout(); this.RamSearchMenu.SuspendLayout(); this.CompareToBox.SuspendLayout(); @@ -165,22 +164,26 @@ private void InitializeComponent() // // WatchListView // - this.WatchListView.CellWidthPadding = 3; this.WatchListView.AllowColumnReorder = true; this.WatchListView.AllowColumnResize = true; this.WatchListView.AllowDrop = true; + this.WatchListView.AlwaysScroll = false; this.WatchListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); + this.WatchListView.CellHeightPadding = 0; + this.WatchListView.CellWidthPadding = 0; this.WatchListView.ContextMenuStrip = this.ListViewContextMenu; this.WatchListView.FullRowSelect = true; - this.WatchListView.GridLines = true; - this.WatchListView.RowCount = 0; + this.WatchListView.HorizontalOrientation = false; + this.WatchListView.LetKeysModifySelection = false; this.WatchListView.Location = new System.Drawing.Point(9, 65); this.WatchListView.Name = "WatchListView"; + this.WatchListView.RowCount = 0; + this.WatchListView.ScrollSpeed = 0; + this.WatchListView.SeekingCutoffInterval = 0; this.WatchListView.Size = new System.Drawing.Size(230, 366); this.WatchListView.TabIndex = 1; - this.WatchListView.MultiSelect = true; this.WatchListView.ColumnClick += new BizHawk.Client.EmuHawk.InputRoll.ColumnClickEventHandler(this.WatchListView_ColumnClick); this.WatchListView.SelectedIndexChanged += new System.EventHandler(this.WatchListView_SelectedIndexChanged); this.WatchListView.DragDrop += new System.Windows.Forms.DragEventHandler(this.NewRamSearch_DragDrop); @@ -314,7 +317,7 @@ private void InitializeComponent() this.RecentSubMenu.Text = "Recent"; this.RecentSubMenu.DropDownOpened += new System.EventHandler(this.RecentSubMenu_DropDownOpened); // - // settingsToolStripMenuItem + // OptionsSubMenuMenuItem // this.OptionsSubMenuMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.modeToolStripMenuItem, @@ -397,18 +400,12 @@ private void InitializeComponent() // DefinePreviousValueSubMenu // this.DefinePreviousValueSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.Previous_LastSearchMenuItem, this.PreviousFrameMenuItem, this.Previous_OriginalMenuItem, this.Previous_LastChangeMenuItem}); this.DefinePreviousValueSubMenu.Text = "Define Previous Value"; this.DefinePreviousValueSubMenu.DropDownOpened += new System.EventHandler(this.DefinePreviousValueSubMenu_DropDownOpened); // - // Previous_LastSearchMenuItem - // - this.Previous_LastSearchMenuItem.Text = "Last &Search"; - this.Previous_LastSearchMenuItem.Click += new System.EventHandler(this.Previous_LastSearchMenuItem_Click); - // // PreviousFrameMenuItem // this.PreviousFrameMenuItem.Text = "&Previous Frame"; @@ -429,7 +426,7 @@ private void InitializeComponent() this.searchToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.newSearchToolStripMenuItem, this.toolStripSeparator7, - SearchMenuItem, + this.SearchMenuItem, this.UndoMenuItem, this.RedoMenuItem, this.CopyValueToPrevMenuItem, @@ -504,12 +501,19 @@ private void InitializeComponent() this.FreezeAddressMenuItem.Text = "Freeze Address"; this.FreezeAddressMenuItem.Click += new System.EventHandler(this.FreezeAddressMenuItem_Click); // + // SelectAllMenuItem + // + this.SelectAllMenuItem.ShortcutKeyDisplayString = "Ctrl+A"; + this.SelectAllMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.A))); + this.SelectAllMenuItem.Text = "Select All"; + this.SelectAllMenuItem.Click += new System.EventHandler(this.SelectAllMenuItem_Click); + // // ClearUndoMenuItem // this.ClearUndoMenuItem.Text = "Clear Undo History"; this.ClearUndoMenuItem.Click += new System.EventHandler(this.ClearUndoMenuItem_Click); // - // optionsToolStripMenuItem + // SettingsMenuItem // this.SettingsMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.PreviewModeMenuItem, @@ -546,13 +550,6 @@ private void InitializeComponent() this.UseUndoHistoryMenuItem.Text = "&Use Undo History"; this.UseUndoHistoryMenuItem.Click += new System.EventHandler(this.UseUndoHistoryMenuItem_Click); // - // SelectAllMenuItem - // - this.SelectAllMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys) ((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.A))); - this.SelectAllMenuItem.ShortcutKeyDisplayString = "Ctrl+A"; - this.SelectAllMenuItem.Text = "Select All"; - this.SelectAllMenuItem.Click += new System.EventHandler(this.SelectAllMenuItem_Click); - // // MemDomainLabel // this.MemDomainLabel.Location = new System.Drawing.Point(135, 49); @@ -571,9 +568,9 @@ private void InitializeComponent() this.AutoSearchCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.AutoSearchCheckBox.Appearance = System.Windows.Forms.Appearance.Button; this.AutoSearchCheckBox.AutoSize = true; - this.AutoSearchCheckBox.Location = new System.Drawing.Point(316, 410); + this.AutoSearchCheckBox.Location = new System.Drawing.Point(348, 410); this.AutoSearchCheckBox.Name = "AutoSearchCheckBox"; - this.AutoSearchCheckBox.Size = new System.Drawing.Size(38, 22); + this.AutoSearchCheckBox.Size = new System.Drawing.Size(6, 6); this.AutoSearchCheckBox.TabIndex = 105; this.AutoSearchCheckBox.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; this.toolTip1.SetToolTip(this.AutoSearchCheckBox, "Automatically search each frame"); @@ -607,11 +604,12 @@ private void InitializeComponent() this.DifferenceBox.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper; this.DifferenceBox.Enabled = false; this.DifferenceBox.Location = new System.Drawing.Point(114, 98); - this.DifferenceBox.MaxLength = 8; + this.DifferenceBox.MaxLength = 2; this.DifferenceBox.Name = "DifferenceBox"; this.DifferenceBox.Nullable = false; this.DifferenceBox.Size = new System.Drawing.Size(72, 20); this.DifferenceBox.TabIndex = 45; + this.DifferenceBox.Text = "00"; this.DifferenceBox.Type = BizHawk.Client.Common.WatchDisplayType.Hex; this.DifferenceBox.TextChanged += new System.EventHandler(this.CompareToValue_TextChanged); // @@ -746,7 +744,7 @@ private void InitializeComponent() this.DoSearchToolButton.Enabled = false; this.DoSearchToolButton.ImageTransparentColor = System.Drawing.Color.Magenta; this.DoSearchToolButton.Name = "DoSearchToolButton"; - this.DoSearchToolButton.Size = new System.Drawing.Size(65, 22); + this.DoSearchToolButton.Size = new System.Drawing.Size(49, 22); this.DoSearchToolButton.Text = "Search "; this.DoSearchToolButton.Click += new System.EventHandler(this.SearchMenuItem_Click); // @@ -754,7 +752,7 @@ private void InitializeComponent() // this.NewSearchToolButton.ImageTransparentColor = System.Drawing.Color.Magenta; this.NewSearchToolButton.Name = "NewSearchToolButton"; - this.NewSearchToolButton.Size = new System.Drawing.Size(51, 22); + this.NewSearchToolButton.Size = new System.Drawing.Size(35, 22); this.NewSearchToolButton.Text = "New"; this.NewSearchToolButton.Click += new System.EventHandler(this.NewSearchMenuMenuItem_Click); // @@ -882,11 +880,12 @@ private void InitializeComponent() this.DifferentByBox.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper; this.DifferentByBox.Enabled = false; this.DifferentByBox.Location = new System.Drawing.Point(88, 132); - this.DifferentByBox.MaxLength = 9; + this.DifferentByBox.MaxLength = 2; this.DifferentByBox.Name = "DifferentByBox"; this.DifferentByBox.Nullable = false; this.DifferentByBox.Size = new System.Drawing.Size(55, 20); this.DifferentByBox.TabIndex = 85; + this.DifferentByBox.Text = "00"; this.DifferentByBox.Type = BizHawk.Client.Common.WatchDisplayType.Hex; this.DifferentByBox.TextChanged += new System.EventHandler(this.DifferentByBox_TextChanged); // @@ -1071,7 +1070,6 @@ private void InitializeComponent() #endregion private BizHawk.WinForms.Controls.LocLabelEx TotalSearchLabel; - private BizHawk.WinForms.Controls.ToolStripMenuItemEx SearchMenuItem; private InputRoll WatchListView; private BizHawk.WinForms.Controls.ToolStripMenuItemEx fileToolStripMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx OpenMenuItem; @@ -1132,7 +1130,6 @@ private void InitializeComponent() private BizHawk.WinForms.Controls.ToolStripSeparatorEx toolStripSeparator8; private BizHawk.WinForms.Controls.ToolStripMenuItemEx DefinePreviousValueSubMenu; private BizHawk.WinForms.Controls.ToolStripMenuItemEx PreviousFrameMenuItem; - private BizHawk.WinForms.Controls.ToolStripMenuItemEx Previous_LastSearchMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx Previous_OriginalMenuItem; private System.Windows.Forms.GroupBox CompareToBox; private System.Windows.Forms.RadioButton DifferenceRadio; @@ -1184,5 +1181,6 @@ private void InitializeComponent() private BizHawk.WinForms.Controls.ToolStripMenuItemEx Previous_LastChangeMenuItem; private BizHawk.WinForms.Controls.ToolStripMenuItemEx AutoSearchAccountForLagMenuItem; private ToolStripMenuItemEx SelectAllMenuItem; + private ToolStripMenuItemEx SearchMenuItem; } -} \ No newline at end of file +} diff --git a/src/BizHawk.Client.EmuHawk/tools/Watch/RamSearch.cs b/src/BizHawk.Client.EmuHawk/tools/Watch/RamSearch.cs index d297bf1fce1..f6166455af8 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Watch/RamSearch.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Watch/RamSearch.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; @@ -189,7 +188,7 @@ private void ListView_QueryItemBkColor(int index, RollColumn column, ref Color c var nextColor = Color.White; var search = _searches[index]; var isCheat = MainForm.CheatList.IsActive(_settings.Domain, search.Address); - var isWeeded = Settings.PreviewMode && !_forcePreviewClear && _searches.Preview(search.Address); + var isWeeded = Settings.PreviewMode && !_forcePreviewClear && _searches.Preview(index); if (!search.IsValid) { @@ -271,8 +270,6 @@ private void FrameUpdate() { if (_searches.Count > 0) { - _searches.Update(); - if (_autoSearch) { if (InputPollableCore != null && Settings.AutoSearchTakeLagFramesIntoAccount && InputPollableCore.IsLagFrame) @@ -281,21 +278,24 @@ private void FrameUpdate() } else { - DoSearch(); + DoSearch(true); } } + else if (_settings.IsDetailed()) + { + _searches.Update(true); + } _forcePreviewClear = false; WatchListView.RowCount = _searches.Count; } } + // TODO: this seems to be missing some logic from FrameUpdate that probably should exist here private void MinimalUpdate() { if (_searches.Count > 0) { - _searches.Update(); - if (_autoSearch) { DoSearch(); @@ -305,6 +305,8 @@ private void MinimalUpdate() public override void Restart() { + if (!IsHandleCreated) return; + _settings = new SearchEngineSettings(MemoryDomains, Settings.UseUndoHistory); _searches = new RamSearchEngine(_settings, MemoryDomains); MessageLabel.Text = "Search restarted"; @@ -419,7 +421,7 @@ private void ToggleSearchDependentToolBarItems() WatchListView.AnyRowsSelected && _searches.Domain.Writable; } - private long? CompareToValue + private uint? CompareToValue { get { @@ -430,29 +432,29 @@ private long? CompareToValue if (SpecificValueRadio.Checked) { - return (long)SpecificValueBox.ToRawInt() & 0x00000000FFFFFFFF; + return SpecificValueBox.ToRawUInt(); } if (SpecificAddressRadio.Checked) { - return SpecificAddressBox.ToRawInt(); + return SpecificAddressBox.ToRawUInt(); } if (NumberOfChangesRadio.Checked) { - return NumberOfChangesBox.ToRawInt(); + return NumberOfChangesBox.ToRawUInt(); } if (DifferenceRadio.Checked) { - return DifferenceBox.ToRawInt(); + return DifferenceBox.ToRawUInt(); } return null; } } - private int? DifferentByValue => DifferentByRadio.Checked ? DifferentByBox.ToRawInt() : null; + private uint? DifferentByValue => DifferentByRadio.Checked ? DifferentByBox.ToRawUInt() : null; private ComparisonOperator Operator { @@ -520,14 +522,14 @@ private Compare Compare } } - public void DoSearch() + public void DoSearch(bool updatePrevious = false) { _searches.CompareValue = CompareToValue; _searches.DifferentBy = DifferentByValue; _searches.Operator = Operator; _searches.CompareTo = Compare; - var removed = _searches.DoSearch(); + var removed = _searches.DoSearch(updatePrevious); UpdateList(); SetRemovedMessage(removed); ToggleSearchDependentToolBarItems(); @@ -586,7 +588,6 @@ private void DoDomainSizeCheck() && _settings.IsDetailed()) { _settings.Mode = SearchMode.Fast; - SetReboot(true); MessageLabel.Text = "Large domain, switching to fast mode"; } } @@ -736,7 +737,7 @@ private void SetCompareTo(Compare comp) WatchListView.Refresh(); } - private void SetCompareValue(int? value) + private void SetCompareValue(uint? value) { _searches.CompareValue = value; WatchListView.Refresh(); @@ -752,6 +753,7 @@ private void SetReboot(bool rebootNeeded) private void SetToDetailedMode() { _settings.Mode = SearchMode.Detailed; + _searches.SetMode(SearchMode.Detailed); NumberOfChangesRadio.Enabled = true; NumberOfChangesBox.Enabled = true; DifferenceRadio.Enabled = true; @@ -762,7 +764,6 @@ private void SetToDetailedMode() ChangesMenuItem.Checked = true; ColumnToggleCallback(); - SetReboot(true); } private ToolStripMenuItem ChangesMenuItem @@ -781,11 +782,7 @@ private ToolStripMenuItem ChangesMenuItem private void SetToFastMode() { _settings.Mode = SearchMode.Fast; - - if (_settings.PreviousType == PreviousType.LastFrame || _settings.PreviousType == PreviousType.LastChange) - { - SetPreviousType(PreviousType.LastSearch); - } + _searches.SetMode(SearchMode.Fast); NumberOfChangesRadio.Enabled = false; NumberOfChangesBox.Enabled = false; @@ -801,7 +798,6 @@ private void SetToFastMode() ChangesMenuItem.Checked = false; ColumnToggleCallback(); - SetReboot(true); } private void RemoveAddresses() @@ -1083,7 +1079,6 @@ private void DisplayTypeSubMenu_DropDownOpened(object sender, EventArgs e) private void DefinePreviousValueSubMenu_DropDownOpened(object sender, EventArgs e) { - Previous_LastSearchMenuItem.Checked = false; PreviousFrameMenuItem.Checked = false; Previous_OriginalMenuItem.Checked = false; Previous_LastChangeMenuItem.Checked = false; @@ -1091,9 +1086,6 @@ private void DefinePreviousValueSubMenu_DropDownOpened(object sender, EventArgs switch (_settings.PreviousType) { default: - case PreviousType.LastSearch: - Previous_LastSearchMenuItem.Checked = true; - break; case PreviousType.LastFrame: PreviousFrameMenuItem.Checked = true; break; @@ -1104,9 +1096,6 @@ private void DefinePreviousValueSubMenu_DropDownOpened(object sender, EventArgs Previous_LastChangeMenuItem.Checked = true; break; } - - PreviousFrameMenuItem.Enabled = _settings.IsDetailed(); - Previous_LastChangeMenuItem.Enabled = _settings.IsDetailed(); } private void DetailedMenuItem_Click(object sender, EventArgs e) @@ -1136,7 +1125,7 @@ private void DWordMenuItem_Click_Click(object sender, EventArgs e) private void CheckMisalignedMenuItem_Click(object sender, EventArgs e) { - _settings.CheckMisAligned ^= true; + _settings.CheckMisAligned = !_settings.CheckMisAligned; SetReboot(true); } @@ -1145,11 +1134,6 @@ private void Previous_LastFrameMenuItem_Click(object sender, EventArgs e) SetPreviousType(PreviousType.LastFrame); } - private void Previous_LastSearchMenuItem_Click(object sender, EventArgs e) - { - SetPreviousType(PreviousType.LastSearch); - } - private void Previous_OriginalMenuItem_Click(object sender, EventArgs e) { SetPreviousType(PreviousType.Original); @@ -1162,14 +1146,12 @@ private void Previous_LastChangeMenuItem_Click(object sender, EventArgs e) private void BigEndianMenuItem_Click(object sender, EventArgs e) { - _settings.BigEndian ^= true; + _settings.BigEndian = !_settings.BigEndian; _searches.SetEndian(_settings.BigEndian); } private void SearchSubMenu_DropDownOpened(object sender, EventArgs e) { - ClearChangeCountsMenuItem.Enabled = _settings.IsDetailed(); - RemoveMenuItem.Enabled = AddToRamWatchMenuItem.Enabled = WatchListView.AnyRowsSelected; @@ -1286,13 +1268,11 @@ private void SettingsSubMenu_DropDownOpened(object sender, EventArgs e) } private void PreviewModeMenuItem_Click(object sender, EventArgs e) - { - Settings.PreviewMode ^= true; - } + => Settings.PreviewMode = !Settings.PreviewMode; private void AutoSearchMenuItem_Click(object sender, EventArgs e) { - _autoSearch ^= true; + _autoSearch = !_autoSearch; AutoSearchCheckBox.Checked = _autoSearch; DoSearchToolButton.Enabled = SearchButton.Enabled = @@ -1300,13 +1280,11 @@ private void AutoSearchMenuItem_Click(object sender, EventArgs e) } private void AutoSearchAccountForLagMenuItem_Click(object sender, EventArgs e) - { - Settings.AutoSearchTakeLagFramesIntoAccount ^= true; - } + => Settings.AutoSearchTakeLagFramesIntoAccount = !Settings.AutoSearchTakeLagFramesIntoAccount; private void ExcludeRamWatchMenuItem_Click(object sender, EventArgs e) { - Settings.AlwaysExcludeRamWatch ^= true; + Settings.AlwaysExcludeRamWatch = !Settings.AlwaysExcludeRamWatch; if (Settings.AlwaysExcludeRamWatch) { RemoveRamWatchesFromList(); @@ -1315,7 +1293,7 @@ private void ExcludeRamWatchMenuItem_Click(object sender, EventArgs e) private void UseUndoHistoryMenuItem_Click(object sender, EventArgs e) { - _searches.UndoEnabled ^= true; + _searches.UndoEnabled = !_searches.UndoEnabled; Settings.UseUndoHistory = _searches.UndoEnabled; } @@ -1463,7 +1441,7 @@ private void SpecificValueRadio_Click(object sender, EventArgs e) SpecificAddressBox.ResetText(); } - _searches.CompareValue = SpecificValueBox.ToRawInt(); + _searches.CompareValue = SpecificValueBox.ToRawUInt(); if (Focused) { @@ -1485,7 +1463,7 @@ private void SpecificAddressRadio_Click(object sender, EventArgs e) SpecificAddressBox.ResetText(); } - _searches.CompareValue = SpecificAddressBox.ToRawInt(); + _searches.CompareValue = SpecificAddressBox.ToRawUInt(); if (Focused) { @@ -1507,7 +1485,7 @@ private void NumberOfChangesRadio_Click(object sender, EventArgs e) NumberOfChangesBox.ResetText(); } - _searches.CompareValue = NumberOfChangesBox.ToRawInt(); + _searches.CompareValue = NumberOfChangesBox.ToRawUInt(); if (Focused) { @@ -1529,7 +1507,7 @@ private void DifferenceRadio_Click(object sender, EventArgs e) DifferenceBox.ResetText(); } - _searches.CompareValue = DifferenceBox.ToRawInt(); + _searches.CompareValue = DifferenceBox.ToRawUInt(); if (Focused) { @@ -1541,7 +1519,7 @@ private void DifferenceRadio_Click(object sender, EventArgs e) private void CompareToValue_TextChanged(object sender, EventArgs e) { - SetCompareValue(((INumberBox)sender).ToRawInt()); + SetCompareValue(((INumberBox)sender).ToRawUInt()); } private void EqualToRadio_Click(object sender, EventArgs e) @@ -1589,7 +1567,7 @@ private void DifferentByRadio_Click(object sender, EventArgs e) DifferentByBox.ResetText(); } - _searches.DifferentBy = DifferenceBox.ToRawInt(); + _searches.DifferentBy = DifferenceBox.ToRawUInt(); if (Focused) { @@ -1601,7 +1579,7 @@ private void DifferentByRadio_Click(object sender, EventArgs e) private void DifferentByBox_TextChanged(object sender, EventArgs e) { - _searches.DifferentBy = !string.IsNullOrWhiteSpace(DifferentByBox.Text) ? DifferentByBox.ToRawInt() : null; + _searches.DifferentBy = !string.IsNullOrWhiteSpace(DifferentByBox.Text) ? DifferentByBox.ToRawUInt() : null; WatchListView.Refresh(); } @@ -1635,7 +1613,7 @@ private void WatchListView_Enter(object sender, EventArgs e) private void WatchListView_ColumnClick(object sender, InputRoll.ColumnClickEventArgs e) { - var column = e.Column; + var column = e.Column!; if (column.Name != _sortedColumn) { _sortReverse = false; @@ -1644,7 +1622,7 @@ private void WatchListView_ColumnClick(object sender, InputRoll.ColumnClickEvent _searches.Sort(column.Name, _sortReverse); _sortedColumn = column.Name; - _sortReverse ^= true; + _sortReverse = !_sortReverse; WatchListView.Refresh(); } diff --git a/src/BizHawk.Client.EmuHawk/tools/Watch/RamSearch.resx b/src/BizHawk.Client.EmuHawk/tools/Watch/RamSearch.resx index db23b6f6955..6eaa06301e0 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Watch/RamSearch.resx +++ b/src/BizHawk.Client.EmuHawk/tools/Watch/RamSearch.resx @@ -117,9 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - False - 161, 17 diff --git a/src/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.Designer.cs b/src/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.Designer.cs index 53f38813772..fa416b3c98c 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.Designer.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.Designer.cs @@ -30,101 +30,101 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - this.WatchCountLabel = new BizHawk.WinForms.Controls.LocLabelEx(); - this.ListViewContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); - this.newToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.EditContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.RemoveContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.DuplicateContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.SplitContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.PokeContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.FreezeContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.UnfreezeAllContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.ViewInHexEditorContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.Separator4 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); - this.ReadBreakpointContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.WriteBreakpointContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.Separator6 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); - this.InsertSeperatorContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.MoveUpContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.MoveDownContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.MoveTopContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.MoveBottomContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.statusStrip1 = new StatusStripEx(); - this.ErrorIconButton = new System.Windows.Forms.ToolStripButton(); - this.MessageLabel = new System.Windows.Forms.ToolStripStatusLabel(); - this.toolStrip1 = new ToolStripEx(); - this.newToolStripButton = new System.Windows.Forms.ToolStripButton(); - this.openToolStripButton = new System.Windows.Forms.ToolStripButton(); - this.saveToolStripButton = new System.Windows.Forms.ToolStripButton(); - this.toolStripSeparator = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); - this.newWatchToolStripButton = new System.Windows.Forms.ToolStripButton(); - this.editWatchToolStripButton = new System.Windows.Forms.ToolStripButton(); - this.cutToolStripButton = new System.Windows.Forms.ToolStripButton(); - this.clearChangeCountsToolStripButton = new System.Windows.Forms.ToolStripButton(); - this.duplicateWatchToolStripButton = new System.Windows.Forms.ToolStripButton(); - this.SplitWatchToolStripButton = new System.Windows.Forms.ToolStripButton(); - this.PokeAddressToolBarItem = new System.Windows.Forms.ToolStripButton(); - this.FreezeAddressToolBarItem = new System.Windows.Forms.ToolStripButton(); - this.seperatorToolStripButton = new System.Windows.Forms.ToolStripButton(); - this.toolStripSeparator6 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); - this.moveUpToolStripButton = new System.Windows.Forms.ToolStripButton(); - this.moveDownToolStripButton = new System.Windows.Forms.ToolStripButton(); - this.toolStripSeparator5 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); - this.RamWatchMenu = new MenuStripEx(); - this.FileSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.NewListMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.OpenMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.SaveMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.SaveAsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.AppendMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.RecentSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.noneToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.WatchesSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.MemoryDomainsSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.Separator2 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); - this.toolStripSeparator8 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); - this.NewWatchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.EditWatchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.RemoveWatchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.DuplicateWatchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.SplitWatchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.PokeAddressMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.FreezeAddressMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.InsertSeparatorMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.ClearChangeCountsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.toolStripSeparator3 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); - this.MoveUpMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.MoveDownMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.MoveTopMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.MoveBottomMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.SelectAllMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.components = new System.ComponentModel.Container(); + this.WatchCountLabel = new BizHawk.WinForms.Controls.LocLabelEx(); + this.ListViewContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); + this.newToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.EditContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.RemoveContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.DuplicateContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.SplitContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.PokeContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.FreezeContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.UnfreezeAllContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.ViewInHexEditorContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.Separator4 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); + this.ReadBreakpointContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.WriteBreakpointContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.Separator6 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); + this.InsertSeperatorContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.MoveUpContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.MoveDownContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.MoveTopContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.MoveBottomContextMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.statusStrip1 = new BizHawk.WinForms.Controls.StatusStripEx(); + this.ErrorIconButton = new System.Windows.Forms.ToolStripButton(); + this.MessageLabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.toolStrip1 = new BizHawk.WinForms.Controls.ToolStripEx(); + this.newToolStripButton = new System.Windows.Forms.ToolStripButton(); + this.openToolStripButton = new System.Windows.Forms.ToolStripButton(); + this.saveToolStripButton = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); + this.newWatchToolStripButton = new System.Windows.Forms.ToolStripButton(); + this.editWatchToolStripButton = new System.Windows.Forms.ToolStripButton(); + this.cutToolStripButton = new System.Windows.Forms.ToolStripButton(); + this.clearChangeCountsToolStripButton = new System.Windows.Forms.ToolStripButton(); + this.duplicateWatchToolStripButton = new System.Windows.Forms.ToolStripButton(); + this.SplitWatchToolStripButton = new System.Windows.Forms.ToolStripButton(); + this.PokeAddressToolBarItem = new System.Windows.Forms.ToolStripButton(); + this.FreezeAddressToolBarItem = new System.Windows.Forms.ToolStripButton(); + this.seperatorToolStripButton = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator6 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); + this.moveUpToolStripButton = new System.Windows.Forms.ToolStripButton(); + this.moveDownToolStripButton = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator5 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); + this.RamWatchMenu = new BizHawk.WinForms.Controls.MenuStripEx(); + this.FileSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.NewListMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.OpenMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.SaveMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.SaveAsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.AppendMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.RecentSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.noneToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.WatchesSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.MemoryDomainsSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.Separator2 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); + this.toolStripSeparator8 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); + this.NewWatchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.EditWatchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.RemoveWatchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.DuplicateWatchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.SplitWatchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.PokeAddressMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.FreezeAddressMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.InsertSeparatorMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.ClearChangeCountsMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.toolStripSeparator3 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx(); + this.MoveUpMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.MoveDownMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.MoveTopMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.MoveBottomMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.SelectAllMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); this.OptionsSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.DefinePreviousValueSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.PreviousFrameMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.LastChangeMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.OriginalMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.WatchesOnScreenMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.WatchListView = new InputRoll(); - this.DoubleClickActionSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.DoubleClickToEditMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.DoubleClickToPokeMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); - this.ListViewContextMenu.SuspendLayout(); - this.statusStrip1.SuspendLayout(); - this.toolStrip1.SuspendLayout(); - this.RamWatchMenu.SuspendLayout(); - this.SuspendLayout(); - // - // WatchCountLabel - // - this.WatchCountLabel.Location = new System.Drawing.Point(16, 57); - this.WatchCountLabel.Name = "WatchCountLabel"; - this.WatchCountLabel.Text = "0 watches"; - // - // ListViewContextMenu - // - this.ListViewContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.DefinePreviousValueSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.PreviousFrameMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.LastChangeMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.OriginalMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.WatchesOnScreenMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.DoubleClickActionSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.DoubleClickToEditMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.DoubleClickToPokeMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx(); + this.WatchListView = new BizHawk.Client.EmuHawk.InputRoll(); + this.ListViewContextMenu.SuspendLayout(); + this.statusStrip1.SuspendLayout(); + this.toolStrip1.SuspendLayout(); + this.RamWatchMenu.SuspendLayout(); + this.SuspendLayout(); + // + // WatchCountLabel + // + this.WatchCountLabel.Location = new System.Drawing.Point(16, 57); + this.WatchCountLabel.Name = "WatchCountLabel"; + this.WatchCountLabel.Text = "0 watches"; + // + // ListViewContextMenu + // + this.ListViewContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.newToolStripMenuItem, this.EditContextMenuItem, this.RemoveContextMenuItem, @@ -143,131 +143,131 @@ private void InitializeComponent() this.MoveDownContextMenuItem, this.MoveTopContextMenuItem, this.MoveBottomContextMenuItem}); - this.ListViewContextMenu.Name = "contextMenuStrip1"; - this.ListViewContextMenu.Size = new System.Drawing.Size(245, 346); - this.ListViewContextMenu.Opening += new System.ComponentModel.CancelEventHandler(this.ListViewContextMenu_Opening); - // - // newToolStripMenuItem - // - this.newToolStripMenuItem.Text = "&New Watch"; - this.newToolStripMenuItem.Click += new System.EventHandler(this.NewWatchMenuItem_Click); - // - // EditContextMenuItem - // - this.EditContextMenuItem.ShortcutKeyDisplayString = "Ctrl+E"; - this.EditContextMenuItem.Text = "&Edit"; - this.EditContextMenuItem.Click += new System.EventHandler(this.EditWatchMenuItem_Click); - // - // RemoveContextMenuItem - // - this.RemoveContextMenuItem.ShortcutKeyDisplayString = "Ctrl+R"; - this.RemoveContextMenuItem.Text = "&Remove"; - this.RemoveContextMenuItem.Click += new System.EventHandler(this.RemoveWatchMenuItem_Click); - // - // DuplicateContextMenuItem - // - this.DuplicateContextMenuItem.ShortcutKeyDisplayString = "Ctrl+D"; - this.DuplicateContextMenuItem.Text = "&Duplicate"; - this.DuplicateContextMenuItem.Click += new System.EventHandler(this.DuplicateWatchMenuItem_Click); - // - // SplitContextMenuItem - // - this.SplitContextMenuItem.ShortcutKeyDisplayString = "Ctrl+L"; - this.SplitContextMenuItem.Text = "Sp&lit"; - this.SplitContextMenuItem.Click += new System.EventHandler(this.SplitWatchMenuItem_Click); - // - // PokeContextMenuItem - // - this.PokeContextMenuItem.ShortcutKeyDisplayString = "Ctrl+P"; - this.PokeContextMenuItem.Text = "&Poke"; - this.PokeContextMenuItem.Click += new System.EventHandler(this.PokeAddressMenuItem_Click); - // - // FreezeContextMenuItem - // - this.FreezeContextMenuItem.ShortcutKeyDisplayString = "Ctrl+F"; - this.FreezeContextMenuItem.Text = "&Freeze"; - this.FreezeContextMenuItem.Click += new System.EventHandler(this.FreezeAddressMenuItem_Click); - // - // UnfreezeAllContextMenuItem - // - this.UnfreezeAllContextMenuItem.Text = "Unfreeze &All"; - this.UnfreezeAllContextMenuItem.Click += new System.EventHandler(this.UnfreezeAllContextMenuItem_Click); - // - // ViewInHexEditorContextMenuItem - // - this.ViewInHexEditorContextMenuItem.Text = "View in Hex Editor"; - this.ViewInHexEditorContextMenuItem.Click += new System.EventHandler(this.ViewInHexEditorContextMenuItem_Click); - // - // ReadBreakpointContextMenuItem - // - this.ReadBreakpointContextMenuItem.Text = "Set Read Breakpoint"; - this.ReadBreakpointContextMenuItem.Click += new System.EventHandler(this.ReadBreakpointContextMenuItem_Click); - // - // WriteBreakpointContextMenuItem - // - this.WriteBreakpointContextMenuItem.Text = "Set Write Breakpoint"; - this.WriteBreakpointContextMenuItem.Click += new System.EventHandler(this.WriteBreakpointContextMenuItem_Click); - // - // InsertSeperatorContextMenuItem - // - this.InsertSeperatorContextMenuItem.ShortcutKeyDisplayString = "Ctrl+I"; - this.InsertSeperatorContextMenuItem.Text = "&Insert Separator"; - this.InsertSeperatorContextMenuItem.Click += new System.EventHandler(this.InsertSeparatorMenuItem_Click); - // - // MoveUpContextMenuItem - // - this.MoveUpContextMenuItem.ShortcutKeyDisplayString = "Ctrl+Up"; - this.MoveUpContextMenuItem.Text = "Move &Up"; - this.MoveUpContextMenuItem.Click += new System.EventHandler(this.MoveUpMenuItem_Click); - // - // MoveDownContextMenuItem - // - this.MoveDownContextMenuItem.ShortcutKeyDisplayString = "Ctrl+Down"; - this.MoveDownContextMenuItem.Text = "Move &Down"; - this.MoveDownContextMenuItem.Click += new System.EventHandler(this.MoveDownMenuItem_Click); - // - // MoveTopContextMenuItem - // - this.MoveTopContextMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + this.ListViewContextMenu.Name = "contextMenuStrip1"; + this.ListViewContextMenu.Size = new System.Drawing.Size(245, 368); + this.ListViewContextMenu.Opening += new System.ComponentModel.CancelEventHandler(this.ListViewContextMenu_Opening); + // + // newToolStripMenuItem + // + this.newToolStripMenuItem.Text = "&New Watch"; + this.newToolStripMenuItem.Click += new System.EventHandler(this.NewWatchMenuItem_Click); + // + // EditContextMenuItem + // + this.EditContextMenuItem.ShortcutKeyDisplayString = "Ctrl+E"; + this.EditContextMenuItem.Text = "&Edit"; + this.EditContextMenuItem.Click += new System.EventHandler(this.EditWatchMenuItem_Click); + // + // RemoveContextMenuItem + // + this.RemoveContextMenuItem.ShortcutKeyDisplayString = "Ctrl+R"; + this.RemoveContextMenuItem.Text = "&Remove"; + this.RemoveContextMenuItem.Click += new System.EventHandler(this.RemoveWatchMenuItem_Click); + // + // DuplicateContextMenuItem + // + this.DuplicateContextMenuItem.ShortcutKeyDisplayString = "Ctrl+D"; + this.DuplicateContextMenuItem.Text = "&Duplicate"; + this.DuplicateContextMenuItem.Click += new System.EventHandler(this.DuplicateWatchMenuItem_Click); + // + // SplitContextMenuItem + // + this.SplitContextMenuItem.ShortcutKeyDisplayString = "Ctrl+L"; + this.SplitContextMenuItem.Text = "Sp&lit"; + this.SplitContextMenuItem.Click += new System.EventHandler(this.SplitWatchMenuItem_Click); + // + // PokeContextMenuItem + // + this.PokeContextMenuItem.ShortcutKeyDisplayString = "Ctrl+P"; + this.PokeContextMenuItem.Text = "&Poke"; + this.PokeContextMenuItem.Click += new System.EventHandler(this.PokeAddressMenuItem_Click); + // + // FreezeContextMenuItem + // + this.FreezeContextMenuItem.ShortcutKeyDisplayString = "Ctrl+F"; + this.FreezeContextMenuItem.Text = "&Freeze"; + this.FreezeContextMenuItem.Click += new System.EventHandler(this.FreezeAddressMenuItem_Click); + // + // UnfreezeAllContextMenuItem + // + this.UnfreezeAllContextMenuItem.Text = "Unfreeze &All"; + this.UnfreezeAllContextMenuItem.Click += new System.EventHandler(this.UnfreezeAllContextMenuItem_Click); + // + // ViewInHexEditorContextMenuItem + // + this.ViewInHexEditorContextMenuItem.Text = "View in Hex Editor"; + this.ViewInHexEditorContextMenuItem.Click += new System.EventHandler(this.ViewInHexEditorContextMenuItem_Click); + // + // ReadBreakpointContextMenuItem + // + this.ReadBreakpointContextMenuItem.Text = "Set Read Breakpoint"; + this.ReadBreakpointContextMenuItem.Click += new System.EventHandler(this.ReadBreakpointContextMenuItem_Click); + // + // WriteBreakpointContextMenuItem + // + this.WriteBreakpointContextMenuItem.Text = "Set Write Breakpoint"; + this.WriteBreakpointContextMenuItem.Click += new System.EventHandler(this.WriteBreakpointContextMenuItem_Click); + // + // InsertSeperatorContextMenuItem + // + this.InsertSeperatorContextMenuItem.ShortcutKeyDisplayString = "Ctrl+I"; + this.InsertSeperatorContextMenuItem.Text = "&Insert Separator"; + this.InsertSeperatorContextMenuItem.Click += new System.EventHandler(this.InsertSeparatorMenuItem_Click); + // + // MoveUpContextMenuItem + // + this.MoveUpContextMenuItem.ShortcutKeyDisplayString = "Ctrl+Up"; + this.MoveUpContextMenuItem.Text = "Move &Up"; + this.MoveUpContextMenuItem.Click += new System.EventHandler(this.MoveUpMenuItem_Click); + // + // MoveDownContextMenuItem + // + this.MoveDownContextMenuItem.ShortcutKeyDisplayString = "Ctrl+Down"; + this.MoveDownContextMenuItem.Text = "Move &Down"; + this.MoveDownContextMenuItem.Click += new System.EventHandler(this.MoveDownMenuItem_Click); + // + // MoveTopContextMenuItem + // + this.MoveTopContextMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) | System.Windows.Forms.Keys.Up))); - this.MoveTopContextMenuItem.Text = "Move &Top"; - this.MoveTopContextMenuItem.Click += new System.EventHandler(this.MoveTopMenuItem_Click); - // - // MoveBottomContextMenuItem - // - this.MoveBottomContextMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + this.MoveTopContextMenuItem.Text = "Move &Top"; + this.MoveTopContextMenuItem.Click += new System.EventHandler(this.MoveTopMenuItem_Click); + // + // MoveBottomContextMenuItem + // + this.MoveBottomContextMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) | System.Windows.Forms.Keys.Down))); - this.MoveBottomContextMenuItem.Text = "Move &Bottom"; - this.MoveBottomContextMenuItem.Click += new System.EventHandler(this.MoveBottomMenuItem_Click); - // - // statusStrip1 - // - this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.MoveBottomContextMenuItem.Text = "Move &Bottom"; + this.MoveBottomContextMenuItem.Click += new System.EventHandler(this.MoveBottomMenuItem_Click); + // + // statusStrip1 + // + this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.ErrorIconButton, this.MessageLabel}); - this.statusStrip1.Location = new System.Drawing.Point(0, 356); - this.statusStrip1.Name = "statusStrip1"; - this.statusStrip1.TabIndex = 8; - // - // ErrorIconButton - // - this.ErrorIconButton.BackColor = System.Drawing.Color.NavajoWhite; - this.ErrorIconButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.ErrorIconButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.ErrorIconButton.Name = "ErrorIconButton"; - this.ErrorIconButton.Size = new System.Drawing.Size(23, 20); - this.ErrorIconButton.Text = "Warning! Out of Range Addresses in list, click to remove them"; - this.ErrorIconButton.Click += new System.EventHandler(this.ErrorIconButton_Click); - // - // MessageLabel - // - this.MessageLabel.Name = "MessageLabel"; - this.MessageLabel.Size = new System.Drawing.Size(31, 17); - this.MessageLabel.Text = " "; - // - // toolStrip1 - // - this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.statusStrip1.Location = new System.Drawing.Point(0, 356); + this.statusStrip1.Name = "statusStrip1"; + this.statusStrip1.TabIndex = 8; + // + // ErrorIconButton + // + this.ErrorIconButton.BackColor = System.Drawing.Color.NavajoWhite; + this.ErrorIconButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.ErrorIconButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.ErrorIconButton.Name = "ErrorIconButton"; + this.ErrorIconButton.Size = new System.Drawing.Size(23, 20); + this.ErrorIconButton.Text = "Warning! Out of Range Addresses in list, click to remove them"; + this.ErrorIconButton.Click += new System.EventHandler(this.ErrorIconButton_Click); + // + // MessageLabel + // + this.MessageLabel.Name = "MessageLabel"; + this.MessageLabel.Size = new System.Drawing.Size(31, 17); + this.MessageLabel.Text = " "; + // + // toolStrip1 + // + this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.newToolStripButton, this.openToolStripButton, this.saveToolStripButton, @@ -285,206 +285,206 @@ private void InitializeComponent() this.moveUpToolStripButton, this.moveDownToolStripButton, this.toolStripSeparator5}); - this.toolStrip1.Location = new System.Drawing.Point(0, 24); - this.toolStrip1.Name = "toolStrip1"; - this.toolStrip1.TabIndex = 4; - this.toolStrip1.TabStop = true; - // - // newToolStripButton - // - this.newToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.newToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.newToolStripButton.Name = "newToolStripButton"; - this.newToolStripButton.Size = new System.Drawing.Size(23, 22); - this.newToolStripButton.Text = "&New"; - this.newToolStripButton.Click += new System.EventHandler(this.NewListMenuItem_Click); - // - // openToolStripButton - // - this.openToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.openToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.openToolStripButton.Name = "openToolStripButton"; - this.openToolStripButton.Size = new System.Drawing.Size(23, 22); - this.openToolStripButton.Text = "&Open"; - this.openToolStripButton.Click += new System.EventHandler(this.OpenMenuItem_Click); - // - // saveToolStripButton - // - this.saveToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.saveToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.saveToolStripButton.Name = "saveToolStripButton"; - this.saveToolStripButton.Size = new System.Drawing.Size(23, 22); - this.saveToolStripButton.Text = "&Save"; - this.saveToolStripButton.Click += new System.EventHandler(this.SaveMenuItem_Click); - // - // newWatchToolStripButton - // - this.newWatchToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.newWatchToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.newWatchToolStripButton.Name = "newWatchToolStripButton"; - this.newWatchToolStripButton.Size = new System.Drawing.Size(23, 22); - this.newWatchToolStripButton.Text = "New Watch"; - this.newWatchToolStripButton.ToolTipText = "New Watch"; - this.newWatchToolStripButton.Click += new System.EventHandler(this.NewWatchMenuItem_Click); - // - // editWatchToolStripButton - // - this.editWatchToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.editWatchToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.editWatchToolStripButton.Name = "editWatchToolStripButton"; - this.editWatchToolStripButton.Size = new System.Drawing.Size(23, 22); - this.editWatchToolStripButton.Text = "Edit Watch"; - this.editWatchToolStripButton.Click += new System.EventHandler(this.EditWatchMenuItem_Click); - // - // cutToolStripButton - // - this.cutToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.cutToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.cutToolStripButton.Name = "cutToolStripButton"; - this.cutToolStripButton.Size = new System.Drawing.Size(23, 22); - this.cutToolStripButton.Text = "C&ut"; - this.cutToolStripButton.ToolTipText = "Remove Watch"; - this.cutToolStripButton.Click += new System.EventHandler(this.RemoveWatchMenuItem_Click); - // - // clearChangeCountsToolStripButton - // - this.clearChangeCountsToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.clearChangeCountsToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.clearChangeCountsToolStripButton.Name = "clearChangeCountsToolStripButton"; - this.clearChangeCountsToolStripButton.Size = new System.Drawing.Size(23, 22); - this.clearChangeCountsToolStripButton.Text = "C"; - this.clearChangeCountsToolStripButton.ToolTipText = "Clear Change Counts"; - this.clearChangeCountsToolStripButton.Click += new System.EventHandler(this.ClearChangeCountsMenuItem_Click); - // - // duplicateWatchToolStripButton - // - this.duplicateWatchToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.duplicateWatchToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.duplicateWatchToolStripButton.Name = "duplicateWatchToolStripButton"; - this.duplicateWatchToolStripButton.Size = new System.Drawing.Size(23, 22); - this.duplicateWatchToolStripButton.Text = "Duplicate Watch"; - this.duplicateWatchToolStripButton.Click += new System.EventHandler(this.DuplicateWatchMenuItem_Click); - // - // SplitWatchToolStripButton - // - this.SplitWatchToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.SplitWatchToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.SplitWatchToolStripButton.Name = "SplitWatchToolStripButton"; - this.SplitWatchToolStripButton.Size = new System.Drawing.Size(23, 22); - this.SplitWatchToolStripButton.Text = "Split Watch"; - this.SplitWatchToolStripButton.Click += new System.EventHandler(this.SplitWatchMenuItem_Click); - // - // PokeAddressToolBarItem - // - this.PokeAddressToolBarItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.PokeAddressToolBarItem.ImageTransparentColor = System.Drawing.Color.Magenta; - this.PokeAddressToolBarItem.Name = "PokeAddressToolBarItem"; - this.PokeAddressToolBarItem.Size = new System.Drawing.Size(23, 22); - this.PokeAddressToolBarItem.Text = "toolStripButton2"; - this.PokeAddressToolBarItem.ToolTipText = "Poke address"; - this.PokeAddressToolBarItem.Click += new System.EventHandler(this.PokeAddressMenuItem_Click); - // - // FreezeAddressToolBarItem - // - this.FreezeAddressToolBarItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.FreezeAddressToolBarItem.ImageTransparentColor = System.Drawing.Color.Magenta; - this.FreezeAddressToolBarItem.Name = "FreezeAddressToolBarItem"; - this.FreezeAddressToolBarItem.Size = new System.Drawing.Size(23, 22); - this.FreezeAddressToolBarItem.Text = "Freeze Address"; - this.FreezeAddressToolBarItem.Click += new System.EventHandler(this.FreezeAddressMenuItem_Click); - // - // seperatorToolStripButton - // - this.seperatorToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.seperatorToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.seperatorToolStripButton.Name = "seperatorToolStripButton"; - this.seperatorToolStripButton.Size = new System.Drawing.Size(23, 22); - this.seperatorToolStripButton.Text = "-"; - this.seperatorToolStripButton.ToolTipText = "Insert Separator"; - this.seperatorToolStripButton.Click += new System.EventHandler(this.InsertSeparatorMenuItem_Click); - // - // moveUpToolStripButton - // - this.moveUpToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.moveUpToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.moveUpToolStripButton.Name = "moveUpToolStripButton"; - this.moveUpToolStripButton.Size = new System.Drawing.Size(23, 22); - this.moveUpToolStripButton.Text = "Move Up"; - this.moveUpToolStripButton.Click += new System.EventHandler(this.MoveUpMenuItem_Click); - // - // moveDownToolStripButton - // - this.moveDownToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.moveDownToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; - this.moveDownToolStripButton.Name = "moveDownToolStripButton"; - this.moveDownToolStripButton.Size = new System.Drawing.Size(23, 22); - this.moveDownToolStripButton.Text = "Move Down"; - this.moveDownToolStripButton.Click += new System.EventHandler(this.MoveDownMenuItem_Click); - // - // RamWatchMenu - // - this.RamWatchMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStrip1.Location = new System.Drawing.Point(0, 24); + this.toolStrip1.Name = "toolStrip1"; + this.toolStrip1.TabIndex = 4; + this.toolStrip1.TabStop = true; + // + // newToolStripButton + // + this.newToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.newToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.newToolStripButton.Name = "newToolStripButton"; + this.newToolStripButton.Size = new System.Drawing.Size(23, 22); + this.newToolStripButton.Text = "&New"; + this.newToolStripButton.Click += new System.EventHandler(this.NewListMenuItem_Click); + // + // openToolStripButton + // + this.openToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.openToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.openToolStripButton.Name = "openToolStripButton"; + this.openToolStripButton.Size = new System.Drawing.Size(23, 22); + this.openToolStripButton.Text = "&Open"; + this.openToolStripButton.Click += new System.EventHandler(this.OpenMenuItem_Click); + // + // saveToolStripButton + // + this.saveToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.saveToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.saveToolStripButton.Name = "saveToolStripButton"; + this.saveToolStripButton.Size = new System.Drawing.Size(23, 22); + this.saveToolStripButton.Text = "&Save"; + this.saveToolStripButton.Click += new System.EventHandler(this.SaveMenuItem_Click); + // + // newWatchToolStripButton + // + this.newWatchToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.newWatchToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.newWatchToolStripButton.Name = "newWatchToolStripButton"; + this.newWatchToolStripButton.Size = new System.Drawing.Size(23, 22); + this.newWatchToolStripButton.Text = "New Watch"; + this.newWatchToolStripButton.ToolTipText = "New Watch"; + this.newWatchToolStripButton.Click += new System.EventHandler(this.NewWatchMenuItem_Click); + // + // editWatchToolStripButton + // + this.editWatchToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.editWatchToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.editWatchToolStripButton.Name = "editWatchToolStripButton"; + this.editWatchToolStripButton.Size = new System.Drawing.Size(23, 22); + this.editWatchToolStripButton.Text = "Edit Watch"; + this.editWatchToolStripButton.Click += new System.EventHandler(this.EditWatchMenuItem_Click); + // + // cutToolStripButton + // + this.cutToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.cutToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.cutToolStripButton.Name = "cutToolStripButton"; + this.cutToolStripButton.Size = new System.Drawing.Size(23, 22); + this.cutToolStripButton.Text = "C&ut"; + this.cutToolStripButton.ToolTipText = "Remove Watch"; + this.cutToolStripButton.Click += new System.EventHandler(this.RemoveWatchMenuItem_Click); + // + // clearChangeCountsToolStripButton + // + this.clearChangeCountsToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.clearChangeCountsToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.clearChangeCountsToolStripButton.Name = "clearChangeCountsToolStripButton"; + this.clearChangeCountsToolStripButton.Size = new System.Drawing.Size(23, 22); + this.clearChangeCountsToolStripButton.Text = "C"; + this.clearChangeCountsToolStripButton.ToolTipText = "Clear Change Counts"; + this.clearChangeCountsToolStripButton.Click += new System.EventHandler(this.ClearChangeCountsMenuItem_Click); + // + // duplicateWatchToolStripButton + // + this.duplicateWatchToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.duplicateWatchToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.duplicateWatchToolStripButton.Name = "duplicateWatchToolStripButton"; + this.duplicateWatchToolStripButton.Size = new System.Drawing.Size(23, 22); + this.duplicateWatchToolStripButton.Text = "Duplicate Watch"; + this.duplicateWatchToolStripButton.Click += new System.EventHandler(this.DuplicateWatchMenuItem_Click); + // + // SplitWatchToolStripButton + // + this.SplitWatchToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.SplitWatchToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.SplitWatchToolStripButton.Name = "SplitWatchToolStripButton"; + this.SplitWatchToolStripButton.Size = new System.Drawing.Size(23, 22); + this.SplitWatchToolStripButton.Text = "Split Watch"; + this.SplitWatchToolStripButton.Click += new System.EventHandler(this.SplitWatchMenuItem_Click); + // + // PokeAddressToolBarItem + // + this.PokeAddressToolBarItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.PokeAddressToolBarItem.ImageTransparentColor = System.Drawing.Color.Magenta; + this.PokeAddressToolBarItem.Name = "PokeAddressToolBarItem"; + this.PokeAddressToolBarItem.Size = new System.Drawing.Size(23, 22); + this.PokeAddressToolBarItem.Text = "toolStripButton2"; + this.PokeAddressToolBarItem.ToolTipText = "Poke address"; + this.PokeAddressToolBarItem.Click += new System.EventHandler(this.PokeAddressMenuItem_Click); + // + // FreezeAddressToolBarItem + // + this.FreezeAddressToolBarItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.FreezeAddressToolBarItem.ImageTransparentColor = System.Drawing.Color.Magenta; + this.FreezeAddressToolBarItem.Name = "FreezeAddressToolBarItem"; + this.FreezeAddressToolBarItem.Size = new System.Drawing.Size(23, 22); + this.FreezeAddressToolBarItem.Text = "Freeze Address"; + this.FreezeAddressToolBarItem.Click += new System.EventHandler(this.FreezeAddressMenuItem_Click); + // + // seperatorToolStripButton + // + this.seperatorToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.seperatorToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.seperatorToolStripButton.Name = "seperatorToolStripButton"; + this.seperatorToolStripButton.Size = new System.Drawing.Size(23, 22); + this.seperatorToolStripButton.Text = "-"; + this.seperatorToolStripButton.ToolTipText = "Insert Separator"; + this.seperatorToolStripButton.Click += new System.EventHandler(this.InsertSeparatorMenuItem_Click); + // + // moveUpToolStripButton + // + this.moveUpToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.moveUpToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.moveUpToolStripButton.Name = "moveUpToolStripButton"; + this.moveUpToolStripButton.Size = new System.Drawing.Size(23, 22); + this.moveUpToolStripButton.Text = "Move Up"; + this.moveUpToolStripButton.Click += new System.EventHandler(this.MoveUpMenuItem_Click); + // + // moveDownToolStripButton + // + this.moveDownToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.moveDownToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.moveDownToolStripButton.Name = "moveDownToolStripButton"; + this.moveDownToolStripButton.Size = new System.Drawing.Size(23, 22); + this.moveDownToolStripButton.Text = "Move Down"; + this.moveDownToolStripButton.Click += new System.EventHandler(this.MoveDownMenuItem_Click); + // + // RamWatchMenu + // + this.RamWatchMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.FileSubMenu, this.WatchesSubMenu, this.OptionsSubMenu}); - this.RamWatchMenu.TabIndex = 3; - // - // FileSubMenu - // - this.FileSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.RamWatchMenu.TabIndex = 3; + // + // FileSubMenu + // + this.FileSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.NewListMenuItem, this.OpenMenuItem, this.SaveMenuItem, this.SaveAsMenuItem, this.AppendMenuItem, this.RecentSubMenu}); - this.FileSubMenu.Text = "&Files"; - this.FileSubMenu.DropDownOpened += new System.EventHandler(this.FileSubMenu_DropDownOpened); - // - // NewListMenuItem - // - this.NewListMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N))); - this.NewListMenuItem.Text = "&New List"; - this.NewListMenuItem.Click += new System.EventHandler(this.NewListMenuItem_Click); - // - // OpenMenuItem - // - this.OpenMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); - this.OpenMenuItem.Text = "&Open..."; - this.OpenMenuItem.Click += new System.EventHandler(this.OpenMenuItem_Click); - // - // SaveMenuItem - // - this.SaveMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); - this.SaveMenuItem.Text = "&Save"; - this.SaveMenuItem.Click += new System.EventHandler(this.SaveMenuItem_Click); - // - // SaveAsMenuItem - // - this.SaveAsMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + this.FileSubMenu.Text = "&Files"; + this.FileSubMenu.DropDownOpened += new System.EventHandler(this.FileSubMenu_DropDownOpened); + // + // NewListMenuItem + // + this.NewListMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N))); + this.NewListMenuItem.Text = "&New List"; + this.NewListMenuItem.Click += new System.EventHandler(this.NewListMenuItem_Click); + // + // OpenMenuItem + // + this.OpenMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); + this.OpenMenuItem.Text = "&Open..."; + this.OpenMenuItem.Click += new System.EventHandler(this.OpenMenuItem_Click); + // + // SaveMenuItem + // + this.SaveMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); + this.SaveMenuItem.Text = "&Save"; + this.SaveMenuItem.Click += new System.EventHandler(this.SaveMenuItem_Click); + // + // SaveAsMenuItem + // + this.SaveAsMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) | System.Windows.Forms.Keys.S))); - this.SaveAsMenuItem.Text = "Save &As..."; - this.SaveAsMenuItem.Click += new System.EventHandler(this.SaveAsMenuItem_Click); - // - // AppendMenuItem - // - this.AppendMenuItem.Text = "A&ppend File..."; - this.AppendMenuItem.Click += new System.EventHandler(this.OpenMenuItem_Click); - // - // RecentSubMenu - // - this.RecentSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.SaveAsMenuItem.Text = "Save &As..."; + this.SaveAsMenuItem.Click += new System.EventHandler(this.SaveAsMenuItem_Click); + // + // AppendMenuItem + // + this.AppendMenuItem.Text = "A&ppend File..."; + this.AppendMenuItem.Click += new System.EventHandler(this.OpenMenuItem_Click); + // + // RecentSubMenu + // + this.RecentSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.noneToolStripMenuItem}); - this.RecentSubMenu.Text = "Recent"; - this.RecentSubMenu.DropDownOpened += new System.EventHandler(this.RecentSubMenu_DropDownOpened); - // - // noneToolStripMenuItem - // - this.noneToolStripMenuItem.Text = "None"; - // - // WatchesSubMenu - // - this.WatchesSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.RecentSubMenu.Text = "Recent"; + this.RecentSubMenu.DropDownOpened += new System.EventHandler(this.RecentSubMenu_DropDownOpened); + // + // noneToolStripMenuItem + // + this.noneToolStripMenuItem.Text = "None"; + // + // WatchesSubMenu + // + this.WatchesSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.MemoryDomainsSubMenu, this.toolStripSeparator8, this.NewWatchMenuItem, @@ -502,210 +502,213 @@ private void InitializeComponent() this.MoveTopMenuItem, this.MoveBottomMenuItem, this.SelectAllMenuItem}); - this.WatchesSubMenu.Text = "&Watches"; - this.WatchesSubMenu.DropDownOpened += new System.EventHandler(this.WatchesSubMenu_DropDownOpened); - // - // MemoryDomainsSubMenu - // - this.MemoryDomainsSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.WatchesSubMenu.Text = "&Watches"; + this.WatchesSubMenu.DropDownOpened += new System.EventHandler(this.WatchesSubMenu_DropDownOpened); + // + // MemoryDomainsSubMenu + // + this.MemoryDomainsSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.Separator2}); - this.MemoryDomainsSubMenu.Text = "Default Domain"; - this.MemoryDomainsSubMenu.DropDownOpened += new System.EventHandler(this.MemoryDomainsSubMenu_DropDownOpened); - // - // NewWatchMenuItem - // - this.NewWatchMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.W))); - this.NewWatchMenuItem.Text = "&New Watch"; - this.NewWatchMenuItem.Click += new System.EventHandler(this.NewWatchMenuItem_Click); - // - // EditWatchMenuItem - // - this.EditWatchMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E))); - this.EditWatchMenuItem.Text = "&Edit Watch"; - this.EditWatchMenuItem.Click += new System.EventHandler(this.EditWatchMenuItem_Click); - // - // RemoveWatchMenuItem - // - this.RemoveWatchMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.R))); - this.RemoveWatchMenuItem.Text = "&Remove Watch"; - this.RemoveWatchMenuItem.Click += new System.EventHandler(this.RemoveWatchMenuItem_Click); - // - // DuplicateWatchMenuItem - // - this.DuplicateWatchMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.D))); - this.DuplicateWatchMenuItem.Text = "&Duplicate Watch"; - this.DuplicateWatchMenuItem.Click += new System.EventHandler(this.DuplicateWatchMenuItem_Click); - // - // SplitWatchMenuItem - // - this.SplitWatchMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.L))); - this.SplitWatchMenuItem.Text = "Sp&lit Watch"; - this.SplitWatchMenuItem.Click += new System.EventHandler(this.SplitWatchMenuItem_Click); - // - // PokeAddressMenuItem - // - this.PokeAddressMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P))); - this.PokeAddressMenuItem.Text = "Poke Address"; - this.PokeAddressMenuItem.Click += new System.EventHandler(this.PokeAddressMenuItem_Click); - // - // FreezeAddressMenuItem - // - this.FreezeAddressMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.F))); - this.FreezeAddressMenuItem.Text = "Freeze Address"; - this.FreezeAddressMenuItem.Click += new System.EventHandler(this.FreezeAddressMenuItem_Click); - // - // InsertSeparatorMenuItem - // - this.InsertSeparatorMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.I))); - this.InsertSeparatorMenuItem.Text = "Insert Separator"; - this.InsertSeparatorMenuItem.Click += new System.EventHandler(this.InsertSeparatorMenuItem_Click); - // - // ClearChangeCountsMenuItem - // - this.ClearChangeCountsMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.C))); - this.ClearChangeCountsMenuItem.Text = "&Clear Change Counts"; - this.ClearChangeCountsMenuItem.Click += new System.EventHandler(this.ClearChangeCountsMenuItem_Click); - // - // MoveUpMenuItem - // - this.MoveUpMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Up))); - this.MoveUpMenuItem.Text = "Move &Up"; - this.MoveUpMenuItem.Click += new System.EventHandler(this.MoveUpMenuItem_Click); - // - // MoveDownMenuItem - // - this.MoveDownMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Down))); - this.MoveDownMenuItem.Text = "Move &Down"; - this.MoveDownMenuItem.Click += new System.EventHandler(this.MoveDownMenuItem_Click); - // - // MoveTopMenuItem - // - this.MoveTopMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + this.MemoryDomainsSubMenu.Text = "Default Domain"; + this.MemoryDomainsSubMenu.DropDownOpened += new System.EventHandler(this.MemoryDomainsSubMenu_DropDownOpened); + // + // NewWatchMenuItem + // + this.NewWatchMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.W))); + this.NewWatchMenuItem.Text = "&New Watch"; + this.NewWatchMenuItem.Click += new System.EventHandler(this.NewWatchMenuItem_Click); + // + // EditWatchMenuItem + // + this.EditWatchMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E))); + this.EditWatchMenuItem.Text = "&Edit Watch"; + this.EditWatchMenuItem.Click += new System.EventHandler(this.EditWatchMenuItem_Click); + // + // RemoveWatchMenuItem + // + this.RemoveWatchMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.R))); + this.RemoveWatchMenuItem.Text = "&Remove Watch"; + this.RemoveWatchMenuItem.Click += new System.EventHandler(this.RemoveWatchMenuItem_Click); + // + // DuplicateWatchMenuItem + // + this.DuplicateWatchMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.D))); + this.DuplicateWatchMenuItem.Text = "&Duplicate Watch"; + this.DuplicateWatchMenuItem.Click += new System.EventHandler(this.DuplicateWatchMenuItem_Click); + // + // SplitWatchMenuItem + // + this.SplitWatchMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.L))); + this.SplitWatchMenuItem.Text = "Sp&lit Watch"; + this.SplitWatchMenuItem.Click += new System.EventHandler(this.SplitWatchMenuItem_Click); + // + // PokeAddressMenuItem + // + this.PokeAddressMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P))); + this.PokeAddressMenuItem.Text = "Poke Address"; + this.PokeAddressMenuItem.Click += new System.EventHandler(this.PokeAddressMenuItem_Click); + // + // FreezeAddressMenuItem + // + this.FreezeAddressMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.F))); + this.FreezeAddressMenuItem.Text = "Freeze Address"; + this.FreezeAddressMenuItem.Click += new System.EventHandler(this.FreezeAddressMenuItem_Click); + // + // InsertSeparatorMenuItem + // + this.InsertSeparatorMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.I))); + this.InsertSeparatorMenuItem.Text = "Insert Separator"; + this.InsertSeparatorMenuItem.Click += new System.EventHandler(this.InsertSeparatorMenuItem_Click); + // + // ClearChangeCountsMenuItem + // + this.ClearChangeCountsMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.C))); + this.ClearChangeCountsMenuItem.Text = "&Clear Change Counts"; + this.ClearChangeCountsMenuItem.Click += new System.EventHandler(this.ClearChangeCountsMenuItem_Click); + // + // MoveUpMenuItem + // + this.MoveUpMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Up))); + this.MoveUpMenuItem.Text = "Move &Up"; + this.MoveUpMenuItem.Click += new System.EventHandler(this.MoveUpMenuItem_Click); + // + // MoveDownMenuItem + // + this.MoveDownMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Down))); + this.MoveDownMenuItem.Text = "Move &Down"; + this.MoveDownMenuItem.Click += new System.EventHandler(this.MoveDownMenuItem_Click); + // + // MoveTopMenuItem + // + this.MoveTopMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) | System.Windows.Forms.Keys.Up))); - this.MoveTopMenuItem.Text = "Move &Top"; - this.MoveTopMenuItem.Click += new System.EventHandler(this.MoveTopMenuItem_Click); - // - // MoveBottomMenuItem - // - this.MoveBottomMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + this.MoveTopMenuItem.Text = "Move &Top"; + this.MoveTopMenuItem.Click += new System.EventHandler(this.MoveTopMenuItem_Click); + // + // MoveBottomMenuItem + // + this.MoveBottomMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) | System.Windows.Forms.Keys.Down))); - this.MoveBottomMenuItem.Text = "Move &Bottom"; - this.MoveBottomMenuItem.Click += new System.EventHandler(this.MoveBottomMenuItem_Click); - // - // SelectAllMenuItem - // - this.SelectAllMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys) ((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.A))); - this.SelectAllMenuItem.ShortcutKeyDisplayString = "Ctrl+A"; - this.SelectAllMenuItem.Text = "Select &All"; - this.SelectAllMenuItem.Click += new System.EventHandler(this.SelectAllMenuItem_Click); - // - // OptionsSubMenu - // - this.OptionsSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.MoveBottomMenuItem.Text = "Move &Bottom"; + this.MoveBottomMenuItem.Click += new System.EventHandler(this.MoveBottomMenuItem_Click); + // + // SelectAllMenuItem + // + this.SelectAllMenuItem.ShortcutKeyDisplayString = "Ctrl+A"; + this.SelectAllMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.A))); + this.SelectAllMenuItem.Text = "Select &All"; + this.SelectAllMenuItem.Click += new System.EventHandler(this.SelectAllMenuItem_Click); + // + // OptionsSubMenu + // + this.OptionsSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.DefinePreviousValueSubMenu, this.WatchesOnScreenMenuItem, this.DoubleClickActionSubMenu}); - this.OptionsSubMenu.Text = "&Settings"; - this.OptionsSubMenu.DropDownOpened += new System.EventHandler(this.SettingsSubMenu_DropDownOpened); - // - // DefinePreviousValueSubMenu - // - this.DefinePreviousValueSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.OptionsSubMenu.Text = "&Settings"; + this.OptionsSubMenu.DropDownOpened += new System.EventHandler(this.SettingsSubMenu_DropDownOpened); + // + // DefinePreviousValueSubMenu + // + this.DefinePreviousValueSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.PreviousFrameMenuItem, this.LastChangeMenuItem, this.OriginalMenuItem}); - this.DefinePreviousValueSubMenu.Text = "Define Previous Value"; - this.DefinePreviousValueSubMenu.DropDownOpened += new System.EventHandler(this.DefinePreviousValueSubMenu_DropDownOpened); - // - // PreviousFrameMenuItem - // - this.PreviousFrameMenuItem.Text = "Previous Frame"; - this.PreviousFrameMenuItem.Click += new System.EventHandler(this.PreviousFrameMenuItem_Click); - // - // LastChangeMenuItem - // - this.LastChangeMenuItem.Text = "Last Change"; - this.LastChangeMenuItem.Click += new System.EventHandler(this.LastChangeMenuItem_Click); - // - // OriginalMenuItem - // - this.OriginalMenuItem.Text = "&Original"; - this.OriginalMenuItem.Click += new System.EventHandler(this.OriginalMenuItem_Click); - // - // WatchesOnScreenMenuItem - // - this.WatchesOnScreenMenuItem.Text = "Display Watches On Screen"; - this.WatchesOnScreenMenuItem.Click += new System.EventHandler(this.WatchesOnScreenMenuItem_Click); - // - // WatchListView - // - this.WatchListView.CellWidthPadding = 3; - this.WatchListView.AllowColumnResize = true; - this.WatchListView.AllowColumnReorder = true; - this.WatchListView.FullRowSelect = true; - this.WatchListView.MultiSelect = true; - this.WatchListView.AllowColumnReorder = true; - this.WatchListView.AllowDrop = true; - this.WatchListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.WatchListView.ContextMenuStrip = this.ListViewContextMenu; - this.WatchListView.FullRowSelect = true; - this.WatchListView.GridLines = true; - this.WatchListView.Location = new System.Drawing.Point(16, 76); - this.WatchListView.Name = "WatchListView"; - this.WatchListView.Size = new System.Drawing.Size(363, 281); - this.WatchListView.TabIndex = 2; - this.WatchListView.ColumnClick += new BizHawk.Client.EmuHawk.InputRoll.ColumnClickEventHandler(this.WatchListView_ColumnClick); - this.WatchListView.SelectedIndexChanged += new System.EventHandler(this.WatchListView_SelectedIndexChanged); - this.WatchListView.DragDrop += new System.Windows.Forms.DragEventHandler(this.RamWatch_DragDrop); - this.WatchListView.DragEnter += new System.Windows.Forms.DragEventHandler(this.DragEnterWrapper); - this.WatchListView.KeyDown += new System.Windows.Forms.KeyEventHandler(this.WatchListView_KeyDown); - this.WatchListView.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.WatchListView_MouseDoubleClick); - // - // DoubleClickActionSubMenu - // - this.DoubleClickActionSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.DefinePreviousValueSubMenu.Text = "Define Previous Value"; + this.DefinePreviousValueSubMenu.DropDownOpened += new System.EventHandler(this.DefinePreviousValueSubMenu_DropDownOpened); + // + // PreviousFrameMenuItem + // + this.PreviousFrameMenuItem.Text = "Previous Frame"; + this.PreviousFrameMenuItem.Click += new System.EventHandler(this.PreviousFrameMenuItem_Click); + // + // LastChangeMenuItem + // + this.LastChangeMenuItem.Text = "Last Change"; + this.LastChangeMenuItem.Click += new System.EventHandler(this.LastChangeMenuItem_Click); + // + // OriginalMenuItem + // + this.OriginalMenuItem.Text = "&Original"; + this.OriginalMenuItem.Click += new System.EventHandler(this.OriginalMenuItem_Click); + // + // WatchesOnScreenMenuItem + // + this.WatchesOnScreenMenuItem.Text = "Display Watches On Screen"; + this.WatchesOnScreenMenuItem.Click += new System.EventHandler(this.WatchesOnScreenMenuItem_Click); + // + // DoubleClickActionSubMenu + // + this.DoubleClickActionSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.DoubleClickToEditMenuItem, this.DoubleClickToPokeMenuItem}); - this.DoubleClickActionSubMenu.Text = "On Double-Clicking a Watch"; - this.DoubleClickActionSubMenu.DropDownOpening += new System.EventHandler(this.DoubleClickActionSubMenu_DropDownOpening); - // - // DoubleClickToEditMenuItem - // - this.DoubleClickToEditMenuItem.Text = "Edit Watch"; - this.DoubleClickToEditMenuItem.Click += new System.EventHandler(this.DoubleClickToEditMenuItem_Click); - // - // DoubleClickToPokeMenuItem - // - this.DoubleClickToPokeMenuItem.Text = "Poke Address"; - this.DoubleClickToPokeMenuItem.Click += new System.EventHandler(this.DoubleClickToPokeMenuItem_Click); - // - // RamWatch - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(395, 378); - this.Controls.Add(this.statusStrip1); - this.Controls.Add(this.WatchCountLabel); - this.Controls.Add(this.toolStrip1); - this.Controls.Add(this.RamWatchMenu); - this.Controls.Add(this.WatchListView); - this.Name = "RamWatch"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Load += new System.EventHandler(this.RamWatch_Load); - this.DragDrop += new System.Windows.Forms.DragEventHandler(this.RamWatch_DragDrop); - this.DragEnter += new System.Windows.Forms.DragEventHandler(this.DragEnterWrapper); - this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.WatchListView_KeyDown); - this.ListViewContextMenu.ResumeLayout(false); - this.statusStrip1.ResumeLayout(false); - this.statusStrip1.PerformLayout(); - this.toolStrip1.ResumeLayout(false); - this.toolStrip1.PerformLayout(); - this.RamWatchMenu.ResumeLayout(false); - this.RamWatchMenu.PerformLayout(); - this.ResumeLayout(false); - this.PerformLayout(); + this.DoubleClickActionSubMenu.Text = "On Double-Clicking a Watch"; + this.DoubleClickActionSubMenu.DropDownOpening += new System.EventHandler(this.DoubleClickActionSubMenu_DropDownOpening); + // + // DoubleClickToEditMenuItem + // + this.DoubleClickToEditMenuItem.Text = "Edit Watch"; + this.DoubleClickToEditMenuItem.Click += new System.EventHandler(this.DoubleClickToEditMenuItem_Click); + // + // DoubleClickToPokeMenuItem + // + this.DoubleClickToPokeMenuItem.Text = "Poke Address"; + this.DoubleClickToPokeMenuItem.Click += new System.EventHandler(this.DoubleClickToPokeMenuItem_Click); + // + // WatchListView + // + this.WatchListView.AllowColumnReorder = true; + this.WatchListView.AllowColumnResize = true; + this.WatchListView.AllowDrop = true; + this.WatchListView.AlwaysScroll = false; + this.WatchListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.WatchListView.CellHeightPadding = 0; + this.WatchListView.CellWidthPadding = 0; + this.WatchListView.ContextMenuStrip = this.ListViewContextMenu; + this.WatchListView.FullRowSelect = true; + this.WatchListView.HorizontalOrientation = false; + this.WatchListView.LetKeysModifySelection = false; + this.WatchListView.Location = new System.Drawing.Point(16, 76); + this.WatchListView.Name = "WatchListView"; + this.WatchListView.RowCount = 0; + this.WatchListView.ScrollSpeed = 0; + this.WatchListView.SeekingCutoffInterval = 0; + this.WatchListView.Size = new System.Drawing.Size(363, 281); + this.WatchListView.TabIndex = 2; + this.WatchListView.ColumnClick += new BizHawk.Client.EmuHawk.InputRoll.ColumnClickEventHandler(this.WatchListView_ColumnClick); + this.WatchListView.SelectedIndexChanged += new System.EventHandler(this.WatchListView_SelectedIndexChanged); + this.WatchListView.DragDrop += new System.Windows.Forms.DragEventHandler(this.RamWatch_DragDrop); + this.WatchListView.DragEnter += new System.Windows.Forms.DragEventHandler(this.DragEnterWrapper); + this.WatchListView.KeyDown += new System.Windows.Forms.KeyEventHandler(this.WatchListView_KeyDown); + this.WatchListView.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.WatchListView_MouseDoubleClick); + // + // RamWatch + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(395, 378); + this.Controls.Add(this.statusStrip1); + this.Controls.Add(this.WatchCountLabel); + this.Controls.Add(this.toolStrip1); + this.Controls.Add(this.RamWatchMenu); + this.Controls.Add(this.WatchListView); + this.Name = "RamWatch"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Load += new System.EventHandler(this.RamWatch_Load); + this.DragDrop += new System.Windows.Forms.DragEventHandler(this.RamWatch_DragDrop); + this.DragEnter += new System.Windows.Forms.DragEventHandler(this.DragEnterWrapper); + this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.WatchListView_KeyDown); + this.ListViewContextMenu.ResumeLayout(false); + this.statusStrip1.ResumeLayout(false); + this.statusStrip1.PerformLayout(); + this.toolStrip1.ResumeLayout(false); + this.toolStrip1.PerformLayout(); + this.RamWatchMenu.ResumeLayout(false); + this.RamWatchMenu.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); } diff --git a/src/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.cs b/src/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.cs index e0c2e1e1026..4a994474abc 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; @@ -581,7 +580,7 @@ private void OrderColumn(RollColumn column) _watches.OrderWatches(column.Name, _sortReverse); _sortedColumn = column.Name; - _sortReverse ^= true; + _sortReverse = !_sortReverse; WatchListView.Refresh(); } @@ -928,7 +927,7 @@ private void MoveDownMenuItem_Click(object sender, EventArgs e) { var indices = SelectedIndices.ToList(); if (indices.Count == 0 - || indices[^1] == _watches.Count - 1) // at end already + || indices[indices.Count - 1] == _watches.Count - 1) // at end already { return; } @@ -1042,8 +1041,7 @@ private void OriginalMenuItem_Click(object sender, EventArgs e) private void WatchesOnScreenMenuItem_Click(object sender, EventArgs e) { - Config.DisplayRamWatch ^= true; - + Config.DisplayRamWatch = !Config.DisplayRamWatch; if (!Config.DisplayRamWatch) { DisplayManager.OSD.ClearRamWatches(); @@ -1252,9 +1250,7 @@ private void WatchListView_MouseDoubleClick(object sender, MouseEventArgs e) } private void WatchListView_ColumnClick(object sender, InputRoll.ColumnClickEventArgs e) - { - OrderColumn(e.Column); - } + => OrderColumn(e.Column!); private void ErrorIconButton_Click(object sender, EventArgs e) { diff --git a/src/BizHawk.Client.EmuHawk/tools/Watch/WatchEditor.cs b/src/BizHawk.Client.EmuHawk/tools/Watch/WatchEditor.cs index 7b20ab3490d..92550e08074 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Watch/WatchEditor.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Watch/WatchEditor.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -276,7 +275,7 @@ private void DoEdit() Watches[i] = Watch.GenerateWatch( Watches[i].Domain, - Watches.Count == 1 ? AddressBox.ToRawInt() ?? 0 : Watches[i].Address, + Watches.Count == 1 ? AddressBox.ToRawUInt() ?? 0 : Watches[i].Address, size, _changedDisplayType ? displayType : Watches[i].Type, Watches[i].BigEndian, diff --git a/src/BizHawk.Client.EmuHawk/tools/Watch/WatchValueBox.cs b/src/BizHawk.Client.EmuHawk/tools/Watch/WatchValueBox.cs index 08875e8cd3f..560bc4b99af 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Watch/WatchValueBox.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Watch/WatchValueBox.cs @@ -1,13 +1,14 @@ -using System; using System.Globalization; using System.Linq; using System.Windows.Forms; using BizHawk.Client.Common; +using BizHawk.Client.EmuHawk.CustomControls; using BizHawk.Common.NumberExtensions; +using BizHawk.Common.StringExtensions; namespace BizHawk.Client.EmuHawk { - public class WatchValueBox : TextBox, INumberBox + public class WatchValueBox : ClipboardEventTextBox, INumberBox { private WatchSize _size = WatchSize.Byte; private WatchDisplayType _type = WatchDisplayType.Hex; @@ -54,10 +55,10 @@ public WatchDisplayType Type get => _type; set { - var val = ToRawInt(); + var val = ToRawUInt(); _type = value; SetMaxLength(); - SetFromRawInt(val); + SetFromRawUInt(val); } } @@ -195,7 +196,7 @@ protected override void OnKeyDown(KeyEventArgs e) { default: case WatchDisplayType.Signed: - int val = ToRawInt() ?? 0; + int val = (int)(ToRawUInt() ?? 0); if (val == MaxSignedInt) { val = MinSignedInt; @@ -208,7 +209,7 @@ protected override void OnKeyDown(KeyEventArgs e) Text = val.ToString(); break; case WatchDisplayType.Unsigned: - var uval = (uint)(ToRawInt() ?? 0); + var uval = ToRawUInt() ?? 0; if (uval == MaxUnsignedInt) { uval = 0; @@ -221,7 +222,7 @@ protected override void OnKeyDown(KeyEventArgs e) Text = uval.ToString(); break; case WatchDisplayType.Binary: - var bVal = (uint)(ToRawInt() ?? 0); + var bVal = ToRawUInt() ?? 0; if (bVal == MaxUnsignedInt) { bVal = 0; @@ -235,7 +236,7 @@ protected override void OnKeyDown(KeyEventArgs e) Text = Convert.ToString(bVal, 2).PadLeft(numBits, '0'); break; case WatchDisplayType.Hex: - var hexVal = (uint)(ToRawInt() ?? 0); + var hexVal = ToRawUInt() ?? 0; if (hexVal == MaxUnsignedInt) { hexVal = 0; @@ -307,7 +308,7 @@ protected override void OnKeyDown(KeyEventArgs e) { default: case WatchDisplayType.Signed: - int val = ToRawInt() ?? 0; + int val = (int)(ToRawUInt() ?? 0); if (val == MinSignedInt) { val = MaxSignedInt; @@ -320,7 +321,7 @@ protected override void OnKeyDown(KeyEventArgs e) Text = val.ToString(); break; case WatchDisplayType.Unsigned: - var uval = (uint)(ToRawInt() ?? 0); + var uval = ToRawUInt() ?? 0; if (uval == 0) { uval = MaxUnsignedInt; @@ -333,7 +334,7 @@ protected override void OnKeyDown(KeyEventArgs e) Text = uval.ToString(); break; case WatchDisplayType.Binary: - var bVal = (uint)(ToRawInt() ?? 0); + var bVal = ToRawUInt() ?? 0; if (bVal == 0) { bVal = MaxUnsignedInt; @@ -347,7 +348,7 @@ protected override void OnKeyDown(KeyEventArgs e) Text = Convert.ToString(bVal, 2).PadLeft(numBits, '0'); break; case WatchDisplayType.Hex: - var hexVal = (uint)(ToRawInt() ?? 0); + var hexVal = ToRawUInt() ?? 0; if (hexVal == 0) { hexVal = MaxUnsignedInt; @@ -431,21 +432,33 @@ protected override void OnTextChanged(EventArgs e) base.OnTextChanged(e); } - public int? ToRawInt() + protected override void OnPaste(PasteEventArgs e) + { + if (Type is WatchDisplayType.Hex && e.ContainsText) + { + string text = e.Text.CleanHex(); + PasteWithMaxLength(text); + e.Handled = true; + } + + base.OnPaste(e); + } + + public uint? ToRawUInt() { try { return _type switch { - WatchDisplayType.Signed => int.Parse(Text), - WatchDisplayType.Unsigned => (int)uint.Parse(Text), - WatchDisplayType.Binary => Convert.ToInt32(Text, 2), - WatchDisplayType.Hex => int.Parse(Text, NumberStyles.HexNumber), - WatchDisplayType.FixedPoint_12_4 => (int)(double.Parse(Text, NumberFormatInfo.InvariantInfo) * 16.0), - WatchDisplayType.FixedPoint_20_12 => (int)(double.Parse(Text, NumberFormatInfo.InvariantInfo) * 4096.0), - WatchDisplayType.FixedPoint_16_16 => (int)(double.Parse(Text, NumberFormatInfo.InvariantInfo) * 65536.0), - WatchDisplayType.Float => BitConverter.ToInt32(BitConverter.GetBytes(float.Parse(Text, NumberFormatInfo.InvariantInfo)), 0), - _ => int.Parse(Text) + WatchDisplayType.Signed => (uint)int.Parse(Text), + WatchDisplayType.Unsigned => uint.Parse(Text), + WatchDisplayType.Binary => Convert.ToUInt32(Text, 2), + WatchDisplayType.Hex => uint.Parse(Text, NumberStyles.HexNumber), + WatchDisplayType.FixedPoint_12_4 => (uint)(double.Parse(Text, NumberFormatInfo.InvariantInfo) * 16.0), + WatchDisplayType.FixedPoint_20_12 => (uint)(double.Parse(Text, NumberFormatInfo.InvariantInfo) * 4096.0), + WatchDisplayType.FixedPoint_16_16 => (uint)(double.Parse(Text, NumberFormatInfo.InvariantInfo) * 65536.0), + WatchDisplayType.Float => NumberExtensions.ReinterpretAsUInt32(float.Parse(Text, NumberFormatInfo.InvariantInfo)), + _ => uint.Parse(Text) }; } catch @@ -456,7 +469,7 @@ protected override void OnTextChanged(EventArgs e) return Nullable ? null : 0; } - public void SetFromRawInt(int? val) + public void SetFromRawUInt(uint? val) { if (val.HasValue) { @@ -467,11 +480,11 @@ public void SetFromRawInt(int? val) Text = val.Value.ToString(); break; case WatchDisplayType.Unsigned: - var uval = (uint)val.Value; + var uval = val.Value; Text = uval.ToString(); break; case WatchDisplayType.Binary: - var bVal = (uint)val.Value; + var bVal = val.Value; var numBits = ((int)ByteSize) * 8; Text = Convert.ToString(bVal, 2).PadLeft(numBits, '0'); break; @@ -488,8 +501,7 @@ public void SetFromRawInt(int? val) Text = (val.Value / 65536.0).ToString("F5", NumberFormatInfo.InvariantInfo); break; case WatchDisplayType.Float: - var bytes = BitConverter.GetBytes(val.Value); - float _float = BitConverter.ToSingle(bytes, 0); + float _float = NumberExtensions.ReinterpretAsF32(val.Value); Text = _float.ToString("F6", NumberFormatInfo.InvariantInfo); break; } diff --git a/src/BizHawk.Common/BPSPatcher.cs b/src/BizHawk.Common/BPSPatcher.cs index 3b6bc1e5f6f..5f2c9aa13d7 100644 --- a/src/BizHawk.Common/BPSPatcher.cs +++ b/src/BizHawk.Common/BPSPatcher.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; diff --git a/src/BizHawk.Common/BizHawk.Common.csproj b/src/BizHawk.Common/BizHawk.Common.csproj index 24c41336981..ece8e6f2457 100644 --- a/src/BizHawk.Common/BizHawk.Common.csproj +++ b/src/BizHawk.Common/BizHawk.Common.csproj @@ -16,4 +16,8 @@ + + + diff --git a/src/BizHawk.Common/Colors.cs b/src/BizHawk.Common/Colors.cs index 1d6802561b7..a770e3e3348 100644 --- a/src/BizHawk.Common/Colors.cs +++ b/src/BizHawk.Common/Colors.cs @@ -1,6 +1,8 @@ namespace BizHawk.Common { +#pragma warning disable MA0104 // unlikely to conflict with System.Windows.Media.Colors public static class Colors +#pragma warning restore MA0104 { /// This is just Color.FromArgb(alpha, red, green, blue).ToArgb() with extra steps. public static int ARGB(byte red, byte green, byte blue, byte alpha = 0xFF) => unchecked((int) ((uint) (alpha << 24) | (uint) (red << 16) | (uint) (green << 8) | blue)); diff --git a/src/BizHawk.Common/CustomCollections.cs b/src/BizHawk.Common/CustomCollections.cs index 87b1e113958..83c76634540 100644 --- a/src/BizHawk.Common/CustomCollections.cs +++ b/src/BizHawk.Common/CustomCollections.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; diff --git a/src/BizHawk.Common/DeepEquality.cs b/src/BizHawk.Common/DeepEquality.cs index c02de6f381f..4ef0646a855 100644 --- a/src/BizHawk.Common/DeepEquality.cs +++ b/src/BizHawk.Common/DeepEquality.cs @@ -1,8 +1,8 @@ -using System; using System.Collections.Generic; -using System.Linq; using System.Reflection; +using BizHawk.Common.StringExtensions; + namespace BizHawk.Common { /// Annotated fields will not be used by for comparison. @@ -24,7 +24,7 @@ private static bool IsNonZeroBasedArray(Type t) } // is there a better way to do this? i couldn't find any documentation... - return t.ToString().Contains('*'); + return t.ToString().ContainsOrdinal('*'); } /// diff --git a/src/BizHawk.Common/DeltaSerializer.cs b/src/BizHawk.Common/DeltaSerializer.cs index c69d0fed54a..9ec2acb7e91 100644 --- a/src/BizHawk.Common/DeltaSerializer.cs +++ b/src/BizHawk.Common/DeltaSerializer.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; namespace BizHawk.Common diff --git a/src/BizHawk.Common/EndiannessUtils.cs b/src/BizHawk.Common/EndiannessUtils.cs index cb00446bb0d..e0322bdec0d 100644 --- a/src/BizHawk.Common/EndiannessUtils.cs +++ b/src/BizHawk.Common/EndiannessUtils.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; namespace BizHawk.Common diff --git a/src/BizHawk.Common/Extensions/BufferExtensions.cs b/src/BizHawk.Common/Extensions/BufferExtensions.cs index 43b16777dab..662270d524b 100644 --- a/src/BizHawk.Common/Extensions/BufferExtensions.cs +++ b/src/BizHawk.Common/Extensions/BufferExtensions.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/BizHawk.Common/Extensions/CollectionExtensions.cs b/src/BizHawk.Common/Extensions/CollectionExtensions.cs index 49b2f2fc1a8..5af174e14d6 100644 --- a/src/BizHawk.Common/Extensions/CollectionExtensions.cs +++ b/src/BizHawk.Common/Extensions/CollectionExtensions.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; @@ -7,7 +6,9 @@ namespace BizHawk.Common.CollectionExtensions { +#pragma warning disable MA0104 // unlikely to conflict with System.Collections.Generic.CollectionExtensions public static class CollectionExtensions +#pragma warning restore MA0104 { public static IOrderedEnumerable OrderBy( this IEnumerable source, @@ -146,7 +147,7 @@ public static bool CountIsExactly(this IEnumerable collection, int n) ? countable.Count == n : collection.Take(n + 1).Count() == n; -#if !NET6_0 +#if !(NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_0_OR_GREATER) /// /// Returns the value at . /// If the key is not present, returns default(TValue). diff --git a/src/BizHawk.Common/Extensions/IOExtensions.cs b/src/BizHawk.Common/Extensions/IOExtensions.cs index 956b2747257..212addfd03a 100644 --- a/src/BizHawk.Common/Extensions/IOExtensions.cs +++ b/src/BizHawk.Common/Extensions/IOExtensions.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Text; @@ -43,9 +42,7 @@ public static byte[] ReadAllBytes(this BinaryReader br) /// /// Read a string from a binary reader using utf8 encoding and known byte length /// - /// /// exact number of bytes to read - /// public static string ReadStringFixedUtf8(this BinaryReader r, int bytes) { var read = new byte[bytes]; @@ -56,8 +53,6 @@ public static string ReadStringFixedUtf8(this BinaryReader r, int bytes) /// /// Read a null terminated string from a binary reader using utf8 encoding /// - /// - /// public static string ReadStringUtf8NullTerminated(this BinaryReader br) { using var ms = new MemoryStream(); diff --git a/src/BizHawk.Common/Extensions/NumberExtensions.cs b/src/BizHawk.Common/Extensions/NumberExtensions.cs index 204e723489c..0f236461f2b 100644 --- a/src/BizHawk.Common/Extensions/NumberExtensions.cs +++ b/src/BizHawk.Common/Extensions/NumberExtensions.cs @@ -1,5 +1,5 @@ -using System; using System.Linq; +using System.Runtime.CompilerServices; namespace BizHawk.Common.NumberExtensions { @@ -121,6 +121,17 @@ public static T Clamp(this T val, T min, T max) where T : IComparable return val; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static IntPtr Plus(this IntPtr p, int offset) + => p + offset; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static IntPtr Plus(this IntPtr p, uint offset) + { + var half = unchecked((int) offset >> 1); + return p + half + unchecked((int) (offset - half)); + } + public static void RotateRightU8(ref byte b, int shift) { byte temp = b; @@ -144,5 +155,11 @@ public static void RotateRightU8(ref byte b, int shift) /// don't use this in cores without picking a suitable ε public static bool HawkFloatEquality(this float f, float other, float ε = ReallySmallNumber) => Math.Abs(other - f) < ε; + + /// Reinterprets the byte representation of as a float + public static float ReinterpretAsF32(uint value) => Unsafe.As(ref value); + + /// Reinterprets the byte representation of as a uint + public static uint ReinterpretAsUInt32(float value) => Unsafe.As(ref value); } } diff --git a/src/BizHawk.Common/Extensions/NumericStringExtensions.cs b/src/BizHawk.Common/Extensions/NumericStringExtensions.cs index 755108c245f..d4d32d4952d 100644 --- a/src/BizHawk.Common/Extensions/NumericStringExtensions.cs +++ b/src/BizHawk.Common/Extensions/NumericStringExtensions.cs @@ -1,6 +1,6 @@ -using System; using System.Globalization; using System.Linq; +using System.Text.RegularExpressions; namespace BizHawk.Common.StringExtensions { @@ -33,6 +33,23 @@ public static class NumericStringExtensions /// public static string OnlyHex(this string? raw) => string.IsNullOrWhiteSpace(raw) ? string.Empty : string.Concat(raw.Where(IsHex)).ToUpperInvariant(); + /// + /// A copy of in uppercase after removing 0x/$ prefixes and all whitespace, or + /// if contains other non-hex characters. + /// + public static string CleanHex(this string? raw) + { + if (raw is not null && CleanHexRegex.Match(raw) is { Success: true} match) + { + return match.Groups["hex"].Value.OnlyHex(); + } + else + { + return string.Empty; + } + } + private static readonly Regex CleanHexRegex = new(@"^\s*(?:0x|\$)?(?[0-9A-Fa-f\s]+)\s*$"); + #if NET7_0_OR_GREATER public static ushort ParseU16FromHex(ReadOnlySpan str) => ushort.Parse(str, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); diff --git a/src/BizHawk.Common/Extensions/PathExtensions.cs b/src/BizHawk.Common/Extensions/PathExtensions.cs index fbbdb5289a5..fe9dac7bec6 100644 --- a/src/BizHawk.Common/Extensions/PathExtensions.cs +++ b/src/BizHawk.Common/Extensions/PathExtensions.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Common.StringExtensions; @@ -154,7 +153,7 @@ public static (string? Dir, string File) SplitPathToDirAndFile(this string path) public static (string? Dir, string FileNoExt, string? FileExt) SplitPathToDirFileAndExt(this string path) => ( - Path.GetDirectoryName(path), + string.IsNullOrEmpty(path) ? null : Path.GetDirectoryName(path), Path.GetFileNameWithoutExtension(path), Path.GetExtension(path) is { Length: not 0 } ext ? ext diff --git a/src/BizHawk.Common/Extensions/ReflectionExtensions.cs b/src/BizHawk.Common/Extensions/ReflectionExtensions.cs index 94ea1ee6501..a91b1154cb6 100644 --- a/src/BizHawk.Common/Extensions/ReflectionExtensions.cs +++ b/src/BizHawk.Common/Extensions/ReflectionExtensions.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Collections.Generic; using System.ComponentModel; @@ -95,14 +94,7 @@ public static T GetEnumFromDescription(this string description) /// Takes an enum Type and generates a list of strings from the description attributes /// public static IEnumerable GetEnumDescriptions(this Type type) - { - var vals = Enum.GetValues(type); - - foreach (var v in vals) - { - yield return v.GetDescription(); - } - } + => Enum.GetValues(type).Cast().Select(static v => v.GetDescription()); public static T GetAttribute(this object o) { diff --git a/src/BizHawk.Common/Extensions/StringExtensions.cs b/src/BizHawk.Common/Extensions/StringExtensions.cs index 4a15b1b6a24..3855b678c32 100644 --- a/src/BizHawk.Common/Extensions/StringExtensions.cs +++ b/src/BizHawk.Common/Extensions/StringExtensions.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Runtime.CompilerServices; @@ -13,9 +12,31 @@ public static string CharCodepointsToString(byte[] array) return new(a); } +#if !(NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER) + public static bool Contains(this string haystack, char needle) + => haystack.IndexOf(needle) >= 0; +#endif + public static bool Contains(this string haystack, string needle, StringComparison comparisonType) => haystack.IndexOf(needle, comparisonType) != -1; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsOrdinal(this string haystack, char needle) + => haystack.Contains(needle); // already ordinal + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsOrdinal(this string haystack, string needle) + => haystack.Contains(needle); // already ordinal + +#if !(NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER) + public static bool EndsWith(this string haystack, char needle) + => haystack.Length >= 1 && haystack[^1] == needle; +#endif + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool EndsWithOrdinal(this string haystack, char needle) + => haystack.EndsWith(needle); // already ordinal + /// /// if appears in (case-insensitive) /// diff --git a/src/BizHawk.Common/FFmpegService.cs b/src/BizHawk.Common/FFmpegService.cs index 87e0568e655..a3977883f7b 100644 --- a/src/BizHawk.Common/FFmpegService.cs +++ b/src/BizHawk.Common/FFmpegService.cs @@ -1,4 +1,3 @@ -using System; using System.Threading; using System.Collections.Generic; using System.Diagnostics; @@ -8,6 +7,7 @@ using System.IO; using System.Threading.Tasks; using BizHawk.Common.PathExtensions; +using BizHawk.Common.StringExtensions; namespace BizHawk.Common { @@ -29,9 +29,7 @@ public class AudioQueryResult } private static string[] Escape(IEnumerable args) - { - return args.Select(s => s.Contains(" ") ? $"\"{s}\"" : s).ToArray(); - } + => args.Select(static s => s.ContainsOrdinal(' ') ? $"\"{s}\"" : s).ToArray(); //note: accepts . or : in the stream stream/substream separator in the stream ID format, since that changed at some point in FFMPEG history //if someone has a better idea how to make the determination of whether an audio stream is available, I'm all ears diff --git a/src/BizHawk.Common/FPCtrl.cs b/src/BizHawk.Common/FPCtrl.cs index 05384676618..e52089226ee 100644 --- a/src/BizHawk.Common/FPCtrl.cs +++ b/src/BizHawk.Common/FPCtrl.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Common/HawkFile/HawkFile.cs b/src/BizHawk.Common/HawkFile/HawkFile.cs index ac544d53311..05628e77921 100644 --- a/src/BizHawk.Common/HawkFile/HawkFile.cs +++ b/src/BizHawk.Common/HawkFile/HawkFile.cs @@ -1,9 +1,10 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.CompilerServices; using BizHawk.Common.CollectionExtensions; +using BizHawk.Common.StringExtensions; namespace BizHawk.Common { @@ -21,6 +22,10 @@ namespace BizHawk.Common /// public sealed class HawkFile : IDisposable { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool PathContainsPipe(string s) + => s.ContainsOrdinal('|'); + private readonly List? _archiveItems; private Stream? _boundStream; @@ -90,7 +95,7 @@ public HawkFile([HawkFilePath] string path, bool delayIOAndDearchive = false, bo var split1 = SplitArchiveMemberPath(path); if (split1 != null) (path, autobind) = split1.Value; FullPathWithoutMember = path; - Exists = _rootExists = !string.IsNullOrEmpty(path) && new FileInfo(path).Exists; + Exists = _rootExists = File.Exists(path); if (!_rootExists) return; if (DearchivalMethod != null && allowArchives) diff --git a/src/BizHawk.Common/HawkFile/HawkFilePathAttribute.cs b/src/BizHawk.Common/HawkFile/HawkFilePathAttribute.cs index 4c8ae11d68c..54cee27c318 100644 --- a/src/BizHawk.Common/HawkFile/HawkFilePathAttribute.cs +++ b/src/BizHawk.Common/HawkFile/HawkFilePathAttribute.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Common { /// Indicates that a string value is formatted as a path, with an extension to the format: paths followed by '|' and then a relative path represent a member of an archive file. diff --git a/src/BizHawk.Common/HawkFile/IHawkArchiveFile.cs b/src/BizHawk.Common/HawkFile/IHawkArchiveFile.cs index ff3f9663b8e..069d012d46c 100644 --- a/src/BizHawk.Common/HawkFile/IHawkArchiveFile.cs +++ b/src/BizHawk.Common/HawkFile/IHawkArchiveFile.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; diff --git a/src/BizHawk.Common/IImportResolver.cs b/src/BizHawk.Common/IImportResolver.cs index 7d8f6660a0e..017b4a784bf 100644 --- a/src/BizHawk.Common/IImportResolver.cs +++ b/src/BizHawk.Common/IImportResolver.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; namespace BizHawk.Common diff --git a/src/BizHawk.Common/LSB/DlfcnImports.cs b/src/BizHawk.Common/LSB/DlfcnImports.cs index b93d41634dc..b42ef7263c3 100644 --- a/src/BizHawk.Common/LSB/DlfcnImports.cs +++ b/src/BizHawk.Common/LSB/DlfcnImports.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; namespace BizHawk.Common diff --git a/src/BizHawk.Common/LSB/XlibImports.cs b/src/BizHawk.Common/LSB/XlibImports.cs index 242f989e968..96d504ae55a 100644 --- a/src/BizHawk.Common/LSB/XlibImports.cs +++ b/src/BizHawk.Common/LSB/XlibImports.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; // ReSharper disable FieldCanBeMadeReadOnly.Global diff --git a/src/BizHawk.Common/Log.cs b/src/BizHawk.Common/Log.cs index 4b73db550fb..8689e91ad14 100644 --- a/src/BizHawk.Common/Log.cs +++ b/src/BizHawk.Common/Log.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; @@ -24,7 +23,7 @@ static Log() public static void EnableDomain(string domain) { - if (EnabledLogDomains.Contains(domain) == false) + if (!EnabledLogDomains.Contains(domain)) { EnabledLogDomains.Add(domain); } @@ -39,7 +38,9 @@ public static void DisableDomain(string domain) } // -------------- Logging Action Configuration -------------- - public static readonly Action LogAction = DefaultLogger; +#pragma warning disable CA2211 // public field + public static Action LogAction = DefaultLogger; +#pragma warning restore CA2211 // NOTEs are only logged if the domain is enabled. // ERRORs are logged regardless. diff --git a/src/BizHawk.Common/MemoryBlock/IMemoryBlockPal.cs b/src/BizHawk.Common/MemoryBlock/IMemoryBlockPal.cs index dfa06ea61f9..11d613e4754 100644 --- a/src/BizHawk.Common/MemoryBlock/IMemoryBlockPal.cs +++ b/src/BizHawk.Common/MemoryBlock/IMemoryBlockPal.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Common { /// diff --git a/src/BizHawk.Common/MemoryBlock/MemoryBlock.cs b/src/BizHawk.Common/MemoryBlock/MemoryBlock.cs index ab594db764f..f7b416c36d8 100644 --- a/src/BizHawk.Common/MemoryBlock/MemoryBlock.cs +++ b/src/BizHawk.Common/MemoryBlock/MemoryBlock.cs @@ -1,4 +1,3 @@ -using System; using System.IO; namespace BizHawk.Common diff --git a/src/BizHawk.Common/MemoryBlock/MemoryBlockLinuxPal.cs b/src/BizHawk.Common/MemoryBlock/MemoryBlockLinuxPal.cs index 9b3b890447f..eb4ad8dcf04 100644 --- a/src/BizHawk.Common/MemoryBlock/MemoryBlockLinuxPal.cs +++ b/src/BizHawk.Common/MemoryBlock/MemoryBlockLinuxPal.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using static BizHawk.Common.MemoryBlock; @@ -15,7 +14,6 @@ internal sealed class MemoryBlockLinuxPal : IMemoryBlockPal /// /// Map some bytes /// - /// /// /// failed to mmap /// diff --git a/src/BizHawk.Common/MemoryBlock/MemoryBlockUtils.cs b/src/BizHawk.Common/MemoryBlock/MemoryBlockUtils.cs index fe333ec605b..ad4c93d5714 100644 --- a/src/BizHawk.Common/MemoryBlock/MemoryBlockUtils.cs +++ b/src/BizHawk.Common/MemoryBlock/MemoryBlockUtils.cs @@ -1,4 +1,3 @@ -using System; using System.Buffers; using System.IO; diff --git a/src/BizHawk.Common/MemoryBlock/MemoryBlockWindowsPal.cs b/src/BizHawk.Common/MemoryBlock/MemoryBlockWindowsPal.cs index 03090d62785..7d74998e970 100644 --- a/src/BizHawk.Common/MemoryBlock/MemoryBlockWindowsPal.cs +++ b/src/BizHawk.Common/MemoryBlock/MemoryBlockWindowsPal.cs @@ -1,5 +1,3 @@ -using System; - using static BizHawk.Common.MemoryApiImports; using static BizHawk.Common.MemoryBlock; diff --git a/src/BizHawk.Common/MemoryBlock/MemoryViewStream.cs b/src/BizHawk.Common/MemoryBlock/MemoryViewStream.cs index 43a8a73687c..c1b63273007 100644 --- a/src/BizHawk.Common/MemoryBlock/MemoryViewStream.cs +++ b/src/BizHawk.Common/MemoryBlock/MemoryViewStream.cs @@ -1,4 +1,3 @@ -using System; using System.IO; namespace BizHawk.Common @@ -60,7 +59,7 @@ public override void Flush() private byte* CurrentPointer() => (byte*)Z.SS(_ptr + _pos); -#if NET6_0 +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER public override int Read(Span buffer) #else public int Read(Span buffer) @@ -110,7 +109,7 @@ public override long Seek(long offset, SeekOrigin origin) public override void SetLength(long value) => throw new IOException(); -#if NET6_0 +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER public override void Write(ReadOnlySpan buffer) #else public void Write(ReadOnlySpan buffer) diff --git a/src/BizHawk.Common/MultiPredicateSort.cs b/src/BizHawk.Common/MultiPredicateSort.cs index c4e32079e87..bfb8f8b7f68 100644 --- a/src/BizHawk.Common/MultiPredicateSort.cs +++ b/src/BizHawk.Common/MultiPredicateSort.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Common/OSTailoredCode.cs b/src/BizHawk.Common/OSTailoredCode.cs index 5c965d21c1f..ebb6c7cd23b 100644 --- a/src/BizHawk.Common/OSTailoredCode.cs +++ b/src/BizHawk.Common/OSTailoredCode.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using System.Runtime.InteropServices; @@ -216,7 +215,7 @@ public IntPtr GetProcAddrOrThrow(IntPtr hModule, string procName) public IntPtr LoadOrThrow(string dllToLoad) { var ret = LoadOrZero(dllToLoad); - return ret != IntPtr.Zero ? ret : throw new InvalidOperationException($"got null pointer from {nameof(LoadLibraryW)}, {GetErrorMessage()}"); + return ret != IntPtr.Zero ? ret : throw new InvalidOperationException($"got null pointer from {nameof(LoadLibraryW)} while trying to load {dllToLoad}, {GetErrorMessage()}"); } public unsafe string GetErrorMessage() diff --git a/src/BizHawk.Common/POSIX/DlfcnImports.cs b/src/BizHawk.Common/POSIX/DlfcnImports.cs index 0c2a1c19cbb..8d4cc5ad660 100644 --- a/src/BizHawk.Common/POSIX/DlfcnImports.cs +++ b/src/BizHawk.Common/POSIX/DlfcnImports.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; namespace BizHawk.Common diff --git a/src/BizHawk.Common/POSIX/MmanImports.cs b/src/BizHawk.Common/POSIX/MmanImports.cs index ba2dce379ea..0dfbd4b6613 100644 --- a/src/BizHawk.Common/POSIX/MmanImports.cs +++ b/src/BizHawk.Common/POSIX/MmanImports.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; namespace BizHawk.Common diff --git a/src/BizHawk.Common/PropertyGridConverters/BizDateTimeConverter.cs b/src/BizHawk.Common/PropertyGridConverters/BizDateTimeConverter.cs index 728a2319d75..970cab5f2e1 100644 --- a/src/BizHawk.Common/PropertyGridConverters/BizDateTimeConverter.cs +++ b/src/BizHawk.Common/PropertyGridConverters/BizDateTimeConverter.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Globalization; diff --git a/src/BizHawk.Common/PropertyGridConverters/ConstrainedFloatConverter.cs b/src/BizHawk.Common/PropertyGridConverters/ConstrainedFloatConverter.cs index 9b7f2ceeb69..dd234622974 100644 --- a/src/BizHawk.Common/PropertyGridConverters/ConstrainedFloatConverter.cs +++ b/src/BizHawk.Common/PropertyGridConverters/ConstrainedFloatConverter.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Globalization; using System.ComponentModel.DataAnnotations; diff --git a/src/BizHawk.Common/PropertyGridConverters/ConstrainedIntConverter.cs b/src/BizHawk.Common/PropertyGridConverters/ConstrainedIntConverter.cs index 64ec3dd30e1..b5033c90308 100644 --- a/src/BizHawk.Common/PropertyGridConverters/ConstrainedIntConverter.cs +++ b/src/BizHawk.Common/PropertyGridConverters/ConstrainedIntConverter.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Globalization; using System.ComponentModel.DataAnnotations; diff --git a/src/BizHawk.Common/PropertyGridConverters/ConstrainedStringConverter.cs b/src/BizHawk.Common/PropertyGridConverters/ConstrainedStringConverter.cs index 3425fa8d365..aaf7e392634 100644 --- a/src/BizHawk.Common/PropertyGridConverters/ConstrainedStringConverter.cs +++ b/src/BizHawk.Common/PropertyGridConverters/ConstrainedStringConverter.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Globalization; using System.ComponentModel.DataAnnotations; diff --git a/src/BizHawk.Common/PropertyGridConverters/DescribableEnumConverter.cs b/src/BizHawk.Common/PropertyGridConverters/DescribableEnumConverter.cs index ff062114993..c894f4d6ed9 100644 --- a/src/BizHawk.Common/PropertyGridConverters/DescribableEnumConverter.cs +++ b/src/BizHawk.Common/PropertyGridConverters/DescribableEnumConverter.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Globalization; diff --git a/src/BizHawk.Common/PtrToStringUtf8.cs b/src/BizHawk.Common/PtrToStringUtf8.cs index 37e0ff648c6..3d655682b88 100644 --- a/src/BizHawk.Common/PtrToStringUtf8.cs +++ b/src/BizHawk.Common/PtrToStringUtf8.cs @@ -1,4 +1,3 @@ -using System; using System.Text; namespace BizHawk.Common diff --git a/src/BizHawk.Common/Ranges.cs b/src/BizHawk.Common/Ranges.cs index cf95b170df3..451e669f059 100644 --- a/src/BizHawk.Common/Ranges.cs +++ b/src/BizHawk.Common/Ranges.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; @@ -68,7 +67,8 @@ public static class RangeExtensions { private const ulong MIN_LONG_NEGATION_AS_ULONG = 9223372036854775808UL; - private static readonly ArithmeticException ExclusiveRangeMinValExc = new ArithmeticException("exclusive range end is min value of integral type"); + private static ArithmeticException ExclusiveRangeMinValExc + => new("exclusive range end is min value of integral type"); /// if it's contained in , or else whichever bound of is closest to public static T ConstrainWithin(this T value, Range range) where T : unmanaged, IComparable => value.CompareTo(range.Start) < 0 diff --git a/src/BizHawk.Common/Serializer.cs b/src/BizHawk.Common/Serializer.cs index 9190eb916a0..59a750f4526 100644 --- a/src/BizHawk.Common/Serializer.cs +++ b/src/BizHawk.Common/Serializer.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Collections.Generic; using System.Globalization; using System.IO; diff --git a/src/BizHawk.Common/SimpleTime.cs b/src/BizHawk.Common/SimpleTime.cs index 74132174832..521d8e2c60e 100644 --- a/src/BizHawk.Common/SimpleTime.cs +++ b/src/BizHawk.Common/SimpleTime.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; namespace BizHawk.Common diff --git a/src/BizHawk.Common/SpanStream.cs b/src/BizHawk.Common/SpanStream.cs index 8052ea3a957..b8959d89f46 100644 --- a/src/BizHawk.Common/SpanStream.cs +++ b/src/BizHawk.Common/SpanStream.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Runtime.InteropServices; @@ -14,11 +13,7 @@ public interface ISpanStream } public static class SpanStream { - /// - /// Returns a stream in spanstream mode, or creates a wrapper that provides that functionality - /// - /// - /// + /// a stream in spanstream mode, or a newly-created wrapper which provides that functionality public static ISpanStream GetOrBuild(Stream s) { return s as ISpanStream diff --git a/src/BizHawk.Common/TempFileManager.cs b/src/BizHawk.Common/TempFileManager.cs index 2beb37408aa..64167241383 100644 --- a/src/BizHawk.Common/TempFileManager.cs +++ b/src/BizHawk.Common/TempFileManager.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Collections.Generic; using System.IO; diff --git a/src/BizHawk.Common/Util.cs b/src/BizHawk.Common/Util.cs index ce8f0629c73..7b37bf9427a 100644 --- a/src/BizHawk.Common/Util.cs +++ b/src/BizHawk.Common/Util.cs @@ -1,13 +1,10 @@ -using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; -#if NET6_0 using System.Runtime.CompilerServices; -#endif using System.Threading; namespace BizHawk.Common @@ -56,7 +53,8 @@ public static byte[] DecompressGzipFile(Stream src) if (src.Read(tmp, 0, 2) != 2) throw new InvalidOperationException("Unexpected end of stream"); if (tmp[0] != 0x1F || tmp[1] != 0x8B) throw new InvalidOperationException("GZIP header not present"); src.Seek(-4, SeekOrigin.End); - src.Read(tmp, 0, 4); + var bytesRead = src.Read(tmp, offset: 0, count: tmp.Length); + Debug.Assert(bytesRead == tmp.Length); src.Seek(0, SeekOrigin.Begin); using var gs = new GZipStream(src, CompressionMode.Decompress, true); var data = new byte[BitConverter.ToInt32(tmp, 0)]; @@ -81,16 +79,16 @@ public static bool DictionaryEqual(IDictionary a, ID return a.All(kvp => b.TryGetValue(kvp.Key, out var bVal) && comparer.Equals(kvp.Value, bVal)); } -#if NET6_0 - public static string DescribeIsNull(T? obj, [CallerArgumentExpression("obj")] string? expr = default) +#if NETCOREAPP3_0_OR_GREATER + public static string DescribeIsNull(T? obj, [CallerArgumentExpression(nameof(obj))] string? expr = default) #else public static string DescribeIsNull(T? obj, string expr) #endif where T : class => $"{expr} is {(obj is null ? "null" : "not null")}"; -#if NET6_0 - public static string DescribeIsNullValT(T? boxed, [CallerArgumentExpression("boxed")] string? expr = default) +#if NETCOREAPP3_0_OR_GREATER + public static string DescribeIsNullValT(T? boxed, [CallerArgumentExpression(nameof(boxed))] string? expr = default) #else public static string DescribeIsNullValT(T? boxed, string expr) #endif @@ -171,6 +169,7 @@ public static void Memset(void* ptr, int val, int len) while (len > 0) { var done = br.Read(ret, ofs, len); + if (done is 0) _ = br.ReadByte(); // triggers an EndOfStreamException (as there's otherwise no way to indicate this failure state to the caller) ofs += done; len -= done; } @@ -380,6 +379,31 @@ static bool TryWaitForFileToVanish(string path) } } + /// creates span over octets starting at + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Span UnsafeSpanFromPointer(IntPtr ptr, int length) + { + unsafe + { + return new(pointer: ptr.ToPointer(), length: length); + } + } + + /// + /// creates span over * sizeof() octets + /// starting at + /// + /// uses native endianness + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Span UnsafeSpanFromPointer(IntPtr ptr, int count) + where T : unmanaged + { + unsafe + { + return new(pointer: ptr.ToPointer(), length: count * sizeof(T)); + } + } + public static void WriteByteBuffer(this BinaryWriter bw, byte[]? data) { if (data == null) diff --git a/src/BizHawk.Common/VersionInfo.cs b/src/BizHawk.Common/VersionInfo.cs index c7ece227812..00914e13cb6 100644 --- a/src/BizHawk.Common/VersionInfo.cs +++ b/src/BizHawk.Common/VersionInfo.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Common.StringExtensions; @@ -21,6 +20,8 @@ public static partial class VersionInfo public static readonly string? CustomBuildString; + public static readonly string BizHawkContributorsListURI = "https://github.com/TASEmulators/BizHawk/graphs/contributors"; + static VersionInfo() { var path = Path.Combine( @@ -38,8 +39,25 @@ static VersionInfo() } } + public static (string Label, string TargetURI) GetGitCommitLink() + => ($"Commit :{GIT_BRANCH}@{GIT_SHORTHASH}", $"https://github.com/TASEmulators/BizHawk/commit/{GIT_HASH}"); + + public static string GetFullVersionDetails() + { + //TODO prepare for AArch64/RISC-V + var targetArch = UIntPtr.Size is 8 ? "x64" : "x86"; +#if DEBUG + const string buildConfig = "Debug"; +#else + const string buildConfig = "Release"; +#endif + return DeveloperBuild + ? $"Version {MainVersion} — dev build ({buildConfig}, {targetArch})" + : $"Version {MainVersion} ({targetArch})"; + } + public static string GetEmuVersion() - => DeveloperBuild ? $"GIT {GIT_BRANCH}#{GIT_SHORTHASH}" : $"Version {MainVersion}"; + => DeveloperBuild ? $"GIT {GIT_BRANCH}#{GIT_SHORTHASH}" : $"Version {MainVersion}"; // intentionally leaving '#' here to differentiate it from the "proper" one in `Help` > `About...` --yoshi /// "2.5.1" => 0x02050100 public static uint VersionStrToInt(string s) diff --git a/src/BizHawk.Common/Win32/AVIWriterImports.cs b/src/BizHawk.Common/Win32/AVIWriterImports.cs index 7e5aa962154..e544d33d650 100644 --- a/src/BizHawk.Common/Win32/AVIWriterImports.cs +++ b/src/BizHawk.Common/Win32/AVIWriterImports.cs @@ -1,7 +1,6 @@ #nullable disable #if AVI_SUPPORT -using System; using System.Runtime.InteropServices; // ReSharper disable FieldCanBeMadeReadOnly.Global diff --git a/src/BizHawk.Common/Win32/CWDHacks.cs b/src/BizHawk.Common/Win32/CWDHacks.cs index 2fd478af46d..3409395ebf4 100644 --- a/src/BizHawk.Common/Win32/CWDHacks.cs +++ b/src/BizHawk.Common/Win32/CWDHacks.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; namespace BizHawk.Common diff --git a/src/BizHawk.Common/Win32/CommctrlImports.cs b/src/BizHawk.Common/Win32/CommctrlImports.cs index 26350aa5400..799c9f5d2af 100644 --- a/src/BizHawk.Common/Win32/CommctrlImports.cs +++ b/src/BizHawk.Common/Win32/CommctrlImports.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Runtime.InteropServices; // ReSharper disable FieldCanBeMadeReadOnly.Global diff --git a/src/BizHawk.Common/Win32/HeapApiImports.cs b/src/BizHawk.Common/Win32/HeapApiImports.cs index 30af180d498..8f9d884c25b 100644 --- a/src/BizHawk.Common/Win32/HeapApiImports.cs +++ b/src/BizHawk.Common/Win32/HeapApiImports.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; // ReSharper disable FieldCanBeMadeReadOnly.Global diff --git a/src/BizHawk.Common/Win32/LoaderApiImports.cs b/src/BizHawk.Common/Win32/LoaderApiImports.cs index edb2ef6d3cb..f5913f17282 100644 --- a/src/BizHawk.Common/Win32/LoaderApiImports.cs +++ b/src/BizHawk.Common/Win32/LoaderApiImports.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; // ReSharper disable UnusedMember.Global diff --git a/src/BizHawk.Common/Win32/MemoryApiImports.cs b/src/BizHawk.Common/Win32/MemoryApiImports.cs index a71b87970f8..a907c3851a0 100644 --- a/src/BizHawk.Common/Win32/MemoryApiImports.cs +++ b/src/BizHawk.Common/Win32/MemoryApiImports.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; // ReSharper disable FieldCanBeMadeReadOnly.Global diff --git a/src/BizHawk.Common/Win32/Ole32Imports.cs b/src/BizHawk.Common/Win32/Ole32Imports.cs index af760653c30..9e8753e20f9 100644 --- a/src/BizHawk.Common/Win32/Ole32Imports.cs +++ b/src/BizHawk.Common/Win32/Ole32Imports.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; // ReSharper disable UnusedMember.Global diff --git a/src/BizHawk.Common/Win32/RawInputImports.cs b/src/BizHawk.Common/Win32/RawInputImports.cs index 8377b3f0861..987faaea7b5 100644 --- a/src/BizHawk.Common/Win32/RawInputImports.cs +++ b/src/BizHawk.Common/Win32/RawInputImports.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; // ReSharper disable FieldCanBeMadeReadOnly.Global diff --git a/src/BizHawk.Common/Win32/Shell32Imports.cs b/src/BizHawk.Common/Win32/Shell32Imports.cs index a80c493d90a..fcf32f06de0 100644 --- a/src/BizHawk.Common/Win32/Shell32Imports.cs +++ b/src/BizHawk.Common/Win32/Shell32Imports.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Runtime.InteropServices; // ReSharper disable FieldCanBeMadeReadOnly.Global @@ -35,20 +34,28 @@ public enum FLAGS { /// BIF_RETURNONLYFSDIRS RestrictToFilesystem = 0x0001, + /// BIF_DONTGOBELOWDOMAIN RestrictToDomain = 0x0002, + /// BIF_RETURNFSANCESTORS RestrictToSubfolders = 0x0008, + /// BIF_EDITBOX ShowTextBox = 0x0010, + /// BIF_VALIDATE ValidateSelection = 0x0020, + /// BIF_NEWDIALOGSTYLE NewDialogStyle = 0x0040, + /// BIF_BROWSEFORCOMPUTER BrowseForComputer = 0x1000, + /// BIF_BROWSEFORPRINTER BrowseForPrinter = 0x2000, + /// BIF_BROWSEINCLUDEFILES BrowseForEverything = 0x4000 } diff --git a/src/BizHawk.Common/Win32/ShellLinkImports.cs b/src/BizHawk.Common/Win32/ShellLinkImports.cs index 2e0502d1555..dc8036523de 100644 --- a/src/BizHawk.Common/Win32/ShellLinkImports.cs +++ b/src/BizHawk.Common/Win32/ShellLinkImports.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Common/Win32/ThreadHacks.cs b/src/BizHawk.Common/Win32/ThreadHacks.cs index 21ad48626b7..ed6be0216ba 100644 --- a/src/BizHawk.Common/Win32/ThreadHacks.cs +++ b/src/BizHawk.Common/Win32/ThreadHacks.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; diff --git a/src/BizHawk.Common/Win32/Win32Imports.cs b/src/BizHawk.Common/Win32/Win32Imports.cs index 8a5c146c37f..cb784a3d1c1 100644 --- a/src/BizHawk.Common/Win32/Win32Imports.cs +++ b/src/BizHawk.Common/Win32/Win32Imports.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.IO; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Common/Win32/Win32ShellContextMenu.cs b/src/BizHawk.Common/Win32/Win32ShellContextMenu.cs index fb4e4fbb294..18c0183a918 100644 --- a/src/BizHawk.Common/Win32/Win32ShellContextMenu.cs +++ b/src/BizHawk.Common/Win32/Win32ShellContextMenu.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Common/Win32/WmImports.cs b/src/BizHawk.Common/Win32/WmImports.cs index 0d6d806984a..9ddb1f45898 100644 --- a/src/BizHawk.Common/Win32/WmImports.cs +++ b/src/BizHawk.Common/Win32/WmImports.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Runtime.InteropServices; // ReSharper disable FieldCanBeMadeReadOnly.Global diff --git a/src/BizHawk.Common/checksums/CRC32.cs b/src/BizHawk.Common/checksums/CRC32.cs index 563d766a98a..e3ce0daff24 100644 --- a/src/BizHawk.Common/checksums/CRC32.cs +++ b/src/BizHawk.Common/checksums/CRC32.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; namespace BizHawk.Common diff --git a/src/BizHawk.Common/checksums/CRC32Checksum.cs b/src/BizHawk.Common/checksums/CRC32Checksum.cs index a988b4b8035..44c2eafd7c6 100644 --- a/src/BizHawk.Common/checksums/CRC32Checksum.cs +++ b/src/BizHawk.Common/checksums/CRC32Checksum.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common.BufferExtensions; namespace BizHawk.Common diff --git a/src/BizHawk.Common/checksums/LibBizHash.cs b/src/BizHawk.Common/checksums/LibBizHash.cs index f2aca3f6b92..3bd90514189 100644 --- a/src/BizHawk.Common/checksums/LibBizHash.cs +++ b/src/BizHawk.Common/checksums/LibBizHash.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; namespace BizHawk.Common diff --git a/src/BizHawk.Common/checksums/MD5Checksum.cs b/src/BizHawk.Common/checksums/MD5Checksum.cs index d13f2aa5f57..ae22a96cf48 100644 --- a/src/BizHawk.Common/checksums/MD5Checksum.cs +++ b/src/BizHawk.Common/checksums/MD5Checksum.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using System.Security.Cryptography; @@ -19,7 +18,7 @@ public static class MD5Checksum public /*static readonly*/const string EmptyFile = "D41D8CD98F00B204E9800998ECF8427E"; -#if NET6_0 +#if NET5_0_OR_GREATER public static byte[] Compute(ReadOnlySpan data) => MD5.HashData(data); #else diff --git a/src/BizHawk.Common/checksums/SHA1Checksum.cs b/src/BizHawk.Common/checksums/SHA1Checksum.cs index 00920f3549e..0abe8f4b1ad 100644 --- a/src/BizHawk.Common/checksums/SHA1Checksum.cs +++ b/src/BizHawk.Common/checksums/SHA1Checksum.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Security.Cryptography; @@ -25,17 +24,9 @@ public static class SHA1Checksum public /*static readonly*/const string Zero = "0000000000000000000000000000000000000000"; -#if NET6_0 +#if NET5_0_OR_GREATER public static byte[] Compute(ReadOnlySpan data) => SHA1.HashData(data); - - public static byte[] ComputeConcat(ReadOnlySpan dataA, ReadOnlySpan dataB) - { - using var impl = IncrementalHash.CreateHash(HashAlgorithmName.SHA1); - impl.AppendData(dataA); - impl.AppendData(dataB); - return impl.GetHashAndReset(); - } #else private static unsafe byte[] UnmanagedImpl(byte[] buffer) { @@ -88,7 +79,17 @@ public static string ComputePrefixedHex(byte[] data) public static byte[] Compute(ReadOnlySpan data) => Compute(data.ToArray()); +#endif +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER + public static byte[] ComputeConcat(ReadOnlySpan dataA, ReadOnlySpan dataB) + { + using var impl = IncrementalHash.CreateHash(HashAlgorithmName.SHA1); + impl.AppendData(dataA); + impl.AppendData(dataB); + return impl.GetHashAndReset(); + } +#else public static byte[] ComputeConcat(ReadOnlySpan dataA, ReadOnlySpan dataB) => ComputeConcat(dataA.ToArray(), dataB.ToArray()); #endif diff --git a/src/BizHawk.Common/checksums/SHA256Checksum.cs b/src/BizHawk.Common/checksums/SHA256Checksum.cs index f27d9b53ff7..c8e5d58768e 100644 --- a/src/BizHawk.Common/checksums/SHA256Checksum.cs +++ b/src/BizHawk.Common/checksums/SHA256Checksum.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using System.Security.Cryptography; @@ -19,7 +18,7 @@ public static class SHA256Checksum public /*static readonly*/const string EmptyFile = "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"; -#if NET6_0 +#if NET5_0_OR_GREATER public static byte[] Compute(ReadOnlySpan data) => SHA256.HashData(data); #else diff --git a/src/BizHawk.Common/zstd/LibZstd.cs b/src/BizHawk.Common/zstd/LibZstd.cs index e257dbd7f3f..92ec5375329 100644 --- a/src/BizHawk.Common/zstd/LibZstd.cs +++ b/src/BizHawk.Common/zstd/LibZstd.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Common/zstd/Zstd.cs b/src/BizHawk.Common/zstd/Zstd.cs index 5dc0fa1ad11..566b561c91e 100644 --- a/src/BizHawk.Common/zstd/Zstd.cs +++ b/src/BizHawk.Common/zstd/Zstd.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Emulation.Common/Base Implementations/Axes/AxisDict.cs b/src/BizHawk.Emulation.Common/Base Implementations/Axes/AxisDict.cs index 0973c5852a8..917dc524344 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/Axes/AxisDict.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/Axes/AxisDict.cs @@ -1,7 +1,7 @@ -using System; using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; +using System.Linq; namespace BizHawk.Emulation.Common { @@ -60,12 +60,7 @@ public void Clear() public bool ContainsKey(string key) => _keys.Contains(key); public IEnumerator> GetEnumerator() - { - foreach (var key in _keys) - { - yield return new(key, _specs[key]); - } - } + => _keys.Select(key => new KeyValuePair(key, _specs[key])).GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); diff --git a/src/BizHawk.Emulation.Common/Base Implementations/Axes/AxisSpec.cs b/src/BizHawk.Emulation.Common/Base Implementations/Axes/AxisSpec.cs index d9a683703c6..51e1b685b49 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/Axes/AxisSpec.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/Axes/AxisSpec.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; namespace BizHawk.Emulation.Common diff --git a/src/BizHawk.Emulation.Common/Base Implementations/Axes/CircularAxisConstraint.cs b/src/BizHawk.Emulation.Common/Base Implementations/Axes/CircularAxisConstraint.cs index c56dc67ea98..2a5ce75e3a1 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/Axes/CircularAxisConstraint.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/Axes/CircularAxisConstraint.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Common { public sealed class CircularAxisConstraint : AxisConstraint diff --git a/src/BizHawk.Emulation.Common/Base Implementations/BasicServiceProvider.cs b/src/BizHawk.Emulation.Common/Base Implementations/BasicServiceProvider.cs index 462582d82a9..d44da7836a5 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/BasicServiceProvider.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/BasicServiceProvider.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; @@ -14,7 +13,7 @@ namespace BizHawk.Emulation.Common /// public class BasicServiceProvider : IEmulatorServiceProvider { - private readonly Dictionary _services = new Dictionary(); + private readonly Dictionary _services = [ ]; public BasicServiceProvider(IEmulator core) { @@ -23,7 +22,7 @@ public BasicServiceProvider(IEmulator core) // find the field), but we're going to keep such logic out of the basic provider. anything the passed // core doesn't implement directly needs to be added with Register() // this also fully allows services that are not IEmulatorService - Type coreType = core.GetType(); + var coreType = core.GetType(); foreach (var service in coreType.GetInterfaces().Where(static t => typeof(IEmulatorService).IsAssignableFrom(t) && t != typeof(IEmulatorService) && t != typeof(ISpecializedEmulatorService))) @@ -45,30 +44,32 @@ public BasicServiceProvider(IEmulator core) /// is null public void Register(T provider) where T : class, IEmulatorService - { - _services[typeof(T)] = provider; - } + => _services[typeof(T)] = provider; + + /// + /// the core can call this to unregister an existing service + /// this is particularly useful wrt the auto-registration of services + /// in case the core has some condition which renders a service unusable + /// + /// The to unregister + public void Unregister() + where T : class, IEmulatorService + => _services.Remove(typeof(T)); public T GetService() where T : IEmulatorService => (T) GetService(typeof(T))!; public object? GetService(Type t) - { - return _services.TryGetValue(t, out var service) ? service : null; - } + => _services.TryGetValue(t, out var service) ? service : null; public bool HasService() where T : IEmulatorService - { - return HasService(typeof(T)); - } + => HasService(typeof(T)); public bool HasService(Type t) - { - return _services.ContainsKey(t); - } + => _services.ContainsKey(t); - public IEnumerable AvailableServices =>_services.Select(d => d.Key); + public IEnumerable AvailableServices => _services.Select(d => d.Key); } } diff --git a/src/BizHawk.Emulation.Common/Base Implementations/CallbackBasedTraceBuffer.cs b/src/BizHawk.Emulation.Common/Base Implementations/CallbackBasedTraceBuffer.cs index 7f65081db9c..0628d67ce43 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/CallbackBasedTraceBuffer.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/CallbackBasedTraceBuffer.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Emulation.Common diff --git a/src/BizHawk.Emulation.Common/Base Implementations/CodeDataLog.cs b/src/BizHawk.Emulation.Common/Base Implementations/CodeDataLog.cs index cb28e261ac1..21380f40601 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/CodeDataLog.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/CodeDataLog.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Emulation.Common/Base Implementations/ControllerDefinition.cs b/src/BizHawk.Emulation.Common/Base Implementations/ControllerDefinition.cs index 5b95fb9a791..302d21eefae 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/ControllerDefinition.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/ControllerDefinition.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; diff --git a/src/BizHawk.Emulation.Common/Base Implementations/InputCallbackSystem.cs b/src/BizHawk.Emulation.Common/Base Implementations/InputCallbackSystem.cs index ed67e782b08..ad0f30e82ca 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/InputCallbackSystem.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/InputCallbackSystem.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Common/Base Implementations/LinkedDebuggable.cs b/src/BizHawk.Emulation.Common/Base Implementations/LinkedDebuggable.cs index 8572c9ec3e9..c73210adec6 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/LinkedDebuggable.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/LinkedDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using BizHawk.Common.StringExtensions; diff --git a/src/BizHawk.Emulation.Common/Base Implementations/LinkedMemoryDomains.cs b/src/BizHawk.Emulation.Common/Base Implementations/LinkedMemoryDomains.cs index 4670c57c0b9..23047f428fe 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/LinkedMemoryDomains.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/LinkedMemoryDomains.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Collections.Generic; namespace BizHawk.Emulation.Common diff --git a/src/BizHawk.Emulation.Common/Base Implementations/LinkedSaveRam.cs b/src/BizHawk.Emulation.Common/Base Implementations/LinkedSaveRam.cs index c2d344ef350..fd5da554021 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/LinkedSaveRam.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/LinkedSaveRam.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Emulation.Common @@ -38,7 +37,7 @@ public byte[] CloneSaveRam() int len = 0; for (int i = 0; i < _numCores; i++) { - linkedBuffers.Add(_linkedCores[i].AsSaveRam().CloneSaveRam()!); + linkedBuffers.Add(_linkedCores[i].AsSaveRam().CloneSaveRam() ?? Array.Empty()); len += linkedBuffers[i].Length; } byte[] ret = new byte[len]; @@ -56,7 +55,9 @@ public void StoreSaveRam(byte[] data) int pos = 0; for (int i = 0; i < _numCores; i++) { - var b = new byte[_linkedCores[i].AsSaveRam().CloneSaveRam()!.Length]; + var toCopy = _linkedCores[i].AsSaveRam().CloneSaveRam(); // wait CloneSaveRam is already a copy, why are we copying it again + if (toCopy is null) continue; + var b = new byte[toCopy.Length]; Buffer.BlockCopy(data, pos, b, 0, b.Length); pos += b.Length; _linkedCores[i].AsSaveRam().StoreSaveRam(b); diff --git a/src/BizHawk.Emulation.Common/Base Implementations/MemoryBasedInputCallbackSystem.cs b/src/BizHawk.Emulation.Common/Base Implementations/MemoryBasedInputCallbackSystem.cs index df0f7598441..92420d40249 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/MemoryBasedInputCallbackSystem.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/MemoryBasedInputCallbackSystem.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; diff --git a/src/BizHawk.Emulation.Common/Base Implementations/MemoryCallbackSystem.cs b/src/BizHawk.Emulation.Common/Base Implementations/MemoryCallbackSystem.cs index 3a14bc67867..37bca8e70ce 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/MemoryCallbackSystem.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/MemoryCallbackSystem.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Linq; using System.Collections; using System.Collections.Generic; @@ -219,40 +218,10 @@ private void OnCallbackRemoved(object sender, IMemoryCallback callback) } public IEnumerator GetEnumerator() - { - foreach (var imc in _reads) - { - yield return imc; - } - - foreach (var imc in _writes) - { - yield return imc; - } - - foreach (var imc in _execs) - { - yield return imc; - } - } + => _reads.Concat(_writes).Concat(_execs).GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() - { - foreach (var imc in _reads) - { - yield return imc; - } - - foreach (var imc in _writes) - { - yield return imc; - } - - foreach (var imc in _execs) - { - yield return imc; - } - } + => GetEnumerator(); } public class MemoryCallback : IMemoryCallback diff --git a/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomain.cs b/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomain.cs index 2f89aed99fa..6486115c72e 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomain.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomain.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using BizHawk.Common; namespace BizHawk.Emulation.Common diff --git a/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomainImpls.cs b/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomainImpls.cs index 6393101dd3c..2d9ef3f61b9 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomainImpls.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomainImpls.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Runtime.InteropServices; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomainList.cs b/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomainList.cs index 2261f44272d..fb046ddc652 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomainList.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomainList.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; diff --git a/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomainStream.cs b/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomainStream.cs index 795d4ddb135..82c2342154c 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomainStream.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomainStream.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.IO; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Common/Base Implementations/NullController.cs b/src/BizHawk.Emulation.Common/Base Implementations/NullController.cs index 3017554fe58..42e7c7b80d9 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/NullController.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/NullController.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Collections.Generic; namespace BizHawk.Emulation.Common diff --git a/src/BizHawk.Emulation.Common/Base Implementations/NullSound.cs b/src/BizHawk.Emulation.Common/Base Implementations/NullSound.cs index dfc8c57181d..2bce9b86839 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/NullSound.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/NullSound.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Common { /// diff --git a/src/BizHawk.Emulation.Common/Base Implementations/NullVideo.cs b/src/BizHawk.Emulation.Common/Base Implementations/NullVideo.cs index 4b04dbdb9b0..0a04de87d7d 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/NullVideo.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/NullVideo.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Common { /// diff --git a/src/BizHawk.Emulation.Common/Base Implementations/SimpleSyncSoundProvider.cs b/src/BizHawk.Emulation.Common/Base Implementations/SimpleSyncSoundProvider.cs index 037b1ddce5b..0ce4c4c7b27 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/SimpleSyncSoundProvider.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/SimpleSyncSoundProvider.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Common.Base_Implementations { /// diff --git a/src/BizHawk.Emulation.Common/Base Implementations/StateSerializer.cs b/src/BizHawk.Emulation.Common/Base Implementations/StateSerializer.cs index b864951020c..4fb8c6074ca 100644 --- a/src/BizHawk.Emulation.Common/Base Implementations/StateSerializer.cs +++ b/src/BizHawk.Emulation.Common/Base Implementations/StateSerializer.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.IO; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Common/ControllerDefinitionMerger.cs b/src/BizHawk.Emulation.Common/ControllerDefinitionMerger.cs index 4d7fa28b820..ffbbb08a64f 100644 --- a/src/BizHawk.Emulation.Common/ControllerDefinitionMerger.cs +++ b/src/BizHawk.Emulation.Common/ControllerDefinitionMerger.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Collections.Generic; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Common/CoreAttribute.cs b/src/BizHawk.Emulation.Common/CoreAttribute.cs index 21ee164d6d3..79cc4e5a680 100644 --- a/src/BizHawk.Emulation.Common/CoreAttribute.cs +++ b/src/BizHawk.Emulation.Common/CoreAttribute.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Common { [AttributeUsage(AttributeTargets.Class)] diff --git a/src/BizHawk.Emulation.Common/CoreComms.cs b/src/BizHawk.Emulation.Common/CoreComms.cs index d8572275e17..3f3a7a0c5b3 100644 --- a/src/BizHawk.Emulation.Common/CoreComms.cs +++ b/src/BizHawk.Emulation.Common/CoreComms.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Common { /// @@ -28,12 +26,12 @@ IOpenGLProvider oglProvider public ICoreFileProvider CoreFileProvider { get; } /// - /// Gets a message to show. reasonably annoying (dialog box), shouldn't be used most of the time + /// Gets a message to show. Reasonably annoying (dialog box), shouldn't be used most of the time /// public Action ShowMessage { get; } /// - /// Gets a message to show. less annoying (OSD message). Should be used for ignorable helpful messages + /// Gets a message to show for optional duration in seconds. Less annoying (OSD message). Should be used for ignorable helpful messages /// public Action Notify { get; } diff --git a/src/BizHawk.Emulation.Common/DSKIdentifier.cs b/src/BizHawk.Emulation.Common/DSKIdentifier.cs index 743545e78e1..5f1499e028d 100644 --- a/src/BizHawk.Emulation.Common/DSKIdentifier.cs +++ b/src/BizHawk.Emulation.Common/DSKIdentifier.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Linq; using System.Text; using BizHawk.Common.StringExtensions; diff --git a/src/BizHawk.Emulation.Common/Database/Database.cs b/src/BizHawk.Emulation.Common/Database/Database.cs index 585c30a05e5..72be08b0140 100644 --- a/src/BizHawk.Emulation.Common/Database/Database.cs +++ b/src/BizHawk.Emulation.Common/Database/Database.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -100,9 +99,8 @@ private static void InitializeWork(string path, bool inUser, bool silent) if (!inUser) _expected.Remove(Path.GetFileName(path)); //reminder: this COULD be done on several threads, if it takes even longer using var reader = new StreamReader(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)); - while (reader.EndOfStream == false) + while (reader.ReadLine() is string line) { - var line = reader.ReadLine() ?? ""; try { if (line.StartsWith(';')) continue; // comment @@ -402,6 +400,16 @@ public static GameInfo GetGameInfo(byte[] romData, string fileName) game.System = VSystemID.Raw.TIC80; break; + case ".ADF": + case ".ADZ": + case ".DMS": + case ".IPF": + case ".FDI": + case ".HDF": + case ".LHA": + game.System = VSystemID.Raw.Amiga; + break; + case ".32X": game.System = VSystemID.Raw.Sega32X; game.AddOption("32X", "true"); diff --git a/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs b/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs index baa70fc4f15..28e0ff2c775 100644 --- a/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs +++ b/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs @@ -39,13 +39,16 @@ FirmwareFile File( string desc, string additionalInfo = "", bool isBad = false) - => filesByHash[hash] = new( - hash: hash, - size: size, - recommendedName: recommendedName, - desc: desc, - additionalInfo: additionalInfo, - isBad: isBad); + { + FirmwareFile ff = new( + hash: hash, + size: size, + recommendedName: recommendedName, + desc: desc, + additionalInfo: additionalInfo, + isBad: isBad); + return filesByHash[ff.Hash/*may have been reformatted*/] = ff; + } void Option(string systemId, string id, in FirmwareFile ff, FirmwareOptionStatus status = FirmwareOptionStatus.Acceptable) { @@ -123,8 +126,8 @@ void AddPatchAndMaybeReverse(FirmwarePatchOption fpo) FirmwareAndOption("45BEDC4CBDEAC66C7DF59E9E599195C778D86A92", 8192, "Coleco", "Bios", "Coleco_Bios.bin", "Bios"); - FirmwareAndOption("B9BBF5BB0EAC52D039A4A993A2D8064B862C9E28", 4096, "VEC", "Bios", "Vectrex_Bios.bin", "Bios"); - FirmwareAndOption("65D07426B520DDD3115D40F255511E0FD2E20AE7", 8192, "VEC", "Minestorm", "Vectrex_Minestorm.vec", "Game"); + FirmwareAndOption("B9BBF5BB0EAC52D039A4A993A2D8064B862C9E28", 4096, "VEC", "Bios", "VEC_Bios.bin", "Bios"); + FirmwareAndOption("65D07426B520DDD3115D40F255511E0FD2E20AE7", 8192, "VEC", "Minestorm", "VEC_Minestorm.vec", "Game"); var gbaNormal = File("300C20DF6731A33952DED8C436F7F186D25D3492", 16384, "GBA_bios.rom", "Bios (World)"); var gbaJDebug = File("AA98A2AD32B86106340665D1222D7D973A1361C7", 16384, "GBA_bios_Debug-(J).rom", "Bios (J Debug)"); @@ -170,7 +173,7 @@ void AddPatchAndMaybeReverse(FirmwarePatchOption fpo) FirmwareAndOption(SHA1Checksum.Dummy, 0, "3DS", "aes_keys", "aes_keys.txt", "AES Keys"); FirmwareAndOption(SHA1Checksum.Dummy, 0, "3DS", "seeddb", "seeddb.bin", "SEEDDB"); - FirmwareAndOption("E4ED47FAE31693E016B081C6BDA48DA5B70D7CCB", 512, "Lynx", "Boot", "LYNX_boot.img", "Boot Rom"); + FirmwareAndOption("E4ED47FAE31693E016B081C6BDA48DA5B70D7CCB", 512, "Lynx", "Boot", "Atari_LYNX_boot.img", "Boot Rom"); FirmwareAndOption("5A65B922B562CB1F57DAB51B73151283F0E20C7A", 8192, "INTV", "EROM", "INTV_EROM.bin", "Executive Rom"); FirmwareAndOption("F9608BB4AD1CFE3640D02844C7AD8E0BCD974917", 2048, "INTV", "GROM", "INTV_GROM.bin", "Graphics Rom"); @@ -190,7 +193,7 @@ void AddPatchAndMaybeReverse(FirmwarePatchOption fpo) //FirmwareAndOption("E998F0C441F4F1800EF44E42CD1659150206CF79", 16384, "MSX", "bios_pal", "MSX_8020-20bios.rom", "MSX BIOS (Philips VG-8020)"); //FirmwareAndOption("DF48902F5F12AF8867AE1A87F255145F0E5E0774", 16384, "MSX", "bios_jp", "MSX_4000bios.rom", "MSX BIOS (FS-4000)"); FirmwareAndOption("409E82ADAC40F6BDD18EB6C84E8B2FBDC7FB5498", 32768, "MSX", "bios_basic_usa", "MSX.rom", "MSX BIOS and BASIC"); - FirmwareAndOption("3656BB3BBC17D280D2016FE4F6FF3CDED3082A41", 32768, "MSX", "bios_basic_usa", "MSX.rom", "MSX 1.0 BIOS and BASIC"); + FirmwareAndOption("3656BB3BBC17D280D2016FE4F6FF3CDED3082A41", 32768, "MSX", "bios_basic_usa", "MSX_1.0.rom", "MSX 1.0 BIOS and BASIC"); FirmwareAndOption("302AFB5D8BE26C758309CA3DF611AE69CCED2821", 32768, "MSX", "bios_basic_jpn", "MSX_jpn.rom", "MSX 1.0 JPN BIOS and BASIC"); // Channel F @@ -389,13 +392,14 @@ void AddPatchAndMaybeReverse(FirmwarePatchOption fpo) var psone_r5e = File("DBC7339E5D85827C095764FC077B41F78FD2ECAE", 524288, "PSX_4.5(E).bin", "PSX BIOS (Version 4.5 05/25/00 E)", "Used on PSone SCPH-102 [g]. This is for Rev C PSone hardware [w]."); var ps2_50j = File("D7D6BE084F51354BC951D8FA2D8D912AA70ABC5E", 4194304, "PSX_5.0(J).bin", "PSX BIOS (Version 5.0 10/27/00 J)", "Found on a PS2 [p]. May be known as SCPH18000.BIN."); var ps_dtl_h2000 = File("1A8D6F9453111B1D317BB7DAE300495FBF54600C", 524288, "PSX_DTLH2000.bin", "DTL-H2000 Devkit [t]"); + var psxOnPSP = File("96880D1CA92A016FF054BE5159BB06FE03CB4E14", 524288, "PSXONPSP660.BIN", "PSX on PSP", "From PSP. Allegedly based on PSone v4.5 BIOS."); var ps_ps3 = File("C40146361EB8CF670B19FDC9759190257803CAB7", 524288, "PSX_rom.bin", "PSX BIOS (Version 5.0 06/23/03 A)", "Found on a PS3. [t]"); Firmware("PSX", "U", "BIOS (U)"); Firmware("PSX", "J", "BIOS (J)"); Firmware("PSX", "E", "BIOS (E)"); - Option("PSX", "U", in ps_30a); - Option("PSX", "J", in ps_30j); - Option("PSX", "E", in ps_30e); + Option("PSX", "U", in ps_30a, FirmwareOptionStatus.Ideal); + Option("PSX", "J", in ps_30j, FirmwareOptionStatus.Ideal); + Option("PSX", "E", in ps_30e, FirmwareOptionStatus.Ideal); // in general, alternates aren't allowed.. their quality isn't known. // we have this comment from fobby.net: "SCPH7502 works fine for European games" (TBD) // however, we're sticking with the 3.0 series. @@ -425,6 +429,9 @@ void AddPatchAndMaybeReverse(FirmwarePatchOption fpo) Option("PSX", "J", in ps2_50j, FirmwareOptionStatus.Unacceptable); Option("PSX", "J", in ps_22jv, FirmwareOptionStatus.Unacceptable); Option("PSX", "U", in ps_41aw, FirmwareOptionStatus.Unacceptable); + Option("PSX", "U", in psxOnPSP, FirmwareOptionStatus.Acceptable); + Option("PSX", "E", in psxOnPSP, FirmwareOptionStatus.Unacceptable); // doesn't work w/ PAL titles + Option("PSX", "J", in psxOnPSP, FirmwareOptionStatus.Acceptable); Option("PSX", "U", in ps_ps3, FirmwareOptionStatus.Unacceptable); Option("PSX", "U", in ps_dtl_h2000, FirmwareOptionStatus.Unacceptable); //not really sure what to do with this one, let's just call it region free Option("PSX", "E", in ps_dtl_h2000, FirmwareOptionStatus.Unacceptable); @@ -439,13 +446,13 @@ void AddPatchAndMaybeReverse(FirmwarePatchOption fpo) FirmwareAndOption("B2E1955D957A475DE2411770452EFF4EA19F4CEE", 1024, "O2", "BIOS-O2", "O2_Odyssey2.bin", "Odyssey 2 Bios"); FirmwareAndOption("A6120AED50831C9C0D95DBDF707820F601D9452E", 1024, "O2", "BIOS-C52", "O2_PhillipsC52.bin", "Phillips C52 Bios"); - FirmwareAndOption("5130243429B40B01A14E1304D0394B8459A6FBAE", 1024, "O2", "BIOS-G7400", "G7400_bios.bin", "G7400 Bios"); + FirmwareAndOption("5130243429B40B01A14E1304D0394B8459A6FBAE", 1024, "O2", "BIOS-G7400", "O2_G7400_bios.bin", "G7400 Bios"); Firmware("GB", "World", "Game Boy Boot Rom"); - Option("GB", "World", File("4ED31EC6B0B175BB109C0EB5FD3D193DA823339F", 256, "dmg.bin", "Game Boy Boot Rom"), FirmwareOptionStatus.Ideal); + Option("GB", "World", File("4ED31EC6B0B175BB109C0EB5FD3D193DA823339F", 256, "GB_dmg.bin", "Game Boy Boot Rom"), FirmwareOptionStatus.Ideal); // Early revisions of GB/C boot ROMs are not well-supported because the corresponding CPU differences are not emulated. - Option("GB", "World", File("8BD501E31921E9601788316DBD3CE9833A97BCBC", 256, "dmg0.bin", "Game Boy Boot Rom (Early J Revision)"), FirmwareOptionStatus.Unacceptable); - Option("GB", "World", File("4E68F9DA03C310E84C523654B9026E51F26CE7F0", 256, "mgb.bin", "Game Boy Boot Rom (Pocket)"), FirmwareOptionStatus.Acceptable); + Option("GB", "World", File("8BD501E31921E9601788316DBD3CE9833A97BCBC", 256, "GB_dmg0.bin", "Game Boy Boot Rom (Early J Revision)"), FirmwareOptionStatus.Unacceptable); + Option("GB", "World", File("4E68F9DA03C310E84C523654B9026E51F26CE7F0", 256, "GB_mgb.bin", "Game Boy Boot Rom (Pocket)"), FirmwareOptionStatus.Acceptable); FirmwarePatchData gbCommonPatchAt0xFD = new(0xFD, new byte[] { 0xFE }); // 2 pairs, all have either 0x01 or 0xFF at this octet AddPatchAndMaybeReverse(new( "4ED31EC6B0B175BB109C0EB5FD3D193DA823339F", @@ -455,25 +462,25 @@ void AddPatchAndMaybeReverse(FirmwarePatchOption fpo) // these are only used for supported SGB cores // placed in GB as these are within the Game Boy side rather than the SNES side Firmware("GB", "SGB", "Super Game Boy Boot Rom"); - Option("GB", "SGB", File("AA2F50A77DFB4823DA96BA99309085A3C6278515", 256, "sgb.bin", "Super Game Boy Boot Rom"), FirmwareOptionStatus.Ideal); + Option("GB", "SGB", File("AA2F50A77DFB4823DA96BA99309085A3C6278515", 256, "GB_sgb.bin", "Super Game Boy Boot Rom"), FirmwareOptionStatus.Ideal); Firmware("GB", "SGB2", "Super Game Boy 2 Boot Rom"); - Option("GB", "SGB2", File("93407EA10D2F30AB96A314D8ECA44FE160AEA734", 256, "sgb2.bin", "Super Game Boy 2 Boot Rom"), FirmwareOptionStatus.Ideal); + Option("GB", "SGB2", File("93407EA10D2F30AB96A314D8ECA44FE160AEA734", 256, "GB_sgb2.bin", "Super Game Boy 2 Boot Rom"), FirmwareOptionStatus.Ideal); AddPatchAndMaybeReverse(new( "AA2F50A77DFB4823DA96BA99309085A3C6278515", gbCommonPatchAt0xFD, "93407EA10D2F30AB96A314D8ECA44FE160AEA734")); Firmware("GBC", "World", "Game Boy Color Boot Rom"); - Option("GBC", "World", File("1293D68BF9643BC4F36954C1E80E38F39864528D", 2304, "cgb.bin", "Game Boy Color Boot Rom"), FirmwareOptionStatus.Ideal); + Option("GBC", "World", File("1293D68BF9643BC4F36954C1E80E38F39864528D", 2304, "GBC_cgb.bin", "Game Boy Color Boot Rom"), FirmwareOptionStatus.Ideal); // CGB E models have the logo reading TOCTOU patched (only relevant for bootlegs that logo swap) - Option("GBC", "World", File("F5F33729A956131D9C44310F0AE3BB0599E9EC3E", 2304, "cgbE.bin", "Game Boy Color Boot Rom (Late Revision)")); - Option("GBC", "World", File("DF5A0D2D49DE38FBD31CC2AAB8E62C8550E655C0", 2304, "cgb0.bin", "Game Boy Color Boot Rom (Early Revision)"), FirmwareOptionStatus.Unacceptable); + Option("GBC", "World", File("F5F33729A956131D9C44310F0AE3BB0599E9EC3E", 2304, "GBC_cgbE.bin", "Game Boy Color Boot Rom (Late Revision)")); + Option("GBC", "World", File("DF5A0D2D49DE38FBD31CC2AAB8E62C8550E655C0", 2304, "GBC_cgb0.bin", "Game Boy Color Boot Rom (Early Revision)"), FirmwareOptionStatus.Unacceptable); Firmware("GBC", "AGB", "Game Boy Color Boot Rom (GBA)"); - Option("GBC", "AGB", File("FA5287E24B0FA533B3B5EF2B28A81245346C1A0F", 2304, "agb.bin", "Game Boy Color Boot Rom (GBA)"), FirmwareOptionStatus.Ideal); + Option("GBC", "AGB", File("FA5287E24B0FA533B3B5EF2B28A81245346C1A0F", 2304, "GBC_agb.bin", "Game Boy Color Boot Rom (GBA)"), FirmwareOptionStatus.Ideal); // early GBAs did not patch the logo reading TOCTOU (only relevant for bootlegs that logo swap) - Option("GBC", "AGB", File("0DAAC31ACB6CB346FC954368ACB02ACB3ADCC3AB", 2304, "agb0.bin", "Game Boy Color Boot Rom (GBA, Early Revision)")); + Option("GBC", "AGB", File("0DAAC31ACB6CB346FC954368ACB02ACB3ADCC3AB", 2304, "GBC_agb0.bin", "Game Boy Color Boot Rom (GBA, Early Revision)")); // functionally equal to agb0.bin (no TOCTOU patch) - Option("GBC", "AGB", File("1ECAFA77AB3172193F3305486A857F443E28EBD9", 2304, "agb_gambatte.bin", "Game Boy Color Boot Rom (GBA, Gambatte RE)"), FirmwareOptionStatus.Bad); + Option("GBC", "AGB", File("1ECAFA77AB3172193F3305486A857F443E28EBD9", 2304, "GBC_agb_gambatte.bin", "Game Boy Color Boot Rom (GBA, Gambatte RE)"), FirmwareOptionStatus.Bad); AddPatchAndMaybeReverse(new( "1293D68BF9643BC4F36954C1E80E38F39864528D", new FirmwarePatchData(0xF3, new byte[] { 0x03, 0x00, 0xCD, 0x1D, 0xD5, 0xAA, 0x4F, 0x90, 0x74 }), @@ -498,6 +505,30 @@ void AddPatchAndMaybeReverse(FirmwarePatchOption fpo) FirmwareAndOption("10C4173C2A7EB09C6579818F72EF18FA0B6D32DE", 4 * 1024 * 1024, "N64DD", "IPL_DEV", "64DD_IPL_DEV.bin", "N64DD Development IPL"); FirmwareAndOption("3C5B93CA231550C68693A14F03CEA8D5DBD1BE9E", 4 * 1024 * 1024, "N64DD", "IPL_USA", "64DD_IPL_USA.bin", "N64DD Prototype USA IPL"); + Firmware("Amiga", "A500", "A500 Kickstart"); + Option("Amiga", "A500", File("891E9A547772FE0C6C19B610BAF8BC4EA7FCB785", 262144, "amiga-os-130.rom", "Kickstart v1.3 r34.005 (1987-12)(Commodore)(A500-A1000-A2000-CDTV)[!]"), FirmwareOptionStatus.Ideal); + Option("Amiga", "A500", File("11F9E62CF299F72184835B7B2A70A16333FC0D88", 262144, "amiga-os-120.rom", "Kickstart v1.2 r33.180 (1986-10)(Commodore)(A500-A1000-A2000)[!]")); + Option("Amiga", "A500", File("3B7F1493B27E212830F989F26CA76C02049F09CA", 524288, "amiga-os-310-a600.rom", "Kickstart v3.1 r40.063 (1993-07)(Commodore)(A500-A600-A2000)[!]")); + + Firmware("Amiga", "A600", "A500+/A600/A600HD Kickstart"); + Option("Amiga", "A600", File("02843C4253BBD29ABA535B0AA3BD9A85034ECDE4", 524288, "amiga-os-205-a600.rom", "Kickstart v2.05 r37.350 (1992-04)(Commodore)(A600HD)[!]"), FirmwareOptionStatus.Ideal); + Option("Amiga", "A600", File("C5839F5CB98A7A8947065C3ED2F14F5F42E334A1", 524288, "amiga-os-204.rom", "Kickstart v2.04 r37.175 (1991-05)(Commodore)(A500+)[!]")); + Option("Amiga", "A600", File("3B7F1493B27E212830F989F26CA76C02049F09CA", 524288, "amiga-os-310-a600.rom", "Kickstart v3.1 r40.063 (1993-07)(Commodore)(A500-A600-A2000)[!]")); + + Firmware("Amiga", "A1200", "A1200 Kickstart"); + Option("Amiga", "A1200", File("E21545723FE8374E91342617604F1B3D703094F1", 524288, "amiga-os-310-a1200.rom", "Kickstart v3.1 r40.068 (1993-12)(Commodore)(A1200)[!]"), FirmwareOptionStatus.Ideal); + Option("Amiga", "A1200", File("70033828182FFFC7ED106E5373A8B89DDA76FAA5", 524288, "amiga-os-300-a1200.rom", "Kickstart v3.0 r39.106 (1992-09)(Commodore)(A1200)[!]")); + + Firmware("Amiga", "A4000", "A4000/A4000T Kickstart"); + Option("Amiga", "A4000", File("5FE04842D04A489720F0F4BB0E46948199406F49", 524288, "amiga-os-310-a4000.rom", "Kickstart v3.1 r40.068 (1993-12)(Commodore)(A4000)[!]"), FirmwareOptionStatus.Ideal); + Option("Amiga", "A4000", File("F0B4E9E29E12218C2D5BD7020E4E785297D91FD7", 524288, "amiga-os-300-a4000.rom", "Kickstart v3.0 r39.106 (1992-09)(Commodore)(A4000)[!]")); + Option("Amiga", "A4000", File("B0EC8B84D6768321E01209F11E6248F2F5281A21", 524288, "amiga-os-310-a4000t.rom", "Kickstart v3.1 r40.070 (1994-02)(Commodore)(A4000T)[!]")); + + Firmware("Amiga", "CD32", "CD32 Kickstart"); + Option("Amiga", "CD32", File("3525BE8887F79B5929E017B42380A79EDFEE542D", 524288, "amiga-os-310-cd32.rom", "Kickstart v3.1 r40.060 (1993-05)(Commodore)(CD32)[!].rom"), FirmwareOptionStatus.Ideal); + Firmware("Amiga", "CD32ext", "CD32 Extended ROM"); + Option("Amiga", "CD32ext", File("5BEF3D628CE59CC02A66E6E4AE0DA48F60E78F7F", 524288, "amiga-os-310-cd32-ext.rom", "CD32 Extended-ROM r40.60 (1993)(Commodore)(CD32).rom"), FirmwareOptionStatus.Ideal); + /*Firmware("PS2", "BIOS", "PS2 Bios"); Option("PS2", "BIOS", File("FBD54BFC020AF34008B317DCB80B812DD29B3759", 4 * 1024 * 1024, "ps2-0230j-20080220.bin", "PS2 Bios")); Option("PS2", "BIOS", File("8361D615CC895962E0F0838489337574DBDC9173", 4 * 1024 * 1024, "ps2-0220a-20060905.bin", "PS2 Bios")); diff --git a/src/BizHawk.Emulation.Common/Database/FirmwareFile.cs b/src/BizHawk.Emulation.Common/Database/FirmwareFile.cs index a855962b5c0..0576129e062 100644 --- a/src/BizHawk.Emulation.Common/Database/FirmwareFile.cs +++ b/src/BizHawk.Emulation.Common/Database/FirmwareFile.cs @@ -1,7 +1,23 @@ +using System.Linq; + +using BizHawk.Common.StringExtensions; + namespace BizHawk.Emulation.Common { public readonly struct FirmwareFile { + internal static void CheckChecksumStrIsHex(ref string digest) + { + static bool IsAllowedCharacter(char c) + => c is (>= '0' and <= '9') or (>= 'A' and <= 'F'); //TODO SearchValues? + if (digest.All(IsAllowedCharacter)) return; + if (!digest.IsHex()) throw new ArgumentOutOfRangeException(paramName: nameof(digest), actualValue: digest, message: "malformed checksum digest: must match /[0-9A-F]+/ (no lowercase please)"); + // but if it is hex, let's be lenient + Console.Write("interpreting as hex checksum digest and uppercasing (please fix in source): "); + Console.WriteLine(digest); + digest = digest.ToUpperInvariant(); + } + public readonly string Description; public readonly string Hash; @@ -22,6 +38,7 @@ public FirmwareFile( string additionalInfo = "", bool isBad = false) { + CheckChecksumStrIsHex(ref hash); Description = desc; Hash = hash; Info = additionalInfo; diff --git a/src/BizHawk.Emulation.Common/Database/FirmwareID.cs b/src/BizHawk.Emulation.Common/Database/FirmwareID.cs index 70173dc9c45..98f56198946 100644 --- a/src/BizHawk.Emulation.Common/Database/FirmwareID.cs +++ b/src/BizHawk.Emulation.Common/Database/FirmwareID.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; namespace BizHawk.Emulation.Common @@ -22,8 +21,8 @@ public FirmwareID(string system, string firmware) static bool IsAllowedCharacter(char c) => c is '-' or (>= '0' and <= '9') or (>= 'A' and <= 'Z') or '_' or (>= 'a' and <= 'z'); const string ERR_MSG_INVALID_CHAR = "FWIDs must match /[-0-9A-Z_a-z]+/"; - if (!system.All(IsAllowedCharacter)) throw new ArgumentOutOfRangeException(paramName: system, actualValue: system, message: ERR_MSG_INVALID_CHAR); - if (!firmware.All(IsAllowedCharacter)) throw new ArgumentOutOfRangeException(paramName: firmware, actualValue: firmware, message: ERR_MSG_INVALID_CHAR); + if (!system.All(IsAllowedCharacter)) throw new ArgumentOutOfRangeException(paramName: nameof(system), actualValue: system, message: ERR_MSG_INVALID_CHAR); + if (!firmware.All(IsAllowedCharacter)) throw new ArgumentOutOfRangeException(paramName: nameof(firmware), actualValue: firmware, message: ERR_MSG_INVALID_CHAR); System = system; Firmware = firmware; } diff --git a/src/BizHawk.Emulation.Common/Database/FirmwareOption.cs b/src/BizHawk.Emulation.Common/Database/FirmwareOption.cs index fa5ec1dc1ed..205f1b4b8e3 100644 --- a/src/BizHawk.Emulation.Common/Database/FirmwareOption.cs +++ b/src/BizHawk.Emulation.Common/Database/FirmwareOption.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Common { public readonly struct FirmwareOption : IEquatable @@ -22,6 +20,7 @@ namespace BizHawk.Emulation.Common public FirmwareOption(FirmwareID id, string hash, long size, FirmwareOptionStatus status) { + FirmwareFile.CheckChecksumStrIsHex(ref hash); Hash = hash; ID = id; Size = size; diff --git a/src/BizHawk.Emulation.Common/Database/FirmwarePatchData.cs b/src/BizHawk.Emulation.Common/Database/FirmwarePatchData.cs index 371ffe88511..5239a4b0054 100644 --- a/src/BizHawk.Emulation.Common/Database/FirmwarePatchData.cs +++ b/src/BizHawk.Emulation.Common/Database/FirmwarePatchData.cs @@ -1,13 +1,13 @@ - -using System; - namespace BizHawk.Emulation.Common { /// /// Represents a binary patch, to be applied to a byte array. Patches must be contiguous; multiple instances can be used to for non-contiguous patches. /// Patches usually contain data which needs to be XOR'd with a base file, but with set to , this struct can represent data which should replace part of a base file. /// - /// TODO no mechanism to change length, would that be useful? --yoshi + /// + /// TODO no mechanism to change length, would that be useful? --yoshi
+ /// upon further reflection, I'm heading towards what is effectively a worse .bps, so maybe just use that --a later yoshi + ///
public readonly struct FirmwarePatchData { public readonly byte[] Contents; diff --git a/src/BizHawk.Emulation.Common/Database/FirmwarePatchOption.cs b/src/BizHawk.Emulation.Common/Database/FirmwarePatchOption.cs index 6cd4d69876b..116f8737ea1 100644 --- a/src/BizHawk.Emulation.Common/Database/FirmwarePatchOption.cs +++ b/src/BizHawk.Emulation.Common/Database/FirmwarePatchOption.cs @@ -1,4 +1,3 @@ - using System.Collections.Generic; namespace BizHawk.Emulation.Common @@ -15,6 +14,8 @@ public readonly struct FirmwarePatchOption public FirmwarePatchOption(string baseHash, IReadOnlyList patches, string targetHash) { + FirmwareFile.CheckChecksumStrIsHex(ref baseHash); + FirmwareFile.CheckChecksumStrIsHex(ref targetHash); BaseHash = baseHash; Patches = patches; TargetHash = targetHash; diff --git a/src/BizHawk.Emulation.Common/Database/FirmwareRecord.cs b/src/BizHawk.Emulation.Common/Database/FirmwareRecord.cs index b1b1ee05b63..23cc72c9b6c 100644 --- a/src/BizHawk.Emulation.Common/Database/FirmwareRecord.cs +++ b/src/BizHawk.Emulation.Common/Database/FirmwareRecord.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Common { public readonly struct FirmwareRecord : IEquatable diff --git a/src/BizHawk.Emulation.Common/Database/GameInfo.cs b/src/BizHawk.Emulation.Common/Database/GameInfo.cs index 9cc80b935f2..4928ad32c46 100644 --- a/src/BizHawk.Emulation.Common/Database/GameInfo.cs +++ b/src/BizHawk.Emulation.Common/Database/GameInfo.cs @@ -162,7 +162,7 @@ private void ParseOptionsDictionary(string metaData) return; } - var options = metaData.Split(';').Where(opt => string.IsNullOrEmpty(opt) == false).ToArray(); + var options = metaData.Split(';').Where(opt => !string.IsNullOrEmpty(opt)).ToArray(); foreach (var opt in options) { diff --git a/src/BizHawk.Emulation.Common/EmulationExceptions.cs b/src/BizHawk.Emulation.Common/EmulationExceptions.cs index 1a729e9293f..e5584eb699c 100644 --- a/src/BizHawk.Emulation.Common/EmulationExceptions.cs +++ b/src/BizHawk.Emulation.Common/EmulationExceptions.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Common { public class MissingFirmwareException : Exception diff --git a/src/BizHawk.Emulation.Common/Extensions.cs b/src/BizHawk.Emulation.Common/Extensions.cs index d3e83b7d855..07742c0db86 100644 --- a/src/BizHawk.Emulation.Common/Extensions.cs +++ b/src/BizHawk.Emulation.Common/Extensions.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -17,6 +16,7 @@ public static class EmulatorExtensions /// need to think about e.g. Genesis / Mega Drive using one sysID but having a different display name depending on the BIOS region --yoshi public static readonly IReadOnlyDictionary SystemIDDisplayNames = new Dictionary { + [VSystemID.Raw.Amiga] = "Amiga", [VSystemID.Raw.A26] = "Atari 2600", [VSystemID.Raw.A78] = "Atari 7800", [VSystemID.Raw.AmstradCPC] = "Amstrad CPC", @@ -353,6 +353,12 @@ public static double VsyncRate(this IEmulator core) return core.VsyncNumerator() / (double)core.VsyncDenominator(); } + public static bool HasCycleTiming(this IEmulator core) + => core != null && core.ServiceProvider.HasService(); + + public static ICycleTiming AsCycleTiming(this IEmulator core) + => core.ServiceProvider.GetService(); + public static bool IsImplemented(this MethodInfo info) { return !info.GetCustomAttributes(false).Any(a => a is FeatureNotImplementedAttribute); diff --git a/src/BizHawk.Emulation.Common/Interfaces/IEmulator.cs b/src/BizHawk.Emulation.Common/Interfaces/IEmulator.cs index 1dc0f78735d..b6ed8f92909 100644 --- a/src/BizHawk.Emulation.Common/Interfaces/IEmulator.cs +++ b/src/BizHawk.Emulation.Common/Interfaces/IEmulator.cs @@ -1,7 +1,5 @@ #nullable disable -using System; - namespace BizHawk.Emulation.Common { /// diff --git a/src/BizHawk.Emulation.Common/Interfaces/IEmulatorServiceProvider.cs b/src/BizHawk.Emulation.Common/Interfaces/IEmulatorServiceProvider.cs index 04161897cc4..efd87821d08 100644 --- a/src/BizHawk.Emulation.Common/Interfaces/IEmulatorServiceProvider.cs +++ b/src/BizHawk.Emulation.Common/Interfaces/IEmulatorServiceProvider.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Emulation.Common diff --git a/src/BizHawk.Emulation.Common/Interfaces/IInputCallbackSystem.cs b/src/BizHawk.Emulation.Common/Interfaces/IInputCallbackSystem.cs index 0dba96cbb01..bd26c688e16 100644 --- a/src/BizHawk.Emulation.Common/Interfaces/IInputCallbackSystem.cs +++ b/src/BizHawk.Emulation.Common/Interfaces/IInputCallbackSystem.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Emulation.Common diff --git a/src/BizHawk.Emulation.Common/Interfaces/IMemoryCallbackSystem.cs b/src/BizHawk.Emulation.Common/Interfaces/IMemoryCallbackSystem.cs index 1c6e9ad9a20..7a9af207a83 100644 --- a/src/BizHawk.Emulation.Common/Interfaces/IMemoryCallbackSystem.cs +++ b/src/BizHawk.Emulation.Common/Interfaces/IMemoryCallbackSystem.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Collections.Generic; namespace BizHawk.Emulation.Common diff --git a/src/BizHawk.Emulation.Common/Interfaces/IOpenGLProvider.cs b/src/BizHawk.Emulation.Common/Interfaces/IOpenGLProvider.cs index 3d498f5264e..10ba1498a50 100644 --- a/src/BizHawk.Emulation.Common/Interfaces/IOpenGLProvider.cs +++ b/src/BizHawk.Emulation.Common/Interfaces/IOpenGLProvider.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Common { /// @@ -14,13 +12,12 @@ public interface IOpenGLProvider public bool SupportsGLVersion(int major, int minor); /// - /// Requests an OpenGL context with specified major / minor + /// Requests an OpenGL context with specified major / minor version /// The core profile can be requested (otherwise, the compatibility profile will be used) - /// The forward compatible bit can also be requested /// The requested OpenGL context will be shared with the current context /// Note: creating a context implicitly makes that created context current /// - public object RequestGLContext(int major, int minor, bool coreProfile, bool forwardCompatible); + public object RequestGLContext(int major, int minor, bool coreProfile); /// /// Frees this OpenGL context diff --git a/src/BizHawk.Emulation.Common/Interfaces/Services/ICodeDataLogger.cs b/src/BizHawk.Emulation.Common/Interfaces/Services/ICodeDataLogger.cs index fb8853e6455..82ace49a3b9 100644 --- a/src/BizHawk.Emulation.Common/Interfaces/Services/ICodeDataLogger.cs +++ b/src/BizHawk.Emulation.Common/Interfaces/Services/ICodeDataLogger.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Collections.Generic; diff --git a/src/BizHawk.Emulation.Common/Interfaces/Services/IDebuggable.cs b/src/BizHawk.Emulation.Common/Interfaces/Services/IDebuggable.cs index 54d52b19bb0..b654978b7ed 100644 --- a/src/BizHawk.Emulation.Common/Interfaces/Services/IDebuggable.cs +++ b/src/BizHawk.Emulation.Common/Interfaces/Services/IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Emulation.Common diff --git a/src/BizHawk.Emulation.Common/Interfaces/Services/IDisassemblable.cs b/src/BizHawk.Emulation.Common/Interfaces/Services/IDisassemblable.cs index 8fed0a4555a..a653f5aa871 100644 --- a/src/BizHawk.Emulation.Common/Interfaces/Services/IDisassemblable.cs +++ b/src/BizHawk.Emulation.Common/Interfaces/Services/IDisassemblable.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Collections.Generic; diff --git a/src/BizHawk.Emulation.Common/Interfaces/Services/ISettable.cs b/src/BizHawk.Emulation.Common/Interfaces/Services/ISettable.cs index 55b95b34c18..8f52c7ad0fd 100644 --- a/src/BizHawk.Emulation.Common/Interfaces/Services/ISettable.cs +++ b/src/BizHawk.Emulation.Common/Interfaces/Services/ISettable.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Linq; using System.Reflection; @@ -61,9 +60,7 @@ public interface ISettable : IEmulatorService /// Classes with this attribute will have a BizHawk.Common.SettingsUtil.SetDefaultValues(T) function generated /// [AttributeUsage(AttributeTargets.Class)] - public class CoreSettings : Attribute - { - } + public class CoreSettingsAttribute : Attribute {} //note: this is a bit of a frail API. If a frontend wants a new flag, cores won't know to yea or nay it //this could be solved by adding a KnownSettingsDirtyBits on the settings interface diff --git a/src/BizHawk.Emulation.Common/Interfaces/Services/ISoundProvider.cs b/src/BizHawk.Emulation.Common/Interfaces/Services/ISoundProvider.cs index b83161de34f..58a07c8d8ef 100644 --- a/src/BizHawk.Emulation.Common/Interfaces/Services/ISoundProvider.cs +++ b/src/BizHawk.Emulation.Common/Interfaces/Services/ISoundProvider.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Common { public enum SyncSoundMode diff --git a/src/BizHawk.Emulation.Common/Interfaces/Services/IVideoProvider.cs b/src/BizHawk.Emulation.Common/Interfaces/Services/IVideoProvider.cs index 20abcc9ebb6..4e0561cfba2 100644 --- a/src/BizHawk.Emulation.Common/Interfaces/Services/IVideoProvider.cs +++ b/src/BizHawk.Emulation.Common/Interfaces/Services/IVideoProvider.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Common { /// @@ -12,6 +10,9 @@ public interface IVideoProvider : IEmulatorService { /// /// Returns a frame buffer of the current video content + /// This might be a reference to a stored frame buffer + /// Only * pixels valid + /// (The buffer might be larger than such, so don't rely on /// int[] GetVideoBuffer(); @@ -83,5 +84,19 @@ public static void PopulateFromBuffer(this IVideoProvider videoProvider, int[] f b2[i] = b1[i]; } } + + /// + /// Obtains a copy of the video buffer + /// may return a reference + /// and might be much larger than the reported * (to account for differing frame sizes) + /// so this should be used to get an explicit copy + /// + public static int[] GetVideoBufferCopy(this IVideoProvider videoProvider) + { + var vb = videoProvider.GetVideoBuffer(); + var ret = new int[videoProvider.BufferWidth * videoProvider.BufferHeight]; + vb.AsSpan(0, ret.Length).CopyTo(ret); + return ret; + } } } diff --git a/src/BizHawk.Emulation.Common/N64RomByteswapper.cs b/src/BizHawk.Emulation.Common/N64RomByteswapper.cs index e986da338f3..cafcdb5913d 100644 --- a/src/BizHawk.Emulation.Common/N64RomByteswapper.cs +++ b/src/BizHawk.Emulation.Common/N64RomByteswapper.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; namespace BizHawk.Emulation.Common diff --git a/src/BizHawk.Emulation.Common/SaveController.cs b/src/BizHawk.Emulation.Common/SaveController.cs index 079710f5146..e8f7d65b0bb 100644 --- a/src/BizHawk.Emulation.Common/SaveController.cs +++ b/src/BizHawk.Emulation.Common/SaveController.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Collections.Generic; using System.IO; diff --git a/src/BizHawk.Emulation.Common/ServiceAttributes.cs b/src/BizHawk.Emulation.Common/ServiceAttributes.cs index 442cb9f9c09..87e0fd4e4e6 100644 --- a/src/BizHawk.Emulation.Common/ServiceAttributes.cs +++ b/src/BizHawk.Emulation.Common/ServiceAttributes.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Common/ServiceInjector.cs b/src/BizHawk.Emulation.Common/ServiceInjector.cs index 38f84169197..814bb9aed38 100644 --- a/src/BizHawk.Emulation.Common/ServiceInjector.cs +++ b/src/BizHawk.Emulation.Common/ServiceInjector.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Reflection; diff --git a/src/BizHawk.Emulation.Common/Sound/BlipBuffer.cs b/src/BizHawk.Emulation.Common/Sound/BlipBuffer.cs index 432fafcf888..b93c7de873b 100644 --- a/src/BizHawk.Emulation.Common/Sound/BlipBuffer.cs +++ b/src/BizHawk.Emulation.Common/Sound/BlipBuffer.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Runtime.InteropServices; // ReSharper disable StyleCop.SA1300 diff --git a/src/BizHawk.Emulation.Common/Sound/DCFilter.cs b/src/BizHawk.Emulation.Common/Sound/DCFilter.cs index 6e6f737daea..2666cc954a6 100644 --- a/src/BizHawk.Emulation.Common/Sound/DCFilter.cs +++ b/src/BizHawk.Emulation.Common/Sound/DCFilter.cs @@ -1,7 +1,5 @@ #nullable disable -using System; - namespace BizHawk.Emulation.Common { /// diff --git a/src/BizHawk.Emulation.Common/Sound/SDLResampler.cs b/src/BizHawk.Emulation.Common/Sound/SDLResampler.cs index 2e1f23db5b8..b4fa081419e 100644 --- a/src/BizHawk.Emulation.Common/Sound/SDLResampler.cs +++ b/src/BizHawk.Emulation.Common/Sound/SDLResampler.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Runtime.InteropServices; using static SDL2.SDL; diff --git a/src/BizHawk.Emulation.Common/TextState.cs b/src/BizHawk.Emulation.Common/TextState.cs index 2500b79b312..d2374142752 100644 --- a/src/BizHawk.Emulation.Common/TextState.cs +++ b/src/BizHawk.Emulation.Common/TextState.cs @@ -1,6 +1,5 @@ #nullable disable -using System; using System.Collections.Generic; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Emulation.Common/U8ArrayAsNormalJSONListConverter.cs b/src/BizHawk.Emulation.Common/U8ArrayAsNormalJSONListConverter.cs index 4ab496833ea..083e50876c0 100644 --- a/src/BizHawk.Emulation.Common/U8ArrayAsNormalJSONListConverter.cs +++ b/src/BizHawk.Emulation.Common/U8ArrayAsNormalJSONListConverter.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using Newtonsoft.Json; diff --git a/src/BizHawk.Emulation.Common/filetype_detectors/SatellaviewFileTypeDetector.cs b/src/BizHawk.Emulation.Common/filetype_detectors/SatellaviewFileTypeDetector.cs index 4a051dd4e90..c8913be5154 100644 --- a/src/BizHawk.Emulation.Common/filetype_detectors/SatellaviewFileTypeDetector.cs +++ b/src/BizHawk.Emulation.Common/filetype_detectors/SatellaviewFileTypeDetector.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Common/vpads_schemata/IVirtualPadSchema.cs b/src/BizHawk.Emulation.Common/vpads_schemata/IVirtualPadSchema.cs index 711b5b8d8fa..f2a8e551e57 100644 --- a/src/BizHawk.Emulation.Common/vpads_schemata/IVirtualPadSchema.cs +++ b/src/BizHawk.Emulation.Common/vpads_schemata/IVirtualPadSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Emulation.Common diff --git a/src/BizHawk.Emulation.Common/vpads_schemata/PadSchemaControl.cs b/src/BizHawk.Emulation.Common/vpads_schemata/PadSchemaControl.cs index b7f1c357a4e..1667476da90 100644 --- a/src/BizHawk.Emulation.Common/vpads_schemata/PadSchemaControl.cs +++ b/src/BizHawk.Emulation.Common/vpads_schemata/PadSchemaControl.cs @@ -94,7 +94,7 @@ public sealed class AnalogSchema : PadSchemaControl public AnalogSchema(int x, int y, string nameX) : base(new Point(x, y), nameX) - => SecondaryName = nameX.Replace("X", "Y"); + => SecondaryName = nameX.Replace('X', 'Y'); } /// An (X, Y) pair intended to be a screen coordinate (for zappers, mouse, stylus, etc.) @@ -111,9 +111,7 @@ public sealed class TargetedPairSchema : PadSchemaControl /// Using this ctor, the valid ranges for the X and Y axes are taken to be (0..TargetSize.Width) and (0..TargetSize.Height). public TargetedPairSchema(int x, int y, string nameX) : base(new Point(x, y), nameX) - { - SecondaryName = nameX.Replace("X", "Y"); - } + => SecondaryName = nameX.Replace('X', 'Y'); /// Using this ctor, the valid ranges for the X and Y axes are taken to be (0..maxX) and (0..maxY). public TargetedPairSchema(int x, int y, string nameX, int maxX, int maxY) diff --git a/src/BizHawk.Emulation.Common/vpads_schemata/SchemaAttribute.cs b/src/BizHawk.Emulation.Common/vpads_schemata/SchemaAttribute.cs index 5cb66038508..c9266bd3710 100644 --- a/src/BizHawk.Emulation.Common/vpads_schemata/SchemaAttribute.cs +++ b/src/BizHawk.Emulation.Common/vpads_schemata/SchemaAttribute.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Common { [AttributeUsage(AttributeTargets.Class)] diff --git a/src/BizHawk.Emulation.Cores/Arcades/MAME/LibMAME.cs b/src/BizHawk.Emulation.Cores/Arcades/MAME/LibMAME.cs index 93ea8033ed5..fa4ce8eee4a 100644 --- a/src/BizHawk.Emulation.Cores/Arcades/MAME/LibMAME.cs +++ b/src/BizHawk.Emulation.Cores/Arcades/MAME/LibMAME.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.BizInvoke; diff --git a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.IInputPollable.cs b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.IInputPollable.cs index 1b5b8ee87df..cbc93ea37e5 100644 --- a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.IInputPollable.cs +++ b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.IInputPollable.cs @@ -1,6 +1,4 @@ -using System; using System.Collections.Generic; -using System.Linq; using BizHawk.Common; using BizHawk.Common.StringExtensions; @@ -47,7 +45,7 @@ void AddFieldPtr(string tag, string field) foreach (var buttonField in buttonFields) { - if (buttonField != string.Empty && !buttonField.Contains('%')) + if (buttonField.Length is not 0 && !buttonField.ContainsOrdinal('%')) { var tag = buttonField.SubstringBefore(','); var field = buttonField.SubstringAfterLast(','); @@ -66,7 +64,7 @@ void AddFieldPtr(string tag, string field) foreach (var analogField in analogFields) { - if (analogField != string.Empty && !analogField.Contains('%')) + if (analogField.Length is not 0 && !analogField.ContainsOrdinal('%')) { var keys = analogField.Split(','); var tag = keys[0]; diff --git a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISaveRam.cs index 02e5b697ac3..921d6b918a6 100644 --- a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISaveRam.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; diff --git a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISettable.ComponentModel.cs b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISettable.ComponentModel.cs index fc506c69ffe..9a95ee2994c 100644 --- a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISettable.ComponentModel.cs +++ b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISettable.ComponentModel.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; diff --git a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISettable.cs b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISettable.cs index 65fa861e02e..a2b5e39ce20 100644 --- a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISettable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; @@ -166,7 +165,7 @@ private void GetROMsInfo() } else { - if (hashdata.Contains("^")) + if (hashdata.EndsWithOrdinal('^')) { hashdata = hashdata.RemoveSuffix("^"); name += " (BAD DUMP)"; diff --git a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISoundProvider.cs b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISoundProvider.cs index 5caabf0290b..9b69526167f 100644 --- a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISoundProvider.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Arcades.MAME diff --git a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.IVideoProvider.cs b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.IVideoProvider.cs index 92ec289baa4..99d19629969 100644 --- a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.IVideoProvider.cs +++ b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.IVideoProvider.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Arcades.MAME diff --git a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.MemoryDomains.cs b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.MemoryDomains.cs index f203b1bfb30..5ab82b5fb20 100644 --- a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.MemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.MemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.cs b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.cs index 6fffc072ae5..6c0f486bcef 100644 --- a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.cs +++ b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; diff --git a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAMEMachineDB.cs b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAMEMachineDB.cs index dae31e314d1..b6524909c37 100644 --- a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAMEMachineDB.cs +++ b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAMEMachineDB.cs @@ -1,8 +1,6 @@ -using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Linq; using System.Threading; using BizHawk.Common; @@ -54,7 +52,7 @@ private MAMEMachineDB(string basePath) public static bool IsMAMEMachine(string path) { if (_acquire == null) throw new InvalidOperationException("MAME Machine DB not initialized. It's a client responsibility because only a client knows where the database is located."); - if (path.Contains('|')) return false; // binded archive, can't be a mame zip (note | is not a legal filesystem char, at least on windows) + if (HawkFile.PathContainsPipe(path)) return false; // binded archive, can't be a mame zip (note | is not a legal filesystem char, at least on windows) if (Path.GetExtension(path).ToLowerInvariant() is not ".zip" and not ".7z") return false; _acquire.WaitOne(); return Instance.MachineDB.Contains(Path.GetFileNameWithoutExtension(path).ToLowerInvariant()); diff --git a/src/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/src/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 3657b7a326e..d7b08cadde0 100644 --- a/src/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/src/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -5,7 +5,7 @@ true - $(NoWarn);CA1806;CA1825;CA2214;MA0084;SA1100;SA1120;SA1129;SA1137;SA1205;SA1208;SA1400 + $(NoWarn);BHI1104;CA1806;CA1825;CA2214;MA0060;MA0084;MA0090;MA0140;SA1100;SA1120;SA1129;SA1137;SA1205;SA1208;SA1400;SA1514;SA1517 disable diff --git a/src/BizHawk.Emulation.Cores/CPUs/68000/Instructions/DataMovement.cs b/src/BizHawk.Emulation.Cores/CPUs/68000/Instructions/DataMovement.cs index dcb960e4e38..11e57968f7f 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/68000/Instructions/DataMovement.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/68000/Instructions/DataMovement.cs @@ -1,4 +1,3 @@ -using System; using System.Text; namespace BizHawk.Emulation.Cores.Components.M68000 diff --git a/src/BizHawk.Emulation.Cores/CPUs/68000/Instructions/IntegerMath.cs b/src/BizHawk.Emulation.Cores/CPUs/68000/Instructions/IntegerMath.cs index 77b03704354..bc023efbbde 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/68000/Instructions/IntegerMath.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/68000/Instructions/IntegerMath.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Components.M68000 { partial class MC68000 @@ -348,7 +346,7 @@ private void SUB0() sbyte a = D[dReg].s8; sbyte b = ReadValueB(mode, reg); int result = a - b; - X = C = ((a < b) ^ ((a ^ b) >= 0) == false); + X = C = (a < b) ^ (a ^ b) < 0; V = result > sbyte.MaxValue || result < sbyte.MinValue; N = (result & 0x80) != 0; Z = result == 0; @@ -361,7 +359,7 @@ private void SUB0() short a = D[dReg].s16; short b = ReadValueW(mode, reg); int result = a - b; - X = C = ((a < b) ^ ((a ^ b) >= 0) == false); + X = C = (a < b) ^ (a ^ b) < 0; V = result > short.MaxValue || result < short.MinValue; N = (result & 0x8000) != 0; Z = result == 0; @@ -374,7 +372,7 @@ private void SUB0() int a = D[dReg].s32; int b = ReadValueL(mode, reg); long result = a - b; - X = C = ((a < b) ^ ((a ^ b) >= 0) == false); + X = C = (a < b) ^ (a ^ b) < 0; V = result > int.MaxValue || result < int.MinValue; N = (result & 0x80000000) != 0; Z = result == 0; @@ -399,7 +397,7 @@ private void SUB1() sbyte a = PeekValueB(mode, reg); sbyte b = D[dReg].s8; int result = a - b; - X = C = ((a < b) ^ ((a ^ b) >= 0) == false); + X = C = (a < b) ^ (a ^ b) < 0; V = result > sbyte.MaxValue || result < sbyte.MinValue; N = (result & 0x80) != 0; Z = result == 0; @@ -412,7 +410,7 @@ private void SUB1() short a = PeekValueW(mode, reg); short b = D[dReg].s16; int result = a - b; - X = C = ((a < b) ^ ((a ^ b) >= 0) == false); + X = C = (a < b) ^ (a ^ b) < 0; V = result > short.MaxValue || result < short.MinValue; N = (result & 0x8000) != 0; Z = result == 0; @@ -425,7 +423,7 @@ private void SUB1() int a = PeekValueL(mode, reg); int b = D[dReg].s32; long result = a - b; - X = C = ((a < b) ^ ((a ^ b) >= 0) == false); + X = C = (a < b) ^ (a ^ b) < 0; V = result > int.MaxValue || result < int.MinValue; N = (result & 0x80000000) != 0; Z = result == 0; @@ -471,7 +469,7 @@ private void SUBI() sbyte b = (sbyte)ReadWord(PC); PC += 2; sbyte a = PeekValueB(mode, reg); int result = a - b; - X = C = ((a < b) ^ ((a ^ b) >= 0) == false); + X = C = (a < b) ^ (a ^ b) < 0; V = result > sbyte.MaxValue || result < sbyte.MinValue; N = (result & 0x80) != 0; Z = result == 0; @@ -485,7 +483,7 @@ private void SUBI() short b = ReadWord(PC); PC += 2; short a = PeekValueW(mode, reg); int result = a - b; - X = C = ((a < b) ^ ((a ^ b) >= 0) == false); + X = C = (a < b) ^ (a ^ b) < 0; V = result > short.MaxValue || result < short.MinValue; N = (result & 0x8000) != 0; Z = result == 0; @@ -499,7 +497,7 @@ private void SUBI() int b = ReadLong(PC); PC += 4; int a = PeekValueL(mode, reg); long result = a - b; - X = C = ((a < b) ^ ((a ^ b) >= 0) == false); + X = C = (a < b) ^ (a ^ b) < 0; V = result > int.MaxValue || result < int.MinValue; N = (result & 0x80000000) != 0; Z = result == 0; @@ -555,7 +553,7 @@ private void SUBQ() N = (result & 0x80) != 0; Z = result == 0; V = result > sbyte.MaxValue || result < sbyte.MinValue; - C = X = ((value < data) ^ ((value ^ data) >= 0) == false); + C = X = (value < data) ^ (value ^ data) < 0; WriteValueB(mode, reg, (sbyte)result); if (mode == 0) PendingCycles -= 4; else PendingCycles -= 8 + EACyclesBW[mode, reg]; @@ -575,7 +573,7 @@ private void SUBQ() N = (result & 0x8000) != 0; Z = result == 0; V = result > short.MaxValue || result < short.MinValue; - C = X = ((value < data) ^ ((value ^ data) >= 0) == false); + C = X = (value < data) ^ (value ^ data) < 0; WriteValueW(mode, reg, (short)result); } if (mode <= 1) PendingCycles -= 4; @@ -591,7 +589,7 @@ private void SUBQ() N = (result & 0x80000000) != 0; Z = result == 0; V = result > int.MaxValue || result < int.MinValue; - C = X = ((value < data) ^ ((value ^ data) >= 0) == false); + C = X = (value < data) ^ (value ^ data) < 0; } WriteValueL(mode, reg, (int)result); if (mode <= 1) PendingCycles -= 8; @@ -676,7 +674,7 @@ private void NEG() N = (result & 0x80) != 0; Z = result == 0; V = result > sbyte.MaxValue || result < sbyte.MinValue; - C = X = ((0 < value) ^ ((0 ^ value) >= 0) == false); + C = X = (0 < value) ^ (0 ^ value) < 0; WriteValueB(mode, reg, (sbyte)result); if (mode == 0) PendingCycles -= 4; else PendingCycles -= 8 + EACyclesBW[mode, reg]; @@ -689,7 +687,7 @@ private void NEG() N = (result & 0x8000) != 0; Z = result == 0; V = result > short.MaxValue || result < short.MinValue; - C = X = ((0 < value) ^ ((0 ^ value) >= 0) == false); + C = X = (0 < value) ^ (0 ^ value) < 0; WriteValueW(mode, reg, (short)result); if (mode == 0) PendingCycles -= 4; else PendingCycles -= 8 + EACyclesBW[mode, reg]; @@ -702,7 +700,7 @@ private void NEG() N = (result & 0x80000000) != 0; Z = result == 0; V = result > int.MaxValue || result < int.MinValue; - C = X = ((0 < value) ^ ((0 ^ value) >= 0) == false); + C = X = (0 < value) ^ (0 ^ value) < 0; WriteValueL(mode, reg, (int)result); if (mode == 0) PendingCycles -= 8; else PendingCycles -= 12 + EACyclesL[mode, reg]; @@ -755,7 +753,7 @@ private void CMP() N = (result & 0x80) != 0; Z = result == 0; V = result > sbyte.MaxValue || result < sbyte.MinValue; - C = ((a < b) ^ ((a ^ b) >= 0) == false); + C = (a < b) ^ (a ^ b) < 0; if (mode == 0) PendingCycles -= 8; PendingCycles -= 4 + EACyclesBW[mode, reg]; return; @@ -768,7 +766,7 @@ private void CMP() N = (result & 0x8000) != 0; Z = result == 0; V = result > short.MaxValue || result < short.MinValue; - C = ((a < b) ^ ((a ^ b) >= 0) == false); + C = (a < b) ^ (a ^ b) < 0; if (mode == 0) PendingCycles -= 8; PendingCycles -= 4 + EACyclesBW[mode, reg]; return; @@ -781,7 +779,7 @@ private void CMP() N = (result & 0x80000000) != 0; Z = result == 0; V = result > int.MaxValue || result < int.MinValue; - C = ((a < b) ^ ((a ^ b) >= 0) == false); + C = (a < b) ^ (a ^ b) < 0; PendingCycles -= 6 + EACyclesL[mode, reg]; return; } @@ -832,7 +830,7 @@ private void CMPA() N = (result & 0x8000) != 0; Z = result == 0; V = result > short.MaxValue || result < short.MinValue; - C = ((a < b) ^ ((a ^ b) >= 0) == false); + C = (a < b) ^ (a ^ b) < 0; PendingCycles -= 6 + EACyclesBW[mode, reg]; return; } @@ -844,7 +842,7 @@ private void CMPA() N = (result & 0x80000000) != 0; Z = result == 0; V = result > int.MaxValue || result < int.MinValue; - C = ((a < b) ^ ((a ^ b) >= 0) == false); + C = (a < b) ^ (a ^ b) < 0; PendingCycles -= 6 + EACyclesL[mode, reg]; return; } @@ -890,7 +888,7 @@ private void CMPM() N = (result & 0x80) != 0; Z = result == 0; V = result > sbyte.MaxValue || result < sbyte.MinValue; - C = ((a < b) ^ ((a ^ b) >= 0) == false); + C = (a < b) ^ (a ^ b) < 0; PendingCycles -= 12; return; } @@ -902,7 +900,7 @@ private void CMPM() N = (result & 0x8000) != 0; Z = result == 0; V = result > short.MaxValue || result < short.MinValue; - C = ((a < b) ^ ((a ^ b) >= 0) == false); + C = (a < b) ^ (a ^ b) < 0; PendingCycles -= 12; return; } @@ -914,7 +912,7 @@ private void CMPM() N = (result & 0x80000000) != 0; Z = result == 0; V = result > int.MaxValue || result < int.MinValue; - C = ((a < b) ^ ((a ^ b) >= 0) == false); + C = (a < b) ^ (a ^ b) < 0; PendingCycles -= 20; return; } @@ -954,7 +952,7 @@ private void CMPI() N = (result & 0x80) != 0; Z = result == 0; V = result > sbyte.MaxValue || result < sbyte.MinValue; - C = ((a < b) ^ ((a ^ b) >= 0) == false); + C = (a < b) ^ (a ^ b) < 0; if (mode == 0) PendingCycles -= 8; else PendingCycles -= 8 + EACyclesBW[mode, reg]; return; @@ -967,7 +965,7 @@ private void CMPI() N = (result & 0x8000) != 0; Z = result == 0; V = result > short.MaxValue || result < short.MinValue; - C = ((a < b) ^ ((a ^ b) >= 0) == false); + C = (a < b) ^ (a ^ b) < 0; if (mode == 0) PendingCycles -= 8; else PendingCycles -= 8 + EACyclesBW[mode, reg]; return; @@ -980,7 +978,7 @@ private void CMPI() N = (result & 0x80000000) != 0; Z = result == 0; V = result > int.MaxValue || result < int.MinValue; - C = ((a < b) ^ ((a ^ b) >= 0) == false); + C = (a < b) ^ (a ^ b) < 0; if (mode == 0) PendingCycles -= 14; else PendingCycles -= 12 + EACyclesL[mode, reg]; return; diff --git a/src/BizHawk.Emulation.Cores/CPUs/68000/Instructions/ProgramFlow.cs b/src/BizHawk.Emulation.Cores/CPUs/68000/Instructions/ProgramFlow.cs index 9aa956a982f..f23ed72c82d 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/68000/Instructions/ProgramFlow.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/68000/Instructions/ProgramFlow.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Components.M68000 { partial class MC68000 diff --git a/src/BizHawk.Emulation.Cores/CPUs/68000/Instructions/Supervisor.cs b/src/BizHawk.Emulation.Cores/CPUs/68000/Instructions/Supervisor.cs index 7836d650e05..5b5d23c8b3c 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/68000/Instructions/Supervisor.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/68000/Instructions/Supervisor.cs @@ -1,12 +1,10 @@ -using System; - namespace BizHawk.Emulation.Cores.Components.M68000 { partial class MC68000 { private void MOVEtSR() { - if (S == false) + if (!S) throw new Exception("Write to SR when not in supervisor mode. supposed to trap or something..."); int mode = (op >> 3) & 7; @@ -45,7 +43,7 @@ private void MOVEfSR_Disasm(DisassemblyInfo info) private void MOVEUSP() { - if (S == false) + if (!S) throw new Exception("MOVE to USP when not supervisor. needs to trap"); int dir = (op >> 3) & 1; @@ -69,7 +67,7 @@ private void MOVEUSP_Disasm(DisassemblyInfo info) private void ANDI_SR() { - if (S == false) + if (!S) throw new Exception("trap!"); SR &= ReadWord(PC); PC += 2; PendingCycles -= 20; @@ -85,7 +83,7 @@ private void ANDI_SR_Disasm(DisassemblyInfo info) private void EORI_SR() { - if (S == false) + if (!S) throw new Exception("trap!"); SR ^= ReadWord(PC); PC += 2; PendingCycles -= 20; @@ -101,7 +99,7 @@ private void EORI_SR_Disasm(DisassemblyInfo info) private void ORI_SR() { - if (S == false) + if (!S) throw new Exception("trap!"); SR |= ReadWord(PC); PC += 2; PendingCycles -= 20; @@ -160,4 +158,4 @@ private void TrapVector(int vector) PC = ReadLong(vector * 4); // Jump to vector } } -} \ No newline at end of file +} diff --git a/src/BizHawk.Emulation.Cores/CPUs/68000/MC68000.cs b/src/BizHawk.Emulation.Cores/CPUs/68000/MC68000.cs index ec0ff467236..c5e1afdf8db 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/68000/MC68000.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/68000/MC68000.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using System.IO; using System.Globalization; diff --git a/src/BizHawk.Emulation.Cores/CPUs/68000/Memory.cs b/src/BizHawk.Emulation.Cores/CPUs/68000/Memory.cs index d456c4c5d49..526ac2afc7e 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/68000/Memory.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/68000/Memory.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Components.M68000 { partial class MC68000 diff --git a/src/BizHawk.Emulation.Cores/CPUs/68000/OpcodeTable.cs b/src/BizHawk.Emulation.Cores/CPUs/68000/OpcodeTable.cs index e6fc59cccf5..193c683b1db 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/68000/OpcodeTable.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/68000/OpcodeTable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common.StringExtensions; diff --git a/src/BizHawk.Emulation.Cores/CPUs/ARM/Darm.cs b/src/BizHawk.Emulation.Cores/CPUs/ARM/Darm.cs index 2f51213b6bd..7769abf10e2 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/ARM/Darm.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/ARM/Darm.cs @@ -1,4 +1,3 @@ -using System; using System.Text; using System.Runtime.InteropServices; @@ -99,7 +98,6 @@ public string DisassembleStuff(uint addr, uint opcode) if (Str(d, s, false)) return null; string[] ret = Encoding.ASCII.GetString(s.total, 0, Array.IndexOf(s.total, (byte)0)) - .ToString() .Split(new string[] {" "}, 2, StringSplitOptions.None); return ret[0].PadRight(8) + (ret.Length > 1 ? ret[1] : ""); } diff --git a/src/BizHawk.Emulation.Cores/CPUs/CP1610/CP1610.Execute.cs b/src/BizHawk.Emulation.Cores/CPUs/CP1610/CP1610.Execute.cs index 42a6597b06f..e1eae87e5c6 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/CP1610/CP1610.Execute.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/CP1610/CP1610.Execute.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/CPUs/CP1610/CP1610.cs b/src/BizHawk.Emulation.Cores/CPUs/CP1610/CP1610.cs index 34d2d7828e0..7ac19d08744 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/CP1610/CP1610.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/CP1610/CP1610.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Disassembler.cs b/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Disassembler.cs index 8b4ad69ed77..331930d8087 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Disassembler.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Disassembler.cs @@ -1,5 +1,6 @@ -using System; using System.Collections.Generic; + +using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Components.FairchildF8 @@ -15,17 +16,16 @@ private static string Result(string format, Func read, ref ushort //n immediate succeeds the opcode and the displacement (if present) //nn immediately succeeds the opcode and the displacement (if present) - if (format.IndexOf("nn", StringComparison.Ordinal) != -1) + if (format.ContainsOrdinal("nn")) { format = format.Replace("nn", read(addr++) .ToString("X2") + read(addr++) .ToString("X2") + "h"); // MSB is read first } + if (format.ContainsOrdinal('n')) format = format.Replace("n", $"{read(addr++):X2}h"); - if (format.IndexOf("n", StringComparison.Ordinal) != -1) format = format.Replace("n", $"{read(addr++):X2}h"); - - if (format.IndexOf("+d", StringComparison.Ordinal) != -1) format = format.Replace("+d", "d"); - if (format.IndexOf("d", StringComparison.Ordinal) != -1) + format = format.Replace("+d", "d"); + if (format.ContainsOrdinal('d')) { var b = unchecked((sbyte)read(addr++)); format = format.Replace("d", $"{(b < 0 ? '-' : '+')}{(b < 0 ? -b : b):X2}h"); @@ -322,10 +322,7 @@ public string Cpu public string PCRegisterName => "PC"; - public IEnumerable AvailableCpus - { - get { yield return "F3850"; } - } + public IEnumerable AvailableCpus { get; } = [ "F3850" ]; public string Disassemble(MemoryDomain m, uint addr, out int length) { diff --git a/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Operations.cs b/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Operations.cs index 21f503bbe7b..37fee2bce7a 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Operations.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Operations.cs @@ -26,8 +26,6 @@ public void IN_Func(byte dest, byte src) /// Helper method moving from IO pins to accumulator /// (complement and flags set) /// - /// - /// public void LR_A_IO_Func(byte dest, byte src) { // overflow and carry unconditionally reset @@ -46,8 +44,6 @@ public void LR_A_IO_Func(byte dest, byte src) /// Helper method moving from accumulator to IO pins /// (complement) /// - /// - /// public void OUT_Func(byte dest, byte src) { // data is complemented between accumulator and I/O pins (because PINs are active-low) @@ -66,8 +62,6 @@ public void ClearFlags_Func() /// /// Helper function for transferring data between registers /// - /// - /// public void LR_Func(byte dest, byte src) { if (dest == DB) @@ -94,8 +88,6 @@ public void LR_Func(byte dest, byte src) /// /// Right shift 'src' 'shift' positions (zero fill) /// - /// - /// public void SR_Func(byte src, byte shift) { // overflow and carry unconditionally reset @@ -111,8 +103,6 @@ public void SR_Func(byte src, byte shift) /// /// Left shift 'src' 'shift' positions (zero fill) /// - /// - /// public void SL_Func(byte src, byte shift) { // overflow and carry unconditionally reset @@ -130,8 +120,6 @@ public void SL_Func(byte src, byte shift) /// Statuses modified: OVF, ZERO, CARRY, SIGN /// Statuses unaffected: ICB /// - /// - /// public void ADD_Func(byte dest, byte src, byte src2 = ZERO) { ushort res = (ushort)(Regs[dest] + Regs[src] + Regs[src2]); @@ -152,8 +140,6 @@ public void SUB_Func(byte dest, byte src) /// Decimal Add /// http://www.bitsavers.org/components/fairchild/f8/67095664_F8_Guide_To_Programming_1976.pdf - page 40 /// - /// - /// public void ADDD_Func(byte dest, byte src) { // The accumulator and the memory location addressed by the DCO registers are assumed to contain two BCD digits. @@ -237,8 +223,6 @@ public void CI_Func() /// /// Logical AND regs[dest] with regs[src] and store the result in regs[dest] /// - /// - /// public void AND_Func(byte dest, byte src) { // overflow and carry unconditionally reset @@ -254,8 +238,6 @@ public void AND_Func(byte dest, byte src) /// /// Logical OR regs[dest] with regs[src] and store the result in regs[dest] /// - /// - /// public void OR_Func(byte dest, byte src) { // overflow and carry unconditionally reset @@ -271,8 +253,6 @@ public void OR_Func(byte dest, byte src) /// /// The destination (regs[dest]) is XORed with (regs[src]). /// - /// - /// public void XOR_Func(byte dest, byte src) { // overflow and carry unconditionally reset diff --git a/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Registers.cs b/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Registers.cs index 2981c7ebe1a..7dd49c228ba 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Registers.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Registers.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Tables.cs b/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Tables.cs index 61c12ca6ba2..45fcba1e01a 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Tables.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Tables.cs @@ -396,7 +396,6 @@ private void LR_H_DC() /// Statuses reset: OVF, CARRY /// Statuses unaffected: ICB ///
- /// private void SR(byte index) { PopulateCURINSTR( @@ -414,7 +413,6 @@ private void SR(byte index) /// Statuses reset: OVF, CARRY /// Statuses unaffected: ICB ///
- /// private void SL(byte index) { PopulateCURINSTR( @@ -998,7 +996,6 @@ private void XDC() /// Statuses modified: OVF, ZERO, CARRY, SIGN /// Statuses unaffected: ICB ///
- /// private void DS(byte rIndex) { // only scratch registers 0-16 @@ -1190,7 +1187,6 @@ private void LR_ISAR_A_DEC() /// A 3-bit value provided by the LlSU instruction operand is loaded into the three most significant bits of the ISAR. The three least significant bits of the ISAR are not altered. /// No status bits are affected. ///
- /// private void LISU(byte octal) { PopulateCURINSTR( @@ -1206,7 +1202,6 @@ private void LISU(byte octal) /// A 3-bit value provided by the USL instruction operand is loaded into the three least significant bits of the ISAR. The three most significant bits of the ISAR are not altered. /// No status bits are modified. ///
- /// private void LISL(byte octal) { PopulateCURINSTR( @@ -1223,7 +1218,6 @@ private void LISL(byte octal) /// The most significant four bits of the accumulator are set to "0". /// No status bits are modified. ///
- /// private void LIS(byte index) { PopulateCURINSTR( @@ -1448,7 +1442,6 @@ private void BR7() /// Statuses reset: OVF, CARRY /// Statuses unaffected: ICB ///
- /// private void INS_0(byte index) { Regs[IO] = index; // latch port index early @@ -1474,7 +1467,6 @@ private void INS_0(byte index) /// Statuses reset: OVF, CARRY /// Statuses unaffected: ICB ///
- /// private void INS_1(byte index) { Regs[IO] = index; // latch port index early @@ -1507,7 +1499,6 @@ private void INS_1(byte index) /// I/O ports with addresses from 0 to 1 may be accessed by this instruction. (Outs O or 1 is CPU port only.) /// No status bits are modified. /// - /// private void OUTS_0(byte index) { Regs[IO] = index; // latch port index early @@ -1531,7 +1522,6 @@ private void OUTS_0(byte index) /// I/O ports with addresses from 3 to 15 may be accessed by this instruction. /// No status bits are modified. /// - /// private void OUTS_1(byte index) { Regs[IO] = index; // latch port index early @@ -1566,7 +1556,6 @@ private void OUTS_1(byte index) /// Statuses modified: OVF, ZERO, CARRY, SIGN /// Statuses unaffected: ICB /// - /// private void AS(byte rIndex) { // only scratch registers 0-15 @@ -1641,7 +1630,6 @@ private void AS_IS_DEC() /// Statuses not significant: OVF, SIGN /// Statuses unaffected: ICB /// - /// private void ASD(byte rIndex) { // only scratch registers 0-15 @@ -1738,7 +1726,6 @@ private void ASD_IS_DEC() /// Statuses reset: OVF, CARRY /// Statuses unaffected: ICB /// - /// private void XS(byte rIndex) { // only scratch registers 0-15 @@ -1813,7 +1800,6 @@ private void XS_IS_DEC() /// Statuses modified: ZERO, SIGN /// Statuses unaffected: ICB /// - /// private void NS(byte rIndex) { // only scratch registers 0-15 diff --git a/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.cs b/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.cs index 5d031e83595..23d0ce1f01c 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/CPUs/HuC6280/Disassembler.cs b/src/BizHawk.Emulation.Cores/CPUs/HuC6280/Disassembler.cs index ab99cae77a4..6ed303216e6 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/HuC6280/Disassembler.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/HuC6280/Disassembler.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Components.H6280 { public partial class HuC6280 diff --git a/src/BizHawk.Emulation.Cores/CPUs/HuC6280/Execute.cs b/src/BizHawk.Emulation.Cores/CPUs/HuC6280/Execute.cs index a6a8a7456e6..ddecf3cd139 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/HuC6280/Execute.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/HuC6280/Execute.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; @@ -24,7 +23,7 @@ public void Execute(int cycles) { int lastCycles = PendingCycles; - if (IRQ1Assert && FlagI == false && LagIFlag == false && (IRQControlByte & IRQ1Selector) == 0 && InBlockTransfer == false) + if (IRQ1Assert && !FlagI && !LagIFlag && (IRQControlByte & IRQ1Selector) == 0 && !InBlockTransfer) { WriteMemory((ushort)(S-- + 0x2100), (byte)(PC >> 8)); WriteMemory((ushort)(S-- + 0x2100), (byte)PC); @@ -35,7 +34,7 @@ public void Execute(int cycles) PendingCycles -= 8; } - if (TimerAssert && FlagI == false && LagIFlag == false && (IRQControlByte & TimerSelector) == 0 && InBlockTransfer == false) + if (TimerAssert && !FlagI && !LagIFlag && (IRQControlByte & TimerSelector) == 0 && !InBlockTransfer) { WriteMemory((ushort)(S-- + 0x2100), (byte)(PC >> 8)); WriteMemory((ushort)(S-- + 0x2100), (byte)PC); @@ -46,7 +45,7 @@ public void Execute(int cycles) PendingCycles -= 8; } - if (IRQ2Assert && FlagI == false && LagIFlag == false && (IRQControlByte & IRQ2Selector) == 0 && InBlockTransfer == false) + if (IRQ2Assert && !FlagI && !LagIFlag && (IRQControlByte & IRQ2Selector) == 0 && !InBlockTransfer) { WriteMemory((ushort)(S-- + 0x2100), (byte)(PC >> 8)); WriteMemory((ushort)(S-- + 0x2100), (byte)PC); @@ -87,7 +86,7 @@ public void Execute(int cycles) break; case 0x01: // ORA (addr,X) value8 = ReadMemory(ReadWordPageWrap((ushort)((byte)(ReadMemory(PC++) + X) + 0x2000))); - if (FlagT == false) + if (!FlagT) { A |= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -124,7 +123,7 @@ public void Execute(int cycles) break; case 0x05: // ORA zp value8 = ReadMemory((ushort)(ReadMemory(PC++) + 0x2000)); - if (FlagT == false) + if (!FlagT) { A |= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -161,7 +160,7 @@ public void Execute(int cycles) break; case 0x09: // ORA #nn value8 = ReadMemory(PC++); - if (FlagT == false) + if (!FlagT) { A |= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -193,7 +192,7 @@ public void Execute(int cycles) break; case 0x0D: // ORA addr value8 = ReadMemory(ReadWord(PC)); PC += 2; - if (FlagT == false) + if (!FlagT) { A |= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -230,7 +229,7 @@ public void Execute(int cycles) case 0x10: // BPL +/-rel rel8 = (sbyte)ReadMemory(PC++); value16 = (ushort)(PC + rel8); - if (FlagN == false) + if (!FlagN) { PendingCycles -= 2; PC = value16; @@ -240,7 +239,7 @@ public void Execute(int cycles) case 0x11: // ORA (addr),Y temp16 = ReadWordPageWrap((ushort)(ReadMemory(PC++) + 0x2000)); value8 = ReadMemory((ushort)(temp16 + Y)); - if (FlagT == false) + if (!FlagT) { A |= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -257,7 +256,7 @@ public void Execute(int cycles) break; case 0x12: // ORA (addr) value8 = ReadMemory(ReadWordPageWrap((ushort)(ReadMemory(PC++) + 0x2000))); - if (FlagT == false) + if (!FlagT) { A |= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -288,7 +287,7 @@ public void Execute(int cycles) break; case 0x15: // ORA zp,X value8 = ReadMemory((ushort)(((ReadMemory(PC++) + X) & 0xFF) + 0x2000)); - if (FlagT == false) + if (!FlagT) { A |= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -326,7 +325,7 @@ public void Execute(int cycles) case 0x19: // ORA addr,Y value8 = ReadMemory((ushort)(ReadWord(PC) + Y)); PC += 2; - if (FlagT == false) + if (!FlagT) { A |= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -357,7 +356,7 @@ public void Execute(int cycles) case 0x1D: // ORA addr,X value8 = ReadMemory((ushort)(ReadWord(PC) + X)); PC += 2; - if (FlagT == false) + if (!FlagT) { A |= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -401,7 +400,7 @@ public void Execute(int cycles) break; case 0x21: // AND (addr,X) value8 = ReadMemory(ReadWordPageWrap((ushort)((byte)(ReadMemory(PC++) + X) + 0x2000))); - if (FlagT == false) + if (!FlagT) { A &= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -436,7 +435,7 @@ public void Execute(int cycles) break; case 0x25: // AND zp value8 = ReadMemory((ushort)(ReadMemory(PC++) + 0x2000)); - if (FlagT == false) + if (!FlagT) { A &= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -473,7 +472,7 @@ public void Execute(int cycles) goto AfterClearTFlag; case 0x29: // AND #nn value8 = ReadMemory(PC++); - if (FlagT == false) + if (!FlagT) { A &= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -504,7 +503,7 @@ public void Execute(int cycles) break; case 0x2D: // AND addr value8 = ReadMemory(ReadWord(PC)); PC += 2; - if (FlagT == false) + if (!FlagT) { A &= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -551,7 +550,7 @@ public void Execute(int cycles) case 0x31: // AND (addr),Y temp16 = ReadWordPageWrap((ushort)(ReadMemory(PC++) + 0x2000)); value8 = ReadMemory((ushort)(temp16 + Y)); - if (FlagT == false) + if (!FlagT) { A &= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -568,7 +567,7 @@ public void Execute(int cycles) break; case 0x32: // AND (addr) value8 = ReadMemory(ReadWordPageWrap((ushort)(ReadMemory(PC++) + 0x2000))); - if (FlagT == false) + if (!FlagT) { A &= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -592,7 +591,7 @@ public void Execute(int cycles) break; case 0x35: // AND zp,X value8 = ReadMemory((ushort)(((ReadMemory(PC++) + X) & 0xFF) + 0x2000)); - if (FlagT == false) + if (!FlagT) { A &= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -630,7 +629,7 @@ public void Execute(int cycles) case 0x39: // AND addr,Y value8 = ReadMemory((ushort)(ReadWord(PC) + Y)); PC += 2; - if (FlagT == false) + if (!FlagT) { A &= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -660,7 +659,7 @@ public void Execute(int cycles) case 0x3D: // AND addr,X value8 = ReadMemory((ushort)(ReadWord(PC) + X)); PC += 2; - if (FlagT == false) + if (!FlagT) { A &= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -703,7 +702,7 @@ public void Execute(int cycles) goto AfterClearTFlag; case 0x41: // EOR (addr,X) value8 = ReadMemory(ReadWordPageWrap((ushort)((byte)(ReadMemory(PC++) + X) + 0x2000))); - if (FlagT == false) + if (!FlagT) { A ^= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -747,7 +746,7 @@ public void Execute(int cycles) break; case 0x45: // EOR zp value8 = ReadMemory((ushort)(ReadMemory(PC++) + 0x2000)); - if (FlagT == false) + if (!FlagT) { A ^= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -784,7 +783,7 @@ public void Execute(int cycles) break; case 0x49: // EOR #nn value8 = ReadMemory(PC++); - if (FlagT == false) + if (!FlagT) { A ^= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -811,7 +810,7 @@ public void Execute(int cycles) break; case 0x4D: // EOR addr value8 = ReadMemory(ReadWord(PC)); PC += 2; - if (FlagT == false) + if (!FlagT) { A ^= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -848,7 +847,7 @@ public void Execute(int cycles) case 0x50: // BVC +/-rel rel8 = (sbyte)ReadMemory(PC++); value16 = (ushort)(PC + rel8); - if (FlagV == false) + if (!FlagV) { PendingCycles -= 2; PC = value16; @@ -858,7 +857,7 @@ public void Execute(int cycles) case 0x51: // EOR (addr),Y temp16 = ReadWordPageWrap((ushort)(ReadMemory(PC++) + 0x2000)); value8 = ReadMemory((ushort)(temp16 + Y)); - if (FlagT == false) + if (!FlagT) { A ^= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -875,7 +874,7 @@ public void Execute(int cycles) break; case 0x52: // EOR (addr) value8 = ReadMemory(ReadWordPageWrap((ushort)(ReadMemory(PC++) + 0x2000))); - if (FlagT == false) + if (!FlagT) { A ^= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -905,7 +904,7 @@ public void Execute(int cycles) break; case 0x55: // EOR zp,X value8 = ReadMemory((ushort)(((ReadMemory(PC++) + X) & 0xFF) + 0x2000)); - if (FlagT == false) + if (!FlagT) { A ^= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -943,7 +942,7 @@ public void Execute(int cycles) case 0x59: // EOR addr,Y value8 = ReadMemory((ushort)(ReadWord(PC) + Y)); PC += 2; - if (FlagT == false) + if (!FlagT) { A ^= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -965,7 +964,7 @@ public void Execute(int cycles) case 0x5D: // EOR addr,X value8 = ReadMemory((ushort)(ReadWord(PC) + X)); PC += 2; - if (FlagT == false) + if (!FlagT) { A ^= value8; P = (byte)((P & 0x7D) | TableNZ[A]); @@ -1032,7 +1031,7 @@ public void Execute(int cycles) FlagC = temp > 0xFF; source8 = (byte)temp; } - if (FlagT == false) + if (!FlagT) A = source8; else { @@ -1077,7 +1076,7 @@ public void Execute(int cycles) FlagC = temp > 0xFF; source8 = (byte)temp; } - if (FlagT == false) + if (!FlagT) A = source8; else { @@ -1134,7 +1133,7 @@ public void Execute(int cycles) FlagC = temp > 0xFF; source8 = (byte)temp; } - if (FlagT == false) + if (!FlagT) A = source8; else { @@ -1181,7 +1180,7 @@ public void Execute(int cycles) FlagC = temp > 0xFF; source8 = (byte)temp; } - if (FlagT == false) + if (!FlagT) A = source8; else { @@ -1247,7 +1246,7 @@ public void Execute(int cycles) FlagC = temp > 0xFF; source8 = (byte)temp; } - if (FlagT == false) + if (!FlagT) A = source8; else { @@ -1283,7 +1282,7 @@ public void Execute(int cycles) FlagC = temp > 0xFF; source8 = (byte)temp; } - if (FlagT == false) + if (!FlagT) A = source8; else { @@ -1294,7 +1293,7 @@ public void Execute(int cycles) PendingCycles -= 7; break; case 0x73: // TII src, dest, len - if (InBlockTransfer == false) + if (!InBlockTransfer) { InBlockTransfer = true; btFrom = ReadWord(PC); PC += 2; @@ -1348,7 +1347,7 @@ public void Execute(int cycles) FlagC = temp > 0xFF; source8 = (byte)temp; } - if (FlagT == false) + if (!FlagT) A = source8; else { @@ -1405,7 +1404,7 @@ public void Execute(int cycles) FlagC = temp > 0xFF; source8 = (byte)temp; } - if (FlagT == false) + if (!FlagT) A = source8; else { @@ -1451,7 +1450,7 @@ public void Execute(int cycles) FlagC = temp > 0xFF; source8 = (byte)temp; } - if (FlagT == false) + if (!FlagT) A = source8; else { @@ -1569,7 +1568,7 @@ public void Execute(int cycles) case 0x90: // BCC +/-rel rel8 = (sbyte)ReadMemory(PC++); value16 = (ushort)(PC + rel8); - if (FlagC == false) + if (!FlagC) { PendingCycles -= 2; PC = value16; @@ -1858,7 +1857,7 @@ public void Execute(int cycles) PendingCycles -= 2; break; case 0xC3: // TDD src, dest, len - if (InBlockTransfer == false) + if (!InBlockTransfer) { InBlockTransfer = true; btFrom = ReadWord(PC); PC += 2; @@ -1958,7 +1957,7 @@ public void Execute(int cycles) case 0xD0: // BNE +/-rel rel8 = (sbyte)ReadMemory(PC++); value16 = (ushort)(PC + rel8); - if (FlagZ == false) + if (!FlagZ) { PendingCycles -= 2; PC = value16; @@ -1981,7 +1980,7 @@ public void Execute(int cycles) PendingCycles -= 7; break; case 0xD3: // TIN src, dest, len - if (InBlockTransfer == false) + if (!InBlockTransfer) { InBlockTransfer = true; btFrom = ReadWord(PC); PC += 2; @@ -2103,7 +2102,7 @@ public void Execute(int cycles) PendingCycles -= 7; break; case 0xE3: // TIA src, dest, len - if (InBlockTransfer == false) + if (!InBlockTransfer) { InBlockTransfer = true; btFrom = ReadWord(PC); PC += 2; @@ -2312,7 +2311,7 @@ public void Execute(int cycles) PendingCycles -= 7; break; case 0xF3: // TAI src, dest, len - if (InBlockTransfer == false) + if (!InBlockTransfer) { InBlockTransfer = true; btFrom = ReadWord(PC); PC += 2; @@ -2340,7 +2339,7 @@ public void Execute(int cycles) case 0xF4: // SET int a; // TODO remove these extra checks string b = Disassemble(PC, out a); - if (b.StartsWithOrdinal("ADC") == false && b.StartsWithOrdinal("EOR") == false && b.StartsWithOrdinal("AND") == false && b.StartsWithOrdinal("ORA") == false) + if (!b.StartsWithOrdinal("ADC") && !b.StartsWithOrdinal("EOR") && !b.StartsWithOrdinal("AND") && !b.StartsWithOrdinal("ORA")) Console.WriteLine("SETTING T FLAG, NEXT INSTRUCTION IS UNHANDLED: {0}", b); FlagT = true; PendingCycles -= 2; diff --git a/src/BizHawk.Emulation.Cores/CPUs/HuC6280/HuC6280.cs b/src/BizHawk.Emulation.Cores/CPUs/HuC6280/HuC6280.cs index f17360fa68e..ce1ab42d219 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/HuC6280/HuC6280.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/HuC6280/HuC6280.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; using BizHawk.Emulation.Common; @@ -236,7 +235,7 @@ public void WriteTimer(byte value) public void WriteTimerEnable(byte value) { - if (TimerEnabled == false && (value & 1) == 1) + if (!TimerEnabled && (value & 1) == 1) { TimerValue = TimerReloadValue; // timer value is reset when toggled from off to on TimerTickCounter = 0; @@ -420,4 +419,4 @@ public TraceInfo State() 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }; } -} \ No newline at end of file +} diff --git a/src/BizHawk.Emulation.Cores/CPUs/HuC6280/HuC6280_CDL.cs b/src/BizHawk.Emulation.Cores/CPUs/HuC6280/HuC6280_CDL.cs index 98601be50b4..0da23e2a8c9 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/HuC6280/HuC6280_CDL.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/HuC6280/HuC6280_CDL.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; @@ -24,7 +23,7 @@ public void DisassembleCDL(Stream s, ICodeDataLog cdl, IMemoryDomains mem) { string dis = DisassembleExt( 0, - out int unused, + out _, addr => md.PeekByte(addr + i), addr => md.PeekUshort(addr + i, bigEndian: false)); w.WriteLine("0x{0:x8}: {1}", i, dis); diff --git a/src/BizHawk.Emulation.Cores/CPUs/HuC6280/IDisassemblable.cs b/src/BizHawk.Emulation.Cores/CPUs/HuC6280/IDisassemblable.cs index 0c3bc9d30ed..b1c18d791e5 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/HuC6280/IDisassemblable.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/HuC6280/IDisassemblable.cs @@ -13,10 +13,7 @@ public string Cpu public string PCRegisterName => "PC"; - public IEnumerable AvailableCpus - { - get { yield return "6280"; } - } + public IEnumerable AvailableCpus { get; } = [ "6280" ]; public string Disassemble(MemoryDomain m, uint addr, out int length) { diff --git a/src/BizHawk.Emulation.Cores/CPUs/Intel8048/Disassembler.cs b/src/BizHawk.Emulation.Cores/CPUs/Intel8048/Disassembler.cs index ae81dd1f92b..c67c3f22831 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/Intel8048/Disassembler.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/Intel8048/Disassembler.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/CPUs/Intel8048/I8048.cs b/src/BizHawk.Emulation.Cores/CPUs/Intel8048/I8048.cs index 0badf0243bc..c9618233cde 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/Intel8048/I8048.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/Intel8048/I8048.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/CPUs/Intel8048/Interrupts.cs b/src/BizHawk.Emulation.Cores/CPUs/Intel8048/Interrupts.cs index bae5874f571..f8fff3fac88 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/Intel8048/Interrupts.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/Intel8048/Interrupts.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Components.I8048 { public partial class I8048 diff --git a/src/BizHawk.Emulation.Cores/CPUs/Intel8048/OP_Tables.cs b/src/BizHawk.Emulation.Cores/CPUs/Intel8048/OP_Tables.cs index dd6b1bba20a..2edd6629268 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/Intel8048/OP_Tables.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/Intel8048/OP_Tables.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common.NumberExtensions; namespace BizHawk.Emulation.Cores.Components.I8048 diff --git a/src/BizHawk.Emulation.Cores/CPUs/Intel8048/Registers.cs b/src/BizHawk.Emulation.Cores/CPUs/Intel8048/Registers.cs index 95c8aa8d5db..45af80c93e1 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/Intel8048/Registers.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/Intel8048/Registers.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs b/src/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs index 0243f09fbbc..285e5526467 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Common.NumberExtensions; diff --git a/src/BizHawk.Emulation.Cores/CPUs/LR35902/NewDisassembler.cs b/src/BizHawk.Emulation.Cores/CPUs/LR35902/NewDisassembler.cs index 840294ffd25..b6cd9a4eaad 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/LR35902/NewDisassembler.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/LR35902/NewDisassembler.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/CPUs/LR35902/Registers.cs b/src/BizHawk.Emulation.Cores/CPUs/LR35902/Registers.cs index ecd6a5e932b..6ae3f4e20e3 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/LR35902/Registers.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/LR35902/Registers.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/CPUs/MC6800/Disassembler.cs b/src/BizHawk.Emulation.Cores/CPUs/MC6800/Disassembler.cs index d5b41fe0265..b1d8c9cd1a4 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/MC6800/Disassembler.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/MC6800/Disassembler.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/CPUs/MC6800/Interrupts.cs b/src/BizHawk.Emulation.Cores/CPUs/MC6800/Interrupts.cs index abcf695b21a..efdb0d54b58 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/MC6800/Interrupts.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/MC6800/Interrupts.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Components.MC6800 { public partial class MC6800 diff --git a/src/BizHawk.Emulation.Cores/CPUs/MC6800/MC6800.cs b/src/BizHawk.Emulation.Cores/CPUs/MC6800/MC6800.cs index 407578349fd..15ff5e10129 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/MC6800/MC6800.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/MC6800/MC6800.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/CPUs/MC6809/Disassembler.cs b/src/BizHawk.Emulation.Cores/CPUs/MC6809/Disassembler.cs index 6df0489009f..ffb9527e73f 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/MC6809/Disassembler.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/MC6809/Disassembler.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/CPUs/MC6809/Interrupts.cs b/src/BizHawk.Emulation.Cores/CPUs/MC6809/Interrupts.cs index 094463cbd94..f3000460096 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/MC6809/Interrupts.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/MC6809/Interrupts.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Components.MC6809 { public partial class MC6809 diff --git a/src/BizHawk.Emulation.Cores/CPUs/MC6809/MC6809.cs b/src/BizHawk.Emulation.Cores/CPUs/MC6809/MC6809.cs index 00ee253c9c3..1059e1c3e63 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/MC6809/MC6809.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/MC6809/MC6809.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/CPUs/MC6809/Registers.cs b/src/BizHawk.Emulation.Cores/CPUs/MC6809/Registers.cs index 9772ff5400d..dbf68a05474 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/MC6809/Registers.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/MC6809/Registers.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/CPUs/MOS 6502X/Disassembler.cs b/src/BizHawk.Emulation.Cores/CPUs/MOS 6502X/Disassembler.cs index d88c7491ffd..cb24d414d10 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/MOS 6502X/Disassembler.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/MOS 6502X/Disassembler.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; using System.Collections.Generic; @@ -21,10 +20,7 @@ public string Cpu public string PCRegisterName => "PC"; - public IEnumerable AvailableCpus - { - get { yield return "6502"; } - } + public IEnumerable AvailableCpus { get; } = [ "6502" ]; public string Disassemble(MemoryDomain m, uint addr, out int length) { @@ -60,7 +56,7 @@ public static string Disassemble(ushort pc, out int bytesToAdvance, Func AvailableCpus - { - get { yield return "W65816"; } - } + public IEnumerable AvailableCpus { get; } = [ "W65816" ]; public string PCRegisterName => "PC"; diff --git a/src/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs b/src/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs index ae42bb7f13d..3814dfe2337 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Components.Z80A { public partial class Z80A diff --git a/src/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs b/src/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs index 56b9416026c..613fac029d2 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs @@ -1,6 +1,6 @@ -using System; using System.Collections.Generic; +using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Components.Z80A @@ -13,11 +13,11 @@ private static string Result(string format, Func read, ref ushort //n immediate succeeds the opcode and the displacement (if present) //nn immediately succeeds the opcode and the displacement (if present) - if (format.IndexOf("nn", StringComparison.Ordinal) != -1) format = format.Replace("nn", $"{read(addr++) + (read(addr++) << 8):X4}h"); // LSB is read first - if (format.IndexOf("n", StringComparison.Ordinal) != -1) format = format.Replace("n", $"{read(addr++):X2}h"); + if (format.ContainsOrdinal("nn")) format = format.Replace("nn", $"{read(addr++) + (read(addr++) << 8):X4}h"); // LSB is read first + if (format.ContainsOrdinal('n')) format = format.Replace("n", $"{read(addr++):X2}h"); - if (format.IndexOf("+d", StringComparison.Ordinal) != -1) format = format.Replace("+d", "d"); - if (format.IndexOf("d", StringComparison.Ordinal) != -1) + format = format.Replace("+d", "d"); + if (format.ContainsOrdinal('d')) { var b = unchecked ((sbyte) read(addr++)); format = format.Replace("d", $"{(b < 0 ? '-' : '+')}{(b < 0 ? -b : b):X2}h"); @@ -439,10 +439,7 @@ public string Cpu public string PCRegisterName => "PC"; - public IEnumerable AvailableCpus - { - get { yield return "Z80"; } - } + public IEnumerable AvailableCpus { get; } = [ "Z80" ]; public string Disassemble(MemoryDomain m, uint addr, out int length) { diff --git a/src/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs b/src/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs index 75181abe6d1..1debee7abc2 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/CPUs/x86/Execute.cs b/src/BizHawk.Emulation.Cores/CPUs/x86/Execute.cs index 9dfe0ac01b4..f5b8c6864ff 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/x86/Execute.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/x86/Execute.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Components.x86 { public partial class x86 where TCpu : struct, x86CpuType diff --git a/src/BizHawk.Emulation.Cores/CPUs/x86/x86.cs b/src/BizHawk.Emulation.Cores/CPUs/x86/x86.cs index a5dcfa685f4..319fa0f5665 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/x86/x86.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/x86/x86.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; namespace BizHawk.Emulation.Cores.Components.x86 diff --git a/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IDebuggable.cs index a62c5fc1f86..e30174a0967 100644 --- a/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IEmulator.cs b/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IEmulator.cs index 6b4c26f0bda..1035e4ad690 100644 --- a/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IEmulator.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Calculators.Emu83 diff --git a/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IMemoryDomains.cs index 0d1c9da77f0..60dfbefcda4 100644 --- a/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IStatable.cs b/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IStatable.cs index 1e9b25707e8..428eb22b3f2 100644 --- a/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IStatable.cs +++ b/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.IStatable.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.cs b/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.cs index 5000f61e320..b1c8153b489 100644 --- a/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.cs +++ b/src/BizHawk.Emulation.Cores/Calculators/Emu83/Emu83.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using BizHawk.BizInvoke; @@ -8,7 +7,7 @@ namespace BizHawk.Emulation.Cores.Calculators.Emu83 { - [PortedCore(CoreNames.Emu83, "CasualPokePlayer", "1b8cd90f5b451df3fb07fe3d32d3686a6b93eab4", "https://github.com/CasualPokePlayer/Emu83")] + [PortedCore(CoreNames.Emu83, "CasualPokePlayer", "d2e6e1d", "https://github.com/CasualPokePlayer/Emu83")] [ServiceNotApplicable(new[] { typeof(IBoardInfo), typeof(IRegionable), typeof(ISaveRam), typeof(ISoundProvider) })] public partial class Emu83 : TI83Common { diff --git a/src/BizHawk.Emulation.Cores/Calculators/Emu83/LibEmu83.cs b/src/BizHawk.Emulation.Cores/Calculators/Emu83/LibEmu83.cs index 40014d8d360..f97c208fcf4 100644 --- a/src/BizHawk.Emulation.Cores/Calculators/Emu83/LibEmu83.cs +++ b/src/BizHawk.Emulation.Cores/Calculators/Emu83/LibEmu83.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.BizInvoke; diff --git a/src/BizHawk.Emulation.Cores/Calculators/TI83/TI83.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Calculators/TI83/TI83.IDebuggable.cs index b55e40fac32..cbf4dd9b5eb 100644 --- a/src/BizHawk.Emulation.Cores/Calculators/TI83/TI83.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Calculators/TI83/TI83.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Calculators/TI83/TI83.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Calculators/TI83/TI83.IMemoryDomains.cs index d5faf559493..3c02e355b73 100644 --- a/src/BizHawk.Emulation.Cores/Calculators/TI83/TI83.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Calculators/TI83/TI83.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Calculators/TI83/TI83.cs b/src/BizHawk.Emulation.Cores/Calculators/TI83/TI83.cs index 8b3a5fac227..0f31fa68743 100644 --- a/src/BizHawk.Emulation.Cores/Calculators/TI83/TI83.cs +++ b/src/BizHawk.Emulation.Cores/Calculators/TI83/TI83.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.Z80A; diff --git a/src/BizHawk.Emulation.Cores/Calculators/TI83/TI83LinkPort.cs b/src/BizHawk.Emulation.Cores/Calculators/TI83/TI83LinkPort.cs index e2cabbfeb0e..5291ab378d1 100644 --- a/src/BizHawk.Emulation.Cores/Calculators/TI83/TI83LinkPort.cs +++ b/src/BizHawk.Emulation.Cores/Calculators/TI83/TI83LinkPort.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; diff --git a/src/BizHawk.Emulation.Cores/Computers/Amiga/LibPUAE.cs b/src/BizHawk.Emulation.Cores/Computers/Amiga/LibPUAE.cs new file mode 100644 index 00000000000..eb45c724071 --- /dev/null +++ b/src/BizHawk.Emulation.Cores/Computers/Amiga/LibPUAE.cs @@ -0,0 +1,179 @@ +using BizHawk.BizInvoke; +using BizHawk.Emulation.Cores.Waterbox; + +using System.Runtime.InteropServices; + +namespace BizHawk.Emulation.Cores.Computers.Amiga +{ + public abstract class LibPUAE : LibWaterboxCore + { + public const int PAL_WIDTH = 720; + public const int PAL_HEIGHT = 576; + public const int NTSC_WIDTH = 720; + public const int NTSC_HEIGHT = 480; + public const int FASTMEM_AUTO = -1; + public const int MAX_FLOPPIES = 4; + public const int FILENAME_MAXLENGTH = 64; + public const int KEY_COUNT = 0x68; + public const byte b00000001 = 1 << 0; + public const byte b00000010 = 1 << 1; + public const byte b00000100 = 1 << 2; + public const byte b00001000 = 1 << 3; + public const byte b00010000 = 1 << 4; + public const byte b00100000 = 1 << 5; + public const byte b01000000 = 1 << 6; + public const byte b10000000 = 1 << 7; + + [BizImport(CC, Compatibility = true)] + public abstract bool Init(int argc, string[] argv); + + [StructLayout(LayoutKind.Sequential)] + public new class FrameInfo : LibWaterboxCore.FrameInfo + { + public PUAEJoystick JoystickState; + public byte MouseButtons; + public int MouseX; + public int MouseY; + public KeyBuffer Keys; + public struct KeyBuffer + { + public unsafe fixed byte Buffer[LibPUAE.KEY_COUNT]; + } + public int CurrentDrive; + public DriveAction Action; + public FileName Name; + public struct FileName + { + public unsafe fixed byte Buffer[LibPUAE.FILENAME_MAXLENGTH]; + } + } + + public enum DriveAction : int + { + None, + Eject, + Insert + } + + [Flags] + public enum PUAEJoystick : byte + { + Joystick_Up = b00000001, + Joystick_Down = b00000010, + Joystick_Left = b00000100, + Joystick_Right = b00001000, + Joystick_Button_1 = b00010000, + Joystick_Button_2 = b00100000, + Joystick_Button_3 = b01000000 + } + + // https://wiki.amigaos.net/wiki/Keymap_Library + public enum PUAEKeyboard : int + { + Key_Backquote = 0x00, + Key_1 = 0x01, + Key_2 = 0x02, + Key_3 = 0x03, + Key_4 = 0x04, + Key_5 = 0x05, + Key_6 = 0x06, + Key_7 = 0x07, + Key_8 = 0x08, + Key_9 = 0x09, + Key_0 = 0x0A, + Key_Minus = 0x0B, + Key_Equal = 0x0C, + Key_Backslash = 0x0D, +// Undefined = 0x0E, + Key_NP_0 = 0x0F, + Key_Q = 0x10, + Key_W = 0x11, + Key_E = 0x12, + Key_R = 0x13, + Key_T = 0x14, + Key_Y = 0x15, + Key_U = 0x16, + Key_I = 0x17, + Key_O = 0x18, + Key_P = 0x19, + Key_Left_Bracket = 0x1A, + Key_Right_Bracket = 0x1B, +// Undefined = 0x1C, + Key_NP_1 = 0x1D, + Key_NP_2 = 0x1E, + Key_NP_3 = 0x1F, + Key_A = 0x20, + Key_S = 0x21, + Key_D = 0x22, + Key_F = 0x23, + Key_G = 0x24, + Key_H = 0x25, + Key_J = 0x26, + Key_K = 0x27, + Key_L = 0x28, + Key_Semicolon = 0x29, + Key_Quote = 0x2A, + Key_Number_Sign = 0x2B, // not on most USA keyboards +// Undefined = 0x2C, + Key_NP_4 = 0x2D, + Key_NP_5 = 0x2E, + Key_NP_6 = 0x2F, + Key_Less = 0x30, // not on most USA keyboards + Key_Z = 0x31, + Key_X = 0x32, + Key_C = 0x33, + Key_V = 0x34, + Key_B = 0x35, + Key_N = 0x36, + Key_M = 0x37, + Key_Comma = 0x38, + Key_Period = 0x39, + Key_Slash = 0x3A, +// Undefined = 0x3B, + Key_NP_Delete = 0x3C, + Key_NP_7 = 0x3D, + Key_NP_8 = 0x3E, + Key_NP_9 = 0x3F, + Key_Space = 0x40, + Key_Backspace = 0x41, + Key_Tab = 0x42, + Key_NP_Enter = 0x43, + Key_Return = 0x44, + Key_Escape = 0x45, + Key_Delete = 0x46, +// Undefined = 0x47, +// Undefined = 0x48, +// Undefined = 0x49, + Key_NP_Sub = 0x4A, +// Undefined = 0x4B, + Key_Up = 0x4C, + Key_Down = 0x4D, + Key_Right = 0x4E, + Key_Left = 0x4F, + Key_F1 = 0x50, + Key_F2 = 0x51, + Key_F3 = 0x52, + Key_F4 = 0x53, + Key_F5 = 0x54, + Key_F6 = 0x55, + Key_F7 = 0x56, + Key_F8 = 0x57, + Key_F9 = 0x58, + Key_F10 = 0x59, + Key_NP_Left_Paren = 0x5A, + Key_NP_Right_Paren = 0x5B, + Key_NP_Div = 0x5C, + Key_NP_Mul = 0x5D, + Key_NP_Add = 0x5E, + Key_Help = 0x5F, + Key_Left_Shift = 0x60, + Key_Right_Shift = 0x61, + Key_Caps_Lock = 0x62, + Key_Ctrl = 0x63, + Key_Left_Alt = 0x64, + Key_Right_Alt = 0x65, + Key_Left_Amiga = 0x66, + Key_Right_Amiga = 0x67, + } + } +} \ No newline at end of file diff --git a/src/BizHawk.Emulation.Cores/Computers/Amiga/PUAE.ISettable.cs b/src/BizHawk.Emulation.Cores/Computers/Amiga/PUAE.ISettable.cs new file mode 100644 index 00000000000..e0ddcd356c0 --- /dev/null +++ b/src/BizHawk.Emulation.Cores/Computers/Amiga/PUAE.ISettable.cs @@ -0,0 +1,348 @@ +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; + +using BizHawk.Common; +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Computers.Amiga +{ + public partial class PUAE : ISettable + { + public enum MachineConfig + { + [Display(Name = "A500 OCS KS1.3 512K 512K")] + A500_OCS_130_512K_512K, + [Display(Name = "A600 ECS KS2.05 2M")] + A600_ECS_205_2M, + [Display(Name = "A1200 AGA KS3.1 2M 8M")] + A1200_AGA_310_2M_8M, + [Display(Name = "A4000 AGA KS3.1 2M 8M")] + A4000_AGA_310_2M_8M, + // CD32 + } + + public enum CpuModel + { + [Display(Name = "68000")] + _68000 = 68000, + [Display(Name = "68010")] + _68010 = 68010, + [Display(Name = "68020")] + _68020 = 68020, + [Display(Name = "68030")] + _68030 = 68030, + [Display(Name = "68040")] + _68040 = 68040, + [Display(Name = "68060")] + _68060 = 68060, + Auto + } + + public enum ChipsetCompatible + { + A500, + A600, + A1200, + A4000, + Auto + } + + public enum Chipset + { + OCS, + [Display(Name = "ECS Agnus")] + ECS_Agnus, + [Display(Name = "ECS Denise")] + ECS_Denise, + ECS, + AGA, + Auto + } + + public enum ChipMemory + { + [Display(Name = "512KB")] + KB_512 = 1, + [Display(Name = "1MB")] + MB_1, + [Display(Name = "1.5MB")] + MB_1_5, + [Display(Name = "2MB")] + MB_2, + [Display(Name = "2.5MB")] + MB_2_5, + [Display(Name = "3MB")] + MB_3, + [Display(Name = "3.5MB")] + MB_3_5, + [Display(Name = "4MB")] + MB_4, + [Display(Name = "4.5MB")] + MB_4_5, + [Display(Name = "5MB")] + MB_5, + [Display(Name = "5.5MB")] + MB_5_5, + [Display(Name = "6MB")] + MB_6, + [Display(Name = "6.5MB")] + MB_6_5, + [Display(Name = "7MB")] + MB_7, + [Display(Name = "7.5MB")] + MB_7_5, + [Display(Name = "8MB")] + MB_8, + Auto + } + + public enum SlowMemory + { + [Display(Name = "0")] + KB_0 = 0, + [Display(Name = "512KB")] + KB_512 = 2, + [Display(Name = "1MB")] + MB_1 = 4, + [Display(Name = "1.5MB")] + MB_1_5 = 6, + Auto + } + + public enum DriveType + { + DRV_NONE = -1, + DRV_35_DD = 0, + DRV_35_HD, + DRV_525_SD, + DRV_35_DD_ESCOM, + DRV_PC_525_ONLY_40, + DRV_PC_35_ONLY_80, + DRV_PC_525_40_80, + DRV_525_DD, + DRV_FB + } + + private void CreateArguments(PUAESyncSettings settings) + { + _args = new List + { + "puae", + }; + + switch(settings.MachineConfig) + { + case MachineConfig.A500_OCS_130_512K_512K: + _chipsetCompatible = Enum.GetName(typeof(ChipsetCompatible), ChipsetCompatible.A500); + AppendSetting(new List + { + "cpu_model=" + (int)CpuModel._68000, + "chipset=" + Chipset.OCS, + "chipset_compatible=" + _chipsetCompatible, + "chipmem_size=" + (int)ChipMemory.KB_512, + "bogomem_size=" + (int)SlowMemory.KB_512, + "fastmem_size=0", + }); + EnableCycleExact(); + break; + case MachineConfig.A600_ECS_205_2M: + _chipsetCompatible = Enum.GetName(typeof(ChipsetCompatible), ChipsetCompatible.A600); + AppendSetting(new List + { + "cpu_model=" + (int)CpuModel._68000, + "chipset=" + Chipset.ECS, + "chipset_compatible=" + _chipsetCompatible, + "chipmem_size=" + (int)ChipMemory.MB_2, + "bogomem_size=" + (int)SlowMemory.KB_0, + "fastmem_size=0", + }); + EnableCycleExact(); + break; + case MachineConfig.A1200_AGA_310_2M_8M: + _chipsetCompatible = Enum.GetName(typeof(ChipsetCompatible), ChipsetCompatible.A1200); + AppendSetting(new List + { + "cpu_model=" + (int)CpuModel._68020, + "chipset=" + Chipset.AGA, + "chipset_compatible=" + _chipsetCompatible, + "chipmem_size=" + (int)ChipMemory.MB_2, + "bogomem_size=" + (int)SlowMemory.KB_0, + "fastmem_size=8", + }); + EnableCycleExact(); + break; + case MachineConfig.A4000_AGA_310_2M_8M: + _chipsetCompatible = Enum.GetName(typeof(ChipsetCompatible), ChipsetCompatible.A4000); + AppendSetting(new List + { + "cpu_model=" + (int)CpuModel._68040, + "fpu_model=68040", + "mmu_model=68040", + "chipset=" + Chipset.AGA, + "chipset_compatible=" + _chipsetCompatible, + "chipmem_size=" + (int)ChipMemory.MB_2, + "bogomem_size=" + (int)SlowMemory.KB_0, + "fastmem_size=8", + }); + break; + } + + if (settings.CpuModel != CpuModel.Auto) + { + AppendSetting("cpu_model=" + (int)settings.CpuModel); + + if (settings.CpuModel < CpuModel._68030) + { + EnableCycleExact(); + } + } + + if (settings.Chipset != Chipset.Auto) + { + AppendSetting("chipset=" + (int)settings.Chipset); + } + + if (settings.ChipsetCompatible != ChipsetCompatible.Auto) + { + AppendSetting("chipset_compatible=" + + Enum.GetName(typeof(ChipsetCompatible), settings.ChipsetCompatible)); + } + + if (settings.ChipMemory != ChipMemory.Auto) + { + AppendSetting("chipmem_size=" + (int)settings.ChipMemory); + } + + if (settings.SlowMemory != SlowMemory.Auto) + { + AppendSetting("bogomem_size=" + (int)settings.SlowMemory); + } + + if (settings.FastMemory != LibPUAE.FASTMEM_AUTO) + { + AppendSetting("fastmem_size=" + settings.FastMemory); + } + + AppendSetting("input.mouse_speed=" + settings.MouseSpeed); + AppendSetting("sound_stereo_separation=" + settings.StereoSeparation / 10); + } + + private void AppendSetting(List settings) + { + foreach (var s in settings) + { + AppendSetting(s); + } + } + + private void AppendSetting(string setting) + { + _args.AddRange(new List + { + "-s", setting + }); + } + + private void EnableCycleExact() + { + AppendSetting(new List + { + "cpu_compatible=true", + "cpu_cycle_exact=true", + "cpu_memory_cycle_exact=true", + "blitter_cycle_exact=true", + }); + } + + public object GetSettings() => null; + public PutSettingsDirtyBits PutSettings(object o) => PutSettingsDirtyBits.None; + + private PUAESyncSettings _syncSettings; + public PUAESyncSettings GetSyncSettings() + => _syncSettings.Clone(); + + public PutSettingsDirtyBits PutSyncSettings(PUAESyncSettings o) + { + var ret = PUAESyncSettings.NeedsReboot(_syncSettings, o); + _syncSettings = o; + return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; + } + + [CoreSettings] + public class PUAESyncSettings + { + [DisplayName("Machine configuration")] + [Description("")] + [DefaultValue(MachineConfig.A500_OCS_130_512K_512K)] + [TypeConverter(typeof(DescribableEnumConverter))] + public MachineConfig MachineConfig { get; set; } + + [DisplayName("CPU model")] + [Description("")] + [DefaultValue(CpuModel.Auto)] + [TypeConverter(typeof(DescribableEnumConverter))] + public CpuModel CpuModel { get; set; } + + [DisplayName("Chipset compatible")] + [Description("")] + [DefaultValue(ChipsetCompatible.Auto)] + public ChipsetCompatible ChipsetCompatible { get; set; } + + [DisplayName("Chipset")] + [Description("")] + [DefaultValue(Chipset.Auto)] + [TypeConverter(typeof(DescribableEnumConverter))] + public Chipset Chipset { get; set; } + + [DisplayName("Chip memory")] + [Description("Size of chip-memory")] + [DefaultValue(ChipMemory.Auto)] + [TypeConverter(typeof(DescribableEnumConverter))] + public ChipMemory ChipMemory { get; set; } + + [DisplayName("Slow memory")] + [Description("Size of bogo-memory at 0xC00000")] + [DefaultValue(SlowMemory.Auto)] + [TypeConverter(typeof(DescribableEnumConverter))] + public SlowMemory SlowMemory { get; set; } + + [DisplayName("Fast memory")] + [Description("Size in megabytes of fast-memory. -1 means Auto.")] + [Range(LibPUAE.FASTMEM_AUTO, 512)] + [DefaultValue(LibPUAE.FASTMEM_AUTO)] + [TypeConverter(typeof(ConstrainedIntConverter))] + public int FastMemory { get; set; } + + [DisplayName("Mouse speed")] + [Description("Mouse speed in percents (1% - 1000%). Adjust if there's mismatch between emulated and host mouse movement. Note that maximum mouse movement is still 127 pixels due to Amiga hardware limitations.")] + [Range(1, 1000)] + [DefaultValue(100)] + [TypeConverter(typeof(ConstrainedIntConverter))] + public int MouseSpeed { get; set; } + + [DisplayName("Stereo separation")] + [Description("Stereo separation in percents. 100% is full separation, 0% is mono mode.")] + [Range(0, 100)] + [DefaultValue(70)] + [TypeConverter(typeof(ConstrainedIntConverter))] + public int StereoSeparation { get; set; } + + [DisplayName("Floppy disk drives")] + [Description("How many floppy disk drives to emulate (0 - 4).")] + [Range(0, 4)] + [DefaultValue(1)] + [TypeConverter(typeof(ConstrainedIntConverter))] + public int FloppyDrives { get; set; } + + public PUAESyncSettings() + => SettingsUtil.SetDefaultValues(this); + + public PUAESyncSettings Clone() + => (PUAESyncSettings)MemberwiseClone(); + + public static bool NeedsReboot(PUAESyncSettings x, PUAESyncSettings y) + => !DeepEquality.DeepEquals(x, y); + } + } +} diff --git a/src/BizHawk.Emulation.Cores/Computers/Amiga/PUAE.cs b/src/BizHawk.Emulation.Cores/Computers/Amiga/PUAE.cs new file mode 100644 index 00000000000..5fae12b66ad --- /dev/null +++ b/src/BizHawk.Emulation.Cores/Computers/Amiga/PUAE.cs @@ -0,0 +1,318 @@ +using BizHawk.Common; +using BizHawk.Common.CollectionExtensions; +using BizHawk.Common.StringExtensions; +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Waterbox; +//using BizHawk.Emulation.DiscSystem; + +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace BizHawk.Emulation.Cores.Computers.Amiga +{ + [PortedCore( + name: CoreNames.PUAE, + author: "UAE Team", + portedVersion: "5.0.0", + portedUrl: "https://github.com/libretro/libretro-uae")] + public partial class PUAE : WaterboxCore + { + internal CoreComm _comm { get; } + private readonly List _roms; + //private readonly List _discs; + private LibPUAE _puae; + private List _args; + private string _chipsetCompatible = ""; + private int _currentDrive = 0; + private int _currentSlot = 0; + private byte[] _currentRom; + private bool _ejectPressed = false; + private bool _insertPressed = false; + private bool _nextSlotPressed = false; + private bool _nextDrivePressed = false; + + [CoreConstructor(VSystemID.Raw.Amiga)] + public PUAE(CoreLoadParameters lp) + : base(lp.Comm, new Configuration + { + DefaultWidth = LibPUAE.PAL_WIDTH, + DefaultHeight = LibPUAE.PAL_HEIGHT, + MaxWidth = LibPUAE.PAL_WIDTH, + MaxHeight = LibPUAE.PAL_HEIGHT, + MaxSamples = 2 * 1024, + SystemId = VSystemID.Raw.Amiga, + DefaultFpsNumerator = 50, + DefaultFpsDenominator = 1 + }) + { + _comm = lp.Comm; + _roms = lp.Roms; + //_discs = lp.Discs; + _syncSettings = lp.SyncSettings ?? new(); + var filesToRemove = new List(); + CreateArguments(_syncSettings); + ControllerDefinition = InitInput(); + + _puae = PreInit(new WaterboxOptions + { + Filename = "puae.wbx", + SbrkHeapSizeKB = 5 * 512, + SealedHeapSizeKB = 10 * 1024, + InvisibleHeapSizeKB = 10 * 1024, + PlainHeapSizeKB = 10 * 1024, + MmapHeapSizeKB = 40 * 1024, + SkipCoreConsistencyCheck = lp.Comm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck), + SkipMemoryConsistencyCheck = lp.Comm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck), + }); + + for (var index = 0; index < lp.Roms.Count; index++) + { + if (lp.Roms[index].Extension.ToLowerInvariant() == ".hdf") + { + var access = "ro"; + var device_name = "DH0"; + var volume_name = FileNames.HD + index; + var blocks_per_track = 32; + var surfaces = 1; + var reserved = 2; + var block_size = 512; + var boot_priority = 0; + var filesys_path = ""; + var controller_unit = "uae0"; + + if (Encoding.ASCII.GetString(lp.Roms[index].RomData, 0, 3) == "RDS") + { + blocks_per_track = 0; + surfaces = 0; + reserved = 0; + } + _exe.AddReadonlyFile(lp.Roms[index].FileData, volume_name); + AppendSetting($"hardfile2=" + + $"{access}," + + $"{device_name}:" + + $"\"{volume_name}\"," + + $"{blocks_per_track}," + + $"{surfaces}," + + $"{reserved}," + + $"{block_size}," + + $"{boot_priority}," + + $"{filesys_path}," + + $"{controller_unit}"); + } + else + { + _exe.AddTransientFile(lp.Roms[index].FileData, FileNames.FD + index); + if (index < Math.Min(LibPUAE.MAX_FLOPPIES, _syncSettings.FloppyDrives)) + { + AppendSetting($"floppy{index}={FileNames.FD}{index}"); + AppendSetting($"floppy{index}type={(int)DriveType.DRV_35_DD}"); + AppendSetting($"floppy_write_protect=no"); + } + } + } + + //AppendSetting("filesystem2=ro,DH0:data:Floppy/,0"); + + var (kickstartData, kickstartInfo) = CoreComm.CoreFileProvider.GetFirmwareWithGameInfoOrThrow( + new(VSystemID.Raw.Amiga, _chipsetCompatible), + "Firmware files are required!"); + _exe.AddReadonlyFile(kickstartData, kickstartInfo.Name); + filesToRemove.Add(kickstartInfo.Name); + _args.AddRange( + [ + "-r", kickstartInfo.Name + ]); + + var s = string.Join(" ", _args); + Console.WriteLine(); + Console.WriteLine(s); + Console.WriteLine(); + + if (!_puae.Init(_args.Count, _args.ToArray())) + throw new InvalidOperationException("Core rejected the rom!"); + + foreach (var f in filesToRemove) + { + _exe.RemoveReadonlyFile(f); + } + + PostInit(); + } + + private static ControllerDefinition InitInput() + { + var controller = new ControllerDefinition("Amiga Controller"); + + foreach (var b in Enum.GetValues(typeof(LibPUAE.PUAEJoystick))) + { + var name = Enum.GetName(typeof(LibPUAE.PUAEJoystick), b).Replace('_', ' '); + controller.BoolButtons.Add(name); + controller.CategoryLabels[name] = "Joystick"; + } + + controller.BoolButtons.AddRange( + [ + Inputs.MouseLeftButton, Inputs.MouseMIddleButton, Inputs.MouseRightButton + ]); + + controller + .AddAxis(Inputs.MouseX, (0).RangeTo(LibPUAE.PAL_WIDTH), LibPUAE.PAL_WIDTH / 2) + .AddAxis(Inputs.MouseY, (0).RangeTo(LibPUAE.PAL_HEIGHT), LibPUAE.PAL_HEIGHT / 2); + + foreach (var b in controller.BoolButtons) + { + if (b.StartsWithOrdinal("Mouse")) + { + controller.CategoryLabels[b] = "Mouse"; + } + } + + controller.BoolButtons.AddRange( + [ + Inputs.NextDrive, Inputs.NextSlot, Inputs.Insert, Inputs.Eject + ]); + + foreach (var b in Enum.GetValues(typeof(LibPUAE.PUAEKeyboard))) + { + var name = Enum.GetName(typeof(LibPUAE.PUAEKeyboard), b).Replace('_', ' '); + controller.BoolButtons.Add(name); + controller.CategoryLabels[name] = "Keyboard"; + } + + return controller.MakeImmutable(); + } + + protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound) + { + var fi = new LibPUAE.FrameInfo + { + MouseButtons = 0, + Action = LibPUAE.DriveAction.None + }; + + foreach (var b in Enum.GetValues(typeof(LibPUAE.PUAEJoystick))) + { + if (controller.IsPressed(Enum.GetName(typeof(LibPUAE.PUAEJoystick), b).Replace('_', ' '))) + { + fi.JoystickState |= (LibPUAE.PUAEJoystick)b; + } + } + + if (controller.IsPressed(Inputs.MouseLeftButton)) + { + fi.MouseButtons |= LibPUAE.b00000001; + } + if (controller.IsPressed(Inputs.MouseRightButton)) + { + fi.MouseButtons |= LibPUAE.b00000010; + } + if (controller.IsPressed(Inputs.MouseMIddleButton)) + { + fi.MouseButtons |= LibPUAE.b00000100; + } + fi.MouseX = controller.AxisValue(Inputs.MouseX); + fi.MouseY = controller.AxisValue(Inputs.MouseY); + + if (controller.IsPressed(Inputs.Eject)) + { + if (!_ejectPressed) + { + fi.Action = LibPUAE.DriveAction.Eject; + } + } + else if (controller.IsPressed(Inputs.Insert)) + { + if (!_insertPressed) + { + fi.Action = LibPUAE.DriveAction.Insert; + unsafe + { + string str = FileNames.FD + _currentSlot; + fixed(char* filename = str) + fixed (byte* buffer = fi.Name.Buffer) + { + Encoding.ASCII.GetBytes(filename, str.Length, buffer, LibPUAE.FILENAME_MAXLENGTH); + } + } + } + } + if (controller.IsPressed(Inputs.NextSlot)) + { + if (!_nextSlotPressed) + { + _currentSlot++; + _currentSlot %= _roms.Count; + var selectedFile = _roms[_currentSlot]; + _currentRom = selectedFile.FileData; + _comm.Notify(selectedFile.Game.Name, null); + } + } + if (controller.IsPressed(Inputs.NextDrive)) + { + if (!_nextDrivePressed) + { + _currentDrive++; + _currentDrive %= _syncSettings.FloppyDrives; + _comm.Notify($"Selected FD{ _currentDrive }: Drive", null); + } + } + _ejectPressed = controller.IsPressed(Inputs.Eject); + _insertPressed = controller.IsPressed(Inputs.Insert); + _nextSlotPressed = controller.IsPressed(Inputs.NextSlot); + _nextDrivePressed = controller.IsPressed(Inputs.NextDrive); + fi.CurrentDrive = _currentDrive; + + foreach (var b in Enum.GetValues(typeof(LibPUAE.PUAEKeyboard))) + { + var name = Enum.GetName(typeof(LibPUAE.PUAEKeyboard), b); + var value = (int)Enum.Parse(typeof(LibPUAE.PUAEKeyboard), name); + if (controller.IsPressed(name.Replace('_', ' '))) + { + unsafe + { + fi.Keys.Buffer[value] = 1; + } + } + } + + return fi; + } + + protected override void SaveStateBinaryInternal(BinaryWriter writer) + { + writer.Write(_ejectPressed); + writer.Write(_insertPressed); + writer.Write(_nextSlotPressed); + writer.Write(_nextDrivePressed); + } + + protected override void LoadStateBinaryInternal(BinaryReader reader) + { + _ejectPressed = reader.ReadBoolean(); + _insertPressed = reader.ReadBoolean(); + _nextSlotPressed = reader.ReadBoolean(); + _nextDrivePressed = reader.ReadBoolean(); + } + + private static class FileNames + { + public const string FD = "FloppyDisk"; + public const string CD = "CompactDisk"; + public const string HD = "HardDrive"; + } + + private static class Inputs + { + public const string MouseLeftButton = "Mouse Left Button"; + public const string MouseRightButton = "Mouse Right Button"; + public const string MouseMIddleButton = "Mouse Middle Button"; + public const string MouseX = "Mouse X"; + public const string MouseY = "Mouse Y"; + public const string Eject = "Eject"; + public const string Insert = "Insert"; + public const string NextDrive = "Next Drive"; + public const string NextSlot = "Next Slot"; + } + } +} \ No newline at end of file diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.IDebuggable.cs index d1316422177..ef4dcd92840 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.IMemoryDomains.cs index 9d21bada1be..abe55a6c9d3 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.Util.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.Util.cs index 61d92baf094..d5008f88357 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.Util.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.Util.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Linq.Expressions; diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.cs index c7a2f07cd8e..7088179efcb 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Datacorder/DatacorderDevice.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Datacorder/DatacorderDevice.cs index cf6acdcb395..679697153b7 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Datacorder/DatacorderDevice.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Datacorder/DatacorderDevice.cs @@ -1,6 +1,6 @@ using BizHawk.Common; using BizHawk.Emulation.Cores.Components.Z80A; -using System; + using System.Collections.Generic; using System.Linq; using System.Text; @@ -381,7 +381,7 @@ public bool GetEarBit(long cpuCycle) long cycles = cpuCycle - _lastCycle; // check whether tape is actually playing - if (tapeMotor == false) + if (!tapeMotor) { // it's not playing. Update lastCycle and return _lastCycle = cpuCycle; diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Disk/NECUPD765.Definitions.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Disk/NECUPD765.Definitions.cs index 576f8886c4f..37381369288 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Disk/NECUPD765.Definitions.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Disk/NECUPD765.Definitions.cs @@ -1,5 +1,4 @@ using BizHawk.Common; -using System; namespace BizHawk.Emulation.Cores.Computers.AmstradCPC { diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Disk/NECUPD765.FDD.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Disk/NECUPD765.FDD.cs index 18f07af11af..ead144fb447 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Disk/NECUPD765.FDD.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Disk/NECUPD765.FDD.cs @@ -1,6 +1,5 @@ using BizHawk.Common; using BizHawk.Common.NumberExtensions; -using System; namespace BizHawk.Emulation.Cores.Computers.AmstradCPC { diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Disk/NECUPD765.IPortIODevice.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Disk/NECUPD765.IPortIODevice.cs index 763080209c7..2c37ce05799 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Disk/NECUPD765.IPortIODevice.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Disk/NECUPD765.IPortIODevice.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; using System.Globalization; diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/AmstradGateArray.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/AmstradGateArray.cs index 7384e398f03..3b691e4def8 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/AmstradGateArray.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/AmstradGateArray.cs @@ -2,7 +2,7 @@ using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.Z80A; -using System; + using System.Collections; using System.Collections.Generic; using System.Linq; @@ -1224,14 +1224,14 @@ public void SyncState(Serializer ser) /// public class CharacterLine { +#if false /// /// Screenmode is defined at each HSYNC (start of a new character line) /// Therefore we pass the mode in via constructor /// - //public CharacterLine(int screenMode) - //{ - //ScreenMode = screenMode; - //} + public CharacterLine(int screenMode) + => ScreenMode = screenMode; +#endif public int ScreenMode = 1; public List Phases = new List(); diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/CRTDevice.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/CRTDevice.cs index 06461dadcb0..1a727651af4 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/CRTDevice.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Display/CRTDevice.cs @@ -1,7 +1,6 @@ using BizHawk.Common; using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; -using System; namespace BizHawk.Emulation.Cores.Computers.AmstradCPC { diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Input/StandardKeyboard.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Input/StandardKeyboard.cs index 5c3eb8a24d2..67fcd485259 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Input/StandardKeyboard.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/Input/StandardKeyboard.cs @@ -1,5 +1,5 @@ using BizHawk.Common; -using System; + using System.Collections; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/SoundOutput/AY38912.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/SoundOutput/AY38912.cs index 0e2134c332a..84157ee2419 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/SoundOutput/AY38912.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/SoundOutput/AY38912.cs @@ -1,6 +1,6 @@ using BizHawk.Common; using BizHawk.Emulation.Common; -using System; + using System.Collections.Generic; namespace BizHawk.Emulation.Cores.Computers.AmstradCPC diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/SoundOutput/Beeper.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/SoundOutput/Beeper.cs index 204a2a21e8f..5decb62384b 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/SoundOutput/Beeper.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Hardware/SoundOutput/Beeper.cs @@ -1,6 +1,5 @@ using BizHawk.Common; using BizHawk.Emulation.Common; -using System; namespace BizHawk.Emulation.Cores.Computers.AmstradCPC { diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPC464/CPC464.Port.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPC464/CPC464.Port.cs index 9d2d10e321f..d32a2ad4bf0 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPC464/CPC464.Port.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPC464/CPC464.Port.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; namespace BizHawk.Emulation.Cores.Computers.AmstradCPC diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPC6128/CPC6128.Port.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPC6128/CPC6128.Port.cs index 6cd4c5706c9..537a18f525f 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPC6128/CPC6128.Port.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPC6128/CPC6128.Port.cs @@ -1,5 +1,5 @@ using BizHawk.Common.NumberExtensions; -using System; + using System.Collections; namespace BizHawk.Emulation.Cores.Computers.AmstradCPC diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPCBase.Media.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPCBase.Media.cs index 02dc1620eb3..98841d815cd 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPCBase.Media.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/CPCBase.Media.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/GateArrayBase.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/GateArrayBase.cs index 71cf090839d..abf51750c13 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/GateArrayBase.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Machine/GateArrayBase.cs @@ -1,7 +1,7 @@ using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.Z80A; -using System; + using System.Collections; namespace BizHawk.Emulation.Cores.Computers.AmstradCPC diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Disk/CPCExtendedFloppyDisk.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Disk/CPCExtendedFloppyDisk.cs index 3193db72be0..cd24f967cab 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Disk/CPCExtendedFloppyDisk.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Disk/CPCExtendedFloppyDisk.cs @@ -1,6 +1,6 @@ using System.Text; using BizHawk.Common; -using System; + using System.Collections.Generic; using BizHawk.Common.StringExtensions; diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Disk/CPCFloppyDisk.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Disk/CPCFloppyDisk.cs index 43029789b4b..a28facaa1e3 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Disk/CPCFloppyDisk.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Disk/CPCFloppyDisk.cs @@ -1,7 +1,7 @@ using System.Text; using BizHawk.Common; using System.Collections.Generic; -using System; + using BizHawk.Common.StringExtensions; namespace BizHawk.Emulation.Cores.Computers.AmstradCPC diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Disk/FloppyDisk.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Disk/FloppyDisk.cs index 6caba681fe9..9e6464c017f 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Disk/FloppyDisk.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Disk/FloppyDisk.cs @@ -1,5 +1,5 @@ using BizHawk.Common; -using System; + using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/MediaConverter.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/MediaConverter.cs index 954f76c2ded..2ad77ef297d 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/MediaConverter.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/MediaConverter.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.IO.Compression; diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Tape/CDT/CdtConverter.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Tape/CDT/CdtConverter.cs index 8591e2f0008..c941eb3b03a 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Tape/CDT/CdtConverter.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/Media/Tape/CDT/CdtConverter.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/SoundProviderMixer.cs b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/SoundProviderMixer.cs index 9bc3ec6539e..242c42db66e 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/SoundProviderMixer.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AmstradCPC/SoundProviderMixer.cs @@ -1,5 +1,5 @@ using BizHawk.Emulation.Common; -using System; + using System.Collections.Generic; namespace BizHawk.Emulation.Cores.Computers.AmstradCPC diff --git a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IDebuggable.cs index 9566f1b14a2..390a72d1322 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IDisassembler.cs b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IDisassembler.cs index 4ae4f1a1072..36a22b1c8f9 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IDisassembler.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IDisassembler.cs @@ -17,10 +17,7 @@ public string Cpu public string PCRegisterName => "PC"; - public IEnumerable AvailableCpus - { - get { yield return "6502"; } - } + public IEnumerable AvailableCpus { get; } = [ "6502" ]; public string Disassemble(MemoryDomain m, uint addr, out int length) { diff --git a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IMemoryDomains.cs index 6d7932bb5e3..7827d8afd8c 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.ISaveRam.cs index 332dda89e35..f16ff1b59f1 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.ISaveRam.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.ISettable.cs b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.ISettable.cs index ba5a9519d3a..0a2e6342537 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.ISettable.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.ISoundProvider.cs b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.ISoundProvider.cs index a655d5247b6..144eb5ed705 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.ISoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.ISoundProvider.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Computers.AppleII diff --git a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.cs b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.cs index dfd2082afb3..529ba050840 100644 --- a/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.cs +++ b/src/BizHawk.Emulation.Cores/Computers/AppleII/AppleII.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.IDebuggable.cs index dca7310fb5b..3427d272b31 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.IDebuggable.cs @@ -10,13 +10,7 @@ public partial class C64 : IDebuggable private IDebuggable _selectedDebuggable; private IEnumerable GetAvailableDebuggables() - { - yield return _board.Cpu; - if (_board.DiskDrive != null) - { - yield return _board.DiskDrive; - } - } + => _board.DiskDrive is IDebuggable dd ? [ _board.Cpu, dd ] : [ _board.Cpu ]; private void SetDefaultDebuggable() { diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.IDisassemblable.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.IDisassemblable.cs index 944c24bcb9e..a2d86454067 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.IDisassemblable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.IDisassemblable.cs @@ -10,13 +10,7 @@ public partial class C64 : IDisassemblable private IDisassemblable _selectedDisassemblable; private IEnumerable GetAvailableDisassemblables() - { - yield return _board.Cpu; - if (_board.DiskDrive != null) - { - yield return _board.DiskDrive; - } - } + => _board.DiskDrive is IDisassemblable dd ? [ _board.Cpu, dd ] : [ _board.Cpu ]; private void SetDefaultDisassemblable() { diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.IMemoryDomains.cs index b89b26709ba..942b495ff4e 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs index 9cb55e5548f..8b58d4e3189 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeDevice.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeDevice.cs index 8590a1e4975..97aefdca094 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeDevice.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeDevice.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgePort.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgePort.cs index 055f1fe0afd..0c2163df5f4 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgePort.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgePort.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0000.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0000.cs index 8954ace31d3..54872c9773a 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0000.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0000.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0001.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0001.cs index a7d662796fb..2ec151991a0 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0001.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0001.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0005.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0005.cs index 1fa7e798769..bbefdb5f443 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0005.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0005.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000A.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000A.cs index 7916a457654..a2dec44f0cc 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000A.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000A.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000B.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000B.cs index 9adbd5406d2..56d7b7cffc1 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000B.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000B.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000F.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000F.cs index 2d8090a96f8..250490ed854 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000F.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000F.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0012.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0012.cs index 22783696fa4..0c0ed5731ef 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0012.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0012.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0013.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0013.cs index 19fce67c3e5..946cc454480 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0013.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0013.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0020.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0020.cs index 2ff0806bfec..65b20a04e9c 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0020.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0020.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper002B.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper002B.cs index 8d733d9fcca..4bc455c97a9 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper002B.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper002B.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cassette/CassettePort.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cassette/CassettePort.cs index 9e7be9a88fa..d67ebe8a9f2 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cassette/CassettePort.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cassette/CassettePort.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cassette diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cassette/CassettePortDevice.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cassette/CassettePortDevice.cs index 4039e5c9132..a7d2fef3402 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cassette/CassettePortDevice.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cassette/CassettePortDevice.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cassette diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/FFT.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/FFT.cs index b87c8f5b384..68514b60bf1 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/FFT.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/FFT.cs @@ -1,5 +1,3 @@ -using System; - // Copyright(C) 1996-2001 Takuya Ooura // C# port by J.D. Purcell // You may use, copy, modify this code for any purpose and without fee. diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip23128.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip23128.cs index 5772386af1e..d4a06d13949 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip23128.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip23128.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS { // ROM chips diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6510.IDisassemblable.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6510.IDisassemblable.cs index 6ccfc9f3f7e..8952e076431 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6510.IDisassemblable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6510.IDisassemblable.cs @@ -6,10 +6,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS { public sealed partial class Chip6510 : IDisassemblable { - public IEnumerable AvailableCpus - { - get { yield return "6510"; } - } + public IEnumerable AvailableCpus { get; } = [ "6510" ]; public string Cpu { diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6510.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6510.cs index b2b342c286b..1ff8be0ee5a 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6510.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6510.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.M6502; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6522.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6522.cs index d54e3c2e1af..574f74eec6d 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6522.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6522.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS { public static class Chip6522 diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6526.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6526.cs index f7fb0665f13..6fc72823db3 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6526.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6526.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS { // MOS technology 6526 "CIA" diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip90611401.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip90611401.cs index 75af8f84ac4..36ffb87fd59 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip90611401.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip90611401.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Cia.Port.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Cia.Port.cs index f4af0f5146c..04ff46a04cf 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Cia.Port.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Cia.Port.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS { public sealed partial class Cia diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Cia.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Cia.cs index 91fa4e56514..22bf8856ef0 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Cia.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Cia.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Sid.SoundProvider.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Sid.SoundProvider.cs index cff7a41f8c0..f39bc5b9735 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Sid.SoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Sid.SoundProvider.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Sid.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Sid.cs index f3f3a56e5cb..75a2dd5c153 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Sid.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Sid.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.Port.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.Port.cs index 14d89e0c438..cc9f132b188 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.Port.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.Port.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.cs index a0ec89b9e4f..f278f377e3e 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.cs index b1159ee6431..0d4753f8057 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Vic.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/D64.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/D64.cs index 98ef0649cf1..4698f88fba4 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/D64.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/D64.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -125,7 +124,7 @@ private static byte[] ConvertSectorToGcr(byte[] source, byte sectorNo, byte trac writer.Write(syncBytes40); // sync writer.Write(EncodeGcr(new byte[] { (byte)(errorType == ErrorType.DataNotFound ? 0x00 : 0x08), headerChecksum, sectorNo, trackNo, formatA, formatB, 0x0F, 0x0F })); // header - writer.Write(new byte[] { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }); // gap + writer.Write("UUUUUUUUU"u8.ToArray()); // gap writer.Write(syncBytes40); // sync writer.Write(EncodeGcr(writtenData)); // data writer.Write(Enumerable.Repeat((byte)0x55, gapLength).ToArray()); // gap diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Disk.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Disk.cs index 3ff51cd7703..5405b078565 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Disk.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Disk.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/DiskBuilder.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/DiskBuilder.cs index 778670a31f8..d1e8ff81383 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/DiskBuilder.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/DiskBuilder.cs @@ -1,6 +1,5 @@ -using System; +using System.Buffers.Binary; using System.Collections.Generic; -using System.Linq; using System.Text; namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media @@ -83,21 +82,18 @@ public bool this[int sector] public byte[] GetBytes() { - return GetBytesEnumerable().ToArray(); - } - - private IEnumerable GetBytesEnumerable() - { - yield return unchecked((byte)(Data >> 24)); - yield return unchecked((byte)(Data >> 16)); - yield return unchecked((byte)(Data >> 8)); - yield return unchecked((byte)Data); + var buf = new byte[sizeof(int)]; + BinaryPrimitives.WriteInt32BigEndian(buf, Data); + return buf; } +#if false public IEnumerable Entries { get { +// return Enumerable.Range(start: 0, count: Sectors).Select(i => (Data & (1 << (24 - i))) is not 0); + // ^ simpler implementation, probably has an off-by-one error --yoshi var d = Data; for (var i = 0; i < Sectors; i++) { @@ -106,6 +102,7 @@ public IEnumerable Entries } } } +#endif } protected class LocatedEntry diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/G64.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/G64.cs index ae875049ab4..e2726894414 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/G64.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/G64.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -100,9 +99,8 @@ public static byte[] Write(IList trackData, IList trackNumbers, ILi offsets.Add((int)trackMem.Length); densities.Add(trackDensities[trackIndex]); - var data = trackData[trackIndex]; var buffer = Enumerable.Repeat(dataFillerValue, trackMaxLength).ToArray(); - var dataBytes = data.Select(d => unchecked(d)).ToArray(); + var dataBytes = trackData[trackIndex]; Array.Copy(dataBytes, buffer, dataBytes.Length); trackMemWriter.Write((ushort)dataBytes.Length); trackMemWriter.Write(buffer); diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Tape.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Tape.cs index 529b893b09a..f482788eef0 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Tape.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Tape.cs @@ -1,4 +1,3 @@ -using System; using System.Text; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.IDebuggable.cs index 534b86217e8..71abed5c105 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.IDisassemblable.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.IDisassemblable.cs index c8c159933e1..6135995fde4 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.IDisassemblable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.IDisassemblable.cs @@ -5,10 +5,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial { public sealed partial class Drive1541 : IDisassemblable { - IEnumerable IDisassemblable.AvailableCpus - { - get { yield return "Disk Drive 6502"; } - } + public IEnumerable AvailableCpus { get; } = [ "Disk Drive 6502" ]; string IDisassemblable.Cpu { diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs index 22fd03870af..129f496a0a6 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/SerialPort.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/SerialPort.cs index 725d7111056..352c0bfbd40 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/SerialPort.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/SerialPort.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/SerialPortDevice.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/SerialPortDevice.cs index 657519f580f..a46248444ee 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/SerialPortDevice.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/SerialPortDevice.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/User/UserPort.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/User/UserPort.cs index e92642d09cf..849f816c568 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/User/UserPort.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/User/UserPort.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Computers.Commodore64.User diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/User/UserPortDevice.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/User/UserPortDevice.cs index c47b13d5048..8e0b0c71afc 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/User/UserPortDevice.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/User/UserPortDevice.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Computers.Commodore64.User diff --git a/src/BizHawk.Emulation.Cores/Computers/MSX/LibMSX.cs b/src/BizHawk.Emulation.Cores/Computers/MSX/LibMSX.cs index 43681cc2052..cd1d0506367 100644 --- a/src/BizHawk.Emulation.Cores/Computers/MSX/LibMSX.cs +++ b/src/BizHawk.Emulation.Cores/Computers/MSX/LibMSX.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Computers/MSX/MSX.IEmulator.cs b/src/BizHawk.Emulation.Cores/Computers/MSX/MSX.IEmulator.cs index a7d147424bf..f14cb7a2fe3 100644 --- a/src/BizHawk.Emulation.Cores/Computers/MSX/MSX.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Computers/MSX/MSX.IEmulator.cs @@ -1,5 +1,4 @@ using BizHawk.Emulation.Common; -using System; namespace BizHawk.Emulation.Cores.Computers.MSX { diff --git a/src/BizHawk.Emulation.Cores/Computers/MSX/MSX.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Computers/MSX/MSX.ISaveRam.cs index e9f89ac306d..c628aa99bf5 100644 --- a/src/BizHawk.Emulation.Cores/Computers/MSX/MSX.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Computers/MSX/MSX.ISaveRam.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Computers.MSX diff --git a/src/BizHawk.Emulation.Cores/Computers/MSX/MSX.cs b/src/BizHawk.Emulation.Cores/Computers/MSX/MSX.cs index ad78413d0bf..37143bcc820 100644 --- a/src/BizHawk.Emulation.Cores/Computers/MSX/MSX.cs +++ b/src/BizHawk.Emulation.Cores/Computers/MSX/MSX.cs @@ -1,4 +1,3 @@ -using System; using System.Text; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Datacorder/DatacorderDevice.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Datacorder/DatacorderDevice.cs index e4b7dd6f7ec..2742751816b 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Datacorder/DatacorderDevice.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Datacorder/DatacorderDevice.cs @@ -1,6 +1,6 @@ using BizHawk.Common; using BizHawk.Emulation.Cores.Components.Z80A; -using System; + using System.Collections.Generic; using System.Linq; using System.Text; @@ -418,7 +418,7 @@ public bool GetEarBit(long cpuCycle) bool is48k = _machine.IsIn48kMode(); // check whether tape is actually playing - if (_tapeIsPlaying == false) + if (!_tapeIsPlaying) { // it's not playing. Update lastCycle and return _lastCycle = cpuCycle; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.Definitions.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.Definitions.cs index fb58a807d89..5f66138ee5e 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.Definitions.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.Definitions.cs @@ -1,5 +1,4 @@ using BizHawk.Common; -using System; namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum { diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.FDD.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.FDD.cs index 61fee86bb69..5a57bfa0fff 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.FDD.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.FDD.cs @@ -1,6 +1,5 @@ using BizHawk.Common; using BizHawk.Common.NumberExtensions; -using System; namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum { diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.IPortIODevice.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.IPortIODevice.cs index 4bb412a50a8..468b0d92078 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.IPortIODevice.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Disk/NECUPD765.IPortIODevice.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; using System.Globalization; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/CursorJoystick.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/CursorJoystick.cs index 66c70788965..69a163e1d7d 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/CursorJoystick.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/CursorJoystick.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/KempstonJoystick.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/KempstonJoystick.cs index 5e2d710f7ee..c3331dfb4c3 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/KempstonJoystick.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/KempstonJoystick.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/NullJoystick.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/NullJoystick.cs index f2b52a3d628..c1fe56466d1 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/NullJoystick.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/NullJoystick.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/SinclairJoystick1.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/SinclairJoystick1.cs index b16d024075d..79d5cb2b4a4 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/SinclairJoystick1.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/SinclairJoystick1.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/SinclairJoystick2.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/SinclairJoystick2.cs index d35504e9b07..f267e7c1daa 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/SinclairJoystick2.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/SinclairJoystick2.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/StandardKeyboard.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/StandardKeyboard.cs index b799a6f6200..6b89338aeed 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/StandardKeyboard.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/Input/StandardKeyboard.cs @@ -1,5 +1,5 @@ using BizHawk.Common; -using System; + using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/SoundOuput/AY38912.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/SoundOuput/AY38912.cs index 17e34ae24ac..0595545db89 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/SoundOuput/AY38912.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Hardware/SoundOuput/AY38912.cs @@ -1,7 +1,7 @@ using BizHawk.Common; using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; -using System; + using System.Collections.Generic; namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum @@ -51,7 +51,6 @@ public void Init(int sampleRate, int tStatesPerFrame) /// /// |11-- ---- ---- --0-| - IN - Read value of currently selected register /// - /// public bool ReadPort(ushort port, ref int value) { if (!port.Bit(1)) @@ -72,7 +71,6 @@ public bool ReadPort(ushort port, ref int value) /// |11-- ---- ---- --0-| - OUT - Register Select /// |10-- ---- ---- --0-| - OUT - Write value to currently selected register /// - /// public bool WritePort(ushort port, int value) { if (!port.Bit(1)) diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/Pentagon128K/Pentagon128.Port.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/Pentagon128K/Pentagon128.Port.cs index 72889d1b0d5..277e745471f 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/Pentagon128K/Pentagon128.Port.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/Pentagon128K/Pentagon128.Port.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum @@ -46,9 +45,8 @@ public override byte ReadPort(ushort port) // if this is detected just return the kempston byte if (lowByte == 0x1f) { - if (LocateUniqueJoystick(JoystickType.Kempston) != null) - return (byte)((KempstonJoystick)LocateUniqueJoystick(JoystickType.Kempston)).JoyLine; - + //TODO lines swapped? + if (LocateUniqueJoystick(JoystickType.Kempston) is KempstonJoystick j) return (byte) j.JoyLine; InputRead = true; } else @@ -90,7 +88,7 @@ public override void WritePort(ushort port, byte value) // memory paging // this is controlled by writes to port 0x7ffd // but it is only partially decoded so it actually responds to any port with bits 1 and 15 reset - if (portBits[1] == false && portBits[15] == false) + if (!portBits[1] && !portBits[15]) { Last7ffd = value; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/SpectrumBase.Media.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/SpectrumBase.Media.cs index 61cfe4295f1..5a618e85482 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/SpectrumBase.Media.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/SpectrumBase.Media.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/SpectrumBase.Memory.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/SpectrumBase.Memory.cs index 1e00b123937..23a264d0c0e 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/SpectrumBase.Memory.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/SpectrumBase.Memory.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum { /// diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ULA.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ULA.cs index e75fc1b0b80..679392624d0 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ULA.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ULA.cs @@ -1,6 +1,6 @@ using BizHawk.Common; using BizHawk.Emulation.Common; -using System; + using System.Collections.Generic; namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.Port.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.Port.cs index 5aee11266a2..573acd2370c 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.Port.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128K/ZX128.Port.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum @@ -46,14 +45,9 @@ public override byte ReadPort(ushort port) // if this is detected just return the kempston byte if (lowByte == 0x1f) { - if (LocateUniqueJoystick(JoystickType.Kempston) != null) - { - InputRead = true; - return (byte)((KempstonJoystick)LocateUniqueJoystick(JoystickType.Kempston)).JoyLine; - } - - InputRead = true; - } + InputRead = true; + if (LocateUniqueJoystick(JoystickType.Kempston) is KempstonJoystick j) return (byte) j.JoyLine; + } else { if (KeyboardDevice.ReadPort(port, ref result)) @@ -93,7 +87,7 @@ public override void WritePort(ushort port, byte value) // memory paging // this is controlled by writes to port 0x7ffd // but it is only partially decoded so it actually responds to any port with bits 1 and 15 reset - if (portBits[1] == false && portBits[15] == false) + if (!portBits[1] && !portBits[15]) { Last7ffd = value; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.Port.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.Port.cs index 6301e8ee434..98e4eb22ee7 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.Port.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus2a/ZX128Plus2a.Port.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum @@ -27,14 +26,9 @@ public override byte ReadPort(ushort port) // if this is detected just return the kempston byte if (lowByte == 0x1f) { - if (LocateUniqueJoystick(JoystickType.Kempston) != null) - { - InputRead = true; - return (byte)((KempstonJoystick)LocateUniqueJoystick(JoystickType.Kempston)).JoyLine; - } - - InputRead = true; - } + InputRead = true; + if (LocateUniqueJoystick(JoystickType.Kempston) is KempstonJoystick j) return (byte) j.JoyLine; + } else { if (KeyboardDevice.ReadPort(port, ref result)) diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus3/ZX128Plus3.Port.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus3/ZX128Plus3.Port.cs index 1c1a94ccf02..c883dd3048f 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus3/ZX128Plus3.Port.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum128KPlus3/ZX128Plus3.Port.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum @@ -27,13 +26,8 @@ public override byte ReadPort(ushort port) // if this is detected just return the kempston byte if (lowByte == 0x1f) { - if (LocateUniqueJoystick(JoystickType.Kempston) != null) - { - InputRead = true; - return (byte)((KempstonJoystick)LocateUniqueJoystick(JoystickType.Kempston)).JoyLine; - } - - InputRead = true; + InputRead = true; + if (LocateUniqueJoystick(JoystickType.Kempston) is KempstonJoystick j) return (byte) j.JoyLine; } else if (UPDDiskDevice.ReadPort(port, ref result)) { diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Port.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Port.cs index 0ef9edc8563..702f829ccd1 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Port.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.Port.cs @@ -22,14 +22,9 @@ public override byte ReadPort(ushort port) // if this is detected just return the kempston byte if (lowByte == 0x1f) { - if (LocateUniqueJoystick(JoystickType.Kempston) != null) - { - InputRead = true; - return (byte)((KempstonJoystick)LocateUniqueJoystick(JoystickType.Kempston)).JoyLine; - } - // not a lag frame InputRead = true; + if (LocateUniqueJoystick(JoystickType.Kempston) is KempstonJoystick j) return (byte) j.JoyLine; } // Even ports always address the ULA else if (lowBitReset) diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.cs index eba23b3b599..e4bfbd068be 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Machine/ZXSpectrum48K/ZX48.cs @@ -1,5 +1,5 @@ using BizHawk.Emulation.Cores.Components.Z80A; -using System; + using System.Collections.Generic; using BizHawk.Emulation.Cores.Sound; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/CPCFormat/CPCExtendedFloppyDisk.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/CPCFormat/CPCExtendedFloppyDisk.cs index da3b4446b78..5173b2a4d10 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/CPCFormat/CPCExtendedFloppyDisk.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/CPCFormat/CPCExtendedFloppyDisk.cs @@ -1,6 +1,6 @@ using System.Text; using BizHawk.Common; -using System; + using System.Collections.Generic; using BizHawk.Common.StringExtensions; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/CPCFormat/CPCFloppyDisk.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/CPCFormat/CPCFloppyDisk.cs index a78ed1515f2..43dfbed1277 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/CPCFormat/CPCFloppyDisk.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/CPCFormat/CPCFloppyDisk.cs @@ -1,6 +1,6 @@ using System.Text; using BizHawk.Common; -using System; + using System.Collections.Generic; using BizHawk.Common.StringExtensions; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/FloppyDisk.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/FloppyDisk.cs index ebdb89979c8..d0234451f58 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/FloppyDisk.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/FloppyDisk.cs @@ -1,5 +1,5 @@ using BizHawk.Common; -using System; + using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/IPFFormat/IPFFloppyDisk.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/IPFFormat/IPFFloppyDisk.cs index 4bd90bd4374..a9c4eb6c4dc 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/IPFFormat/IPFFloppyDisk.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/IPFFormat/IPFFloppyDisk.cs @@ -1,6 +1,6 @@ using BizHawk.Common; using BizHawk.Common.NumberExtensions; -using System; + using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/UDIFormat/UDI1_0FloppyDisk.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/UDIFormat/UDI1_0FloppyDisk.cs index 232435898b5..f3c73b7731e 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/UDIFormat/UDI1_0FloppyDisk.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Disk/UDIFormat/UDI1_0FloppyDisk.cs @@ -1,5 +1,5 @@ using BizHawk.Common; -using System; + using System.Collections; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/MediaConverter.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/MediaConverter.cs index 16061604282..d4f0f5787f9 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/MediaConverter.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/MediaConverter.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.IO.Compression; using System.Runtime.InteropServices; @@ -148,9 +147,6 @@ public static int TranslatePause(int pauseInMS) /// /// Caluclate a data block XOR checksum /// - /// - /// - /// public static bool CheckChecksum(byte[] buf, int len) { byte c = 0; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/CSW/CswConverter.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/CSW/CswConverter.cs index 86c0643e2ad..defd68480f2 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/CSW/CswConverter.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/CSW/CswConverter.cs @@ -1,5 +1,5 @@ using BizHawk.Common.NumberExtensions; -using System; + using System.Collections.Generic; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/PZX/PzxConverter.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/PZX/PzxConverter.cs index aa487e45e44..22f69db2301 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/PZX/PzxConverter.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/PZX/PzxConverter.cs @@ -1,5 +1,5 @@ using BizHawk.Common.NumberExtensions; -using System; + using System.Collections.Generic; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/TAP/TapConverter.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/TAP/TapConverter.cs index 1abb0e77ee6..0537028d00e 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/TAP/TapConverter.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/TAP/TapConverter.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/TZX/TzxConverter.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/TZX/TzxConverter.cs index 9da1fd9a242..a66973e0327 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/TZX/TzxConverter.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/TZX/TzxConverter.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -49,10 +48,6 @@ protected override string SelfTypeName /// private readonly DatacorderDevice _datacorder; - /// - /// Constructor - /// - /// public TzxConverter(DatacorderDevice _tapeDevice) { _datacorder = _tapeDevice; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/WAV/StreamHelper.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/WAV/StreamHelper.cs index 1c1669e3d91..902ae3f2183 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/WAV/StreamHelper.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/WAV/StreamHelper.cs @@ -1,4 +1,3 @@ -using System; using System.IO; namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/WAV/WavConverter.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/WAV/WavConverter.cs index cf498216cb5..20187fb095e 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/WAV/WavConverter.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/WAV/WavConverter.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/WAV/WavHeader.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/WAV/WavHeader.cs index 5787213a9db..d481f5c20c0 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/WAV/WavHeader.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/WAV/WavHeader.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/WAV/WavStreamReader.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/WAV/WavStreamReader.cs index 6df9cc22323..d0e7296fb26 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/WAV/WavStreamReader.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/Media/Tape/WAV/WavStreamReader.cs @@ -1,4 +1,3 @@ -using System; using System.IO; namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.ICodeDataLog.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.ICodeDataLog.cs index cef7ea749ce..2f9b15ad84d 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.ICodeDataLog.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.ICodeDataLog.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.IDebuggable.cs index 9d514199964..2136d324a06 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.IMemoryDomains.cs index a76ae31d0e6..f37bb168667 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.Messaging.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.Messaging.cs index cc560ad1843..f08579ad3e6 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.Messaging.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.Messaging.cs @@ -1,4 +1,3 @@ -using System; using System.Globalization; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.Util.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.Util.cs index 058aa948aef..4e88cbc5804 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.Util.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.Util.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Linq.Expressions; diff --git a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.cs b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.cs index 282e8fdd36e..e30a19c7fb4 100644 --- a/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.cs +++ b/src/BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Computers/TIC80/LibTIC80.cs b/src/BizHawk.Emulation.Cores/Computers/TIC80/LibTIC80.cs index 8b93797a016..28761a5e533 100644 --- a/src/BizHawk.Emulation.Cores/Computers/TIC80/LibTIC80.cs +++ b/src/BizHawk.Emulation.Cores/Computers/TIC80/LibTIC80.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.BizInvoke; @@ -128,8 +127,8 @@ public struct TIC80Inputs public TIC80Gamepad P3Gamepad; public TIC80Gamepad P4Gamepad; - public sbyte MouseX; - public sbyte MouseY; + public byte MouseX; + public byte MouseY; public ushort MouseButtons; public TIC80Keys Key1; @@ -143,5 +142,8 @@ public struct TIC80Inputs [BizImport(CC)] public abstract void SetInputs(ref TIC80Inputs inputs); + + [BizImport(CC)] + public abstract bool IsMouseRelative(); } } diff --git a/src/BizHawk.Emulation.Cores/Computers/TIC80/TIC80.ISettable.cs b/src/BizHawk.Emulation.Cores/Computers/TIC80/TIC80.ISettable.cs index 6f978c12a48..ac28cf7801e 100644 --- a/src/BizHawk.Emulation.Cores/Computers/TIC80/TIC80.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Computers/TIC80/TIC80.ISettable.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Computers/TIC80/TIC80.cs b/src/BizHawk.Emulation.Cores/Computers/TIC80/TIC80.cs index 8bd68433350..39cb5eb8b7e 100644 --- a/src/BizHawk.Emulation.Cores/Computers/TIC80/TIC80.cs +++ b/src/BizHawk.Emulation.Cores/Computers/TIC80/TIC80.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -11,7 +10,7 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80 { [PortedCore(CoreNames.TIC80, "nesbox", "v1.0.2164", "https://tic80.com/")] [ServiceNotApplicable(new[] { typeof(IDriveLight), })] - public partial class TIC80 : WaterboxCore + public sealed partial class TIC80 : WaterboxCore { private readonly LibTIC80 _core; @@ -41,7 +40,7 @@ public TIC80(CoreLoadParameters lp) _core = PreInit(new WaterboxOptions { Filename = "tic80.wbx", - SbrkHeapSizeKB = 2 * 1024, + SbrkHeapSizeKB = 64 * 1024, SealedHeapSizeKB = 4, InvisibleHeapSizeKB = 4, PlainHeapSizeKB = 4, @@ -51,7 +50,7 @@ public TIC80(CoreLoadParameters lp) }); var rom = lp.Roms[0].FileData; - var inputsActive = new bool[6] + var inputsActive = new[] { _syncSettings.Gamepad1, _syncSettings.Gamepad2, @@ -72,7 +71,7 @@ public TIC80(CoreLoadParameters lp) InputsActive = Array.AsReadOnly(inputsActive); PostInit(); - DeterministicEmulation = lp.DeterministicEmulationRequested || (!_syncSettings.UseRealTime); + DeterministicEmulation = lp.DeterministicEmulationRequested || !_syncSettings.UseRealTime; InitializeRtc(_syncSettings.InitialTime); } @@ -84,10 +83,10 @@ public TIC80(CoreLoadParameters lp) { var enumValues = Enum.GetValues(typeof(LibTIC80.TIC80Keys)); var ret = new KeyValuePair[enumValues.Length - 1]; - for (int i = 0; i < ret.Length; i++) + for (var i = 0; i < ret.Length; i++) { var val = enumValues.GetValue(i + 1); - var name = Enum.GetName(typeof(LibTIC80.TIC80Keys), val).TrimStart('_').Replace('_', ' '); + var name = Enum.GetName(typeof(LibTIC80.TIC80Keys), val)!.TrimStart('_').Replace('_', ' '); ret[i] = new(name, (LibTIC80.TIC80Keys)val); } @@ -98,7 +97,7 @@ private static ControllerDefinition CreateControllerDefinition(bool[] inputsActi { var ret = new ControllerDefinition("TIC-80 Controller"); - for (int i = 0; i < 4; i++) + for (var i = 0; i < 4; i++) { if (inputsActive[i]) { @@ -111,12 +110,11 @@ private static ControllerDefinition CreateControllerDefinition(bool[] inputsActi if (inputsActive[4]) { - ret.AddXYPair("Mouse Position {0}", AxisPairOrientation.RightAndUp, (-128).RangeTo(127), 0); + ret.AddXYPair("Mouse Position {0}", AxisPairOrientation.RightAndDown, (-128).RangeTo(127), 0); ret.BoolButtons.Add("Mouse Left Click"); ret.BoolButtons.Add("Mouse Middle Click"); ret.BoolButtons.Add("Mouse Right Click"); ret.AddXYPair("Mouse Scroll {0}", AxisPairOrientation.RightAndUp, (-32).RangeTo(31), 0); - ret.BoolButtons.Add("Mouse Relative Toggle"); foreach (var n in ret.BoolButtons) { @@ -139,7 +137,7 @@ private static ControllerDefinition CreateControllerDefinition(bool[] inputsActi { foreach (var k in Enum.GetValues(typeof(LibTIC80.TIC80Keys))) { - var name = Enum.GetName(typeof(LibTIC80.TIC80Keys), k).TrimStart('_').Replace('_', ' '); + var name = Enum.GetName(typeof(LibTIC80.TIC80Keys), k)!.TrimStart('_').Replace('_', ' '); if (name is "Unknown") continue; ret.BoolButtons.Add(name); ret.CategoryLabels[name] = "Keyboard"; @@ -154,7 +152,7 @@ private static ControllerDefinition CreateControllerDefinition(bool[] inputsActi private static void GetGamepads(IController controller, ref LibTIC80.TIC80Inputs inputs) { var gamepads = new LibTIC80.TIC80Gamepad[4]; - for (int i = 0; i < 4; i++) + for (var i = 0; i < 4; i++) { gamepads[i] = 0; foreach (var b in Enum.GetValues(typeof(LibTIC80.TIC80Gamepad))) @@ -175,33 +173,35 @@ private static void GetGamepads(IController controller, ref LibTIC80.TIC80Inputs private static ushort GetMouseButtons(IController controller) { ushort ret = 0; + if (controller.IsPressed("Mouse Left Click")) { - ret |= 0x8000; + ret |= 0x0001; } + if (controller.IsPressed("Mouse Middle Click")) { - ret |= 0x4000; + ret |= 0x0002; } + if (controller.IsPressed("Mouse Right Click")) { - ret |= 0x2000; + ret |= 0x0004; } + var x = (ushort)((sbyte)controller.AxisValue("Mouse Scroll X") + 32); - ret |= (ushort)(x << 7); + ret |= (ushort)(x << 3); + var y = (ushort)((sbyte)controller.AxisValue("Mouse Scroll Y") + 32); - ret |= (ushort)(y << 1); - if (controller.IsPressed("Mouse Relative Toggle")) - { - ret |= 0x0001; - } + ret |= (ushort)(y << (3 + 6)); + return ret; } private static void GetKeys(IController controller, ref LibTIC80.TIC80Inputs inputs) { var keys = new LibTIC80.TIC80Keys[4]; - int i = 0; + var i = 0; foreach (var kvp in KeyMap) { if (controller.IsPressed(kvp.Key)) @@ -224,11 +224,27 @@ protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController contro { var inputs = new LibTIC80.TIC80Inputs { - MouseX = (sbyte)controller.AxisValue("Mouse Position X"), - MouseY = (sbyte)controller.AxisValue("Mouse Position Y"), + MouseX = (byte)(sbyte)controller.AxisValue("Mouse Position X"), + MouseY = (byte)(sbyte)controller.AxisValue("Mouse Position Y"), MouseButtons = GetMouseButtons(controller), }; + // a reset will unset relative mode, but we won't know that until the reset actually happens + if (_core.IsMouseRelative() && !controller.IsPressed("Reset")) + { + inputs.MouseButtons |= 0x8000; + } + else + { + // convert (-128, 127) to (0, 255) + inputs.MouseX += 128; + inputs.MouseY += 128; + + // mouse Y is supposed to be contrained to 0-143 (i.e. screen height range) + // mouse X has the full range regardless (since screen width is 256) + inputs.MouseY = (byte)(inputs.MouseY * 143 / 255); + } + GetGamepads(controller, ref inputs); GetKeys(controller, ref inputs); _core.SetInputs(ref inputs); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.Core.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.Core.cs index c1ae0606569..e4137452969 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.Core.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.Core.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Common.NumberExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.IDebuggable.cs index 71cf6cf9844..59987a2ba4c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.IEmulator.cs index 94882dce2e2..5f9dc175205 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.IEmulator.cs @@ -1,5 +1,4 @@ using BizHawk.Emulation.Common; -using System; namespace BizHawk.Emulation.Cores.Atari.Atari2600 { @@ -69,7 +68,7 @@ public bool FrameAdvance(IController controller, bool render, bool renderSound) _tia.New_Frame = false; - if (renderSound == false) + if (!renderSound) { _tia.AudioClocks = 0; // we need this here since the async sound provider won't check in this case } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.ISettable.cs index 342545632c8..37635102def 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.ISettable.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.RomHeuristics.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.RomHeuristics.cs index cf9e71d6033..743e568155f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.RomHeuristics.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.RomHeuristics.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; @@ -403,8 +402,9 @@ private static bool IsProbablyDpcPlus(byte[] rom) // These signatures are attributed to the MESS project return ContainsAny(rom, new List { - new byte[] { 0x44, 0x50, 0x43, 0x2B }, - new byte[] { 0x44, 0x50, 0x43, 0x2B }, + // why is this checking the same value twice? ... + "DPC+"u8.ToArray(), + "DPC+"u8.ToArray(), }); } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.cs index babcfed61b8..4704d1e42f0 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600ControllerDeck.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600ControllerDeck.cs index 6558d8328df..88e3d9d67fc 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600ControllerDeck.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600ControllerDeck.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600Controllers.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600Controllers.cs index 47cc13cfb81..358a709b241 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600Controllers.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Atari2600Controllers.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/m4A50.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/m4A50.cs index 9d165417ecd..ef6b8f6ff0d 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/m4A50.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/m4A50.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Atari.Atari2600 diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/mAR.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/mAR.cs index 1654df1c1b6..594a90e9878 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/mAR.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/mAR.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/mCM.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/mCM.cs index 95b750b67f2..71c2e363896 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/mCM.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/mCM.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Common.NumberExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/mDPCPlus.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/mDPCPlus.cs index 57a4b1fb635..8bea89e269e 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/mDPCPlus.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/mDPCPlus.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/mMC.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/mMC.cs index 7bccb058f73..e6d82ef30aa 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/mMC.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Mappers/mMC.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Atari.Atari2600 { /* diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs index 7282feeb78c..ae33a1c81a8 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/TIA.cs @@ -1,4 +1,3 @@ -using System; using System.Numerics; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.ISoundProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.ISoundProvider.cs index 95a73b0e56b..cecd02f51a1 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.ISoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/2600/Tia/Tia.ISoundProvider.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Atari.Atari2600 diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IDebuggable.cs index 30476662481..3977ad6a1c8 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs index 80e0ba0a9bf..1532f4e73f2 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.IEmulator.cs @@ -1,5 +1,5 @@ using BizHawk.Emulation.Common; -using System; + using System.Collections.Generic; namespace BizHawk.Emulation.Cores.Atari.A7800Hawk diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.ISaveRam.cs index 875dbcf8d3e..f8012db14d2 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.ISaveRam.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Atari.A7800Hawk diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.ISettable.cs index 79687402806..b9c06464ed3 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.ISettable.cs @@ -1,4 +1,3 @@ -using System; using Newtonsoft.Json; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs index 8657a836909..098e3a5bb8e 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800Hawk.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.M6502; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllerDeck.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllerDeck.cs index c1303b569e4..b37afc89743 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllerDeck.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/A7800HawkControllerDeck.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs index 5997032234e..ea18fd9a2ca 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/A7800Hawk/Maria.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common.NumberExtensions; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/JaguarDisassembler.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/JaguarDisassembler.cs index 73b68a44ea2..8fb15792fb5 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/JaguarDisassembler.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/JaguarDisassembler.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/LibVirtualJaguar.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/LibVirtualJaguar.cs index 300611393b7..6ba419c8e7d 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/LibVirtualJaguar.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/LibVirtualJaguar.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.BizInvoke; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.IDebuggable.cs index 3b80276e415..7cc02d3ea40 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common.StringExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.ISaveRam.cs index f4c5f7fc803..1f3ae2d321a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.ISaveRam.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Atari.Jaguar diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.ITraceable.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.ITraceable.cs index a713d025e5a..b0a38c91d54 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.ITraceable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.ITraceable.cs @@ -1,4 +1,3 @@ -using System; using System.Text; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.cs index 94830007ac1..735920f8148 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/jaguar/VirtualJaguar.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/LibLynx.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/LibLynx.cs index 6d401d205c5..f1ff28d1ea6 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/LibLynx.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/LibLynx.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.BizInvoke; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.IInputPollable.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.IInputPollable.cs index 7c081b73e40..6fc585e53e7 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.IInputPollable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.IInputPollable.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Atari.Lynx diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.IMemoryDomains.cs index 4a090fe8fb1..d306ac5da96 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.ISaveRam.cs index 3cbb9d79755..7cd0eb08744 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.ISaveRam.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.ISoundProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.ISoundProvider.cs index dcae3ea27fb..29038c9d1d7 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.ISoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.ISoundProvider.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Atari.Lynx diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.IStatable.cs index adfff454786..df0d12f4565 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.IStatable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.IStatable.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using Newtonsoft.Json; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs b/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs index efc725ef3dc..45b6e66baaf 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs @@ -1,6 +1,5 @@ -using System; -using System.Text; using System.IO; +using System.Text; using BizHawk.BizInvoke; using BizHawk.Common; @@ -9,7 +8,7 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx { - [PortedCore(CoreNames.Handy, "K. Wilkins, Mednafen Team", "mednafen 0-9-34-1", "http://mednafen.sourceforge.net/")] + [PortedCore(CoreNames.Handy, "K. Wilkins, Mednafen Team", "0.9.34.1", "https://mednafen.github.io/releases/")] [ServiceNotApplicable(new[] { typeof(IDriveLight), typeof(IRegionable), typeof(ISettable<,>) })] public partial class Lynx : IEmulator, IVideoProvider, ISoundProvider, ISaveRam, IStatable, IInputPollable { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Belogic/Uzem.cs b/src/BizHawk.Emulation.Cores/Consoles/Belogic/Uzem.cs index a5fa6049cff..9d2a72eb3b3 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Belogic/Uzem.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Belogic/Uzem.cs @@ -1,6 +1,5 @@ using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Waterbox; -using System; using BizHawk.Common; @@ -22,8 +21,8 @@ public Uzem(CoreComm comm, byte[] rom) MaxHeight = 224, MaxSamples = 4096, SystemId = VSystemID.Raw.UZE, - DefaultFpsNumerator = 28618182, - DefaultFpsDenominator = 476840 + DefaultFpsNumerator = 1125000, + DefaultFpsDenominator = 18733, }) { _uze = PreInit(new WaterboxOptions diff --git a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoControllerDeck.cs b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoControllerDeck.cs index 9a509d268bb..1603d6b956d 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoControllerDeck.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoControllerDeck.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoControllers.cs b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoControllers.cs index 76fe74d9e67..9547ee39c02 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoControllers.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoControllers.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Linq; @@ -96,7 +95,7 @@ public byte Read(IController c, bool leftMode, bool updateWheel, float wheelAngl if (c.IsPressed(Definition.BoolButtons[7])) retVal = 0x0D; if (c.IsPressed(Definition.BoolButtons[12])) retVal = 0x0E; - if (c.IsPressed(Definition.BoolButtons[5]) == false) retVal |= 0x40; + if (!c.IsPressed(Definition.BoolButtons[5])) retVal |= 0x40; retVal |= 0x30; // always set these bits return retVal; } @@ -300,7 +299,7 @@ public byte Read(IController c, bool left_mode, bool updateWheel, float wheelAng if (c.IsPressed(Definition.BoolButtons[18])) retVal = 0x04; if (c.IsPressed(Definition.BoolButtons[19])) retVal = 0x08; - if (c.IsPressed(Definition.BoolButtons[5]) == false) retVal |= 0x40; + if (!c.IsPressed(Definition.BoolButtons[5])) retVal |= 0x40; retVal |= 0x30; // always set these bits return retVal; } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IDebuggable.cs index 9913fad561a..af1d1f91244 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IEmulator.cs index a3e7d77ca80..1343c650cef 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IEmulator.cs @@ -1,6 +1,5 @@ using BizHawk.Emulation.Common; using BizHawk.Common.NumberExtensions; -using System; namespace BizHawk.Emulation.Cores.ColecoVision { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IInputPollable.cs b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IInputPollable.cs index bace4830d46..477288a2227 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IInputPollable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IInputPollable.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.ColecoVision diff --git a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IMemoryDomains.cs index 3ded4d582b5..38879ed1f78 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; @@ -29,15 +28,6 @@ private void SetupMemoryDomains() }, 1) }; - if (use_SGM) - { - var SGMLRam = new MemoryDomainByteArray("SGM Low RAM", MemoryDomain.Endian.Little, SGM_low_RAM, true, 1); - domains.Add(SGMLRam); - - var SGMHRam = new MemoryDomainByteArray("SGM High RAM", MemoryDomain.Endian.Little, SGM_high_RAM, true, 1); - domains.Add(SGMHRam); - } - SyncAllByteArrayDomains(); _memoryDomains = new MemoryDomainList(_byteArrayDomains.Values.Concat(domains).ToList()); @@ -50,6 +40,12 @@ private void SyncAllByteArrayDomains() { SyncByteArrayDomain("Main RAM", _ram); SyncByteArrayDomain("Video RAM", _vdp.VRAM); + + if (use_SGM) + { + SyncByteArrayDomain("SGM Low RAM", SGM_low_RAM); + SyncByteArrayDomain("SGM High RAM", SGM_high_RAM); + } } private void SyncByteArrayDomain(string name, byte[] data) diff --git a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.ISettable.cs index 83d7352afe6..8ea7707b973 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.ISettable.cs @@ -1,4 +1,3 @@ -using System; using Newtonsoft.Json; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.ISoundProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.ISoundProvider.cs index 9d906296a29..ba319c4e8f4 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.ISoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.ISoundProvider.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.ColecoVision diff --git a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.cs b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.cs index 232400c1783..17397c98a30 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.cs @@ -1,6 +1,5 @@ using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.Z80A; -using System; namespace BizHawk.Emulation.Cores.ColecoVision { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Coleco/TMS9918A.cs b/src/BizHawk.Emulation.Cores/Consoles/Coleco/TMS9918A.cs index b6c3b14e368..3c1bbe96e11 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Coleco/TMS9918A.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Coleco/TMS9918A.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.Z80A; @@ -169,7 +167,7 @@ public void RenderScanline(int scanLine) private void RenderBackgroundM0(int scanLine) { - if (DisplayOn == false) + if (!DisplayOn) { Array.Clear(FrameBuffer, scanLine * 256, 256); return; @@ -204,7 +202,7 @@ private void RenderBackgroundM0(int scanLine) private void RenderBackgroundM1(int scanLine) { - if (DisplayOn == false) + if (!DisplayOn) { Array.Clear(FrameBuffer, scanLine * 256, 256); return; @@ -237,7 +235,7 @@ private void RenderBackgroundM1(int scanLine) private void RenderBackgroundM2(int scanLine) { - if (DisplayOn == false) + if (!DisplayOn) { Array.Clear(FrameBuffer, scanLine * 256, 256); return; @@ -274,7 +272,7 @@ private void RenderBackgroundM2(int scanLine) private void RenderBackgroundM3(int scanLine) { - if (DisplayOn == false) + if (!DisplayOn) { Array.Clear(FrameBuffer, scanLine * 256, 256); return; @@ -312,19 +310,15 @@ private void RenderBackgroundM3(int scanLine) private void RenderTmsSprites(int scanLine) { - if (EnableDoubledSprites == false) - { - RenderTmsSpritesStandard(scanLine); - } - else - { + if (EnableDoubledSprites) RenderTmsSpritesDouble(scanLine); - } + else + RenderTmsSpritesStandard(scanLine); } private void RenderTmsSpritesStandard(int scanLine) { - if (DisplayOn == false) return; + if (!DisplayOn) return; Array.Clear(ScanlinePriorityBuffer, 0, 256); Array.Clear(SpriteCollisionBuffer, 0, 256); @@ -391,7 +385,7 @@ private void RenderTmsSpritesStandard(int scanLine) private void RenderTmsSpritesDouble(int scanLine) { - if (DisplayOn == false) return; + if (!DisplayOn) return; Array.Clear(ScanlinePriorityBuffer, 0, 256); Array.Clear(SpriteCollisionBuffer, 0, 256); @@ -517,4 +511,4 @@ public void SyncState(Serializer ser) } } } -} \ No newline at end of file +} diff --git a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Audio.cs b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Audio.cs index 39ec65e9aa2..be37035910a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Audio.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Audio.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Consoles.ChannelF diff --git a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IDebuggable.cs index 1e66f2539a8..0a0fc3044ba 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.MemoryDomains.cs b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.MemoryDomains.cs index f77585ee8e0..073da8f504f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.MemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/ChannelF.MemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Memory.cs b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Memory.cs index 2025dd96923..06976b966f4 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Memory.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/Memory.cs @@ -11,8 +11,6 @@ public partial class ChannelF /// /// Simulates reading a byte of data from the address space /// - /// - /// public byte ReadBus(ushort addr) { if (addr < 0x400) @@ -36,7 +34,6 @@ public byte ReadBus(ushort addr) /// Simulates writing a byte of data to the address space (in its default configuration, there is no writeable RAM in the /// Channel F addressable through the address space) /// - /// public void WriteBus(ushort addr, byte value) { Cartridge.WriteBus(addr, value); diff --git a/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/Audio.cs b/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/Audio.cs index 5eaf9b2e2ee..1fe2d2d0dd3 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/Audio.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/Audio.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Common.NumberExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/HW_Registers.cs b/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/HW_Registers.cs index 96b32e27452..aa3e16db4ae 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/HW_Registers.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/HW_Registers.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common.NumberExtensions; namespace BizHawk.Emulation.Cores.Consoles.Vectrex diff --git a/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/PPU.cs b/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/PPU.cs index 22dc6819e78..dd9c7d585bf 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/PPU.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/PPU.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Consoles.Vectrex diff --git a/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.ICodeDataLog.cs b/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.ICodeDataLog.cs index f8670541312..bda6962df44 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.ICodeDataLog.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.ICodeDataLog.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.IDebuggable.cs index f3a3b273021..28d8fcb055d 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.cs b/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.cs index 1142efd5258..13cfb717182 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawk.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.MC6809; diff --git a/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawkControllerDeck.cs b/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawkControllerDeck.cs index 71d05d1377f..b0cd2084de3 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawkControllerDeck.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/GCE/Vectrex/VectrexHawkControllerDeck.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs index 393c5af0aa3..3705a674a7f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Cartridge.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Controllers/IntellivisionControllerDeck.cs b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Controllers/IntellivisionControllerDeck.cs index 26b3cc892c3..84905f215dd 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Controllers/IntellivisionControllerDeck.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Controllers/IntellivisionControllerDeck.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Controllers/IntellivisionControllers.cs b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Controllers/IntellivisionControllers.cs index 376b35cdd8c..e3affe511f7 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Controllers/IntellivisionControllers.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Controllers/IntellivisionControllers.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellicart.cs b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellicart.cs index e2e4d7c7d0b..293d989874a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellicart.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellicart.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Intellivision diff --git a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.IDebuggable.cs index eb3b68a1d49..1f0de6044a6 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.IDisassemblable.cs b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.IDisassemblable.cs index df00bdc290c..412aa7e8637 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.IDisassemblable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.IDisassemblable.cs @@ -13,10 +13,7 @@ public string Cpu public string PCRegisterName => "PC"; - public IEnumerable AvailableCpus - { - get { yield return "CP1610"; } - } + public IEnumerable AvailableCpus { get; } = [ "CP1610" ]; public string Disassemble(MemoryDomain m, uint addr, out int length) { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.ISettable.cs index 999929b2f3a..ad9f177cfcc 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.ISettable.cs @@ -1,4 +1,3 @@ -using System; using Newtonsoft.Json; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.cs b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.cs index 4c9de475613..9a8fc2bd1dd 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/Intellivision.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.CP1610; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/PSG.cs b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/PSG.cs index 3f3c24bcf8e..b4caabf1419 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/PSG.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/PSG.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs index ec49aa5d55e..fb85dae2957 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Intellivision/STIC.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.ICodeDataLog.cs b/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.ICodeDataLog.cs index 0c9c80a9a92..601b635affc 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.ICodeDataLog.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.ICodeDataLog.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.I8048; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IDebuggable.cs index ab564bf940f..381054509c3 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.ISaveRam.cs index efa4a2cd83b..64e2c887094 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.ISaveRam.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Consoles.O2Hawk diff --git a/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.cs b/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.cs index ee389b83b3b..68d4388986e 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.I8048; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2HawkControllerDeck.cs b/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2HawkControllerDeck.cs index ac8dedf1cb5..d2203df6c31 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2HawkControllerDeck.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2HawkControllerDeck.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/PPU.cs b/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/PPU.cs index 13b4274582b..610c6a3c836 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/PPU.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/PPU.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/NEC/PCE/HyperNyma.cs b/src/BizHawk.Emulation.Cores/Consoles/NEC/PCE/HyperNyma.cs index db4e95d88c9..3ba961c73b9 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/NEC/PCE/HyperNyma.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/NEC/PCE/HyperNyma.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Runtime.InteropServices; @@ -10,7 +9,7 @@ namespace BizHawk.Emulation.Cores.Consoles.NEC.PCE { - [PortedCore(CoreNames.HyperNyma, "Mednafen Team", "1.29.0", "https://mednafen.github.io/releases/")] + [PortedCore(CoreNames.HyperNyma, "Mednafen Team", "1.32.1", "https://mednafen.github.io/releases/")] public class HyperNyma : NymaCore, IRegionable, IPceGpuView { private HyperNyma(CoreComm comm) diff --git a/src/BizHawk.Emulation.Cores/Consoles/NEC/PCE/TurboNyma.cs b/src/BizHawk.Emulation.Cores/Consoles/NEC/PCE/TurboNyma.cs index 60978421dda..ca7cb4b3fac 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/NEC/PCE/TurboNyma.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/NEC/PCE/TurboNyma.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; @@ -12,7 +11,7 @@ namespace BizHawk.Emulation.Cores.Consoles.NEC.PCE { - [PortedCore(CoreNames.TurboNyma, "Mednafen Team", "1.29.0", "https://mednafen.github.io/releases/")] + [PortedCore(CoreNames.TurboNyma, "Mednafen Team", "1.32.1", "https://mednafen.github.io/releases/")] public class TurboNyma : NymaCore, IRegionable, IPceGpuView { private TurboNyma(CoreComm comm) diff --git a/src/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/Tst.cs b/src/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/Tst.cs index 643bc2c91f0..8d72904ee4f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/Tst.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/NEC/PCFX/Tst.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; @@ -6,7 +5,7 @@ namespace BizHawk.Emulation.Cores.Consoles.NEC.PCFX { - [PortedCore(CoreNames.TST, "Mednafen Team", "1.29.0", "https://mednafen.github.io/releases/")] + [PortedCore(CoreNames.TST, "Mednafen Team", "1.32.1", "https://mednafen.github.io/releases/")] public class Tst : NymaCore { private Tst(CoreComm comm) diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/3DSMotionEmu.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/3DSMotionEmu.cs index a2001e34ec8..3dd4661aee9 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/3DSMotionEmu.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/3DSMotionEmu.cs @@ -1,4 +1,3 @@ -using System; using System.Numerics; namespace BizHawk.Emulation.Cores.Consoles.Nintendo.N3DS @@ -6,7 +5,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.N3DS public class _3DSMotionEmu { // update per frame - private const float UPDATE_PERIOD = (float)(4481136.0 / 268111856.0); + private const float UPDATE_PERIOD = (float)(268111856.0 / 4481136.0); // todo: make these adjustable private const float SENSITIVITY = 0.01f; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IInputPollable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IInputPollable.cs index 215e2f6d058..0d5de162b64 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IInputPollable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IInputPollable.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IMemoryDomains.cs index fa354149246..0665eb230c5 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.ISettable.cs index a4b9a5e0edf..63cbb9726ee 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.ISettable.cs @@ -1,7 +1,6 @@ using BizHawk.Common; using BizHawk.Emulation.Common; -using System; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.ISoundProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.ISoundProvider.cs index 92f6793ed53..ee830b4590a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.ISoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.ISoundProvider.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IStatable.cs index 42f0b580e2c..1c81a0f79e3 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IStatable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IStatable.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IVideoProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IVideoProvider.cs index 41a4e72e073..246b026d231 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IVideoProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.IVideoProvider.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Consoles.Nintendo.N3DS diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.cs index ac709d26b74..9d1d318f8cf 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.IO; @@ -11,8 +10,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.N3DS { - [PortedCore(CoreNames.Encore, "", "nightly-2104", "https://github.com/CasualPokePlayer/encore", singleInstance: true, isReleased: false)] - [ServiceNotApplicable(new[] { typeof(IDriveLight), typeof(IRegionable) })] + [PortedCore(CoreNames.Encore, "", "nightly-2104", "https://github.com/CasualPokePlayer/encore", singleInstance: true)] + [ServiceNotApplicable([ typeof(IDriveLight), typeof(IRegionable) ])] public partial class Encore { private static DynamicLibraryImportResolver _resolver; @@ -46,7 +45,7 @@ private static void ResetEncoreResolver() [CoreConstructor(VSystemID.Raw.N3DS)] public Encore(CoreLoadParameters lp) { - if (lp.Roms.Exists(r => r.RomPath.Contains("|"))) + if (lp.Roms.Exists(static r => HawkFile.PathContainsPipe(r.RomPath))) { throw new InvalidOperationException("3DS does not support compressed ROMs"); } @@ -169,7 +168,7 @@ public Encore(CoreLoadParameters lp) private IntPtr RequestGLContextCallback() { - var context = _openGLProvider.RequestGLContext(4, 3, true, false); + var context = _openGLProvider.RequestGLContext(4, 3, true); _glContexts.Add(context); var handle = GCHandle.Alloc(context, GCHandleType.Weak); return GCHandle.ToIntPtr(handle); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/LibEncore.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/LibEncore.cs index 0cc9e25e231..5f3f596fd93 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/LibEncore.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/LibEncore.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.BizInvoke; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/Ares64.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/Ares64.IDebuggable.cs index 028037eb2a0..6340f0cdf98 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/Ares64.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/Ares64.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/Ares64.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/Ares64.ISettable.cs index d12f60b73ef..82552b3d9a9 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/Ares64.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/Ares64.ISettable.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/Ares64.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/Ares64.cs index c4a280c8d03..ea00ece41e6 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/Ares64.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/Ares64.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Linq; @@ -9,7 +8,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Ares64 { - [PortedCore(CoreNames.Ares64, "ares team, Near", "v130.1", "https://ares-emu.net/")] + [PortedCore(CoreNames.Ares64, "ares team, Near", "v138", "https://ares-emu.net/")] [ServiceNotApplicable(new[] { typeof(IDriveLight), })] public partial class Ares64 : WaterboxCore, IRegionable { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/LibAres64.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/LibAres64.cs index 0d35a41ab91..88fb5945879 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/LibAres64.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Ares64/LibAres64.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.BizInvoke; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesApi.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesApi.cs index 9059d116310..a4e5a3fb5b3 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesApi.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesApi.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Collections.Generic; using System.Reflection; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesControllers.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesControllers.cs index c2b785b1781..6d0b6d2f059 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesControllers.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesControllers.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IDebuggable.cs index 07ae55aadcf..3f619577213 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IEmulator.cs index 02668bd7d03..fb6c1119731 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IEmulator.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IMemoryDomains.cs index 32c5a8cc04d..0e4804416c0 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.ISaveRam.cs index f2b391f4ffa..4e2a3010d2a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.ISaveRam.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.ISettable.cs index c82aac4d190..a35f43ff737 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.ISettable.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.BSNES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IVideoProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IVideoProvider.cs index 0aa0cb3b390..5fdf044ab1f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IVideoProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.IVideoProvider.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.BSNES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.cs index d7b35ed2a49..0109ea1adb8 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/BsnesCore.cs @@ -1,6 +1,6 @@ -using System; using System.IO; using System.Runtime.InteropServices; + using BizHawk.Common; using BizHawk.Common.PathExtensions; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/SNESGraphicsDecoder.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/SNESGraphicsDecoder.cs index a94cb2c68b6..f89217476db 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/SNESGraphicsDecoder.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/BSNES/SNESGraphicsDecoder.cs @@ -1,4 +1,3 @@ -using System; using System.Drawing; using BizHawk.Emulation.Cores.Nintendo.SNES; using static BizHawk.Emulation.Cores.Nintendo.BSNES.BsnesApi.SNES_REGISTER; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Faust/Faust.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Faust/Faust.cs index 1eb073a93cd..f80b6972fc7 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Faust/Faust.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Faust/Faust.cs @@ -1,10 +1,11 @@ using System.Collections.Generic; + using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Waterbox; namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Faust { - [PortedCore(CoreNames.Faust, "Mednafen Team", "1.29.0", "https://mednafen.github.io/releases/")] + [PortedCore(CoreNames.Faust, "Mednafen Team", "1.32.1", "https://mednafen.github.io/releases/")] public class Faust : NymaCore, IRegionable { private Faust(CoreComm comm) diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/IGBAGPUViewable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/IGBAGPUViewable.cs index ef79005a7b7..72b4b91eadc 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/IGBAGPUViewable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/IGBAGPUViewable.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.GBA diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibmGBA.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibmGBA.cs index a2165dbfbdb..d73abfb266b 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibmGBA.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibmGBA.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.BizInvoke; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IDebuggable.cs index f09a6eb44ca..7c4831d0936 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IEmulator.cs index ba3939546bb..b5bde2c7bca 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IEmulator.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IGBAGPUViewable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IGBAGPUViewable.cs index bc730afa1ac..6984ec572a6 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IGBAGPUViewable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IGBAGPUViewable.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Nintendo.GBA { public partial class MGBAHawk : IGBAGPUViewable diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IMemoryDomains.cs index 3c1dcdd0f59..15aa186163f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.ISaveRam.cs index bd9decc3153..04f8e6ffd45 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.ISaveRam.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.ISettable.cs index 9dd1f027da8..784cd3a9fdf 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.ISettable.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.ComponentModel.DataAnnotations; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.ISoundProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.ISoundProvider.cs index 2981dc7e086..f8b34c97994 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.ISoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.ISoundProvider.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.GBA diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IStatable.cs index 8257bdfe78e..87df176368f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IStatable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.IStatable.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs index 24f4d0c5311..1bc52740410 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.BizInvoke; using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAMemoryCallbackSystem.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAMemoryCallbackSystem.cs index 9e536250995..21e666ba570 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAMemoryCallbackSystem.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAMemoryCallbackSystem.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Audio.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Audio.cs index aef73aec305..75ca2c73a5f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Audio.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Audio.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Common.NumberExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_GB_PPU.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_GB_PPU.cs index 17f37b93166..7f3be74edbd 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_GB_PPU.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_GB_PPU.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common.NumberExtensions; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_PPU.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_PPU.cs index 78bec138e61..be5fff9a225 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_PPU.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBC_PPU.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common.NumberExtensions; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ICodeDataLog.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ICodeDataLog.cs index f55e94cd005..a037a14de5e 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ICodeDataLog.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ICodeDataLog.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.LR35902; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IDebuggable.cs index f3d71a4c0e1..d48ac942d72 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs index 15abfbafd1e..8938eb7479e 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs @@ -1,6 +1,5 @@ using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; -using System; namespace BizHawk.Emulation.Cores.Nintendo.GBHawk { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISaveRam.cs index d77ee0d3173..1d7bbdfb69d 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISaveRam.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.GBHawk diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISettable.cs index f272bc7dbf3..da9375d6f66 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISettable.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using Newtonsoft.Json; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs index b3c68f1da41..65fcac68548 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.LR35902; @@ -122,7 +120,7 @@ internal static class RomChecksums public LR35902 cpu; public PPU ppu; - public Timer timer; + public readonly GBTimer timer; public Audio audio; public SerialPort serialport; @@ -147,7 +145,7 @@ public GBHawk(CoreComm comm, GameInfo game, byte[] rom, /*string gameDbFn,*/ GBS SetIntRegs = SetIntRegs }; - timer = new Timer(); + timer = new(); audio = new Audio(); serialport = new SerialPort(); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawkControllerDeck.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawkControllerDeck.cs index 7353fb98970..0d16ba318d5 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawkControllerDeck.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawkControllerDeck.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawkControllers.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawkControllers.cs index cb11d4de95e..b995d0cfc3f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawkControllers.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawkControllers.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GB_PPU.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GB_PPU.cs index 9c7963f3e05..7e926959c9c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GB_PPU.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GB_PPU.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common.NumberExtensions; namespace BizHawk.Emulation.Cores.Nintendo.GBHawk diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/HW_Registers.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/HW_Registers.cs index 5308e1f411a..0fc0bd5d52c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/HW_Registers.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/HW_Registers.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common.NumberExtensions; namespace BizHawk.Emulation.Cores.Nintendo.GBHawk diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_Sachen_MMC1.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_Sachen_MMC1.cs index c25e688cacd..822a5f9c191 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_Sachen_MMC1.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_Sachen_MMC1.cs @@ -1,5 +1,4 @@ using BizHawk.Common; -using System; using BizHawk.Emulation.Cores.Components.LR35902; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_Sachen_MMC2.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_Sachen_MMC2.cs index f326dd172ae..51a67cb770c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_Sachen_MMC2.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_Sachen_MMC2.cs @@ -1,5 +1,4 @@ using BizHawk.Common; -using System; using BizHawk.Emulation.Cores.Components.LR35902; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/MemoryMap.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/MemoryMap.cs index 95adf2bb57b..bcde748da1e 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/MemoryMap.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/MemoryMap.cs @@ -1,5 +1,4 @@ using BizHawk.Emulation.Common; -using System; /* $FFFF Interrupt Enable Flag diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Timer.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Timer.cs index 34316d72438..e1b3136d971 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Timer.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Timer.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; using BizHawk.Common.NumberExtensions; @@ -18,7 +17,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk // there is a coincident timer increment, there will be an additional increment along with this write. // not sure it effects all models or of exact details, see test tac_set_timer_disabled.gbc - public class Timer + public sealed class GBTimer { public GBHawk Core { get; set; } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.ICodeDataLog.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.ICodeDataLog.cs index 9151badcbc9..3fd8cad8fe4 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.ICodeDataLog.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.ICodeDataLog.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.IDebuggable.cs index ca6e0bd755e..9760100ea38 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common.StringExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.IEmulator.cs index 46f2e497931..10de459fd80 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.IEmulator.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.ISaveRam.cs index a671dd8f34e..e10568c5797 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.ISaveRam.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.ISettable.cs index 394316e1eee..3f87bf2e5cc 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.ISettable.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using Newtonsoft.Json; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.cs index 825b2ea42eb..18424d48ae1 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLink.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy; using BizHawk.Emulation.Cores.Nintendo.GBHawk; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLinkControllerDeck.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLinkControllerDeck.cs index 74a3f497bc2..586e15bb78c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLinkControllerDeck.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink/GBHawkLinkControllerDeck.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.ICodeDataLog.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.ICodeDataLog.cs index 6f9bdd900bc..1385166db92 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.ICodeDataLog.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.ICodeDataLog.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.IDebuggable.cs index acb4770f21f..44cf269178a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common.StringExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.IEmulator.cs index d77e1e9e201..4290ee7a712 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.IEmulator.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink3x diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.ISaveRam.cs index 6820452edb5..841fb59c551 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.ISaveRam.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink3x diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.ISettable.cs index 92afbc6032f..2505b2354c1 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.ISettable.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using Newtonsoft.Json; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.cs index b3ac4a216b4..7893995d4c9 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3x.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy; using BizHawk.Emulation.Cores.Nintendo.GBHawk; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3xControllerDeck.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3xControllerDeck.cs index 65b6399ecc3..bf75deb2afc 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3xControllerDeck.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink3x/GBHawkLink3xControllerDeck.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ICodeDataLog.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ICodeDataLog.cs index d7698af937e..5ad7fd37735 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ICodeDataLog.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ICodeDataLog.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IDebuggable.cs index 79e6aa23c19..aa0d4c291e3 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common.StringExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IEmulator.cs index 335dbe81cfa..e1d72e184a6 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IEmulator.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ISaveRam.cs index 3568c636526..3c3195cf244 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ISaveRam.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ISettable.cs index 339f9195e16..b89cd3c0cb8 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.ISettable.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using Newtonsoft.Json; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.cs index cc33f7f5769..1201a5382bf 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy; using BizHawk.Emulation.Cores.Nintendo.GBHawk; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4xControllerDeck.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4xControllerDeck.cs index d0f4aa29a48..bf46368c95f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4xControllerDeck.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4xControllerDeck.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GBColors.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GBColors.cs index 49d86db34dd..6812bbac556 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GBColors.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GBColors.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Nintendo.Gameboy { public static class GBColors diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ICodeDataLog.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ICodeDataLog.cs index a8c4fb93c90..d5dbff8b624 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ICodeDataLog.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ICodeDataLog.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IDebuggable.cs index c3a7c6f8fbb..adae5f4dd05 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IEmulator.cs index 1a266ef0580..f6b1ed33483 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IEmulator.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IMemoryDomains.cs index 9abd38e17cb..05e8d97005a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISaveRam.cs index 6dffe7b6d72..476e388e0c3 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISaveRam.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.Gameboy diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISoundProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISoundProvider.cs index 9286c623ab5..aa4edc1b1c7 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISoundProvider.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.Gameboy diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IStatable.cs index 42eb99b0e9f..3350697e027 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IStatable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IStatable.cs @@ -1,6 +1,5 @@ //#define USE_UPSTREAM_STATES // really more for testing due to needing to use these anyways for initial state code. could potentially be used outright for states -using System; using System.IO; using Newtonsoft.Json; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ITraceable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ITraceable.cs index fa4c34a9393..2661488eddd 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ITraceable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ITraceable.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs index 4fd8d8a93c6..2c841e8c224 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -13,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy /// /// a gameboy/gameboy color emulator wrapped around native C++ libgambatte /// - [PortedCore(CoreNames.Gambatte, "", "Gambatte-Speedrun r717+", "https://github.com/pokemon-speedrunning/gambatte-speedrun")] + [PortedCore(CoreNames.Gambatte, "sinamas/PSR org", "r830", "https://github.com/pokemon-speedrunning/gambatte-core")] [ServiceNotApplicable(new[] { typeof(IDriveLight) })] public partial class Gameboy : IInputPollable, IRomInfo, IGameboyCommon, ICycleTiming, ILinkable { @@ -195,15 +194,15 @@ bool ForceBios() InitMemoryDomains(); - var mbcBuf = new byte[32]; + var mbcBuf = new byte[32 + 1]; LibGambatte.gambatte_pakinfo(GambatteState, mbcBuf, out var rambanks, out var rombanks, out var crc, out var headerchecksumok); - var romNameBuf = new byte[32]; + var romNameBuf = new byte[16 + 1]; LibGambatte.gambatte_romtitle(GambatteState, romNameBuf); - var romname = Encoding.ASCII.GetString(romNameBuf).TrimEnd(); + var romname = Encoding.ASCII.GetString(romNameBuf).TrimEnd('\0'); RomDetails = $"{game.Name}\r\n{SHA1Checksum.ComputePrefixedHex(file)}\r\n{MD5Checksum.ComputePrefixedHex(file)}\r\n\r\n"; - BoardName = Encoding.ASCII.GetString(mbcBuf).TrimEnd(); + BoardName = Encoding.ASCII.GetString(mbcBuf).TrimEnd('\0'); RomDetails += $"Core reported Header Name: {romname}\r\n"; RomDetails += $"Core reported RAM Banks: {rambanks}\r\n"; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.ICodeDataLog.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.ICodeDataLog.cs index 60972c86de2..d4427aab281 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.ICodeDataLog.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.ICodeDataLog.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IEmulator.cs index 861bd1d5364..97e3a1fd721 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IEmulator.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.Gameboy diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.ISettable.cs index 3fbd3ada1d1..74f60eb5f5a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.ISettable.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.Gameboy diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.ISoundProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.ISoundProvider.cs index 7e9ca7b22d0..d08710f0715 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.ISoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.ISoundProvider.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.Gameboy diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IStatable.cs index 437370815d1..3817e78acac 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IStatable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.IStatable.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using Newtonsoft.Json; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs index cf5d337b9bd..e66dc3b3c89 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using BizHawk.Common.CollectionExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambattePrinter.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambattePrinter.cs index fa44cb05337..948f2ed888f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambattePrinter.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambattePrinter.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy; namespace BizHawk.Emulation.Cores.Nintendo.Gameboy diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/IGameboyCommon.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/IGameboyCommon.cs index beee0640790..66aa8ae45a8 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/IGameboyCommon.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/IGameboyCommon.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy @@ -33,7 +31,6 @@ public interface IGameboyCommon : ISpecializedEmulatorService /// Acquire GPU memory for inspection. The returned object must be disposed as soon as the frontend /// tool is done inspecting it, and the pointers become invalid once it is disposed. /// - /// IGPUMemoryAreas LockGPU(); /// diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs index d9777446a4d..58f42decdfb 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.Emulation.Common; @@ -411,7 +410,7 @@ public enum Buttons: uint /// Pakinfo of currently loaded ROM image. /// /// opaque state pointer - /// enough room for 25 ascii chars plus terminator + /// enough room for 32 ascii chars plus terminator /// number of rambanks /// number of rombanks /// core reported crc32 diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IDebuggable.cs index 3658e6a7cb8..e3b26a7419a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IDisassemblable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IDisassemblable.cs index 3e1a4a6ae84..232cde0f5ba 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IDisassemblable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IDisassemblable.cs @@ -13,13 +13,7 @@ public string Cpu set { } } - public IEnumerable AvailableCpus - { - get - { - yield return "R4300"; - } - } + public IEnumerable AvailableCpus { get; } = [ "R4300" ]; public string PCRegisterName => "PC"; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IMemoryDomains.cs index 299ff862e64..23981348be2 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IStatable.cs index 2f57f588624..3e127f3ab6c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IStatable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.IStatable.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.cs index 0f3093fdedf..db5a6dc4f2b 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64.cs @@ -1,4 +1,3 @@ -using System; using System.Threading; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64Audio.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64Audio.cs index b9e4069887c..58395a637da 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64Audio.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64Audio.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Nintendo.N64.NativeApi; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64VideoProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64VideoProvider.cs index 1dfb4aea56a..7f8ec8793c8 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64VideoProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64VideoProvider.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Nintendo.N64.NativeApi; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusAudioApi.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusAudioApi.cs index bd020930574..f56faace1df 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusAudioApi.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusAudioApi.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusCoreApi.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusCoreApi.cs index b2fe0876bbf..d08c062bc55 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusCoreApi.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusCoreApi.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Reflection; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusInputApi.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusInputApi.cs index 259220cc705..782608d63d9 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusInputApi.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusInputApi.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusVideoApi.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusVideoApi.cs index 3f6d073d852..06883dae086 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusVideoApi.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusVideoApi.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Runtime.InteropServices; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/LibMelonDS.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/LibMelonDS.cs index 0a813055fd7..0f8d76e0c5c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/LibMelonDS.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/LibMelonDS.cs @@ -1,5 +1,3 @@ -using System; -using System.Linq; using System.Runtime.InteropServices; using BizHawk.BizInvoke; @@ -27,145 +25,89 @@ public enum Buttons : uint TOUCH = 0x1000, LIDOPEN = 0x2000, LIDCLOSE = 0x4000, - POWER = 0x8000, } [StructLayout(LayoutKind.Sequential)] public new class FrameInfo : LibWaterboxCore.FrameInfo { + public IntPtr Console; public Buttons Keys; public byte TouchX; public byte TouchY; public byte MicVolume; public byte GBALightSensor; - public bool ConsiderAltLag; + public byte ConsiderAltLag; } [StructLayout(LayoutKind.Sequential)] - public struct RenderSettings + public struct ConsoleCreationArgs { - public bool SoftThreaded; - public int GLScaleFactor; - public bool GLBetterPolygons; - } - - [StructLayout(LayoutKind.Sequential)] - public struct NDSTime - { - public int Year; - public int Month; - public int Day; - public int Hour; - public int Minute; - public int Second; - } - - [StructLayout(LayoutKind.Sequential)] - public unsafe struct FirmwareSettings - { - public bool OverrideSettings; - public int UsernameLength; - public fixed char Username[10]; - public NDS.NDSSyncSettings.Language Language; - public NDS.NDSSyncSettings.Month BirthdayMonth; - public int BirthdayDay; - public NDS.NDSSyncSettings.Color Color; - public int MessageLength; - public fixed char Message[26]; - } - - [StructLayout(LayoutKind.Sequential)] - public struct InitConfig - { - public bool SkipFW; - public bool HasGBACart; - public bool DSi; - public bool ClearNAND; - public bool LoadDSiWare; - public bool IsWinApi; - public NDS.NDSSyncSettings.ThreeDeeRendererType ThreeDeeRenderer; - public RenderSettings RenderSettings; - public NDSTime StartTime; - public FirmwareSettings FirmwareSettings; - } - - public enum ConfigEntry - { - // JIT_ENABLED define would add 5 entries here - // it is currently not (and unlikely ever to be) defined + public IntPtr NdsRomData; + public int NdsRomLength; - ExternalBIOSEnable, + public IntPtr GbaRomData; + public int GbaRomLength; - DLDI_Enable, - DLDI_ImagePath, - DLDI_ImageSize, - DLDI_ReadOnly, - DLDI_FolderSync, - DLDI_FolderPath, + public IntPtr Arm9BiosData; + public int Arm9BiosLength; - DSiSD_Enable, - DSiSD_ImagePath, - DSiSD_ImageSize, - DSiSD_ReadOnly, - DSiSD_FolderSync, - DSiSD_FolderPath, + public IntPtr Arm7BiosData; + public int Arm7BiosLength; - Firm_MAC, + public IntPtr FirmwareData; + public int FirmwareLength; - WifiSettingsPath, + public IntPtr Arm9iBiosData; + public int Arm9iBiosLength; - AudioBitDepth, + public IntPtr Arm7iBiosData; + public int Arm7iBiosLength; - DSi_FullBIOSBoot, + public IntPtr NandData; + public int NandLength; - // GDBSTUB_ENABLED define would add 5 entries here - // it will not be defined for our purposes - } + public IntPtr DsiWareData; + public int DsiWareLength; - [UnmanagedFunctionPointer(CC)] - public delegate bool GetBooleanSettingCallback(ConfigEntry configEntry); + public IntPtr TmdData; + public int TmdLength; - [UnmanagedFunctionPointer(CC)] - public delegate int GetIntegerSettingCallback(ConfigEntry configEntry); - - [UnmanagedFunctionPointer(CC)] - public delegate void GetStringSettingCallback(ConfigEntry configEntry, IntPtr buffer, int bufferSize); + public bool DSi; + public bool ClearNAND; + public bool SkipFW; - [UnmanagedFunctionPointer(CC)] - public delegate void GetArraySettingCallback(ConfigEntry configEntry, IntPtr buffer); + public NDS.NDSSettings.AudioBitDepthType BitDepth; + public NDS.NDSSettings.AudioInterpolationType Interpolation; - [StructLayout(LayoutKind.Sequential)] - public struct ConfigCallbackInterface - { - public GetBooleanSettingCallback GetBoolean; - public GetIntegerSettingCallback GetInteger; - public GetStringSettingCallback GetString; - public GetArraySettingCallback GetArray; - - public IntPtr[] AllCallbacksInArray(ICallingConventionAdapter adapter) - { - return new Delegate[] { GetBoolean, GetInteger, GetString, GetArray } - .Select(adapter.GetFunctionPointerForDelegate).ToArray(); - } + public NDS.NDSSyncSettings.ThreeDeeRendererType ThreeDeeRenderer; + public bool Threaded3D; + public int ScaleFactor; + public bool BetterPolygons; + public bool HiResCoordinates; + + public int StartYear; + public int StartMonth; + public int StartDay; + public int StartHour; + public int StartMinute; + public int StartSecond; + + public FirmwareSettings FwSettings; } - [UnmanagedFunctionPointer(CC)] - public delegate int GetFileLengthCallback(string path); - - [UnmanagedFunctionPointer(CC)] - public delegate void GetFileDataCallback(string path, IntPtr buffer); - [StructLayout(LayoutKind.Sequential)] - public struct FileCallbackInterface + public unsafe struct FirmwareSettings { - public GetFileLengthCallback GetLength; - public GetFileDataCallback GetData; - - public IntPtr[] AllCallbacksInArray(ICallingConventionAdapter adapter) - { - return new Delegate[] { GetLength, GetData } - .Select(adapter.GetFunctionPointerForDelegate).ToArray(); - } + public bool OverrideSettings; + public int UsernameLength; + public fixed char Username[10]; + public NDS.NDSSyncSettings.Language Language; + public NDS.NDSSyncSettings.Month BirthdayMonth; + public int BirthdayDay; + public NDS.NDSSyncSettings.Color Color; + public int MessageLength; + public fixed char Message[26]; + public fixed byte MacAddress[6]; } [UnmanagedFunctionPointer(CC)] @@ -183,42 +125,47 @@ public enum LogLevel : int public delegate void LogCallback(LogLevel level, string message); [BizImport(CC)] - public abstract IntPtr Init( - ref InitConfig loadData, - IntPtr[] configCallbackInterface, /* ref ConfigCallbackInterface */ - IntPtr[] fileCallbackInterface, /* ref FileCallbackInterface */ - LogCallback logCallback, - GetGLProcAddressCallback getGLProcAddressCallback); + public abstract void SetLogCallback(LogCallback logCallback); [BizImport(CC)] - public abstract void PutSaveRam(byte[] data, uint len); + public abstract IntPtr InitGL(GetGLProcAddressCallback getGLProcAddressCallback, + NDS.NDSSyncSettings.ThreeDeeRendererType threeDeeRenderer, int scaleFactor, bool isWinApi); [BizImport(CC)] - public abstract void GetSaveRam(byte[] data); + public abstract IntPtr CreateConsole(ref ConsoleCreationArgs args, byte[] error); [BizImport(CC)] - public abstract int GetSaveRamLength(); + public abstract void ResetConsole(IntPtr console, bool skipFw, ulong dsiTitleId); + + [BizImport(CC)] + public abstract void PutSaveRam(IntPtr console, byte[] data, uint len); + + [BizImport(CC)] + public abstract void GetSaveRam(IntPtr console, byte[] data); + + [BizImport(CC)] + public abstract int GetSaveRamLength(IntPtr console); [BizImport(CC)] public abstract bool SaveRamIsDirty(); [BizImport(CC)] - public abstract void ImportDSiWareSavs(uint titleId, byte[] data); + public abstract void ImportDSiWareSavs(IntPtr console, uint titleId); [BizImport(CC)] - public abstract void ExportDSiWareSavs(uint titleId, byte[] data); + public abstract void ExportDSiWareSavs(IntPtr console, uint titleId); [BizImport(CC)] - public abstract void DSiWareSavsLength(uint titleId, out int publicSavSize, out int privateSavSize, out int bannerSavSize); + public abstract void DSiWareSavsLength(IntPtr console, uint titleId, out int publicSavSize, out int privateSavSize, out int bannerSavSize); [BizImport(CC)] - public abstract void GetRegs(uint[] regs); + public abstract void GetRegs(IntPtr console, uint[] regs); [BizImport(CC)] - public abstract void SetReg(int ncpu, int index, int val); + public abstract void SetReg(IntPtr console, int ncpu, int index, int val); [BizImport(CC)] - public abstract int GetCallbackCycleOffset(); + public abstract int GetCallbackCycleOffset(IntPtr console); [UnmanagedFunctionPointer(CC)] public delegate void MemoryCallback(uint addr); @@ -255,10 +202,10 @@ public enum TraceMask : uint public abstract void SetThreadStartCallback(ThreadStartCallback callback); [BizImport(CC)] - public abstract int GetNANDSize(); + public abstract int GetNANDSize(IntPtr console); [BizImport(CC)] - public abstract void GetNANDData(byte[] buf); + public abstract void GetNANDData(IntPtr console, byte[] buf); [BizImport(CC)] public abstract int GetGLTexture(); @@ -271,8 +218,7 @@ public enum ScreenLayout : int Natural, Vertical, Horizontal, - // TODO? do we want this? - // Hybrid, + Hybrid, } public enum ScreenRotation : int @@ -301,7 +247,10 @@ public struct ScreenSettings } [BizImport(CC)] - public abstract void SetScreenSettings(ref ScreenSettings screenSettings, out int width, out int height, out int vwidth, out int vheight); + public abstract void SetScreenSettings(IntPtr console, ref ScreenSettings screenSettings, out int width, out int height, out int vwidth, out int vheight); + + [BizImport(CC)] + public abstract void SetSoundConfig(IntPtr console, NDS.NDSSettings.AudioBitDepthType bitDepth, NDS.NDSSettings.AudioInterpolationType interpolation); [BizImport(CC)] public abstract void GetTouchCoords(ref int x, ref int y); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.IDebuggable.cs index 141b5640be4..ff58227834b 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; @@ -10,7 +9,7 @@ public partial class NDS : IDebuggable public IDictionary GetCpuFlagsAndRegisters() { var regs = new uint[2 * 16]; - _core.GetRegs(regs); + _core.GetRegs(_console, regs); var ret = new Dictionary(); for (var i = 0; i < 2; i++) @@ -40,7 +39,7 @@ public void SetCpuRegister(string register, int value) { throw new InvalidOperationException("Invalid Reg Index???"); } - _core.SetReg(ncpu == 9 ? 0 : 1, index, value); + _core.SetReg(_console, ncpu == 9 ? 0 : 1, index, value); } public bool CanStep(StepType type) => false; @@ -48,11 +47,12 @@ public void SetCpuRegister(string register, int value) [FeatureNotImplemented] public void Step(StepType type) => throw new NotImplementedException(); - public long TotalExecutedCycles => CycleCount + _core.GetCallbackCycleOffset(); + public long TotalExecutedCycles => CycleCount + _core.GetCallbackCycleOffset(_console); public IMemoryCallbackSystem MemoryCallbacks => _memoryCallbacks; - private readonly MemoryCallbackSystem _memoryCallbacks = new(new[] { "System Bus" }); + // FIXME: internally the code actually just does this for either bus (probably don't want to bother adding support) + private readonly MemoryCallbackSystem _memoryCallbacks = new([ "ARM9 System Bus" ]); private LibMelonDS.MemoryCallback _readCallback; private LibMelonDS.MemoryCallback _writeCallback; @@ -67,7 +67,7 @@ LibMelonDS.MemoryCallback CreateCallback(MemoryCallbackFlags flags, Func g { if (getHasCBOfType()) { - MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, "System Bus"); + MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, "ARM9 System Bus"); } }; } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.IGLTextureProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.IGLTextureProvider.cs index 7efa2d4ad93..f93f6dc12e7 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.IGLTextureProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.IGLTextureProvider.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.ISaveRam.cs index f1f472a9c17..45b5d82d756 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.ISaveRam.cs @@ -4,9 +4,10 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS { public partial class NDS : ISaveRam { + private readonly int PublicSavSize, PrivateSavSize, BannerSavSize; private readonly int DSiWareSaveLength; - public new bool SaveRamModified => IsDSiWare || _core.SaveRamIsDirty(); + public new bool SaveRamModified => IsDSiWare ? DSiWareSaveLength != 0 : _core.SaveRamIsDirty(); public new byte[] CloneSaveRam() { @@ -17,17 +18,32 @@ public partial class NDS : ISaveRam return null; } + _exe.AddTransientFile([ ], "public.sav"); + _exe.AddTransientFile([ ], "private.sav"); + _exe.AddTransientFile([ ], "banner.sav"); + _core.ExportDSiWareSavs(_console, DSiTitleId.Lower); + + var publicSav = _exe.RemoveTransientFile("public.sav"); + var privateSav = _exe.RemoveTransientFile("private.sav"); + var bannerSav = _exe.RemoveTransientFile("banner.sav"); + if (publicSav.Length != PublicSavSize || privateSav.Length != PrivateSavSize || bannerSav.Length != BannerSavSize) + { + throw new InvalidOperationException("Unexpected size difference in DSiWare sav files!"); + } + var ret = new byte[DSiWareSaveLength]; - _core.ExportDSiWareSavs(DSiTitleId.Lower, ret); + publicSav.AsSpan().CopyTo(ret.AsSpan().Slice(0, PublicSavSize)); + privateSav.AsSpan().CopyTo(ret.AsSpan().Slice(PublicSavSize, PrivateSavSize)); + bannerSav.AsSpan().CopyTo(ret.AsSpan().Slice(PublicSavSize + PrivateSavSize, BannerSavSize)); return ret; } - var length = _core.GetSaveRamLength(); + var length = _core.GetSaveRamLength(_console); if (length > 0) { var ret = new byte[length]; - _core.GetSaveRam(ret); + _core.GetSaveRam(_console, ret); return ret; } @@ -40,12 +56,20 @@ public partial class NDS : ISaveRam { if (data.Length == DSiWareSaveLength) { - _core.ImportDSiWareSavs(DSiTitleId.Lower, data); + if (PublicSavSize > 0) _exe.AddReadonlyFile(data.AsSpan().Slice(0, PublicSavSize).ToArray(), "public.sav"); + if (PrivateSavSize > 0) _exe.AddReadonlyFile(data.AsSpan().Slice(PublicSavSize, PrivateSavSize).ToArray(), "private.sav"); + if (BannerSavSize > 0) _exe.AddReadonlyFile(data.AsSpan().Slice(PublicSavSize + PrivateSavSize, BannerSavSize).ToArray(), "banner.sav"); + + _core.ImportDSiWareSavs(_console, DSiTitleId.Lower); + + if (PublicSavSize > 0) _exe.RemoveReadonlyFile("public.sav"); + if (PrivateSavSize > 0) _exe.RemoveReadonlyFile("private.sav"); + if (BannerSavSize > 0) _exe.RemoveReadonlyFile("banner.sav"); } } else if (data.Length > 0) { - _core.PutSaveRam(data, (uint)data.Length); + _core.PutSaveRam(_console, data, (uint)data.Length); } } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.ISettable.cs index 6770a52b218..b0a22006f4c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.ISettable.cs @@ -1,8 +1,5 @@ -using System; using System.ComponentModel; using System.ComponentModel.DataAnnotations; -using System.Runtime.InteropServices; -using System.Text; using Newtonsoft.Json; @@ -19,75 +16,13 @@ public partial class NDS : ISettable private NDSSyncSettings _syncSettings; private readonly NDSSyncSettings _activeSyncSettings; - private readonly LibMelonDS.ConfigCallbackInterface _configCallbackInterface; - - private bool GetBooleanSettingCallback(LibMelonDS.ConfigEntry configEntry) => configEntry switch - { - LibMelonDS.ConfigEntry.ExternalBIOSEnable => _activeSyncSettings.UseRealBIOS, - LibMelonDS.ConfigEntry.DLDI_Enable => false, // TODO - LibMelonDS.ConfigEntry.DLDI_ReadOnly => false, // TODO - LibMelonDS.ConfigEntry.DLDI_FolderSync => false, // TODO - LibMelonDS.ConfigEntry.DSiSD_Enable => false, // TODO - LibMelonDS.ConfigEntry.DSiSD_ReadOnly => false, // TODO - LibMelonDS.ConfigEntry.DSiSD_FolderSync => false, // TODO - LibMelonDS.ConfigEntry.DSi_FullBIOSBoot => false, // TODO - _ => throw new InvalidOperationException() - }; - - private int GetIntegerSettingCallback(LibMelonDS.ConfigEntry configEntry) => configEntry switch - { - LibMelonDS.ConfigEntry.DLDI_ImageSize => 0, // TODO - LibMelonDS.ConfigEntry.DSiSD_ImageSize => 0, // TODO - LibMelonDS.ConfigEntry.AudioBitDepth => (int)_settings.AudioBitDepth, - _ => throw new InvalidOperationException() - }; - - private static void GetStringSettingCallback(LibMelonDS.ConfigEntry configEntry, IntPtr buffer, int bufferSize) - { - // none of these are actually implemented yet - var ret = configEntry switch - { - LibMelonDS.ConfigEntry.DLDI_ImagePath => "dldi.bin", - LibMelonDS.ConfigEntry.DLDI_FolderPath => "dldi", - LibMelonDS.ConfigEntry.DSiSD_ImagePath => "sd.bin", - LibMelonDS.ConfigEntry.DSiSD_FolderPath => "sd", - LibMelonDS.ConfigEntry.WifiSettingsPath => "wfcsettings.bin", - _ => throw new InvalidOperationException() - }; - - if (string.IsNullOrEmpty(ret)) - { - Marshal.WriteByte(buffer, 0, 0); - return; - } - - var bytes = Encoding.UTF8.GetBytes(ret); - var numToCopy = Math.Min(bytes.Length, bufferSize - 1); - Marshal.Copy(bytes, 0, buffer, numToCopy); - Marshal.WriteByte(buffer, numToCopy, 0); - } - - private static void GetArraySettingCallback(LibMelonDS.ConfigEntry configEntry, IntPtr buffer) - { - if (configEntry != LibMelonDS.ConfigEntry.Firm_MAC) - { - throw new InvalidOperationException(); - } - - // TODO make MAC configurable - Marshal.WriteByte(buffer, 0, 0x00); - Marshal.WriteByte(buffer, 1, 0x09); - Marshal.WriteByte(buffer, 2, 0xBF); - Marshal.WriteByte(buffer, 3, 0x0E); - Marshal.WriteByte(buffer, 4, 0x49); - Marshal.WriteByte(buffer, 5, 0x16); - } public enum ScreenLayoutKind { Natural, Vertical, Horizontal, + Hybrid, [Display(Name = "Top Only")] Top, [Display(Name = "Bottom Only")] @@ -153,6 +88,22 @@ public enum AudioBitDepthType : int [TypeConverter(typeof(DescribableEnumConverter))] public AudioBitDepthType AudioBitDepth { get; set; } + public enum AudioInterpolationType : int + { + None, + Linear, + Cosine, + Cubic, + [Display(Name = "Gaussian (SNES)")] + SNESGaussian, + } + + [DisplayName("Audio Interpolation")] + [Description("Audio enhancement (original hardware has no audio interpolation).")] + [DefaultValue(AudioInterpolationType.None)] + [TypeConverter(typeof(DescribableEnumConverter))] + public AudioInterpolationType AudioInterpolation { get; set; } + [DisplayName("Alt Lag")] [Description("If true, touch screen polling and ARM7 key polling will be considered for lag frames. Otherwise, only ARM9 key polling will be considered.")] [DefaultValue(false)] @@ -219,13 +170,12 @@ public enum ThreeDeeRendererType : int Software, [Display(Name = "OpenGL Classic")] OpenGL_Classic, - // [Display(Name = "OpenGL Compute")] - //OpenGL_Compute, + [Display(Name = "OpenGL Compute")] + OpenGL_Compute, } [DisplayName("3D Renderer")] - // [Description("Renderer used for 3D. OpenGL Classic requires at least OpenGL 3.2, OpenGL Compute requires at least OpenGL 4.3. Forced to Software when recording a movie.")] - [Description("Renderer used for 3D. OpenGL Classic requires at least OpenGL 3.2. Forced to Software when recording a movie.")] + [Description("Renderer used for 3D. OpenGL Classic requires at least OpenGL 3.2, OpenGL Compute requires at least OpenGL 4.3. Forced to Software when recording a movie.")] [DefaultValue(ThreeDeeRendererType.Software)] [TypeConverter(typeof(DescribableEnumConverter))] public ThreeDeeRendererType ThreeDeeRenderer { get; set; } @@ -248,10 +198,15 @@ public int GLScaleFactor } [DisplayName("OpenGL Better Polygons")] - [Description("Enhances polygon quality with OpenGL. Not used for the software renderer.")] + [Description("Enhances polygon quality with OpenGL Classic. Not used for the software nor OpenGL Compute renderer.")] [DefaultValue(false)] public bool GLBetterPolygons { get; set; } + [DisplayName("OpenGL Hi Res Coordinates")] + [Description("Uses high resolution coordinates with OpenGL Compute. Not used for the software nor OpenGL Classic renderer.")] + [DefaultValue(false)] + public bool GLHiResCoordinates { get; set; } + [JsonIgnore] private DateTime _initaltime; @@ -462,6 +417,14 @@ public unsafe void GetFirmwareSettings(out LibMelonDS.FirmwareSettings fwSetting .Slice(0, fwSettings.MessageLength) .CopyTo(message); } + + // TODO make MAC configurable + fwSettings.MacAddress[0] = 0x00; + fwSettings.MacAddress[1] = 0x09; + fwSettings.MacAddress[2] = 0xBF; + fwSettings.MacAddress[3] = 0x0E; + fwSettings.MacAddress[4] = 0x49; + fwSettings.MacAddress[5] = 0x16; } public NDSSyncSettings Clone() @@ -489,6 +452,7 @@ private void RefreshScreenSettings(NDSSettings settings) ScreenLayoutKind.Natural => LibMelonDS.ScreenLayout.Natural, ScreenLayoutKind.Vertical => LibMelonDS.ScreenLayout.Vertical, ScreenLayoutKind.Horizontal => LibMelonDS.ScreenLayout.Horizontal, + ScreenLayoutKind.Hybrid => LibMelonDS.ScreenLayout.Hybrid, _ => LibMelonDS.ScreenLayout.Natural, }, ScreenRotation = settings.ScreenRotation switch @@ -510,7 +474,7 @@ private void RefreshScreenSettings(NDSSettings settings) }; _openGLProvider.ActivateGLContext(_glContext); // SetScreenSettings will re-present the frame, so needs OpenGL context active - _core.SetScreenSettings(ref screenSettings, out var w , out var h, out var vw, out var vh); + _core.SetScreenSettings(_console, ref screenSettings, out var w , out var h, out var vw, out var vh); BufferWidth = w; BufferHeight = h; @@ -530,6 +494,8 @@ public PutSettingsDirtyBits PutSettings(NDSSettings o) RefreshScreenSettings(o); } + _core.SetSoundConfig(_console, o.AudioBitDepth, o.AudioInterpolation); + _settings = o; return ret ? PutSettingsDirtyBits.ScreenLayoutChanged : PutSettingsDirtyBits.None; } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.ITraceable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.ITraceable.cs index ff2220ef272..ad139a9b851 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.ITraceable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.ITraceable.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.cs index 73dadc080d7..cf489bac659 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/MelonDS.cs @@ -1,10 +1,10 @@ -using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Numerics; using System.Runtime.InteropServices; +using System.Text; using System.Threading; using BizHawk.BizInvoke; @@ -19,33 +19,12 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.NDS { [PortedCore(CoreNames.MelonDS, "Arisotura", "0.9.5", "https://melonds.kuribo64.net/")] [ServiceNotApplicable(new[] { typeof(IDriveLight), typeof(IRegionable) })] - public partial class NDS : WaterboxCore + public sealed partial class NDS : WaterboxCore { private readonly LibMelonDS _core; + private readonly IntPtr _console; private readonly NDSDisassembler _disassembler; - private readonly Dictionary _coreFiles = new(); - private readonly LibMelonDS.FileCallbackInterface _fileCallbackInterface; - - private int GetFileLengthCallback(string path) - => _coreFiles.TryGetValue(path, out var file) ? file.Length : 0; - - private void GetFileDataCallback(string path, IntPtr buffer) - { - var file = _coreFiles[path]; - Marshal.Copy(file, 0, buffer, file.Length); - } - - private void AddCoreFile(string path, byte[] file) - { - if (file.Length == 0) - { - throw new InvalidOperationException($"Tried to add 0-sized core file to {path}"); - } - - _coreFiles.Add(path, file); - } - private readonly LibMelonDS.LogCallback _logCallback; private static void LogCallback(LibMelonDS.LogLevel level, string message) @@ -70,7 +49,7 @@ public Vector2 GetTouchCoords(int x, int y) else { // no GL context, so nothing fancy can be applied - y = Math.Max(0, y - 192); + y -= 192; } return new(x, y); @@ -85,7 +64,7 @@ public Vector2 GetScreenCoords(float x, float y) else { // no GL context, so nothing fancy can be applied - y = Math.Min(256, y + 192); + y += 192; } return new(x, y); @@ -97,246 +76,274 @@ public NDS(CoreLoadParameters lp) { DefaultWidth = 256, DefaultHeight = 384, - MaxWidth = 256 * 16, - MaxHeight = (384 + 128) * 16, - MaxSamples = 1024, + MaxWidth = (256 * 16) * 3 + ((128 * 16) * 4 / 3) + 1, + MaxHeight = (384 / 2 * 16) * 2 + (128 * 16), + MaxSamples = 4096, // rather large max samples is intentional, see comment in ThreadStartCallback DefaultFpsNumerator = 33513982, DefaultFpsDenominator = 560190, SystemId = VSystemID.Raw.NDS, }) { - _syncSettings = lp.SyncSettings ?? new(); - _settings = lp.Settings ?? new(); - - _activeSyncSettings = _syncSettings.Clone(); - - IsDSi = _activeSyncSettings.UseDSi; - - var roms = lp.Roms.Select(r => r.RomData).ToList(); - - DSiTitleId = GetDSiTitleId(roms[0]); - IsDSi |= IsDSiWare; - - if (roms.Count > (IsDSi ? 1 : 2)) + try { - throw new InvalidOperationException("Wrong number of ROMs!"); - } + _syncSettings = lp.SyncSettings ?? new(); + _settings = lp.Settings ?? new(); - InitMemoryCallbacks(); + _activeSyncSettings = _syncSettings.Clone(); - _traceCallback = MakeTrace; - _threadStartCallback = ThreadStartCallback; + IsDSi = _activeSyncSettings.UseDSi; - _configCallbackInterface.GetBoolean = GetBooleanSettingCallback; - _configCallbackInterface.GetInteger = GetIntegerSettingCallback; - _configCallbackInterface.GetString = GetStringSettingCallback; - _configCallbackInterface.GetArray = GetArraySettingCallback; + var roms = lp.Roms.Select(r => r.RomData).ToList(); - _fileCallbackInterface.GetLength = GetFileLengthCallback; - _fileCallbackInterface.GetData = GetFileDataCallback; + DSiTitleId = GetDSiTitleId(roms[0]); + IsDSi |= IsDSiWare; - _logCallback = LogCallback; + if (roms.Count > (IsDSi ? 1 : 2)) + { + throw new InvalidOperationException("Wrong number of ROMs!"); + } - _openGLProvider = CoreComm.OpenGLProvider; - _getGLProcAddressCallback = GetGLProcAddressCallback; + InitMemoryCallbacks(); - if (lp.DeterministicEmulationRequested) - { - _activeSyncSettings.ThreeDeeRenderer = NDSSyncSettings.ThreeDeeRendererType.Software; - } + _traceCallback = MakeTrace; + _threadStartCallback = ThreadStartCallback; - if (_activeSyncSettings.ThreeDeeRenderer != NDSSyncSettings.ThreeDeeRendererType.Software) - { - // ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault - var (majorGlVersion, minorGlVersion) = _activeSyncSettings.ThreeDeeRenderer switch - { - NDSSyncSettings.ThreeDeeRendererType.OpenGL_Classic => (3, 2), - // NDSSyncSettings.ThreeDeeRendererType.OpenGL_Compute => (4, 3), - _ => throw new InvalidOperationException($"Invalid {nameof(NDSSyncSettings.ThreeDeeRenderer)}") - }; + _logCallback = LogCallback; - if (!_openGLProvider.SupportsGLVersion(majorGlVersion, minorGlVersion)) + _openGLProvider = CoreComm.OpenGLProvider; + _getGLProcAddressCallback = GetGLProcAddressCallback; + + if (lp.DeterministicEmulationRequested) { - lp.Comm.Notify($"OpenGL {majorGlVersion}.{minorGlVersion} is not supported on this machine, falling back to software renderer", null); _activeSyncSettings.ThreeDeeRenderer = NDSSyncSettings.ThreeDeeRendererType.Software; } - else - { - _glContext = _openGLProvider.RequestGLContext(majorGlVersion, minorGlVersion, true, false); - } - } - if (_activeSyncSettings.ThreeDeeRenderer == NDSSyncSettings.ThreeDeeRendererType.Software) - { - if (!_openGLProvider.SupportsGLVersion(3, 1)) + if (_activeSyncSettings.ThreeDeeRenderer != NDSSyncSettings.ThreeDeeRendererType.Software) { - lp.Comm.Notify("OpenGL 3.1 is not supported on this machine, screen control options will not work.", null); + // ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault + var (majorGlVersion, minorGlVersion) = _activeSyncSettings.ThreeDeeRenderer switch + { + NDSSyncSettings.ThreeDeeRendererType.OpenGL_Classic => (3, 2), + NDSSyncSettings.ThreeDeeRendererType.OpenGL_Compute => (4, 3), + _ => throw new InvalidOperationException($"Invalid {nameof(NDSSyncSettings.ThreeDeeRenderer)}") + }; + + if (!_openGLProvider.SupportsGLVersion(majorGlVersion, minorGlVersion)) + { + lp.Comm.Notify($"OpenGL {majorGlVersion}.{minorGlVersion} is not supported on this machine, falling back to software renderer", null); + _activeSyncSettings.ThreeDeeRenderer = NDSSyncSettings.ThreeDeeRendererType.Software; + } + else + { + _glContext = _openGLProvider.RequestGLContext(majorGlVersion, minorGlVersion, true); + } } - else + + if (_activeSyncSettings.ThreeDeeRenderer == NDSSyncSettings.ThreeDeeRendererType.Software) { - _glContext = _openGLProvider.RequestGLContext(3, 1, true, false); + if (!_openGLProvider.SupportsGLVersion(3, 1)) + { + lp.Comm.Notify("OpenGL 3.1 is not supported on this machine, screen control options will not work.", null); + } + else + { + _glContext = _openGLProvider.RequestGLContext(3, 1, true); + } } - } - - _core = PreInit(new() - { - Filename = "melonDS.wbx", - SbrkHeapSizeKB = 2 * 1024, - SealedHeapSizeKB = 4, - InvisibleHeapSizeKB = 4 * 1024, - PlainHeapSizeKB = 4, - MmapHeapSizeKB = 1920 * 1024, - SkipCoreConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck), - SkipMemoryConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck), - }, new Delegate[] - { - _readCallback, _writeCallback, _execCallback, _traceCallback, _threadStartCallback, - _configCallbackInterface.GetBoolean, _configCallbackInterface.GetInteger, - _configCallbackInterface.GetString, _configCallbackInterface.GetArray, - _fileCallbackInterface.GetLength, _fileCallbackInterface.GetData, - _logCallback, _getGLProcAddressCallback - }); - _activeSyncSettings.UseRealBIOS |= IsDSi; + _core = PreInit(new() + { + Filename = "melonDS.wbx", + SbrkHeapSizeKB = 2 * 1024, + SealedHeapSizeKB = 4, + InvisibleHeapSizeKB = 16 * 1024, + PlainHeapSizeKB = 4, + MmapHeapSizeKB = 1024 * 1024, + SkipCoreConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck), + SkipMemoryConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck), + }, new Delegate[] + { + _readCallback, _writeCallback, _execCallback, _traceCallback, + _threadStartCallback, _logCallback, _getGLProcAddressCallback + }); - if (_activeSyncSettings.UseRealBIOS) - { - AddCoreFile("bios7.bin", CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios7"))); - AddCoreFile("bios9.bin", CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios9"))); - AddCoreFile("firmware.bin", CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", IsDSi ? "firmwarei" : "firmware"))); - } + _core.SetLogCallback(_logCallback); - if (IsDSi) - { - AddCoreFile("bios7i.bin", CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios7i"))); - AddCoreFile("bios9i.bin", CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios9i"))); - AddCoreFile("nand.bin", DecideNAND(CoreComm.CoreFileProvider, (DSiTitleId.Upper & ~0xFF) == 0x00030000, roms[0][0x1B0])); - } - - if (IsDSiWare) - { - AddCoreFile("tmd.rom", GetTMDData(DSiTitleId.Full)); - AddCoreFile("dsiware.rom", roms[0]); - } - else - { - AddCoreFile("nds.rom", roms[0]); - if (roms.Count == 2) + if (_glContext != null) { - AddCoreFile("gba.rom", roms[1]); + var error = _core.InitGL(_getGLProcAddressCallback, _activeSyncSettings.ThreeDeeRenderer, _activeSyncSettings.GLScaleFactor, !OSTailoredCode.IsUnixHost); + if (error != IntPtr.Zero) + { + using (_exe.EnterExit()) + { + throw new InvalidOperationException(Marshal.PtrToStringAnsi(error)); + } + } } - } - _activeSyncSettings.FirmwareOverride |= !_activeSyncSettings.UseRealBIOS || lp.DeterministicEmulationRequested; + _activeSyncSettings.UseRealBIOS |= IsDSi; - // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags - if (!IsDSi && _activeSyncSettings.FirmwareStartUp == NDSSyncSettings.StartUp.AutoBoot) - { - _activeSyncSettings.FirmwareLanguage |= (NDSSyncSettings.Language)0x40; - } + byte[] bios9 = null, bios7 = null, firmware = null; + if (_activeSyncSettings.UseRealBIOS) + { + bios9 = CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios9")); + bios7 = CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios7")); + firmware = CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", IsDSi ? "firmwarei" : "firmware")); - _activeSyncSettings.UseRealTime &= !lp.DeterministicEmulationRequested; - var startTime = _activeSyncSettings.UseRealTime ? DateTime.Now : _activeSyncSettings.InitialTime; - - LibMelonDS.InitConfig initConfig; - initConfig.SkipFW = _activeSyncSettings.SkipFirmware; - initConfig.HasGBACart = roms.Count == 2; - initConfig.DSi = IsDSi; - initConfig.ClearNAND = _activeSyncSettings.ClearNAND || lp.DeterministicEmulationRequested; - initConfig.LoadDSiWare = IsDSiWare; - initConfig.IsWinApi = !OSTailoredCode.IsUnixHost; - initConfig.ThreeDeeRenderer = _activeSyncSettings.ThreeDeeRenderer; - initConfig.RenderSettings.SoftThreaded = _activeSyncSettings.ThreadedRendering; - initConfig.RenderSettings.GLScaleFactor = _activeSyncSettings.GLScaleFactor; - initConfig.RenderSettings.GLBetterPolygons = _activeSyncSettings.GLBetterPolygons; - initConfig.StartTime.Year = startTime.Year % 100; - initConfig.StartTime.Month = startTime.Month; - initConfig.StartTime.Day = startTime.Day; - initConfig.StartTime.Hour = startTime.Hour; - initConfig.StartTime.Minute = startTime.Minute; - initConfig.StartTime.Second = startTime.Second; - _activeSyncSettings.GetFirmwareSettings(out initConfig.FirmwareSettings); - - if (_activeSyncSettings.UseRealBIOS) - { - var fw = _coreFiles["firmware.bin"]; + if (firmware.Length is not (0x20000 or 0x40000 or 0x80000)) + { + throw new InvalidOperationException("Invalid firmware length"); + } - if (fw.Length is not (0x20000 or 0x40000 or 0x80000)) - { - throw new InvalidOperationException("Invalid firmware length"); + NDSFirmware.MaybeWarnIfBadFw(firmware, CoreComm.ShowMessage); } - NDSFirmware.MaybeWarnIfBadFw(fw, CoreComm.ShowMessage); - } - - var error = _core.Init( - ref initConfig, - _configCallbackInterface.AllCallbacksInArray(_adapter), - _fileCallbackInterface.AllCallbacksInArray(_adapter), - _logCallback, - _glContext != null ? _getGLProcAddressCallback : null); + byte[] bios9i = null, bios7i = null, nand = null; + if (IsDSi) + { + bios9i = CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios9i")); + bios7i = CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios7i")); + nand = DecideNAND(CoreComm.CoreFileProvider, (DSiTitleId.Upper & ~0xFF) == 0x00030000, roms[0][0x1B0]); + } - if (error != IntPtr.Zero) - { - using (_exe.EnterExit()) + byte[] ndsRom = null, gbaRom = null, dsiWare = null, tmd = null; + if (IsDSiWare) { - throw new InvalidOperationException(Marshal.PtrToStringAnsi(error)); + tmd = GetTMDData(DSiTitleId.Full); + dsiWare = roms[0]; + } + else + { + ndsRom = roms[0]; + if (roms.Count == 2) + { + gbaRom = roms[1]; + } } - } - // add DSiWare sav files to the core files, so we can import/export for SaveRAM - if (IsDSiWare) - { - _core.DSiWareSavsLength(DSiTitleId.Lower, out var publicSavSize, out var privateSavSize, out var bannerSavSize); + _activeSyncSettings.FirmwareOverride |= !_activeSyncSettings.UseRealBIOS || lp.DeterministicEmulationRequested; - if (publicSavSize != 0) + // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags + if (!IsDSi && _activeSyncSettings.FirmwareStartUp == NDSSyncSettings.StartUp.AutoBoot) { - AddCoreFile("public.sav", new byte[publicSavSize]); + _activeSyncSettings.FirmwareLanguage |= (NDSSyncSettings.Language)0x40; } - if (privateSavSize != 0) + _activeSyncSettings.UseRealTime &= !lp.DeterministicEmulationRequested; + var startTime = _activeSyncSettings.UseRealTime ? DateTime.Now : _activeSyncSettings.InitialTime; + + LibMelonDS.ConsoleCreationArgs consoleCreationArgs; + + consoleCreationArgs.NdsRomLength = ndsRom?.Length ?? 0; + consoleCreationArgs.GbaRomLength = gbaRom?.Length ?? 0; + consoleCreationArgs.Arm9BiosLength = bios9?.Length ?? 0; + consoleCreationArgs.Arm7BiosLength = bios7?.Length ?? 0; + consoleCreationArgs.FirmwareLength = firmware?.Length ?? 0; + consoleCreationArgs.Arm9iBiosLength = bios9i?.Length ?? 0; + consoleCreationArgs.Arm7iBiosLength = bios7i?.Length ?? 0; + consoleCreationArgs.NandLength = nand?.Length ?? 0; + consoleCreationArgs.DsiWareLength = dsiWare?.Length ?? 0; + consoleCreationArgs.TmdLength = tmd?.Length ?? 0; + + consoleCreationArgs.DSi = IsDSi; + consoleCreationArgs.ClearNAND = _activeSyncSettings.ClearNAND || lp.DeterministicEmulationRequested; + consoleCreationArgs.SkipFW = _activeSyncSettings.SkipFirmware; + + consoleCreationArgs.BitDepth = _settings.AudioBitDepth; + consoleCreationArgs.Interpolation = _settings.AudioInterpolation; + + consoleCreationArgs.ThreeDeeRenderer = _activeSyncSettings.ThreeDeeRenderer; + consoleCreationArgs.Threaded3D = _activeSyncSettings.ThreadedRendering; + consoleCreationArgs.ScaleFactor = _activeSyncSettings.GLScaleFactor; + consoleCreationArgs.BetterPolygons = _activeSyncSettings.GLBetterPolygons; + consoleCreationArgs.HiResCoordinates = _activeSyncSettings.GLHiResCoordinates; + + consoleCreationArgs.StartYear = startTime.Year % 100; + consoleCreationArgs.StartMonth = startTime.Month; + consoleCreationArgs.StartDay = startTime.Day; + consoleCreationArgs.StartHour = startTime.Hour; + consoleCreationArgs.StartMinute = startTime.Minute; + consoleCreationArgs.StartSecond = startTime.Second; + + _activeSyncSettings.GetFirmwareSettings(out consoleCreationArgs.FwSettings); + + var errorBuffer = new byte[1024]; + unsafe { - AddCoreFile("private.sav", new byte[privateSavSize]); + fixed (byte* + ndsRomPtr = ndsRom, + gbaRomPtr = gbaRom, + bios9Ptr = bios9, + bios7Ptr = bios7, + firmwarePtr = firmware, + bios9iPtr = bios9i, + bios7iPtr = bios7i, + nandPtr = nand, + dsiWarePtr = dsiWare, + tmdPtr = tmd) + { + consoleCreationArgs.NdsRomData = (IntPtr)ndsRomPtr; + consoleCreationArgs.GbaRomData = (IntPtr)gbaRomPtr; + consoleCreationArgs.Arm9BiosData = (IntPtr)bios9Ptr; + consoleCreationArgs.Arm7BiosData = (IntPtr)bios7Ptr; + consoleCreationArgs.FirmwareData = (IntPtr)firmwarePtr; + consoleCreationArgs.Arm9iBiosData = (IntPtr)bios9iPtr; + consoleCreationArgs.Arm7iBiosData = (IntPtr)bios7iPtr; + consoleCreationArgs.NandData = (IntPtr)nandPtr; + consoleCreationArgs.DsiWareData = (IntPtr)dsiWarePtr; + consoleCreationArgs.TmdData = (IntPtr)tmdPtr; + _console = _core.CreateConsole(ref consoleCreationArgs, errorBuffer); + } } - if (bannerSavSize != 0) + if (_console == IntPtr.Zero) { - AddCoreFile("banner.sav", new byte[bannerSavSize]); + var errorStr = Encoding.ASCII.GetString(errorBuffer).TrimEnd('\0'); + throw new InvalidOperationException(errorStr); } - DSiWareSaveLength = publicSavSize + privateSavSize + bannerSavSize; - } + if (IsDSiWare) + { + _core.DSiWareSavsLength(_console, DSiTitleId.Lower, out PublicSavSize, out PrivateSavSize, out BannerSavSize); + DSiWareSaveLength = PublicSavSize + PrivateSavSize + BannerSavSize; + } - PostInit(); + PostInit(); - ((MemoryDomainList)this.AsMemoryDomains()).SystemBus = new NDSSystemBus(this.AsMemoryDomains()["ARM9 System Bus"], this.AsMemoryDomains()["ARM7 System Bus"]); + ((MemoryDomainList)this.AsMemoryDomains()).SystemBus = new NDSSystemBus(this.AsMemoryDomains()["ARM9 System Bus"], this.AsMemoryDomains()["ARM7 System Bus"]); - DeterministicEmulation = lp.DeterministicEmulationRequested || !_activeSyncSettings.UseRealTime; + DeterministicEmulation = lp.DeterministicEmulationRequested || !_activeSyncSettings.UseRealTime; - _frameThreadPtr = _core.GetFrameThreadProc(); - if (_frameThreadPtr != IntPtr.Zero) - { - Console.WriteLine($"Setting up waterbox thread for 0x{(ulong)_frameThreadPtr:X16}"); - _frameThread = new(FrameThreadProc) { IsBackground = true }; - _frameThread.Start(); - _frameThreadAction = CallingConventionAdapters - .GetWaterboxUnsafeUnwrapped() - .GetDelegateForFunctionPointer(_frameThreadPtr); - _core.SetThreadStartCallback(_threadStartCallback); - } + _frameThreadPtr = _core.GetFrameThreadProc(); + if (_frameThreadPtr != IntPtr.Zero) + { + Console.WriteLine($"Setting up waterbox thread for 0x{(ulong)_frameThreadPtr:X16}"); + _frameThread = new(FrameThreadProc) { IsBackground = true }; + _frameThread.Start(); + _frameThreadAction = CallingConventionAdapters + .GetWaterboxUnsafeUnwrapped() + .GetDelegateForFunctionPointer(_frameThreadPtr); + _core.SetThreadStartCallback(_threadStartCallback); + } - _disassembler = new(_core); - _serviceProvider.Register(_disassembler); + _disassembler = new(_core); + _serviceProvider.Register(_disassembler); - const string TRACE_HEADER = "ARM9+ARM7: Opcode address, opcode, registers (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, SP, LR, PC, Cy, CpuMode)"; - Tracer = new TraceBuffer(TRACE_HEADER); - _serviceProvider.Register(Tracer); + const string TRACE_HEADER = "ARM9+ARM7: Opcode address, opcode, registers (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, SP, LR, PC, Cy, CpuMode)"; + Tracer = new TraceBuffer(TRACE_HEADER); + _serviceProvider.Register(Tracer); - if (_glContext != null) + if (_glContext != null) + { + _glTextureProvider = new(this, _core, () => _openGLProvider.ActivateGLContext(_glContext)); + _serviceProvider.Register(_glTextureProvider); + RefreshScreenSettings(_settings); + } + } + catch { - _glTextureProvider = new(this, _core, () => _openGLProvider.ActivateGLContext(_glContext)); - _serviceProvider.Register(_glTextureProvider); - RefreshScreenSettings(_settings); + Dispose(); + throw; } } @@ -385,12 +392,12 @@ private static byte[] GetTMDData(ulong titleId) // todo: wire this up w/ frontend public byte[] GetNAND() { - var length = _core.GetNANDSize(); + var length = _core.GetNANDSize(_console); if (length > 0) { var ret = new byte[length]; - _core.GetNANDData(ret); + _core.GetNANDData(_console, ret); return ret; } @@ -449,8 +456,6 @@ private static LibMelonDS.Buttons GetButtons(IController c) b |= LibMelonDS.Buttons.LIDCLOSE; if (c.IsPressed("Touch")) b |= LibMelonDS.Buttons.TOUCH; - if (c.IsPressed("Power")) - b |= LibMelonDS.Buttons.POWER; return b; } @@ -464,14 +469,20 @@ protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController contro _core.SetTraceCallback(Tracer.IsEnabled() ? _traceCallback : null, _settings.GetTraceMask()); + if (controller.IsPressed("Power")) + { + _core.ResetConsole(_console, _activeSyncSettings.SkipFirmware, DSiTitleId.Full); + } + return new LibMelonDS.FrameInfo { + Console = _console, Keys = GetButtons(controller), TouchX = (byte)controller.AxisValue("Touch X"), TouchY = (byte)controller.AxisValue("Touch Y"), MicVolume = (byte)controller.AxisValue("Mic Volume"), GBALightSensor = (byte)controller.AxisValue("GBA Light Sensor"), - ConsiderAltLag = _settings.ConsiderAltLag, + ConsiderAltLag = (byte)(_settings.ConsiderAltLag ? 1 : 0), }; } @@ -548,6 +559,8 @@ protected override void LoadStateBinaryInternal(BinaryReader reader) { throw new InvalidOperationException("_frameThreadPtr mismatch"); } + + _core.SetSoundConfig(_console, _settings.AudioBitDepth, _settings.AudioInterpolation); } // omega hack @@ -555,24 +568,44 @@ public class NDSSystemBus : MemoryDomain { private readonly MemoryDomain Arm9Bus; private readonly MemoryDomain Arm7Bus; + private bool _useArm9; public NDSSystemBus(MemoryDomain arm9, MemoryDomain arm7) { - Name = "System Bus"; Size = 1L << 32; WordSize = 4; EndianType = Endian.Little; - Writable = false; + Writable = true; Arm9Bus = arm9; Arm7Bus = arm7; + + UseArm9 = true; // important to set the initial name correctly } - public bool UseArm9 { get; set; } = true; + public bool UseArm9 + { + get => _useArm9; + set + { + _useArm9 = value; + Name = _useArm9 ? "ARM9 System Bus" : "ARM7 System Bus"; + } + } public override byte PeekByte(long addr) => UseArm9 ? Arm9Bus.PeekByte(addr) : Arm7Bus.PeekByte(addr); - public override void PokeByte(long addr, byte val) => throw new InvalidOperationException(); + public override void PokeByte(long addr, byte val) + { + if (UseArm9) + { + Arm9Bus.PokeByte(addr, val); + } + else + { + Arm7Bus.PokeByte(addr, val); + } + } } } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/NDSDisassembler.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/NDSDisassembler.cs index 111f26932cb..7ee3c86d1a6 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/NDSDisassembler.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/NDSDisassembler.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/NDSFirmware.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/NDSFirmware.cs index 66ff7f153bb..67a6cea5470 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/NDSFirmware.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NDS/NDSFirmware.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/APU.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/APU.cs index 337ad9c43dc..16c6f553fc6 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/APU.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/APU.cs @@ -10,7 +10,6 @@ // TODO - refactor length counter to be separate component -using System; using System.Runtime.CompilerServices; using BizHawk.Common; using BizHawk.Common.NumberExtensions; @@ -1408,7 +1407,7 @@ public void RunOneLast() // since the units run concurrently, the APU frame sequencer is ran last because // it can change the output values of the pulse/triangle channels // we want the changes to affect it on the *next* cycle. - if (sequencer_irq_flag == false) + if (!sequencer_irq_flag) sequencer_irq = false; if (DebugCallbackDivider != 0) diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/CNROM.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/CNROM.cs index 85c83aaa74b..eb061ad0626 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/CNROM.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/CNROM.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES @@ -136,7 +135,7 @@ public override void WritePrg(int addr, byte value) public override byte ReadPpu(int addr) { - if (chr_enabled == false) + if (!chr_enabled) { return 0x12; } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Cony.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Cony.cs index 2d1abb76c19..5311673ceb4 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Cony.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Cony.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; using BizHawk.Common.NumberExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/CoolBoy.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/CoolBoy.cs index 9009b742d47..80ec5ad954e 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/CoolBoy.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/CoolBoy.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; using BizHawk.Common.NumberExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/DatachBarcode.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/DatachBarcode.cs index 8e2d9f12e21..171647016f6 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/DatachBarcode.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/DatachBarcode.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common.NumberExtensions; using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/ExROM.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/ExROM.cs index 3302df54040..7122b1563f4 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/ExROM.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/ExROM.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/GxROM.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/GxROM.cs index 337ff4955ba..d23f26a2f31 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/GxROM.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/GxROM.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/InesBoardImplAttribute.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/InesBoardImplAttribute.cs index c222e89fbe1..c3c82c8ed41 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/InesBoardImplAttribute.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/InesBoardImplAttribute.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Nintendo.NES { // this will be used to track classes that implement boards diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MLT-ACTION52.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MLT-ACTION52.cs index 41cd228132c..ff79dfd1ad1 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MLT-ACTION52.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MLT-ACTION52.cs @@ -128,7 +128,7 @@ public override byte ReadPpu(int addr) public override byte ReadPrg(int addr) { - if (prg_mode == false) + if (!prg_mode) { int bank = (prg_reg >> 1) & prg_bank_mask_32k; return Rom[(bank * 0x8000) + addr + chip_offset]; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper074.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper074.cs index f28adc32af7..b883a333f35 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper074.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper074.cs @@ -1,4 +1,3 @@ -using System; //27 //TODO - could merge functionality with 192 somehow diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper115.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper115.cs index d97f26cab20..5c0261d96fa 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper115.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper115.cs @@ -54,7 +54,7 @@ public override void WriteWram(int addr, byte value) protected override int Get_PRGBank_8K(int addr) { int bank_8k = mmc3.Get_PRGBank_8K(addr); - if (prg_mode_mapper == false) return bank_8k; + if (!prg_mode_mapper) return bank_8k; else if (addr < 0x2000) { return prg_page*4; @@ -80,4 +80,4 @@ protected override int Get_CHRBank_1K(int addr) return bank_1k | chr_block_or; } } -} \ No newline at end of file +} diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper196.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper196.cs index b46dd6d6e58..c49183fbb9d 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper196.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MMC3_family/Mapper196.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper030.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper030.cs index f6b50c273f5..6698ba8d1d1 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper030.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper030.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper036.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper036.cs index 03f3280b0b3..a8391202859 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper036.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper036.cs @@ -1,6 +1,5 @@ using BizHawk.Common; using BizHawk.Common.NumberExtensions; -using System; namespace BizHawk.Emulation.Cores.Nintendo.NES { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper042.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper042.cs index 72bdf388559..bad92d4ce82 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper042.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper042.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper058.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper058.cs index 8725b3bb649..e61664bf030 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper058.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper058.cs @@ -53,7 +53,7 @@ public override void WritePrg(int addr, byte value) public override byte ReadPrg(int addr) { - if (prg_mode == false) + if (!prg_mode) { return Rom[((prg_reg >> 1) * 0x8000) + addr]; } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper078.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper078.cs index a6cb9cce095..076ffc8eccc 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper078.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper078.cs @@ -54,7 +54,7 @@ public override void WritePrg(int addr, byte value) prg_bank_16k = (byte)(value & 7); SyncPRG(); - if (value.Bit(3) == false) + if (!value.Bit(3)) { if (holydiver) SetMirrorType(EMirrorType.Horizontal); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper116.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper116.cs index f84dd9703c6..9154d0d3984 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper116.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper116.cs @@ -1,6 +1,5 @@ //TODO - emulation of mirroring is all bolloxed. -using System; using BizHawk.Common; using BizHawk.Common.NumberExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper222.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper222.cs index 28ae4dd63f8..02a202013f0 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper222.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper222.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; using BizHawk.Common.NumberExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper225.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper225.cs index bcdcc613e79..d42d2eec9ff 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper225.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper225.cs @@ -60,7 +60,7 @@ public override void WritePrg(int addr, byte value) public override byte ReadPrg(int addr) { - if (prg_mode == false) + if (!prg_mode) { int bank = (prg_reg >> 1) & prg_bank_mask_32k; return Rom[(bank * 0x8000) + addr]; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper226.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper226.cs index 19f8c8bd201..d6406366443 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper226.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper226.cs @@ -84,7 +84,7 @@ public override byte ReadPrg(int addr) { int baseAddr = resetSwitchMode && resetFlag ? 0x80000 : 0; - if (prg_mode == false) + if (!prg_mode) { return Rom[baseAddr + (( ((prg_page >> 1) & prg_mask_32k) << 15) + (addr & 0x7FFF))]; } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper227.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper227.cs index c62ee92d397..3b1ed6409be 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper227.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper227.cs @@ -64,7 +64,7 @@ public override void WritePrg(int addr, byte value) //maybe only the multicarts do it, to keep the game from clobbering vram on accident //vram_protected = o; - if (o && S == false) + if (o && !S) { _prgBanks16K[0] = (byte)(p); _prgBanks16K[1] = (byte)(p); @@ -74,22 +74,22 @@ public override void WritePrg(int addr, byte value) _prgBanks16K[0] = (byte)((p & ~1)); _prgBanks16K[1] = (byte)((p & ~1) + 1); } - if (o == false && S == false && L == false) + if (!o && !S && !L) { _prgBanks16K[0] = (byte)p; _prgBanks16K[1] = (byte)(p & 0x38); } - if (o == false && S && L == false) + if (!o && S && !L) { _prgBanks16K[0] = (byte)(p & 0x3E); _prgBanks16K[1] = (byte)(p & 0x38); } - if (o == false && S == false && L) + if (!o && !S && L) { _prgBanks16K[0] = (byte)p; _prgBanks16K[1] = (byte)(p | 0x07); } - if (o == false && S && L) + if (!o && S && L) { _prgBanks16K[0] = (byte)(p & 0x3E); _prgBanks16K[1] = (byte)(p | 0x07); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper230.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper230.cs index c87c00cee12..c8bd71b5b24 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper230.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper230.cs @@ -74,7 +74,7 @@ public override byte ReadPrg(int addr) } else { - if (prg_mode == false) + if (!prg_mode) { return Rom[((prg_page >> 1) * 0x8000) + addr + chip1_offset]; } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper233.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper233.cs index e7993e79e04..c9d9017fb9c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper233.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper233.cs @@ -55,7 +55,7 @@ public override void WritePrg(int addr, byte value) public override byte ReadPrg(int addr) { - if (prg_mode == false) + if (!prg_mode) { return Rom[((prg_page >> 1) * 0x8000) + addr]; } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper236.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper236.cs index b7d6b8755fe..ddf0400bfe1 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper236.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper236.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper240.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper240.cs index fa69a78a463..dbeb896a714 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper240.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper240.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper61.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper61.cs index fd6a985da7f..5194b7b4c6f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper61.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper61.cs @@ -50,7 +50,7 @@ public override void WritePrg(int addr, byte value) public override byte ReadPrg(int addr) { - if (prg_mode == false) + if (!prg_mode) { return Rom[(((prg_page >> 1) * 0x8000) + addr) & prg_byte_mask]; } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper62.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper62.cs index e5e5df2a0e2..d67f8540d28 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper62.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Mapper62.cs @@ -51,7 +51,7 @@ public override void WritePrg(int addr, byte value) public override byte ReadPrg(int addr) { - if (prg_mode == false) + if (!prg_mode) { return Rom[((prg_reg >> 1) * 0x8000) + addr]; } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MapperPropAttribute.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MapperPropAttribute.cs index dc73bfec26c..5e834c4ede6 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MapperPropAttribute.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/MapperPropAttribute.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/NSFBoard.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/NSFBoard.cs index cfca9a6d681..ec8b388a413 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/NSFBoard.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/NSFBoard.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; //NSF ROM and general approaches are heavily derived from FCEUX. the general ideas: diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Namcot1xx/Mapper112.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Namcot1xx/Mapper112.cs index 4fb147c36cd..32a63a317bf 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Namcot1xx/Mapper112.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Namcot1xx/Mapper112.cs @@ -1,5 +1,4 @@ using BizHawk.Common; -using System; namespace BizHawk.Emulation.Cores.Nintendo.NES { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Namcot1xx/Namco163Audio.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Namcot1xx/Namco163Audio.cs index 3f45aff95c3..1796f612114 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Namcot1xx/Namco163Audio.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Namcot1xx/Namco163Audio.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/NesBoardBase.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/NesBoardBase.cs index b432621f7f0..5cf7cfbd6cc 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/NesBoardBase.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/NesBoardBase.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/SEEPROM.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/SEEPROM.cs index 90c412b6be8..f8b3babd1e5 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/SEEPROM.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/SEEPROM.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Common.NumberExtensions; @@ -8,9 +6,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES /// /// describes a 24C01 or 24C02 as connected to a BANDAI-FCG /// - - // http://pdf1.alldatasheet.com/datasheet-pdf/view/56094/ATMEL/24C01.html 24C01 - // http://www.atmel.com/Images/doc0180.pdf 24C02 and others + /// + /// 24C01
+ /// 24C02 and others + ///
public sealed class SEEPROM { /// diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/SachenSimple.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/SachenSimple.cs index ff2d18b3186..eaaf8fb9171 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/SachenSimple.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/SachenSimple.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Sunsoft2_m89.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Sunsoft2_m89.cs index fc034208115..d3808a4c66f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Sunsoft2_m89.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/Sunsoft2_m89.cs @@ -51,7 +51,7 @@ public override void WritePrg(int addr, byte value) prg_bank_16k = (byte)((value >> 4) & 7); SyncPRG(); - if (value.Bit(3) == false) + if (!value.Bit(3)) SetMirrorType(EMirrorType.OneScreenA); else SetMirrorType(EMirrorType.OneScreenB); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/SxROM.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/SxROM.cs index f0d74c00909..8e7638db507 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/SxROM.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/SxROM.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; using BizHawk.Common.NumberExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UNIF/UNIF_BMC-Ghostbusters63in1.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UNIF/UNIF_BMC-Ghostbusters63in1.cs index d5b3ab3f711..0a875596e05 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UNIF/UNIF_BMC-Ghostbusters63in1.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UNIF/UNIF_BMC-Ghostbusters63in1.cs @@ -1,6 +1,5 @@ using BizHawk.Common; using BizHawk.Common.NumberExtensions; -using System; namespace BizHawk.Emulation.Cores.Nintendo.NES { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UNIF/UNIF_UNL_DripGame.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UNIF/UNIF_UNL_DripGame.cs index 99105137d34..603e7182554 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UNIF/UNIF_UNL_DripGame.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UNIF/UNIF_UNL_DripGame.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UxROM.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UxROM.cs index 45c68de8d6b..0a72456802c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UxROM.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/UxROM.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/VRC2_4.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/VRC2_4.cs index 7ce93f85702..2b6f17c425c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/VRC2_4.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/VRC2_4.cs @@ -1,6 +1,5 @@ //TODO - for chr, refactor to use 8 registers of 8 bits instead of 16 registers of 4 bits. more realistic, less weird code. -using System; using BizHawk.Common; using BizHawk.Common.NumberExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/VRC6.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/VRC6.cs index 6ebbe1476ce..50b7bcb433e 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/VRC6.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/VRC6.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Cores.Components; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/VRC7.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/VRC7.cs index a95c9101b38..331a050d3c4 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/VRC7.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Boards/VRC7.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Cores.Components; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/BootGodDB.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/BootGodDB.cs index d1b772f8eab..b4d0b3db0a2 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/BootGodDB.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/BootGodDB.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using System.Collections.Generic; using System.IO; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/FDS.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/FDS.cs index fe9f778c0cd..cff9525cbfb 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/FDS.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/FDS.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Text; using System.IO; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/FDSAudio.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/FDSAudio.cs index 48fda7c3d92..2534cf1e010 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/FDSAudio.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/FDSAudio.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/FDSInspector.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/FDSInspector.cs index 884e65fed22..e1e91cd7b9a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/FDSInspector.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/FDSInspector.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/RamAdapter.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/RamAdapter.cs index a6eb72c53fe..4473a2e2214 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/RamAdapter.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/RamAdapter.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/INESPPUViewable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/INESPPUViewable.cs index 8ec1d8e67a3..1eef797f931 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/INESPPUViewable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/INESPPUViewable.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.BoardSystem.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.BoardSystem.cs index f4f486a5c83..756da13f868 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.BoardSystem.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.BoardSystem.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs index 94a8cf434f4..66fb4c88f1c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.Core.cs @@ -1,7 +1,5 @@ // NOTE: to match Mesen timings, set idleSynch to true at power on, and set start_up_offset to -3 -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.M6502; @@ -10,7 +8,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES { - public partial class NES : IEmulator, ISoundProvider/*, ICycleTiming*/ + public partial class NES : IEmulator, ISoundProvider, ICycleTiming { internal static class RomChecksums { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.ICodeDataLogger.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.ICodeDataLogger.cs index dfaef1ad0b3..d3aa311e5de 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.ICodeDataLogger.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.ICodeDataLogger.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.IDebuggable.cs index d19298777b8..647de97cc3e 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.INESPPUViewable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.INESPPUViewable.cs index 4906a3469d2..d1c1bcd30c8 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.INESPPUViewable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.INESPPUViewable.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.ISaveRam.cs index e5d0692f4c8..271046e5249 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.ISaveRam.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.ISettable.cs index f6cbfbbc2cf..2a4aa1873bd 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.ISettable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; @@ -62,24 +61,14 @@ public enum Region public NESControlSettings Controls = new NESControlSettings(); - [JsonConverter(typeof(U8ArrayAsNormalJSONListConverter))] // this preserves the old behaviour of e,g, 0x1234ABCD --> [18,52,171,205]; omitting it will use base64 e.g. "EjSrzQ==" - [JsonProperty(PropertyName = nameof(InitialWRamStatePattern))] - private byte[]/*?*/ _initialWRamStatePattern = null; - [JsonIgnore] + private byte[]/*?*/ _initialWRamStatePattern; + + [JsonConverter(typeof(U8ArrayAsNormalJSONListConverter))] // this preserves the old behaviour of e,g, 0x1234ABCD --> [18,52,171,205]; omitting it will use base64 e.g. "EjSrzQ==" public byte[] InitialWRamStatePattern { - get - { - if (_initialWRamStatePattern is null) return Array.Empty(); - if (_initialWRamStatePattern.Length is 0) - { - _initialWRamStatePattern = null; - return Array.Empty(); - } - return _initialWRamStatePattern; - } - set => _initialWRamStatePattern = value.Length is 0 ? null : value; + get => _initialWRamStatePattern ?? [ ]; + set => _initialWRamStatePattern = value; } public NESSyncSettings Clone() diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.IStatable.cs index 61f179eb749..a448bd8a9d2 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.IStatable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.IStatable.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.cs index 4a952d00c6a..9411b62b915 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.IO; using System.Collections.Generic; @@ -71,6 +70,12 @@ public NES(CoreComm comm, GameInfo game, byte[] rom, NESSettings settings, NESSy } } + // only the subframe core should have ICycleTiming registered + if (!subframe) + { + ser.Unregister(); + } + ResetControllerDefinition(subframe); } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.iNES.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.iNES.cs index 26d85972a9a..0fb18f3d860 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.iNES.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.iNES.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Text; using BizHawk.Common.NumberExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NESControllers.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NESControllers.cs index 1a6870de566..bd4c8937f6d 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NESControllers.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NESControllers.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NSFFormat.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NSFFormat.cs index b975a2b3f8f..e047175ea08 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NSFFormat.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NSFFormat.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Common.IOExtensions; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.cs index b65481aab1c..1a357cf3f0f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.NES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.regs.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.regs.cs index b27632148ea..8c8fe4d50b7 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.regs.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.regs.cs @@ -6,7 +6,6 @@ // 0x09,0x01,0x34,0x03, 0x00,0x04,0x00,0x14, 0x08,0x3A,0x00,0x02, 0x00,0x20,0x2C,0x08 //}; -using System; using System.Runtime.CompilerServices; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Unif.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Unif.cs index a4e14129d57..b625198f700 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Unif.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/Unif.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/LibQuickNES.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/LibQuickNES.cs index 78bcfe0d62c..675a22dd1ae 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/LibQuickNES.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/LibQuickNES.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.BizInvoke; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/Nes_NTSC_Colors.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/Nes_NTSC_Colors.cs index c84eec5eee4..b558aa60dbf 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/Nes_NTSC_Colors.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/Nes_NTSC_Colors.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES { public static class Nes_NTSC_Colors diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IDebuggable.cs index c102a3b1145..969f458c1e2 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IDisassembler.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IDisassembler.cs index 5599675375a..19b4d44741c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IDisassembler.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IDisassembler.cs @@ -16,10 +16,7 @@ public string Cpu public string PCRegisterName => "PC"; - public IEnumerable AvailableCpus - { - get { yield return "6502"; } - } + public IEnumerable AvailableCpus { get; } = [ "6502" ]; public string Disassemble(MemoryDomain m, uint addr, out int length) { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IInputPollable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IInputPollable.cs index 290dc0463d8..a7eb3fc9be7 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IInputPollable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IInputPollable.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IMemoryDomains.cs index 8f1fa83be7d..9e1e76bae8f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.INESPPUViewable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.INESPPUViewable.cs index f81083570f3..acdd07fc833 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.INESPPUViewable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.INESPPUViewable.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Nintendo.NES; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ISettable.cs index 012c651bebd..64b7afd6635 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ISettable.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ISoundProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ISoundProvider.cs index 643fe0e7c6a..6280c9b4c5c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ISoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ISoundProvider.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IStatable.cs index 6c334f1ba3e..c5366380af8 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IStatable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.IStatable.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ITraceable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ITraceable.cs index faa08568736..71ea850b100 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ITraceable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ITraceable.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs index 5afc7bfd3ca..884a1b87010 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs @@ -1,14 +1,13 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; +using BizHawk.BizInvoke; using BizHawk.Common; using BizHawk.Common.CollectionExtensions; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Nintendo.NES; -using BizHawk.BizInvoke; namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi.cs index 5d1cdd0d3e0..901dcd076c2 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Collections.Generic; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_QUERY.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_QUERY.cs index d5f70386ba9..38232401713 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_QUERY.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_QUERY.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_SIG.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_SIG.cs index 41c1918b8bc..735f4c0fbba 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_SIG.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_SIG.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; namespace BizHawk.Emulation.Cores.Nintendo.SNES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesControllerDeck.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesControllerDeck.cs index 0c82bbb75df..0cc085e989c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesControllerDeck.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesControllerDeck.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IDebuggable.cs index 6f95426cd23..8d57d19509b 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IMemoryDomains.cs index 404e8277e41..f612807875a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.ISaveRam.cs index 3f89c642f0c..2e81c159239 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.ISaveRam.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.ISoundProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.ISoundProvider.cs index f03e13fbc42..91bc8ec9e5b 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.ISoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.ISoundProvider.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.SNES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs index 50a9eb2a338..0cc511b3c77 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Xml; using System.IO; @@ -18,7 +17,7 @@ // wrap dll code around some kind of library-accessing interface so that it doesn't malfunction if the dll is unavailable namespace BizHawk.Emulation.Cores.Nintendo.SNES { - [PortedCore(CoreNames.Bsnes, "byuu", "v87", "https://github.com/bsnes-emu/bsnes/tree/386ac87d21d14fafd15162d480a111209c9955ba")] + [PortedCore(CoreNames.Bsnes, "byuu", "v87", "https://github.com/bsnes-emu/bsnes/tree/v087")] [ServiceNotApplicable(new[] { typeof(IDriveLight) })] public unsafe partial class LibsnesCore : IEmulator, IVideoProvider, ISaveRam, IStatable, IInputPollable, IRegionable, ICodeDataLogger, IDebuggable, ISettable, IBSNESForGfxDebugger diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/SNESGraphicsDecoder.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/SNESGraphicsDecoder.cs index 02c0e4e5fba..f93553c5131 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/SNESGraphicsDecoder.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/SNESGraphicsDecoder.cs @@ -9,7 +9,7 @@ //when a BG is not available, the last rendered BG still shows up. should clear it using BizHawk.Common; -using System; + using System.Drawing; namespace BizHawk.Emulation.Cores.Nintendo.SNES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/ScanlineHookManager.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/ScanlineHookManager.cs index cf91b7e18d4..74b3875e7c9 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/ScanlineHookManager.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/ScanlineHookManager.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Emulation.Cores.Nintendo.SNES diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs index 7005f4f8172..6d637228cdd 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9x.cs @@ -1,13 +1,13 @@ -using System; -using BizHawk.Emulation.Common; -using BizHawk.Emulation.Cores.Waterbox; -using System.IO; using System.ComponentModel; +using System.IO; + using BizHawk.Common; +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Waterbox; namespace BizHawk.Emulation.Cores.Nintendo.SNES9X { - [PortedCore(CoreNames.Snes9X, "", "e49165c5607011f4d95adcb7b5983140ab5a75f1", "https://github.com/snes9xgit/snes9x")] + [PortedCore(CoreNames.Snes9X, "", "e49165c", "https://github.com/snes9xgit/snes9x")] [ServiceNotApplicable(new[] { typeof(IDriveLight) })] public class Snes9x : WaterboxCore, ISettable, IRegionable diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9xControllers.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9xControllers.cs index 23a7bc14452..2a405c03a89 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9xControllers.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES9X/Snes9xControllers.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/LibSameBoy.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/LibSameBoy.cs index e6b94c45a58..f88d3676fb9 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/LibSameBoy.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/LibSameBoy.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.BizInvoke; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IDebuggable.cs index 17fa17a5c19..e2e79be60d2 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IEmulator.cs index ccc1722a5bd..1e9d96f298a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IEmulator.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IMemoryDomains.cs index 99748ec8dec..144adca6233 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.ISaveRam.cs index 79458d617a8..dad1b2c930c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.ISaveRam.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.Sameboy diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.ISettable.cs index 2ab9a6ff888..93b9ce2c4d5 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.ISettable.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.ComponentModel.DataAnnotations; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.ISoundProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.ISoundProvider.cs index fd6e111d3c7..1fb26424522 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.ISoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.ISoundProvider.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.Sameboy diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IStatable.cs index d22b984efdb..9ed871e2c4c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IStatable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.IStatable.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.cs index 2c6840f8712..dfd5506a1a8 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SameBoy/SameBoy.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Text; @@ -13,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Sameboy /// /// a gameboy/gameboy color emulator wrapped around native C libsameboy /// - [PortedCore(CoreNames.Sameboy, "LIJI32", "0.15.6", "https://github.com/LIJI32/SameBoy")] + [PortedCore(CoreNames.Sameboy, "LIJI32", "0.16.3", "https://github.com/LIJI32/SameBoy")] [ServiceNotApplicable(new[] { typeof(IDriveLight) })] public partial class Sameboy : ICycleTiming, IInputPollable, ILinkable, IRomInfo, IBoardInfo, IGameboyCommon { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IEmulator.cs index cb9a646f165..fad2dd0fd38 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.IEmulator.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.SubGBHawk diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.cs index 32914f6b8f9..40752246870 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubGBHawk/SubGBHawk.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IEmulator.cs index 18a6ac94a9b..ca973234003 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.IEmulator.cs @@ -1,5 +1,5 @@ -using System; using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Nintendo.NES; namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk { @@ -35,6 +35,45 @@ public bool FrameAdvance(IController controller, bool render, bool renderSound) reset_cycle = controller.AxisValue("Reset Cycle"); reset_cycle_int = (int)Math.Floor(reset_cycle); + if (_nesCore.Board is FDS fds) + { + if (controller.IsPressed("FDS Eject")) + { + fds.Eject(); + } + + for (var i = 0; i < fds.NumSides; i++) + { + if (controller.IsPressed("FDS Insert " + i)) + { + fds.InsertSide(i); + } + } + } + + if (_nesCore.IsVS) + { + _nesCore.VS_service = (byte)(controller.IsPressed("Service Switch") ? 1 : 0); + + if (controller.IsPressed("Insert Coin P1")) + { + _nesCore.VS_coin_inserted |= 1; + } + else + { + _nesCore.VS_coin_inserted &= 2; + } + + if (controller.IsPressed("Insert Coin P2")) + { + _nesCore.VS_coin_inserted |= 2; + } + else + { + _nesCore.VS_coin_inserted &= 1; + } + } + _nesCore.lagged = true; DoFrame(controller); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.cs index 67990a2acee..301833d6b86 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/SubNESHawk/SubNESHawk.cs @@ -4,9 +4,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk { [Core(CoreNames.SubNesHawk, "")] - [ServiceNotApplicable(new[] { typeof(IDriveLight) })] - public partial class SubNESHawk : IEmulator, IStatable, IInputPollable, - ISettable, ICycleTiming + public partial class SubNESHawk : IEmulator, IStatable, IInputPollable, ISettable { [CoreConstructor(VSystemID.Raw.NES, Priority = CorePriority.SuperLow)] public SubNESHawk(CoreComm comm, GameInfo game, byte[] rom, /*string gameDbFn,*/ NES.NES.NESSettings settings, NES.NES.NESSyncSettings syncSettings) @@ -36,6 +34,8 @@ public SubNESHawk(CoreComm comm, GameInfo game, byte[] rom, /*string gameDbFn,*/ ser.Register(_nesCore.ServiceProvider.GetService()); ser.Register(_nesCore.ServiceProvider.GetService()); ser.Register(_nesCore.ServiceProvider.GetService()); + ser.Register(_nesCore.ServiceProvider.GetService()); + ser.Register(_nesCore.ServiceProvider.GetService()); const string TRACE_HEADER = "6502: PC, machine code, mnemonic, operands, registers (A, X, Y, P, SP), flags (NVTBDIZCR), CPU Cycle, PPU Cycle"; _tracer = new TraceBuffer(TRACE_HEADER); @@ -76,8 +76,5 @@ private void SoftReset() public NES.NES.NESSyncSettings GetSyncSettings() => _nesCore.GetSyncSettings(); public PutSettingsDirtyBits PutSettings(NES.NES.NESSettings o) => _nesCore.PutSettings(o); public PutSettingsDirtyBits PutSyncSettings(NES.NES.NESSyncSettings o) => _nesCore.PutSyncSettings(o); - - public long CycleCount => _nesCore.CycleCount; - public double ClockRate => _nesCore.ClockRate; } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/VirtualBoyee.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/VirtualBoyee.cs index 9d11ff9cf08..3015c87e772 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/VirtualBoyee.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/VirtualBoyee.cs @@ -5,7 +5,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB { - [PortedCore(CoreNames.VirtualBoyee, "Mednafen Team", "1.29.0", "https://mednafen.github.io/releases/")] + [PortedCore(CoreNames.VirtualBoyee, "Mednafen Team", "1.32.1", "https://mednafen.github.io/releases/")] public class VirtualBoyee : NymaCore { private VirtualBoyee(CoreComm comm) diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/ADPCM.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/ADPCM.cs index 6e61a6400b8..c7d2ffe1ed2 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/ADPCM.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/ADPCM.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components; @@ -106,7 +104,7 @@ public void AdpcmControlWrite(byte value) if (AdpcmIsPlaying && (value & 0x20) == 0) AdpcmIsPlaying = false; // clearing this bit stops playback - if (AdpcmIsPlaying == false && (value & 0x20) != 0) + if (!AdpcmIsPlaying && (value & 0x20) != 0) { if ((value & 0x40) == 0) Console.WriteLine("a thing that's normally set is not set"); @@ -168,7 +166,7 @@ public void Think(int cycles) _scsi.Think(); } - if (_scsi.DataTransferInProgress == false) + if (!_scsi.DataTransferInProgress) Port180B = 0; } @@ -254,7 +252,7 @@ private int AddClamped(int num1, int num2, int min, int max) private byte ReadNibble() { byte value; - if (nibble == false) + if (!nibble) value = (byte)(RAM[ReadAddress] >> 4); else { @@ -275,13 +273,13 @@ private void DecodeAdpcmSample() int m = StepFactor[mag]; int adjustment = StepSize[(magnitude * 8) + mag]; magnitude = AddClamped(magnitude, m, 0, 48); - if (positive == false) adjustment *= -1; + if (!positive) adjustment *= -1; playingSample = AddClamped(playingSample, adjustment, 0, 4095); } private void AdpcmEmitSample() { - if (AdpcmIsPlaying == false) + if (!AdpcmIsPlaying) _synchronizer.EnqueueSample(0, 0); else { diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/IGpuView.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/IGpuView.cs index 57c651ea0f0..8754549e9de 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/IGpuView.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/IGpuView.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/MemoryMap.TurboCD.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/MemoryMap.TurboCD.cs index bd1e30a8100..e6aac80656e 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/MemoryMap.TurboCD.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/MemoryMap.TurboCD.cs @@ -41,7 +41,7 @@ private byte ReadMemoryCD(int addr) if (addr >= 0x1EE000 && addr <= 0x1EE7FF) // BRAM { - if (BramEnabled && BramLocked == false) + if (BramEnabled && !BramLocked) return BRAM[addr & 0x7FF]; return 0xFF; } @@ -84,7 +84,7 @@ private void WriteMemoryCD(int addr, byte value) else if (addr >= 0x1EE000 && addr <= 0x1EE7FF) // BRAM { - if (BramEnabled && BramLocked == false) + if (BramEnabled && !BramLocked) { BRAM[addr & 0x7FF] = value; SaveRamModified = true; @@ -95,4 +95,4 @@ private void WriteMemoryCD(int addr, byte value) Log.Error("MEM", "UNHANDLED WRITE: {0:X6}:{1:X2}", addr, value); } } -} \ No newline at end of file +} diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/MemoryMap.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/MemoryMap.cs index f60cb7655fd..a52f76fb30a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/MemoryMap.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/MemoryMap.cs @@ -29,7 +29,7 @@ private byte ReadMemory(int addr) if (addr >= 0x1EE000 && addr <= 0x1EE7FF) // BRAM { - if (BramEnabled && BramLocked == false) + if (BramEnabled && !BramLocked) return BRAM[addr & 0x7FF]; return 0xFF; } @@ -61,7 +61,7 @@ private void WriteMemory(int addr, byte value) } else if (addr >= 0x1EE000 && addr <= 0x1EE7FF) // BRAM { - if (BramEnabled && BramLocked == false) + if (BramEnabled && !BramLocked) { BRAM[addr & 0x7FF] = value; SaveRamModified = true; @@ -75,4 +75,4 @@ private void WriteMemory(int addr, byte value) //CoreComm.MemoryCallbackSystem.CallWrite((uint)addr); } } -} \ No newline at end of file +} diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ArcadeCard.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ArcadeCard.cs index 33ce5525af1..9807b714ce4 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ArcadeCard.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ArcadeCard.cs @@ -48,7 +48,7 @@ public int EffectiveAddress private void WriteArcadeCard(int addr, byte value) { - if (ArcadeCard == false) + if (!ArcadeCard) { return; } @@ -114,7 +114,7 @@ private void WriteArcadeCard(int addr, byte value) private byte ReadArcadeCard(int addr) { - if (ArcadeCard == false) return 0xFF; + if (!ArcadeCard) return 0xFF; var page = ArcadePage[(addr >> 4) & 3]; switch (addr & 0x0F) { @@ -144,7 +144,7 @@ public void ArcadeCardSyncState(Serializer ser) ser.Sync(nameof(ShiftAmount), ref ShiftAmount); ser.Sync(nameof(RotateAmount), ref RotateAmount); - if (ArcadeCardRewindHack == false || ser.IsText) + if (!ArcadeCardRewindHack || ser.IsText) { ser.Sync("ArcadeRAM", ref ArcadeRam, false); } @@ -163,4 +163,4 @@ public void ArcadeCardSyncState(Serializer ser) ser.EndSection(); } } -} \ No newline at end of file +} diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ICodeDataLogger.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ICodeDataLogger.cs index b30f8490d75..f474b90ed44 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ICodeDataLogger.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ICodeDataLogger.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IDebuggable.cs index e2416cf9225..1a756b5f567 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IMemoryDomains.cs index 59a1075653e..3b9ae269ffb 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISaveRam.cs index 0a4b50e6970..4fd573749a1 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.ISaveRam.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.PCEngine diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.Input.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.Input.cs index a77a22eadac..381f3f04d5a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.Input.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.Input.cs @@ -18,7 +18,7 @@ private void WriteInput(byte value) _selectedController = 0; } - if (Clr == false && prevSel == false && Sel) + if (!Clr && !prevSel && Sel) { _selectedController++; } @@ -43,7 +43,7 @@ private byte ReadInput() value |= 0x40; } - if (Type != NecSystemType.TurboCD && BramEnabled == false) + if (Type != NecSystemType.TurboCD && !BramEnabled) { value |= 0x80; } diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.TurboCD.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.TurboCD.cs index 809338cb608..4d7ba97f23a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.TurboCD.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.TurboCD.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.PCEngine diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs index 504e57fd515..8cc473e6c5a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PCEngine.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; @@ -49,7 +48,7 @@ public PCEngine(CoreLoadParameters lp) lp.Comm.ShowMessage( "The PCE-CD System Card you have selected is not recognized in our database. That might mean it's a bad dump, or isn't the correct rom."); } - else if (biosInfo["BIOS"] == false) + else if (!biosInfo["BIOS"]) { // zeromus says: someone please write a note about how this could possibly happen. // it seems like this is a relic of using gameDB for storing whether something is a bios? firmwareDB should be handling it now. @@ -62,7 +61,7 @@ public PCEngine(CoreLoadParameters lp) lp.Game.AddOption("SuperSysCard", ""); } - if (lp.Game["NeedSuperSysCard"] && lp.Game["SuperSysCard"] == false) + if (lp.Game["NeedSuperSysCard"] && !lp.Game["SuperSysCard"]) { lp.Comm.ShowMessage( "This game requires a version 3.0 System card and won't run with the system card you've selected. Try selecting a 3.0 System Card in the firmware configuration."); @@ -224,7 +223,7 @@ private void Init(GameInfo game, byte[] rom) RomLength = RomData.Length; // user request: current value of the SF2MapperLatch on the tracelogger - Cpu.Logger = s => Tracer.Put(new(disassembly: $"{SF2MapperLatch:X1}:{s}", registerInfo: string.Empty)); + Cpu.Logger = s => Tracer.Put(new(disassembly: $"{SF2MapperLatch:X1}:{s.Disassembly}", registerInfo: string.Empty)); } else { diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PceControllerDeck.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PceControllerDeck.cs index 674f850bd53..a9f82e2dada 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PceControllerDeck.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/PceControllerDeck.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using BizHawk.Emulation.Common; @@ -125,7 +124,7 @@ public byte Read(IController c, bool sel) { byte result = 0x3F; - if (sel == false) + if (!sel) { if (c.IsPressed($"P{PortNum} B1")) result &= 0xFE; if (c.IsPressed($"P{PortNum} B2")) result &= 0xFD; diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/QuickCollections.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/QuickCollections.cs index 228f18f437b..7d7ccb58748 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/QuickCollections.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/QuickCollections.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.PCEngine { // If you're wondering what the point of this is: It's mostly to have .Clear() be fast. diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/ScsiCDBus.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/ScsiCDBus.cs index 35aa6986434..add4bab4afd 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/ScsiCDBus.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/ScsiCDBus.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Cores.Components; diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/VDC.Render.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/VDC.Render.cs index aff3a72b5fe..a00973094f9 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/VDC.Render.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/VDC.Render.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.PCEngine @@ -91,7 +90,7 @@ public void ExecFrame(bool render) cpu.Execute(455 - HBlankCycles - 2); - if (InActiveDisplay == false && DmaRequested) + if (!InActiveDisplay && DmaRequested) RunDmaForScanline(); ScanLine++; @@ -122,7 +121,7 @@ private unsafe void RenderBackgroundScanlineUnsafe(bool show) { Array.Clear(PriorityBuffer, 0, FrameWidth); - if (BackgroundEnabled == false) + if (!BackgroundEnabled) { int p = vce.Palette[256]; fixed (int* FBptr = FrameBuffer) @@ -202,7 +201,7 @@ private void RenderBackgroundScanlineSafe(bool show) { Array.Clear(PriorityBuffer, 0, FrameWidth); - if (BackgroundEnabled == false) + if (!BackgroundEnabled) { for (int i = 0; i < FrameWidth; i++) FrameBuffer[((ActiveLine + ViewStartLine - pce.Settings.TopLine) * FramePitch) + i] = vce.Palette[256]; @@ -242,7 +241,7 @@ private void RenderBackgroundScanlineSafe(bool show) public void RenderSpritesScanline(bool show) { - if (SpritesEnabled == false) + if (!SpritesEnabled) { return; } @@ -286,7 +285,7 @@ public void RenderSpritesScanline(bool show) patternNo &= 0x1FE; int yofs = 0; - if (vflip == false) + if (!vflip) { yofs = (ActiveLine - y) & 15; if (height == 32) @@ -351,7 +350,7 @@ public void RenderSpritesScanline(bool show) } } - if (hflip == false) + if (!hflip) { if (x + width > 0 && y + height > 0) { diff --git a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/VPC.cs b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/VPC.cs index 3f08e6b54d6..d6a5f8fa5ab 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/PC Engine/VPC.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/PC Engine/VPC.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.H6280; @@ -228,10 +226,10 @@ public void ExecFrame(bool render) CPU.Execute(455 - VDC1.HBlankCycles - 2); - if (InActiveDisplay == false && VDC1.DmaRequested) + if (!InActiveDisplay && VDC1.DmaRequested) VDC1.RunDmaForScanline(); - if (InActiveDisplay == false && VDC2.DmaRequested) + if (!InActiveDisplay && VDC2.DmaRequested) VDC2.RunDmaForScanline(); VDC1.RCRCounter++; @@ -280,7 +278,7 @@ private void InitializeScanLine(int scanline) private unsafe void RenderBackgroundScanline(VDC vdc, byte priority, bool show) { - if (vdc.BackgroundEnabled == false) + if (!vdc.BackgroundEnabled) return; // per-line parameters @@ -351,7 +349,7 @@ private unsafe void RenderBackgroundScanline(VDC vdc, byte priority, bool show) private void RenderSpritesScanline(VDC vdc, byte lowPriority, byte highPriority, bool show) { - if (vdc.SpritesEnabled == false) + if (!vdc.SpritesEnabled) return; // clear inter-sprite priority buffer @@ -378,7 +376,7 @@ private void RenderSpritesScanline(VDC vdc, byte lowPriority, byte highPriority, patternNo &= 0x1FE; int yofs; - if (vflip == false) + if (!vflip) { yofs = (vdc.ActiveLine - y) & 15; if (height == 32) @@ -442,7 +440,7 @@ private void RenderSpritesScanline(VDC vdc, byte lowPriority, byte highPriority, } } } - if (hflip == false) + if (!hflip) { if (x + width > 0 && y + height > 0) { diff --git a/src/BizHawk.Emulation.Cores/Consoles/SNK/NeoGeoPort.cs b/src/BizHawk.Emulation.Cores/Consoles/SNK/NeoGeoPort.cs index 68dd08e2f48..8c4ef0d0d7a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/SNK/NeoGeoPort.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/SNK/NeoGeoPort.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; @@ -6,7 +5,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SNK { - [PortedCore(CoreNames.NeoPop, "Thomas Klausner, Mednafen Team", "1.29.0", "https://mednafen.github.io/releases/")] + [PortedCore(CoreNames.NeoPop, "Thomas Klausner, Mednafen Team", "1.32.1", "https://mednafen.github.io/releases/")] public class NeoGeoPort : NymaCore, ISaveRam // NGP provides its own saveram interface { diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.ICodeDataLog.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.ICodeDataLog.cs index c40d3c73804..7ed0dc8175c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.ICodeDataLog.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.ICodeDataLog.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IDebuggable.cs index d6a2348f829..71addf8a864 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IEmulator.cs index 8b6d4c9797d..27a5be31347 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.IEmulator.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Sega.GGHawkLink diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.ISaveRam.cs index 9ea36de517e..dc6c7904d1a 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.ISaveRam.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Sega.GGHawkLink diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.cs index 529d460f7bc..a49e3867570 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLink.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Sega.MasterSystem; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLinkControllerDeck.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLinkControllerDeck.cs index 6c29341cf65..9aea7635bd7 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLinkControllerDeck.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/GGHawkLink/GGHawkLinkControllerDeck.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/LibPicoDrive.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/LibPicoDrive.cs index ea07e055d9d..69f69e6148b 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/LibPicoDrive.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/LibPicoDrive.cs @@ -1,6 +1,6 @@ using BizHawk.BizInvoke; using BizHawk.Emulation.Cores.Waterbox; -using System; + using System.Runtime.InteropServices; namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs index fad21257993..7ea7b488555 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs @@ -1,15 +1,15 @@ -using BizHawk.Emulation.Common; -using BizHawk.Emulation.Cores.Waterbox; -using BizHawk.Emulation.DiscSystem; -using System; -using System.Runtime.InteropServices; +using System.ComponentModel; using System.IO; +using System.Runtime.InteropServices; + using BizHawk.Common; -using System.ComponentModel; +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Waterbox; +using BizHawk.Emulation.DiscSystem; namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive { - [PortedCore(CoreNames.PicoDrive, "notaz", "0e352905c7aa80b166933970abbcecfce96ad64e", "https://github.com/notaz/picodrive")] + [PortedCore(CoreNames.PicoDrive, "notaz", "0e35290", "https://github.com/notaz/picodrive")] public class PicoDrive : WaterboxCore, IDriveLight, IRegionable, ISettable { private readonly LibPicoDrive _core; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/EEPROM.93c46.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/EEPROM.93c46.cs index 1f74f70daf0..7ccb69acb74 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/EEPROM.93c46.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/EEPROM.93c46.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; namespace BizHawk.Emulation.Cores.Sega.MasterSystem diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/MemoryMap.EEPROM.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/MemoryMap.EEPROM.cs index 267c0b2d30f..87f4e5be691 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/MemoryMap.EEPROM.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/MemoryMap.EEPROM.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.Cores.Sega.MasterSystem { public partial class SMS diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ICodeDataLogger.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ICodeDataLogger.cs index 477fbfdaa31..b816631da99 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ICodeDataLogger.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ICodeDataLogger.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IDebuggable.cs index 9d8a340ad46..1488abe4ae8 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs index 561342ec0d2..1c044015e4f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs @@ -28,7 +28,7 @@ public bool FrameAdvance(IController controller, bool render, bool renderSound) Cpu.TraceCallback = null; } - if (IsGameGear_C == false) + if (!IsGameGear_C) { Cpu.NonMaskableInterrupt = controller.IsPressed("Pause"); } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IMemoryDomains.cs index 3801f193e69..3dc4bd18dac 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISaveRam.cs index 20ab96123a6..62b011f3789 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISaveRam.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Sega.MasterSystem diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISoundProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISoundProvider.cs index f97b5bf2f90..8a142c74617 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.ISoundProvider.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.Input.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.Input.cs index 34f99d66ed9..0a476501e47 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.Input.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.Input.cs @@ -173,7 +173,7 @@ internal void ProcessLineControls() private byte ReadPort0() { - if (IsGameGear_C == false) + if (!IsGameGear_C) { return 0xFF; } @@ -242,4 +242,4 @@ private void PostsetControllerState(int pin) } } } -} \ No newline at end of file +} diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs index 3d281368297..0bead53efde 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components; using BizHawk.Emulation.Cores.Components.Z80A; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMSControllerDeck.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMSControllerDeck.cs index ac46a247a0a..ce6aecb755f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMSControllerDeck.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMSControllerDeck.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.Mode4.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.Mode4.cs index 623a70c60b8..d8c2b6c8a9d 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.Mode4.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.Mode4.cs @@ -1,5 +1,3 @@ -using System; - // Contains rendering functions for TMS9918 Mode 4. namespace BizHawk.Emulation.Cores.Sega.MasterSystem @@ -11,7 +9,7 @@ internal void RenderBackgroundCurrentLine(bool show) if (ScanLine >= FrameHeight) return; - if (DisplayOn == false) + if (!DisplayOn) { for (int x = 0; x < 256; x++) FrameBuffer[(ScanLine * 256) + x] = Palette[BackdropColor]; @@ -64,7 +62,7 @@ internal void RenderBackgroundCurrentLine(bool show) if (VFlip) yOfs = 7 - yOfs; - if (HFlip == false) + if (!HFlip) { FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 0] + PaletteBase] : Palette[BackdropColor]; FrameBuffer[(ScanLine * 256) + horzOffset++] = show ? Palette[PatternBuffer[(tileNo * 64) + (yOfs * 8) + 1] + PaletteBase] : Palette[BackdropColor]; @@ -288,7 +286,7 @@ internal void RenderLineBlanking(bool render) internal void ProcessOverscan() { - if (Sms.Settings.DisplayOverscan == false) + if (!Sms.Settings.DisplayOverscan) return; if (OverscanFrameBuffer == null) @@ -346,7 +344,7 @@ internal void ProcessGGScreen() if (mode != VdpMode.GameGear) return; - if (Sms.Settings.ShowClippedRegions == false) + if (!Sms.Settings.ShowClippedRegions) { int yStart = (FrameHeight - 144) / 2; for (int y = 0; y < 144; y++) diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.ModeTMS.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.ModeTMS.cs index 3106ffd3a81..12663a4a2da 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.ModeTMS.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.ModeTMS.cs @@ -1,5 +1,4 @@ // Contains rendering functions for legacy TMS9918 modes. -using System; namespace BizHawk.Emulation.Cores.Sega.MasterSystem { @@ -30,7 +29,7 @@ private void RenderBackgroundM0(bool show) if (ScanLine >= FrameHeight) return; - if (DisplayOn == false) + if (!DisplayOn) { Array.Clear(FrameBuffer, ScanLine * 256, 256); return; @@ -68,7 +67,7 @@ private void RenderBackgroundM2(bool show) if (ScanLine >= FrameHeight) return; - if (DisplayOn == false) + if (!DisplayOn) { Array.Clear(FrameBuffer, ScanLine * 256, 256); return; @@ -105,13 +104,13 @@ private void RenderBackgroundM2(bool show) private void RenderTmsSprites(bool show) { - if (ScanLine >= FrameHeight || DisplayOn == false) + if (ScanLine >= FrameHeight || !DisplayOn) return; - if (EnableDoubledSprites == false) - RenderTmsSpritesStandard(show); - else + if (EnableDoubledSprites) RenderTmsSpritesDouble(show); + else + RenderTmsSpritesStandard(show); } private void RenderTmsSpritesStandard(bool show) diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.cs index cc497188452..96365047306 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.cs @@ -239,7 +239,7 @@ public int CalcNameTableBase() private void CheckVideoMode() { - if (Mode4Bit == false) // check old TMS modes + if (!Mode4Bit) // check old TMS modes { if (Mode1Bit) TmsMode = 1; else if (Mode2Bit) TmsMode = 2; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/Saturnus.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/Saturnus.cs index 23dca2639f7..6169012aebf 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/Saturnus.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/Saturnus.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; @@ -6,7 +5,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn { - [PortedCore(CoreNames.Saturnus, "Mednafen Team", "1.29.0", "https://mednafen.github.io/releases/")] + [PortedCore(CoreNames.Saturnus, "Mednafen Team", "1.32.1", "https://mednafen.github.io/releases/")] public class Saturnus : NymaCore, IRegionable, ISaveRam { private readonly LibSaturnus _saturnus; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ICodeDataLogger.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ICodeDataLogger.cs index d2f992cb9f3..b684ff38867 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ICodeDataLogger.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ICodeDataLogger.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Emulation.Common; @@ -10,8 +9,7 @@ public partial class GPGX : ICodeDataLogger public void SetCDL(ICodeDataLog cdl) { CDL = cdl; - if (cdl == null) Core.gpgx_set_cd_callback(null); - else Core.gpgx_set_cd_callback(CDCallback); + Core.gpgx_set_cd_callback(cdl == null ? null : CDCallback); } public void NewCDL(ICodeDataLog cdl) @@ -21,7 +19,10 @@ public void NewCDL(ICodeDataLog cdl) cdl["Z80 RAM"] = new byte[_memoryDomains["Z80 RAM"]!.Size]; var found = _memoryDomains["SRAM"]; - if (found is not null) cdl["SRAM"] = new byte[found.Size]; + if (found is not null) + { + cdl["SRAM"] = new byte[found.Size]; + } cdl.SubType = "GEN"; cdl.SubVer = 0; @@ -29,24 +30,29 @@ public void NewCDL(ICodeDataLog cdl) // TODO: we have Disassembling now // not supported - public void DisassembleCDL(Stream s, ICodeDataLog cdl) { } + public void DisassembleCDL(Stream s, ICodeDataLog cdl) + { + } private ICodeDataLog CDL; private void CDCallbackProc(int addr, LibGPGX.CDLog_AddrType addrtype, LibGPGX.CDLog_Flags flags) { - //TODO - hard reset makes CDL go nuts. + // TODO - hard reset makes CDL go nuts. - if (CDL == null) return; - if (!CDL.Active) return; - string key; - switch (addrtype) + if (CDL is not { Active: true }) { - case LibGPGX.CDLog_AddrType.MDCART: key = "MD CART"; break; - case LibGPGX.CDLog_AddrType.RAM68k: key = "68K RAM"; break; - case LibGPGX.CDLog_AddrType.RAMZ80: key = "Z80 RAM"; break; - case LibGPGX.CDLog_AddrType.SRAM: key = "SRAM"; break; - default: throw new InvalidOperationException("Lagrangian earwax incident"); + return; } + + var key = addrtype switch + { + LibGPGX.CDLog_AddrType.MDCART => "MD CART", + LibGPGX.CDLog_AddrType.RAM68k => "68K RAM", + LibGPGX.CDLog_AddrType.RAMZ80 => "Z80 RAM", + LibGPGX.CDLog_AddrType.SRAM => "SRAM", + _ => throw new InvalidOperationException("Lagrangian earwax incident") + }; + CDL[key][addr] |= (byte)flags; } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IDebuggable.cs index 1d201d55fee..b5cc096e8a7 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IDebuggable.cs @@ -1,6 +1,6 @@ -using System; using System.Collections.Generic; using System.Runtime.InteropServices; + using BizHawk.Common; using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; @@ -14,7 +14,10 @@ public IDictionary GetCpuFlagsAndRegisters() var regs = new LibGPGX.RegisterInfo[Core.gpgx_getmaxnumregs()]; var n = Core.gpgx_getregs(regs); if (n > regs.Length) + { throw new InvalidOperationException("A buffer overrun has occured!"); + } + var ret = new Dictionary(); using (_elf.EnterExit()) { @@ -24,7 +27,9 @@ public IDictionary GetCpuFlagsAndRegisters() var name = Marshal.PtrToStringAnsi(regs[i].Name); byte size = 32; if (name!.Contains("68K SR") || name.StartsWithOrdinal("Z80")) + { size = 16; + } ret[name] = new RegisterValue((ulong)regs[i].Value, size); } @@ -35,9 +40,7 @@ public IDictionary GetCpuFlagsAndRegisters() [FeatureNotImplemented] public void SetCpuRegister(string register, int value) - { - throw new NotImplementedException(); - } + => throw new NotImplementedException(); public IMemoryCallbackSystem MemoryCallbacks { @@ -60,7 +63,7 @@ public IMemoryCallbackSystem MemoryCallbacks [FeatureNotImplemented] public long TotalExecutedCycles => throw new NotImplementedException(); - private readonly MemoryCallbackSystem _memoryCallbacks = new(new[] { "M68K BUS" }); + private readonly MemoryCallbackSystem _memoryCallbacks = new([ "M68K BUS" ]); private LibGPGX.mem_cb ExecCallback; private LibGPGX.mem_cb ReadCallback; @@ -99,14 +102,12 @@ private void InitMemCallbacks() private void RefreshMemCallbacks() { Core.gpgx_set_mem_callback( - MemoryCallbacks.HasReads ? ReadCallback : null, - MemoryCallbacks.HasWrites ? WriteCallback : null, - MemoryCallbacks.HasExecutes ? ExecCallback : null); + _memoryCallbacks.HasReads ? ReadCallback : null, + _memoryCallbacks.HasWrites ? WriteCallback : null, + _memoryCallbacks.HasExecutes ? ExecCallback : null); } private void KillMemCallbacks() - { - Core.gpgx_set_mem_callback(null, null, null); - } + => Core.gpgx_set_mem_callback(null, null, null); } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IDisassembler.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IDisassembler.cs index ebf79160186..cdd4aa5b568 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IDisassembler.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IDisassembler.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; + using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components.M68000; @@ -16,24 +17,21 @@ public string Cpu public string PCRegisterName => "M68K PC"; - public IEnumerable AvailableCpus - { - get { yield return "M68000"; } - } + public IEnumerable AvailableCpus { get; } = [ "M68000" ]; public string Disassemble(MemoryDomain m, uint addr, out int length) { - _disassemblerInstance.ReadWord = (a) => (short)m.PeekUshort(a, m.EndianType == MemoryDomain.Endian.Big); - _disassemblerInstance.ReadByte = (a) => (sbyte)m.PeekByte(a); - _disassemblerInstance.ReadLong = (a) => (int)m.PeekUint(a, m.EndianType == MemoryDomain.Endian.Big); + _disassemblerInstance.ReadWord = a => (short)m.PeekUshort(a, m.EndianType == MemoryDomain.Endian.Big); + _disassemblerInstance.ReadByte = a => (sbyte)m.PeekByte(a); + _disassemblerInstance.ReadLong = a => (int)m.PeekUint(a, m.EndianType == MemoryDomain.Endian.Big); var info = _disassemblerInstance.Disassemble((int)addr); length = info.Length; - return $"{info.RawBytes.Substring(0, 4):X4} {info.Mnemonic,-7} {info.Args}"; + return $"{info.RawBytes[..4]} {info.Mnemonic,-7} {info.Args}"; } // TODO: refactor MC6800's disassembler to be a static call - private readonly MC68000 _disassemblerInstance = new MC68000(); + private readonly MC68000 _disassemblerInstance = new(); } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IEmulator.cs index 229c118b96a..753a1026edf 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IEmulator.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx @@ -12,32 +11,47 @@ public partial class GPGX : IEmulator, ISoundProvider public bool FrameAdvance(IController controller, bool render, bool renderSound = true) { if (controller.IsPressed("Reset")) + { Core.gpgx_reset(false); + } + if (controller.IsPressed("Power")) + { Core.gpgx_reset(true); + } + if (_cds != null) { var prev = controller.IsPressed("Previous Disk"); var next = controller.IsPressed("Next Disk"); - int newDisk = _discIndex; + var newDisk = _discIndex; if (prev && !_prevDiskPressed) + { newDisk--; + } + if (next && !_nextDiskPressed) + { newDisk++; + } _prevDiskPressed = prev; _nextDiskPressed = next; if (newDisk < -1) + { newDisk = -1; + } + if (newDisk >= _cds.Length) + { newDisk = _cds.Length - 1; + } if (newDisk != _discIndex) { _discIndex = newDisk; Core.gpgx_swap_disc(_discIndex == -1 ? null : GetCDDataStruct(_cds[_discIndex])); - Console.WriteLine("IMMA CHANGING MAH DISKS"); } } @@ -47,10 +61,17 @@ public bool FrameAdvance(IController controller, bool render, bool renderSound = ControlConverter.ScreenWidth = _vwidth; ControlConverter.ScreenHeight = _vheight; - ControlConverter.Convert(controller, input); + ControlConverter.Convert(controller, _input); + + if (controller.IsPressed("Pause")) + { + _input.pad[0] |= LibGPGX.INPUT_KEYS.INPUT_START; + } - if (!Core.gpgx_put_control(input, inputsize)) + if (!Core.gpgx_put_control(_input, _inputSize)) + { throw new Exception($"{nameof(Core.gpgx_put_control)}() failed!"); + } IsLagFrame = true; @@ -58,18 +79,26 @@ public bool FrameAdvance(IController controller, bool render, bool renderSound = Core.gpgx_advance(); - if (render) + if (render) + { UpdateVideo(); + } - if (renderSound) - update_audio(); + if (renderSound) + { + UpdateAudio(); + } if (IsLagFrame) + { LagCount++; + } if (_cds != null) - DriveLightOn = _driveLight; - + { + DriveLightOn = _driveLight; + } + Frame++; return true; @@ -93,9 +122,15 @@ public void Dispose() if (!_disposed) { _elf?.Dispose(); + if (_cds != null) + { foreach (var cd in _cds) + { cd.Dispose(); + } + } + _disposed = true; } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IInputPollable.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IInputPollable.cs index 008b1ab06ac..066b031c79b 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IInputPollable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IInputPollable.cs @@ -12,9 +12,9 @@ public partial class GPGX : IInputPollable private readonly LibGPGX.input_cb _inputCallback; - private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); + private readonly InputCallbackSystem _inputCallbacks = [ ]; - private void input_callback() + private void InputCallback() { InputCallbacks.Call(); IsLagFrame = false; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IMemoryDomains.cs index 41a861fa87e..16ad217c1df 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Runtime.InteropServices; @@ -22,7 +21,10 @@ private unsafe void SetMemoryDomains() var size = 0; var pName = Core.gpgx_get_memdom(i, ref area, ref size); if (area == IntPtr.Zero || pName == IntPtr.Zero || size == 0) + { continue; + } + var name = Marshal.PtrToStringAnsi(pName)!; // typically Genesis domains will be 2 bytes large (and thus big endian and byteswapped) @@ -32,97 +34,109 @@ private unsafe void SetMemoryDomains() ? MemoryDomain.Endian.Little : MemoryDomain.Endian.Big; - if (name == "VRAM") + switch (name) { - // vram pokes need to go through hook which invalidates cached tiles - var p = (byte*)area; - if (SystemId == VSystemID.Raw.GEN) + case "VRAM": { - // Genesis has more VRAM, and GPGX byteswaps it - mm.Add(new MemoryDomainDelegate(name, size, MemoryDomain.Endian.Big, - addr => - { - if (addr is < 0 or > 0xFFFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); - using (_elf.EnterExit()) - return p![addr ^ 1]; - }, - (addr, val) => - { - if (addr is < 0 or > 0xFFFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); - Core.gpgx_poke_vram((int)addr ^ 1, val); - }, - wordSize: 1)); - } - else - { - mm.Add(new MemoryDomainDelegate(name, size, MemoryDomain.Endian.Big, - addr => - { - if (addr is < 0 or > 0x3FFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); - using (_elf.EnterExit()) - return p![addr]; - }, - (addr, val) => - { - if (addr is < 0 or > 0x3FFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); - Core.gpgx_poke_vram((int)addr, val); - }, - wordSize: 1)); + // vram pokes need to go through hook which invalidates cached tiles + var p = (byte*)area; + if (SystemId == VSystemID.Raw.GEN) + { + // Genesis has more VRAM, and GPGX byteswaps it + mm.Add(new MemoryDomainDelegate(name, size, MemoryDomain.Endian.Big, + addr => + { + if (addr is < 0 or > 0xFFFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); + using (_elf.EnterExit()) + return p![addr ^ 1]; + }, + (addr, val) => + { + if (addr is < 0 or > 0xFFFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); + Core.gpgx_poke_vram((int)addr ^ 1, val); + }, + wordSize: 1)); + } + else + { + mm.Add(new MemoryDomainDelegate(name, size, MemoryDomain.Endian.Big, + addr => + { + if (addr is < 0 or > 0x3FFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); + using (_elf.EnterExit()) + return p![addr]; + }, + (addr, val) => + { + if (addr is < 0 or > 0x3FFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); + Core.gpgx_poke_vram((int)addr, val); + }, + wordSize: 1)); + } + + break; } - } - else if (name == "CRAM") - { - var p = (byte*)area; - if (SystemId == VSystemID.Raw.GEN) + case "CRAM": { - // CRAM for Genesis in the core is internally a different format than what it is natively - // this internal format isn't really useful, so let's convert it back - mm.Add(new MemoryDomainDelegate(name, size, MemoryDomain.Endian.Big, - addr => - { - if (addr is < 0 or > 0x7F) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); - using (_elf.EnterExit()) + var p = (byte*)area; + if (SystemId == VSystemID.Raw.GEN) + { + // CRAM for Genesis in the core is internally a different format than what it is natively + // this internal format isn't really useful, so let's convert it back + mm.Add(new MemoryDomainDelegate(name, size, MemoryDomain.Endian.Big, + addr => + { + if (addr is < 0 or > 0x7F) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); + using (_elf.EnterExit()) + { + var c = *(ushort*)&p![addr & ~1]; + c = (ushort)(((c & 0x1C0) << 3) | ((c & 0x038) << 2) | ((c & 0x007) << 1)); + return (byte)((addr & 1) != 0 ? c & 0xFF : c >> 8); + } + }, + (addr, val) => + { + if (addr is < 0 or > 0x7F) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); + Core.gpgx_poke_cram((int)addr, val); + }, + wordSize: 2)); + } + else + { + mm.Add(new MemoryDomainDelegate(name, size, MemoryDomain.Endian.Big, + addr => { - var c = *(ushort*)&p![addr & ~1]; - c = (ushort)(((c & 0x1C0) << 3) | ((c & 0x038) << 2) | ((c & 0x007) << 1)); - return (byte)((addr & 1) != 0 ? c & 0xFF : c >> 8); - } - }, - (addr, val) => - { - if (addr is < 0 or > 0x7F) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); - Core.gpgx_poke_cram((int)addr, val); - }, - wordSize: 2)); + if (addr is < 0 or > 0x3F) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); + using (_elf.EnterExit()) + { + var c = *(ushort*)&p![addr & ~1]; + return (byte)((addr & 1) != 0 ? c & 0xFF : c >> 8); + } + }, + (addr, val) => + { + if (addr is < 0 or > 0x3F) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); + Core.gpgx_poke_cram((int)addr, val); + }, + wordSize: 2)); + } + + break; } - else + default: { - mm.Add(new MemoryDomainDelegate(name, size, MemoryDomain.Endian.Big, - addr => - { - if (addr is < 0 or > 0x3F) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); - using (_elf.EnterExit()) - { - var c = *(ushort*)&p![addr & ~1]; - return (byte)((addr & 1) != 0 ? c & 0xFF : c >> 8); - } - }, - (addr, val) => - { - if (addr is < 0 or > 0x3F) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range"); - Core.gpgx_poke_cram((int)addr, val); - }, - wordSize: 2)); + if (oneByteWidth) + { + mm.Add(new MemoryDomainIntPtrMonitor(name, endian, area, size, true, 1, _elf)); + } + else + { + mm.Add(new MemoryDomainIntPtrSwap16Monitor(name, endian, area, size, true, _elf)); + } + + break; } } - else if (oneByteWidth) - { - mm.Add(new MemoryDomainIntPtrMonitor(name, endian, area, size, true, 1, _elf)); - } - else - { - mm.Add(new MemoryDomainIntPtrSwap16Monitor(name, endian, area, size, true, _elf)); - } } MemoryDomain systemBus; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ISaveRam.cs index 2a28bed9c39..7107a7d9b6c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ISaveRam.cs @@ -1,5 +1,5 @@ -using System; using System.Runtime.InteropServices; + using BizHawk.Common; using BizHawk.Emulation.Common; @@ -9,14 +9,19 @@ public partial class GPGX : ISaveRam { public byte[] CloneSaveRam() { - int size = 0; - IntPtr area = Core.gpgx_get_sram(ref size); + var size = 0; + var area = Core.gpgx_get_sram(ref size); if (size == 0 || area == IntPtr.Zero) + { return null; + } - byte[] ret = new byte[size]; + var ret = new byte[size]; using (_elf.EnterExit()) + { Marshal.Copy(area, ret, 0, size); + } + return ret; } @@ -27,6 +32,7 @@ public void StoreSaveRam(byte[] data) // not sure how this is happening, but reject them return; } + if (!Core.gpgx_put_sram(data, data.Length)) { throw new Exception("Core rejected saveram"); @@ -37,8 +43,8 @@ public bool SaveRamModified { get { - int size = 0; - IntPtr area = Core.gpgx_get_sram(ref size); + var size = 0; + var area = Core.gpgx_get_sram(ref size); return size > 0 && area != IntPtr.Zero; } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ISettable.cs index 540eeb38499..c43a2e187cc 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ISettable.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Globalization; @@ -6,24 +5,19 @@ using BizHawk.Emulation.Common; using Newtonsoft.Json; - namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx { public partial class GPGX : ISettable { public GPGXSettings GetSettings() - { - return _settings.Clone(); - } + => _settings.Clone(); public GPGXSyncSettings GetSyncSettings() - { - return _syncSettings.Clone(); - } + => _syncSettings.Clone(); public PutSettingsDirtyBits PutSettings(GPGXSettings o) { - bool ret = GPGXSettings.NeedsReboot(_settings, o); + var ret = GPGXSettings.NeedsReboot(_settings, o); _settings = o; Core.gpgx_set_draw_mask(_settings.GetDrawMask()); Core.gpgx_set_sprite_limit_enabled(!_settings.NoSpriteLimit); @@ -32,7 +26,7 @@ public PutSettingsDirtyBits PutSettings(GPGXSettings o) public PutSettingsDirtyBits PutSyncSettings(GPGXSyncSettings o) { - bool ret = GPGXSyncSettings.NeedsReboot(_syncSettings, o); + var ret = GPGXSyncSettings.NeedsReboot(_syncSettings, o); _syncSettings = o; return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; } @@ -40,18 +34,14 @@ public PutSettingsDirtyBits PutSyncSettings(GPGXSyncSettings o) private class UintToHexConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } + => sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) - { - return destinationType == typeof(string) || base.CanConvertTo(context, destinationType); - } + => destinationType == typeof(string) || base.CanConvertTo(context, destinationType); public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { - if (destinationType == typeof(string) && value.GetType() == typeof(uint)) + if (destinationType == typeof(string) && value is uint) { return $"0x{value:x8}"; } @@ -61,13 +51,14 @@ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cul public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { - if (value.GetType() == typeof(string)) + if (value?.GetType() == typeof(string)) { - string input = (string)value; + var input = (string)value; if (input.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { - input = input.Substring(2); + input = input[2..]; } + return uint.Parse(input, NumberStyles.HexNumber, culture); } @@ -78,18 +69,14 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c private class UshortToHexConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } + => sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) - { - return destinationType == typeof(string) || base.CanConvertTo(context, destinationType); - } + => destinationType == typeof(string) || base.CanConvertTo(context, destinationType); public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { - if (destinationType == typeof(string) && value.GetType() == typeof(ushort)) + if (destinationType == typeof(string) && value is ushort) { return $"0x{value:x4}"; } @@ -99,13 +86,14 @@ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cul public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { - if (value.GetType() == typeof(string)) + if (value?.GetType() == typeof(string)) { - string input = (string)value; + var input = (string)value; if (input.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { - input = input.Substring(2); + input = input[2..]; } + return ushort.Parse(input, NumberStyles.HexNumber, culture); } @@ -210,16 +198,11 @@ public bool NoSpriteLimit set => _noSpriteLimit = value; } - public GPGXSettings() - { - SettingsUtil.SetDefaultValues(this); - } + => SettingsUtil.SetDefaultValues(this); public GPGXSettings Clone() - { - return (GPGXSettings)MemberwiseClone(); - } + => (GPGXSettings)MemberwiseClone(); public LibGPGX.DrawMask GetDrawMask() { @@ -233,11 +216,7 @@ public LibGPGX.DrawMask GetDrawMask() } public static bool NeedsReboot(GPGXSettings x, GPGXSettings y) - { - return !DeepEquality.DeepEquals(x, y); - } - - + => !DeepEquality.DeepEquals(x, y); } [CoreSettings] @@ -263,6 +242,11 @@ public class GPGXSyncSettings [DefaultValue(LibGPGX.Region.Autodetect)] public LibGPGX.Region Region { get; set; } + [DisplayName("Force VDP Mode")] + [Description("Overrides the VDP mode to force it to run at either 60Hz (NTSC) or 50Hz (PAL), regardless of system region.")] + [DefaultValue(LibGPGX.ForceVDP.Disabled)] + public LibGPGX.ForceVDP ForceVDP { get; set; } + [DisplayName("Load BIOS")] [Description("Indicates whether to load the system BIOS rom.")] [DefaultValue(false)] @@ -349,6 +333,7 @@ public LibGPGX.InitSettings GetNativeSettings(GameInfo game) InputSystemA = SystemForSystem(ControlTypeLeft), InputSystemB = SystemForSystem(ControlTypeRight), Region = Region, + ForceVDP = ForceVDP, LoadBIOS = LoadBIOS, ForceSram = game["sram"], SMSFMSoundChip = SMSFMSoundChip, @@ -360,19 +345,13 @@ public LibGPGX.InitSettings GetNativeSettings(GameInfo game) } public GPGXSyncSettings() - { - SettingsUtil.SetDefaultValues(this); - } + => SettingsUtil.SetDefaultValues(this); public GPGXSyncSettings Clone() - { - return (GPGXSyncSettings)MemberwiseClone(); - } + => (GPGXSyncSettings)MemberwiseClone(); public static bool NeedsReboot(GPGXSyncSettings x, GPGXSyncSettings y) - { - return !DeepEquality.DeepEquals(x, y); - } + => !DeepEquality.DeepEquals(x, y); } } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ISoundProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ISoundProvider.cs index 7e66fd11a7a..aab348cf412 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ISoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ISoundProvider.cs @@ -1,7 +1,7 @@ -using System; -using BizHawk.Emulation.Common; using System.Runtime.InteropServices; + using BizHawk.Common; +using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx { @@ -20,9 +20,7 @@ public void GetSamplesSync(out short[] samples, out int nsamp) } public void DiscardSamples() - { - _nsamp = 0; - } + => _nsamp = 0; public void SetSyncMode(SyncSoundMode mode) { @@ -30,23 +28,23 @@ public void SetSyncMode(SyncSoundMode mode) { throw new NotSupportedException("Async mode is not supported."); } - } + public SyncSoundMode SyncMode => SyncSoundMode.Sync; public void GetSamplesAsync(short[] samples) - { - throw new InvalidOperationException("Async mode is not supported."); - } + => throw new InvalidOperationException("Async mode is not supported."); - private void update_audio() + private void UpdateAudio() { - IntPtr src = IntPtr.Zero; + var src = IntPtr.Zero; Core.gpgx_get_audio(ref _nsamp, ref src); if (src != IntPtr.Zero) { using (_elf.EnterExit()) + { Marshal.Copy(src, _samples, 0, _nsamp * 2); + } } } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IStatable.cs index 9b851efefd0..dea8a5c86f4 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IStatable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IStatable.cs @@ -1,4 +1,5 @@ using System.IO; + using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx @@ -20,7 +21,7 @@ public void LoadStateBinary(BinaryReader reader) // any managed pointers that we sent to the core need to be resent now! Core.gpgx_set_input_callback(_inputCallback); RefreshMemCallbacks(); - Core.gpgx_set_cdd_callback(cd_callback_handle); + Core.gpgx_set_cdd_callback(CDReadCallback); Core.gpgx_invalidate_pattern_cache(); Core.gpgx_set_draw_mask(_settings.GetDrawMask()); Core.gpgx_set_sprite_limit_enabled(!_settings.NoSpriteLimit); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ITraceable.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ITraceable.cs index be50c93d80e..1ee47f63b27 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ITraceable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.ITraceable.cs @@ -9,17 +9,18 @@ public partial class GPGX { private readonly ITraceable _tracer; - public class GPGXTraceBuffer : CallbackBasedTraceBuffer + public class GPGXTraceBuffer( + IDebuggable debuggableCore, + IMemoryDomains memoryDomains, + IDisassemblable disassembler) + : CallbackBasedTraceBuffer(debuggableCore, memoryDomains, disassembler, TRACE_HEADER) { private const string TRACE_HEADER = "M68K: PC, machine code, mnemonic, operands, registers (D0-D7, A0-A7, SR, USP), flags (XNZVC)"; - public GPGXTraceBuffer(IDebuggable debuggableCore, IMemoryDomains memoryDomains, IDisassemblable disassembler) - : base(debuggableCore, memoryDomains, disassembler, TRACE_HEADER) {} - protected override void TraceFromCallback(uint addr, uint value, uint flags) { var regs = DebuggableCore.GetCpuFlagsAndRegisters(); - uint pc = (uint)regs["M68K PC"].Value; + var pc = (uint)regs["M68K PC"].Value; var disasm = Disassembler.Disassemble(MemoryDomains.SystemBus, pc & 0xFFFFFF, out _); var sb = new StringBuilder(); @@ -36,6 +37,7 @@ protected override void TraceFromCallback(uint addr, uint value, uint flags) } } } + var sr = regs["M68K SR"].Value; sb.Append(string.Concat( (sr & 16) > 0 ? "X" : "x", diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IVideoProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IVideoProvider.cs index 1b65b94b859..86face68543 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IVideoProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.IVideoProvider.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; using BizHawk.Common; @@ -23,7 +21,7 @@ public partial class GPGX : IVideoProvider public int VsyncDenominator { get; } - private int[] _vidBuff = Array.Empty(); + private int[] _vidBuff = [ ]; private int _vwidth; private int _vheight; @@ -70,7 +68,7 @@ private void UpdateVideoInitial() _vwidth = VirtualWidth; _vheight = VirtualHeight; _vidBuff = new int[_vwidth * _vheight]; - for (int i = 0; i < _vidBuff.Length; i++) + for (var i = 0; i < _vidBuff.Length; i++) { _vidBuff[i] = unchecked((int)0xff000000); } @@ -86,8 +84,7 @@ private unsafe void UpdateVideo() using (_elf.EnterExit()) { - IntPtr src = IntPtr.Zero; - + var src = IntPtr.Zero; Core.gpgx_get_video(out var gpwidth, out var gpheight, out var gppitch, ref src); _vwidth = gpwidth; @@ -96,31 +93,41 @@ private unsafe void UpdateVideo() if (_settings.PadScreen320 && _vwidth < 320) _vwidth = 320; - int xpad = (_vwidth - gpwidth) / 2; - int xpad2 = _vwidth - gpwidth - xpad; + var xpad = (_vwidth - gpwidth) / 2; + var xpad2 = _vwidth - gpwidth - xpad; if (_vidBuff.Length < _vwidth * _vheight) + { _vidBuff = new int[_vwidth * _vheight]; + } - int rinc = (gppitch / 4) - gpwidth; + var rinc = (gppitch / 4) - gpwidth; fixed (int* pdst_ = _vidBuff) { - int* pdst = pdst_; - int* psrc = (int*)src; + var pdst = pdst_; + var psrc = (int*)src; - for (int j = 0; j < gpheight; j++) + for (var j = 0; j < gpheight; j++) { - for (int i = 0; i < xpad; i++) + for (var i = 0; i < xpad; i++) + { *pdst++ = unchecked((int)0xff000000); - for (int i = 0; i < gpwidth; i++) + } + + for (var i = 0; i < gpwidth; i++) + { *pdst++ = *psrc++; - for (int i = 0; i < xpad2; i++) + } + + for (var i = 0; i < xpad2; i++) + { *pdst++ = unchecked((int)0xff000000); + } + psrc += rinc; } } } } - } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.cs index e6739e5f163..40f6390b11c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGX.cs @@ -1,13 +1,12 @@ -using System; using System.Runtime.InteropServices; +using System.Linq; using BizHawk.BizInvoke; +using BizHawk.Common; using BizHawk.Common.PathExtensions; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Waterbox; -using BizHawk.Common; using BizHawk.Emulation.DiscSystem; -using System.Linq; namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx { @@ -25,11 +24,11 @@ public partial class GPGX : IEmulator, IVideoProvider, ISaveRam, IStatable, IReg [CoreConstructor(VSystemID.Raw.SG)] public GPGX(CoreLoadParameters lp) { - LoadCallback = load_archive; - _inputCallback = input_callback; + LoadCallback = LoadArchive; + _inputCallback = InputCallback; InitMemCallbacks(); // ExecCallback, ReadCallback, WriteCallback CDCallback = CDCallbackProc; - cd_callback_handle = CDRead; + CDReadCallback = CDRead; ServiceProvider = new BasicServiceProvider(this); // this can influence some things internally (autodetect romtype, etc) @@ -53,7 +52,7 @@ public GPGX(CoreLoadParameters lp) // three or six button? // http://www.sega-16.com/forum/showthread.php?4398-Forgotten-Worlds-giving-you-GAME-OVER-immediately-Fix-inside&highlight=forgotten%20worlds - //hack, don't use + // hack, don't use if (lp.Roms.FirstOrDefault()?.RomData.Length > 32 * 1024 * 1024) { throw new InvalidOperationException("ROM too big! Did you try to load a CD as a ROM?"); @@ -75,7 +74,7 @@ public GPGX(CoreLoadParameters lp) var callingConventionAdapter = CallingConventionAdapters.MakeWaterbox(new Delegate[] { LoadCallback, _inputCallback, ExecCallback, ReadCallback, WriteCallback, - CDCallback, cd_callback_handle, + CDCallback, CDReadCallback, }, _elf); using (_elf.EnterExit()) @@ -97,7 +96,7 @@ public GPGX(CoreLoadParameters lp) _cds = lp.Discs.Select(d => d.DiscData).ToArray(); _cdReaders = _cds.Select(c => new DiscSectorReader(c)).ToArray(); - Core.gpgx_set_cdd_callback(cd_callback_handle); + Core.gpgx_set_cdd_callback(CDReadCallback); DriveLightEnabled = true; } @@ -132,7 +131,7 @@ public GPGX(CoreLoadParameters lp) // and CdCallback Core.gpgx_set_cdd_callback(null); _elf.Seal(); - Core.gpgx_set_cdd_callback(cd_callback_handle); + Core.gpgx_set_cdd_callback(CDReadCallback); SetControllerDefinition(); @@ -158,27 +157,17 @@ public GPGX(CoreLoadParameters lp) _romfile = null; } - private static LibGPGX.INPUT_SYSTEM SystemForSystem(ControlType c) + private static LibGPGX.INPUT_SYSTEM SystemForSystem(ControlType c) => c switch { - switch (c) - { - default: - case ControlType.None: - return LibGPGX.INPUT_SYSTEM.SYSTEM_NONE; - case ControlType.Normal: - return LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; - case ControlType.Xea1p: - return LibGPGX.INPUT_SYSTEM.SYSTEM_XE_A1P; - case ControlType.Activator: - return LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR; - case ControlType.Teamplayer: - return LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER; - case ControlType.Wayplay: - return LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY; - case ControlType.Mouse: - return LibGPGX.INPUT_SYSTEM.SYSTEM_MOUSE; - } - } + ControlType.Normal => LibGPGX.INPUT_SYSTEM.SYSTEM_GAMEPAD, + ControlType.Xea1p => LibGPGX.INPUT_SYSTEM.SYSTEM_XE_A1P, + ControlType.Activator => LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR, + ControlType.Teamplayer => LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER, + ControlType.Wayplay => LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY, + ControlType.Mouse => LibGPGX.INPUT_SYSTEM.SYSTEM_MOUSE, + ControlType.Paddle => LibGPGX.INPUT_SYSTEM.SYSTEM_PADDLE, + _ => LibGPGX.INPUT_SYSTEM.SYSTEM_NONE + }; private readonly LibGPGX Core; private readonly WaterboxHost _elf; @@ -191,12 +180,13 @@ private static LibGPGX.INPUT_SYSTEM SystemForSystem(ControlType c) private readonly byte[] _romfile; - private bool _disposed = false; + private bool _disposed; - private LibGPGX.load_archive_cb LoadCallback; + // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable + private readonly LibGPGX.load_archive_cb LoadCallback; private bool _firmwareRequestFailed; - private readonly LibGPGX.InputData input = new LibGPGX.InputData(); + private readonly LibGPGX.InputData _input = new(); public enum ControlType { @@ -206,10 +196,10 @@ public enum ControlType Activator, Teamplayer, Wayplay, - Mouse + Mouse, + Paddle, } - /// /// core callback for file loading /// @@ -217,9 +207,9 @@ public enum ControlType /// buffer to load file to /// maximum length buffer can hold /// actual size loaded, or 0 on failure - private int load_archive(string filename, IntPtr buffer, int maxsize) + private int LoadArchive(string filename, IntPtr buffer, int maxsize) { - byte[] srcdata = null; + byte[] srcdata; if (buffer == IntPtr.Zero) { @@ -227,69 +217,66 @@ private int load_archive(string filename, IntPtr buffer, int maxsize) return 0; } - if (filename == "PRIMARY_ROM") + switch (filename) { - if (_romfile == null) - { + case "PRIMARY_ROM" when _romfile == null: Console.WriteLine("Couldn't satisfy firmware request PRIMARY_ROM because none was provided."); return 0; - } - srcdata = _romfile; - } - else if (filename is "PRIMARY_CD" or "SECONDARY_CD") - { - if (filename == "PRIMARY_CD" && _romfile != null) - { + case "PRIMARY_ROM": + srcdata = _romfile; + break; + case ("PRIMARY_CD" or "SECONDARY_CD") and "PRIMARY_CD" when _romfile != null: Console.WriteLine("Declined to satisfy firmware request PRIMARY_CD because PRIMARY_ROM was provided."); return 0; - } - else + case "PRIMARY_CD" or "SECONDARY_CD" when _cds == null: + Console.WriteLine("Couldn't satisfy firmware request {0} because none was provided.", filename); + return 0; + case "PRIMARY_CD" or "SECONDARY_CD": { - if (_cds == null) - { - Console.WriteLine("Couldn't satisfy firmware request {0} because none was provided.", filename); - return 0; - } srcdata = GetCDData(_cds[0]); if (srcdata.Length != maxsize) { Console.WriteLine("Couldn't satisfy firmware request {0} because of struct size ({1} != {2}).", filename, srcdata.Length, maxsize); return 0; } + + break; } - } - else - { - // use fromtend firmware interface - - FirmwareID? firmwareID = filename switch - { - "MD_BIOS" => new(system: VSystemID.Raw.GEN, firmware: "Boot"), - "CD_BIOS_EU" => new(system: VSystemID.Raw.GEN, firmware: "CD_BIOS_EU"), - "CD_BIOS_JP" => new(system: VSystemID.Raw.GEN, firmware: "CD_BIOS_JP"), - "CD_BIOS_US" => new(system: VSystemID.Raw.GEN, firmware: "CD_BIOS_US"), - "GG_BIOS" => new(system: VSystemID.Raw.GG, firmware: "Majesco"), - "MS_BIOS_EU" => new(system: VSystemID.Raw.SMS, firmware: "Export"), - "MS_BIOS_JP" => new(system: VSystemID.Raw.SMS, firmware: "Japan"), - "MS_BIOS_US" => new(system: VSystemID.Raw.SMS, firmware: "Export"), - _ => null - }; - - if (firmwareID != null) + default: { - // this path will be the most common PEBKAC error, so be a bit more vocal about the problem - srcdata = CoreComm.CoreFileProvider.GetFirmware(firmwareID.Value, "GPGX firmwares are usually required."); - if (srcdata == null) + // use fromtend firmware interface + + FirmwareID? firmwareID = filename switch + { + "MD_BIOS" => new(system: VSystemID.Raw.GEN, firmware: "Boot"), + "CD_BIOS_EU" => new(system: VSystemID.Raw.GEN, firmware: "CD_BIOS_EU"), + "CD_BIOS_JP" => new(system: VSystemID.Raw.GEN, firmware: "CD_BIOS_JP"), + "CD_BIOS_US" => new(system: VSystemID.Raw.GEN, firmware: "CD_BIOS_US"), + "GG_BIOS" => new(system: VSystemID.Raw.GG, firmware: "Majesco"), + "MS_BIOS_EU" => new(system: VSystemID.Raw.SMS, firmware: "Export"), + "MS_BIOS_JP" => new(system: VSystemID.Raw.SMS, firmware: "Japan"), + "MS_BIOS_US" => new(system: VSystemID.Raw.SMS, firmware: "Export"), + _ => null + }; + + if (firmwareID != null) + { + // this path will be the most common PEBKAC error, so be a bit more vocal about the problem + srcdata = CoreComm.CoreFileProvider.GetFirmware(firmwareID.Value, "GPGX firmwares are usually required."); + if (srcdata == null) + { + _firmwareRequestFailed = true; + Console.WriteLine($"Frontend couldn't satisfy firmware request {firmwareID}"); + return 0; + } + } + else { - _firmwareRequestFailed = true; - Console.WriteLine($"Frontend couldn't satisfy firmware request {firmwareID}"); + Console.WriteLine("Unrecognized firmware request {0}", filename); return 0; } - } - else - { - Console.WriteLine("Unrecognized firmware request {0}", filename); - return 0; + + break; } } @@ -300,18 +287,13 @@ private int load_archive(string filename, IntPtr buffer, int maxsize) Console.WriteLine("Couldn't satisfy firmware request {0} because {1} > {2}", filename, srcdata.Length, maxsize); return 0; } - else - { - Marshal.Copy(srcdata, 0, buffer, srcdata.Length); - Console.WriteLine("Firmware request {0} satisfied at size {1}", filename, srcdata.Length); - return srcdata.Length; - } - } - else - { - throw new InvalidOperationException("Unknown error processing firmware"); + + Marshal.Copy(srcdata, 0, buffer, srcdata.Length); + Console.WriteLine("Firmware request {0} satisfied at size {1}", filename, srcdata.Length); + return srcdata.Length; } + throw new InvalidOperationException("Unknown error processing firmware"); } private CoreComm CoreComm { get; } @@ -336,7 +318,8 @@ private void CDRead(int lba, IntPtr dest, bool subcode) } } - private readonly LibGPGX.cd_read_cb cd_callback_handle; + // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable + private readonly LibGPGX.cd_read_cb CDReadCallback; public static LibGPGX.CDData GetCDDataStruct(Disc cd) { @@ -394,61 +377,41 @@ public static unsafe byte[] GetCDData(Disc cd) /// /// size of native input struct /// - private int inputsize; + private int _inputSize; private GPGXControlConverter ControlConverter; private void SetControllerDefinition() { - inputsize = Marshal.SizeOf(typeof(LibGPGX.InputData)); - if (!Core.gpgx_get_control(input, inputsize)) + _inputSize = Marshal.SizeOf(typeof(LibGPGX.InputData)); + if (!Core.gpgx_get_control(_input, _inputSize)) { throw new Exception($"{nameof(Core.gpgx_get_control)}() failed"); } - ControlConverter = new(input, systemId: SystemId, cdButtons: _cds is not null); + ControlConverter = new(_input, systemId: SystemId, cdButtons: _cds is not null); ControllerDefinition = ControlConverter.ControllerDef; } public LibGPGX.INPUT_DEVICE[] GetDevices() - { - return (LibGPGX.INPUT_DEVICE[])input.dev.Clone(); - } + => (LibGPGX.INPUT_DEVICE[])_input.dev.Clone(); public bool IsMegaCD => _cds != null; - public class VDPView : IMonitor + public class VDPView(in LibGPGX.VDPView v, IMonitor m) : IMonitor { - private readonly IMonitor _m; - - public VDPView(in LibGPGX.VDPView v, IMonitor m) - { - _m = m; - VRAM = v.VRAM; - PatternCache = v.PatternCache; - ColorCache = v.ColorCache; - NTA = v.NTA; - NTB = v.NTB; - NTW = v.NTW; - } - - public IntPtr VRAM; - public IntPtr PatternCache; - public IntPtr ColorCache; - public LibGPGX.VDPNameTable NTA; - public LibGPGX.VDPNameTable NTB; - public LibGPGX.VDPNameTable NTW; - + public IntPtr VRAM = v.VRAM; + public IntPtr PatternCache = v.PatternCache; + public IntPtr ColorCache = v.ColorCache; + public LibGPGX.VDPNameTable NTA = v.NTA; + public LibGPGX.VDPNameTable NTB = v.NTB; + public LibGPGX.VDPNameTable NTW = v.NTW; public void Enter() - { - _m.Enter(); - } + => m.Enter(); public void Exit() - { - _m.Exit(); - } + => m.Exit(); } public VDPView UpdateVDPViewContext() @@ -459,14 +422,10 @@ public VDPView UpdateVDPViewContext() } public int AddDeepFreezeValue(int address, byte value) - { - return Core.gpgx_add_deepfreeze_list_entry(address, value); - } + => Core.gpgx_add_deepfreeze_list_entry(address, value); public void ClearDeepFreezeList() - { - Core.gpgx_clear_deepfreeze_list(); - } + => Core.gpgx_clear_deepfreeze_list(); public DisplayType Region { get; } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGXControlConverter.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGXControlConverter.cs index db32f515d9a..449dec13577 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGXControlConverter.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GPGXControlConverter.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; @@ -10,118 +9,118 @@ public class GPGXControlConverter { // this isn't all done - private struct CName + private readonly struct CName(string name, LibGPGX.INPUT_KEYS key) { - public readonly string Name; - public readonly LibGPGX.INPUT_KEYS Key; - public CName(string name, LibGPGX.INPUT_KEYS key) - { - Name = name; - Key = key; - } + public readonly string Name = name; + public readonly LibGPGX.INPUT_KEYS Key = key; } private static readonly CName[] SMS2B = -{ - new CName("Up", LibGPGX.INPUT_KEYS.INPUT_UP), - new CName("Down", LibGPGX.INPUT_KEYS.INPUT_DOWN), - new CName("Left", LibGPGX.INPUT_KEYS.INPUT_LEFT), - new CName("Right", LibGPGX.INPUT_KEYS.INPUT_RIGHT), - new CName("B1", LibGPGX.INPUT_KEYS.INPUT_BUTTON1), - new CName("B2", LibGPGX.INPUT_KEYS.INPUT_BUTTON2) - }; + [ + new("Up", LibGPGX.INPUT_KEYS.INPUT_UP), + new("Down", LibGPGX.INPUT_KEYS.INPUT_DOWN), + new("Left", LibGPGX.INPUT_KEYS.INPUT_LEFT), + new("Right", LibGPGX.INPUT_KEYS.INPUT_RIGHT), + new("B1", LibGPGX.INPUT_KEYS.INPUT_BUTTON1), + new("B2", LibGPGX.INPUT_KEYS.INPUT_BUTTON2), + ]; private static readonly CName[] GameGear = -{ - new CName("Up", LibGPGX.INPUT_KEYS.INPUT_UP), - new CName("Down", LibGPGX.INPUT_KEYS.INPUT_DOWN), - new CName("Left", LibGPGX.INPUT_KEYS.INPUT_LEFT), - new CName("Right", LibGPGX.INPUT_KEYS.INPUT_RIGHT), - new CName("B1", LibGPGX.INPUT_KEYS.INPUT_BUTTON1), - new CName("B2", LibGPGX.INPUT_KEYS.INPUT_BUTTON2), - new CName("Start", LibGPGX.INPUT_KEYS.INPUT_START), - }; + [ + new("Up", LibGPGX.INPUT_KEYS.INPUT_UP), + new("Down", LibGPGX.INPUT_KEYS.INPUT_DOWN), + new("Left", LibGPGX.INPUT_KEYS.INPUT_LEFT), + new("Right", LibGPGX.INPUT_KEYS.INPUT_RIGHT), + new("B1", LibGPGX.INPUT_KEYS.INPUT_BUTTON1), + new("B2", LibGPGX.INPUT_KEYS.INPUT_BUTTON2), + new("Start", LibGPGX.INPUT_KEYS.INPUT_START), + ]; private static readonly CName[] Genesis3 = - { - new CName("Up", LibGPGX.INPUT_KEYS.INPUT_UP), - new CName("Down", LibGPGX.INPUT_KEYS.INPUT_DOWN), - new CName("Left", LibGPGX.INPUT_KEYS.INPUT_LEFT), - new CName("Right", LibGPGX.INPUT_KEYS.INPUT_RIGHT), - new CName("A", LibGPGX.INPUT_KEYS.INPUT_A), - new CName("B", LibGPGX.INPUT_KEYS.INPUT_B), - new CName("C", LibGPGX.INPUT_KEYS.INPUT_C), - new CName("Start", LibGPGX.INPUT_KEYS.INPUT_START), - }; + [ + new("Up", LibGPGX.INPUT_KEYS.INPUT_UP), + new("Down", LibGPGX.INPUT_KEYS.INPUT_DOWN), + new("Left", LibGPGX.INPUT_KEYS.INPUT_LEFT), + new("Right", LibGPGX.INPUT_KEYS.INPUT_RIGHT), + new("A", LibGPGX.INPUT_KEYS.INPUT_A), + new("B", LibGPGX.INPUT_KEYS.INPUT_B), + new("C", LibGPGX.INPUT_KEYS.INPUT_C), + new("Start", LibGPGX.INPUT_KEYS.INPUT_START), + ]; private static readonly CName[] Genesis6 = - { - new CName("Up", LibGPGX.INPUT_KEYS.INPUT_UP), - new CName("Down", LibGPGX.INPUT_KEYS.INPUT_DOWN), - new CName("Left", LibGPGX.INPUT_KEYS.INPUT_LEFT), - new CName("Right", LibGPGX.INPUT_KEYS.INPUT_RIGHT), - new CName("A", LibGPGX.INPUT_KEYS.INPUT_A), - new CName("B", LibGPGX.INPUT_KEYS.INPUT_B), - new CName("C", LibGPGX.INPUT_KEYS.INPUT_C), - new CName("Start", LibGPGX.INPUT_KEYS.INPUT_START), - new CName("X", LibGPGX.INPUT_KEYS.INPUT_X), - new CName("Y", LibGPGX.INPUT_KEYS.INPUT_Y), - new CName("Z", LibGPGX.INPUT_KEYS.INPUT_Z), - new CName("Mode", LibGPGX.INPUT_KEYS.INPUT_MODE), - }; + [ + new("Up", LibGPGX.INPUT_KEYS.INPUT_UP), + new("Down", LibGPGX.INPUT_KEYS.INPUT_DOWN), + new("Left", LibGPGX.INPUT_KEYS.INPUT_LEFT), + new("Right", LibGPGX.INPUT_KEYS.INPUT_RIGHT), + new("A", LibGPGX.INPUT_KEYS.INPUT_A), + new("B", LibGPGX.INPUT_KEYS.INPUT_B), + new("C", LibGPGX.INPUT_KEYS.INPUT_C), + new("Start", LibGPGX.INPUT_KEYS.INPUT_START), + new("X", LibGPGX.INPUT_KEYS.INPUT_X), + new("Y", LibGPGX.INPUT_KEYS.INPUT_Y), + new("Z", LibGPGX.INPUT_KEYS.INPUT_Z), + new("Mode", LibGPGX.INPUT_KEYS.INPUT_MODE), + ]; private static readonly CName[] Mouse = - { - new CName("Mouse Left", LibGPGX.INPUT_KEYS.INPUT_MOUSE_LEFT), - new CName("Mouse Center", LibGPGX.INPUT_KEYS.INPUT_MOUSE_CENTER), - new CName("Mouse Right", LibGPGX.INPUT_KEYS.INPUT_MOUSE_RIGHT), - new CName("Mouse Start", LibGPGX.INPUT_KEYS.INPUT_MOUSE_START), - }; + [ + new("Mouse Left", LibGPGX.INPUT_KEYS.INPUT_MOUSE_LEFT), + new("Mouse Center", LibGPGX.INPUT_KEYS.INPUT_MOUSE_CENTER), + new("Mouse Right", LibGPGX.INPUT_KEYS.INPUT_MOUSE_RIGHT), + new("Mouse Start", LibGPGX.INPUT_KEYS.INPUT_MOUSE_START), + ]; private static readonly CName[] Lightgun = - { - new CName("Lightgun Trigger", LibGPGX.INPUT_KEYS.INPUT_MENACER_TRIGGER), - new CName("Lightgun Start", LibGPGX.INPUT_KEYS.INPUT_MENACER_START), - new CName("Lightgun B", LibGPGX.INPUT_KEYS.INPUT_MENACER_B), - new CName("Lightgun C", LibGPGX.INPUT_KEYS.INPUT_MENACER_C), - }; + [ + new("Lightgun Trigger", LibGPGX.INPUT_KEYS.INPUT_MENACER_TRIGGER), + new("Lightgun Start", LibGPGX.INPUT_KEYS.INPUT_MENACER_START), + new("Lightgun B", LibGPGX.INPUT_KEYS.INPUT_MENACER_B), + new("Lightgun C", LibGPGX.INPUT_KEYS.INPUT_MENACER_C), + ]; private static readonly CName[] Activator = - { - new CName("1L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_1L), - new CName("1U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_1U), - new CName("2L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_2L), - new CName("2U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_2U), - new CName("3L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_3L), - new CName("3U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_3U), - new CName("4L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_4L), - new CName("4U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_4U), - new CName("5L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_5L), - new CName("5U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_5U), - new CName("6L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_6L), - new CName("6U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_6U), - new CName("7L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_7L), - new CName("7U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_7U), - new CName("8L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_8L), - new CName("8U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_8U), - }; + [ + new("1L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_1L), + new("1U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_1U), + new("2L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_2L), + new("2U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_2U), + new("3L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_3L), + new("3U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_3U), + new("4L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_4L), + new("4U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_4U), + new("5L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_5L), + new("5U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_5U), + new("6L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_6L), + new("6U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_6U), + new("7L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_7L), + new("7U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_7U), + new("8L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_8L), + new("8U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_8U), + ]; private static readonly CName[] Xea1P = - { - new CName("XE A", LibGPGX.INPUT_KEYS.INPUT_XE_A), - new CName("XE B", LibGPGX.INPUT_KEYS.INPUT_XE_B), - new CName("XE C", LibGPGX.INPUT_KEYS.INPUT_XE_C), - new CName("XE D", LibGPGX.INPUT_KEYS.INPUT_XE_D), - new CName("XE Start", LibGPGX.INPUT_KEYS.INPUT_XE_START), - new CName("XE Select", LibGPGX.INPUT_KEYS.INPUT_XE_SELECT), - new CName("XE E1", LibGPGX.INPUT_KEYS.INPUT_XE_E1), - new CName("XE E2", LibGPGX.INPUT_KEYS.INPUT_XE_E2), - }; + [ + new("XE A", LibGPGX.INPUT_KEYS.INPUT_XE_A), + new("XE B", LibGPGX.INPUT_KEYS.INPUT_XE_B), + new("XE C", LibGPGX.INPUT_KEYS.INPUT_XE_C), + new("XE D", LibGPGX.INPUT_KEYS.INPUT_XE_D), + new("XE Start", LibGPGX.INPUT_KEYS.INPUT_XE_START), + new("XE Select", LibGPGX.INPUT_KEYS.INPUT_XE_SELECT), + new("XE E1", LibGPGX.INPUT_KEYS.INPUT_XE_E1), + new("XE E2", LibGPGX.INPUT_KEYS.INPUT_XE_E2), + ]; + + private static readonly CName[] Paddle = + [ + new("B1", LibGPGX.INPUT_KEYS.INPUT_BUTTON1) + ]; private LibGPGX.InputData _target; private IController _source; - private readonly List _converts = new List(); + private readonly List _converts = [ ]; public ControllerDefinition ControllerDef { get; } @@ -129,7 +128,7 @@ private void AddToController(int idx, int player, IEnumerable buttons) { foreach (var button in buttons) { - string name = $"P{player} {button.Name}"; + var name = $"P{player} {button.Name}"; ControllerDef.BoolButtons.Add(name); var buttonFlag = button.Key; _converts.Add(() => @@ -190,27 +189,49 @@ private void DoXea1PAnalog(int idx, int player) }); } + private void DoPaddleAnalog(int idx, int player) + { + ControllerDef.AddAxis($"P{player} Paddle", 0.RangeTo(255), 128); + + _converts.Add(() => + { + _target.analog[2 * idx] = (byte)_source.AxisValue($"P{player} Paddle"); + }); + } + public GPGXControlConverter(LibGPGX.InputData input, string systemId, bool cdButtons) { - Console.WriteLine("Genesis Controller report:"); + Console.WriteLine("GPGX Controller report:"); foreach (var e in input.system) Console.WriteLine(" S:{0}", e); foreach (var e in input.dev) Console.WriteLine(" D:{0}", e); - int player = 1; + var player = 1; - ControllerDef = new("GPGX Genesis Controller"); + ControllerDef = new(systemId switch + { + VSystemID.Raw.SMS or VSystemID.Raw.SG => "SMS Controller", + VSystemID.Raw.GG => "GG Controller", + VSystemID.Raw.GEN => "GPGX Genesis Controller", // GPGX in controller def name is more for backwards compat sake + _ => throw new InvalidOperationException(), + }); ControllerDef.BoolButtons.Add("Power"); ControllerDef.BoolButtons.Add("Reset"); + + if (systemId is VSystemID.Raw.SMS or VSystemID.Raw.SG) + { + ControllerDef.BoolButtons.Add("Pause"); + } + if (cdButtons) { ControllerDef.BoolButtons.Add("Previous Disk"); ControllerDef.BoolButtons.Add("Next Disk"); } - for (int i = 0; i < LibGPGX.MAX_DEVICES; i++) + for (var i = 0; i < LibGPGX.MAX_DEVICES; i++) { switch (input.dev[i]) { @@ -240,9 +261,13 @@ public GPGXControlConverter(LibGPGX.InputData input, string systemId, bool cdBut player++; break; case LibGPGX.INPUT_DEVICE.DEVICE_PADDLE: + AddToController(i, player, Paddle); + DoPaddleAnalog(i, player); + player++; + break; case LibGPGX.INPUT_DEVICE.DEVICE_SPORTSPAD: case LibGPGX.INPUT_DEVICE.DEVICE_TEREBI: - throw new Exception("Not implemented yet."); + throw new NotImplementedException(); case LibGPGX.INPUT_DEVICE.DEVICE_ACTIVATOR: AddToController(i, player, Activator); player++; @@ -256,7 +281,7 @@ public GPGXControlConverter(LibGPGX.InputData input, string systemId, bool cdBut // PICO isn't finished on the unmanaged side either throw new Exception("Sega PICO not implemented yet!"); default: - throw new Exception("Unknown Genesis control device! Something went wrong."); + throw new Exception("Unknown GPGX control device! Something went wrong."); } } @@ -280,6 +305,7 @@ public void Convert(IController source, LibGPGX.InputData target) /// must be set for proper lightgun operation /// public int ScreenWidth { get; set; } + /// /// must be set for proper lightgun operation /// diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GenDbgHlp.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GenDbgHlp.cs deleted file mode 100644 index cfeec6d2519..00000000000 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/GenDbgHlp.cs +++ /dev/null @@ -1,190 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.IO; - -using BizHawk.Common; -using BizHawk.Common.StringExtensions; - -namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx -{ - /* - * how to use: - * 0) get https://code.google.com/p/pdbparse/ - * 1) set modulename to the name of the dll file. - * 2) set symbolname to the name of a file that you produced by executing the following command: - * pdb_print_gvars.py [module pdb file] 0x00000000 > [output file] - * 3) set start to an address (relative to the beginning of the dll) to start scanning - * 4) set length to the byte length of the scan area - * 5) instantiate a GenDbWind, and use it to control the scanner while you manipulate the dll into various configurations. - * - * ideas for modification: - * 1) unhardcode config parameters and allow modifying them through the interface - * 2) read section sizes and positions from the dll itself instead of the start\length params - * 3) support an ignore list of symbols - */ - - public sealed class GenDbgHlp : IDisposable - { - // config - private const string modulename = "libgenplusgx.dll"; - private const string symbolname = @"D:\encodes\bizhawksrc\genplus-gx\libretro\msvc\Debug\vars.txt"; - private const int start = 0x0c7d8000 - 0x0c540000; - private const int length = 0x01082000; - - private bool disposed => DllBase == IntPtr.Zero; - - public void Dispose() - { - if (DllBase == IntPtr.Zero) return; // already freed - OSTailoredCode.LinkedLibManager.FreeByPtr(DllBase); - DllBase = IntPtr.Zero; - } - - private IntPtr DllBase; - - private readonly List SymbolsByAddr = new List(); - private readonly IDictionary SymbolsByName = new Dictionary(); - - private readonly byte[][] data = new byte[10][]; - - public void SaveState(int statenum) - { - if (disposed) throw new ObjectDisposedException(nameof(GenDbgHlp)); - - data[statenum] ??= new byte[length]; - - Marshal.Copy(DllBase + start, data[statenum], 0, length); - Console.WriteLine("State {0} saved", statenum); - } - - - public unsafe void Cmp(int statex, int statey) - { - if (disposed) throw new ObjectDisposedException(nameof(GenDbgHlp)); - List> bads = new List>(); - - byte[] x = data[statex]; - byte[] y = data[statey]; - - if (x == null || y == null) - { - Console.WriteLine("Missing State!"); - return; - } - - bool inrange = false; - int startsec = 0; - - fixed (byte* p0 = &x[0]) - fixed (byte* p1 = &y[0]) - { - for (int i = 0; i < length; i++) - { - if (!inrange) - { - if (p0[i] != p1[i]) - { - startsec = i; - inrange = true; - } - } - else - { - if (p0[i] == p1[i]) - { - bads.Add(new Tuple(startsec, i)); - inrange = false; - } - } - } - } - if (inrange) - bads.Add(new Tuple(startsec, length)); - - for (int i = 0; i < bads.Count; i++) - { - IntPtr addr = (IntPtr)(bads[i].Item1 + start); - int len = bads[i].Item2 - bads[i].Item1; - - var ss = Find(addr, len); - Console.WriteLine("0x{0:X8}[0x{1}]", (int)addr, len); - foreach (var sym in ss) - Console.WriteLine(sym); - Console.WriteLine(); - } - if (bads.Count == 0) - Console.WriteLine("Clean!"); - } - - public GenDbgHlp() - { - using (StreamReader sr = new StreamReader(symbolname)) - { - string line; - while ((line = sr.ReadLine()) != null) - { - Symbol sym = Symbol.FromString(line); - SymbolsByAddr.Add(sym); - SymbolsByName.Add(sym.name, sym); - } - SymbolsByAddr.Sort(); - } - DllBase = OSTailoredCode.LinkedLibManager.LoadOrThrow(modulename); - } - - public List Find(IntPtr addr, int length) - { - if (disposed) throw new ObjectDisposedException(nameof(GenDbgHlp)); - Symbol min = new Symbol { addr = addr }; - Symbol max = new Symbol { addr = addr + length }; - - int minidx = SymbolsByAddr.BinarySearch(min); - if (minidx < 0) - { - minidx = ~minidx; - // inexact matches return the first larger value, so find the next smallset one - if (minidx > 0) - minidx--; - } - int maxidx = SymbolsByAddr.BinarySearch(max); - if (maxidx < 0) - { - maxidx = ~maxidx; - if (maxidx > 0) - maxidx--; - } - return SymbolsByAddr.GetRange(minidx, maxidx - minidx + 1); - } - - public struct Symbol : IComparable - { - public IntPtr addr; - public string section; - public string name; - - public static Symbol FromString(string s) - { - string[] ss = s.Split(','); - if (ss.Length != 4) - throw new Exception(); - if (!ss[1].StartsWithOrdinal("0x")) - throw new Exception(); - Symbol ret = new Symbol - { - addr = (IntPtr)int.Parse(ss[1].Substring(2), System.Globalization.NumberStyles.AllowHexSpecifier), - section = ss[3], - name = ss[0] - }; - return ret; - } - - public int CompareTo(Symbol other) - { - return (int)this.addr - (int)other.addr; - } - - public override string ToString() => $"0x{(int)addr:X8} {name} ({section})"; - } - } -} diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/LibGPGX.cs b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/LibGPGX.cs index f6780b9b571..f315ec62de1 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/LibGPGX.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sega/gpgx64/LibGPGX.cs @@ -1,9 +1,9 @@ -using System; using System.Runtime.InteropServices; using BizHawk.BizInvoke; #pragma warning disable IDE1006 +#pragma warning disable CA1069 namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx { @@ -30,23 +30,33 @@ public enum Region : int Japan_PAL = 4 } + public enum ForceVDP : int + { + Disabled = 0, + NTSC = 1, + PAL = 2 + } + [StructLayout(LayoutKind.Sequential)] public struct InitSettings { public uint BackdropColor; public Region Region; + public ForceVDP ForceVDP; public ushort LowPassRange; public short LowFreq; public short HighFreq; public short LowGain; public short MidGain; public short HighGain; + public enum FilterType : byte { None = 0, LowPass = 1, ThreeBand = 2 } + public FilterType Filter; public INPUT_SYSTEM InputSystemA; @@ -60,6 +70,7 @@ public enum SMSFMSoundChipType : byte YM2413_MAME, YM2413_NUKED } + public SMSFMSoundChipType SMSFMSoundChip; public enum GenesisFMSoundChipType : byte @@ -70,6 +81,7 @@ public enum GenesisFMSoundChipType : byte Nuked_YM2612, Nuked_YM3438 } + public GenesisFMSoundChipType GenesisFMSoundChip; public bool SpritesAlwaysOnTop; @@ -83,6 +95,7 @@ public enum OverscanType : byte Horizontal = 1 << 1, All = Vertical | Horizontal, } + public OverscanType Overscan; public bool GGExtra; } @@ -126,19 +139,20 @@ public abstract bool gpgx_init( public enum INPUT_SYSTEM : byte { - SYSTEM_NONE = 0, // unconnected port - SYSTEM_MD_GAMEPAD = 1, // single 3-buttons or 6-buttons Control Pad - SYSTEM_MOUSE = 2, // Sega Mouse - SYSTEM_MENACER = 3, // Sega Menacer -- port B only - SYSTEM_JUSTIFIER = 4, // Konami Justifiers -- port B only - SYSTEM_XE_A1P = 5, // XE-A1P analog controller -- port A only - SYSTEM_ACTIVATOR = 6, // Sega Activator - SYSTEM_MS_GAMEPAD = 7, // single 2-buttons Control Pad -- Master System - SYSTEM_LIGHTPHASER = 8, // Sega Light Phaser -- Master System - SYSTEM_PADDLE = 9, // Sega Paddle Control -- Master System - SYSTEM_SPORTSPAD = 10, // Sega Sports Pad -- Master System - SYSTEM_TEAMPLAYER = 11, // Multi Tap -- Sega TeamPlayer - SYSTEM_WAYPLAY = 12, // Multi Tap -- EA 4-Way Play -- use both ports + SYSTEM_NONE = 0, // unconnected port + SYSTEM_GAMEPAD = 1, // single 2-buttons, 3-buttons or 6-buttons Control Pad + SYSTEM_MOUSE = 2, // Sega Mouse + SYSTEM_MENACER = 3, // Sega Menacer -- port B only + SYSTEM_JUSTIFIER = 4, // Konami Justifiers -- port B only + SYSTEM_XE_A1P = 5, // XE-A1P analog controller -- port A only + SYSTEM_ACTIVATOR = 6, // Sega Activator + SYSTEM_LIGHTPHASER = 7, // Sega Light Phaser -- Master System + SYSTEM_PADDLE = 8, // Sega Paddle Control -- Master System + SYSTEM_SPORTSPAD = 9, // Sega Sports Pad -- Master System + SYSTEM_GRAPHIC_BOARD = 10,// Sega Graphic Board + SYSTEM_MASTERTAP = 11, // Multi Tap -- Furrtek's Master Tap (unofficial) + SYSTEM_TEAMPLAYER = 12, // Multi Tap -- Sega TeamPlayer + SYSTEM_WAYPLAY = 13, // Multi Tap -- EA 4-Way Play -- use both ports } public enum INPUT_DEVICE : byte @@ -157,7 +171,6 @@ public enum INPUT_DEVICE : byte DEVICE_ACTIVATOR = 0x0a,// Activator } - public enum CDLog_AddrType { MDCART, RAM68k, RAMZ80, SRAM, @@ -174,7 +187,6 @@ public enum CDLog_Flags DMASource = 0x40, } - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void input_cb(); @@ -267,22 +279,27 @@ public class InputData { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public readonly INPUT_SYSTEM[] system = new INPUT_SYSTEM[2]; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_DEVICES)] public readonly INPUT_DEVICE[] dev = new INPUT_DEVICE[MAX_DEVICES]; + /// /// digital inputs /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_DEVICES)] public readonly INPUT_KEYS[] pad = new INPUT_KEYS[MAX_DEVICES]; + /// /// analog (x/y) /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_DEVICES * 2)] public readonly short[] analog = new short[MAX_DEVICES * 2]; + /// /// gun horizontal offset /// public int x_offset; + /// /// gun vertical offset /// @@ -290,8 +307,10 @@ public class InputData public void ClearAllBools() { - for (int i = 0; i < pad.Length; i++) + for (var i = 0; i < pad.Length; i++) + { pad[i] = 0; + } } } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Nymashock.cs b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Nymashock.cs index d78e7adfa22..5442f218ee1 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Nymashock.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Nymashock.cs @@ -8,7 +8,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX { - [PortedCore(CoreNames.Nymashock, "Mednafen Team", "1.29.0", "https://mednafen.github.io/releases/")] + [PortedCore(CoreNames.Nymashock, "Mednafen Team", "1.32.1", "https://mednafen.github.io/releases/")] public class Nymashock : NymaCore, IRegionable, ICycleTiming, IRedumpDiscChecksumInfo { public string RomDetails { get; } diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.IDebuggable.cs index 2d901ab2e53..8cb60cfb062 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.IDebuggable.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.IDisassemblable.cs b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.IDisassemblable.cs index cfeb69304ca..3d697e6fbbd 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.IDisassemblable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.IDisassemblable.cs @@ -12,13 +12,7 @@ public string Cpu set { } } - public IEnumerable AvailableCpus - { - get - { - yield return "R3000A"; - } - } + public IEnumerable AvailableCpus { get; } = [ "R3000A" ]; public string PCRegisterName => "pc"; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.ITraceable.cs b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.ITraceable.cs index f93a71b5ca8..74d5af3ef48 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.ITraceable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.ITraceable.cs @@ -1,4 +1,3 @@ -using System; using System.Text; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs index 9b20ba1998b..c63abf5bf51 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs @@ -10,7 +10,6 @@ //perhaps moving the slider is meaningless if the disc is ejected--it only affects what disc is inserted when the disc gets inserted!! yeah! this might could save us! //not exactly user friendly but maybe we can build it from there with a custom UI.. a disk-changer? dunno if that would help -using System; using System.ComponentModel; using System.Runtime.InteropServices; using System.IO; @@ -811,7 +810,7 @@ public bool FrameAdvance(IController controller, bool render, bool rendersound) LagCount++; //what happens to sound in this case? - if (render == false) + if (!render) { Frame++; return true; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/OctoshockDll.cs b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/OctoshockDll.cs index c413fa0ffe5..85e805d76bd 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/OctoshockDll.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/OctoshockDll.cs @@ -1,6 +1,5 @@ //TODO - make sure msvc builds with 32bit enums and get rid of the extra marshalling fluff here -using System; using System.Runtime.InteropServices; using System.Text; diff --git a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/PSF.cs b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/PSF.cs index 4ec469872b5..1bdb0c938f1 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/PSF.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Sony/PSX/PSF.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Collections.Generic; diff --git a/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/BizSwan.cs b/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/BizSwan.cs index 58a9b390837..31cd7f21fc0 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/BizSwan.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/BizSwan.cs @@ -1,4 +1,3 @@ -using System; using System.Text; using System.Runtime.InteropServices; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.ISaveRam.cs b/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.ISaveRam.cs index cb775adc3ab..b44c001a166 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.ISaveRam.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.ISaveRam.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.WonderSwan diff --git a/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.ISettable.cs b/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.ISettable.cs index c0c5e0d76f8..dd819cba496 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.ISettable.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.ISoundProvider.cs b/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.ISoundProvider.cs index fe8983b1c9d..a2009534116 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.ISoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.ISoundProvider.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.WonderSwan diff --git a/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.IStatable.cs b/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.IStatable.cs index 427d4fd14c6..31066bd3219 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.IStatable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.IStatable.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Runtime.InteropServices; diff --git a/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.cs b/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.cs index 044b411809d..96d3a9846a7 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/WonderSwan/WonderSwan.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/CoreInventory.cs b/src/BizHawk.Emulation.Cores/CoreInventory.cs index 6573150a4d7..a6515a34184 100644 --- a/src/BizHawk.Emulation.Cores/CoreInventory.cs +++ b/src/BizHawk.Emulation.Cores/CoreInventory.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Reflection; diff --git a/src/BizHawk.Emulation.Cores/CoreNames.cs b/src/BizHawk.Emulation.Cores/CoreNames.cs index bc7c0e38515..8c90317d99b 100644 --- a/src/BizHawk.Emulation.Cores/CoreNames.cs +++ b/src/BizHawk.Emulation.Cores/CoreNames.cs @@ -46,6 +46,7 @@ public static class CoreNames public const string Octoshock = "Octoshock"; public const string PceHawk = "PCEHawk"; public const string PicoDrive = "PicoDrive"; + public const string PUAE = "PUAE"; public const string QuickNes = "quickerNES"; public const string Sameboy = "SameBoy"; public const string Saturnus = "Saturnus"; diff --git a/src/BizHawk.Emulation.Cores/FileID.cs b/src/BizHawk.Emulation.Cores/FileID.cs index 59a77464674..05b415394b0 100644 --- a/src/BizHawk.Emulation.Cores/FileID.cs +++ b/src/BizHawk.Emulation.Cores/FileID.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Collections.Generic; diff --git a/src/BizHawk.Emulation.Cores/Libretro/Libretro.Api.cs b/src/BizHawk.Emulation.Cores/Libretro/Libretro.Api.cs index 038315cf95a..9cf2323fc79 100644 --- a/src/BizHawk.Emulation.Cores/Libretro/Libretro.Api.cs +++ b/src/BizHawk.Emulation.Cores/Libretro/Libretro.Api.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.BizInvoke; diff --git a/src/BizHawk.Emulation.Cores/Libretro/Libretro.IEmulator.cs b/src/BizHawk.Emulation.Cores/Libretro/Libretro.IEmulator.cs index e559b302222..872b5c96167 100644 --- a/src/BizHawk.Emulation.Cores/Libretro/Libretro.IEmulator.cs +++ b/src/BizHawk.Emulation.Cores/Libretro/Libretro.IEmulator.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Libretro/Libretro.IInputPollable.cs b/src/BizHawk.Emulation.Cores/Libretro/Libretro.IInputPollable.cs index 4602b3c836f..1f8b488e239 100644 --- a/src/BizHawk.Emulation.Cores/Libretro/Libretro.IInputPollable.cs +++ b/src/BizHawk.Emulation.Cores/Libretro/Libretro.IInputPollable.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; using static BizHawk.Emulation.Cores.Libretro.LibretroApi; diff --git a/src/BizHawk.Emulation.Cores/Libretro/Libretro.IMemoryDomains.cs b/src/BizHawk.Emulation.Cores/Libretro/Libretro.IMemoryDomains.cs index 1f26a620546..8d4960954b5 100644 --- a/src/BizHawk.Emulation.Cores/Libretro/Libretro.IMemoryDomains.cs +++ b/src/BizHawk.Emulation.Cores/Libretro/Libretro.IMemoryDomains.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Libretro/Libretro.ISoundProvider.cs b/src/BizHawk.Emulation.Cores/Libretro/Libretro.ISoundProvider.cs index e2557be88dd..914e5c6911b 100644 --- a/src/BizHawk.Emulation.Cores/Libretro/Libretro.ISoundProvider.cs +++ b/src/BizHawk.Emulation.Cores/Libretro/Libretro.ISoundProvider.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Libretro diff --git a/src/BizHawk.Emulation.Cores/Libretro/Libretro.IStatable.cs b/src/BizHawk.Emulation.Cores/Libretro/Libretro.IStatable.cs index eb19dfe6c9c..b11969c4284 100644 --- a/src/BizHawk.Emulation.Cores/Libretro/Libretro.IStatable.cs +++ b/src/BizHawk.Emulation.Cores/Libretro/Libretro.IStatable.cs @@ -1,44 +1,32 @@ -using System; using System.IO; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Libretro { - // not all Libretro cores implement savestates - // we use this so we can optionally register IStatable - // todo: this can probably be genericized - public class StatableLibretro : IStatable + // note: Not all Libretro cores implement savestates + public partial class LibretroHost : IStatable { - private readonly LibretroHost _host; - private readonly LibretroApi _api; - private readonly byte[] _stateBuf; - - public StatableLibretro(LibretroHost host, LibretroApi api, int maxSize) - { - _host = host; - _api = api; - _stateBuf = new byte[maxSize]; - } + private byte[] _stateBuf = [ ]; public bool AvoidRewind => false; public void SaveStateBinary(BinaryWriter writer) { - var len = checked((int)_api.retro_serialize_size()); + var len = checked((int)api.retro_serialize_size()); if (len > _stateBuf.Length) { throw new Exception("Core attempted to grow state size. This is not allowed per the libretro API."); } - _api.retro_serialize(_stateBuf, len); + api.retro_serialize(_stateBuf, len); writer.Write(len); writer.Write(_stateBuf, 0, len); // host variables - writer.Write(_host.Frame); - writer.Write(_host.LagCount); - writer.Write(_host.IsLagFrame); + writer.Write(Frame); + writer.Write(LagCount); + writer.Write(IsLagFrame); } public void LoadStateBinary(BinaryReader reader) @@ -49,13 +37,13 @@ public void LoadStateBinary(BinaryReader reader) throw new Exception("State buffer size exceeded the core's maximum state size!"); } - reader.Read(_stateBuf, 0, len); - _api.retro_unserialize(_stateBuf, len); + _ = reader.Read(_stateBuf, 0, len); + api.retro_unserialize(_stateBuf, len); // host variables - _host.Frame = reader.ReadInt32(); - _host.LagCount = reader.ReadInt32(); - _host.IsLagFrame = reader.ReadBoolean(); + Frame = reader.ReadInt32(); + LagCount = reader.ReadInt32(); + IsLagFrame = reader.ReadBoolean(); } } } diff --git a/src/BizHawk.Emulation.Cores/Libretro/Libretro.cs b/src/BizHawk.Emulation.Cores/Libretro/Libretro.cs index a6d163e5d0f..7636451cacf 100644 --- a/src/BizHawk.Emulation.Cores/Libretro/Libretro.cs +++ b/src/BizHawk.Emulation.Cores/Libretro/Libretro.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Runtime.InteropServices; using System.Text; @@ -12,7 +11,7 @@ namespace BizHawk.Emulation.Cores.Libretro // nb: multiple libretro cores could theoretically be ran at once // but all of them would need to be different cores, a core itself is single instance [PortedCore(CoreNames.Libretro, "CasualPokePlayer", singleInstance: true, isReleased: false)] - [ServiceNotApplicable(new[] { typeof(IDriveLight) })] + [ServiceNotApplicable([ typeof(IDriveLight) ])] public partial class LibretroHost { private static readonly LibretroBridge bridge; @@ -28,32 +27,24 @@ static LibretroHost() } private readonly LibretroApi api; - private IStatable _stateWrapper; - private readonly IntPtr cbHandler; - private readonly BridgeGuard _guard; - private class BridgeGuard : IMonitor + private class BridgeGuard(IntPtr parentHandler) : IMonitor { private static readonly object _sync = new(); private static IntPtr _activeHandler; private static int _refCount; - private readonly IntPtr _parentHandler; - - public BridgeGuard(IntPtr parentHandler) - => _parentHandler = parentHandler; - public void Enter() { lock (_sync) { if (_activeHandler == IntPtr.Zero) { - _activeHandler = _parentHandler; - bridge.LibretroBridge_SetGlobalCallbackHandler(_parentHandler); + _activeHandler = parentHandler; + bridge.LibretroBridge_SetGlobalCallbackHandler(parentHandler); } - else if (_activeHandler != _parentHandler) + else if (_activeHandler != parentHandler) { throw new InvalidOperationException("Multiple callback handlers cannot be active at once!"); } @@ -94,10 +85,9 @@ public LibretroHost(CoreComm comm, IGameInfo game, string corePath, bool analysi throw new Exception("Failed to create callback handler!"); } - _guard = new(cbHandler); - + var guard = new BridgeGuard(cbHandler); api = BizInvoker.GetInvoker( - new DynamicLibraryImportResolver(corePath, hasLimitedLifetime: false), _guard, CallingConventionAdapters.Native); + new DynamicLibraryImportResolver(corePath, hasLimitedLifetime: false), guard, CallingConventionAdapters.Native); _serviceProvider = new(this); @@ -140,23 +130,17 @@ public LibretroHost(CoreComm comm, IGameInfo game, string corePath, bool analysi } } - private class RetroData : IDisposable + private class RetroData(object o, long len = 0) : IDisposable { - private readonly GCHandle _handle; + private GCHandle _handle = GCHandle.Alloc(o, GCHandleType.Pinned); public IntPtr PinnedData => _handle.AddrOfPinnedObject(); - public long Length { get; } - - public RetroData(object o, long len = 0) - { - _handle = GCHandle.Alloc(o, GCHandleType.Pinned); - Length = len; - } + public long Length { get; } = len; public void Dispose() => _handle.Free(); } - private byte[] RetroString(string managedString) + private static byte[] RetroString(string managedString) { var ret = Encoding.UTF8.GetBytes(managedString); Array.Resize(ref ret, ret.Length + 1); @@ -205,11 +189,11 @@ private bool LoadHandler(RETRO_LOAD which, RetroData path = null, RetroData data success = api.retro_load_no_game(); break; case RETRO_LOAD.PATH: - game = new() { path = path.PinnedData }; + game = new() { path = path!.PinnedData }; success = api.retro_load_game(ref game); break; case RETRO_LOAD.DATA: - game = new() { path = path.PinnedData, data = data.PinnedData, size = data.Length }; + game = new() { path = path!.PinnedData, data = data!.PinnedData, size = data.Length }; success = api.retro_load_game(ref game); break; default: @@ -237,8 +221,11 @@ private bool LoadHandler(RETRO_LOAD which, RetroData path = null, RetroData data var len = checked((int)api.retro_serialize_size()); if (len > 0) { - _stateWrapper = new StatableLibretro(this, api, len); - _serviceProvider.Register(_stateWrapper); + _stateBuf = new byte[len]; + } + else + { + _serviceProvider.Unregister(); } _region = api.retro_get_region(); diff --git a/src/BizHawk.Emulation.Cores/Properties/Resources.cs b/src/BizHawk.Emulation.Cores/Properties/Resources.cs index 6a24c693316..7ba78a8d3f0 100644 --- a/src/BizHawk.Emulation.Cores/Properties/Resources.cs +++ b/src/BizHawk.Emulation.Cores/Properties/Resources.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common.IOExtensions; namespace BizHawk.Emulation.Cores.Properties { diff --git a/src/BizHawk.Emulation.Cores/Sound/CDAudio.cs b/src/BizHawk.Emulation.Cores/Sound/CDAudio.cs index 6a51a20da9c..08cb480c189 100644 --- a/src/BizHawk.Emulation.Cores/Sound/CDAudio.cs +++ b/src/BizHawk.Emulation.Cores/Sound/CDAudio.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; using BizHawk.Emulation.Common; using BizHawk.Emulation.DiscSystem; diff --git a/src/BizHawk.Emulation.Cores/Sound/DualSyncSound.cs b/src/BizHawk.Emulation.Cores/Sound/DualSyncSound.cs index 5974f33a872..69144f9b3a0 100644 --- a/src/BizHawk.Emulation.Cores/Sound/DualSyncSound.cs +++ b/src/BizHawk.Emulation.Cores/Sound/DualSyncSound.cs @@ -1,5 +1,4 @@ using BizHawk.Emulation.Common; -using System; namespace BizHawk.Emulation.Cores.Sound { diff --git a/src/BizHawk.Emulation.Cores/Sound/HuC6280PSG.cs b/src/BizHawk.Emulation.Cores/Sound/HuC6280PSG.cs index 4a7cf528b31..950e1bc2221 100644 --- a/src/BizHawk.Emulation.Cores/Sound/HuC6280PSG.cs +++ b/src/BizHawk.Emulation.Cores/Sound/HuC6280PSG.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using BizHawk.Common; @@ -104,7 +103,7 @@ private void WritePSGImmediate(int register, byte value) Channels[VoiceLatch].Volume = (byte)(value & 0x1F); Channels[VoiceLatch].Enabled = (value & 0x80) != 0; Channels[VoiceLatch].DDA = (value & 0x40) != 0; - if (Channels[VoiceLatch].Enabled == false && Channels[VoiceLatch].DDA) + if (!Channels[VoiceLatch].Enabled && Channels[VoiceLatch].DDA) { //for the soudn debugger, this might be a useful indication that a new note has begun.. but not for sure WaveTableWriteOffset = 0; @@ -114,7 +113,7 @@ private void WritePSGImmediate(int register, byte value) Channels[VoiceLatch].Panning = value; break; case 6: // Wave data - if (Channels[VoiceLatch].DDA == false) + if (!Channels[VoiceLatch].DDA) { Channels[VoiceLatch].Wave[WaveTableWriteOffset++] = (short)((value * 2047) - 32767); WaveTableWriteOffset &= 31; @@ -193,8 +192,8 @@ private void MixSamples(short[] samples, int start, int len) private void MixChannel(short[] samples, int start, int len, PSGChannel channel) { - if (channel.Enabled == false) return; - if (channel.DDA == false && channel.Volume == 0) return; + if (!channel.Enabled) return; + if (!channel.DDA && channel.Volume == 0) return; short[] wave = channel.Wave; int freq; @@ -283,4 +282,4 @@ private class QueuedCommand public long Time; } } -} \ No newline at end of file +} diff --git a/src/BizHawk.Emulation.Cores/Sound/MMC5Audio.cs b/src/BizHawk.Emulation.Cores/Sound/MMC5Audio.cs index 48bb0e9fcaf..9107858d48b 100644 --- a/src/BizHawk.Emulation.Cores/Sound/MMC5Audio.cs +++ b/src/BizHawk.Emulation.Cores/Sound/MMC5Audio.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Common.NumberExtensions; diff --git a/src/BizHawk.Emulation.Cores/Sound/OneBitBeeper.cs b/src/BizHawk.Emulation.Cores/Sound/OneBitBeeper.cs index a70d7e9d8be..7554efe6d45 100644 --- a/src/BizHawk.Emulation.Cores/Sound/OneBitBeeper.cs +++ b/src/BizHawk.Emulation.Cores/Sound/OneBitBeeper.cs @@ -1,4 +1,3 @@ -using System; using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Sound/SoundMixer.cs b/src/BizHawk.Emulation.Cores/Sound/SoundMixer.cs index 7754ac651e4..e1d4af4131a 100644 --- a/src/BizHawk.Emulation.Cores/Sound/SoundMixer.cs +++ b/src/BizHawk.Emulation.Cores/Sound/SoundMixer.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/Sound/Sunsoft5BAudio.cs b/src/BizHawk.Emulation.Cores/Sound/Sunsoft5BAudio.cs index 8f79032eb90..7d0f0d95584 100644 --- a/src/BizHawk.Emulation.Cores/Sound/Sunsoft5BAudio.cs +++ b/src/BizHawk.Emulation.Cores/Sound/Sunsoft5BAudio.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Common.NumberExtensions; diff --git a/src/BizHawk.Emulation.Cores/Sound/SyncSoundMixer.cs b/src/BizHawk.Emulation.Cores/Sound/SyncSoundMixer.cs index 333f250407c..dbf53e2af17 100644 --- a/src/BizHawk.Emulation.Cores/Sound/SyncSoundMixer.cs +++ b/src/BizHawk.Emulation.Cores/Sound/SyncSoundMixer.cs @@ -1,5 +1,5 @@ using BizHawk.Emulation.Common; -using System; + using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Sound/VRC6Alt.cs b/src/BizHawk.Emulation.Cores/Sound/VRC6Alt.cs index e95f4bf75d7..7be9ddebd3d 100644 --- a/src/BizHawk.Emulation.Cores/Sound/VRC6Alt.cs +++ b/src/BizHawk.Emulation.Cores/Sound/VRC6Alt.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Common.NumberExtensions; diff --git a/src/BizHawk.Emulation.Cores/Sound/YM2413.cs b/src/BizHawk.Emulation.Cores/Sound/YM2413.cs index 843cd71e422..5eb9ecce1e2 100644 --- a/src/BizHawk.Emulation.Cores/Sound/YM2413.cs +++ b/src/BizHawk.Emulation.Cores/Sound/YM2413.cs @@ -4,7 +4,7 @@ // TODO The savestate support here is very simplistic and incomplete. However, this does not result in desyncs as the YM2413 is write-only. // TODO This should eventually be replaced, due to 1) uncertain licensing terms 2) This is not a native C# implementation, but a naive port. -using System; + using BizHawk.Common; namespace BizHawk.Emulation.Cores.Components diff --git a/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs b/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs index 6145b3b08d5..532bb114b03 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/LibNymaCore.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.BizInvoke; @@ -182,7 +181,6 @@ public struct SystemInfo /// /// Set a callback to be called whenever the core calls MDFN_MakeFName for a firmware, so that we can load firmwares on demand /// - /// [BizImport(CC)] public abstract void SetFrontendFirmwareNotify(FrontendFirmwareNotify cb); @@ -208,7 +206,6 @@ public struct Track /// /// Callback to receive a disk TOC /// - /// /// Deposit a LibNymaCore.TOC here [UnmanagedFunctionPointer(CC)] public delegate void CDTOCCallback(int disk, IntPtr dest); diff --git a/src/BizHawk.Emulation.Cores/Waterbox/LibWaterboxCore.cs b/src/BizHawk.Emulation.Cores/Waterbox/LibWaterboxCore.cs index 035ac090e9a..1965ceedbc4 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/LibWaterboxCore.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/LibWaterboxCore.cs @@ -1,5 +1,5 @@ using BizHawk.BizInvoke; -using System; + using System.Runtime.InteropServices; namespace BizHawk.Emulation.Cores.Waterbox diff --git a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Cd.cs b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Cd.cs index 42c15e084f1..56d0e7a1505 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Cd.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Cd.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.Emulation.Common; using BizHawk.Emulation.DiscSystem; diff --git a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Controller.cs b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Controller.cs index 42f3c54155c..933e1b53bb3 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Controller.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Controller.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Settings.ComponentModel.cs b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Settings.ComponentModel.cs index be7b0379cb0..44f1b88b0e0 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Settings.ComponentModel.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Settings.ComponentModel.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; diff --git a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Settings.cs b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Settings.cs index c3995e39a94..b4a6bd828d7 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Settings.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.Settings.cs @@ -1,8 +1,8 @@ -using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.InteropServices; using System.Text; + +using BizHawk.Common; using BizHawk.Emulation.Common; using NymaTypes; @@ -215,7 +215,7 @@ protected string SettingsQuery(string name) return val; } - private unsafe void SettingsQuery(string name, IntPtr dest) + private void SettingsQuery(string name, IntPtr dest) { var val = SettingsQuery(name); var bytes = val is null ? Array.Empty() : Encoding.UTF8.GetBytes(val); @@ -223,9 +223,9 @@ private unsafe void SettingsQuery(string name, IntPtr dest) { throw new InvalidOperationException($"Value {val} for setting {name} was too long"); } - - new Span((void*)dest, 256).Clear(); - Marshal.Copy(bytes, 0, dest, bytes.Length); + var dstSpan = Util.UnsafeSpanFromPointer(ptr: dest, length: 256); + dstSpan.Clear(); + bytes.CopyTo(dstSpan); } private LibNymaCore.FrontendSettingQuery _settingsQueryDelegate; diff --git a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs index 02543259124..8d72141e41d 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/NymaCore.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Globalization; using System.IO; diff --git a/src/BizHawk.Emulation.Cores/Waterbox/ProxiedFile.cs b/src/BizHawk.Emulation.Cores/Waterbox/ProxiedFile.cs index b71b9513449..6b6b93de4ba 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/ProxiedFile.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/ProxiedFile.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.IO; namespace BizHawk.Emulation.Cores.Waterbox diff --git a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs index 0710d8b2205..b09862697c5 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxCore.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Linq; using System.Collections.Generic; @@ -13,6 +12,8 @@ namespace BizHawk.Emulation.Cores.Waterbox public abstract class WaterboxCore : IEmulator, IVideoProvider, ISoundProvider, IStatable, IInputPollable, ISaveRam { + private const int AUDIO_CHANNEL_COUNT = 2; + private LibWaterboxCore _core; protected WaterboxHost _exe; protected ICallingConventionAdapter _adapter; @@ -37,7 +38,7 @@ protected WaterboxCore(CoreComm comm, Configuration c) BufferWidth = c.DefaultWidth; BufferHeight = c.DefaultHeight; _videoBuffer = new int[c.MaxWidth * c.MaxHeight]; - _soundBuffer = new short[c.MaxSamples * 2]; + _soundBuffer = new short[AUDIO_CHANNEL_COUNT * c.MaxSamples]; //TODO rename prop to MaxSamplesPerChannel VsyncNumerator = c.DefaultFpsNumerator; VsyncDenominator = c.DefaultFpsDenominator; _serviceProvider = new BasicServiceProvider(this); @@ -206,6 +207,7 @@ public unsafe bool FrameAdvance(IController controller, bool render, bool render var frame = FrameAdvancePrep(controller, render, rendersound); frame.VideoBuffer = (IntPtr)vp; frame.SoundBuffer = (IntPtr)sp; + //TODO it seems no-one thought to let the core know the LENGTH of either buffer; is it actually writing past the end? --yoshi _core.FrameAdvance(frame); @@ -336,10 +338,20 @@ public void SetSyncMode(SyncSoundMode mode) } } + private string/*?*/ _finalCoreName = null; + + private string FinalCoreName => _finalCoreName ??= this.Attributes().CoreName; + public void GetSamplesSync(out short[] samples, out int nsamp) { samples = _soundBuffer; nsamp = _numSamples; + var maxPerChannel = samples.Length / AUDIO_CHANNEL_COUNT; + if (maxPerChannel < nsamp) + { + Util.DebugWriteLine($"FrameAdvance in Waterbox core {FinalCoreName} claimed to have written {AUDIO_CHANNEL_COUNT}x{nsamp} audio samples but buffer is only {AUDIO_CHANNEL_COUNT}x{maxPerChannel} long!"); + nsamp = maxPerChannel; + } } public void GetSamplesAsync(short[] samples) diff --git a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxHost.cs b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxHost.cs index cfe81d3f87f..4779521bf33 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxHost.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxHost.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Runtime.InteropServices; @@ -100,12 +99,12 @@ public ReadWriteWrapper(Stream backingStream, bool disposeStreamAfterUse = true) _handle = GCHandle.Alloc(this, GCHandleType.Weak); } - public unsafe IntPtr Read(IntPtr data, UIntPtr size) + public IntPtr Read(IntPtr data, UIntPtr size) { + var count = checked((int) size); try { - var count = (int)size; - var n = _backingSpanStream.Read(new((void*)data, count)); + var n = _backingSpanStream.Read(Util.UnsafeSpanFromPointer(ptr: data, length: count)); return Z.SS(n); } catch @@ -114,12 +113,12 @@ public unsafe IntPtr Read(IntPtr data, UIntPtr size) } } - public unsafe int Write(IntPtr data, UIntPtr size) + public int Write(IntPtr data, UIntPtr size) { + var count = checked((int) size); try { - var count = (int)size; - _backingSpanStream.Write(new((void*)data, count)); + _backingSpanStream.Write(Util.UnsafeSpanFromPointer(ptr: data, length: count)); return 0; } catch diff --git a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxHostNative.cs b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxHostNative.cs index 0d8d82e78c2..65a345db7a1 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxHostNative.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxHostNative.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.BizInvoke; diff --git a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxMemoryDomain.cs b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxMemoryDomain.cs index 63840d3a0ef..393fad05489 100644 --- a/src/BizHawk.Emulation.Cores/Waterbox/WaterboxMemoryDomain.cs +++ b/src/BizHawk.Emulation.Cores/Waterbox/WaterboxMemoryDomain.cs @@ -1,6 +1,5 @@ -using System; using System.Runtime.InteropServices; using BizHawk.BizInvoke; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/A26Schema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/A26Schema.cs index 0201dc9963a..f11bd51f2f5 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/A26Schema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/A26Schema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/A78Schema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/A78Schema.cs index 361e5a16f06..fe99ee1e79b 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/A78Schema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/A78Schema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/AppleIISchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/AppleIISchema.cs index 4c7975055df..8dbe94aed7d 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/AppleIISchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/AppleIISchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/C64Schema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/C64Schema.cs index e350af63f02..12f59f37f6f 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/C64Schema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/C64Schema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/ColecoSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/ColecoSchema.cs index 81d7e3b8fec..4aedd0d6241 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/ColecoSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/ColecoSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/DualGBSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/DualGBSchema.cs index 71c1fd0bdc5..86f08fd62a4 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/DualGBSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/DualGBSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/GBASchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/GBASchema.cs index 0b1373c792c..ec9974e202b 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/GBASchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/GBASchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/GBSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/GBSchema.cs index 3c282ed3332..e370755b4e3 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/GBSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/GBSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/GGLSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/GGLSchema.cs index cabb1d15475..46662b945ac 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/GGLSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/GGLSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/GenSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/GenSchema.cs index 1fbce3d2185..741a7d669f6 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/GenSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/GenSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/IntvSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/IntvSchema.cs index c128f4e0f93..4a1bd19586e 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/IntvSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/IntvSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/JaguarSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/JaguarSchema.cs index d3a3915ac67..f206796dbf3 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/JaguarSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/JaguarSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/LynxSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/LynxSchema.cs index 8373e2416ca..5f95a824326 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/LynxSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/LynxSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/N3DSSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/N3DSSchema.cs new file mode 100644 index 00000000000..55b365d126a --- /dev/null +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/N3DSSchema.cs @@ -0,0 +1,92 @@ +using System.Collections.Generic; +using System.Drawing; + +using BizHawk.Common; +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores +{ + [Schema(VSystemID.Raw.N3DS)] + public class N3DSSchema : IVirtualPadSchema + { + public IEnumerable GetPadSchemas(IEmulator core, Action showMessageBox) + { + yield return Controller(); + yield return Console(); + } + + private static PadSchema Controller() + { + static AxisSpec MakeSpec() + => new((-128).RangeTo(127), 0); + + return new PadSchema + { + Size = new Size(770, 435), + Buttons = + [ + new AnalogSchema(6, 14, "Circle Pad X") + { + Spec = MakeSpec(), + SecondarySpec = MakeSpec() + }, + + new AnalogSchema(6, 224, "C-Stick X") + { + Spec = MakeSpec(), + SecondarySpec = MakeSpec() + }, + + ButtonSchema.Up(294, 129), + ButtonSchema.Down(294, 172), + ButtonSchema.Left(282, 150), + ButtonSchema.Right(304, 150), + new ButtonSchema(292, 10, "L"), + new ButtonSchema(317, 10, "ZL"), + new ButtonSchema(710, 10, "R"), + new ButtonSchema(675, 10, "ZR"), + new ButtonSchema(685, 179, "Start"), + new ButtonSchema(685, 201, "Select"), + new ButtonSchema(685, 100, "Y"), + new ButtonSchema(709, 113, "B"), + new ButtonSchema(685, 76, "X"), + new ButtonSchema(710, 86, "A"), + + // Screen + new TargetedPairSchema(352, 35, "Touch X") + { + TargetSize = new Size(320, 240) + }, + new ButtonSchema(352, 10, "Touch") + ] + }; + } + + private static PadSchema Console() + { + return new ConsoleSchema + { + Size = new Size(240, 200), + Buttons = + [ + new ButtonSchema(8, 18, "Tilt"), + new ButtonSchema(43, 18, "Reset"), + + new SingleAxisSchema(8, 58, "Tilt X") + { + TargetSize = new Size(226, 69), + MinValue = 0, + MaxValue = 320 + }, + + new SingleAxisSchema(8, 128, "Tilt Y") + { + TargetSize = new Size(226, 69), + MinValue = 0, + MaxValue = 240 + } + ] + }; + } + } +} diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/N64Schema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/N64Schema.cs index 481573139b7..078cef350c5 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/N64Schema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/N64Schema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/NdsSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/NdsSchema.cs index 22965830c85..260d80a8ebe 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/NdsSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/NdsSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/NesSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/NesSchema.cs index fc9fccb088d..f5885d8f23a 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/NesSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/NesSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/NgpSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/NgpSchema.cs index 2e5c42010d9..16ec03e17dc 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/NgpSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/NgpSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/O2Schema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/O2Schema.cs index 7ea49912381..d47bb90c9f0 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/O2Schema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/O2Schema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/PSXSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/PSXSchema.cs index f2eb13e5d75..c02d6f1d03e 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/PSXSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/PSXSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/PceSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/PceSchema.cs index d9dbff0623a..29c510c9e4b 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/PceSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/PceSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/PcfxSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/PcfxSchema.cs index f561ec063ad..0b5b4d22ce5 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/PcfxSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/PcfxSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/SGBSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/SGBSchema.cs index 4f2a6daa518..dfea3575a2e 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/SGBSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/SGBSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/SaturnSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/SaturnSchema.cs index 68a61b75094..b751b22de78 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/SaturnSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/SaturnSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/SmsSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/SmsSchema.cs index 8753ab62942..a1624509afb 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/SmsSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/SmsSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/SnesSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/SnesSchema.cs index bf6cca9dd88..89be3c82311 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/SnesSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/SnesSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/TIC80Schema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/TIC80Schema.cs index 647e801d19e..8e3bf6cdba2 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/TIC80Schema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/TIC80Schema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/VECSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/VECSchema.cs index dfeabd79c0b..ce5c9b8c943 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/VECSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/VECSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/VirtualBoySchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/VirtualBoySchema.cs index c2776514d35..33f7901f079 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/VirtualBoySchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/VirtualBoySchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/WonderSwanSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/WonderSwanSchema.cs index 8eb20a10ebe..b964b8015f0 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/WonderSwanSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/WonderSwanSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/ZXSpectrumSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/ZXSpectrumSchema.cs index 42eaeb8767e..1ce8fe013fe 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/ZXSpectrumSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/ZXSpectrumSchema.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; diff --git a/src/BizHawk.Emulation.DiscSystem/API_MednaDisc.cs b/src/BizHawk.Emulation.DiscSystem/API_MednaDisc.cs index 4ada99f9b27..f7c212bf731 100644 --- a/src/BizHawk.Emulation.DiscSystem/API_MednaDisc.cs +++ b/src/BizHawk.Emulation.DiscSystem/API_MednaDisc.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.DiscSystem/Disc.cs b/src/BizHawk.Emulation.DiscSystem/Disc.cs index 5ce69c5e7f3..e06eb6cde23 100644 --- a/src/BizHawk.Emulation.DiscSystem/Disc.cs +++ b/src/BizHawk.Emulation.DiscSystem/Disc.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; // ARCHITECTURE NOTE: diff --git a/src/BizHawk.Emulation.DiscSystem/DiscDecoding.cs b/src/BizHawk.Emulation.DiscSystem/DiscDecoding.cs index af214f7cba5..f996c24a9b6 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscDecoding.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscDecoding.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.DiscSystem/DiscExceptions.cs b/src/BizHawk.Emulation.DiscSystem/DiscExceptions.cs index 8c9268519a8..065bb77778d 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscExceptions.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscExceptions.cs @@ -1,5 +1,3 @@ -using System; - // some old junk namespace BizHawk.Emulation.DiscSystem { diff --git a/src/BizHawk.Emulation.DiscSystem/DiscExtensions.cs b/src/BizHawk.Emulation.DiscSystem/DiscExtensions.cs index 067e639568c..c3fee8528c0 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscExtensions.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscExtensions.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.DiscSystem { public static class DiscExtensions diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/Blob_CHD.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/Blob_CHD.cs index 15394dcf6a1..00b6bd05d6a 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/Blob_CHD.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/Blob_CHD.cs @@ -1,4 +1,3 @@ -using System; using System.IO; namespace BizHawk.Emulation.DiscSystem diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/Blob_ECM.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/Blob_ECM.cs index 0b9b32c2cbe..e56b4bfa062 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/Blob_ECM.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/Blob_ECM.cs @@ -3,7 +3,6 @@ //TODO - make a background thread to validate the EDC. be sure to terminate thread when the Blob disposes //remember: may need another stream for that. the IBlob architecture doesn't demand multi-threading support -using System; using System.IO; using System.Collections.Generic; diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/Blob_WaveFile.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/Blob_WaveFile.cs index 9f28c2ed324..ec6bad2535a 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/Blob_WaveFile.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/Blob_WaveFile.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.IO; diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/Blob_ZeroPadAdapter.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/Blob_ZeroPadAdapter.cs index 16b3847c59c..92854aafedc 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/Blob_ZeroPadAdapter.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/Blob_ZeroPadAdapter.cs @@ -1,5 +1,3 @@ -using System; - //I have an ff9 disc which is truncated namespace BizHawk.Emulation.DiscSystem diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/IBlob.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/IBlob.cs index 9572ed2284e..ed7385bf2a4 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/IBlob.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/IBlob.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.DiscSystem { /// diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/RiffMaster.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/RiffMaster.cs index 56201fee4f0..2c2f6ffa16a 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/RiffMaster.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/Blobs/RiffMaster.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CCD_format.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CCD_format.cs index b947327d2f6..4f67776a518 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CCD_format.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CCD_format.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Globalization; using System.Collections.Generic; @@ -438,8 +437,8 @@ public static void Dump(Disc disc, string path) var buf2448 = new byte[2448]; var dsr = new DiscSectorReader(disc); - using var imgFile = File.OpenWrite(imgPath); - using var subFile = File.OpenWrite(subPath); + using var imgFile = File.Create(imgPath); + using var subFile = File.Create(subPath); var nLBA = disc.Sessions[disc.Sessions.Count - 1].LeadoutLBA; for (var lba = 0; lba < nLBA; lba++) { diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CDI_format.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CDI_format.cs index 76af9ce656a..3d0d024eed6 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CDI_format.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CDI_format.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CHD_format.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CHD_format.cs index 640068da2ba..4bd3d71e202 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CHD_format.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CHD_format.cs @@ -1,4 +1,3 @@ -using System; using System.Buffers.Binary; using System.Collections.Generic; using System.IO; @@ -878,7 +877,7 @@ public static void Dump(Disc disc, string path) throw new NotSupportedException("CHD does not support multisession discs"); } - using var fs = File.OpenWrite(path); + using var fs = File.Create(path); using var bw = new BinaryWriter(fs); // write header diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Compile.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Compile.cs index 451a0a8b60f..4d16e0ca222 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Compile.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Compile.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Collections.Generic; using System.Linq; diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Load.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Load.cs index b3c489a8706..80a7ffb89a8 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Load.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Load.cs @@ -17,7 +17,6 @@ //PREGAP commands are special : at the moment it is received, emit flat records with a different pregap structure //POSTGAP commands are special : TBD -using System; using System.IO; using System.Collections.Generic; using BizHawk.Common; diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Parse.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Parse.cs index 6831187ed24..1d3de8c1c54 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Parse.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Parse.cs @@ -1,6 +1,5 @@ //TODO - object initialization syntax cleanup -using System; using System.Text.RegularExpressions; using System.IO; diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_SynthExtras.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_SynthExtras.cs index 151e3fcf859..70d88d32a7f 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_SynthExtras.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_SynthExtras.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.DiscSystem.CUE { // extra synths using SS_Base, not used by CUEs but used for other formats diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Synths.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Synths.cs index 299ddd5e8dc..6e89618ea44 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Synths.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Synths.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.DiscSystem.CUE { internal abstract class SS_Base : ISectorSynthJob2448 diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Types.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Types.cs index 7b919527bfe..e4c221636fa 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Types.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CUE_Types.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.DiscSystem.CUE { [Flags] diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CueFileResolver.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CueFileResolver.cs index e5b83baf6d7..2f382223555 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CueFileResolver.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/CUE/CueFileResolver.cs @@ -1,8 +1,6 @@ -using System; using System.IO; using System.Collections.Generic; using System.Linq; -using BizHawk.Common.PathExtensions; namespace BizHawk.Emulation.DiscSystem.CUE { @@ -73,7 +71,9 @@ private MyFileInfo[] MyFileInfosFromFileInfos(FileInfo[] fis) /// public List Resolve(string path) { - var (targetFile, targetFragment, _) = path.SplitPathToDirFileAndExt(); + string targetFile = Path.GetFileName(path); + string targetFragment = Path.GetFileNameWithoutExtension(path); + DirectoryInfo di = null; MyFileInfo[] fileInfos; if (!string.IsNullOrEmpty(Path.GetDirectoryName(path))) diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/MDS_Format.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/MDS_Format.cs index b8a4b701335..1926e36ba3d 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/MDS_Format.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/MDS_Format.cs @@ -1,7 +1,7 @@ -using System; using System.Text; using System.IO; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using BizHawk.Common.PathExtensions; @@ -115,7 +115,7 @@ public AHeader Parse(Stream stream) var bc = EndianBitConverter.CreateForLittleEndian(); var header = new byte[88]; - stream.Read(header, 0, 88); + _ = stream.Read(header, offset: 0, count: header.Length); // stream size checked at callsite this.Signature = Encoding.ASCII.GetString(header.Take(16).ToArray()); this.Version = header.Skip(16).Take(2).ToArray(); @@ -339,7 +339,8 @@ public static AFile Parse(FileStream stream) for (var se = 0; se < aFile.Header.SessionCount; se++) { var sessionHeader = new byte[24]; - stream.Read(sessionHeader, 0, 24); + var bytesRead = stream.Read(sessionHeader, offset: 0, count: sessionHeader.Length); + Debug.Assert(bytesRead == sessionHeader.Length, "reached end-of-file while reading session header"); //sessionHeader.Reverse().ToArray(); var session = new ASession @@ -375,7 +376,8 @@ public static AFile Parse(FileStream stream) var trackHeader = new byte[80]; var track = new ATrack(); - stream.Read(trackHeader, 0, 80); + var bytesRead = stream.Read(trackHeader, offset: 0, count: trackHeader.Length); + Debug.Assert(bytesRead == trackHeader.Length, "reached end-of-file while reading track header"); track.Mode = trackHeader[0]; track.SubMode = trackHeader[1]; @@ -405,7 +407,8 @@ public static AFile Parse(FileStream stream) { var extHeader = new byte[8]; stream.Seek(track.ExtraOffset, SeekOrigin.Begin); - stream.Read(extHeader, 0, 8); + var bytesRead1 = stream.Read(extHeader, offset: 0, count: extHeader.Length); + Debug.Assert(bytesRead1 == extHeader.Length, "reached end-of-file while reading extra block of track"); track.ExtraBlock.Pregap = bc.ToInt32(extHeader.Take(4).ToArray()); track.ExtraBlock.Sectors = bc.ToInt32(extHeader.Skip(4).Take(4).ToArray()); stream.Seek(currPos, SeekOrigin.Begin); @@ -426,7 +429,8 @@ public static AFile Parse(FileStream stream) var foot = new byte[16]; stream.Seek(track.FooterOffset, SeekOrigin.Begin); - stream.Read(foot, 0, 16); + var bytesRead1 = stream.Read(foot, offset: 0, count: foot.Length); + Debug.Assert(bytesRead1 == foot.Length, "reached end-of-file while reading track footer"); var f = new AFooter { @@ -466,7 +470,8 @@ public static AFile Parse(FileStream stream) // read the filename - stream.Read(fname, 0, fname.Length); + var bytesRead2 = stream.Read(fname, offset: 0, count: fname.Length); + Debug.Assert(bytesRead2 == fname.Length, "reached end-of-file while reading track filename"); // if widechar is 1 filename is stored using 16-bit, otherwise 8-bit is used if (f.WideChar == 1) diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/NRG_format.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/NRG_format.cs index b7eda98fcf8..35484c49459 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/NRG_format.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/NRG_format.cs @@ -1,4 +1,3 @@ -using System; using System.Buffers.Binary; using System.IO; using System.Collections.Generic; diff --git a/src/BizHawk.Emulation.DiscSystem/DiscFormats/SBI_format.cs b/src/BizHawk.Emulation.DiscSystem/DiscFormats/SBI_format.cs index 5b38a77cf11..2519bd92d0e 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscFormats/SBI_format.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscFormats/SBI_format.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Collections.Generic; diff --git a/src/BizHawk.Emulation.DiscSystem/DiscHasher.cs b/src/BizHawk.Emulation.DiscSystem/DiscHasher.cs index d2d7f0d2d2c..c606696633f 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscHasher.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscHasher.cs @@ -1,5 +1,3 @@ -using System; - using BizHawk.Common; using BizHawk.Common.BufferExtensions; diff --git a/src/BizHawk.Emulation.DiscSystem/DiscIdentifier.cs b/src/BizHawk.Emulation.DiscSystem/DiscIdentifier.cs index 80a14f51e8f..a75a1a7f0c0 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscIdentifier.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscIdentifier.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/BizHawk.Emulation.DiscSystem/DiscJob.cs b/src/BizHawk.Emulation.DiscSystem/DiscJob.cs index 6c2c77c2cf8..d4adeadd644 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscJob.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscJob.cs @@ -1,4 +1,3 @@ -using System; using System.IO; namespace BizHawk.Emulation.DiscSystem diff --git a/src/BizHawk.Emulation.DiscSystem/DiscMountJob.cs b/src/BizHawk.Emulation.DiscSystem/DiscMountJob.cs index e3c053de40a..42558deda31 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscMountJob.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscMountJob.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using BizHawk.Common.PathExtensions; using BizHawk.Emulation.DiscSystem.CUE; diff --git a/src/BizHawk.Emulation.DiscSystem/DiscMountPolicy.cs b/src/BizHawk.Emulation.DiscSystem/DiscMountPolicy.cs index 353395abf61..cd8945944b2 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscMountPolicy.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscMountPolicy.cs @@ -1,4 +1,3 @@ - namespace BizHawk.Emulation.DiscSystem { /// diff --git a/src/BizHawk.Emulation.DiscSystem/DiscSectorReader.cs b/src/BizHawk.Emulation.DiscSystem/DiscSectorReader.cs index 79c2fbdaf9b..6218ac2bf7b 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscSectorReader.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscSectorReader.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.DiscSystem { public class DiscSectorReaderPolicy diff --git a/src/BizHawk.Emulation.DiscSystem/DiscStream.cs b/src/BizHawk.Emulation.DiscSystem/DiscStream.cs index ef9dda3f8a4..842279707cc 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscStream.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscStream.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.DiscSystem { public enum EDiscStreamView diff --git a/src/BizHawk.Emulation.DiscSystem/DiscSubQ.cs b/src/BizHawk.Emulation.DiscSystem/DiscSubQ.cs index 8e467c388eb..703993411b5 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscSubQ.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscSubQ.cs @@ -1,5 +1,3 @@ -using System; - //TODO - call on unmanaged code in mednadisc if available to do deinterleaving faster. be sure to benchmark it though.. //a decent little subcode reference diff --git a/src/BizHawk.Emulation.DiscSystem/DiscTypes.cs b/src/BizHawk.Emulation.DiscSystem/DiscTypes.cs index 57950f38bb6..8ed8ab3c28d 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscTypes.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscTypes.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.DiscSystem { /// diff --git a/src/BizHawk.Emulation.DiscSystem/DiscUtils.cs b/src/BizHawk.Emulation.DiscSystem/DiscUtils.cs index deb5ce6a905..456aad4fd40 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscUtils.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscUtils.cs @@ -1,5 +1,3 @@ -using System; - namespace BizHawk.Emulation.DiscSystem { public static class DiscUtils diff --git a/src/BizHawk.Emulation.DiscSystem/DiscoHawkLogic/AudioExtractor.cs b/src/BizHawk.Emulation.DiscSystem/DiscoHawkLogic/AudioExtractor.cs index 0a134d4027d..0f232be8c14 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscoHawkLogic/AudioExtractor.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscoHawkLogic/AudioExtractor.cs @@ -1,4 +1,3 @@ -using System; using System.Threading.Tasks; using System.IO; diff --git a/src/BizHawk.Emulation.DiscSystem/DiscoHawkLogic/DiscoHawkLogic.cs b/src/BizHawk.Emulation.DiscSystem/DiscoHawkLogic/DiscoHawkLogic.cs index c656c5fddb5..81c426fc4a4 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscoHawkLogic/DiscoHawkLogic.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscoHawkLogic/DiscoHawkLogic.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Threading; diff --git a/src/BizHawk.Emulation.DiscSystem/DiscoHawkLogic/ECMTest.cs b/src/BizHawk.Emulation.DiscSystem/DiscoHawkLogic/ECMTest.cs index d11f8170b4a..93d5051c10a 100644 --- a/src/BizHawk.Emulation.DiscSystem/DiscoHawkLogic/ECMTest.cs +++ b/src/BizHawk.Emulation.DiscSystem/DiscoHawkLogic/ECMTest.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/src/BizHawk.Emulation.DiscSystem/Internal/Jobs/Synthesize_A0A1A2_Job.cs b/src/BizHawk.Emulation.DiscSystem/Internal/Jobs/Synthesize_A0A1A2_Job.cs index 68365bb826a..a952831941d 100644 --- a/src/BizHawk.Emulation.DiscSystem/Internal/Jobs/Synthesize_A0A1A2_Job.cs +++ b/src/BizHawk.Emulation.DiscSystem/Internal/Jobs/Synthesize_A0A1A2_Job.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; //TODO - generate correct Q subchannel CRC diff --git a/src/BizHawk.Emulation.DiscSystem/Internal/Jobs/Synthesize_DiscTOC_From_RawTOCEntries_Job.cs b/src/BizHawk.Emulation.DiscSystem/Internal/Jobs/Synthesize_DiscTOC_From_RawTOCEntries_Job.cs index 6b48907bf00..81be1d044ea 100644 --- a/src/BizHawk.Emulation.DiscSystem/Internal/Jobs/Synthesize_DiscTOC_From_RawTOCEntries_Job.cs +++ b/src/BizHawk.Emulation.DiscSystem/Internal/Jobs/Synthesize_DiscTOC_From_RawTOCEntries_Job.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Emulation.DiscSystem diff --git a/src/BizHawk.Emulation.DiscSystem/Internal/Jobs/Synthesize_DiscTracks_From_DiscTOC_Job.cs b/src/BizHawk.Emulation.DiscSystem/Internal/Jobs/Synthesize_DiscTracks_From_DiscTOC_Job.cs index ed208d143cf..05744a19f8e 100644 --- a/src/BizHawk.Emulation.DiscSystem/Internal/Jobs/Synthesize_DiscTracks_From_DiscTOC_Job.cs +++ b/src/BizHawk.Emulation.DiscSystem/Internal/Jobs/Synthesize_DiscTracks_From_DiscTOC_Job.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Emulation.DiscSystem diff --git a/src/BizHawk.Emulation.DiscSystem/Internal/Jobs/Synthesize_Leadout_Job.cs b/src/BizHawk.Emulation.DiscSystem/Internal/Jobs/Synthesize_Leadout_Job.cs index b0925a0ff27..10cae531a8a 100644 --- a/src/BizHawk.Emulation.DiscSystem/Internal/Jobs/Synthesize_Leadout_Job.cs +++ b/src/BizHawk.Emulation.DiscSystem/Internal/Jobs/Synthesize_Leadout_Job.cs @@ -1,9 +1,6 @@ - - -//TODO - generate correct Q subchannel CRC - namespace BizHawk.Emulation.DiscSystem { + //TODO - generate correct Q subchannel CRC /// /// generates lead-out sectors according to very crude approximations diff --git a/src/BizHawk.Emulation.DiscSystem/Internal/SectorSynth.cs b/src/BizHawk.Emulation.DiscSystem/Internal/SectorSynth.cs index 723c6e01bde..05c295d923a 100644 --- a/src/BizHawk.Emulation.DiscSystem/Internal/SectorSynth.cs +++ b/src/BizHawk.Emulation.DiscSystem/Internal/SectorSynth.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace BizHawk.Emulation.DiscSystem diff --git a/src/BizHawk.Emulation.DiscSystem/LibChd.cs b/src/BizHawk.Emulation.DiscSystem/LibChd.cs index c3adbca8f20..6caede046c0 100644 --- a/src/BizHawk.Emulation.DiscSystem/LibChd.cs +++ b/src/BizHawk.Emulation.DiscSystem/LibChd.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.InteropServices; #pragma warning disable IDE1006 diff --git a/src/BizHawk.Tests.Testroms.GB.GambatteSuite/BizHawk.Tests.Testroms.GB.GambatteSuite.csproj b/src/BizHawk.Tests.Testroms.GB.GambatteSuite/BizHawk.Tests.Testroms.GB.GambatteSuite.csproj index 355afc4e45f..e34a2f78c13 100644 --- a/src/BizHawk.Tests.Testroms.GB.GambatteSuite/BizHawk.Tests.Testroms.GB.GambatteSuite.csproj +++ b/src/BizHawk.Tests.Testroms.GB.GambatteSuite/BizHawk.Tests.Testroms.GB.GambatteSuite.csproj @@ -1,6 +1,6 @@ - net8.0 + net48 @@ -9,6 +9,5 @@ - diff --git a/src/BizHawk.Tests.Testroms.GB.GambatteSuite/GambatteSuite.Cases.cs b/src/BizHawk.Tests.Testroms.GB.GambatteSuite/GambatteSuite.Cases.cs index b6815206878..6564955a047 100644 --- a/src/BizHawk.Tests.Testroms.GB.GambatteSuite/GambatteSuite.Cases.cs +++ b/src/BizHawk.Tests.Testroms.GB.GambatteSuite/GambatteSuite.Cases.cs @@ -382,35 +382,21 @@ public readonly struct GambatteHexStrTestCase "lycEnable.ff41_disable_2_dmg08_out0_cgb04c_out2 on DMG in GBHawk", "lycEnable.ff41_disable_2_dmg08_out0_cgb04c_out2 on DMG in SameBoy", "lycEnable.ff41_disable_2_dmg08_out0_cgb04c_out2 on DMG in SameBoy (no BIOS)", - "lycEnable.ff41_disable_ds_1_cgb04c_out1 on CGB_C in SameBoy", - "lycEnable.ff41_disable_ds_1_cgb04c_out1 on CGB_C in SameBoy (no BIOS)", "lycEnable.ff45_disable_ds_1_cgb04c_out1 on CGB_C in GBHawk", - "lycEnable.ff45_disable_ds_1_cgb04c_out1 on CGB_C in SameBoy", - "lycEnable.ff45_disable_ds_1_cgb04c_out1 on CGB_C in SameBoy (no BIOS)", "lycEnable.ff45_enable_weirdpoint_2_dmg08_out3_cgb04c_out1 on CGB_C in GBHawk", "lycEnable.ff45_enable_weirdpoint_3_dmg08_out1_cgb04c_out3 on DMG in GBHawk", - "lycEnable.ff45_enable_weirdpoint_ds_1_cgb04c_out3 on CGB_C in SameBoy", - "lycEnable.ff45_enable_weirdpoint_ds_1_cgb04c_out3 on CGB_C in SameBoy (no BIOS)", "lycEnable.ff45_enable_weirdpoint_ds_2_cgb04c_out1 on CGB_C in GBHawk", - "lycEnable.ff45_enable_weirdpoint_ds_2_cgb04c_out1 on CGB_C in SameBoy", - "lycEnable.ff45_enable_weirdpoint_ds_2_cgb04c_out1 on CGB_C in SameBoy (no BIOS)", "lycEnable.ff45_enable_weirdpoint_ds_3_cgb04c_out1 on CGB_C in GBHawk", - "lycEnable.ff45_enable_weirdpoint_ds_3_cgb04c_out1 on CGB_C in SameBoy", - "lycEnable.ff45_enable_weirdpoint_ds_3_cgb04c_out1 on CGB_C in SameBoy (no BIOS)", "lycEnable.ff45_enable_weirdpoint_ds_lcdoffset1_2_cgb04c_out0 on CGB_C in GBHawk", "lycEnable.ff45_enable_weirdpoint_ds_lcdoffset1_2_cgb04c_out0 on CGB_C in SameBoy", "lycEnable.ff45_enable_weirdpoint_ds_lcdoffset1_2_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", "lycEnable.ff45_enable_weirdpoint_ds_lcdoffset1_3_cgb04c_out0 on CGB_C in GBHawk", - "lycEnable.ff45_enable_weirdpoint_ds_lcdoffset1_4_cgb04c_out2 on CGB_C in SameBoy", - "lycEnable.ff45_enable_weirdpoint_ds_lcdoffset1_4_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", "lycEnable.ff45_enable_weirdpoint_lcdoffset1_2_cgb04c_out0 on CGB_C in GBHawk", "lycEnable.late_ff41_enable_after_m2int_disable_dmg08_cgb04c_out2 on CGB_C in GBHawk", "lycEnable.late_ff41_enable_after_m2int_disable_dmg08_cgb04c_out2 on DMG in GBHawk", "lycEnable.late_ff41_enable_after_m2int_dmg08_cgb04c_out2 on CGB_C in GBHawk", "lycEnable.late_ff41_enable_after_m2int_dmg08_cgb04c_out2 on DMG in GBHawk", "lycEnable.late_ff41_enable_ds_1_cgb04c_out3 on CGB_C in GBHawk", - "lycEnable.late_ff41_enable_ds_1_cgb04c_out3 on CGB_C in SameBoy", - "lycEnable.late_ff41_enable_ds_1_cgb04c_out3 on CGB_C in SameBoy (no BIOS)", "lycEnable.late_ff41_enable_ds_lcdoffset1_1_cgb04c_out2 on CGB_C in GBHawk", "lycEnable.late_ff41_enable_ds_lcdoffset1_2_cgb04c_out0 on CGB_C in SameBoy", "lycEnable.late_ff41_enable_ds_lcdoffset1_2_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", @@ -418,10 +404,6 @@ public readonly struct GambatteHexStrTestCase "lycEnable.late_ff45_enable_after_m2int_dmg08_cgb04c_out2 on CGB_C in GBHawk", "lycEnable.late_ff45_enable_after_m2int_dmg08_cgb04c_out2 on DMG in GBHawk", "lycEnable.late_ff45_enable_ds_1_cgb04c_out3 on CGB_C in GBHawk", - "lycEnable.late_ff45_enable_ds_1_cgb04c_out3 on CGB_C in SameBoy", - "lycEnable.late_ff45_enable_ds_1_cgb04c_out3 on CGB_C in SameBoy (no BIOS)", - "lycEnable.late_ff45_enable_ds_2_cgb04c_out1 on CGB_C in SameBoy", - "lycEnable.late_ff45_enable_ds_2_cgb04c_out1 on CGB_C in SameBoy (no BIOS)", "lycEnable.late_ff45_enable_ds_lcdoffset1_1_cgb04c_out2 on CGB_C in GBHawk", "lycEnable.late_ff45_enable_ds_lcdoffset1_2_cgb04c_out0 on CGB_C in SameBoy", "lycEnable.late_ff45_enable_ds_lcdoffset1_2_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", @@ -436,18 +418,12 @@ public readonly struct GambatteHexStrTestCase "lycEnable.lcdoff_lycirqen_4_dmg08_outE2_cgb04c_outE0 on DMG in SameBoy", "lycEnable.lcdoff_lycirqen_4_dmg08_outE2_cgb04c_outE0 on DMG in SameBoy (no BIOS)", "lycEnable.lyc_ff45_disable2_ds_1_cgb04c_out1 on CGB_C in GBHawk", - "lycEnable.lyc_ff45_disable2_ds_1_cgb04c_out1 on CGB_C in SameBoy", - "lycEnable.lyc_ff45_disable2_ds_1_cgb04c_out1 on CGB_C in SameBoy (no BIOS)", "lycEnable.lyc_ff45_trigger_delay_2_dmg08_out0_cgb04c_out2 on CGB_C in SameBoy", "lycEnable.lyc_ff45_trigger_delay_2_dmg08_out0_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", "lycEnable.lyc_ff45_trigger_delay_ds_1_cgb04c_out0 on CGB_C in GBHawk", // completely blank "lycEnable.lyc_ff45_trigger_delay_ds_2_cgb04c_out2 on CGB_C in GBHawk", // completely blank "lycEnable.lyc0_ff41_disable_2_dmg08_cgb04c_outE2 on CGB_C in GBHawk", - "lycEnable.lyc0_ff41_disable_ds_1_cgb04c_outE0 on CGB_C in SameBoy", - "lycEnable.lyc0_ff41_disable_ds_1_cgb04c_outE0 on CGB_C in SameBoy (no BIOS)", "lycEnable.lyc0_ff45_disable_ds_1_cgb04c_outE0 on CGB_C in GBHawk", - "lycEnable.lyc0_ff45_disable_ds_1_cgb04c_outE0 on CGB_C in SameBoy", - "lycEnable.lyc0_ff45_disable_ds_1_cgb04c_outE0 on CGB_C in SameBoy (no BIOS)", "lycEnable.lyc0_m1disable_2_dmg08_outE2_cgb04c_outE0 on CGB_C in GBHawk", "lycEnable.lyc0_m1disable_2_dmg08_outE2_cgb04c_outE0 on CGB_C in SameBoy", "lycEnable.lyc0_m1disable_2_dmg08_outE2_cgb04c_outE0 on CGB_C in SameBoy (no BIOS)", @@ -461,8 +437,6 @@ public readonly struct GambatteHexStrTestCase "lycEnable.lyc153_late_enable_m1disable_3_dmg08_cgb04c_outE0 on CGB_C in SameBoy", "lycEnable.lyc153_late_enable_m1disable_3_dmg08_cgb04c_outE0 on CGB_C in SameBoy (no BIOS)", "lycEnable.lyc153_late_ff41_enable_ds_1_cgb04c_outE2 on CGB_C in GBHawk", - "lycEnable.lyc153_late_ff41_enable_ds_1_cgb04c_outE2 on CGB_C in SameBoy", - "lycEnable.lyc153_late_ff41_enable_ds_1_cgb04c_outE2 on CGB_C in SameBoy (no BIOS)", "lycEnable.lyc153_late_ff41_enable_ds_lcdoffset1_1_cgb04c_outE2 on CGB_C in GBHawk", "lycEnable.lyc153_late_ff41_enable_ds_lcdoffset1_2_cgb04c_outE0 on CGB_C in SameBoy", "lycEnable.lyc153_late_ff41_enable_ds_lcdoffset1_2_cgb04c_outE0 on CGB_C in SameBoy (no BIOS)", @@ -471,8 +445,6 @@ public readonly struct GambatteHexStrTestCase "lycEnable.lyc153_late_ff45_enable_3_dmg08_outE0_cgb04c_outE2 on CGB_C in SameBoy", "lycEnable.lyc153_late_ff45_enable_3_dmg08_outE0_cgb04c_outE2 on CGB_C in SameBoy (no BIOS)", "lycEnable.lyc153_late_ff45_enable_3_dmg08_outE0_cgb04c_outE2 on DMG in GBHawk", - "lycEnable.lyc153_late_ff45_enable_ds_1_cgb04c_outE2 on CGB_C in SameBoy", - "lycEnable.lyc153_late_ff45_enable_ds_1_cgb04c_outE2 on CGB_C in SameBoy (no BIOS)", "lycEnable.lyc153_late_ff45_enable_ds_2_cgb04c_outE0 on CGB_C in GBHawk", "lycEnable.lyc153_late_ff45_enable_ds_3_cgb04c_outE0 on CGB_C in GBHawk", "lycEnable.lyc153_late_ff45_enable_ds_4_cgb04c_outE2 on CGB_C in GBHawk", @@ -512,8 +484,6 @@ public readonly struct GambatteHexStrTestCase "m0enable.disable_scx4_2_dmg08_out0_cgb04c_out2 on CGB_C in SameBoy", "m0enable.disable_scx4_2_dmg08_out0_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", "m0enable.disable_scx5_ds_2_cgb04c_out3 on CGB_C in GBHawk", - "m0enable.disable_scx5_ds_2_cgb04c_out3 on CGB_C in SameBoy", - "m0enable.disable_scx5_ds_2_cgb04c_out3 on CGB_C in SameBoy (no BIOS)", "m0enable.disable_scx7_2_dmg08_out0_cgb04c_out2 on CGB_C in SameBoy", "m0enable.disable_scx7_2_dmg08_out0_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", "m0enable.disable_scx7_2_dmg08_out0_cgb04c_out2 on DMG in GBHawk", @@ -553,6 +523,8 @@ public readonly struct GambatteHexStrTestCase "m0enable.lycdisable_ff41_2_dmg08_out2_cgb04c_out0 on DMG in GBHawk", "m0enable.lycdisable_ff41_2_dmg08_out2_cgb04c_out0 on DMG in SameBoy", "m0enable.lycdisable_ff41_2_dmg08_out2_cgb04c_out0 on DMG in SameBoy (no BIOS)", + "m0enable.lycdisable_ff41_scx1_ds_2_cgb04c_out0 on CGB_C in SameBoy", // was 2 + "m0enable.lycdisable_ff41_scx1_ds_2_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", // was 2 "m0enable.lycdisable_ff41_scx3_2_dmg08_out2_cgb04c_out0 on DMG in GBHawk", "m0enable.lycdisable_ff41_scx3_2_dmg08_out2_cgb04c_out0 on DMG in SameBoy", "m0enable.lycdisable_ff41_scx3_2_dmg08_out2_cgb04c_out0 on DMG in SameBoy (no BIOS)", @@ -562,6 +534,8 @@ public readonly struct GambatteHexStrTestCase "m0enable.lycdisable_ff45_scx1_2_dmg08_out2_cgb04c_out0 on CGB_C in SameBoy", "m0enable.lycdisable_ff45_scx1_2_dmg08_out2_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", "m0enable.lycdisable_ff45_scx1_ds_1_cgb04c_out2 on CGB_C in GBHawk", + "m0enable.lycdisable_ff45_scx1_ds_2_cgb04c_out0 on CGB_C in SameBoy", // was 2 + "m0enable.lycdisable_ff45_scx1_ds_2_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", // was 2 "m0enable.lycdisable_ff45_scx2_2_dmg08_out2_cgb04c_out0 on CGB_C in SameBoy", "m0enable.lycdisable_ff45_scx2_2_dmg08_out2_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", "m0enable.lycdisable_ff45_scx3_2_dmg08_out2_cgb04c_out0 on CGB_C in SameBoy", @@ -580,6 +554,8 @@ public readonly struct GambatteHexStrTestCase "m1.ly143_late_m2enable_ds_lcdoffset1_2_cgb04c_out1 on CGB_C in SameBoy", "m1.ly143_late_m2enable_ds_lcdoffset1_2_cgb04c_out1 on CGB_C in SameBoy (no BIOS)", "m1.lyc143_late_m0enable_lycdisable_2_dmg08_cgb04c_out1 on DMG in GBHawk", + "m1.lyc143_late_m0enable_lycdisable_ds_1_cgb04c_out1 on CGB_C in SameBoy", // was 3 + "m1.lyc143_late_m0enable_lycdisable_ds_1_cgb04c_out1 on CGB_C in SameBoy (no BIOS)", // was 3 "m1.lyc143_late_m2enable_lycdisable_1_dmg08_cgb04c_out3 on DMG in GBHawk", "m1.lyc143_late_m2enable_lycdisable_2_dmg08_cgb04c_out1 on CGB_C in SameBoy", "m1.lyc143_late_m2enable_lycdisable_2_dmg08_cgb04c_out1 on CGB_C in SameBoy (no BIOS)", @@ -639,14 +615,10 @@ public readonly struct GambatteHexStrTestCase "m2enable.late_enable_after_lycint_disable_2_dmg08_out0_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", "m2enable.late_enable_after_lycint_disable_2_dmg08_out0_cgb04c_out2 on DMG in GBHawk", "m2enable.late_enable_ds_1_cgb04c_out2 on CGB_C in GBHawk", - "m2enable.late_enable_ds_1_cgb04c_out2 on CGB_C in SameBoy", - "m2enable.late_enable_ds_1_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", "m2enable.late_enable_ds_lcdoffset1_1_cgb04c_out2 on CGB_C in GBHawk", "m2enable.late_enable_lcdoffset2_1_cgb04c_out2 on CGB_C in GBHawk", "m2enable.late_enable_lcdoffset3_1_cgb04c_out2 on CGB_C in GBHawk", "m2enable.late_enable_ly0_ds_1_cgb04c_out2 on CGB_C in GBHawk", - "m2enable.late_enable_ly0_ds_1_cgb04c_out2 on CGB_C in SameBoy", - "m2enable.late_enable_ly0_ds_1_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", "m2enable.late_enable_ly0_ds_lcdoffset1_1_cgb04c_out2 on CGB_C in SameBoy", "m2enable.late_enable_ly0_ds_lcdoffset1_1_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", "m2enable.late_enable_ly0_lcdoffset2_1_cgb04c_out2 on CGB_C in SameBoy", @@ -657,16 +629,12 @@ public readonly struct GambatteHexStrTestCase "m2enable.late_enable_m0disable_2_dmg08_out0_cgb04c_out2 on CGB_C in GBHawk", "m2enable.late_enable_m0disable_2_dmg08_out0_cgb04c_out2 on DMG in GBHawk", "m2enable.late_enable_m0disable_ds_1_cgb04c_out2 on CGB_C in GBHawk", - "m2enable.late_enable_m0disable_ds_1_cgb04c_out2 on CGB_C in SameBoy", - "m2enable.late_enable_m0disable_ds_1_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", "m2enable.late_enable_m1disable_ly0_1_dmg08_cgb04c_out2 on DMG in GBHawk", "m2enable.late_enable_m1disable_ly0_2_dmg08_out2_cgb04c_out0 on CGB_C in SameBoy", "m2enable.late_enable_m1disable_ly0_2_dmg08_out2_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", "m2enable.late_enable_m1disable_ly0_2_dmg08_out2_cgb04c_out0 on DMG in SameBoy", "m2enable.late_enable_m1disable_ly0_2_dmg08_out2_cgb04c_out0 on DMG in SameBoy (no BIOS)", "m2enable.late_enable_m1disable_ly0_ds_1_cgb04c_out2 on CGB_C in GBHawk", - "m2enable.late_enable_m1disable_ly0_ds_1_cgb04c_out2 on CGB_C in SameBoy", - "m2enable.late_enable_m1disable_ly0_ds_1_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", "m2enable.late_m1disable_ly0_1_dmg08_cgb04c_out2 on DMG in GBHawk", "m2enable.late_m1disable_ly0_2_dmg08_out2_cgb04c_out0 on CGB_C in SameBoy", "m2enable.late_m1disable_ly0_2_dmg08_out2_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", @@ -677,8 +645,6 @@ public readonly struct GambatteHexStrTestCase "m2enable.lyc0_late_m2enable_lycdisable_2_dmg08_out2_cgb04c_out0 on DMG in GBHawk", "m2enable.lyc0_late_m2enable_lycdisable_2_dmg08_out2_cgb04c_out0 on DMG in SameBoy", "m2enable.lyc0_late_m2enable_lycdisable_2_dmg08_out2_cgb04c_out0 on DMG in SameBoy (no BIOS)", - "m2enable.lyc0_late_m2enable_lycdisable_ds_1_cgb04c_out2 on CGB_C in SameBoy", - "m2enable.lyc0_late_m2enable_lycdisable_ds_1_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", "m2enable.lyc1_late_m2enable_lycdisable_1_dmg08_out0_cgb04c_out2 on CGB_C in GBHawk", "m2enable.lyc1_late_m2enable_lycdisable_1_dmg08_out0_cgb04c_out2 on CGB_C in SameBoy", "m2enable.lyc1_late_m2enable_lycdisable_1_dmg08_out0_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", @@ -686,11 +652,7 @@ public readonly struct GambatteHexStrTestCase "m2enable.lyc1_late_m2enable_lycdisable_ds_1_cgb04c_out2 on CGB_C in SameBoy", "m2enable.lyc1_late_m2enable_lycdisable_ds_1_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", "m2enable.lyc1_late_m2enable_lycdisable_ds_3_cgb04c_out2 on CGB_C in GBHawk", - "m2enable.lyc1_late_m2enable_lycdisable_ds_3_cgb04c_out2 on CGB_C in SameBoy", - "m2enable.lyc1_late_m2enable_lycdisable_ds_3_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", "m2enable.lyc1_m2irq_late_lyc255_ds_1_cgb04c_out2 on CGB_C in GBHawk", - "m2enable.lyc1_m2irq_late_lyc255_ds_1_cgb04c_out2 on CGB_C in SameBoy", - "m2enable.lyc1_m2irq_late_lyc255_ds_1_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", "m2enable.lyc1_m2irq_late_lycdisable_1_dmg08_cgb04c_out2 on CGB_C in SameBoy", "m2enable.lyc1_m2irq_late_lycdisable_1_dmg08_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", "m2enable.lyc1_m2irq_late_lycdisable_1_dmg08_cgb04c_out2 on DMG in GBHawk", @@ -703,6 +665,8 @@ public readonly struct GambatteHexStrTestCase "m2enable.m2_late_m0disable_1_dmg08_cgb04c_out2 on DMG in SameBoy (no BIOS)", "m2enable.m2_late_m0disable_ds_1_cgb04c_out2 on CGB_C in SameBoy", "m2enable.m2_late_m0disable_ds_1_cgb04c_out2 on CGB_C in SameBoy (no BIOS)", + "m2enable.m2_late_m1disable_ly0_ds_2_cgb04c_out0 on CGB_C in SameBoy", // was 2 + "m2enable.m2_late_m1disable_ly0_ds_2_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", // was 2 "m2int_m0irq.m2int_m0irq_scx3_ifw_ds_2_cgb04c_out0 on CGB_C in GBHawk", "m2int_m3stat.scx.late_scx4_ds_1_cgb04c_out3 on CGB_C in GBHawk", "m2int_m3stat.scx.late_scx4_ds_1_cgb04c_out3 on CGB_C in SameBoy", @@ -732,13 +696,7 @@ public readonly struct GambatteHexStrTestCase "miscmstatirq.lycstatwirq_trigger_m0_late_ly44_lyc44_08_40_4_dmg08_cgb04c_outE0 on DMG in GBHawk", "miscmstatirq.lycstatwirq_trigger_m0_late_ly44_lyc44_08_40_4_dmg08_cgb04c_outE0 on DMG in SameBoy", "miscmstatirq.lycstatwirq_trigger_m0_late_ly44_lyc44_08_40_4_dmg08_cgb04c_outE0 on DMG in SameBoy (no BIOS)", - "miscmstatirq.lycstatwirq_trigger_m0_late_ly44_lyc44_08_40_ds_1_cgb04c_outE0 on CGB_C in SameBoy", - "miscmstatirq.lycstatwirq_trigger_m0_late_ly44_lyc44_08_40_ds_1_cgb04c_outE0 on CGB_C in SameBoy (no BIOS)", - "miscmstatirq.lycstatwirq_trigger_m0_late_ly44_lyc44_08_40_ds_2_cgb04c_outE0 on CGB_C in SameBoy", - "miscmstatirq.lycstatwirq_trigger_m0_late_ly44_lyc44_08_40_ds_2_cgb04c_outE0 on CGB_C in SameBoy (no BIOS)", "miscmstatirq.lycstatwirq_trigger_m0_late_ly44_lyc44_08_40_ds_3_cgb04c_outE2 on CGB_C in GBHawk", - "miscmstatirq.lycstatwirq_trigger_m0_late_ly44_lyc44_08_40_ds_3_cgb04c_outE2 on CGB_C in SameBoy", - "miscmstatirq.lycstatwirq_trigger_m0_late_ly44_lyc44_08_40_ds_3_cgb04c_outE2 on CGB_C in SameBoy (no BIOS)", "miscmstatirq.lycstatwirq_trigger_m0_ly44_lyc44_00_40_dmg08_cgb04c_outE2 on DMG in GBHawk", "miscmstatirq.lycstatwirq_trigger_m0_ly44_lyc44_00_48_dmg08_cgb04c_outE2 on DMG in GBHawk", "miscmstatirq.lycstatwirq_trigger_m0_ly44_lyc44_08_40_dmg08_cgb04c_outE0 on CGB_C in SameBoy", @@ -802,10 +760,6 @@ public readonly struct GambatteHexStrTestCase "oamdma.late_sp00x_ds_2_cgb04c_out3 on CGB_C in GBHawk", "oamdma.late_sp00x_ds_2_cgb04c_out3 on CGB_C in SameBoy", "oamdma.late_sp00x_ds_2_cgb04c_out3 on CGB_C in SameBoy (no BIOS)", - "oamdma.late_sp00y_1_dmg08_cgb04c_out3 on CGB_C in SameBoy", - "oamdma.late_sp00y_1_dmg08_cgb04c_out3 on CGB_C in SameBoy (no BIOS)", - "oamdma.late_sp00y_1_dmg08_cgb04c_out3 on DMG in SameBoy", - "oamdma.late_sp00y_1_dmg08_cgb04c_out3 on DMG in SameBoy (no BIOS)", "oamdma.late_sp00y_2_dmg08_cgb04c_out0 on CGB_C in GBHawk", "oamdma.late_sp00y_2_dmg08_cgb04c_out0 on DMG in GBHawk", "oamdma.late_sp00y_ds_1_cgb04c_out3 on CGB_C in SameBoy", @@ -822,8 +776,6 @@ public readonly struct GambatteHexStrTestCase "oamdma.late_sp01x_ds_2_cgb04c_out3 on CGB_C in SameBoy (no BIOS)", "oamdma.late_sp01y_1_dmg08_cgb04c_out3 on CGB_C in SameBoy", "oamdma.late_sp01y_1_dmg08_cgb04c_out3 on CGB_C in SameBoy (no BIOS)", - "oamdma.late_sp01y_1_dmg08_cgb04c_out3 on DMG in SameBoy", - "oamdma.late_sp01y_1_dmg08_cgb04c_out3 on DMG in SameBoy (no BIOS)", "oamdma.late_sp01y_ds_1_cgb04c_out3 on CGB_C in SameBoy", "oamdma.late_sp01y_ds_1_cgb04c_out3 on CGB_C in SameBoy (no BIOS)", "oamdma.late_sp01y_ds_2_cgb04c_out0 on CGB_C in GBHawk", @@ -833,10 +785,6 @@ public readonly struct GambatteHexStrTestCase "oamdma.late_sp02x_2_dmg08_cgb04c_out3 on DMG in GBHawk", "oamdma.late_sp02x_2_dmg08_cgb04c_out3 on DMG in SameBoy", "oamdma.late_sp02x_2_dmg08_cgb04c_out3 on DMG in SameBoy (no BIOS)", - "oamdma.late_sp02y_1_dmg08_cgb04c_out3 on CGB_C in SameBoy", - "oamdma.late_sp02y_1_dmg08_cgb04c_out3 on CGB_C in SameBoy (no BIOS)", - "oamdma.late_sp02y_1_dmg08_cgb04c_out3 on DMG in SameBoy", - "oamdma.late_sp02y_1_dmg08_cgb04c_out3 on DMG in SameBoy (no BIOS)", "oamdma.late_sp02y_2_dmg08_cgb04c_out0 on CGB_C in GBHawk", "oamdma.late_sp02y_2_dmg08_cgb04c_out0 on DMG in GBHawk", "oamdma.late_sp39x_1_dmg08_cgb04c_out0 on CGB_C in GBHawk", @@ -855,8 +803,6 @@ public readonly struct GambatteHexStrTestCase "oamdma.late_sp39y_1_dmg08_cgb04c_out3 on CGB_C in SameBoy", "oamdma.late_sp39y_1_dmg08_cgb04c_out3 on CGB_C in SameBoy (no BIOS)", "oamdma.late_sp39y_1_dmg08_cgb04c_out3 on DMG in GBHawk", - "oamdma.late_sp39y_1_dmg08_cgb04c_out3 on DMG in SameBoy", - "oamdma.late_sp39y_1_dmg08_cgb04c_out3 on DMG in SameBoy (no BIOS)", "oamdma.late_sp39y_ds_1_cgb04c_out3 on CGB_C in GBHawk", "oamdma.late_sp39y_ds_1_cgb04c_out3 on CGB_C in SameBoy", "oamdma.late_sp39y_ds_1_cgb04c_out3 on CGB_C in SameBoy (no BIOS)", @@ -1156,6 +1102,8 @@ public readonly struct GambatteHexStrTestCase "oamdma.oamdma_srcA000_busypushA001_2_dmg08_cgb04c_out55FFAAFF on CGB_C in SameBoy", "oamdma.oamdma_srcA000_busypushA001_2_dmg08_cgb04c_out55FFAAFF on CGB_C in SameBoy (no BIOS)", "oamdma.oamdma_srcA000_busypushA001_2_dmg08_cgb04c_out55FFAAFF on DMG in GBHawk", + "oamdma.oamdma_srcA000_busypushA001_2_dmg08_cgb04c_out55FFAAFF on DMG in SameBoy", // was 5555AAFF + "oamdma.oamdma_srcA000_busypushA001_2_dmg08_cgb04c_out55FFAAFF on DMG in SameBoy (no BIOS)", // was 5555AAFF "oamdma.oamdma_srcA000_busypushA001_dmg08_cgb04c_out5576AA34 on CGB_C in GBHawk", "oamdma.oamdma_srcA000_busypushA001_dmg08_cgb04c_out5576AA34 on CGB_C in SameBoy", "oamdma.oamdma_srcA000_busypushA001_dmg08_cgb04c_out5576AA34 on CGB_C in SameBoy (no BIOS)", @@ -1166,6 +1114,8 @@ public readonly struct GambatteHexStrTestCase "oamdma.oamdma_srcA000_busypushC001_2_dmg08_out55AAFF34_cgb04c_outFFAAFF55 on CGB_C in SameBoy", "oamdma.oamdma_srcA000_busypushC001_2_dmg08_out55AAFF34_cgb04c_outFFAAFF55 on CGB_C in SameBoy (no BIOS)", "oamdma.oamdma_srcA000_busypushC001_2_dmg08_out55AAFF34_cgb04c_outFFAAFF55 on DMG in GBHawk", + "oamdma.oamdma_srcA000_busypushC001_2_dmg08_out55AAFF34_cgb04c_outFFAAFF55 on DMG in SameBoy", // was 5500FF34 + "oamdma.oamdma_srcA000_busypushC001_2_dmg08_out55AAFF34_cgb04c_outFFAAFF55 on DMG in SameBoy (no BIOS)", // was 5500FF34 "oamdma.oamdma_srcA000_busypushC001_dmg08_out55AA1234_cgb04c_out65AA1255 on CGB_C in GBHawk", "oamdma.oamdma_srcA000_busypushC001_dmg08_out55AA1234_cgb04c_out65AA1255 on CGB_C in SameBoy", "oamdma.oamdma_srcA000_busypushC001_dmg08_out55AA1234_cgb04c_out65AA1255 on CGB_C in SameBoy (no BIOS)", @@ -1230,6 +1180,8 @@ public readonly struct GambatteHexStrTestCase "oamdma.oamdma_srcBF00_busypushA001_2_dmg08_cgb04c_out55FFAAFF on CGB_C in SameBoy", "oamdma.oamdma_srcBF00_busypushA001_2_dmg08_cgb04c_out55FFAAFF on CGB_C in SameBoy (no BIOS)", "oamdma.oamdma_srcBF00_busypushA001_2_dmg08_cgb04c_out55FFAAFF on DMG in GBHawk", + "oamdma.oamdma_srcBF00_busypushA001_2_dmg08_cgb04c_out55FFAAFF on DMG in SameBoy", // was 5555AAFF + "oamdma.oamdma_srcBF00_busypushA001_2_dmg08_cgb04c_out55FFAAFF on DMG in SameBoy (no BIOS)", // was 5555AAFF "oamdma.oamdma_srcBF00_busypushA001_dmg08_cgb04c_out5576AA34 on CGB_C in GBHawk", "oamdma.oamdma_srcBF00_busypushA001_dmg08_cgb04c_out5576AA34 on CGB_C in SameBoy", "oamdma.oamdma_srcBF00_busypushA001_dmg08_cgb04c_out5576AA34 on CGB_C in SameBoy (no BIOS)", @@ -1240,6 +1192,8 @@ public readonly struct GambatteHexStrTestCase "oamdma.oamdma_srcBF00_busypushC001_2_dmg08_out55AAFF34_cgb04c_outFFAAFF55 on CGB_C in SameBoy", "oamdma.oamdma_srcBF00_busypushC001_2_dmg08_out55AAFF34_cgb04c_outFFAAFF55 on CGB_C in SameBoy (no BIOS)", "oamdma.oamdma_srcBF00_busypushC001_2_dmg08_out55AAFF34_cgb04c_outFFAAFF55 on DMG in GBHawk", + "oamdma.oamdma_srcBF00_busypushC001_2_dmg08_out55AAFF34_cgb04c_outFFAAFF55 on DMG in SameBoy", // was 5500FF34 + "oamdma.oamdma_srcBF00_busypushC001_2_dmg08_out55AAFF34_cgb04c_outFFAAFF55 on DMG in SameBoy (no BIOS)", // was 5500FF34 "oamdma.oamdma_srcBF00_busypushC001_dmg08_out55AA1234_cgb04c_out65AA1255 on CGB_C in GBHawk", "oamdma.oamdma_srcBF00_busypushC001_dmg08_out55AA1234_cgb04c_out65AA1255 on CGB_C in SameBoy", "oamdma.oamdma_srcBF00_busypushC001_dmg08_out55AA1234_cgb04c_out65AA1255 on CGB_C in SameBoy (no BIOS)", @@ -2014,8 +1968,6 @@ public readonly struct GambatteHexStrTestCase "window.late_disable_1_dmg08_out3_cgb04c_out0 on CGB_C in GBHawk", "window.late_disable_1_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy", "window.late_disable_1_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", - "window.late_disable_1_dmg08_out3_cgb04c_out0 on DMG in SameBoy", - "window.late_disable_1_dmg08_out3_cgb04c_out0 on DMG in SameBoy (no BIOS)", "window.late_disable_ds_1_cgb04c_out0 on CGB_C in GBHawk", "window.late_disable_ds_1_cgb04c_out0 on CGB_C in SameBoy", "window.late_disable_ds_1_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", @@ -2049,50 +2001,45 @@ public readonly struct GambatteHexStrTestCase "window.late_disable_late_scx00_wx10_ds_1_cgb04c_out0 on CGB_C in SameBoy", "window.late_disable_late_scx00_wx10_ds_1_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", "window.late_disable_late_scx03_wx0f_1_dmg08_cgb04c_out0 on CGB_C in GBHawk", + "window.late_disable_late_scx03_wx0f_1_dmg08_cgb04c_out0 on CGB_C in SameBoy", // was 3 + "window.late_disable_late_scx03_wx0f_1_dmg08_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", // was 3 "window.late_disable_late_scx03_wx0f_1_dmg08_cgb04c_out0 on DMG in GBHawk", "window.late_disable_late_scx03_wx0f_2_dmg08_out3_cgb04c_out0 on CGB_C in GBHawk", "window.late_disable_late_scx03_wx0f_2_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy", "window.late_disable_late_scx03_wx0f_2_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", - "window.late_disable_late_scx03_wx0f_2_dmg08_out3_cgb04c_out0 on DMG in SameBoy", - "window.late_disable_late_scx03_wx0f_2_dmg08_out3_cgb04c_out0 on DMG in SameBoy (no BIOS)", "window.late_disable_late_scx03_wx10_1_dmg08_cgb04c_out0 on CGB_C in GBHawk", "window.late_disable_late_scx03_wx10_1_dmg08_cgb04c_out0 on DMG in GBHawk", "window.late_disable_late_scx03_wx10_2_dmg08_out3_cgb04c_out0 on CGB_C in GBHawk", - "window.late_disable_late_scx03_wx10_2_dmg08_out3_cgb04c_out0 on DMG in SameBoy", - "window.late_disable_late_scx03_wx10_2_dmg08_out3_cgb04c_out0 on DMG in SameBoy (no BIOS)", + "window.late_disable_late_scx03_wx10_2_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy", // was 3 + "window.late_disable_late_scx03_wx10_2_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", // was 3 "window.late_disable_late_scx03_wx11_1_dmg08_cgb04c_out0 on CGB_C in GBHawk", "window.late_disable_late_scx03_wx11_1_dmg08_cgb04c_out0 on DMG in GBHawk", "window.late_disable_late_scx03_wx11_2_dmg08_out3_cgb04c_out0 on CGB_C in GBHawk", - "window.late_disable_late_scx03_wx11_2_dmg08_out3_cgb04c_out0 on CGB_C in GBHawk", - "window.late_disable_late_scx03_wx11_2_dmg08_out3_cgb04c_out0 on DMG in SameBoy", - "window.late_disable_late_scx03_wx11_2_dmg08_out3_cgb04c_out0 on DMG in SameBoy (no BIOS)", - "window.late_disable_late_scx03_wx12_1_dmg08_cgb04c_out0 on CGB_C in GBHawk", + "window.late_disable_late_scx03_wx11_2_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy", // was 3 + "window.late_disable_late_scx03_wx11_2_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", // was 3 "window.late_disable_late_scx03_wx12_1_dmg08_cgb04c_out0 on CGB_C in GBHawk", + "window.late_disable_late_scx03_wx12_1_dmg08_cgb04c_out0 on CGB_C in SameBoy", // was 3 + "window.late_disable_late_scx03_wx12_1_dmg08_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", // was 3 "window.late_disable_late_scx03_wx12_1_dmg08_cgb04c_out0 on DMG in GBHawk", - "window.late_disable_late_scx03_wx12_1_dmg08_cgb04c_out0 on DMG in GBHawk", - "window.late_disable_late_scx03_wx12_2_dmg08_cgb04c_out3 on DMG in SameBoy", - "window.late_disable_late_scx03_wx12_2_dmg08_cgb04c_out3 on DMG in SameBoy (no BIOS)", "window.late_disable_scx2_0_dmg08_cgb04c_out0 on CGB_C in GBHawk", + "window.late_disable_scx2_0_dmg08_cgb04c_out0 on CGB_C in SameBoy", // was 3 + "window.late_disable_scx2_0_dmg08_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", // was 3 "window.late_disable_scx2_0_dmg08_cgb04c_out0 on DMG in GBHawk", "window.late_disable_scx2_1_dmg08_out3_cgb04c_out0 on CGB_C in GBHawk", "window.late_disable_scx2_1_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy", "window.late_disable_scx2_1_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", - "window.late_disable_scx2_1_dmg08_out3_cgb04c_out0 on DMG in SameBoy", - "window.late_disable_scx2_1_dmg08_out3_cgb04c_out0 on DMG in SameBoy (no BIOS)", "window.late_disable_scx3_0_dmg08_cgb04c_out0 on CGB_C in GBHawk", + "window.late_disable_scx3_0_dmg08_cgb04c_out0 on CGB_C in SameBoy", // was 3 + "window.late_disable_scx3_0_dmg08_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", // was 3 "window.late_disable_scx3_0_dmg08_cgb04c_out0 on DMG in GBHawk", "window.late_disable_scx3_1_dmg08_out3_cgb04c_out0 on CGB_C in GBHawk", "window.late_disable_scx3_1_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy", "window.late_disable_scx3_1_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", - "window.late_disable_scx3_1_dmg08_out3_cgb04c_out0 on DMG in SameBoy", - "window.late_disable_scx3_1_dmg08_out3_cgb04c_out0 on DMG in SameBoy (no BIOS)", "window.late_disable_scx5_0_dmg08_cgb04c_out0 on CGB_C in GBHawk", "window.late_disable_scx5_0_dmg08_cgb04c_out0 on DMG in GBHawk", "window.late_disable_scx5_1_dmg08_out3_cgb04c_out0 on CGB_C in GBHawk", "window.late_disable_scx5_1_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy", "window.late_disable_scx5_1_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", - "window.late_disable_scx5_1_dmg08_out3_cgb04c_out0 on DMG in SameBoy", - "window.late_disable_scx5_1_dmg08_out3_cgb04c_out0 on DMG in SameBoy (no BIOS)", "window.late_disable_scx5_ds_1_cgb04c_out0 on CGB_C in GBHawk", "window.late_disable_scx5_ds_1_cgb04c_out0 on CGB_C in SameBoy", "window.late_disable_scx5_ds_1_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", @@ -2103,8 +2050,6 @@ public readonly struct GambatteHexStrTestCase "window.late_disable_wx0f_1_dmg08_out3_cgb04c_out0 on CGB_C in GBHawk", "window.late_disable_wx0f_1_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy", "window.late_disable_wx0f_1_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", - "window.late_disable_wx0f_1_dmg08_out3_cgb04c_out0 on DMG in SameBoy", - "window.late_disable_wx0f_1_dmg08_out3_cgb04c_out0 on DMG in SameBoy (no BIOS)", "window.late_enable_afterVblank_2_dmg08_out3_cgb04c_out0 on CGB_C in GBHawk", "window.late_enable_afterVblank_2_dmg08_out3_cgb04c_out0 on DMG in SameBoy", "window.late_enable_afterVblank_2_dmg08_out3_cgb04c_out0 on DMG in SameBoy (no BIOS)", @@ -2148,8 +2093,6 @@ public readonly struct GambatteHexStrTestCase "window.late_scx_late_disable_1_dmg08_out3_cgb04c_out0 on CGB_C in GBHawk", "window.late_scx_late_disable_1_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy", "window.late_scx_late_disable_1_dmg08_out3_cgb04c_out0 on CGB_C in SameBoy (no BIOS)", - "window.late_scx_late_disable_1_dmg08_out3_cgb04c_out0 on DMG in SameBoy", - "window.late_scx_late_disable_1_dmg08_out3_cgb04c_out0 on DMG in SameBoy (no BIOS)", "window.late_wx_1_dmg08_cgb04c_out0 on CGB_C in GBHawk", "window.late_wx_1_dmg08_cgb04c_out0 on DMG in GBHawk", "window.late_wx_ds_1_cgb04c_out0 on CGB_C in GBHawk", diff --git a/src/BizHawk.Tests.Testroms.GB.GambatteSuite/GambatteSuite.cs b/src/BizHawk.Tests.Testroms.GB.GambatteSuite/GambatteSuite.cs index 80e46394f36..71036c3fec0 100644 --- a/src/BizHawk.Tests.Testroms.GB.GambatteSuite/GambatteSuite.cs +++ b/src/BizHawk.Tests.Testroms.GB.GambatteSuite/GambatteSuite.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Globalization; @@ -10,8 +9,6 @@ using BizHawk.Common.IOExtensions; using BizHawk.Common.StringExtensions; -using Microsoft.VisualStudio.TestTools.UnitTesting; - using static BizHawk.Tests.Testroms.GB.GBHelper; namespace BizHawk.Tests.Testroms.GB.GambatteSuite diff --git a/src/BizHawk.Tests.Testroms.GB.GambatteSuite/Properties/AssemblyInfo.cs b/src/BizHawk.Tests.Testroms.GB.GambatteSuite/Properties/AssemblyInfo.cs index 025cb0d7169..326ee1dc160 100644 --- a/src/BizHawk.Tests.Testroms.GB.GambatteSuite/Properties/AssemblyInfo.cs +++ b/src/BizHawk.Tests.Testroms.GB.GambatteSuite/Properties/AssemblyInfo.cs @@ -1,3 +1 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; - [assembly: TestDataSourceDiscovery(TestDataSourceDiscoveryOption.DuringExecution)] diff --git a/src/BizHawk.Tests.Testroms.GB.GambatteSuite/readme.md b/src/BizHawk.Tests.Testroms.GB.GambatteSuite/readme.md index dc6d5ad7ac9..0323e8b8fe9 100644 --- a/src/BizHawk.Tests.Testroms.GB.GambatteSuite/readme.md +++ b/src/BizHawk.Tests.Testroms.GB.GambatteSuite/readme.md @@ -12,4 +12,4 @@ Note that firmware does not need to be copied here. They are taken from `../BizH > This test suite is huge and takes a **really long time** to run. Like several hours. -Summary of `BIZHAWKTEST_RUN_KNOWN_FAILURES=1 ./run_tests_release.sh` should read 22425 passed / 2550 skipped / 0 failed. +Summary of `BIZHAWKTEST_RUN_KNOWN_FAILURES=1 ./run_tests_release.sh` should read 22479 passed / 2496 skipped / 0 failed. diff --git a/src/BizHawk.Tests.Testroms.GB/BizHawk.Tests.Testroms.GB.csproj b/src/BizHawk.Tests.Testroms.GB/BizHawk.Tests.Testroms.GB.csproj index 6304d947fcb..bc824455d2e 100644 --- a/src/BizHawk.Tests.Testroms.GB/BizHawk.Tests.Testroms.GB.csproj +++ b/src/BizHawk.Tests.Testroms.GB/BizHawk.Tests.Testroms.GB.csproj @@ -1,6 +1,6 @@ - net8.0 + net48 @@ -16,12 +16,15 @@ $(DefineConstants);SAVE_IMAGES_ON_FAIL;SAVE_IMAGES_ON_PASS + + true + + - diff --git a/src/BizHawk.Tests.Testroms.GB/DummyFrontend.cs b/src/BizHawk.Tests.Testroms.GB/DummyFrontend.cs index 83ea9d2f38e..5d5e018fe9c 100644 --- a/src/BizHawk.Tests.Testroms.GB/DummyFrontend.cs +++ b/src/BizHawk.Tests.Testroms.GB/DummyFrontend.cs @@ -1,10 +1,8 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; -using BizHawk.Bizware.BizwareGL; using BizHawk.Bizware.Graphics; using BizHawk.Client.Common; using BizHawk.Common.IOExtensions; @@ -79,38 +77,6 @@ public string GetUserPath(string sysID, bool temp) => throw new NotImplementedException(); // only used by Encore } - public sealed class SimpleGDIPDisplayManager : DisplayManagerBase - { - private SimpleGDIPDisplayManager(Config config, IEmulator emuCore, IGL_GDIPlus glImpl) - : base( - config, - emuCore, - inputManager: null, - movieSession: null, - EDispMethod.GdiPlus, - glImpl, - new GDIPlusGuiRenderer(glImpl)) - {} - - public SimpleGDIPDisplayManager(Config config, IEmulator emuCore, Func<(int Width, int Height)> getVirtualSize) - : this(config, emuCore, new IGL_GDIPlus()) {} - - protected override void ActivateGraphicsControlContext() {} - - public override void ActivateOpenGLContext() {} - - protected override Size GetGraphicsControlSize() - => throw new NotImplementedException(); - - public override Size GetPanelNativeSize() - => throw new NotImplementedException(); - - protected override Point GraphicsControlPointToClient(Point p) - => throw new NotImplementedException(); - - protected override void SwapBuffersOfGraphicsControl() {} - } - private static int _totalFrames = 0; private static readonly object _totalFramesMutex = new(); diff --git a/src/BizHawk.Tests.Testroms.GB/GB_GBC/AcidTestroms.cs b/src/BizHawk.Tests.Testroms.GB/GB_GBC/AcidTestroms.cs index 66abe9599fe..43958da3adf 100644 --- a/src/BizHawk.Tests.Testroms.GB/GB_GBC/AcidTestroms.cs +++ b/src/BizHawk.Tests.Testroms.GB/GB_GBC/AcidTestroms.cs @@ -1,12 +1,9 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using BizHawk.Common.IOExtensions; -using Microsoft.VisualStudio.TestTools.UnitTesting; - using static BizHawk.Tests.Testroms.GB.GBHelper; namespace BizHawk.Tests.Testroms.GB diff --git a/src/BizHawk.Tests.Testroms.GB/GB_GBC/BullyGB.cs b/src/BizHawk.Tests.Testroms.GB/GB_GBC/BullyGB.cs index 98e36b5bbd2..62ef6a6100e 100644 --- a/src/BizHawk.Tests.Testroms.GB/GB_GBC/BullyGB.cs +++ b/src/BizHawk.Tests.Testroms.GB/GB_GBC/BullyGB.cs @@ -1,12 +1,9 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using BizHawk.Common.IOExtensions; -using Microsoft.VisualStudio.TestTools.UnitTesting; - using static BizHawk.Tests.Testroms.GB.GBHelper; namespace BizHawk.Tests.Testroms.GB diff --git a/src/BizHawk.Tests.Testroms.GB/GB_GBC/CPPTestroms.cs b/src/BizHawk.Tests.Testroms.GB/GB_GBC/CPPTestroms.cs index cd75dbc57c3..3c77dd77689 100644 --- a/src/BizHawk.Tests.Testroms.GB/GB_GBC/CPPTestroms.cs +++ b/src/BizHawk.Tests.Testroms.GB/GB_GBC/CPPTestroms.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Globalization; @@ -8,8 +7,6 @@ using BizHawk.Common.CollectionExtensions; using BizHawk.Common.IOExtensions; -using Microsoft.VisualStudio.TestTools.UnitTesting; - using static BizHawk.Tests.Testroms.GB.GBHelper; namespace BizHawk.Tests.Testroms.GB.CPPTestroms @@ -86,11 +83,7 @@ public readonly struct CPPTestromsHexStrTestCase public static readonly IReadOnlyList KnownFailures = new[] { "open-bus-ss-test on CGB_C in GBHawk", - "open-bus-ss-test on CGB_C in SameBoy", - "open-bus-ss-test on CGB_C in SameBoy (no BIOS)", "open-bus-ss-test on DMG in GBHawk", - "open-bus-ss-test on DMG in SameBoy", - "open-bus-ss-test on DMG in SameBoy (no BIOS)", "ramg-mbc3-test on CGB_C in GBHawk", "ramg-mbc3-test on DMG in GBHawk", "rtc-invalid-banks-test on CGB_C in GBHawk", @@ -221,7 +214,12 @@ bool GlyphRowMatches(int y) if (!ImageUtils.SkipFileIO(state)) { ImageUtils.SaveScreenshot(NormaliseGBScreenshot(actualUnnormalised, testCase.Setup), (SUITE_ID, caseStr)); - Console.WriteLine($"should read: {string.Join("\n", testCase.ExpectedValue.Chunk(40).Select(static a => string.Concat(a)))}"); + Console.WriteLine("should read: "); + const int STR_FOLD_COL = 40; + for (var iEx = 0; iEx < testCase.ExpectedValue.Length; iEx += STR_FOLD_COL) + { + Console.WriteLine(testCase.ExpectedValue.Substring(startIndex: iEx, length: STR_FOLD_COL)); + } } switch (state) { diff --git a/src/BizHawk.Tests.Testroms.GB/GB_GBC/GBHelper.cs b/src/BizHawk.Tests.Testroms.GB/GB_GBC/GBHelper.cs index e6ecb07c9c1..b9a4eb0b47f 100644 --- a/src/BizHawk.Tests.Testroms.GB/GB_GBC/GBHelper.cs +++ b/src/BizHawk.Tests.Testroms.GB/GB_GBC/GBHelper.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.IO; @@ -9,8 +8,6 @@ using BizHawk.Emulation.Cores.Nintendo.GBHawk; using BizHawk.Emulation.Cores.Nintendo.Sameboy; -using Microsoft.VisualStudio.TestTools.UnitTesting; - using static BizHawk.Emulation.Cores.Nintendo.Gameboy.Gameboy; using static BizHawk.Emulation.Cores.Nintendo.GBHawk.GBHawk; using static BizHawk.Emulation.Cores.Nintendo.Sameboy.Sameboy; diff --git a/src/BizHawk.Tests.Testroms.GB/GB_GBC/MealybugTearoomTests.cs b/src/BizHawk.Tests.Testroms.GB/GB_GBC/MealybugTearoomTests.cs index 500ca8b2c72..aa25154efbd 100644 --- a/src/BizHawk.Tests.Testroms.GB/GB_GBC/MealybugTearoomTests.cs +++ b/src/BizHawk.Tests.Testroms.GB/GB_GBC/MealybugTearoomTests.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -11,8 +10,6 @@ using BizHawk.Emulation.Cores.Nintendo.GBHawk; using BizHawk.Emulation.Cores.Nintendo.Sameboy; -using Microsoft.VisualStudio.TestTools.UnitTesting; - using static BizHawk.Tests.Testroms.GB.GBHelper; namespace BizHawk.Tests.Testroms.GB @@ -68,8 +65,6 @@ public readonly struct MealybugTestCase "m3_lcdc_obj_en_change_variant on CGB_C in SameBoy", "m3_lcdc_obj_en_change_variant on CGB_C in SameBoy (no BIOS)", "m3_lcdc_obj_en_change_variant on CGB_D in GBHawk", - "m3_lcdc_obj_en_change_variant on CGB_D in SameBoy", - "m3_lcdc_obj_en_change_variant on CGB_D in SameBoy (no BIOS)", "m3_lcdc_obj_en_change_variant on DMG in Gambatte", "m3_lcdc_obj_en_change_variant on DMG in Gambatte (no BIOS)", "m3_lcdc_obj_en_change_variant on DMG in GBHawk", @@ -79,10 +74,14 @@ public readonly struct MealybugTestCase "m3_lcdc_obj_size_change on DMG in Gambatte", "m3_lcdc_obj_size_change on DMG in Gambatte (no BIOS)", "m3_lcdc_obj_size_change on DMG in GBHawk", + "m3_lcdc_obj_size_change on DMG in SameBoy", + "m3_lcdc_obj_size_change on DMG in SameBoy (no BIOS)", "m3_lcdc_obj_size_change_scx on CGB_C in GBHawk", "m3_lcdc_obj_size_change_scx on DMG in Gambatte", "m3_lcdc_obj_size_change_scx on DMG in Gambatte (no BIOS)", "m3_lcdc_obj_size_change_scx on DMG in GBHawk", + "m3_lcdc_obj_size_change_scx on DMG in SameBoy", + "m3_lcdc_obj_size_change_scx on DMG in SameBoy (no BIOS)", "m3_lcdc_tile_sel_change on CGB_C in Gambatte", "m3_lcdc_tile_sel_change on CGB_C in Gambatte (no BIOS)", "m3_lcdc_tile_sel_change on CGB_C in GBHawk", @@ -115,8 +114,6 @@ public readonly struct MealybugTestCase "m3_lcdc_win_en_change_multiple_wx on DMG_B in Gambatte", "m3_lcdc_win_en_change_multiple_wx on DMG_B in Gambatte (no BIOS)", "m3_lcdc_win_en_change_multiple_wx on DMG_B in GBHawk", - "m3_lcdc_win_en_change_multiple_wx on DMG_B in SameBoy", - "m3_lcdc_win_en_change_multiple_wx on DMG_B in SameBoy (no BIOS)", "m3_lcdc_win_map_change on CGB_C in GBHawk", "m3_lcdc_win_map_change on DMG in GBHawk", "m3_lcdc_win_map_change2 on CGB_C in GBHawk", @@ -159,8 +156,6 @@ public readonly struct MealybugTestCase "m3_wx_4_change on DMG in Gambatte", "m3_wx_4_change on DMG in Gambatte (no BIOS)", "m3_wx_4_change on DMG in GBHawk", - "m3_wx_4_change on DMG in SameBoy", - "m3_wx_4_change on DMG in SameBoy (no BIOS)", "m3_wx_4_change_sprites on CGB_C in Gambatte", "m3_wx_4_change_sprites on CGB_C in Gambatte (no BIOS)", "m3_wx_4_change_sprites on CGB_C in GBHawk", @@ -169,13 +164,9 @@ public readonly struct MealybugTestCase "m3_wx_4_change_sprites on DMG in Gambatte", "m3_wx_4_change_sprites on DMG in Gambatte (no BIOS)", "m3_wx_4_change_sprites on DMG in GBHawk", - "m3_wx_4_change_sprites on DMG in SameBoy", - "m3_wx_4_change_sprites on DMG in SameBoy (no BIOS)", "m3_wx_5_change on DMG in Gambatte", "m3_wx_5_change on DMG in Gambatte (no BIOS)", "m3_wx_5_change on DMG in GBHawk", - "m3_wx_5_change on DMG in SameBoy", - "m3_wx_5_change on DMG in SameBoy (no BIOS)", "m3_wx_6_change on DMG in GBHawk", }; diff --git a/src/BizHawk.Tests.Testroms.GB/GB_GBC/RTC3Test.cs b/src/BizHawk.Tests.Testroms.GB/GB_GBC/RTC3Test.cs index f1e0af112da..de931754749 100644 --- a/src/BizHawk.Tests.Testroms.GB/GB_GBC/RTC3Test.cs +++ b/src/BizHawk.Tests.Testroms.GB/GB_GBC/RTC3Test.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -7,8 +6,6 @@ using BizHawk.Common.IOExtensions; using BizHawk.Emulation.Cores; -using Microsoft.VisualStudio.TestTools.UnitTesting; - using static BizHawk.Tests.Testroms.GB.GBHelper; namespace BizHawk.Tests.Testroms.GB diff --git a/src/BizHawk.Tests.Testroms.GB/ImageUtils.cs b/src/BizHawk.Tests.Testroms.GB/ImageUtils.cs index 0db88f362dd..3536a2e0a50 100644 --- a/src/BizHawk.Tests.Testroms.GB/ImageUtils.cs +++ b/src/BizHawk.Tests.Testroms.GB/ImageUtils.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; @@ -43,7 +42,7 @@ int Lookup(int c) public static void PrintPalette(Image imgA, string labelA, Image imgB, string labelB) { - static IReadOnlySet CollectPalette(Image img) + static HashSet CollectPalette(Image img) { var b = img.AsBitmap(); HashSet paletteE = new(); diff --git a/src/BizHawk.Tests.Testroms.GB/Properties/AssemblyInfo.cs b/src/BizHawk.Tests.Testroms.GB/Properties/AssemblyInfo.cs index 025cb0d7169..326ee1dc160 100644 --- a/src/BizHawk.Tests.Testroms.GB/Properties/AssemblyInfo.cs +++ b/src/BizHawk.Tests.Testroms.GB/Properties/AssemblyInfo.cs @@ -1,3 +1 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; - [assembly: TestDataSourceDiscovery(TestDataSourceDiscoveryOption.DuringExecution)] diff --git a/src/BizHawk.Tests.Testroms.GB/TestUtils.cs b/src/BizHawk.Tests.Testroms.GB/TestUtils.cs index a7b1f64a66c..d230d249c0e 100644 --- a/src/BizHawk.Tests.Testroms.GB/TestUtils.cs +++ b/src/BizHawk.Tests.Testroms.GB/TestUtils.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -8,8 +7,6 @@ using BizHawk.Common; using BizHawk.Emulation.Common; -using Microsoft.VisualStudio.TestTools.UnitTesting; - namespace BizHawk.Tests.Testroms.GB { public static class TestUtils diff --git a/src/BizHawk.Tests.Testroms.GB/readme.md b/src/BizHawk.Tests.Testroms.GB/readme.md index c31def54f35..f7cf0cddf91 100644 --- a/src/BizHawk.Tests.Testroms.GB/readme.md +++ b/src/BizHawk.Tests.Testroms.GB/readme.md @@ -72,4 +72,4 @@ $Env:BIZHAWKTEST_SAVE_IMAGES = "all" dotnet test -c Release -l "console;verbosity=detailed" ``` -Summary of `BIZHAWKTEST_RUN_KNOWN_FAILURES=1 ./run_tests_release.sh` should read 192 passed / 178 skipped / 0 failed. +Summary of `BIZHAWKTEST_RUN_KNOWN_FAILURES=1 ./run_tests_release.sh` should read 202 passed / 168 skipped / 0 failed. diff --git a/src/BizHawk.Tests/BizHawk.Tests.csproj b/src/BizHawk.Tests/BizHawk.Tests.csproj index 95504a65c9c..89447a5c106 100644 --- a/src/BizHawk.Tests/BizHawk.Tests.csproj +++ b/src/BizHawk.Tests/BizHawk.Tests.csproj @@ -1,13 +1,11 @@ - net8.0 - - - netcoreapp3.1 + net48 $(DefineConstants);SKIP_PLATFORM_TESTS + $(MSBuildProjectDirectory)/../MainSln.runsettings diff --git a/src/BizHawk.Tests/Client.Common/Api/MemoryApiTests.cs b/src/BizHawk.Tests/Client.Common/Api/MemoryApiTests.cs index ec6c5f14536..8e2e10df8c0 100644 --- a/src/BizHawk.Tests/Client.Common/Api/MemoryApiTests.cs +++ b/src/BizHawk.Tests/Client.Common/Api/MemoryApiTests.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; using System.Linq; @@ -7,8 +6,6 @@ using BizHawk.Client.Common; using BizHawk.Emulation.Common; -using Microsoft.VisualStudio.TestTools.UnitTesting; - namespace BizHawk.Tests.Client.Common.Api { [TestClass] diff --git a/src/BizHawk.Tests/Client.Common/Display/InputDisplayTests.cs b/src/BizHawk.Tests/Client.Common/Display/InputDisplayTests.cs index 612287b86a3..9807c167258 100644 --- a/src/BizHawk.Tests/Client.Common/Display/InputDisplayTests.cs +++ b/src/BizHawk.Tests/Client.Common/Display/InputDisplayTests.cs @@ -1,5 +1,3 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; - using BizHawk.Client.Common; using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Tests/Client.Common/Movie/LogGeneratorTests.cs b/src/BizHawk.Tests/Client.Common/Movie/LogGeneratorTests.cs index d2f4c36c296..40e66c4a778 100644 --- a/src/BizHawk.Tests/Client.Common/Movie/LogGeneratorTests.cs +++ b/src/BizHawk.Tests/Client.Common/Movie/LogGeneratorTests.cs @@ -1,5 +1,3 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; - using BizHawk.Client.Common; using BizHawk.Common; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Tests/Client.Common/Movie/MovieServiceTests.cs b/src/BizHawk.Tests/Client.Common/Movie/MovieServiceTests.cs index a9c20cf14d7..b9dd00facad 100644 --- a/src/BizHawk.Tests/Client.Common/Movie/MovieServiceTests.cs +++ b/src/BizHawk.Tests/Client.Common/Movie/MovieServiceTests.cs @@ -1,5 +1,4 @@ using BizHawk.Client.Common; -using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BizHawk.Tests.Client.Common.Movie { diff --git a/src/BizHawk.Tests/Client.Common/Movie/ZwinderStateManagerTests.cs b/src/BizHawk.Tests/Client.Common/Movie/ZwinderStateManagerTests.cs index 5965b1bb299..2730b89648f 100644 --- a/src/BizHawk.Tests/Client.Common/Movie/ZwinderStateManagerTests.cs +++ b/src/BizHawk.Tests/Client.Common/Movie/ZwinderStateManagerTests.cs @@ -1,13 +1,37 @@ -using System; using System.IO; using System.Linq; using BizHawk.Client.Common; using BizHawk.Common; using BizHawk.Emulation.Common; -using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BizHawk.Tests.Client.Common.Movie { +#if !(NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER) + internal static class Extensions + { + public static void NextBytes(this Random rng, Span buf) + { + var a = buf.ToArray(); + rng.NextBytes(a); + a.CopyTo(buf); + } + + public static int Read(this BinaryReader br, Span buf) + { + var a = buf.ToArray(); + var result = br.Read(a, index: 0, count: a.Length); + a.CopyTo(buf); + return result; + } + + public static void Write(this BinaryWriter bw, ReadOnlySpan buf) + => bw.Write(buf.ToArray()); + + public static void Write(this Stream stream, ReadOnlySpan buf) + => stream.Write(buf.ToArray(), offset: 0, count: buf.Length); + } +#endif + [TestClass] public class ZwinderStateManagerTests { @@ -487,7 +511,7 @@ public void TestReadBytesCorruption() Assert.AreEqual(0, state.Frame); Assert.AreEqual(4, state.Size); var bb = new byte[2]; - state.GetReadStream().Read(bb, 0, 2); + _ = state.GetReadStream().Read(bb, offset: 0, count: bb.Length); Assert.AreEqual(1, bb[0]); Assert.AreEqual(2, bb[1]); } diff --git a/src/BizHawk.Tests/Client.Common/cheats/CheatDecoderTests.cs b/src/BizHawk.Tests/Client.Common/cheats/CheatDecoderTests.cs index e5616bc224b..8e5d72a9ba4 100644 --- a/src/BizHawk.Tests/Client.Common/cheats/CheatDecoderTests.cs +++ b/src/BizHawk.Tests/Client.Common/cheats/CheatDecoderTests.cs @@ -1,10 +1,7 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Reflection; -using Microsoft.VisualStudio.TestTools.UnitTesting; - using BizHawk.Client.Common; using BizHawk.Client.Common.cheats; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Tests/Client.Common/config/CorePickerStabilityTests.cs b/src/BizHawk.Tests/Client.Common/config/CorePickerStabilityTests.cs index bc98692c58d..a5f4903ebd0 100644 --- a/src/BizHawk.Tests/Client.Common/config/CorePickerStabilityTests.cs +++ b/src/BizHawk.Tests/Client.Common/config/CorePickerStabilityTests.cs @@ -2,10 +2,9 @@ using System.Linq; using BizHawk.Client.Common; +using BizHawk.Common; using BizHawk.Emulation.Cores; -using Microsoft.VisualStudio.TestTools.UnitTesting; - namespace BizHawk.Tests.Client.Common.config { [TestClass] @@ -27,7 +26,9 @@ public void AssertAllChoicesInMenu() { Assert.IsTrue( appliesTo.Any(multiCoreSystems.Contains), - $"core picker has submenu for {appliesTo[0]} ({string.Join('/', appliesTo)}), but {(appliesTo.Length == 1 ? "that system doesn't have" : "none of those systems have")} alternate cores"); + appliesTo.Length is 1 + ? $"core picker has submenu for {appliesTo[0]}, but that system doesn't have alternate cores" + : $"core picker has submenu for {appliesTo[0]} ({string.Join("/", appliesTo)}), but none of those systems have alternate cores"); } } diff --git a/src/BizHawk.Tests/Client.Common/config/SerializationStabilityTests.cs b/src/BizHawk.Tests/Client.Common/config/SerializationStabilityTests.cs index 658ebade061..3e14ad78d17 100644 --- a/src/BizHawk.Tests/Client.Common/config/SerializationStabilityTests.cs +++ b/src/BizHawk.Tests/Client.Common/config/SerializationStabilityTests.cs @@ -1,10 +1,8 @@ -using System; using System.Collections.Generic; using System.Reflection; using BizHawk.Client.Common; - -using Microsoft.VisualStudio.TestTools.UnitTesting; +using BizHawk.Common; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -20,7 +18,7 @@ public sealed class SerializationStabilityTests private const string ZWINDER_SER = @"{""CurrentUseCompression"":false,""CurrentBufferSize"":256,""CurrentTargetFrameLength"":500,""CurrentStoreType"":0,""RecentUseCompression"":false,""RecentBufferSize"":128,""RecentTargetFrameLength"":2000,""RecentStoreType"":0,""GapsUseCompression"":false,""GapsBufferSize"":64,""GapsTargetFrameLength"":125,""GapsStoreType"":0,""AncientStateInterval"":5000,""AncientStoreType"":0}"; -#if NET6_0 +#if NET5_0_OR_GREATER private static readonly IReadOnlySet KnownGoodFromStdlib = new HashSet #else private static readonly ICollection KnownGoodFromStdlib = new HashSet @@ -52,7 +50,6 @@ public sealed class SerializationStabilityTests [typeof(RewindConfig)] = @"{""UseCompression"":false,""UseDelta"":false,""Enabled"":true,""AllowSlowStates"":false,""BufferSize"":512,""UseFixedRewindInterval"":false,""TargetFrameLength"":600,""TargetRewindInterval"":5,""AllowOutOfOrderStates"":true,""BackingStore"":0}", [typeof(SaveStateConfig)] = @"{""Type"":0,""CompressionLevelNormal"":1,""CompressionLevelRewind"":0,""MakeBackups"":true,""SaveScreenshot"":true,""BigScreenshotSize"":131072,""NoLowResLargeScreenshots"":false}", [typeof(ToolDialogSettings)] = @"{""_wndx"":52,""_wndy"":44,""Width"":796,""Height"":455,""SaveWindowPosition"":true,""TopMost"":false,""FloatingWindow"":true,""AutoLoad"":false}", - [typeof(ZoomFactors)] = @"{""NULL"":2,""GB"":3}", [typeof(ZwinderStateManagerSettings)] = ZWINDER_SER, }; diff --git a/src/BizHawk.Tests/Client.Common/dearchive/DearchivalTests.cs b/src/BizHawk.Tests/Client.Common/dearchive/DearchivalTests.cs index b2ce159d8d6..103f108f916 100644 --- a/src/BizHawk.Tests/Client.Common/dearchive/DearchivalTests.cs +++ b/src/BizHawk.Tests/Client.Common/dearchive/DearchivalTests.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Linq; @@ -6,8 +5,6 @@ using BizHawk.Common; using BizHawk.Common.IOExtensions; -using Microsoft.VisualStudio.TestTools.UnitTesting; - namespace BizHawk.Tests.Client.Common.Dearchive { [TestClass] diff --git a/src/BizHawk.Tests/Client.Common/lua/LuaTests.cs b/src/BizHawk.Tests/Client.Common/lua/LuaTests.cs index 93b70b933a1..5600242a16e 100644 --- a/src/BizHawk.Tests/Client.Common/lua/LuaTests.cs +++ b/src/BizHawk.Tests/Client.Common/lua/LuaTests.cs @@ -1,15 +1,13 @@ -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using BizHawk.Client.Common; -using Microsoft.VisualStudio.TestTools.UnitTesting; - namespace BizHawk.Tests.Client.Common.Lua { #if !SKIP_PLATFORM_TESTS + [DoNotParallelize] [TestClass] #endif public class LuaTests diff --git a/src/BizHawk.Tests/Common/CollectionExtensions/CollectionExtensionTests.cs b/src/BizHawk.Tests/Common/CollectionExtensions/CollectionExtensionTests.cs index 9366a78b6ee..a9eec1cc26c 100644 --- a/src/BizHawk.Tests/Common/CollectionExtensions/CollectionExtensionTests.cs +++ b/src/BizHawk.Tests/Common/CollectionExtensions/CollectionExtensionTests.cs @@ -1,12 +1,9 @@ -using System; using System.Collections; using System.Collections.Generic; using System.Linq; using BizHawk.Common.CollectionExtensions; -using Microsoft.VisualStudio.TestTools.UnitTesting; - using CE = BizHawk.Common.CollectionExtensions.CollectionExtensions; namespace BizHawk.Tests.Common.CollectionExtensions diff --git a/src/BizHawk.Tests/Common/ConversionTests.cs b/src/BizHawk.Tests/Common/ConversionTests.cs new file mode 100644 index 00000000000..04d3d5a7a62 --- /dev/null +++ b/src/BizHawk.Tests/Common/ConversionTests.cs @@ -0,0 +1,24 @@ +using BizHawk.Common.NumberExtensions; + +namespace BizHawk.Tests.Common; + +[TestClass] +public class ConversionTests +{ + [TestMethod] + [DataRow(0U, 0)] + [DataRow(1U, 1.401298E-45F)] + [DataRow(1109917696U, 42)] + [DataRow(1123477881U, 123.456F)] + [DataRow(3212836864U, -1)] + public void TestReinterpretAsF32(uint input, float expected) + { + float converted = NumberExtensions.ReinterpretAsF32(input); + + Assert.AreEqual(expected, converted); + + uint restoredInput = NumberExtensions.ReinterpretAsUInt32(converted); + + Assert.AreEqual(input, restoredInput); + } +} diff --git a/src/BizHawk.Tests/Common/CustomCollections/CustomCollectionTests.cs b/src/BizHawk.Tests/Common/CustomCollections/CustomCollectionTests.cs index 37d79783f99..83835f741b5 100644 --- a/src/BizHawk.Tests/Common/CustomCollections/CustomCollectionTests.cs +++ b/src/BizHawk.Tests/Common/CustomCollections/CustomCollectionTests.cs @@ -2,8 +2,6 @@ using BizHawk.Common; -using Microsoft.VisualStudio.TestTools.UnitTesting; - namespace BizHawk.Tests.Common.CustomCollections { [TestClass] diff --git a/src/BizHawk.Tests/Common/EndiannessUtils/EndiannessUtilsTests.cs b/src/BizHawk.Tests/Common/EndiannessUtils/EndiannessUtilsTests.cs index f1a35a841ee..0f487e22dc4 100644 --- a/src/BizHawk.Tests/Common/EndiannessUtils/EndiannessUtilsTests.cs +++ b/src/BizHawk.Tests/Common/EndiannessUtils/EndiannessUtilsTests.cs @@ -1,9 +1,5 @@ -using System; - using BizHawk.Common; -using Microsoft.VisualStudio.TestTools.UnitTesting; - namespace BizHawk.Tests.Common { [TestClass] diff --git a/src/BizHawk.Tests/Common/MultiPredicateSort/MultiPredicateSortTests.cs b/src/BizHawk.Tests/Common/MultiPredicateSort/MultiPredicateSortTests.cs index 28711116058..ddfc081a016 100644 --- a/src/BizHawk.Tests/Common/MultiPredicateSort/MultiPredicateSortTests.cs +++ b/src/BizHawk.Tests/Common/MultiPredicateSort/MultiPredicateSortTests.cs @@ -1,11 +1,8 @@ -using System; using System.Collections.Generic; using System.Linq; using BizHawk.Common; -using Microsoft.VisualStudio.TestTools.UnitTesting; - namespace BizHawk.Tests.Common.MultiPredicateSort { [TestClass] diff --git a/src/BizHawk.Tests/Common/StringExtensions/NumericStringExtensionTests.cs b/src/BizHawk.Tests/Common/StringExtensions/NumericStringExtensionTests.cs new file mode 100644 index 00000000000..ef298b3c17a --- /dev/null +++ b/src/BizHawk.Tests/Common/StringExtensions/NumericStringExtensionTests.cs @@ -0,0 +1,26 @@ +using BizHawk.Common.StringExtensions; + +namespace BizHawk.Tests.Common.StringExtensions +{ + [TestClass] + public class NumericStringExtensionTests + { + [TestMethod] + public void TesCleanHex() + { + Assert.AreEqual("0123456789ABCDEFABCDEF", "0123456789ABCDEFabcdef".CleanHex()); + Assert.AreEqual("ABCDEF", "0xABCDEF".CleanHex()); + Assert.AreEqual("ABCDEF", "$ABCDEF".CleanHex()); + Assert.AreEqual("ABCDEF", " AB CD\nEF ".CleanHex()); + Assert.AreEqual("ABCDEF", " 0xABCDEF ".CleanHex()); + + Assert.AreEqual(string.Empty, (null as string).CleanHex()); + Assert.AreEqual(string.Empty, string.Empty.CleanHex()); + Assert.AreEqual(string.Empty, "0x$ABCDEF".CleanHex()); + Assert.AreEqual(string.Empty, "$0xABCDEF".CleanHex()); + Assert.AreEqual(string.Empty, "$$ABCDEF".CleanHex()); + Assert.AreEqual(string.Empty, "ABCDEF$".CleanHex()); + Assert.AreEqual(string.Empty, "A!B.C(DE)F".CleanHex()); + } + } +} diff --git a/src/BizHawk.Tests/Common/StringExtensions/StringExtensionTests.cs b/src/BizHawk.Tests/Common/StringExtensions/StringExtensionTests.cs index 811f6dcff53..d212f31e287 100644 --- a/src/BizHawk.Tests/Common/StringExtensions/StringExtensionTests.cs +++ b/src/BizHawk.Tests/Common/StringExtensions/StringExtensionTests.cs @@ -1,4 +1,3 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; using BizHawk.Common.StringExtensions; namespace BizHawk.Tests.Common.StringExtensions diff --git a/src/BizHawk.Tests/Common/checksums/CRC32Tests.cs b/src/BizHawk.Tests/Common/checksums/CRC32Tests.cs index 734c3d79128..13946133f70 100644 --- a/src/BizHawk.Tests/Common/checksums/CRC32Tests.cs +++ b/src/BizHawk.Tests/Common/checksums/CRC32Tests.cs @@ -1,9 +1,8 @@ using BizHawk.Common; -using Microsoft.VisualStudio.TestTools.UnitTesting; - namespace BizHawk.Tests.Common.checksums { + [DoNotParallelize] // I only noticed problems w/ SHA1, but better safe than sorry --yoshi [TestClass] public sealed class CRC32Tests { diff --git a/src/BizHawk.Tests/Common/checksums/SHA1Tests.cs b/src/BizHawk.Tests/Common/checksums/SHA1Tests.cs index 8481e513ff1..3bca144f900 100644 --- a/src/BizHawk.Tests/Common/checksums/SHA1Tests.cs +++ b/src/BizHawk.Tests/Common/checksums/SHA1Tests.cs @@ -1,20 +1,18 @@ -using System; using System.Linq; using System.Text; using BizHawk.Common; -using Microsoft.VisualStudio.TestTools.UnitTesting; - namespace BizHawk.Tests.Common.checksums { + [DoNotParallelize] [TestClass] public sealed class SHA1Tests { [TestMethod] public void TestSHA1Empty() { - byte[] data = Array.Empty(); // empty data - byte[] expectedSha = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09 }; + byte[] data = [ ]; // empty data + byte[] expectedSha = [ 0xDA, 0x39, 0xA3, 0xEE, 0x5E, 0x6B, 0x4B, 0x0D, 0x32, 0x55, 0xBF, 0xEF, 0x95, 0x60, 0x18, 0x90, 0xAF, 0xD8, 0x07, 0x09 ]; Assert.IsTrue(expectedSha.SequenceEqual(SHA1Checksum.Compute(data))); } @@ -22,15 +20,15 @@ public void TestSHA1Empty() [TestMethod] public void TestSHA1Simple() { - byte[] data = { (byte)'h', (byte)'a', (byte)'s', (byte)'h' }; // random short data - byte[] expectedSha = { 0x23, 0x46, 0xad, 0x27, 0xd7, 0x56, 0x8b, 0xa9, 0x89, 0x6f, 0x1b, 0x7d, 0xa6, 0xb5, 0x99, 0x12, 0x51, 0xde, 0xbd, 0xf2 }; + byte[] data = "hash"u8.ToArray(); // random short data + byte[] expectedSha = [ 0x23, 0x46, 0xAD, 0x27, 0xD7, 0x56, 0x8B, 0xA9, 0x89, 0x6F, 0x1B, 0x7D, 0xA6, 0xB5, 0x99, 0x12, 0x51, 0xDE, 0xBD, 0xF2 ]; Assert.IsTrue(expectedSha.SequenceEqual(SHA1Checksum.Compute(data))); Assert.IsTrue(expectedSha.SequenceEqual(SHA1Checksum.ComputeConcat(Array.Empty(), data))); Assert.IsTrue(expectedSha.SequenceEqual(SHA1Checksum.ComputeConcat(data, Array.Empty()))); - data = new[] { (byte)'h', (byte)'a' }; - byte[] data2 = { (byte)'s', (byte)'h' }; + data = "ha"u8.ToArray(); + byte[] data2 = "sh"u8.ToArray(); Assert.IsTrue(expectedSha.SequenceEqual(SHA1Checksum.ComputeConcat(data, data2))); } @@ -40,17 +38,17 @@ public void TestSHA1LessSimple() { const string testString = "The quick brown fox jumps over the lazy dog."; byte[] data = Encoding.ASCII.GetBytes(testString); - byte[] expectedSha1 = { 0x40, 0x8d, 0x94, 0x38, 0x42, 0x16, 0xf8, 0x90, 0xff, 0x7a, 0x0c, 0x35, 0x28, 0xe8, 0xbe, 0xd1, 0xe0, 0xb0, 0x16, 0x21 }; + byte[] expectedSha1 = [ 0x40, 0x8D, 0x94, 0x38, 0x42, 0x16, 0xF8, 0x90, 0xFF, 0x7A, 0x0C, 0x35, 0x28, 0xE8, 0xBE, 0xD1, 0xE0, 0xB0, 0x16, 0x21 ]; Assert.IsTrue(expectedSha1.SequenceEqual(SHA1Checksum.Compute(data))); data = new byte[65]; Encoding.ASCII.GetBytes(testString).CopyTo(data, 0); - byte[] expectedSha2 = { 0x65, 0x87, 0x84, 0xE2, 0x68, 0xBF, 0xB1, 0x67, 0x94, 0x7B, 0xB7, 0xF3, 0xFB, 0x76, 0x69, 0x62, 0x79, 0x3E, 0x8C, 0x46 }; + byte[] expectedSha2 = [ 0x65, 0x87, 0x84, 0xE2, 0x68, 0xBF, 0xB1, 0x67, 0x94, 0x7B, 0xB7, 0xF3, 0xFB, 0x76, 0x69, 0x62, 0x79, 0x3E, 0x8C, 0x46 ]; Assert.IsTrue(expectedSha2.SequenceEqual(SHA1Checksum.Compute(new Span(data, 0, 64)))); - byte[] expectedSha3 = { 0x34, 0xF3, 0xA2, 0x57, 0xBD, 0x12, 0x5E, 0x6E, 0x0E, 0x28, 0xD0, 0xE5, 0xDA, 0xBE, 0x22, 0x28, 0x97, 0xFA, 0x69, 0x55 }; + byte[] expectedSha3 = [ 0x34, 0xF3, 0xA2, 0x57, 0xBD, 0x12, 0x5E, 0x6E, 0x0E, 0x28, 0xD0, 0xE5, 0xDA, 0xBE, 0x22, 0x28, 0x97, 0xFA, 0x69, 0x55 ]; Assert.IsTrue(expectedSha3.SequenceEqual(SHA1Checksum.Compute(data))); } } diff --git a/src/BizHawk.Tests/EmbeddedData.cs b/src/BizHawk.Tests/EmbeddedData.cs index dc80be02e0f..d62401b15c2 100644 --- a/src/BizHawk.Tests/EmbeddedData.cs +++ b/src/BizHawk.Tests/EmbeddedData.cs @@ -1,7 +1,8 @@ -using System; using System.IO; using System.Reflection; +[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)] + namespace BizHawk.Tests { public static class EmbeddedData diff --git a/src/BizHawk.Tests/Emulation.Common/Base Implementations/MemoryCallbackSystemTests.cs b/src/BizHawk.Tests/Emulation.Common/Base Implementations/MemoryCallbackSystemTests.cs index 8753a7a57a5..462e9bd2c7e 100644 --- a/src/BizHawk.Tests/Emulation.Common/Base Implementations/MemoryCallbackSystemTests.cs +++ b/src/BizHawk.Tests/Emulation.Common/Base Implementations/MemoryCallbackSystemTests.cs @@ -2,8 +2,6 @@ using System.Linq; using BizHawk.Emulation.Common; -using Microsoft.VisualStudio.TestTools.UnitTesting; - namespace BizHawk.Tests.Emulation.Common { [TestClass] diff --git a/src/BizHawk.Tests/Emulation.Common/Database/FirmwareDatabaseTests.cs b/src/BizHawk.Tests/Emulation.Common/Database/FirmwareDatabaseTests.cs index 9a885f3bc5b..abd76e040ea 100644 --- a/src/BizHawk.Tests/Emulation.Common/Database/FirmwareDatabaseTests.cs +++ b/src/BizHawk.Tests/Emulation.Common/Database/FirmwareDatabaseTests.cs @@ -1,5 +1,3 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; - using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; diff --git a/src/BizHawk.Tests/Client.Common/Movie/MovieConversionExtensionTests.cs b/src/BizHawk.Tests/PlatformTests/Client.Common.movie/MovieConversionExtensionTests.cs similarity index 92% rename from src/BizHawk.Tests/Client.Common/Movie/MovieConversionExtensionTests.cs rename to src/BizHawk.Tests/PlatformTests/Client.Common.movie/MovieConversionExtensionTests.cs index 95b18ef784f..f8a63e1a9e9 100644 --- a/src/BizHawk.Tests/Client.Common/Movie/MovieConversionExtensionTests.cs +++ b/src/BizHawk.Tests/PlatformTests/Client.Common.movie/MovieConversionExtensionTests.cs @@ -1,6 +1,5 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using BizHawk.Client.Common; - +using BizHawk.Client.Common; + namespace BizHawk.Tests.Client.Common.Movie { [TestClass] @@ -14,6 +13,8 @@ public class MovieConversionExtensionTests [DataRow("C:\\Temp\\TestMovie.tasproj", "C:\\Temp\\TestMovie.tasproj")] public void ConvertFileNameToTasMovie(string original, string expected) { + PlatformTestUtils.OnlyRunOnWindows(); + var actual = MovieConversionExtensions.ConvertFileNameToTasMovie(original); Assert.AreEqual(expected, actual); } diff --git a/src/BizHawk.Tests/PlatformTests/Common.PathExtensions/PathExtensionTests.cs b/src/BizHawk.Tests/PlatformTests/Common.PathExtensions/PathExtensionTests.cs index 0726ec3be34..877c23dfb08 100644 --- a/src/BizHawk.Tests/PlatformTests/Common.PathExtensions/PathExtensionTests.cs +++ b/src/BizHawk.Tests/PlatformTests/Common.PathExtensions/PathExtensionTests.cs @@ -1,8 +1,6 @@ using BizHawk.Common; using BizHawk.Common.PathExtensions; -using Microsoft.VisualStudio.TestTools.UnitTesting; - using PE = BizHawk.Common.PathExtensions.PathExtensions; namespace BizHawk.Tests.Common.PathExtensions @@ -37,8 +35,10 @@ public void TestNullability() [DataRow(true, "/usr", "/usr")] [DataRow(true, "/usr", "/usr/")] [DataRow(false, "/etc/rmdir", "/etc/rm")] // not naive StartsWith; these don't exist but the implementation uses `realpath -m` so they will be classed as two real and distinct dirs +#if false // don't work on NixOS and probably other distros, presumably all 32-bit distros [DataRow(true, "/usr/lib64", "/usr/lib")] // symlink to same dir [DataRow(true, "/usr/lib64/gconv", "/usr/lib")] // same symlink, checking child +#endif public void TestIsSubfolderOfUnix(bool expectedIsSubfolder, string childPath, string parentPath) { PlatformTestUtils.OnlyRunOnRealUnix(); diff --git a/src/BizHawk.Tests/PlatformTests/PlatformTestUtils.cs b/src/BizHawk.Tests/PlatformTests/PlatformTestUtils.cs index 90977089e33..702c175f8e2 100644 --- a/src/BizHawk.Tests/PlatformTests/PlatformTestUtils.cs +++ b/src/BizHawk.Tests/PlatformTests/PlatformTestUtils.cs @@ -1,7 +1,5 @@ using BizHawk.Common; -using Microsoft.VisualStudio.TestTools.UnitTesting; - namespace BizHawk.Tests { public static class PlatformTestUtils diff --git a/src/BizHawk.WinForms.Controls/BizHawk.WinForms.Controls.csproj b/src/BizHawk.WinForms.Controls/BizHawk.WinForms.Controls.csproj index db07bf00139..31744f1864b 100644 --- a/src/BizHawk.WinForms.Controls/BizHawk.WinForms.Controls.csproj +++ b/src/BizHawk.WinForms.Controls/BizHawk.WinForms.Controls.csproj @@ -3,8 +3,11 @@ net48 + + true + - + diff --git a/src/BizHawk.WinForms.Controls/GroupBoxEx/RadioButtonGroupTracker.cs b/src/BizHawk.WinForms.Controls/GroupBoxEx/RadioButtonGroupTracker.cs index 01a7c444820..729c1ebceca 100644 --- a/src/BizHawk.WinForms.Controls/GroupBoxEx/RadioButtonGroupTracker.cs +++ b/src/BizHawk.WinForms.Controls/GroupBoxEx/RadioButtonGroupTracker.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Windows.Forms; diff --git a/src/BizHawk.WinForms.Controls/MenuEx/MenuItemEx.cs b/src/BizHawk.WinForms.Controls/MenuEx/MenuItemEx.cs index f0b8e472aaf..b952616e2d7 100644 --- a/src/BizHawk.WinForms.Controls/MenuEx/MenuItemEx.cs +++ b/src/BizHawk.WinForms.Controls/MenuEx/MenuItemEx.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.WinForms.Controls/MenuEx/MenuStripEx.cs b/src/BizHawk.WinForms.Controls/MenuEx/MenuStripEx.cs index e1b6ee1d091..6ea0a4c0d30 100644 --- a/src/BizHawk.WinForms.Controls/MenuEx/MenuStripEx.cs +++ b/src/BizHawk.WinForms.Controls/MenuEx/MenuStripEx.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.WinForms.Controls/MenuEx/StatusLabelEx.cs b/src/BizHawk.WinForms.Controls/MenuEx/StatusLabelEx.cs index 4f184248702..d0c04aaa10e 100644 --- a/src/BizHawk.WinForms.Controls/MenuEx/StatusLabelEx.cs +++ b/src/BizHawk.WinForms.Controls/MenuEx/StatusLabelEx.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.WinForms.Controls/MenuEx/StatusStripEx.cs b/src/BizHawk.WinForms.Controls/MenuEx/StatusStripEx.cs index e921c7827ef..f3600623cdc 100644 --- a/src/BizHawk.WinForms.Controls/MenuEx/StatusStripEx.cs +++ b/src/BizHawk.WinForms.Controls/MenuEx/StatusStripEx.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; diff --git a/src/BizHawk.WinForms.Controls/MenuEx/ToolStripEx.cs b/src/BizHawk.WinForms.Controls/MenuEx/ToolStripEx.cs index 9e59d427475..57b23520937 100644 --- a/src/BizHawk.WinForms.Controls/MenuEx/ToolStripEx.cs +++ b/src/BizHawk.WinForms.Controls/MenuEx/ToolStripEx.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; diff --git a/src/MainSln.runsettings b/src/MainSln.runsettings new file mode 100644 index 00000000000..cbcc17a7c42 --- /dev/null +++ b/src/MainSln.runsettings @@ -0,0 +1,7 @@ + + + + 300000 + true + + diff --git a/src/MainSlnCommon.props b/src/MainSlnCommon.props index ee63db92524..c28261ab535 100644 --- a/src/MainSlnCommon.props +++ b/src/MainSlnCommon.props @@ -1,12 +1,14 @@ + + true + $(ExecProjTargetFrameworkOverride) + false embedded $(DefineConstants);AVI_SUPPORT - true - $(NoWarn);CS1573;CS1591;NU1702 - $(MSBuildProjectDirectory)/../../output/dll + $(NoWarn);CS1573;NU1702 None @@ -15,12 +17,9 @@ false - - true - $(ExecProjTargetFrameworkOverride) - + diff --git a/src/MainSlnExecutable.props b/src/MainSlnExecutable.props index d184891f85a..0249f6573ec 100644 --- a/src/MainSlnExecutable.props +++ b/src/MainSlnExecutable.props @@ -1,12 +1,22 @@ - $(MSBuildProjectDirectory)/../../output/ + + $(MSBuildProjectDirectory)/../../output/dll/ + $(MSBuildProjectDirectory)/../../output/ + for the executable on build (as one would expect). So we still need to rename the executable file below. Using this method has the advantage + of IDEs respecting the TargetFileName and expecting it. --> $(MSBuildProjectName.Substring($([MSBuild]::Add($(MSBuildProjectName.LastIndexOf('.')), 1)))).exe + + $(ExecFilesDest)$(TargetFileName) + + + + Exe @@ -16,11 +26,12 @@ - - + - + - + + + diff --git a/src/TestProjects.props b/src/TestProjects.props index 60d1d8440da..4c835c68a3b 100644 --- a/src/TestProjects.props +++ b/src/TestProjects.props @@ -5,8 +5,12 @@ $(ProjectDir)../../test_output Exe + + $(TestProjTargetFrameworkOverride) + + \ No newline at end of file diff --git a/submodules/gambatte b/submodules/gambatte index e35e24de89f..0838651ca7c 160000 --- a/submodules/gambatte +++ b/submodules/gambatte @@ -1 +1 @@ -Subproject commit e35e24de89f06642852f622d7d4159ba6a4abea2 +Subproject commit 0838651ca7c06d8c236834dcf5aa307092b2a82e diff --git a/waterbox/.gitignore b/waterbox/.gitignore index 5a1cb4060d8..b57d6819398 100644 --- a/waterbox/.gitignore +++ b/waterbox/.gitignore @@ -1,2 +1,3 @@ /*/obj /sysroot +/llvm-project diff --git a/waterbox/ares64/BizInterface.cpp b/waterbox/ares64/BizInterface.cpp index f5103bc0d99..a29315dfad9 100644 --- a/waterbox/ares64/BizInterface.cpp +++ b/waterbox/ares64/BizInterface.cpp @@ -746,7 +746,7 @@ static u8 PeekFunc(u64 address) } ares::Nintendo64::Thread unused; - return ares::Nintendo64::bus.read(addr, unused); + return ares::Nintendo64::bus.read(addr, unused, nullptr); } static void SysBusAccess(u8* buffer, u64 address, u64 count, bool write) @@ -755,7 +755,7 @@ static void SysBusAccess(u8* buffer, u64 address, u64 count, bool write) { ares::Nintendo64::Thread unused; while (count--) - ares::Nintendo64::bus.write(address++, *buffer++, unused); + ares::Nintendo64::bus.write(address++, *buffer++, unused, nullptr); } else { diff --git a/waterbox/ares64/ares/ares/ares/ares.cpp b/waterbox/ares64/ares/ares/ares/ares.cpp index 46d6c7bbef8..4c7515497bd 100644 --- a/waterbox/ares64/ares/ares/ares/ares.cpp +++ b/waterbox/ares64/ares/ares/ares/ares.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -8,4 +9,13 @@ namespace ares { Platform* platform = nullptr; bool _runAhead = false; +const string Name = "ares"; +const string Version = "138"; +const string Copyright = "ares team, Near"; +const string License = "ISC"; +const string LicenseURI = "https://opensource.org/licenses/ISC"; +const string Website = "ares-emu.net"; +const string WebsiteURI = "https://ares-emu.net/"; +const u32 SerializerSignature = 0x31545342; //"BST1" (little-endian) + } diff --git a/waterbox/ares64/ares/ares/ares/ares.hpp b/waterbox/ares64/ares/ares/ares/ares.hpp index ccebe326286..3bd4ccbd847 100644 --- a/waterbox/ares64/ares/ares/ares/ares.hpp +++ b/waterbox/ares64/ares/ares/ares/ares.hpp @@ -2,7 +2,6 @@ #include #include - #include #include @@ -42,16 +41,14 @@ using namespace nall; using namespace nall::primitives; namespace ares { - static const string Name = "ares"; - static const string Version = "133"; - static const string Copyright = "ares team, Near"; - static const string License = "ISC"; - static const string LicenseURI = "https://opensource.org/licenses/ISC"; - static const string Website = "ares-emu.net"; - static const string WebsiteURI = "https://ares-emu.net/"; - - //incremented only when serialization format changes - static const u32 SerializerSignature = 0x31545342; //"BST1" (little-endian) + extern const string Name; + extern const string Version; + extern const string Copyright; + extern const string License; + extern const string LicenseURI; + extern const string Website; + extern const string WebsiteURI; + extern const u32 SerializerSignature; namespace VFS { using Pak = shared_pointer; diff --git a/waterbox/ares64/ares/ares/ares/memory/fixed-allocator.cpp b/waterbox/ares64/ares/ares/ares/memory/fixed-allocator.cpp index 14f914c9894..4998459b052 100644 --- a/waterbox/ares64/ares/ares/ares/memory/fixed-allocator.cpp +++ b/waterbox/ares64/ares/ares/ares/memory/fixed-allocator.cpp @@ -1,21 +1,32 @@ #include +#if !defined(PLATFORM_MACOS) +#define STATIC_ALLOCATION +#endif + namespace ares::Memory { constexpr u32 fixedBufferSize = 8_MiB; -#if defined(PLATFORM_MACOS) -//dynamic allocation for unsupported platforms -FixedAllocator::FixedAllocator() { - _allocator.resize(fixedBufferSize, bump_allocator::executable); -} -#else -alignas(4096) u8 fixedBuffer[fixedBufferSize]; +#if defined(STATIC_ALLOCATION) +u8 fixedBuffer[fixedBufferSize + 64_KiB]; +#endif FixedAllocator::FixedAllocator() { - _allocator.resize(sizeof(fixedBuffer), 0, fixedBuffer); + u8* buffer = nullptr; + + #if defined(STATIC_ALLOCATION) + //align to 64 KiB (maximum page size of any supported OS) + auto offset = -(uintptr)fixedBuffer % 64_KiB; + //set protection to executable + if(memory::protect(fixedBuffer + offset, fixedBufferSize, true)) { + //use static allocation + buffer = fixedBuffer + offset; + } + #endif + + _allocator.resize(fixedBufferSize, bump_allocator::executable, buffer); } -#endif auto FixedAllocator::get() -> bump_allocator& { static FixedAllocator allocator; diff --git a/waterbox/ares64/ares/ares/ares/memory/fixed-allocator.hpp b/waterbox/ares64/ares/ares/ares/memory/fixed-allocator.hpp index 09d8d85e444..e2763229387 100644 --- a/waterbox/ares64/ares/ares/ares/memory/fixed-allocator.hpp +++ b/waterbox/ares64/ares/ares/ares/memory/fixed-allocator.hpp @@ -1,14 +1,14 @@ -#pragma once - -namespace ares::Memory { - -struct FixedAllocator { - static auto get() -> bump_allocator&; - -private: - FixedAllocator(); - - bump_allocator _allocator; -}; - -} +#pragma once + +namespace ares::Memory { + +struct FixedAllocator { + static auto get() -> bump_allocator&; + +private: + FixedAllocator(); + + bump_allocator _allocator; +}; + +} diff --git a/waterbox/ares64/ares/ares/ares/node/debugger/tracer/instruction.hpp b/waterbox/ares64/ares/ares/ares/node/debugger/tracer/instruction.hpp index 0c354c3b2af..31a778cc512 100644 --- a/waterbox/ares64/ares/ares/ares/node/debugger/tracer/instruction.hpp +++ b/waterbox/ares64/ares/ares/ares/node/debugger/tracer/instruction.hpp @@ -71,9 +71,7 @@ struct Instruction : Tracer { if(!enabled()) return; if(_omitted) { - PlatformLog({ - "[Omitted: ", _omitted, "]\n"} - ); + PlatformLog(shared(), {"[Omitted: ", _omitted, "]"}); _omitted = 0; } @@ -84,7 +82,7 @@ struct Instruction : Tracer { context, " ", extra }; - PlatformLog({output.strip(), "\n"}); + PlatformLog(shared(), {output.strip()}); } auto serialize(string& output, string depth) -> void override { diff --git a/waterbox/ares64/ares/ares/ares/node/debugger/tracer/notification.hpp b/waterbox/ares64/ares/ares/ares/node/debugger/tracer/notification.hpp index a9f7331d387..95a3489807f 100644 --- a/waterbox/ares64/ares/ares/ares/node/debugger/tracer/notification.hpp +++ b/waterbox/ares64/ares/ares/ares/node/debugger/tracer/notification.hpp @@ -6,12 +6,7 @@ struct Notification : Tracer { auto notify(const string& message = {}) -> void { if(!enabled()) return; - - if(message) { - PlatformLog({_component, " ", _name, ": ", message, "\n"}); - } else { - PlatformLog({_component, " ", _name, "\n"}); - } + PlatformLog(shared(), message); } protected: diff --git a/waterbox/ares64/ares/ares/ares/node/debugger/tracer/tracer.hpp b/waterbox/ares64/ares/ares/ares/node/debugger/tracer/tracer.hpp index 82f38e201ac..7ded508506a 100644 --- a/waterbox/ares64/ares/ares/ares/node/debugger/tracer/tracer.hpp +++ b/waterbox/ares64/ares/ares/ares/node/debugger/tracer/tracer.hpp @@ -6,24 +6,40 @@ struct Tracer : Debugger { } auto component() const -> string { return _component; } - auto enabled() const -> bool { return _enabled; } + auto enabled() const -> bool { return file() || terminal(); } + auto prefix() const -> bool { return _prefix; } + auto terminal() const -> bool { return _terminal; } + auto file() const -> bool { return _file; } + auto autoLineBreak() const -> bool { return _autoLineBreak; } + auto setToggle(function toggle) -> void { _toggle = toggle; } auto setComponent(string component) -> void { _component = component; } - auto setEnabled(bool enabled) -> void { _enabled = enabled; } + auto setPrefix(bool prefix) -> void { _prefix = prefix; } + auto setTerminal(bool terminal) -> void { _terminal = terminal; if(_toggle) _toggle(); } + auto setFile(bool file) -> void { _file = file; if(_toggle) _toggle(); } + auto setAutoLineBreak(bool autoLineBreak) -> void { _autoLineBreak = autoLineBreak; } auto serialize(string& output, string depth) -> void override { Debugger::serialize(output, depth); output.append(depth, " component: ", _component, "\n"); - output.append(depth, " enabled: ", _enabled, "\n"); + output.append(depth, " prefix: ", _prefix, "\n"); + output.append(depth, " terminal: ", _terminal, "\n"); + output.append(depth, " file: ", _file, "\n"); } auto unserialize(Markup::Node node) -> void override { Debugger::unserialize(node); _component = node["component"].string(); - _enabled = node["enabled"].boolean(); + _prefix = node["prefix"].boolean(); + _terminal = node["terminal"].boolean(); + _file = node["file"].boolean(); } protected: + function _toggle; string _component; - bool _enabled = false; + bool _prefix = false; + bool _terminal = false; + bool _file = false; + bool _autoLineBreak = true; }; diff --git a/waterbox/ares64/ares/ares/ares/node/input/rumble.hpp b/waterbox/ares64/ares/ares/ares/node/input/rumble.hpp index ea83472d3c7..7d0c5371f84 100644 --- a/waterbox/ares64/ares/ares/ares/node/input/rumble.hpp +++ b/waterbox/ares64/ares/ares/ares/node/input/rumble.hpp @@ -5,7 +5,9 @@ struct Rumble : Input { auto weakValue() const -> u16 { return _weak; } auto strongValue() const -> u16 { return _strong; } - auto setValues(u16 weak, u16 strong) -> void { _weak = weak; _strong = strong; } + auto setValues(u16 strong, u16 weak) -> void { _weak = weak; _strong = strong; } + auto setWeak(u16 weak) -> void { _weak = weak; } + auto setStrong(u16 strong) -> void { _strong = strong; } // For systems with binary motors auto enable() const -> bool { return _weak > 0 || _strong > 0; } diff --git a/waterbox/ares64/ares/ares/ares/node/node.hpp b/waterbox/ares64/ares/ares/ares/node/node.hpp index e91ed880d40..d381bee0a77 100644 --- a/waterbox/ares64/ares/ares/ares/node/node.hpp +++ b/waterbox/ares64/ares/ares/ares/node/node.hpp @@ -94,7 +94,7 @@ namespace ares::Core { // forward declarations static auto PlatformAttach(Node::Object) -> void; static auto PlatformDetach(Node::Object) -> void; - static auto PlatformLog(string_view) -> void; + static auto PlatformLog(Node::Debugger::Tracer::Tracer tracer, string_view) -> void; #include #include diff --git a/waterbox/ares64/ares/ares/ares/node/video/screen.cpp b/waterbox/ares64/ares/ares/ares/node/video/screen.cpp index 19fe96a0443..39e613e42f7 100644 --- a/waterbox/ares64/ares/ares/ares/node/video/screen.cpp +++ b/waterbox/ares64/ares/ares/ares/node/video/screen.cpp @@ -25,11 +25,15 @@ Screen::~Screen() { auto Screen::main(uintptr_t) -> void { while(!_kill) { - usleep(1); - if(_frame) { + unique_lock lock(_frameMutex); + + auto timeout = std::chrono::milliseconds(10); + if(_frameCondition.wait_for(lock, timeout, [&] { return _frame.load(); })) { refresh(); _frame = false; } + + if(_kill) break; } } @@ -68,6 +72,15 @@ auto Screen::setRefresh(function refresh) -> void { _refresh = refresh; } +auto Screen::refreshRateHint(double pixelFrequency, int dotsPerLine, int linesPerFrame) -> void { + refreshRateHint(1.0f / ((double)(dotsPerLine * linesPerFrame) / pixelFrequency)); +} + +auto Screen::refreshRateHint(double refreshRate) -> void { + lock_guard lock(_mutex); + platform->refreshRateHint(refreshRate); +} + auto Screen::setViewport(u32 x, u32 y, u32 width, u32 height) -> void { lock_guard lock(_mutex); _viewportX = x; @@ -76,6 +89,11 @@ auto Screen::setViewport(u32 x, u32 y, u32 width, u32 height) -> void { _viewportHeight = height; } +auto Screen::setOverscan(bool overscan) -> void { + lock_guard lock(_mutex); + _overscan = overscan; +} + auto Screen::setSize(u32 width, u32 height) -> void { lock_guard lock(_mutex); _width = width; @@ -171,10 +189,12 @@ auto Screen::frame() -> void { lock_guard lock(_mutex); _inputA.swap(_inputB); - _frame = true; if constexpr(!ares::Video::Threaded) { refresh(); _frame = false; + } else { + _frame = true; + _frameCondition.notify_one(); } } @@ -228,14 +248,18 @@ auto Screen::refresh() -> void { } } - if(_colorBleed) { + if (_colorBleed) { n32 mask = 1 << 24 | 1 << 16 | 1 << 8 | 1 << 0; - for(u32 y : range(height)) { + for (u32 y : range(height)) { auto target = output + y * width; - for(u32 x : range(width)) { - auto a = target[x]; - auto b = target[x + (x != width - 1)]; - target[x] = (a + b - ((a ^ b) & mask)) >> 1; + for (u32 x : range(0, width, _colorBleedWidth)) { + for (u32 offset = 0; offset < _colorBleedWidth && (x + offset) < width; ++offset) { + u32 next = x + _colorBleedWidth; + if (next + offset >= width) next = x; + auto a = target[x + offset]; + auto b = target[next + offset]; + target[x + offset] = (a + b - ((a ^ b) & mask)) >> 1; + } } } } diff --git a/waterbox/ares64/ares/ares/ares/node/video/screen.hpp b/waterbox/ares64/ares/ares/ares/node/video/screen.hpp index bcc13d1dc59..11e8e985ea2 100644 --- a/waterbox/ares64/ares/ares/ares/node/video/screen.hpp +++ b/waterbox/ares64/ares/ares/ares/node/video/screen.hpp @@ -16,6 +16,7 @@ struct Screen : Video { auto scaleY() const -> f64 { return _scaleY; } auto aspectX() const -> f64 { return _aspectX; } auto aspectY() const -> f64 { return _aspectY; } + auto overscan() const -> bool { return _overscan; } auto colors() const -> u32 { return _colors; } auto pixels(bool frame = 0) -> array_span; @@ -33,10 +34,13 @@ struct Screen : Video { auto setRefresh(function refresh) -> void; auto setViewport(u32 x, u32 y, u32 width, u32 height) -> void; + auto refreshRateHint(double refreshRate) -> void; + auto refreshRateHint(double pixelFrequency, int dotsPerLine, int linesPerFrame) -> void; auto setSize(u32 width, u32 height) -> void; auto setScale(f64 scaleX, f64 scaleY) -> void; auto setAspect(f64 aspectX, f64 aspectY) -> void; + auto setOverscan(bool overscan) -> void; auto setSaturation(f64 saturation) -> void; auto setGamma(f64 gamma) -> void; @@ -44,6 +48,7 @@ struct Screen : Video { auto setFillColor(u32 fillColor) -> void; auto setColorBleed(bool colorBleed) -> void; + auto setColorBleedWidth(u32 width) -> void; auto setInterframeBlending(bool interframeBlending) -> void; auto setRotation(u32 rotation) -> void; @@ -78,7 +83,9 @@ struct Screen : Video { f64 _luminance = 1.0; u32 _fillColor = 0; bool _colorBleed = false; + bool _colorBleedWidth = 1; bool _interframeBlending = false; + bool _overscan = true; u32 _rotation = 0; //counter-clockwise (90 = left, 270 = right) function _color; @@ -92,6 +99,8 @@ struct Screen : Video { //unserialized: nall::thread _thread; recursive_mutex _mutex; + mutex _frameMutex; + condition_variable _frameCondition; atomic _kill = false; atomic _frame = false; function _refresh; diff --git a/waterbox/ares64/ares/ares/ares/platform.hpp b/waterbox/ares64/ares/ares/ares/platform.hpp index c2e670f4ac4..93d1cb34fd0 100644 --- a/waterbox/ares64/ares/ares/ares/platform.hpp +++ b/waterbox/ares64/ares/ares/ares/platform.hpp @@ -15,11 +15,13 @@ struct Platform { virtual auto detach(Node::Object) -> void {} virtual auto pak(Node::Object) -> shared_pointer { return {}; } virtual auto event(Event) -> void {} - virtual auto log(string_view message) -> void {} + virtual auto log(Node::Debugger::Tracer::Tracer, string_view message) -> void {} virtual auto status(string_view message) -> void {} virtual auto video(Node::Video::Screen, const u32* data, u32 pitch, u32 width, u32 height) -> void {} + virtual auto refreshRateHint(double refreshRate) -> void {} virtual auto audio(Node::Audio::Stream) -> void {} virtual auto input(Node::Input::Input) -> void {} + virtual auto cheat(u32 addr) -> maybe { return nothing; } virtual auto time() -> n64 { return ::time(0); } }; @@ -31,5 +33,5 @@ namespace ares::Core { // forward declarations auto PlatformAttach(Node::Object node) -> void { if(platform && node->name()) platform->attach(node); } auto PlatformDetach(Node::Object node) -> void { if(platform && node->name()) platform->detach(node); } - auto PlatformLog(string_view text) -> void { if(platform) platform->log(text); } + auto PlatformLog(Node::Debugger::Tracer::Tracer node, string_view text) -> void { if(platform) platform->log(node, text); } } diff --git a/waterbox/ares64/ares/ares/ares/scheduler/scheduler.hpp b/waterbox/ares64/ares/ares/ares/scheduler/scheduler.hpp index 51dd625dfc5..0f9d67026cf 100644 --- a/waterbox/ares64/ares/ares/ares/scheduler/scheduler.hpp +++ b/waterbox/ares64/ares/ares/ares/scheduler/scheduler.hpp @@ -41,7 +41,7 @@ struct Scheduler { vector _threads; bool _synchronize = false; - friend class Thread; + friend struct Thread; }; extern Scheduler scheduler; diff --git a/waterbox/ares64/ares/ares/ares/scheduler/thread.hpp b/waterbox/ares64/ares/ares/ares/scheduler/thread.hpp index f40941f6ec8..382d88df4fb 100644 --- a/waterbox/ares64/ares/ares/ares/scheduler/thread.hpp +++ b/waterbox/ares64/ares/ares/ares/scheduler/thread.hpp @@ -46,5 +46,5 @@ struct Thread { u64 _scalar = 0; u64 _clock = 0; - friend class Scheduler; + friend struct Scheduler; }; diff --git a/waterbox/ares64/ares/ares/n64/ai/ai.cpp b/waterbox/ares64/ares/ares/n64/ai/ai.cpp index 1b64e26993e..89b5f61da37 100644 --- a/waterbox/ares64/ares/ares/n64/ai/ai.cpp +++ b/waterbox/ares64/ares/ares/n64/ai/ai.cpp @@ -38,7 +38,7 @@ auto AI::sample(f64& left, f64& right) -> void { if(io.dmaLength[0] && io.dmaEnable) { io.dmaAddress[0].bit(13,23) += io.dmaAddressCarry; - auto data = rdram.ram.read(io.dmaAddress[0]); + auto data = rdram.ram.read(io.dmaAddress[0], "AI"); auto l = s16(data >> 16); auto r = s16(data >> 0); left = l / 32768.0; @@ -50,8 +50,9 @@ auto AI::sample(f64& left, f64& right) -> void { } if(!io.dmaLength[0]) { if(--io.dmaCount) { - io.dmaAddress[0] = io.dmaAddress[1]; - io.dmaLength [0] = io.dmaLength [1]; + io.dmaAddress[0] = io.dmaAddress[1]; + io.dmaLength [0] = io.dmaLength [1]; + io.dmaOriginPc[0] = io.dmaOriginPc[1]; mi.raise(MI::IRQ::AI); } } diff --git a/waterbox/ares64/ares/ares/n64/ai/ai.hpp b/waterbox/ares64/ares/ares/n64/ai/ai.hpp index aee1602da89..e6ff587e523 100644 --- a/waterbox/ares64/ares/ares/n64/ai/ai.hpp +++ b/waterbox/ares64/ares/ares/n64/ai/ai.hpp @@ -38,6 +38,7 @@ struct AI : Thread, Memory::RCP { n1 dmaAddressCarry; n18 dmaLength[2]; n2 dmaCount; + u64 dmaOriginPc[2]; n14 dacRate; n4 bitRate; } io; diff --git a/waterbox/ares64/ares/ares/n64/ai/io.cpp b/waterbox/ares64/ares/ares/n64/ai/io.cpp index d72a3ef408e..ce4694685bc 100644 --- a/waterbox/ares64/ares/ares/n64/ai/io.cpp +++ b/waterbox/ares64/ares/ares/n64/ai/io.cpp @@ -1,5 +1,5 @@ auto AI::readWord(u32 address, Thread& thread) -> u32 { - address = (address & 0xfffff) >> 2; + address = (address & 0x1f) >> 2; n32 data; if(address != 3) { @@ -22,7 +22,7 @@ auto AI::readWord(u32 address, Thread& thread) -> u32 { } auto AI::writeWord(u32 address, u32 data_, Thread& thread) -> void { - address = (address & 0xfffff) >> 2; + address = (address & 0x1f) >> 2; n32 data = data_; if(address == 0) { @@ -38,6 +38,7 @@ auto AI::writeWord(u32 address, u32 data_, Thread& thread) -> void { if(io.dmaCount < 2) { if(io.dmaCount == 0) mi.raise(MI::IRQ::AI); io.dmaLength[io.dmaCount] = length; + io.dmaOriginPc[io.dmaCount] = cpu.ipu.pc; io.dmaCount++; } } diff --git a/waterbox/ares64/ares/ares/n64/cartridge/cartridge.cpp b/waterbox/ares64/ares/ares/n64/cartridge/cartridge.cpp index 9826499ec4e..14a1f788046 100644 --- a/waterbox/ares64/ares/ares/n64/cartridge/cartridge.cpp +++ b/waterbox/ares64/ares/ares/n64/cartridge/cartridge.cpp @@ -47,7 +47,12 @@ auto Cartridge::connect() -> void { rtc.load(); - isviewer.ram.allocate(64_KiB); + if(rom.size <= 0x03fe'ffff) { + isviewer.ram.allocate(64_KiB); + isviewer.tracer = node->append("ISViewer", "Cartridge"); + isviewer.tracer->setAutoLineBreak(false); + isviewer.tracer->setTerminal(true); + } debugger.load(node); diff --git a/waterbox/ares64/ares/ares/n64/cartridge/cartridge.hpp b/waterbox/ares64/ares/ares/n64/cartridge/cartridge.hpp index 22825ba5e3c..9efbf30a4a4 100644 --- a/waterbox/ares64/ares/ares/n64/cartridge/cartridge.hpp +++ b/waterbox/ares64/ares/ares/n64/cartridge/cartridge.hpp @@ -40,8 +40,12 @@ struct Cartridge { } flash; struct ISViewer : Memory::PI { Memory::Writable ram; //unserialized + Node::Debugger::Tracer::Notification tracer; + + auto enabled() -> bool { return ram.size; } //isviewer.cpp + auto messageChar(char c) -> void; auto readHalf(u32 address) -> u16; auto writeHalf(u32 address, u16 data) -> void; auto readWord(u32 address) -> u32; diff --git a/waterbox/ares64/ares/ares/n64/cartridge/flash.cpp b/waterbox/ares64/ares/ares/n64/cartridge/flash.cpp index cfcbe2bf72e..32402929d33 100644 --- a/waterbox/ares64/ares/ares/n64/cartridge/flash.cpp +++ b/waterbox/ares64/ares/ares/n64/cartridge/flash.cpp @@ -85,7 +85,8 @@ auto Cartridge::Flash::writeWord(u32 address, u64 data) -> void { } if(mode == Mode::Write) { for(u32 index = 0; index < 128; index += 2) { - u16 half = rdram.ram.read(source + index); + // FIXME: this is obviously wrong, the flash can't access RDRAM + u16 half = rdram.ram.read(source + index, "Flash"); Memory::Writable::write(offset + index, half); } } diff --git a/waterbox/ares64/ares/ares/n64/cartridge/isviewer.cpp b/waterbox/ares64/ares/ares/n64/cartridge/isviewer.cpp index f7df89abfa5..bb38b3e74d7 100644 --- a/waterbox/ares64/ares/ares/n64/cartridge/isviewer.cpp +++ b/waterbox/ares64/ares/ares/n64/cartridge/isviewer.cpp @@ -8,6 +8,11 @@ auto Cartridge::ISViewer::readWord(u32 address) -> u32 { return ram.read(address); } +auto Cartridge::ISViewer::messageChar(char c) -> void { + if(!tracer->enabled()) return; + tracer->notify(c); +} + auto Cartridge::ISViewer::writeHalf(u32 address, u16 data) -> void { address = (address & 0xffff); @@ -23,7 +28,7 @@ auto Cartridge::ISViewer::writeHalf(u32 address, u16 data) -> void { // functional. for(auto address : range(data)) { char c = ram.read(0x20 + address); - fputc(c, stdout); + messageChar(c); } return; } diff --git a/waterbox/ares64/ares/ares/n64/cartridge/rtc.cpp b/waterbox/ares64/ares/ares/n64/cartridge/rtc.cpp index 66530fa593c..30459491815 100644 --- a/waterbox/ares64/ares/ares/n64/cartridge/rtc.cpp +++ b/waterbox/ares64/ares/ares/n64/cartridge/rtc.cpp @@ -1,4 +1,3 @@ - auto Cartridge::RTC::power(bool reset) -> void { if(present) run(!status.bit(7)); } @@ -11,8 +10,16 @@ auto Cartridge::RTC::load() -> void { present = 1; n64 timestamp = ram.read(24); if(!~timestamp) { - ram.fill(0); - ram.write(21, 1); + time_t t = (time_t)0; + struct tm tmm = *gmtime(&t); + ram.write(16, BCD::encode(tmm.tm_sec)); + ram.write(17, BCD::encode(tmm.tm_min)); + ram.write(18, BCD::encode(tmm.tm_hour) | 0x80); + ram.write(19, BCD::encode(tmm.tm_mday)); + ram.write(20, BCD::encode(tmm.tm_wday)); + ram.write(21, BCD::encode(tmm.tm_mon + 1)); + ram.write(22, BCD::encode(tmm.tm_year % 100)); + ram.write(23, BCD::encode(tmm.tm_year / 100)); } timestamp = platform->time() - timestamp; @@ -45,26 +52,42 @@ auto Cartridge::RTC::running() -> bool { } auto Cartridge::RTC::advance(int nsec) -> void { - struct tm tmm = {}; - tmm.tm_sec = BCD::decode(ram.read(16)); - tmm.tm_min = BCD::decode(ram.read(17)); - tmm.tm_hour = BCD::decode(ram.read(18) & 0x7f); - tmm.tm_mday = BCD::decode(ram.read(19)); - tmm.tm_mon = BCD::decode(ram.read(21)) - 1; - tmm.tm_year = BCD::decode(ram.read(22)) + 100 * BCD::decode(ram.read(23)); - time_t t = mktime(&tmm); + auto seconds = BCD::decode(ram.read(16)); + auto minutes = BCD::decode(ram.read(17)); + auto hours = BCD::decode(ram.read(18) & 0x7f); + auto day = BCD::decode(ram.read(19)); + auto wday = BCD::decode(ram.read(20)); + auto month = BCD::decode(ram.read(21)); + auto year = BCD::decode(ram.read(22)) + 100 * BCD::decode(ram.read(23)); - t += nsec; + while(nsec--) { + if(++seconds == 60) { + seconds = 0; + if(++minutes == 60) { + minutes = 0; + if(++hours == 24) { + hours = 0; + if(++wday == 7) wday = 0; + if(++day > chrono::daysInMonth(month, year)) { + day = 1; + if(++month == 13) { + month = 1; + year++; + } + } + } + } + } + } - tmm = *localtime(&t); - ram.write(16, BCD::encode(tmm.tm_sec)); - ram.write(17, BCD::encode(tmm.tm_min)); - ram.write(18, BCD::encode(tmm.tm_hour) | 0x80); - ram.write(19, BCD::encode(tmm.tm_mday)); - ram.write(20, BCD::encode(tmm.tm_wday)); - ram.write(21, BCD::encode(tmm.tm_mon + 1)); - ram.write(22, BCD::encode(tmm.tm_year % 100)); - ram.write(23, BCD::encode(tmm.tm_year / 100)); + ram.write(16, BCD::encode(seconds)); + ram.write(17, BCD::encode(minutes)); + ram.write(18, BCD::encode(hours) | 0x80); + ram.write(19, BCD::encode(day)); + ram.write(20, BCD::encode(wday)); + ram.write(21, BCD::encode(month)); + ram.write(22, BCD::encode(year % 100)); + ram.write(23, BCD::encode(year / 100)); } auto Cartridge::RTC::read(u2 block, n8* data) -> void { diff --git a/waterbox/ares64/ares/ares/n64/controller/gamepad/gamepad.cpp b/waterbox/ares64/ares/ares/n64/controller/gamepad/gamepad.cpp index 837cb588d05..f3c96424c86 100644 --- a/waterbox/ares64/ares/ares/n64/controller/gamepad/gamepad.cpp +++ b/waterbox/ares64/ares/ares/n64/controller/gamepad/gamepad.cpp @@ -8,7 +8,7 @@ Gamepad::Gamepad(Node::Port parent) { port->setAllocate([&](auto name) { return allocate(name); }); port->setConnect([&] { return connect(); }); port->setDisconnect([&] { return disconnect(); }); - port->setSupported({"Controller Pak", "Rumble Pak"}); + port->setSupported({"Controller Pak", "Rumble Pak", "Transfer Pak"}); x = node->append ("X-Axis"); y = node->append ("Y-Axis"); @@ -166,9 +166,7 @@ auto Gamepad::comm(n8 send, n8 recv, n8 input[], n8 output[]) -> n2 { if(transferPak) { u16 address = (input[1] << 8 | input[2] << 0) & ~31; if(pif.addressCRC(address) == (n5)input[2]) { - for(u32 index : range(recv - 1)) { - output[index] = transferPak.read(address++); - } + for(u32 index : range(recv - 1)) output[index] = transferPak.read(address++); output[recv - 1] = pif.dataCRC({&output[0], recv - 1u}); valid = 1; } diff --git a/waterbox/ares64/ares/ares/n64/cpu/cpu.cpp b/waterbox/ares64/ares/ares/n64/cpu/cpu.cpp index 7bb06317ff3..0994f4a1d14 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/cpu.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/cpu.cpp @@ -1,4 +1,5 @@ #include +#include namespace ares::Nintendo64 { @@ -63,7 +64,7 @@ auto CPU::synchronize() -> void { case Queue::SI_DMA_Write: return si.dmaWrite(); case Queue::SI_BUS_Write: return si.writeFinished(); case Queue::RTC_Tick: return cartridge.rtc.tick(); - case Queue::DD_Clock_Tick: return dd.rtcTickClock(); + case Queue::DD_Clock_Tick: return dd.rtc.tickClock(); case Queue::DD_MECHA_Response: return dd.mechaResponse(); case Queue::DD_BM_Request: return dd.bmRequest(); case Queue::DD_Motor_Mode: return dd.motorChange(); @@ -90,6 +91,10 @@ auto CPU::instruction() -> void { step(1 * 2); return exception.nmi(); } + if (scc.sysadFrozen) { + step(1 * 2); + return; + } if constexpr(Accuracy::CPU::Recompiler) { // Fast path: attempt to lookup previously compiled blocks with devirtualizeFast @@ -104,26 +109,30 @@ auto CPU::instruction() -> void { } if (auto address = devirtualize(ipu.pc)) { - auto block = recompiler.block(ipu.pc, *address); + auto block = recompiler.block(ipu.pc, *address, false); block->execute(*this); } } if constexpr(Accuracy::CPU::Interpreter) { - pipeline.address = ipu.pc; auto data = fetch(ipu.pc); if (!data) return; - pipeline.instruction = *data; - debugger.instruction(); + instructionPrologue(*data); decoderEXECUTE(); instructionEpilogue(); } } +auto CPU::instructionPrologue(u32 instruction) -> void { + pipeline.address = ipu.pc; + pipeline.instruction = instruction; + debugger.instruction(); +} + auto CPU::instructionEpilogue() -> s32 { if constexpr(Accuracy::CPU::Recompiler) { //simulates timings without performing actual icache loads - icache.step(ipu.pc, devirtualizeFast(ipu.pc)); + icache.step(ipu.pc, devirtualizeFast(ipu.pc)); } ipu.r[0].u64 = 0; @@ -168,9 +177,7 @@ auto CPU::power(bool reset) -> void { if constexpr(Accuracy::CPU::Recompiler) { auto buffer = ares::Memory::FixedAllocator::get().tryAcquire(4_MiB); - memory::jitprotect(false); - recompiler.allocator.resize(4_MiB, bump_allocator::executable | bump_allocator::zero_fill, buffer); - memory::jitprotect(true); + recompiler.allocator.resize(4_MiB, bump_allocator::executable, buffer); recompiler.reset(); } } diff --git a/waterbox/ares64/ares/ares/n64/cpu/cpu.hpp b/waterbox/ares64/ares/ares/n64/cpu/cpu.hpp index 82ba1fdc812..6abad3678c9 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/cpu.hpp +++ b/waterbox/ares64/ares/ares/n64/cpu/cpu.hpp @@ -36,6 +36,7 @@ struct CPU : Thread { auto synchronize() -> void; auto instruction() -> void; + auto instructionPrologue(u32 instruction) -> void; auto instructionEpilogue() -> s32; auto power(bool reset) -> void; @@ -147,26 +148,12 @@ struct CPU : Thread { cpu.step(48 * 2); valid = 1; tag = address & ~0x0000'0fff; - words[0] = cpu.busRead(tag | index | 0x00); - words[1] = cpu.busRead(tag | index | 0x04); - words[2] = cpu.busRead(tag | index | 0x08); - words[3] = cpu.busRead(tag | index | 0x0c); - words[4] = cpu.busRead(tag | index | 0x10); - words[5] = cpu.busRead(tag | index | 0x14); - words[6] = cpu.busRead(tag | index | 0x18); - words[7] = cpu.busRead(tag | index | 0x1c); + cpu.busReadBurst(tag | index, words); } auto writeBack(CPU& cpu) -> void { cpu.step(48 * 2); - cpu.busWrite(tag | index | 0x00, words[0]); - cpu.busWrite(tag | index | 0x04, words[1]); - cpu.busWrite(tag | index | 0x08, words[2]); - cpu.busWrite(tag | index | 0x0c, words[3]); - cpu.busWrite(tag | index | 0x10, words[4]); - cpu.busWrite(tag | index | 0x14, words[5]); - cpu.busWrite(tag | index | 0x18, words[6]); - cpu.busWrite(tag | index | 0x1c, words[7]); + cpu.busWriteBurst(tag | index, words); } auto read(u32 address) const -> u32 { return words[address >> 2 & 7]; } @@ -186,19 +173,22 @@ struct CPU : Thread { template auto write(u32 vaddr, u32 address, u64 data) -> void; auto power(bool reset) -> void; + auto readDebug(u32 vaddr, u32 address) -> u8; + //8KB struct Line { auto hit(u32 address) const -> bool; - template auto fill(u32 address, u64 data) -> void; auto fill(u32 address) -> void; auto writeBack() -> void; template auto read(u32 address) const -> u64; template auto write(u32 address, u64 data) -> void; bool valid; - bool dirty; + u16 dirty; u32 tag; u16 index; + u64 fillPc; + u64 dirtyPc; union { u8 bytes[16]; u16 halfs[8]; @@ -242,11 +232,12 @@ struct CPU : Thread { } entry[TLB::Entries]; //tlb.cpp - auto load(u64 vaddr) -> Match; - auto load(u64 vaddr, const Entry& entry) -> Match; + auto load(u64 vaddr, bool noExceptions = false) -> Match; + auto load(u64 vaddr, const Entry& entry, bool noExceptions = false) -> maybe; + auto loadFast(u64 vaddr) -> Match; auto store(u64 vaddr) -> Match; - auto store(u64 vaddr, const Entry& entry) -> Match; + auto store(u64 vaddr, const Entry& entry) -> maybe; struct TlbCache { ; static constexpr int entries = 4; @@ -292,15 +283,20 @@ struct CPU : Thread { auto segment(u64 vaddr) -> Context::Segment; auto devirtualize(u64 vaddr) -> maybe; alwaysinline auto devirtualizeFast(u64 vaddr) -> u64; + auto devirtualizeDebug(u64 vaddr) -> u64; auto fetch(u64 vaddr) -> maybe; template auto busWrite(u32 address, u64 data) -> void; template auto busRead(u32 address) -> u64; + template auto busWriteBurst(u32 address, u32 *data) -> void; + template auto busReadBurst(u32 address, u32 *data) -> void; template auto read(u64 vaddr) -> maybe; template auto write(u64 vaddr, u64 data, bool alignedError=true) -> bool; template auto vaddrAlignedError(u64 vaddr, bool write) -> bool; auto addressException(u64 vaddr) -> void; + auto readDebug(u64 vaddr) -> u8; + //serialization.cpp auto serialize(serializer&) -> void; @@ -631,6 +627,7 @@ struct CPU : Thread { //other n64 latch; n1 nmiPending; + n1 sysadFrozen; } scc; //interpreter-scc.cpp @@ -655,7 +652,7 @@ struct CPU : Thread { struct Coprocessor { static constexpr u8 revision = 0x00; - static constexpr u8 implementation = 0x0b; + static constexpr u8 implementation = 0x0a; } coprocessor; struct ControlStatus { @@ -690,7 +687,9 @@ struct CPU : Thread { //interpreter-fpu.cpp float_env fenv; - template auto fgr(u32) -> T&; + template auto fgr_t(u32) -> T&; + template auto fgr_s(u32) -> T&; + template auto fgr_d(u32) -> T&; auto getControlRegisterFPU(n5) -> u32; auto setControlRegisterFPU(n5, n32) -> void; template auto checkFPUExceptions() -> bool; @@ -701,8 +700,10 @@ struct CPU : Thread { auto fpeInvalidOperation() -> bool; auto fpeUnimplemented() -> bool; auto fpuCheckStart() -> bool; - auto fpuCheckInput(f32& f) -> bool; - auto fpuCheckInput(f64& f) -> bool; + template + auto fpuCheckInput(T& f) -> bool; + template + auto fpuCheckInputs(T& f1, T& f2) -> bool; auto fpuCheckOutput(f32& f) -> bool; auto fpuCheckOutput(f64& f) -> bool; auto fpuClearCause() -> void; @@ -894,10 +895,10 @@ struct CPU : Thread { } auto pool(u32 address) -> Pool*; - auto block(u32 vaddr, u32 address) -> Block*; + auto block(u32 vaddr, u32 address, bool singleInstruction = false) -> Block*; auto fastFetchBlock(u32 address) -> Block*; - auto emit(u32 vaddr, u32 address) -> Block*; + auto emit(u32 vaddr, u32 address, bool singleInstruction = false) -> Block*; auto emitEXECUTE(u32 instruction) -> bool; auto emitSPECIAL(u32 instruction) -> bool; auto emitREGIMM(u32 instruction) -> bool; @@ -905,6 +906,7 @@ struct CPU : Thread { auto emitFPU(u32 instruction) -> bool; auto emitCOP2(u32 instruction) -> bool; + bool callInstructionPrologue = false; bump_allocator allocator; Pool* pools[1 << 21]; //2_MiB * sizeof(void*) == 16_MiB } recompiler{*this}; diff --git a/waterbox/ares64/ares/ares/n64/cpu/dcache.cpp b/waterbox/ares64/ares/ares/n64/cpu/dcache.cpp index 5fa69aa3d3a..96befd01c76 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/dcache.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/dcache.cpp @@ -2,63 +2,19 @@ auto CPU::DataCache::Line::hit(u32 address) const -> bool { return valid && tag == (address & ~0x0000'0fff); } -template auto CPU::DataCache::Line::fill(u32 address, u64 data) -> void { - cpu.step(40 * 2); - valid = 1; - dirty = 1; - tag = address & ~0x0000'0fff; - //read words according to critical doubleword first scheme - switch(address & 8) { - case 0: - if constexpr(Size != Dual) { - words[0] = cpu.busRead(tag | index | 0x0); - words[1] = cpu.busRead(tag | index | 0x4); - } - write(address, data); - words[2] = cpu.busRead(tag | index | 0x8); - words[3] = cpu.busRead(tag | index | 0xc); - break; - case 8: - if constexpr(Size != Dual) { - words[2] = cpu.busRead(tag | index | 0x8); - words[3] = cpu.busRead(tag | index | 0xc); - } - write(address, data); - words[0] = cpu.busRead(tag | index | 0x0); - words[1] = cpu.busRead(tag | index | 0x4); - break; - } -} - auto CPU::DataCache::Line::fill(u32 address) -> void { cpu.step(40 * 2); - valid = 1; - dirty = 0; - tag = address & ~0x0000'0fff; - //read words according to critical doubleword first scheme - switch(address & 8) { - case 0: - words[0] = cpu.busRead(tag | index | 0x0); - words[1] = cpu.busRead(tag | index | 0x4); - words[2] = cpu.busRead(tag | index | 0x8); - words[3] = cpu.busRead(tag | index | 0xc); - break; - case 8: - words[2] = cpu.busRead(tag | index | 0x8); - words[3] = cpu.busRead(tag | index | 0xc); - words[0] = cpu.busRead(tag | index | 0x0); - words[1] = cpu.busRead(tag | index | 0x4); - break; - } + valid = 1; + dirty = 0; + tag = address & ~0x0000'0fff; + fillPc = cpu.ipu.pc; + cpu.busReadBurst(tag | index, words); } auto CPU::DataCache::Line::writeBack() -> void { cpu.step(40 * 2); dirty = 0; - cpu.busWrite(tag | index | 0x0, words[0]); - cpu.busWrite(tag | index | 0x4, words[1]); - cpu.busWrite(tag | index | 0x8, words[2]); - cpu.busWrite(tag | index | 0xc, words[3]); + cpu.busWriteBurst(tag | index, words); } auto CPU::DataCache::line(u32 vaddr) -> Line& { @@ -86,7 +42,8 @@ auto CPU::DataCache::Line::write(u32 address, u64 data) -> void { words[address >> 2 & 2 | 0] = data >> 32; words[address >> 2 & 2 | 1] = data >> 0; } - dirty = 1; + dirty |= ((1 << Size) - 1) << (address & 0xF); + dirtyPc = cpu.ipu.pc; } template @@ -101,12 +58,21 @@ auto CPU::DataCache::read(u32 vaddr, u32 address) -> u64 { return line.read(address); } +auto CPU::DataCache::readDebug(u32 vaddr, u32 address) -> u8 { + auto& line = this->line(vaddr); + if(!line.hit(address)) { + Thread dummyThread{}; + return bus.read(address, dummyThread, "Ares Debugger"); + } + return line.read(address); +} + template auto CPU::DataCache::write(u32 vaddr, u32 address, u64 data) -> void { auto& line = this->line(vaddr); if(!line.hit(address)) { if(line.valid && line.dirty) line.writeBack(); - return line.fill(address, data); + line.fill(address); } else { cpu.step(1 * 2); } @@ -123,3 +89,6 @@ auto CPU::DataCache::power(bool reset) -> void { for(auto& word : line.words) word = 0; } } + +template +auto CPU::DataCache::Line::write(u32 address, u64 data) -> void; diff --git a/waterbox/ares64/ares/ares/n64/cpu/debugger.cpp b/waterbox/ares64/ares/ares/n64/cpu/debugger.cpp index dc284e5b154..3a061cc9d92 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/debugger.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/debugger.cpp @@ -2,6 +2,12 @@ auto CPU::Debugger::load(Node::Object parent) -> void { tracer.instruction = parent->append("Instruction", "CPU"); tracer.instruction->setAddressBits(64, 2); tracer.instruction->setDepth(64); + if constexpr(Accuracy::CPU::Recompiler) { + tracer.instruction->setToggle([&] { + cpu.recompiler.reset(); + cpu.recompiler.callInstructionPrologue = tracer.instruction->enabled(); + }); + } tracer.exception = parent->append("Exception", "CPU"); tracer.interrupt = parent->append("Interrupt", "CPU"); diff --git a/waterbox/ares64/ares/ares/n64/cpu/exceptions.cpp b/waterbox/ares64/ares/ares/n64/cpu/exceptions.cpp index 310662f4968..00189db5c12 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/exceptions.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/exceptions.cpp @@ -1,6 +1,11 @@ auto CPU::Exception::trigger(u32 code, u32 coprocessor, bool tlbMiss) -> void { self.debugger.exception(code); + if(code != 0) { + auto sig = (code == 2 || code == 3) ? GDB::Signal::SEGV : GDB::Signal::TRAP; + GDB::server.reportSignal(sig, self.ipu.pc); + } + u64 vectorBase = !self.scc.status.vectorLocation ? (s32)0x8000'0000 : (s32)0xbfc0'0200; u16 vectorOffset = 0x0180; diff --git a/waterbox/ares64/ares/ares/n64/cpu/interpreter-fpu.cpp b/waterbox/ares64/ares/ares/n64/cpu/interpreter-fpu.cpp index 796d2636064..5da902a278e 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/interpreter-fpu.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/interpreter-fpu.cpp @@ -7,7 +7,7 @@ auto CPU::FPU::setFloatingPointMode(bool mode) -> void { } } -template<> auto CPU::fgr(u32 index) -> s32& { +template<> auto CPU::fgr_t(u32 index) -> s32& { if(scc.status.floatingPointMode) { return fpu.r[index].s32; } else if(index & 1) { @@ -17,21 +17,41 @@ template<> auto CPU::fgr(u32 index) -> s32& { } } -template<> auto CPU::fgr(u32 index) -> u32& { - return (u32&)fgr(index); +template<> auto CPU::fgr_s(u32 index) -> s32& { + if(scc.status.floatingPointMode) { + return fpu.r[index].s32; + } else { + return fpu.r[index & ~1].s32; + } +} + +template<> auto CPU::fgr_d(u32 index) -> s32& { + fpu.r[index].s32h = 0; + return fpu.r[index].s32; +} + +template<> auto CPU::fgr_t(u32 index) -> u32& { + return (u32&)fgr_t(index); +} + +template<> auto CPU::fgr_t(u32 index) -> f32& { + return fpu.r[index].f32; } -template<> auto CPU::fgr(u32 index) -> f32& { +template<> auto CPU::fgr_d(u32 index) -> f32& { + fpu.r[index].f32h = 0; + return fpu.r[index].f32; +} + +template<> auto CPU::fgr_s(u32 index) -> f32& { if(scc.status.floatingPointMode) { return fpu.r[index].f32; - } else if(index & 1) { - return fpu.r[index & ~1].f32h; } else { return fpu.r[index & ~1].f32; } } -template<> auto CPU::fgr(u32 index) -> s64& { +template<> auto CPU::fgr_t(u32 index) -> s64& { if(scc.status.floatingPointMode) { return fpu.r[index].s64; } else { @@ -39,11 +59,31 @@ template<> auto CPU::fgr(u32 index) -> s64& { } } -template<> auto CPU::fgr(u32 index) -> u64& { - return (u64&)fgr(index); +template<> auto CPU::fgr_d(u32 index) -> s64& { + return fpu.r[index].s64; +} + +template<> auto CPU::fgr_s(u32 index) -> s64& { + return fgr_t(index); +} + +template<> auto CPU::fgr_t(u32 index) -> u64& { + return (u64&)fgr_t(index); +} + +template<> auto CPU::fgr_s(u32 index) -> u64& { + return fgr_t(index); +} + +template<> auto CPU::fgr_t(u32 index) -> f64& { + return fpu.r[index].f64; } -template<> auto CPU::fgr(u32 index) -> f64& { +template<> auto CPU::fgr_d(u32 index) -> f64& { + return fgr_t(index); +} + +template<> auto CPU::fgr_s(u32 index) -> f64& { if(scc.status.floatingPointMode) { return fpu.r[index].f64; } else { @@ -210,8 +250,9 @@ auto CPU::checkFPUExceptions() -> bool { #define CHECK_FPE_IMPL(type, res, operation, convert) \ fenv.clearExcept(); \ - type res = [&]() noinline -> type { return operation; }(); \ - if (checkFPUExceptions()) return; + volatile type v##res = [&]() noinline -> type { return operation; }(); \ + if (checkFPUExceptions()) return; \ + type res = v##res; #define CHECK_FPE(type, res, operation) CHECK_FPE_IMPL(type, res, operation, false) #define CHECK_FPE_CONV(type, res, operation) CHECK_FPE_IMPL(type, res, operation, true) @@ -240,7 +281,9 @@ auto CPU::fpuCheckStart() -> bool { return true; } -auto CPU::fpuCheckInput(f32& f) -> bool { +template +auto CPU::fpuCheckInput(T& f) -> bool { + static_assert(std::is_same_v || std::is_same_v); switch (fpclassify(f)) { case FP_SUBNORMAL: if(fpeUnimplemented()) return exception.floatingPoint(), false; @@ -253,19 +296,23 @@ auto CPU::fpuCheckInput(f32& f) -> bool { return true; } -auto CPU::fpuCheckInput(f64& f) -> bool { - switch (fpclassify(f)) { - case FP_SUBNORMAL: +template +auto CPU::fpuCheckInputs(T& f1, T& f2) -> bool { + static_assert(std::is_same_v || std::is_same_v); + int cl1 = fpclassify(f1), cl2 = fpclassify(f2); + if((cl1 == FP_NAN && !qnan(f1)) || (cl2 == FP_NAN && !qnan(f2))) { + if(fpeUnimplemented()) return exception.floatingPoint(), false; + } + if(cl1 == FP_SUBNORMAL || cl2 == FP_SUBNORMAL) { if(fpeUnimplemented()) return exception.floatingPoint(), false; - return true; - case FP_NAN: - if(qnan(f) ? fpeInvalidOperation() : fpeUnimplemented()) - return exception.floatingPoint(), false; - return true; + } + if((cl1 == FP_NAN && qnan(f1)) || (cl2 == FP_NAN && qnan(f2))) { + if(fpeInvalidOperation()) return exception.floatingPoint(), false; } return true; } + template auto fpuFlushResult(T f, u32 roundMode) -> T { @@ -364,9 +411,9 @@ auto CPU::fpuCheckInputConv(f64& f) -> bool { } #define CF fpu.csr.compare -#define FD(type) fgr(fd) -#define FS(type) fgr(fs) -#define FT(type) fgr(ft) +#define FD(type) fgr_d(fd) +#define FS(type) fgr_s(fs) +#define FT(type) fgr_t(ft) auto CPU::BC1(bool value, bool likely, s16 imm) -> void { if(!fpuCheckStart()) return; @@ -416,8 +463,7 @@ auto CPU::FABS_D(u8 fd, u8 fs) -> void { auto CPU::FADD_S(u8 fd, u8 fs, u8 ft) -> void { if(!fpuCheckStart()) return; f32 ffs = FS(f32), fft = FT(f32); - if(!fpuCheckInput(ffs)) return; - if(!fpuCheckInput(fft)) return; + if(!fpuCheckInputs(ffs, fft)) return; CHECK_FPE(f32, ffd, FS(f32) + FT(f32)); if(!fpuCheckOutput(ffd)) return; FD(f32) = ffd; @@ -427,8 +473,7 @@ auto CPU::FADD_S(u8 fd, u8 fs, u8 ft) -> void { auto CPU::FADD_D(u8 fd, u8 fs, u8 ft) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64), fft = FT(f64); - if(!fpuCheckInput(ffs)) return; - if(!fpuCheckInput(fft)) return; + if(!fpuCheckInputs(ffs, fft)) return; CHECK_FPE(f64, ffd, ffs + fft); if(!fpuCheckOutput(ffd)) return; FD(f64) = ffd; @@ -758,8 +803,7 @@ auto CPU::FCVT_W_D(u8 fd, u8 fs) -> void { auto CPU::FDIV_S(u8 fd, u8 fs, u8 ft) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f32), fft = FT(f32); - if(!fpuCheckInput(ffs)) return; - if(!fpuCheckInput(fft)) return; + if(!fpuCheckInputs(ffs, fft)) return; CHECK_FPE(f32, ffd, ffs / fft); if(!fpuCheckOutput(ffd)) return; FD(f32) = ffd; @@ -769,8 +813,7 @@ auto CPU::FDIV_S(u8 fd, u8 fs, u8 ft) -> void { auto CPU::FDIV_D(u8 fd, u8 fs, u8 ft) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64), fft = FT(f64); - if(!fpuCheckInput(ffs)) return; - if(!fpuCheckInput(fft)) return; + if(!fpuCheckInputs(ffs, fft)) return; CHECK_FPE(f64, ffd, ffs / fft); if(!fpuCheckOutput(ffd)) return; FD(f64) = ffd; @@ -814,8 +857,7 @@ auto CPU::FFLOOR_W_D(u8 fd, u8 fs) -> void { } auto CPU::FMOV_S(u8 fd, u8 fs) -> void { - if(!scc.status.enable.coprocessor1) return exception.coprocessor1(); - FD(f32) = FS(f32); + return FMOV_D(fd, fs); } auto CPU::FMOV_D(u8 fd, u8 fs) -> void { @@ -826,8 +868,7 @@ auto CPU::FMOV_D(u8 fd, u8 fs) -> void { auto CPU::FMUL_S(u8 fd, u8 fs, u8 ft) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f32), fft = FT(f32); - if(!fpuCheckInput(ffs)) return; - if(!fpuCheckInput(fft)) return; + if(!fpuCheckInputs(ffs, fft)) return; CHECK_FPE(f32, ffd, ffs * fft); if(!fpuCheckOutput(ffd)) return; FD(f32) = ffd; @@ -837,8 +878,7 @@ auto CPU::FMUL_S(u8 fd, u8 fs, u8 ft) -> void { auto CPU::FMUL_D(u8 fd, u8 fs, u8 ft) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64), fft = FT(f64); - if(!fpuCheckInput(ffs)) return; - if(!fpuCheckInput(fft)) return; + if(!fpuCheckInputs(ffs, fft)) return; CHECK_FPE(f64, ffd, ffs * fft); if(!fpuCheckOutput(ffd)) return; FD(f64) = ffd; @@ -926,8 +966,7 @@ auto CPU::FSQRT_D(u8 fd, u8 fs) -> void { auto CPU::FSUB_S(u8 fd, u8 fs, u8 ft) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f32), fft = FT(f32); - if(!fpuCheckInput(ffs)) return; - if(!fpuCheckInput(fft)) return; + if(!fpuCheckInputs(ffs, fft)) return; CHECK_FPE(f32, ffd, ffs - fft); if(!fpuCheckOutput(ffd)) return; FD(f32) = ffd; @@ -937,8 +976,7 @@ auto CPU::FSUB_S(u8 fd, u8 fs, u8 ft) -> void { auto CPU::FSUB_D(u8 fd, u8 fs, u8 ft) -> void { if(!fpuCheckStart()) return; auto ffs = FS(f64), fft = FT(f64); - if(!fpuCheckInput(ffs)) return; - if(!fpuCheckInput(fft)) return; + if(!fpuCheckInputs(ffs, fft)) return; CHECK_FPE(f64, ffd, ffs - fft); if(!fpuCheckOutput(ffd)) return; FD(f64) = ffd; @@ -995,14 +1033,14 @@ auto CPU::LWC1(u8 ft, cr64& rs, s16 imm) -> void { if(auto data = read(rs.u64 + imm)) FT(u32) = *data; } -auto CPU::MFC1(r64& rt, u8 fs) -> void { +auto CPU::MFC1(r64& rt, u8 ft) -> void { if(!scc.status.enable.coprocessor1) return exception.coprocessor1(); - rt.u64 = FS(s32); + rt.u64 = FT(s32); } -auto CPU::MTC1(cr64& rt, u8 fs) -> void { +auto CPU::MTC1(cr64& rt, u8 ft) -> void { if(!scc.status.enable.coprocessor1) return exception.coprocessor1(); - FS(s32) = rt.u32; + FT(s32) = rt.u32; } auto CPU::SDC1(u8 ft, cr64& rs, s16 imm) -> void { diff --git a/waterbox/ares64/ares/ares/n64/cpu/memory.cpp b/waterbox/ares64/ares/ares/n64/cpu/memory.cpp index dc0d44ec3c5..e319d26360a 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/memory.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/memory.cpp @@ -140,14 +140,28 @@ auto CPU::devirtualizeFast(u64 vaddr) -> u64 { return devirtualizeCache.pbase = 0; } +auto CPU::devirtualizeDebug(u64 vaddr) -> u64 { + return devirtualizeFast(vaddr); // this wrapper preserves the inlining of 'devirtualizeFast' +} + template inline auto CPU::busWrite(u32 address, u64 data) -> void { - bus.write(address, data, *this); + bus.write(address, data, *this, "CPU"); +} + +template +inline auto CPU::busWriteBurst(u32 address, u32 *data) -> void { + bus.writeBurst(address, data, *this); } template inline auto CPU::busRead(u32 address) -> u64 { - return bus.read(address, *this); + return bus.read(address, *this, "CPU"); +} + +template +inline auto CPU::busReadBurst(u32 address, u32 *data) -> void { + return bus.readBurst(address, data, *this); } auto CPU::fetch(u64 vaddr) -> maybe { @@ -185,6 +199,8 @@ auto CPU::fetch(u64 vaddr) -> maybe { template auto CPU::read(u64 vaddr) -> maybe { if(vaddrAlignedError(vaddr, false)) return nothing; + GDB::server.reportMemRead(vaddr, Size); + switch(segment(vaddr)) { case Context::Segment::Unused: step(1 * 2); @@ -215,10 +231,37 @@ auto CPU::read(u64 vaddr) -> maybe { unreachable; } +auto CPU::readDebug(u64 vaddr) -> u8 { + Thread dummyThread{}; + + switch(segment(vaddr)) { + case Context::Segment::Unused: return 0; + case Context::Segment::Mapped: + if(auto match = tlb.load(vaddr, true)) { + if(match.cache) return dcache.readDebug(vaddr, match.address & context.physMask); + return bus.read(match.address & context.physMask, dummyThread, "Ares Debugger"); + } + return 0; + case Context::Segment::Cached: + return dcache.readDebug(vaddr, vaddr & 0x1fff'ffff); + case Context::Segment::Cached32: + return dcache.readDebug(vaddr, vaddr & 0xffff'ffff); + case Context::Segment::Direct: + return bus.read(vaddr & 0x1fff'ffff, dummyThread, "Ares Debugger"); + case Context::Segment::Direct32: + return bus.read(vaddr & 0xffff'ffff, dummyThread, "Ares Debugger"); + } + + unreachable; +} + template auto CPU::write(u64 vaddr0, u64 data, bool alignedError) -> bool { if(alignedError && vaddrAlignedError(vaddr0, true)) return false; u64 vaddr = vaddr0 & ~((u64)Size - 1); + + GDB::server.reportMemWrite(vaddr0, Size); + switch(segment(vaddr)) { case Context::Segment::Unused: step(1 * 2); diff --git a/waterbox/ares64/ares/ares/n64/cpu/recompiler.cpp b/waterbox/ares64/ares/ares/n64/cpu/recompiler.cpp index 030a2f0957a..7c870ae0bcf 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/recompiler.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/recompiler.cpp @@ -1,12 +1,17 @@ auto CPU::Recompiler::pool(u32 address) -> Pool* { auto& pool = pools[address >> 8 & 0x1fffff]; - if(!pool) pool = (Pool*)allocator.acquire(sizeof(Pool)); + if(!pool) { + pool = (Pool*)allocator.acquire(sizeof(Pool)); + memory::jitprotect(false); + *pool = {}; + memory::jitprotect(true); + } return pool; } -auto CPU::Recompiler::block(u32 vaddr, u32 address) -> Block* { +auto CPU::Recompiler::block(u32 vaddr, u32 address, bool singleInstruction) -> Block* { if(auto block = pool(address)->blocks[address >> 2 & 0x3f]) return block; - auto block = emit(vaddr, address); + auto block = emit(vaddr, address, singleInstruction); pool(address)->blocks[address >> 2 & 0x3f] = block; memory::jitprotect(true); return block; @@ -18,12 +23,10 @@ auto CPU::Recompiler::fastFetchBlock(u32 address) -> Block* { return nullptr; } -auto CPU::Recompiler::emit(u32 vaddr, u32 address) -> Block* { +auto CPU::Recompiler::emit(u32 vaddr, u32 address, bool singleInstruction) -> Block* { if(unlikely(allocator.available() < 1_MiB)) { print("CPU allocator flush\n"); - memory::jitprotect(false); - allocator.release(bump_allocator::zero_fill); - memory::jitprotect(true); + allocator.release(); reset(); } @@ -33,7 +36,11 @@ auto CPU::Recompiler::emit(u32 vaddr, u32 address) -> Block* { Thread thread; bool hasBranched = 0; while(true) { - u32 instruction = bus.read(address, thread); + u32 instruction = bus.read(address, thread, "Ares Recompiler"); + if(callInstructionPrologue) { + mov32(reg(1), imm(instruction)); + call(&CPU::instructionPrologue); + } bool branched = emitEXECUTE(instruction); if(unlikely(instruction == 0x1000'ffff //beq 0,0, || instruction == (2 << 26 | vaddr >> 2 & 0x3ff'ffff))) { //j @@ -44,7 +51,7 @@ auto CPU::Recompiler::emit(u32 vaddr, u32 address) -> Block* { call(&CPU::instructionEpilogue); vaddr += 4; address += 4; - if(hasBranched || (address & 0xfc) == 0) break; //block boundary + if(hasBranched || (address & 0xfc) == 0 || singleInstruction) break; //block boundary hasBranched = branched; testJumpEpilog(); } diff --git a/waterbox/ares64/ares/ares/n64/cpu/serialization.cpp b/waterbox/ares64/ares/ares/n64/cpu/serialization.cpp index 48f9d03cfdd..fc6880f582a 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/serialization.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/serialization.cpp @@ -117,6 +117,7 @@ auto CPU::serialize(serializer& s) -> void { s(scc.epcError); s(scc.latch); s(scc.nmiPending); + s(scc.sysadFrozen); for(auto& r : fpu.r) s(r.u64); s(fpu.csr.roundMode); diff --git a/waterbox/ares64/ares/ares/n64/cpu/tlb.cpp b/waterbox/ares64/ares/ares/n64/cpu/tlb.cpp index 94fec4cfa93..d596179a094 100644 --- a/waterbox/ares64/ares/ares/n64/cpu/tlb.cpp +++ b/waterbox/ares64/ares/ares/n64/cpu/tlb.cpp @@ -1,39 +1,40 @@ -auto CPU::TLB::load(u64 vaddr, const Entry& entry) -> Match { +auto CPU::TLB::load(u64 vaddr, const Entry& entry, bool noExceptions) -> maybe { + if(!entry.globals && entry.addressSpaceID != self.scc.tlb.addressSpaceID) return nothing; + if((vaddr & entry.addressMaskHi) != entry.virtualAddress) return nothing; + if(vaddr >> 62 != entry.region) return nothing; bool lo = vaddr & entry.addressSelect; if(!entry.valid[lo]) { + if(noExceptions)return Match{false}; + self.addressException(vaddr); self.debugger.tlbLoadInvalid(vaddr); self.exception.tlbLoadInvalid(); - return {false}; + return Match{false}; } physicalAddress = entry.physicalAddress[lo] + (vaddr & entry.addressMaskLo); self.debugger.tlbLoad(vaddr, physicalAddress); - return {true, entry.cacheAlgorithm[lo] != 2, physicalAddress}; + return Match{true, entry.cacheAlgorithm[lo] != 2, physicalAddress}; } -auto CPU::TLB::load(u64 vaddr) -> Match { +auto CPU::TLB::load(u64 vaddr, bool noExceptions) -> Match { for(auto& entry : this->tlbCache.entry) { if(!entry.entry) continue; - if(!entry.entry->globals && entry.entry->addressSpaceID != self.scc.tlb.addressSpaceID) continue; - if((vaddr & entry.entry->addressMaskHi) != entry.entry->virtualAddress) continue; - if(vaddr >> 62 != entry.entry->region) continue; - if(auto match = load(vaddr, *entry.entry)) { + if(auto match = load(vaddr, *entry.entry, noExceptions)) { entry.frequency++; - return match; + return *match; } } for(auto& entry : this->entry) { - if(!entry.globals && entry.addressSpaceID != self.scc.tlb.addressSpaceID) continue; - if((vaddr & entry.addressMaskHi) != entry.virtualAddress) continue; - if(vaddr >> 62 != entry.region) continue; - if(auto match = load(vaddr, entry)) { + if(auto match = load(vaddr, entry, noExceptions)) { this->tlbCache.insert(entry); - return match; + return *match; } } + if(noExceptions)return {false}; + self.addressException(vaddr); self.debugger.tlbLoadMiss(vaddr); self.exception.tlbLoadMiss(); @@ -56,46 +57,41 @@ auto CPU::TLB::loadFast(u64 vaddr) -> Match { return {false, 0, 0}; } -auto CPU::TLB::store(u64 vaddr, const Entry& entry) -> Match { +auto CPU::TLB::store(u64 vaddr, const Entry& entry) -> maybe { + if(!entry.globals && entry.addressSpaceID != self.scc.tlb.addressSpaceID) return nothing; + if((vaddr & entry.addressMaskHi) != entry.virtualAddress) return nothing; + if(vaddr >> 62 != entry.region) return nothing; bool lo = vaddr & entry.addressSelect; if(!entry.valid[lo]) { self.addressException(vaddr); self.debugger.tlbStoreInvalid(vaddr); self.exception.tlbStoreInvalid(); - return {false}; + return Match{false}; } if(!entry.dirty[lo]) { self.addressException(vaddr); self.debugger.tlbModification(vaddr); self.exception.tlbModification(); - return {false}; + return Match{false}; } physicalAddress = entry.physicalAddress[lo] + (vaddr & entry.addressMaskLo); self.debugger.tlbStore(vaddr, physicalAddress); - return {true, entry.cacheAlgorithm[lo] != 2, physicalAddress}; + return Match{true, entry.cacheAlgorithm[lo] != 2, physicalAddress}; } auto CPU::TLB::store(u64 vaddr) -> Match { for(auto& entry : this->tlbCache.entry) { if(!entry.entry) continue; - if(!entry.entry->globals && entry.entry->addressSpaceID != self.scc.tlb.addressSpaceID) continue; - if((vaddr & entry.entry->addressMaskHi) != entry.entry->virtualAddress) continue; - if(vaddr >> 62 != entry.entry->region) continue; - if(auto match = store(vaddr, *entry.entry)) { entry.frequency++; - return match; + return *match; } } for(auto& entry : this->entry) { - if(!entry.globals && entry.addressSpaceID != self.scc.tlb.addressSpaceID) continue; - if((vaddr & entry.addressMaskHi) != entry.virtualAddress) continue; - if(vaddr >> 62 != entry.region) continue; - if(auto match = store(vaddr, entry)) { this->tlbCache.insert(entry); - return match; + return *match; } } diff --git a/waterbox/ares64/ares/ares/n64/dd/controller.cpp b/waterbox/ares64/ares/ares/n64/dd/controller.cpp index aaa6384f4d8..8c9810cd9c6 100644 --- a/waterbox/ares64/ares/ares/n64/dd/controller.cpp +++ b/waterbox/ares64/ares/ares/n64/dd/controller.cpp @@ -144,22 +144,22 @@ auto DD::command(n16 command) -> void { } } break; case Command::SetRTCYearMonth: { - rtc.write(0, io.data); + rtc.ram.write(0, io.data); } break; case Command::SetRTCDayHour: { - rtc.write(2, io.data); + rtc.ram.write(2, io.data); } break; case Command::SetRTCMinuteSecond: { - rtc.write(4, io.data); + rtc.ram.write(4, io.data); } break; case Command::GetRTCYearMonth: { - io.data = rtc.read(0); + io.data = rtc.ram.read(0); } break; case Command::GetRTCDayHour: { - io.data = rtc.read(2); + io.data = rtc.ram.read(2); } break; case Command::GetRTCMinuteSecond: { - io.data = rtc.read(4); + io.data = rtc.ram.read(4); } break; case Command::SetLEDBlinkRate: { if (io.data.bit(24,31) != 0) ctl.ledOnTime = io.data.bit(24,31); @@ -187,7 +187,11 @@ auto DD::command(n16 command) -> void { auto DD::mechaResponse() -> void { if(state.seek) { state.seek = 0; - motorActive(); + if (io.status.diskPresent) { + motorActive(); + } else { + motorStop(); + } } io.status.busyState = 0; raise(IRQ::MECHA); diff --git a/waterbox/ares64/ares/ares/n64/dd/dd.cpp b/waterbox/ares64/ares/ares/n64/dd/dd.cpp index 316e53903e2..76336b86469 100644 --- a/waterbox/ares64/ares/ares/n64/dd/dd.cpp +++ b/waterbox/ares64/ares/ares/n64/dd/dd.cpp @@ -24,13 +24,14 @@ auto DD::load(Node::Object parent) -> void { c2s.allocate(0x400); ds.allocate(0x100); ms.allocate(0x40); - rtc.allocate(0x10); // TODO: Detect correct CIC from ipl rom if(auto fp = system.pak->read("64dd.ipl.rom")) { iplrom.load(fp); } + rtc.load(); + debugger.load(parent->append("Nintendo 64DD")); } @@ -79,9 +80,9 @@ auto DD::connect() -> void { if(auto fp = pak->read("program.disk")) { disk.allocate(fp->size()); disk.load(fp); + io.status.diskChanged = 1; + io.status.diskPresent = 1; } - - rtcLoad(); } auto DD::disconnect() -> void { @@ -89,7 +90,34 @@ auto DD::disconnect() -> void { save(); pak.reset(); + disk.reset(); information = {}; + + if(iplrom) { + string id; + id.append((char)iplrom.read(0x3b)); + id.append((char)iplrom.read(0x3c)); + id.append((char)iplrom.read(0x3d)); + id.append((char)iplrom.read(0x3e)); + if(id.match("NDDJ")) dd.information.cic = "CIC-NUS-8303"; + if(id.match("NDDE")) dd.information.cic = "CIC-NUS-DDUS"; + if(id.match("NDXJ")) dd.information.cic = "CIC-NUS-8401"; + } + + io.status.diskPresent = 0; + + //Deal with cases when the disk is removed while in use + if(io.status.busyState) { + //MECHA + io.status.mechaError = 1; + } + + if(io.bm.start) { + //BM + io.bm.start = 0; + io.bm.error = 1; + } + motorStop(); } auto DD::save() -> void { @@ -100,7 +128,7 @@ auto DD::save() -> void { } #endif - rtcSave(); + rtc.save(); } auto DD::power(bool reset) -> void { @@ -114,6 +142,9 @@ auto DD::power(bool reset) -> void { state = {}; io.status.resetState = 1; + io.status.diskChanged = 1; + if(disk) io.status.diskPresent = 1; + io.id = 3; if(dd.information.cic.match("CIC-NUS-8401")) io.id = 4; diff --git a/waterbox/ares64/ares/ares/n64/dd/dd.hpp b/waterbox/ares64/ares/ares/n64/dd/dd.hpp index d6b9f2a7e81..ff94407e743 100644 --- a/waterbox/ares64/ares/ares/n64/dd/dd.hpp +++ b/waterbox/ares64/ares/ares/n64/dd/dd.hpp @@ -11,7 +11,6 @@ struct DD : Memory::PI
{ Memory::Writable c2s; Memory::Writable ds; Memory::Writable ms; - Memory::Writable rtc; Memory::Writable disk; Memory::Writable error; @@ -27,6 +26,21 @@ struct DD : Memory::PI
{ } tracer; } debugger; + struct RTC { + Memory::Writable ram; + + //rtc.cpp + auto load() -> void; + auto reset() -> void; + auto save() -> void; + auto serialize(serializer& s) -> void; + auto tick(u32 offset) -> void; + auto tickClock() -> void; + auto tickSecond() -> void; + auto valid() -> bool; + auto daysInMonth(u8 month, u8 year) -> u8; + } rtc; + auto title() const -> string { return information.title; } auto cic() const -> string { return information.cic; } @@ -59,13 +73,6 @@ struct DD : Memory::PI
{ auto motorStop() -> void; auto motorChange() -> void; - //rtc.cpp - auto rtcLoad() -> void; - auto rtcSave() -> void; - auto rtcTick(u32 offset) -> void; - auto rtcTickClock() -> void; - auto rtcTickSecond() -> void; - //io.cpp auto readHalf(u32 address) -> u16; auto writeHalf(u32 address, u16 data) -> void; @@ -125,6 +132,7 @@ struct DD : Memory::PI
{ n1 writeProtect; n1 mechaError; n1 diskChanged; + n1 diskPresent; } status; n16 currentTrack; diff --git a/waterbox/ares64/ares/ares/n64/dd/io.cpp b/waterbox/ares64/ares/ares/n64/dd/io.cpp index a85269edd91..6d8423f1814 100644 --- a/waterbox/ares64/ares/ares/n64/dd/io.cpp +++ b/waterbox/ares64/ares/ares/n64/dd/io.cpp @@ -20,7 +20,7 @@ auto DD::readHalf(u32 address) -> u16 { data.bit(4) = io.status.spindleMotorStopped; data.bit(6) = io.status.resetState; data.bit(7) = io.status.busyState; - data.bit(8) = (bool)disk; //disk present + data.bit(8) = io.status.diskPresent; data.bit(9) = irq.mecha.line; data.bit(10) = irq.bm.line; data.bit(11) = io.bm.error; @@ -57,7 +57,7 @@ auto DD::readHalf(u32 address) -> u16 { data.bit(0,7) = io.error.sector; data.bit(8) = io.error.selfStop; data.bit(9) = io.error.clockUnlock; - data.bit(10) = ~(bool)disk; //no disk + data.bit(10) = ~io.status.diskPresent; //no disk data.bit(11) = io.error.offTrack; data.bit(12) = io.error.overrun; data.bit(13) = io.error.spindle; @@ -123,7 +123,6 @@ auto DD::readHalf(u32 address) -> u16 { if(address == 36) { } - debugger.io(Read, address, data); return data; } @@ -195,7 +194,7 @@ auto DD::writeHalf(u32 address, u16 data_) -> void { //ASIC_HARD_RESET if(address == 16) { - if((data >> 16) == 0xAAAA) { + if(data == 0xAAAA) { power(true); } } @@ -242,18 +241,20 @@ auto DD::writeHalf(u32 address, u16 data_) -> void { //ASIC_TEST_PIN_SEL if(address == 36) { } - - debugger.io(Write, address, data); } auto DD::readWord(u32 address) -> u32 { + address = (address & 0x7f); n32 data; data.bit(16,31) = readHalf(address + 0); data.bit( 0,15) = readHalf(address + 2); + debugger.io(Read, address >> 2, data); return (u32)data; } auto DD::writeWord(u32 address, u32 data) -> void { + address = (address & 0x7f); writeHalf(address + 0, data >> 16); writeHalf(address + 2, data & 0xffff); + debugger.io(Write, address >> 2, data); } diff --git a/waterbox/ares64/ares/ares/n64/dd/rtc.cpp b/waterbox/ares64/ares/ares/n64/dd/rtc.cpp index 961a5a85ea4..4fa2fea0a8a 100644 --- a/waterbox/ares64/ares/ares/n64/dd/rtc.cpp +++ b/waterbox/ares64/ares/ares/n64/dd/rtc.cpp @@ -1,75 +1,119 @@ -auto DD::rtcLoad() -> void { +auto DD::RTC::load() -> void { + ram.allocate(0x10); #if false if(auto fp = system.pak->read("time.rtc")) { - rtc.load(fp); + ram.load(fp); } #endif + //byte 0 to 7 = raw rtc time (last updated, only 6 bytes are used) n64 check = 0; - for(auto n : range(8)) check.byte(n) = rtc.read(n); + for(auto n : range(8)) check.byte(n) = ram.read(n); if(!~check) return; //new save file + //check for invalid time info, if invalid, set time info to something invalid and ignore the rest + if (!valid()) { + for(auto n : range(8)) ram.write(n, 0xff); + return; + } + + //byte 8 to 15 = timestamp of when the last save was made n64 timestamp = 0; - for(auto n : range(8)) timestamp.byte(n) = rtc.read(8 + n); + for(auto n : range(8)) timestamp.byte(n) = ram.read(8 + n); if(!~timestamp) return; //new save file + //update based on the amount of time that has passed since the last save timestamp = platform->time() - timestamp; - while(timestamp--) rtcTickSecond(); + while(timestamp--) tickSecond(); } -auto DD::rtcSave() -> void { - n64 timestamp = platform->time(); - for(auto n : range(8)) rtc.write(8 + n, timestamp.byte(n)); +auto DD::RTC::reset() -> void { + ram.reset(); +} +auto DD::RTC::save() -> void { #if false + n64 timestamp = platform->time(); + for(auto n : range(8)) ram.write(8 + n, timestamp.byte(n)); + if(auto fp = system.pak->write("time.rtc")) { - rtc.save(fp); + ram.save(fp); } #endif } -auto DD::rtcTick(u32 offset) -> void { - u8 n = rtc.read(offset); +auto DD::RTC::serialize(serializer& s) -> void { + s(ram); +} + +auto DD::RTC::tick(u32 offset) -> void { + u8 n = ram.read(offset); if((++n & 0xf) > 9) n = (n & 0xf0) + 0x10; if((n & 0xf0) > 0x90) n = 0; - rtc.write(offset, n); + ram.write(offset, n); } -auto DD::rtcTickClock() -> void { - rtcTickSecond(); +auto DD::RTC::tickClock() -> void { + tickSecond(); queue.remove(Queue::DD_Clock_Tick); queue.insert(Queue::DD_Clock_Tick, 187'500'000); } -auto DD::rtcTickSecond() -> void { +auto DD::RTC::tickSecond() -> void { + if (!valid()) return; + //second - rtcTick(5); - if(rtc.read(5) < 0x60) return; - rtc.write(5, 0); + tick(5); + if(ram.read(5) < 0x60) return; + ram.write(5, 0); //minute - rtcTick(4); - if(rtc.read(4) < 0x60) return; - rtc.write(4, 0); + tick(4); + if(ram.read(4) < 0x60) return; + ram.write(4, 0); //hour - rtcTick(3); - if(rtc.read(3) < 0x24) return; - rtc.write(3, 0); + tick(3); + if(ram.read(3) < 0x24) return; + ram.write(3, 0); //day - u32 daysInMonth[12] = {0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31}; - if(rtc.read(0) && !(BCD::decode(rtc.read(0)) % 4)) daysInMonth[1]++; - - rtcTick(2); - if(rtc.read(2) <= daysInMonth[BCD::decode(rtc.read(1))-1]) return; - rtc.write(2, 1); + tick(2); + if(ram.read(2) <= BCD::encode(chrono::daysInMonth(BCD::decode(ram.read(1)), BCD::decode(ram.read(0))))) return; + ram.write(2, 1); //month - rtcTick(1); - if(rtc.read(1) < 0x12) return; - rtc.write(1, 1); + tick(1); + if(ram.read(1) <= 0x12) return; + ram.write(1, 1); + + //year + tick(0); +} + +auto DD::RTC::valid() -> bool { + //check validity of ram rtc data (if it's BCD valid or not) + for(auto n : range(6)) { + if((ram.read(n) & 0x0f) >= 0x0a) return false; + } + //check for valid values of each byte //year - rtcTick(0); + if(ram.read(0) >= 0xa0) return false; + //second + if(ram.read(5) >= 0x60) return false; + //minute + if(ram.read(4) >= 0x60) return false; + //hour + if(ram.read(3) >= 0x24) return false; + //month + if(ram.read(1) > 0x12) return false; + if(ram.read(1) < 1) return false; + //day + if(ram.read(2) < 1) return false; + if(ram.read(2) > BCD::encode(chrono::daysInMonth(BCD::decode(ram.read(1)), BCD::decode(ram.read(0))))) return false; + + //everything is valid + return true; } + diff --git a/waterbox/ares64/ares/ares/n64/dd/serialization.cpp b/waterbox/ares64/ares/ares/n64/dd/serialization.cpp index f9047a15f6b..0d5c8d41eda 100644 --- a/waterbox/ares64/ares/ares/n64/dd/serialization.cpp +++ b/waterbox/ares64/ares/ares/n64/dd/serialization.cpp @@ -1,4 +1,6 @@ auto DD::serialize(serializer& s) -> void { + s(rtc); + s(irq.bm.line); s(irq.bm.mask); s(irq.mecha.line); diff --git a/waterbox/ares64/ares/ares/n64/memory/bus.hpp b/waterbox/ares64/ares/ares/n64/memory/bus.hpp index bff5a4e093d..61dd10a29ff 100644 --- a/waterbox/ares64/ares/ares/n64/memory/bus.hpp +++ b/waterbox/ares64/ares/ares/n64/memory/bus.hpp @@ -1,13 +1,13 @@ template -inline auto Bus::read(u32 address, Thread& thread) -> u64 { - static constexpr u64 unmapped = 0; - address &= 0x1fff'ffff - (Size - 1); +inline auto Bus::read(u32 address, Thread& thread, const char *peripheral) -> u64 { + static_assert(Size == Byte || Size == Half || Size == Word || Size == Dual); - if(address <= 0x007f'ffff) return rdram.ram.read(address); - if(address <= 0x03ef'ffff) return unmapped; + if(address <= 0x03ef'ffff) return rdram.ram.read(address, peripheral); if(address <= 0x03ff'ffff) return rdram.read(address, thread); + if(Size == Dual) return freezeDualRead(address), 0; if(address <= 0x0407'ffff) return rsp.read(address, thread); - if(address <= 0x040f'ffff) return rsp.status.read(address, thread); + if(address <= 0x040b'ffff) return rsp.status.read(address, thread); + if(address <= 0x040f'ffff) return freezeUnmapped(address), 0; if(address <= 0x041f'ffff) return rdp.read(address, thread); if(address <= 0x042f'ffff) return rdp.io.read(address, thread); if(address <= 0x043f'ffff) return mi.read(address, thread); @@ -16,26 +16,49 @@ inline auto Bus::read(u32 address, Thread& thread) -> u64 { if(address <= 0x046f'ffff) return pi.read(address, thread); if(address <= 0x047f'ffff) return ri.read(address, thread); if(address <= 0x048f'ffff) return si.read(address, thread); - if(address <= 0x04ff'ffff) return unmapped; + if(address <= 0x04ff'ffff) return freezeUnmapped(address), 0; if(address <= 0x1fbf'ffff) return pi.read(address, thread); if(address <= 0x1fcf'ffff) return si.read(address, thread); if(address <= 0x7fff'ffff) return pi.read(address, thread); - return unmapped; + return freezeUnmapped(address), 0; } template -inline auto Bus::write(u32 address, u64 data, Thread& thread) -> void { - address &= 0x1fff'ffff - (Size - 1); +inline auto Bus::readBurst(u32 address, u32 *data, Thread& thread) -> void { + static_assert(Size == DCache || Size == ICache); + + if(address <= 0x03ef'ffff) return rdram.ram.readBurst(address, data, "CPU"); + if(address <= 0x03ff'ffff) { + // FIXME: not hardware validated, no idea of the behavior + data[0] = rdram.readWord(address | 0x0, thread); + data[1] = 0; + data[2] = 0; + data[3] = 0; + if constexpr(Size == ICache) { + data[4] = 0; + data[5] = 0; + data[6] = 0; + data[7] = 0; + } + return; + } + + return freezeUncached(address); +} + +template +inline auto Bus::write(u32 address, u64 data, Thread& thread, const char *peripheral) -> void { + static_assert(Size == Byte || Size == Half || Size == Word || Size == Dual); if constexpr(Accuracy::CPU::Recompiler) { cpu.recompiler.invalidate(address + 0); if constexpr(Size == Dual) cpu.recompiler.invalidate(address + 4); } - if(address <= 0x007f'ffff) return rdram.ram.write(address, data); - if(address <= 0x03ef'ffff) return; + if(address <= 0x03ef'ffff) return rdram.ram.write(address, data, peripheral); if(address <= 0x03ff'ffff) return rdram.write(address, data, thread); if(address <= 0x0407'ffff) return rsp.write(address, data, thread); - if(address <= 0x040f'ffff) return rsp.status.write(address, data, thread); + if(address <= 0x040b'ffff) return rsp.status.write(address, data, thread); + if(address <= 0x040f'ffff) return freezeUnmapped(address); if(address <= 0x041f'ffff) return rdp.write(address, data, thread); if(address <= 0x042f'ffff) return rdp.io.write(address, data, thread); if(address <= 0x043f'ffff) return mi.write(address, data, thread); @@ -44,9 +67,41 @@ inline auto Bus::write(u32 address, u64 data, Thread& thread) -> void { if(address <= 0x046f'ffff) return pi.write(address, data, thread); if(address <= 0x047f'ffff) return ri.write(address, data, thread); if(address <= 0x048f'ffff) return si.write(address, data, thread); - if(address <= 0x04ff'ffff) return; + if(address <= 0x04ff'ffff) return freezeUnmapped(address); if(address <= 0x1fbf'ffff) return pi.write(address, data, thread); if(address <= 0x1fcf'ffff) return si.write(address, data, thread); if(address <= 0x7fff'ffff) return pi.write(address, data, thread); - return; + return freezeUnmapped(address); +} + +template +inline auto Bus::writeBurst(u32 address, u32 *data, Thread& thread) -> void { + static_assert(Size == DCache || Size == ICache); + if constexpr(Accuracy::CPU::Recompiler) { + cpu.recompiler.invalidateRange(address, Size == DCache ? 16 : 32); + } + + if(address <= 0x03ef'ffff) return rdram.ram.writeBurst(address, data, "CPU"); + if(address <= 0x03ff'ffff) { + // FIXME: not hardware validated, but a good guess + rdram.writeWord(address | 0x0, data[0], thread); + return; + } + + return freezeUncached(address); +} + +inline auto Bus::freezeUnmapped(u32 address) -> void { + debug(unusual, "[Bus::freezeUnmapped] CPU frozen because of access to RCP unmapped area: 0x", hex(address, 8L)); + cpu.scc.sysadFrozen = true; +} + +inline auto Bus::freezeUncached(u32 address) -> void { + debug(unusual, "[Bus::freezeUncached] CPU frozen because of cached access to non-RDRAM area: 0x", hex(address, 8L)); + cpu.scc.sysadFrozen = true; +} + +inline auto Bus::freezeDualRead(u32 address) -> void { + debug(unusual, "[Bus::freezeDualRead] CPU frozen because of 64-bit read from non-RDRAM area: 0x ", hex(address, 8L)); + cpu.scc.sysadFrozen = true; } diff --git a/waterbox/ares64/ares/ares/n64/memory/memory.hpp b/waterbox/ares64/ares/ares/n64/memory/memory.hpp index f1ce23dcbaf..7206e3d0674 100644 --- a/waterbox/ares64/ares/ares/n64/memory/memory.hpp +++ b/waterbox/ares64/ares/ares/n64/memory/memory.hpp @@ -31,8 +31,15 @@ namespace Memory { struct Bus { //bus.hpp - template auto read(u32 address, Thread& thread) -> u64; - template auto write(u32 address, u64 data, Thread& thread) -> void; + template auto read(u32 address, Thread& thread, const char *peripheral) -> u64; + template auto write(u32 address, u64 data, Thread& thread, const char *peripheral) -> void; + + template auto readBurst(u32 address, u32* data, Thread& thread) -> void; + template auto writeBurst(u32 address, u32* data, Thread& thread) -> void; + + auto freezeUnmapped(u32 address) -> void; + auto freezeUncached(u32 address) -> void; + auto freezeDualRead(u32 address) -> void; }; extern Bus bus; diff --git a/waterbox/ares64/ares/ares/n64/mi/io.cpp b/waterbox/ares64/ares/ares/n64/mi/io.cpp index 9806d558d21..5555b0e2ea8 100644 --- a/waterbox/ares64/ares/ares/n64/mi/io.cpp +++ b/waterbox/ares64/ares/ares/n64/mi/io.cpp @@ -1,5 +1,5 @@ auto MI::readWord(u32 address, Thread& thread) -> u32 { - address = (address & 0xfffff) >> 2; + address = (address & 0xf) >> 2; n32 data; if(address == 0) { @@ -43,7 +43,7 @@ auto MI::readWord(u32 address, Thread& thread) -> u32 { } auto MI::writeWord(u32 address, u32 data_, Thread& thread) -> void { - address = (address & 0xfffff) >> 2; + address = (address & 0xf) >> 2; n32 data = data_; if(address == 0) { diff --git a/waterbox/ares64/ares/ares/n64/n64.hpp b/waterbox/ares64/ares/ares/n64/n64.hpp index 7d579c69ef3..d7d151a697d 100644 --- a/waterbox/ares64/ares/ares/n64/n64.hpp +++ b/waterbox/ares64/ares/ares/n64/n64.hpp @@ -23,13 +23,18 @@ using v128 = __m128i; #include #endif +// Include the GB core, we can use its cartridge emulation for Transfer Pak +#if defined(CORE_GB) +#include +#endif + namespace ares::Nintendo64 { auto enumerate() -> vector; auto load(Node::System& node, string name) -> bool; auto option(string name, string value) -> bool; enum : u32 { Read, Write }; - enum : u32 { Byte = 1, Half = 2, Word = 4, Dual = 8 }; + enum : u32 { Byte = 1, Half = 2, Word = 4, Dual = 8, DCache = 16, ICache = 32 }; struct Region { static inline auto NTSC() -> bool; @@ -91,8 +96,8 @@ namespace ares::Nintendo64 { #include #include #include - #include #include + #include #include #include #include diff --git a/waterbox/ares64/ares/ares/n64/pi/bus.hpp b/waterbox/ares64/ares/ares/n64/pi/bus.hpp index 4614edaedcd..5473b833fb4 100644 --- a/waterbox/ares64/ares/ares/n64/pi/bus.hpp +++ b/waterbox/ares64/ares/ares/n64/pi/bus.hpp @@ -2,11 +2,13 @@ inline auto PI::readWord(u32 address, Thread& thread) -> u32 { if(address <= 0x046f'ffff) return ioRead(address); if (unlikely(io.ioBusy)) { + debug(unusual, "[PI::readWord] PI read to 0x", hex(address, 8L), " will not behave as expected because PI writing is in progress"); thread.step(writeForceFinish() * 2); return io.busLatch; } thread.step(250 * 2); - return busRead(address); + io.busLatch = busRead(address); + return io.busLatch; } template @@ -42,13 +44,13 @@ inline auto PI::busRead(u32 address) -> u32 { if(cartridge.flash) return cartridge.flash.read(address); return unmapped; } - if(address <= 0x13fe'ffff) { - if(cartridge.rom ) return cartridge.rom.read(address); - return unmapped; + if(cartridge.isviewer.enabled() && address >= 0x13f0'0000 && address <= 0x13ff'ffff) { + return cartridge.isviewer.read(address); + } + if(address <= 0x1000'0000 + cartridge.rom.size - 1) { + return cartridge.rom.read(address); } - if(address <= 0x13ff'ffff) return cartridge.isviewer.read(address); - if(address <= 0x7fff'ffff) return unmapped; - return unmapped; //accesses here actually lock out the RCP + return unmapped; } inline auto PI::writeWord(u32 address, u32 data, Thread& thread) -> void { @@ -92,13 +94,16 @@ inline auto PI::busWrite(u32 address, u32 data) -> void { if(cartridge.flash) return cartridge.flash.write(address, data); return; } - if(address <= 0x13fe'ffff) { - if(cartridge.rom ) return cartridge.rom.write(address, data); - return; + if(address >= 0x13f0'0000 && address <= 0x13ff'ffff) { + if(cartridge.isviewer.enabled()) { + writeForceFinish(); //Debugging channel for homebrew, be gentle + return cartridge.isviewer.write(address, data); + } else { + debug(unhandled, "[PI::busWrite] attempt to write to ISViewer: ROM is too big so ISViewer is disabled"); + } } - if(address <= 0x13ff'ffff) { - writeForceFinish(); //Debugging channel for homebrew, be gentle - return cartridge.isviewer.write(address, data); + if(address <= 0x1000'0000 + cartridge.rom.size - 1) { + return cartridge.rom.write(address, data); } if(address <= 0x7fff'ffff) return; } diff --git a/waterbox/ares64/ares/ares/n64/pi/dma.cpp b/waterbox/ares64/ares/ares/n64/pi/dma.cpp index 4f3a5c90249..5640ac83478 100644 --- a/waterbox/ares64/ares/ares/n64/pi/dma.cpp +++ b/waterbox/ares64/ares/ares/n64/pi/dma.cpp @@ -1,49 +1,52 @@ auto PI::dmaRead() -> void { io.readLength = (io.readLength | 1) + 1; + + u32 lastCacheline = 0xffff'ffff; for(u32 address = 0; address < io.readLength; address += 2) { - u16 data = rdram.ram.read(io.dramAddress + address); + u16 data = rdram.ram.read(io.dramAddress + address, "PI DMA"); busWrite(io.pbusAddress + address, data); } } auto PI::dmaWrite() -> void { u8 mem[128]; - bool first_block = true; i32 length = io.writeLength+1; + i32 maxBlockSize = 128; + bool firstBlock = true; - io.writeLength = 0x7F; - if (length <= 8) io.writeLength -= io.dramAddress&7; + if constexpr(Accuracy::CPU::Recompiler) { + cpu.recompiler.invalidateRange(io.dramAddress, (length + 1) & ~1); + } while (length > 0) { - u32 dest = io.dramAddress & 0x7FFFFE; - i32 misalign = dest & 7; - i32 block_len = 128 - misalign; - i32 cur_len = min(length, block_len); - - length -= cur_len; - if (length.bit(0)) length += 1; + i32 misalign = io.dramAddress & 7; + i32 distEndOfRow = 0x800-(io.dramAddress&0x7ff); + i32 blockLen = min(maxBlockSize-misalign, distEndOfRow); + i32 curLen = min(length, blockLen); - i32 rom_len = (cur_len + 1) & ~1; - for (u32 i = 0; i < rom_len; i += 2) { + for (int i=0; i(io.pbusAddress); - mem[i + 0] = data >> 8; - mem[i + 1] = data & 0xFF; + mem[i+0] = data >> 8; + mem[i+1] = data >> 0; io.pbusAddress += 2; + length -= 2; } - if (first_block) { - if (cur_len == block_len-1) cur_len++; - cur_len = max(cur_len-misalign, 0); + if (firstBlock && curLen < 127-misalign) { + for (i32 i = 0; i < curLen-misalign; i++) { + rdram.ram.write(io.dramAddress++, mem[i], "PI DMA"); + } + } else { + for (i32 i = 0; i < curLen-misalign; i+=2) { + rdram.ram.write(io.dramAddress++, mem[i+0], "PI DMA"); + rdram.ram.write(io.dramAddress++, mem[i+1], "PI DMA"); + } } - if constexpr(Accuracy::CPU::Recompiler) { - cpu.recompiler.invalidateRange(io.dramAddress, cur_len); - } - for (u32 i = 0; i < cur_len; i++) - rdram.ram.write(io.dramAddress++, mem[i]); io.dramAddress = (io.dramAddress + 7) & ~7; - - first_block = false; + io.writeLength = curLen <= 8 ? 127-misalign : 127; + firstBlock = false; + maxBlockSize = distEndOfRow < 8 ? 128-misalign : 128; } } diff --git a/waterbox/ares64/ares/ares/n64/pi/io.cpp b/waterbox/ares64/ares/ares/n64/pi/io.cpp index c131bf3a694..0884439b67d 100644 --- a/waterbox/ares64/ares/ares/n64/pi/io.cpp +++ b/waterbox/ares64/ares/ares/n64/pi/io.cpp @@ -1,5 +1,5 @@ auto PI::ioRead(u32 address) -> u32 { - address = (address & 0xfffff) >> 2; + address = (address & 0x3f) >> 2; n32 data; if(address == 0) { @@ -70,12 +70,20 @@ auto PI::ioRead(u32 address) -> u32 { data.bit(0,7) = bsd2.releaseDuration; } + if(address == 13) { + data.bit(0,31) = io.busLatch; + } + + if(address == 14) { + data.bit(0,31) = io.busLatch; + } + debugger.io(Read, address, data); return data; } auto PI::ioWrite(u32 address, u32 data_) -> void { - address = (address & 0xfffff) >> 2; + address = (address & 0x3f) >> 2; n32 data = data_; //only PI_STATUS can be written while PI is busy @@ -98,6 +106,7 @@ auto PI::ioWrite(u32 address, u32 data_) -> void { //PI_READ_LENGTH io.readLength = n24(data); io.dmaBusy = 1; + io.originPc = cpu.ipu.pc; queue.insert(Queue::PI_DMA_Read, dmaDuration(true)); dmaRead(); } @@ -106,6 +115,7 @@ auto PI::ioWrite(u32 address, u32 data_) -> void { //PI_WRITE_LENGTH io.writeLength = n24(data); io.dmaBusy = 1; + io.originPc = cpu.ipu.pc; queue.insert(Queue::PI_DMA_Write, dmaDuration(false)); dmaWrite(); } diff --git a/waterbox/ares64/ares/ares/n64/pi/pi.hpp b/waterbox/ares64/ares/ares/n64/pi/pi.hpp index 240f177dd6c..e824d5d7391 100644 --- a/waterbox/ares64/ares/ares/n64/pi/pi.hpp +++ b/waterbox/ares64/ares/ares/n64/pi/pi.hpp @@ -51,6 +51,7 @@ struct PI : Memory::RCP { n32 readLength; n32 writeLength; n32 busLatch; + u64 originPc; } io; struct BSD { diff --git a/waterbox/ares64/ares/ares/n64/pif/io.cpp b/waterbox/ares64/ares/ares/n64/pif/io.cpp index 4d1ac5478f1..0b472a199dd 100644 --- a/waterbox/ares64/ares/ares/n64/pif/io.cpp +++ b/waterbox/ares64/ares/ares/n64/pif/io.cpp @@ -23,21 +23,23 @@ auto PIF::readWord(u32 address) -> u32 { auto PIF::writeWord(u32 address, u32 data) -> void { writeInt(address, data); - return intA(Write, Size4); + intA(Write, Size4); + mainHLE(); } auto PIF::dmaRead(u32 address, u32 ramAddress) -> void { intA(Read, Size64); for(u32 offset = 0; offset < 64; offset += 4) { u32 data = readInt(address + offset); - rdram.ram.write(ramAddress + offset, data); + rdram.ram.write(ramAddress + offset, data, "SI DMA"); } } auto PIF::dmaWrite(u32 address, u32 ramAddress) -> void { for(u32 offset = 0; offset < 64; offset += 4) { - u32 data = rdram.ram.read(ramAddress + offset); + u32 data = rdram.ram.read(ramAddress + offset, "SI DMA"); writeInt(address + offset, data); } intA(Write, Size64); + mainHLE(); } diff --git a/waterbox/ares64/ares/ares/n64/rdp/io.cpp b/waterbox/ares64/ares/ares/n64/rdp/io.cpp index 992554bbc0c..ead06fcde6c 100644 --- a/waterbox/ares64/ares/ares/n64/rdp/io.cpp +++ b/waterbox/ares64/ares/ares/n64/rdp/io.cpp @@ -1,5 +1,5 @@ auto RDP::readWord(u32 address, Thread& thread) -> u32 { - address = (address & 0xfffff) >> 2; + address = (address & 0x1f) >> 2; n32 data; if(address == 0) { @@ -57,7 +57,7 @@ auto RDP::readWord(u32 address, Thread& thread) -> u32 { } auto RDP::writeWord(u32 address, u32 data_, Thread& thread) -> void { - address = (address & 0xfffff) >> 2; + address = (address & 0x1f) >> 2; n32 data = data_; if(address == 0) { diff --git a/waterbox/ares64/ares/ares/n64/rdp/render.cpp b/waterbox/ares64/ares/ares/n64/rdp/render.cpp index 0495eb23f05..9ad19ea42f4 100644 --- a/waterbox/ares64/ares/ares/n64/rdp/render.cpp +++ b/waterbox/ares64/ares/ares/n64/rdp/render.cpp @@ -57,7 +57,7 @@ auto RDP::render() -> void { command.current = command.end; return; - auto& memory = !command.source ? rdram.ram : rsp.dmem; + auto& memory = !command.source ? (Memory::Writable&)rdram.ram : (Memory::Writable&)rsp.dmem; auto fetch = [&]() -> u64 { u64 op = memory.readUnaligned(command.current); diff --git a/waterbox/ares64/ares/ares/n64/rdram/debugger.cpp b/waterbox/ares64/ares/ares/n64/rdram/debugger.cpp index 3829628d02e..0aab188d878 100644 --- a/waterbox/ares64/ares/ares/n64/rdram/debugger.cpp +++ b/waterbox/ares64/ares/ares/n64/rdram/debugger.cpp @@ -1,11 +1,32 @@ auto RDRAM::Debugger::load(Node::Object parent) -> void { memory.ram = parent->append("RDRAM"); - memory.ram->setSize(4_MiB + 4_MiB); + if(!system.expansionPak) { + memory.ram->setSize(4_MiB); + } else { + memory.ram->setSize(4_MiB + 4_MiB); + } + memory.ram->setRead([&](u32 address) -> u8 { - return rdram.ram.read(address); + return rdram.ram.read(address, "Ares Debugger"); }); memory.ram->setWrite([&](u32 address, u8 data) -> void { - return rdram.ram.write(address, data); + return rdram.ram.write(address, data, "Ares Debugger"); + }); + + memory.dcache = parent->append("DCache"); + memory.dcache->setSize(4_MiB + 4_MiB); + memory.dcache->setRead([&](u32 address) -> u8 { + u32 vaddr = address | 0x8000'0000; + return cpu.dcache.readDebug(vaddr, address); + }); + memory.dcache->setWrite([&](u32 address, u8 data) -> void { + u32 vaddr = address | 0x8000'0000; + auto& line = cpu.dcache.line(vaddr); + if(line.hit(address)) { + line.write(address, data); + } else { + rdram.ram.write(address, data, "Ares Debugger"); + } }); tracer.io = parent->append("I/O", "RDRAM"); @@ -38,3 +59,51 @@ auto RDRAM::Debugger::io(bool mode, u32 chipID, u32 address, u32 data) -> void { tracer.io->notify(message); } } + +auto RDRAM::Debugger::cacheErrorContext(string peripheral) -> string { + if(peripheral == "CPU") { + return { "\tCurrent CPU PC: 0x", hex(cpu.ipu.pc, 16L), "\n" }; + } + if(peripheral == "RSP DMA") { + if(rsp.dma.current.originCpu) { + return { "\tRSP DMA started at CPU PC: 0x", hex(rsp.dma.current.originPc, 16L), "\n" }; + } else { + return { "\tRSP DMA started at RSP PC: 0x", hex(rsp.dma.current.originPc, 3L), "\n" }; + } + } + if(peripheral == "PI DMA") { + return { "\tPI DMA started at CPU PC: 0x", hex(pi.io.originPc, 16L), "\n" }; + } + if(peripheral == "AI DMA") { + return { "\tAI DMA started at CPU PC: 0x", hex(ai.io.dmaOriginPc[0], 16L), "\n" }; + } + return ""; +} + +auto RDRAM::Debugger::readWord(u32 address, int size, const char *peripheral) -> void { + if (system.homebrewMode && (address & ~15) != lastReadCacheline) { + lastReadCacheline = address & ~15; + auto& line = cpu.dcache.line(address); + u16 dirtyMask = ((1 << size) - 1) << (address & 0xF); + if (line.hit(address) && (line.dirty & dirtyMask)) { + string msg = { peripheral, " reading from RDRAM address 0x", hex(address), " which is modified in the cache (missing cache writeback?)\n"}; + msg.append(string{ "\tCacheline was loaded at CPU PC: 0x", hex(line.fillPc, 16L), "\n" }); + msg.append(string{ "\tCacheline was last written at CPU PC: 0x", hex(line.dirtyPc, 16L), "\n" }); + msg.append(cacheErrorContext(peripheral)); + debug(unusual, msg); + } + } +} + +auto RDRAM::Debugger::writeWord(u32 address, int size, u64 value, const char *peripheral) -> void { + if (system.homebrewMode && (address & ~15) != lastWrittenCacheline) { + lastWrittenCacheline = address & ~15; + auto& line = cpu.dcache.line(address); + if (line.hit(address)) { + string msg = { peripheral, " writing to RDRAM address 0x", hex(address), " which is cached (missing cache invalidation?)\n"}; + msg.append(string{ "\tCacheline was loaded at CPU PC: 0x", hex(line.fillPc, 16L), "\n" }); + msg.append(cacheErrorContext(peripheral)); + debug(unusual, msg); + } + } +} diff --git a/waterbox/ares64/ares/ares/n64/rdram/rdram.cpp b/waterbox/ares64/ares/ares/n64/rdram/rdram.cpp index f17acd4843f..bcbd53130ed 100644 --- a/waterbox/ares64/ares/ares/n64/rdram/rdram.cpp +++ b/waterbox/ares64/ares/ares/n64/rdram/rdram.cpp @@ -10,11 +10,15 @@ RDRAM rdram; auto RDRAM::load(Node::Object parent) -> void { node = parent->append("RDRAM"); - //4_MiB internal - //4_MiB expansion pak - ram.allocate(4_MiB + 4_MiB); - - debugger.load(node); + if(!system.expansionPak) { + //4MB internal + ram.allocate(4_MiB); + } else { + //4MB internal + 4MB expansion pak + ram.allocate(4_MiB + 4_MiB); + } + + debugger.load(node); } auto RDRAM::unload() -> void { diff --git a/waterbox/ares64/ares/ares/n64/rdram/rdram.hpp b/waterbox/ares64/ares/ares/n64/rdram/rdram.hpp index 6b4d772ee06..0183159820d 100644 --- a/waterbox/ares64/ares/ares/n64/rdram/rdram.hpp +++ b/waterbox/ares64/ares/ares/n64/rdram/rdram.hpp @@ -4,26 +4,79 @@ struct RDRAM : Memory::RCP { Node::Object node; struct Writable : public Memory::Writable { + RDRAM& self; + + Writable(RDRAM& self) : self(self) {} + template - auto read(u32 address) -> u64 { + auto read(u32 address, const char *peripheral) -> u64 { if (address >= size) return 0; + if (peripheral && system.homebrewMode) { + self.debugger.readWord(address, Size, peripheral); + } return Memory::Writable::read(address); } template - auto write(u32 address, u64 value) -> void { + auto write(u32 address, u64 value, const char *peripheral) -> void { if (address >= size) return; + if (peripheral && system.homebrewMode) { + self.debugger.writeWord(address, Size, value, peripheral); + } Memory::Writable::write(address, value); } - } ram; + + template + auto writeBurst(u32 address, u32 *value, const char *peripheral) -> void { + if (address >= size) return; + Memory::Writable::write(address | 0x00, value[0]); + Memory::Writable::write(address | 0x04, value[1]); + Memory::Writable::write(address | 0x08, value[2]); + Memory::Writable::write(address | 0x0c, value[3]); + if (Size == ICache) { + Memory::Writable::write(address | 0x10, value[4]); + Memory::Writable::write(address | 0x14, value[5]); + Memory::Writable::write(address | 0x18, value[6]); + Memory::Writable::write(address | 0x1c, value[7]); + } + } + + template + auto readBurst(u32 address, u32 *value, const char *peripheral) -> void { + if (address >= size) { + value[0] = value[1] = value[2] = value[3] = 0; + if (Size == ICache) + value[4] = value[5] = value[6] = value[7] = 0; + return; + } + value[0] = Memory::Writable::read(address | 0x00); + value[1] = Memory::Writable::read(address | 0x04); + value[2] = Memory::Writable::read(address | 0x08); + value[3] = Memory::Writable::read(address | 0x0c); + if (Size == ICache) { + value[4] = Memory::Writable::read(address | 0x10); + value[5] = Memory::Writable::read(address | 0x14); + value[6] = Memory::Writable::read(address | 0x18); + value[7] = Memory::Writable::read(address | 0x1c); + } + } + + } ram{*this}; struct Debugger { + u32 lastReadCacheline = 0xffff'ffff; + u32 lastWrittenCacheline = 0xffff'ffff; + //debugger.cpp auto load(Node::Object) -> void; auto io(bool mode, u32 chipID, u32 address, u32 data) -> void; + auto readWord(u32 address, int size, const char *peripheral) -> void; + auto writeWord(u32 address, int size, u64 value, const char *peripheral) -> void; + auto cacheErrorContext(string peripheral) -> string; struct Memory { Node::Debugger::Memory ram; + Node::Debugger::Memory dcache; } memory; struct Tracer { diff --git a/waterbox/ares64/ares/ares/n64/ri/io.cpp b/waterbox/ares64/ares/ares/n64/ri/io.cpp index 6c88fbaac03..f6c37c8f1c1 100644 --- a/waterbox/ares64/ares/ares/n64/ri/io.cpp +++ b/waterbox/ares64/ares/ares/n64/ri/io.cpp @@ -1,5 +1,5 @@ auto RI::readWord(u32 address, Thread& thread) -> u32 { - address = (address & 0xfffff) >> 2; + address = (address & 0x1f) >> 2; n32 data = 0; if(address == 0) { @@ -59,7 +59,7 @@ auto RI::readWord(u32 address, Thread& thread) -> u32 { } auto RI::writeWord(u32 address, u32 data_, Thread& thread) -> void { - address = (address & 0xfffff) >> 2; + address = (address & 0x1f) >> 2; n32 data = data_; if(address == 0) { diff --git a/waterbox/ares64/ares/ares/n64/ri/ri.cpp b/waterbox/ares64/ares/ares/n64/ri/ri.cpp index 1ebca7025c7..5267965c4bf 100644 --- a/waterbox/ares64/ares/ares/n64/ri/ri.cpp +++ b/waterbox/ares64/ares/ares/n64/ri/ri.cpp @@ -27,8 +27,8 @@ auto RI::power(bool reset) -> void { io.refresh = 0x0006'3634; //store RDRAM size result into memory - rdram.ram.write(0x318, rdram.ram.size); //CIC-NUS-6102 - rdram.ram.write(0x3f0, rdram.ram.size); //CIC-NUS-6105 + rdram.ram.write(0x318, rdram.ram.size, "IPL3"); //CIC-NUS-6102 + rdram.ram.write(0x3f0, rdram.ram.size, "IPL3"); //CIC-NUS-6105 } } diff --git a/waterbox/ares64/ares/ares/n64/rsp/debugger.cpp b/waterbox/ares64/ares/ares/n64/rsp/debugger.cpp index 22144184933..6bb0afd11a5 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/debugger.cpp +++ b/waterbox/ares64/ares/ares/n64/rsp/debugger.cpp @@ -22,8 +22,23 @@ auto RSP::Debugger::load(Node::Object parent) -> void { tracer.instruction = parent->append("Instruction", "RSP"); tracer.instruction->setAddressBits(12, 2); tracer.instruction->setDepth(64); + if constexpr(Accuracy::RSP::Recompiler) { + tracer.instruction->setToggle([&] { + rsp.recompiler.reset(); + rsp.recompiler.callInstructionPrologue = tracer.instruction->enabled(); + }); + } tracer.io = parent->append("I/O", "RSP"); + + if (system.homebrewMode) { + for (auto& taintWord : taintMask.dmem) { + taintWord = {}; + } + for (auto& taintWord : taintMask.imem) { + taintWord = {}; + } + } } auto RSP::Debugger::unload() -> void { @@ -89,4 +104,81 @@ auto RSP::Debugger::ioStatus(bool mode, u32 address, u32 data) -> void { } } +auto RSP::Debugger::dmaReadWord(u32 rdramAddress, u32 pbusRegion, u32 pbusAddress) -> void { + if (system.homebrewMode) { + auto& line = cpu.dcache.line(rdramAddress); + u16 dmaMask = 0xff << (rdramAddress & 0xF); + auto& tm = !pbusRegion ? taintMask.dmem : taintMask.imem; + auto& taintWord = tm[pbusAddress >> 3]; + if (line.hit(rdramAddress) && (line.dirty & dmaMask)) { + taintWord.dirty = (line.dirty & dmaMask) >> (rdramAddress & 0x8); + taintWord.ctxDmaRdramAddress = rdramAddress & ~0x7; + taintWord.ctxDmaOriginPc = rsp.dma.current.originPc; + taintWord.ctxDmaOriginCpu = rsp.dma.current.originCpu; + taintWord.ctxCacheFillPc = line.fillPc; + taintWord.ctxCacheDirtyPc = line.dirtyPc; + } else { + taintWord.dirty = 0; + } + } +} + +auto RSP::Debugger::dmemReadWord(u12 address, int size, const char *peripheral) -> void { + if (system.homebrewMode) { + u8 readMask = ((1 << size) - 1) << (address & 0x7); + auto& taintWord = taintMask.dmem[address >> 3]; + if (taintWord.dirty & readMask) { + u32 rdramAddress = taintWord.ctxDmaRdramAddress + (address & 0x7); + string msg = { peripheral, " reading from DMEM address 0x", hex(address), " which contains a value which is not cache coherent\n"}; + msg.append(string{ "\tCurrent RSP PC: 0x", hex(rsp.ipu.pc, 3L), "\n" }); + msg.append(string{ "\tThe value read was previously written by RSP DMA from RDRAM address 0x", hex(rdramAddress, 8L), "\n" }); + if(taintWord.ctxDmaOriginCpu) { + msg.append(string{ "\tRSP DMA started at CPU PC: 0x", hex(taintWord.ctxDmaOriginPc, 16L), "\n" }); + } else { + msg.append(string{ "\tRSP DMA started at RSP PC: 0x", hex(taintWord.ctxDmaOriginPc, 3L), "\n" }); + } + msg.append(string{ "\tThe relative CPU cacheline was dirty (missing cache writeback?)\n" }); + msg.append(string{ "\tCacheline was last written at CPU PC: 0x", hex(taintWord.ctxCacheDirtyPc, 16L), "\n" }); + msg.append(string{ "\tCacheline was loaded at CPU PC: 0x", hex(taintWord.ctxCacheFillPc, 16L), "\n" }); + debug(unusual, msg); + taintWord.dirty = 0; + } + } +} + +auto RSP::Debugger::dmemReadUnalignedWord(u12 address, int size, const char *peripheral) -> void { + if (system.homebrewMode) { + u32 addressAlignedStart = address & ~7; + u32 addressAlignedEnd = address + size - 1 & ~7; + if(addressAlignedStart == addressAlignedEnd) { + dmemReadWord(address, size, "RSP"); + } else { + int sizeStart = addressAlignedEnd - address; + dmemReadWord(address, sizeStart, "RSP"); + dmemReadWord(address + sizeStart, size - sizeStart, "RSP"); + } + } +} + +auto RSP::Debugger::dmemWriteWord(u12 address, int size, u64 value) -> void { + if (system.homebrewMode) { + auto& taintWord = taintMask.dmem[address >> 3]; + taintWord.dirty &= ~(((1 << size) - 1) << (address & 0x7)); + } +} + +auto RSP::Debugger::dmemWriteUnalignedWord(u12 address, int size, u64 value) -> void { + if (system.homebrewMode) { + u32 addressAlignedStart = address & ~7; + u32 addressAlignedEnd = address + size - 1 & ~7; + if(addressAlignedStart == addressAlignedEnd) { + dmemWriteWord(address, size, value); + } else { + int sizeStart = addressAlignedEnd - address; + dmemWriteWord(address, sizeStart, value); + dmemWriteWord(address + sizeStart, size - sizeStart, value); + } + } +} + #undef rsp diff --git a/waterbox/ares64/ares/ares/n64/rsp/dma.cpp b/waterbox/ares64/ares/ares/n64/rsp/dma.cpp index fbc00b79625..72b14eec4ac 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/dma.cpp +++ b/waterbox/ares64/ares/ares/n64/rsp/dma.cpp @@ -18,8 +18,11 @@ auto RSP::dmaTransferStep() -> void { } } for(u32 i = 0; i <= dma.current.length; i += 8) { - u64 data = rdram.ram.read(dma.current.dramAddress); + u64 data = rdram.ram.read(dma.current.dramAddress, nullptr); region.write(dma.current.pbusAddress, data); + if (system.homebrewMode) { + rsp.debugger.dmaReadWord(dma.current.dramAddress, dma.current.pbusRegion, dma.current.pbusAddress); + } dma.current.dramAddress += 8; dma.current.pbusAddress += 8; } @@ -27,7 +30,7 @@ auto RSP::dmaTransferStep() -> void { if(dma.busy.write) { for(u32 i = 0; i <= dma.current.length; i += 8) { u64 data = region.read(dma.current.pbusAddress); - rdram.ram.write(dma.current.dramAddress, data); + rdram.ram.write(dma.current.dramAddress, data, "RSP DMA"); dma.current.dramAddress += 8; dma.current.pbusAddress += 8; } diff --git a/waterbox/ares64/ares/ares/n64/rsp/interpreter-scc.cpp b/waterbox/ares64/ares/ares/n64/rsp/interpreter-scc.cpp index 672716aec7c..528f87231bc 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/interpreter-scc.cpp +++ b/waterbox/ares64/ares/ares/n64/rsp/interpreter-scc.cpp @@ -1,9 +1,9 @@ auto RSP::MFC0(r32& rt, u8 rd) -> void { - if((rd & 8) == 0) rt.u32 = Nintendo64::rsp.ioRead ((rd & 7) << 2); + if((rd & 8) == 0) rt.u32 = Nintendo64::rsp.ioRead ((rd & 7) << 2, *this); if((rd & 8) != 0) rt.u32 = Nintendo64::rdp.readWord((rd & 7) << 2, *this); } auto RSP::MTC0(cr32& rt, u8 rd) -> void { - if((rd & 8) == 0) Nintendo64::rsp.ioWrite ((rd & 7) << 2, rt.u32); + if((rd & 8) == 0) Nintendo64::rsp.ioWrite ((rd & 7) << 2, rt.u32, *this); if((rd & 8) != 0) Nintendo64::rdp.writeWord((rd & 7) << 2, rt.u32, *this); } diff --git a/waterbox/ares64/ares/ares/n64/rsp/interpreter-vpu.cpp b/waterbox/ares64/ares/ares/n64/rsp/interpreter-vpu.cpp index 24cdf0b2ca5..f9ed14db582 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/interpreter-vpu.cpp +++ b/waterbox/ares64/ares/ares/n64/rsp/interpreter-vpu.cpp @@ -150,7 +150,7 @@ auto RSP::CTC2(cr32& rt, u8 rd) -> void { if constexpr(Accuracy::RSP::SIMD) { #if ARCHITECTURE_SUPPORTS_SSE4_1 - static const v128 mask = _mm_set_epi16(0x0101, 0x0202, 0x0404, 0x0808, 0x1010, 0x2020, 0x4040, 0x8080); + static const v128 mask = _mm_set_epi16(0x0101, 0x0202, 0x0404, 0x0808, 0x1010, 0x2020, 0x4040, 0x8080u); lo->v128 = _mm_cmpeq_epi8(_mm_and_si128(_mm_set1_epi8(~rt.u32 >> 0), mask), zero); hi->v128 = _mm_cmpeq_epi8(_mm_and_si128(_mm_set1_epi8(~rt.u32 >> 8), mask), zero); #endif diff --git a/waterbox/ares64/ares/ares/n64/rsp/io.cpp b/waterbox/ares64/ares/ares/n64/rsp/io.cpp index 1daa5fccc0e..b776f9d4851 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/io.cpp +++ b/waterbox/ares64/ares/ares/n64/rsp/io.cpp @@ -3,11 +3,11 @@ auto RSP::readWord(u32 address, Thread& thread) -> u32 { if(address & 0x1000) return imem.read(address); else return dmem.read(address); } - return ioRead(address); + return ioRead(address, thread); } -auto RSP::ioRead(u32 address) -> u32 { - address = (address & 0x3ffff) >> 2; +auto RSP::ioRead(u32 address, Thread &thread) -> u32 { + address = (address & 0x1f) >> 2; n32 data; if(address == 0) { @@ -72,12 +72,11 @@ auto RSP::writeWord(u32 address, u32 data, Thread& thread) -> void { if(address & 0x1000) return recompiler.invalidate(address & 0xfff), imem.write(address, data); else return dmem.write(address, data); } - return ioWrite(address, data); + return ioWrite(address, data, thread); } -auto RSP::ioWrite(u32 address, u32 data_) -> void { - - address = (address & 0x3ffff) >> 2; +auto RSP::ioWrite(u32 address, u32 data_, Thread& thread) -> void { + address = (address & 0x1f) >> 2; n32 data = data_; if(address == 0) { @@ -96,8 +95,11 @@ auto RSP::ioWrite(u32 address, u32 data_) -> void { dma.pending.length.bit(3,11) = data.bit( 3,11); dma.pending.count = data.bit(12,19); dma.pending.skip.bit(3,11) = data.bit(23,31); + dma.pending.originCpu = &thread != this; + dma.pending.originPc = dma.pending.originCpu ? cpu.ipu.pc : (u64)rsp.ipu.r[31].u32; dma.full.read = 1; dma.full.write = 0; + // printf("RSP DMA Read: %08x => %08x %08x\n", dma.pending.dramAddress, dma.pending.pbusAddress, dma.pending.length); dmaTransferStart(); } @@ -106,6 +108,8 @@ auto RSP::ioWrite(u32 address, u32 data_) -> void { dma.pending.length.bit(3,11) = data.bit( 3,11); dma.pending.count = data.bit(12,19); dma.pending.skip.bit(3,11) = data.bit(23,31); + dma.pending.originCpu = &thread != this; + dma.pending.originPc = dma.pending.originCpu ? cpu.ipu.pc : (u64)rsp.ipu.r[31].u32; dma.full.write = 1; dma.full.read = 0; dmaTransferStart(); @@ -157,7 +161,7 @@ auto RSP::ioWrite(u32 address, u32 data_) -> void { } auto RSP::Status::readWord(u32 address, Thread& thread) -> u32 { - address = (address & 0x7ffff) >> 2; + address = (address & 0x1f) >> 2; n32 data; if(address == 0) { @@ -178,7 +182,7 @@ auto RSP::Status::readWord(u32 address, Thread& thread) -> u32 { } auto RSP::Status::writeWord(u32 address, u32 data_, Thread& thread) -> void { - address = (address & 0x7ffff) >> 2; + address = (address & 0x1f) >> 2; n32 data = data_; if(address == 0) { diff --git a/waterbox/ares64/ares/ares/n64/rsp/recompiler.cpp b/waterbox/ares64/ares/ares/n64/rsp/recompiler.cpp index f9f190fa996..85468c2b0e6 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/recompiler.cpp +++ b/waterbox/ares64/ares/ares/n64/rsp/recompiler.cpp @@ -61,9 +61,7 @@ auto RSP::Recompiler::block(u12 address) -> Block* { auto RSP::Recompiler::emit(u12 address) -> Block* { if(unlikely(allocator.available() < 1_MiB)) { print("RSP allocator flush\n"); - memory::jitprotect(false); - allocator.release(bump_allocator::zero_fill); - memory::jitprotect(true); + allocator.release(); reset(); } @@ -75,19 +73,27 @@ auto RSP::Recompiler::emit(u12 address) -> Block* { u12 start = address; bool hasBranched = 0; while(true) { - pipeline.begin(); u32 instruction = self.imem.read(address); + if(callInstructionPrologue) { + mov32(reg(1), imm(instruction)); + call(&RSP::instructionPrologue); + } + pipeline.begin(); OpInfo op0 = self.decoderEXECUTE(instruction); pipeline.issue(op0); bool branched = emitEXECUTE(instruction); if(!pipeline.singleIssue && !branched && u12(address + 4) != start) { - u32 instruction = self.imem.read(address + 4); + u32 instruction = self.imem.read(address + 4); OpInfo op1 = self.decoderEXECUTE(instruction); if(RSP::canDualIssue(op0, op1)) { mov32(reg(1), imm(0)); call(&RSP::instructionEpilogue); + if(callInstructionPrologue) { + mov32(reg(1), imm(instruction)); + call(&RSP::instructionPrologue); + } address += 4; pipeline.issue(op1); branched = emitEXECUTE(instruction); diff --git a/waterbox/ares64/ares/ares/n64/rsp/rsp.cpp b/waterbox/ares64/ares/ares/n64/rsp/rsp.cpp index 821cd9437c5..5edcc63d1f1 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/rsp.cpp +++ b/waterbox/ares64/ares/ares/n64/rsp/rsp.cpp @@ -43,12 +43,11 @@ auto RSP::instruction() -> void { } if constexpr(Accuracy::RSP::Interpreter) { + u32 instruction = imem.read(ipu.pc); + instructionPrologue(instruction); pipeline.begin(); - pipeline.address = ipu.pc; - pipeline.instruction = imem.read(pipeline.address); - OpInfo op0 = decoderEXECUTE(pipeline.instruction); + OpInfo op0 = decoderEXECUTE(instruction); pipeline.issue(op0); - debugger.instruction(); interpreterEXECUTE(); if(!pipeline.singleIssue && !op0.branch()) { @@ -57,10 +56,8 @@ auto RSP::instruction() -> void { if(canDualIssue(op0, op1)) { instructionEpilogue(0); - pipeline.address = ipu.pc; - pipeline.instruction = instruction; + instructionPrologue(instruction); pipeline.issue(op1); - debugger.instruction(); interpreterEXECUTE(); } } @@ -74,6 +71,12 @@ auto RSP::instruction() -> void { step(pipeline.clocks); } +auto RSP::instructionPrologue(u32 instruction) -> void { + pipeline.address = ipu.pc; + pipeline.instruction = instruction; + debugger.instruction(); +} + auto RSP::instructionEpilogue(u32 clocks) -> s32 { if constexpr(Accuracy::RSP::Recompiler) { step(clocks); @@ -142,9 +145,7 @@ auto RSP::power(bool reset) -> void { if constexpr(Accuracy::RSP::Recompiler) { auto buffer = ares::Memory::FixedAllocator::get().tryAcquire(4_MiB); - memory::jitprotect(false); - recompiler.allocator.resize(4_MiB, bump_allocator::executable | bump_allocator::zero_fill, buffer); - memory::jitprotect(true); + recompiler.allocator.resize(64_MiB, bump_allocator::executable, buffer); recompiler.reset(); } diff --git a/waterbox/ares64/ares/ares/n64/rsp/rsp.hpp b/waterbox/ares64/ares/ares/n64/rsp/rsp.hpp index 3a6bd95fe2b..cb4f2ea45c0 100644 --- a/waterbox/ares64/ares/ares/n64/rsp/rsp.hpp +++ b/waterbox/ares64/ares/ares/n64/rsp/rsp.hpp @@ -2,7 +2,36 @@ struct RSP : Thread, Memory::RCP { Node::Object node; - Memory::Writable dmem; + struct Writable : public Memory::Writable { + RSP& self; + + Writable(RSP& self) : self(self) {} + + template + auto read(u32 address) -> u64 { + if (system.homebrewMode) self.debugger.dmemReadWord(address, Size, "RSP"); + return Memory::Writable::read(address); + } + + template + auto readUnaligned(u32 address) -> u64 { + if (system.homebrewMode) self.debugger.dmemReadUnalignedWord(address, Size, "RSP"); + return Memory::Writable::readUnaligned(address); + } + + template + auto write(u32 address, u64 value) -> void { + if (system.homebrewMode) self.debugger.dmemWriteWord(address, Size, value); + Memory::Writable::write(address, value); + } + + template + auto writeUnaligned(u32 address, u64 value) -> void { + if (system.homebrewMode) self.debugger.dmemWriteUnalignedWord(address, Size, value); + Memory::Writable::writeUnaligned(address, value); + } + + } dmem{*this}; Memory::Writable imem; struct Debugger { @@ -14,6 +43,23 @@ struct RSP : Thread, Memory::RCP { auto ioSCC(bool mode, u32 address, u32 data) -> void; auto ioStatus(bool mode, u32 address, u32 data) -> void; + auto dmaReadWord(u32 rdramAddress, u32 pbusRegion, u32 pbusAddress) -> void; + auto dmemReadWord(u12 address, int size, const char *peripheral) -> void; + auto dmemWriteWord(u12 address, int size, u64 value) -> void; + auto dmemReadUnalignedWord(u12 address, int size, const char *peripheral) -> void; + auto dmemWriteUnalignedWord(u12 address, int size, u64 value) -> void; + + struct TaintMask { + struct TaintWord { + u8 dirty; + u32 ctxDmaRdramAddress; + u64 ctxDmaOriginPc; + u1 ctxDmaOriginCpu; + u64 ctxCacheFillPc; + u64 ctxCacheDirtyPc; + } dmem[512], imem[512]; + } taintMask; + struct Memory { Node::Debugger::Memory dmem; Node::Debugger::Memory imem; @@ -32,6 +78,7 @@ struct RSP : Thread, Memory::RCP { auto main() -> void; auto instruction() -> void; + auto instructionPrologue(u32 instruction) -> void; auto instructionEpilogue(u32 clocks) -> s32; auto power(bool reset) -> void; @@ -165,8 +212,8 @@ struct RSP : Thread, Memory::RCP { //io.cpp auto readWord(u32 address, Thread& thread) -> u32; auto writeWord(u32 address, u32 data, Thread& thread) -> void; - auto ioRead(u32 address) -> u32; - auto ioWrite(u32 address, u32 data) -> void; + auto ioRead(u32 address, Thread& thread) -> u32; + auto ioWrite(u32 address, u32 data, Thread& thread) -> void; //serialization.cpp auto serialize(serializer&) -> void; @@ -179,7 +226,9 @@ struct RSP : Thread, Memory::RCP { n12 length; n12 skip; n8 count; - + n64 originPc; + n1 originCpu; + auto serialize(serializer&) -> void; } pending, current; @@ -512,6 +561,7 @@ struct RSP : Thread, Memory::RCP { return s <= e ? smask & emask : smask | emask; } + bool callInstructionPrologue = false; Pipeline pipeline; bump_allocator allocator; array context; diff --git a/waterbox/ares64/ares/ares/n64/si/dma.cpp b/waterbox/ares64/ares/ares/n64/si/dma.cpp index 35f13aeb2ac..c2690ab2b0d 100644 --- a/waterbox/ares64/ares/ares/n64/si/dma.cpp +++ b/waterbox/ares64/ares/ares/n64/si/dma.cpp @@ -1,6 +1,8 @@ auto SI::dmaRead() -> void { pif.dmaRead(io.readAddress, io.dramAddress); io.dmaBusy = 0; + io.pchState = 0; + io.dmaState = 0; io.interrupt = 1; mi.raise(MI::IRQ::SI); } @@ -8,6 +10,8 @@ auto SI::dmaRead() -> void { auto SI::dmaWrite() -> void { pif.dmaWrite(io.writeAddress, io.dramAddress); io.dmaBusy = 0; + io.pchState = 0; + io.dmaState = 0; io.interrupt = 1; mi.raise(MI::IRQ::SI); } diff --git a/waterbox/ares64/ares/ares/n64/si/io.cpp b/waterbox/ares64/ares/ares/n64/si/io.cpp index eccc777b93c..b415c058485 100644 --- a/waterbox/ares64/ares/ares/n64/si/io.cpp +++ b/waterbox/ares64/ares/ares/n64/si/io.cpp @@ -9,7 +9,7 @@ auto SI::readWord(u32 address, Thread& thread) -> u32 { } auto SI::ioRead(u32 address) -> u32 { - address = (address & 0xfffff) >> 2; + address = (address & 0x1f) >> 2; n32 data; if(address == 0) { diff --git a/waterbox/ares64/ares/ares/n64/system/serialization.cpp b/waterbox/ares64/ares/ares/n64/system/serialization.cpp index e7ba25d2226..f12ef7fd318 100644 --- a/waterbox/ares64/ares/ares/n64/system/serialization.cpp +++ b/waterbox/ares64/ares/ares/n64/system/serialization.cpp @@ -1,4 +1,4 @@ -static const string SerializerVersion = "v133.1"; +static const string SerializerVersion = "v134"; auto System::serialize(bool synchronize) -> serializer { serializer s; diff --git a/waterbox/ares64/ares/ares/n64/system/system.cpp b/waterbox/ares64/ares/ares/n64/system/system.cpp index cd1a9840b7c..6b9e93577e4 100644 --- a/waterbox/ares64/ares/ares/n64/system/system.cpp +++ b/waterbox/ares64/ares/ares/n64/system/system.cpp @@ -1,5 +1,7 @@ #include +#include + namespace ares::Nintendo64 { auto enumerate() -> vector { @@ -29,6 +31,8 @@ auto option(string name, string value) -> bool { if(vulkan.internalUpscale == 1) vulkan.supersampleScanout = false; vulkan.outputUpscale = vulkan.supersampleScanout ? 1 : vulkan.internalUpscale; #endif + if(name == "Homebrew Mode") system.homebrewMode = value.boolean(); + if(name == "Expansion Pak") system.expansionPak = value.boolean(); return true; } diff --git a/waterbox/ares64/ares/ares/n64/system/system.hpp b/waterbox/ares64/ares/ares/n64/system/system.hpp index cae1e955fdd..e3f7547dc4b 100644 --- a/waterbox/ares64/ares/ares/n64/system/system.hpp +++ b/waterbox/ares64/ares/ares/n64/system/system.hpp @@ -1,6 +1,8 @@ struct System { Node::System node; VFS::Pak pak; + bool homebrewMode = false; + bool expansionPak = true; enum class Region : u32 { NTSC, PAL }; @@ -31,6 +33,8 @@ struct System { bool dd = false; } information; + auto initDebugHooks() -> void; + //serialization.cpp auto serialize(serializer&, bool synchronize) -> void; }; diff --git a/waterbox/ares64/ares/ares/n64/vi/io.cpp b/waterbox/ares64/ares/ares/n64/vi/io.cpp index 773378c2726..4b3482a933f 100644 --- a/waterbox/ares64/ares/ares/n64/vi/io.cpp +++ b/waterbox/ares64/ares/ares/n64/vi/io.cpp @@ -1,5 +1,5 @@ auto VI::readWord(u32 address, Thread& thread) -> u32 { - address = (address & 0xfffff) >> 2; + address = (address & 0x3f) >> 2; n32 data; if(address == 0) { @@ -97,7 +97,7 @@ auto VI::readWord(u32 address, Thread& thread) -> u32 { } auto VI::writeWord(u32 address, u32 data_, Thread& thread) -> void { - address = (address & 0xfffff) >> 2; + address = (address & 0x3f) >> 2; n32 data = data_; #if defined(VULKAN) diff --git a/waterbox/ares64/ares/ares/n64/vi/vi.cpp b/waterbox/ares64/ares/ares/n64/vi/vi.cpp index cd22eb70848..7f5aa6e6f05 100644 --- a/waterbox/ares64/ares/ares/n64/vi/vi.cpp +++ b/waterbox/ares64/ares/ares/n64/vi/vi.cpp @@ -26,6 +26,7 @@ auto VI::load(Node::Object parent) -> void { #endif screen = node->append("Screen", width, height); screen->setRefresh({&VI::refresh, this}); + screen->refreshRateHint(Region::PAL() ? 50 : 60); // TODO: More accurate refresh rate hint screen->colors((1 << 24) + (1 << 15), [&](n32 color) -> n64 { if(color < (1 << 24)) { u64 a = 65535; @@ -159,7 +160,7 @@ auto VI::refresh() -> void { auto line = screen->pixels(1).data() + (dy - vscan_start) * hscan_len; u32 x0 = vi.io.xsubpixel + vi.io.xscale * (dx0 - vi.io.hstart); for(i32 dx = dx0; dx < dx1; dx++) { - u16 data = rdram.ram.read(address + (x0 >> 10) * 2); + u16 data = rdram.ram.read(address + (x0 >> 10) * 2, "VI"); line[dx - hscan_start] = 1 << 24 | data >> 1; x0 += vi.io.xscale; } @@ -177,7 +178,7 @@ auto VI::refresh() -> void { auto line = screen->pixels(1).data() + (dy - vscan_start) * hscan_len; u32 x0 = vi.io.xsubpixel + vi.io.xscale * (dx0 - vi.io.hstart); for(i32 dx = dx0; dx < dx1; dx++) { - u32 data = rdram.ram.read(address + (x0 >> 10) * 4); + u32 data = rdram.ram.read(address + (x0 >> 10) * 4, "VI"); line[dx - hscan_start] = data >> 8; x0 += vi.io.xscale; } diff --git a/waterbox/ares64/ares/nall/arithmetic.hpp b/waterbox/ares64/ares/nall/arithmetic.hpp index baf00a9fb28..4d0ebbf3824 100644 --- a/waterbox/ares64/ares/nall/arithmetic.hpp +++ b/waterbox/ares64/ares/nall/arithmetic.hpp @@ -3,6 +3,8 @@ //multi-precision arithmetic //warning: each size is quadratically more expensive than the size before it! +#include + #include #include #include diff --git a/waterbox/ares64/ares/nall/arithmetic/natural.hpp b/waterbox/ares64/ares/nall/arithmetic/natural.hpp index e90f2b3bf18..0cedfaee5af 100644 --- a/waterbox/ares64/ares/nall/arithmetic/natural.hpp +++ b/waterbox/ares64/ares/nall/arithmetic/natural.hpp @@ -1,3 +1,5 @@ +#include + #define ConcatenateType(Size) u##Size #define DeclareType(Size) ConcatenateType(Size) @@ -278,7 +280,7 @@ template alwaysinline auto ror(const Pair& lhs, const T& rhs) -> Pai return lhs >> rhs | lhs << (PairBits - rhs); } -#define EI /*typename =*/ enable_if_t::value> +#define EI enable_if_t::value> template auto& operator*= (T& lhs, const Pair& rhs) { return lhs = lhs * T(rhs); } template auto& operator/= (T& lhs, const Pair& rhs) { return lhs = lhs / T(rhs); } diff --git a/waterbox/ares64/ares/nall/arithmetic/unsigned.hpp b/waterbox/ares64/ares/nall/arithmetic/unsigned.hpp index bc82a4c09de..35e8a34b9e7 100644 --- a/waterbox/ares64/ares/nall/arithmetic/unsigned.hpp +++ b/waterbox/ares64/ares/nall/arithmetic/unsigned.hpp @@ -2,34 +2,34 @@ namespace nall { -template::value>> +template::value>> inline auto upper(T value) -> T { return value >> sizeof(T) * 4; } -template::value>> +template::value>> inline auto lower(T value) -> T { static const T Mask = ~T(0) >> sizeof(T) * 4; return value & Mask; } -template::value>, typename = enable_if_t::value>> +template::value>, enable_if_t::value>> inline auto mul(T lhs, U rhs) -> uintmax { return lhs * rhs; } -template::value>> +template::value>> inline auto square(T value) -> uintmax { return value * value; } -template::value>> -inline auto rol(T lhs, U rhs) -> T { +template +inline auto rol(T lhs, U rhs, enable_if_t::value>* = 0) -> T { return lhs << rhs | lhs >> sizeof(T) * 8 - rhs; } -template::value>> -inline auto ror(T lhs, U rhs) -> T { +template +inline auto ror(T lhs, U rhs, enable_if_t::value>* = 0) -> T { return lhs >> rhs | lhs << sizeof(T) * 8 - rhs; } diff --git a/waterbox/ares64/ares/nall/bit.hpp b/waterbox/ares64/ares/nall/bit.hpp index b259c122010..3a50c130bb5 100644 --- a/waterbox/ares64/ares/nall/bit.hpp +++ b/waterbox/ares64/ares/nall/bit.hpp @@ -78,6 +78,14 @@ namespace bit { return first; } + //return index of the last bit set (or zero of no bits are set) + //last(0b11000) == 4 + constexpr inline auto last(u64 x) -> u32 { + u32 i = 0; + while(x) { x >>= 1; i++; } + return i > 0 ? --i : i; + } + //round up to next highest single bit: //round(15) == 16, round(16) == 16, round(17) == 32 constexpr inline auto round(u64 x) -> u64 { diff --git a/waterbox/ares64/ares/nall/bump-allocator.hpp b/waterbox/ares64/ares/nall/bump-allocator.hpp index dbf1e52adc5..7a4aac57891 100644 --- a/waterbox/ares64/ares/nall/bump-allocator.hpp +++ b/waterbox/ares64/ares/nall/bump-allocator.hpp @@ -28,9 +28,6 @@ struct bump_allocator { reset(); if(buffer) { - if(flags & executable) { - memory::protect(buffer, capacity, true); - } if(flags & zero_fill) { memset(buffer, 0x00, capacity); } @@ -88,9 +85,9 @@ struct bump_allocator { _offset = nextOffset(size); //alignment } - auto tryAcquire(u32 size) -> u8* { + auto tryAcquire(u32 size, bool reserve = true) -> u8* { if((nextOffset(size)) > _capacity) return nullptr; - return acquire(size); + return reserve ? acquire(size) : acquire(); } private: diff --git a/waterbox/ares64/ares/nall/cd/session.hpp b/waterbox/ares64/ares/nall/cd/session.hpp index f8b826c5e1e..7bff004d3df 100644 --- a/waterbox/ares64/ares/nall/cd/session.hpp +++ b/waterbox/ares64/ares/nall/cd/session.hpp @@ -268,7 +268,9 @@ struct Session { q[0] = track.control << 4 | 1; q[1] = BCD::encode(trackID); q[2] = BCD::encode(indexID); - auto msf = MSF(lba - track.indices[1].lba); + auto msf = indexID == 0 + ? MSF(track.indices[0].end - lba) + : MSF(lba - track.indices[1].lba); q[3] = BCD::encode(msf.minute); q[4] = BCD::encode(msf.second); q[5] = BCD::encode(msf.frame); diff --git a/waterbox/ares64/ares/nall/chrono.hpp b/waterbox/ares64/ares/nall/chrono.hpp index dec25cbd8d9..49e83a6ef1c 100644 --- a/waterbox/ares64/ares/nall/chrono.hpp +++ b/waterbox/ares64/ares/nall/chrono.hpp @@ -25,6 +25,12 @@ inline auto benchmark(const function& f, u64 times = 1) -> void { print("[chrono::benchmark] ", (double)(end - start) / 1'000'000'000.0, "s\n"); } +inline auto daysInMonth(u32 month, u32 year) -> u8 { + u32 days = 30 + ((month + (month >> 3)) & 1); + if (month == 2) days -= (year % 4 == 0) ? 1 : 2; + return days; +} + //exact date/time functions (from system epoch) struct timeinfo { diff --git a/waterbox/ares64/ares/nall/decode/chd.hpp b/waterbox/ares64/ares/nall/decode/chd.hpp index b150787f68a..bd09f640855 100644 --- a/waterbox/ares64/ares/nall/decode/chd.hpp +++ b/waterbox/ares64/ares/nall/decode/chd.hpp @@ -31,7 +31,7 @@ struct CHD { }; auto load(const string& location) -> bool; - auto read(u32 sector) -> vector; + auto read(u32 sector) const -> vector; auto sectorCount() const -> u32; vector tracks; @@ -40,10 +40,10 @@ struct CHD { #if false chd_file* chd = nullptr; #endif - const int chd_sector_size = 2352 + 96; + static constexpr int chd_sector_size = 2352 + 96; size_t chd_hunk_size; - vector chd_hunk_buffer; - int chd_current_hunk = -1; + mutable vector chd_hunk_buffer; + mutable int chd_current_hunk = -1; }; inline CHD::~CHD() { @@ -123,11 +123,10 @@ inline auto CHD::load(const string& location) -> bool { return false; } - // Ensure two second pregap is present const bool pregap_in_file = (pregap_frames > 0 && pgtype[0] == 'V'); - if (pregap_frames <= 0 && typeStr != "AUDIO") { - pregap_frames = 2 * 75; - } + + // First track should have 2 second pregap as standard + if(track_no == 1 && !pregap_in_file) pregap_frames = 2 * 75; // Add the new track Track track; @@ -136,7 +135,7 @@ inline auto CHD::load(const string& location) -> bool { track.pregap = pregap_frames; track.postgap = postgap_frames; - // Pregap + // index0 = Pregap if (pregap_frames > 0) { Index index; index.number = 0; @@ -190,7 +189,7 @@ inline auto CHD::load(const string& location) -> bool { #endif } -inline auto CHD::read(u32 sector) -> vector { +inline auto CHD::read(u32 sector) const -> vector { // Convert LBA in CD-ROM to LBA in CHD #if false for(auto& track : tracks) { diff --git a/waterbox/ares64/ares/nall/decode/url.hpp b/waterbox/ares64/ares/nall/decode/url.hpp index 18382d1c96b..62a99e24887 100644 --- a/waterbox/ares64/ares/nall/decode/url.hpp +++ b/waterbox/ares64/ares/nall/decode/url.hpp @@ -1,5 +1,7 @@ #pragma once +#include + namespace nall::Decode { //returns empty string on malformed content diff --git a/waterbox/ares64/ares/nall/file-buffer.hpp b/waterbox/ares64/ares/nall/file-buffer.hpp index 41bd2e298da..eac95707019 100644 --- a/waterbox/ares64/ares/nall/file-buffer.hpp +++ b/waterbox/ares64/ares/nall/file-buffer.hpp @@ -229,10 +229,10 @@ struct file_buffer { auto bufferSynchronize() -> void { if(!fileHandle) return; - if(bufferOffset == (fileOffset & ~(buffer.size() - 1))) return; + if(bufferOffset == (fileOffset & ~u64(buffer.size() - 1))) return; bufferFlush(); - bufferOffset = fileOffset & ~(buffer.size() - 1); + bufferOffset = fileOffset & ~u64(buffer.size() - 1); fseek(fileHandle, bufferOffset, SEEK_SET); u64 length = bufferOffset + buffer.size() <= fileSize ? buffer.size() : fileSize & buffer.size() - 1; if(length) (void)fread(buffer.data(), 1, length, fileHandle); diff --git a/waterbox/ares64/ares/nall/file-map.cpp b/waterbox/ares64/ares/nall/file-map.cpp index c579f0c607e..3172378ab07 100644 --- a/waterbox/ares64/ares/nall/file-map.cpp +++ b/waterbox/ares64/ares/nall/file-map.cpp @@ -41,14 +41,17 @@ NALL_HEADER_INLINE auto file_map::open(const string& filename, u32 mode_) -> boo _file = CreateFileW(utf16_t(filename), desiredAccess, FILE_SHARE_READ, nullptr, creationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr); - if(_file == INVALID_HANDLE_VALUE) return false; + if(_file == INVALID_HANDLE_VALUE) { + _file = nullptr; + return false; + } _size = GetFileSize(_file, nullptr); _map = CreateFileMapping(_file, nullptr, protection, 0, _size, nullptr); - if(_map == INVALID_HANDLE_VALUE) { + if(_map == nullptr) { CloseHandle(_file); - _file = INVALID_HANDLE_VALUE; + _file = nullptr; return false; } @@ -62,14 +65,14 @@ NALL_HEADER_INLINE auto file_map::close() -> void { _data = nullptr; } - if(_map != INVALID_HANDLE_VALUE) { + if(_map != nullptr) { CloseHandle(_map); - _map = INVALID_HANDLE_VALUE; + _map = nullptr; } - if(_file != INVALID_HANDLE_VALUE) { + if(_file != nullptr) { CloseHandle(_file); - _file = INVALID_HANDLE_VALUE; + _file = nullptr; } _open = false; diff --git a/waterbox/ares64/ares/nall/file-map.hpp b/waterbox/ares64/ares/nall/file-map.hpp index 0a7ec70094f..66e2cc2e1c1 100644 --- a/waterbox/ares64/ares/nall/file-map.hpp +++ b/waterbox/ares64/ares/nall/file-map.hpp @@ -50,8 +50,8 @@ struct file_map { #if defined(API_WINDOWS) - HANDLE _file = INVALID_HANDLE_VALUE; - HANDLE _map = INVALID_HANDLE_VALUE; + HANDLE _file = nullptr; + HANDLE _map = nullptr; public: auto operator=(file_map&& source) -> file_map& { @@ -67,8 +67,8 @@ struct file_map { source._open = false; source._data = nullptr; source._size = 0; - source._file = INVALID_HANDLE_VALUE; - source._map = INVALID_HANDLE_VALUE; + source._file = nullptr; + source._map = nullptr; return *this; } diff --git a/waterbox/ares64/ares/nall/gdb/Readme.md b/waterbox/ares64/ares/nall/gdb/Readme.md new file mode 100644 index 00000000000..dd81ff811cc --- /dev/null +++ b/waterbox/ares64/ares/nall/gdb/Readme.md @@ -0,0 +1,227 @@ +# Debug Server + +The file `server.cpp` adds a gdb-server compatible with several GDB versions and IDEs like VScode and CLion.
+It is implemented as a standalone server independent of any specific system, and even ares itself.
+This allows for easy integration with systems without having to worry about the details of GDB itself.
+ +Managing the server itself, including the underlying TCP connection, is done by ares.
+System specific logic is handled via (optional) call-backs that a can be registered,
+as well as methods to report events to GDB. + +The overall design of this server is to be as neutral as possible.
+Meaning that things like stopping, stepping and reading memory should not affect the game.
+This is done to make sure that games behave the same as if they were running without a debugger, down to the cycle.
+ +## Integration Guide +This section describes how to implement the debugger for a system in ares.
+It should not be necessary to modify the server itself, or to know much about the GDB protocol.
+Simply registering callbacks and reporting events are enough to get the full set of features working.
+ +For a minimal working debugging session, register/memory reads and a way to report the PC are required.
+Although implementing as much as possible is recommended to make GDB more stable. + +Interactions with the server can be split in three categories: +- **Hooks:** lets GDB call functions in your ares system (e.g.: memory read) +- **Report-functions:** notify GDB about events (e.g.: exceptions) +- **Status-functions:** helper to check the GDB status (e.g.: are breakpoints set or not) + +Hooks can be set via setting the callbacks in `GDB::server.hooks.XXX`.
+Report functions are prefixed `GDB::server.reportXXX()`, and status functions a documented here separately.
+All hooks/report/status functions can be safely set or called even if the server is not running.
+ +As an example of a fictional system, this is what a memory read could look like: +```cpp +GDB::server.hooks.regRead = [](u32 regIdx) { + return hex(cpu.readRegister(regIdx), 16, '0'); +}; +``` +Or the main execution loop: +```cpp +while(!endOfFrame && GDB::server.reportPC(cpu.getPC())) { + cpu.step(); +} +``` + +For a real reference implementation, you can take a look at the N64 system.
+ +## Hooks + +### Memory Read - `read = (u64 address, u32 byteCount) -> string` +Reads `byteCount` bytes from `address` and returns them as a hex-string.
+Both the hex-encoding / single-byte reads are dictated by the GDB protocol.
+ +It is important to implement this in a neutral way: no exceptions and status changes.
+The GDB-client may issue reads from any address at any point while halted.
+If not handled properly, this can cause game crashes or different emulation behavior.
+ +If your system emulates cache, make sure to also handle this here.
+A read must be able to see the cache, but never cause a flush.
+ +Example response (reading 3 bytes): `A1B200` + +### Memory Write - `write = (u64 address, u32 unitSize, u64 value) -> void` +Writes `value` of byte-size `unitSize` to `address`.
+For example, writing a 32-bit value would issue a call like this: `write(0x80001230, 4, 0x0000000012345678)`.
+Contrary to read, this is not required to be neutral, and is allowed to cause exceptions.
+ +If your system emulates cache, make sure to also handle this here.
+The write should behave the same as if it was done via a CPU instruction, incl. flushing the cache if needed.
+ +### Normalize Address - `normalizeAddress = (u64 address) -> u64` +Normalizes an address into something that makes it comparable.
+This is only used for memory-watchpoints, which needs to compare what GDB send to what ares has internally.
+If your system has virtual addresses or masks, this should de-virtualize it.
+ +It's OK to not set this function, or to simply return the input untouched.
+In case that memory-watchpoint are not working, this is probably the place to fix it.
+ +Example implementation: +```cpp +GDB::server.hooks.normalizeAddress = [](u64 address) { + return address & 0x0FFF'FFFF; +}; +``` + +### Register Read - `regRead = (u32 regIdx) -> string` +Reads a single register at `regIdx` and returns it as a hex-string.
+The size of the hex-string is dictated by the specific architecture.
+ +Same as for memory-read, this must be implemented in a neutral way.
+Any invalid register can be returned as zero.
+ +Example response: `00000000000123AB` + +### Register Write - `regWrite = (u32 regIdx, u64 regValue) -> bool` + +Writes the value `regValue` to the register at `regIdx`.
+This write is allowed to have side effects.
+ +If the specific register is not writable or doesn't exist, `false` must be returned.
+On success, `true` must be returned.
+ +### Register Read (General) - `regReadGeneral = () -> string` +Most common way for GDB to read registers, this fetches all registers at once.
+The amount and order of registers is dictated by the specific architecture and GDB.
+When implementing this, GDB will usually complain if the order/size is incorrect.
+ +Same as for single reads, this must be implemented in a neutral way.
+ +Due to some issues regarding exception handling, you are given the option to return a different PC.
+This PC-override can be accessed via `GDB::server.getPcOverride() -> maybe`.
+The reasons for that are explained later in `reportSignal()`. + +Other than that, this can be implemented by looping over `hooks.regRead` and returning a concatenated string.
+Example response: `0000000000000000ffffffff8001000000000000000000420000000000000000000000000000000100000`... + +### Register Write (General) - `regWriteGeneral = (const string ®Data) -> void` +Writes all registers at once, this happens very rarely.
+The format of `regData` is the same as the response of `hooks.regReadGeneral`.
+Any register that is not writable or doesn't exist can be ignored.
+ +### Emulator Cache - `emuCacheInvalidate = (u64 address) -> void` +Should invalidate the emulator's cache at `address`.
+This is only necessary if you have a re-compiler or some form of instruction cache.
+ +### Target XML - `targetXML = () -> string` +Provides an XML description of the target system.
+The XML must not contain any newlines, and should be as short as possible.
+If the client has access to an `.elf` file, this will be mostly ignored. + +Example implementation: +```cpp +GDB::server.hooks.targetXML = []() -> string { + return "" + "mips:4000" + ""; +}; +``` +Documentation: https://sourceware.org/gdb/onlinedocs/gdb/Target-Description-Format.html#Target-Description-Format +
+ +## Report-Functions + +### Signal `reportSignal(Signal sig, u64 originPC) -> bool` +Reports a signal/exception `sig` that occurred at `originPC`.
+The architecture specific exception must be mapped to the enum in `Signal`.
+As a default, `Signal::TRAP` can be used.
+ +It will return `false` if the exception occurred while the game was already paused.
+This can be safely ignored.
+ +Since you may not be able to stop the execution before an exception occurs,
+The `originPC` value will be saved until the next time the game is resumed.
+An `hooks.regReadGeneral` implementation may use this to temp. return a different PC.
+This is done to allow GDB to halt on the causing instruction instead of the exception handler.
+If you can halt before an exception occurs, you can ignore this.
+ +### PC `reportPC(u64 pc) -> bool` +Sets a new PC, this will internally check for break- and watch-points.
+For convenience, it will return `false` if you should halt execution.
+If no debugger is running, it will always return `true`.
+ +You must only call this once per step, before the instruction at the given address gets executed.
+This also means a return value of `false` should make it halt before the instruction too.
+Once halted, it's safe to call this with the same PC each iteration.
+ +If a re-compiler is used, you may not want to call this for every single instruction.
+In that case take a look at `hasBreakpoints()` on how to optimize this.
+ +In case you need the information if a halt is required multiple times, use `GDB::server.isHalted()` instead.
+ +### Memory Read `reportMemRead(u64 address, u32 size) -> void` +Reports that a memory read occurred at `address` with `size` bytes.
+The passed address must be the raw un-normalized address.
+ +This is exclusively used for memory-watchpoints.
+No PC override mechanism is provided here, since it's breaks GDB.
+ +### Memory Write `reportMemWrite(u64 address, u32 size) -> void` +Exactly the same as `reportMemRead`, but for writes instead.
+The new value of that location will be automatically fetched by the client via a memory read,
+and is therefore not needed here. + +## Status-Functions + +### Halted `isHalted() -> bool` +Returns if the game should be currently halted or not.
+For convenience, the same value gets directly returned from `reportPC`.
+ +### Breakpoints `hasBreakpoints() -> bool` +Return `true` if at least one break- or watch-point is set.
+ +If you use a block-based re-compiler, stopping at every instruction may not be possible.
+You may use this information to force single-instruction execution in that case.
+If it returns false, you can safely resume using the block-based execution again.
+ +### PC Override `getPcOverride() -> maybe` +Returns a value if a PC override is active.
+As mentioned in `reportSignal()`, this can be used to return a different PC letting GDB halt at the causing instruction.
+You can safely call this function multiple times.
+Once a single step is taken, or the game is resumed, the override is cleared.
+ +## API Usage + +This API can also be used without GDB, which allows for more use cases.
+For example, you can write automated tooling or custom debugging UIs.
+To make access easier, no strict checks are performed.
+This means that the handshake protocol is optional, and checksums are not verified. + +### TCP +TCP connections behave the same way as a GDB session.
+The connection is kept open the entire time, and commands are sent sequentially, each waiting for an response before sending the next command. + +However, it is possible to send commands even if the game is still running, +this allows for real-time data access. + +Keep in minds that the server uses the RDP-commands, which are different from what you would type into a GDB client.
+For a list of all commands, see: https://sourceware.org/gdb/onlinedocs/gdb/Packets.html#Packets + +As an example, reading from memory would look like this: +``` +$m8020a504,100#00 +``` +This reads 100 bytes from address `0x8020a504`, the `$` and `#` define the message start/end, and the `00` is the checksum (which is not checked). + +One detail, and security check, is that new connections must send `+` as the first byte in the first payload.
+It's also a good idea to send a proper disconnect-command before closing the socket.
+Otherwise, the debugger will not accept new connections until a reset or restart occurs. \ No newline at end of file diff --git a/waterbox/ares64/ares/nall/gdb/server.cpp b/waterbox/ares64/ares/nall/gdb/server.cpp new file mode 100644 index 00000000000..eeb9ffb5751 --- /dev/null +++ b/waterbox/ares64/ares/nall/gdb/server.cpp @@ -0,0 +1,552 @@ +#include + +#include + +using string = ::nall::string; +using string_view = ::nall::string_view; + +namespace { + constexpr bool GDB_LOG_MESSAGES = false; + + constexpr u32 MAX_REQUESTS_PER_UPDATE = 10; + constexpr u32 MAX_PACKET_SIZE = 0x4096; + constexpr u32 DEF_BREAKPOINT_SIZE = 64; + constexpr bool NON_STOP_MODE = false; // broken for now, mainly useful for multi-thread debugging, which we can't really support + + auto gdbCalcChecksum(const string &payload) -> u8 { + u8 checksum = 0; + for(char c : payload)checksum += c; + return checksum; + } + + template + inline auto addOrRemoveEntry(vector &data, T value, bool shouldAdd) { + if(shouldAdd) { + data.append(value); + } else { + data.removeByValue(value); + } + } +} + +namespace nall::GDB { + Server server{}; + + auto Server::reportSignal(Signal sig, u64 originPC) -> bool { + if(!hasActiveClient || !handshakeDone)return true; // no client -> no error + if(forceHalt)return false; // Signals can only happen while the game is running, ignore others + + pcOverride = originPC; + + forceHalt = true; + haltSignalSent = true; + sendSignal(sig); + + return true; + } + + auto Server::reportWatchpoint(const Watchpoint &wp, u64 address) -> void { + auto orgAddress = wp.addressStartOrg + (address - wp.addressStart); + forceHalt = true; + haltSignalSent = true; + sendSignal(Signal::TRAP, {wp.getTypePrefix(), hex(orgAddress), ";"}); + } + + auto Server::reportMemRead(u64 address, u32 size) -> void { + if(!watchpointRead)return; + + if(hooks.normalizeAddress) { + address = hooks.normalizeAddress(address); + } + + u64 addressEnd = address + size - 1; + for(const auto& wp : watchpointRead) { + if(wp.hasOverlap(address, addressEnd)) { + return reportWatchpoint(wp, address); + } + } + } + + auto Server::reportMemWrite(u64 address, u32 size) -> void { + if(!watchpointWrite)return; + + if(hooks.normalizeAddress) { + address = hooks.normalizeAddress(address); + } + + u64 addressEnd = address + size - 1; + for(const auto& wp : watchpointWrite) { + if(wp.hasOverlap(address, addressEnd)) { + return reportWatchpoint(wp, address); + } + } + } + + auto Server::reportPC(u64 pc) -> bool { + if(!hasActiveClient)return true; + + currentPC = pc; + bool needHalts = forceHalt || breakpoints.contains(pc); + + if(needHalts) { + forceHalt = true; // breakpoints may get deleted after a signal, but we have to stay stopped + + if(!haltSignalSent) { + haltSignalSent = true; + sendSignal(Signal::TRAP); + } + } + + if(singleStepActive) { + singleStepActive = false; + forceHalt = true; + } + + return !needHalts; + } + + /** + * NOTE: please read the comment in the header server.hpp file before making any changes here! + */ + auto Server::processCommand(const string& cmd, bool &shouldReply) -> string + { + auto cmdParts = cmd.split(":"); + auto cmdName = cmdParts[0]; + char cmdPrefix = cmdName.size() > 0 ? cmdName(0) : ' '; + + if constexpr(GDB_LOG_MESSAGES) { + print("GDB <: %s\n", cmdBuffer.data()); + } + + switch(cmdPrefix) + { + case '!': return "OK"; // informs us that "extended remote-debugging" is used + + case '?': // handshake: why did we halt? + haltProgram(); + haltSignalSent = true; + return "T05"; // needs to be faked, otherwise the GDB-client hangs up and eats 100% CPU + + case 'c': // continue + case 'C': // continue (with signal, signal itself can be ignored) + // normal stop-mode is only allowed to respond once a signal was raised, non-stop must return OK immediately + handshakeDone = true; // good indicator that GDB is done, also enables exception sending + shouldReply = NON_STOP_MODE; + resumeProgram(); + return "OK"; + + case 'D': // client wants to detach (Note: VScode doesn't seem to use this, uses vKill instead) + requestDisconnect = true; + return "OK"; + break; + + case 'g': // dump all general registers + if(hooks.regReadGeneral) { + return hooks.regReadGeneral(); + } else { + return "0000000000000000000000000000000000000000"; + } + break; + + case 'G': // set all general registers + if(hooks.regWriteGeneral) { + hooks.regWriteGeneral(cmd.slice(1)); + return "OK"; + } + break; + + case 'H': // set which thread a 'c' command that may follow belongs to (can be ignored in stop-mode) + if(cmdName == "Hc0")currentThreadC = 0; + if(cmdName == "Hc-1")currentThreadC = -1; + return "OK"; + + case 'k': // old version of vKill + if(handshakeDone) { // sometimes this gets send during handshake (to reset the program?) -> ignore + requestDisconnect = true; + } + return "OK"; + break; + + case 'm': // read memory (e.g.: "m80005A00,4") + { + if(!hooks.read) { + return ""; + } + + auto sepIdxMaybe = cmdName.find(","); + u32 sepIdx = sepIdxMaybe ? sepIdxMaybe.get() : 1; + + u64 address = cmdName.slice(1, sepIdx-1).hex(); + u64 count = cmdName.slice(sepIdx+1, cmdName.size()-sepIdx).hex(); + return hooks.read(address, count); + } + break; + + case 'M': // write memory (e.g.: "M801ef90a,4:01000000") + { + if(!hooks.write) { + return ""; + } + + auto sepIdxMaybe = cmdName.find(","); + u32 sepIdx = sepIdxMaybe ? sepIdxMaybe.get() : 1; + + u64 address = cmdName.slice(1, sepIdx-1).hex(); + u64 unitSize = cmdName.slice(sepIdx+1, 1).hex(); + u64 value = cmdParts.size() > 1 ? cmdParts[1].hex() : 0; + + hooks.write(address, unitSize, value); + return "OK"; + } + + break; + + case 'p': // read specific register (e.g.: "p15") + if(hooks.regRead) { + u32 regIdx = cmdName.slice(1).integer(); + return hooks.regRead(regIdx); + } else { + return "00000000"; + } + break; + + case 'P': // write specific register (e.g.: "P15=FFFFFFFF80001234") + if(hooks.regWrite) { + auto sepIdxMaybe = cmdName.find("="); + u32 sepIdx = sepIdxMaybe ? sepIdxMaybe.get() : 1; + + u32 regIdx = static_cast(cmdName.slice(1, sepIdx-1).hex()); + u64 regValue = cmdName.slice(sepIdx+1).hex(); + + return hooks.regWrite(regIdx, regValue) ? "OK" : "E00"; + } + break; + + case 'q': + // This tells the client what we can and can't do + if(cmdName == "qSupported"){ return { + "PacketSize=", hex(MAX_PACKET_SIZE), + ";fork-events-;swbreak+;hwbreak-", + ";vContSupported-", // prevent vCont commands (reduces potential GDB variations: some prefer using it, others don't) + NON_STOP_MODE ? ";QNonStop+" : "", + "QStartNoAckMode+", + hooks.targetXML ? ";xmlRegisters+;qXfer:features:read+" : "" // (see: https://marc.info/?l=gdb&m=149901965961257&w=2) + };} + + // handshake-command, most return dummy values to convince gdb to connect + if(cmdName == "qTStatus")return forceHalt ? "T1" : ""; + if(cmdName == "qAttached")return "1"; // we are always attached, since a game is running + if(cmdName == "qOffsets")return "Text=0;Data=0;Bss=0"; + + if(cmdName == "qSymbol")return "OK"; // client offers us symbol-names -> we don't care + + // client asks us about existing breakpoints (may happen after a re-connect) -> ignore since we clear them on connect + if(cmdName == "qTfP")return ""; + if(cmdName == "qTsP")return ""; + + // extended target features (gdb extension), most return XML data + if(cmdName == "qXfer" && cmdParts.size() > 4) + { + if(cmdParts[1] == "features" && cmdParts[2] == "read") { + // informs the client about arch/registers (https://sourceware.org/gdb/onlinedocs/gdb/Target-Description-Format.html#Target-Description-Format) + if(cmdParts[3] == "target.xml") { + return hooks.targetXML ? string{"l", hooks.targetXML()} : string{""}; + } + } + } + + // Thread-related queries + if(cmdName == "qfThreadInfo")return {"m1"}; + if(cmdName == "qsThreadInfo")return {"l"}; + if(cmdName == "qThreadExtraInfo,1")return ""; // ignoring this command fixes support for CLion (and VSCode?), otherwise gdb hangs + if(cmdName == "qC")return {"QC1"}; + // there will also be a "qP0000001f0000000000000001" command depending on the IDE, this is ignored to prevent GDB from hanging up + break; + + case 'Q': + if(cmdName == "QNonStop") { // 0=stop, 1=non-stop-mode (this allows for async GDB-communication) + if(cmdParts.size() <= 1)return "E00"; + nonStopMode = cmdParts[1] == "1"; + + if(nonStopMode) { + haltProgram(); + } else { + resumeProgram(); + } + return "OK"; + } + + if(cmdName == "QStartNoAckMode") { + if (noAckMode) { + return "OK"; + } + // The final OK has to be sent in ack mode. + sendPayload("OK"); + shouldReply = false; + noAckMode = true; + return ""; + } + break; + + case 's': { + if(cmdName.size() > 1) { + u64 address = cmdName.slice(1).integer(); + printf("stepping at address unsupported, ignore (%016" PRIX64 ")\n", address); + } + + shouldReply = false; + singleStepActive = true; + resumeProgram(); + return ""; + } break; + + case 'v': { + // normalize (e.g. "vAttach;1" -> "vAttach") + auto sepIdxMaybe = cmdName.find(";"); + auto vName = sepIdxMaybe ? cmdName.slice(0, sepIdxMaybe.get()) : cmdName; + + if(vName == "vMustReplyEmpty")return ""; // handshake-command / keep-alive (must return the same as an unknown command would) + if(vName == "vAttach")return NON_STOP_MODE ? "OK" : "S05"; // attaches to the process, we must return a fake trap-exception to make gdb happy + if(vName == "vCont?")return ""; // even though "vContSupported-" is set, gdb may still ask for it -> ignore to force e.g. `s` instead of `vCont;s:1;c` + if(vName == "vStopped")return ""; + if(vName == "vCtrlC") { + haltProgram(); + return "OK"; + } + + if(vName == "vKill") { + if(handshakeDone) { // sometimes this gets send during handshake (to reset the program?) -> ignore + requestDisconnect = true; + } + return "OK"; + } + + if(vName == "vCont") return "E00"; // if GDB completely ignores both "vCont is unsupported" responses, throw an error here + + } break; + + case 'Z': // insert breakpoint (e.g. "Z0,801a0ef4,4") + case 'z': // remove breakpoint (e.g. "z0,801a0ef4,4") + { + bool isInsert = cmdPrefix == 'Z'; + bool isHardware = cmdName(1) == '1'; // 0=software, 1=hardware + auto sepIdxMaybe = cmdName.findFrom(3, ","); + u32 sepIdx = sepIdxMaybe ? (sepIdxMaybe.get()+3) : 0; + + u64 address = cmdName.slice(3, sepIdx-1).hex(); + u64 addressStart = address; + u64 addressEnd = address + cmdName.slice(sepIdx+1).hex() - 1; + + if(hooks.normalizeAddress) { + addressStart = hooks.normalizeAddress(addressStart); + addressEnd = hooks.normalizeAddress(addressEnd); + } + Watchpoint wp{addressStart, addressEnd, address}; + + switch(cmdName(1)) { + case '0': // (hardware/software breakpoints are the same for us) + case '1': addOrRemoveEntry(breakpoints, address, isInsert); break; + + case '2': + wp.type = WatchpointType::WRITE; + addOrRemoveEntry(watchpointWrite, wp, isInsert); + break; + + case '3': + wp.type = WatchpointType::READ; + addOrRemoveEntry(watchpointRead, wp, isInsert); + break; + + case '4': + wp.type = WatchpointType::ACCESS; + addOrRemoveEntry(watchpointRead, wp, isInsert); + addOrRemoveEntry(watchpointWrite, wp, isInsert); + break; + default: return "E00"; + } + + if(hooks.emuCacheInvalidate) { // for re-compiler, otherwise breaks might be skipped + hooks.emuCacheInvalidate(address); + } + return "OK"; + } + } + + printf("Unknown-Command: %s (data: %s)\n", cmdName.data(), cmdBuffer.data()); + return ""; + } + + auto Server::onText(string_view text) -> void { + + if(cmdBuffer.size() == 0) { + cmdBuffer.reserve(text.size()); + } + + for(char c : text) + { + switch(c) + { + case '$': + insideCommand = true; + break; + + case '#': { // end of message + 2-char checksum after that + insideCommand = false; + + ++messageCount; + bool shouldReply = true; + auto cmdRes = processCommand(cmdBuffer, shouldReply); + if(shouldReply) { + sendPayload(cmdRes); + } else if(!noAckMode) { + sendText("+"); + } + + cmdBuffer = ""; + } break; + + case '+': break; // "OK" response -> ignore + + case '\x03': // CTRL+C (same as "vCtrlC" packet) -> force halt + if constexpr(GDB_LOG_MESSAGES) { + printf("GDB <: CTRL+C [0x03]\n"); + } + haltProgram(); + break; + + default: + if(insideCommand) { + cmdBuffer.append(c); + } + } + } + } + + auto Server::updateLoop() -> void { + if(!isStarted())return; + + if(requestDisconnect) { + requestDisconnect = false; + if(!noAckMode) { + sendText("+"); + } + disconnectClient(); + resumeProgram(); + return; + } + + // The following code manages the message processing which gets exchanged from the server thread. + // It was carefully build to balance latency, throughput and CPU usage to let the game still run at full speed + // while allowing for fast processing once the debugger is halted. + + u32 loopFrames = isHalted() ? 20 : 1; // "frames" to check (loops with sleep in-between) + u32 loopCount = isHalted() ? 500 : 100; // loops inside a frame, the more the less latency, but CPU usage goes up + u32 maxLoopResets = 10000; // how many times can a new message reset the counter (prevents infinite loops with misbehaving clients) + bool wasHalted = isHalted(); + + for(u32 frame=0; frame 0 && maxLoopResets > 0) { + i = loopCount; // reset loop here to keep a fast chain of messages going (reduces latency) + --maxLoopResets; + } + } + + if(wasHalted)usleep(1); + } + } + + auto Server::getStatusText(u32 port, bool useIPv4) -> string { + auto url = getURL(port, useIPv4); + string prefix = isHalted() ? "⬛" : "▶"; + + if(hasClient())return {prefix, " GDB connected ", url}; + if(isStarted())return {"GDB listening ", url}; + return {"GDB pending (", url, ")"}; + } + + auto Server::sendSignal(Signal code) -> void { + sendPayload({"S", hex(static_cast(code), 2)}); + } + + auto Server::sendSignal(Signal code, const string& reason) -> void { + sendPayload({"T", hex(static_cast(code), 2), reason}); + } + + auto Server::sendPayload(const string& payload) -> void { + string msg{noAckMode ? "$" : "+$", payload, '#', hex(gdbCalcChecksum(payload), 2, '0')}; + if constexpr(GDB_LOG_MESSAGES) { + printf("GDB >: %.*s\n", msg.size() > 100 ? 100 : msg.size(), msg.data()); + } + sendText(msg); + } + + auto Server::haltProgram() -> void { + forceHalt = true; + haltSignalSent = false; + } + + auto Server::resumeProgram() -> void { + pcOverride.reset(); + forceHalt = false; + haltSignalSent = false; + } + + auto Server::onConnect() -> void { + printf("GDB client connected\n"); + resetClientData(); + hasActiveClient = true; + } + + auto Server::onDisconnect() -> void { + printf("GDB client disconnected\n"); + hadHandshake = false; + resetClientData(); + } + + auto Server::reset() -> void { + hooks.read.reset(); + hooks.write.reset(); + hooks.normalizeAddress.reset(); + hooks.regReadGeneral.reset(); + hooks.regWriteGeneral.reset(); + hooks.regRead.reset(); + hooks.regWrite.reset(); + hooks.emuCacheInvalidate.reset(); + hooks.targetXML.reset(); + + resetClientData(); + } + + auto Server::resetClientData() -> void { + breakpoints.reset(); + breakpoints.reserve(DEF_BREAKPOINT_SIZE); + + watchpointRead.reset(); + watchpointRead.reserve(DEF_BREAKPOINT_SIZE); + + watchpointWrite.reset(); + watchpointWrite.reserve(DEF_BREAKPOINT_SIZE); + + pcOverride.reset(); + insideCommand = false; + cmdBuffer = ""; + haltSignalSent = false; + forceHalt = false; + singleStepActive = false; + nonStopMode = false; + noAckMode = false; + + currentThreadC = -1; + hasActiveClient = false; + handshakeDone = false; + requestDisconnect = false; + } + +}; diff --git a/waterbox/ares64/ares/nall/gdb/server.hpp b/waterbox/ares64/ares/nall/gdb/server.hpp new file mode 100644 index 00000000000..a7674293567 --- /dev/null +++ b/waterbox/ares64/ares/nall/gdb/server.hpp @@ -0,0 +1,131 @@ +#pragma once + +#include +#include + +namespace nall::GDB { + +enum class Signal : u8 { + HANGUP = 1, + INT = 2, + QUIT = 3, + ILLEGAL = 4, + TRAP = 5, + ABORT = 6, + SEGV = 11, +}; + +/** + * This implements a GDB server to handle remote debugging via a GDB client. + * It is both independent of ares itself and any specific system. + * Functionality is added by providing system-specific callbacks, as well as using the API inside a system. + * (See the Readme.md file for more information.) + * + * NOTE: + * Command handling and the overall logic was carefully designed to support as many IDEs and GDB versions as possible. + * Things can break very easily (and the official documentation may lie), so be very sure of any changes made here. + * If changes are necessary, please verify that the following gdb-versions / IDEs still work properly: + * + * GDB: + * - gdb-multiarch (the plain vanilla version exists in most package managers, supports a lot of arches) + * - mips64-ultra-elf-gdb (special MIPS build of gdb-multiarch, i do NOT recommend it, behaves strangely) + * - mingw-w64-x86_64-gdb (vanilla build for Windows/MSYS) + * + * IDEs/Tools: + * - GDB's CLI + * - VSCode + * - CLion (with bundled gdb-multiarch) + * + * For testing, please also check both linux and windows (WSL2). + * With WSL2, windows-ares is started from within WSL, while the debugger runs in linux. + * This can be easily tested with VSCode and it's debugger. + */ +class Server : public nall::TCPText::Server { + public: + + auto reset() -> void; + + struct { + // Memory + function read{}; + function write{}; + function normalizeAddress{}; + + // Registers + function regReadGeneral{}; + function regWriteGeneral{}; + function regRead{}; + function regWrite{}; + + // Emulator + function emuCacheInvalidate{}; + function targetXML{}; + + + } hooks{}; + + // Exception + auto reportSignal(Signal sig, u64 originPC) -> bool; + + // PC / Memory State Updates + auto reportPC(u64 pc) -> bool; + auto reportMemRead(u64 address, u32 size) -> void; + auto reportMemWrite(u64 address, u32 size) -> void; + + // Breakpoints / Watchpoints + auto isHalted() const { return forceHalt && haltSignalSent; } + auto hasBreakpoints() const { + return breakpoints || singleStepActive || watchpointRead || watchpointWrite; + } + + auto getPcOverride() const { return pcOverride; }; + + auto updateLoop() -> void; + auto getStatusText(u32 port, bool useIPv4) -> string; + + protected: + auto onText(string_view text) -> void override; + auto onConnect() -> void override; + auto onDisconnect() -> void override; + + private: + bool insideCommand{false}; + string cmdBuffer{""}; + + bool haltSignalSent{false}; // marks if a signal as been sent for new halts (force-halt and breakpoints) + bool forceHalt{false}; // forces a halt despite no breakpoints being hit + bool singleStepActive{false}; + + bool noAckMode{false}; // gets set if lldb prefers no acknowledgements + bool nonStopMode{false}; // (NOTE: Not working for now), gets set if gdb wants to switch over to async-messaging + bool handshakeDone{false}; // set to true after a few handshake commands, used to prevent exception-reporting until client is ready + bool requestDisconnect{false}; // set to true if the client decides it wants to disconnect + + bool hasActiveClient{false}; + u32 messageCount{0}; // message count per update loop + s32 currentThreadC{-1}; // selected thread for the next 'c' command + + u64 currentPC{0}; + maybe pcOverride{0}; // temporary override to handle edge-cases for exceptions/watchpoints + + // client-state: + vector breakpoints{}; + vector watchpointRead{}; + vector watchpointWrite{}; + + auto processCommand(const string& cmd, bool &shouldReply) -> string; + auto resetClientData() -> void; + + auto reportWatchpoint(const Watchpoint &wp, u64 address) -> void; + + auto sendPayload(const string& payload) -> void; + auto sendSignal(Signal code) -> void; + auto sendSignal(Signal code, const string& reason) -> void; + + auto haltProgram() -> void; + auto resumeProgram() -> void; +}; + +extern Server server; + +} diff --git a/waterbox/ares64/ares/nall/gdb/watchpoint.hpp b/waterbox/ares64/ares/nall/gdb/watchpoint.hpp new file mode 100644 index 00000000000..b60d32657dc --- /dev/null +++ b/waterbox/ares64/ares/nall/gdb/watchpoint.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include + +namespace nall::GDB { + + enum class WatchpointType : u32 { + WRITE, READ, ACCESS + }; + + struct Watchpoint { + u64 addressStart{0}; + u64 addressEnd{0}; + u64 addressStartOrg{0}; // un-normalized address, GDB needs this + WatchpointType type{}; + + auto operator==(const Watchpoint& w) const { + return addressStart == w.addressStart && addressEnd == w.addressEnd + && addressStartOrg == w.addressStartOrg && type == w.type; + } + + auto hasOverlap(u64 start, u64 end) const { + return (end >= addressStart) && (start <= addressEnd); + } + + auto getTypePrefix() const -> string { + if(type == WatchpointType::WRITE)return "watch:"; + if(type == WatchpointType::READ)return "rwatch:"; + return "awatch:"; + } + }; +} \ No newline at end of file diff --git a/waterbox/ares64/ares/nall/hid.hpp b/waterbox/ares64/ares/nall/hid.hpp index cc8e7f120d3..c2ce520ecd7 100644 --- a/waterbox/ares64/ares/nall/hid.hpp +++ b/waterbox/ares64/ares/nall/hid.hpp @@ -17,7 +17,7 @@ struct Input { private: string _name; s16 _value = 0; - friend class Group; + friend struct Group; }; struct Group : vector { @@ -36,7 +36,7 @@ struct Group : vector { private: string _name; - friend class Device; + friend struct Device; }; struct Device : vector { diff --git a/waterbox/ares64/ares/nall/image/multifactor.hpp b/waterbox/ares64/ares/nall/image/multifactor.hpp index be7722aa5e2..4c1b1d4e741 100644 --- a/waterbox/ares64/ares/nall/image/multifactor.hpp +++ b/waterbox/ares64/ares/nall/image/multifactor.hpp @@ -3,24 +3,24 @@ namespace nall { inline multiFactorImage::multiFactorImage(const multiFactorImage& source) { - (*this) = source; + operator=(source); } inline multiFactorImage::multiFactorImage(multiFactorImage&& source) { - operator=(std::forward(source)); + operator=(std::move(source)); } inline multiFactorImage::multiFactorImage(const image& lowDPI, const image& highDPI) { - (*(image*)this) = lowDPI; + image::operator=(lowDPI); _highDPI = highDPI; } inline multiFactorImage::multiFactorImage(const image& source) { - (*(image*)this) = source; + image::operator=(source); } inline multiFactorImage::multiFactorImage(image&& source) { - operator=(std::forward(source)); + image::operator=(std::move(source)); } inline multiFactorImage::multiFactorImage() { @@ -32,7 +32,7 @@ inline multiFactorImage::~multiFactorImage() { inline auto multiFactorImage::operator=(const multiFactorImage& source) -> multiFactorImage& { if(this == &source) return *this; - (*(image*)this) = source; + image::operator=(source); _highDPI = source._highDPI; return *this; @@ -41,15 +41,15 @@ inline auto multiFactorImage::operator=(const multiFactorImage& source) -> multi inline auto multiFactorImage::operator=(multiFactorImage&& source) -> multiFactorImage& { if(this == &source) return *this; - (*(image*)this) = source; - _highDPI = source._highDPI; + image::operator=(std::move(source)); + _highDPI = std::move(source._highDPI); return *this; } inline auto multiFactorImage::operator==(const multiFactorImage& source) const -> bool { - if((const image&)*this != (const image&)source) return false; - return _highDPI != source._highDPI; + if(image::operator!=(source)) return false; + return _highDPI == source._highDPI; } inline auto multiFactorImage::operator!=(const multiFactorImage& source) const -> bool { diff --git a/waterbox/ares64/ares/nall/intrinsics.hpp b/waterbox/ares64/ares/nall/intrinsics.hpp index c3aa3d48712..d00b54bc01a 100644 --- a/waterbox/ares64/ares/nall/intrinsics.hpp +++ b/waterbox/ares64/ares/nall/intrinsics.hpp @@ -25,7 +25,6 @@ namespace nall { static constexpr bool GCC = 0; static constexpr bool Microsoft = 0; }; - #pragma clang diagnostic error "-Wc++20-extensions" #pragma clang diagnostic error "-Wgnu-case-range" #pragma clang diagnostic error "-Wgnu-statement-expression" #pragma clang diagnostic error "-Wvla" @@ -64,6 +63,10 @@ namespace nall { static constexpr bool GCC = 0; static constexpr bool Microsoft = 1; }; + #pragma warning(disable:4146) //unary minus operator applied to unsigned type, result still unsigned + #pragma warning(disable:4244) //conversion from 'type1' to 'type2', possible loss of data + #pragma warning(disable:4804) //unsafe use of type 'bool' in operation + #pragma warning(disable:4805) //unsafe mix of type 'bool' and type 'type' in operation #pragma warning(disable:4996) //libc "deprecation" warnings #else #error "unable to detect compiler" @@ -188,6 +191,8 @@ namespace nall { static constexpr bool arm32 = 0; static constexpr bool ppc64 = 0; static constexpr bool ppc32 = 0; + static constexpr bool rv64 = 0; + static constexpr bool rv32 = 0; }; #elif defined(__amd64__) || defined(_M_AMD64) #define ARCHITECTURE_AMD64 @@ -201,6 +206,8 @@ namespace nall { static constexpr bool arm32 = 0; static constexpr bool ppc64 = 0; static constexpr bool ppc32 = 0; + static constexpr bool rv64 = 0; + static constexpr bool rv32 = 0; }; #elif defined(__aarch64__) || defined(_M_ARM64) #define ARCHITECTURE_ARM64 @@ -214,6 +221,8 @@ namespace nall { static constexpr bool arm32 = 0; static constexpr bool ppc64 = 0; static constexpr bool ppc32 = 0; + static constexpr bool rv64 = 0; + static constexpr bool rv32 = 0; }; #elif defined(__arm__) #define ARCHITECTURE_ARM32 @@ -224,6 +233,8 @@ namespace nall { static constexpr bool arm32 = 1; static constexpr bool ppc64 = 0; static constexpr bool ppc32 = 0; + static constexpr bool rv64 = 0; + static constexpr bool rv32 = 0; }; #elif defined(__ppc64__) || defined(_ARCH_PPC64) #define ARCHITECTURE_PPC64 @@ -234,6 +245,8 @@ namespace nall { static constexpr bool arm32 = 0; static constexpr bool ppc64 = 1; static constexpr bool ppc32 = 0; + static constexpr bool rv64 = 0; + static constexpr bool rv32 = 0; }; #elif defined(__ppc__) || defined(_ARCH_PPC) || defined(_M_PPC) #define ARCHITECTURE_PPC32 @@ -244,6 +257,32 @@ namespace nall { static constexpr bool arm32 = 0; static constexpr bool ppc64 = 0; static constexpr bool ppc32 = 1; + static constexpr bool rv64 = 0; + static constexpr bool rv32 = 0; + }; +#elif defined(__riscv) && __riscv_xlen == 64 + #define ARCHITECTURE_RV64 + struct Architecture { + static constexpr bool x86 = 0; + static constexpr bool amd64 = 0; + static constexpr bool arm64 = 0; + static constexpr bool arm32 = 0; + static constexpr bool ppc64 = 0; + static constexpr bool ppc32 = 0; + static constexpr bool rv64 = 1; + static constexpr bool rv32 = 0; + }; +#elif defined(__riscv) && __riscv_xlen == 32 + #define ARCHITECTURE_RV32 + struct Architecture { + static constexpr bool x86 = 0; + static constexpr bool amd64 = 0; + static constexpr bool arm64 = 0; + static constexpr bool arm32 = 0; + static constexpr bool ppc64 = 0; + static constexpr bool ppc32 = 0; + static constexpr bool rv64 = 0; + static constexpr bool rv32 = 1; }; #else #error "unable to detect architecture" diff --git a/waterbox/ares64/ares/nall/ips.hpp b/waterbox/ares64/ares/nall/ips.hpp new file mode 100644 index 00000000000..3bc480025ff --- /dev/null +++ b/waterbox/ares64/ares/nall/ips.hpp @@ -0,0 +1,63 @@ +#pragma once + +namespace nall::IPS { + +inline auto apply(array_view source, array_view patch, maybe result = {}) -> maybe> { + #define error(text) { if(result) *result = {"error: ", text}; return {}; } + #define success() { if(result) *result = ""; return target; } + + vector target; + for (u32 i : range(source.size())) { + target.append(source[i]); + } + + u32 patchOffset = 0; + auto read = [&]() -> u8 { + return patch[patchOffset++]; + }; + auto readOffset = [&]() -> u32 { + u32 result = read() << 16; + result |= read() << 8; + result |= read(); + return result; + }; + auto readLength = [&]() -> u32 { + u32 result = read() << 8; + result |= read(); + return result; + }; + auto write = [&](u32 index, u8 data) { + target[index] = data; + }; + + if(read() != 'P') error("IPS header invalid"); + if(read() != 'A') error("IPS header invalid"); + if(read() != 'T') error("IPS header invalid"); + if(read() != 'C') error("IPS header invalid"); + if(read() != 'H') error("IPS header invalid"); + + u32 patchSize = patch.size(); + while (patchOffset < patchSize - 3) { + u32 offset = readOffset(); + u32 length = readLength(); + + if(target.size() < offset + length) error("Invalid IPS patch file"); + + if (length == 0) { + length = readLength(); + u8 data = read(); + for(u32 i : range(length)) write(offset + i, data); + } else { + for (u32 i : range(length)) write(offset + i, read()); + } + } + + if(read() != 'E') error("IPS footer invalid"); + if(read() != 'O') error("IPS footer invalid"); + if(read() != 'F') error("IPS footer invalid"); + + success(); + #undef error + #undef success +} +} diff --git a/waterbox/ares64/ares/nall/main.cpp b/waterbox/ares64/ares/nall/main.cpp index 37b7a5ee30b..c11cf2ad088 100644 --- a/waterbox/ares64/ares/nall/main.cpp +++ b/waterbox/ares64/ares/nall/main.cpp @@ -1,6 +1,7 @@ #include #if defined(PLATFORM_WINDOWS) + #include #include #include #include diff --git a/waterbox/ares64/ares/nall/memory.cpp b/waterbox/ares64/ares/nall/memory.cpp index 8479cff96b6..831eb255680 100644 --- a/waterbox/ares64/ares/nall/memory.cpp +++ b/waterbox/ares64/ares/nall/memory.cpp @@ -29,18 +29,17 @@ NALL_HEADER_INLINE auto unmap(void* target, u32 size) -> void { #endif } -NALL_HEADER_INLINE auto protect(void* target, u32 size, bool executable) -> void { +NALL_HEADER_INLINE auto protect(void* target, u32 size, bool executable) -> bool { #if defined(API_WINDOWS) DWORD protect = executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; DWORD oldProtect; - VirtualProtect(target, size, protect, &oldProtect); + return VirtualProtect(target, size, protect, &oldProtect); #elif defined(API_POSIX) int prot = PROT_READ | PROT_WRITE; if(executable) { prot |= PROT_EXEC; } - int ret = mprotect(target, size, prot); - assert(ret == 0); + return !mprotect(target, size, prot); #endif } diff --git a/waterbox/ares64/ares/nall/memory.hpp b/waterbox/ares64/ares/nall/memory.hpp index c932702bae5..23c08b1c43c 100644 --- a/waterbox/ares64/ares/nall/memory.hpp +++ b/waterbox/ares64/ares/nall/memory.hpp @@ -34,7 +34,7 @@ namespace nall::memory { auto map(u32 size, bool executable) -> void*; auto unmap(void* target, u32 size) -> void; - auto protect(void* target, u32 size, bool executable) -> void; + auto protect(void* target, u32 size, bool executable) -> bool; auto jitprotect(bool executable) -> void; } @@ -195,16 +195,18 @@ template auto writem(void* target, T data) -> void { for(s32 n = size - 1; n >= 0; n--) *p++ = data >> n * 8; } -auto map(u32 size, bool executable) -> void*; - -auto unmap(void* target, u32 size) -> void; - -auto protect(void* target, u32 size, bool executable) -> void; - inline auto jitprotect(bool executable) -> void { #if defined(PLATFORM_MACOS) if(__builtin_available(macOS 11.0, *)) { - pthread_jit_write_protect_np(executable); + static thread_local s32 depth = 0; + if(!executable && depth++ == 0 + || executable && --depth == 0) { + pthread_jit_write_protect_np(executable); + } + #if defined(DEBUG) + struct unmatched_jitprotect {}; + if(depth < 0 || depth > 10) throw unmatched_jitprotect{}; + #endif } #endif } diff --git a/waterbox/ares64/ares/nall/nall.cpp b/waterbox/ares64/ares/nall/nall.cpp index 223dde853cc..890c9882e6d 100644 --- a/waterbox/ares64/ares/nall/nall.cpp +++ b/waterbox/ares64/ares/nall/nall.cpp @@ -10,7 +10,6 @@ #include #include #include -//#include #include #include #include @@ -18,6 +17,8 @@ #include #include #include +#include +#include //currently unused by ares //#include //#include diff --git a/waterbox/ares64/ares/nall/path.cpp b/waterbox/ares64/ares/nall/path.cpp index 02a12b9f30d..265cf9fe3a9 100644 --- a/waterbox/ares64/ares/nall/path.cpp +++ b/waterbox/ares64/ares/nall/path.cpp @@ -2,6 +2,8 @@ #if defined(PLATFORM_WINDOWS) #include +#elif defined(PLATFORM_MACOS) + #include #endif namespace nall::Path { @@ -14,12 +16,34 @@ NALL_HEADER_INLINE auto program() -> string { result.transform("\\", "/"); return Path::real(result); #else + #if defined(PLATFORM_MACOS) + if (CFBundleRef bundle = CFBundleGetMainBundle()) { + char path[PATH_MAX] = ""; + CFURLRef url = CFBundleCopyBundleURL(bundle); + CFURLGetFileSystemRepresentation(url, true, reinterpret_cast(path), sizeof(path)); + CFRelease(url); + return Path::real(path); + } + #endif Dl_info info; dladdr((void*)&program, &info); return Path::real(info.dli_fname); #endif } +NALL_HEADER_INLINE auto resources() -> string { + #if defined(PLATFORM_MACOS) + if (CFBundleRef bundle = CFBundleGetMainBundle()) { + char path[PATH_MAX] = ""; + CFURLRef url = CFBundleCopyBundleURL(bundle); + CFURLGetFileSystemRepresentation(url, true, reinterpret_cast(path), sizeof(path)); + CFRelease(url); + return string(path).append("/Contents/Resources/"); + } + #endif + return program(); +} + NALL_HEADER_INLINE auto root() -> string { #if defined(PLATFORM_WINDOWS) wchar_t path[PATH_MAX] = L""; diff --git a/waterbox/ares64/ares/nall/path.hpp b/waterbox/ares64/ares/nall/path.hpp index b9b602a68d1..62181100503 100644 --- a/waterbox/ares64/ares/nall/path.hpp +++ b/waterbox/ares64/ares/nall/path.hpp @@ -26,6 +26,10 @@ inline auto real(string_view name) -> string { auto program() -> string; +// program() +// ./ares.app/Contents/Resources/ +auto resources() -> string; + // / // c:/ auto root() -> string; diff --git a/waterbox/ares64/ares/nall/platform.hpp b/waterbox/ares64/ares/nall/platform.hpp index 5fabcb2aed6..a87eab5ced0 100644 --- a/waterbox/ares64/ares/nall/platform.hpp +++ b/waterbox/ares64/ares/nall/platform.hpp @@ -22,6 +22,7 @@ namespace Math { #include #include #include +#include #include #include diff --git a/waterbox/ares64/ares/nall/random.hpp b/waterbox/ares64/ares/nall/random.hpp index c8114ba285b..182707e91e1 100644 --- a/waterbox/ares64/ares/nall/random.hpp +++ b/waterbox/ares64/ares/nall/random.hpp @@ -57,7 +57,7 @@ struct LFSR : RNG { static const u64 crc64 = 0xc96c'5795'd787'0f42; u64 lfsr = crc64; - friend class RNG; + friend struct RNG; }; struct PCG : RNG { @@ -91,7 +91,7 @@ struct PCG : RNG { u64 state = 0; u64 increment = 0; - friend class RNG; + friend struct RNG; }; } @@ -121,7 +121,7 @@ struct XChaCha20 : RNG { Cipher::XChaCha20 context{0, 0}; u32 counter = 0; - friend class RNG; + friend struct RNG; }; } diff --git a/waterbox/ares64/ares/nall/recompiler/generic/encoder-calls.hpp b/waterbox/ares64/ares/nall/recompiler/generic/encoder-calls.hpp index cb7e935d08c..b4a1b0174ba 100644 --- a/waterbox/ares64/ares/nall/recompiler/generic/encoder-calls.hpp +++ b/waterbox/ares64/ares/nall/recompiler/generic/encoder-calls.hpp @@ -44,7 +44,7 @@ template alwaysinline auto call(auto (C::*function)(P...) -> R, C* object, P0 p0) { sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, imm64{object}.data); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, imm64{p0}.data); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, imm64(p0).data); sljit_s32 type = SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_W, 1) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_W, 2); if constexpr(!std::is_void_v) type |= SLJIT_ARG_RETURN(SLJIT_ARG_TYPE_W); @@ -54,8 +54,8 @@ template alwaysinline auto call(auto (C::*function)(P...) -> R, C* object, P0 p0, P1 p1) { sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, imm64{object}.data); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, imm64{p0}.data); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, imm64{p1}.data); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, imm64(p0).data); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, imm64(p1).data); sljit_s32 type = SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_W, 1) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_W, 2) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_W, 3); @@ -66,9 +66,9 @@ template alwaysinline auto call(auto (C::*function)(P...) -> R, C* object, P0 p0, P1 p1, P2 p2) { sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, imm64{object}.data); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, imm64{p0}.data); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, imm64{p1}.data); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, imm64{p2}.data); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, imm64(p0).data); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, imm64(p1).data); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, imm64(p2).data); sljit_s32 type = SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_W, 1) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_W, 2) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_W, 3) diff --git a/waterbox/ares64/ares/nall/recompiler/generic/generic.hpp b/waterbox/ares64/ares/nall/recompiler/generic/generic.hpp index 8872c460d25..dd102be37e1 100644 --- a/waterbox/ares64/ares/nall/recompiler/generic/generic.hpp +++ b/waterbox/ares64/ares/nall/recompiler/generic/generic.hpp @@ -3,7 +3,7 @@ #if defined(SLJIT) namespace nall::recompiler { struct generic { - static constexpr bool supported = Architecture::amd64 | Architecture::arm64 | Architecture::ppc64; + static constexpr bool supported = Architecture::amd64 | Architecture::arm64 | Architecture::ppc64 | Architecture::rv64; bump_allocator& allocator; sljit_compiler* compiler = nullptr; @@ -31,6 +31,7 @@ namespace nall::recompiler { auto endFunction() -> u8* { u8* code = (u8*)sljit_generate_code(compiler); + allocator.reserve(sljit_get_generated_code_size(compiler)); resetCompiler(); return code; } diff --git a/waterbox/ares64/ares/nall/serializer.hpp b/waterbox/ares64/ares/nall/serializer.hpp index 741753db1cf..229edf23d68 100644 --- a/waterbox/ares64/ares/nall/serializer.hpp +++ b/waterbox/ares64/ares/nall/serializer.hpp @@ -76,11 +76,10 @@ struct serializer { } template auto operator()(T& value) -> serializer& { - constexpr bool integral = is_integral_v || is_same_v; - static_assert(has_serialize_v || integral || is_floating_point_v); + static_assert(has_serialize_v || is_integral_v || is_floating_point_v); if constexpr(has_serialize_v) { value.serialize(*this); - } else if constexpr(integral) { + } else if constexpr(is_integral_v) { integer(value); } else if constexpr(is_floating_point_v) { real(value); diff --git a/waterbox/ares64/ares/nall/string/format.hpp b/waterbox/ares64/ares/nall/string/format.hpp index 8400811951a..5aeca7e1ee7 100644 --- a/waterbox/ares64/ares/nall/string/format.hpp +++ b/waterbox/ares64/ares/nall/string/format.hpp @@ -108,6 +108,12 @@ template inline auto hex(T value, long precision, char padchar) -> s return buffer; } +// ~3x faster than method above with larger payloads of single individual bytes +inline auto hexByte(char* out, u8 value) -> void { + out[0] = "0123456789ABCDEF"[value >> 4]; + out[1] = "0123456789ABCDEF"[value & 0xF]; +} + template inline auto octal(T value, long precision, char padchar) -> string { string buffer; buffer.resize(sizeof(T) * 3); diff --git a/waterbox/ares64/ares/nall/string/markup/node.hpp b/waterbox/ares64/ares/nall/string/markup/node.hpp index 2f1ad7bfedb..243b2a53b0e 100644 --- a/waterbox/ares64/ares/nall/string/markup/node.hpp +++ b/waterbox/ares64/ares/nall/string/markup/node.hpp @@ -40,7 +40,7 @@ struct ManagedNode { auto _lookup(const string& path) const -> Node; auto _create(const string& path) -> Node; - friend class Node; + friend struct Node; }; struct Node { diff --git a/waterbox/ares64/ares/nall/string/pascal.hpp b/waterbox/ares64/ares/nall/string/pascal.hpp index e2aca838ee3..59bdb0b0825 100644 --- a/waterbox/ares64/ares/nall/string/pascal.hpp +++ b/waterbox/ares64/ares/nall/string/pascal.hpp @@ -33,7 +33,7 @@ struct string_pascal { explicit operator bool() const { return _data; } operator const char*() const { return _data ? _data + sizeof(u32) : nullptr; } - operator string() const { return _data ? string{_data + sizeof(u32)} : ""; } + operator string() const { return _data ? string{_data + sizeof(u32)} : ""_s; } auto operator=(const string_pascal& source) -> type& { if(this == &source) return *this; diff --git a/waterbox/ares64/ares/nall/tcptext/tcp-socket.cpp b/waterbox/ares64/ares/nall/tcptext/tcp-socket.cpp new file mode 100644 index 00000000000..c13fe0f1068 --- /dev/null +++ b/waterbox/ares64/ares/nall/tcptext/tcp-socket.cpp @@ -0,0 +1,312 @@ +#include + +#include +#include +#include + +#if defined(PLATFORM_WINDOWS) + #include +#else + #include +#endif + +struct sockaddr_in; +struct sockaddr_in6; + +namespace { + constexpr bool TCP_LOG_MESSAGES = false; + + constexpr u32 TCP_BUFFER_SIZE = 1024 * 16; + constexpr u32 CLIENT_SLEEP_MS = 10; // ms to sleep while checking for new clients + constexpr u32 CYCLES_BEFORE_SLEEP = 100; // how often to do a send/receive check before a sleep + constexpr u32 RECEIVE_TIMEOUT_SEC = 1; // only important for latency of disconnecting clients, reads are blocming anyways + + // A few platform specific socket functions: + // (In general, windows+linux share the same names, yet they behave differenly) + auto socketSetBlockingMode(s32 socket, bool isBlocking) -> bool + { + if(socket < 0)return false; + #if defined(O_NONBLOCK) // Linux + auto oldFlags = fcntl(socket, F_GETFL, 0); + auto newFlags = isBlocking ? (oldFlags ^ O_NONBLOCK) : (oldFlags | O_NONBLOCK); + return fcntl(socket, F_SETFL, newFlags) == 0; + #elif defined(FIONBIO) // Windows + u_long state = isBlocking ? 0 : 1; + return ioctlsocket(socket, FIONBIO, &state) == NO_ERROR; + #endif + } + + auto socketShutdown(s32 socket) { + if(socket < 0)return; + #if defined(SD_BOTH) // Windows + ::shutdown(socket, SD_BOTH); + #elif defined(SHUT_RDWR) // Linux, Mac + ::shutdown(socket, SHUT_RDWR); + #endif + } + + auto socketClose(s32 socket) { + if(socket < 0)return; + #if defined(PLATFORM_WINDOWS) + ::closesocket(socket); + #else + ::close(socket); + #endif + } +} + +namespace nall::TCP { + +NALL_HEADER_INLINE auto Socket::getURL(u32 port, bool useIPv4) const -> string { + return {useIPv4 ? "127.0.0.1:" : "[::1]:", port}; +} + +NALL_HEADER_INLINE auto Socket::open(u32 port, bool useIPv4) -> bool { + stopServer = false; + + auto url = getURL(port, useIPv4); + printf("Opening TCP-server on %s\n", url.data()); + + auto threadServer = std::thread([this, port, useIPv4]() { + serverRunning = true; + + while (!stopServer) { + fdServer = socket(useIPv4 ? AF_INET : AF_INET6, SOCK_STREAM, 0); + if(fdServer < 0) + break; + + { + s32 valueOn = 1; + #if defined(SO_NOSIGPIPE) //BSD, OSX + setsockopt(fdServer, SOL_SOCKET, SO_NOSIGPIPE, &valueOn, sizeof(s32)); + #endif + + #if defined(SO_REUSEADDR) //BSD, Linux, OSX + setsockopt(fdServer, SOL_SOCKET, SO_REUSEADDR, &valueOn, sizeof(s32)); + #endif + + #if defined(SO_REUSEPORT) //BSD, OSX + setsockopt(fdServer, SOL_SOCKET, SO_REUSEPORT, &valueOn, sizeof(s32)); + #endif + + #if defined(TCP_NODELAY) + setsockopt(fdServer, IPPROTO_TCP, TCP_NODELAY, &valueOn, sizeof(s32)); + #endif + + if(!socketSetBlockingMode(fdServer, true)) { + print("TCP: failed to set to blocking mode!\n"); + } + + #if defined(SO_RCVTIMEO) + #if defined(PLATFORM_WINDOWS) + DWORD rcvTimeMs = 1000 * RECEIVE_TIMEOUT_SEC; + setsockopt(fdServer, SOL_SOCKET, SO_RCVTIMEO, &rcvTimeMs, sizeof(rcvTimeMs)); + #else + struct timeval rcvtimeo; + rcvtimeo.tv_sec = RECEIVE_TIMEOUT_SEC; + rcvtimeo.tv_usec = 0; + setsockopt(fdServer, SOL_SOCKET, SO_RCVTIMEO, &rcvtimeo, sizeof(rcvtimeo)); + #endif + #endif + } + + s32 bindRes; + if(useIPv4) { + sockaddr_in serverAddrV4{}; + serverAddrV4.sin_family = AF_INET; + serverAddrV4.sin_addr.s_addr = htonl(INADDR_ANY); + serverAddrV4.sin_port = htons(port); + + bindRes = ::bind(fdServer, (sockaddr*)&serverAddrV4, sizeof(serverAddrV4)) < 0; + } else { + sockaddr_in6 serverAddrV6{}; + serverAddrV6.sin6_family = AF_INET6; + serverAddrV6.sin6_addr = in6addr_loopback; + serverAddrV6.sin6_port = htons(port); + + bindRes = ::bind(fdServer, (sockaddr*)&serverAddrV6, sizeof(serverAddrV6)) < 0; + } + + if(bindRes < 0 || listen(fdServer, 1) < 0) { + printf("error binding socket on port %d! (%s)\n", port, strerror(errno)); + break; + } + + // scan for new connections + while(fdClient < 0) { + fdClient = ::accept(fdServer, nullptr, nullptr); + if(fdClient < 0) { + if(errno != EAGAIN) { + if(!stopServer) + printf("error accepting connection! (%s)\n", strerror(errno)); + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(CLIENT_SLEEP_MS)); + } + } + if (fdClient < 0) { + break; + } + + // close the server socket, we only want one client + socketClose(fdServer); + fdServer = -1; + + while (!stopServer && fdClient >= 0) { + // Kick client if we need to + if(wantKickClient) { + socketClose(fdClient); + fdClient = -1; + wantKickClient = false; + onDisconnect(); + break; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(CLIENT_SLEEP_MS)); + } + } + + printf("Stopping TCP-server...\n"); + + socketClose(fdClient); + fdClient = -1; + + wantKickClient = false; + + printf("TCP-server stopped\n"); + serverRunning = false; + }); + + auto threadSend = std::thread([this]() + { + vector localSendBuffer{}; + u32 cycles = 0; + + while(!stopServer) + { + if(fdClient < 0) { + std::this_thread::sleep_for(std::chrono::milliseconds(CLIENT_SLEEP_MS)); + continue; + } + + { // copy send-data to minimize lock time + std::lock_guard guard{sendBufferMutex}; + if(sendBuffer.size() > 0) { + localSendBuffer = sendBuffer; + sendBuffer.resize(0); + } + } + + // send data + if(localSendBuffer.size() > 0) { + auto bytesWritten = send(fdClient, localSendBuffer.data(), localSendBuffer.size(), 0); + if(bytesWritten < localSendBuffer.size()) { + printf("Error sending data! (%s)\n", strerror(errno)); + } + + if constexpr(TCP_LOG_MESSAGES) { + printf("%.4f | TCP >: [%" PRIu64 "]: %.*s\n", (f64)chrono::millisecond() / 1000.0, localSendBuffer.size(), localSendBuffer.size() > 100 ? 100 : (int)localSendBuffer.size(), (char*)localSendBuffer.data()); + } + + localSendBuffer.resize(0); + cycles = 0; // sending once has a good chance of sending more -> reset sleep timer + } + + if(cycles++ >= CYCLES_BEFORE_SLEEP) { + std::this_thread::sleep_for(std::chrono::microseconds(1)); + cycles = 0; + } + } + }); + + auto threadReceive = std::thread([this]() + { + u8 packet[TCP_BUFFER_SIZE]{0}; + + while(!stopServer) + { + if(fdClient < 0 || wantKickClient) { + std::this_thread::sleep_for(std::chrono::milliseconds(CLIENT_SLEEP_MS)); + continue; + } + + // receive data from connected clients + s32 length = recv(fdClient, packet, TCP_BUFFER_SIZE, MSG_NOSIGNAL); + if(length > 0) { + std::lock_guard guard{receiveBufferMutex}; + auto oldSize = receiveBuffer.size(); + receiveBuffer.resize(oldSize + length); + memcpy(receiveBuffer.data() + oldSize, packet, length); + + if constexpr(TCP_LOG_MESSAGES) { + printf("%.4f | TCP <: [%d]: %.*s ([%d]: %.*s)\n", (f64)chrono::millisecond() / 1000.0, length, length, (char*)receiveBuffer.data(), length, length, (char*)packet); + } + } else if(length == 0) { + disconnectClient(); + } else { + #if defined(PLATFORM_WINDOWS) + if (WSAGetLastError() != WSAETIMEDOUT) { + #else + if (errno != EAGAIN) { + #endif + printf("TCP server: error receiving data from client: %s\n", strerror(errno)); + disconnectClient(); + } + } + } + }); + + threadServer.detach(); + threadSend.detach(); + threadReceive.detach(); + + return true; +} + +NALL_HEADER_INLINE auto Socket::close(bool notifyHandler) -> void { + stopServer = true; + + // we have to forcefully shut it down here, since otherwise accept() would hang causing a UI crash + socketShutdown(fdServer); + socketClose(fdClient); + socketClose(fdServer); + fdServer = -1; + fdClient = -1; + + while(serverRunning) { + std::this_thread::sleep_for(std::chrono::milliseconds(250)); // wait for other threads to stop + } + + if(notifyHandler) { + onDisconnect(); // don't call this in destructor, it's virtual + } +} + +NALL_HEADER_INLINE auto Socket::update() -> void { + vector data{}; + + { // local copy, minimize lock time + std::lock_guard guard{receiveBufferMutex}; + if(receiveBuffer.size() > 0) { + data = receiveBuffer; + receiveBuffer.resize(0); + } + } + + if(data.size() > 0) { + onData(data); + } +} + +NALL_HEADER_INLINE auto Socket::disconnectClient() -> void { + wantKickClient = true; +} + +NALL_HEADER_INLINE auto Socket::sendData(const u8* data, u32 size) -> void { + std::lock_guard guard{sendBufferMutex}; + u32 oldSize = sendBuffer.size(); + sendBuffer.resize(oldSize + size); + memcpy(sendBuffer.data() + oldSize, data, size); +} + +} diff --git a/waterbox/ares64/ares/nall/tcptext/tcp-socket.hpp b/waterbox/ares64/ares/nall/tcptext/tcp-socket.hpp new file mode 100644 index 00000000000..7cabb2317b9 --- /dev/null +++ b/waterbox/ares64/ares/nall/tcptext/tcp-socket.hpp @@ -0,0 +1,65 @@ +#pragma once + +/** + * Opens a TCP server with callbacks to send and receive data. + * + * This spawns 3 new threads: + * threadServer: listens for new connections, kicks connections + * threadSend: sends data to the client + * threadReceive: receives data from the client + * + * Each contains it's own loop including sleeps to not use too much CPU. + * The exception is threadReceive which relies on the blocking recv() call (kernel wakes it up again). + * + * Incoming and outgoing data is synchronized using mutexes, + * and put into buffers that are shared with the main thread. + * Meaning, the thread that calls 'update()' with also be the one that gets 'onData()' calls. + * No additional synchronization is needed. + * + * NOTE: if you work on the loop/sleeps, make sure to test CPU usage and package-latency. + */ +namespace nall::TCP { + +class Socket { + public: + auto open(u32 port, bool useIPv4) -> bool; + auto close(bool notifyHandler = true) -> void; + + auto disconnectClient() -> void; + + auto isStarted() const -> bool { return serverRunning; } + auto hasClient() const -> bool { return fdClient >= 0; } + + auto getURL(u32 port, bool useIPv4) const -> string; + + ~Socket() { close(false); } + + protected: + auto update() -> void; + + auto sendData(const u8* data, u32 size) -> void; + virtual auto onData(const vector &data) -> void = 0; + + virtual auto onConnect() -> void = 0; + virtual auto onDisconnect() -> void = 0; + + private: + std::atomic stopServer{false}; // set to true to let the server-thread know to stop. + std::atomic serverRunning{false}; // signals the current state of the server-thread + std::atomic wantKickClient{false}; // set to true to let server know to disconnect the current client (if conn.) + + std::atomic fdServer{-1}; + std::atomic fdClient{-1}; + + vector receiveBuffer{}; + std::mutex receiveBufferMutex{}; + + vector sendBuffer{}; + std::mutex sendBufferMutex{}; +}; + +} + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/tcptext/tcptext-server.cpp b/waterbox/ares64/ares/nall/tcptext/tcptext-server.cpp new file mode 100644 index 00000000000..4d0581f9d6e --- /dev/null +++ b/waterbox/ares64/ares/nall/tcptext/tcptext-server.cpp @@ -0,0 +1,29 @@ +#include + +namespace nall::TCPText { + NALL_HEADER_INLINE auto Server::sendText(const string &text) -> void { + sendData((const u8*)text.data(), text.size()); + } + + NALL_HEADER_INLINE auto Server::onData(const vector &data) -> void { + string_view dataStr((const char*)data.data(), (u32)data.size()); + + if(!hadHandshake) { + hadHandshake = true; + + // This is a security check for browsers. + // Any website can request localhost via JS or HTML, while it can't see the result, + // GDB will receive the data and commands could be injected (true for all GDB-servers). + // Since all HTTP requests start with headers, we can simply block anything that doesn't start like a GDB client. + if(dataStr[0] != '+') { + printf("Non-GDB client detected (message: %s), disconnect client\n", dataStr.data()); + disconnectClient(); + return; + } + + onConnect(); + } + + onText(dataStr); + } +} diff --git a/waterbox/ares64/ares/nall/tcptext/tcptext-server.hpp b/waterbox/ares64/ares/nall/tcptext/tcptext-server.hpp new file mode 100644 index 00000000000..8299bcdea6c --- /dev/null +++ b/waterbox/ares64/ares/nall/tcptext/tcptext-server.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include + +/** + * Provides text-based TCP server on top of the Socket. + * This handles incoming messages and can send data back to the client. + */ +namespace nall::TCPText { + +class Server : public TCP::Socket { + public: + bool hadHandshake{false}; + + protected: + auto onData(const vector &data) -> void override; + + auto sendText(const string &text) -> void; + virtual auto onText(string_view text) -> void = 0; +}; + +} + +#if defined(NALL_HEADER_ONLY) + #include +#endif diff --git a/waterbox/ares64/ares/nall/thread.hpp b/waterbox/ares64/ares/nall/thread.hpp index a76896f9ac9..17714a1a664 100644 --- a/waterbox/ares64/ares/nall/thread.hpp +++ b/waterbox/ares64/ares/nall/thread.hpp @@ -13,8 +13,10 @@ namespace nall { using mutex = std::mutex; using recursive_mutex = std::recursive_mutex; + using condition_variable = std::condition_variable; template using lock_guard = std::lock_guard; template using atomic = std::atomic; + template using unique_lock = std::unique_lock; } #if defined(API_POSIX) diff --git a/waterbox/ares64/ares/nall/traits.hpp b/waterbox/ares64/ares/nall/traits.hpp index 5862b36bb7d..523ee5d22bc 100644 --- a/waterbox/ares64/ares/nall/traits.hpp +++ b/waterbox/ares64/ares/nall/traits.hpp @@ -24,16 +24,10 @@ namespace nall { using std::is_base_of; using std::is_base_of_v; using std::is_function; - using std::is_integral; - using std::is_integral_v; using std::is_pointer; using std::is_pointer_v; using std::is_same; using std::is_same_v; - using std::is_signed; - using std::is_signed_v; - using std::is_unsigned; - using std::is_unsigned_v; using std::nullptr_t; using std::remove_extent; using std::remove_extent_t; @@ -41,13 +35,22 @@ namespace nall { using std::remove_reference_t; using std::swap; using std::true_type; -} -namespace std { - #if defined(__SIZEOF_INT128__) - template<> struct is_integral : true_type {}; + //directly specializing std traits would result in undefined behavior + template struct is_integral : std::is_integral {}; + template struct is_signed : std::is_signed {}; + template struct is_unsigned : std::is_unsigned {}; + + template inline constexpr bool is_integral_v = is_integral::value; + template inline constexpr bool is_signed_v = is_signed ::value; + template inline constexpr bool is_unsigned_v = is_unsigned::value; + + //defined in arithmetic.hpp when unavailable as a builtin template<> struct is_integral : true_type {}; - template<> struct is_signed : true_type {}; template<> struct is_unsigned : true_type {}; + + #if defined(__SIZEOF_INT128__) + template<> struct is_integral : true_type {}; + template<> struct is_signed : true_type {}; #endif } diff --git a/waterbox/ares64/ares/nall/vector.hpp b/waterbox/ares64/ares/nall/vector.hpp index ed52da7a5dc..a8c129554e7 100644 --- a/waterbox/ares64/ares/nall/vector.hpp +++ b/waterbox/ares64/ares/nall/vector.hpp @@ -124,6 +124,7 @@ struct vector_base { auto find(const function& comparator) -> maybe; auto find(const T& value) const -> maybe; auto findSorted(const T& value) const -> maybe; + auto contains(const T& value) const -> bool; auto foreach(const function& callback) -> void; auto foreach(const function& callback) -> void; diff --git a/waterbox/ares64/ares/nall/vector/utility.hpp b/waterbox/ares64/ares/nall/vector/utility.hpp index 14f70f95998..670ff97392d 100644 --- a/waterbox/ares64/ares/nall/vector/utility.hpp +++ b/waterbox/ares64/ares/nall/vector/utility.hpp @@ -36,6 +36,13 @@ template auto vector::findSorted(const T& value) const -> maybe auto vector::contains(const T& value) const -> bool { + for(const auto &v : *this) { + if(v == value) return true; + } + return false; +} + template auto vector::foreach(const function& callback) -> void { for(u64 n : range(size())) callback(_pool[n]); } diff --git a/waterbox/ares64/ares/nall/vfs/cdrom.hpp b/waterbox/ares64/ares/nall/vfs/cdrom.hpp index f410a0b66be..d572891eb49 100644 --- a/waterbox/ares64/ares/nall/vfs/cdrom.hpp +++ b/waterbox/ares64/ares/nall/vfs/cdrom.hpp @@ -11,6 +11,10 @@ namespace nall::vfs { struct cdrom : file { + ~cdrom() { + _thread.join(); + } + static auto open(const string& location) -> shared_pointer { auto instance = shared_pointer{new cdrom}; if(location.iendsWith(".cue") && instance->loadCue(location)) return instance; @@ -19,8 +23,8 @@ struct cdrom : file { } auto writable() const -> bool override { return false; } - auto data() const -> const u8* override { return _image.data(); } - auto data() -> u8* override { return _image.data(); } + auto data() const -> const u8* override { wait(size()); return _image.data(); } + auto data() -> u8* override { wait(size()); return _image.data(); } auto size() const -> u64 override { return _image.size(); } auto offset() const -> u64 override { return _offset; } @@ -36,19 +40,33 @@ struct cdrom : file { auto read() -> u8 override { if(_offset >= _image.size()) return 0x00; + wait(_offset); return _image[_offset++]; } auto write(u8 data) -> void override { //CD-ROMs are read-only; but allow writing anyway if needed, since the image is in memory if(_offset >= _image.size()) return; + wait(_offset); _image[_offset++] = data; } + auto wait(u64 offset) const -> void { + bool force = false; + if(offset >= _image.size()) { + offset = _image.size() - 1; + force = true; + } + //subchannel data is always loaded + if(offset % 2448 < 2352 || force) { + while(offset + 1 > _loadOffset) usleep(1); + } + } + private: auto loadCue(const string& cueLocation) -> bool { - Decode::CUE cuesheet; - if(!cuesheet.load(cueLocation)) return false; + auto cuesheet = shared_pointer::create(); + if(!cuesheet->load(cueLocation)) return false; CD::Session session; session.leadIn.lba = -LeadInSectors; @@ -56,19 +74,19 @@ struct cdrom : file { s32 lbaFileBase = 0; // add 2 sec pregap to 1st track - if(!cuesheet.files[0].tracks[0].pregap) - cuesheet.files[0].tracks[0].pregap = Track1Pregap; + if(!cuesheet->files[0].tracks[0].pregap) + cuesheet->files[0].tracks[0].pregap = Track1Pregap; else - cuesheet.files[0].tracks[0].pregap = Track1Pregap + cuesheet.files[0].tracks[0].pregap(); + cuesheet->files[0].tracks[0].pregap = Track1Pregap + cuesheet->files[0].tracks[0].pregap(); - if(cuesheet.files[0].tracks[0].indices[0].number == 1) { + if(cuesheet->files[0].tracks[0].indices[0].number == 1) { session.tracks[1].indices[0].lba = 0; session.tracks[1].indices[0].end = - cuesheet.files[0].tracks[0].pregap() + cuesheet.files[0].tracks[0].indices[0].lba - 1; + cuesheet->files[0].tracks[0].pregap() + cuesheet->files[0].tracks[0].indices[0].lba - 1; } s32 lbaIndex = 0; - for(auto& file : cuesheet.files) { + for(auto& file : cuesheet->files) { for(auto& track : file.tracks) { session.tracks[track.number].control = track.type == "audio" ? 0b0000 : 0b0100; if(track.pregap) lbaFileBase += track.pregap(); @@ -117,8 +135,15 @@ struct cdrom : file { _image.resize(2448 * (LeadInSectors + lbaFileBase + LeadOutSectors)); - lbaFileBase = 0; - for(auto& file : cuesheet.files) { + //preload subchannel data + loadSub({Location::notsuffix(cueLocation), ".sub"}, session); + + //load user data on separate thread + _thread = thread::create( + [this, cueLocation, cuesheet = std::move(cuesheet)](uintptr) -> void { + + s32 lbaFileBase = 0; + for(auto& file : cuesheet->files) { auto location = string{Location::path(cueLocation), file.name}; auto filedata = nall::file::open(location, nall::file::mode::read); if(file.type == "wave") filedata.seek(44); //skip RIFF header @@ -127,7 +152,8 @@ struct cdrom : file { for(auto& index : track.indices) { if(index.lba < 0) continue; // ignore gaps (not in file) for(s32 sector : range(index.sectorCount())) { - auto target = _image.data() + 2448ull * (LeadInSectors + lbaFileBase + index.lba + sector); + auto offset = 2448ull * (LeadInSectors + lbaFileBase + index.lba + sector); + auto target = _image.data() + offset; auto length = track.sectorSize(); if(length == 2048) { //ISO: generate header + parity data @@ -145,39 +171,30 @@ struct cdrom : file { //BIN + WAV: direct copy filedata.read({target, length}); } + _loadOffset = offset + 2448; } } if(track.postgap) lbaFileBase += track.postgap(); } lbaFileBase += file.tracks.last().indices.last().end + 1; } + _loadOffset = _image.size(); - auto subchannel = session.encode(LeadInSectors + session.leadOut.end + 1); - if(auto overlay = nall::file::read({Location::notsuffix(cueLocation), ".sub"})) { - auto target = subchannel.data() + 96 * (LeadInSectors + Track1Pregap); - auto length = (s64)subchannel.size() - 96 * (LeadInSectors + Track1Pregap); - memory::copy(target, length, overlay.data(), overlay.size()); - } - - for(u64 sector : range(size() / 2448)) { - auto source = subchannel.data() + sector * 96; - auto target = _image.data() + sector * 2448 + 2352; - memory::copy(target, source, 96); - } + }); return true; } auto loadChd(const string& location) -> bool { - Decode::CHD chd; - if(!chd.load(location)) return false; + auto chd = shared_pointer::create(); + if(!chd->load(location)) return false; CD::Session session; session.leadIn.lba = -LeadInSectors; session.leadIn.end = -1; s32 lbaIndex = 0; - for(auto& track : chd.tracks) { + for(auto& track : chd->tracks) { session.tracks[track.number].control = track.type == "AUDIO" ? 0b0000 : 0b0100; for(auto& index : track.indices) { session.tracks[track.number].indices[index.number].lba = index.lba; @@ -209,12 +226,20 @@ struct cdrom : file { _image.resize(2448 * (LeadInSectors + lbaIndex + LeadOutSectors)); + //preload subchannel data + loadSub({Location::notsuffix(location), ".sub"}, session); + + //load user data on separate thread + _thread = thread::create( + [this, chd = std::move(chd)](uintptr) -> void { + s32 lba = 0; - for(auto& track : chd.tracks) { + for(auto& track : chd->tracks) { for(auto& index : track.indices) { for(s32 sector : range(index.sectorCount())) { - auto target = _image.data() + 2448ull * (LeadInSectors + index.lba + sector); - auto sectorData = chd.read(lba); + auto offset = 2448ull * (LeadInSectors + index.lba + sector); + auto target = _image.data() + offset; + auto sectorData = chd->read(lba); if(sectorData.size() == 2048) { //ISO: generate header + parity data memory::assign(target + 0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff); //sync @@ -230,12 +255,22 @@ struct cdrom : file { memory::copy(target, 2352, sectorData.data(), sectorData.size()); } lba++; + _loadOffset = offset + 2448; } } } + _loadOffset = _image.size(); + + }); + return true; + } + +private: + void loadSub(const string& location, const CD::Session& session) { auto subchannel = session.encode(LeadInSectors + session.leadOut.end + 1); - if(auto overlay = nall::file::read({Location::notsuffix(location), ".sub"})) { + + if(auto overlay = nall::file::read(location)) { auto target = subchannel.data() + 96 * (LeadInSectors + Track1Pregap); auto length = (s64)subchannel.size() - 96 * (LeadInSectors + Track1Pregap); memory::copy(target, length, overlay.data(), overlay.size()); @@ -246,12 +281,12 @@ struct cdrom : file { auto target = _image.data() + sector * 2448 + 2352; memory::copy(target, source, 96); } - - return true; } vector _image; u64 _offset = 0; + atomic _loadOffset = 0; + thread _thread; static constexpr s32 LeadInSectors = 7500; static constexpr s32 Track1Pregap = 150; diff --git a/waterbox/ares64/ares/thirdparty/sljit/.gitignore b/waterbox/ares64/ares/thirdparty/sljit/.gitignore deleted file mode 100644 index 83f5a0011ac..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -bin -taring diff --git a/waterbox/ares64/ares/thirdparty/sljit/API_CHANGES b/waterbox/ares64/ares/thirdparty/sljit/API_CHANGES index 8ec367e3025..6afa9750a6c 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/API_CHANGES +++ b/waterbox/ares64/ares/thirdparty/sljit/API_CHANGES @@ -1,5 +1,38 @@ This file is the short summary of the API changes: +21.02.2024 - Non-backward compatible + The sljit_set_put_label() function is renamed + to sljit_emit_mov_addr() and sljit_put_label + is merged into sljit_jump and removed. + +01.11.2023 - Non-backward compatible + The SLJIT_ARG_TYPE_VOID definition is changed + to SLJIT_ARG_TYPE_RET_VOID to improve Windows + compatibility. + +05.09.2023 - Non-backward compatible + Turn SLJIT_IMM from a flag to a single value. + +10.08.2023 - Non-backward compatible + Rename SLJIT_INT_REGISTER to SLJIT_GP_REGISTER. + +01.08.2023 - Non-backward compatible + A type argument is added to sljit_get_register_index + and sljit_get_float_register_index is removed. + +19.07.2023 - Non-backward compatible + SLJIT_MEM_UNALIGNED_16/32 options are renamed + to SLJIT_MEM_ALIGNED_16/32 and a type argument + is added to sljit_get_float_register_index. + +16.02.2022 - Non-backward compatible + The sljit_emit_cmov operation is replaced + by sljit_emit_select. + +11.02.2022 - Non-backward compatible + All floating point comparisons are supported, + sljit_cmp_info return value is changed. + 02.02.2022 - Backward compatible All SLJIT_SET_* constants are even numbers. diff --git a/waterbox/ares64/ares/thirdparty/sljit/Makefile b/waterbox/ares64/ares/thirdparty/sljit/Makefile deleted file mode 100644 index eb85af35b3c..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/Makefile +++ /dev/null @@ -1,99 +0,0 @@ -ifdef CROSS_COMPILER -CC = $(CROSS_COMPILER) -else -ifndef CC -# default compiler -CC = gcc -endif -endif - -ifndef EXTRA_CPPFLAGS -EXTRA_CPPFLAGS= -endif - -ifndef EXTRA_LDFLAGS -EXTRA_LDFLAGS= -endif - -CPPFLAGS = $(EXTRA_CPPFLAGS) -Isljit_src -CFLAGS += -O2 -Wall -Wextra -Wconversion -Wsign-compare -Werror -REGEX_CFLAGS += $(CFLAGS) -fshort-wchar -LDFLAGS = $(EXTRA_LDFLAGS) - -BINDIR = bin -SRCDIR = sljit_src -TESTDIR = test_src -REGEXDIR = regex_src -EXAMPLEDIR = doc/tutorial - -TARGET = $(BINDIR)/sljit_test $(BINDIR)/regex_test -EXAMPLE_TARGET = $(BINDIR)/func_call $(BINDIR)/first_program $(BINDIR)/branch $(BINDIR)/loop $(BINDIR)/array_access $(BINDIR)/func_call $(BINDIR)/struct_access $(BINDIR)/temp_var $(BINDIR)/brainfuck - -SLJIT_HEADERS = $(SRCDIR)/sljitLir.h $(SRCDIR)/sljitConfig.h $(SRCDIR)/sljitConfigInternal.h - -SLJIT_LIR_FILES = $(SRCDIR)/sljitLir.c $(SRCDIR)/sljitUtils.c \ - $(SRCDIR)/allocator_src/sljitExecAllocatorCore.c $(SRCDIR)/allocator_src/sljitExecAllocatorApple.c \ - $(SRCDIR)/allocator_src/sljitExecAllocatorPosix.c $(SRCDIR)/allocator_src/sljitExecAllocatorWindows.c \ - $(SRCDIR)/allocator_src/sljitProtExecAllocatorNetBSD.c $(SRCDIR)/allocator_src/sljitProtExecAllocatorPosix.c \ - $(SRCDIR)/allocator_src/sljitWXExecAllocatorPosix.c $(SRCDIR)/allocator_src/sljitWXExecAllocatorWindows.c \ - $(SRCDIR)/sljitNativeARM_32.c $(SRCDIR)/sljitNativeARM_T2_32.c $(SRCDIR)/sljitNativeARM_64.c \ - $(SRCDIR)/sljitNativeMIPS_common.c $(SRCDIR)/sljitNativeMIPS_32.c $(SRCDIR)/sljitNativeMIPS_64.c \ - $(SRCDIR)/sljitNativePPC_common.c $(SRCDIR)/sljitNativePPC_32.c $(SRCDIR)/sljitNativePPC_64.c \ - $(SRCDIR)/sljitNativeRISCV_common.c $(SRCDIR)/sljitNativeRISCV_32.c $(SRCDIR)/sljitNativeRISCV_64.c \ - $(SRCDIR)/sljitNativeS390X.c \ - $(SRCDIR)/sljitNativeX86_common.c $(SRCDIR)/sljitNativeX86_32.c $(SRCDIR)/sljitNativeX86_64.c - -.PHONY: all clean examples - -all: $(TARGET) - -clean: - -$(RM) $(BINDIR)/*.o $(BINDIR)/sljit_test $(BINDIR)/regex_test $(EXAMPLE_TARGET) - -$(BINDIR)/.keep : - mkdir -p $(BINDIR) - @touch $@ - -$(BINDIR)/sljitLir.o : $(BINDIR)/.keep $(SLJIT_LIR_FILES) $(SLJIT_HEADERS) - $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(SRCDIR)/sljitLir.c - -$(BINDIR)/sljitMain.o : $(TESTDIR)/sljitMain.c $(BINDIR)/.keep $(SLJIT_HEADERS) - $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(TESTDIR)/sljitMain.c - -$(BINDIR)/regexMain.o : $(REGEXDIR)/regexMain.c $(BINDIR)/.keep $(SLJIT_HEADERS) - $(CC) $(CPPFLAGS) $(REGEX_CFLAGS) -c -o $@ $(REGEXDIR)/regexMain.c - -$(BINDIR)/regexJIT.o : $(REGEXDIR)/regexJIT.c $(BINDIR)/.keep $(SLJIT_HEADERS) $(REGEXDIR)/regexJIT.h - $(CC) $(CPPFLAGS) $(REGEX_CFLAGS) -c -o $@ $(REGEXDIR)/regexJIT.c - -$(BINDIR)/sljit_test: $(BINDIR)/.keep $(BINDIR)/sljitMain.o $(TESTDIR)/sljitTest.c $(SRCDIR)/sljitLir.c $(SLJIT_LIR_FILES) $(SLJIT_HEADERS) $(TESTDIR)/sljitConfigPre.h $(TESTDIR)/sljitConfigPost.h - $(CC) $(CPPFLAGS) -DSLJIT_HAVE_CONFIG_PRE=1 -I$(TESTDIR) $(CFLAGS) $(LDFLAGS) $(BINDIR)/sljitMain.o $(TESTDIR)/sljitTest.c $(SRCDIR)/sljitLir.c -o $@ -lm -lpthread - -$(BINDIR)/regex_test: $(BINDIR)/.keep $(BINDIR)/regexMain.o $(BINDIR)/regexJIT.o $(BINDIR)/sljitLir.o - $(CC) $(CFLAGS) $(LDFLAGS) $(BINDIR)/regexMain.o $(BINDIR)/regexJIT.o $(BINDIR)/sljitLir.o -o $@ -lm -lpthread - -examples: $(EXAMPLE_TARGET) - -$(BINDIR)/first_program: $(EXAMPLEDIR)/first_program.c $(BINDIR)/.keep $(BINDIR)/sljitLir.o - $(CC) $(CPPFLAGS) $(LDFLAGS) $(EXAMPLEDIR)/first_program.c $(BINDIR)/sljitLir.o -o $@ -lm -lpthread - -$(BINDIR)/branch: $(EXAMPLEDIR)/branch.c $(BINDIR)/.keep $(BINDIR)/sljitLir.o - $(CC) $(CPPFLAGS) $(LDFLAGS) $(EXAMPLEDIR)/branch.c $(BINDIR)/sljitLir.o -o $@ -lm -lpthread - -$(BINDIR)/loop: $(EXAMPLEDIR)/loop.c $(BINDIR)/.keep $(BINDIR)/sljitLir.o - $(CC) $(CPPFLAGS) $(LDFLAGS) $(EXAMPLEDIR)/loop.c $(BINDIR)/sljitLir.o -o $@ -lm -lpthread - -$(BINDIR)/array_access: $(EXAMPLEDIR)/array_access.c $(BINDIR)/.keep $(BINDIR)/sljitLir.o - $(CC) $(CPPFLAGS) $(LDFLAGS) $(EXAMPLEDIR)/array_access.c $(BINDIR)/sljitLir.o -o $@ -lm -lpthread - -$(BINDIR)/func_call: $(EXAMPLEDIR)/func_call.c $(BINDIR)/.keep $(BINDIR)/sljitLir.o - $(CC) $(CPPFLAGS) $(LDFLAGS) $(EXAMPLEDIR)/func_call.c $(BINDIR)/sljitLir.o -o $@ -lm -lpthread - -$(BINDIR)/struct_access: $(EXAMPLEDIR)/struct_access.c $(BINDIR)/.keep $(BINDIR)/sljitLir.o - $(CC) $(CPPFLAGS) $(LDFLAGS) $(EXAMPLEDIR)/struct_access.c $(BINDIR)/sljitLir.o -o $@ -lm -lpthread - -$(BINDIR)/temp_var: $(EXAMPLEDIR)/temp_var.c $(BINDIR)/.keep $(BINDIR)/sljitLir.o - $(CC) $(CPPFLAGS) $(LDFLAGS) $(EXAMPLEDIR)/temp_var.c $(BINDIR)/sljitLir.o -o $@ -lm -lpthread - -$(BINDIR)/brainfuck: $(EXAMPLEDIR)/brainfuck.c $(BINDIR)/.keep $(BINDIR)/sljitLir.o - $(CC) $(CPPFLAGS) $(LDFLAGS) $(EXAMPLEDIR)/brainfuck.c $(BINDIR)/sljitLir.o -o $@ -lm -lpthread diff --git a/waterbox/ares64/ares/thirdparty/sljit/README b/waterbox/ares64/ares/thirdparty/sljit/README index 1fc2337e412..e45495cdc02 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/README +++ b/waterbox/ares64/ares/thirdparty/sljit/README @@ -2,18 +2,45 @@ SLJIT - Stack Less JIT Compiler Purpose: - A simple, machine independent JIT compiler, which suitable for - translating interpreted byte code to machine code. The sljitLir.h + A low-level, machine independent JIT compiler, which is suitable for + translating interpreted byte code into machine code. The sljitLir.h describes the LIR (low-level intermediate representation) of SLJIT. +Key features: + - Supports several target architectures: + x86 32/64, ARM 32/64, RiscV 32/64, s390x 64, + PowerPC 32/64, LoongArch 64, MIPS 32/64 + - Supports a large number of operations + - Supports self-modifying code + - Supports tail calls + - Support fast calls (non-ABI compatible) + - Supports byte order reverse (endianness switching) + - Supports unaligned memory accesses + - Supports SIMD / atomic operations on certain CPUs + - Direct register access, both integer and floating point + - Stack space allocated for function local variables can be + accessed as a linear memory area + - All-in-one compilation is supported + - When sljitLir.c is directly included by a C source file, + the jit compiler API can be completely hidden from + external use (see SLJIT_CONFIG_STATIC macro) + - Code can be generated for multiple target cpus + by including sljitLir.c in different C files, where + each compiler instance is configured to target a + different architecture + - The compiler can be serialized into a byte buffer + - Useful for ahead-of-time compiling + - Code generation can be resumed after deserialization + (partial ahead-of-time compiling) + Compatible: - Any C (C++) compiler. At least I hope so. + C99 (C++) compilers. Using sljit: Copy the content of sljit_src directory into your project source directory. Add sljitLir.c source file to your build environment. All other files are included by sljitLir.c (if required). Define the machine by SLJIT_CONFIG_* - selector. See sljitConfig.h for all possible values. For C++ compilers, + selector. See sljitConfigCPU.h for all possible values. For C++ compilers, rename sljitLir.c to sljitLir.cpp. More info: @@ -35,6 +62,7 @@ Special thanks: Marc Mutz Martin Storsjö Michael McConville + Mingtao Zhou (LoongArch support) Walter Lee Wen Xichang YunQiang Su diff --git a/waterbox/ares64/ares/thirdparty/sljit/doc/overview.txt b/waterbox/ares64/ares/thirdparty/sljit/doc/overview.txt deleted file mode 100644 index af74947954a..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/doc/overview.txt +++ /dev/null @@ -1,226 +0,0 @@ -The following text is a brief overview of those key -principles which are useful to know when generating code -with SLJIT. Further details can be found in sljitLir.h. - ----------------------------------------------------------------- - What is SLJIT? ----------------------------------------------------------------- - -SLJIT is a platform independent assembler which - - provides access to common CPU features - - can be easily ported to wide-spread CPU - architectures (e.g. x86, ARM, POWER, MIPS, SPARC, s390x) - -The key challenge of this project is finding a common -subset of CPU features which - - covers traditional assembly level programming - - can be translated to machine code efficiently - -This aim is achieved by selecting those instructions / CPU -features which are either available on all platforms or -simulating them has a low performance overhead. - -For example, some SLJIT instructions support base register -pre-update when [base+offs] memory accessing mode is used. -Although this feature is only available on ARM and POWER -CPUs, the simulation overhead is low on other CPUs. - ----------------------------------------------------------------- - The generic CPU model of SLJIT ----------------------------------------------------------------- - -The CPU has - - integer registers, which can store either an - int32_t (4 byte) or intptr_t (4 or 8 byte) value - - floating point registers, which can store either a - single (4 byte) or double (8 byte) precision value - - boolean status flags - -*** Integer registers: - -The most important rule is: when a source operand of -an instruction is a register, the data type of the -register must match the data type expected by an -instruction. - -For example, the following code snippet -is a valid instruction sequence: - - sljit_emit_op1(compiler, SLJIT_MOV32, - SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), 0); - // An int32_t value is loaded into SLJIT_R0 - sljit_emit_op1(compiler, SLJIT_NOT32, - SLJIT_R0, 0, SLJIT_R0, 0); - // the int32_t value in SLJIT_R0 is bit inverted - // and the type of the result is still int32_t - -The next code snippet is not allowed: - - sljit_emit_op1(compiler, SLJIT_MOV, - SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), 0); - // An intptr_t value is loaded into SLJIT_R0 - sljit_emit_op1(compiler, SLJIT_NOT32, - SLJIT_R0, 0, SLJIT_R0, 0); - // The result of SLJIT_NOT instruction - // is undefined. Even crash is possible - // (e.g. on MIPS-64). - -However, it is always allowed to overwrite a -register regardless its previous value: - - sljit_emit_op1(compiler, SLJIT_MOV, - SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), 0); - // An intptr_t value is loaded into SLJIT_R0 - sljit_emit_op1(compiler, SLJIT_MOV32, - SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R2), 0); - // From now on SLJIT_R0 contains an int32_t - // value. The previous value is discarded. - -Type conversion instructions are provided to convert an -int32_t value to an intptr_t value and vice versa. In -certain architectures these conversions are nops (no -instructions are emitted). - -Memory accessing: - -Registers arguments of SLJIT_MEM1 / SLJIT_MEM2 addressing -modes must contain intptr_t data. - -Signed / unsigned values: - -Most operations are executed in the same way regardless -the value is signed or unsigned. These operations have -only one instruction form (e.g. SLJIT_ADD / SLJIT_MUL). -Instructions where the result depends on the sign have -two forms (e.g. integer division, long multiply). - -*** Floating point registers - -Floating point registers can either contain a single -or double precision value. Similar to integer registers, -the data type of the value stored in a source register -must match the data type expected by the instruction. -Otherwise the result is undefined (even crash is possible). - -Rounding: - -Similar to standard C, floating point computation -results are rounded toward zero. - -*** Boolean status flags: - -Conditional branches usually depend on the value -of CPU status flags. These status flags are boolean -values and can be set by certain instructions. - -To achive maximum efficiency and portability, the -following rules were introduced: - - Most instructions can freely modify these status - flags except if SLJIT_KEEP_FLAGS is passed. - - The SLJIT_KEEP_FLAGS option may have a performance - overhead, so it should only be used when necessary. - - The SLJIT_SET_E, SLJIT_SET_U, etc. options can - force an instruction to correctly set the - specified status flags. However, all other - status flags are undefined. This rule must - always be kept in mind! - - Status flags cannot be controlled directly - (there are no set/clear/invert operations) - -The last two rules allows efficent mapping of status flags. -For example the arithmetic and multiply overflow flag is -mapped to the same overflow flag bit on x86. This is allowed, -since no instruction can set both of these flags. When -either of them is set by an instruction, the other can -have any value (this satisfies the "all other flags are -undefined" rule). Therefore mapping two SLJIT flags to the -same CPU flag is possible. Even though SLJIT supports -a dozen status flags, they can be efficiently mapped -to CPUs with only 4 status flags (e.g. ARM or SPARC). - ----------------------------------------------------------------- - Complex instructions ----------------------------------------------------------------- - -We noticed, that introducing complex instructions for common -tasks can improve performance. For example, compare and -branch instruction sequences can be optimized if certain -conditions apply, but these conditions depend on the target -CPU. SLJIT can do these optimizations, but it needs to -understand the "purpose" of the generated code. Static -instruction analysis has a large performance overhead -however, so we choose another approach: we introduced -complex instruction forms for certain non-atomic tasks. -SLJIT can optimize these "instructions" more efficiently -since the "purpose" is known to the compiler. These complex -instruction forms can often be assembled from other SLJIT -instructions, but we recommended to use them since the -compiler can optimize them on certain CPUs. - ----------------------------------------------------------------- - Generating functions ----------------------------------------------------------------- - -SLJIT is often used for generating function bodies which are -called from C. SLJIT provides two complex instructions for -generating function entry and return: sljit_emit_enter and -sljit_emit_return. The sljit_emit_enter also initializes the -"compiling context" which specify the current register mapping, -local space size, etc. configurations. The sljit_set_context -can also set this context without emitting any machine -instructions. - -This context is important since it affects the compiler, so -the first instruction after a compiler is created must be -either sljit_emit_enter or sljit_set_context. The context can -be changed by calling sljit_emit_enter or sljit_set_context -again. - ----------------------------------------------------------------- - All-in-one building ----------------------------------------------------------------- - -Instead of using a separate library, the whole SLJIT -compiler infrastructure can be directly included: - -#define SLJIT_CONFIG_STATIC 1 -#include "sljitLir.c" - -This approach is useful for single file compilers. - -Advantages: - - Everything provided by SLJIT is available - (no need to include anything else). - - Configuring SLJIT is easy - (e.g. redefining SLJIT_MALLOC / SLJIT_FREE). - - The SLJIT compiler API is hidden from the - world which improves securtity. - - The C compiler can optimize the SLJIT code - generator (e.g. removing unused functions). - ----------------------------------------------------------------- - Types and macros ----------------------------------------------------------------- - -The sljitConfig.h contains those defines, which controls -the compiler. The beginning of sljitConfigInternal.h -lists architecture specific types and macros provided -by SLJIT. Some of these macros: - -SLJIT_DEBUG : enabled by default - Enables assertions. Should be disabled in release mode. - -SLJIT_VERBOSE : enabled by default - When this macro is enabled, the sljit_compiler_verbose - function can be used to dump SLJIT instructions. - Otherwise this function is not available. Should be - disabled in release mode. - -SLJIT_SINGLE_THREADED : disabled by default - Single threaded programs can define this flag which - eliminates the pthread dependency. - -sljit_sw, sljit_uw, etc. : - It is recommended to use these types instead of long, - intptr_t, etc. Improves readability / portability of - the code. diff --git a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/99bottles.bf b/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/99bottles.bf deleted file mode 100644 index 4a4a46a0d89..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/99bottles.bf +++ /dev/null @@ -1,247 +0,0 @@ -########################## -### -### Severely updated version! -### (now says "1 bottle" and -### contains no extra "0" verse) -### -########################## -### 99 Bottles of Beer ### -### coded in Brainfuck ### -### with explanations ### -########################## -# -# This Bottles of Beer program -# was written by Andrew Paczkowski -# Coder Alias: thepacz -# three_halves_plus_one@yahoo.com -##### - -> 0 in the zeroth cell -+++++++>++++++++++[<+++++>-] 57 in the first cell or "9" -+++++++>++++++++++[<+++++>-] 57 in second cell or "9" -++++++++++ 10 in third cell ->+++++++++ 9 in fourth cell - -########################################## -### create ASCII chars in higher cells ### -########################################## - ->>++++++++[<++++>-] " " ->++++++++++++++[<+++++++>-] b -+>+++++++++++[<++++++++++>-] o -++>+++++++++++++++++++[<++++++>-] t -++>+++++++++++++++++++[<++++++>-] t ->++++++++++++[<+++++++++>-] l -+>++++++++++[<++++++++++>-] e -+>+++++++++++++++++++[<++++++>-] s ->++++++++[<++++>-] " " -+>+++++++++++[<++++++++++>-] o -++>++++++++++[<++++++++++>-] f ->++++++++[<++++>-] " " ->++++++++++++++[<+++++++>-] b -+>++++++++++[<++++++++++>-] e -+>++++++++++[<++++++++++>-] e ->+++++++++++++++++++[<++++++>-] r ->++++++++[<++++>-] " " -+>+++++++++++[<++++++++++>-] o ->+++++++++++[<++++++++++>-] n ->++++++++[<++++>-] " " -++>+++++++++++++++++++[<++++++>-] t -++++>++++++++++[<++++++++++>-] h -+>++++++++++[<++++++++++>-] e ->++++++++[<++++>-] " " -++>+++++++++++++[<+++++++++>-] w -+>++++++++++++[<++++++++>-] a ->++++++++++++[<+++++++++>-] l ->++++++++++++[<+++++++++>-] l ->+++++[<++>-] LF -++>+++++++++++++++++++[<++++++>-] t -+>++++++++++++[<++++++++>-] a -+++>+++++++++++++[<++++++++>-] k -+>++++++++++[<++++++++++>-] e ->++++++++[<++++>-] " " -+>+++++++++++[<++++++++++>-] o ->+++++++++++[<++++++++++>-] n -+>++++++++++[<++++++++++>-] e ->++++++++[<++++>-] " " ->++++++++++[<++++++++++>-] d -+>+++++++++++[<++++++++++>-] o -++>+++++++++++++[<+++++++++>-] w ->+++++++++++[<++++++++++>-] n ->++++++++[<++++>-] " " -+>++++++++++++[<++++++++>-] a ->+++++++++++[<++++++++++>-] n ->++++++++++[<++++++++++>-] d ->++++++++[<++++>-] " " -++>+++++++++++[<++++++++++>-] p -+>++++++++++++[<++++++++>-] a -+>+++++++++++++++++++[<++++++>-] s -+>+++++++++++++++++++[<++++++>-] s ->++++++++[<++++>-] " " -+>+++++++++++++[<++++++++>-] i -++>+++++++++++++++++++[<++++++>-] t ->++++++++[<++++>-] " " -+>++++++++++++[<++++++++>-] a ->+++++++++++++++++++[<++++++>-] r -+>+++++++++++[<++++++++++>-] o ->+++++++++++++[<+++++++++>-] u ->+++++++++++[<++++++++++>-] n ->++++++++++[<++++++++++>-] d ->+++++[<++>-] LF -+++++++++++++ CR - -[<]>>>> go back to fourth cell - -################################# -### initiate the display loop ### -################################# - -[ loop - < back to cell 3 - [ loop - [>]<< go to last cell and back to LF - .. output 2 newlines - [<]> go to first cell - - ################################### - #### begin display of characters### - ################################### - # - #.>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> - #X X b o t t l e s o f b e e r - #.>.>.>.>.>.>.>.>.>.>.>. - #o n t h e w a l l N - #[<]> go to first cell - #.>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>>>>>>>>>>>>>.> - #X X b o t t l e s o f b e e r N - #.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> - #t a k e o n e d o w n a n d p a s s - #.>.>.>.>.>.>.>.>.>. - #i t a r o u n d N - ##### - - [<]>> go to cell 2 - - subtract 1 from cell 2 - < go to cell 1 - - ######################## - ### display last line ## - ######################## - # - #.>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> - #X X b o t t l e s o f b e e r - #.>.>.>.>.>.>.>.>.>.>. - #o n t h e w a l l - ##### - - [<]>>>- go to cell 3/subtract 1 - ] end loop when cell 3 is 0 - ++++++++++ add 10 to cell 3 - <++++++++++ back to cell 2/add 10 - <- back to cell 1/subtract 1 - [>]<. go to last line/carriage return - [<]> go to first line - -######################## -### correct last line ## -######################## -# -#.>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> -#X X b o t t l e s o f b e e r -#.>.>.>.>.>.>.>.>.>.>. -#o n t h e w a l l -##### - - [<]>>>>- go to cell 4/subtract 1 -] end loop when cell 4 is 0 - -############################################################## -### By this point verses 9910 are displayed but to work ### -### with the lower numbered verses in a more readable way ### -### we initiate a new loop for verses 9{CODE} that will not ### -### use the fourth cell at all ### -############################################################## - -+ add 1 to cell four (to keep it nonzero) -<-- back to cell 3/subtract 2 - -[ loop - [>]<< go to last cell and back to LF - .. output 2 newlines - [<]> go to first cell - - ################################### - #### begin display of characters### - ################################### - # - #>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> - # X b o t t l e s o f b e e r - #.>.>.>.>.>.>.>.>.>.>.>. - #o n t h e w a l l N - #[<]> go to first cell - #>.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>>>>>>>>>>>>>.> - # X b o t t l e s o f b e e r N - #.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> - #t a k e o n e d o w n a n d p a s s - #.>.>.>.>.>.>.>.>.>. - #i t a r o u n d N - ##### - - [<]>> go to cell 2 - - subtract 1 from cell 2 - - ######################## - ### display last line ## - ######################## - # - #.>>>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> - #X b o t t l e s o f b e e r - #.>.>.>.>.>.>.>.>.>.>. - #o n t h e w a l l - ##### - - [<]>>>- go to cell 3/subtract 1 -] end loop when cell 3 is 0 -+ add 1 to cell 3 to keep it nonzero - -[>]<. go to last line/carriage return -[<]> go to first line - -######################## -### correct last line ## -######################## -# -#>.>>>.>.>.>.>.>.>.>>.>.>.>.>.>.>.>.>.> -# X b o t t l e o f b e e r -#.>.>.>.>.>.>.>.>.>.>.<<<<. -#o n t h e w a l l -##### - -[>]<< go to last cell and back to LF -.. output 2 newlines -[<]> go to first line - -######################### -### the final verse ## -######################### -# -#>.>>>.>.>.>.>.>.>.>>.>.>.>.>.>.>.>.>.> -# X b o t t l e o f b e e r -#.>.>.>.>.>.>.>.>.>.>.>. -#o n t h e w a l l N -#[<]> go to first cell -#>.>>>.>.>.>.>.>.>.>>.>.>.>.>.>.>.>.>>>>>>>>>>>>>.> -# X b o t t l e o f b e e r N -#.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> -#t a k e o n e d o w n a n d p a s s -#.>.>.>.>.>.>.>.>.>. -#i t a r o u n d N -#[>]< go to last line -#<<<.<<.<<<. -# n o -#[<]>>>> go to fourth cell -#>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.> -# b o t t l e s o f b e e r -#.>.>.>.>.>.>.>.>.>.>.>. -#o n t h e w a l l N -#####fin## \ No newline at end of file diff --git a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/README b/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/README deleted file mode 100644 index 1279694a2ed..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/README +++ /dev/null @@ -1,3 +0,0 @@ -These files were contributed by Wen Xichang. - -Copyright 2015 Wen Xichang (wenxichang@163.com). All rights reserved. diff --git a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/array_access.c b/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/array_access.c deleted file mode 100644 index 1404cf936ca..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/array_access.c +++ /dev/null @@ -1,71 +0,0 @@ -#include "sljitLir.h" - -#include -#include - -typedef long (SLJIT_FUNC *func_arr_t)(long *arr, long narr); - -static long SLJIT_FUNC print_num(long a) -{ - printf("num = %ld\n", a); - return a + 1; -} - -/* - This example, we generate a function like this: - -long func(long *array, long narray) -{ - long i; - for (i = 0; i < narray; ++i) - print_num(array[i]); - return narray; -} - -*/ - -static int array_access(long *arr, long narr) -{ - void *code; - unsigned long len; - func_arr_t func; - - /* Create a SLJIT compiler */ - struct sljit_compiler *C = sljit_create_compiler(NULL, NULL); - - sljit_emit_enter(C, 0, SLJIT_ARGS2(W, P, W), 1, 3, 0, 0, 0); - /* opt arg R S FR FS local_size */ - sljit_emit_op2(C, SLJIT_XOR, SLJIT_S2, 0, SLJIT_S2, 0, SLJIT_S2, 0); // S2 = 0 - sljit_emit_op1(C, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, narr); // S1 = narr - struct sljit_label *loopstart = sljit_emit_label(C); // loopstart: - struct sljit_jump *out = sljit_emit_cmp(C, SLJIT_GREATER_EQUAL, SLJIT_S2, 0, SLJIT_S1, 0); // S2 >= a --> jump out - - sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_S2), SLJIT_WORD_SHIFT);// R0 = (long *)S0[S2]; - sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num)); // print_num(R0); - - sljit_emit_op2(C, SLJIT_ADD, SLJIT_S2, 0, SLJIT_S2, 0, SLJIT_IMM, 1); // S2 += 1 - sljit_set_label(sljit_emit_jump(C, SLJIT_JUMP), loopstart); // jump loopstart - sljit_set_label(out, sljit_emit_label(C)); // out: - sljit_emit_return(C, SLJIT_MOV, SLJIT_S1, 0); // return RET - - /* Generate machine code */ - code = sljit_generate_code(C); - len = sljit_get_generated_code_size(C); - - /* Execute code */ - func = (func_arr_t)code; - printf("func return %ld\n", func(arr, narr)); - - /* dump_code(code, len); */ - - /* Clean up */ - sljit_free_compiler(C); - sljit_free_code(code, NULL); - return 0; -} - -int main() -{ - long arr[8] = { 3, -10, 4, 6, 8, 12, 2000, 0 }; - return array_access(arr, 8); -} diff --git a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/brainfuck.c b/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/brainfuck.c deleted file mode 100644 index 53a491dd0ec..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/brainfuck.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Brainfuck interpreter with SLJIT - * - * Copyright 2015 Wen Xichang (wenxichang@163.com). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "sljitLir.h" - -#include -#include - -#define BF_CELL_SIZE 3000 -#define BF_LOOP_LEVEL 256 - -static int readvalid(FILE *src) -{ - int chr; - - while ((chr = fgetc(src)) != EOF) { - switch (chr) { - case '+': - case '-': - case '>': - case '<': - case '.': - case ',': - case '[': - case ']': - return chr; - } - } - - return chr; -} - -/* reading same instruction, and count, for optimization */ -/* ++++ -> '+', 4 */ -static int gettoken(FILE *src, int *ntok) -{ - int chr = readvalid(src); - int chr2; - int cnt = 1; - - if (chr == EOF) - return EOF; - - if (chr == '.' || chr == ',' || chr == '[' || chr == ']') { - *ntok = 1; - return chr; - } - - while ((chr2 = readvalid(src)) == chr) - cnt++; - - if (chr2 != EOF) - ungetc(chr2, src); - - *ntok = cnt; - return chr; -} - -/* maintaining loop matched [] */ -struct loop_node_st { - struct sljit_label *loop_start; - struct sljit_jump *loop_end; -}; - -/* stack of loops */ -static struct loop_node_st loop_stack[BF_LOOP_LEVEL]; -static int loop_sp; - -static int loop_push(struct sljit_label *loop_start, struct sljit_jump *loop_end) -{ - if (loop_sp >= BF_LOOP_LEVEL) - return -1; - - loop_stack[loop_sp].loop_start = loop_start; - loop_stack[loop_sp].loop_end = loop_end; - loop_sp++; - return 0; -} - -static int loop_pop(struct sljit_label **loop_start, struct sljit_jump **loop_end) -{ - if (loop_sp <= 0) - return -1; - - loop_sp--; - *loop_start = loop_stack[loop_sp].loop_start; - *loop_end = loop_stack[loop_sp].loop_end; - return 0; -} - -static void *SLJIT_FUNC my_alloc(long size, long n) -{ - return calloc(size, n); -} - -static void SLJIT_FUNC my_putchar(long c) -{ - putchar(c); -} - -static long SLJIT_FUNC my_getchar(void) -{ - return getchar(); -} - -static void SLJIT_FUNC my_free(void *mem) -{ - free(mem); -} - -#define loop_empty() (loop_sp == 0) - -/* compile bf source to a void func() */ -static void *compile(FILE *src, unsigned long *lcode) -{ - void *code = NULL; - int chr; - int nchr; - - struct sljit_compiler *C = sljit_create_compiler(NULL, NULL); - struct sljit_jump *end; - struct sljit_label *loop_start; - struct sljit_jump *loop_end; - - int SP = SLJIT_S0; /* bf SP */ - int CELLS = SLJIT_S1; /* bf array */ - - sljit_emit_enter(C, 0, SLJIT_ARGS2(VOID, W, W), 2, 2, 0, 0, 0); /* opt arg R S FR FS local_size */ - - sljit_emit_op2(C, SLJIT_XOR, SP, 0, SP, 0, SP, 0); /* SP = 0 */ - - sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, BF_CELL_SIZE); - sljit_emit_op1(C, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1); - sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS2(P, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(my_alloc));/* calloc(BF_CELL_SIZE, 1) => R0 */ - - end = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0); /* R0 == 0 --> jump end */ - - sljit_emit_op1(C, SLJIT_MOV, CELLS, 0, SLJIT_R0, 0); /* CELLS = R0 */ - - while ((chr = gettoken(src, &nchr)) != EOF) { - switch (chr) { - case '+': - case '-': - sljit_emit_op1(C, SLJIT_MOV_U8, SLJIT_R0, 0, SLJIT_MEM2(CELLS, SP), 0); /* R0 = CELLS[SP] */ - sljit_emit_op2(C, chr == '+' ? SLJIT_ADD : SLJIT_SUB, - SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, nchr); /* R0 ?= nchr */ - sljit_emit_op1(C, SLJIT_MOV_U8, SLJIT_MEM2(CELLS, SP), 0, SLJIT_R0, 0); /* CELLS[SP] = R0 */ - break; - case '>': - case '<': - sljit_emit_op2(C, chr == '>' ? SLJIT_ADD : SLJIT_SUB, - SP, 0, SP, 0, SLJIT_IMM, nchr); /* SP ?= nchr */ - break; - case '.': - sljit_emit_op1(C, SLJIT_MOV_U8, SLJIT_R0, 0, SLJIT_MEM2(CELLS, SP), 0); /* R0 = CELLS[SP] */ - sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(my_putchar)); /* putchar(R0) */ - break; - case ',': - sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS0(W), SLJIT_IMM, SLJIT_FUNC_ADDR(my_getchar)); /* R0 = getchar() */ - sljit_emit_op1(C, SLJIT_MOV_U8, SLJIT_MEM2(CELLS, SP), 0, SLJIT_R0, 0); /* CELLS[SP] = R0 */ - break; - case '[': - loop_start = sljit_emit_label(C); /* loop_start: */ - sljit_emit_op1(C, SLJIT_MOV_U8, SLJIT_R0, 0, SLJIT_MEM2(CELLS, SP), 0); /* R0 = CELLS[SP] */ - loop_end = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0); /* IF R0 == 0 goto loop_end */ - - if (loop_push(loop_start, loop_end)) { - fprintf(stderr, "Too many loop level\n"); - goto compile_failed; - } - break; - case ']': - if (loop_pop(&loop_start, &loop_end)) { - fprintf(stderr, "Unmatch loop ]\n"); - goto compile_failed; - } - - sljit_set_label(sljit_emit_jump(C, SLJIT_JUMP), loop_start); /* goto loop_start */ - sljit_set_label(loop_end, sljit_emit_label(C)); /* loop_end: */ - break; - } - } - - if (!loop_empty()) { - fprintf(stderr, "Unmatch loop [\n"); - goto compile_failed; - } - - sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, CELLS, 0); - sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(P, P), SLJIT_IMM, SLJIT_FUNC_ADDR(my_free)); /* free(CELLS) */ - - sljit_set_label(end, sljit_emit_label(C)); - sljit_emit_return_void(C); - - code = sljit_generate_code(C); - if (lcode) - *lcode = sljit_get_generated_code_size(C); - -compile_failed: - sljit_free_compiler(C); - return code; -} - -/* function prototype of bf compiled code */ -typedef void (*bf_entry_t)(void); - -int main(int argc, char **argv) -{ - void *code; - bf_entry_t entry; - FILE *fp; - - if (argc < 2) { - fprintf(stderr, "Usage: %s \n", argv[0]); - return -1; - } - - fp = fopen(argv[1], "rb"); - if (!fp) { - perror("open"); - return -1; - } - - code = compile(fp, NULL); - fclose(fp); - - if (!code) { - fprintf(stderr, "[Fatal]: Compile failed\n"); - return -1; - } - - entry = (bf_entry_t)code; - entry(); - - sljit_free_code(code, NULL); - return 0; -} diff --git a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/branch.c b/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/branch.c deleted file mode 100644 index f36c64b4d60..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/branch.c +++ /dev/null @@ -1,77 +0,0 @@ -#include "sljitLir.h" - -#include -#include - -typedef long (SLJIT_FUNC *func3_t)(long a, long b, long c); - -/* - This example, we generate a function like this: - -long func(long a, long b, long c) -{ - if ((a & 1) == 0) - return c; - return b; -} - - */ -static int branch(long a, long b, long c) -{ - void *code; - unsigned long len; - func3_t func; - - struct sljit_jump *ret_c; - struct sljit_jump *out; - - /* Create a SLJIT compiler */ - struct sljit_compiler *C = sljit_create_compiler(NULL, NULL); - - /* 3 arg, 1 temp reg, 3 save reg */ - sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 1, 3, 0, 0, 0); - - /* R0 = a & 1, S0 is argument a */ - sljit_emit_op2(C, SLJIT_AND, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 1); - - /* if R0 == 0 then jump to ret_c, where is ret_c? we assign it later */ - ret_c = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0); - - /* R0 = b, S1 is argument b */ - sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_S1, 0); - - /* jump to out */ - out = sljit_emit_jump(C, SLJIT_JUMP); - - /* here is the 'ret_c' should jump, we emit a label and set it to ret_c */ - sljit_set_label(ret_c, sljit_emit_label(C)); - - /* R0 = c, S2 is argument c */ - sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_S2, 0); - - /* here is the 'out' should jump */ - sljit_set_label(out, sljit_emit_label(C)); - - /* end of function */ - sljit_emit_return(C, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - /* Generate machine code */ - code = sljit_generate_code(C); - len = sljit_get_generated_code_size(C); - - /* Execute code */ - func = (func3_t)code; - printf("func return %ld\n", func(a, b, c)); - - /* dump_code(code, len); */ - - /* Clean up */ - sljit_free_compiler(C); - sljit_free_code(code, NULL); - return 0; -} - -int main() -{ - return branch(4, 5, 6); -} diff --git a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/first_program.c b/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/first_program.c deleted file mode 100644 index 3fa685dd1df..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/first_program.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "sljitLir.h" - -#include -#include - -typedef long (SLJIT_FUNC *func3_t)(long a, long b, long c); - -static int add3(long a, long b, long c) -{ - void *code; - unsigned long len; - func3_t func; - - /* Create a SLJIT compiler */ - struct sljit_compiler *C = sljit_create_compiler(NULL, NULL); - - /* Start a context(function entry), have 3 arguments, discuss later */ - sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 1, 3, 0, 0, 0); - - /* The first arguments of function is register SLJIT_S0, 2nd, SLJIT_S1, etc. */ - /* R0 = first */ - sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0); - - /* R0 = R0 + second */ - sljit_emit_op2(C, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S1, 0); - - /* R0 = R0 + third */ - sljit_emit_op2(C, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S2, 0); - - /* This statement mov R0 to RETURN REG and return */ - /* in fact, R0 is RETURN REG itself */ - sljit_emit_return(C, SLJIT_MOV, SLJIT_R0, 0); - - /* Generate machine code */ - code = sljit_generate_code(C); - len = sljit_get_generated_code_size(C); - - /* Execute code */ - func = (func3_t)code; - printf("func return %ld\n", func(a, b, c)); - - /* dump_code(code, len); */ - - /* Clean up */ - sljit_free_compiler(C); - sljit_free_code(code, NULL); - return 0; -} - -int main() -{ - return add3(4, 5, 6); -} diff --git a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/func_call.c b/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/func_call.c deleted file mode 100644 index 4a15f048d19..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/func_call.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "sljitLir.h" - -#include -#include - -typedef long (SLJIT_FUNC *func3_t)(long a, long b, long c); - -static long SLJIT_FUNC print_num(long a) -{ - printf("a = %ld\n", a); - return a + 1; -} - -/* - This example, we generate a function like this: - -long func(long a, long b, long c) -{ - if ((a & 1) == 0) - return print_num(c); - return print_num(b); -} -*/ - -static int func_call(long a, long b, long c) -{ - void *code; - unsigned long len; - func3_t func; - - struct sljit_jump *out; - struct sljit_jump *print_c; - - /* Create a SLJIT compiler */ - struct sljit_compiler *C = sljit_create_compiler(NULL, NULL); - - sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 3, 3, 0, 0, 0); - - /* a & 1 --> R0 */ - sljit_emit_op2(C, SLJIT_AND, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 1); - /* R0 == 0 --> jump print_c */ - print_c = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0); - - /* R0 = S1; print_num(R0) */ - sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S1, 0); - sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num)); - - /* jump out */ - out = sljit_emit_jump(C, SLJIT_JUMP); - /* print_c: */ - sljit_set_label(print_c, sljit_emit_label(C)); - - /* R0 = c; print_num(R0); */ - sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S2, 0); - sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num)); - - /* out: */ - sljit_set_label(out, sljit_emit_label(C)); - sljit_emit_return(C, SLJIT_MOV, SLJIT_R0, 0); - - /* Generate machine code */ - code = sljit_generate_code(C); - len = sljit_get_generated_code_size(C); - - /* Execute code */ - func = (func3_t)code; - printf("func return %ld\n", func(a, b, c)); - - /* dump_code(code, len); */ - - /* Clean up */ - sljit_free_compiler(C); - sljit_free_code(code, NULL); - return 0; -} - -int main() -{ - return func_call(4, 5, 6); -} diff --git a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/hello.bf b/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/hello.bf deleted file mode 100644 index 3c87e66675f..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/hello.bf +++ /dev/null @@ -1,21 +0,0 @@ -+++++ +++++ initialize counter (cell #0) to 10\ -[ use loop to set the next four cells to 70/100/30/10\ - > +++++ ++ add 7 to cell #1\ - > +++++ +++++ add 10 to cell #2 \ - > +++ add 3 to cell #3\ - > + add 1 to cell #4\ - <<<< - decrement counter (cell #0)\ -]\ -> ++ . print 'H'\ -> + . print 'e'\ -+++++ ++ . print 'l'\ -. print 'l'\ -+++ . print 'o'\ -> ++ . print ' '\ -<< +++++ +++++ +++++ . print 'W'\ -> . print 'o'\ -+++ . print 'r'\ ------ - . print 'l'\ ------ --- . print 'd'\ -> + . print '!'\ -> . print '\n'\ \ No newline at end of file diff --git a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/loop.c b/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/loop.c deleted file mode 100644 index fc3ccdcebed..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/loop.c +++ /dev/null @@ -1,76 +0,0 @@ -#include "sljitLir.h" - -#include -#include - -typedef long (SLJIT_FUNC *func2_t)(long a, long b); - -/* - This example, we generate a function like this: - -long func(long a, long b) -{ - long i; - long ret = 0; - for (i = 0; i < a; ++i) { - ret += b; - } - return ret; -} -*/ - -static int loop(long a, long b) -{ - void *code; - unsigned long len; - func2_t func; - - struct sljit_label *loopstart; - struct sljit_jump *out; - - /* Create a SLJIT compiler */ - struct sljit_compiler *C = sljit_create_compiler(NULL, NULL); - - /* 2 arg, 2 temp reg, 2 saved reg */ - sljit_emit_enter(C, 0, SLJIT_ARGS2(W, W, W), 2, 2, 0, 0, 0); - - /* R0 = 0 */ - sljit_emit_op2(C, SLJIT_XOR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R1, 0); - /* RET = 0 */ - sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); - /* loopstart: */ - loopstart = sljit_emit_label(C); - /* R1 >= a --> jump out */ - out = sljit_emit_cmp(C, SLJIT_GREATER_EQUAL, SLJIT_R1, 0, SLJIT_S0, 0); - /* RET += b */ - sljit_emit_op2(C, SLJIT_ADD, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0, SLJIT_S1, 0); - /* R1 += 1 */ - sljit_emit_op2(C, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); - /* jump loopstart */ - sljit_set_label(sljit_emit_jump(C, SLJIT_JUMP), loopstart); - /* out: */ - sljit_set_label(out, sljit_emit_label(C)); - - /* return RET */ - sljit_emit_return(C, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - /* Generate machine code */ - code = sljit_generate_code(C); - len = sljit_get_generated_code_size(C); - - /* Execute code */ - func = (func2_t)code; - printf("func return %ld\n", func(a, b)); - - /* dump_code(code, len); */ - - /* Clean up */ - sljit_free_compiler(C); - sljit_free_code(code, NULL); - return 0; -} - -int main() -{ - return loop(4, 5); -} diff --git a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/sljit_tutorial.html b/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/sljit_tutorial.html deleted file mode 100644 index fba7738bfb1..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/sljit_tutorial.html +++ /dev/null @@ -1,584 +0,0 @@ - - - - - - SLJIT tutorial - - - - - - -
- - - - -
- -
-SourceForge.net Logo -
-

SLJIT tutorial

- -

Before started

- -Download the tutorial sources
-
-SLJIT is a light-weight, platform independent JIT compiler, it's easy to -embed to your own project, as a result of its 'stack-less', SLJIT have -some limit to register usage.
-
-Here is some other JIT compiler I digged these days, place here if you have interest:
- -
    - Libjit/liblighning: - the backend of GNU.net
    - Libgccjit: - introduced in GCC5.0, its different from other JIT lib, this - one seems like constructing a C code, it use the backend of GCC.
    - AsmJIT: - branch from the famous V8 project (JavaScript engine in Chrome), - support only X86/X86_64.
    - DynASM: - used in LuaJIT.
    -
- -
-AsmJIT and DynASM work in the instruction level, look like coding with ASM language, -SLJIT look like ASM also, but it hide the detail of the specific CPU, make it more -common, and become portable, libjit work on higher layer, libgccjit as I mention, -really you are constructing the C code.
- -

First program

- -Usage of SLJIT: -
    -1. #include "sljitLir.h" in the head of your C/C++ program
    -2. Compile with sljit_src/sljitLir.c
    -
- -ALL example can be compile like this: -
    -gcc -Wall -Ipath/to/sljit_src -DSLJIT_CONFIG_AUTO=1 \
    -
      xxx.c path/to/sljit_src/sljitLir.c -o program
    -
- -OK, let's take a look at the first program, this program we create a function that -return the sum of 3 arguments.
-
-
-
    -#include "sljitLir.h"
    -
    -#include <stdio.h>
    -#include <stdlib.h>
    -
    -typedef sljit_sw (*func3_t)(sljit_sw a, sljit_sw b, sljit_sw c);
    -
    -static int add3(sljit_sw a, sljit_sw b, sljit_sw c)
    -{
    -
      - void *code;
      - sljit_sw len;
      - func3_t func;
      -
      - /* Create a SLJIT compiler */
      - struct sljit_compiler *C = sljit_create_compiler();
      -
      - /* Start a context(function entry), has 3 arguments, discuss later */
      - sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 1, 3, 0, 0, 0);
      -
      - /* The first arguments of function is register SLJIT_S0, 2nd, SLJIT_S1, etc. */
      - /* R0 = first */
      - sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);
      -
      - /* R0 = R0 + second */
      - sljit_emit_op2(C, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S1, 0);
      -
      - /* R0 = R0 + third */
      - sljit_emit_op2(C, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S2, 0);
      -
      - /* This statement mov R0 to RETURN REG and return */
      - /* in fact, R0 is RETURN REG itself */
      - sljit_emit_return(C, SLJIT_MOV, SLJIT_R0, 0);
      -
      - /* Generate machine code */
      - code = sljit_generate_code(C);
      - len = sljit_get_generated_code_size(C);
      -
      - /* Execute code */
      - func = (func3_t)code;
      - printf("func return %ld\n", func(a, b, c));
      -
      - /* dump_code(code, len); */
      -
      - /* Clean up */
      - sljit_free_compiler(C);
      - sljit_free_code(code);
      - return 0;
      -
    -}
    -
    -int main()
    -{
    -
      - return add3(4, 5, 6);
      -
    -}
    -
-
- -
-The function sljit_emit_enter create a context, save some registers to the stack, -and create a call-frame, sljit_emit_return restore the saved-register and clean-up -the frame. SLJIT is design to embed into other application, the code it generated -has to follow some basic rule.
-
-The standard called Application Binary Interface, or ABI for short, here is a -document for X86_64 CPU (ABI.pdf), -almost all Linux/Unix follow this standard. MS windows has its own, read this for more: -X86_calling_conventions
-
-When reading the doc of sljit_emit_emter, the parameters 'saveds' and 'scratchs' make -me confused. The fact is, the registers in CPU has different functions in the ABI spec, -some of them used to pass arguments, some of them are 'callee-saved', some of them are -'temporary used', take X86_64 for example, RAX, R10, R11 are temporary used, that means, -they may be changed after a call instruction. And RBX, R12-R15 are callee-saved, those -will remain the same values after the call. The rule is, every function should save -those registers before using it.
-
-Fortunately, SLJIT have done the most for us, SLJIT_S[0-9] represent those 'safe' -registers, SLJIT_R[0-9] however, only for 'temporary used'.
-
-When a function start, SLJIT move the function arguments to S0, S1, S2 register, it -means function arguments are always 'safe' in the context; a maximum of 4 -arguments is supported by SLJIT.
-
-Sljit_emit_opX is easy to understand, in SLJIT a data value is represented by 2 -parameters, it can be a register, an In-memory data, or an immediate number.
-
- - - - - - - - -
First parameter Second parameter Meaning
SLJIT_R*, SLJIT_S* 0 Temp/saved registers
SLJIT_IMM Number Immediate number
SLJIT_MEM Address In-mem data with Absolute address
SLJIT_MEM1(r) Offset In-mem data in [R + offset]
SLJIT_MEM2(r1, r2) Shift(size) In-mem array, R1 as base address, R2 as index,
- Shift as size(0 for bytes, 1 for shorts, 2 for
- 4bytes, 3 for 8bytes)
- -

Branch

-
-
    -#include "sljitLir.h"
    -
    -#include <stdio.h>
    -#include <stdlib.h>
    -
    -typedef sljit_sw (*func3_t)(sljit_sw a, sljit_sw b, sljit_sw c);
    -
    -/*
    - This example, we generate a function like this:
    -
    -sljit_sw func(sljit_sw a, sljit_sw b, sljit_sw c)
    -{
    -
      - if ((a & 1) == 0)
      -
        - return c;
        -
      - return b;
      -
    -}
    -
    - */
    -static int branch(sljit_sw a, sljit_sw b, sljit_sw c)
    -{
    -
      - void *code;
      - sljit_uw len;
      - func3_t func;
      -
      - struct sljit_jump *ret_c;
      - struct sljit_jump *out;
      -
      - /* Create a SLJIT compiler */
      - struct sljit_compiler *C = sljit_create_compiler();
      -
      - /* 3 arg, 1 temp reg, 3 save reg */
      - sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 1, 3, 0, 0, 0);
      -
      - /* R0 = a & 1, S0 is argument a */
      - sljit_emit_op2(C, SLJIT_AND, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 1);
      -
      - /* if R0 == 0 then jump to ret_c, where is ret_c? we assign it later */
      - ret_c = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0);
      -
      - /* R0 = b, S1 is argument b */
      - sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_S1, 0);
      -
      - /* jump to out */
      - out = sljit_emit_jump(C, SLJIT_JUMP);
      -
      - /* here is the 'ret_c' should jump, we emit a label and set it to ret_c */
      - sljit_set_label(ret_c, sljit_emit_label(C));
      -
      - /* R0 = c, S2 is argument c */
      - sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_S2, 0);
      -
      - /* here is the 'out' should jump */
      - sljit_set_label(out, sljit_emit_label(C));
      -
      - /* end of function */
      - sljit_emit_return(C, SLJIT_MOV, SLJIT_RETURN_REG, 0);
      -
      - /* Generate machine code */
      - code = sljit_generate_code(C);
      - len = sljit_get_generated_code_size(C);
      -
      - /* Execute code */
      - func = (func3_t)code;
      - printf("func return %ld\n", func(a, b, c));
      -
      - /* dump_code(code, len); */
      -
      - /* Clean up */
      - sljit_free_compiler(C);
      - sljit_free_code(code);
      - return 0;
      -
    -}
    -
    -int main()
    -{
    -
      - return branch(4, 5, 6);
      -
    -}
    -
-
- -The key to implement branch is 'struct sljit_jump' and 'struct sljit_label', -the 'jump' contain a jump instruction, it does not know where to jump unless -you set a label to it, the 'label' is a code address just like label in ASM -language.
-
-sljit_emit_cmp/sljit_emit_jump generate a conditional/unconditional jump, -take the statement
-
    -ret_c = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0);
    -
-For example, it create a jump instruction, the condition is R0 equals 0, and -the position of jumping will assign later with the sljit_set_label statement.
-
-In this example, it creates a branch like this:
-
    -
      - R0 = a & 1;
      - if R0 == 0 then goto ret_c;
      - R0 = b;
      - goto out;
      -
    -ret_c:
    -
      - R0 = c;
      -
    -out:
    -
      - return R0;
      -
    -
-
-This is how high-level-language compiler handle branch.
-
- -

Loop

- -Loop example is similar with Branch. - -
-
    -/* - This example, we generate a function like this:
    -
    -sljit_sw func(sljit_sw a, sljit_sw b)
    -{
    -
      - sljit_sw i;
      - sljit_sw ret = 0;
      - for (i = 0; i < a; ++i) {
      -
        - ret += b;
        -
      - }
      - return ret;
      -
    -}
    -*/
    -
    -
      - /* 2 arg, 2 temp reg, 2 saved reg */
      - sljit_emit_enter(C, 0, SLJIT_ARGS2(W, W, W), 2, 2, 0, 0, 0);
      -
      - /* R0 = 0 */
      - sljit_emit_op2(C, SLJIT_XOR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R1, 0);
      - /* RET = 0 */
      - sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
      - /* loopstart: */
      - loopstart = sljit_emit_label(C);
      - /* R1 >= a --> jump out */
      - out = sljit_emit_cmp(C, SLJIT_GREATER_EQUAL, SLJIT_R1, 0, SLJIT_S0, 0);
      - /* RET += b */
      - sljit_emit_op2(C, SLJIT_ADD, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0, SLJIT_S1, 0);
      - /* R1 += 1 */
      - sljit_emit_op2(C, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
      - /* jump loopstart */
      - sljit_set_label(sljit_emit_jump(C, SLJIT_JUMP), loopstart);
      - /* out: */
      - sljit_set_label(out, sljit_emit_label(C));
      -
      - /* return RET */
      - sljit_emit_return(C, SLJIT_MOV, SLJIT_RETURN_REG, 0);
      -
    -
-
- -After this example, you are ready to construct any program that contain complex branch -and loop.
-
-Here is an interesting fact, 'xor reg, reg' is better than 'mov reg, 0', it save 2 bytes -in X86 machine.
-
-I will give only the key code in the rest of this tutorial, the full source of each -chapter can be found in the attachment.
- - -

Call external function

- -It's easy to call an external function in SLJIT, we use sljit_emit_icall with SLJIT_CALL -operation to do so.
-
-SLJIT_CALL is use to call a function with N arguments, the number of arguments -and the return type are defined in the third parameter from sljit_emit_icall -just like it is done for SLJIT defined dunctions.
-the arguments for the callee function are passed from SLJIT_R0, R1 and R2. Keep in mind to maintain those 'temp registers'.
-
-Assume that we have an external function:
-
    - sljit_sw print_num(sljit_sw a); -
- -JIT code to call print_num(S1): - -
-
    - /* R0 = S1; */
    - sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S1, 0);
    - /* print_num(R0) */
    - sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num));
    -
-
-
-This code call a imm-data(address of print_num), which is linked properly when the -program loaded. There no problem in 1-time compile and execute, but when you planning -to save to file and load/execute next time, that address may not correct as you expect, -in some platform that support PIC, the address of print_num may relocate to another -address in run-time. Check this out: -PIC
-
- -

Structure access

- -SLJIT use SLJIT_MEM1 to implement [Reg + offset] memory access.
-
-
    -struct point_st {
    -
      - sljit_sw x;
      - int y;
      - short z;
      - char d;
      -
    -};
    -
    -sljit_emit_op1(C, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0),
    -
      -SLJIT_OFFSETOF(struct point_st, y));
      -
    -
-
- -In this case, SLJIT_S0 is the address of the point_st structure, offset of member 'y' -is determined in compile time, the important MOV operation always comes with a -'signed/size' postfix, like this one _S32 means 'signed 32bits integer', the postfix -list:
-
    - U8 = unsigned byte (8 bit)
    - S8 = signed byte (8 bit)
    - U16 = unsigned half (16 bit)
    - S16 = signed half (16 bit)
    - U32 = unsigned int (32 bit)
    - S32 = signed int (32 bit)
    - P = pointer (sljit_p) size
    -
- -

Array accessing

- -SLJIT use SLJIT_MEM2 to access arrays, like this:
- -
-
    -sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_S2),
    -
      -SLJIT_WORD_SHIFT); -
    -
-
- -This statement generates a code like this:
-
    -WORD S0[];
    -R0 = S0[S2]
    -
-
-The array S0 is declared to be WORD (using SLJIT_WORD_SHIFT), which will be sizeof(sljit_sw) in length. -SLJIT use a 'shift' for length representation: (0 for single byte, 1 for 2 -bytes, 2 for 4 bytes, 3 for 8bytes).
-
-The file array_access.c demonstrate a array-print example, should be easy -to understand.
- -

Local variables

- -SLJIT provide SLJIT_MEM1(SLJIT_SP) to access the reserved space in -sljit_emit_enter's last parameter.
-In this example we have to pass the address to print_arr, local variable -is the only choice.
- -
-
    - /* reserved space in stack for sljit_sw arr[3] */
    - sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 2, 3, 0, 0, 3 * sizeof(sljit_sw));
    - /* opt arg R S FR FS local_size */
    -
    - /* arr[0] = S0, SLJIT_SP is the init address of local var */
    - sljit_emit_op1(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_S0, 0);
    - /* arr[1] = S1 */
    - sljit_emit_op1(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 1 * sizeof(sljit_sw), SLJIT_S1, 0);
    - /* arr[2] = S2 */
    - sljit_emit_op1(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_sw), SLJIT_S2, 0);
    -
    - /* R0 = arr; in fact SLJIT_SP is the address of arr, but can't do so in SLJIT */
    - sljit_get_local_base(C, SLJIT_R0, 0, 0); /* get the address of local variables */
    - sljit_emit_op1(C, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3); /* R1 = 3; */
    - sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS2(W, P, W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_arr));
    - sljit_emit_return(C, SLJIT_MOV, SLJIT_R0, 0);
    -
-
-
-SLJIT_SP can only be used in SLJIT_MEM1(SLJIT_SP). In this case, SP is the -address of 'arr', but we cannot assign it to Reg using SLJIT_MOV opr, -instead, we use sljit_get_local_base, which load the address and offset of -local variable to the target.
- -

Brainfuck compiler

- -Ok, the basic usage of SLJIT ends here, with more detail, I suggest reading -sljitLir.h directly, having fun hacking the wonder of SLJIT!
-
-The brainfuck machine introduction can be found here: -Brainfuck
-
- -

Extra

- -1. Dump_code function
-SLJIT didn't provide disassemble functional, this is a simple function to do this(X86 only)
-
- -
-
    -static void dump_code(void *code, sljit_uw len)
    -{
    -
      - FILE *fp = fopen("/tmp/slj_dump", "wb");
      - if (!fp)
      -
        - return;
        -
      - fwrite(code, len, 1, fp);
      - fclose(fp);
      -
    -#if defined(SLJIT_CONFIG_X86_64)
    -
      - system("objdump -b binary -m l1om -D /tmp/slj_dump");
      -
    -#elif defined(SLJIT_CONFIG_X86_32)
    -
      - system("objdump -b binary -m i386 -D /tmp/slj_dump");
      -
    -#endif
    -} -
-
- -The branch example disassembling:
-
-0000000000000000 <.data>:
-
    - - - - - - - - - - - - - - - - - - - - -
    0:53push %rbx
    1:41 57push %r15
    3:41 56push %r14
    5:48 8b dfmov %rdi,%rbx
    8:4c 8b femov %rsi,%r15
    b:4c 8b f2mov %rdx,%r14
    e:48 83 ec 10sub $0x10,%rsp
    12:48 89 d8mov %rbx,%rax
    15:48 83 e0 01and $0x1,%rax
    19:48 83 f8 00cmp $0x0,%rax
    1d:74 05je 0x24
    1f:4c 89 f8mov %r15,%rax
    22:eb 03jmp 0x27
    24:4c 89 f0mov %r14,%rax
    27:48 83 c4 10add $0x10,%rsp
    2b:41 5epop %r14
    2d:41 5fpop %r15
    2f:5bpop %rbx
    30:c3retq
    -
-
-with GCC -O2
-0000000000000000 <func>:
-
    - - - - - -
    0:48 89 d0mov %rdx,%rax
    3:83 e7 01and $0x1,%edi
    6:48 0f 45 c6cmovne %rsi,%rax
    a:c3retq
    -
-
-Err... Ok, the optimization here may be weak, or, optimization there is crazy... :-)
- - - -
Originally by wenxichang#163.com, 2015.5.10
- -
-
- - - diff --git a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/struct_access.c b/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/struct_access.c deleted file mode 100644 index 577a627d711..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/struct_access.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "sljitLir.h" - -#include -#include - -struct point_st { - long x; - int y; - short z; - char d; -}; - -typedef long (SLJIT_FUNC *point_func_t)(struct point_st *point);; - -static long SLJIT_FUNC print_num(long a) -{ - printf("a = %ld\n", a); - return a + 1; -} - -/* - This example, we generate a function like this: - -long func(struct point_st *point) -{ - print_num(point->x); - print_num(point->y); - print_num(point->z); - print_num(point->d); - return point->x; -} -*/ - -static int struct_access() -{ - void *code; - unsigned long len; - point_func_t func; - - struct point_st point = { - -5, -20, 5, 'a' - }; - - /* Create a SLJIT compiler */ - struct sljit_compiler *C = sljit_create_compiler(NULL, NULL); - - sljit_emit_enter(C, 0, SLJIT_ARGS1(W, W), 1, 1, 0, 0, 0); - /* opt arg R S FR FS local_size */ - - sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct point_st, x)); // S0->x --> R0 - sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, P), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num)); // print_num(R0); - - sljit_emit_op1(C, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct point_st, y)); // S0->y --> R0 - sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, P), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num)); // print_num(R0); - - sljit_emit_op1(C, SLJIT_MOV_S16, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct point_st, z)); // S0->z --> R0 - sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, P), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num)); // print_num(R0); - - sljit_emit_op1(C, SLJIT_MOV_S8, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct point_st, d)); // S0->d --> R0 - sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, P), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num)); // print_num(R0); - - sljit_emit_return(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct point_st, x)); // return S0->x - - /* Generate machine code */ - code = sljit_generate_code(C); - len = sljit_get_generated_code_size(C); - - /* Execute code */ - func = (point_func_t)code; - printf("func return %ld\n", func(&point)); - - /* dump_code(code, len); */ - - /* Clean up */ - sljit_free_compiler(C); - sljit_free_code(code, NULL); - return 0; -} - -int main() -{ - return struct_access(); -} diff --git a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/temp_var.c b/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/temp_var.c deleted file mode 100644 index a0619317775..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/doc/tutorial/temp_var.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "sljitLir.h" - -#include -#include - -typedef long (SLJIT_FUNC *func3_t)(long a, long b, long c); - -static long SLJIT_FUNC print_arr(long *a, long n) -{ - long i; - long sum = 0; - for (i = 0; i < n; ++i) { - sum += a[i]; - printf("arr[%ld] = %ld\n", i, a[i]); - } - return sum; -} - -/* - This example, we generate a function like this: - -long func(long a, long b, long c) -{ - long arr[3] = { a, b, c }; - return print_arr(arr, 3); -} -*/ - -static int temp_var(long a, long b, long c) -{ - void *code; - unsigned long len; - func3_t func; - - /* Create a SLJIT compiler */ - struct sljit_compiler *C = sljit_create_compiler(NULL, NULL); - - /* reserved space in stack for long arr[3] */ - sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 2, 3, 0, 0, 3 * sizeof(long)); - /* opt arg R S FR FS local_size */ - - /* arr[0] = S0, SLJIT_SP is the init address of local var */ - sljit_emit_op1(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_S0, 0); - /* arr[1] = S1 */ - sljit_emit_op1(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 1 * sizeof(long), SLJIT_S1, 0); - /* arr[2] = S2 */ - sljit_emit_op1(C, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(long), SLJIT_S2, 0); - - /* R0 = arr; in fact SLJIT_SP is the address of arr, but can't do so in SLJIT */ - sljit_get_local_base(C, SLJIT_R0, 0, 0); /* get the address of local variables */ - sljit_emit_op1(C, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3); /* R1 = 3; */ - sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS2(W, P, W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_arr)); - sljit_emit_return(C, SLJIT_MOV, SLJIT_R0, 0); - - /* Generate machine code */ - code = sljit_generate_code(C); - len = sljit_get_generated_code_size(C); - - /* Execute code */ - func = (func3_t)code; - printf("func return %ld\n", func(a, b, c)); - - /* dump_code(code, len); */ - - /* Clean up */ - sljit_free_compiler(C); - sljit_free_code(code, NULL); - return 0; -} - -int main() -{ - return temp_var(7, 8, 9); -} diff --git a/waterbox/ares64/ares/thirdparty/sljit/regex_src/regexJIT.c b/waterbox/ares64/ares/thirdparty/sljit/regex_src/regexJIT.c deleted file mode 100644 index 2eaecd96e14..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/regex_src/regexJIT.c +++ /dev/null @@ -1,2595 +0,0 @@ -/* - * Stack-less Just-In-Time compiler - * - * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "sljitLir.h" -#include "regexJIT.h" - -#include - -#ifdef REGEX_MATCH_VERBOSE -#include -#endif - -/* Extra, hidden flags: - {id!} where id > 0 found in the code. */ -#define REGEX_ID_CHECK 0x100 -/* When REGEX_NEWLINE && REGEX_MATCH_BEGIN defined, the pattern turn to a normal search, - which starts with [\r\n] character range. */ -#define REGEX_FAKE_MATCH_BEGIN 0x200 -/* When REGEX_NEWLINE && REGEX_MATCH_END defined, the pattern turn to a normal search, - which ends with [\r\n] character range. */ -#define REGEX_FAKE_MATCH_END 0x400 - -/* --------------------------------------------------------------------- */ -/* Structures for JIT-ed pattern matching */ -/* --------------------------------------------------------------------- */ - -struct regex_machine -{ - /* flags. */ - int flags; - /* Number of state descriptors for one term. */ - sljit_sw no_states; - /* Total size. */ - sljit_sw size; - - union { - void *init_match; - sljit_sw (SLJIT_FUNC *call_init)(void *next, void* match); - } u; -#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) - struct sljit_function_context context; -#endif - - void *continue_match; - - /* Variable sized array to contain the handler addresses. */ - sljit_uw entry_addrs[1]; -}; - -struct regex_match -{ - /* Current and next state array. */ - sljit_sw *current; - sljit_sw *next; - /* Starting. */ - sljit_sw head; - /* String character index (ever increasing). */ - sljit_sw index; - /* Best match found so far (members in priority order). */ - sljit_sw best_begin; - sljit_sw best_end; - sljit_sw best_id; - /* Bool flags (encoded as word). */ - sljit_sw fast_quit; - sljit_sw fast_forward; - /* Machine. */ - struct regex_machine *machine; - - union { - void *continue_match; - void (SLJIT_FUNC *call_continue)(struct regex_match *match, const regex_char_t *input_string, int length); - } u; - - /* Variable sized array to contain the state arrays. */ - sljit_sw states[1]; -}; - -/* State vector - ITEM[0] - pointer to the address inside the machine code - ITEM[1] - next pointer - ITEM[2] - string started from (optional) - ITEM[3] - max ID (optional) */ - -/* Register allocation. */ -/* Current state array (loaded & stored: regex_match->current). */ -#define R_CURR_STATE SLJIT_S0 -/* Next state array (loaded & stored: regex_match->next). */ -#define R_NEXT_STATE SLJIT_S1 -/* Head (loaded & stored: regex_match->head). */ -#define R_NEXT_HEAD SLJIT_S2 -/* String fragment pointer. */ -#define R_STRING SLJIT_S3 -/* String fragment length. */ -#define R_LENGTH SLJIT_S4 -/* 'struct regex_match*' */ -#define R_REGEX_MATCH SLJIT_R0 -/* Current character. */ -#define R_CURR_CHAR SLJIT_R1 -/* Temporary register. */ -#define R_TEMP SLJIT_R2 -/* Caches the regex_match->best_begin. */ -#define R_BEST_BEGIN SLJIT_R3 -/* Current character index. */ -#define R_CURR_INDEX SLJIT_R4 - -/* --------------------------------------------------------------------- */ -/* Stack management */ -/* --------------------------------------------------------------------- */ - -/* Try to allocate 2^n blocks. */ -#define STACK_FRAGMENT_SIZE (((64 * sizeof(struct stack_item)) - (sizeof(struct stack_fragment_data))) / (sizeof(struct stack_item))) - -struct stack_item { - int type; - int value; -}; - -struct stack_fragment_data { - struct stack_fragment *next; - struct stack_fragment *prev; -}; - -struct stack_fragment { - struct stack_fragment_data data; - struct stack_item items[STACK_FRAGMENT_SIZE]; -}; - -struct stack { - struct stack_fragment *first; - struct stack_fragment *last; - sljit_uw index; - sljit_uw count; -}; - -#if (defined SLJIT_DEBUG && SLJIT_DEBUG) - -static void stack_check(struct stack *stack) -{ - struct stack_fragment *curr; - int found; - - if (!stack) - return; - - SLJIT_ASSERT(stack->index < STACK_FRAGMENT_SIZE); - - if (stack->first == NULL) { - SLJIT_ASSERT(stack->first == NULL && stack->last == NULL); - SLJIT_ASSERT(stack->index == STACK_FRAGMENT_SIZE - 1 && stack->count == 0); - return; - } - - found = 0; - if (stack->last == NULL) { - SLJIT_ASSERT(stack->index == STACK_FRAGMENT_SIZE - 1 && stack->count == 0); - found = 1; - } - - SLJIT_ASSERT(stack->first->data.prev == NULL); - curr = stack->first; - while (curr) { - if (curr == stack->last) - found = 1; - if (curr->data.next) - SLJIT_ASSERT(curr->data.next->data.prev == curr); - curr = curr->data.next; - } - SLJIT_ASSERT(found); -} - -#endif - -static void stack_init(struct stack *stack) -{ - stack->first = NULL; - stack->last = NULL; - stack->index = STACK_FRAGMENT_SIZE - 1; - stack->count = 0; -} - -static void stack_destroy(struct stack *stack) -{ - struct stack_fragment *curr = stack->first; - struct stack_fragment *prev; - -#if (defined SLJIT_DEBUG && SLJIT_DEBUG) - stack_check(stack); -#endif - - while (curr) { - prev = curr; - curr = curr->data.next; - SLJIT_FREE(prev, NULL); - } -} - -static SLJIT_INLINE struct stack_item* stack_top(struct stack *stack) -{ - SLJIT_ASSERT(stack->last); - return stack->last->items + stack->index; -} - -static int stack_push(struct stack *stack, int type, int value) -{ - if (stack->last) { - stack->index++; - if (stack->index >= STACK_FRAGMENT_SIZE) { - stack->index = 0; - if (!stack->last->data.next) { - stack->last->data.next = (struct stack_fragment*)SLJIT_MALLOC(sizeof(struct stack_fragment), NULL); - if (!stack->last->data.next) - return 1; - stack->last->data.next->data.next = NULL; - stack->last->data.next->data.prev = stack->last; - } - stack->last = stack->last->data.next; - } - } - else if (!stack->first) { - stack->last = (struct stack_fragment*)SLJIT_MALLOC(sizeof(struct stack_fragment), NULL); - if (!stack->last) - return 1; - stack->last->data.prev = NULL; - stack->last->data.next = NULL; - stack->first = stack->last; - stack->index = 0; - } - else { - stack->last = stack->first; - stack->index = 0; - } - stack->last->items[stack->index].type = type; - stack->last->items[stack->index].value = value; - stack->count++; -#if (defined SLJIT_DEBUG && SLJIT_DEBUG) - stack_check(stack); -#endif - return 0; -} - -static struct stack_item* stack_pop(struct stack *stack) -{ - struct stack_item *ret = stack_top(stack); - - if (stack->index > 0) - stack->index--; - else { - stack->last = stack->last->data.prev; - stack->index = STACK_FRAGMENT_SIZE - 1; - } - - stack->count--; -#if (defined SLJIT_DEBUG && SLJIT_DEBUG) - stack_check(stack); -#endif - return ret; -} - -static SLJIT_INLINE void stack_clone(struct stack *src, struct stack *dst) -{ - *dst = *src; -} - -static int stack_push_copy(struct stack *stack, int items, int length) -{ - struct stack_fragment *frag1; - struct stack_fragment *frag2; - sljit_uw ind1, ind2; - sljit_uw counter; - - SLJIT_ASSERT(stack->count >= (sljit_uw)length && items <= length && items > 0); - - /* Allocate the necessary elements. */ - counter = (sljit_uw)items; - frag1 = stack->last; - ind1 = stack->index; - while (counter > 0) { - if (stack->index + counter >= STACK_FRAGMENT_SIZE) { - SLJIT_ASSERT(counter >= STACK_FRAGMENT_SIZE - stack->index - 1 + 1); - counter -= STACK_FRAGMENT_SIZE - stack->index - 1 + 1; - stack->index = 0; - if (!stack->last->data.next) { - stack->last->data.next = (struct stack_fragment*)SLJIT_MALLOC(sizeof(struct stack_fragment), NULL); - if (!stack->last->data.next) - return 1; - stack->last->data.next->data.next = NULL; - stack->last->data.next->data.prev = stack->last; - } - stack->last = stack->last->data.next; - } - else { - stack->index += counter; - counter = 0; - } - } - - frag2 = stack->last; - ind2 = stack->index; - while (length > 0) { - frag2->items[ind2] = frag1->items[ind1]; - - if (ind1 == 0) { - ind1 = STACK_FRAGMENT_SIZE; - frag1 = frag1->data.prev; - } - if (ind2 == 0) { - ind2 = STACK_FRAGMENT_SIZE; - frag2 = frag2->data.prev; - } - - ind1--; - ind2--; - length--; - } - -#if (defined SLJIT_DEBUG && SLJIT_DEBUG) - stack_check(stack); -#endif - stack->count += (sljit_uw)items; - return 0; -} - -/* --------------------------------------------------------------------- */ -/* Parser */ -/* --------------------------------------------------------------------- */ - -enum { - /* Common. */ - type_begin, - type_end, - type_char, - type_newline, - type_id, - type_rng_start, - type_rng_end, - type_rng_char, - type_rng_left, - type_rng_right, - - /* generator only. */ - type_branch, - type_jump, - - /* Parser only. */ - type_open_br, - type_close_br, - type_select, - type_asterisk, - type_plus_sign, - type_qestion_mark -}; - -struct compiler_common { - /* Temporary stacks. */ - struct stack stack; - struct stack depth; - /* REGEX_ flags. */ - int flags; - /* Encoded size of the dfa representation. */ - sljit_uw dfa_size; - /* Number of terms. */ - sljit_sw terms_size; - /* Number of state descriptors for one term (same as machine->no_states). */ - sljit_sw no_states; - /* Number of type_rng_(char|left)-s in the longest character range. */ - sljit_sw longest_range_size; - - /* DFA linear representation (size: dfa_size). */ - struct stack_item *dfa_transitions; - /* Term id and search state pairs (size: dfa_size). */ - struct stack_item *search_states; - - /* sljit compiler */ - struct sljit_compiler *compiler; - /* Machine data, which must be kept for later use. */ - struct regex_machine *machine; - /* Temporary space for jumps (size: longest_range_size). */ - struct sljit_jump **range_jump_list; -}; - -static const regex_char_t* decode_number(const regex_char_t *regex_string, int length, int *result) -{ - int value = 0; - - SLJIT_ASSERT(length > 0); - if (*regex_string < '0' || *regex_string > '9') { - *result = -1; - return regex_string; - } - - while (length > 0 && *regex_string >= '0' && *regex_string <= '9') { - value = value * 10 + (*regex_string - '0'); - length--; - regex_string++; - } - - *result = value; - return regex_string; -} - -static int iterate(struct stack *stack, int min, int max) -{ - struct stack it; - struct stack_item *item; - int count = -1; - int len = 0; - int depth = 0; - - stack_clone(stack, &it); - - /* Calculate size. */ - while (count < 0) { - item = stack_pop(&it); - switch (item->type) { - case type_id: - case type_rng_end: - case type_rng_char: - case type_rng_left: - case type_rng_right: - case type_plus_sign: - case type_qestion_mark: - len++; - break; - - case type_asterisk: - len += 2; - break; - - case type_close_br: - depth++; - break; - - case type_open_br: - SLJIT_ASSERT(depth > 0); - depth--; - if (depth == 0) - count = (int)it.count; - break; - - case type_select: - SLJIT_ASSERT(depth > 0); - len += 2; - break; - - default: - SLJIT_ASSERT(item->type != type_begin && item->type != type_end); - if (depth == 0) - count = (int)it.count; - len++; - break; - } - } - - if (min == 0 && max == 0) { - /* {0,0} case, not {0,} case: delete subtree. */ - stack_clone(&it, stack); - /* and put an empty bracket expression instead of it. */ - if (stack_push(stack, type_open_br, 0)) - return REGEX_MEMORY_ERROR; - if (stack_push(stack, type_close_br, 0)) - return REGEX_MEMORY_ERROR; - return len; - } - - count = (int)stack->count - count; - - /* Put an open bracket before the sequence. */ - if (stack_push_copy(stack, 1, count)) - return -1; - -#if (defined SLJIT_DEBUG && SLJIT_DEBUG) - SLJIT_ASSERT(stack_push(&it, type_open_br, 0) == 0); -#else - stack_push(&it, type_open_br, 0); -#endif - - /* Copy the data. */ - if (max > 0) { - len = len * (max - 1); - max -= min; - /* Insert ? operators. */ - len += max; - - if (min > 0) { - min--; - while (min > 0) { - if (stack_push_copy(stack, count, count)) - return -1; - min--; - } - if (max > 0) { - if (stack_push_copy(stack, count, count)) - return -1; - if (stack_push(stack, type_qestion_mark, 0)) - return REGEX_MEMORY_ERROR; - count++; - max--; - } - } - else { - SLJIT_ASSERT(max > 0); - max--; - count++; - if (stack_push(stack, type_qestion_mark, 0)) - return REGEX_MEMORY_ERROR; - } - - while (max > 0) { - if (stack_push_copy(stack, count, count)) - return -1; - max--; - } - } - else { - SLJIT_ASSERT(min > 0); - min--; - /* Insert + operator. */ - len = len * min + 1; - while (min > 0) { - if (stack_push_copy(stack, count, count)) - return -1; - min--; - } - - if (stack_push(stack, type_plus_sign, 0)) - return REGEX_MEMORY_ERROR; - } - - /* Close the opened bracket. */ - if (stack_push(stack, type_close_br, 0)) - return REGEX_MEMORY_ERROR; - - return len; -} - -static int parse_iterator(const regex_char_t *regex_string, int length, struct stack *stack, sljit_uw *dfa_size, int begin) -{ - /* We only know that *regex_string == { . */ - int val1, val2; - const regex_char_t *base_from = regex_string; - const regex_char_t *from; - - length--; - regex_string++; - - /* Decode left value. */ - val2 = -1; - if (length == 0) - return -2; - if (*regex_string == ',') { - val1 = 0; - length--; - regex_string++; - } - else { - from = regex_string; - regex_string = decode_number(regex_string, length, &val1); - if (val1 < 0) - return -2; - length -= (int)(regex_string - from); - - if (length == 0) - return -2; - if (*regex_string == '}') { - val2 = val1; - if (val1 == 0) - val1 = -1; - } - else if (length >= 2 && *regex_string == '!' && regex_string[1] == '}') { - /* Non posix extension. */ - if (stack_push(stack, type_id, val1)) - return -1; - (*dfa_size)++; - return (int)(regex_string - base_from) + 1; - } - else { - if (*regex_string != ',') - return -2; - length--; - regex_string++; - } - } - - if (begin) - return -2; - - /* Decode right value. */ - if (val2 == -1) { - if (length == 0) - return -2; - if (*regex_string == '}') - val2 = 0; - else { - from = regex_string; - regex_string = decode_number(regex_string, length, &val2); - length -= (int)(regex_string - from); - if (val2 < 0 || length == 0 || *regex_string != '}' || val2 < val1) - return -2; - if (val2 == 0) { - SLJIT_ASSERT(val1 == 0); - val1 = -1; - } - } - } - - /* Fast cases. */ - if (val1 > 1 || val2 > 1) { - val1 = iterate(stack, val1, val2); - if (val1 < 0) - return -1; - *dfa_size += (sljit_uw)val1; - } - else if (val1 == 0 && val2 == 0) { - if (stack_push(stack, type_asterisk, 0)) - return -1; - *dfa_size += 2; - } - else if (val1 == 1 && val2 == 0) { - if (stack_push(stack, type_plus_sign, 0)) - return -1; - (*dfa_size)++; - } - else if (val1 == 0 && val2 == 1) { - if (stack_push(stack, type_qestion_mark, 0)) - return -1; - (*dfa_size)++; - } - else if (val1 == -1) { - val1 = iterate(stack, 0, 0); - if (val1 < 0) - return -1; - *dfa_size -= (sljit_uw)val1; - SLJIT_ASSERT(*dfa_size >= 2); - } - else { - /* Ignore. */ - SLJIT_ASSERT(val1 == 1 && val2 == 1); - } - return (int)(regex_string - base_from); -} - -static int parse_char_range(const regex_char_t *regex_string, int length, struct compiler_common *compiler_common) -{ - struct stack* stack = &compiler_common->stack; - const regex_char_t *base_from = regex_string; - regex_char_t left_char, right_char, tmp_char; - - length--; - regex_string++; - - if (length == 0) - return -2; - - if (*regex_string != '^') { - if (stack_push(stack, type_rng_start, 0)) - return -1; - } - else { - length--; - regex_string++; - - if (length == 0) - return -2; - - if (stack_push(stack, type_rng_start, 1)) - return -1; - } - /* For both the type_rng_start & type_rng_end. */ - compiler_common->dfa_size += 2; - - /* Range must be at least 1 character. */ - if (*regex_string == ']') { - length--; - regex_string++; - if (stack_push(stack, type_rng_char, ']')) - return -1; - compiler_common->dfa_size++; - } - - while (1) { - if (length == 0) - return -2; - - if (*regex_string == ']') - break; - - if (*regex_string != '\\') - left_char = *regex_string; - else { - regex_string++; - length--; - if (length == 0) - return -2; - left_char = *regex_string; - } - regex_string++; - length--; - - /* Is a range here? */ - if (length >= 3 && *regex_string == '-' && *(regex_string + 1) != ']') { - regex_string++; - length--; - - if (*regex_string != '\\') - right_char = *regex_string; - else { - regex_string++; - length--; - if (length == 0) - return -2; - right_char = *regex_string; - } - regex_string++; - length--; - - if (left_char > right_char) { - /* Swap if necessary. */ - tmp_char = left_char; - left_char = right_char; - right_char = tmp_char; - } - - if (stack_push(stack, type_rng_left, left_char)) - return -1; - if (stack_push(stack, type_rng_right, right_char)) - return -1; - compiler_common->dfa_size += 2; - } - else { - if (stack_push(stack, type_rng_char, left_char)) - return -1; - compiler_common->dfa_size++; - } - } - - if (stack_push(stack, type_rng_end, 0)) - return -1; - return (int)(regex_string - base_from); -} - -static int parse(const regex_char_t *regex_string, int length, struct compiler_common *compiler_common) -{ - /* Depth of bracketed expressions. */ - int depth = 0; - /* Have we already found a term? '1' if not yet. */ - int begin = 1; - /* Cache stack pointer. */ - struct stack* stack = &compiler_common->stack; - int tmp; - - /* Type_begin and type_end. */ - compiler_common->dfa_size = 2; - stack_init(stack); - if (stack_push(stack, type_begin, 0)) - return REGEX_MEMORY_ERROR; - - if (length > 0 && *regex_string == '^') { - compiler_common->flags |= REGEX_MATCH_BEGIN; - length--; - regex_string++; - } - - if ((compiler_common->flags & (REGEX_MATCH_BEGIN | REGEX_NEWLINE)) == (REGEX_MATCH_BEGIN | REGEX_NEWLINE)) { - /* Replace REGEX_MATCH_BEGIN flag to REGEX_FAKE_MATCH_BEGIN */ - compiler_common->flags &= ~REGEX_MATCH_BEGIN; - compiler_common->flags |= REGEX_FAKE_MATCH_BEGIN; - /* and append a new-line search. */ - if (stack_push(stack, type_newline, 0)) - return REGEX_MEMORY_ERROR; - compiler_common->dfa_size++; - /* Begin intentionally kept as 1. */ - } - - while (length > 0) { - switch (*regex_string) { - case '\\' : - length--; - regex_string++; - if (length == 0) - return REGEX_INVALID_REGEX; - if (stack_push(stack, type_char, *regex_string)) - return REGEX_MEMORY_ERROR; - begin = 0; - compiler_common->dfa_size++; - break; - - case '.' : - if (stack_push(stack, type_rng_start, 1)) - return REGEX_MEMORY_ERROR; - if (compiler_common->flags & REGEX_NEWLINE) { - if (stack_push(stack, type_rng_char, '\n')) - return REGEX_MEMORY_ERROR; - if (stack_push(stack, type_rng_char, '\r')) - return REGEX_MEMORY_ERROR; - compiler_common->dfa_size += 2; - } - if (stack_push(stack, type_rng_end, 1)) - return REGEX_MEMORY_ERROR; - begin = 0; - compiler_common->dfa_size += 2; - break; - - case '(' : - depth++; - if (stack_push(stack, type_open_br, 0)) - return REGEX_MEMORY_ERROR; - begin = 1; - break; - - case ')' : - if (depth == 0) - return REGEX_INVALID_REGEX; - depth--; - if (stack_push(stack, type_close_br, 0)) - return REGEX_MEMORY_ERROR; - begin = 0; - break; - - case '|' : - if (stack_push(stack, type_select, 0)) - return REGEX_MEMORY_ERROR; - begin = 1; - compiler_common->dfa_size += 2; - break; - - case '*' : - if (begin) - return REGEX_INVALID_REGEX; - if (stack_push(stack, type_asterisk, 0)) - return REGEX_MEMORY_ERROR; - compiler_common->dfa_size += 2; - break; - - case '?' : - case '+' : - if (begin) - return REGEX_INVALID_REGEX; - if (stack_push(stack, (*regex_string == '+') ? type_plus_sign : type_qestion_mark, 0)) - return REGEX_MEMORY_ERROR; - compiler_common->dfa_size++; - break; - - case '{' : - tmp = parse_iterator(regex_string, length, stack, &compiler_common->dfa_size, begin); - - if (tmp >= 0) { - length -= tmp; - regex_string += tmp; - } - else if (tmp == -1) - return REGEX_MEMORY_ERROR; - else { - /* Not a valid range expression. */ - SLJIT_ASSERT(tmp == -2); - if (stack_push(stack, type_char, '{')) - return REGEX_MEMORY_ERROR; - compiler_common->dfa_size++; - } - break; - - case '[' : - tmp = parse_char_range(regex_string, length, compiler_common); - if (tmp >= 0) { - length -= tmp; - regex_string += tmp; - } - else if (tmp == -1) - return REGEX_MEMORY_ERROR; - else { - SLJIT_ASSERT(tmp == -2); - return REGEX_INVALID_REGEX; - } - begin = 0; - break; - - default: - if (length == 1 && *regex_string == '$') { - compiler_common->flags |= REGEX_MATCH_END; - break; - } - if (stack_push(stack, type_char, *regex_string)) - return REGEX_MEMORY_ERROR; - begin = 0; - compiler_common->dfa_size++; - break; - } - length--; - regex_string++; - } - - if (depth != 0) - return REGEX_INVALID_REGEX; - - if ((compiler_common->flags & (REGEX_MATCH_END | REGEX_NEWLINE)) == (REGEX_MATCH_END | REGEX_NEWLINE)) { - /* Replace REGEX_MATCH_END flag to REGEX_FAKE_MATCH_END */ - compiler_common->flags &= ~REGEX_MATCH_END; - compiler_common->flags |= REGEX_FAKE_MATCH_END; - /* and append a new-line search. */ - if (stack_push(stack, type_newline, 1)) - return REGEX_MEMORY_ERROR; - compiler_common->dfa_size++; - /* Begin intentionally kept as 1. */ - } - - if (stack_push(stack, type_end, 0)) - return REGEX_MEMORY_ERROR; - - return REGEX_NO_ERROR; -} - -/* --------------------------------------------------------------------- */ -/* Generating machine state transitions */ -/* --------------------------------------------------------------------- */ - -#define PUT_TRANSITION(typ, val) \ - do { \ - --transitions_ptr; \ - transitions_ptr->type = typ; \ - transitions_ptr->value = val; \ - } while (0) - -static struct stack_item* handle_iteratives(struct stack_item *transitions_ptr, struct stack_item *transitions, struct stack *depth) -{ - struct stack_item *item; - - while (1) { - item = stack_top(depth); - - switch (item->type) { - case type_asterisk: - SLJIT_ASSERT(transitions[item->value].type == type_branch); - transitions[item->value].value = (int)(transitions_ptr - transitions); - PUT_TRANSITION(type_branch, item->value + 1); - break; - - case type_plus_sign: - SLJIT_ASSERT(transitions[item->value].type == type_branch); - transitions[item->value].value = (int)(transitions_ptr - transitions); - break; - - case type_qestion_mark: - PUT_TRANSITION(type_branch, item->value); - break; - - default: - return transitions_ptr; - } - stack_pop(depth); - } -} - -static int generate_transitions(struct compiler_common *compiler_common) -{ - struct stack *stack = &compiler_common->stack; - struct stack *depth = &compiler_common->depth; - struct stack_item *transitions_ptr; - struct stack_item *item; - - stack_init(depth); - compiler_common->dfa_transitions = SLJIT_MALLOC(sizeof(struct stack_item) * compiler_common->dfa_size, NULL); - if (!compiler_common->dfa_transitions) - return REGEX_MEMORY_ERROR; - - /* Go through the items of the stack and generate the necessary branches and jumps (edges of DFA). */ - transitions_ptr = compiler_common->dfa_transitions + compiler_common->dfa_size; - while (stack->count > 0) { - item = stack_pop(stack); - switch (item->type) { - case type_begin: - case type_open_br: - item = stack_pop(depth); - if (item->type == type_select) - PUT_TRANSITION(type_branch, item->value + 1); - else - SLJIT_ASSERT(item->type == type_close_br); - if (stack->count == 0) - PUT_TRANSITION(type_begin, 0); - else - transitions_ptr = handle_iteratives(transitions_ptr, compiler_common->dfa_transitions, depth); - break; - - case type_end: - case type_close_br: - if (item->type == type_end) - *--transitions_ptr = *item; - if (stack_push(depth, type_close_br, (int)(transitions_ptr - compiler_common->dfa_transitions))) - return REGEX_MEMORY_ERROR; - break; - - case type_select: - item = stack_top(depth); - if (item->type == type_select) { - SLJIT_ASSERT(compiler_common->dfa_transitions[item->value].type == type_jump); - PUT_TRANSITION(type_branch, item->value + 1); - PUT_TRANSITION(type_jump, item->value); - item->value = (int)(transitions_ptr - compiler_common->dfa_transitions); - } - else { - SLJIT_ASSERT(item->type == type_close_br); - item->type = type_select; - PUT_TRANSITION(type_jump, item->value); - item->value = (int)(transitions_ptr - compiler_common->dfa_transitions); - } - break; - - case type_asterisk: - case type_plus_sign: - case type_qestion_mark: - if (item->type != type_qestion_mark) - PUT_TRANSITION(type_branch, 0); - if (stack_push(depth, item->type, (int)(transitions_ptr - compiler_common->dfa_transitions))) - return REGEX_MEMORY_ERROR; - break; - - case type_char: - case type_newline: - case type_rng_start: - /* Requires handle_iteratives. */ - *--transitions_ptr = *item; - transitions_ptr = handle_iteratives(transitions_ptr, compiler_common->dfa_transitions, depth); - break; - - default: - *--transitions_ptr = *item; - break; - } - } - - SLJIT_ASSERT(compiler_common->dfa_transitions == transitions_ptr); - SLJIT_ASSERT(depth->count == 0); - return REGEX_NO_ERROR; -} - -#undef PUT_TRANSITION - -#ifdef REGEX_MATCH_VERBOSE - -static void verbose_transitions(struct compiler_common *compiler_common) -{ - struct stack_item *transitions_ptr = compiler_common->dfa_transitions; - struct stack_item *transitions_end = transitions_ptr + compiler_common->dfa_size; - struct stack_item *search_states_ptr = compiler_common->search_states; - int pos; - - printf("-----------------\nTransitions\n-----------------\n"); - pos = 0; - while (transitions_ptr < transitions_end) { - printf("[%3d] ", pos++); - if (search_states_ptr->type >= 0) - printf("(%3d) ", search_states_ptr->type); - switch (transitions_ptr->type) { - case type_begin: - printf("type_begin\n"); - break; - - case type_end: - printf("type_end\n"); - break; - - case type_char: - if (transitions_ptr->value >= ' ') - printf("type_char '%c'\n", transitions_ptr->value); - else - printf("type_char 0x%x\n", transitions_ptr->value); - break; - - case type_newline: - printf("type_newline %s\n", transitions_ptr->value ? "(end)" : "(begin)"); - break; - - case type_id: - printf("type_id %d\n", transitions_ptr->value); - break; - - case type_rng_start: - printf("type_rng_start %s\n", transitions_ptr->value ? "(invert)" : "(normal)"); - break; - - case type_rng_end: - printf("type_rng_end\n"); - break; - - case type_rng_char: - if (transitions_ptr->value >= ' ') - printf("type_rng_char '%c'\n", transitions_ptr->value); - else - printf("type_rng_char 0x%x\n", transitions_ptr->value); - break; - - case type_rng_left: - if (transitions_ptr->value >= ' ') - printf("type_rng_left '%c'\n", transitions_ptr->value); - else - printf("type_rng_left 0x%x\n", transitions_ptr->value); - break; - - case type_rng_right: - if (transitions_ptr->value >= ' ') - printf("type_rng_right '%c'\n", transitions_ptr->value); - else - printf("type_rng_right 0x%x\n", transitions_ptr->value); - break; - - case type_branch: - printf("type_branch -> %d\n", transitions_ptr->value); - break; - - case type_jump: - printf("type_jump -> %d\n", transitions_ptr->value); - break; - - default: - printf("UNEXPECTED TYPE\n"); - break; - } - transitions_ptr++; - search_states_ptr++; - } - printf("flags: "); - if (!(compiler_common->flags & (REGEX_MATCH_BEGIN | REGEX_MATCH_END | REGEX_NEWLINE | REGEX_ID_CHECK | REGEX_FAKE_MATCH_BEGIN | REGEX_FAKE_MATCH_END))) - printf("none "); - if (compiler_common->flags & REGEX_MATCH_BEGIN) - printf("REGEX_MATCH_BEGIN "); - if (compiler_common->flags & REGEX_MATCH_END) - printf("REGEX_MATCH_END "); - if (compiler_common->flags & REGEX_NEWLINE) - printf("REGEX_NEWLINE "); - if (compiler_common->flags & REGEX_ID_CHECK) - printf("REGEX_ID_CHECK "); - if (compiler_common->flags & REGEX_FAKE_MATCH_BEGIN) - printf("REGEX_FAKE_MATCH_BEGIN "); - if (compiler_common->flags & REGEX_FAKE_MATCH_END) - printf("REGEX_FAKE_MATCH_END "); - if (compiler_common->longest_range_size > 0) - printf("(longest range: %ld) ", (long)compiler_common->longest_range_size); - printf("\n"); -} - -#endif - -/* --------------------------------------------------------------------- */ -/* Utilities */ -/* --------------------------------------------------------------------- */ - -static int generate_search_states(struct compiler_common *compiler_common) -{ - struct stack_item *transitions_ptr = compiler_common->dfa_transitions; - struct stack_item *transitions_end = transitions_ptr + compiler_common->dfa_size; - struct stack_item *search_states_ptr; - struct stack_item *rng_start = NULL; - - compiler_common->terms_size = !(compiler_common->flags & REGEX_FAKE_MATCH_END) ? 1 : 2; - compiler_common->longest_range_size = 0; - compiler_common->search_states = SLJIT_MALLOC(sizeof(struct stack_item) * compiler_common->dfa_size, NULL); - if (!compiler_common->search_states) - return REGEX_MEMORY_ERROR; - - search_states_ptr = compiler_common->search_states; - while (transitions_ptr < transitions_end) { - switch (transitions_ptr->type) { - case type_begin: - case type_end: - search_states_ptr->type = 0; - break; - - case type_char: - search_states_ptr->type = (int)compiler_common->terms_size++; - break; - - case type_newline: - if (transitions_ptr->value) - search_states_ptr->type = 1; - else - search_states_ptr->type = (int)compiler_common->terms_size++; - SLJIT_ASSERT(search_states_ptr->type == 1 || search_states_ptr->type == 2); - break; - - case type_id: - if (transitions_ptr->value > 0) - compiler_common->flags |= REGEX_ID_CHECK; - search_states_ptr->type = -1; - break; - - case type_rng_start: - search_states_ptr->type = (int)compiler_common->terms_size; - rng_start = search_states_ptr; - break; - - case type_rng_end: - search_states_ptr->type = (int)compiler_common->terms_size++; - /* This is an over estimation. */ - if (compiler_common->longest_range_size < search_states_ptr - rng_start) - compiler_common->longest_range_size = search_states_ptr - rng_start; - break; - - default: - search_states_ptr->type = -1; - break; - } - search_states_ptr->value = -1; - search_states_ptr++; - transitions_ptr++; - } - return REGEX_NO_ERROR; -} - -static int trace_transitions(int from, struct compiler_common *compiler_common) -{ - int id = 0; - struct stack *stack = &compiler_common->stack; - struct stack *depth = &compiler_common->depth; - struct stack_item *dfa_transitions = compiler_common->dfa_transitions; - struct stack_item *search_states = compiler_common->search_states; - - SLJIT_ASSERT(search_states[from].type >= 0); - - from++; - - /* Be prepared for any paths (loops, etc). */ - while (1) { - if (dfa_transitions[from].type == type_id) - if (id < dfa_transitions[from].value) - id = dfa_transitions[from].value; - - if (search_states[from].value < id) { - /* Forward step. */ - if (search_states[from].value == -1) - if (stack_push(stack, 0, from)) - return REGEX_MEMORY_ERROR; - search_states[from].value = id; - - if (dfa_transitions[from].type == type_branch) { - if (stack_push(depth, id, from)) - return REGEX_MEMORY_ERROR; - from++; - continue; - } - else if (dfa_transitions[from].type == type_jump) { - from = dfa_transitions[from].value; - continue; - } - else if (search_states[from].type < 0) { - from++; - continue; - } - } - - /* Back tracking. */ - if (depth->count > 0) { - id = stack_top(depth)->type; - from = dfa_transitions[stack_pop(depth)->value].value; - continue; - } - return 0; - } -} - -/* --------------------------------------------------------------------- */ -/* Code generator */ -/* --------------------------------------------------------------------- */ - -#define TERM_OFFSET_OF(index, offs) (((index) * no_states + (offs)) * (sljit_sw)sizeof(sljit_sw)) -#define TERM_REL_OFFSET_OF(base, offs) ((base) + ((offs) * (sljit_sw)sizeof(sljit_sw))) - -#define EMIT_OP1(type, arg1, arg2, arg3, arg4) \ - CHECK(sljit_emit_op1(compiler, type, arg1, arg2, arg3, arg4)) - -#define EMIT_OP2(type, arg1, arg2, arg3, arg4, arg5, arg6) \ - CHECK(sljit_emit_op2(compiler, type, arg1, arg2, arg3, arg4, arg5, arg6)) - -#define EMIT_OP2U(type, arg1, arg2, arg3, arg4) \ - CHECK(sljit_emit_op2u(compiler, type, arg1, arg2, arg3, arg4)) - -#define EMIT_LABEL(label) \ - label = sljit_emit_label(compiler); \ - CHECK(!label) - -#define EMIT_JUMP(jump, type) \ - jump = sljit_emit_jump(compiler, type); \ - CHECK(!jump) - -#define EMIT_CMP(jump, type, arg1, arg2, arg3, arg4) \ - jump = sljit_emit_cmp(compiler, type, arg1, arg2, arg3, arg4); \ - CHECK(!jump) - -/* CHECK depends on the use case. */ - -#define CHECK(exp) \ - if (SLJIT_UNLIKELY(exp)) \ - return REGEX_MEMORY_ERROR - -static int compile_uncond_tran(struct compiler_common *compiler_common, int reg) -{ - struct sljit_compiler *compiler = compiler_common->compiler; - struct stack *stack = &compiler_common->stack; - struct stack_item *search_states = compiler_common->search_states; - int flags = compiler_common->flags; - sljit_sw no_states = compiler_common->no_states; - sljit_sw head = 0; - sljit_sw offset, value; - - if (reg != R_CURR_STATE || !(compiler_common->flags & REGEX_FAKE_MATCH_BEGIN)) { - CHECK(trace_transitions(0, compiler_common)); - } - else { - CHECK(trace_transitions(1, compiler_common)); - } - - while (stack->count > 0) { - value = stack_pop(stack)->value; - if (search_states[value].type >= 0) { - offset = TERM_OFFSET_OF(search_states[value].type, 0); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 1), SLJIT_IMM, head); - if (offset > 0) - head = offset; - - if (!(flags & REGEX_MATCH_BEGIN)) { - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 2), R_TEMP, 0); - if (flags & REGEX_ID_CHECK) { - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 3), SLJIT_IMM, search_states[value].value); - } - } - else if (flags & REGEX_ID_CHECK) { - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 2), SLJIT_IMM, search_states[value].value); - } - } - search_states[value].value = -1; - } - if (reg == R_NEXT_STATE) { - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_NEXT_HEAD, 0); - } - else if (flags & REGEX_FAKE_MATCH_BEGIN) { - SLJIT_ASSERT(compiler_common->dfa_transitions[1].type == type_newline && !compiler_common->dfa_transitions[1].value); - offset = TERM_OFFSET_OF(search_states[1].type, 0); - - SLJIT_ASSERT(!(flags & REGEX_MATCH_BEGIN)); - - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 1), SLJIT_IMM, head); - head = offset; - - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 2), SLJIT_IMM, 1); - if (flags & REGEX_ID_CHECK) { - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(reg), TERM_REL_OFFSET_OF(offset, 3), SLJIT_IMM, 0); - } - } - EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, head); - return REGEX_NO_ERROR; -} - -static int compile_cond_tran(struct compiler_common *compiler_common, sljit_sw curr_index) -{ - struct sljit_compiler *compiler = compiler_common->compiler; - struct stack *stack = &compiler_common->stack; - struct stack_item *search_states = compiler_common->search_states; - sljit_sw offset; - int flags; - sljit_sw no_states; - sljit_sw value; - struct sljit_jump *jump1; - struct sljit_jump *jump2; - struct sljit_jump *jump3; - struct sljit_jump *jump4; - struct sljit_jump *jump5; - struct sljit_label *label1; - - flags = compiler_common->flags; - no_states = compiler_common->no_states; - - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_forward), SLJIT_IMM, 0); - if (!(flags & (REGEX_ID_CHECK | REGEX_MATCH_BEGIN))) { - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 2)); - } - - while (stack->count > 0) { - value = stack_pop(stack)->value; - if (search_states[value].type >= 0) { -#ifdef REGEX_MATCH_VERBOSE - if (flags & REGEX_MATCH_VERBOSE) - printf("-> (%3d:%3d) ", search_states[value].type, search_states[value].value); -#endif - offset = TERM_OFFSET_OF(search_states[value].type, 0); - - if (!(flags & REGEX_ID_CHECK)) { - if (!(flags & REGEX_MATCH_BEGIN)) { - /* Check whether item is inserted. */ - EMIT_CMP(jump1, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + (sljit_sw)sizeof(sljit_sw), SLJIT_IMM, -1); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + (sljit_sw)sizeof(sljit_sw), R_NEXT_HEAD, 0); - if (offset > 0) { - EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, offset); - } - EMIT_JUMP(jump2, SLJIT_JUMP); - - /* Check whether old index <= index. */ - EMIT_LABEL(label1); - sljit_set_label(jump1, label1); - - EMIT_CMP(jump1, SLJIT_LESS_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * (sljit_sw)sizeof(sljit_sw), R_TEMP, 0); - - EMIT_LABEL(label1); - sljit_set_label(jump2, label1); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * (sljit_sw)sizeof(sljit_sw), R_TEMP, 0); - - EMIT_LABEL(label1); - sljit_set_label(jump1, label1); - } - else { - /* Check whether item is inserted. */ - EMIT_CMP(jump1, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + (sljit_sw)sizeof(sljit_sw), SLJIT_IMM, -1); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + (sljit_sw)sizeof(sljit_sw), R_NEXT_HEAD, 0); - if (offset > 0) { - EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, offset); - } - EMIT_LABEL(label1); - sljit_set_label(jump1, label1); - } - } - else { - if (!(flags & REGEX_MATCH_BEGIN)) { - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 2)); - - /* Check whether item is inserted. */ - EMIT_CMP(jump1, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + (sljit_sw)sizeof(sljit_sw), SLJIT_IMM, -1); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + (sljit_sw)sizeof(sljit_sw), R_NEXT_HEAD, 0); - if (offset > 0) { - EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, offset); - } - EMIT_JUMP(jump2, SLJIT_JUMP); - - /* Check whether old index != index. */ - EMIT_LABEL(label1); - sljit_set_label(jump1, label1); - - EMIT_OP2U(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * (sljit_sw)sizeof(sljit_sw), R_TEMP, 0); - EMIT_JUMP(jump1, SLJIT_LESS); - EMIT_JUMP(jump3, SLJIT_NOT_EQUAL); /* Greater. */ - - /* Old index == index. */ - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 3)); - if (search_states[value].value > 0) { - EMIT_CMP(jump4, SLJIT_GREATER, R_TEMP, 0, SLJIT_IMM, search_states[value].value); - - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_IMM, search_states[value].value); - EMIT_LABEL(label1); - sljit_set_label(jump4, label1); - } - - EMIT_OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + 3 * (sljit_sw)sizeof(sljit_sw), R_TEMP, 0); - EMIT_JUMP(jump4, SLJIT_GREATER_EQUAL); - EMIT_JUMP(jump5, SLJIT_JUMP); - - /* Overwrite index & id. */ - EMIT_LABEL(label1); - sljit_set_label(jump3, label1); - sljit_set_label(jump2, label1); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * (sljit_sw)sizeof(sljit_sw), R_TEMP, 0); - - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 3)); - if (search_states[value].value > 0) { - EMIT_CMP(jump3, SLJIT_GREATER, R_TEMP, 0, SLJIT_IMM, search_states[value].value); - - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_IMM, search_states[value].value); - EMIT_LABEL(label1); - sljit_set_label(jump3, label1); - } - - EMIT_LABEL(label1); - sljit_set_label(jump5, label1); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + 3 * (sljit_sw)sizeof(sljit_sw), R_TEMP, 0); - - /* Exit. */ - EMIT_LABEL(label1); - sljit_set_label(jump1, label1); - sljit_set_label(jump4, label1); - } - else { - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(curr_index, 2)); - - if (search_states[value].value > 0) { - EMIT_CMP(jump1, SLJIT_GREATER, R_TEMP, 0, SLJIT_IMM, search_states[value].value); - - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_IMM, search_states[value].value); - EMIT_LABEL(label1); - sljit_set_label(jump1, label1); - } - - /* Check whether item is inserted. */ - EMIT_CMP(jump1, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + (sljit_sw)sizeof(sljit_sw), SLJIT_IMM, -1); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + (sljit_sw)sizeof(sljit_sw), R_NEXT_HEAD, 0); - if (offset > 0) { - EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, offset); - } - EMIT_JUMP(jump2, SLJIT_JUMP); - - /* Check whether old id >= id. */ - EMIT_LABEL(label1); - sljit_set_label(jump1, label1); - - EMIT_CMP(jump1, SLJIT_GREATER_EQUAL, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * (sljit_sw)sizeof(sljit_sw), R_TEMP, 0); - - EMIT_LABEL(label1); - sljit_set_label(jump2, label1); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), offset + 2 * (sljit_sw)sizeof(sljit_sw), R_TEMP, 0); - - EMIT_LABEL(label1); - sljit_set_label(jump1, label1); - } - } - } - search_states[value].value = -1; - } - -#ifdef REGEX_MATCH_VERBOSE - if (flags & REGEX_MATCH_VERBOSE) - printf("\n"); -#endif - return REGEX_NO_ERROR; -} - -static int compile_end_check(struct compiler_common *compiler_common, struct sljit_label *end_check_label) -{ - struct sljit_compiler *compiler = compiler_common->compiler; - struct sljit_jump *jump; - struct sljit_jump *clear_states_jump; - struct sljit_label *label; - struct sljit_label *leave_label; - struct sljit_label *begin_loop_label; - - /* Priority order: best_begin > best_end > best_id. - In other words: - if (new best_begin > old test_begin) do nothing - otherwise we know that new_end > old_end, since R_CURR_INDEX ever increasing - therefore we must overwrite all best_* variables (new_id also contains the highest id for this turn). */ - - /* Both R_CURR_CHAR and R_BEST_BEGIN used as temporary registers. */ - - if (!(compiler_common->flags & REGEX_MATCH_BEGIN)) { - EMIT_OP1(SLJIT_MOV, R_CURR_CHAR, 0, SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 2)); - EMIT_CMP(jump, !(compiler_common->flags & REGEX_MATCH_NON_GREEDY) ? SLJIT_LESS : SLJIT_LESS_EQUAL, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin), R_CURR_CHAR, 0); - sljit_set_label(jump, end_check_label); - - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin), R_CURR_CHAR, 0); - if (!(compiler_common->flags & (REGEX_FAKE_MATCH_BEGIN | REGEX_FAKE_MATCH_END))) { - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0); - } - else { - if ((compiler_common->flags & (REGEX_FAKE_MATCH_BEGIN | REGEX_FAKE_MATCH_END)) == (REGEX_FAKE_MATCH_BEGIN | REGEX_FAKE_MATCH_END)) { - EMIT_OP2(SLJIT_SUB, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0, SLJIT_IMM, 2); - } - else { - EMIT_OP2(SLJIT_SUB, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0, SLJIT_IMM, 1); - } - } - if (compiler_common->flags & REGEX_ID_CHECK) { - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 3)); - } - - EMIT_CMP(clear_states_jump, SLJIT_LESS, R_CURR_CHAR, 0, R_BEST_BEGIN, 0); - - EMIT_LABEL(leave_label); - EMIT_OP1(SLJIT_MOV, R_BEST_BEGIN, 0, R_CURR_CHAR, 0); - EMIT_JUMP(jump, SLJIT_JUMP); - sljit_set_label(jump, end_check_label); - - /* A loop to clear all states, which are > (or >=) than R_CURR_CHAR. */ - EMIT_LABEL(label); - sljit_set_label(clear_states_jump, label); - - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_NEXT_HEAD, 0); - EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, 0); - - /* Begin of the loop. */ - EMIT_LABEL(begin_loop_label); - EMIT_CMP(jump, SLJIT_EQUAL, R_TEMP, 0, SLJIT_IMM, 0); - sljit_set_label(jump, leave_label); - - EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, R_CURR_STATE, 0); - EMIT_OP1(SLJIT_MOV, R_BEST_BEGIN, 0, SLJIT_MEM1(R_TEMP), sizeof(sljit_sw)); - EMIT_CMP(clear_states_jump, !(compiler_common->flags & REGEX_MATCH_NON_GREEDY) ? SLJIT_GREATER : SLJIT_GREATER_EQUAL, SLJIT_MEM1(R_TEMP), 2 * sizeof(sljit_sw), R_CURR_CHAR, 0); - - /* Case 1: keep this case. */ - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_TEMP), sizeof(sljit_sw), R_NEXT_HEAD, 0); - EMIT_OP2(SLJIT_SUB, R_NEXT_HEAD, 0, R_TEMP, 0, R_CURR_STATE, 0); - - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_BEST_BEGIN, 0); - EMIT_JUMP(jump, SLJIT_JUMP); - sljit_set_label(jump, begin_loop_label); - - /* Case 2: remove this case. */ - EMIT_LABEL(label); - sljit_set_label(clear_states_jump, label); - - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_TEMP), sizeof(sljit_sw), SLJIT_IMM, -1); - - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_BEST_BEGIN, 0); - EMIT_JUMP(jump, SLJIT_JUMP); - sljit_set_label(jump, begin_loop_label); - } - else { - EMIT_OP1(SLJIT_MOV, R_BEST_BEGIN, 0, SLJIT_IMM, 0); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin), SLJIT_IMM, 0); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0); - if (compiler_common->flags & REGEX_ID_CHECK) { - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 2)); - } - EMIT_JUMP(jump, SLJIT_JUMP); - sljit_set_label(jump, end_check_label); - } - return REGEX_NO_ERROR; -} - -static int compile_leave_fast_forward(struct compiler_common *compiler_common, struct sljit_label *fast_forward_label) -{ - struct sljit_compiler *compiler = compiler_common->compiler; - struct stack *stack = &compiler_common->stack; - struct stack_item *dfa_transitions = compiler_common->dfa_transitions; - struct stack_item *search_states = compiler_common->search_states; - int ind; - struct sljit_jump *jump; - int init_range = 1, prev_value = 0; - - while (stack->count > 0) { - ind = stack_pop(stack)->value; - search_states[ind].value = -1; - if (search_states[ind].type >= 0) { - if (dfa_transitions[ind].type == type_char) { - EMIT_CMP(jump, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, dfa_transitions[ind].value); - sljit_set_label(jump, fast_forward_label); - } - else if (dfa_transitions[ind].type == type_rng_start) { - SLJIT_ASSERT(!dfa_transitions[ind].value); - ind++; - while (dfa_transitions[ind].type != type_rng_end) { - if (dfa_transitions[ind].type == type_rng_char) { - EMIT_CMP(jump, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, dfa_transitions[ind].value); - sljit_set_label(jump, fast_forward_label); - } - else { - SLJIT_ASSERT(dfa_transitions[ind].type == type_rng_left); - if (init_range) { - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_CURR_CHAR, 0); - init_range = 0; - } - if (dfa_transitions[ind].value != prev_value) { - /* Best compatibility to all archs. */ - prev_value -= dfa_transitions[ind].value; - if (prev_value < 0) { - EMIT_OP2(SLJIT_SUB, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, -prev_value); - } - else { - EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, prev_value); - } - prev_value = dfa_transitions[ind].value; - } - EMIT_CMP(jump, SLJIT_LESS_EQUAL, R_TEMP, 0, SLJIT_IMM, dfa_transitions[ind + 1].value - dfa_transitions[ind].value); - sljit_set_label(jump, fast_forward_label); - ind++; - } - ind++; - } - } - else { - SLJIT_ASSERT(dfa_transitions[ind].type == type_newline); - EMIT_CMP(jump, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, '\n'); - sljit_set_label(jump, fast_forward_label); - EMIT_CMP(jump, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, '\r'); - sljit_set_label(jump, fast_forward_label); - } - } - } - return REGEX_NO_ERROR; -} - -static int compile_newline_check(struct compiler_common *compiler_common, sljit_sw ind) -{ - struct sljit_compiler *compiler = compiler_common->compiler; - struct sljit_jump *jump1; - struct sljit_jump *jump2; - struct sljit_label *label; - sljit_sw no_states; - sljit_sw offset; - - /* Check whether a new-line character is found. */ - EMIT_CMP(jump1, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, '\n'); - EMIT_CMP(jump2, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, '\r'); - - no_states = compiler_common->no_states; - offset = TERM_OFFSET_OF(compiler_common->search_states[ind].type, 1); - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), offset); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_CURR_STATE), offset, SLJIT_IMM, -1); - CHECK(sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0)); - - EMIT_LABEL(label); - sljit_set_label(jump1, label); - sljit_set_label(jump2, label); - return REGEX_NO_ERROR; -} - -#undef CHECK - -#define CHECK(exp) \ - if (SLJIT_UNLIKELY(exp)) \ - return 0 - -static SLJIT_INLINE void range_set_label(struct sljit_jump **range_jump_list, struct sljit_label *label) -{ - while (*range_jump_list) { - sljit_set_label(*range_jump_list, label); - range_jump_list++; - } -} - -static sljit_sw compile_range_check(struct compiler_common *compiler_common, sljit_sw ind) -{ - struct sljit_compiler *compiler = compiler_common->compiler; - struct stack_item *dfa_transitions = compiler_common->dfa_transitions; - struct sljit_jump **range_jump_list = compiler_common->range_jump_list; - int invert = dfa_transitions[ind].value; - struct sljit_label *label; - sljit_sw no_states; - sljit_sw offset; - int init_range = 1, prev_value = 0; - - ind++; - - while (dfa_transitions[ind].type != type_rng_end) { - if (dfa_transitions[ind].type == type_rng_char) { - EMIT_CMP(*range_jump_list, SLJIT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, dfa_transitions[ind].value); - range_jump_list++; - } - else { - SLJIT_ASSERT(dfa_transitions[ind].type == type_rng_left); - if (init_range) { - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_CURR_CHAR, 0); - init_range = 0; - } - if (dfa_transitions[ind].value != prev_value) { - /* Best compatibility to all archs. */ - prev_value -= dfa_transitions[ind].value; - if (prev_value < 0) { - EMIT_OP2(SLJIT_SUB, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, -prev_value); - } - else { - EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, prev_value); - } - prev_value = dfa_transitions[ind].value; - } - EMIT_CMP(*range_jump_list, SLJIT_LESS_EQUAL, R_TEMP, 0, SLJIT_IMM, dfa_transitions[ind + 1].value - dfa_transitions[ind].value); - range_jump_list++; - ind++; - } - ind++; - } - - *range_jump_list = NULL; - - if (!invert) { - no_states = compiler_common->no_states; - offset = TERM_OFFSET_OF(compiler_common->search_states[ind].type, 1); - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), offset); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_CURR_STATE), offset, SLJIT_IMM, -1); - CHECK(sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0)); - - EMIT_LABEL(label); - range_set_label(compiler_common->range_jump_list, label); - /* Clears the jump list. */ - *compiler_common->range_jump_list = NULL; - } - return ind; -} - -#undef TERM_OFFSET_OF -#undef EMIT_OP1 -#undef EMIT_OP2 -#undef EMIT_LABEL -#undef EMIT_JUMP -#undef EMIT_CMP -#undef CHECK - -/* --------------------------------------------------------------------- */ -/* Main compiler */ -/* --------------------------------------------------------------------- */ - -#define TERM_OFFSET_OF(ind, offs) (((ind) * compiler_common.no_states + (offs)) * (sljit_sw)sizeof(sljit_sw)) - -#define EMIT_OP1(type, arg1, arg2, arg3, arg4) \ - CHECK(sljit_emit_op1(compiler_common.compiler, type, arg1, arg2, arg3, arg4)) - -#define EMIT_OP2(type, arg1, arg2, arg3, arg4, arg5, arg6) \ - CHECK(sljit_emit_op2(compiler_common.compiler, type, arg1, arg2, arg3, arg4, arg5, arg6)) - -#define EMIT_LABEL(label) \ - label = sljit_emit_label(compiler_common.compiler); \ - CHECK(!label) - -#define EMIT_JUMP(jump, type) \ - jump = sljit_emit_jump(compiler_common.compiler, type); \ - CHECK(!jump) - -#define EMIT_CMP(jump, type, arg1, arg2, arg3, arg4) \ - jump = sljit_emit_cmp(compiler_common.compiler, type, arg1, arg2, arg3, arg4); \ - CHECK(!jump) - -/* A do {} while(0) expression helps to avoid goto statements. */ -#define BEGIN_GUARD \ - do { - -#define END_GUARD \ - } while(0); - -#define CHECK(exp) \ - if (SLJIT_UNLIKELY(exp)) \ - break; - -struct regex_machine* regex_compile(const regex_char_t *regex_string, int length, int re_flags, int *error) -{ - struct compiler_common compiler_common; - sljit_sw ind; - int error_code, done, suggest_fast_forward; - /* ID of an empty match (-1 if not reachable). */ - int empty_match_id; - - struct sljit_jump *jump; - struct sljit_jump *best_match_found_jump; - struct sljit_jump *fast_forward_jump = NULL; - struct sljit_jump *length_is_zero_jump; - struct sljit_jump *end_check_jump = NULL; - struct sljit_jump *best_match_check_jump = NULL; - struct sljit_jump *non_greedy_end_jump = NULL; - struct sljit_label *label; - struct sljit_label *end_check_label = NULL; - struct sljit_label *start_label; - struct sljit_label *fast_forward_label; - struct sljit_label *fast_forward_return_label; - - if (error) - *error = REGEX_NO_ERROR; -#ifdef REGEX_MATCH_VERBOSE - compiler_common.flags = re_flags & (REGEX_MATCH_BEGIN | REGEX_MATCH_END | REGEX_MATCH_NON_GREEDY | REGEX_NEWLINE | REGEX_MATCH_VERBOSE); -#else - compiler_common.flags = re_flags & (REGEX_MATCH_BEGIN | REGEX_MATCH_END | REGEX_MATCH_NON_GREEDY | REGEX_NEWLINE); -#endif - - /* Step 1: parsing (Left->Right). - Syntax check and AST generator. */ - error_code = parse(regex_string, length, &compiler_common); - if (error_code) { - stack_destroy(&compiler_common.stack); - if (error) - *error = error_code; - return NULL; - } - - /* Step 2: generating branches (Right->Left). */ - error_code = generate_transitions(&compiler_common); - stack_destroy(&compiler_common.stack); - stack_destroy(&compiler_common.depth); - if (error_code) { - if (compiler_common.dfa_transitions) - SLJIT_FREE(compiler_common.dfa_transitions, NULL); - if (error) - *error = error_code; - return NULL; - } - - /* Step 3: Generate necessary data for depth-first search (Left->Right). */ - error_code = generate_search_states(&compiler_common); - if (error_code) { - SLJIT_FREE(compiler_common.dfa_transitions, NULL); - if (error) - *error = error_code; - return NULL; - } - -#ifdef REGEX_MATCH_VERBOSE - if (compiler_common.flags & REGEX_MATCH_VERBOSE) - verbose_transitions(&compiler_common); -#endif - - /* Step 4: Left->Right generate code. */ - stack_init(&compiler_common.stack); - stack_init(&compiler_common.depth); - done = 0; - compiler_common.machine = NULL; - compiler_common.compiler = NULL; - compiler_common.range_jump_list = NULL; - - BEGIN_GUARD - - compiler_common.machine = (struct regex_machine*)SLJIT_MALLOC(sizeof(struct regex_machine) + (sljit_uw)(compiler_common.terms_size - 1) * sizeof(sljit_uw), NULL); - CHECK(!compiler_common.machine); - - compiler_common.compiler = sljit_create_compiler(NULL, NULL); - CHECK(!compiler_common.compiler); - - if (compiler_common.longest_range_size > 0) { - compiler_common.range_jump_list = (struct sljit_jump**)SLJIT_MALLOC(sizeof(struct sljit_jump*) * (sljit_uw)compiler_common.longest_range_size, NULL); - CHECK(!compiler_common.range_jump_list); - } - - if ((compiler_common.flags & REGEX_ID_CHECK) && !(compiler_common.flags & REGEX_MATCH_BEGIN)) - compiler_common.no_states = 4; - else if (!(compiler_common.flags & REGEX_ID_CHECK) && (compiler_common.flags & REGEX_MATCH_BEGIN)) - compiler_common.no_states = 2; - else - compiler_common.no_states = 3; - - compiler_common.machine->flags = compiler_common.flags; - compiler_common.machine->no_states = compiler_common.no_states; - compiler_common.machine->size = compiler_common.machine->no_states * compiler_common.terms_size; - - /* Study the regular expression. */ - empty_match_id = -1; - suggest_fast_forward = 1; - if (!(compiler_common.flags & REGEX_FAKE_MATCH_BEGIN)) { - CHECK(trace_transitions(0, &compiler_common)); - while (compiler_common.stack.count > 0) { - ind = stack_pop(&compiler_common.stack)->value; - if (compiler_common.search_states[ind].type == 0) { - SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type == type_end); - suggest_fast_forward = 0; - empty_match_id = compiler_common.search_states[ind].value; - } - else if (compiler_common.search_states[ind].type > 0) { - SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type != type_end); - if (compiler_common.dfa_transitions[ind].type == type_rng_start && compiler_common.dfa_transitions[ind].value) - suggest_fast_forward = 0; - } - compiler_common.search_states[ind].value = -1; - } - } - else { - SLJIT_ASSERT(compiler_common.dfa_transitions[1].type == type_newline); - CHECK(trace_transitions(1, &compiler_common)); - while (compiler_common.stack.count > 0) { - ind = stack_pop(&compiler_common.stack)->value; - if (compiler_common.search_states[ind].type == 0) { - SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type == type_end); - suggest_fast_forward = 0; - empty_match_id = compiler_common.search_states[ind].value; - } - compiler_common.search_states[ind].value = -1; - } - } - - /* Step 4.1: Generate entry. */ - CHECK(sljit_emit_enter(compiler_common.compiler, 0, SLJIT_ARGS3(VOID, P, P, 32), 5, 5, 0, 0, 0)); - - /* Copy arguments to their place. */ - EMIT_OP1(SLJIT_MOV, R_REGEX_MATCH, 0, SLJIT_S0, 0); - EMIT_OP1(SLJIT_MOV, R_STRING, 0, SLJIT_S1, 0); - EMIT_OP2(SLJIT_ADD, R_LENGTH, 0, SLJIT_S2, 0, SLJIT_IMM, 1); - - /* Init global registers. */ - EMIT_OP1(SLJIT_MOV, R_CURR_STATE, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, current)); - EMIT_OP1(SLJIT_MOV, R_NEXT_STATE, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, next)); - EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, head)); - EMIT_OP1(SLJIT_MOV, R_BEST_BEGIN, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin)); - EMIT_OP1(SLJIT_MOV, R_CURR_INDEX, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, index)); - - /* Check whether the best match has already found in a previous frame. */ - EMIT_CMP(jump, SLJIT_EQUAL, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_quit), SLJIT_IMM, 0); - EMIT_JUMP(best_match_found_jump, SLJIT_JUMP); - -#ifdef REGEX_MATCH_VERBOSE - if (compiler_common.flags & REGEX_MATCH_VERBOSE) - printf("\n-----------------\nTrace\n-----------------\n"); -#endif - - /* Step 4.2: Generate code for state 0. */ - EMIT_LABEL(label); - sljit_emit_op0(compiler_common.compiler, SLJIT_ENDBR); - compiler_common.machine->entry_addrs[0] = (sljit_uw)label; - - /* Swapping current and next. */ - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_CURR_STATE, 0); - EMIT_OP1(SLJIT_MOV, R_CURR_STATE, 0, R_NEXT_STATE, 0); - EMIT_OP1(SLJIT_MOV, R_NEXT_STATE, 0, R_TEMP, 0); - - /* Checking whether the best case needs to be updated. */ - if (!(compiler_common.flags & REGEX_MATCH_END)) { - EMIT_CMP(end_check_jump, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 1), SLJIT_IMM, -1); - EMIT_LABEL(end_check_label); - } - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_NEXT_STATE), TERM_REL_OFFSET_OF(0, 1), SLJIT_IMM, -1); - EMIT_OP2(SLJIT_ADD, R_CURR_INDEX, 0, R_CURR_INDEX, 0, SLJIT_IMM, 1); - - /* Checking whether best case has already found. */ - if (!(compiler_common.flags & REGEX_MATCH_END) || (compiler_common.flags & REGEX_MATCH_BEGIN)) { - if (!(compiler_common.flags & REGEX_MATCH_BEGIN)) { - /* We can bail out if no more active states remain and R_BEST_BEGIN != -1. */ - EMIT_CMP(best_match_check_jump, SLJIT_NOT_EQUAL, R_BEST_BEGIN, 0, SLJIT_IMM, -1); - } - else { - /* We can bail out if no more active states remain (regardless of R_BEST_BEGIN). */ - EMIT_CMP(best_match_check_jump, SLJIT_EQUAL, R_NEXT_HEAD, 0, SLJIT_IMM, 0); - } - } - - EMIT_LABEL(start_label); - sljit_set_label(jump, start_label); - - if (!(compiler_common.flags & REGEX_MATCH_BEGIN) && suggest_fast_forward) { - EMIT_CMP(fast_forward_jump, SLJIT_NOT_EQUAL, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_forward), SLJIT_IMM, 0); - } - - /* Loading the next character. */ - EMIT_OP2(SLJIT_SUB | SLJIT_SET_Z, R_LENGTH, 0, R_LENGTH, 0, SLJIT_IMM, 1); - EMIT_JUMP(length_is_zero_jump, SLJIT_EQUAL); - - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_STRING, 0); -#ifdef REGEX_USE_8BIT_CHARS - EMIT_OP1(SLJIT_MOV_U8, R_CURR_CHAR, 0, SLJIT_MEM1(R_TEMP), 0); - EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, 1); -#else - EMIT_OP1(SLJIT_MOV_UH, R_CURR_CHAR, 0, SLJIT_MEM1(R_TEMP), 0); - EMIT_OP2(SLJIT_ADD, R_TEMP, 0, R_TEMP, 0, SLJIT_IMM, 2); -#endif - EMIT_OP1(SLJIT_MOV, R_STRING, 0, R_TEMP, 0); - -#ifdef REGEX_MATCH_VERBOSE - if (compiler_common.flags & REGEX_MATCH_VERBOSE) { - printf("(%3d): ", 0); - CHECK(trace_transitions(0, &compiler_common)); - while (compiler_common.stack.count > 0) { - ind = stack_pop(&compiler_common.stack)->value; - if (compiler_common.search_states[ind].type >= 0) - printf("-> (%3d:%3d) ", compiler_common.search_states[ind].type, compiler_common.search_states[ind].value); - compiler_common.search_states[ind].value = -1; - } - printf("\n"); - } -#endif - - EMIT_LABEL(fast_forward_return_label); - if (!(compiler_common.flags & REGEX_MATCH_BEGIN)) { - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_forward), SLJIT_IMM, 1); - if (!(compiler_common.flags & REGEX_MATCH_END)) { - EMIT_CMP(jump, SLJIT_NOT_EQUAL, R_BEST_BEGIN, 0, SLJIT_IMM, -1); - } - - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_CURR_INDEX, 0); - CHECK(compile_uncond_tran(&compiler_common, R_NEXT_STATE)); - /* And branching to the first state. */ - CHECK(sljit_emit_ijump(compiler_common.compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0)); - - if (!(compiler_common.flags & REGEX_MATCH_END)) { - EMIT_LABEL(label); - sljit_set_label(jump, label); - } - } - /* This is the case where we only have to reset the R_NEXT_HEAD. */ - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, R_NEXT_HEAD, 0); - EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, 0); - CHECK(sljit_emit_ijump(compiler_common.compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0)); - - /* Fast-forward loop. */ - if (fast_forward_jump) { - /* Quit from fast-forward loop. */ - EMIT_LABEL(fast_forward_label); - EMIT_OP2(SLJIT_SUB, R_TEMP, 0, R_NEXT_HEAD, 0, SLJIT_IMM, 1); - EMIT_OP1(SLJIT_MOV, R_LENGTH, 0, R_NEXT_STATE, 0); - EMIT_OP1(SLJIT_MOV, R_STRING, 0, R_CURR_STATE, 0); - EMIT_OP1(SLJIT_MOV, R_CURR_INDEX, 0, R_NEXT_HEAD, 0); - EMIT_OP1(SLJIT_MOV, R_NEXT_STATE, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, next)); - EMIT_OP1(SLJIT_MOV, R_CURR_STATE, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, current)); - EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, head)); - - /* Update the start field of the locations. */ - CHECK(trace_transitions(0, &compiler_common)); - while (compiler_common.stack.count > 0) { - ind = stack_pop(&compiler_common.stack)->value; - if (compiler_common.search_states[ind].type >= 0) { - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(compiler_common.search_states[ind].type, 2), R_TEMP, 0); - } - compiler_common.search_states[ind].value = -1; - } - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_forward), SLJIT_IMM, 0); - EMIT_JUMP(jump, SLJIT_JUMP); - sljit_set_label(jump, fast_forward_return_label); - - /* Start fast-forward. */ - EMIT_LABEL(label); - sljit_set_label(fast_forward_jump, label); - - /* Moving everything to registers. */ - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, next), R_NEXT_STATE, 0); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, current), R_CURR_STATE, 0); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, head), R_NEXT_HEAD, 0); - EMIT_OP1(SLJIT_MOV, R_NEXT_STATE, 0, R_LENGTH, 0); - EMIT_OP1(SLJIT_MOV, R_CURR_STATE, 0, R_STRING, 0); - EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, R_CURR_INDEX, 0); - - /* Fast forward mainloop. */ - EMIT_LABEL(label); - EMIT_OP2(SLJIT_SUB | SLJIT_SET_Z, R_NEXT_STATE, 0, R_NEXT_STATE, 0, SLJIT_IMM, 1); - EMIT_JUMP(fast_forward_jump, SLJIT_EQUAL); - -#ifdef REGEX_USE_8BIT_CHARS - EMIT_OP1(SLJIT_MOV_U8, R_CURR_CHAR, 0, SLJIT_MEM1(R_CURR_STATE), 0); - EMIT_OP2(SLJIT_ADD, R_CURR_STATE, 0, R_CURR_STATE, 0, SLJIT_IMM, 1); -#else - EMIT_OP1(SLJIT_MOV_UH, R_CURR_CHAR, 0, SLJIT_MEM1(R_CURR_STATE), 0); - EMIT_OP2(SLJIT_ADD, R_CURR_STATE, 0, R_CURR_STATE, 0, SLJIT_IMM, 2); -#endif - - CHECK(trace_transitions(0, &compiler_common)); - CHECK(compile_leave_fast_forward(&compiler_common, fast_forward_label)); - - EMIT_OP2(SLJIT_ADD, R_NEXT_HEAD, 0, R_NEXT_HEAD, 0, SLJIT_IMM, 1); - EMIT_JUMP(jump, SLJIT_JUMP); - sljit_set_label(jump, label); - - /* String is finished. */ - EMIT_LABEL(label); - sljit_set_label(fast_forward_jump, label); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, index), R_NEXT_HEAD, 0); - EMIT_JUMP(fast_forward_jump, SLJIT_JUMP); - } - - /* End check. */ - if (end_check_jump) { - EMIT_LABEL(label); - sljit_set_label(end_check_jump, label); - - if (!(compiler_common.flags & REGEX_MATCH_NON_GREEDY) || !(compiler_common.flags & REGEX_MATCH_BEGIN)) { - CHECK(compile_end_check(&compiler_common, end_check_label)); - } - else { - /* Since we leave, we do not need to update the R_BEST_BEGIN. */ - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_begin), SLJIT_IMM, 0); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_end), R_CURR_INDEX, 0); - if (compiler_common.flags & REGEX_ID_CHECK) { - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_MEM1(R_CURR_STATE), TERM_REL_OFFSET_OF(0, 2)); - } - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_quit), SLJIT_IMM, 1); - EMIT_JUMP(non_greedy_end_jump, SLJIT_JUMP); - } - } - - /* Finish check. */ - if (best_match_check_jump) { - EMIT_LABEL(label); - sljit_set_label(best_match_check_jump, label); - - if (!(compiler_common.flags & REGEX_MATCH_BEGIN)) { - EMIT_CMP(jump, SLJIT_NOT_EQUAL, R_NEXT_HEAD, 0, SLJIT_IMM, 0); - sljit_set_label(jump, start_label); - } - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, fast_quit), SLJIT_IMM, 1); - } - - /* Leaving matching and storing the necessary values. */ - EMIT_LABEL(label); - sljit_set_label(length_is_zero_jump, label); - if (non_greedy_end_jump) - sljit_set_label(non_greedy_end_jump, label); - - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, index), R_CURR_INDEX, 0); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, head), R_NEXT_HEAD, 0); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, next), R_NEXT_STATE, 0); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_REGEX_MATCH), SLJIT_OFFSETOF(struct regex_match, current), R_CURR_STATE, 0); - - /* Exit from JIT. */ - EMIT_LABEL(label); - sljit_set_label(best_match_found_jump, label); - if (fast_forward_jump) - sljit_set_label(fast_forward_jump, label); - CHECK(sljit_emit_return_void(compiler_common.compiler)); - - for (ind = 1; ind < (sljit_sw)compiler_common.dfa_size - 1; ind++) { - if (compiler_common.search_states[ind].type >= 0) { - SLJIT_ASSERT(compiler_common.search_states[ind].type < compiler_common.terms_size); - EMIT_LABEL(label); - sljit_emit_op0(compiler_common.compiler, SLJIT_ENDBR); - compiler_common.machine->entry_addrs[compiler_common.search_states[ind].type] = (sljit_uw)label; - - if (compiler_common.dfa_transitions[ind].type == type_char) { - EMIT_CMP(jump, SLJIT_NOT_EQUAL, R_CURR_CHAR, 0, SLJIT_IMM, compiler_common.dfa_transitions[ind].value); - } - else if (compiler_common.dfa_transitions[ind].type == type_rng_start) { - ind = compile_range_check(&compiler_common, ind); - CHECK(!ind); - } - else { - SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type == type_newline); - CHECK(compile_newline_check(&compiler_common, ind)); - } - - CHECK(trace_transitions((int)ind, &compiler_common)); -#ifdef REGEX_MATCH_VERBOSE - if (compiler_common.flags & REGEX_MATCH_VERBOSE) - printf("(%3d): ", compiler_common.search_states[ind].type); -#endif - CHECK(compile_cond_tran(&compiler_common, compiler_common.search_states[ind].type)); - - if (compiler_common.dfa_transitions[ind].type == type_char) { - EMIT_LABEL(label); - sljit_set_label(jump, label); - } - else if (compiler_common.dfa_transitions[ind].type == type_rng_end) { - EMIT_LABEL(label); - range_set_label(compiler_common.range_jump_list, label); - } - else { - SLJIT_ASSERT(compiler_common.dfa_transitions[ind].type == type_newline); - } - - /* Branch to the next item in the list. */ - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(compiler_common.search_states[ind].type, 1)); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(R_CURR_STATE), TERM_OFFSET_OF(compiler_common.search_states[ind].type, 1), SLJIT_IMM, -1); - CHECK(sljit_emit_ijump(compiler_common.compiler, SLJIT_JUMP, SLJIT_MEM2(R_CURR_STATE, R_TEMP), 0)); - } - } - - if (ind == (sljit_sw)compiler_common.dfa_size - 1) { - /* Generate an init stub function. */ - EMIT_LABEL(label); - CHECK(sljit_emit_enter(compiler_common.compiler, 0, SLJIT_ARGS2(W, P, P), 3, 3, 0, 0, 0)); - - if (empty_match_id == -1) { - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, best_begin), SLJIT_IMM, -1); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_IMM, 0); - } - else { - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, best_begin), SLJIT_IMM, 0); - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, best_id), SLJIT_IMM, empty_match_id); - } - - EMIT_OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), SLJIT_OFFSETOF(struct regex_match, index), SLJIT_IMM, !(compiler_common.flags & REGEX_FAKE_MATCH_BEGIN) ? 1 : 2); - - if (!(compiler_common.flags & REGEX_MATCH_NON_GREEDY) || empty_match_id == -1) { - /* The else is a really rare event, so we still generate an empty function instead of a runtime pointer check. */ - SLJIT_ASSERT(R_CURR_STATE == SLJIT_S0); - if (!(compiler_common.flags & REGEX_MATCH_BEGIN)) { - /* R_CURR_INDEX (put to R_TEMP) is zero. */ - EMIT_OP1(SLJIT_MOV, R_TEMP, 0, SLJIT_IMM, 0); - } - CHECK(compile_uncond_tran(&compiler_common, R_CURR_STATE)); - } - else { - EMIT_OP1(SLJIT_MOV, R_NEXT_HEAD, 0, SLJIT_IMM, 0); - } - CHECK(sljit_emit_return(compiler_common.compiler, SLJIT_MOV, R_NEXT_HEAD, 0)); - - compiler_common.machine->continue_match = sljit_generate_code(compiler_common.compiler); -#ifndef SLJIT_INDIRECT_CALL - compiler_common.machine->u.init_match = (void*)(sljit_sw)sljit_get_label_addr(label); -#else - sljit_set_function_context(&compiler_common.machine->u.init_match, &compiler_common.machine->context, sljit_get_label_addr(label), regex_compile); -#endif -#ifdef REGEX_MATCH_VERBOSE - if (compiler_common.flags & REGEX_MATCH_VERBOSE) - printf("Continue match: %p Init match: %p\n\n", compiler_common.machine->continue_match, compiler_common.machine->u.init_match); -#endif - if (compiler_common.machine->continue_match) { - for (ind = 0; ind < compiler_common.terms_size; ++ind) - compiler_common.machine->entry_addrs[ind] = sljit_get_label_addr((struct sljit_label*)compiler_common.machine->entry_addrs[ind]); - done = 1; - } - } - END_GUARD - - stack_destroy(&compiler_common.stack); - stack_destroy(&compiler_common.depth); - SLJIT_FREE(compiler_common.dfa_transitions, NULL); - SLJIT_FREE(compiler_common.search_states, NULL); - if (compiler_common.range_jump_list) - SLJIT_FREE(compiler_common.range_jump_list, NULL); - if (compiler_common.compiler) - sljit_free_compiler(compiler_common.compiler); - if (done) - return compiler_common.machine; - - if (compiler_common.machine) { - SLJIT_FREE(compiler_common.machine, NULL); - } - if (error) - *error = REGEX_MEMORY_ERROR; - return NULL; -} - -#undef TERM_OFFSET_OF -#undef EMIT_OP1 -#undef EMIT_OP2 -#undef EMIT_LABEL -#undef EMIT_JUMP -#undef EMIT_CMP -#undef BEGIN_GUARD -#undef END_GUARD -#undef CHECK - -void regex_free_machine(struct regex_machine *machine) -{ - sljit_free_code(machine->continue_match, NULL); - SLJIT_FREE(machine, NULL); -} - -const char* regex_get_platform_name(void) -{ - return sljit_get_platform_name(); -} - -/* --------------------------------------------------------------------- */ -/* Mathching utilities */ -/* --------------------------------------------------------------------- */ - -struct regex_match* regex_begin_match(struct regex_machine *machine) -{ - sljit_sw *ptr1; - sljit_sw *ptr2; - sljit_sw *end; - sljit_sw *entry_addrs; - - struct regex_match *match = (struct regex_match*)SLJIT_MALLOC(sizeof(struct regex_match) + (sljit_uw)(machine->size * 2 - 1) * sizeof(sljit_sw), NULL); - if (!match) - return NULL; - - ptr1 = match->states; - ptr2 = match->states + machine->size; - end = ptr2; - entry_addrs = (sljit_sw*)machine->entry_addrs; - - match->current = ptr1; - match->next = ptr2; - match->head = 0; - match->machine = machine; - - /* Init machine states. */ - switch (machine->no_states) { - case 2: - while (ptr1 < end) { - *ptr1++ = *entry_addrs; - *ptr2++ = *entry_addrs++; - *ptr1++ = -1; - *ptr2++ = -1; - } - break; - - case 3: - while (ptr1 < end) { - *ptr1++ = *entry_addrs; - *ptr2++ = *entry_addrs++; - *ptr1++ = -1; - *ptr2++ = -1; - *ptr1++ = 0; - *ptr2++ = 0; - } - break; - - case 4: - while (ptr1 < end) { - *ptr1++ = *entry_addrs; - *ptr2++ = *entry_addrs++; - *ptr1++ = -1; - *ptr2++ = -1; - *ptr1++ = 0; - *ptr2++ = 0; - *ptr1++ = 0; - *ptr2++ = 0; - } - break; - - default: - SLJIT_UNREACHABLE(); - break; - } - - SLJIT_ASSERT(ptr1 == end); - - match->u.continue_match = machine->continue_match; - - regex_reset_match(match); - return match; -} - -void regex_reset_match(struct regex_match *match) -{ - struct regex_machine *machine = match->machine; - sljit_sw current, ind; - sljit_sw *current_ptr; - - match->best_end = 0; - match->fast_quit = 0; - match->fast_forward = 0; - - if (match->head != 0) { - /* Clear the current state. */ - current = match->head; - current_ptr = match->current; - do { - ind = (current / (sljit_sw)sizeof(sljit_sw)) + 1; - current = current_ptr[ind]; - current_ptr[ind] = -1; - } while (current != 0); - } - match->head = machine->u.call_init(match->current, match); -} - -void regex_free_match(struct regex_match *match) -{ - SLJIT_FREE(match, NULL); -} - -void regex_continue_match(struct regex_match *match, const regex_char_t *input_string, int length) -{ - match->u.call_continue(match, input_string, length); -} - -int regex_get_result(struct regex_match *match, int *end, int *id) -{ - int flags = match->machine->flags; - sljit_sw no_states; - - *end = (int)match->best_end; - *id = (int)match->best_id; - if (!(flags & (REGEX_MATCH_END | REGEX_FAKE_MATCH_END))) - return (int)match->best_begin; - - if (flags & REGEX_FAKE_MATCH_END) { - SLJIT_ASSERT(!(flags & (REGEX_MATCH_BEGIN | REGEX_MATCH_END))); - if (match->best_begin != -1) - return (int)match->best_begin; - - no_states = match->machine->no_states; - if (match->current[no_states + 1] == -1) - return -1; - if (flags & REGEX_ID_CHECK) - *id = (int)match->current[no_states + 3]; - if (!(flags & REGEX_FAKE_MATCH_BEGIN)) - *end = (int)match->index - 1; - else - *end = (int)match->index - 2; - return (int)match->current[no_states + 2]; - } - else { - /* Check the status of the last code. */ - if (!(flags & REGEX_MATCH_BEGIN)) { - /* No shortcut in this case. */ - if (!(flags & REGEX_ID_CHECK)) { - if (match->current[1] == -1) - return -1; - *end = (int)match->index - 1; - return (int)match->current[2]; - } - - if (match->current[1] == -1) - return -1; - *end = (int)match->index - 1; - *id = (int)match->current[3]; - return (int)match->current[2]; - } - - /* Shortcut is possible in this case. */ - if (!(flags & REGEX_ID_CHECK)) { - if (match->current[1] == -1 || match->head == -1) - return -1; - *end = (int)match->index - 1; - return 0; - } - - if (match->current[1] == -1 || match->head == -1) - return -1; - *end = (int)match->index - 1; - *id = (int)match->current[2]; - return 0; - } -} - -int regex_is_match_finished(struct regex_match *match) -{ - return (int)match->fast_quit; -} - -#ifdef REGEX_MATCH_VERBOSE -void regex_continue_match_debug(struct regex_match *match, const regex_char_t *input_string, int length) -{ - sljit_sw *ptr; - sljit_sw *end; - sljit_sw count; -#if (defined SLJIT_DEBUG && SLJIT_DEBUG) - sljit_sw current; -#endif - sljit_sw no_states = match->machine->no_states; - sljit_sw len = match->machine->size; - - while (length > 0) { - match->u.call_continue(match, input_string, 1); - - if (match->fast_forward) { - if (match->machine->flags & REGEX_MATCH_VERBOSE) - printf("fast forward\n"); - } - - /* Verbose (first). */ - if (match->machine->flags & REGEX_MATCH_VERBOSE) { - ptr = match->current; - end = ptr + len; - count = 0; - printf("'%c' (%3ld->%3ld [%3ld]) ", *input_string, (long)match->best_begin, (long)match->best_end, (long)match->best_id); - while (ptr < end) { - printf("[%3ld:", (long)count++); - switch (no_states) { - case 2: - if (ptr[1] != -1) - printf("+] "); - else - printf(" ] "); - break; - - case 3: - if (ptr[1] != -1) - printf("+,%3ld] ", (long)ptr[2]); - else - printf(" ,XXX] "); - break; - - case 4: - if (ptr[1] != -1) - printf("+,%3ld,%3ld] ", (long)ptr[2], (long)ptr[3]); - else - printf(" ,XXX,XXX] "); - break; - } - ptr += no_states; - } - printf("\n"); - } - -#if (defined SLJIT_DEBUG && SLJIT_DEBUG) - /* Sanity check (later). */ - ptr = match->next; - end = ptr + len; - while (ptr < end) { - SLJIT_ASSERT(ptr[1] == -1); - ptr += no_states; - } - - /* Check number of active elements. */ - ptr = match->current + no_states; - end = ptr + len - no_states; - count = 0; - while (ptr < end) { - if (ptr[1] != -1) - count++; - ptr += no_states; - } - - /* Check chain list. */ - current = match->head; - ptr = match->current; - while (current != 0) { - SLJIT_ASSERT(current >= 0 && current < len * (sljit_sw)sizeof(sljit_sw)); - SLJIT_ASSERT((current % (no_states * (sljit_sw)sizeof(sljit_sw))) == 0); - SLJIT_ASSERT(count > 0); - current = ptr[(current / (sljit_sw)sizeof(sljit_sw)) + 1]; - count--; - } - SLJIT_ASSERT(count == 0); -#endif - - if (match->fast_quit) { - /* the machine has stopped working. */ - if (match->machine->flags & REGEX_MATCH_VERBOSE) - printf("Best match has found\n"); - break; - } - - input_string++; - length--; - } -} -#endif diff --git a/waterbox/ares64/ares/thirdparty/sljit/regex_src/regexJIT.h b/waterbox/ares64/ares/thirdparty/sljit/regex_src/regexJIT.h deleted file mode 100644 index 95c55ff05b4..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/regex_src/regexJIT.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Stack-less Just-In-Time compiler - * - * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _REGEX_JIT_H_ -#define _REGEX_JIT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Character type config. */ -#define REGEX_USE_8BIT_CHARS - -#ifdef REGEX_USE_8BIT_CHARS -typedef char regex_char_t; -#else -typedef wchar_t regex_char_t; -#endif - -/* Error codes. */ -#define REGEX_NO_ERROR 0 -#define REGEX_MEMORY_ERROR 1 -#define REGEX_INVALID_REGEX 2 - -/* Note: large, nested {a,b} iterations can blow up the memory consumption - a{n,m} is replaced by aa...aaa?a?a?a?a? (n >= 0, m > 0) - \__n__/\____m___/ - a{n,} is replaced by aa...aaa+ (n > 0) - \_n-1_/ -*/ - -/* The value returned by regex_compile. Can be used for multiple matching. */ -struct regex_machine; - -/* A matching state. */ -struct regex_match; - -/* Note: REGEX_MATCH_BEGIN and REGEX_MATCH_END does not change the parsing - (Hence ^ and $ are parsed normally). - Force matching to start from begining of the string (same as ^). */ -#define REGEX_MATCH_BEGIN 0x01 -/* Force matching to continue until the last character (same as $). */ -#define REGEX_MATCH_END 0x02 -/* Changes . to [^\r\n] - Note: [...] and [^...] are NOT affected at all (as other regex engines do). */ -#define REGEX_NEWLINE 0x04 -/* Non greedy matching. In case of Thompson (non-recursive) algorithm, - it (usually) does not have a significant speed gain. */ -#define REGEX_MATCH_NON_GREEDY 0x08 -/* Verbose. This define can be commented out, which disables all verbose features. */ -#define REGEX_MATCH_VERBOSE 0x10 - -/* If error occures the function returns NULL, and the error code returned in error variable. - You can pass NULL to error if you don't care about the error code. - The re_flags argument contains the default REGEX_MATCH flags. See above. */ -struct regex_machine* regex_compile(const regex_char_t *regex_string, int length, int re_flags, int *error); -void regex_free_machine(struct regex_machine *machine); - -/* Create and init match structure for a given machine. */ -struct regex_match* regex_begin_match(struct regex_machine *machine); -void regex_reset_match(struct regex_match *match); -void regex_free_match(struct regex_match *match); - -/* Pattern matching. - regex_continue_match does not support REGEX_MATCH_VERBOSE flag. */ -void regex_continue_match(struct regex_match *match, const regex_char_t *input_string, int length); -int regex_get_result(struct regex_match *match, int *end, int *id); -/* Returns true, if the best match has already found. */ -int regex_is_match_finished(struct regex_match *match); - -/* Only exists if VERBOSE is defined in regexJIT.c - Do both sanity check and verbose. - (The latter only if REGEX_MATCH_VERBOSE was passed to regex_compile) */ -void regex_continue_match_debug(struct regex_match *match, const regex_char_t *input_string, int length); - -/* Misc. */ -const char* regex_get_platform_name(void); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/waterbox/ares64/ares/thirdparty/sljit/regex_src/regexMain.c b/waterbox/ares64/ares/thirdparty/sljit/regex_src/regexMain.c deleted file mode 100644 index 8951a0a7b56..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/regex_src/regexMain.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Stack-less Just-In-Time compiler - * - * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* Must be the first one. Must not depend on any other include. */ -#include "sljitLir.h" -#include "regexJIT.h" - -#include - -#if defined _WIN32 || defined _WIN64 -#define COLOR_RED -#define COLOR_GREEN -#define COLOR_ARCH -#define COLOR_DEFAULT -#else -#define COLOR_RED "\33[31m" -#define COLOR_GREEN "\33[32m" -#define COLOR_ARCH "\33[33m" -#define COLOR_DEFAULT "\33[0m" -#endif - -#ifdef REGEX_USE_8BIT_CHARS -#define S(str) str -#else -#define S(str) L##str -#endif - -#ifdef REGEX_MATCH_VERBOSE -void verbose_test(regex_char_t *pattern, regex_char_t *string) -{ - int error; - regex_char_t *ptr; - struct regex_machine* machine; - struct regex_match* match; - int begin, end, id; - - ptr = pattern; - while (*ptr) - ptr++; - - printf("Start test '%s' matches to '%s'\n", pattern, string); - machine = regex_compile(pattern, (int)(ptr - pattern), REGEX_MATCH_VERBOSE | REGEX_NEWLINE, &error); - - if (error) { - printf("WARNING: Error %d\n", error); - return; - } - if (!machine) { - printf("ERROR: machine must be exists. Report this bug, please\n"); - return; - } - - match = regex_begin_match(machine); - if (!match) { - printf("WARNING: Not enough memory for matching\n"); - regex_free_machine(machine); - return; - } - - ptr = string; - while (*ptr) - ptr++; - - regex_continue_match_debug(match, string, (int)(ptr - string)); - - begin = regex_get_result(match, &end, &id); - printf("Math returns: %3d->%3d [%3d]\n", begin, end, id); - - regex_free_match(match); - regex_free_machine(machine); -} -#endif - -struct test_case { - int begin; /* Expected begin. */ - int end; /* Expected end. */ - int id; /* Expected id. */ - int finished; /* -1 : don't care, 0 : false, 1 : true. */ - int flags; /* REGEX_MATCH_* */ - const regex_char_t *pattern; /* NULL : use the previous pattern. */ - const regex_char_t *string; /* NULL : end of tests. */ -}; - -static void run_tests(struct test_case* test, int verbose, int silent) -{ - int error; - const regex_char_t *ptr; - struct regex_machine* machine = NULL; - struct regex_match* match; - int begin, end, id, finished; - int success = 0, fail = 0; - - if (!verbose && !silent) - printf("Pass -v to enable verbose, -s to disable this hint.\n\n"); - - for ( ; test->string ; test++) { - if (verbose) - printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string); - fail++; - - if (test->pattern) { - if (machine) - regex_free_machine(machine); - - ptr = test->pattern; - while (*ptr) - ptr++; - - machine = regex_compile(test->pattern, (int)(ptr - test->pattern), test->flags, &error); - - if (error) { - if (!verbose) - printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string); - printf("ABORT: Error %d\n", error); - return; - } - if (!machine) { - if (!verbose) - printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string); - printf("ABORT: machine must be exists. Report this bug, please\n"); - return; - } - } - else if (test->flags != 0) { - if (!verbose) - printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string); - printf("ABORT: flag must be 0 if no pattern\n"); - return; - } - - ptr = test->string; - while (*ptr) - ptr++; - - match = regex_begin_match(machine); -#ifdef REGEX_MATCH_VERBOSE - if (!match) { - if (!verbose) - printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string); - printf("ABORT: Not enough memory for matching\n"); - regex_free_machine(machine); - return; - } - regex_continue_match_debug(match, test->string, (int)(ptr - test->string)); - begin = regex_get_result(match, &end, &id); - finished = regex_is_match_finished(match); - - if (begin != test->begin || end != test->end || id != test->id) { - if (!verbose) - printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string); - printf("FAIL A: begin: %d != %d || end: %d != %d || id: %d != %d\n", test->begin, begin, test->end, end, test->id, id); - continue; - } - if (test->finished != -1 && test->finished != !!finished) { - if (!verbose) - printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string); - printf("FAIL A: finish check\n"); - continue; - } -#endif - - regex_reset_match(match); - regex_continue_match(match, test->string, (int)(ptr - test->string)); - begin = regex_get_result(match, &end, &id); - finished = regex_is_match_finished(match); - regex_free_match(match); - - if (begin != test->begin || end != test->end || id != test->id) { - if (!verbose) - printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string); - printf("FAIL B: begin: %d != %d || end: %d != %d || id: %d != %d\n", test->begin, begin, test->end, end, test->id, id); - continue; - } - if (test->finished != -1 && test->finished != !!finished) { - if (!verbose) - printf("test: '%s' '%s': ", test->pattern ? test->pattern : "[[REUSE]]", test->string); - printf("FAIL B: finish check\n"); - continue; - } - - if (verbose) - printf("SUCCESS\n"); - fail--; - success++; - } - if (machine) - regex_free_machine(machine); - - printf("REGEX tests: "); - if (fail == 0) - printf("all tests are " COLOR_GREEN "PASSED" COLOR_DEFAULT " "); - else - printf(COLOR_RED "%d" COLOR_DEFAULT " (" COLOR_RED "%d%%" COLOR_DEFAULT ") tests are failed ", fail, fail * 100 / (success + fail)); - printf("on " COLOR_ARCH "%s" COLOR_DEFAULT "\n", regex_get_platform_name()); -} - -/* Testing. */ - -static struct test_case tests[] = { -{ 3, 7, 0, -1, 0, - S("text"), S("is textile") }, -{ 0, 10, 0, -1, 0, - S("^(ab|c)*?d+(es)?"), S("abccabddeses") }, -{ -1, 0, 0, 1, 0, - S("^a+"), S("saaaa") }, -{ 3, 6, 0, 0, 0, - S("(a+|b+)$"), S("saabbb") }, -{ 1, 6, 0, 0, 0, - S("(a+|b+){,2}$"), S("saabbb") }, -{ 1, 6, 0, 1, 0, - S("(abcde|bc)(a+*|(b|c){2}+){0}"), S("babcdeaaaaaaaa") }, -{ 1, 6, 0, 1, 0, - S("(abc(aa)?|(cab+){2})"), S("cabcaa") }, -{ -1, 0, 0, 1, 0, - S("^(abc(aa)?|(cab+){2})$"), S("cabcaa") }, -{ 0, 3, 1, -1, 0, - S("^(ab{001!})?c"), S("abcde") }, -{ 1, 15, 2, -1, 0, - S("(c?(a|bb{2!}){2,3}()+d){2,3}"), S("ccabbadbbadcaadcaad") }, -{ 2, 9, 0, -1, 0, - NULL, S("cacaadaadaa") }, -{ -1, 0, 0, -1, REGEX_MATCH_BEGIN, - S("(((ab?c|d{1})))"), S("ad") }, -{ 0, 9, 3, -1, REGEX_MATCH_BEGIN, - S("^((a{1!}|b{2!}|c{3!}){3,6}d)+"), S("cabadbacddaa") }, -{ 1, 6, 0, 0, REGEX_MATCH_END, - S("(a+(bb|cc?)?){4,}"), S("maaaac") }, -{ 3, 12, 1, 0, REGEX_MATCH_END, - S("(x+x+{02,03}(x+|{1!})){03,06}$"), S("aaaxxxxxxxxx") }, -{ 1, 2, 3, -1, 0, - S("((c{1!})?|x+{2!}|{3!})(a|c)"), S("scs") }, -{ 1, 4, 2, 1, 0, - NULL, S("sxxaxxxaccacca") }, -{ 0, 2, 1, 1, 0, - NULL, S("ccdcdcdddddcdccccd") }, -{ 0, 3, 0, -1, REGEX_MATCH_NON_GREEDY, - S("^a+a+a+"), S("aaaaaa") }, -{ 2, 5, 0, -1, REGEX_MATCH_NON_GREEDY, - S("a+a+a+"), S("bbaaaaaa") }, -{ 1, 4, 0, 1, 0, - S("baa|a+"), S("sbaaaaaa") }, -{ 0, 6, 0, 1, 0, - S("baaa|baa|sbaaaa"), S("sbaaaaa") }, -{ 1, 4, 0, 1, REGEX_MATCH_NON_GREEDY, - S("baaa|baa"), S("xbaaa") }, -{ 0, 0, 3, 1, 0, - S("{3!}"), S("xx") }, -{ 0, 0, 1, 1, 0, - S("{1!}(a{2!})*"), S("xx") }, -{ 0, 2, 2, 0, 0, - NULL, S("aa") }, -{ 0, 0, 1, 1, REGEX_MATCH_NON_GREEDY, - S("{1!}(a{2!})*"), S("aaxx") }, -{ 4, 12, 0, 1, 0, - S("(.[]-]){3}[^]-]{2}"), S("ax-xs-[][]lmn") }, -{ 3, 7, 1, 1, 0, - S("([ABC]|[abc]{1!}){3,5}"), S("AbSAabbx") }, -{ 0, 8, 3, 0, 0, - S("^[x\\-y[\\]]+([[\\]]{3!})*$"), S("x-y[-][]") }, -{ 0, 9, 0, 0, 0, - NULL, S("x-y[-][]x") }, -{ 2, 8, 0, 1, 0, - S("<(/{1!})?[^>]+>"), S(" ") }, -{ 2, 9, 1, 1, 0, - NULL, S(" ") }, -{ 2, 9, 0, 1, 0, - S("[A-Z0-9a-z]+"), S("[(Iden9aA)]") }, -{ 1, 4, 0, 1, 0, - S("[^x-y]+[a-c_]{2,3}"), S("x_a_y") }, -{ 4, 11, 0, 0, 0, - NULL, S("ssaymmaa_ccl") }, -{ 3, 6, 0, 1, REGEX_NEWLINE, - S(".a[^k]"), S("\na\nxa\ns") }, -{ 0, 2, 0, 1, REGEX_NEWLINE, - S("^a+"), S("aa\n") }, -{ 1, 4, 0, 1, 0 /* =REGEX_NEWLINE */, - NULL, S("\naaa\n") }, -{ 2, 3, 0, 1, 0 /* =REGEX_NEWLINE */, - NULL, S("\n\na\n") }, -{ 0, 2, 0, 1, REGEX_NEWLINE, - S("a+$"), S("aa\n") }, -{ 0, 3, 0, 0, 0 /* =REGEX_NEWLINE */, - NULL, S("aaa") }, -{ 2, 4, 1, 1, REGEX_NEWLINE, - S("^a(a{1!})*$"), S("\n\naa\n\n") }, -{ 0, 1, 0, 0, 0 /* REGEX_NEWLINE */, - NULL, S("a") }, -{ -1, 0, 0, -1, 0 /* REGEX_NEWLINE */, - NULL, S("ab\nba") }, -{ -1, 0, 0, 0, 0, - NULL, NULL } -}; - -int main(int argc, char* argv[]) -{ - int has_arg = (argc >= 2 && argv[1][0] == '-' && argv[1][2] == '\0'); - -/* verbose_test("a((b)((c|d))|)c|"); */ -/* verbose_test("Xa{009,0010}Xb{,7}Xc{5,}Xd{,}Xe{1,}Xf{,1}X"); */ -/* verbose_test("{3!}({3})({0!}){,"); */ -/* verbose_test("(s(ab){2,4}t){2,}*S(a*(b)(c()|)d+){3,4}{0,0}*M"); */ -/* verbose_test("^a({2!})*b+(a|{1!}b)+d$"); */ -/* verbose_test("((a|b|c)*(xy)+)+", "asbcxyxy"); */ - - run_tests(tests, has_arg && argv[1][1] == 'v', has_arg && argv[1][1] == 's'); - -#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) - sljit_free_unused_memory_exec(); -#endif /* !SLJIT_CONFIG_UNSUPPORTED */ - - return 0; -} diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c index 6352377c4d9..95b9842fa97 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c @@ -33,15 +33,18 @@ On non-macOS systems, returns MAP_JIT if it is defined. */ #include -#if TARGET_OS_OSX -#if defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86 + +#if (defined(TARGET_OS_OSX) && TARGET_OS_OSX) || (TARGET_OS_MAC && !TARGET_OS_IPHONE) + +#if defined(SLJIT_CONFIG_X86) && SLJIT_CONFIG_X86 + #include #include #define SLJIT_MAP_JIT (get_map_jit_flag()) #define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) -static SLJIT_INLINE int get_map_jit_flag() +static SLJIT_INLINE int get_map_jit_flag(void) { size_t page_size; void *ptr; @@ -67,10 +70,8 @@ static SLJIT_INLINE int get_map_jit_flag() } return map_jit_flag; } -#else /* !SLJIT_CONFIG_X86 */ -#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) -#error "Unsupported architecture" -#endif /* SLJIT_CONFIG_ARM */ + +#elif defined(SLJIT_CONFIG_ARM) && SLJIT_CONFIG_ARM #include #include @@ -81,15 +82,29 @@ static SLJIT_INLINE int get_map_jit_flag() static SLJIT_INLINE void apple_update_wx_flags(sljit_s32 enable_exec) { -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 110000 - pthread_jit_write_protect_np(enable_exec); -#else -#error "Must target Big Sur or newer" +#if MAC_OS_X_VERSION_MIN_REQUIRED < 110000 + if (__builtin_available(macos 11, *)) #endif /* BigSur */ + pthread_jit_write_protect_np(enable_exec); } -#endif /* SLJIT_CONFIG_X86 */ + +#elif defined(SLJIT_CONFIG_PPC) && SLJIT_CONFIG_PPC + +#define SLJIT_MAP_JIT (0) +#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) + +#else +#error "Unsupported architecture" +#endif /* SLJIT_CONFIG */ + #else /* !TARGET_OS_OSX */ + +#ifdef MAP_JIT #define SLJIT_MAP_JIT (MAP_JIT) +#else +#define SLJIT_MAP_JIT (0) +#endif + #endif /* TARGET_OS_OSX */ static SLJIT_INLINE void* alloc_chunk(sljit_uw size) diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c index 6cd391104c2..85f3a9d1ea9 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c @@ -308,7 +308,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) free_block = free_blocks; while (free_block) { next_free_block = free_block->next; - if (!free_block->header.prev_size && + if (!free_block->header.prev_size && AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) { total_size -= free_block->size; sljit_remove_free_block(free_block); @@ -317,7 +317,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) free_block = next_free_block; } - SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks)); + SLJIT_ASSERT(total_size || (!total_size && !free_blocks)); SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 1); SLJIT_ALLOCATOR_UNLOCK(); } diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfig.h b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfig.h index e11d4a2e1a1..364c8bb7884 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfig.h +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfig.h @@ -38,28 +38,6 @@ extern "C" { non-zero value. */ -/* --------------------------------------------------------------------- */ -/* Architecture */ -/* --------------------------------------------------------------------- */ - -/* Architecture selection. */ -/* #define SLJIT_CONFIG_X86_32 1 */ -/* #define SLJIT_CONFIG_X86_64 1 */ -/* #define SLJIT_CONFIG_ARM_V5 1 */ -/* #define SLJIT_CONFIG_ARM_V7 1 */ -/* #define SLJIT_CONFIG_ARM_THUMB2 1 */ -/* #define SLJIT_CONFIG_ARM_64 1 */ -/* #define SLJIT_CONFIG_PPC_32 1 */ -/* #define SLJIT_CONFIG_PPC_64 1 */ -/* #define SLJIT_CONFIG_MIPS_32 1 */ -/* #define SLJIT_CONFIG_MIPS_64 1 */ -/* #define SLJIT_CONFIG_RISCV_32 1 */ -/* #define SLJIT_CONFIG_RISCV_64 1 */ -/* #define SLJIT_CONFIG_S390X 1 */ - -/* #define SLJIT_CONFIG_AUTO 1 */ -/* #define SLJIT_CONFIG_UNSUPPORTED 1 */ - /* --------------------------------------------------------------------- */ /* Utilities */ /* --------------------------------------------------------------------- */ diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfigCPU.h b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfigCPU.h new file mode 100644 index 00000000000..2720bdab0bd --- /dev/null +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfigCPU.h @@ -0,0 +1,188 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SLJIT_CONFIG_CPU_H_ +#define SLJIT_CONFIG_CPU_H_ + +/* --------------------------------------------------------------------- */ +/* Architecture */ +/* --------------------------------------------------------------------- */ + +/* Architecture selection. */ +/* #define SLJIT_CONFIG_X86_32 1 */ +/* #define SLJIT_CONFIG_X86_64 1 */ +/* #define SLJIT_CONFIG_ARM_V6 1 */ +/* #define SLJIT_CONFIG_ARM_V7 1 */ +/* #define SLJIT_CONFIG_ARM_THUMB2 1 */ +/* #define SLJIT_CONFIG_ARM_64 1 */ +/* #define SLJIT_CONFIG_PPC_32 1 */ +/* #define SLJIT_CONFIG_PPC_64 1 */ +/* #define SLJIT_CONFIG_MIPS_32 1 */ +/* #define SLJIT_CONFIG_MIPS_64 1 */ +/* #define SLJIT_CONFIG_RISCV_32 1 */ +/* #define SLJIT_CONFIG_RISCV_64 1 */ +/* #define SLJIT_CONFIG_S390X 1 */ +/* #define SLJIT_CONFIG_LOONGARCH_64 */ + +/* #define SLJIT_CONFIG_AUTO 1 */ +/* #define SLJIT_CONFIG_UNSUPPORTED 1 */ + +/*****************/ +/* Sanity check. */ +/*****************/ + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ + + (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ + + (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) \ + + (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ + + (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \ + + (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ + + (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ + + (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ + + (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ + + (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \ + + (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \ + + (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \ + + (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \ + + (defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64) \ + + (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \ + + (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2 +#error "Multiple architectures are selected" +#endif + +#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ + && !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ + && !(defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) \ + && !(defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ + && !(defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \ + && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ + && !(defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ + && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ + && !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ + && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \ + && !(defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \ + && !(defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \ + && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \ + && !(defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64) \ + && !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) \ + && !(defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) +#if defined SLJIT_CONFIG_AUTO && !SLJIT_CONFIG_AUTO +#error "An architecture must be selected" +#else /* SLJIT_CONFIG_AUTO */ +#define SLJIT_CONFIG_AUTO 1 +#endif /* !SLJIT_CONFIG_AUTO */ +#endif /* !SLJIT_CONFIG */ + +/********************************************************/ +/* Automatic CPU detection (requires compiler support). */ +/********************************************************/ + +#if (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) +#ifndef _WIN32 + +#if defined(__i386__) || defined(__i386) +#define SLJIT_CONFIG_X86_32 1 +#elif defined(__x86_64__) +#define SLJIT_CONFIG_X86_64 1 +#elif defined(__aarch64__) +#define SLJIT_CONFIG_ARM_64 1 +#elif defined(__thumb2__) +#define SLJIT_CONFIG_ARM_THUMB2 1 +#elif (defined(__ARM_ARCH) && __ARM_ARCH >= 7) || \ + ((defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7S__)) \ + || (defined(__ARM_ARCH_8A__) || defined(__ARM_ARCH_8R__)) \ + || (defined(__ARM_ARCH_9A__))) +#define SLJIT_CONFIG_ARM_V7 1 +#elif defined(__arm__) || defined (__ARM__) +#define SLJIT_CONFIG_ARM_V6 1 +#elif defined(__ppc64__) || defined(__powerpc64__) || (defined(_ARCH_PPC64) && defined(__64BIT__)) || (defined(_POWER) && defined(__64BIT__)) +#define SLJIT_CONFIG_PPC_64 1 +#elif defined(__ppc__) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(_ARCH_PWR) || defined(_ARCH_PWR2) || defined(_POWER) +#define SLJIT_CONFIG_PPC_32 1 +#elif defined(__mips__) && !defined(_LP64) +#define SLJIT_CONFIG_MIPS_32 1 +#elif defined(__mips64) +#define SLJIT_CONFIG_MIPS_64 1 +#elif defined (__riscv_xlen) && (__riscv_xlen == 32) +#define SLJIT_CONFIG_RISCV_32 1 +#elif defined (__riscv_xlen) && (__riscv_xlen == 64) +#define SLJIT_CONFIG_RISCV_64 1 +#elif defined (__loongarch_lp64) +#define SLJIT_CONFIG_LOONGARCH_64 1 +#elif defined(__s390x__) +#define SLJIT_CONFIG_S390X 1 +#else +/* Unsupported architecture */ +#define SLJIT_CONFIG_UNSUPPORTED 1 +#endif + +#else /* _WIN32 */ + +#if defined(_M_X64) || defined(__x86_64__) +#define SLJIT_CONFIG_X86_64 1 +#elif (defined(_M_ARM) && _M_ARM >= 7 && defined(_M_ARMT)) || defined(__thumb2__) +#define SLJIT_CONFIG_ARM_THUMB2 1 +#elif (defined(_M_ARM) && _M_ARM >= 7) +#define SLJIT_CONFIG_ARM_V7 1 +#elif defined(_ARM_) +#define SLJIT_CONFIG_ARM_V6 1 +#elif defined(_M_ARM64) || defined(__aarch64__) +#define SLJIT_CONFIG_ARM_64 1 +#else +#define SLJIT_CONFIG_X86_32 1 +#endif + +#endif /* !_WIN32 */ +#endif /* SLJIT_CONFIG_AUTO */ + +#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) +#undef SLJIT_EXECUTABLE_ALLOCATOR +#endif /* SLJIT_CONFIG_UNSUPPORTED */ + +/******************************/ +/* CPU family type detection. */ +/******************************/ + +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ + || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) +#define SLJIT_CONFIG_ARM_32 1 +#endif + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) +#define SLJIT_CONFIG_X86 1 +#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) +#define SLJIT_CONFIG_ARM 1 +#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) +#define SLJIT_CONFIG_PPC 1 +#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) +#define SLJIT_CONFIG_MIPS 1 +#elif (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) || (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) +#define SLJIT_CONFIG_RISCV 1 +#elif (defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64) +#define SLJIT_CONFIG_LOONGARCH 1 +#endif + +#endif /* SLJIT_CONFIG_CPU_H_ */ diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfigInternal.h b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfigInternal.h index e9bd4d93225..f12505e9c82 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfigInternal.h +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitConfigInternal.h @@ -72,6 +72,8 @@ extern "C" { SLJIT_NUMBER_OF_FLOAT_REGISTERS : number of available floating point registers SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS : number of available floating point scratch registers SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS : number of available floating point saved registers + SLJIT_NUMBER_OF_TEMPORARY_REGISTERS : number of available temporary registers + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS : number of available temporary floating point registers SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index SLJIT_F32_SHIFT : the shift required to apply when accessing a single precision floating point array by index @@ -81,141 +83,27 @@ extern "C" { the scratch register index of ecx is stored in this variable SLJIT_LOCALS_OFFSET : local space starting offset (SLJIT_SP + SLJIT_LOCALS_OFFSET) SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address + SLJIT_CONV_MAX_FLOAT : result when a floating point value is converted to integer + and the floating point value is higher than the maximum integer value + (possible values: SLJIT_CONV_RESULT_MAX_INT or SLJIT_CONV_RESULT_MIN_INT) + SLJIT_CONV_MIN_FLOAT : result when a floating point value is converted to integer + and the floating point value is lower than the minimum integer value + (possible values: SLJIT_CONV_RESULT_MAX_INT or SLJIT_CONV_RESULT_MIN_INT) + SLJIT_CONV_NAN_FLOAT : result when a NaN floating point value is converted to integer + (possible values: SLJIT_CONV_RESULT_MAX_INT, SLJIT_CONV_RESULT_MIN_INT, + or SLJIT_CONV_RESULT_ZERO) Other macros: + SLJIT_TMP_R0 .. R9 : accessing temporary registers + SLJIT_TMP_R(i) : accessing temporary registers + SLJIT_TMP_FR0 .. FR9 : accessing temporary floating point registers + SLJIT_TMP_FR(i) : accessing temporary floating point registers SLJIT_FUNC : calling convention attribute for both calling JIT from C and C calling back from JIT SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (platform independent helper) + SLJIT_F64_SECOND(reg) : provides the register index of the second 32 bit part of a 64 bit + floating point register when SLJIT_HAS_F64_AS_F32_PAIR returns non-zero */ -/*****************/ -/* Sanity check. */ -/*****************/ - -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ - + (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ - + (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \ - + (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ - + (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \ - + (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ - + (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ - + (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ - + (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ - + (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \ - + (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \ - + (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \ - + (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \ - + (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \ - + (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2 -#error "Multiple architectures are selected" -#endif - -#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ - && !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ - && !(defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \ - && !(defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ - && !(defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \ - && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ - && !(defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ - && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ - && !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ - && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \ - && !(defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \ - && !(defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \ - && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \ - && !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) \ - && !(defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) -#if defined SLJIT_CONFIG_AUTO && !SLJIT_CONFIG_AUTO -#error "An architecture must be selected" -#else /* SLJIT_CONFIG_AUTO */ -#define SLJIT_CONFIG_AUTO 1 -#endif /* !SLJIT_CONFIG_AUTO */ -#endif /* !SLJIT_CONFIG */ - -/********************************************************/ -/* Automatic CPU detection (requires compiler support). */ -/********************************************************/ - -#if (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) -#ifndef _WIN32 - -#if defined(__i386__) || defined(__i386) -#define SLJIT_CONFIG_X86_32 1 -#elif defined(__x86_64__) -#define SLJIT_CONFIG_X86_64 1 -#elif defined(__aarch64__) -#define SLJIT_CONFIG_ARM_64 1 -#elif defined(__thumb2__) -#define SLJIT_CONFIG_ARM_THUMB2 1 -#elif (defined(__ARM_ARCH) && __ARM_ARCH >= 7) || \ - ((defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7S__)) \ - || (defined(__ARM_ARCH_8A__) || defined(__ARM_ARCH_8R__)) \ - || (defined(__ARM_ARCH_9A__))) -#define SLJIT_CONFIG_ARM_V7 1 -#elif defined(__arm__) || defined (__ARM__) -#define SLJIT_CONFIG_ARM_V5 1 -#elif defined(__ppc64__) || defined(__powerpc64__) || (defined(_ARCH_PPC64) && defined(__64BIT__)) || (defined(_POWER) && defined(__64BIT__)) -#define SLJIT_CONFIG_PPC_64 1 -#elif defined(__ppc__) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(_ARCH_PWR) || defined(_ARCH_PWR2) || defined(_POWER) -#define SLJIT_CONFIG_PPC_32 1 -#elif defined(__mips__) && !defined(_LP64) -#define SLJIT_CONFIG_MIPS_32 1 -#elif defined(__mips64) -#define SLJIT_CONFIG_MIPS_64 1 -#elif defined (__riscv_xlen) && (__riscv_xlen == 32) -#define SLJIT_CONFIG_RISCV_32 1 -#elif defined (__riscv_xlen) && (__riscv_xlen == 64) -#define SLJIT_CONFIG_RISCV_64 1 -#elif defined(__s390x__) -#define SLJIT_CONFIG_S390X 1 -#else -/* Unsupported architecture */ -#define SLJIT_CONFIG_UNSUPPORTED 1 -#endif - -#else /* _WIN32 */ - -#if defined(_M_X64) || defined(__x86_64__) -#define SLJIT_CONFIG_X86_64 1 -#elif (defined(_M_ARM) && _M_ARM >= 7 && defined(_M_ARMT)) || defined(__thumb2__) -#define SLJIT_CONFIG_ARM_THUMB2 1 -#elif (defined(_M_ARM) && _M_ARM >= 7) -#define SLJIT_CONFIG_ARM_V7 1 -#elif defined(_ARM_) -#define SLJIT_CONFIG_ARM_V5 1 -#elif defined(_M_ARM64) || defined(__aarch64__) -#define SLJIT_CONFIG_ARM_64 1 -#else -#define SLJIT_CONFIG_X86_32 1 -#endif - -#endif /* !_WIN32 */ -#endif /* SLJIT_CONFIG_AUTO */ - -#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) -#undef SLJIT_EXECUTABLE_ALLOCATOR -#endif - -/******************************/ -/* CPU family type detection. */ -/******************************/ - -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ - || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) -#define SLJIT_CONFIG_ARM_32 1 -#endif - -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) -#define SLJIT_CONFIG_X86 1 -#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) -#define SLJIT_CONFIG_ARM 1 -#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) -#define SLJIT_CONFIG_PPC 1 -#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) -#define SLJIT_CONFIG_MIPS 1 -#elif (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) || (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) -#define SLJIT_CONFIG_RISCV 1 -#endif - /***********************************************************/ /* Intel Control-flow Enforcement Technology (CET) spport. */ /***********************************************************/ @@ -244,23 +132,23 @@ extern "C" { */ #ifndef SLJIT_MALLOC -#define SLJIT_MALLOC(size, allocator_data) malloc(size) +#define SLJIT_MALLOC(size, allocator_data) (malloc(size)) #endif #ifndef SLJIT_FREE -#define SLJIT_FREE(ptr, allocator_data) free(ptr) +#define SLJIT_FREE(ptr, allocator_data) (free(ptr)) #endif #ifndef SLJIT_MEMCPY -#define SLJIT_MEMCPY(dest, src, len) memcpy(dest, src, len) +#define SLJIT_MEMCPY(dest, src, len) (memcpy(dest, src, len)) #endif #ifndef SLJIT_MEMMOVE -#define SLJIT_MEMMOVE(dest, src, len) memmove(dest, src, len) +#define SLJIT_MEMMOVE(dest, src, len) (memmove(dest, src, len)) #endif #ifndef SLJIT_ZEROMEM -#define SLJIT_ZEROMEM(dest, len) memset(dest, 0, len) +#define SLJIT_ZEROMEM(dest, len) (memset(dest, 0, len)) #endif /***************************/ @@ -310,7 +198,7 @@ extern "C" { /* Type of public API functions. */ /*********************************/ -#ifndef SLJIT_API_FUNC_ATTRIBUTE +#ifndef SLJIT_API_FUNC_ATTRIBUTE #if (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) /* Static ABI functions. For all-in-one programs. */ @@ -330,6 +218,10 @@ extern "C" { /* Instruction cache flush. */ /****************************/ +#ifdef __APPLE__ +#include +#endif + /* * TODO: * @@ -370,7 +262,7 @@ extern "C" { /* Not required to implement on archs with unified caches. */ #define SLJIT_CACHE_FLUSH(from, to) -#elif defined __APPLE__ +#elif defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 /* Supported by all macs since Mac OS 10.5. However, it does not work on non-jailbroken iOS devices, @@ -435,14 +327,15 @@ typedef signed int sljit_s32; #if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) /* Just to have something. */ #define SLJIT_WORD_SHIFT 0 -typedef unsigned long int sljit_uw; -typedef long int sljit_sw; +typedef unsigned int sljit_uw; +typedef int sljit_sw; #elif !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \ && !(defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \ - && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) + && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \ + && !(defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64) #define SLJIT_32BIT_ARCHITECTURE 1 #define SLJIT_WORD_SHIFT 2 typedef unsigned int sljit_uw; @@ -478,12 +371,46 @@ typedef double sljit_f64; #define SLJIT_F32_SHIFT 2 #define SLJIT_F64_SHIFT 3 +#define SLJIT_CONV_RESULT_MAX_INT 0 +#define SLJIT_CONV_RESULT_MIN_INT 1 +#define SLJIT_CONV_RESULT_ZERO 2 + +#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) +#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MIN_INT +#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT +#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MIN_INT +#elif (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) +#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT +#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT +#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_ZERO +#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) +#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT +#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MAX_INT +#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MAX_INT +#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) +#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT +#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT +#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MIN_INT +#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) +#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT +#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT +#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MAX_INT +#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) +#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT +#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT +#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MIN_INT +#elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH) +#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT +#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT +#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_ZERO +#else +#error "Result for float to integer conversion is not defined" +#endif + #ifndef SLJIT_W /* Defining long constants. */ -#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) -#define SLJIT_W(w) (w##l) -#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) +#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) #ifdef _WIN64 #define SLJIT_W(w) (w##ll) #else /* !windows */ @@ -523,9 +450,10 @@ typedef double sljit_f64; /* Auto detecting mips revision. */ #if (defined __mips_isa_rev) && (__mips_isa_rev >= 6) #define SLJIT_MIPS_REV 6 -#elif (defined __mips_isa_rev && __mips_isa_rev >= 1) \ - || (defined __clang__ && defined _MIPS_ARCH_OCTEON) \ - || (defined __clang__ && defined _MIPS_ARCH_P5600) +#elif defined(__mips_isa_rev) && __mips_isa_rev >= 1 +#define SLJIT_MIPS_REV __mips_isa_rev +#elif defined(__clang__) \ + && (defined(_MIPS_ARCH_OCTEON) || defined(_MIPS_ARCH_P5600)) /* clang either forgets to define (clang-7) __mips_isa_rev at all * or sets it to zero (clang-8,-9) for -march=octeon (MIPS64 R2+) * and -march=p5600 (MIPS32 R5). @@ -564,7 +492,8 @@ typedef double sljit_f64; || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \ || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \ - || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) + || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \ + || (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH) #define SLJIT_UNALIGNED 1 #endif @@ -576,7 +505,8 @@ typedef double sljit_f64; || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \ || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \ - || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) + || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \ + || (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH) #define SLJIT_FPU_UNALIGNED 1 #endif @@ -649,8 +579,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_NUMBER_OF_REGISTERS 12 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 7 +#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 1 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 7 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0 +#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1 #define SLJIT_LOCALS_OFFSET_BASE (8 * SSIZE_OF(sw)) #define SLJIT_PREF_SHIFT_REG SLJIT_R2 #define SLJIT_MASKED_SHIFT 1 @@ -659,7 +591,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) #define SLJIT_NUMBER_OF_REGISTERS 13 +#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 2 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 15 +#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1 #ifndef _WIN64 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 6 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0 @@ -673,28 +607,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_MASKED_SHIFT 1 #define SLJIT_MASKED_SHIFT32 1 -#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) - -#define SLJIT_NUMBER_OF_REGISTERS 12 -#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8 -#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 14 -#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8 -#define SLJIT_LOCALS_OFFSET_BASE 0 - -#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) +#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) #define SLJIT_NUMBER_OF_REGISTERS 12 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8 +#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 2 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 14 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8 +#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2 #define SLJIT_LOCALS_OFFSET_BASE 0 #elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) #define SLJIT_NUMBER_OF_REGISTERS 26 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 10 +#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 3 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8 +#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2 #define SLJIT_LOCALS_OFFSET_BASE (2 * (sljit_s32)sizeof(sljit_sw)) #define SLJIT_MASKED_SHIFT 1 #define SLJIT_MASKED_SHIFT32 1 @@ -703,8 +633,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_NUMBER_OF_REGISTERS 23 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 17 +#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 3 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 18 +#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined _AIX) #define SLJIT_LOCALS_OFFSET_BASE ((6 + 8) * (sljit_s32)sizeof(sljit_sw)) #elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) @@ -727,6 +659,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 29 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8 #endif +#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5 +#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 3 #define SLJIT_MASKED_SHIFT 1 #define SLJIT_MASKED_SHIFT32 1 @@ -734,9 +668,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_NUMBER_OF_REGISTERS 23 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 12 -#define SLJIT_LOCALS_OFFSET_BASE 0 +#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12 +#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2 +#define SLJIT_LOCALS_OFFSET_BASE 0 #define SLJIT_MASKED_SHIFT 1 #define SLJIT_MASKED_SHIFT32 1 @@ -765,17 +701,34 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_NUMBER_OF_REGISTERS 12 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8 +#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 3 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 15 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8 +#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1 #define SLJIT_LOCALS_OFFSET_BASE SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE #define SLJIT_MASKED_SHIFT 1 +#elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH) + +#define SLJIT_NUMBER_OF_REGISTERS 23 +#define SLJIT_NUMBER_OF_SAVED_REGISTERS 10 +#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5 +#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30 +#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12 +#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2 +#define SLJIT_LOCALS_OFFSET_BASE 0 +#define SLJIT_MASKED_SHIFT 1 +#define SLJIT_MASKED_SHIFT32 1 + #elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) +/* Just to have something. */ #define SLJIT_NUMBER_OF_REGISTERS 0 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 0 +#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 0 #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 0 #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0 +#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 0 #define SLJIT_LOCALS_OFFSET_BASE 0 #endif @@ -788,6 +741,45 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS \ (SLJIT_NUMBER_OF_FLOAT_REGISTERS - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS) +/**********************************/ +/* Temporary register management. */ +/**********************************/ + +#define SLJIT_TMP_REGISTER_BASE (SLJIT_NUMBER_OF_REGISTERS + 2) +#define SLJIT_TMP_FREGISTER_BASE (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) + +/* WARNING: Accessing temporary registers is not recommended, because they + are also used by the JIT compiler for various computations. Using them + might have any side effects including incorrect operations and crashes, + so use them at your own risk. The machine registers themselves might have + limitations, e.g. the r0 register on s390x / ppc cannot be used as + base address for memory operations. */ + +/* Temporary registers */ +#define SLJIT_TMP_R0 (SLJIT_TMP_REGISTER_BASE + 0) +#define SLJIT_TMP_R1 (SLJIT_TMP_REGISTER_BASE + 1) +#define SLJIT_TMP_R2 (SLJIT_TMP_REGISTER_BASE + 2) +#define SLJIT_TMP_R3 (SLJIT_TMP_REGISTER_BASE + 3) +#define SLJIT_TMP_R4 (SLJIT_TMP_REGISTER_BASE + 4) +#define SLJIT_TMP_R5 (SLJIT_TMP_REGISTER_BASE + 5) +#define SLJIT_TMP_R6 (SLJIT_TMP_REGISTER_BASE + 6) +#define SLJIT_TMP_R7 (SLJIT_TMP_REGISTER_BASE + 7) +#define SLJIT_TMP_R8 (SLJIT_TMP_REGISTER_BASE + 8) +#define SLJIT_TMP_R9 (SLJIT_TMP_REGISTER_BASE + 9) +#define SLJIT_TMP_R(i) (SLJIT_TMP_REGISTER_BASE + (i)) + +#define SLJIT_TMP_FR0 (SLJIT_TMP_FREGISTER_BASE + 0) +#define SLJIT_TMP_FR1 (SLJIT_TMP_FREGISTER_BASE + 1) +#define SLJIT_TMP_FR2 (SLJIT_TMP_FREGISTER_BASE + 2) +#define SLJIT_TMP_FR3 (SLJIT_TMP_FREGISTER_BASE + 3) +#define SLJIT_TMP_FR4 (SLJIT_TMP_FREGISTER_BASE + 4) +#define SLJIT_TMP_FR5 (SLJIT_TMP_FREGISTER_BASE + 5) +#define SLJIT_TMP_FR6 (SLJIT_TMP_FREGISTER_BASE + 6) +#define SLJIT_TMP_FR7 (SLJIT_TMP_FREGISTER_BASE + 7) +#define SLJIT_TMP_FR8 (SLJIT_TMP_FREGISTER_BASE + 8) +#define SLJIT_TMP_FR9 (SLJIT_TMP_FREGISTER_BASE + 9) +#define SLJIT_TMP_FR(i) (SLJIT_TMP_FREGISTER_BASE + (i)) + /********************************/ /* CPU status flags management. */ /********************************/ @@ -796,10 +788,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \ || (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \ || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \ - || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) + || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \ + || (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH) #define SLJIT_HAS_STATUS_FLAGS_STATE 1 #endif +/***************************************/ +/* Floating point register management. */ +/***************************************/ + +#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \ + || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) +#define SLJIT_F64_SECOND(reg) \ + ((reg) + SLJIT_FS0 + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS) +#else /* !SLJIT_CONFIG_ARM_32 && !SLJIT_CONFIG_MIPS_32 */ +#define SLJIT_F64_SECOND(reg) \ + (reg) +#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */ + /*************************************/ /* Debug and verbose related macros. */ /*************************************/ diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitLir.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitLir.c index 4a73e8e4955..bfaee050ea5 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitLir.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitLir.c @@ -123,47 +123,71 @@ #endif /* Parameter parsing. */ -#define REG_MASK 0x3f +#define REG_MASK 0x7f #define OFFS_REG(reg) (((reg) >> 8) & REG_MASK) #define OFFS_REG_MASK (REG_MASK << 8) #define TO_OFFS_REG(reg) ((reg) << 8) -/* When reg cannot be unused. */ -#define FAST_IS_REG(reg) ((reg) <= REG_MASK) +#define FAST_IS_REG(reg) ((reg) < REG_MASK) /* Mask for argument types. */ #define SLJIT_ARG_MASK 0x7 #define SLJIT_ARG_FULL_MASK (SLJIT_ARG_MASK | SLJIT_ARG_TYPE_SCRATCH_REG) -/* Mask for sljit_emit_mem. */ -#define REG_PAIR_MASK 0xff00 -#define REG_PAIR_FIRST(reg) ((reg) & 0xff) +/* Mask for register pairs. */ +#define REG_PAIR_MASK 0x7f00 +#define REG_PAIR_FIRST(reg) ((reg) & 0x7f) #define REG_PAIR_SECOND(reg) ((reg) >> 8) /* Mask for sljit_emit_enter. */ #define SLJIT_KEPT_SAVEDS_COUNT(options) ((options) & 0x3) +/* Getters for simd operations, which returns with log2(size). */ +#define SLJIT_SIMD_GET_OPCODE(type) ((type) & 0xff) +#define SLJIT_SIMD_GET_REG_SIZE(type) (((type) >> 12) & 0x3f) +#define SLJIT_SIMD_GET_ELEM_SIZE(type) (((type) >> 18) & 0x3f) +#define SLJIT_SIMD_GET_ELEM2_SIZE(type) (((type) >> 24) & 0x3f) + +#define SLJIT_SIMD_CHECK_REG(type) (((type) & 0x3f000) >= SLJIT_SIMD_REG_64 && ((type) & 0x3f000) <= SLJIT_SIMD_REG_512) +#define SLJIT_SIMD_TYPE_MASK(m) ((sljit_s32)0xff000fff & ~(SLJIT_SIMD_FLOAT | SLJIT_SIMD_TEST | (m))) +#define SLJIT_SIMD_TYPE_MASK2(m) ((sljit_s32)0xc0000fff & ~(SLJIT_SIMD_FLOAT | SLJIT_SIMD_TEST | (m))) + /* Jump flags. */ -#define JUMP_LABEL 0x1 -#define JUMP_ADDR 0x2 +#define JUMP_ADDR 0x1 +#define JUMP_MOV_ADDR 0x2 /* SLJIT_REWRITABLE_JUMP is 0x1000. */ #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) -# define PATCH_MB 0x4 -# define PATCH_MW 0x8 +# define PATCH_MB 0x04 +# define PATCH_MW 0x08 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) # define PATCH_MD 0x10 -#endif +# define MOV_ADDR_HI 0x20 +# define JUMP_MAX_SIZE ((sljit_uw)(10 + 3)) +# define CJUMP_MAX_SIZE ((sljit_uw)(2 + 10 + 3)) +#else /* !SLJIT_CONFIG_X86_64 */ +# define JUMP_MAX_SIZE ((sljit_uw)5) +# define CJUMP_MAX_SIZE ((sljit_uw)6) +#endif /* SLJIT_CONFIG_X86_64 */ # define TYPE_SHIFT 13 +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) +/* Bits 7..12 is for debug jump size, SLJIT_REWRITABLE_JUMP is 0x1000 */ +# define JUMP_SIZE_SHIFT 7 +#endif /* SLJIT_DEBUG */ #endif /* SLJIT_CONFIG_X86 */ -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) -# define IS_BL 0x4 -# define PATCH_B 0x8 -#endif /* SLJIT_CONFIG_ARM_V5 || SLJIT_CONFIG_ARM_V7 */ +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) +# define IS_BL 0x04 +# define PATCH_B 0x08 +#endif /* SLJIT_CONFIG_ARM_V6 || SLJIT_CONFIG_ARM_V7 */ -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) # define CPOOL_SIZE 512 -#endif /* SLJIT_CONFIG_ARM_V5 */ +#endif /* SLJIT_CONFIG_ARM_V6 */ + +#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) +# define JUMP_SIZE_SHIFT 26 +# define JUMP_MAX_SIZE ((sljit_uw)3) +#endif /* SLJIT_CONFIG_ARM_V7 */ #if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) # define IS_COND 0x04 @@ -172,25 +196,30 @@ # define PATCH_TYPE1 0x10 /* conditional + imm20 */ # define PATCH_TYPE2 0x20 - /* IT + imm24 */ -# define PATCH_TYPE3 0x30 /* imm11 */ -# define PATCH_TYPE4 0x40 +# define PATCH_TYPE3 0x30 /* imm24 */ -# define PATCH_TYPE5 0x50 +# define PATCH_TYPE4 0x40 /* BL + imm24 */ -# define PATCH_BL 0x60 +# define PATCH_TYPE5 0x50 + /* addwi/subwi */ +# define PATCH_TYPE6 0x60 /* 0xf00 cc code for branches */ +# define JUMP_SIZE_SHIFT 26 +# define JUMP_MAX_SIZE ((sljit_uw)5) #endif /* SLJIT_CONFIG_ARM_THUMB2 */ #if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) # define IS_COND 0x004 # define IS_CBZ 0x008 # define IS_BL 0x010 -# define PATCH_B 0x020 -# define PATCH_COND 0x040 -# define PATCH_ABS48 0x080 -# define PATCH_ABS64 0x100 +# define PATCH_COND 0x020 +# define PATCH_B 0x040 +# define PATCH_B32 0x080 +# define PATCH_ABS48 0x100 +# define PATCH_ABS64 0x200 +# define JUMP_SIZE_SHIFT 58 +# define JUMP_MAX_SIZE ((sljit_uw)5) #endif /* SLJIT_CONFIG_ARM_64 */ #if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) @@ -201,8 +230,12 @@ #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) # define PATCH_ABS32 0x040 # define PATCH_ABS48 0x080 +# define JUMP_SIZE_SHIFT 58 +# define JUMP_MAX_SIZE ((sljit_uw)7) +#else /* !SLJIT_CONFIG_PPC_64 */ +# define JUMP_SIZE_SHIFT 26 +# define JUMP_MAX_SIZE ((sljit_uw)4) #endif /* SLJIT_CONFIG_PPC_64 */ -# define REMOVE_COND 0x100 #endif /* SLJIT_CONFIG_PPC */ #if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) @@ -244,11 +277,26 @@ # define PATCH_ABS32 0x080 # define PATCH_ABS44 0x100 # define PATCH_ABS52 0x200 +# define JUMP_SIZE_SHIFT 58 +# define JUMP_MAX_SIZE ((sljit_uw)6) #else /* !SLJIT_CONFIG_RISCV_64 */ -# define PATCH_REL32 0x0 +# define JUMP_SIZE_SHIFT 26 +# define JUMP_MAX_SIZE ((sljit_uw)2) #endif /* SLJIT_CONFIG_RISCV_64 */ #endif /* SLJIT_CONFIG_RISCV */ +#if (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH) +# define IS_COND 0x004 +# define IS_CALL 0x008 + +# define PATCH_B 0x010 +# define PATCH_J 0x020 + +# define PATCH_REL32 0x040 +# define PATCH_ABS32 0x080 +# define PATCH_ABS52 0x100 + +#endif /* SLJIT_CONFIG_LOONGARCH */ /* Stack management. */ #define GET_SAVED_REGISTERS_SIZE(scratches, saveds, extra) \ @@ -447,9 +495,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) compiler->args_size = -1; -#endif +#endif /* SLJIT_CONFIG_X86_32 */ -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) compiler->cpool = (sljit_uw*)SLJIT_MALLOC(CPOOL_SIZE * sizeof(sljit_uw) + CPOOL_SIZE * sizeof(sljit_u8), allocator_data); if (!compiler->cpool) { @@ -460,18 +508,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo } compiler->cpool_unique = (sljit_u8*)(compiler->cpool + CPOOL_SIZE); compiler->cpool_diff = 0xffffffff; -#endif +#endif /* SLJIT_CONFIG_ARM_V6 */ #if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) compiler->delay_slot = UNMOVABLE_INS; -#endif +#endif /* SLJIT_CONFIG_MIPS */ #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ || (defined SLJIT_DEBUG && SLJIT_DEBUG) compiler->last_flags = 0; compiler->last_return = -1; compiler->logical_local_size = 0; -#endif +#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */ #if (defined SLJIT_NEEDS_COMPILER_INIT && SLJIT_NEEDS_COMPILER_INIT) if (!compiler_initialized) { @@ -504,7 +552,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compile SLJIT_FREE(curr, allocator_data); } -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) SLJIT_FREE(compiler->cpool, allocator_data); #endif SLJIT_FREE(compiler, allocator_data); @@ -546,7 +594,6 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sl { if (SLJIT_LIKELY(!!jump) && SLJIT_LIKELY(!!label)) { jump->flags &= (sljit_uw)~JUMP_ADDR; - jump->flags |= JUMP_LABEL; jump->u.label = label; } } @@ -554,18 +601,11 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sl SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target) { if (SLJIT_LIKELY(!!jump)) { - jump->flags &= (sljit_uw)~JUMP_LABEL; jump->flags |= JUMP_ADDR; jump->u.target = target; } } -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label) -{ - if (SLJIT_LIKELY(!!put_label)) - put_label->label = label; -} - #define SLJIT_CURRENT_FLAGS_ALL \ (SLJIT_CURRENT_FLAGS_32 | SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE) @@ -660,31 +700,44 @@ static SLJIT_INLINE void reverse_buf(struct sljit_compiler *compiler) compiler->buf = prev; } -/* Only used in RISC architectures where the instruction size is constant */ -#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ - && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) +#define SLJIT_MAX_ADDRESS ~(sljit_uw)0 -static SLJIT_INLINE sljit_uw compute_next_addr(struct sljit_label *label, struct sljit_jump *jump, - struct sljit_const *const_, struct sljit_put_label *put_label) -{ - sljit_uw result = ~(sljit_uw)0; +#define SLJIT_GET_NEXT_SIZE(ptr) (ptr != NULL) ? ((ptr)->size) : SLJIT_MAX_ADDRESS +#define SLJIT_GET_NEXT_ADDRESS(ptr) (ptr != NULL) ? ((ptr)->addr) : SLJIT_MAX_ADDRESS + +#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) - if (label) - result = label->size; +#define SLJIT_NEXT_DEFINE_TYPES \ + sljit_uw next_label_size; \ + sljit_uw next_jump_addr; \ + sljit_uw next_const_addr; \ + sljit_uw next_min_addr - if (jump && jump->addr < result) - result = jump->addr; +#define SLJIT_NEXT_INIT_TYPES() \ + next_label_size = SLJIT_GET_NEXT_SIZE(label); \ + next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); \ + next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_); - if (const_ && const_->addr < result) - result = const_->addr; +#define SLJIT_GET_NEXT_MIN() \ + next_min_addr = sljit_get_next_min(next_label_size, next_jump_addr, next_const_addr); - if (put_label && put_label->addr < result) - result = put_label->addr; +static SLJIT_INLINE sljit_uw sljit_get_next_min(sljit_uw next_label_size, + sljit_uw next_jump_addr, sljit_uw next_const_addr) +{ + sljit_uw result = next_jump_addr; + + SLJIT_ASSERT(result == SLJIT_MAX_ADDRESS || result != next_const_addr); + + if (next_const_addr < result) + result = next_const_addr; + + if (next_label_size < result) + result = next_label_size; return result; } -#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_S390X */ +#endif /* !SLJIT_CONFIG_X86 */ static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, @@ -725,8 +778,9 @@ static SLJIT_INLINE void set_set_context(struct sljit_compiler *compiler, static SLJIT_INLINE void set_label(struct sljit_label *label, struct sljit_compiler *compiler) { label->next = NULL; + label->u.index = compiler->label_count++; label->size = compiler->size; - if (compiler->last_label) + if (compiler->last_label != NULL) compiler->last_label->next = label; else compiler->labels = label; @@ -737,7 +791,21 @@ static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler { jump->next = NULL; jump->flags = flags; - if (compiler->last_jump) + jump->u.label = NULL; + if (compiler->last_jump != NULL) + compiler->last_jump->next = jump; + else + compiler->jumps = jump; + compiler->last_jump = jump; +} + +static SLJIT_INLINE void set_mov_addr(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_uw offset) +{ + jump->next = NULL; + jump->addr = compiler->size - offset; + jump->flags = JUMP_MOV_ADDR; + jump->u.label = NULL; + if (compiler->last_jump != NULL) compiler->last_jump->next = jump; else compiler->jumps = jump; @@ -748,26 +816,13 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp { const_->next = NULL; const_->addr = compiler->size; - if (compiler->last_const) + if (compiler->last_const != NULL) compiler->last_const->next = const_; else compiler->consts = const_; compiler->last_const = const_; } -static SLJIT_INLINE void set_put_label(struct sljit_put_label *put_label, struct sljit_compiler *compiler, sljit_uw offset) -{ - put_label->next = NULL; - put_label->label = NULL; - put_label->addr = compiler->size - offset; - put_label->flags = 0; - if (compiler->last_put_label) - compiler->last_put_label->next = put_label; - else - compiler->put_labels = put_label; - compiler->last_put_label = put_label; -} - #define ADDRESSING_DEPENDS_ON(exp, reg) \ (((exp) & SLJIT_MEM) && (((exp) & REG_MASK) == reg || OFFS_REG(exp) == reg)) @@ -827,11 +882,8 @@ static sljit_s32 function_check_arguments(sljit_s32 arg_types, sljit_s32 scratch #define FUNCTION_CHECK_IS_REG(r) \ (((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) \ - || ((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0)) - -#define FUNCTION_CHECK_IS_FREG(fr) \ - (((fr) >= SLJIT_FR0 && (fr) < (SLJIT_FR0 + compiler->fscratches)) \ - || ((fr) > (SLJIT_FS0 - compiler->fsaveds) && (fr) <= SLJIT_FS0)) + || ((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0) \ + || ((r) >= SLJIT_TMP_REGISTER_BASE && (r) < (SLJIT_TMP_REGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_REGISTERS))) #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) #define CHECK_IF_VIRTUAL_REGISTER(p) ((p) <= SLJIT_S3 && (p) >= SLJIT_S8) @@ -841,7 +893,7 @@ static sljit_s32 function_check_arguments(sljit_s32 arg_types, sljit_s32 scratch static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) { - if (compiler->scratches == -1 || compiler->saveds == -1) + if (compiler->scratches == -1) return 0; if (!(p & SLJIT_MEM)) @@ -878,7 +930,7 @@ static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) { - if (compiler->scratches == -1 || compiler->saveds == -1) + if (compiler->scratches == -1) return 0; if (FUNCTION_CHECK_IS_REG(p)) @@ -895,7 +947,7 @@ static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) { - if (compiler->scratches == -1 || compiler->saveds == -1) + if (compiler->scratches == -1) return 0; if (FUNCTION_CHECK_IS_REG(p)) @@ -907,19 +959,59 @@ static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p #define FUNCTION_CHECK_DST(p, i) \ CHECK_ARGUMENT(function_check_dst(compiler, p, i)); +#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \ + || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + +#define FUNCTION_CHECK_IS_FREG(fr, is_32) \ + function_check_is_freg(compiler, (fr), (is_32)) + +static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32); + +#define FUNCTION_FCHECK(p, i, is_32) \ + CHECK_ARGUMENT(function_fcheck(compiler, (p), (i), (is_32))); + +static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i, sljit_s32 is_32) +{ + if (compiler->scratches == -1) + return 0; + + if (FUNCTION_CHECK_IS_FREG(p, is_32)) + return (i == 0); + + return function_check_src_mem(compiler, p, i); +} + +#else /* !SLJIT_CONFIG_ARM_32 && !SLJIT_CONFIG_MIPS_32 */ +#define FUNCTION_CHECK_IS_FREG(fr, is_32) \ + function_check_is_freg(compiler, (fr)) + +static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr) +{ + if (compiler->scratches == -1) + return 0; + + return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->fscratches)) + || (fr > (SLJIT_FS0 - compiler->fsaveds) && fr <= SLJIT_FS0) + || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)); +} + +#define FUNCTION_FCHECK(p, i, is_32) \ + CHECK_ARGUMENT(function_fcheck(compiler, (p), (i))); + static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) { - if (compiler->scratches == -1 || compiler->saveds == -1) + if (compiler->scratches == -1) return 0; - if (FUNCTION_CHECK_IS_FREG(p)) + if ((p >= SLJIT_FR0 && p < (SLJIT_FR0 + compiler->fscratches)) + || (p > (SLJIT_FS0 - compiler->fsaveds) && p <= SLJIT_FS0) + || (p >= SLJIT_TMP_FREGISTER_BASE && p < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS))) return (i == 0); return function_check_src_mem(compiler, p, i); } -#define FUNCTION_FCHECK(p, i) \ - CHECK_ARGUMENT(function_fcheck(compiler, p, i)); +#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */ #endif /* SLJIT_ARGUMENT_CHECKS */ @@ -948,23 +1040,35 @@ static void sljit_verbose_reg(struct sljit_compiler *compiler, sljit_s32 r) { if (r < (SLJIT_R0 + compiler->scratches)) fprintf(compiler->verbose, "r%d", r - SLJIT_R0); - else if (r != SLJIT_SP) + else if (r < SLJIT_SP) fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - r); - else + else if (r == SLJIT_SP) fprintf(compiler->verbose, "sp"); + else + fprintf(compiler->verbose, "t%d", r - SLJIT_TMP_REGISTER_BASE); } static void sljit_verbose_freg(struct sljit_compiler *compiler, sljit_s32 r) { +#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \ + || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + if (r >= SLJIT_F64_SECOND(SLJIT_FR0)) { + fprintf(compiler->verbose, "^"); + r -= SLJIT_F64_SECOND(0); + } +#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */ + if (r < (SLJIT_FR0 + compiler->fscratches)) fprintf(compiler->verbose, "fr%d", r - SLJIT_FR0); - else + else if (r < SLJIT_TMP_FREGISTER_BASE) fprintf(compiler->verbose, "fs%d", SLJIT_NUMBER_OF_FLOAT_REGISTERS - r); + else + fprintf(compiler->verbose, "ft%d", r - SLJIT_TMP_FREGISTER_BASE); } static void sljit_verbose_param(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) { - if ((p) & SLJIT_IMM) + if ((p) == SLJIT_IMM) fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i)); else if ((p) & SLJIT_MEM) { if ((p) & REG_MASK) { @@ -1016,9 +1120,17 @@ static const char* op0_names[] = { }; static const char* op1_names[] = { + "mov", "mov", "mov", "mov", + "mov", "mov", "mov", "mov", + "mov", "clz", "ctz", "rev", + "rev", "rev", "rev", "rev" +}; + +static const char* op1_types[] = { "", ".u8", ".s8", ".u16", ".s16", ".u32", ".s32", "32", - ".p", "clz", "ctz", "rev" + ".p", "", "", "", + ".u16", ".s16", ".u32", ".s32" }; static const char* op2_names[] = { @@ -1037,14 +1149,27 @@ static const char* op_src_dst_names[] = { static const char* fop1_names[] = { "mov", "conv", "conv", "conv", - "conv", "conv", "cmp", "neg", - "abs", + "conv", "conv", "conv", "conv", + "cmp", "neg", "abs", +}; + +static const char* fop1_conv_types[] = { + "sw", "s32", "sw", "s32", + "uw", "u32" }; static const char* fop2_names[] = { "add", "sub", "mul", "div" }; +static const char* fop2r_names[] = { + "copysign" +}; + +static const char* simd_op2_names[] = { + "and", "or", "xor" +}; + static const char* jump_names[] = { "equal", "not_equal", "less", "greater_equal", @@ -1052,7 +1177,8 @@ static const char* jump_names[] = { "sig_less", "sig_greater_equal", "sig_greater", "sig_less_equal", "overflow", "not_overflow", - "carry", "", + "carry", "not_carry", + "atomic_stored", "atomic_not_stored", "f_equal", "f_not_equal", "f_less", "f_greater_equal", "f_greater", "f_less_equal", @@ -1095,7 +1221,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_com jump = compiler->jumps; while (jump) { /* All jumps have target. */ - CHECK_ARGUMENT(jump->flags & (JUMP_LABEL | JUMP_ADDR)); + CHECK_ARGUMENT((jump->flags & JUMP_ADDR) || jump->u.label != NULL); jump = jump->next; } #endif @@ -1224,7 +1350,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return_void(struct sljit_ } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(compiler->last_return == SLJIT_ARG_TYPE_VOID); + CHECK_ARGUMENT(compiler->last_return == SLJIT_ARG_TYPE_RET_VOID); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) @@ -1267,7 +1393,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compi if (GET_OPCODE(op) < SLJIT_MOV_F64) { FUNCTION_CHECK_SRC(src, srcw); } else { - FUNCTION_FCHECK(src, srcw); + FUNCTION_FCHECK(src, srcw, op & SLJIT_32); } compiler->last_flags = 0; #endif @@ -1275,7 +1401,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compi if (SLJIT_UNLIKELY(!!compiler->verbose)) { if (GET_OPCODE(op) < SLJIT_MOV_F64) { fprintf(compiler->verbose, " return%s%s ", !(op & SLJIT_32) ? "" : "32", - op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE]); + op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]); sljit_verbose_param(compiler, src, srcw); } else { fprintf(compiler->verbose, " return%s ", !(op & SLJIT_32) ? ".f64" : ".f32"); @@ -1336,7 +1462,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_REV); + CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_REV_S32); switch (GET_OPCODE(op)) { case SLJIT_MOV: @@ -1344,6 +1470,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler case SLJIT_MOV_S32: case SLJIT_MOV32: case SLJIT_MOV_P: + case SLJIT_REV_U32: + case SLJIT_REV_S32: /* Nothing allowed */ CHECK_ARGUMENT(!(op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK))); break; @@ -1358,17 +1486,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - if (GET_OPCODE(op) <= SLJIT_MOV_P) - { - fprintf(compiler->verbose, " mov%s%s ", !(op & SLJIT_32) ? "" : "32", - op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE]); - } - else - { - fprintf(compiler->verbose, " %s%s%s%s%s ", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE], !(op & SLJIT_32) ? "" : "32", - !(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".", - !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]); - } + fprintf(compiler->verbose, " %s%s%s ", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE], + !(op & SLJIT_32) ? "" : "32", op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]); sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, ", "); @@ -1379,6 +1498,94 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler CHECK_RETURN_OK; } +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 mem_reg) +{ + if (SLJIT_UNLIKELY(compiler->skip_checks)) { + compiler->skip_checks = 0; + CHECK_RETURN_OK; + } + +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_ATOMIC)); + CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOV_P); + CHECK_ARGUMENT(GET_OPCODE(op) != SLJIT_MOV_S8 && GET_OPCODE(op) != SLJIT_MOV_S16 && GET_OPCODE(op) != SLJIT_MOV_S32); + + /* All arguments must be valid registers. */ + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(mem_reg) && !CHECK_IF_VIRTUAL_REGISTER(mem_reg)); + + if (op == SLJIT_MOV32_U8 || op == SLJIT_MOV32_U16) { + /* Only SLJIT_32 is allowed. */ + CHECK_ARGUMENT(!(op & (VARIABLE_FLAG_MASK | SLJIT_SET_Z))); + } else { + /* Nothing allowed. */ + CHECK_ARGUMENT(!(op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK))); + } + + compiler->last_flags = 0; +#endif /* SLJIT_ARGUMENT_CHECKS */ +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " atomic_load%s%s ", !(op & SLJIT_32) ? "" : "32", + op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]); + sljit_verbose_reg(compiler, dst_reg); + fprintf(compiler->verbose, ", ["); + sljit_verbose_reg(compiler, mem_reg); + fprintf(compiler->verbose, "]\n"); + } +#endif /* SLJIT_VERBOSE */ + CHECK_RETURN_OK; +} + +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_reg, + sljit_s32 mem_reg, + sljit_s32 temp_reg) +{ + if (SLJIT_UNLIKELY(compiler->skip_checks)) { + compiler->skip_checks = 0; + CHECK_RETURN_OK; + } + +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_ATOMIC)); + CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOV_P); + CHECK_ARGUMENT(GET_OPCODE(op) != SLJIT_MOV_S8 && GET_OPCODE(op) != SLJIT_MOV_S16 && GET_OPCODE(op) != SLJIT_MOV_S32); + + /* All arguments must be valid registers. */ + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src_reg)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(mem_reg) && !CHECK_IF_VIRTUAL_REGISTER(mem_reg)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(temp_reg) && src_reg != temp_reg); + + CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE(op) == SLJIT_ATOMIC_STORED); + + if (GET_OPCODE(op) == SLJIT_MOV_U8 || GET_OPCODE(op) == SLJIT_MOV_U16) { + /* Only SLJIT_32, SLJIT_ATOMIC_STORED are allowed. */ + CHECK_ARGUMENT(!(op & SLJIT_SET_Z)); + } else { + /* Only SLJIT_ATOMIC_STORED is allowed. */ + CHECK_ARGUMENT(!(op & (SLJIT_32 | SLJIT_SET_Z))); + } + + compiler->last_flags = GET_FLAG_TYPE(op) | (op & SLJIT_32); +#endif /* SLJIT_ARGUMENT_CHECKS */ +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " atomic_store%s%s%s ", !(op & SLJIT_32) ? "" : "32", + op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE], !(op & VARIABLE_FLAG_MASK) ? "" : ".stored"); + sljit_verbose_reg(compiler, src_reg); + fprintf(compiler->verbose, ", ["); + sljit_verbose_reg(compiler, mem_reg); + fprintf(compiler->verbose, "], "); + sljit_verbose_reg(compiler, temp_reg); + fprintf(compiler->verbose, "\n"); + } +#endif /* SLJIT_VERBOSE */ + CHECK_RETURN_OK; +} + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 unset, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, @@ -1541,20 +1748,19 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_dst(struct sljit_compi CHECK_RETURN_OK; } -static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_register_index(sljit_s32 reg) -{ - SLJIT_UNUSED_ARG(reg); -#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(reg > 0 && reg <= SLJIT_NUMBER_OF_REGISTERS); -#endif - CHECK_RETURN_OK; -} - -static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_float_register_index(sljit_s32 reg) +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_register_index(sljit_s32 type, sljit_s32 reg) { + SLJIT_UNUSED_ARG(type); SLJIT_UNUSED_ARG(reg); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(reg > 0 && reg <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); + if (type == SLJIT_GP_REGISTER) { + CHECK_ARGUMENT((reg > 0 && reg <= SLJIT_NUMBER_OF_REGISTERS) + || (reg >= SLJIT_TMP_REGISTER_BASE && reg < (SLJIT_TMP_REGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_REGISTERS))); + } else { + CHECK_ARGUMENT(type == SLJIT_FLOAT_REGISTER || ((type >> 12) == 0 || ((type >> 12) >= 3 && (type >> 12) <= 6))); + CHECK_ARGUMENT((reg > 0 && reg <= SLJIT_NUMBER_OF_FLOAT_REGISTERS) + || (reg >= SLJIT_TMP_FREGISTER_BASE && reg < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS))); + } #endif CHECK_RETURN_OK; } @@ -1608,8 +1814,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compile CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV_F64 && GET_OPCODE(op) <= SLJIT_ABS_F64); CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); - FUNCTION_FCHECK(src, srcw); - FUNCTION_FCHECK(dst, dstw); + FUNCTION_FCHECK(src, srcw, op & SLJIT_32); + FUNCTION_FCHECK(dst, dstw, op & SLJIT_32); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { @@ -1648,8 +1854,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_com CHECK_ARGUMENT(!(op & SLJIT_SET_Z)); CHECK_ARGUMENT((op & VARIABLE_FLAG_MASK) || (GET_FLAG_TYPE(op) >= SLJIT_F_EQUAL && GET_FLAG_TYPE(op) <= SLJIT_ORDERED_LESS_EQUAL)); - FUNCTION_FCHECK(src1, src1w); - FUNCTION_FCHECK(src2, src2w); + FUNCTION_FCHECK(src1, src1w, op & SLJIT_32); + FUNCTION_FCHECK(src2, src2w, op & SLJIT_32); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { @@ -1678,15 +1884,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_sw_from_f64(str #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); - CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_SW_FROM_F64 && GET_OPCODE(op) <= SLJIT_CONV_S32_FROM_F64); CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); - FUNCTION_FCHECK(src, srcw); + FUNCTION_FCHECK(src, srcw, op & SLJIT_32); FUNCTION_CHECK_DST(dst, dstw); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s.from%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE], - (GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64) ? ".s32" : ".sw", + fop1_conv_types[GET_OPCODE(op) - SLJIT_CONV_SW_FROM_F64], (op & SLJIT_32) ? ".f32" : ".f64"); sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, ", "); @@ -1697,7 +1902,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_sw_from_f64(str CHECK_RETURN_OK; } -static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { @@ -1708,16 +1913,15 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_sw(str #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); - CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_F64_FROM_SW && GET_OPCODE(op) <= SLJIT_CONV_F64_FROM_S32); CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); FUNCTION_CHECK_SRC(src, srcw); - FUNCTION_FCHECK(dst, dstw); + FUNCTION_FCHECK(dst, dstw, op & SLJIT_32); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " %s%s.from%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE], + fprintf(compiler->verbose, " %s%s.from.%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE], (op & SLJIT_32) ? ".f32" : ".f64", - (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) ? ".s32" : ".sw"); + fop1_conv_types[GET_OPCODE(op) - SLJIT_CONV_SW_FROM_F64]); sljit_verbose_fparam(compiler, dst, dstw); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, src, srcw); @@ -1732,13 +1936,18 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compile sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { + if (SLJIT_UNLIKELY(compiler->skip_checks)) { + compiler->skip_checks = 0; + CHECK_RETURN_OK; + } + #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD_F64 && GET_OPCODE(op) <= SLJIT_DIV_F64); CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); - FUNCTION_FCHECK(src1, src1w); - FUNCTION_FCHECK(src2, src2w); - FUNCTION_FCHECK(dst, dstw); + FUNCTION_FCHECK(src1, src1w, op & SLJIT_32); + FUNCTION_FCHECK(src2, src2w, op & SLJIT_32); + FUNCTION_FCHECK(dst, dstw, op & SLJIT_32); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { @@ -1754,6 +1963,80 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compile CHECK_RETURN_OK; } +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); + CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_COPYSIGN_F64); + FUNCTION_FCHECK(src1, src1w, op & SLJIT_32); + FUNCTION_FCHECK(src2, src2w, op & SLJIT_32); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(dst_freg, op & SLJIT_32)); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " %s%s ", fop2r_names[GET_OPCODE(op) - SLJIT_FOP2R_BASE], (op & SLJIT_32) ? ".f32" : ".f64"); + sljit_verbose_freg(compiler, dst_freg); + fprintf(compiler->verbose, ", "); + sljit_verbose_fparam(compiler, src1, src1w); + fprintf(compiler->verbose, ", "); + sljit_verbose_fparam(compiler, src2, src2w); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fset32(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f32 value) +{ + SLJIT_UNUSED_ARG(value); + + if (SLJIT_UNLIKELY(compiler->skip_checks)) { + compiler->skip_checks = 0; + CHECK_RETURN_OK; + } + +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 1)); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " fset32 "); + sljit_verbose_freg(compiler, freg); + fprintf(compiler->verbose, ", %f\n", value); + } +#endif + CHECK_RETURN_OK; +} + +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fset64(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f64 value) +{ + SLJIT_UNUSED_ARG(value); + + if (SLJIT_UNLIKELY(compiler->skip_checks)) { + compiler->skip_checks = 0; + CHECK_RETURN_OK; + } + +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0)); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " fset64 "); + sljit_verbose_freg(compiler, freg); + fprintf(compiler->verbose, ", %f\n", value); + } +#endif + CHECK_RETURN_OK; +} + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 freg, sljit_s32 reg) { @@ -1761,7 +2044,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcopy(struct sljit_compil CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_COPY_TO_F64 && GET_OPCODE(op) <= SLJIT_COPY_FROM_F64); CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, op & SLJIT_32)); #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg)); @@ -1836,7 +2119,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compil #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ || (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) #define CHECK_UNORDERED(type, last_flags) \ - ((((type) & 0xff) == SLJIT_UNORDERED || ((type) & 0xff) == SLJIT_ORDERED) && \ + ((((type) & 0xfe) == SLJIT_ORDERED) && \ ((last_flags) & 0xff) >= SLJIT_UNORDERED && ((last_flags) & 0xff) <= SLJIT_ORDERED_LESS_EQUAL) #else #define CHECK_UNORDERED(type, last_flags) 0 @@ -1945,10 +2228,9 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compile #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_32))); - CHECK_ARGUMENT((type & 0xff) >= SLJIT_F_EQUAL && (type & 0xff) <= SLJIT_ORDERED_LESS_EQUAL - && ((type & 0xff) <= SLJIT_ORDERED || sljit_cmp_info(type & 0xff))); - FUNCTION_FCHECK(src1, src1w); - FUNCTION_FCHECK(src2, src2w); + CHECK_ARGUMENT((type & 0xff) >= SLJIT_F_EQUAL && (type & 0xff) <= SLJIT_ORDERED_LESS_EQUAL); + FUNCTION_FCHECK(src1, src1w, type & SLJIT_32); + FUNCTION_FCHECK(src2, src2w, type & SLJIT_32); compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) @@ -2055,7 +2337,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " flags.%s%s%s ", GET_OPCODE(op) < SLJIT_OP2_BASE ? "mov" : op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], - GET_OPCODE(op) < SLJIT_OP2_BASE ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : ((op & SLJIT_32) ? "32" : ""), + GET_OPCODE(op) < SLJIT_OP2_BASE ? op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE] : ((op & SLJIT_32) ? "32" : ""), !(op & SLJIT_SET_Z) ? "" : ".z"); sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, ", %s\n", jump_names[type]); @@ -2064,9 +2346,10 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com CHECK_RETURN_OK; } -static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, - sljit_s32 src, sljit_sw srcw) + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_reg) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) sljit_s32 cond = type & ~SLJIT_32; @@ -2075,25 +2358,68 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compile CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1); CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg)); - if (src != SLJIT_IMM) { - CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src)); - CHECK_ARGUMENT(srcw == 0); - } + FUNCTION_CHECK_SRC(src1, src1w); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src2_reg)); if (cond <= SLJIT_NOT_ZERO) CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z); - else + else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) { + CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY); + compiler->last_flags = 0; + } else CHECK_ARGUMENT((cond & 0xfe) == (compiler->last_flags & 0xff) || CHECK_UNORDERED(cond, compiler->last_flags)); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " cmov%s %s, ", + fprintf(compiler->verbose, " select%s %s, ", !(type & SLJIT_32) ? "" : "32", jump_names[type & ~SLJIT_32]); sljit_verbose_reg(compiler, dst_reg); fprintf(compiler->verbose, ", "); - sljit_verbose_param(compiler, src, srcw); + sljit_verbose_param(compiler, src1, src1w); + fprintf(compiler->verbose, ", "); + sljit_verbose_reg(compiler, src2_reg); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_freg) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + sljit_s32 cond = type & ~SLJIT_32; + + CHECK_ARGUMENT(cond >= SLJIT_EQUAL && cond <= SLJIT_ORDERED_LESS_EQUAL); + + CHECK_ARGUMENT(compiler->fscratches != -1 && compiler->fsaveds != -1); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(dst_freg, type & SLJIT_32)); + FUNCTION_FCHECK(src1, src1w, type & SLJIT_32); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src2_freg, type & SLJIT_32)); + + if (cond <= SLJIT_NOT_ZERO) + CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z); + else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) { + CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY); + compiler->last_flags = 0; + } else + CHECK_ARGUMENT((cond & 0xfe) == (compiler->last_flags & 0xff) + || CHECK_UNORDERED(cond, compiler->last_flags)); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " fselect%s %s, ", + !(type & SLJIT_32) ? "" : "32", + jump_names[type & ~SLJIT_32]); + sljit_verbose_freg(compiler, dst_freg); + fprintf(compiler->verbose, ", "); + sljit_verbose_fparam(compiler, src1, src1w); + fprintf(compiler->verbose, ", "); + sljit_verbose_freg(compiler, src2_freg); fprintf(compiler->verbose, "\n"); } #endif @@ -2104,33 +2430,35 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler sljit_s32 reg, sljit_s32 mem, sljit_sw memw) { +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + sljit_s32 allowed_flags; +#endif /* SLJIT_ARGUMENT_CHECKS */ + if (SLJIT_UNLIKELY(compiler->skip_checks)) { compiler->skip_checks = 0; CHECK_RETURN_OK; } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - sljit_s32 allowed_flags; - if (type & SLJIT_MEM_UNALIGNED) { - CHECK_ARGUMENT(!(type & (SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32))); - } else if (type & SLJIT_MEM_UNALIGNED_16) { - CHECK_ARGUMENT(!(type & SLJIT_MEM_UNALIGNED_32)); + CHECK_ARGUMENT(!(type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32))); + } else if (type & SLJIT_MEM_ALIGNED_16) { + CHECK_ARGUMENT(!(type & SLJIT_MEM_ALIGNED_32)); } else { - CHECK_ARGUMENT((reg & REG_PAIR_MASK) || (type & SLJIT_MEM_UNALIGNED_32)); + CHECK_ARGUMENT((reg & REG_PAIR_MASK) || (type & SLJIT_MEM_ALIGNED_32)); } allowed_flags = SLJIT_MEM_UNALIGNED; switch (type & 0xff) { + case SLJIT_MOV_P: + case SLJIT_MOV: + allowed_flags |= SLJIT_MEM_ALIGNED_32; + /* fallthrough */ case SLJIT_MOV_U32: case SLJIT_MOV_S32: case SLJIT_MOV32: - allowed_flags = SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16; - break; - case SLJIT_MOV: - case SLJIT_MOV_P: - allowed_flags = SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32; + allowed_flags |= SLJIT_MEM_ALIGNED_16; break; } @@ -2157,15 +2485,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler else fprintf(compiler->verbose, " %s%s%s", (type & SLJIT_MEM_STORE) ? "store" : "load", - !(type & SLJIT_32) ? "" : "32", - op1_names[(type & 0xff) - SLJIT_OP1_BASE]); + !(type & SLJIT_32) ? "" : "32", op1_types[(type & 0xff) - SLJIT_OP1_BASE]); if (type & SLJIT_MEM_UNALIGNED) - printf(".un"); - else if (type & SLJIT_MEM_UNALIGNED_16) - printf(".un16"); - else if (type & SLJIT_MEM_UNALIGNED_32) - printf(".un32"); + printf(".unal"); + else if (type & SLJIT_MEM_ALIGNED_16) + printf(".al16"); + else if (type & SLJIT_MEM_ALIGNED_32) + printf(".al32"); if (reg & REG_PAIR_MASK) { fprintf(compiler->verbose, " {"); @@ -2218,7 +2545,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem_update(struct sljit_c fprintf(compiler->verbose, " %s%s%s.%s ", (type & SLJIT_MEM_STORE) ? "store" : "load", !(type & SLJIT_32) ? "" : "32", - op1_names[(type & 0xff) - SLJIT_OP1_BASE], + op1_types[(type & 0xff) - SLJIT_OP1_BASE], (type & SLJIT_MEM_POST) ? "post" : "pre"); sljit_verbose_reg(compiler, reg); @@ -2235,19 +2562,20 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compile sljit_s32 mem, sljit_sw memw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64); if (type & SLJIT_MEM_UNALIGNED) { - CHECK_ARGUMENT(!(type & (SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32))); - } else if (type & SLJIT_MEM_UNALIGNED_16) { - CHECK_ARGUMENT(!(type & SLJIT_MEM_UNALIGNED_32)); + CHECK_ARGUMENT(!(type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32))); + } else if (type & SLJIT_MEM_ALIGNED_16) { + CHECK_ARGUMENT(!(type & SLJIT_MEM_ALIGNED_32)); } else { - CHECK_ARGUMENT(type & SLJIT_MEM_UNALIGNED_32); + CHECK_ARGUMENT(type & SLJIT_MEM_ALIGNED_32); CHECK_ARGUMENT(!(type & SLJIT_32)); } - CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32))); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg)); + CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32))); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, type & SLJIT_32)); FUNCTION_CHECK_SRC_MEM(mem, memw); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) @@ -2257,11 +2585,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compile !(type & SLJIT_32) ? "f64" : "f32"); if (type & SLJIT_MEM_UNALIGNED) - printf(".un"); - else if (type & SLJIT_MEM_UNALIGNED_16) - printf(".un16"); - else if (type & SLJIT_MEM_UNALIGNED_32) - printf(".un32"); + printf(".unal"); + else if (type & SLJIT_MEM_ALIGNED_16) + printf(".al16"); + else if (type & SLJIT_MEM_ALIGNED_32) + printf(".al32"); fprintf(compiler->verbose, " "); sljit_verbose_freg(compiler, freg); @@ -2278,10 +2606,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem_update(struct sljit_ sljit_s32 mem, sljit_sw memw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64); CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_POST)) == 0); FUNCTION_CHECK_SRC_MEM(mem, memw); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, type & SLJIT_32)); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { @@ -2306,6 +2635,297 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem_update(struct sljit_ CHECK_RETURN_OK; } +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 srcdst, sljit_sw srcdstw) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD)); + CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK2(SLJIT_SIMD_STORE)) == 0); + CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type)); + CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) <= SLJIT_SIMD_GET_REG_SIZE(type)); + CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM2_SIZE(type) <= (srcdst & SLJIT_MEM) ? SLJIT_SIMD_GET_REG_SIZE(type) : 0); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0)); + FUNCTION_FCHECK(srcdst, srcdstw, 0); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + if (type & SLJIT_SIMD_TEST) + CHECK_RETURN_OK; + if (sljit_emit_simd_mov(compiler, type | SLJIT_SIMD_TEST, freg, srcdst, srcdstw) == SLJIT_ERR_UNSUPPORTED) { + fprintf(compiler->verbose, " # simd_mem: unsupported form, no instructions are emitted\n"); + CHECK_RETURN_OK; + } + + fprintf(compiler->verbose, " simd_%s.%d.%s%d", + (type & SLJIT_SIMD_STORE) ? "store" : "load", + (8 << SLJIT_SIMD_GET_REG_SIZE(type)), + (type & SLJIT_SIMD_FLOAT) ? "f" : "", + (8 << SLJIT_SIMD_GET_ELEM_SIZE(type))); + + if ((type & 0x3f000000) == SLJIT_SIMD_MEM_UNALIGNED) + fprintf(compiler->verbose, ".unal "); + else + fprintf(compiler->verbose, ".al%d ", (8 << SLJIT_SIMD_GET_ELEM2_SIZE(type))); + + sljit_verbose_freg(compiler, freg); + fprintf(compiler->verbose, ", "); + sljit_verbose_fparam(compiler, srcdst, srcdstw); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_sw srcw) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD)); + CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(0)) == 0); + CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type)); + CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0)); + + if (type & SLJIT_SIMD_FLOAT) { + if (src == SLJIT_IMM) { + CHECK_ARGUMENT(srcw == 0); + } else { + FUNCTION_FCHECK(src, srcw, SLJIT_SIMD_GET_ELEM_SIZE(type) == 2); + } + } else if (src != SLJIT_IMM) { + FUNCTION_CHECK_DST(src, srcw); + } +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + if (type & SLJIT_SIMD_TEST) + CHECK_RETURN_OK; + if (sljit_emit_simd_replicate(compiler, type | SLJIT_SIMD_TEST, freg, src, srcw) == SLJIT_ERR_UNSUPPORTED) { + fprintf(compiler->verbose, " # simd_dup: unsupported form, no instructions are emitted\n"); + CHECK_RETURN_OK; + } + + fprintf(compiler->verbose, " simd_replicate.%d.%s%d ", + (8 << SLJIT_SIMD_GET_REG_SIZE(type)), + (type & SLJIT_SIMD_FLOAT) ? "f" : "", + (8 << SLJIT_SIMD_GET_ELEM_SIZE(type))); + + sljit_verbose_freg(compiler, freg); + fprintf(compiler->verbose, ", "); + if (type & SLJIT_SIMD_FLOAT) + sljit_verbose_fparam(compiler, src, srcw); + else + sljit_verbose_param(compiler, src, srcw); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, sljit_s32 lane_index, + sljit_s32 srcdst, sljit_sw srcdstw) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD)); + CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_ZERO | SLJIT_SIMD_LANE_SIGNED | SLJIT_32)) == 0); + CHECK_ARGUMENT((type & (SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_ZERO)) != (SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_ZERO)); + CHECK_ARGUMENT((type & (SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_SIGNED)) != SLJIT_SIMD_LANE_SIGNED); + CHECK_ARGUMENT(!(type & SLJIT_SIMD_FLOAT) || !(type & (SLJIT_SIMD_LANE_SIGNED | SLJIT_32))); + CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type)); + CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type)); + CHECK_ARGUMENT(!(type & SLJIT_32) || SLJIT_SIMD_GET_ELEM_SIZE(type) <= 2); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0)); + CHECK_ARGUMENT(lane_index >= 0 && lane_index < (1 << (SLJIT_SIMD_GET_REG_SIZE(type) - SLJIT_SIMD_GET_ELEM_SIZE(type)))); + + if (type & SLJIT_SIMD_FLOAT) { + FUNCTION_FCHECK(srcdst, srcdstw, SLJIT_SIMD_GET_ELEM_SIZE(type) == 2); + } else if ((type & SLJIT_SIMD_STORE) || srcdst != SLJIT_IMM) { + FUNCTION_CHECK_DST(srcdst, srcdstw); + } +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + if (type & SLJIT_SIMD_TEST) + CHECK_RETURN_OK; + if (sljit_emit_simd_lane_mov(compiler, type | SLJIT_SIMD_TEST, freg, lane_index, srcdst, srcdstw) == SLJIT_ERR_UNSUPPORTED) { + fprintf(compiler->verbose, " # simd_move_lane: unsupported form, no instructions are emitted\n"); + CHECK_RETURN_OK; + } + + fprintf(compiler->verbose, " simd_%s_lane%s%s%s.%d.%s%d ", + (type & SLJIT_SIMD_STORE) ? "store" : "load", + (type & SLJIT_32) ? "32" : "", + (type & SLJIT_SIMD_LANE_ZERO) ? "_z" : "", + (type & SLJIT_SIMD_LANE_SIGNED) ? "_s" : "", + (8 << SLJIT_SIMD_GET_REG_SIZE(type)), + (type & SLJIT_SIMD_FLOAT) ? "f" : "", + (8 << SLJIT_SIMD_GET_ELEM_SIZE(type))); + + sljit_verbose_freg(compiler, freg); + fprintf(compiler->verbose, "[%d], ", lane_index); + if (type & SLJIT_SIMD_FLOAT) + sljit_verbose_fparam(compiler, srcdst, srcdstw); + else + sljit_verbose_param(compiler, srcdst, srcdstw); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_s32 src_lane_index) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD)); + CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(0)) == 0); + CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type)); + CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src, 0)); + CHECK_ARGUMENT(src_lane_index >= 0 && src_lane_index < (1 << (SLJIT_SIMD_GET_REG_SIZE(type) - SLJIT_SIMD_GET_ELEM_SIZE(type)))); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + if (type & SLJIT_SIMD_TEST) + CHECK_RETURN_OK; + if (sljit_emit_simd_lane_replicate(compiler, type | SLJIT_SIMD_TEST, freg, src, src_lane_index) == SLJIT_ERR_UNSUPPORTED) { + fprintf(compiler->verbose, " # simd_lane_replicate: unsupported form, no instructions are emitted\n"); + CHECK_RETURN_OK; + } + + fprintf(compiler->verbose, " simd_lane_replicate.%d.%s%d ", + (8 << SLJIT_SIMD_GET_REG_SIZE(type)), + (type & SLJIT_SIMD_FLOAT) ? "f" : "", + (8 << SLJIT_SIMD_GET_ELEM_SIZE(type))); + + sljit_verbose_freg(compiler, freg); + fprintf(compiler->verbose, ", "); + sljit_verbose_freg(compiler, src); + fprintf(compiler->verbose, "[%d]\n", src_lane_index); + } +#endif + CHECK_RETURN_OK; +} + +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_sw srcw) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD)); + CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK2(SLJIT_SIMD_EXTEND_SIGNED)) == 0); + CHECK_ARGUMENT((type & (SLJIT_SIMD_EXTEND_SIGNED | SLJIT_SIMD_FLOAT)) != (SLJIT_SIMD_EXTEND_SIGNED | SLJIT_SIMD_FLOAT)); + CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type)); + CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM2_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type)); + CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_ELEM2_SIZE(type)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0)); + FUNCTION_FCHECK(src, srcw, SLJIT_SIMD_GET_ELEM_SIZE(type) == 2); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + if (type & SLJIT_SIMD_TEST) + CHECK_RETURN_OK; + if (sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_TEST, freg, src, srcw) == SLJIT_ERR_UNSUPPORTED) { + fprintf(compiler->verbose, " # simd_extend: unsupported form, no instructions are emitted\n"); + CHECK_RETURN_OK; + } + + fprintf(compiler->verbose, " simd_load_extend%s.%d.%s%d.%s%d ", + (type & SLJIT_SIMD_EXTEND_SIGNED) ? "_s" : "", + (8 << SLJIT_SIMD_GET_REG_SIZE(type)), + (type & SLJIT_SIMD_FLOAT) ? "f" : "", + (8 << SLJIT_SIMD_GET_ELEM2_SIZE(type)), + (type & SLJIT_SIMD_FLOAT) ? "f" : "", + (8 << SLJIT_SIMD_GET_ELEM_SIZE(type))); + + sljit_verbose_freg(compiler, freg); + fprintf(compiler->verbose, ", "); + sljit_verbose_fparam(compiler, src, srcw); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 dst, sljit_sw dstw) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD)); + CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(SLJIT_32)) == SLJIT_SIMD_STORE); + CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type)); + CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0)); + FUNCTION_CHECK_DST(dst, dstw); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + if (type & SLJIT_SIMD_TEST) + CHECK_RETURN_OK; + if (sljit_emit_simd_sign(compiler, type | SLJIT_SIMD_TEST, freg, dst, dstw) == SLJIT_ERR_UNSUPPORTED) { + fprintf(compiler->verbose, " # simd_sign: unsupported form, no instructions are emitted\n"); + CHECK_RETURN_OK; + } + + fprintf(compiler->verbose, " simd_store_sign%s.%d.%s%d ", + (type & SLJIT_32) ? "32" : "", + (8 << SLJIT_SIMD_GET_REG_SIZE(type)), + (type & SLJIT_SIMD_FLOAT) ? "f" : "", + (8 << SLJIT_SIMD_GET_ELEM_SIZE(type))); + + sljit_verbose_freg(compiler, freg); + fprintf(compiler->verbose, ", "); + sljit_verbose_param(compiler, dst, dstw); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD)); + CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(0)) >= SLJIT_SIMD_OP2_AND && (type & SLJIT_SIMD_TYPE_MASK(0)) <= SLJIT_SIMD_OP2_XOR); + CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type)); + CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) <= SLJIT_SIMD_GET_REG_SIZE(type)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(dst_freg, 0)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src1_freg, 0)); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src2_freg, 0)); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + if (type & SLJIT_SIMD_TEST) + CHECK_RETURN_OK; + if (sljit_emit_simd_op2(compiler, type | SLJIT_SIMD_TEST, dst_freg, src1_freg, src2_freg) == SLJIT_ERR_UNSUPPORTED) { + fprintf(compiler->verbose, " # simd_op2: unsupported form, no instructions are emitted\n"); + CHECK_RETURN_OK; + } + + fprintf(compiler->verbose, " simd_%s.%d.%s%d ", + simd_op2_names[SLJIT_SIMD_GET_OPCODE(type) - 1], + (8 << SLJIT_SIMD_GET_REG_SIZE(type)), + (type & SLJIT_SIMD_FLOAT) ? "f" : "", + (8 << SLJIT_SIMD_GET_ELEM_SIZE(type))); + + sljit_verbose_freg(compiler, dst_freg); + fprintf(compiler->verbose, ", "); + sljit_verbose_freg(compiler, src1_freg); + fprintf(compiler->verbose, ", "); + sljit_verbose_freg(compiler, src2_freg); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) { /* Any offset is allowed. */ @@ -2341,14 +2961,14 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compil CHECK_RETURN_OK; } -static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) FUNCTION_CHECK_DST(dst, dstw); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " put_label "); + fprintf(compiler->verbose, " mov_addr "); sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, "\n"); } @@ -2363,7 +2983,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_put_label(struct sljit_co #endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */ #define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) \ - SLJIT_COMPILE_ASSERT(!(SLJIT_CONV_SW_FROM_F64 & 0x1) && !(SLJIT_CONV_F64_FROM_SW & 0x1), \ + SLJIT_COMPILE_ASSERT(!(SLJIT_CONV_SW_FROM_F64 & 0x1) && !(SLJIT_CONV_F64_FROM_SW & 0x1) && !(SLJIT_CONV_F64_FROM_UW & 0x1), \ invalid_float_opcodes); \ if (GET_OPCODE(op) >= SLJIT_CONV_SW_FROM_F64 && GET_OPCODE(op) <= SLJIT_CMP_F64) { \ if (GET_OPCODE(op) == SLJIT_CMP_F64) { \ @@ -2378,48 +2998,22 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_put_label(struct sljit_co ADJUST_LOCAL_OFFSET(src, srcw); \ return sljit_emit_fop1_conv_sw_from_f64(compiler, op, dst, dstw, src, srcw); \ } \ - CHECK(check_sljit_emit_fop1_conv_f64_from_sw(compiler, op, dst, dstw, src, srcw)); \ + if ((GET_OPCODE(op) | 0x1) == SLJIT_CONV_F64_FROM_S32) { \ + CHECK(check_sljit_emit_fop1_conv_f64_from_w(compiler, op, dst, dstw, src, srcw)); \ + ADJUST_LOCAL_OFFSET(dst, dstw); \ + ADJUST_LOCAL_OFFSET(src, srcw); \ + return sljit_emit_fop1_conv_f64_from_sw(compiler, op, dst, dstw, src, srcw); \ + } \ + CHECK(check_sljit_emit_fop1_conv_f64_from_w(compiler, op, dst, dstw, src, srcw)); \ ADJUST_LOCAL_OFFSET(dst, dstw); \ ADJUST_LOCAL_OFFSET(src, srcw); \ - return sljit_emit_fop1_conv_f64_from_sw(compiler, op, dst, dstw, src, srcw); \ + return sljit_emit_fop1_conv_f64_from_uw(compiler, op, dst, dstw, src, srcw); \ } \ CHECK(check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw)); \ ADJUST_LOCAL_OFFSET(dst, dstw); \ ADJUST_LOCAL_OFFSET(src, srcw); -#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ - || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \ - || ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)) \ - || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \ - || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) - -static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 dst_reg, - sljit_s32 src, sljit_sw srcw) -{ - struct sljit_label *label; - struct sljit_jump *jump; - sljit_s32 op = (type & SLJIT_32) ? SLJIT_MOV32 : SLJIT_MOV; - - SLJIT_SKIP_CHECKS(compiler); - jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1); - FAIL_IF(!jump); - - SLJIT_SKIP_CHECKS(compiler); - FAIL_IF(sljit_emit_op1(compiler, op, dst_reg, 0, src, srcw)); - - SLJIT_SKIP_CHECKS(compiler); - label = sljit_emit_label(compiler); - FAIL_IF(!label); - - sljit_set_label(jump, label); - return SLJIT_SUCCESS; -} - -#endif - -#if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)) \ - && !(defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +#if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)) static sljit_s32 sljit_emit_mem_unaligned(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, @@ -2432,7 +3026,7 @@ static sljit_s32 sljit_emit_mem_unaligned(struct sljit_compiler *compiler, sljit return sljit_emit_op1(compiler, type & (0xff | SLJIT_32), reg, 0, mem, memw); } -#endif /* (!SLJIT_CONFIG_MIPS || SLJIT_MIPS_REV >= 6) && !SLJIT_CONFIG_ARM_V5 */ +#endif /* (!SLJIT_CONFIG_MIPS || SLJIT_MIPS_REV >= 6) */ #if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)) \ && !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) @@ -2478,7 +3072,7 @@ static sljit_s32 sljit_emit_fmem_unaligned(struct sljit_compiler *compiler, slji #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) # include "sljitNativeX86_common.c" -#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +#elif (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) # include "sljitNativeARM_32.c" #elif (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) # include "sljitNativeARM_32.c" @@ -2494,8 +3088,12 @@ static sljit_s32 sljit_emit_fmem_unaligned(struct sljit_compiler *compiler, slji # include "sljitNativeRISCV_common.c" #elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) # include "sljitNativeS390X.c" +#elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH) +# include "sljitNativeLOONGARCH_64.c" #endif +#include "sljitSerialize.c" + static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) @@ -2540,8 +3138,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp return sljit_emit_return_void(compiler); } +#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ + && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \ + && !(defined(SLJIT_CONFIG_LOONGARCH_64) && SLJIT_CONFIG_LOONGARCH_64) + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_fop2r(compiler, op, dst_freg, src1, src1w, src2, src2w)); + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_fop2(compiler, op, dst_freg, 0, src1, src1w, src2, src2w); +} + +#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_S390X && !SLJIT_CONFIG_LOONGARCH_64 */ + #if !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \ - && !(defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) + && !(defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \ + && !(defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH) SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, @@ -2557,18 +3176,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler condition = type & 0xff; #if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) if ((condition == SLJIT_EQUAL || condition == SLJIT_NOT_EQUAL)) { - if ((src1 & SLJIT_IMM) && !src1w) { + if (src1 == SLJIT_IMM && !src1w) { src1 = src2; src1w = src2w; src2 = SLJIT_IMM; src2w = 0; } - if ((src2 & SLJIT_IMM) && !src2w) + if (src2 == SLJIT_IMM && !src2w) return emit_cmp_to0(compiler, type, src1, src1w); } #endif - if (SLJIT_UNLIKELY((src1 & SLJIT_IMM) && !(src2 & SLJIT_IMM))) { + if (SLJIT_UNLIKELY(src1 == SLJIT_IMM && src2 != SLJIT_IMM)) { /* Immediate is preferred as second argument by most architectures. */ switch (condition) { case SLJIT_LESS: @@ -2621,20 +3240,17 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler #endif /* !SLJIT_CONFIG_MIPS */ -#if (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) +#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) { - if (type < SLJIT_UNORDERED || type > SLJIT_ORDERED_LESS_EQUAL) - return 0; - switch (type) { case SLJIT_UNORDERED_OR_EQUAL: case SLJIT_ORDERED_NOT_EQUAL: - return 0; + return 1; } - return 1; + return 0; } #endif /* SLJIT_CONFIG_ARM */ @@ -2707,519 +3323,174 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler #endif /* !SLJIT_CONFIG_ARM_64 && !SLJIT_CONFIG_PPC */ #if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ - && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) + && !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \ + && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 srcdst, sljit_sw srcdstw) { CHECK_ERROR(); - CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset)); - - ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset); - - SLJIT_SKIP_CHECKS(compiler); + CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw)); + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(freg); + SLJIT_UNUSED_ARG(srcdst); + SLJIT_UNUSED_ARG(srcdstw); - if (offset != 0) - return sljit_emit_op2(compiler, SLJIT_ADD, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset); - return sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_SP, 0); + return SLJIT_ERR_UNSUPPORTED; } -#endif - -#else /* SLJIT_CONFIG_UNSUPPORTED */ - -/* Empty function bodies for those machines, which are not (yet) supported. */ - -SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_sw srcw) { - return "unsupported"; -} + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw)); + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(freg); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); -SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data, void *exec_allocator_data) -{ - SLJIT_UNUSED_ARG(allocator_data); - SLJIT_UNUSED_ARG(exec_allocator_data); - SLJIT_UNREACHABLE(); - return NULL; + return SLJIT_ERR_UNSUPPORTED; } -SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, sljit_s32 lane_index, + sljit_s32 srcdst, sljit_sw srcdstw) { + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw)); SLJIT_UNUSED_ARG(compiler); - SLJIT_UNREACHABLE(); -} + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(freg); + SLJIT_UNUSED_ARG(lane_index); + SLJIT_UNUSED_ARG(srcdst); + SLJIT_UNUSED_ARG(srcdstw); -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; } -SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_s32 src_lane_index) { + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index)); SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(size); - SLJIT_UNREACHABLE(); - return NULL; -} + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(freg); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(src_lane_index); -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) -SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(verbose); - SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; } -#endif -SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_sw srcw) { + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw)); SLJIT_UNUSED_ARG(compiler); - SLJIT_UNREACHABLE(); - return NULL; -} + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(freg); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) -{ - SLJIT_UNUSED_ARG(feature_type); - SLJIT_UNREACHABLE(); - return 0; + return SLJIT_ERR_UNSUPPORTED; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) -{ - SLJIT_UNUSED_ARG(type); - SLJIT_UNREACHABLE(); - return 0; -} - -SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data) -{ - SLJIT_UNUSED_ARG(code); - SLJIT_UNUSED_ARG(exec_allocator_data); - SLJIT_UNREACHABLE(); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, - sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(options); - SLJIT_UNUSED_ARG(arg_types); - SLJIT_UNUSED_ARG(scratches); - SLJIT_UNUSED_ARG(saveds); - SLJIT_UNUSED_ARG(fscratches); - SLJIT_UNUSED_ARG(fsaveds); - SLJIT_UNUSED_ARG(local_size); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, - sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(options); - SLJIT_UNUSED_ARG(arg_types); - SLJIT_UNUSED_ARG(scratches); - SLJIT_UNUSED_ARG(saveds); - SLJIT_UNUSED_ARG(fscratches); - SLJIT_UNUSED_ARG(fsaveds); - SLJIT_UNUSED_ARG(local_size); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(op); - SLJIT_UNUSED_ARG(src); - SLJIT_UNUSED_ARG(srcw); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(src); - SLJIT_UNUSED_ARG(srcw); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 dst, sljit_sw dstw) { + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw)); SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(freg); SLJIT_UNUSED_ARG(dst); SLJIT_UNUSED_ARG(dstw); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(op); - SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 dst, sljit_sw dstw, - sljit_s32 src, sljit_sw srcw) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg) { + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg)); SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(op); - SLJIT_UNUSED_ARG(dst); - SLJIT_UNUSED_ARG(dstw); - SLJIT_UNUSED_ARG(src); - SLJIT_UNUSED_ARG(srcw); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(dst_freg); + SLJIT_UNUSED_ARG(src1_freg); + SLJIT_UNUSED_ARG(src2_freg); -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 dst, sljit_sw dstw, - sljit_s32 src1, sljit_sw src1w, - sljit_s32 src2, sljit_sw src2w) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(op); - SLJIT_UNUSED_ARG(dst); - SLJIT_UNUSED_ARG(dstw); - SLJIT_UNUSED_ARG(src1); - SLJIT_UNUSED_ARG(src1w); - SLJIT_UNUSED_ARG(src2); - SLJIT_UNUSED_ARG(src2w); - SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 src1, sljit_sw src1w, - sljit_s32 src2, sljit_sw src2w) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(op); - SLJIT_UNUSED_ARG(src1); - SLJIT_UNUSED_ARG(src1w); - SLJIT_UNUSED_ARG(src2); - SLJIT_UNUSED_ARG(src2w); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} +#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM */ + +#if !(defined(SLJIT_CONFIG_X86) && SLJIT_CONFIG_X86) \ + && !(defined(SLJIT_CONFIG_ARM) && SLJIT_CONFIG_ARM) \ + && !(defined(SLJIT_CONFIG_S390X) && SLJIT_CONFIG_S390X) \ + && !(defined(SLJIT_CONFIG_LOONGARCH) && SLJIT_CONFIG_LOONGARCH) -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, + sljit_s32 op, sljit_s32 dst_reg, - sljit_s32 src1_reg, - sljit_s32 src2_reg, - sljit_s32 src3, sljit_sw src3w) + sljit_s32 mem_reg) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(op); SLJIT_UNUSED_ARG(dst_reg); - SLJIT_UNUSED_ARG(src1_reg); - SLJIT_UNUSED_ARG(src2_reg); - SLJIT_UNUSED_ARG(src3); - SLJIT_UNUSED_ARG(src3w); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 src, sljit_sw srcw) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(op); - SLJIT_UNUSED_ARG(src); - SLJIT_UNUSED_ARG(srcw); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) -{ - SLJIT_UNREACHABLE(); - return reg; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, - void *instruction, sljit_u32 size) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(instruction); - SLJIT_UNUSED_ARG(size); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} + SLJIT_UNUSED_ARG(mem_reg); -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(current_flags); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 dst, sljit_sw dstw, - sljit_s32 src, sljit_sw srcw) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(op); - SLJIT_UNUSED_ARG(dst); - SLJIT_UNUSED_ARG(dstw); - SLJIT_UNUSED_ARG(src); - SLJIT_UNUSED_ARG(srcw); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 dst, sljit_sw dstw, - sljit_s32 src1, sljit_sw src1w, - sljit_s32 src2, sljit_sw src2w) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(op); - SLJIT_UNUSED_ARG(dst); - SLJIT_UNUSED_ARG(dstw); - SLJIT_UNUSED_ARG(src1); - SLJIT_UNUSED_ARG(src1w); - SLJIT_UNUSED_ARG(src2); - SLJIT_UNUSED_ARG(src2w); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 freg, sljit_s32 reg) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(op); - SLJIT_UNUSED_ARG(freg); - SLJIT_UNUSED_ARG(reg); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} - -SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNREACHABLE(); - return NULL; -} - -SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(type); - SLJIT_UNREACHABLE(); - return NULL; -} - -SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 arg_types) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(arg_types); - SLJIT_UNREACHABLE(); - return NULL; -} - -SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 src1, sljit_sw src1w, - sljit_s32 src2, sljit_sw src2w) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(src1); - SLJIT_UNUSED_ARG(src1w); - SLJIT_UNUSED_ARG(src2); - SLJIT_UNUSED_ARG(src2w); - SLJIT_UNREACHABLE(); - return NULL; -} - -SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 src1, sljit_sw src1w, - sljit_s32 src2, sljit_sw src2w) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(src1); - SLJIT_UNUSED_ARG(src1w); - SLJIT_UNUSED_ARG(src2); - SLJIT_UNUSED_ARG(src2w); - SLJIT_UNREACHABLE(); - return NULL; -} - -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label) -{ - SLJIT_UNUSED_ARG(jump); - SLJIT_UNUSED_ARG(label); - SLJIT_UNREACHABLE(); -} - -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target) -{ - SLJIT_UNUSED_ARG(jump); - SLJIT_UNUSED_ARG(target); - SLJIT_UNREACHABLE(); -} - -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label) -{ - SLJIT_UNUSED_ARG(put_label); - SLJIT_UNUSED_ARG(label); - SLJIT_UNREACHABLE(); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(src); - SLJIT_UNUSED_ARG(srcw); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} + CHECK_ERROR(); + CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 arg_types, - sljit_s32 src, sljit_sw srcw) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(arg_types); - SLJIT_UNUSED_ARG(src); - SLJIT_UNUSED_ARG(srcw); - SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 dst, sljit_sw dstw, - sljit_s32 type) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, + sljit_s32 op, + sljit_s32 src_reg, + sljit_s32 mem_reg, + sljit_s32 temp_reg) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(op); - SLJIT_UNUSED_ARG(dst); - SLJIT_UNUSED_ARG(dstw); - SLJIT_UNUSED_ARG(type); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} + SLJIT_UNUSED_ARG(src_reg); + SLJIT_UNUSED_ARG(mem_reg); + SLJIT_UNUSED_ARG(temp_reg); -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 dst_reg, - sljit_s32 src, sljit_sw srcw) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(dst_reg); - SLJIT_UNUSED_ARG(src); - SLJIT_UNUSED_ARG(srcw); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(reg); - SLJIT_UNUSED_ARG(mem); - SLJIT_UNUSED_ARG(memw); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} + CHECK_ERROR(); + CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg)); -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(reg); - SLJIT_UNUSED_ARG(mem); - SLJIT_UNUSED_ARG(memw); - SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(freg); - SLJIT_UNUSED_ARG(mem); - SLJIT_UNUSED_ARG(memw); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} +#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM && !SLJIT_CONFIG_S390X && !SLJIT_CONFIG_LOONGARCH */ -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(type); - SLJIT_UNUSED_ARG(freg); - SLJIT_UNUSED_ARG(mem); - SLJIT_UNUSED_ARG(memw); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} +#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ + && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) { - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(dst); - SLJIT_UNUSED_ARG(dstw); - SLJIT_UNUSED_ARG(offset); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} + CHECK_ERROR(); + CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset)); -SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw initval) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(dst); - SLJIT_UNUSED_ARG(dstw); - SLJIT_UNUSED_ARG(initval); - SLJIT_UNREACHABLE(); - return NULL; -} + ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset); -SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(dst); - SLJIT_UNUSED_ARG(dstw); - return NULL; -} + SLJIT_SKIP_CHECKS(compiler); -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) -{ - SLJIT_UNUSED_ARG(addr); - SLJIT_UNUSED_ARG(new_target); - SLJIT_UNUSED_ARG(executable_offset); - SLJIT_UNREACHABLE(); + if (offset != 0) + return sljit_emit_op2(compiler, SLJIT_ADD, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset); + return sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_SP, 0); } -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) -{ - SLJIT_UNUSED_ARG(addr); - SLJIT_UNUSED_ARG(new_constant); - SLJIT_UNUSED_ARG(executable_offset); - SLJIT_UNREACHABLE(); -} +#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM_64 */ #endif /* !SLJIT_CONFIG_UNSUPPORTED */ diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitLir.h b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitLir.h index 87805dd7fda..0974056d6c9 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitLir.h +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitLir.h @@ -72,6 +72,7 @@ #include "sljitConfigPre.h" #endif /* SLJIT_HAVE_CONFIG_PRE */ +#include "sljitConfigCPU.h" #include "sljitConfig.h" /* The following header file defines useful macros for fine tuning @@ -107,9 +108,9 @@ extern "C" { /* Cannot allocate executable memory. Only sljit_generate_code() returns with this error code. */ #define SLJIT_ERR_EX_ALLOC_FAILED 3 -/* Return value for SLJIT_CONFIG_UNSUPPORTED placeholder architecture. */ +/* Unsupported instruction form. */ #define SLJIT_ERR_UNSUPPORTED 4 -/* An ivalid argument is passed to any SLJIT function. */ +/* An invalid argument is passed to any SLJIT function. */ #define SLJIT_ERR_BAD_ARGUMENT 5 /* --------------------------------------------------------------------- */ @@ -127,40 +128,40 @@ extern "C" { is the first saved register, the one before the last is the second saved register, and so on. - If an architecture provides two scratch and three saved registers, - its scratch and saved register sets are the following: + For example, in an architecture with only five registers (A-E), if two + are scratch and three saved registers, they will be defined as follows: - R0 | | R0 is always a scratch register - R1 | | R1 is always a scratch register - [R2] | S2 | R2 and S2 represent the same physical register - [R3] | S1 | R3 and S1 represent the same physical register - [R4] | S0 | R4 and S0 represent the same physical register + A | R0 | | R0 always represent scratch register A + B | R1 | | R1 always represent scratch register B + C | [R2] | S2 | R2 and S2 represent the same physical register C + D | [R3] | S1 | R3 and S1 represent the same physical register D + E | [R4] | S0 | R4 and S0 represent the same physical register E - Note: SLJIT_NUMBER_OF_SCRATCH_REGISTERS would be 2 and - SLJIT_NUMBER_OF_SAVED_REGISTERS would be 3 for this architecture. + Note: SLJIT_NUMBER_OF_SCRATCH_REGISTERS will be 2 and + SLJIT_NUMBER_OF_SAVED_REGISTERS will be 3. - Note: On all supported architectures SLJIT_NUMBER_OF_REGISTERS >= 12 + Note: For all supported architectures SLJIT_NUMBER_OF_REGISTERS >= 12 and SLJIT_NUMBER_OF_SAVED_REGISTERS >= 6. However, 6 registers are virtual on x86-32. See below. The purpose of this definition is convenience: saved registers can - be used as extra scratch registers. For example four registers can - be specified as scratch registers and the fifth one as saved register - on the CPU above and any user code which requires four scratch - registers can run unmodified. The SLJIT compiler automatically saves - the content of the two extra scratch register on the stack. Scratch - registers can also be preserved by saving their value on the stack - but this needs to be done manually. + be used as extra scratch registers. For example, building in the + previous example, four registers can be specified as scratch registers + and the fifth one as saved register, allowing any user code which requires + four scratch registers to run unmodified. The SLJIT compiler automatically + saves the content of the two extra scratch register on the stack. Scratch + registers can also be preserved by saving their value on the stack but + that needs to be done manually. Note: To emphasize that registers assigned to R2-R4 are saved registers, they are enclosed by square brackets. - Note: sljit_emit_enter and sljit_set_context defines whether a register - is S or R register. E.g: when 3 scratches and 1 saved is mapped - by sljit_emit_enter, the allowed register set will be: R0-R2 and - S0. Although S2 is mapped to the same position as R2, it does not - available in the current configuration. Furthermore the S1 register - is not available at all. + Note: sljit_emit_enter and sljit_set_context define whether a register + is S or R register. E.g: if in the previous example 3 scratches and + 1 saved are mapped by sljit_emit_enter, the allowed register set + will be: R0-R2 and S0. Although S2 is mapped to the same register + than R2, it is not available in that configuration. Furthermore + the S1 register cannot be used at all. */ /* Scratch registers. */ @@ -209,7 +210,7 @@ extern "C" { /* The SLJIT_SP provides direct access to the linear stack space allocated by sljit_emit_enter. It can only be used in the following form: SLJIT_MEM1(SLJIT_SP). The immediate offset is extended by the relative stack offset automatically. - The sljit_get_local_base can be used to obtain the real address of a value. */ + sljit_get_local_base can be used to obtain the real address of a value. */ #define SLJIT_SP (SLJIT_NUMBER_OF_REGISTERS + 1) /* Return with machine word. */ @@ -221,7 +222,7 @@ extern "C" { /* --------------------------------------------------------------------- */ /* Each floating point register can store a 32 or a 64 bit precision - value. The FR and FS register sets are overlap in the same way as R + value. The FR and FS register sets overlap in the same way as R and S register sets. See above. */ /* Floating point scratch registers. */ @@ -231,6 +232,10 @@ extern "C" { #define SLJIT_FR3 4 #define SLJIT_FR4 5 #define SLJIT_FR5 6 +#define SLJIT_FR6 7 +#define SLJIT_FR7 8 +#define SLJIT_FR8 9 +#define SLJIT_FR9 10 /* All FR registers provided by the architecture can be accessed by SLJIT_FR(i) The i parameter must be >= 0 and < SLJIT_NUMBER_OF_FLOAT_REGISTERS. */ #define SLJIT_FR(i) (1 + (i)) @@ -242,6 +247,10 @@ extern "C" { #define SLJIT_FS3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 3) #define SLJIT_FS4 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 4) #define SLJIT_FS5 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 5) +#define SLJIT_FS6 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 6) +#define SLJIT_FS7 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 7) +#define SLJIT_FS8 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 8) +#define SLJIT_FS9 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 9) /* All S registers provided by the architecture can be accessed by SLJIT_FS(i) The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS. */ #define SLJIT_FS(i) (SLJIT_NUMBER_OF_FLOAT_REGISTERS - (i)) @@ -260,23 +269,39 @@ extern "C" { /* The following argument type definitions are used by sljit_emit_enter, sljit_set_context, sljit_emit_call, and sljit_emit_icall functions. - As for sljit_emit_call and sljit_emit_icall, the first integer argument + For sljit_emit_call and sljit_emit_icall, the first integer argument must be placed into SLJIT_R0, the second one into SLJIT_R1, and so on. Similarly the first floating point argument must be placed into SLJIT_FR0, the second one into SLJIT_FR1, and so on. - As for sljit_emit_enter, the integer arguments can be stored in scratch - or saved registers. The first integer argument without _R postfix is - stored in SLJIT_S0, the next one in SLJIT_S1, and so on. The integer - arguments with _R postfix are placed into scratch registers. The index - of the scratch register is the count of the previous integer arguments - starting from SLJIT_R0. The floating point arguments are always placed - into SLJIT_FR0, SLJIT_FR1, and so on. + For sljit_emit_enter, the integer arguments can be stored in scratch + or saved registers. Scratch registers are identified by a _R suffix. - Note: if a function is called by sljit_emit_call/sljit_emit_icall and - an argument is stored in a scratch register by sljit_emit_enter, - that argument uses the same scratch register index for both - integer and floating point arguments. + If only saved registers are used, then the allocation mirrors what is + done for the "call" functions but using saved registers, meaning that + the first integer argument goes to SLJIT_S0, the second one goes into + SLJIT_S1, and so on. + + If scratch registers are used, then the way the integer registers are + allocated changes so that SLJIT_S0, SLJIT_S1, etc; will be assigned + only for the arguments not using scratch registers, while SLJIT_R + will be used for the ones using scratch registers. + + Furthermore, the index (shown as "n" above) that will be used for the + scratch register depends on how many previous integer registers + (scratch or saved) were used already, starting with SLJIT_R0. + Eventhough some indexes will be likely skipped, they still need to be + accounted for in the scratches parameter of sljit_emit_enter. See below + for some examples. + + The floating point arguments always use scratch registers (but not the + _R suffix like the integer arguments) and must use SLJIT_FR0, SLJIT_FR1, + just like in the "call" functions. + + Note: the mapping for scratch registers is part of the compiler context + and therefore a new context after sljit_emit_call/sljit_emit_icall + could remove access to some scratch registers that were used as + arguments. Example function definition: sljit_f32 SLJIT_FUNC example_c_callback(void *arg_a, @@ -292,25 +317,29 @@ extern "C" { Argument passing: arg_a must be placed in SLJIT_R0 - arg_c must be placed in SLJIT_R1 arg_b must be placed in SLJIT_FR0 + arg_c must be placed in SLJIT_R1 arg_d must be placed in SLJIT_FR1 Examples for argument processing by sljit_emit_enter: - SLJIT_ARGS4(VOID, P, 32_R, F32, W) + SLJIT_ARGS4V(P, 32_R, F32, W) Arguments are placed into: SLJIT_S0, SLJIT_R1, SLJIT_FR0, SLJIT_S1 + The type of the result is void. - SLJIT_ARGS4(VOID, W, W_R, W, W_R) + SLJIT_ARGS4(F32, W, W_R, W, W_R) Arguments are placed into: SLJIT_S0, SLJIT_R1, SLJIT_S1, SLJIT_R3 + The type of the result is sljit_f32. - SLJIT_ARGS4(VOID, F64, W, F32, W_R) + SLJIT_ARGS4(P, W, F32, P_R) Arguments are placed into: SLJIT_FR0, SLJIT_S0, SLJIT_FR1, SLJIT_R1 + The type of the result is pointer. Note: it is recommended to pass the scratch arguments first followed by the saved arguments: - SLJIT_ARGS4(VOID, W_R, W_R, W, W) + SLJIT_ARGS4(W, W_R, W_R, W, W) Arguments are placed into: SLJIT_R0, SLJIT_R1, SLJIT_S0, SLJIT_S1 + The type of the result is sljit_sw / sljit_uw. */ /* The following flag is only allowed for the integer arguments of @@ -318,21 +347,21 @@ extern "C" { stored in a scratch register instead of a saved register. */ #define SLJIT_ARG_TYPE_SCRATCH_REG 0x8 -/* Void result, can only be used by SLJIT_ARG_RETURN. */ -#define SLJIT_ARG_TYPE_VOID 0 +/* No return value, only supported by SLJIT_ARG_RETURN. */ +#define SLJIT_ARG_TYPE_RET_VOID 0 /* Machine word sized integer argument or result. */ -#define SLJIT_ARG_TYPE_W 1 +#define SLJIT_ARG_TYPE_W 1 #define SLJIT_ARG_TYPE_W_R (SLJIT_ARG_TYPE_W | SLJIT_ARG_TYPE_SCRATCH_REG) /* 32 bit integer argument or result. */ -#define SLJIT_ARG_TYPE_32 2 +#define SLJIT_ARG_TYPE_32 2 #define SLJIT_ARG_TYPE_32_R (SLJIT_ARG_TYPE_32 | SLJIT_ARG_TYPE_SCRATCH_REG) /* Pointer sized integer argument or result. */ -#define SLJIT_ARG_TYPE_P 3 +#define SLJIT_ARG_TYPE_P 3 #define SLJIT_ARG_TYPE_P_R (SLJIT_ARG_TYPE_P | SLJIT_ARG_TYPE_SCRATCH_REG) /* 64 bit floating point argument or result. */ -#define SLJIT_ARG_TYPE_F64 4 +#define SLJIT_ARG_TYPE_F64 4 /* 32 bit floating point argument or result. */ -#define SLJIT_ARG_TYPE_F32 5 +#define SLJIT_ARG_TYPE_F32 5 #define SLJIT_ARG_SHIFT 4 #define SLJIT_ARG_RETURN(type) (type) @@ -345,24 +374,40 @@ extern "C" { can be shortened to: SLJIT_ARGS1(W, F32) + + Another example where no value is returned: + SLJIT_ARG_RETURN(SLJIT_ARG_TYPE_RET_VOID) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_W_R, 1) + + can be shortened to: + SLJIT_ARGS1V(W_R) */ #define SLJIT_ARG_TO_TYPE(type) SLJIT_ARG_TYPE_ ## type #define SLJIT_ARGS0(ret) \ SLJIT_ARG_RETURN(SLJIT_ARG_TO_TYPE(ret)) +#define SLJIT_ARGS0V() \ + SLJIT_ARG_RETURN(SLJIT_ARG_TYPE_RET_VOID) #define SLJIT_ARGS1(ret, arg1) \ (SLJIT_ARGS0(ret) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg1), 1)) +#define SLJIT_ARGS1V(arg1) \ + (SLJIT_ARGS0V() | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg1), 1)) #define SLJIT_ARGS2(ret, arg1, arg2) \ (SLJIT_ARGS1(ret, arg1) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg2), 2)) +#define SLJIT_ARGS2V(arg1, arg2) \ + (SLJIT_ARGS1V(arg1) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg2), 2)) #define SLJIT_ARGS3(ret, arg1, arg2, arg3) \ (SLJIT_ARGS2(ret, arg1, arg2) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg3), 3)) +#define SLJIT_ARGS3V(arg1, arg2, arg3) \ + (SLJIT_ARGS2V(arg1, arg2) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg3), 3)) #define SLJIT_ARGS4(ret, arg1, arg2, arg3, arg4) \ (SLJIT_ARGS3(ret, arg1, arg2, arg3) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg4), 4)) +#define SLJIT_ARGS4V(arg1, arg2, arg3, arg4) \ + (SLJIT_ARGS3V(arg1, arg2, arg3) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg4), 4)) /* --------------------------------------------------------------------- */ /* Main structures and functions */ @@ -382,7 +427,10 @@ struct sljit_memory_fragment { struct sljit_label { struct sljit_label *next; - sljit_uw addr; + union { + sljit_uw index; + sljit_uw addr; + } u; /* The maximum size difference. */ sljit_uw size; }; @@ -398,13 +446,6 @@ struct sljit_jump { } u; }; -struct sljit_put_label { - struct sljit_put_label *next; - struct sljit_label *label; - sljit_uw addr; - sljit_uw flags; -}; - struct sljit_const { struct sljit_const *next; sljit_uw addr; @@ -416,18 +457,18 @@ struct sljit_compiler { struct sljit_label *labels; struct sljit_jump *jumps; - struct sljit_put_label *put_labels; struct sljit_const *consts; struct sljit_label *last_label; struct sljit_jump *last_jump; struct sljit_const *last_const; - struct sljit_put_label *last_put_label; void *allocator_data; void *exec_allocator_data; struct sljit_memory_fragment *buf; struct sljit_memory_fragment *abuf; + /* Number of labels created by the compiler. */ + sljit_uw label_count; /* Available scratch registers. */ sljit_s32 scratches; /* Available saved registers. */ @@ -447,17 +488,18 @@ struct sljit_compiler { #if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE) sljit_s32 status_flags_state; -#endif +#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */ #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) sljit_s32 args_size; -#endif +#endif /* SLJIT_CONFIG_X86_32 */ #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + /* Temporary fields. */ sljit_s32 mode32; -#endif +#endif /* SLJIT_CONFIG_X86_64 */ -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) /* Constant pool handling. */ sljit_uw *cpool; sljit_u8 *cpool_unique; @@ -466,44 +508,54 @@ struct sljit_compiler { /* Other members. */ /* Contains pointer, "ldr pc, [...]" pairs. */ sljit_uw patches; -#endif +#endif /* SLJIT_CONFIG_ARM_V6 */ -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) /* Temporary fields. */ sljit_uw shift_imm; -#endif /* SLJIT_CONFIG_ARM_V5 || SLJIT_CONFIG_ARM_V7 */ +#endif /* SLJIT_CONFIG_ARM_V6 || SLJIT_CONFIG_ARM_V6 */ #if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__) sljit_uw args_size; -#endif +#endif /* SLJIT_CONFIG_ARM_32 && __SOFTFP__ */ #if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) + /* Temporary fields. */ sljit_u32 imm; -#endif +#endif /* SLJIT_CONFIG_PPC */ #if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) sljit_s32 delay_slot; + /* Temporary fields. */ sljit_s32 cache_arg; sljit_sw cache_argw; -#endif +#endif /* SLJIT_CONFIG_MIPS */ #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) sljit_uw args_size; -#endif +#endif /* SLJIT_CONFIG_MIPS_32 */ #if (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) + /* Temporary fields. */ sljit_s32 cache_arg; sljit_sw cache_argw; -#endif +#endif /* SLJIT_CONFIG_RISCV */ #if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) /* Need to allocate register save area to make calls. */ + /* Temporary fields. */ sljit_s32 mode; -#endif +#endif /* SLJIT_CONFIG_S390X */ + +#if (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH) + /* Temporary fields. */ + sljit_s32 cache_arg; + sljit_sw cache_argw; +#endif /* SLJIT_CONFIG_LOONGARCH */ #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) FILE* verbose; -#endif +#endif /* SLJIT_VERBOSE */ #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ || (defined SLJIT_DEBUG && SLJIT_DEBUG) @@ -514,7 +566,7 @@ struct sljit_compiler { sljit_s32 last_return; /* Local size passed to entry functions. */ sljit_s32 logical_local_size; -#endif +#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */ #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ || (defined SLJIT_DEBUG && SLJIT_DEBUG) \ @@ -522,7 +574,7 @@ struct sljit_compiler { /* Trust arguments when an API function is called. Used internally for calling API functions. */ sljit_s32 skip_checks; -#endif +#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG || SLJIT_VERBOSE */ }; /* --------------------------------------------------------------------- */ @@ -637,24 +689,37 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler #define SLJIT_HAS_COPY_F32 9 /* [Emulated] Copy from/to f64 operation is available (see sljit_emit_fcopy). */ #define SLJIT_HAS_COPY_F64 10 +/* [Not emulated] The 64 bit floating point registers can be used as + two separate 32 bit floating point registers (e.g. ARM32). The + second 32 bit part can be accessed by SLJIT_F64_SECOND. */ +#define SLJIT_HAS_F64_AS_F32_PAIR 11 +/* [Not emulated] Some SIMD operations are supported by the compiler. */ +#define SLJIT_HAS_SIMD 12 +/* [Not emulated] SIMD registers are mapped to a pair of double precision + floating point registers. E.g. passing either SLJIT_FR0 or SLJIT_FR1 to + a simd operation represents the same 128 bit register, and both SLJIT_FR0 + and SLJIT_FR1 are overwritten. */ +#define SLJIT_SIMD_REGS_ARE_PAIRS 13 +/* [Not emulated] Atomic support is available (fine-grained). */ +#define SLJIT_HAS_ATOMIC 14 #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) -/* [Not emulated] SSE2 support is available on x86. */ -#define SLJIT_HAS_SSE2 100 +/* [Not emulated] AVX support is available on x86. */ +#define SLJIT_HAS_AVX 100 +/* [Not emulated] AVX2 support is available on x86. */ +#define SLJIT_HAS_AVX2 101 #endif SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type); /* If type is between SLJIT_ORDERED_EQUAL and SLJIT_ORDERED_LESS_EQUAL, - sljit_cmp_info returns one, if the cpu supports the passed floating - point comparison type. + sljit_cmp_info returns with: + zero - if the cpu supports the floating point comparison type + one - if the comparison requires two machine instructions + two - if the comparison requires more than two machine instructions - If type is SLJIT_UNORDERED or SLJIT_ORDERED, sljit_cmp_info returns - one, if the cpu supports checking the unordered comparison result - regardless of the comparison type passed to the comparison instruction. - The returned value is always one, if there is at least one type between - SLJIT_ORDERED_EQUAL and SLJIT_ORDERED_LESS_EQUAL where sljit_cmp_info - returns with a zero value. + When the result is non-zero, it is recommended to avoid + using the specified comparison type if it is easy to do so. Otherwise it returns zero. */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type); @@ -665,7 +730,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type); /* The executable code is a function from the viewpoint of the C - language. The function calls must obey to the ABI (Application + language. The function calls must conform to the ABI (Application Binary Interface) of the platform, which specify the purpose of machine registers and stack handling among other things. The sljit_emit_enter function emits the necessary instructions for @@ -724,7 +789,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type); #define SLJIT_ENTER_REG_ARG 0x00000004 /* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */ -#define SLJIT_MAX_LOCAL_SIZE 65536 +#define SLJIT_MAX_LOCAL_SIZE 1048576 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, @@ -735,9 +800,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi by sljit_emit_enter. Several functions (such as sljit_emit_return) requires this context to be able to generate the appropriate code. However, some code fragments (compiled separately) may have no - normal entry point so their context is unknown for the compiler. + normal entry point so their context is unknown to the compiler. - The sljit_set_context and sljit_emit_enter have the same arguments, + sljit_set_context and sljit_emit_enter have the same arguments, but sljit_set_context does not generate any machine code. Note: every call of sljit_emit_enter and sljit_set_context overwrites @@ -797,7 +862,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *c Note: Different architectures have different addressing limitations. A single instruction is enough for the following addressing - modes. Other adrressing modes are emulated by instruction + modes. Other addressing modes are emulated by instruction sequences. This information could help to improve those code generators which focuses only a few architectures. @@ -828,6 +893,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *c s390x: [reg+imm], -2^19 <= imm < 2^19 [reg+reg] is supported Write-back is not supported + loongarch: [reg+imm], -2048 <= imm <= 2047 + [reg+reg] is supported + Write-back is not supported */ /* Macros for specifying operand types. */ @@ -835,9 +903,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *c #define SLJIT_MEM0() (SLJIT_MEM) #define SLJIT_MEM1(r1) (SLJIT_MEM | (r1)) #define SLJIT_MEM2(r1, r2) (SLJIT_MEM | (r1) | ((r2) << 8)) -#define SLJIT_IMM 0x40 +#define SLJIT_IMM 0x7f #define SLJIT_REG_PAIR(r1, r2) ((r1) | ((r2) << 8)) +/* Macros for checking operand types (only for valid arguments). */ +#define SLJIT_IS_REG(arg) ((arg) > 0 && (arg) < SLJIT_IMM) +#define SLJIT_IS_MEM(arg) ((arg) & SLJIT_MEM) +#define SLJIT_IS_MEM0(arg) ((arg) == SLJIT_MEM) +#define SLJIT_IS_MEM1(arg) ((arg) > SLJIT_MEM && (arg) < (SLJIT_MEM << 1)) +#define SLJIT_IS_MEM2(arg) (((arg) & SLJIT_MEM) && (arg) >= (SLJIT_MEM << 1)) +#define SLJIT_IS_IMM(arg) ((arg) == SLJIT_IMM) +#define SLJIT_IS_REG_PAIR(arg) (!((arg) & SLJIT_MEM) && (arg) >= (SLJIT_MEM << 1)) + +/* Macros for extracting registers from operands. */ +/* Support operands which contains a single register or + constructed using SLJIT_MEM1, SLJIT_MEM2, or SLJIT_REG_PAIR. */ +#define SLJIT_EXTRACT_REG(arg) ((arg) & 0x7f) +/* Support operands which constructed using SLJIT_MEM2, or SLJIT_REG_PAIR. */ +#define SLJIT_EXTRACT_SECOND_REG(arg) ((arg) >> 8) + /* Sets 32 bit operation mode on 64 bit CPUs. This option is ignored on 32 bit CPUs. When this option is set for an arithmetic operation, only the lower 32 bits of the input registers are used, and the CPU status @@ -1054,6 +1138,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile Note: immediate source argument is not supported */ #define SLJIT_REV (SLJIT_OP1_BASE + 11) #define SLJIT_REV32 (SLJIT_REV | SLJIT_32) +/* Reverse the order of bytes in the lower 16 bit and extend as unsigned + Flags: - (may destroy flags) + Note: converts between little and big endian formats + Note: immediate source argument is not supported */ +#define SLJIT_REV_U16 (SLJIT_OP1_BASE + 12) +#define SLJIT_REV32_U16 (SLJIT_REV_U16 | SLJIT_32) +/* Reverse the order of bytes in the lower 16 bit and extend as signed + Flags: - (may destroy flags) + Note: converts between little and big endian formats + Note: immediate source argument is not supported */ +#define SLJIT_REV_S16 (SLJIT_OP1_BASE + 13) +#define SLJIT_REV32_S16 (SLJIT_REV_S16 | SLJIT_32) +/* Reverse the order of bytes in the lower 32 bit and extend as unsigned + Flags: - (may destroy flags) + Note: converts between little and big endian formats + Note: immediate source argument is not supported */ +#define SLJIT_REV_U32 (SLJIT_OP1_BASE + 14) +/* Reverse the order of bytes in the lower 32 bit and extend as signed + Flags: - (may destroy flags) + Note: converts between little and big endian formats + Note: immediate source argument is not supported */ +#define SLJIT_REV_S32 (SLJIT_OP1_BASE + 15) /* The following unary operations are supported by using sljit_emit_op2: - binary not: SLJIT_XOR with immedate -1 as src1 or src2 @@ -1276,15 +1382,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp /* Flags: - (may destroy flags) */ #define SLJIT_CONV_F64_FROM_S32 (SLJIT_FOP1_BASE + 5) #define SLJIT_CONV_F32_FROM_S32 (SLJIT_CONV_F64_FROM_S32 | SLJIT_32) +/* Flags: - (may destroy flags) */ +#define SLJIT_CONV_F64_FROM_UW (SLJIT_FOP1_BASE + 6) +#define SLJIT_CONV_F32_FROM_UW (SLJIT_CONV_F64_FROM_UW | SLJIT_32) +/* Flags: - (may destroy flags) */ +#define SLJIT_CONV_F64_FROM_U32 (SLJIT_FOP1_BASE + 7) +#define SLJIT_CONV_F32_FROM_U32 (SLJIT_CONV_F64_FROM_U32 | SLJIT_32) /* Note: dst is the left and src is the right operand for SLJIT_CMP_F32/64. Flags: EQUAL_F | LESS_F | GREATER_EQUAL_F | GREATER_F | LESS_EQUAL_F */ -#define SLJIT_CMP_F64 (SLJIT_FOP1_BASE + 6) +#define SLJIT_CMP_F64 (SLJIT_FOP1_BASE + 8) #define SLJIT_CMP_F32 (SLJIT_CMP_F64 | SLJIT_32) /* Flags: - (may destroy flags) */ -#define SLJIT_NEG_F64 (SLJIT_FOP1_BASE + 7) +#define SLJIT_NEG_F64 (SLJIT_FOP1_BASE + 9) #define SLJIT_NEG_F32 (SLJIT_NEG_F64 | SLJIT_32) /* Flags: - (may destroy flags) */ -#define SLJIT_ABS_F64 (SLJIT_FOP1_BASE + 8) +#define SLJIT_ABS_F64 (SLJIT_FOP1_BASE + 10) #define SLJIT_ABS_F32 (SLJIT_ABS_F64 | SLJIT_32) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, @@ -1312,6 +1424,26 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w); +/* Starting index of opcodes for sljit_emit_fop2r. */ +#define SLJIT_FOP2R_BASE 168 + +/* Flags: - (may destroy flags) */ +#define SLJIT_COPYSIGN_F64 (SLJIT_FOP2R_BASE + 0) +#define SLJIT_COPYSIGN_F32 (SLJIT_COPYSIGN_F64 | SLJIT_32) + +/* Similar to sljit_emit_fop2, except the destination is always a register. */ +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w); + +/* Sets a floating point register to an immediate value. */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f32 value); +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f64 value); + /* The following opcodes are used by sljit_emit_fcopy(). */ /* 64 bit: copy a 64 bit value from an integer register into a @@ -1410,28 +1542,32 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi #define SLJIT_SET_CARRY SLJIT_SET(SLJIT_CARRY) #define SLJIT_NOT_CARRY 13 +#define SLJIT_ATOMIC_STORED 14 +#define SLJIT_SET_ATOMIC_STORED SLJIT_SET(SLJIT_ATOMIC_STORED) +#define SLJIT_ATOMIC_NOT_STORED 15 + /* Basic floating point comparison types. Note: when the comparison result is unordered, their behaviour is unspecified. */ -#define SLJIT_F_EQUAL 14 +#define SLJIT_F_EQUAL 16 #define SLJIT_SET_F_EQUAL SLJIT_SET(SLJIT_F_EQUAL) -#define SLJIT_F_NOT_EQUAL 15 +#define SLJIT_F_NOT_EQUAL 17 #define SLJIT_SET_F_NOT_EQUAL SLJIT_SET(SLJIT_F_EQUAL) -#define SLJIT_F_LESS 16 +#define SLJIT_F_LESS 18 #define SLJIT_SET_F_LESS SLJIT_SET(SLJIT_F_LESS) -#define SLJIT_F_GREATER_EQUAL 17 +#define SLJIT_F_GREATER_EQUAL 19 #define SLJIT_SET_F_GREATER_EQUAL SLJIT_SET(SLJIT_F_LESS) -#define SLJIT_F_GREATER 18 +#define SLJIT_F_GREATER 20 #define SLJIT_SET_F_GREATER SLJIT_SET(SLJIT_F_GREATER) -#define SLJIT_F_LESS_EQUAL 19 +#define SLJIT_F_LESS_EQUAL 21 #define SLJIT_SET_F_LESS_EQUAL SLJIT_SET(SLJIT_F_GREATER) /* Jumps when either argument contains a NaN value. */ -#define SLJIT_UNORDERED 20 +#define SLJIT_UNORDERED 22 #define SLJIT_SET_UNORDERED SLJIT_SET(SLJIT_UNORDERED) /* Jumps when neither argument contains a NaN value. */ -#define SLJIT_ORDERED 21 +#define SLJIT_ORDERED 23 #define SLJIT_SET_ORDERED SLJIT_SET(SLJIT_UNORDERED) /* Ordered / unordered floating point comparison types. @@ -1439,41 +1575,41 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi Note: each comparison type has an ordered and unordered form. Some architectures supports only either of them (see: sljit_cmp_info). */ -#define SLJIT_ORDERED_EQUAL 22 +#define SLJIT_ORDERED_EQUAL 24 #define SLJIT_SET_ORDERED_EQUAL SLJIT_SET(SLJIT_ORDERED_EQUAL) -#define SLJIT_UNORDERED_OR_NOT_EQUAL 23 +#define SLJIT_UNORDERED_OR_NOT_EQUAL 25 #define SLJIT_SET_UNORDERED_OR_NOT_EQUAL SLJIT_SET(SLJIT_ORDERED_EQUAL) -#define SLJIT_ORDERED_LESS 24 +#define SLJIT_ORDERED_LESS 26 #define SLJIT_SET_ORDERED_LESS SLJIT_SET(SLJIT_ORDERED_LESS) -#define SLJIT_UNORDERED_OR_GREATER_EQUAL 25 +#define SLJIT_UNORDERED_OR_GREATER_EQUAL 27 #define SLJIT_SET_UNORDERED_OR_GREATER_EQUAL SLJIT_SET(SLJIT_ORDERED_LESS) -#define SLJIT_ORDERED_GREATER 26 +#define SLJIT_ORDERED_GREATER 28 #define SLJIT_SET_ORDERED_GREATER SLJIT_SET(SLJIT_ORDERED_GREATER) -#define SLJIT_UNORDERED_OR_LESS_EQUAL 27 +#define SLJIT_UNORDERED_OR_LESS_EQUAL 29 #define SLJIT_SET_UNORDERED_OR_LESS_EQUAL SLJIT_SET(SLJIT_ORDERED_GREATER) -#define SLJIT_UNORDERED_OR_EQUAL 28 +#define SLJIT_UNORDERED_OR_EQUAL 30 #define SLJIT_SET_UNORDERED_OR_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_EQUAL) -#define SLJIT_ORDERED_NOT_EQUAL 29 +#define SLJIT_ORDERED_NOT_EQUAL 31 #define SLJIT_SET_ORDERED_NOT_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_EQUAL) -#define SLJIT_UNORDERED_OR_LESS 30 +#define SLJIT_UNORDERED_OR_LESS 32 #define SLJIT_SET_UNORDERED_OR_LESS SLJIT_SET(SLJIT_UNORDERED_OR_LESS) -#define SLJIT_ORDERED_GREATER_EQUAL 31 +#define SLJIT_ORDERED_GREATER_EQUAL 33 #define SLJIT_SET_ORDERED_GREATER_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_LESS) -#define SLJIT_UNORDERED_OR_GREATER 32 +#define SLJIT_UNORDERED_OR_GREATER 34 #define SLJIT_SET_UNORDERED_OR_GREATER SLJIT_SET(SLJIT_UNORDERED_OR_GREATER) -#define SLJIT_ORDERED_LESS_EQUAL 33 +#define SLJIT_ORDERED_LESS_EQUAL 35 #define SLJIT_SET_ORDERED_LESS_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_GREATER) /* Unconditional jump types. */ -#define SLJIT_JUMP 34 +#define SLJIT_JUMP 36 /* Fast calling method. See the description above. */ -#define SLJIT_FAST_CALL 35 +#define SLJIT_FAST_CALL 37 /* Default C calling convention. */ -#define SLJIT_CALL 36 +#define SLJIT_CALL 38 /* Called function must be compiled by SLJIT. See SLJIT_ENTER_REG_ARG option. */ -#define SLJIT_CALL_REG_ARG 37 +#define SLJIT_CALL_REG_ARG 39 /* The target can be changed during runtime (see: sljit_set_jump_addr). */ #define SLJIT_REWRITABLE_JUMP 0x1000 @@ -1563,19 +1699,42 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co sljit_s32 dst, sljit_sw dstw, sljit_s32 type); -/* Emit a conditional mov instruction which moves source to destination, - if the condition is satisfied. Unlike other arithmetic operations this - instruction does not support memory access. +/* Emit a conditional select instruction which moves src1 to dst_reg, + if the condition is satisfied, or src2_reg to dst_reg otherwise. type must be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL - type can be combined (or'ed) with SLJIT_32 - dst_reg must be a valid register - src must be a valid register or immediate (SLJIT_IMM) + type can be combined (or'ed) with SLJIT_32 to move 32 bit + register values instead of word sized ones + dst_reg and src2_reg must be valid registers + src1 must be valid operand + + Note: if src1 is a memory operand, its value + might be loaded even if the condition is false. Flags: - (does not modify flags) */ -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, - sljit_s32 src, sljit_sw srcw); + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_reg); + +/* Emit a conditional floating point select instruction which moves + src1 to dst_reg, if the condition is satisfied, or src2_reg to + dst_reg otherwise. + + type must be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL + type can be combined (or'ed) with SLJIT_32 to move 32 bit + floating point values instead of 64 bit ones + dst_freg and src2_freg must be valid floating point registers + src1 must be valid operand + + Note: if src1 is a memory operand, its value + might be loaded even if the condition is false. + + Flags: - (does not modify flags) */ +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_freg); /* The following flags are used by sljit_emit_mem(), sljit_emit_mem_update(), sljit_emit_fmem(), and sljit_emit_fmem_update(). */ @@ -1590,9 +1749,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil /* Load or stora data from an unaligned (byte aligned) address. */ #define SLJIT_MEM_UNALIGNED 0x000400 /* Load or stora data from a 16 bit aligned address. */ -#define SLJIT_MEM_UNALIGNED_16 0x000800 +#define SLJIT_MEM_ALIGNED_16 0x000800 /* Load or stora data from a 32 bit aligned address. */ -#define SLJIT_MEM_UNALIGNED_32 0x001000 +#define SLJIT_MEM_ALIGNED_32 0x001000 /* The following flags are used by sljit_emit_mem_update(), and sljit_emit_fmem_update(). */ @@ -1610,8 +1769,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil /* The sljit_emit_mem emits instructions for various memory operations: - When SLJIT_MEM_UNALIGNED / SLJIT_MEM_UNALIGNED_16 / - SLJIT_MEM_UNALIGNED_32 is set in type argument: + When SLJIT_MEM_UNALIGNED / SLJIT_MEM_ALIGNED_16 / + SLJIT_MEM_ALIGNED_32 is set in type argument: Emit instructions for unaligned memory loads or stores. When SLJIT_UNALIGNED is not defined, the only way to access unaligned memory data is using sljit_emit_mem. Otherwise all operations (e.g. @@ -1626,8 +1785,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil location specified by the mem/memw arguments, and the end address of this operation is the starting address of the data transfer between the second register and memory. The type argument must - be SLJIT_MOV. The SLJIT_MEM_UNALIGNED* options are allowed for - this operation. + be SLJIT_MOV. The SLJIT_MEM_UNALIGNED / SLJIT_MEM_ALIGNED_* + options are allowed for this operation. type must be between SLJIT_MOV and SLJIT_MOV_P and can be combined (or'ed) with SLJIT_MEM_* flags @@ -1691,6 +1850,286 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler sljit_s32 freg, sljit_s32 mem, sljit_sw memw); +/* The following options are used by several simd operations. */ + +/* Load data into a simd register, this is the default */ +#define SLJIT_SIMD_LOAD 0x000000 +/* Store data from a simd register */ +#define SLJIT_SIMD_STORE 0x000001 +/* The simd register contains floating point values */ +#define SLJIT_SIMD_FLOAT 0x000400 +/* Tests whether the operation is available */ +#define SLJIT_SIMD_TEST 0x000800 +/* Move data to/from a 64 bit (8 byte) long SIMD register */ +#define SLJIT_SIMD_REG_64 (3 << 12) +/* Move data to/from a 128 bit (16 byte) long SIMD register */ +#define SLJIT_SIMD_REG_128 (4 << 12) +/* Move data to/from a 256 bit (32 byte) long SIMD register */ +#define SLJIT_SIMD_REG_256 (5 << 12) +/* Move data to/from a 512 bit (64 byte) long SIMD register */ +#define SLJIT_SIMD_REG_512 (6 << 12) +/* Element size is 8 bit long (this is the default), usually cannot be combined with SLJIT_SIMD_FLOAT */ +#define SLJIT_SIMD_ELEM_8 (0 << 18) +/* Element size is 16 bit long, usually cannot be combined with SLJIT_SIMD_FLOAT */ +#define SLJIT_SIMD_ELEM_16 (1 << 18) +/* Element size is 32 bit long */ +#define SLJIT_SIMD_ELEM_32 (2 << 18) +/* Element size is 64 bit long */ +#define SLJIT_SIMD_ELEM_64 (3 << 18) +/* Element size is 128 bit long */ +#define SLJIT_SIMD_ELEM_128 (4 << 18) +/* Element size is 256 bit long */ +#define SLJIT_SIMD_ELEM_256 (5 << 18) + +/* The following options are used by sljit_emit_simd_mov(). */ + +/* Memory address is unaligned (this is the default) */ +#define SLJIT_SIMD_MEM_UNALIGNED (0 << 24) +/* Memory address is 16 bit aligned */ +#define SLJIT_SIMD_MEM_ALIGNED_16 (1 << 24) +/* Memory address is 32 bit aligned */ +#define SLJIT_SIMD_MEM_ALIGNED_32 (2 << 24) +/* Memory address is 64 bit aligned */ +#define SLJIT_SIMD_MEM_ALIGNED_64 (3 << 24) +/* Memory address is 128 bit aligned */ +#define SLJIT_SIMD_MEM_ALIGNED_128 (4 << 24) +/* Memory address is 256 bit aligned */ +#define SLJIT_SIMD_MEM_ALIGNED_256 (5 << 24) +/* Memory address is 512 bit aligned */ +#define SLJIT_SIMD_MEM_ALIGNED_512 (6 << 24) + +/* Moves data between a simd register and memory. + + If the operation is not supported, it returns with + SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed, + it does not emit any instructions. + + type must be a combination of SLJIT_SIMD_* and + SLJIT_SIMD_MEM_* options + freg is the source or destination simd register + of the operation + srcdst must be a memory operand or a simd register + + Note: + The alignment and element size must be + less or equal than simd register size. + + Flags: - (does not modify flags) */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 srcdst, sljit_sw srcdstw); + +/* Replicates a scalar value to all lanes of a simd + register. + + If the operation is not supported, it returns with + SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed, + it does not emit any instructions. + + type must be a combination of SLJIT_SIMD_* options + except SLJIT_SIMD_STORE. + freg is the destination simd register of the operation + src is the value which is replicated + + Note: + The src == SLJIT_IMM and srcw == 0 can be used to + clear a register even when SLJIT_SIMD_FLOAT is set. + + Flags: - (does not modify flags) */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_sw srcw); + +/* The following options are used by sljit_emit_simd_lane_mov(). */ + +/* Clear all bits of the simd register before loading the lane. */ +#define SLJIT_SIMD_LANE_ZERO 0x000002 +/* Sign extend the integer value stored from the lane. */ +#define SLJIT_SIMD_LANE_SIGNED 0x000004 + +/* Moves data between a simd register lane and a register or + memory. If the srcdst argument is a register, it must be + a floating point register when SLJIT_SIMD_FLOAT is specified, + or a general purpose register otherwise. + + If the operation is not supported, it returns with + SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed, + it does not emit any instructions. + + type must be a combination of SLJIT_SIMD_* options + Further options: + SLJIT_32 - when SLJIT_SIMD_FLOAT is not set + SLJIT_SIMD_LANE_SIGNED - when SLJIT_SIMD_STORE + is set and SLJIT_SIMD_FLOAT is not set + SLJIT_SIMD_LANE_ZERO - when SLJIT_SIMD_LOAD + is specified + freg is the source or destination simd register + of the operation + lane_index is the index of the lane + srcdst is the destination operand for loads, and + source operand for stores + + Note: + The elem size must be lower than register size. + + Flags: - (does not modify flags) */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, sljit_s32 lane_index, + sljit_s32 srcdst, sljit_sw srcdstw); + +/* Replicates a scalar value from a lane to all lanes + of a simd register. + + If the operation is not supported, it returns with + SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed, + it does not emit any instructions. + + type must be a combination of SLJIT_SIMD_* options + except SLJIT_SIMD_STORE. + freg is the destination simd register of the operation + src is the simd register which lane is replicated + src_lane_index is the lane index of the src register + + Flags: - (does not modify flags) */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_s32 src_lane_index); + +/* The following options are used by sljit_emit_simd_load_extend(). */ + +/* Sign extend the integer elements */ +#define SLJIT_SIMD_EXTEND_SIGNED 0x000002 +/* Extend data to 16 bit */ +#define SLJIT_SIMD_EXTEND_16 (1 << 24) +/* Extend data to 32 bit */ +#define SLJIT_SIMD_EXTEND_32 (2 << 24) +/* Extend data to 64 bit */ +#define SLJIT_SIMD_EXTEND_64 (3 << 24) + +/* Extend elements and stores them in a simd register. + The extension operation increases the size of the + elements (e.g. from 16 bit to 64 bit). For integer + values, the extension can be signed or unsigned. + + If the operation is not supported, it returns with + SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed, + it does not emit any instructions. + + type must be a combination of SLJIT_SIMD_*, and + SLJIT_SIMD_EXTEND_* options except SLJIT_SIMD_STORE + freg is the destination simd register of the operation + src must be a memory operand or a simd register. + In the latter case, the source elements are stored + in the lower half of the register. + + Flags: - (does not modify flags) */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_sw srcw); + +/* Extract the highest bit (usually the sign bit) from + each elements of a vector. + + If the operation is not supported, it returns with + SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed, + it does not emit any instructions. + + type must be a combination of SLJIT_SIMD_* and SLJIT_32 + options except SLJIT_SIMD_LOAD + freg is the source simd register of the operation + dst is the destination operand + + Flags: - (does not modify flags) */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 dst, sljit_sw dstw); + +/* The following options are used by sljit_emit_simd_op2(). */ + +/* Binary 'and' operation */ +#define SLJIT_SIMD_OP2_AND 0x000001 +/* Binary 'or' operation */ +#define SLJIT_SIMD_OP2_OR 0x000002 +/* Binary 'xor' operation */ +#define SLJIT_SIMD_OP2_XOR 0x000003 + +/* Perform simd operations using simd registers. + + If the operation is not supported, it returns with + SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed, + it does not emit any instructions. + + type must be a combination of SLJIT_SIMD_* and SLJIT_SIMD_OP2_ + options except SLJIT_SIMD_LOAD and SLJIT_SIMD_STORE + dst_freg is the destination register of the operation + src1_freg is the first source register of the operation + src1_freg is the second source register of the operation + + Flags: - (does not modify flags) */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg); + +/* The sljit_emit_atomic_load and sljit_emit_atomic_store operation pair + can perform an atomic read-modify-write operation. First, an unsigned + value must be loaded from memory using sljit_emit_atomic_load. Then, + the updated value must be written back to the same memory location by + sljit_emit_atomic_store. A thread can only perform a single atomic + operation at a time. + + Note: atomic operations are experimental, and not implemented + for all cpus. + + The following conditions must be satisfied, or the operation + is undefined: + - the address provided in mem_reg must be divisible by the size of + the value (only naturally aligned updates are supported) + - no memory writes are allowed between the load and store operations + regardless of its target address (currently read operations are + allowed, but this might change in the future) + - the memory operation (op) and the base address (stored in mem_reg) + passed to the load/store operations must be the same (the mem_reg + can be a different register, only its value must be the same) + - an store must always follow a load for the same transaction. + + op must be between SLJIT_MOV and SLJIT_MOV_P, excluding all + signed loads such as SLJIT_MOV32_S16 + dst_reg is the register where the data will be loaded into + mem_reg is the base address of the memory load (it cannot be + SLJIT_SP or a virtual register on x86-32) + + Flags: - (does not modify flags) */ +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 mem_reg); + +/* The sljit_emit_atomic_load and sljit_emit_atomic_store operations + allows performing an atomic read-modify-write operation. See the + description of sljit_emit_atomic_load. + + op must be between SLJIT_MOV and SLJIT_MOV_P, excluding all signed + loads such as SLJIT_MOV32_S16 + src_reg is the register which value is stored into the memory + mem_reg is the base address of the memory store (it cannot be + SLJIT_SP or a virtual register on x86-32) + temp_reg is a not preserved scratch register, which must be + initialized with the value loaded into the dst_reg during the + corresponding sljit_emit_atomic_load operation, or the operation + is undefined + + Flags: ATOMIC_STORED is set if the operation is successful, + otherwise the memory remains unchanged. */ +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_reg, + sljit_s32 mem_reg, + sljit_s32 temp_reg); + /* Copies the base address of SLJIT_SP + offset to dst. The offset can represent the starting address of a value in the local data (stack). The offset is not limited by the local data limits, it can be any value. @@ -1708,17 +2147,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c Flags: - (does not modify flags) */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value); -/* Store the value of a label (see: sljit_set_put_label) +/* Store the value of a label (see: sljit_set_label / sljit_set_target) Flags: - (does not modify flags) */ -SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw); +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw); -/* Set the value stored by put_label to this label. */ -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label); - -/* After the code generation the address for label, jump and const instructions - are computed. Since these structures are freed by sljit_free_compiler, the - addresses must be preserved by the user program elsewere. */ -static SLJIT_INLINE sljit_uw sljit_get_label_addr(struct sljit_label *label) { return label->addr; } +/* Provides the address of label, jump and const instructions after sljit_generate_code + is called. The returned value is unspecified before the sljit_generate_code call. + Since these structures are freed by sljit_free_compiler, the addresses must be + preserved by the user program elsewere. */ +static SLJIT_INLINE sljit_uw sljit_get_label_addr(struct sljit_label *label) { return label->u.addr; } static SLJIT_INLINE sljit_uw sljit_get_jump_addr(struct sljit_jump *jump) { return jump->addr; } static SLJIT_INLINE sljit_uw sljit_get_const_addr(struct sljit_const *const_) { return const_->addr; } @@ -1731,30 +2168,39 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta /* CPU specific functions */ /* --------------------------------------------------------------------- */ +/* Types for sljit_get_register_index */ + +/* General purpose (integer) registers. */ +#define SLJIT_GP_REGISTER 0 +/* Floating point registers. */ +#define SLJIT_FLOAT_REGISTER 1 + /* The following function is a helper function for sljit_emit_op_custom. - It returns with the real machine register index ( >=0 ) of any SLJIT_R, - SLJIT_S and SLJIT_SP registers. + It returns with the real machine register index ( >=0 ) of any registers. - Note: it returns with -1 for virtual registers (only on x86-32). */ + When type is SLJIT_GP_REGISTER: + reg must be an SLJIT_R(i), SLJIT_S(i), or SLJIT_SP register -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg); + When type is SLJIT_FLOAT_REGISTER: + reg must be an SLJIT_FR(i) or SLJIT_FS(i) register -/* The following function is a helper function for sljit_emit_op_custom. - It returns with the real machine register ( >= 0 ) index of any SLJIT_FR, - and SLJIT_FS register. + When type is SLJIT_SIMD_REG_64 / 128 / 256 / 512 : + reg must be an SLJIT_FR(i) or SLJIT_FS(i) register - Note: the index is always an even number on ARM-32, MIPS. */ + Note: it returns with -1 for unknown registers, such as virtual + registers on x86-32 or unsupported simd registers. */ -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg); +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg); /* Any instruction can be inserted into the instruction stream by sljit_emit_op_custom. It has a similar purpose as inline assembly. The size parameter must match to the instruction size of the target architecture: - x86: 0 < size <= 15. The instruction argument can be byte aligned. + x86: 0 < size <= 15, the instruction argument can be byte aligned. Thumb2: if size == 2, the instruction argument must be 2 byte aligned. if size == 4, the instruction argument must be 4 byte aligned. + s390x: size can be 2, 4, or 6, the instruction argument can be byte aligned. Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, @@ -1782,6 +2228,98 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags); +/* --------------------------------------------------------------------- */ +/* Serialization functions */ +/* --------------------------------------------------------------------- */ + +/* Label/jump/const enumeration functions. The items in each group + are enumerated in creation order. Serialization / deserialization + preserves this order for each group. For example the fifth label + after deserialization refers to the same machine code location as + the fifth label before the serialization. */ +static SLJIT_INLINE struct sljit_label *sljit_get_first_label(struct sljit_compiler *compiler) { return compiler->labels; } +static SLJIT_INLINE struct sljit_jump *sljit_get_first_jump(struct sljit_compiler *compiler) { return compiler->jumps; } +static SLJIT_INLINE struct sljit_const *sljit_get_first_const(struct sljit_compiler *compiler) { return compiler->consts; } + +static SLJIT_INLINE struct sljit_label *sljit_get_next_label(struct sljit_label *label) { return label->next; } +static SLJIT_INLINE struct sljit_jump *sljit_get_next_jump(struct sljit_jump *jump) { return jump->next; } +static SLJIT_INLINE struct sljit_const *sljit_get_next_const(struct sljit_const *const_) { return const_->next; } + +/* A number starting from 0 is assigned to each label, which +represents its creation index. The first label created by the +compiler has index 0, the second has index 1, the third has +index 2, and so on. The returned value is unspecified after +sljit_generate_code() is called. */ +static SLJIT_INLINE sljit_uw sljit_get_label_index(struct sljit_label *label) { return label->u.index; } + +/* The sljit_jump_has_label() and sljit_jump_has_target() functions +returns non-zero value if a label or target is set for the jump +respectively. Both may return with a zero value. The other two +functions return the value assigned to the jump. */ +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_label(struct sljit_jump *jump); +static SLJIT_INLINE struct sljit_label *sljit_jump_get_label(struct sljit_jump *jump) { return jump->u.label; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_target(struct sljit_jump *jump); +static SLJIT_INLINE sljit_uw sljit_jump_get_target(struct sljit_jump *jump) { return jump->u.target; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_is_mov_addr(struct sljit_jump *jump); + +/* Option bits for sljit_serialize_compiler. */ + +/* When debugging is enabled, the serialized buffer contains +debugging information unless this option is specified. */ +#define SLJIT_SERIALIZE_IGNORE_DEBUG 0x1 + +/* Serialize the internal structure of the compiler into a buffer. +If the serialization is successful, the returned value is a newly +allocated buffer which is allocated by the memory allocator assigned +to the compiler. Otherwise the returned value is NULL. Unlike +sljit_generate_code(), serialization does not modify the internal +state of the compiler, so the code generation can be continued. + + options must be the combination of SLJIT_SERIALIZE_* option bits + size is an output argument, which is set to the byte size of + the result buffer if the operation is successful + +Notes: + - This function is useful for ahead-of-time compilation (AOT). + - The returned buffer must be freed later by the caller. + The SLJIT_FREE() macro is suitable for this purpose: + SLJIT_FREE(returned_buffer, sljit_get_allocator_data(compiler)) + - Memory allocated by sljit_alloc_memory() is not serialized. + - The type of the returned buffer is sljit_uw* to emphasize that + the buffer is word aligned. However, the 'size' output argument + contains the byte size, so this value is always divisible by + sizeof(sljit_uw). +*/ +SLJIT_API_FUNC_ATTRIBUTE sljit_uw* sljit_serialize_compiler(struct sljit_compiler *compiler, + sljit_s32 options, sljit_uw *size); + +/* Construct a new compiler instance from a buffer produced by +sljit_serialize_compiler(). If the operation is successful, the new +compiler instance is returned. Otherwise the returned value is NULL. + + buffer points to a word aligned memory data which was + created by sljit_serialize_compiler() + size is the byte size of the buffer + options must be 0 + allocator_data and exec_allocator_data specify an allocator + specific data similar to sljit_create_compiler() + +Notes: + - Labels assigned to jumps are restored with their + corresponding label in the label set created by + the deserializer. Target addresses assigned to + jumps are also restored. Uninitialized jumps + remain uninitialized. + - After the deserialization, sljit_generate_code() does + not need to be the next operation on the returned + compiler, the code generation can be continued. + Even sljit_serialize_compiler() can be called again. + - When debugging is enabled, a buffers without debug + information cannot be deserialized. +*/ +SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler *sljit_deserialize_compiler(sljit_uw* buffer, sljit_uw size, + sljit_s32 options, void *allocator_data, void *exec_allocator_data); + /* --------------------------------------------------------------------- */ /* Miscellaneous utility functions */ /* --------------------------------------------------------------------- */ diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_32.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_32.c index 8175293d2b3..0d2fa559688 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_32.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_32.c @@ -34,13 +34,16 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) { #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) return "ARMv7" SLJIT_CPUINFO ARM_ABI_INFO; -#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - return "ARMv5" SLJIT_CPUINFO ARM_ABI_INFO; +#elif (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + return "ARMv6" SLJIT_CPUINFO ARM_ABI_INFO; #else #error "Internal error: Unknown ARM architecture" #endif } +/* Length of an instruction word. */ +typedef sljit_u32 sljit_ins; + /* Last register + 1. */ #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) @@ -55,27 +58,39 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) #define CONST_POOL_EMPTY 0xffffffff #define ALIGN_INSTRUCTION(ptr) \ - (sljit_uw*)(((sljit_uw)(ptr) + (CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1) & ~((CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1)) + (sljit_ins*)(((sljit_ins)(ptr) + (CONST_POOL_ALIGNMENT * sizeof(sljit_ins)) - 1) & ~((CONST_POOL_ALIGNMENT * sizeof(sljit_ins)) - 1)) #define MAX_DIFFERENCE(max_diff) \ - (((max_diff) / (sljit_s32)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1)) + (((max_diff) / (sljit_s32)sizeof(sljit_ins)) - (CONST_POOL_ALIGNMENT - 1)) /* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = { 0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 12, 14, 15 }; -static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { - 0, 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8, 6, 7 +static const sljit_u8 freg_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) + 1] = { + 0, + 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8, + 7, 6, + 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8, + 7, 6 +}; + +static const sljit_u8 freg_ebit_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) + 1] = { + 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1 }; -#define RM(rm) ((sljit_uw)reg_map[rm]) -#define RM8(rm) ((sljit_uw)reg_map[rm] << 8) -#define RD(rd) ((sljit_uw)reg_map[rd] << 12) -#define RN(rn) ((sljit_uw)reg_map[rn] << 16) +#define RM(rm) ((sljit_ins)reg_map[rm]) +#define RM8(rm) ((sljit_ins)reg_map[rm] << 8) +#define RD(rd) ((sljit_ins)reg_map[rd] << 12) +#define RN(rn) ((sljit_ins)reg_map[rn] << 16) -#define VM(rm) ((sljit_uw)freg_map[rm]) -#define VD(rd) ((sljit_uw)freg_map[rd] << 12) -#define VN(rn) ((sljit_uw)freg_map[rn] << 16) +#define VM(vm) (((sljit_ins)freg_map[vm]) | ((sljit_ins)freg_ebit_map[vm] << 5)) +#define VD(vd) (((sljit_ins)freg_map[vd] << 12) | ((sljit_ins)freg_ebit_map[vd] << 22)) +#define VN(vn) (((sljit_ins)freg_map[vn] << 16) | ((sljit_ins)freg_ebit_map[vn] << 7)) /* --------------------------------------------------------------------- */ /* Instrucion forms */ @@ -92,16 +107,19 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define AND 0xe0000000 #define B 0xea000000 #define BIC 0xe1c00000 +#define BKPT 0xe1200070 #define BL 0xeb000000 #define BLX 0xe12fff30 #define BX 0xe12fff10 #define CLZ 0xe16f0f10 #define CMN 0xe1600000 #define CMP 0xe1400000 -#define BKPT 0xe1200070 #define EOR 0xe0200000 #define LDR 0xe5100000 #define LDR_POST 0xe4100000 +#define LDREX 0xe1900f9f +#define LDREXB 0xe1d00f9f +#define LDREXH 0xe1f00f9f #define MOV 0xe1a00000 #define MUL 0xe0000090 #define MVN 0xe1e00000 @@ -109,51 +127,89 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define ORR 0xe1800000 #define PUSH 0xe92d0000 #define POP 0xe8bd0000 -#define RBIT 0xe6ff0f30 #define REV 0xe6bf0f30 +#define REV16 0xe6bf0fb0 #define RSB 0xe0600000 #define RSC 0xe0e00000 #define SBC 0xe0c00000 #define SMULL 0xe0c00090 #define STR 0xe5000000 +#define STREX 0xe1800f90 +#define STREXB 0xe1c00f90 +#define STREXH 0xe1e00f90 #define SUB 0xe0400000 +#define SXTB 0xe6af0070 +#define SXTH 0xe6bf0070 #define TST 0xe1000000 #define UMULL 0xe0800090 +#define UXTB 0xe6ef0070 +#define UXTH 0xe6ff0070 #define VABS_F32 0xeeb00ac0 #define VADD_F32 0xee300a00 +#define VAND 0xf2000110 #define VCMP_F32 0xeeb40a40 #define VCVT_F32_S32 0xeeb80ac0 +#define VCVT_F32_U32 0xeeb80a40 #define VCVT_F64_F32 0xeeb70ac0 #define VCVT_S32_F32 0xeebd0ac0 #define VDIV_F32 0xee800a00 +#define VDUP 0xee800b10 +#define VDUP_s 0xf3b00c00 +#define VEOR 0xf3000110 +#define VLD1 0xf4200000 +#define VLD1_r 0xf4a00c00 +#define VLD1_s 0xf4a00000 #define VLDR_F32 0xed100a00 #define VMOV_F32 0xeeb00a40 #define VMOV 0xee000a10 #define VMOV2 0xec400a10 +#define VMOV_i 0xf2800010 +#define VMOV_s 0xee000b10 +#define VMOVN 0xf3b20200 #define VMRS 0xeef1fa10 #define VMUL_F32 0xee200a00 #define VNEG_F32 0xeeb10a40 +#define VORR 0xf2200110 #define VPOP 0xecbd0b00 #define VPUSH 0xed2d0b00 +#define VSHLL 0xf2800a10 +#define VSHR 0xf2800010 +#define VSRA 0xf2800110 +#define VST1 0xf4000000 +#define VST1_s 0xf4800000 #define VSTR_F32 0xed000a00 #define VSUB_F32 0xee300a40 #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) /* Arm v7 specific instructions. */ -#define MOVW 0xe3000000 #define MOVT 0xe3400000 -#define SXTB 0xe6af0070 -#define SXTH 0xe6bf0070 -#define UXTB 0xe6ef0070 -#define UXTH 0xe6ff0070 +#define MOVW 0xe3000000 +#define RBIT 0xe6ff0f30 #endif -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + +static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32) +{ + if (compiler->scratches == -1) + return 0; + + if (is_32 && fr >= SLJIT_F64_SECOND(SLJIT_FR0)) + fr -= SLJIT_F64_SECOND(0); + + return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->fscratches)) + || (fr > (SLJIT_FS0 - compiler->fsaveds) && fr <= SLJIT_FS0) + || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)); +} + +#endif /* SLJIT_ARGUMENT_CHECKS */ + +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) static sljit_s32 push_cpool(struct sljit_compiler *compiler) { /* Pushing the constant pool into the instruction stream. */ - sljit_uw* inst; + sljit_ins* inst; sljit_uw* cpool_ptr; sljit_uw* cpool_end; sljit_s32 i; @@ -163,13 +219,13 @@ static sljit_s32 push_cpool(struct sljit_compiler *compiler) compiler->last_label->size += compiler->cpool_fill + (CONST_POOL_ALIGNMENT - 1) + 1; SLJIT_ASSERT(compiler->cpool_fill > 0 && compiler->cpool_fill <= CPOOL_SIZE); - inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); + inst = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!inst); compiler->size++; *inst = 0xff000000 | compiler->cpool_fill; for (i = 0; i < CONST_POOL_ALIGNMENT - 1; i++) { - inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); + inst = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!inst); compiler->size++; *inst = 0; @@ -178,7 +234,7 @@ static sljit_s32 push_cpool(struct sljit_compiler *compiler) cpool_ptr = compiler->cpool; cpool_end = cpool_ptr + compiler->cpool_fill; while (cpool_ptr < cpool_end) { - inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); + inst = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!inst); compiler->size++; *inst = *cpool_ptr++; @@ -188,23 +244,23 @@ static sljit_s32 push_cpool(struct sljit_compiler *compiler) return SLJIT_SUCCESS; } -static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_uw inst) +static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins inst) { - sljit_uw* ptr; + sljit_ins* ptr; if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092))) FAIL_IF(push_cpool(compiler)); - ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); + ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!ptr); compiler->size++; *ptr = inst; return SLJIT_SUCCESS; } -static sljit_s32 push_inst_with_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal) +static sljit_s32 push_inst_with_literal(struct sljit_compiler *compiler, sljit_ins inst, sljit_uw literal) { - sljit_uw* ptr; + sljit_ins* ptr; sljit_uw cpool_index = CPOOL_SIZE; sljit_uw* cpool_ptr; sljit_uw* cpool_end; @@ -240,7 +296,7 @@ static sljit_s32 push_inst_with_literal(struct sljit_compiler *compiler, sljit_u } SLJIT_ASSERT((inst & 0xfff) == 0); - ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); + ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!ptr); compiler->size++; *ptr = inst | cpool_index; @@ -252,14 +308,15 @@ static sljit_s32 push_inst_with_literal(struct sljit_compiler *compiler, sljit_u return SLJIT_SUCCESS; } -static sljit_s32 push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal) +static sljit_s32 push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_ins inst, sljit_uw literal) { - sljit_uw* ptr; + sljit_ins* ptr; + if (SLJIT_UNLIKELY((compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)) || compiler->cpool_fill >= CPOOL_SIZE)) FAIL_IF(push_cpool(compiler)); SLJIT_ASSERT(compiler->cpool_fill < CPOOL_SIZE && (inst & 0xfff) == 0); - ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); + ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!ptr); compiler->size++; *ptr = inst | compiler->cpool_fill; @@ -306,7 +363,7 @@ static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_ while (last_pc_patch < code_ptr) { /* Data transfer instruction with Rn == r15. */ - if ((*last_pc_patch & 0x0c0f0000) == 0x040f0000) { + if ((*last_pc_patch & 0x0e0f0000) == 0x040f0000) { diff = (sljit_uw)(const_pool - last_pc_patch); ind = (*last_pc_patch) & 0xfff; @@ -396,11 +453,11 @@ static sljit_s32 resolve_const_pool_index(struct sljit_compiler *compiler, struc #else -static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_uw inst) +static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins inst) { - sljit_uw* ptr; + sljit_ins* ptr; - ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); + ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!ptr); compiler->size++; *ptr = inst; @@ -422,14 +479,15 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw if (jump->flags & SLJIT_REWRITABLE_JUMP) return 0; -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) if (jump->flags & IS_BL) code_ptr--; +#endif /* SLJIT_CONFIG_ARM_V6 */ if (jump->flags & JUMP_ADDR) diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset); else { - SLJIT_ASSERT(jump->flags & JUMP_LABEL); + SLJIT_ASSERT(jump->u.label != NULL); diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2)); } @@ -437,6 +495,7 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw if (diff & 0x3) return 0; +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) if (jump->flags & IS_BL) { if (diff <= 0x01ffffff && diff >= -0x02000000) { *code_ptr = (BL - CONDITIONAL) | (*(code_ptr + 1) & COND_MASK); @@ -450,34 +509,22 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw jump->flags |= PATCH_B; } } -#else - if (jump->flags & JUMP_ADDR) - diff = ((sljit_sw)jump->u.target - (sljit_sw)code_ptr - executable_offset); - else { - SLJIT_ASSERT(jump->flags & JUMP_LABEL); - diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)code_ptr); - } - - /* Branch to Thumb code has not been optimized yet. */ - if (diff & 0x3) - return 0; - +#else /* !SLJIT_CONFIG_ARM_V6 */ if (diff <= 0x01ffffff && diff >= -0x02000000) { - code_ptr -= 2; - *code_ptr = ((jump->flags & IS_BL) ? (BL - CONDITIONAL) : (B - CONDITIONAL)) | (code_ptr[2] & COND_MASK); + *code_ptr = ((jump->flags & IS_BL) ? (BL - CONDITIONAL) : (B - CONDITIONAL)) | (*code_ptr & COND_MASK); jump->flags |= PATCH_B; return 1; } -#endif +#endif /* SLJIT_CONFIG_ARM_V6 */ return 0; } -static SLJIT_INLINE void inline_set_jump_addr(sljit_uw jump_ptr, sljit_sw executable_offset, sljit_uw new_addr, sljit_s32 flush_cache) +static void set_jump_addr(sljit_uw jump_ptr, sljit_sw executable_offset, sljit_uw new_addr, sljit_s32 flush_cache) { -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - sljit_uw *ptr = (sljit_uw *)jump_ptr; - sljit_uw *inst = (sljit_uw *)ptr[0]; - sljit_uw mov_pc = ptr[1]; +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + sljit_ins *ptr = (sljit_ins*)jump_ptr; + sljit_ins *inst = (sljit_ins*)ptr[0]; + sljit_ins mov_pc = ptr[1]; sljit_s32 bl = (mov_pc & 0x0000f000) != RD(TMP_PC); sljit_sw diff = (sljit_sw)(((sljit_sw)new_addr - (sljit_sw)(inst + 2) - executable_offset) >> 2); @@ -492,7 +539,7 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw jump_ptr, sljit_sw execut inst[0] = (mov_pc & COND_MASK) | (B - CONDITIONAL) | (diff & 0xffffff); if (flush_cache) { SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1); - inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); + inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 1); } } else { @@ -503,7 +550,7 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw jump_ptr, sljit_sw execut inst[1] = NOP; if (flush_cache) { SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1); - inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); + inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } } @@ -522,14 +569,14 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw jump_ptr, sljit_sw execut if (!bl) { if (flush_cache) { SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1); - inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); + inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 1); } } else { inst[1] = BLX | RM(TMP_REG1); if (flush_cache) { SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1); - inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); + inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } } @@ -545,8 +592,8 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw jump_ptr, sljit_sw execut SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1); } } -#else - sljit_uw *inst = (sljit_uw*)jump_ptr; +#else /* !SLJIT_CONFIG_ARM_V6 */ + sljit_ins *inst = (sljit_ins*)jump_ptr; SLJIT_UNUSED_ARG(executable_offset); @@ -561,21 +608,21 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw jump_ptr, sljit_sw execut if (flush_cache) { SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1); - inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); + inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } -#endif +#endif /* SLJIT_CONFIG_ARM_V6 */ } static sljit_uw get_imm(sljit_uw imm); static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm); static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg); -static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_offset, sljit_uw new_constant, sljit_s32 flush_cache) +static void set_const_value(sljit_uw addr, sljit_sw executable_offset, sljit_uw new_constant, sljit_s32 flush_cache) { -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - sljit_uw *ptr = (sljit_uw*)addr; - sljit_uw *inst = (sljit_uw*)ptr[0]; +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + sljit_ins *ptr = (sljit_ins*)addr; + sljit_ins *inst = (sljit_ins*)ptr[0]; sljit_uw ldr_literal = ptr[1]; sljit_uw src2; @@ -591,7 +638,7 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_off if (flush_cache) { SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1); - inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); + inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 1); } return; @@ -607,7 +654,7 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_off if (flush_cache) { SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1); - inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); + inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 1); } return; @@ -627,7 +674,7 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_off if (flush_cache) { SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1); - inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); + inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 1); } } @@ -641,8 +688,8 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_off if (flush_cache) { SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1); } -#else - sljit_uw *inst = (sljit_uw*)addr; +#else /* !SLJIT_CONFIG_ARM_V6 */ + sljit_ins *inst = (sljit_ins*)addr; SLJIT_UNUSED_ARG(executable_offset); @@ -657,90 +704,185 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_off if (flush_cache) { SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1); - inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); + inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } -#endif +#endif /* SLJIT_CONFIG_ARM_V6 */ +} + +static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) +{ + sljit_uw addr; + sljit_sw diff; + SLJIT_UNUSED_ARG(executable_offset); + + if (jump->flags & JUMP_ADDR) + addr = jump->u.target; + else + addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset); + + /* The pc+8 offset is represented by the 2 * SSIZE_OF(ins) below. */ + diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + + if ((diff & 0x3) == 0 && diff <= (0x3fc + 2 * SSIZE_OF(ins)) && diff >= (-0x3fc + 2 * SSIZE_OF(ins))) { + jump->flags |= PATCH_B; + return 0; + } + +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + return 0; +#else /* !SLJIT_CONFIG_ARM_V6 */ + return 1; +#endif /* SLJIT_CONFIG_ARM_V6 */ +} + +#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) + +static void reduce_code_size(struct sljit_compiler *compiler) +{ + struct sljit_label *label; + struct sljit_jump *jump; + struct sljit_const *const_; + SLJIT_NEXT_DEFINE_TYPES; + sljit_uw total_size; + sljit_uw size_reduce = 0; + sljit_sw diff; + + label = compiler->labels; + jump = compiler->jumps; + const_ = compiler->consts; + SLJIT_NEXT_INIT_TYPES(); + + while (1) { + SLJIT_GET_NEXT_MIN(); + + if (next_min_addr == SLJIT_MAX_ADDRESS) + break; + + if (next_min_addr == next_label_size) { + label->size -= size_reduce; + + label = label->next; + next_label_size = SLJIT_GET_NEXT_SIZE(label); + } + + if (next_min_addr == next_const_addr) { + const_->addr -= size_reduce; + const_ = const_->next; + next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_); + continue; + } + + if (next_min_addr != next_jump_addr) + continue; + + jump->addr -= size_reduce; + if (!(jump->flags & JUMP_MOV_ADDR)) { + total_size = JUMP_MAX_SIZE - 1; + + if (!(jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR))) { + /* Unit size: instruction. */ + diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr - 2; + + if (diff <= (0x01ffffff / SSIZE_OF(ins)) && diff >= (-0x02000000 / SSIZE_OF(ins))) + total_size = 1 - 1; + } + + size_reduce += JUMP_MAX_SIZE - 1 - total_size; + } else { + /* Real size minus 1. Unit size: instruction. */ + total_size = 1; + + if (!(jump->flags & JUMP_ADDR)) { + diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; + if (diff <= 0xff + 2 && diff >= -0xff + 2) + total_size = 0; + } + + size_reduce += 1 - total_size; + } + + jump->flags |= total_size << JUMP_SIZE_SHIFT; + jump = jump->next; + next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); + } + + compiler->size -= size_reduce; } +#endif /* SLJIT_CONFIG_ARM_V7 */ + SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) { struct sljit_memory_fragment *buf; - sljit_uw *code; - sljit_uw *code_ptr; - sljit_uw *buf_ptr; - sljit_uw *buf_end; - sljit_uw size; + sljit_ins *code; + sljit_ins *code_ptr; + sljit_ins *buf_ptr; + sljit_ins *buf_end; sljit_uw word_count; - sljit_uw next_addr; + SLJIT_NEXT_DEFINE_TYPES; sljit_sw executable_offset; sljit_uw addr; -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + sljit_sw diff; +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) sljit_uw cpool_size; sljit_uw cpool_skip_alignment; sljit_uw cpool_current_index; - sljit_uw *cpool_start_address; - sljit_uw *last_pc_patch; + sljit_ins *cpool_start_address; + sljit_ins *last_pc_patch; struct future_patch *first_patch; #endif struct sljit_label *label; struct sljit_jump *jump; struct sljit_const *const_; - struct sljit_put_label *put_label; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_generate_code(compiler)); - reverse_buf(compiler); /* Second code generation pass. */ -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - size = compiler->size + (compiler->patches << 1); +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + compiler->size += (compiler->patches << 1); if (compiler->cpool_fill > 0) - size += compiler->cpool_fill + CONST_POOL_ALIGNMENT - 1; -#else - size = compiler->size; -#endif - code = (sljit_uw*)SLJIT_MALLOC_EXEC(size * sizeof(sljit_uw), compiler->exec_allocator_data); + compiler->size += compiler->cpool_fill + CONST_POOL_ALIGNMENT - 1; +#else /* !SLJIT_CONFIG_ARM_V6 */ + reduce_code_size(compiler); +#endif /* SLJIT_CONFIG_ARM_V6 */ + code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data); PTR_FAIL_WITH_EXEC_IF(code); + + reverse_buf(compiler); buf = compiler->buf; -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) cpool_size = 0; cpool_skip_alignment = 0; cpool_current_index = 0; cpool_start_address = NULL; first_patch = NULL; last_pc_patch = code; -#endif +#endif /* SLJIT_CONFIG_ARM_V6 */ code_ptr = code; word_count = 0; - next_addr = 1; executable_offset = SLJIT_EXEC_OFFSET(code); label = compiler->labels; jump = compiler->jumps; const_ = compiler->consts; - put_label = compiler->put_labels; - - if (label && label->size == 0) { - label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset); - label = label->next; - } + SLJIT_NEXT_INIT_TYPES(); + SLJIT_GET_NEXT_MIN(); do { - buf_ptr = (sljit_uw*)buf->memory; + buf_ptr = (sljit_ins*)buf->memory; buf_end = buf_ptr + (buf->used_size >> 2); do { - word_count++; -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) if (cpool_size > 0) { if (cpool_skip_alignment > 0) { buf_ptr++; cpool_skip_alignment--; - } - else { + } else { if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) { SLJIT_FREE_EXEC(code, compiler->exec_allocator_data); compiler->error = SLJIT_ERR_ALLOC_FAILED; @@ -750,64 +892,63 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil if (++cpool_current_index >= cpool_size) { SLJIT_ASSERT(!first_patch); cpool_size = 0; - if (label && label->size == word_count) { - /* Points after the current instruction. */ - label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); - label->size = (sljit_uw)(code_ptr - code); - label = label->next; - - next_addr = compute_next_addr(label, jump, const_, put_label); - } } } - } - else if ((*buf_ptr & 0xff000000) != PUSH_POOL) { -#endif + } else if ((*buf_ptr & 0xff000000) != PUSH_POOL) { +#endif /* SLJIT_CONFIG_ARM_V6 */ *code_ptr = *buf_ptr++; - if (next_addr == word_count) { + if (next_min_addr == word_count) { SLJIT_ASSERT(!label || label->size >= word_count); SLJIT_ASSERT(!jump || jump->addr >= word_count); SLJIT_ASSERT(!const_ || const_->addr >= word_count); - SLJIT_ASSERT(!put_label || put_label->addr >= word_count); - - /* These structures are ordered by their address. */ - if (jump && jump->addr == word_count) { -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - if (detect_jump_type(jump, code_ptr, code, executable_offset)) - code_ptr--; - jump->addr = (sljit_uw)code_ptr; -#else - jump->addr = (sljit_uw)(code_ptr - 2); - if (detect_jump_type(jump, code_ptr, code, executable_offset)) - code_ptr -= 2; -#endif - jump = jump->next; - } - if (label && label->size == word_count) { - /* code_ptr can be affected above. */ - label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr + 1, executable_offset); - label->size = (sljit_uw)((code_ptr + 1) - code); + + if (next_min_addr == next_label_size) { + label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + label->size = (sljit_uw)(code_ptr - code); label = label->next; + next_label_size = SLJIT_GET_NEXT_SIZE(label); } - if (const_ && const_->addr == word_count) { -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + + /* These structures are ordered by their address. */ + if (next_min_addr == next_jump_addr) { + if (!(jump->flags & JUMP_MOV_ADDR)) { +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + if (detect_jump_type(jump, code_ptr, code, executable_offset)) + code_ptr--; + jump->addr = (sljit_uw)code_ptr; +#else /* !SLJIT_CONFIG_ARM_V6 */ + word_count += jump->flags >> JUMP_SIZE_SHIFT; + jump->addr = (sljit_uw)code_ptr; + if (!detect_jump_type(jump, code_ptr, code, executable_offset)) { + code_ptr[2] = code_ptr[0]; + addr = ((code_ptr[0] & 0xf) << 12); + code_ptr[0] = MOVW | addr; + code_ptr[1] = MOVT | addr; + code_ptr += 2; + } + SLJIT_ASSERT((sljit_uw)code_ptr - jump->addr <= (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)); +#endif /* SLJIT_CONFIG_ARM_V6 */ + } else { +#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) + word_count += jump->flags >> JUMP_SIZE_SHIFT; +#endif /* SLJIT_CONFIG_ARM_V7 */ + addr = (sljit_uw)code_ptr; + code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset); + jump->addr = addr; + } + jump = jump->next; + next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); + } else if (next_min_addr == next_const_addr) { const_->addr = (sljit_uw)code_ptr; -#else - const_->addr = (sljit_uw)(code_ptr - 1); -#endif const_ = const_->next; + next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_); } - if (put_label && put_label->addr == word_count) { - SLJIT_ASSERT(put_label->label); - put_label->addr = (sljit_uw)code_ptr; - put_label = put_label->next; - } - next_addr = compute_next_addr(label, jump, const_, put_label); + + SLJIT_GET_NEXT_MIN(); } code_ptr++; -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - } - else { +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + } else { /* Fortunately, no need to shift. */ cpool_size = *buf_ptr++ & ~PUSH_POOL; SLJIT_ASSERT(cpool_size > 0); @@ -815,30 +956,36 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, cpool_size); if (cpool_current_index > 0) { /* Unconditional branch. */ - *code_ptr = B | (((sljit_uw)(cpool_start_address - code_ptr) + cpool_current_index - 2) & ~PUSH_POOL); - code_ptr = (sljit_uw*)(cpool_start_address + cpool_current_index); + *code_ptr = B | (((sljit_ins)(cpool_start_address - code_ptr) + cpool_current_index - 2) & ~PUSH_POOL); + code_ptr = (sljit_ins*)(cpool_start_address + cpool_current_index); } cpool_skip_alignment = CONST_POOL_ALIGNMENT - 1; cpool_current_index = 0; last_pc_patch = code_ptr; } -#endif +#endif /* SLJIT_CONFIG_ARM_V6 */ + word_count++; } while (buf_ptr < buf_end); buf = buf->next; } while (buf); + if (label && label->size == word_count) { + label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset); + label->size = (sljit_uw)(code_ptr - code); + label = label->next; + } + SLJIT_ASSERT(!label); SLJIT_ASSERT(!jump); SLJIT_ASSERT(!const_); - SLJIT_ASSERT(!put_label); -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) SLJIT_ASSERT(cpool_size == 0); if (compiler->cpool_fill > 0) { cpool_start_address = ALIGN_INSTRUCTION(code_ptr); cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, compiler->cpool_fill); if (cpool_current_index > 0) - code_ptr = (sljit_uw*)(cpool_start_address + cpool_current_index); + code_ptr = (sljit_ins*)(cpool_start_address + cpool_current_index); buf_ptr = compiler->cpool; buf_end = buf_ptr + compiler->cpool_fill; @@ -858,91 +1005,95 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil jump = compiler->jumps; while (jump) { - buf_ptr = (sljit_uw *)jump->addr; + addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr; + buf_ptr = (sljit_ins*)jump->addr; + + if (jump->flags & JUMP_MOV_ADDR) { +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + SLJIT_ASSERT((buf_ptr[0] & (sljit_ins)0xffff0000) == 0xe59f0000); +#else /* !SLJIT_CONFIG_ARM_V6 */ + SLJIT_ASSERT((buf_ptr[0] & ~(sljit_ins)0xf000) == 0); +#endif /* SLJIT_CONFIG_ARM_V6 */ + + if (jump->flags & PATCH_B) { + SLJIT_ASSERT((((sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset)) & 0x3) == 0); + diff = ((sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset)) >> 2; + + SLJIT_ASSERT(diff <= 0xff && diff >= -0xff); + + addr = ADD; + if (diff < 0) { + diff = -diff; + addr = SUB; + } - if (jump->flags & PATCH_B) { - addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset); - if (!(jump->flags & JUMP_ADDR)) { - SLJIT_ASSERT(jump->flags & JUMP_LABEL); - SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - addr) <= 0x01ffffff && (sljit_sw)(jump->u.label->addr - addr) >= -0x02000000); - *buf_ptr |= ((jump->u.label->addr - addr) >> 2) & 0x00ffffff; - } - else { - SLJIT_ASSERT((sljit_sw)(jump->u.target - addr) <= 0x01ffffff && (sljit_sw)(jump->u.target - addr) >= -0x02000000); - *buf_ptr |= ((jump->u.target - addr) >> 2) & 0x00ffffff; + buf_ptr[0] = addr | (buf_ptr[0] & 0xf000) | RN(TMP_PC) | (1 << 25) | (0xf << 8) | (sljit_ins)(diff & 0xff); + } else { +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + buf_ptr[((buf_ptr[0] & 0xfff) >> 2) + 2] = addr; +#else /* !SLJIT_CONFIG_ARM_V6 */ + buf_ptr[1] = MOVT | buf_ptr[0] | ((addr >> 12) & 0xf0000) | ((addr >> 16) & 0xfff); + buf_ptr[0] = MOVW | buf_ptr[0] | ((addr << 4) & 0xf0000) | (addr & 0xfff); +#endif /* SLJIT_CONFIG_ARM_V6 */ } - } - else if (jump->flags & SLJIT_REWRITABLE_JUMP) { -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - jump->addr = (sljit_uw)code_ptr; - code_ptr[0] = (sljit_uw)buf_ptr; - code_ptr[1] = *buf_ptr; - inline_set_jump_addr((sljit_uw)code_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0); - code_ptr += 2; -#else - inline_set_jump_addr((sljit_uw)buf_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0); -#endif - } - else { -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + } else if (jump->flags & PATCH_B) { + diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset); + SLJIT_ASSERT(diff <= 0x01ffffff && diff >= -0x02000000); + *buf_ptr |= (diff >> 2) & 0x00ffffff; + } else { +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) if (jump->flags & IS_BL) buf_ptr--; - if (*buf_ptr & (1 << 23)) - buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2; - else - buf_ptr += 1; - *buf_ptr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; -#else - inline_set_jump_addr((sljit_uw)buf_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0); -#endif + + if (jump->flags & SLJIT_REWRITABLE_JUMP) { + jump->addr = (sljit_uw)code_ptr; + code_ptr[0] = (sljit_ins)buf_ptr; + code_ptr[1] = *buf_ptr; + set_jump_addr((sljit_uw)code_ptr, executable_offset, addr, 0); + code_ptr += 2; + } else { + if (*buf_ptr & (1 << 23)) + buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2; + else + buf_ptr += 1; + *buf_ptr = addr; + } +#else /* !SLJIT_CONFIG_ARM_V6 */ + set_jump_addr((sljit_uw)buf_ptr, executable_offset, addr, 0); +#endif /* SLJIT_CONFIG_ARM_V6 */ } + jump = jump->next; } -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) const_ = compiler->consts; while (const_) { - buf_ptr = (sljit_uw*)const_->addr; + buf_ptr = (sljit_ins*)const_->addr; const_->addr = (sljit_uw)code_ptr; - code_ptr[0] = (sljit_uw)buf_ptr; + code_ptr[0] = (sljit_ins)buf_ptr; code_ptr[1] = *buf_ptr; if (*buf_ptr & (1 << 23)) buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2; else buf_ptr += 1; /* Set the value again (can be a simple constant). */ - inline_set_const((sljit_uw)code_ptr, executable_offset, *buf_ptr, 0); + set_const_value((sljit_uw)code_ptr, executable_offset, *buf_ptr, 0); code_ptr += 2; const_ = const_->next; } -#endif - - put_label = compiler->put_labels; - while (put_label) { - addr = put_label->label->addr; - buf_ptr = (sljit_uw*)put_label->addr; - -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - SLJIT_ASSERT((buf_ptr[0] & 0xffff0000) == 0xe59f0000); - buf_ptr[((buf_ptr[0] & 0xfff) >> 2) + 2] = addr; -#else - SLJIT_ASSERT((buf_ptr[-1] & 0xfff00000) == MOVW && (buf_ptr[0] & 0xfff00000) == MOVT); - buf_ptr[-1] |= ((addr << 4) & 0xf0000) | (addr & 0xfff); - buf_ptr[0] |= ((addr >> 12) & 0xf0000) | ((addr >> 16) & 0xfff); -#endif - put_label = put_label->next; - } +#endif /* SLJIT_CONFIG_ARM_V6 */ - SLJIT_ASSERT(code_ptr - code <= (sljit_s32)size); + SLJIT_ASSERT(code_ptr - code <= (sljit_s32)compiler->size); compiler->error = SLJIT_ERR_COMPILED; compiler->executable_offset = executable_offset; compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_uw); - code = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset); - code_ptr = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + code = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(code, executable_offset); + code_ptr = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); SLJIT_CACHE_FLUSH(code, code_ptr); SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1); @@ -953,29 +1104,42 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) { switch (feature_type) { case SLJIT_HAS_FPU: + case SLJIT_HAS_F64_AS_F32_PAIR: #ifdef SLJIT_IS_FPU_AVAILABLE - return SLJIT_IS_FPU_AVAILABLE; + return (SLJIT_IS_FPU_AVAILABLE) != 0; #else /* Available by default. */ return 1; -#endif +#endif /* SLJIT_IS_FPU_AVAILABLE */ + case SLJIT_HAS_SIMD: +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + return 0; +#else +#ifdef SLJIT_IS_FPU_AVAILABLE + return (SLJIT_IS_FPU_AVAILABLE) != 0; +#else + /* Available by default. */ + return 1; +#endif /* SLJIT_IS_FPU_AVAILABLE */ +#endif /* SLJIT_CONFIG_ARM_V6 */ + case SLJIT_SIMD_REGS_ARE_PAIRS: case SLJIT_HAS_CLZ: case SLJIT_HAS_ROT: case SLJIT_HAS_CMOV: -#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) - case SLJIT_HAS_CTZ: case SLJIT_HAS_REV: case SLJIT_HAS_PREFETCH: -#endif case SLJIT_HAS_COPY_F32: case SLJIT_HAS_COPY_F64: + case SLJIT_HAS_ATOMIC: return 1; -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) case SLJIT_HAS_CTZ: +#if defined(SLJIT_CONFIG_ARM_V6) && SLJIT_CONFIG_ARM_V6 return 2; -#endif +#else + return 1; +#endif /* SLJIT_CONFIG_ARM_V6 */ default: return 0; @@ -995,17 +1159,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) #define LOAD_DATA 0x08 /* Flag bits for emit_op. */ -#define ALLOW_IMM 0x10 -#define ALLOW_INV_IMM 0x20 -#define ALLOW_ANY_IMM (ALLOW_IMM | ALLOW_INV_IMM) -#define ALLOW_NEG_IMM 0x40 +#define ALLOW_IMM 0x10 +#define ALLOW_INV_IMM 0x20 +#define ALLOW_ANY_IMM (ALLOW_IMM | ALLOW_INV_IMM) +#define ALLOW_NEG_IMM 0x40 +#define ALLOW_DOUBLE_IMM 0x80 /* s/l - store/load (1 bit) u/s - signed/unsigned (1 bit) w/b/h/N - word/byte/half/NOT allowed (2 bit) Storing signed and unsigned values are the same operations. */ -static const sljit_uw data_transfer_insts[16] = { +static const sljit_ins data_transfer_insts[16] = { /* s u w */ 0xe5000000 /* str */, /* s u b */ 0xe5400000 /* strb */, /* s u h */ 0xe10000b0 /* strh */, @@ -1026,7 +1191,7 @@ static const sljit_uw data_transfer_insts[16] = { }; #define EMIT_DATA_TRANSFER(type, add, target_reg, base_reg, arg) \ - (data_transfer_insts[(type) & 0xf] | ((add) << 23) | RD(target_reg) | RN(base_reg) | (sljit_uw)(arg)) + (data_transfer_insts[(type) & 0xf] | ((add) << 23) | RD(target_reg) | RN(base_reg) | (sljit_ins)(arg)) /* Normal ldr/str instruction. Type2: ldrsb, ldrh, ldrsh */ @@ -1036,7 +1201,7 @@ static const sljit_uw data_transfer_insts[16] = { (((imm) & 0xf) | (((imm) & 0xf0) << 4) | (1 << 22)) #define EMIT_FPU_OPERATION(opcode, mode, dst, src1, src2) \ - ((sljit_uw)(opcode) | (sljit_uw)(mode) | VD(dst) | VM(src1) | VN(src2)) + ((sljit_ins)(opcode) | (sljit_ins)(mode) | VD(dst) | VM(src1) | VN(src2)) /* Flags for emit_op: */ /* Arguments are swapped. */ @@ -1108,12 +1273,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) { - FAIL_IF(push_inst(compiler, VPUSH | VD(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1))); + FAIL_IF(push_inst(compiler, VPUSH | VD(SLJIT_FS0) | ((sljit_ins)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1))); } else { if (fsaveds > 0) - FAIL_IF(push_inst(compiler, VPUSH | VD(SLJIT_FS0) | ((sljit_uw)fsaveds << 1))); + FAIL_IF(push_inst(compiler, VPUSH | VD(SLJIT_FS0) | ((sljit_ins)fsaveds << 1))); if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) - FAIL_IF(push_inst(compiler, VPUSH | VD(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1))); + FAIL_IF(push_inst(compiler, VPUSH | VD(fscratches) | ((sljit_ins)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1))); } } @@ -1142,7 +1307,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi FAIL_IF(push_inst(compiler, VMOV2 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count)); else FAIL_IF(push_inst(compiler, VLDR_F32 | 0x800100 | RN(SLJIT_SP) - | (float_arg_count << 12) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2))); + | (float_arg_count << 12) | ((offset + (sljit_ins)size - 4 * sizeof(sljit_sw)) >> 2))); float_arg_count++; offset += sizeof(sljit_f64) - sizeof(sljit_sw); break; @@ -1151,7 +1316,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi FAIL_IF(push_inst(compiler, VMOV | (float_arg_count << 16) | (offset << 10))); else FAIL_IF(push_inst(compiler, VLDR_F32 | 0x800000 | RN(SLJIT_SP) - | (float_arg_count << 12) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2))); + | (float_arg_count << 12) | ((offset + (sljit_ins)size - 4 * sizeof(sljit_sw)) >> 2))); float_arg_count++; break; default: @@ -1168,7 +1333,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi if (offset < 4 * sizeof(sljit_sw)) FAIL_IF(push_inst(compiler, MOV | RD(tmp) | (offset >> 2))); else - FAIL_IF(push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(tmp) | (offset + (sljit_uw)size - 4 * sizeof(sljit_sw)))); + FAIL_IF(push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(tmp) | (offset + (sljit_ins)size - 4 * sizeof(sljit_sw)))); break; } @@ -1221,7 +1386,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi #endif if (local_size > 0) - FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size)); + FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM | ALLOW_DOUBLE_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size)); return SLJIT_SUCCESS; } @@ -1250,13 +1415,8 @@ static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm) { sljit_uw imm2 = get_imm(imm); - if (imm2 == 0) { - imm2 = (imm & ~(sljit_uw)0x3ff) >> 10; - imm = (imm & 0x3ff) >> 2; - - FAIL_IF(push_inst(compiler, ADD | SRC2_IMM | RD(SLJIT_SP) | RN(SLJIT_SP) | 0xb00 | imm2)); - return push_inst(compiler, ADD | SRC2_IMM | RD(SLJIT_SP) | RN(SLJIT_SP) | 0xf00 | (imm & 0xff)); - } + if (imm2 == 0) + return emit_op(compiler, SLJIT_ADD, ALLOW_IMM | ALLOW_DOUBLE_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, (sljit_sw)imm); return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | imm2); } @@ -1279,12 +1439,12 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size)); if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) { - FAIL_IF(push_inst(compiler, VPOP | VD(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1))); + FAIL_IF(push_inst(compiler, VPOP | VD(SLJIT_FS0) | ((sljit_ins)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1))); } else { if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) - FAIL_IF(push_inst(compiler, VPOP | VD(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1))); + FAIL_IF(push_inst(compiler, VPOP | VD(fscratches) | ((sljit_ins)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1))); if (fsaveds > 0) - FAIL_IF(push_inst(compiler, VPOP | VD(SLJIT_FS0) | ((sljit_uw)fsaveds << 1))); + FAIL_IF(push_inst(compiler, VPOP | VD(SLJIT_FS0) | ((sljit_ins)fsaveds << 1))); } local_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1) & 0x7; @@ -1335,10 +1495,10 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit if (frame_size == 0) return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | 0x800008); if (frame_size > 2 * SSIZE_OF(sw)) - return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | (sljit_uw)(frame_size - (2 * SSIZE_OF(sw)))); + return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | (sljit_ins)(frame_size - (2 * SSIZE_OF(sw)))); } - FAIL_IF(push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(restored_reg) | (sljit_uw)local_size)); + FAIL_IF(push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(restored_reg) | (sljit_ins)local_size)); tmp = 1; } else if (frame_size == 0) { frame_size = (restored_reg == TMP_REG2) ? SSIZE_OF(sw) : 2 * SSIZE_OF(sw); @@ -1354,7 +1514,7 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit local_size += SSIZE_OF(sw); if (frame_size > local_size) - FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | (sljit_uw)(frame_size - local_size))); + FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | (sljit_ins)(frame_size - local_size))); else if (frame_size < local_size) FAIL_IF(emit_add_sp(compiler, (sljit_uw)(local_size - frame_size))); @@ -1366,11 +1526,11 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit if (restored_reg != TMP_REG2) frame_size -= SSIZE_OF(sw); - return push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(restored_reg) | (sljit_uw)frame_size); + return push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(restored_reg) | (sljit_ins)frame_size); } tmp = (restored_reg == TMP_REG2) ? 0x800004 : 0x800008; - return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | (sljit_uw)tmp); + return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | (sljit_ins)tmp); } if (local_size > 0) @@ -1389,7 +1549,7 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit FAIL_IF(push_inst(compiler, POP | reg_list)); if (frame_size > 0) - return push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | ((sljit_uw)frame_size - sizeof(sljit_sw))); + return push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | ((sljit_ins)frame_size - sizeof(sljit_sw))); if (lr_dst != 0) return SLJIT_SUCCESS; @@ -1437,7 +1597,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl sljit_s32 is_masked; sljit_uw shift_type; - switch (GET_OPCODE(op)) { + switch (op) { case SLJIT_MOV: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); if (dst != src2) { @@ -1451,17 +1611,10 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl case SLJIT_MOV_U8: case SLJIT_MOV_S8: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); - if (flags & MOVE_REG_CONV) { -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - if (op == SLJIT_MOV_U8) - return push_inst(compiler, AND | RD(dst) | RN(src2) | SRC2_IMM | 0xff); - FAIL_IF(push_inst(compiler, MOV | RD(dst) | (24 << 7) | RM(src2))); - return push_inst(compiler, MOV | RD(dst) | (24 << 7) | (op == SLJIT_MOV_U8 ? 0x20 : 0x40) | RM(dst)); -#else + if (flags & MOVE_REG_CONV) return push_inst(compiler, (op == SLJIT_MOV_U8 ? UXTB : SXTB) | RD(dst) | RM(src2)); -#endif - } - else if (dst != src2) { + + if (dst != src2) { SLJIT_ASSERT(src2 & SRC2_IMM); return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2); } @@ -1470,15 +1623,10 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl case SLJIT_MOV_U16: case SLJIT_MOV_S16: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); - if (flags & MOVE_REG_CONV) { -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - FAIL_IF(push_inst(compiler, MOV | RD(dst) | (16 << 7) | RM(src2))); - return push_inst(compiler, MOV | RD(dst) | (16 << 7) | (op == SLJIT_MOV_U16 ? 0x20 : 0x40) | RM(dst)); -#else + if (flags & MOVE_REG_CONV) return push_inst(compiler, (op == SLJIT_MOV_U16 ? UXTH : SXTH) | RD(dst) | RM(src2)); -#endif - } - else if (dst != src2) { + + if (dst != src2) { SLJIT_ASSERT(src2 & SRC2_IMM); return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2); } @@ -1492,30 +1640,30 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl case SLJIT_CTZ: SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) FAIL_IF(push_inst(compiler, RSB | SRC2_IMM | RD(TMP_REG1) | RN(src2) | 0)); FAIL_IF(push_inst(compiler, AND | RD(TMP_REG2) | RN(src2) | RM(TMP_REG1))); FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(TMP_REG2))); FAIL_IF(push_inst(compiler, CMP | SET_FLAGS | SRC2_IMM | RN(dst) | 32)); return push_inst(compiler, (EOR ^ 0xf0000000) | SRC2_IMM | RD(dst) | RN(dst) | 0x1f); -#else /* !SLJIT_CONFIG_ARM_V5 */ +#else /* !SLJIT_CONFIG_ARM_V6 */ FAIL_IF(push_inst(compiler, RBIT | RD(dst) | RM(src2))); return push_inst(compiler, CLZ | RD(dst) | RM(dst)); -#endif /* SLJIT_CONFIG_ARM_V5 */ +#endif /* SLJIT_CONFIG_ARM_V6 */ case SLJIT_REV: -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (8 << 7) | (0 << 5) | RM(src2))); - FAIL_IF(push_inst(compiler, MOV | RD(dst) | (24 << 7) | (1 << 5) | RM(src2))); - FAIL_IF(push_inst(compiler, ORR | RD(dst) | RN(dst) | (16 << 7) | (0 << 5) | RM(TMP_REG1))); - FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (16 << 7) | (1 << 5) | RM(TMP_REG1))); - FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (8 << 7) | (3 << 5) | RM(TMP_REG1))); - FAIL_IF(push_inst(compiler, ORR | RD(dst) | RN(dst) | (8 << 7) | (0 << 5) | RM(TMP_REG1))); - return push_inst(compiler, ORR | RD(dst) | RN(dst) | (8 << 7) | (1 << 5) | RM(TMP_REG1)); -#else /* !SLJIT_CONFIG_ARM_V5 */ + case SLJIT_REV_U32: + case SLJIT_REV_S32: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); return push_inst(compiler, REV | RD(dst) | RM(src2)); -#endif /* SLJIT_CONFIG_ARM_V5 */ + case SLJIT_REV_U16: + case SLJIT_REV_S16: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED) && src2 != TMP_REG1 && dst != TMP_REG1); + FAIL_IF(push_inst(compiler, REV16 | RD(dst) | RM(src2))); + if (dst == TMP_REG2 || (src2 == TMP_REG2 && op == SLJIT_REV_U16)) + return SLJIT_SUCCESS; + return push_inst(compiler, (op == SLJIT_REV_U16 ? UXTH : SXTH) | RD(dst) | RM(dst)); case SLJIT_ADD: SLJIT_ASSERT(!(flags & INV_IMM)); @@ -1546,7 +1694,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl SLJIT_ASSERT(!(src2 & SRC2_IMM)); compiler->status_flags_state = 0; - if (!HAS_FLAGS(op)) + if (!(flags & SET_FLAGS)) return push_inst(compiler, MUL | RN(dst) | RM8(src2) | RM(src1)); FAIL_IF(push_inst(compiler, SMULL | RN(TMP_REG1) | RD(dst) | RM8(src2) | RM(src1))); @@ -1574,19 +1722,19 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl case SLJIT_SHL: case SLJIT_MSHL: shift_type = 0; - is_masked = GET_OPCODE(op) == SLJIT_MSHL; + is_masked = op == SLJIT_MSHL; break; case SLJIT_LSHR: case SLJIT_MLSHR: shift_type = 1; - is_masked = GET_OPCODE(op) == SLJIT_MLSHR; + is_masked = op == SLJIT_MLSHR; break; case SLJIT_ASHR: case SLJIT_MASHR: shift_type = 2; - is_masked = GET_OPCODE(op) == SLJIT_MASHR; + is_masked = op == SLJIT_MASHR; break; case SLJIT_ROTL: @@ -1626,7 +1774,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) - | RM8(src2) | (sljit_uw)(shift_type << 5) | 0x10 | RM(src1)); + | RM8(src2) | (sljit_ins)(shift_type << 5) | 0x10 | RM(src1)); } #undef EMIT_SHIFT_INS_AND_RETURN @@ -1643,8 +1791,7 @@ static sljit_uw get_imm(sljit_uw imm) if (!(imm & 0xff000000)) { imm <<= 8; rol = 8; - } - else { + } else { imm = (imm << 24) | (imm >> 8); rol = 0; } @@ -1666,22 +1813,19 @@ static sljit_uw get_imm(sljit_uw imm) if (!(imm & 0x00ffffff)) return SRC2_IMM | (imm >> 24) | (rol << 8); - else - return 0; + return 0; } -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) -static sljit_s32 generate_int(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm, sljit_s32 positive) +static sljit_uw compute_imm(sljit_uw imm, sljit_uw* imm2) { sljit_uw mask; sljit_uw imm1; - sljit_uw imm2; sljit_uw rol; /* Step1: Search a zero byte (8 continous zero bit). */ mask = 0xff000000; rol = 8; - while(1) { + while (1) { if (!(imm & mask)) { /* Rol imm by rol. */ imm = (imm << rol) | (imm >> (32 - rol)); @@ -1689,6 +1833,7 @@ static sljit_s32 generate_int(struct sljit_compiler *compiler, sljit_s32 reg, sl rol = 4 + (rol >> 1); break; } + rol += 2; mask >>= 2; if (mask & 0x3) { @@ -1718,9 +1863,8 @@ static sljit_s32 generate_int(struct sljit_compiler *compiler, sljit_s32 reg, sl if (!(imm & 0xff000000)) { imm1 = SRC2_IMM | ((imm >> 16) & 0xff) | (((rol + 4) & 0xf) << 8); - imm2 = SRC2_IMM | ((imm >> 8) & 0xff) | (((rol + 8) & 0xf) << 8); - } - else if (imm & 0xc0000000) { + *imm2 = SRC2_IMM | ((imm >> 8) & 0xff) | (((rol + 8) & 0xf) << 8); + } else if (imm & 0xc0000000) { imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8); imm <<= 8; rol += 4; @@ -1741,11 +1885,10 @@ static sljit_s32 generate_int(struct sljit_compiler *compiler, sljit_s32 reg, sl } if (!(imm & 0x00ffffff)) - imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8); + *imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8); else return 0; - } - else { + } else { if (!(imm & 0xf0000000)) { imm <<= 4; rol += 2; @@ -1771,25 +1914,23 @@ static sljit_s32 generate_int(struct sljit_compiler *compiler, sljit_s32 reg, sl } if (!(imm & 0x00ffffff)) - imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8); + *imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8); else return 0; } - FAIL_IF(push_inst(compiler, (positive ? MOV : MVN) | RD(reg) | imm1)); - FAIL_IF(push_inst(compiler, (positive ? ORR : BIC) | RD(reg) | RN(reg) | imm2)); - return 1; + return imm1; } -#endif static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm) { sljit_uw tmp; - -#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + sljit_uw imm1, imm2; +#else /* !SLJIT_CONFIG_ARM_V6 */ if (!(imm & ~(sljit_uw)0xffff)) return push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)); -#endif +#endif /* SLJIT_CONFIG_ARM_V6 */ /* Create imm by 1 inst. */ tmp = get_imm(imm); @@ -1800,19 +1941,28 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, if (tmp) return push_inst(compiler, MVN | RD(reg) | tmp); -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) /* Create imm by 2 inst. */ - FAIL_IF(generate_int(compiler, reg, imm, 1)); - FAIL_IF(generate_int(compiler, reg, ~imm, 0)); + imm1 = compute_imm(imm, &imm2); + if (imm1 != 0) { + FAIL_IF(push_inst(compiler, MOV | RD(reg) | imm1)); + return push_inst(compiler, ORR | RD(reg) | RN(reg) | imm2); + } + + imm1 = compute_imm(~imm, &imm2); + if (imm1 != 0) { + FAIL_IF(push_inst(compiler, MVN | RD(reg) | imm1)); + return push_inst(compiler, BIC | RD(reg) | RN(reg) | imm2); + } /* Load integer. */ return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, reg, TMP_PC, 0), imm); -#else +#else /* !SLJIT_CONFIG_ARM_V6 */ FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff))); if (imm <= 0xffff) return SLJIT_SUCCESS; return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff)); -#endif +#endif /* SLJIT_CONFIG_ARM_V6 */ } static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, @@ -1849,13 +1999,13 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, s argw &= 0x3; if (argw != 0 && (mask == 0xff)) { - FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | RM(offset_reg) | ((sljit_uw)argw << 7))); + FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | RM(offset_reg) | ((sljit_ins)argw << 7))); return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, TYPE2_TRANSFER_IMM(0))); } /* Bit 25: RM is offset. */ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, - RM(offset_reg) | (mask == 0xff ? 0 : (1 << 25)) | ((sljit_uw)argw << 7))); + RM(offset_reg) | (mask == 0xff ? 0 : (1 << 25)) | ((sljit_ins)argw << 7))); } arg &= REG_MASK; @@ -1917,10 +2067,16 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 /* We prefers register and simple consts. */ sljit_s32 dst_reg; - sljit_s32 src1_reg; + sljit_s32 src1_reg = 0; sljit_s32 src2_reg = 0; sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0; sljit_s32 neg_op = 0; + sljit_u32 imm2; + + op = GET_OPCODE(op); + + if (flags & SET_FLAGS) + inp_flags &= ~ALLOW_DOUBLE_IMM; if (dst == TMP_REG2) flags |= UNUSED_RETURN; @@ -1928,7 +2084,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 SLJIT_ASSERT(!(inp_flags & ALLOW_INV_IMM) || (inp_flags & ALLOW_IMM)); if (inp_flags & ALLOW_NEG_IMM) { - switch (GET_OPCODE(op)) { + switch (op) { case SLJIT_ADD: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD; neg_op = SLJIT_SUB; @@ -1952,10 +2108,11 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 if (!(inp_flags & ALLOW_IMM)) break; - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { src2_reg = (sljit_s32)get_imm((sljit_uw)src2w); if (src2_reg) break; + if (inp_flags & ALLOW_INV_IMM) { src2_reg = (sljit_s32)get_imm(~(sljit_uw)src2w); if (src2_reg) { @@ -1963,8 +2120,9 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 break; } } + if (neg_op != 0) { - src2_reg = (sljit_s32)get_imm((sljit_uw)-src2w); + src2_reg = (sljit_s32)get_imm((neg_op == SLJIT_ADD || neg_op == SLJIT_SUB) ? (sljit_uw)-src2w : ~(sljit_uw)src2w); if (src2_reg) { op = neg_op | GET_ALL_FLAGS(op); break; @@ -1972,7 +2130,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 } } - if (src1 & SLJIT_IMM) { + if (src1 == SLJIT_IMM) { src2_reg = (sljit_s32)get_imm((sljit_uw)src1w); if (src2_reg) { flags |= ARGS_SWAPPED; @@ -1980,6 +2138,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 src1w = src2w; break; } + if (inp_flags & ALLOW_INV_IMM) { src2_reg = (sljit_s32)get_imm(~(sljit_uw)src1w); if (src2_reg) { @@ -1989,8 +2148,11 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 break; } } + if (neg_op >= SLJIT_SUB) { /* Note: additive operation (commutative). */ + SLJIT_ASSERT(op == SLJIT_ADD || op == SLJIT_ADDC); + src2_reg = (sljit_s32)get_imm((sljit_uw)-src1w); if (src2_reg) { src1 = src2; @@ -2008,8 +2170,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 else if (src1 & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1)); src1_reg = TMP_REG1; - } - else { + } else if (!(inp_flags & ALLOW_DOUBLE_IMM) || src2_reg != 0 || op == SLJIT_SUB || op == SLJIT_SUBC) { FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w)); src1_reg = TMP_REG1; } @@ -2038,8 +2199,62 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 src2_reg = src2; else if (src2 & SLJIT_MEM) FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, src2_reg, src2, src2w, TMP_REG2)); - else + else if (!(inp_flags & ALLOW_DOUBLE_IMM)) FAIL_IF(load_immediate(compiler, src2_reg, (sljit_uw)src2w)); + else { + SLJIT_ASSERT(!(flags & SET_FLAGS)); + + if (src1_reg == 0) { + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w)); + src1_reg = TMP_REG1; + } + + src2_reg = (sljit_s32)compute_imm((sljit_uw)src2w, &imm2); + + if (src2_reg == 0 && neg_op != 0) { + src2_reg = (sljit_s32)compute_imm((sljit_uw)-src2w, &imm2); + if (src2_reg != 0) + op = neg_op; + } + + if (src2_reg == 0) { + FAIL_IF(load_immediate(compiler, TMP_REG2, (sljit_uw)src2w)); + src2_reg = TMP_REG2; + } else { + FAIL_IF(emit_single_op(compiler, op, flags, (sljit_uw)dst_reg, (sljit_uw)src1_reg, (sljit_uw)src2_reg)); + src1_reg = dst_reg; + src2_reg = (sljit_s32)imm2; + + if (op == SLJIT_ADDC) + op = SLJIT_ADD; + else if (op == SLJIT_SUBC) + op = SLJIT_SUB; + } + } + } + + if (src1_reg == 0) { + SLJIT_ASSERT((inp_flags & ALLOW_DOUBLE_IMM) && !(flags & SET_FLAGS)); + + src1_reg = (sljit_s32)compute_imm((sljit_uw)src1w, &imm2); + + if (src1_reg == 0 && neg_op != 0) { + src1_reg = (sljit_s32)compute_imm((sljit_uw)-src1w, &imm2); + if (src1_reg != 0) + op = neg_op; + } + + if (src1_reg == 0) { + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w)); + src1_reg = TMP_REG1; + } else { + FAIL_IF(emit_single_op(compiler, op, flags, (sljit_uw)dst_reg, (sljit_uw)src2_reg, (sljit_uw)src1_reg)); + src1_reg = dst_reg; + src2_reg = (sljit_s32)imm2; + + if (op == SLJIT_ADDC) + op = SLJIT_ADD; + } } FAIL_IF(emit_single_op(compiler, op, flags, (sljit_uw)dst_reg, (sljit_uw)src1_reg, (sljit_uw)src2_reg)); @@ -2129,7 +2344,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile SLJIT_ASSERT(saved_reg_list[1] < 8); FAIL_IF(push_inst(compiler, LDR | 0x8d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */)); } - return push_inst(compiler, (LDR ^ (1 << 24)) | 0x8d0000 | (sljit_uw)(saved_reg_count >= 3 ? 16 : 8) + return push_inst(compiler, (LDR ^ (1 << 24)) | 0x8d0000 | (sljit_ins)(saved_reg_count >= 3 ? 16 : 8) | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */); } return SLJIT_SUCCESS; @@ -2159,21 +2374,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_MOV_U8: - return emit_op(compiler, SLJIT_MOV_U8, ALLOW_ANY_IMM | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw); + return emit_op(compiler, SLJIT_MOV_U8, ALLOW_ANY_IMM | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw); case SLJIT_MOV_S8: - return emit_op(compiler, SLJIT_MOV_S8, ALLOW_ANY_IMM | SIGNED | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw); + return emit_op(compiler, SLJIT_MOV_S8, ALLOW_ANY_IMM | SIGNED | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw); case SLJIT_MOV_U16: - return emit_op(compiler, SLJIT_MOV_U16, ALLOW_ANY_IMM | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw); + return emit_op(compiler, SLJIT_MOV_U16, ALLOW_ANY_IMM | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw); case SLJIT_MOV_S16: - return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); + return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw); case SLJIT_CLZ: case SLJIT_CTZ: case SLJIT_REV: + case SLJIT_REV_U32: + case SLJIT_REV_S32: return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_REV_U16: + case SLJIT_REV_S16: + return emit_op(compiler, op, HALF_SIZE, dst, dstw, TMP_REG1, 0, src, srcw); } return SLJIT_SUCCESS; @@ -2197,14 +2418,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile case SLJIT_ADDC: case SLJIT_SUB: case SLJIT_SUBC: - return emit_op(compiler, op, ALLOW_IMM | ALLOW_NEG_IMM, dst, dstw, src1, src1w, src2, src2w); + return emit_op(compiler, op, ALLOW_IMM | ALLOW_NEG_IMM | ALLOW_DOUBLE_IMM, dst, dstw, src1, src1w, src2, src2w); case SLJIT_OR: - return emit_op(compiler, op, ALLOW_IMM, dst, dstw, src1, src1w, src2, src2w); + return emit_op(compiler, op, ALLOW_IMM | ALLOW_DOUBLE_IMM, dst, dstw, src1, src1w, src2, src2w); case SLJIT_XOR: - inp_flags = ALLOW_IMM; - if (((src1 & SLJIT_IMM) && src1w == -1) || ((src2 & SLJIT_IMM) && src2w == -1)) { + inp_flags = ALLOW_IMM | ALLOW_DOUBLE_IMM; + if ((src1 == SLJIT_IMM && src1w == -1) || (src2 == SLJIT_IMM && src2w == -1)) { inp_flags |= ALLOW_INV_IMM; } return emit_op(compiler, op, inp_flags, dst, dstw, src1, src1w, src2, src2w); @@ -2223,7 +2444,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile case SLJIT_MASHR: case SLJIT_ROTL: case SLJIT_ROTR: - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { compiler->shift_imm = src2w & 0x1f; return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src1, src1w); } else { @@ -2268,15 +2489,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * ADJUST_LOCAL_OFFSET(src3, src3w); /* Shift type of ROR is 3. */ - if (src3 & SLJIT_IMM) { + if (src3 == SLJIT_IMM) { src3w &= 0x1f; if (src3w == 0) return SLJIT_SUCCESS; - FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM(src1_reg) | ((sljit_uw)(is_left ? 0 : 1) << 5) | ((sljit_uw)src3w << 7))); + FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM(src1_reg) | ((sljit_ins)(is_left ? 0 : 1) << 5) | ((sljit_ins)src3w << 7))); src3w = (src3w ^ 0x1f) + 1; - return push_inst(compiler, ORR | RD(dst_reg) | RN(dst_reg) | RM(src2_reg) | ((sljit_uw)(is_left ? 1 : 0) << 5) | ((sljit_uw)src3w << 7)); + return push_inst(compiler, ORR | RD(dst_reg) | RN(dst_reg) | RM(src2_reg) | ((sljit_ins)(is_left ? 1 : 0) << 5) | ((sljit_ins)src3w << 7)); } if (src3 & SLJIT_MEM) { @@ -2289,10 +2510,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * src3 = TMP_REG2; } - FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM8(src3) | ((sljit_uw)(is_left ? 0 : 1) << 5) | 0x10 | RM(src1_reg))); - FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src2_reg) | ((sljit_uw)(is_left ? 1 : 0) << 5) | (1 << 7))); + FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM8(src3) | ((sljit_ins)(is_left ? 0 : 1) << 5) | 0x10 | RM(src1_reg))); + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src2_reg) | ((sljit_ins)(is_left ? 1 : 0) << 5) | (1 << 7))); FAIL_IF(push_inst(compiler, EOR | SRC2_IMM | RD(TMP_REG2) | RN(src3) | 0x1f)); - return push_inst(compiler, ORR | RD(dst_reg) | RN(dst_reg) | RM8(TMP_REG2) | ((sljit_uw)(is_left ? 1 : 0) << 5) | 0x10 | RM(TMP_REG1)); + return push_inst(compiler, ORR | RD(dst_reg) | RN(dst_reg) | RM8(TMP_REG2) | ((sljit_ins)(is_left ? 1 : 0) << 5) | 0x10 | RM(TMP_REG1)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, @@ -2318,12 +2539,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp case SLJIT_PREFETCH_L2: case SLJIT_PREFETCH_L3: case SLJIT_PREFETCH_ONCE: -#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) SLJIT_ASSERT(src & SLJIT_MEM); return emit_op_mem(compiler, PRELOAD | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1); -#else /* !SLJIT_CONFIG_ARM_V7 */ - return SLJIT_SUCCESS; -#endif /* SLJIT_CONFIG_ARM_V7 */ } return SLJIT_SUCCESS; @@ -2369,16 +2586,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg) { - CHECK_REG_INDEX(check_sljit_get_register_index(reg)); - return reg_map[reg]; -} + CHECK_REG_INDEX(check_sljit_get_register_index(type, reg)); -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) -{ - CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); - return (freg_map[reg] << 1); + if (type == SLJIT_GP_REGISTER) + return reg_map[reg]; + + if (type == SLJIT_FLOAT_REGISTER || type == SLJIT_SIMD_REG_64) + return freg_map[reg]; + + if (type != SLJIT_SIMD_REG_128) + return freg_map[reg] & ~0x1; + + return -1; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, @@ -2388,7 +2609,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c CHECK_ERROR(); CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); - return push_inst(compiler, *(sljit_uw*)instruction); + return push_inst(compiler, *(sljit_ins*)instruction); } /* --------------------------------------------------------------------- */ @@ -2397,18 +2618,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c #define FPU_LOAD (1 << 20) #define EMIT_FPU_DATA_TRANSFER(inst, add, base, freg, offs) \ - ((inst) | (sljit_uw)((add) << 23) | RN(base) | VD(freg) | (sljit_uw)(offs)) + ((inst) | (sljit_ins)((add) << 23) | RN(base) | VD(freg) | (sljit_ins)(offs)) static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) { sljit_uw imm; - sljit_uw inst = VSTR_F32 | (flags & (SLJIT_32 | FPU_LOAD)); + sljit_ins inst = VSTR_F32 | (flags & (SLJIT_32 | FPU_LOAD)); SLJIT_ASSERT(arg & SLJIT_MEM); arg &= ~SLJIT_MEM; if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { - FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (((sljit_uw)argw & 0x3) << 7))); + FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (((sljit_ins)argw & 0x3) << 7))); arg = TMP_REG2; argw = 0; } @@ -2463,14 +2684,12 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw); } -static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, +static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; - op ^= SLJIT_32; - if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, VMOV | RD(src) | VN(TMP_FREG1))); else if (src & SLJIT_MEM) { @@ -2482,16 +2701,30 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp FAIL_IF(push_inst(compiler, VMOV | RD(TMP_REG1) | VN(TMP_FREG1))); } - FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F32_S32, op & SLJIT_32, dst_r, TMP_FREG1, 0))); + FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(ins, ins & SLJIT_32, dst_r, TMP_FREG1, 0))); if (dst & SLJIT_MEM) - return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw); + return emit_fop_mem(compiler, (ins & SLJIT_32), TMP_FREG1, dst, dstw); return SLJIT_SUCCESS; } -static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 src1, sljit_sw src1w, - sljit_s32 src2, sljit_sw src2w) +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + return sljit_emit_fop1_conv_f64_from_w(compiler, VCVT_F32_S32 | (~op & SLJIT_32), dst, dstw, src, srcw); +} + +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + return sljit_emit_fop1_conv_f64_from_w(compiler, VCVT_F32_U32 | (~op & SLJIT_32), dst, dstw, src, srcw); +} + +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) { op ^= SLJIT_32; @@ -2506,7 +2739,12 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile } FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCMP_F32, op & SLJIT_32, src1, src2, 0))); - return push_inst(compiler, VMRS); + FAIL_IF(push_inst(compiler, VMRS)); + + if (GET_FLAG_TYPE(op) != SLJIT_UNORDERED_OR_EQUAL) + return SLJIT_SUCCESS; + + return push_inst(compiler, (CMP - CONDITIONAL) | (0x60000000 /* VS */) | SET_FLAGS | RN(TMP_REG1) | RM(TMP_REG1)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, @@ -2587,18 +2825,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil case SLJIT_ADD_F64: FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VADD_F32, op & SLJIT_32, dst_r, src2, src1))); break; - case SLJIT_SUB_F64: FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VSUB_F32, op & SLJIT_32, dst_r, src2, src1))); break; - case SLJIT_MUL_F64: FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMUL_F32, op & SLJIT_32, dst_r, src2, src1))); break; - case SLJIT_DIV_F64: FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VDIV_F32, op & SLJIT_32, dst_r, src2, src1))); break; + case SLJIT_COPYSIGN_F64: + FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(src2) | RD(TMP_REG1) | ((op & SLJIT_32) ? (1 << 7) : 0))); + FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_32, dst_r, src1, 0))); + FAIL_IF(push_inst(compiler, CMP | SET_FLAGS | RN(TMP_REG1) | SRC2_IMM | 0)); + return push_inst(compiler, EMIT_FPU_OPERATION((VNEG_F32 & ~COND_MASK) | 0xb0000000, op & SLJIT_32, dst_r, dst_r, 0)); } if (dst_r == TMP_FREG1) @@ -2609,11 +2849,79 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil #undef EMIT_FPU_DATA_TRANSFER +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f32 value) +{ +#if defined(__ARM_NEON) && __ARM_NEON + sljit_u32 exp; + sljit_ins ins; +#endif /* NEON */ + union { + sljit_u32 imm; + sljit_f32 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset32(compiler, freg, value)); + + u.value = value; + +#if defined(__ARM_NEON) && __ARM_NEON + if ((u.imm << (32 - 19)) == 0) { + exp = (u.imm >> (23 + 2)) & 0x3f; + + if (exp == 0x20 || exp == 0x1f) { + ins = ((u.imm >> 24) & 0x80) | ((u.imm >> 19) & 0x7f); + return push_inst(compiler, (VMOV_F32 ^ (1 << 6)) | ((ins & 0xf0) << 12) | VD(freg) | (ins & 0xf)); + } + } +#endif /* NEON */ + + FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm)); + return push_inst(compiler, VMOV | VN(freg) | RD(TMP_REG1)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f64 value) +{ +#if defined(__ARM_NEON) && __ARM_NEON + sljit_u32 exp; + sljit_ins ins; +#endif /* NEON */ + union { + sljit_u32 imm[2]; + sljit_f64 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset64(compiler, freg, value)); + + u.value = value; + +#if defined(__ARM_NEON) && __ARM_NEON + if (u.imm[0] == 0 && (u.imm[1] << (64 - 48)) == 0) { + exp = (u.imm[1] >> ((52 - 32) + 2)) & 0x1ff; + + if (exp == 0x100 || exp == 0xff) { + ins = ((u.imm[1] >> (56 - 32)) & 0x80) | ((u.imm[1] >> (48 - 32)) & 0x7f); + return push_inst(compiler, (VMOV_F32 ^ (1 << 6)) | (1 << 8) | ((ins & 0xf0) << 12) | VD(freg) | (ins & 0xf)); + } + } +#endif /* NEON */ + + FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0])); + if (u.imm[0] == u.imm[1]) + return push_inst(compiler, VMOV2 | RN(TMP_REG1) | RD(TMP_REG1) | VM(freg)); + + FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1])); + return push_inst(compiler, VMOV2 | RN(TMP_REG2) | RD(TMP_REG1) | VM(freg)); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 freg, sljit_s32 reg) { sljit_s32 reg2; - sljit_uw inst; + sljit_ins inst; CHECK_ERROR(); CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); @@ -2640,19 +2948,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compi /* Conditional instructions */ /* --------------------------------------------------------------------- */ -static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type) +static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type) { switch (type) { case SLJIT_EQUAL: + case SLJIT_ATOMIC_STORED: case SLJIT_F_EQUAL: case SLJIT_ORDERED_EQUAL: - case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */ + case SLJIT_UNORDERED_OR_EQUAL: return 0x00000000; case SLJIT_NOT_EQUAL: + case SLJIT_ATOMIC_NOT_STORED: case SLJIT_F_NOT_EQUAL: case SLJIT_UNORDERED_OR_NOT_EQUAL: - case SLJIT_ORDERED_NOT_EQUAL: /* Not supported. */ + case SLJIT_ORDERED_NOT_EQUAL: return 0x10000000; case SLJIT_CARRY: @@ -2757,31 +3067,29 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile SLJIT_ASSERT(reg_map[TMP_REG1] != 14); -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) if (type >= SLJIT_FAST_CALL) PTR_FAIL_IF(prepare_blx(compiler)); + + jump->addr = compiler->size; PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(compiler, type), 0)); - if (jump->flags & SLJIT_REWRITABLE_JUMP) { - jump->addr = compiler->size; + if (jump->flags & SLJIT_REWRITABLE_JUMP) compiler->patches++; - } if (type >= SLJIT_FAST_CALL) { jump->flags |= IS_BL; + jump->addr = compiler->size; PTR_FAIL_IF(emit_blx(compiler)); } - - if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) - jump->addr = compiler->size; -#else +#else /* !SLJIT_CONFIG_ARM_V6 */ + jump->addr = compiler->size; if (type >= SLJIT_FAST_CALL) jump->flags |= IS_BL; - PTR_FAIL_IF(emit_imm(compiler, TMP_REG1, 0)); PTR_FAIL_IF(push_inst(compiler, (((type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)) & ~COND_MASK) | get_cc(compiler, type))); - jump->addr = compiler->size; -#endif + compiler->size += JUMP_MAX_SIZE - 1; +#endif /* SLJIT_CONFIG_ARM_V6 */ return jump; } @@ -2799,7 +3107,7 @@ static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit sljit_u8 *offset_ptr = offsets; if (src && FAST_IS_REG(*src)) - src_offset = (sljit_uw)reg_map[*src] * sizeof(sljit_sw); + src_offset = (sljit_u32)reg_map[*src] * sizeof(sljit_sw); arg_types >>= SLJIT_ARG_SHIFT; @@ -2834,7 +3142,7 @@ static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit if (is_tail_call) offset += sizeof(sljit_sw); - offset = ((offset - 4 * sizeof(sljit_sw)) + 0x7) & ~(sljit_uw)0x7; + offset = ((offset - 4 * sizeof(sljit_sw)) + 0x7) & ~(sljit_u32)0x7; *extra_space = offset; @@ -2964,8 +3272,6 @@ static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit #endif /* __SOFTFP__ */ -#undef EMIT_FPU_OPERATION - SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types) { @@ -3032,7 +3338,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi SLJIT_ASSERT(reg_map[TMP_REG1] != 14); - if (!(src & SLJIT_IMM)) { + if (src != SLJIT_IMM) { if (FAST_IS_REG(src)) { SLJIT_ASSERT(reg_map[src] != 14); return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src)); @@ -3049,17 +3355,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0)); jump->u.target = (sljit_uw)srcw; -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) if (type >= SLJIT_FAST_CALL) FAIL_IF(prepare_blx(compiler)); + jump->addr = compiler->size; FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0)); - if (type >= SLJIT_FAST_CALL) + if (type >= SLJIT_FAST_CALL) { + jump->addr = compiler->size; FAIL_IF(emit_blx(compiler)); -#else - FAIL_IF(emit_imm(compiler, TMP_REG1, 0)); - FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1))); -#endif + } +#else /* !SLJIT_CONFIG_ARM_V6 */ jump->addr = compiler->size; + FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1))); + compiler->size += JUMP_MAX_SIZE - 1; +#endif /* SLJIT_CONFIG_ARM_V6 */ return SLJIT_SUCCESS; } @@ -3157,7 +3466,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co sljit_s32 type) { sljit_s32 dst_reg, flags = GET_ALL_FLAGS(op); - sljit_uw cc, ins; + sljit_ins cc, ins; CHECK_ERROR(); CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); @@ -3193,61 +3502,114 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, - sljit_s32 src, sljit_sw srcw) + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_reg) { - sljit_uw cc, tmp; + sljit_ins cc, tmp; CHECK_ERROR(); - CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); + CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg)); + + ADJUST_LOCAL_OFFSET(src1, src1w); + + if (src2_reg != dst_reg && src1 == dst_reg) { + src1 = src2_reg; + src1w = 0; + src2_reg = dst_reg; + type ^= 0x1; + } + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, (src2_reg != dst_reg) ? dst_reg : TMP_REG1, src1, src1w, TMP_REG2)); + + if (src2_reg != dst_reg) { + src1 = src2_reg; + src1w = 0; + type ^= 0x1; + } else { + src1 = TMP_REG1; + src1w = 0; + } + } else if (dst_reg != src2_reg) + FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM(src2_reg))); cc = get_cc(compiler, type & ~SLJIT_32); - if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { - tmp = get_imm((sljit_uw)srcw); + if (SLJIT_UNLIKELY(src1 == SLJIT_IMM)) { + tmp = get_imm((sljit_uw)src1w); if (tmp) return push_inst(compiler, ((MOV | RD(dst_reg) | tmp) & ~COND_MASK) | cc); - tmp = get_imm(~(sljit_uw)srcw); + tmp = get_imm(~(sljit_uw)src1w); if (tmp) return push_inst(compiler, ((MVN | RD(dst_reg) | tmp) & ~COND_MASK) | cc); #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) - tmp = (sljit_uw)srcw; + tmp = (sljit_ins)src1w; FAIL_IF(push_inst(compiler, (MOVW & ~COND_MASK) | cc | RD(dst_reg) | ((tmp << 4) & 0xf0000) | (tmp & 0xfff))); if (tmp <= 0xffff) return SLJIT_SUCCESS; return push_inst(compiler, (MOVT & ~COND_MASK) | cc | RD(dst_reg) | ((tmp >> 12) & 0xf0000) | ((tmp >> 16) & 0xfff)); -#else - FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw)); - src = TMP_REG1; -#endif +#else /* !SLJIT_CONFIG_ARM_V7 */ + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w)); + src1 = TMP_REG1; +#endif /* SLJIT_CONFIG_ARM_V7 */ + } + + return push_inst(compiler, ((MOV | RD(dst_reg) | RM(src1)) & ~COND_MASK) | cc); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_freg) +{ + sljit_ins cc; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg)); + + ADJUST_LOCAL_OFFSET(src1, src1w); + + type ^= SLJIT_32; + + if (dst_freg != src2_freg) { + if (dst_freg == src1) { + src1 = src2_freg; + src1w = 0; + type ^= 0x1; + } else + FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, (type & SLJIT_32), dst_freg, src2_freg, 0))); + } + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_fop_mem(compiler, (type & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w)); + src1 = TMP_FREG1; } - return push_inst(compiler, ((MOV | RD(dst_reg) | RM(src)) & ~COND_MASK) | cc); + cc = get_cc(compiler, type & ~SLJIT_32); + return push_inst(compiler, EMIT_FPU_OPERATION((VMOV_F32 & ~COND_MASK) | cc, (type & SLJIT_32), dst_freg, src1, 0)); } +#undef EMIT_FPU_OPERATION + static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s32 max_offset) { sljit_s32 arg = *mem; sljit_sw argw = *memw; sljit_uw imm, tmp; -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - sljit_sw mask = max_offset >= 0xf00 ? 0xfff : 0xff; - sljit_sw sign = max_offset >= 0xf00 ? 0x1000 : 0x100; -#else /* !SLJIT_CONFIG_ARM_V5 */ sljit_sw mask = 0xfff; sljit_sw sign = 0x1000; SLJIT_ASSERT(max_offset >= 0xf00); -#endif /* SLJIT_CONFIG_ARM_V5 */ *mem = TMP_REG1; if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { *memw = 0; - return push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((sljit_uw)(argw & 0x3) << 7)); + return push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((sljit_ins)(argw & 0x3) << 7)); } arg &= REG_MASK; @@ -3295,158 +3657,6 @@ static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem return push_inst(compiler, ADD | RD(TMP_REG1) | RN(TMP_REG1) | RM(arg)); } -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - -static sljit_s32 sljit_emit_mem_unaligned(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 reg, - sljit_s32 mem, sljit_sw memw) -{ - sljit_s32 flags, steps, tmp_reg; - sljit_uw add, shift; - - switch (type & 0xff) { - case SLJIT_MOV_U8: - case SLJIT_MOV_S8: - flags = BYTE_SIZE; - if (!(type & SLJIT_MEM_STORE)) - flags |= LOAD_DATA; - if ((type & 0xff) == SLJIT_MOV_S8) - flags |= SIGNED; - - return emit_op_mem(compiler, flags, reg, mem, memw, TMP_REG1); - - case SLJIT_MOV_U16: - FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 1)); - flags = BYTE_SIZE; - steps = 1; - break; - - case SLJIT_MOV_S16: - FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xff - 1)); - flags = BYTE_SIZE | SIGNED; - steps = 1; - break; - - default: - if (type & SLJIT_MEM_UNALIGNED_32) { - flags = WORD_SIZE; - if (!(type & SLJIT_MEM_STORE)) - flags |= LOAD_DATA; - - return emit_op_mem(compiler, flags, reg, mem, memw, TMP_REG1); - } - - if (!(type & SLJIT_MEM_UNALIGNED_16)) { - FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 3)); - flags = BYTE_SIZE; - steps = 3; - break; - } - - FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xff - 2)); - - add = 1; - if (memw < 0) { - add = 0; - memw = -memw; - } - - tmp_reg = reg; - - if (type & SLJIT_MEM_STORE) { - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(HALF_SIZE, add, reg, mem, TYPE2_TRANSFER_IMM(memw)))); - FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(reg) | (16 << 7) | (2 << 4))); - } else { - if (reg == mem) { - SLJIT_ASSERT(reg != TMP_REG1); - tmp_reg = TMP_REG1; - } - - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(HALF_SIZE | LOAD_DATA, add, tmp_reg, mem, TYPE2_TRANSFER_IMM(memw)))); - } - - if (!add) { - memw -= 2; - if (memw <= 0) { - memw = -memw; - add = 1; - } - } else - memw += 2; - - if (type & SLJIT_MEM_STORE) - return push_inst(compiler, EMIT_DATA_TRANSFER(HALF_SIZE, add, TMP_REG2, mem, TYPE2_TRANSFER_IMM(memw))); - - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(HALF_SIZE | LOAD_DATA, add, TMP_REG2, mem, TYPE2_TRANSFER_IMM(memw)))); - return push_inst(compiler, ORR | RD(reg) | RN(tmp_reg) | RM(TMP_REG2) | (16 << 7)); - } - - SLJIT_ASSERT(steps > 0); - - add = 1; - if (memw < 0) { - add = 0; - memw = -memw; - } - - if (type & SLJIT_MEM_STORE) { - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(BYTE_SIZE, add, reg, mem, memw))); - FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(reg) | (8 << 7) | (2 << 4))); - - while (1) { - if (!add) { - memw -= 1; - if (memw == 0) - add = 1; - } else - memw += 1; - - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(BYTE_SIZE, add, TMP_REG2, mem, memw))); - - if (--steps == 0) - return SLJIT_SUCCESS; - - FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(TMP_REG2) | (8 << 7) | (2 << 4))); - } - } - - tmp_reg = reg; - - if (reg == mem) { - SLJIT_ASSERT(reg != TMP_REG1); - tmp_reg = TMP_REG1; - } - - shift = 8; - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(BYTE_SIZE | LOAD_DATA, add, tmp_reg, mem, memw))); - - do { - if (!add) { - memw -= 1; - if (memw == 0) - add = 1; - } else - memw += 1; - - if (steps > 1) { - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(BYTE_SIZE | LOAD_DATA, add, TMP_REG2, mem, memw))); - FAIL_IF(push_inst(compiler, ORR | RD(tmp_reg) | RN(tmp_reg) | RM(TMP_REG2) | (shift << 7))); - shift += 8; - } - } while (--steps != 0); - - flags |= LOAD_DATA; - - if (flags & SIGNED) - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(flags, add, TMP_REG2, mem, TYPE2_TRANSFER_IMM(memw)))); - else - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(flags, add, TMP_REG2, mem, memw))); - - return push_inst(compiler, ORR | RD(reg) | RN(tmp_reg) | RM(TMP_REG2) | (shift << 7)); -} - -#endif /* SLJIT_CONFIG_ARM_V5 */ - SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) @@ -3456,30 +3666,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile CHECK_ERROR(); CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); - if (!(reg & REG_PAIR_MASK)) { -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - ADJUST_LOCAL_OFFSET(mem, memw); -#endif /* SLJIT_CONFIG_ARM_V5 */ - + if (!(reg & REG_PAIR_MASK)) return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); - } ADJUST_LOCAL_OFFSET(mem, memw); -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - if (type & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16)) { - FAIL_IF(update_mem_addr(compiler, &mem, &memw, (type & SLJIT_MEM_UNALIGNED_16) ? 0xfff - 6 : 0xfff - 7)); - - if (!(type & SLJIT_MEM_STORE) && REG_PAIR_FIRST(reg) == (mem & REG_MASK)) { - FAIL_IF(sljit_emit_mem_unaligned(compiler, type, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw))); - return sljit_emit_mem_unaligned(compiler, type, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw); - } - - FAIL_IF(sljit_emit_mem_unaligned(compiler, type, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw)); - return sljit_emit_mem_unaligned(compiler, type, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw)); - } -#endif /* SLJIT_CONFIG_ARM_V5 */ - FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4)); flags = WORD_SIZE; @@ -3502,7 +3693,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler * sljit_s32 mem, sljit_sw memw) { sljit_s32 flags; - sljit_uw is_type1_transfer, inst; + sljit_ins is_type1_transfer, inst; CHECK_ERROR(); CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw)); @@ -3561,7 +3752,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler * if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { memw &= 0x3; - inst = EMIT_DATA_TRANSFER(flags, 1, reg, mem & REG_MASK, RM(OFFS_REG(mem)) | ((sljit_uw)memw << 7)); + inst = EMIT_DATA_TRANSFER(flags, 1, reg, mem & REG_MASK, RM(OFFS_REG(mem)) | ((sljit_ins)memw << 7)); if (is_type1_transfer) inst |= (1 << 25); @@ -3587,7 +3778,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler * else memw = -memw; - return push_inst(compiler, inst | (sljit_uw)memw); + return push_inst(compiler, inst | (sljit_ins)memw); } if (memw >= 0) @@ -3595,76 +3786,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler * else memw = -memw; - return push_inst(compiler, inst | TYPE2_TRANSFER_IMM((sljit_uw)memw)); + return push_inst(compiler, inst | TYPE2_TRANSFER_IMM((sljit_ins)memw)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) { -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - sljit_s32 max_offset; - sljit_s32 dst; -#endif /* SLJIT_CONFIG_ARM_V5 */ - CHECK_ERROR(); CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); - if (type & SLJIT_MEM_UNALIGNED_32) + if (type & SLJIT_MEM_ALIGNED_32) return emit_fop_mem(compiler, ((type ^ SLJIT_32) & SLJIT_32) | ((type & SLJIT_MEM_STORE) ? 0 : FPU_LOAD), freg, mem, memw); -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - if (type & SLJIT_MEM_STORE) { - FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | RD(TMP_REG2))); - - if (type & SLJIT_32) - return sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_UNALIGNED_16), TMP_REG2, mem, memw); - - max_offset = 0xfff - 7; - if (type & SLJIT_MEM_UNALIGNED_16) - max_offset++; - - FAIL_IF(update_mem_addr(compiler, &mem, &memw, max_offset)); - mem |= SLJIT_MEM; - - FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_UNALIGNED_16), TMP_REG2, mem, memw)); - - FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | 0x80 | RD(TMP_REG2))); - return sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_UNALIGNED_16), TMP_REG2, mem, memw + 4); - } - - max_offset = (type & SLJIT_32) ? 0xfff - 3 : 0xfff - 7; - if (type & SLJIT_MEM_UNALIGNED_16) - max_offset++; - - FAIL_IF(update_mem_addr(compiler, &mem, &memw, max_offset)); - - dst = TMP_REG1; - - /* Stack offset adjustment is not needed because dst - is not stored on the stack when mem is SLJIT_SP. */ - - if (mem == TMP_REG1) { - dst = SLJIT_R3; - - if (compiler->scratches >= 4) - FAIL_IF(push_inst(compiler, STR | (1 << 21) | RN(SLJIT_SP) | RD(SLJIT_R3) | 8)); - } - - mem |= SLJIT_MEM; - - FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | (type & SLJIT_MEM_UNALIGNED_16), dst, mem, memw)); - FAIL_IF(push_inst(compiler, VMOV | VN(freg) | RD(dst))); - - if (!(type & SLJIT_32)) { - FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | (type & SLJIT_MEM_UNALIGNED_16), dst, mem, memw + 4)); - FAIL_IF(push_inst(compiler, VMOV | VN(freg) | 0x80 | RD(dst))); - } - - if (dst == SLJIT_R3 && compiler->scratches >= 4) - FAIL_IF(push_inst(compiler, (LDR ^ (0x1 << 24)) | (0x1 << 23) | RN(SLJIT_SP) | RD(SLJIT_R3) | 8)); - return SLJIT_SUCCESS; -#else /* !SLJIT_CONFIG_ARM_V5 */ if (type & SLJIT_MEM_STORE) { FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | RD(TMP_REG2))); @@ -3690,72 +3824,779 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, mem, memw, TMP_REG1)); FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, mem, memw + 4, TMP_REG1)); return push_inst(compiler, VMOV2 | VM(freg) | RD(TMP_REG2) | RN(TMP_REG1)); -#endif /* SLJIT_CONFIG_ARM_V5 */ } -#undef FPU_LOAD - -SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) +static sljit_s32 sljit_emit_simd_mem_offset(struct sljit_compiler *compiler, sljit_s32 *mem_ptr, sljit_sw memw) { - struct sljit_const *const_; - sljit_s32 dst_r; + sljit_s32 mem = *mem_ptr; + sljit_uw imm; - CHECK_ERROR_PTR(); - CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); - ADJUST_LOCAL_OFFSET(dst, dstw); + if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { + *mem_ptr = TMP_REG1; + return push_inst(compiler, ADD | RD(TMP_REG1) | RN(mem & REG_MASK) | RM(OFFS_REG(mem)) | ((sljit_ins)(memw & 0x3) << 7)); + } - dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + if (SLJIT_UNLIKELY(!(mem & REG_MASK))) { + *mem_ptr = TMP_REG1; + return load_immediate(compiler, TMP_REG1, (sljit_uw)memw); + } -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - PTR_FAIL_IF(push_inst_with_unique_literal(compiler, - EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), (sljit_uw)init_value)); - compiler->patches++; -#else - PTR_FAIL_IF(emit_imm(compiler, dst_r, init_value)); -#endif + mem &= REG_MASK; - const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); - PTR_FAIL_IF(!const_); - set_const(const_, compiler); + if (memw == 0) { + *mem_ptr = mem; + return SLJIT_SUCCESS; + } - if (dst & SLJIT_MEM) - PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1)); - return const_; + *mem_ptr = TMP_REG1; + imm = get_imm((sljit_uw)(memw < 0 ? -memw : memw)); + + if (imm != 0) + return push_inst(compiler, ((memw < 0) ? SUB : ADD) | RD(TMP_REG1) | RN(mem) | imm); + + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw)); + return push_inst(compiler, ADD | RD(TMP_REG1) | RN(TMP_REG1) | RM(mem)); } -SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +static SLJIT_INLINE sljit_s32 simd_get_quad_reg_index(sljit_s32 freg) { - struct sljit_put_label *put_label; - sljit_s32 dst_r; + freg += freg & 0x1; - CHECK_ERROR_PTR(); - CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw)); - ADJUST_LOCAL_OFFSET(dst, dstw); + SLJIT_ASSERT((freg_map[freg] & 0x1) == (freg <= SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS)); - dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + if (freg <= SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS) + freg--; -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), 0)); - compiler->patches++; -#else - PTR_FAIL_IF(emit_imm(compiler, dst_r, 0)); -#endif + return freg; +} - put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label)); - PTR_FAIL_IF(!put_label); - set_put_label(put_label, compiler, 0); +#define SLJIT_QUAD_OTHER_HALF(freg) ((((freg) & 0x1) << 1) - 1) - if (dst & SLJIT_MEM) - PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1)); - return put_label; +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 srcdst, sljit_sw srcdstw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_s32 alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type); + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw)); + + ADJUST_LOCAL_OFFSET(srcdst, srcdstw); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 4) + freg = simd_get_quad_reg_index(freg); + + if (!(srcdst & SLJIT_MEM)) { + if (reg_size == 4) + srcdst = simd_get_quad_reg_index(srcdst); + + if (type & SLJIT_SIMD_STORE) + ins = VD(srcdst) | VN(freg) | VM(freg); + else + ins = VD(freg) | VN(srcdst) | VM(srcdst); + + if (reg_size == 4) + ins |= (sljit_ins)1 << 6; + + return push_inst(compiler, VORR | ins); + } + + FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw)); + + if (elem_size > 3) + elem_size = 3; + + ins = ((type & SLJIT_SIMD_STORE) ? VST1 : VLD1) | VD(freg) + | (sljit_ins)((reg_size == 3) ? (0x7 << 8) : (0xa << 8)); + + SLJIT_ASSERT(reg_size >= alignment); + + if (alignment == 3) + ins |= 0x10; + else if (alignment >= 3) + ins |= 0x20; + + return push_inst(compiler, ins | RN(srcdst) | ((sljit_ins)elem_size) << 6 | 0xf); +} + +static sljit_ins simd_get_imm(sljit_s32 elem_size, sljit_uw value) +{ + sljit_ins result; + + if (elem_size > 1 && (sljit_u16)value == (value >> 16)) { + elem_size = 1; + value = (sljit_u16)value; + } + + if (elem_size == 1 && (sljit_u8)value == (value >> 8)) { + elem_size = 0; + value = (sljit_u8)value; + } + + switch (elem_size) { + case 0: + SLJIT_ASSERT(value <= 0xff); + result = 0xe00; + break; + case 1: + SLJIT_ASSERT(value <= 0xffff); + result = 0; + + while (1) { + if (value <= 0xff) { + result |= 0x800; + break; + } + + if ((value & 0xff) == 0) { + value >>= 8; + result |= 0xa00; + break; + } + + if (result != 0) + return ~(sljit_ins)0; + + value ^= (sljit_uw)0xffff; + result = (1 << 5); + } + break; + default: + SLJIT_ASSERT(value <= 0xffffffff); + result = 0; + + while (1) { + if (value <= 0xff) { + result |= 0x000; + break; + } + + if ((value & ~(sljit_uw)0xff00) == 0) { + value >>= 8; + result |= 0x200; + break; + } + + if ((value & ~(sljit_uw)0xff0000) == 0) { + value >>= 16; + result |= 0x400; + break; + } + + if ((value & ~(sljit_uw)0xff000000) == 0) { + value >>= 24; + result |= 0x600; + break; + } + + if ((value & (sljit_uw)0xff) == 0xff && (value >> 16) == 0) { + value >>= 8; + result |= 0xc00; + break; + } + + if ((value & (sljit_uw)0xffff) == 0xffff && (value >> 24) == 0) { + value >>= 16; + result |= 0xd00; + break; + } + + if (result != 0) + return ~(sljit_ins)0; + + value = ~value; + result = (1 << 5); + } + break; + } + + return ((sljit_ins)value & 0xf) | (((sljit_ins)value & 0x70) << 12) | (((sljit_ins)value & 0x80) << 17) | result; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins, imm; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw)); + + ADJUST_LOCAL_OFFSET(src, srcw); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 4) + freg = simd_get_quad_reg_index(freg); + + if (src == SLJIT_IMM && srcw == 0) + return push_inst(compiler, VMOV_i | ((reg_size == 4) ? (1 << 6) : 0) | VD(freg)); + + if (SLJIT_UNLIKELY(elem_size == 3)) { + SLJIT_ASSERT(type & SLJIT_SIMD_FLOAT); + + if (src & SLJIT_MEM) { + FAIL_IF(emit_fop_mem(compiler, FPU_LOAD | SLJIT_32, freg, src, srcw)); + src = freg; + } else if (freg != src) + FAIL_IF(push_inst(compiler, VORR | VD(freg) | VN(src) | VM(src))); + + freg += SLJIT_QUAD_OTHER_HALF(freg); + + if (freg != src) + return push_inst(compiler, VORR | VD(freg) | VN(src) | VM(src)); + return SLJIT_SUCCESS; + } + + if (src & SLJIT_MEM) { + FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw)); + + ins = (sljit_ins)(elem_size << 6); + + if (reg_size == 4) + ins |= (sljit_ins)1 << 5; + + return push_inst(compiler, VLD1_r | ins | VD(freg) | RN(src) | 0xf); + } + + if (type & SLJIT_SIMD_FLOAT) { + SLJIT_ASSERT(elem_size == 2); + ins = ((sljit_ins)freg_ebit_map[src] << (16 + 2 + 1)) | ((sljit_ins)1 << (16 + 2)); + + if (reg_size == 4) + ins |= (sljit_ins)1 << 6; + + return push_inst(compiler, VDUP_s | ins | VD(freg) | (sljit_ins)freg_map[src]); + } + + if (src == SLJIT_IMM) { + if (elem_size < 2) + srcw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1; + + imm = simd_get_imm(elem_size, (sljit_uw)srcw); + + if (imm != ~(sljit_ins)0) { + if (reg_size == 4) + imm |= (sljit_ins)1 << 6; + + return push_inst(compiler, VMOV_i | imm | VD(freg)); + } + + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw)); + src = TMP_REG1; + } + + switch (elem_size) { + case 0: + ins = 1 << 22; + break; + case 1: + ins = 1 << 5; + break; + default: + ins = 0; + break; + } + + if (reg_size == 4) + ins |= (sljit_ins)1 << 21; + + return push_inst(compiler, VDUP | ins | VN(freg) | RD(src)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, sljit_s32 lane_index, + sljit_s32 srcdst, sljit_sw srcdstw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw)); + + ADJUST_LOCAL_OFFSET(srcdst, srcdstw); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 4) + freg = simd_get_quad_reg_index(freg); + + if (type & SLJIT_SIMD_LANE_ZERO) { + ins = (reg_size == 3) ? 0 : ((sljit_ins)1 << 6); + + if (type & SLJIT_SIMD_FLOAT) { + if (elem_size == 3 && !(srcdst & SLJIT_MEM)) { + if (lane_index == 1) + freg += SLJIT_QUAD_OTHER_HALF(freg); + + if (srcdst != freg) + FAIL_IF(push_inst(compiler, VORR | VD(freg) | VN(srcdst) | VM(srcdst))); + + freg += SLJIT_QUAD_OTHER_HALF(freg); + return push_inst(compiler, VMOV_i | VD(freg)); + } + + if (srcdst == freg || (elem_size == 3 && srcdst == (freg + SLJIT_QUAD_OTHER_HALF(freg)))) { + FAIL_IF(push_inst(compiler, VORR | ins | VD(TMP_FREG2) | VN(freg) | VM(freg))); + srcdst = TMP_FREG2; + srcdstw = 0; + } + } + + FAIL_IF(push_inst(compiler, VMOV_i | ins | VD(freg))); + } + + if (reg_size == 4 && lane_index >= (0x8 >> elem_size)) { + lane_index -= (0x8 >> elem_size); + freg += SLJIT_QUAD_OTHER_HALF(freg); + } + + if (srcdst & SLJIT_MEM) { + if (elem_size == 3) + return emit_fop_mem(compiler, ((type & SLJIT_SIMD_STORE) ? 0 : FPU_LOAD) | SLJIT_32, freg, srcdst, srcdstw); + + FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw)); + + lane_index = lane_index << elem_size; + ins = (sljit_ins)((elem_size << 10) | (lane_index << 5)); + return push_inst(compiler, ((type & SLJIT_SIMD_STORE) ? VST1_s : VLD1_s) | ins | VD(freg) | RN(srcdst) | 0xf); + } + + if (type & SLJIT_SIMD_FLOAT) { + if (elem_size == 3) { + if (type & SLJIT_SIMD_STORE) + return push_inst(compiler, VORR | VD(srcdst) | VN(freg) | VM(freg)); + return push_inst(compiler, VMOV_F32 | SLJIT_32 | VD(freg) | VM(srcdst)); + } + + if (type & SLJIT_SIMD_STORE) { + if (freg_ebit_map[freg] == 0) { + if (lane_index == 1) + freg = SLJIT_F64_SECOND(freg); + + return push_inst(compiler, VMOV_F32 | VD(srcdst) | VM(freg)); + } + + FAIL_IF(push_inst(compiler, VMOV_s | (1 << 20) | ((sljit_ins)lane_index << 21) | VN(freg) | RD(TMP_REG1))); + return push_inst(compiler, VMOV | VN(srcdst) | RD(TMP_REG1)); + } + + FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(srcdst) | RD(TMP_REG1))); + return push_inst(compiler, VMOV_s | ((sljit_ins)lane_index << 21) | VN(freg) | RD(TMP_REG1)); + } + + if (srcdst == SLJIT_IMM) { + if (elem_size < 2) + srcdstw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1; + + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcdstw)); + srcdst = TMP_REG1; + } + + if (elem_size == 0) + ins = 0x400000; + else if (elem_size == 1) + ins = 0x20; + else + ins = 0; + + lane_index = lane_index << elem_size; + ins |= (sljit_ins)(((lane_index & 0x4) << 19) | ((lane_index & 0x3) << 5)); + + if (type & SLJIT_SIMD_STORE) { + ins |= (1 << 20); + + if (elem_size < 2 && !(type & SLJIT_SIMD_LANE_SIGNED)) + ins |= (1 << 23); + } + + return push_inst(compiler, VMOV_s | ins | VN(freg) | RD(srcdst)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_s32 src_lane_index) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index)); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 4) { + freg = simd_get_quad_reg_index(freg); + src = simd_get_quad_reg_index(src); + + if (src_lane_index >= (0x8 >> elem_size)) { + src_lane_index -= (0x8 >> elem_size); + src += SLJIT_QUAD_OTHER_HALF(src); + } + } + + if (elem_size == 3) { + if (freg != src) + FAIL_IF(push_inst(compiler, VORR | VD(freg) | VN(src) | VM(src))); + + freg += SLJIT_QUAD_OTHER_HALF(freg); + + if (freg != src) + return push_inst(compiler, VORR | VD(freg) | VN(src) | VM(src)); + return SLJIT_SUCCESS; + } + + ins = ((((sljit_ins)src_lane_index << 1) | 1) << (16 + elem_size)); + + if (reg_size == 4) + ins |= (sljit_ins)1 << 6; + + return push_inst(compiler, VDUP_s | ins | VD(freg) | VM(src)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type); + sljit_s32 dst_reg; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw)); + + ADJUST_LOCAL_OFFSET(src, srcw); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size != 2 || elem2_size != 3)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 4) + freg = simd_get_quad_reg_index(freg); + + if (src & SLJIT_MEM) { + FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw)); + if (reg_size == 4 && elem2_size - elem_size == 1) + FAIL_IF(push_inst(compiler, VLD1 | (0x7 << 8) | VD(freg) | RN(src) | 0xf)); + else + FAIL_IF(push_inst(compiler, VLD1_s | (sljit_ins)((reg_size - elem2_size + elem_size) << 10) | VD(freg) | RN(src) | 0xf)); + src = freg; + } else if (reg_size == 4) + src = simd_get_quad_reg_index(src); + + if (!(type & SLJIT_SIMD_FLOAT)) { + dst_reg = (reg_size == 4) ? freg : TMP_FREG2; + + do { + FAIL_IF(push_inst(compiler, VSHLL | ((type & SLJIT_SIMD_EXTEND_SIGNED) ? 0 : (1 << 24)) + | ((sljit_ins)1 << (19 + elem_size)) | VD(dst_reg) | VM(src))); + src = dst_reg; + } while (++elem_size < elem2_size); + + if (dst_reg == TMP_FREG2) + return push_inst(compiler, VORR | VD(freg) | VN(TMP_FREG2) | VM(TMP_FREG2)); + return SLJIT_SUCCESS; + } + + /* No SIMD variant, must use VFP instead. */ + SLJIT_ASSERT(reg_size == 4); + + if (freg == src) { + freg += SLJIT_QUAD_OTHER_HALF(freg); + FAIL_IF(push_inst(compiler, VCVT_F64_F32 | VD(freg) | VM(src) | 0x20)); + freg += SLJIT_QUAD_OTHER_HALF(freg); + return push_inst(compiler, VCVT_F64_F32 | VD(freg) | VM(src)); + } + + FAIL_IF(push_inst(compiler, VCVT_F64_F32 | VD(freg) | VM(src))); + freg += SLJIT_QUAD_OTHER_HALF(freg); + return push_inst(compiler, VCVT_F64_F32 | VD(freg) | VM(src) | 0x20); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 dst, sljit_sw dstw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins, imms; + sljit_s32 dst_r; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw)); + + ADJUST_LOCAL_OFFSET(dst, dstw); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + switch (elem_size) { + case 0: + imms = 0x243219; + ins = VSHR | (1 << 24) | (0x9 << 16); + break; + case 1: + imms = (reg_size == 4) ? 0x243219 : 0x2231; + ins = VSHR | (1 << 24) | (0x11 << 16); + break; + case 2: + imms = (reg_size == 4) ? 0x2231 : 0x21; + ins = VSHR | (1 << 24) | (0x21 << 16); + break; + default: + imms = 0x21; + ins = VSHR | (1 << 24) | (0x1 << 16) | (1 << 7); + break; + } + + if (reg_size == 4) { + freg = simd_get_quad_reg_index(freg); + ins |= (sljit_ins)1 << 6; + } + + SLJIT_ASSERT((freg_map[TMP_FREG2] & 0x1) == 0); + FAIL_IF(push_inst(compiler, ins | VD(TMP_FREG2) | VM(freg))); + + if (reg_size == 4 && elem_size > 0) + FAIL_IF(push_inst(compiler, VMOVN | ((sljit_ins)(elem_size - 1) << 18) | VD(TMP_FREG2) | VM(TMP_FREG2))); + + ins = (reg_size == 4 && elem_size == 0) ? (1 << 6) : 0; + + while (imms >= 0x100) { + FAIL_IF(push_inst(compiler, VSRA | (1 << 24) | ins | ((imms & 0xff) << 16) | VD(TMP_FREG2) | VM(TMP_FREG2))); + imms >>= 8; + } + + FAIL_IF(push_inst(compiler, VSRA | (1 << 24) | ins | (1 << 7) | (imms << 16) | VD(TMP_FREG2) | VM(TMP_FREG2))); + + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; + FAIL_IF(push_inst(compiler, VMOV_s | (1 << 20) | (1 << 23) | (0x2 << 21) | RD(dst_r) | VN(TMP_FREG2))); + + if (reg_size == 4 && elem_size == 0) { + SLJIT_ASSERT(freg_map[TMP_FREG2] + 1 == freg_map[TMP_FREG1]); + FAIL_IF(push_inst(compiler, VMOV_s | (1 << 20) | (1 << 23) | (0x2 << 21) | RD(TMP_REG2) | VN(TMP_FREG1))); + FAIL_IF(push_inst(compiler, ORR | RD(dst_r) | RN(dst_r) | RM(TMP_REG2) | (0x8 << 7))); + } + + if (dst_r == TMP_REG1) + return emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg)); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + switch (SLJIT_SIMD_GET_OPCODE(type)) { + case SLJIT_SIMD_OP2_AND: + ins = VAND; + break; + case SLJIT_SIMD_OP2_OR: + ins = VORR; + break; + case SLJIT_SIMD_OP2_XOR: + ins = VEOR; + break; + } + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 4) { + dst_freg = simd_get_quad_reg_index(dst_freg); + src1_freg = simd_get_quad_reg_index(src1_freg); + src2_freg = simd_get_quad_reg_index(src2_freg); + ins |= (sljit_ins)1 << 6; + } + + return push_inst(compiler, ins | VD(dst_freg) | VN(src1_freg) | VM(src2_freg)); +} + +#undef FPU_LOAD + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 mem_reg) +{ + sljit_u32 ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); + + switch (GET_OPCODE(op)) { + case SLJIT_MOV_U8: + ins = LDREXB; + break; + case SLJIT_MOV_U16: + ins = LDREXH; + break; + default: + ins = LDREX; + break; + } + + return push_inst(compiler, ins | RN(mem_reg) | RD(dst_reg)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_reg, + sljit_s32 mem_reg, + sljit_s32 temp_reg) +{ + sljit_u32 ins; + + /* temp_reg == mem_reg is undefined so use another temp register */ + SLJIT_UNUSED_ARG(temp_reg); + + CHECK_ERROR(); + CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg)); + + switch (GET_OPCODE(op)) { + case SLJIT_MOV_U8: + ins = STREXB; + break; + case SLJIT_MOV_U16: + ins = STREXH; + break; + default: + ins = STREX; + break; + } + + FAIL_IF(push_inst(compiler, ins | RN(mem_reg) | RD(TMP_REG1) | RM(src_reg))); + if (op & SLJIT_SET_ATOMIC_STORED) + return push_inst(compiler, CMP | SET_FLAGS | SRC2_IMM | RN(TMP_REG1)); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) +{ + struct sljit_const *const_; + sljit_s32 dst_r; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); + PTR_FAIL_IF(!const_); + set_const(const_, compiler); + + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + PTR_FAIL_IF(push_inst_with_unique_literal(compiler, + EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), (sljit_ins)init_value)); + compiler->patches++; +#else /* !SLJIT_CONFIG_ARM_V6 */ + PTR_FAIL_IF(emit_imm(compiler, dst_r, init_value)); +#endif /* SLJIT_CONFIG_ARM_V6 */ + + if (dst & SLJIT_MEM) + PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1)); + return const_; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +{ + struct sljit_jump *jump; + sljit_s32 dst_r; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), 0)); + compiler->patches++; +#else /* !SLJIT_CONFIG_ARM_V6 */ + PTR_FAIL_IF(push_inst(compiler, RD(dst_r))); +#endif /* SLJIT_CONFIG_ARM_V6 */ + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_mov_addr(jump, compiler, 1); + +#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) + compiler->size += 1; +#endif /* SLJIT_CONFIG_ARM_V7 */ + + if (dst & SLJIT_MEM) + PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1)); + return jump; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { - inline_set_jump_addr(addr, executable_offset, new_target, 1); + set_jump_addr(addr, executable_offset, new_target, 1); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) { - inline_set_const(addr, executable_offset, (sljit_uw)new_constant, 1); + set_const_value(addr, executable_offset, (sljit_uw)new_constant, 1); } diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_64.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_64.c index c3215742f4d..50e4c14dd32 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_64.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_64.c @@ -67,81 +67,125 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { /* Instrucion forms */ /* --------------------------------------------------------------------- */ -#define ADC 0x9a000000 -#define ADD 0x8b000000 -#define ADDE 0x8b200000 -#define ADDI 0x91000000 -#define AND 0x8a000000 -#define ANDI 0x92000000 -#define ASRV 0x9ac02800 -#define B 0x14000000 -#define B_CC 0x54000000 -#define BL 0x94000000 -#define BLR 0xd63f0000 -#define BR 0xd61f0000 -#define BRK 0xd4200000 -#define CBZ 0xb4000000 -#define CLZ 0xdac01000 -#define CSEL 0x9a800000 -#define CSINC 0x9a800400 -#define EOR 0xca000000 -#define EORI 0xd2000000 -#define EXTR 0x93c00000 -#define FABS 0x1e60c000 -#define FADD 0x1e602800 -#define FCMP 0x1e602000 -#define FCVT 0x1e224000 -#define FCVTZS 0x9e780000 -#define FDIV 0x1e601800 -#define FMOV 0x1e604000 -#define FMOV_R 0x9e660000 -#define FMUL 0x1e600800 -#define FNEG 0x1e614000 -#define FSUB 0x1e603800 -#define LDRI 0xf9400000 -#define LDRI_F64 0xfd400000 -#define LDRI_POST 0xf8400400 -#define LDP 0xa9400000 -#define LDP_F64 0x6d400000 -#define LDP_POST 0xa8c00000 -#define LDR_PRE 0xf8400c00 -#define LSLV 0x9ac02000 -#define LSRV 0x9ac02400 -#define MADD 0x9b000000 -#define MOVK 0xf2800000 -#define MOVN 0x92800000 -#define MOVZ 0xd2800000 -#define NOP 0xd503201f -#define ORN 0xaa200000 -#define ORR 0xaa000000 -#define ORRI 0xb2000000 -#define RBIT 0xdac00000 -#define RET 0xd65f0000 -#define REV 0xdac00c00 -#define RORV 0x9ac02c00 -#define SBC 0xda000000 -#define SBFM 0x93000000 -#define SCVTF 0x9e620000 -#define SDIV 0x9ac00c00 -#define SMADDL 0x9b200000 -#define SMULH 0x9b403c00 -#define STP 0xa9000000 -#define STP_F64 0x6d000000 -#define STP_PRE 0xa9800000 -#define STRB 0x38206800 -#define STRBI 0x39000000 -#define STRI 0xf9000000 -#define STRI_F64 0xfd000000 -#define STR_FI 0x3d000000 -#define STR_FR 0x3c206800 -#define STUR_FI 0x3c000000 -#define STURBI 0x38000000 -#define SUB 0xcb000000 -#define SUBI 0xd1000000 -#define SUBS 0xeb000000 -#define UBFM 0xd3000000 -#define UDIV 0x9ac00800 -#define UMULH 0x9bc03c00 +#define ADC 0x9a000000 +#define ADD 0x8b000000 +#define ADDE 0x8b200000 +#define ADDI 0x91000000 +#define ADR 0x10000000 +#define ADRP 0x90000000 +#define AND 0x8a000000 +#define ANDI 0x92000000 +#define AND_v 0x0e201c00 +#define ASRV 0x9ac02800 +#define B 0x14000000 +#define B_CC 0x54000000 +#define BL 0x94000000 +#define BLR 0xd63f0000 +#define BR 0xd61f0000 +#define BRK 0xd4200000 +#define CAS 0xc8a07c00 +#define CASB 0x08a07c00 +#define CASH 0x48a07c00 +#define CBZ 0xb4000000 +#define CCMPI 0xfa400800 +#define CLZ 0xdac01000 +#define CSEL 0x9a800000 +#define CSINC 0x9a800400 +#define DUP_e 0x0e000400 +#define DUP_g 0x0e000c00 +#define EOR 0xca000000 +#define EOR_v 0x2e201c00 +#define EORI 0xd2000000 +#define EXTR 0x93c00000 +#define FABS 0x1e60c000 +#define FADD 0x1e602800 +#define FCMP 0x1e602000 +#define FCSEL 0x1e600c00 +#define FCVT 0x1e224000 +#define FCVTL 0x0e217800 +#define FCVTZS 0x9e780000 +#define FDIV 0x1e601800 +#define FMOV 0x1e604000 +#define FMOV_R 0x9e660000 +#define FMOV_I 0x1e601000 +#define FMUL 0x1e600800 +#define FNEG 0x1e614000 +#define FSUB 0x1e603800 +#define INS 0x4e001c00 +#define INS_e 0x6e000400 +#define LD1 0x0c407000 +#define LD1_s 0x0d400000 +#define LD1R 0x0d40c000 +#define LDRI 0xf9400000 +#define LDRI_F64 0xfd400000 +#define LDRI_POST 0xf8400400 +#define LDP 0xa9400000 +#define LDP_F64 0x6d400000 +#define LDP_POST 0xa8c00000 +#define LDR_PRE 0xf8400c00 +#define LDXR 0xc85f7c00 +#define LDXRB 0x085f7c00 +#define LDXRH 0x485f7c00 +#define LSLV 0x9ac02000 +#define LSRV 0x9ac02400 +#define MADD 0x9b000000 +#define MOVI 0x0f000400 +#define MOVK 0xf2800000 +#define MOVN 0x92800000 +#define MOVZ 0xd2800000 +#define NOP 0xd503201f +#define ORN 0xaa200000 +#define ORR 0xaa000000 +#define ORR_v 0x0ea01c00 +#define ORRI 0xb2000000 +#define RBIT 0xdac00000 +#define RET 0xd65f0000 +#define REV 0xdac00c00 +#define REV16 0xdac00400 +#define RORV 0x9ac02c00 +#define SBC 0xda000000 +#define SBFM 0x93400000 +#define SCVTF 0x9e620000 +#define SDIV 0x9ac00c00 +#define SMADDL 0x9b200000 +#define SMOV 0x0e002c00 +#define SMULH 0x9b403c00 +#define SSHLL 0x0f00a400 +#define ST1 0x0c007000 +#define ST1_s 0x0d000000 +#define STP 0xa9000000 +#define STP_F64 0x6d000000 +#define STP_PRE 0xa9800000 +#define STRB 0x38206800 +#define STRBI 0x39000000 +#define STRI 0xf9000000 +#define STRI_F64 0xfd000000 +#define STR_FI 0x3d000000 +#define STR_FR 0x3c206800 +#define STUR_FI 0x3c000000 +#define STURBI 0x38000000 +#define STXR 0xc8007c00 +#define STXRB 0x8007c00 +#define STXRH 0x48007c00 +#define SUB 0xcb000000 +#define SUBI 0xd1000000 +#define SUBS 0xeb000000 +#define TBZ 0x36000000 +#define UBFM 0xd3400000 +#define UCVTF 0x9e630000 +#define UDIV 0x9ac00800 +#define UMOV 0x0e003c00 +#define UMULH 0x9bc03c00 +#define USHLL 0x2f00a400 +#define USHR 0x2f000400 +#define USRA 0x2f001400 +#define XTN 0x0e212800 + +#define CSET (CSINC | RM(TMP_ZERO) | RN(TMP_ZERO)) +#define LDR (STRI | (1 << 22)) +#define LDRB (STRBI | (1 << 22)) +#define LDRH (LDRB | (1 << 30)) +#define MOV (ORR | RN(TMP_ZERO)) static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins) { @@ -160,74 +204,260 @@ static SLJIT_INLINE sljit_s32 emit_imm64_const(struct sljit_compiler *compiler, return push_inst(compiler, MOVK | RD(dst) | ((sljit_ins)(imm >> 48) << 5) | (3 << 21)); } -static SLJIT_INLINE sljit_sw detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) +static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) { sljit_sw diff; sljit_uw target_addr; - if (jump->flags & SLJIT_REWRITABLE_JUMP) { - jump->flags |= PATCH_ABS64; - return 0; - } + if (jump->flags & SLJIT_REWRITABLE_JUMP) + goto exit; if (jump->flags & JUMP_ADDR) target_addr = jump->u.target; else { - SLJIT_ASSERT(jump->flags & JUMP_LABEL); + SLJIT_ASSERT(jump->u.label != NULL); target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset; } - diff = (sljit_sw)target_addr - (sljit_sw)(code_ptr + 4) - executable_offset; + diff = (sljit_sw)target_addr - (sljit_sw)code_ptr - executable_offset; if (jump->flags & IS_COND) { diff += SSIZE_OF(ins); if (diff <= 0xfffff && diff >= -0x100000) { - code_ptr[-5] ^= (jump->flags & IS_CBZ) ? (0x1 << 24) : 0x1; - jump->addr -= sizeof(sljit_ins); + *(--code_ptr) ^= (jump->flags & IS_CBZ) ? (0x1 << 24) : 0x1; jump->flags |= PATCH_COND; - return 5; + jump->addr -= sizeof(sljit_ins); + return code_ptr; } diff -= SSIZE_OF(ins); } if (diff <= 0x7ffffff && diff >= -0x8000000) { + if (jump->flags & IS_COND) + code_ptr[-1] -= (4 << 5); jump->flags |= PATCH_B; - return 4; + return code_ptr; } if (target_addr < 0x100000000l) { if (jump->flags & IS_COND) - code_ptr[-5] -= (2 << 5); - code_ptr[-2] = code_ptr[0]; - return 2; + code_ptr[-1] -= (2 << 5); + code_ptr[2] = code_ptr[0]; + return code_ptr + 2; + } + + if (diff <= 0xfffff000l && diff >= -0x100000000l) { + if (jump->flags & IS_COND) + code_ptr[-1] -= (2 << 5); + jump->flags |= PATCH_B32; + code_ptr[2] = code_ptr[0]; + return code_ptr + 2; } if (target_addr < 0x1000000000000l) { if (jump->flags & IS_COND) - code_ptr[-5] -= (1 << 5); + code_ptr[-1] -= (1 << 5); jump->flags |= PATCH_ABS48; - code_ptr[-1] = code_ptr[0]; - return 1; + code_ptr[3] = code_ptr[0]; + return code_ptr + 3; } +exit: jump->flags |= PATCH_ABS64; - return 0; + code_ptr[4] = code_ptr[0]; + return code_ptr + 4; } -static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label) +static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) { - if (max_label < 0x100000000l) { - put_label->flags = 0; - return 2; + sljit_uw addr; + sljit_sw diff; + SLJIT_UNUSED_ARG(executable_offset); + + SLJIT_ASSERT(jump->flags < ((sljit_uw)4 << JUMP_SIZE_SHIFT)); + if (jump->flags & JUMP_ADDR) + addr = jump->u.target; + else + addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset); + + diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + + if (diff <= 0xfffff && diff >= -0x100000) { + jump->flags |= PATCH_B; + return 0; } - if (max_label < 0x1000000000000l) { - put_label->flags = 1; + if (diff <= 0xfffff000l && diff >= -0x100000000l) { + SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT)); + jump->flags |= PATCH_B32; return 1; } - put_label->flags = 2; - return 0; + if (addr < 0x100000000l) { + SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT)); + return 1; + } + + if (addr < 0x1000000000000l) { + SLJIT_ASSERT(jump->flags >= ((sljit_uw)2 << JUMP_SIZE_SHIFT)); + jump->flags |= PATCH_ABS48; + return 2; + } + + SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT)); + jump->flags |= PATCH_ABS64; + return 3; +} + +static SLJIT_INLINE void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executable_offset) +{ + sljit_sw addr = (sljit_sw)((jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr); + sljit_ins* buf_ptr = (sljit_ins*)jump->addr; + sljit_u32 dst; + SLJIT_UNUSED_ARG(executable_offset); + + if (!(jump->flags & JUMP_MOV_ADDR)) { + if (jump->flags & PATCH_COND) { + addr = (addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2; + SLJIT_ASSERT(addr <= 0x3ffff && addr >= -0x40000); + buf_ptr[0] = (buf_ptr[0] & ~(sljit_ins)0xffffe0) | (sljit_ins)((addr & 0x7ffff) << 5); + return; + } + + if (jump->flags & PATCH_B) { + addr = (addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2; + SLJIT_ASSERT(addr <= 0x1ffffff && addr >= -0x2000000); + buf_ptr[0] = ((jump->flags & IS_BL) ? BL : B) | (sljit_ins)(addr & 0x3ffffff); + return; + } + + dst = (buf_ptr[0] >> 5) & 0x1f; + + if (jump->flags & PATCH_B32) { + addr -= (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) & ~(sljit_sw)0xfff; + SLJIT_ASSERT(addr <= 0xfffff000l && addr >= -0x100000000l); + buf_ptr[0] = ADRP | (((sljit_ins)(addr >> 12) & 0x3) << 29) | (((sljit_ins)(addr >> 14) & 0x7ffff) << 5) | dst; + buf_ptr[1] = ADDI | dst | (dst << 5) | ((sljit_ins)(addr & 0xfff) << 10); + return; + } + } else { + dst = *buf_ptr; + + if (jump->flags & PATCH_B) { + addr -= (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset); + SLJIT_ASSERT(addr <= 0xfffff && addr >= -0x100000); + buf_ptr[0] = ADR | (((sljit_ins)addr & 0x3) << 29) | (((sljit_ins)(addr >> 2) & 0x7ffff) << 5) | dst; + return; + } + + if (jump->flags & PATCH_B32) { + addr -= ((sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) & ~(sljit_sw)0xfff; + SLJIT_ASSERT(addr <= 0xffffffffl && addr >= -0x100000000l); + buf_ptr[0] = ADRP | (((sljit_ins)(addr >> 12) & 0x3) << 29) | (((sljit_ins)(addr >> 14) & 0x7ffff) << 5) | dst; + buf_ptr[1] = ADDI | dst | (dst << 5) | ((sljit_ins)(addr & 0xfff) << 10); + return; + } + } + + SLJIT_ASSERT((jump->flags & (PATCH_ABS48 | PATCH_ABS64)) || (sljit_uw)addr <= (sljit_uw)0xffffffff); + SLJIT_ASSERT((jump->flags & PATCH_ABS64) || (sljit_uw)addr <= (sljit_uw)0xffffffffffff); + + buf_ptr[0] = MOVZ | (((sljit_ins)addr & 0xffff) << 5) | dst; + buf_ptr[1] = MOVK | (((sljit_ins)(addr >> 16) & 0xffff) << 5) | (1 << 21) | dst; + if (jump->flags & (PATCH_ABS48 | PATCH_ABS64)) + buf_ptr[2] = MOVK | (((sljit_ins)(addr >> 32) & 0xffff) << 5) | (2 << 21) | dst; + + if (jump->flags & PATCH_ABS64) + buf_ptr[3] = MOVK | ((sljit_ins)((sljit_uw)addr >> 48) << 5) | (3 << 21) | dst; +} + +static void reduce_code_size(struct sljit_compiler *compiler) +{ + struct sljit_label *label; + struct sljit_jump *jump; + struct sljit_const *const_; + SLJIT_NEXT_DEFINE_TYPES; + sljit_uw total_size; + sljit_uw size_reduce = 0; + sljit_sw diff; + + label = compiler->labels; + jump = compiler->jumps; + const_ = compiler->consts; + SLJIT_NEXT_INIT_TYPES(); + + while (1) { + SLJIT_GET_NEXT_MIN(); + + if (next_min_addr == SLJIT_MAX_ADDRESS) + break; + + if (next_min_addr == next_label_size) { + label->size -= size_reduce; + + label = label->next; + next_label_size = SLJIT_GET_NEXT_SIZE(label); + } + + if (next_min_addr == next_const_addr) { + const_->addr -= size_reduce; + const_ = const_->next; + next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_); + continue; + } + + if (next_min_addr != next_jump_addr) + continue; + + jump->addr -= size_reduce; + if (!(jump->flags & JUMP_MOV_ADDR)) { + total_size = JUMP_MAX_SIZE; + + if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) { + if (jump->flags & JUMP_ADDR) { + if (jump->u.target < 0x100000000l) + total_size = 3; + else if (jump->u.target < 0x1000000000000l) + total_size = 4; + } else { + /* Unit size: instruction. */ + diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; + + if ((jump->flags & IS_COND) && (diff + 1) <= (0xfffff / SSIZE_OF(ins)) && (diff + 1) >= (-0x100000 / SSIZE_OF(ins))) + total_size = 0; + else if (diff <= (0x7ffffff / SSIZE_OF(ins)) && diff >= (-0x8000000 / SSIZE_OF(ins))) + total_size = 1; + else if (diff <= (0xfffff000l / SSIZE_OF(ins)) && diff >= (-0x100000000l / SSIZE_OF(ins))) + total_size = 3; + } + } + + size_reduce += JUMP_MAX_SIZE - total_size; + } else { + /* Real size minus 1. Unit size: instruction. */ + total_size = 3; + + if (!(jump->flags & JUMP_ADDR)) { + diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; + + if (diff <= (0xfffff / SSIZE_OF(ins)) && diff >= (-0x100000 / SSIZE_OF(ins))) + total_size = 0; + else if (diff <= (0xfffff000l / SSIZE_OF(ins)) && diff >= (-0x100000000l / SSIZE_OF(ins))) + total_size = 1; + } else if (jump->u.target < 0x100000000l) + total_size = 1; + else if (jump->u.target < 0x1000000000000l) + total_size = 2; + + size_reduce += 3 - total_size; + } + + jump->flags |= total_size << JUMP_SIZE_SHIFT; + jump = jump->next; + next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); + } + + compiler->size -= size_reduce; } SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) @@ -238,67 +468,75 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil sljit_ins *buf_ptr; sljit_ins *buf_end; sljit_uw word_count; - sljit_uw next_addr; + SLJIT_NEXT_DEFINE_TYPES; sljit_sw executable_offset; sljit_sw addr; - sljit_u32 dst; struct sljit_label *label; struct sljit_jump *jump; struct sljit_const *const_; - struct sljit_put_label *put_label; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_generate_code(compiler)); - reverse_buf(compiler); + + reduce_code_size(compiler); code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data); PTR_FAIL_WITH_EXEC_IF(code); + + reverse_buf(compiler); buf = compiler->buf; code_ptr = code; word_count = 0; - next_addr = 0; executable_offset = SLJIT_EXEC_OFFSET(code); label = compiler->labels; jump = compiler->jumps; const_ = compiler->consts; - put_label = compiler->put_labels; + SLJIT_NEXT_INIT_TYPES(); + SLJIT_GET_NEXT_MIN(); do { buf_ptr = (sljit_ins*)buf->memory; buf_end = buf_ptr + (buf->used_size >> 2); do { *code_ptr = *buf_ptr++; - if (next_addr == word_count) { + if (next_min_addr == word_count) { SLJIT_ASSERT(!label || label->size >= word_count); SLJIT_ASSERT(!jump || jump->addr >= word_count); SLJIT_ASSERT(!const_ || const_->addr >= word_count); - SLJIT_ASSERT(!put_label || put_label->addr >= word_count); /* These structures are ordered by their address. */ - if (label && label->size == word_count) { - label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + if (next_min_addr == next_label_size) { + label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); label->size = (sljit_uw)(code_ptr - code); label = label->next; + next_label_size = SLJIT_GET_NEXT_SIZE(label); } - if (jump && jump->addr == word_count) { - jump->addr = (sljit_uw)(code_ptr - 4); - code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset); - jump = jump->next; - } - if (const_ && const_->addr == word_count) { + + if (next_min_addr == next_jump_addr) { + if (!(jump->flags & JUMP_MOV_ADDR)) { + word_count = word_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT); + jump->addr = (sljit_uw)code_ptr; + code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset); + SLJIT_ASSERT((jump->flags & PATCH_COND) || ((sljit_uw)code_ptr - jump->addr < (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins))); + } else { + word_count += jump->flags >> JUMP_SIZE_SHIFT; + addr = (sljit_sw)code_ptr; + code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset); + jump->addr = (sljit_uw)addr; + } + + jump = jump->next; + next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); + } else if (next_min_addr == next_const_addr) { const_->addr = (sljit_uw)code_ptr; const_ = const_->next; + next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_); } - if (put_label && put_label->addr == word_count) { - SLJIT_ASSERT(put_label->label); - put_label->addr = (sljit_uw)(code_ptr - 3); - code_ptr -= put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size)); - put_label = put_label->next; - } - next_addr = compute_next_addr(label, jump, const_, put_label); + + SLJIT_GET_NEXT_MIN(); } code_ptr++; word_count++; @@ -308,7 +546,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil } while (buf); if (label && label->size == word_count) { - label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); label->size = (sljit_uw)(code_ptr - code); label = label->next; } @@ -316,61 +554,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil SLJIT_ASSERT(!label); SLJIT_ASSERT(!jump); SLJIT_ASSERT(!const_); - SLJIT_ASSERT(!put_label); SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size); jump = compiler->jumps; while (jump) { - do { - addr = (sljit_sw)((jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target); - buf_ptr = (sljit_ins *)jump->addr; - - if (jump->flags & PATCH_B) { - addr = (addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2; - SLJIT_ASSERT(addr <= 0x1ffffff && addr >= -0x2000000); - buf_ptr[0] = ((jump->flags & IS_BL) ? BL : B) | (sljit_ins)(addr & 0x3ffffff); - if (jump->flags & IS_COND) - buf_ptr[-1] -= (4 << 5); - break; - } - if (jump->flags & PATCH_COND) { - addr = (addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2; - SLJIT_ASSERT(addr <= 0x3ffff && addr >= -0x40000); - buf_ptr[0] = (buf_ptr[0] & ~(sljit_ins)0xffffe0) | (sljit_ins)((addr & 0x7ffff) << 5); - break; - } - - SLJIT_ASSERT((jump->flags & (PATCH_ABS48 | PATCH_ABS64)) || (sljit_uw)addr <= (sljit_uw)0xffffffff); - SLJIT_ASSERT((jump->flags & PATCH_ABS64) || (sljit_uw)addr <= (sljit_uw)0xffffffffffff); - - dst = buf_ptr[0] & 0x1f; - buf_ptr[0] = MOVZ | dst | (((sljit_ins)addr & 0xffff) << 5); - buf_ptr[1] = MOVK | dst | (((sljit_ins)(addr >> 16) & 0xffff) << 5) | (1 << 21); - if (jump->flags & (PATCH_ABS48 | PATCH_ABS64)) - buf_ptr[2] = MOVK | dst | (((sljit_ins)(addr >> 32) & 0xffff) << 5) | (2 << 21); - if (jump->flags & PATCH_ABS64) - buf_ptr[3] = MOVK | dst | ((sljit_ins)(addr >> 48) << 5) | (3 << 21); - } while (0); + generate_jump_or_mov_addr(jump, executable_offset); jump = jump->next; } - put_label = compiler->put_labels; - while (put_label) { - addr = (sljit_sw)put_label->label->addr; - buf_ptr = (sljit_ins*)put_label->addr; - - buf_ptr[0] |= ((sljit_ins)addr & 0xffff) << 5; - buf_ptr[1] |= ((sljit_ins)(addr >> 16) & 0xffff) << 5; - - if (put_label->flags >= 1) - buf_ptr[2] |= ((sljit_ins)(addr >> 32) & 0xffff) << 5; - - if (put_label->flags >= 2) - buf_ptr[3] |= (sljit_ins)(addr >> 48) << 5; - - put_label = put_label->next; - } - compiler->error = SLJIT_ERR_COMPILED; compiler->executable_offset = executable_offset; compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins); @@ -387,8 +578,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) { switch (feature_type) { case SLJIT_HAS_FPU: + case SLJIT_HAS_SIMD: #ifdef SLJIT_IS_FPU_AVAILABLE - return SLJIT_IS_FPU_AVAILABLE; + return (SLJIT_IS_FPU_AVAILABLE) != 0; #else /* Available by default. */ return 1; @@ -402,6 +594,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) case SLJIT_HAS_PREFETCH: case SLJIT_HAS_COPY_F32: case SLJIT_HAS_COPY_F64: + case SLJIT_HAS_ATOMIC: return 1; default: @@ -409,6 +602,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) } } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) +{ + switch (type) { + case SLJIT_UNORDERED_OR_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: + return 2; + } + + return 0; +} + /* --------------------------------------------------------------------- */ /* Core code generator functions. */ /* --------------------------------------------------------------------- */ @@ -642,6 +846,10 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s case SLJIT_CLZ: case SLJIT_CTZ: case SLJIT_REV: + case SLJIT_REV_U16: + case SLJIT_REV_S16: + case SLJIT_REV_U32: + case SLJIT_REV_S32: case SLJIT_ADDC: case SLJIT_SUBC: /* No form with immediate operand (except imm 0, which @@ -725,6 +933,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s inst_bits = ((sljit_ins)1 << 22) | (((sljit_ins)-imm & 0x3f) << 16) | ((63 - (sljit_ins)imm) << 10); } + inv_bits |= inv_bits >> 9; FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | inst_bits)); goto set_flags; case SLJIT_LSHR: @@ -734,6 +943,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s if (flags & ARG1_IMM) break; + inv_bits |= inv_bits >> 9; if (op >= SLJIT_ASHR) inv_bits |= 1 << 30; @@ -787,22 +997,22 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); if (dst == arg2) return SLJIT_SUCCESS; - return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(arg2)); + return push_inst(compiler, MOV | RD(dst) | RM(arg2)); case SLJIT_MOV_U8: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); - return push_inst(compiler, (UBFM ^ W_OP) | RD(dst) | RN(arg2) | (7 << 10)); + inv_bits |= inv_bits >> 9; + return push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg2) | (7 << 10)); case SLJIT_MOV_S8: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); - if (!(flags & INT_OP)) - inv_bits |= 1 << 22; + inv_bits |= inv_bits >> 9; return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (7 << 10)); case SLJIT_MOV_U16: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); - return push_inst(compiler, (UBFM ^ W_OP) | RD(dst) | RN(arg2) | (15 << 10)); + inv_bits |= inv_bits >> 9; + return push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg2) | (15 << 10)); case SLJIT_MOV_S16: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); - if (!(flags & INT_OP)) - inv_bits |= 1 << 22; + inv_bits |= inv_bits >> 9; return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (15 << 10)); case SLJIT_MOV32: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); @@ -811,7 +1021,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s /* fallthrough */ case SLJIT_MOV_U32: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); - return push_inst(compiler, (ORR ^ W_OP) | RD(dst) | RN(TMP_ZERO) | RM(arg2)); + return push_inst(compiler, (MOV ^ W_OP) | RD(dst) | RM(arg2)); case SLJIT_MOV_S32: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); return push_inst(compiler, SBFM | (1 << 22) | RD(dst) | RN(arg2) | (31 << 10)); @@ -826,6 +1036,21 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s SLJIT_ASSERT(arg1 == TMP_REG1); inv_bits |= inv_bits >> 21; return push_inst(compiler, (REV ^ inv_bits) | RD(dst) | RN(arg2)); + case SLJIT_REV_U16: + case SLJIT_REV_S16: + SLJIT_ASSERT(arg1 == TMP_REG1 && dst != TMP_REG2); + FAIL_IF(push_inst(compiler, (REV16 ^ (sljit_ins)0x80000000) | RD(dst) | RN(arg2))); + if (dst == TMP_REG1 || (arg2 == TMP_REG2 && op == SLJIT_REV_U16)) + return SLJIT_SUCCESS; + inv_bits |= inv_bits >> 9; + return push_inst(compiler, ((op == SLJIT_REV_U16 ? UBFM : SBFM) ^ inv_bits) | RD(dst) | RN(dst) | (15 << 10)); + case SLJIT_REV_U32: + case SLJIT_REV_S32: + SLJIT_ASSERT(arg1 == TMP_REG1 && dst != TMP_REG2); + FAIL_IF(push_inst(compiler, (REV ^ (sljit_ins)0x80000400) | RD(dst) | RN(arg2))); + if (op == SLJIT_REV_U32 || dst == TMP_REG1) + return SLJIT_SUCCESS; + return push_inst(compiler, SBFM | (1 << 22) | RD(dst) | RN(dst) | (31 << 10)); case SLJIT_ADD: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD; CHECK_FLAGS(1 << 29); @@ -955,14 +1180,20 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, s if (argw <= 0xff && argw >= -0x100) return push_inst(compiler, STURBI | type | RT(reg) | RN(arg) | (((sljit_ins)argw & 0x1ff) << 12)); - if (argw >= 0) { - if (argw <= 0xfff0ff && ((argw + 0x100) & 0xfff) <= 0x1ff) { + if (((argw + 0x100) & 0xfff) <= 0x1ff && argw <= 0xfff0ff && argw >= -0xfff100) { + if (argw >= 0) { + if (argw & 0x100) + argw += 0x1000; + FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)argw >> 12) << 10))); return push_inst(compiler, STURBI | type | RT(reg) | RN(tmp_reg) | (((sljit_ins)argw & 0x1ff) << 12)); + } else { + if (!(argw & 0x100)) + argw -= 0x1000; + + FAIL_IF(push_inst(compiler, SUBI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)-argw >> 12) << 10))); + return push_inst(compiler, STURBI | type | RT(reg) | RN(tmp_reg) | (((sljit_ins)argw & 0x1ff) << 12)); } - } else if (argw >= -0xfff100 && ((-argw + 0xff) & 0xfff) <= 0x1ff) { - FAIL_IF(push_inst(compiler, SUBI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)-argw >> 12) << 10))); - return push_inst(compiler, STURBI | type | RT(reg) | RN(tmp_reg) | (((sljit_ins)argw & 0x1ff) << 12)); } FAIL_IF(load_immediate(compiler, tmp_reg, argw)); @@ -1072,7 +1303,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi while (arg_types) { if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) { if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) { - FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0 - saved_arg_count) | RN(TMP_ZERO) | RM(tmp))); + FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S0 - saved_arg_count) | RM(tmp))); saved_arg_count++; } tmp++; @@ -1279,7 +1510,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *c src = TMP_REG1; srcw = 0; } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { - FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(src))); + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src))); src = TMP_REG1; srcw = 0; } @@ -1309,12 +1540,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile return push_inst(compiler, NOP); case SLJIT_LMUL_UW: case SLJIT_LMUL_SW: - FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0))); + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(SLJIT_R0))); FAIL_IF(push_inst(compiler, MADD | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO))); return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULH : SMULH) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1)); case SLJIT_DIVMOD_UW: case SLJIT_DIVMOD_SW: - FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0))); + FAIL_IF(push_inst(compiler, (MOV ^ inv_bits) | RD(TMP_REG1) | RM(SLJIT_R0))); FAIL_IF(push_inst(compiler, ((op == SLJIT_DIVMOD_UW ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1))); FAIL_IF(push_inst(compiler, (MADD ^ inv_bits) | RD(SLJIT_R1) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO))); return push_inst(compiler, (SUB ^ inv_bits) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1)); @@ -1356,33 +1587,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile break; case SLJIT_MOV_U8: mem_flags = BYTE_SIZE; - if (src & SLJIT_IMM) + if (src == SLJIT_IMM) srcw = (sljit_u8)srcw; break; case SLJIT_MOV_S8: mem_flags = BYTE_SIZE | SIGNED; - if (src & SLJIT_IMM) + if (src == SLJIT_IMM) srcw = (sljit_s8)srcw; break; case SLJIT_MOV_U16: mem_flags = HALF_SIZE; - if (src & SLJIT_IMM) + if (src == SLJIT_IMM) srcw = (sljit_u16)srcw; break; case SLJIT_MOV_S16: mem_flags = HALF_SIZE | SIGNED; - if (src & SLJIT_IMM) + if (src == SLJIT_IMM) srcw = (sljit_s16)srcw; break; case SLJIT_MOV_U32: mem_flags = INT_SIZE; - if (src & SLJIT_IMM) + if (src == SLJIT_IMM) srcw = (sljit_u32)srcw; break; case SLJIT_MOV_S32: case SLJIT_MOV32: mem_flags = INT_SIZE | SIGNED; - if (src & SLJIT_IMM) + if (src == SLJIT_IMM) srcw = (sljit_s32)srcw; break; default: @@ -1391,7 +1622,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile break; } - if (src & SLJIT_IMM) + if (src == SLJIT_IMM) FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG1, srcw)); else if (!(src & SLJIT_MEM)) dst_r = src; @@ -1404,11 +1635,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile } flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0; - mem_flags = WORD_SIZE; - if (op_flags & SLJIT_32) { - flags |= INT_OP; + switch (op) { + case SLJIT_REV_U16: + case SLJIT_REV_S16: + mem_flags = HALF_SIZE; + break; + case SLJIT_REV_U32: + case SLJIT_REV_S32: mem_flags = INT_SIZE; + break; + default: + mem_flags = WORD_SIZE; + + if (op_flags & SLJIT_32) { + flags |= INT_OP; + mem_flags = INT_SIZE; + } + break; } if (src & SLJIT_MEM) { @@ -1458,12 +1702,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile src2 = TMP_REG2; } - if (src1 & SLJIT_IMM) + if (src1 == SLJIT_IMM) flags |= ARG1_IMM; else src1w = src1; - if (src2 & SLJIT_IMM) + if (src2 == SLJIT_IMM) flags |= ARG2_IMM; else src2w = src2; @@ -1510,7 +1754,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * inv_bits = (op & SLJIT_32) ? W_OP : 0; - if (src3 & SLJIT_IMM) { + if (src3 == SLJIT_IMM) { mask = inv_bits ? 0x1f : 0x3f; src3w &= mask; @@ -1528,7 +1772,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * FAIL_IF(emit_op_mem(compiler, inv_bits ? INT_SIZE : WORD_SIZE, TMP_REG2, src3, src3w, TMP_REG2)); src3 = TMP_REG2; } else if (dst_reg == src3) { - FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG2) | RN(TMP_ZERO) | RM(src3))); + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src3))); src3 = TMP_REG2; } @@ -1541,7 +1785,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * else imm = (sljit_ins)(inv_bits ? ((31 << 16) | (30 << 10)) : ((63 << 16) | (62 << 10) | (1 << 22))); - FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(TMP_REG1) | RN(src2_reg) | imm)); + FAIL_IF(push_inst(compiler, (UBFM ^ (inv_bits | (inv_bits >> 9))) | RD(TMP_REG1) | RN(src2_reg) | imm)); /* Set imm to mask. */ imm = (sljit_ins)(inv_bits ? (4 << 10) : ((5 << 10) | (1 << 22))); @@ -1565,7 +1809,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp switch (op) { case SLJIT_FAST_RETURN: if (FAST_IS_REG(src)) - FAIL_IF(push_inst(compiler, ORR | RD(TMP_LR) | RN(TMP_ZERO) | RM(src))); + FAIL_IF(push_inst(compiler, MOV | RD(TMP_LR) | RM(src))); else FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw, TMP_REG1)); @@ -1607,7 +1851,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp switch (op) { case SLJIT_FAST_ENTER: if (FAST_IS_REG(dst)) - return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(TMP_LR)); + return push_inst(compiler, MOV | RD(dst) | RM(TMP_LR)); break; case SLJIT_GET_RETURN_ADDRESS: dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; @@ -1621,15 +1865,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg) { - CHECK_REG_INDEX(check_sljit_get_register_index(reg)); - return reg_map[reg]; -} + CHECK_REG_INDEX(check_sljit_get_register_index(type, reg)); + + if (type == SLJIT_GP_REGISTER) + return reg_map[reg]; + + if (type != SLJIT_FLOAT_REGISTER && type != SLJIT_SIMD_REG_64 && type != SLJIT_SIMD_REG_128) + return -1; -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) -{ - CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); return freg_map[reg]; } @@ -1707,7 +1952,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp inv_bits |= W_OP; if (src & SLJIT_MEM) { - emit_fop_mem(compiler, (op & SLJIT_32) ? INT_SIZE : WORD_SIZE, TMP_FREG1, src, srcw); + FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) ? INT_SIZE : WORD_SIZE, TMP_FREG1, src, srcw)); src = TMP_FREG1; } @@ -1718,34 +1963,59 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp return SLJIT_SUCCESS; } -static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, +static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; - sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0; - - if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) - inv_bits |= W_OP; if (src & SLJIT_MEM) { - emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) ? INT_SIZE : WORD_SIZE), TMP_REG1, src, srcw, TMP_REG1); + emit_op_mem(compiler, (ins & W_OP) ? WORD_SIZE : INT_SIZE, TMP_REG1, src, srcw, TMP_REG1); src = TMP_REG1; - } else if (src & SLJIT_IMM) { - if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) - srcw = (sljit_s32)srcw; - + } else if (src == SLJIT_IMM) { FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); src = TMP_REG1; } - FAIL_IF(push_inst(compiler, (SCVTF ^ inv_bits) | VD(dst_r) | RN(src))); + FAIL_IF(push_inst(compiler, ins | VD(dst_r) | RN(src))); if (dst & SLJIT_MEM) - return emit_fop_mem(compiler, ((op & SLJIT_32) ? INT_SIZE : WORD_SIZE) | STORE, TMP_FREG1, dst, dstw); + return emit_fop_mem(compiler, ((ins & (1 << 22)) ? WORD_SIZE : INT_SIZE) | STORE, TMP_FREG1, dst, dstw); return SLJIT_SUCCESS; } +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0; + + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) { + inv_bits |= W_OP; + + if (src == SLJIT_IMM) + srcw = (sljit_s32)srcw; + } + + return sljit_emit_fop1_conv_f64_from_w(compiler, SCVTF ^ inv_bits, dst, dstw, src, srcw); +} + +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0; + + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) { + inv_bits |= W_OP; + + if (src == SLJIT_IMM) + srcw = (sljit_u32)srcw; + } + + return sljit_emit_fop1_conv_f64_from_w(compiler, UCVTF ^ inv_bits, dst, dstw, src, srcw); +} + static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) @@ -1754,16 +2024,22 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0; if (src1 & SLJIT_MEM) { - emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w); + FAIL_IF(emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w)); src1 = TMP_FREG1; } if (src2 & SLJIT_MEM) { - emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w); + FAIL_IF(emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w)); src2 = TMP_FREG2; } - return push_inst(compiler, (FCMP ^ inv_bits) | VN(src1) | VM(src2)); + FAIL_IF(push_inst(compiler, (FCMP ^ inv_bits) | VN(src1) | VM(src2))); + + if (GET_FLAG_TYPE(op) != SLJIT_UNORDERED_OR_EQUAL) + return SLJIT_SUCCESS; + + FAIL_IF(push_inst(compiler, CSINC | (0x0 << 12) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(TMP_ZERO))); + return push_inst(compiler, CCMPI | (0x0 << 16) | (0x7 << 12) | RN(TMP_REG1) | 0x4); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, @@ -1782,7 +2058,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src & SLJIT_MEM) { - emit_fop_mem(compiler, (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) ? (mem_flags ^ 0x1) : mem_flags, dst_r, src, srcw); + FAIL_IF(emit_fop_mem(compiler, (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) ? (mem_flags ^ 0x1) : mem_flags, dst_r, src, srcw)); src = dst_r; } @@ -1827,11 +2103,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src1 & SLJIT_MEM) { - emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w); + FAIL_IF(emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w)); src1 = TMP_FREG1; } if (src2 & SLJIT_MEM) { - emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w); + FAIL_IF(emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w)); src2 = TMP_FREG2; } @@ -1848,6 +2124,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil case SLJIT_DIV_F64: FAIL_IF(push_inst(compiler, (FDIV ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2))); break; + case SLJIT_COPYSIGN_F64: + FAIL_IF(push_inst(compiler, (FMOV_R ^ ((op & SLJIT_32) ? (W_OP | (1 << 22)) : 0)) | VN(src2) | RD(TMP_REG1))); + FAIL_IF(push_inst(compiler, (FABS ^ inv_bits) | VD(dst_r) | VN(src1))); + FAIL_IF(push_inst(compiler, TBZ | ((op & SLJIT_32) ? 0 : ((sljit_ins)1 << 31)) | (0x1f << 19) | (2 << 5) | RT(TMP_REG1))); + return push_inst(compiler, (FNEG ^ inv_bits) | VD(dst_r) | VN(dst_r)); } if (!(dst & SLJIT_MEM)) @@ -1855,6 +2136,62 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil return emit_fop_mem(compiler, mem_flags | STORE, TMP_FREG1, dst, dstw); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f32 value) +{ + sljit_u32 exp; + union { + sljit_u32 imm; + sljit_f32 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset32(compiler, freg, value)); + + u.value = value; + + if (u.imm == 0) + return push_inst(compiler, (FMOV_R ^ (W_OP | (1 << 22))) | RN(TMP_ZERO) | VD(freg) | (1 << 16)); + + if ((u.imm << (32 - 19)) == 0) { + exp = (u.imm >> (23 + 2)) & 0x3f; + + if (exp == 0x20 || exp == 0x1f) + return push_inst(compiler, (FMOV_I ^ (1 << 22)) | (sljit_ins)((((u.imm >> 24) & 0x80) | ((u.imm >> 19) & 0x7f)) << 13) | VD(freg)); + } + + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_s32)u.imm)); + return push_inst(compiler, (FMOV_R ^ (W_OP | (1 << 22))) | RN(TMP_REG1) | VD(freg) | (1 << 16)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f64 value) +{ + sljit_uw exp; + union { + sljit_uw imm; + sljit_f64 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset64(compiler, freg, value)); + + u.value = value; + + if (u.imm == 0) + return push_inst(compiler, FMOV_R | RN(TMP_ZERO) | VD(freg) | (sljit_ins)1 << 16); + + if ((u.imm << (64 - 48)) == 0) { + exp = (u.imm >> (52 + 2)) & 0x1ff; + + if (exp == 0x100 || exp == 0xff) + return push_inst(compiler, FMOV_I | (sljit_ins)((((u.imm >> 56) & 0x80) | ((u.imm >> 48) & 0x7f)) << 13) | VD(freg)); + } + + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_sw)u.imm)); + return push_inst(compiler, FMOV_R | RN(TMP_REG1) | VD(freg) | (1 << 16)); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 freg, sljit_s32 reg) { @@ -1864,12 +2201,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compi CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) - inst = FMOV_R | RN(reg) | VD(freg) | (sljit_ins)1 << 16; + inst = FMOV_R | RN(reg) | VD(freg) | (1 << 16); else inst = FMOV_R | VN(freg) | RD(reg); if (op & SLJIT_32) - inst ^= ((sljit_ins)1 << 31) | ((sljit_ins)1 << 22); + inst ^= W_OP | (1 << 22); return push_inst(compiler, inst); } @@ -1882,15 +2219,17 @@ static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type) { switch (type) { case SLJIT_EQUAL: + case SLJIT_ATOMIC_STORED: case SLJIT_F_EQUAL: case SLJIT_ORDERED_EQUAL: - case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */ + case SLJIT_UNORDERED_OR_EQUAL: return 0x1; case SLJIT_NOT_EQUAL: + case SLJIT_ATOMIC_NOT_STORED: case SLJIT_F_NOT_EQUAL: case SLJIT_UNORDERED_OR_NOT_EQUAL: - case SLJIT_ORDERED_NOT_EQUAL: /* Not supported. */ + case SLJIT_ORDERED_NOT_EQUAL: return 0x0; case SLJIT_CARRY: @@ -1996,14 +2335,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile if (type < SLJIT_JUMP) { jump->flags |= IS_COND; PTR_FAIL_IF(push_inst(compiler, B_CC | (6 << 5) | get_cc(compiler, type))); - } - else if (type >= SLJIT_FAST_CALL) + } else if (type >= SLJIT_FAST_CALL) jump->flags |= IS_BL; - PTR_FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0)); jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG1))); + /* Maximum number of instructions required for generating a constant. */ + compiler->size += JUMP_MAX_SIZE - 1; return jump; } @@ -2041,7 +2380,7 @@ static SLJIT_INLINE struct sljit_jump* emit_cmp_to0(struct sljit_compiler *compi PTR_FAIL_IF(emit_op_mem(compiler, inv_bits ? INT_SIZE : WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } - else if (src & SLJIT_IMM) { + else if (src == SLJIT_IMM) { PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); src = TMP_REG1; } @@ -2052,9 +2391,11 @@ static SLJIT_INLINE struct sljit_jump* emit_cmp_to0(struct sljit_compiler *compi inv_bits |= 1 << 24; PTR_FAIL_IF(push_inst(compiler, (CBZ ^ inv_bits) | (6 << 5) | RT(src))); - PTR_FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0)); jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, BR | RN(TMP_REG1))); + + /* Maximum number of instructions required for generating a constant. */ + compiler->size += JUMP_MAX_SIZE - 1; return jump; } @@ -2065,7 +2406,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); - if (!(src & SLJIT_IMM)) { + if (src != SLJIT_IMM) { if (src & SLJIT_MEM) { ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); @@ -2080,8 +2421,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0)); jump->u.target = (sljit_uw)srcw; - FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0)); jump->addr = compiler->size; + /* Maximum number of instructions required for generating a constant. */ + compiler->size += JUMP_MAX_SIZE - 1; return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG1)); } @@ -2101,7 +2443,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi if (type & SLJIT_CALL_RETURN) { if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { - FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(src))); + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src))); src = TMP_REG1; } @@ -2161,27 +2503,53 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, - sljit_s32 src, sljit_sw srcw) + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_reg) { sljit_ins inv_bits = (type & SLJIT_32) ? W_OP : 0; sljit_ins cc; CHECK_ERROR(); - CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); + CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg)); + + ADJUST_LOCAL_OFFSET(src1, src1w); - if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { + if (src1 == SLJIT_IMM) { if (type & SLJIT_32) - srcw = (sljit_s32)srcw; - FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); - src = TMP_REG1; - srcw = 0; + src1w = (sljit_s32)src1w; + FAIL_IF(load_immediate(compiler, TMP_REG1, src1w)); + src1 = TMP_REG1; + } else if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src1, src1w, TMP_REG2)); + src1 = TMP_REG1; } cc = get_cc(compiler, type & ~SLJIT_32); + return push_inst(compiler, (CSEL ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(src2_reg) | RM(src1)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_freg) +{ + sljit_ins inv_bits = (type & SLJIT_32) ? (1 << 22) : 0; + sljit_ins cc; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg)); - return push_inst(compiler, (CSEL ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(dst_reg) | RM(src)); + ADJUST_LOCAL_OFFSET(src1, src1w); + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_fop_mem(compiler, (type & SLJIT_32) ? INT_SIZE : WORD_SIZE, TMP_FREG1, src1, src1w)); + src1 = TMP_FREG1; + } + + cc = get_cc(compiler, type & ~SLJIT_32); + return push_inst(compiler, (FCSEL ^ inv_bits) | (cc << 12) | VD(dst_freg) | VN(src2_freg) | VM(src1)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, @@ -2338,44 +2706,699 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler return push_inst(compiler, inst | VT(freg) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x1ff) << 12)); } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) +static sljit_s32 sljit_emit_simd_mem_offset(struct sljit_compiler *compiler, sljit_s32 *mem_ptr, sljit_sw memw) { - sljit_s32 dst_reg; sljit_ins ins; + sljit_s32 mem = *mem_ptr; - CHECK_ERROR(); - CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset)); - ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset); + if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { + *mem_ptr = TMP_REG1; + return push_inst(compiler, ADD | RD(TMP_REG1) | RN(mem & REG_MASK) | RM(OFFS_REG(mem)) | ((sljit_ins)(memw & 0x3) << 10)); + } - dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1; + if (!(mem & REG_MASK)) { + *mem_ptr = TMP_REG1; + return load_immediate(compiler, TMP_REG1, memw); + } - /* Not all instruction forms support accessing SP register. */ - if (offset <= 0xffffff && offset >= -0xffffff) { - ins = ADDI; - if (offset < 0) { - offset = -offset; - ins = SUBI; - } + mem &= REG_MASK; - if (offset <= 0xfff) - FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | (sljit_ins)(offset << 10))); - else { - FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | (sljit_ins)((offset & 0xfff000) >> (12 - 10)) | (1 << 22))); + if (memw == 0) { + *mem_ptr = mem; + return SLJIT_SUCCESS; + } - offset &= 0xfff; - if (offset != 0) - FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(dst_reg) | (sljit_ins)(offset << 10))); - } + *mem_ptr = TMP_REG1; + + if (memw < -0xffffff || memw > 0xffffff) { + FAIL_IF(load_immediate(compiler, TMP_REG1, memw)); + return push_inst(compiler, ADD | RD(TMP_REG1) | RN(TMP_REG1) | RM(mem)); } - else { - FAIL_IF(load_immediate (compiler, dst_reg, offset)); - /* Add extended register form. */ - FAIL_IF(push_inst(compiler, ADDE | (0x3 << 13) | RD(dst_reg) | RN(SLJIT_SP) | RM(dst_reg))); + + ins = ADDI; + + if (memw < 0) { + memw = -memw; + ins = SUBI; } - if (SLJIT_UNLIKELY(dst & SLJIT_MEM)) - return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG1); - return SLJIT_SUCCESS; + if (memw > 0xfff) { + FAIL_IF(push_inst(compiler, ins | (1 << 22) | RD(TMP_REG1) | RN(mem) | ((sljit_ins)(memw >> 12) << 10))); + + memw &= 0xfff; + if (memw == 0) + return SLJIT_SUCCESS; + + mem = TMP_REG1; + } + + return push_inst(compiler, ins | RD(TMP_REG1) | RN(mem) | ((sljit_ins)memw << 10)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 srcdst, sljit_sw srcdstw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw)); + + ADJUST_LOCAL_OFFSET(srcdst, srcdstw); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (!(srcdst & SLJIT_MEM)) { + if (type & SLJIT_SIMD_STORE) + ins = VD(srcdst) | VN(freg) | VM(freg); + else + ins = VD(freg) | VN(srcdst) | VM(srcdst); + + if (reg_size == 4) + ins |= (1 << 30); + + return push_inst(compiler, ORR_v | ins); + } + + FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw)); + + if (elem_size > 3) + elem_size = 3; + + ins = (type & SLJIT_SIMD_STORE) ? ST1 : LD1; + + if (reg_size == 4) + ins |= (1 << 30); + + return push_inst(compiler, ins | ((sljit_ins)elem_size << 10) | RN(srcdst) | VT(freg)); +} + +static sljit_ins simd_get_imm(sljit_s32 elem_size, sljit_uw value) +{ + sljit_ins result; + + if (elem_size > 2 && (sljit_u32)value == (value >> 32)) { + elem_size = 2; + value = (sljit_u32)value; + } + + if (elem_size == 2 && (sljit_u16)value == (value >> 16)) { + elem_size = 1; + value = (sljit_u16)value; + } + + if (elem_size == 1 && (sljit_u8)value == (value >> 8)) { + elem_size = 0; + value = (sljit_u8)value; + } + + switch (elem_size) { + case 0: + SLJIT_ASSERT(value <= 0xff); + result = 0xe000; + break; + case 1: + SLJIT_ASSERT(value <= 0xffff); + result = 0; + + while (1) { + if (value <= 0xff) { + result |= 0x8000; + break; + } + + if ((value & 0xff) == 0) { + value >>= 8; + result |= 0xa000; + break; + } + + if (result != 0) + return ~(sljit_ins)0; + + value ^= (sljit_uw)0xffff; + result = (1 << 29); + } + break; + case 2: + SLJIT_ASSERT(value <= 0xffffffff); + result = 0; + + while (1) { + if (value <= 0xff) { + result |= 0x0000; + break; + } + + if ((value & ~(sljit_uw)0xff00) == 0) { + value >>= 8; + result |= 0x2000; + break; + } + + if ((value & ~(sljit_uw)0xff0000) == 0) { + value >>= 16; + result |= 0x4000; + break; + } + + if ((value & ~(sljit_uw)0xff000000) == 0) { + value >>= 24; + result |= 0x6000; + break; + } + + if ((value & (sljit_uw)0xff) == 0xff && (value >> 16) == 0) { + value >>= 8; + result |= 0xc000; + break; + } + + if ((value & (sljit_uw)0xffff) == 0xffff && (value >> 24) == 0) { + value >>= 16; + result |= 0xd000; + break; + } + + if (result != 0) + return ~(sljit_ins)0; + + value ^= (sljit_uw)0xffffffff; + result = (1 << 29); + } + break; + default: + return ~(sljit_ins)0; + } + + return (((sljit_ins)value & 0x1f) << 5) | (((sljit_ins)value & 0xe0) << 11) | result; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins, imm; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw)); + + ADJUST_LOCAL_OFFSET(src, srcw); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (src & SLJIT_MEM) { + FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw)); + + ins = (sljit_ins)elem_size << 10; + + if (reg_size == 4) + ins |= (sljit_ins)1 << 30; + + return push_inst(compiler, LD1R | ins | RN(src) | VT(freg)); + } + + ins = (sljit_ins)1 << (16 + elem_size); + + if (reg_size == 4) + ins |= (sljit_ins)1 << 30; + + if (type & SLJIT_SIMD_FLOAT) { + if (src == SLJIT_IMM) + return push_inst(compiler, MOVI | (ins & ((sljit_ins)1 << 30)) | VD(freg)); + + return push_inst(compiler, DUP_e | ins | VD(freg) | VN(src)); + } + + if (src == SLJIT_IMM) { + if (elem_size < 3) + srcw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1; + + imm = simd_get_imm(elem_size, (sljit_uw)srcw); + + if (imm != ~(sljit_ins)0) { + imm |= ins & ((sljit_ins)1 << 30); + + return push_inst(compiler, MOVI | imm | VD(freg)); + } + + FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); + src = TMP_REG1; + } + + return push_inst(compiler, DUP_g | ins | VD(freg) | RN(src)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, sljit_s32 lane_index, + sljit_s32 srcdst, sljit_sw srcdstw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw)); + + ADJUST_LOCAL_OFFSET(srcdst, srcdstw); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (type & SLJIT_SIMD_LANE_ZERO) { + ins = (reg_size == 3) ? 0 : ((sljit_ins)1 << 30); + + if ((type & SLJIT_SIMD_FLOAT) && freg == srcdst) { + FAIL_IF(push_inst(compiler, ORR_v | ins | VD(TMP_FREG1) | VN(freg) | VM(freg))); + srcdst = TMP_FREG1; + srcdstw = 0; + } + + FAIL_IF(push_inst(compiler, MOVI | ins | VD(freg))); + } + + if (srcdst & SLJIT_MEM) { + FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw)); + + if (elem_size == 3) + ins = 0x8400; + else if (elem_size == 0) + ins = 0; + else + ins = (sljit_ins)0x2000 << elem_size; + + lane_index = lane_index << elem_size; + ins |= (sljit_ins)(((lane_index & 0x8) << 27) | ((lane_index & 0x7) << 10)); + + return push_inst(compiler, ((type & SLJIT_SIMD_STORE) ? ST1_s : LD1_s) | ins | RN(srcdst) | VT(freg)); + } + + if (type & SLJIT_SIMD_FLOAT) { + if (type & SLJIT_SIMD_STORE) + ins = INS_e | ((sljit_ins)1 << (16 + elem_size)) | ((sljit_ins)lane_index << (11 + elem_size)) | VD(srcdst) | VN(freg); + else + ins = INS_e | ((((sljit_ins)lane_index << 1) | 1) << (16 + elem_size)) | VD(freg) | VN(srcdst); + + return push_inst(compiler, ins); + } + + if (srcdst == SLJIT_IMM) { + if (elem_size < 3) + srcdstw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1; + + FAIL_IF(load_immediate(compiler, TMP_REG1, srcdstw)); + srcdst = TMP_REG1; + } + + if (type & SLJIT_SIMD_STORE) { + ins = RD(srcdst) | VN(freg); + + if ((type & SLJIT_SIMD_LANE_SIGNED) && (elem_size < 2 || (elem_size == 2 && !(type & SLJIT_32)))) { + ins |= SMOV; + + if (!(type & SLJIT_32)) + ins |= (sljit_ins)1 << 30; + } else + ins |= UMOV; + } else + ins = INS | VD(freg) | RN(srcdst); + + if (elem_size == 3) + ins |= (sljit_ins)1 << 30; + + return push_inst(compiler, ins | ((((sljit_ins)lane_index << 1) | 1) << (16 + elem_size))); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_s32 src_lane_index) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index)); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + ins = (((sljit_ins)src_lane_index << 1) | 1) << (16 + elem_size); + + if (reg_size == 4) + ins |= (sljit_ins)1 << 30; + + return push_inst(compiler, DUP_e | ins | VD(freg) | VN(src)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type); + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw)); + + ADJUST_LOCAL_OFFSET(src, srcw); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size != 2 || elem2_size != 3)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (src & SLJIT_MEM) { + FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw)); + + if (reg_size == 4 && elem2_size - elem_size == 1) + FAIL_IF(push_inst(compiler, LD1 | ((sljit_ins)elem_size << 10) | RN(src) | VT(freg))); + else + FAIL_IF(push_inst(compiler, LD1_s | ((sljit_ins)0x2000 << (reg_size - elem2_size + elem_size)) | RN(src) | VT(freg))); + src = freg; + } + + if (type & SLJIT_SIMD_FLOAT) { + SLJIT_ASSERT(reg_size == 4); + return push_inst(compiler, FCVTL | (1 << 22) | VD(freg) | VN(src)); + } + + do { + FAIL_IF(push_inst(compiler, ((type & SLJIT_SIMD_EXTEND_SIGNED) ? SSHLL : USHLL) + | ((sljit_ins)1 << (19 + elem_size)) | VD(freg) | VN(src))); + src = freg; + } while (++elem_size < elem2_size); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 dst, sljit_sw dstw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins, imms; + sljit_s32 dst_r; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw)); + + ADJUST_LOCAL_OFFSET(dst, dstw); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + switch (elem_size) { + case 0: + imms = 0x643219; + ins = USHR | (0x9 << 16); + break; + case 1: + imms = (reg_size == 4) ? 0x643219 : 0x6231; + ins = USHR | (0x11 << 16); + break; + case 2: + imms = (reg_size == 4) ? 0x6231 : 0x61; + ins = USHR | (0x21 << 16); + break; + default: + imms = 0x61; + ins = USHR | (0x41 << 16); + break; + } + + if (reg_size == 4) + ins |= (1 << 30); + + FAIL_IF(push_inst(compiler, ins | VD(TMP_FREG1) | VN(freg))); + + if (reg_size == 4 && elem_size > 0) + FAIL_IF(push_inst(compiler, XTN | ((sljit_ins)(elem_size - 1) << 22) | VD(TMP_FREG1) | VN(TMP_FREG1))); + + if (imms >= 0x100) { + ins = (reg_size == 4 && elem_size == 0) ? (1 << 30) : 0; + + do { + FAIL_IF(push_inst(compiler, USRA | ins | ((imms & 0xff) << 16) | VD(TMP_FREG1) | VN(TMP_FREG1))); + imms >>= 8; + } while (imms >= 0x100); + } + + FAIL_IF(push_inst(compiler, USRA | (1 << 30) | (imms << 16) | VD(TMP_FREG1) | VN(TMP_FREG1))); + + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; + ins = (0x1 << 16); + + if (reg_size == 4 && elem_size == 0) { + FAIL_IF(push_inst(compiler, INS_e | (0x3 << 16) | (0x8 << 11) | VD(TMP_FREG1) | VN(TMP_FREG1))); + ins = (0x2 << 16); + } + + FAIL_IF(push_inst(compiler, UMOV | ins | RD(dst_r) | VN(TMP_FREG1))); + + if (dst_r == TMP_REG1) + return emit_op_mem(compiler, STORE | ((type & SLJIT_32) ? INT_SIZE : WORD_SIZE), TMP_REG1, dst, dstw, TMP_REG2); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg)); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + switch (SLJIT_SIMD_GET_OPCODE(type)) { + case SLJIT_SIMD_OP2_AND: + ins = AND_v; + break; + case SLJIT_SIMD_OP2_OR: + ins = ORR_v; + break; + case SLJIT_SIMD_OP2_XOR: + ins = EOR_v; + break; + } + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 4) + ins |= (sljit_ins)1 << 30; + + return push_inst(compiler, ins | VD(dst_freg) | VN(src1_freg) | VM(src2_freg)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 mem_reg) +{ + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); + +#ifdef __ARM_FEATURE_ATOMICS + switch (GET_OPCODE(op)) { + case SLJIT_MOV32: + case SLJIT_MOV_U32: + ins = LDR ^ (1 << 30); + break; + case SLJIT_MOV_U16: + ins = LDRH; + break; + case SLJIT_MOV_U8: + ins = LDRB; + break; + default: + ins = LDR; + break; + } +#else /* !__ARM_FEATURE_ATOMICS */ + switch (GET_OPCODE(op)) { + case SLJIT_MOV32: + case SLJIT_MOV_U32: + ins = LDXR ^ (1 << 30); + break; + case SLJIT_MOV_U8: + ins = LDXRB; + break; + case SLJIT_MOV_U16: + ins = LDXRH; + break; + default: + ins = LDXR; + break; + } +#endif /* ARM_FEATURE_ATOMICS */ + return push_inst(compiler, ins | RN(mem_reg) | RT(dst_reg)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_reg, + sljit_s32 mem_reg, + sljit_s32 temp_reg) +{ + sljit_ins ins; + sljit_s32 tmp = temp_reg; + sljit_ins cmp = 0; + sljit_ins inv_bits = W_OP; + + CHECK_ERROR(); + CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg)); + +#ifdef __ARM_FEATURE_ATOMICS + if (op & SLJIT_SET_ATOMIC_STORED) + cmp = (SUBS ^ W_OP) | RD(TMP_ZERO); + + switch (GET_OPCODE(op)) { + case SLJIT_MOV32: + case SLJIT_MOV_U32: + ins = CAS ^ (1 << 30); + break; + case SLJIT_MOV_U16: + ins = CASH; + break; + case SLJIT_MOV_U8: + ins = CASB; + break; + default: + ins = CAS; + inv_bits = 0; + if (cmp) + cmp ^= W_OP; + break; + } + + if (cmp) { + FAIL_IF(push_inst(compiler, (MOV ^ inv_bits) | RM(temp_reg) | RD(TMP_REG1))); + tmp = TMP_REG1; + } + FAIL_IF(push_inst(compiler, ins | RM(tmp) | RN(mem_reg) | RD(src_reg))); + if (!cmp) + return SLJIT_SUCCESS; + + FAIL_IF(push_inst(compiler, cmp | RM(tmp) | RN(temp_reg))); + FAIL_IF(push_inst(compiler, (CSET ^ inv_bits) | RD(tmp))); + return push_inst(compiler, cmp | RM(tmp) | RN(TMP_ZERO)); +#else /* !__ARM_FEATURE_ATOMICS */ + SLJIT_UNUSED_ARG(tmp); + SLJIT_UNUSED_ARG(inv_bits); + + if (op & SLJIT_SET_ATOMIC_STORED) + cmp = (SUBI ^ W_OP) | (1 << 29); + + switch (GET_OPCODE(op)) { + case SLJIT_MOV32: + case SLJIT_MOV_U32: + ins = STXR ^ (1 << 30); + break; + case SLJIT_MOV_U8: + ins = STXRB; + break; + case SLJIT_MOV_U16: + ins = STXRH; + break; + default: + ins = STXR; + break; + } + + FAIL_IF(push_inst(compiler, ins | RM(TMP_REG1) | RN(mem_reg) | RT(src_reg))); + return cmp ? push_inst(compiler, cmp | RD(TMP_ZERO) | RN(TMP_REG1)) : SLJIT_SUCCESS; +#endif /* __ARM_FEATURE_ATOMICS */ +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) +{ + sljit_s32 dst_reg; + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset)); + ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset); + + dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1; + + /* Not all instruction forms support accessing SP register. */ + if (offset <= 0xffffff && offset >= -0xffffff) { + ins = ADDI; + if (offset < 0) { + offset = -offset; + ins = SUBI; + } + + if (offset <= 0xfff) + FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | (sljit_ins)(offset << 10))); + else { + FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | (sljit_ins)((offset & 0xfff000) >> (12 - 10)) | (1 << 22))); + + offset &= 0xfff; + if (offset != 0) + FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(dst_reg) | (sljit_ins)(offset << 10))); + } + } + else { + FAIL_IF(load_immediate (compiler, dst_reg, offset)); + /* Add extended register form. */ + FAIL_IF(push_inst(compiler, ADDE | (0x3 << 13) | RD(dst_reg) | RN(SLJIT_SP) | RM(dst_reg))); + } + + if (SLJIT_UNLIKELY(dst & SLJIT_MEM)) + return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG1); + return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) @@ -2399,26 +3422,28 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi return const_; } -SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { - struct sljit_put_label *put_label; + struct sljit_jump *jump; sljit_s32 dst_r; CHECK_ERROR_PTR(); - CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw)); + CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; - PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, 0)); + PTR_FAIL_IF(push_inst(compiler, RD(dst_r))); - put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label)); - PTR_FAIL_IF(!put_label); - set_put_label(put_label, compiler, 1); + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_mov_addr(jump, compiler, 1); + + compiler->size += 3; if (dst & SLJIT_MEM) PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2)); - return put_label; + return jump; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_T2_32.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_T2_32.c index 73dd7f99d5b..4d74f4803dd 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_T2_32.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeARM_T2_32.c @@ -49,8 +49,20 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = { 0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 12, 14, 15 }; -static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { - 0, 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8, 6, 7 +static const sljit_u8 freg_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) + 1] = { + 0, + 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8, + 7, 6, + 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8, + 7, 6 +}; + +static const sljit_u8 freg_ebit_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) + 1] = { + 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1 }; #define COPY_BITS(src, from, to, bits) \ @@ -75,13 +87,15 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { (reg_map[reg1] <= 7 && reg_map[reg2] <= 7 && reg_map[reg3] <= 7) /* Thumb32 encodings. */ -#define RD4(rd) ((sljit_ins)reg_map[rd] << 8) -#define RN4(rn) ((sljit_ins)reg_map[rn] << 16) #define RM4(rm) ((sljit_ins)reg_map[rm]) +#define RD4(rd) ((sljit_ins)reg_map[rd] << 8) #define RT4(rt) ((sljit_ins)reg_map[rt] << 12) -#define DD4(dd) ((sljit_ins)freg_map[dd] << 12) -#define DN4(dn) ((sljit_ins)freg_map[dn] << 16) -#define DM4(dm) ((sljit_ins)freg_map[dm]) +#define RN4(rn) ((sljit_ins)reg_map[rn] << 16) + +#define VM4(vm) (((sljit_ins)freg_map[vm]) | ((sljit_ins)freg_ebit_map[vm] << 5)) +#define VD4(vd) (((sljit_ins)freg_map[vd] << 12) | ((sljit_ins)freg_ebit_map[vd] << 22)) +#define VN4(vn) (((sljit_ins)freg_map[vn] << 16) | ((sljit_ins)freg_ebit_map[vn] << 7)) + #define IMM5(imm) \ (COPY_BITS(imm, 2, 12, 3) | (((sljit_ins)imm & 0x3) << 6)) #define IMM12(imm) \ @@ -128,9 +142,12 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define EORS 0x4040 #define EOR_W 0xea800000 #define IT 0xbf00 -#define LDR_SP 0x9800 #define LDR 0xf8d00000 +#define LDR_SP 0x9800 #define LDRD 0xe9500000 +#define LDREX 0xe8500f00 +#define LDREXB 0xe8d00f4f +#define LDREXH 0xe8d00f5f #define LDRI 0xf8500800 #define LSLS 0x4080 #define LSLSI 0x0000 @@ -162,6 +179,8 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define PUSH_W 0xe92d0000 #define REV 0xba00 #define REV_W 0xfa90f080 +#define REV16 0xba40 +#define REV16_W 0xfa90f090 #define RBIT 0xfa90f0a0 #define RORS 0x41c0 #define ROR_W 0xfa60f000 @@ -173,8 +192,11 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define SBC_W 0xeb600000 #define SDIV 0xfb90f0f0 #define SMULL 0xfb800000 -#define STRD 0xe9400000 #define STR_SP 0x9000 +#define STRD 0xe9400000 +#define STREX 0xe8400000 +#define STREXB 0xe8c00f40 +#define STREXH 0xe8c00f50 #define SUBS 0x1a00 #define SUBSI3 0x1e00 #define SUBSI8 0x3800 @@ -197,23 +219,57 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define UXTH_W 0xfa1ff080 #define VABS_F32 0xeeb00ac0 #define VADD_F32 0xee300a00 +#define VAND 0xef000110 #define VCMP_F32 0xeeb40a40 #define VCVT_F32_S32 0xeeb80ac0 +#define VCVT_F32_U32 0xeeb80a40 #define VCVT_F64_F32 0xeeb70ac0 #define VCVT_S32_F32 0xeebd0ac0 #define VDIV_F32 0xee800a00 +#define VDUP 0xee800b10 +#define VDUP_s 0xffb00c00 +#define VEOR 0xff000110 +#define VLD1 0xf9200000 +#define VLD1_r 0xf9a00c00 +#define VLD1_s 0xf9a00000 #define VLDR_F32 0xed100a00 #define VMOV_F32 0xeeb00a40 #define VMOV 0xee000a10 #define VMOV2 0xec400a10 +#define VMOV_i 0xef800010 +#define VMOV_s 0xee000b10 +#define VMOVN 0xffb20200 #define VMRS 0xeef1fa10 #define VMUL_F32 0xee200a00 #define VNEG_F32 0xeeb10a40 +#define VORR 0xef200110 #define VPOP 0xecbd0b00 #define VPUSH 0xed2d0b00 +#define VSHLL 0xef800a10 +#define VSHR 0xef800010 +#define VSRA 0xef800110 +#define VST1 0xf9000000 +#define VST1_s 0xf9800000 #define VSTR_F32 0xed000a00 #define VSUB_F32 0xee300a40 +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + +static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32) +{ + if (compiler->scratches == -1) + return 0; + + if (is_32 && fr >= SLJIT_F64_SECOND(SLJIT_FR0)) + fr -= SLJIT_F64_SECOND(0); + + return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->fscratches)) + || (fr > (SLJIT_FS0 - compiler->fsaveds) && fr <= SLJIT_FS0) + || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)); +} + +#endif /* SLJIT_ARGUMENT_CHECKS */ + static sljit_s32 push_inst16(struct sljit_compiler *compiler, sljit_ins inst) { sljit_u16 *ptr; @@ -236,7 +292,7 @@ static sljit_s32 push_inst32(struct sljit_compiler *compiler, sljit_ins inst) return SLJIT_SUCCESS; } -static SLJIT_INLINE sljit_s32 emit_imm32_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm) +static sljit_s32 emit_imm32_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm) { FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) | COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff))); @@ -244,134 +300,259 @@ static SLJIT_INLINE sljit_s32 emit_imm32_const(struct sljit_compiler *compiler, | COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16)); } -static SLJIT_INLINE void modify_imm32_const(sljit_u16 *inst, sljit_uw new_imm) +/* Dst must be in bits[11-8] */ +static void set_imm32_const(sljit_u16 *inst, sljit_ins dst, sljit_uw new_imm) { - sljit_ins dst = inst[1] & 0x0f00; - SLJIT_ASSERT(((inst[0] & 0xfbf0) == (MOVW >> 16)) && ((inst[2] & 0xfbf0) == (MOVT >> 16)) && dst == (inst[3] & 0x0f00)); inst[0] = (sljit_u16)((MOVW >> 16) | COPY_BITS(new_imm, 12, 0, 4) | COPY_BITS(new_imm, 11, 10, 1)); inst[1] = (sljit_u16)(dst | COPY_BITS(new_imm, 8, 12, 3) | (new_imm & 0xff)); inst[2] = (sljit_u16)((MOVT >> 16) | COPY_BITS(new_imm, 12 + 16, 0, 4) | COPY_BITS(new_imm, 11 + 16, 10, 1)); inst[3] = (sljit_u16)(dst | COPY_BITS(new_imm, 8 + 16, 12, 3) | ((new_imm & 0xff0000) >> 16)); } -static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset) +static SLJIT_INLINE void modify_imm32_const(sljit_u16 *inst, sljit_uw new_imm) +{ + sljit_ins dst = inst[1] & 0x0f00; + SLJIT_ASSERT(((inst[0] & 0xfbf0) == (MOVW >> 16)) && ((inst[2] & 0xfbf0) == (MOVT >> 16)) && dst == (inst[3] & 0x0f00)); + set_imm32_const(inst, dst, new_imm); +} + +static SLJIT_INLINE sljit_u16* detect_jump_type(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset) { sljit_sw diff; if (jump->flags & SLJIT_REWRITABLE_JUMP) - return 0; + goto exit; if (jump->flags & JUMP_ADDR) { /* Branch to ARM code is not optimized yet. */ if (!(jump->u.target & 0x1)) - return 0; - diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset) >> 1; - } - else { - SLJIT_ASSERT(jump->flags & JUMP_LABEL); - diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2)) >> 1; + goto exit; + diff = (sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset; + } else { + SLJIT_ASSERT(jump->u.label != NULL); + diff = (sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2); } if (jump->flags & IS_COND) { SLJIT_ASSERT(!(jump->flags & IS_BL)); - if (diff <= 127 && diff >= -128) { + /* Size of the prefix IT instruction. */ + diff += SSIZE_OF(u16); + if (diff <= 0xff && diff >= -0x100) { jump->flags |= PATCH_TYPE1; - return 5; + jump->addr = (sljit_uw)(code_ptr - 1); + return code_ptr - 1; } - if (diff <= 524287 && diff >= -524288) { + if (diff <= 0xfffff && diff >= -0x100000) { jump->flags |= PATCH_TYPE2; - return 4; + jump->addr = (sljit_uw)(code_ptr - 1); + return code_ptr; } - /* +1 comes from the prefix IT instruction. */ - diff--; - if (diff <= 8388607 && diff >= -8388608) { - jump->flags |= PATCH_TYPE3; - return 3; + diff -= SSIZE_OF(u16); + } else if (jump->flags & IS_BL) { + /* Branch and link. */ + if (diff <= 0xffffff && diff >= -0x1000000) { + jump->flags |= PATCH_TYPE5; + return code_ptr + 1; } + goto exit; + } else if (diff <= 0x7ff && diff >= -0x800) { + jump->flags |= PATCH_TYPE3; + return code_ptr; } - else if (jump->flags & IS_BL) { - if (diff <= 8388607 && diff >= -8388608) { - jump->flags |= PATCH_BL; - return 3; - } + + if (diff <= 0xffffff && diff >= -0x1000000) { + jump->flags |= PATCH_TYPE4; + return code_ptr + 1; } - else { - if (diff <= 1023 && diff >= -1024) { - jump->flags |= PATCH_TYPE4; - return 4; - } - if (diff <= 8388607 && diff >= -8388608) { - jump->flags |= PATCH_TYPE5; - return 3; - } + +exit: + code_ptr[4] = code_ptr[0]; + + if (jump->flags & IS_COND) { + code_ptr[3] = code_ptr[-1]; + jump->addr = (sljit_uw)(code_ptr - 1); + } + + return code_ptr + 4; +} + +static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset) +{ + sljit_uw addr; + sljit_sw diff; + SLJIT_UNUSED_ARG(executable_offset); + + if (jump->flags & JUMP_ADDR) + addr = jump->u.target; + else + addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset); + + /* The pc+4 offset is represented by the 2 * SSIZE_OF(sljit_u16) below. */ + diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + + /* Note: ADR with imm8 does not set the last bit (Thumb2 flag). */ + + if (diff <= 0xffd + 2 * SSIZE_OF(u16) && diff >= -0xfff + 2 * SSIZE_OF(u16)) { + jump->flags |= PATCH_TYPE6; + return 1; } - return 0; + return 3; } -static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump, sljit_sw executable_offset) +static SLJIT_INLINE void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executable_offset) { sljit_s32 type = (jump->flags >> 4) & 0xf; + sljit_u16 *jump_inst = (sljit_u16*)jump->addr; sljit_sw diff; - sljit_u16 *jump_inst; - sljit_s32 s, j1, j2; + sljit_ins ins; + + diff = (sljit_sw)((jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr); if (SLJIT_UNLIKELY(type == 0)) { - modify_imm32_const((sljit_u16*)jump->addr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target); + ins = (jump->flags & JUMP_MOV_ADDR) ? *jump_inst : RDN3(TMP_REG1); + set_imm32_const((sljit_u16*)jump->addr, ins, (sljit_uw)diff); return; } - if (jump->flags & JUMP_ADDR) { - SLJIT_ASSERT(jump->u.target & 0x1); - diff = ((sljit_sw)jump->u.target - (sljit_sw)(jump->addr + sizeof(sljit_u32)) - executable_offset) >> 1; - } - else { - SLJIT_ASSERT(jump->u.label->addr & 0x1); - diff = ((sljit_sw)(jump->u.label->addr) - (sljit_sw)(jump->addr + sizeof(sljit_u32)) - executable_offset) >> 1; + if (SLJIT_UNLIKELY(type == 6)) { + SLJIT_ASSERT(jump->flags & JUMP_MOV_ADDR); + diff -= (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_inst + 2, executable_offset) & ~(sljit_sw)0x3; + + SLJIT_ASSERT(diff <= 0xfff && diff >= -0xfff); + + ins = ADDWI >> 16; + if (diff <= 0) { + diff = -diff; + ins = SUBWI >> 16; + } + + jump_inst[1] = (sljit_u16)(jump_inst[0] | COPY_BITS(diff, 8, 12, 3) | (diff & 0xff)); + jump_inst[0] = (sljit_u16)(ins | 0xf | COPY_BITS(diff, 11, 10, 1)); + return; } - jump_inst = (sljit_u16*)jump->addr; + + SLJIT_ASSERT((diff & 0x1) != 0 && !(jump->flags & JUMP_MOV_ADDR)); + diff = (diff - (sljit_sw)(jump->addr + sizeof(sljit_u32)) - executable_offset) >> 1; switch (type) { case 1: /* Encoding T1 of 'B' instruction */ - SLJIT_ASSERT(diff <= 127 && diff >= -128 && (jump->flags & IS_COND)); + SLJIT_ASSERT(diff <= 0x7f && diff >= -0x80 && (jump->flags & IS_COND)); jump_inst[0] = (sljit_u16)(0xd000 | (jump->flags & 0xf00) | ((sljit_ins)diff & 0xff)); return; case 2: /* Encoding T3 of 'B' instruction */ - SLJIT_ASSERT(diff <= 524287 && diff >= -524288 && (jump->flags & IS_COND)); + SLJIT_ASSERT(diff <= 0x7ffff && diff >= -0x80000 && (jump->flags & IS_COND)); jump_inst[0] = (sljit_u16)(0xf000 | COPY_BITS(jump->flags, 8, 6, 4) | COPY_BITS(diff, 11, 0, 6) | COPY_BITS(diff, 19, 10, 1)); jump_inst[1] = (sljit_u16)(0x8000 | COPY_BITS(diff, 17, 13, 1) | COPY_BITS(diff, 18, 11, 1) | ((sljit_ins)diff & 0x7ff)); return; case 3: - SLJIT_ASSERT(jump->flags & IS_COND); - *jump_inst++ = (sljit_u16)(IT | ((jump->flags >> 4) & 0xf0) | 0x8); - diff--; - type = 5; - break; - case 4: /* Encoding T2 of 'B' instruction */ - SLJIT_ASSERT(diff <= 1023 && diff >= -1024 && !(jump->flags & IS_COND)); + SLJIT_ASSERT(diff <= 0x3ff && diff >= -0x400 && !(jump->flags & IS_COND)); jump_inst[0] = (sljit_u16)(0xe000 | (diff & 0x7ff)); return; } - SLJIT_ASSERT(diff <= 8388607 && diff >= -8388608); + SLJIT_ASSERT(diff <= 0x7fffff && diff >= -0x800000); + + /* Really complex instruction form for branches. Negate with sign bit. */ + diff ^= ((diff >> 2) & 0x600000) ^ 0x600000; - /* Really complex instruction form for branches. */ - s = (diff >> 23) & 0x1; - j1 = (~(diff >> 22) ^ s) & 0x1; - j2 = (~(diff >> 21) ^ s) & 0x1; - jump_inst[0] = (sljit_u16)(0xf000 | ((sljit_ins)s << 10) | COPY_BITS(diff, 11, 0, 10)); - jump_inst[1] = (sljit_u16)((j1 << 13) | (j2 << 11) | (diff & 0x7ff)); + jump_inst[0] = (sljit_u16)(0xf000 | COPY_BITS(diff, 11, 0, 10) | COPY_BITS(diff, 23, 10, 1)); + jump_inst[1] = (sljit_u16)((diff & 0x7ff) | COPY_BITS(diff, 22, 13, 1) | COPY_BITS(diff, 21, 11, 1)); + + SLJIT_ASSERT(type == 4 || type == 5); /* The others have a common form. */ - if (type == 5) /* Encoding T4 of 'B' instruction */ + if (type == 4) /* Encoding T4 of 'B' instruction */ jump_inst[1] |= 0x9000; - else if (type == 6) /* Encoding T1 of 'BL' instruction */ + else /* Encoding T1 of 'BL' instruction */ jump_inst[1] |= 0xd000; - else - SLJIT_UNREACHABLE(); +} + +static void reduce_code_size(struct sljit_compiler *compiler) +{ + struct sljit_label *label; + struct sljit_jump *jump; + struct sljit_const *const_; + SLJIT_NEXT_DEFINE_TYPES; + sljit_uw total_size; + sljit_uw size_reduce = 0; + sljit_sw diff; + + label = compiler->labels; + jump = compiler->jumps; + const_ = compiler->consts; + SLJIT_NEXT_INIT_TYPES(); + + while (1) { + SLJIT_GET_NEXT_MIN(); + + if (next_min_addr == SLJIT_MAX_ADDRESS) + break; + + if (next_min_addr == next_label_size) { + label->size -= size_reduce; + + label = label->next; + next_label_size = SLJIT_GET_NEXT_SIZE(label); + } + + if (next_min_addr == next_const_addr) { + const_->addr -= size_reduce; + const_ = const_->next; + next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_); + continue; + } + + if (next_min_addr != next_jump_addr) + continue; + + jump->addr -= size_reduce; + if (!(jump->flags & JUMP_MOV_ADDR)) { + total_size = JUMP_MAX_SIZE; + + if (!(jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR))) { + /* Unit size: instruction. */ + diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr - 2; + + if (jump->flags & IS_COND) { + diff++; + + if (diff <= (0xff / SSIZE_OF(u16)) && diff >= (-0x100 / SSIZE_OF(u16))) + total_size = 0; + else if (diff <= (0xfffff / SSIZE_OF(u16)) && diff >= (-0x100000 / SSIZE_OF(u16))) + total_size = 1; + diff--; + } else if (!(jump->flags & IS_BL) && diff <= (0x7ff / SSIZE_OF(u16)) && diff >= (-0x800 / SSIZE_OF(u16))) + total_size = 1; + + if (total_size == JUMP_MAX_SIZE && diff <= (0xffffff / SSIZE_OF(u16)) && diff >= (-0x1000000 / SSIZE_OF(u16))) + total_size = 2; + } + + size_reduce += JUMP_MAX_SIZE - total_size; + } else { + /* Real size minus 1. Unit size: instruction. */ + total_size = 3; + + if (!(jump->flags & JUMP_ADDR)) { + diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; + + if (diff <= (0xffd / SSIZE_OF(u16)) && diff >= (-0xfff / SSIZE_OF(u16))) + total_size = 1; + } + + size_reduce += 3 - total_size; + } + + jump->flags |= total_size << JUMP_SIZE_SHIFT; + jump = jump->next; + next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); + } + + compiler->size -= size_reduce; } SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) @@ -382,64 +563,76 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil sljit_u16 *buf_ptr; sljit_u16 *buf_end; sljit_uw half_count; - sljit_uw next_addr; + SLJIT_NEXT_DEFINE_TYPES; + sljit_sw addr; sljit_sw executable_offset; struct sljit_label *label; struct sljit_jump *jump; struct sljit_const *const_; - struct sljit_put_label *put_label; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_generate_code(compiler)); - reverse_buf(compiler); + + reduce_code_size(compiler); code = (sljit_u16*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_u16), compiler->exec_allocator_data); PTR_FAIL_WITH_EXEC_IF(code); + + reverse_buf(compiler); buf = compiler->buf; code_ptr = code; half_count = 0; - next_addr = 0; executable_offset = SLJIT_EXEC_OFFSET(code); label = compiler->labels; jump = compiler->jumps; const_ = compiler->consts; - put_label = compiler->put_labels; + SLJIT_NEXT_INIT_TYPES(); + SLJIT_GET_NEXT_MIN(); do { buf_ptr = (sljit_u16*)buf->memory; buf_end = buf_ptr + (buf->used_size >> 1); do { *code_ptr = *buf_ptr++; - if (next_addr == half_count) { + if (next_min_addr == half_count) { SLJIT_ASSERT(!label || label->size >= half_count); SLJIT_ASSERT(!jump || jump->addr >= half_count); SLJIT_ASSERT(!const_ || const_->addr >= half_count); - SLJIT_ASSERT(!put_label || put_label->addr >= half_count); /* These structures are ordered by their address. */ - if (label && label->size == half_count) { - label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1; + if (next_min_addr == next_label_size) { + label->u.addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1; label->size = (sljit_uw)(code_ptr - code); label = label->next; + next_label_size = SLJIT_GET_NEXT_SIZE(label); } - if (jump && jump->addr == half_count) { - jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_COND) ? 10 : 8); - code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset); - jump = jump->next; - } - if (const_ && const_->addr == half_count) { + + if (next_min_addr == next_jump_addr) { + if (!(jump->flags & JUMP_MOV_ADDR)) { + half_count = half_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT); + jump->addr = (sljit_uw)code_ptr; + code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset); + SLJIT_ASSERT((sljit_uw)code_ptr - jump->addr < + ((jump->flags >> JUMP_SIZE_SHIFT) + ((jump->flags & 0xf0) <= PATCH_TYPE2)) * sizeof(sljit_u16)); + } else { + half_count += jump->flags >> JUMP_SIZE_SHIFT; + addr = (sljit_sw)code_ptr; + code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset); + jump->addr = (sljit_uw)addr; + } + + jump = jump->next; + next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); + } else if (next_min_addr == next_const_addr) { const_->addr = (sljit_uw)code_ptr; const_ = const_->next; + next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_); } - if (put_label && put_label->addr == half_count) { - SLJIT_ASSERT(put_label->label); - put_label->addr = (sljit_uw)code_ptr; - put_label = put_label->next; - } - next_addr = compute_next_addr(label, jump, const_, put_label); + + SLJIT_GET_NEXT_MIN(); } code_ptr++; half_count++; @@ -449,7 +642,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil } while (buf); if (label && label->size == half_count) { - label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1; + label->u.addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1; label->size = (sljit_uw)(code_ptr - code); label = label->next; } @@ -457,21 +650,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil SLJIT_ASSERT(!label); SLJIT_ASSERT(!jump); SLJIT_ASSERT(!const_); - SLJIT_ASSERT(!put_label); SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size); jump = compiler->jumps; while (jump) { - set_jump_instruction(jump, executable_offset); + generate_jump_or_mov_addr(jump, executable_offset); jump = jump->next; } - put_label = compiler->put_labels; - while (put_label) { - modify_imm32_const((sljit_u16 *)put_label->addr, put_label->label->addr); - put_label = put_label->next; - } - compiler->error = SLJIT_ERR_COMPILED; compiler->executable_offset = executable_offset; compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_u16); @@ -490,13 +676,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) { switch (feature_type) { case SLJIT_HAS_FPU: + case SLJIT_HAS_F64_AS_F32_PAIR: + case SLJIT_HAS_SIMD: #ifdef SLJIT_IS_FPU_AVAILABLE - return SLJIT_IS_FPU_AVAILABLE; + return (SLJIT_IS_FPU_AVAILABLE) != 0; #else /* Available by default. */ return 1; #endif + case SLJIT_SIMD_REGS_ARE_PAIRS: case SLJIT_HAS_CLZ: case SLJIT_HAS_CTZ: case SLJIT_HAS_REV: @@ -505,6 +694,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) case SLJIT_HAS_PREFETCH: case SLJIT_HAS_COPY_F32: case SLJIT_HAS_COPY_F64: + case SLJIT_HAS_ATOMIC: return 1; default: @@ -621,6 +811,10 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s case SLJIT_CLZ: case SLJIT_CTZ: case SLJIT_REV: + case SLJIT_REV_U16: + case SLJIT_REV_S16: + case SLJIT_REV_U32: + case SLJIT_REV_S32: case SLJIT_MUL: /* No form with immediate operand. */ break; @@ -657,9 +851,14 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s break; case SLJIT_ADDC: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD; - imm = get_imm(imm); - if (imm != INVALID_IMM) - return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); + imm2 = get_imm(imm); + if (imm2 != INVALID_IMM) + return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2); + if (flags & ARG2_IMM) { + imm = get_imm(~imm); + if (imm != INVALID_IMM) + return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); + } break; case SLJIT_SUB: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB; @@ -712,9 +911,12 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB; if (flags & ARG1_IMM) break; - imm = get_imm(imm); + imm2 = get_imm(imm); + if (imm2 != INVALID_IMM) + return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2); + imm = get_imm(~imm); if (imm != INVALID_IMM) - return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); + return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_AND: imm2 = get_imm(imm); @@ -793,8 +995,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s imm = arg2; arg2 = (arg1 == TMP_REG1) ? TMP_REG2 : TMP_REG1; FAIL_IF(load_immediate(compiler, (sljit_s32)arg2, imm)); - } - else { + } else { imm = arg1; arg1 = (arg2 == TMP_REG1) ? TMP_REG2 : TMP_REG1; FAIL_IF(load_immediate(compiler, (sljit_s32)arg1, imm)); @@ -842,9 +1043,28 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s FAIL_IF(push_inst32(compiler, RBIT | RN4(arg2) | RD4(dst) | RM4(arg2))); return push_inst32(compiler, CLZ | RN4(dst) | RD4(dst) | RM4(dst)); case SLJIT_REV: + case SLJIT_REV_U32: + case SLJIT_REV_S32: + SLJIT_ASSERT(arg1 == TMP_REG2); if (IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, REV | RD3(dst) | RN3(arg2)); return push_inst32(compiler, REV_W | RN4(arg2) | RD4(dst) | RM4(arg2)); + case SLJIT_REV_U16: + case SLJIT_REV_S16: + SLJIT_ASSERT(arg1 == TMP_REG2 && dst != TMP_REG2); + + flags &= 0xffff; + if (IS_2_LO_REGS(dst, arg2)) + FAIL_IF(push_inst16(compiler, REV16 | RD3(dst) | RN3(arg2))); + else + FAIL_IF(push_inst32(compiler, REV16_W | RN4(arg2) | RD4(dst) | RM4(arg2))); + + if (dst == TMP_REG1 || (arg2 == TMP_REG1 && flags == SLJIT_REV_U16)) + return SLJIT_SUCCESS; + + if (reg_map[dst] <= 7) + return push_inst16(compiler, (flags == SLJIT_REV_U16 ? UXTH : SXTH) | RD3(dst) | RN3(dst)); + return push_inst32(compiler, (flags == SLJIT_REV_U16 ? UXTH_W : SXTH_W) | RD4(dst) | RM4(dst)); case SLJIT_ADD: compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD; if (IS_3_LO_REGS(dst, arg1, arg2)) @@ -895,32 +1115,36 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s return push_inst16(compiler, EORS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, EOR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_MSHL: - FAIL_IF(push_inst32(compiler, ANDI | RD4(TMP_REG2) | RN4(arg2) | 0x1f)); - arg2 = TMP_REG2; + reg = (arg2 == TMP_REG1) ? TMP_REG1 : TMP_REG2; + FAIL_IF(push_inst32(compiler, ANDI | RD4(reg) | RN4(arg2) | 0x1f)); + arg2 = (sljit_uw)reg; /* fallthrough */ case SLJIT_SHL: if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, LSLS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, LSL_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_MLSHR: - FAIL_IF(push_inst32(compiler, ANDI | RD4(TMP_REG2) | RN4(arg2) | 0x1f)); - arg2 = TMP_REG2; + reg = (arg2 == TMP_REG1) ? TMP_REG1 : TMP_REG2; + FAIL_IF(push_inst32(compiler, ANDI | RD4(reg) | RN4(arg2) | 0x1f)); + arg2 = (sljit_uw)reg; /* fallthrough */ case SLJIT_LSHR: if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, LSRS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, LSR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_MASHR: - FAIL_IF(push_inst32(compiler, ANDI | RD4(TMP_REG2) | RN4(arg2) | 0x1f)); - arg2 = TMP_REG2; + reg = (arg2 == TMP_REG1) ? TMP_REG1 : TMP_REG2; + FAIL_IF(push_inst32(compiler, ANDI | RD4(reg) | RN4(arg2) | 0x1f)); + arg2 = (sljit_uw)reg; /* fallthrough */ case SLJIT_ASHR: if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, ASRS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, ASR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_ROTL: - FAIL_IF(push_inst32(compiler, RSB_WI | RD4(TMP_REG2) | RN4(arg2) | 0)); - arg2 = TMP_REG2; + reg = (arg2 == TMP_REG1) ? TMP_REG1 : TMP_REG2; + FAIL_IF(push_inst32(compiler, RSB_WI | RD4(reg) | RN4(arg2) | 0)); + arg2 = (sljit_uw)reg; /* fallthrough */ case SLJIT_ROTR: if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2)) @@ -1180,12 +1404,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) { - FAIL_IF(push_inst32(compiler, VPUSH | DD4(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1))); + FAIL_IF(push_inst32(compiler, VPUSH | VD4(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1))); } else { if (fsaveds > 0) - FAIL_IF(push_inst32(compiler, VPUSH | DD4(SLJIT_FS0) | ((sljit_uw)fsaveds << 1))); + FAIL_IF(push_inst32(compiler, VPUSH | VD4(SLJIT_FS0) | ((sljit_uw)fsaveds << 1))); if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) - FAIL_IF(push_inst32(compiler, VPUSH | DD4(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1))); + FAIL_IF(push_inst32(compiler, VPUSH | VD4(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1))); } } @@ -1262,17 +1486,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi switch (arg_types & SLJIT_ARG_MASK) { case SLJIT_ARG_TYPE_F64: if (offset != old_offset) - *remap_ptr++ = VMOV_F32 | SLJIT_32 | DD4(offset) | DM4(old_offset); + *remap_ptr++ = VMOV_F32 | SLJIT_32 | VD4(offset) | VM4(old_offset); old_offset++; offset++; break; case SLJIT_ARG_TYPE_F32: if (f32_offset != 0) { - *remap_ptr++ = VMOV_F32 | 0x20 | DD4(offset) | DM4(f32_offset); + *remap_ptr++ = VMOV_F32 | 0x20 | VD4(offset) | VM4(f32_offset); f32_offset = 0; } else { if (offset != old_offset) - *remap_ptr++ = VMOV_F32 | DD4(offset) | DM4(old_offset); + *remap_ptr++ = VMOV_F32 | VD4(offset) | VM4(old_offset); f32_offset = old_offset; old_offset++; } @@ -1406,12 +1630,12 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size)); if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) { - FAIL_IF(push_inst32(compiler, VPOP | DD4(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1))); + FAIL_IF(push_inst32(compiler, VPOP | VD4(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1))); } else { if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) - FAIL_IF(push_inst32(compiler, VPOP | DD4(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1))); + FAIL_IF(push_inst32(compiler, VPOP | VD4(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1))); if (fsaveds > 0) - FAIL_IF(push_inst32(compiler, VPOP | DD4(SLJIT_FS0) | ((sljit_uw)fsaveds << 1))); + FAIL_IF(push_inst32(compiler, VPOP | VD4(SLJIT_FS0) | ((sljit_uw)fsaveds << 1))); } local_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1) & 0x7; @@ -1710,22 +1934,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile break; case SLJIT_MOV_U8: flags = BYTE_SIZE; - if (src & SLJIT_IMM) + if (src == SLJIT_IMM) srcw = (sljit_u8)srcw; break; case SLJIT_MOV_S8: flags = BYTE_SIZE | SIGNED; - if (src & SLJIT_IMM) + if (src == SLJIT_IMM) srcw = (sljit_s8)srcw; break; case SLJIT_MOV_U16: flags = HALF_SIZE; - if (src & SLJIT_IMM) + if (src == SLJIT_IMM) srcw = (sljit_u16)srcw; break; case SLJIT_MOV_S16: flags = HALF_SIZE | SIGNED; - if (src & SLJIT_IMM) + if (src == SLJIT_IMM) srcw = (sljit_s16)srcw; break; default: @@ -1734,7 +1958,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile break; } - if (src & SLJIT_IMM) + if (src == SLJIT_IMM) FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG2, (sljit_uw)srcw)); else if (src & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, flags, dst_r, src, srcw, TMP_REG1)); @@ -1750,10 +1974,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2); } + SLJIT_COMPILE_ASSERT(WORD_SIZE == 0, word_size_must_be_0); flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0; + if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) + flags |= HALF_SIZE; + if (src & SLJIT_MEM) { - FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); + FAIL_IF(emit_op_mem(compiler, flags, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } @@ -1783,7 +2011,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile if (dst == TMP_REG1) flags |= UNUSED_RETURN; - if (src1 & SLJIT_IMM) + if (src1 == SLJIT_IMM) flags |= ARG1_IMM; else if (src1 & SLJIT_MEM) { emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src1, src1w, TMP_REG1); @@ -1792,7 +2020,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile else src1w = src1; - if (src2 & SLJIT_IMM) + if (src2 == SLJIT_IMM) flags |= ARG2_IMM; else if (src2 & SLJIT_MEM) { src2_reg = (!(flags & ARG1_IMM) && (src1w == TMP_REG1)) ? TMP_REG2 : TMP_REG1; @@ -1841,7 +2069,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * ADJUST_LOCAL_OFFSET(src3, src3w); - if (src3 & SLJIT_IMM) { + if (src3 == SLJIT_IMM) { src3w &= 0x1f; if (src3w == 0) @@ -1946,16 +2174,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg) { - CHECK_REG_INDEX(check_sljit_get_register_index(reg)); - return reg_map[reg]; -} + CHECK_REG_INDEX(check_sljit_get_register_index(type, reg)); -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) -{ - CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); - return (freg_map[reg] << 1); + if (type == SLJIT_GP_REGISTER) + return reg_map[reg]; + + if (type == SLJIT_FLOAT_REGISTER || type == SLJIT_SIMD_REG_64) + return freg_map[reg]; + + if (type != SLJIT_SIMD_REG_128) + return freg_map[reg] & ~0x1; + + return -1; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, @@ -1991,35 +2223,35 @@ static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, if ((arg & REG_MASK) && (argw & 0x3) == 0) { if (!(argw & ~0x3fc)) - return push_inst32(compiler, inst | 0x800000 | RN4(arg & REG_MASK) | DD4(reg) | ((sljit_uw)argw >> 2)); + return push_inst32(compiler, inst | 0x800000 | RN4(arg & REG_MASK) | VD4(reg) | ((sljit_uw)argw >> 2)); if (!(-argw & ~0x3fc)) - return push_inst32(compiler, inst | RN4(arg & REG_MASK) | DD4(reg) | ((sljit_uw)-argw >> 2)); + return push_inst32(compiler, inst | RN4(arg & REG_MASK) | VD4(reg) | ((sljit_uw)-argw >> 2)); } if (arg & REG_MASK) { if (emit_set_delta(compiler, TMP_REG1, arg & REG_MASK, argw) != SLJIT_ERR_UNSUPPORTED) { FAIL_IF(compiler->error); - return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg)); + return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | VD4(reg)); } imm = get_imm((sljit_uw)argw & ~(sljit_uw)0x3fc); if (imm != INVALID_IMM) { FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm)); - return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg) | (((sljit_uw)argw & 0x3fc) >> 2)); + return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | VD4(reg) | (((sljit_uw)argw & 0x3fc) >> 2)); } imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0x3fc); if (imm != INVALID_IMM) { argw = -argw; FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm)); - return push_inst32(compiler, inst | RN4(TMP_REG1) | DD4(reg) | (((sljit_uw)argw & 0x3fc) >> 2)); + return push_inst32(compiler, inst | RN4(TMP_REG1) | VD4(reg) | (((sljit_uw)argw & 0x3fc) >> 2)); } } FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)argw)); if (arg & REG_MASK) FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, (arg & REG_MASK)))); - return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg)); + return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | VD4(reg)); } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, @@ -2033,41 +2265,53 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp src = TMP_FREG1; } - FAIL_IF(push_inst32(compiler, VCVT_S32_F32 | (op & SLJIT_32) | DD4(TMP_FREG1) | DM4(src))); + FAIL_IF(push_inst32(compiler, VCVT_S32_F32 | (op & SLJIT_32) | VD4(TMP_FREG1) | VM4(src))); if (FAST_IS_REG(dst)) - return push_inst32(compiler, VMOV | (1 << 20) | RT4(dst) | DN4(TMP_FREG1)); + return push_inst32(compiler, VMOV | (1 << 20) | RT4(dst) | VN4(TMP_FREG1)); /* Store the integer value from a VFP register. */ return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw); } -static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, +static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; - op ^= SLJIT_32; - if (FAST_IS_REG(src)) - FAIL_IF(push_inst32(compiler, VMOV | RT4(src) | DN4(TMP_FREG1))); + FAIL_IF(push_inst32(compiler, VMOV | RT4(src) | VN4(TMP_FREG1))); else if (src & SLJIT_MEM) { /* Load the integer value into a VFP register. */ FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw)); } else { FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw)); - FAIL_IF(push_inst32(compiler, VMOV | RT4(TMP_REG1) | DN4(TMP_FREG1))); + FAIL_IF(push_inst32(compiler, VMOV | RT4(TMP_REG1) | VN4(TMP_FREG1))); } - FAIL_IF(push_inst32(compiler, VCVT_F32_S32 | (op & SLJIT_32) | DD4(dst_r) | DM4(TMP_FREG1))); + FAIL_IF(push_inst32(compiler, ins | VD4(dst_r) | VM4(TMP_FREG1))); if (dst & SLJIT_MEM) - return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw); + return emit_fop_mem(compiler, (ins & SLJIT_32), TMP_FREG1, dst, dstw); return SLJIT_SUCCESS; } +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + return sljit_emit_fop1_conv_f64_from_w(compiler, VCVT_F32_S32 | (~op & SLJIT_32), dst, dstw, src, srcw); +} + +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + return sljit_emit_fop1_conv_f64_from_w(compiler, VCVT_F32_U32 | (~op & SLJIT_32), dst, dstw, src, srcw); +} + static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) @@ -2075,17 +2319,23 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile op ^= SLJIT_32; if (src1 & SLJIT_MEM) { - emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w); + FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w)); src1 = TMP_FREG1; } if (src2 & SLJIT_MEM) { - emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w); + FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w)); src2 = TMP_FREG2; } - FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_32) | DD4(src1) | DM4(src2))); - return push_inst32(compiler, VMRS); + FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_32) | VD4(src1) | VM4(src2))); + FAIL_IF(push_inst32(compiler, VMRS)); + + if (GET_FLAG_TYPE(op) != SLJIT_UNORDERED_OR_EQUAL) + return SLJIT_SUCCESS; + + FAIL_IF(push_inst16(compiler, IT | (0x6 << 4) | 0x8)); + return push_inst16(compiler, CMP /* Rm, Rn = r0 */); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, @@ -2105,7 +2355,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil op ^= SLJIT_32; if (src & SLJIT_MEM) { - emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, dst_r, src, srcw); + FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, dst_r, src, srcw)); src = dst_r; } @@ -2113,19 +2363,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil case SLJIT_MOV_F64: if (src != dst_r) { if (dst_r != TMP_FREG1) - FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_32) | DD4(dst_r) | DM4(src))); + FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(src))); else dst_r = src; } break; case SLJIT_NEG_F64: - FAIL_IF(push_inst32(compiler, VNEG_F32 | (op & SLJIT_32) | DD4(dst_r) | DM4(src))); + FAIL_IF(push_inst32(compiler, VNEG_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(src))); break; case SLJIT_ABS_F64: - FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_32) | DD4(dst_r) | DM4(src))); + FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(src))); break; case SLJIT_CONV_F64_FROM_F32: - FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | (op & SLJIT_32) | DD4(dst_r) | DM4(src))); + FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(src))); op ^= SLJIT_32; break; } @@ -2152,27 +2402,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src1 & SLJIT_MEM) { - emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w); + FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w)); src1 = TMP_FREG1; } if (src2 & SLJIT_MEM) { - emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w); + FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w)); src2 = TMP_FREG2; } switch (GET_OPCODE(op)) { case SLJIT_ADD_F64: - FAIL_IF(push_inst32(compiler, VADD_F32 | (op & SLJIT_32) | DD4(dst_r) | DN4(src1) | DM4(src2))); + FAIL_IF(push_inst32(compiler, VADD_F32 | (op & SLJIT_32) | VD4(dst_r) | VN4(src1) | VM4(src2))); break; case SLJIT_SUB_F64: - FAIL_IF(push_inst32(compiler, VSUB_F32 | (op & SLJIT_32) | DD4(dst_r) | DN4(src1) | DM4(src2))); + FAIL_IF(push_inst32(compiler, VSUB_F32 | (op & SLJIT_32) | VD4(dst_r) | VN4(src1) | VM4(src2))); break; case SLJIT_MUL_F64: - FAIL_IF(push_inst32(compiler, VMUL_F32 | (op & SLJIT_32) | DD4(dst_r) | DN4(src1) | DM4(src2))); + FAIL_IF(push_inst32(compiler, VMUL_F32 | (op & SLJIT_32) | VD4(dst_r) | VN4(src1) | VM4(src2))); break; case SLJIT_DIV_F64: - FAIL_IF(push_inst32(compiler, VDIV_F32 | (op & SLJIT_32) | DD4(dst_r) | DN4(src1) | DM4(src2))); + FAIL_IF(push_inst32(compiler, VDIV_F32 | (op & SLJIT_32) | VD4(dst_r) | VN4(src1) | VM4(src2))); break; + case SLJIT_COPYSIGN_F64: + FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | VN4(src2) | RT4(TMP_REG1) | ((op & SLJIT_32) ? (1 << 7) : 0))); + FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(src1))); + FAIL_IF(push_inst32(compiler, CMPI_W | RN4(TMP_REG1) | 0)); + FAIL_IF(push_inst16(compiler, IT | (0xb << 4) | 0x8)); + return push_inst32(compiler, VNEG_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(dst_r)); } if (!(dst & SLJIT_MEM)) @@ -2180,6 +2436,74 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f32 value) +{ +#if defined(__ARM_NEON) && __ARM_NEON + sljit_u32 exp; + sljit_ins ins; +#endif /* NEON */ + union { + sljit_u32 imm; + sljit_f32 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset32(compiler, freg, value)); + + u.value = value; + +#if defined(__ARM_NEON) && __ARM_NEON + if ((u.imm << (32 - 19)) == 0) { + exp = (u.imm >> (23 + 2)) & 0x3f; + + if (exp == 0x20 || exp == 0x1f) { + ins = ((u.imm >> 24) & 0x80) | ((u.imm >> 19) & 0x7f); + return push_inst32(compiler, (VMOV_F32 ^ (1 << 6)) | ((ins & 0xf0) << 12) | VD4(freg) | (ins & 0xf)); + } + } +#endif /* NEON */ + + FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm)); + return push_inst32(compiler, VMOV | VN4(freg) | RT4(TMP_REG1)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f64 value) +{ +#if defined(__ARM_NEON) && __ARM_NEON + sljit_u32 exp; + sljit_ins ins; +#endif /* NEON */ + union { + sljit_u32 imm[2]; + sljit_f64 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset64(compiler, freg, value)); + + u.value = value; + +#if defined(__ARM_NEON) && __ARM_NEON + if (u.imm[0] == 0 && (u.imm[1] << (64 - 48)) == 0) { + exp = (u.imm[1] >> ((52 - 32) + 2)) & 0x1ff; + + if (exp == 0x100 || exp == 0xff) { + ins = ((u.imm[1] >> (56 - 32)) & 0x80) | ((u.imm[1] >> (48 - 32)) & 0x7f); + return push_inst32(compiler, (VMOV_F32 ^ (1 << 6)) | (1 << 8) | ((ins & 0xf0) << 12) | VD4(freg) | (ins & 0xf)); + } + } +#endif /* NEON */ + + FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0])); + if (u.imm[0] == u.imm[1]) + return push_inst32(compiler, VMOV2 | RN4(TMP_REG1) | RT4(TMP_REG1) | VM4(freg)); + + FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1])); + return push_inst32(compiler, VMOV2 | RN4(TMP_REG2) | RT4(TMP_REG1) | VM4(freg)); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 freg, sljit_s32 reg) { @@ -2193,9 +2517,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compi reg2 = REG_PAIR_SECOND(reg); reg = REG_PAIR_FIRST(reg); - inst = VMOV2 | RN4(reg) | RT4(reg2) | DM4(freg); + inst = VMOV2 | RN4(reg) | RT4(reg2) | VM4(freg); } else { - inst = VMOV | DN4(freg) | RT4(reg); + inst = VMOV | VN4(freg) | RT4(reg); if (!(op & SLJIT_32)) inst |= 1 << 7; @@ -2215,15 +2539,17 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type) { switch (type) { case SLJIT_EQUAL: + case SLJIT_ATOMIC_STORED: case SLJIT_F_EQUAL: case SLJIT_ORDERED_EQUAL: - case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */ + case SLJIT_UNORDERED_OR_EQUAL: return 0x0; case SLJIT_NOT_EQUAL: + case SLJIT_ATOMIC_NOT_STORED: case SLJIT_F_NOT_EQUAL: case SLJIT_UNORDERED_OR_NOT_EQUAL: - case SLJIT_ORDERED_NOT_EQUAL: /* Not supported. */ + case SLJIT_ORDERED_NOT_EQUAL: return 0x1; case SLJIT_CARRY: @@ -2327,7 +2653,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); type &= 0xff; - PTR_FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0)); if (type < SLJIT_JUMP) { jump->flags |= IS_COND; cc = get_cc(compiler, type); @@ -2343,6 +2668,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile PTR_FAIL_IF(push_inst16(compiler, BLX | RN3(TMP_REG1))); } + /* Maximum number of instructions required for generating a constant. */ + compiler->size += JUMP_MAX_SIZE - 1; return jump; } @@ -2498,18 +2825,18 @@ static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit switch (arg_types & SLJIT_ARG_MASK) { case SLJIT_ARG_TYPE_F64: if (offset != new_offset) - FAIL_IF(push_inst32(compiler, VMOV_F32 | SLJIT_32 | DD4(new_offset) | DM4(offset))); + FAIL_IF(push_inst32(compiler, VMOV_F32 | SLJIT_32 | VD4(new_offset) | VM4(offset))); new_offset++; offset++; break; case SLJIT_ARG_TYPE_F32: if (f32_offset != 0) { - FAIL_IF(push_inst32(compiler, VMOV_F32 | 0x400000 | DD4(f32_offset) | DM4(offset))); + FAIL_IF(push_inst32(compiler, VMOV_F32 | 0x400000 | VD4(f32_offset) | VM4(offset))); f32_offset = 0; } else { if (offset != new_offset) - FAIL_IF(push_inst32(compiler, VMOV_F32 | 0x400000 | DD4(new_offset) | DM4(offset))); + FAIL_IF(push_inst32(compiler, VMOV_F32 | 0x400000 | VD4(new_offset) | VM4(offset))); f32_offset = new_offset; new_offset++; } @@ -2591,7 +2918,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi SLJIT_ASSERT(reg_map[TMP_REG1] != 14); - if (!(src & SLJIT_IMM)) { + if (src != SLJIT_IMM) { if (FAST_IS_REG(src)) { SLJIT_ASSERT(reg_map[src] != 14); return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(src)); @@ -2608,8 +2935,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0)); jump->u.target = (sljit_uw)srcw; - FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0)); jump->addr = compiler->size; + /* Maximum number of instructions required for generating a constant. */ + compiler->size += JUMP_MAX_SIZE - 1; return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1)); } @@ -2690,8 +3018,8 @@ static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *com if (FAST_IS_REG(src)) { if (op & SLJIT_32) - return push_inst32(compiler, VMOV | (1 << 20) | DN4(src) | RT4(SLJIT_R0)); - return push_inst32(compiler, VMOV2 | (1 << 20) | DM4(src) | RT4(SLJIT_R0) | RN4(SLJIT_R1)); + return push_inst32(compiler, VMOV | (1 << 20) | VN4(src) | RT4(SLJIT_R0)); + return push_inst32(compiler, VMOV2 | (1 << 20) | VM4(src) | RT4(SLJIT_R0) | RN4(SLJIT_R1)); } SLJIT_SKIP_CHECKS(compiler); @@ -2756,23 +3084,47 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst_r)); } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, - sljit_s32 src, sljit_sw srcw) + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_reg) { sljit_uw cc, tmp; CHECK_ERROR(); - CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); + CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg)); + + ADJUST_LOCAL_OFFSET(src1, src1w); + + if (src2_reg != dst_reg && src1 == dst_reg) { + src1 = src2_reg; + src1w = 0; + src2_reg = dst_reg; + type ^= 0x1; + } + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, (src2_reg != dst_reg) ? dst_reg : TMP_REG1, src1, src1w, TMP_REG2)); + + if (src2_reg != dst_reg) { + src1 = src2_reg; + src1w = 0; + type ^= 0x1; + } else { + src1 = TMP_REG1; + src1w = 0; + } + } else if (dst_reg != src2_reg) + FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(dst_reg, src2_reg))); cc = get_cc(compiler, type & ~SLJIT_32); - if (!(src & SLJIT_IMM)) { + if (src1 != SLJIT_IMM) { FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); - return push_inst16(compiler, MOV | SET_REGS44(dst_reg, src)); + return push_inst16(compiler, MOV | SET_REGS44(dst_reg, src1)); } - tmp = (sljit_uw) srcw; + tmp = (sljit_uw)src1w; if (tmp < 0x10000) { /* set low 16 bits, set hi 16 bits to 0. */ @@ -2781,13 +3133,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil | COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff)); } - tmp = get_imm((sljit_uw)srcw); + tmp = get_imm((sljit_uw)src1w); if (tmp != INVALID_IMM) { FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); return push_inst32(compiler, MOV_WI | RD4(dst_reg) | tmp); } - tmp = get_imm(~(sljit_uw)srcw); + tmp = get_imm(~(sljit_uw)src1w); if (tmp != INVALID_IMM) { FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); return push_inst32(compiler, MVN_WI | RD4(dst_reg) | tmp); @@ -2795,13 +3147,43 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil FAIL_IF(push_inst16(compiler, IT | (cc << 4) | ((cc & 0x1) << 3) | 0x4)); - tmp = (sljit_uw) srcw; + tmp = (sljit_uw)src1w; FAIL_IF(push_inst32(compiler, MOVW | RD4(dst_reg) | COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff))); return push_inst32(compiler, MOVT | RD4(dst_reg) | COPY_BITS(tmp, 12 + 16, 16, 4) | COPY_BITS(tmp, 11 + 16, 26, 1) | COPY_BITS(tmp, 8 + 16, 12, 3) | ((tmp & 0xff0000) >> 16)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_freg) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg)); + + ADJUST_LOCAL_OFFSET(src1, src1w); + + type ^= SLJIT_32; + + if (dst_freg != src2_freg) { + if (dst_freg == src1) { + src1 = src2_freg; + src1w = 0; + type ^= 0x1; + } else + FAIL_IF(push_inst32(compiler, VMOV_F32 | (type & SLJIT_32) | VD4(dst_freg) | VM4(src2_freg))); + } + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_fop_mem(compiler, (type & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w)); + src1 = TMP_FREG1; + } + + FAIL_IF(push_inst16(compiler, IT | (get_cc(compiler, type & ~SLJIT_32) << 4) | 0x8)); + return push_inst32(compiler, VMOV_F32 | (type & SLJIT_32) | VD4(dst_freg) | VM4(src1)); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) @@ -2815,7 +3197,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile if (!(reg & REG_PAIR_MASK)) return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); - if (type & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32)) { + if (type & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)) { if ((mem & REG_MASK) == 0) { if ((memw & 0xfff) >= (0x1000 - SSIZE_OF(sw))) { imm = get_imm((sljit_uw)((memw + 0x1000) & ~0xfff)); @@ -2826,7 +3208,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile imm = get_imm((sljit_uw)(memw & ~0xfff)); if (imm != INVALID_IMM) - memw &= 0xff; + memw &= 0xfff; } if (imm == INVALID_IMM) { @@ -3103,11 +3485,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil CHECK_ERROR(); CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); - if (type & SLJIT_MEM_UNALIGNED_32) + if (type & SLJIT_MEM_ALIGNED_32) return emit_fop_mem(compiler, ((type ^ SLJIT_32) & SLJIT_32) | ((type & SLJIT_MEM_STORE) ? 0 : FPU_LOAD), freg, mem, memw); if (type & SLJIT_MEM_STORE) { - FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | DN4(freg) | RT4(TMP_REG2))); + FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | VN4(freg) | RT4(TMP_REG2))); if (type & SLJIT_32) return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw, TMP_REG1); @@ -3116,13 +3498,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil mem |= SLJIT_MEM; FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw, TMP_REG1)); - FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | DN4(freg) | 0x80 | RT4(TMP_REG2))); + FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | VN4(freg) | 0x80 | RT4(TMP_REG2))); return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw + 4, TMP_REG1); } if (type & SLJIT_32) { FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1)); - return push_inst32(compiler, VMOV | DN4(freg) | RT4(TMP_REG2)); + return push_inst32(compiler, VMOV | VN4(freg) | RT4(TMP_REG2)); } FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4)); @@ -3130,51 +3512,756 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1)); FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, mem, memw + 4, TMP_REG1)); - return push_inst32(compiler, VMOV2 | DM4(freg) | RT4(TMP_REG2) | RN4(TMP_REG1)); + return push_inst32(compiler, VMOV2 | VM4(freg) | RT4(TMP_REG2) | RN4(TMP_REG1)); } -#undef FPU_LOAD - -SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) +static sljit_s32 sljit_emit_simd_mem_offset(struct sljit_compiler *compiler, sljit_s32 *mem_ptr, sljit_sw memw) { - struct sljit_const *const_; - sljit_s32 dst_r; + sljit_uw imm; + sljit_s32 mem = *mem_ptr; - CHECK_ERROR_PTR(); - CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); - ADJUST_LOCAL_OFFSET(dst, dstw); + if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { + *mem_ptr = TMP_REG1; + return push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(mem & REG_MASK) | RM4(OFFS_REG(mem)) | ((sljit_uw)(memw & 0x3) << 6)); + } - const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); - PTR_FAIL_IF(!const_); - set_const(const_, compiler); + if (SLJIT_UNLIKELY(!(mem & REG_MASK))) { + *mem_ptr = TMP_REG1; + return load_immediate(compiler, TMP_REG1, (sljit_uw)memw); + } - dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; - PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, (sljit_uw)init_value)); + mem &= REG_MASK; - if (dst & SLJIT_MEM) - PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2)); - return const_; + if (memw == 0) { + *mem_ptr = mem; + return SLJIT_SUCCESS; + } + + *mem_ptr = TMP_REG1; + imm = get_imm((sljit_uw)(memw < 0 ? -memw : memw)); + + if (imm != INVALID_IMM) + return push_inst32(compiler, ((memw < 0) ? SUB_WI : ADD_WI) | RD4(TMP_REG1) | RN4(mem) | imm); + + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw)); + return push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, mem)); } -SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +static SLJIT_INLINE sljit_s32 simd_get_quad_reg_index(sljit_s32 freg) { - struct sljit_put_label *put_label; - sljit_s32 dst_r; + freg += freg & 0x1; - CHECK_ERROR_PTR(); - CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw)); - ADJUST_LOCAL_OFFSET(dst, dstw); + SLJIT_ASSERT((freg_map[freg] & 0x1) == (freg <= SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS)); - put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label)); - PTR_FAIL_IF(!put_label); - set_put_label(put_label, compiler, 0); + if (freg <= SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS) + freg--; - dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; - PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, 0)); + return freg; +} - if (dst & SLJIT_MEM) - PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2)); - return put_label; +#define SLJIT_QUAD_OTHER_HALF(freg) ((((freg) & 0x1) << 1) - 1) + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 srcdst, sljit_sw srcdstw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_s32 alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type); + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw)); + + ADJUST_LOCAL_OFFSET(srcdst, srcdstw); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 4) + freg = simd_get_quad_reg_index(freg); + + if (!(srcdst & SLJIT_MEM)) { + if (reg_size == 4) + srcdst = simd_get_quad_reg_index(srcdst); + + if (type & SLJIT_SIMD_STORE) + ins = VD4(srcdst) | VN4(freg) | VM4(freg); + else + ins = VD4(freg) | VN4(srcdst) | VM4(srcdst); + + if (reg_size == 4) + ins |= (sljit_ins)1 << 6; + + return push_inst32(compiler, VORR | ins); + } + + FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw)); + + if (elem_size > 3) + elem_size = 3; + + ins = ((type & SLJIT_SIMD_STORE) ? VST1 : VLD1) | VD4(freg) + | (sljit_ins)((reg_size == 3) ? (0x7 << 8) : (0xa << 8)); + + SLJIT_ASSERT(reg_size >= alignment); + + if (alignment == 3) + ins |= 0x10; + else if (alignment >= 4) + ins |= 0x20; + + return push_inst32(compiler, ins | RN4(srcdst) | ((sljit_ins)elem_size) << 6 | 0xf); +} + +static sljit_ins simd_get_imm(sljit_s32 elem_size, sljit_uw value) +{ + sljit_ins result; + + if (elem_size > 1 && (sljit_u16)value == (value >> 16)) { + elem_size = 1; + value = (sljit_u16)value; + } + + if (elem_size == 1 && (sljit_u8)value == (value >> 8)) { + elem_size = 0; + value = (sljit_u8)value; + } + + switch (elem_size) { + case 0: + SLJIT_ASSERT(value <= 0xff); + result = 0xe00; + break; + case 1: + SLJIT_ASSERT(value <= 0xffff); + result = 0; + + while (1) { + if (value <= 0xff) { + result |= 0x800; + break; + } + + if ((value & 0xff) == 0) { + value >>= 8; + result |= 0xa00; + break; + } + + if (result != 0) + return ~(sljit_ins)0; + + value ^= (sljit_uw)0xffff; + result = (1 << 5); + } + break; + default: + SLJIT_ASSERT(value <= 0xffffffff); + result = 0; + + while (1) { + if (value <= 0xff) { + result |= 0x000; + break; + } + + if ((value & ~(sljit_uw)0xff00) == 0) { + value >>= 8; + result |= 0x200; + break; + } + + if ((value & ~(sljit_uw)0xff0000) == 0) { + value >>= 16; + result |= 0x400; + break; + } + + if ((value & ~(sljit_uw)0xff000000) == 0) { + value >>= 24; + result |= 0x600; + break; + } + + if ((value & (sljit_uw)0xff) == 0xff && (value >> 16) == 0) { + value >>= 8; + result |= 0xc00; + break; + } + + if ((value & (sljit_uw)0xffff) == 0xffff && (value >> 24) == 0) { + value >>= 16; + result |= 0xd00; + break; + } + + if (result != 0) + return ~(sljit_ins)0; + + value = ~value; + result = (1 << 5); + } + break; + } + + return ((sljit_ins)value & 0xf) | (((sljit_ins)value & 0x70) << 12) | (((sljit_ins)value & 0x80) << 21) | result; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins, imm; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw)); + + ADJUST_LOCAL_OFFSET(src, srcw); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 4) + freg = simd_get_quad_reg_index(freg); + + if (src == SLJIT_IMM && srcw == 0) + return push_inst32(compiler, VMOV_i | ((reg_size == 4) ? (1 << 6) : 0) | VD4(freg)); + + if (SLJIT_UNLIKELY(elem_size == 3)) { + SLJIT_ASSERT(type & SLJIT_SIMD_FLOAT); + + if (src & SLJIT_MEM) { + FAIL_IF(emit_fop_mem(compiler, FPU_LOAD | SLJIT_32, freg, src, srcw)); + src = freg; + } else if (freg != src) + FAIL_IF(push_inst32(compiler, VORR | VD4(freg) | VN4(src) | VM4(src))); + + freg += SLJIT_QUAD_OTHER_HALF(freg); + + if (freg != src) + return push_inst32(compiler, VORR | VD4(freg) | VN4(src) | VM4(src)); + return SLJIT_SUCCESS; + } + + if (src & SLJIT_MEM) { + FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw)); + + ins = (sljit_ins)(elem_size << 6); + + if (reg_size == 4) + ins |= 1 << 5; + + return push_inst32(compiler, VLD1_r | ins | VD4(freg) | RN4(src) | 0xf); + } + + if (type & SLJIT_SIMD_FLOAT) { + SLJIT_ASSERT(elem_size == 2); + ins = ((sljit_ins)freg_ebit_map[src] << (16 + 2 + 1)) | ((sljit_ins)1 << (16 + 2)); + + if (reg_size == 4) + ins |= (sljit_ins)1 << 6; + + return push_inst32(compiler, VDUP_s | ins | VD4(freg) | (sljit_ins)freg_map[src]); + } + + if (src == SLJIT_IMM) { + if (elem_size < 2) + srcw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1; + + imm = simd_get_imm(elem_size, (sljit_uw)srcw); + + if (imm != ~(sljit_ins)0) { + if (reg_size == 4) + imm |= (sljit_ins)1 << 6; + + return push_inst32(compiler, VMOV_i | imm | VD4(freg)); + } + + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw)); + src = TMP_REG1; + } + + switch (elem_size) { + case 0: + ins = 1 << 22; + break; + case 1: + ins = 1 << 5; + break; + default: + ins = 0; + break; + } + + if (reg_size == 4) + ins |= (sljit_ins)1 << 21; + + return push_inst32(compiler, VDUP | ins | VN4(freg) | RT4(src)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, sljit_s32 lane_index, + sljit_s32 srcdst, sljit_sw srcdstw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw)); + + ADJUST_LOCAL_OFFSET(srcdst, srcdstw); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 4) + freg = simd_get_quad_reg_index(freg); + + if (type & SLJIT_SIMD_LANE_ZERO) { + ins = (reg_size == 3) ? 0 : ((sljit_ins)1 << 6); + + if (type & SLJIT_SIMD_FLOAT) { + if (elem_size == 3 && !(srcdst & SLJIT_MEM)) { + if (lane_index == 1) + freg += SLJIT_QUAD_OTHER_HALF(freg); + + if (srcdst != freg) + FAIL_IF(push_inst32(compiler, VORR | VD4(freg) | VN4(srcdst) | VM4(srcdst))); + + freg += SLJIT_QUAD_OTHER_HALF(freg); + return push_inst32(compiler, VMOV_i | VD4(freg)); + } + + if (srcdst == freg || (elem_size == 3 && srcdst == (freg + SLJIT_QUAD_OTHER_HALF(freg)))) { + FAIL_IF(push_inst32(compiler, VORR | ins | VD4(TMP_FREG2) | VN4(freg) | VM4(freg))); + srcdst = TMP_FREG2; + srcdstw = 0; + } + } + + FAIL_IF(push_inst32(compiler, VMOV_i | ins | VD4(freg))); + } + + if (reg_size == 4 && lane_index >= (0x8 >> elem_size)) { + lane_index -= (0x8 >> elem_size); + freg += SLJIT_QUAD_OTHER_HALF(freg); + } + + if (srcdst & SLJIT_MEM) { + if (elem_size == 3) + return emit_fop_mem(compiler, ((type & SLJIT_SIMD_STORE) ? 0 : FPU_LOAD) | SLJIT_32, freg, srcdst, srcdstw); + + FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw)); + + lane_index = lane_index << elem_size; + ins = (sljit_ins)((elem_size << 10) | (lane_index << 5)); + return push_inst32(compiler, ((type & SLJIT_SIMD_STORE) ? VST1_s : VLD1_s) | ins | VD4(freg) | RN4(srcdst) | 0xf); + } + + if (type & SLJIT_SIMD_FLOAT) { + if (elem_size == 3) { + if (type & SLJIT_SIMD_STORE) + return push_inst32(compiler, VORR | VD4(srcdst) | VN4(freg) | VM4(freg)); + return push_inst32(compiler, VMOV_F32 | SLJIT_32 | VD4(freg) | VM4(srcdst)); + } + + if (type & SLJIT_SIMD_STORE) { + if (freg_ebit_map[freg] == 0) { + if (lane_index == 1) + freg = SLJIT_F64_SECOND(freg); + + return push_inst32(compiler, VMOV_F32 | VD4(srcdst) | VM4(freg)); + } + + FAIL_IF(push_inst32(compiler, VMOV_s | (1 << 20) | ((sljit_ins)lane_index << 21) | VN4(freg) | RT4(TMP_REG1))); + return push_inst32(compiler, VMOV | VN4(srcdst) | RT4(TMP_REG1)); + } + + FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | VN4(srcdst) | RT4(TMP_REG1))); + return push_inst32(compiler, VMOV_s | ((sljit_ins)lane_index << 21) | VN4(freg) | RT4(TMP_REG1)); + } + + if (srcdst == SLJIT_IMM) { + if (elem_size < 2) + srcdstw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1; + + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcdstw)); + srcdst = TMP_REG1; + } + + if (elem_size == 0) + ins = 0x400000; + else if (elem_size == 1) + ins = 0x20; + else + ins = 0; + + lane_index = lane_index << elem_size; + ins |= (sljit_ins)(((lane_index & 0x4) << 19) | ((lane_index & 0x3) << 5)); + + if (type & SLJIT_SIMD_STORE) { + ins |= (1 << 20); + + if (elem_size < 2 && !(type & SLJIT_SIMD_LANE_SIGNED)) + ins |= (1 << 23); + } + + return push_inst32(compiler, VMOV_s | ins | VN4(freg) | RT4(srcdst)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_s32 src_lane_index) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index)); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 4) { + freg = simd_get_quad_reg_index(freg); + src = simd_get_quad_reg_index(src); + + if (src_lane_index >= (0x8 >> elem_size)) { + src_lane_index -= (0x8 >> elem_size); + src += SLJIT_QUAD_OTHER_HALF(src); + } + } + + if (elem_size == 3) { + if (freg != src) + FAIL_IF(push_inst32(compiler, VORR | VD4(freg) | VN4(src) | VM4(src))); + + freg += SLJIT_QUAD_OTHER_HALF(freg); + + if (freg != src) + return push_inst32(compiler, VORR | VD4(freg) | VN4(src) | VM4(src)); + return SLJIT_SUCCESS; + } + + ins = ((((sljit_ins)src_lane_index << 1) | 1) << (16 + elem_size)); + + if (reg_size == 4) + ins |= (sljit_ins)1 << 6; + + return push_inst32(compiler, VDUP_s | ins | VD4(freg) | VM4(src)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type); + sljit_s32 dst_reg; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw)); + + ADJUST_LOCAL_OFFSET(src, srcw); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size != 2 || elem2_size != 3)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 4) + freg = simd_get_quad_reg_index(freg); + + if (src & SLJIT_MEM) { + FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw)); + if (reg_size == 4 && elem2_size - elem_size == 1) + FAIL_IF(push_inst32(compiler, VLD1 | (0x7 << 8) | VD4(freg) | RN4(src) | 0xf)); + else + FAIL_IF(push_inst32(compiler, VLD1_s | (sljit_ins)((reg_size - elem2_size + elem_size) << 10) | VD4(freg) | RN4(src) | 0xf)); + src = freg; + } else if (reg_size == 4) + src = simd_get_quad_reg_index(src); + + if (!(type & SLJIT_SIMD_FLOAT)) { + dst_reg = (reg_size == 4) ? freg : TMP_FREG2; + + do { + FAIL_IF(push_inst32(compiler, VSHLL | ((type & SLJIT_SIMD_EXTEND_SIGNED) ? 0 : (1 << 28)) + | ((sljit_ins)1 << (19 + elem_size)) | VD4(dst_reg) | VM4(src))); + src = dst_reg; + } while (++elem_size < elem2_size); + + if (dst_reg == TMP_FREG2) + return push_inst32(compiler, VORR | VD4(freg) | VN4(TMP_FREG2) | VM4(TMP_FREG2)); + return SLJIT_SUCCESS; + } + + /* No SIMD variant, must use VFP instead. */ + SLJIT_ASSERT(reg_size == 4); + + if (freg == src) { + freg += SLJIT_QUAD_OTHER_HALF(freg); + FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | VD4(freg) | VM4(src) | 0x20)); + freg += SLJIT_QUAD_OTHER_HALF(freg); + return push_inst32(compiler, VCVT_F64_F32 | VD4(freg) | VM4(src)); + } + + FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | VD4(freg) | VM4(src))); + freg += SLJIT_QUAD_OTHER_HALF(freg); + return push_inst32(compiler, VCVT_F64_F32 | VD4(freg) | VM4(src) | 0x20); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 dst, sljit_sw dstw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins, imms; + sljit_s32 dst_r; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw)); + + ADJUST_LOCAL_OFFSET(dst, dstw); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + switch (elem_size) { + case 0: + imms = 0x243219; + ins = VSHR | (1 << 28) | (0x9 << 16); + break; + case 1: + imms = (reg_size == 4) ? 0x243219 : 0x2231; + ins = VSHR | (1 << 28) | (0x11 << 16); + break; + case 2: + imms = (reg_size == 4) ? 0x2231 : 0x21; + ins = VSHR | (1 << 28) | (0x21 << 16); + break; + default: + imms = 0x21; + ins = VSHR | (1 << 28) | (0x1 << 16) | (1 << 7); + break; + } + + if (reg_size == 4) { + freg = simd_get_quad_reg_index(freg); + ins |= (sljit_ins)1 << 6; + } + + SLJIT_ASSERT((freg_map[TMP_FREG2] & 0x1) == 0); + FAIL_IF(push_inst32(compiler, ins | VD4(TMP_FREG2) | VM4(freg))); + + if (reg_size == 4 && elem_size > 0) + FAIL_IF(push_inst32(compiler, VMOVN | ((sljit_ins)(elem_size - 1) << 18) | VD4(TMP_FREG2) | VM4(TMP_FREG2))); + + ins = (reg_size == 4 && elem_size == 0) ? (1 << 6) : 0; + + while (imms >= 0x100) { + FAIL_IF(push_inst32(compiler, VSRA | (1 << 28) | ins | ((imms & 0xff) << 16) | VD4(TMP_FREG2) | VM4(TMP_FREG2))); + imms >>= 8; + } + + FAIL_IF(push_inst32(compiler, VSRA | (1 << 28) | ins | (1 << 7) | (imms << 16) | VD4(TMP_FREG2) | VM4(TMP_FREG2))); + + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; + FAIL_IF(push_inst32(compiler, VMOV_s | (1 << 20) | (1 << 23) | (0x2 << 21) | RT4(dst_r) | VN4(TMP_FREG2))); + + if (reg_size == 4 && elem_size == 0) { + SLJIT_ASSERT(freg_map[TMP_FREG2] + 1 == freg_map[TMP_FREG1]); + FAIL_IF(push_inst32(compiler, VMOV_s | (1 << 20) | (1 << 23) | (0x2 << 21) | RT4(TMP_REG2)| VN4(TMP_FREG1))); + FAIL_IF(push_inst32(compiler, ORR_W | RD4(dst_r) | RN4(dst_r) | RM4(TMP_REG2) | (0x2 << 12))); + } + + if (dst_r == TMP_REG1) + return emit_op_mem(compiler, STORE | WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg)); + + if (reg_size != 3 && reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + switch (SLJIT_SIMD_GET_OPCODE(type)) { + case SLJIT_SIMD_OP2_AND: + ins = VAND; + break; + case SLJIT_SIMD_OP2_OR: + ins = VORR; + break; + case SLJIT_SIMD_OP2_XOR: + ins = VEOR; + break; + } + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 4) { + dst_freg = simd_get_quad_reg_index(dst_freg); + src1_freg = simd_get_quad_reg_index(src1_freg); + src2_freg = simd_get_quad_reg_index(src2_freg); + ins |= (sljit_ins)1 << 6; + } + + return push_inst32(compiler, ins | VD4(dst_freg) | VN4(src1_freg) | VM4(src2_freg)); +} + +#undef FPU_LOAD + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 mem_reg) +{ + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); + + switch (GET_OPCODE(op)) { + case SLJIT_MOV_U8: + ins = LDREXB; + break; + case SLJIT_MOV_U16: + ins = LDREXH; + break; + default: + ins = LDREX; + break; + } + + return push_inst32(compiler, ins | RN4(mem_reg) | RT4(dst_reg)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_reg, + sljit_s32 mem_reg, + sljit_s32 temp_reg) +{ + sljit_ins ins; + + /* temp_reg == mem_reg is undefined so use another temp register */ + SLJIT_UNUSED_ARG(temp_reg); + + CHECK_ERROR(); + CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg)); + + switch (GET_OPCODE(op)) { + case SLJIT_MOV_U8: + ins = STREXB | RM4(TMP_REG1); + break; + case SLJIT_MOV_U16: + ins = STREXH | RM4(TMP_REG1); + break; + default: + ins = STREX | RD4(TMP_REG1); + break; + } + + FAIL_IF(push_inst32(compiler, ins | RN4(mem_reg) | RT4(src_reg))); + if (op & SLJIT_SET_ATOMIC_STORED) + return push_inst32(compiler, CMPI_W | RN4(TMP_REG1)); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) +{ + struct sljit_const *const_; + sljit_s32 dst_r; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); + PTR_FAIL_IF(!const_); + set_const(const_, compiler); + + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; + PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, (sljit_uw)init_value)); + + if (dst & SLJIT_MEM) + PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2)); + return const_; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +{ + struct sljit_jump *jump; + sljit_s32 dst_r; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_mov_addr(jump, compiler, 0); + + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; + PTR_FAIL_IF(push_inst16(compiler, RDN3(dst_r))); + compiler->size += 3; + + if (dst & SLJIT_MEM) + PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2)); + return jump; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeLOONGARCH_64.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeLOONGARCH_64.c new file mode 100644 index 00000000000..a6fd044855d --- /dev/null +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeLOONGARCH_64.c @@ -0,0 +1,3158 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) +{ + return "LOONGARCH" SLJIT_CPUINFO; +} + +typedef sljit_u32 sljit_ins; + +#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) +#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) +#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4) +#define TMP_ZERO 0 + +/* Flags are kept in volatile registers. */ +#define EQUAL_FLAG (SLJIT_NUMBER_OF_REGISTERS + 5) +#define RETURN_ADDR_REG TMP_REG2 +#define OTHER_FLAG (SLJIT_NUMBER_OF_REGISTERS + 6) + +#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) +#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) + +static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = { + 0, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 22, 31, 30, 29, 28, 27, 26, 25, 24, 23, 3, 13, 1, 14, 12, 15 +}; + +static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { + 0, 0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 31, 30, 29, 28, 27, 26, 25, 24, 8, 9 +}; + +/* --------------------------------------------------------------------- */ +/* Instrucion forms */ +/* --------------------------------------------------------------------- */ + +/* +LoongArch instructions are 32 bits wide, belonging to 9 basic instruction formats (and variants of them): + +| Format name | Composition | +| 2R | Opcode + Rj + Rd | +| 3R | Opcode + Rk + Rj + Rd | +| 4R | Opcode + Ra + Rk + Rj + Rd | +| 2RI8 | Opcode + I8 + Rj + Rd | +| 2RI12 | Opcode + I12 + Rj + Rd | +| 2RI14 | Opcode + I14 + Rj + Rd | +| 2RI16 | Opcode + I16 + Rj + Rd | +| 1RI21 | Opcode + I21L + Rj + I21H | +| I26 | Opcode + I26L + I26H | + +Rd is the destination register operand, while Rj, Rk and Ra (“a” stands for “additional”) are the source register operands. +I8/I12/I14/I16/I21/I26 are immediate operands of respective width. The longer I21 and I26 are stored in separate higher and +lower parts in the instruction word, denoted by the “L” and “H” suffixes. */ + +#define RD(rd) ((sljit_ins)reg_map[rd]) +#define RJ(rj) ((sljit_ins)reg_map[rj] << 5) +#define RK(rk) ((sljit_ins)reg_map[rk] << 10) +#define RA(ra) ((sljit_ins)reg_map[ra] << 15) + +#define FD(fd) ((sljit_ins)reg_map[fd]) +#define FRD(fd) ((sljit_ins)freg_map[fd]) +#define FRJ(fj) ((sljit_ins)freg_map[fj] << 5) +#define FRK(fk) ((sljit_ins)freg_map[fk] << 10) +#define FRA(fa) ((sljit_ins)freg_map[fa] << 15) + +#define IMM_I8(imm) (((sljit_ins)(imm)&0xff) << 10) +#define IMM_I12(imm) (((sljit_ins)(imm)&0xfff) << 10) +#define IMM_I14(imm) (((sljit_ins)(imm)&0xfff3) << 10) +#define IMM_I16(imm) (((sljit_ins)(imm)&0xffff) << 10) +#define IMM_I21(imm) ((((sljit_ins)(imm)&0xffff) << 10) | (((sljit_ins)(imm) >> 16) & 0x1f)) +#define IMM_I26(imm) ((((sljit_ins)(imm)&0xffff) << 10) | (((sljit_ins)(imm) >> 16) & 0x3ff)) + +#define OPC_I26(opc) ((sljit_ins)(opc) << 26) +#define OPC_1RI21(opc) ((sljit_ins)(opc) << 26) +#define OPC_2RI16(opc) ((sljit_ins)(opc) << 26) +#define OPC_2RI14(opc) ((sljit_ins)(opc) << 24) +#define OPC_2RI12(opc) ((sljit_ins)(opc) << 22) +#define OPC_2RI8(opc) ((sljit_ins)(opc) << 18) +#define OPC_4R(opc) ((sljit_ins)(opc) << 20) +#define OPC_3R(opc) ((sljit_ins)(opc) << 15) +#define OPC_2R(opc) ((sljit_ins)(opc) << 10) +#define OPC_1RI20(opc) ((sljit_ins)(opc) << 25) + +/* Arithmetic operation instructions */ +#define ADD_W OPC_3R(0x20) +#define ADD_D OPC_3R(0x21) +#define SUB_W OPC_3R(0x22) +#define SUB_D OPC_3R(0x23) +#define ADDI_W OPC_2RI12(0xa) +#define ADDI_D OPC_2RI12(0xb) +#define ANDI OPC_2RI12(0xd) +#define ORI OPC_2RI12(0xe) +#define XORI OPC_2RI12(0xf) +#define ADDU16I_D OPC_2RI16(0x4) +#define LU12I_W OPC_1RI20(0xa) +#define LU32I_D OPC_1RI20(0xb) +#define LU52I_D OPC_2RI12(0xc) +#define SLT OPC_3R(0x24) +#define SLTU OPC_3R(0x25) +#define SLTI OPC_2RI12(0x8) +#define SLTUI OPC_2RI12(0x9) +#define PCADDI OPC_1RI20(0xc) +#define PCALAU12I OPC_1RI20(0xd) +#define PCADDU12I OPC_1RI20(0xe) +#define PCADDU18I OPC_1RI20(0xf) +#define NOR OPC_3R(0x28) +#define AND OPC_3R(0x29) +#define OR OPC_3R(0x2a) +#define XOR OPC_3R(0x2b) +#define ORN OPC_3R(0x2c) +#define ANDN OPC_3R(0x2d) +#define MUL_W OPC_3R(0x38) +#define MULH_W OPC_3R(0x39) +#define MULH_WU OPC_3R(0x3a) +#define MUL_D OPC_3R(0x3b) +#define MULH_D OPC_3R(0x3c) +#define MULH_DU OPC_3R(0x3d) +#define MULW_D_W OPC_3R(0x3e) +#define MULW_D_WU OPC_3R(0x3f) +#define DIV_W OPC_3R(0x40) +#define MOD_W OPC_3R(0x41) +#define DIV_WU OPC_3R(0x42) +#define MOD_WU OPC_3R(0x43) +#define DIV_D OPC_3R(0x44) +#define MOD_D OPC_3R(0x45) +#define DIV_DU OPC_3R(0x46) +#define MOD_DU OPC_3R(0x47) + +/* Bit-shift instructions */ +#define SLL_W OPC_3R(0x2e) +#define SRL_W OPC_3R(0x2f) +#define SRA_W OPC_3R(0x30) +#define SLL_D OPC_3R(0x31) +#define SRL_D OPC_3R(0x32) +#define SRA_D OPC_3R(0x33) +#define ROTR_W OPC_3R(0x36) +#define ROTR_D OPC_3R(0x37) +#define SLLI_W OPC_3R(0x81) +#define SLLI_D ((sljit_ins)(0x41) << 16) +#define SRLI_W OPC_3R(0x89) +#define SRLI_D ((sljit_ins)(0x45) << 16) +#define SRAI_W OPC_3R(0x91) +#define SRAI_D ((sljit_ins)(0x49) << 16) +#define ROTRI_W OPC_3R(0x99) +#define ROTRI_D ((sljit_ins)(0x4d) << 16) + +/* Bit-manipulation instructions */ +#define CLO_W OPC_2R(0x4) +#define CLZ_W OPC_2R(0x5) +#define CTO_W OPC_2R(0x6) +#define CTZ_W OPC_2R(0x7) +#define CLO_D OPC_2R(0x8) +#define CLZ_D OPC_2R(0x9) +#define CTO_D OPC_2R(0xa) +#define CTZ_D OPC_2R(0xb) +#define REVB_2H OPC_2R(0xc) +#define REVB_4H OPC_2R(0xd) +#define REVB_2W OPC_2R(0xe) +#define REVB_D OPC_2R(0xf) +#define REVH_2W OPC_2R(0x10) +#define REVH_D OPC_2R(0x11) +#define BITREV_4B OPC_2R(0x12) +#define BITREV_8B OPC_2R(0x13) +#define BITREV_W OPC_2R(0x14) +#define BITREV_D OPC_2R(0x15) +#define EXT_W_H OPC_2R(0x16) +#define EXT_W_B OPC_2R(0x17) +#define BSTRINS_W (0x1 << 22 | 1 << 21) +#define BSTRPICK_W (0x1 << 22 | 1 << 21 | 1 << 15) +#define BSTRINS_D (0x2 << 22) +#define BSTRPICK_D (0x3 << 22) + +/* Branch instructions */ +#define BEQZ OPC_1RI21(0x10) +#define BNEZ OPC_1RI21(0x11) +#define JIRL OPC_2RI16(0x13) +#define B OPC_I26(0x14) +#define BL OPC_I26(0x15) +#define BEQ OPC_2RI16(0x16) +#define BNE OPC_2RI16(0x17) +#define BLT OPC_2RI16(0x18) +#define BGE OPC_2RI16(0x19) +#define BLTU OPC_2RI16(0x1a) +#define BGEU OPC_2RI16(0x1b) + +/* Memory access instructions */ +#define LD_B OPC_2RI12(0xa0) +#define LD_H OPC_2RI12(0xa1) +#define LD_W OPC_2RI12(0xa2) +#define LD_D OPC_2RI12(0xa3) + +#define ST_B OPC_2RI12(0xa4) +#define ST_H OPC_2RI12(0xa5) +#define ST_W OPC_2RI12(0xa6) +#define ST_D OPC_2RI12(0xa7) + +#define LD_BU OPC_2RI12(0xa8) +#define LD_HU OPC_2RI12(0xa9) +#define LD_WU OPC_2RI12(0xaa) + +#define LDX_B OPC_3R(0x7000) +#define LDX_H OPC_3R(0x7008) +#define LDX_W OPC_3R(0x7010) +#define LDX_D OPC_3R(0x7018) + +#define STX_B OPC_3R(0x7020) +#define STX_H OPC_3R(0x7028) +#define STX_W OPC_3R(0x7030) +#define STX_D OPC_3R(0x7038) + +#define LDX_BU OPC_3R(0x7040) +#define LDX_HU OPC_3R(0x7048) +#define LDX_WU OPC_3R(0x7050) + +#define PRELD OPC_2RI12(0xab) + +/* Atomic memory access instructions */ +#define LL_W OPC_2RI14(0x20) +#define SC_W OPC_2RI14(0x21) +#define LL_D OPC_2RI14(0x22) +#define SC_D OPC_2RI14(0x23) + +/* LoongArch V1.10 Instructions */ +#define AMCAS_B OPC_3R(0x70B0) +#define AMCAS_H OPC_3R(0x70B1) +#define AMCAS_W OPC_3R(0x70B2) +#define AMCAS_D OPC_3R(0x70B3) + +/* Other instructions */ +#define BREAK OPC_3R(0x54) +#define DBGCALL OPC_3R(0x55) +#define SYSCALL OPC_3R(0x56) + +/* Basic Floating-Point Instructions */ +/* Floating-Point Arithmetic Operation Instructions */ +#define FADD_S OPC_3R(0x201) +#define FADD_D OPC_3R(0x202) +#define FSUB_S OPC_3R(0x205) +#define FSUB_D OPC_3R(0x206) +#define FMUL_S OPC_3R(0x209) +#define FMUL_D OPC_3R(0x20a) +#define FDIV_S OPC_3R(0x20d) +#define FDIV_D OPC_3R(0x20e) +#define FCMP_COND_S OPC_4R(0xc1) +#define FCMP_COND_D OPC_4R(0xc2) +#define FCOPYSIGN_S OPC_3R(0x225) +#define FCOPYSIGN_D OPC_3R(0x226) +#define FSEL OPC_4R(0xd0) +#define FABS_S OPC_2R(0x4501) +#define FABS_D OPC_2R(0x4502) +#define FNEG_S OPC_2R(0x4505) +#define FNEG_D OPC_2R(0x4506) +#define FMOV_S OPC_2R(0x4525) +#define FMOV_D OPC_2R(0x4526) + +/* Floating-Point Conversion Instructions */ +#define FCVT_S_D OPC_2R(0x4646) +#define FCVT_D_S OPC_2R(0x4649) +#define FTINTRZ_W_S OPC_2R(0x46a1) +#define FTINTRZ_W_D OPC_2R(0x46a2) +#define FTINTRZ_L_S OPC_2R(0x46a9) +#define FTINTRZ_L_D OPC_2R(0x46aa) +#define FFINT_S_W OPC_2R(0x4744) +#define FFINT_S_L OPC_2R(0x4746) +#define FFINT_D_W OPC_2R(0x4748) +#define FFINT_D_L OPC_2R(0x474a) + +/* Floating-Point Move Instructions */ +#define FMOV_S OPC_2R(0x4525) +#define FMOV_D OPC_2R(0x4526) +#define MOVGR2FR_W OPC_2R(0x4529) +#define MOVGR2FR_D OPC_2R(0x452a) +#define MOVGR2FRH_W OPC_2R(0x452b) +#define MOVFR2GR_S OPC_2R(0x452d) +#define MOVFR2GR_D OPC_2R(0x452e) +#define MOVFRH2GR_S OPC_2R(0x452f) +#define MOVGR2FCSR OPC_2R(0x4530) +#define MOVFCSR2GR OPC_2R(0x4532) +#define MOVFR2CF OPC_2R(0x4534) +#define MOVCF2FR OPC_2R(0x4535) +#define MOVGR2CF OPC_2R(0x4536) +#define MOVCF2GR OPC_2R(0x4537) + +/* Floating-Point Branch Instructions */ +#define BCEQZ OPC_I26(0x12) +#define BCNEZ OPC_I26(0x12) + +/* Floating-Point Common Memory Access Instructions */ +#define FLD_S OPC_2RI12(0xac) +#define FLD_D OPC_2RI12(0xae) +#define FST_S OPC_2RI12(0xad) +#define FST_D OPC_2RI12(0xaf) + +#define FLDX_S OPC_3R(0x7060) +#define FLDX_D OPC_3R(0x7068) +#define FSTX_S OPC_3R(0x7070) +#define FSTX_D OPC_3R(0x7078) + +#define I12_MAX (0x7ff) +#define I12_MIN (-0x800) +#define BRANCH16_MAX (0x7fff << 2) +#define BRANCH16_MIN (-(0x8000 << 2)) +#define BRANCH21_MAX (0xfffff << 2) +#define BRANCH21_MIN (-(0x100000 << 2)) +#define JUMP_MAX (0x1ffffff << 2) +#define JUMP_MIN (-(0x2000000 << 2)) +#define JIRL_MAX (0x7fff << 2) +#define JIRL_MIN (-(0x8000 << 2)) + +#define S32_MAX (0x7fffffffl) +#define S32_MIN (-0x80000000l) +#define S52_MAX (0x7ffffffffffffl) + +#define INST(inst, type) ((sljit_ins)((type & SLJIT_32) ? inst##_W : inst##_D)) + +/* LoongArch CPUCFG register for feature detection */ +#define LOONGARCH_CFG2 0x02 +#define LOONGARCH_FEATURE_LAMCAS (1 << 28) + +static sljit_u32 cpu_feature_list = 0; + +static SLJIT_INLINE sljit_u32 get_cpu_features(void) +{ + if (cpu_feature_list == 0) + __asm__ ("cpucfg %0, %1" : "+&r"(cpu_feature_list) : "r"(LOONGARCH_CFG2)); + return cpu_feature_list; +} + +static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins) +{ + sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); + FAIL_IF(!ptr); + *ptr = ins; + compiler->size++; + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset) +{ + sljit_sw diff; + sljit_uw target_addr; + sljit_ins *inst; + + inst = (sljit_ins *)jump->addr; + + if (jump->flags & SLJIT_REWRITABLE_JUMP) + goto exit; + + if (jump->flags & JUMP_ADDR) + target_addr = jump->u.target; + else { + SLJIT_ASSERT(jump->u.label != NULL); + target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset; + } + + diff = (sljit_sw)target_addr - (sljit_sw)inst - executable_offset; + + if (jump->flags & IS_COND) { + inst--; + diff += SSIZE_OF(ins); + + if (diff >= BRANCH16_MIN && diff <= BRANCH16_MAX) { + jump->flags |= PATCH_B; + inst[0] = (inst[0] & 0xfc0003ff) ^ 0x4000000; + jump->addr = (sljit_uw)inst; + return inst; + } + + inst++; + diff -= SSIZE_OF(ins); + } + + if (diff >= JUMP_MIN && diff <= JUMP_MAX) { + if (jump->flags & IS_COND) { + inst[-1] |= (sljit_ins)IMM_I16(2); + } + + jump->flags |= PATCH_J; + return inst; + } + + if (diff >= S32_MIN && diff <= S32_MAX) { + if (jump->flags & IS_COND) + inst[-1] |= (sljit_ins)IMM_I16(3); + + jump->flags |= PATCH_REL32; + inst[1] = inst[0]; + return inst + 1; + } + + if (target_addr <= (sljit_uw)S32_MAX) { + if (jump->flags & IS_COND) + inst[-1] |= (sljit_ins)IMM_I16(3); + + jump->flags |= PATCH_ABS32; + inst[1] = inst[0]; + return inst + 1; + } + + if (target_addr <= S52_MAX) { + if (jump->flags & IS_COND) + inst[-1] |= (sljit_ins)IMM_I16(4); + + jump->flags |= PATCH_ABS52; + inst[2] = inst[0]; + return inst + 2; + } + +exit: + if (jump->flags & IS_COND) + inst[-1] |= (sljit_ins)IMM_I16(5); + inst[3] = inst[0]; + return inst + 3; +} + +static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label) +{ + if (max_label <= (sljit_uw)S32_MAX) { + put_label->flags = PATCH_ABS32; + return 1; + } + + if (max_label <= S52_MAX) { + put_label->flags = PATCH_ABS52; + return 2; + } + + put_label->flags = 0; + return 3; +} + +static SLJIT_INLINE void load_addr_to_reg(void *dst, sljit_u32 reg) +{ + struct sljit_jump *jump = NULL; + struct sljit_put_label *put_label; + sljit_uw flags; + sljit_ins *inst; + sljit_uw addr; + + if (reg != 0) { + jump = (struct sljit_jump*)dst; + flags = jump->flags; + inst = (sljit_ins*)jump->addr; + addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->addr; + } else { + put_label = (struct sljit_put_label*)dst; + flags = put_label->flags; + inst = (sljit_ins*)put_label->addr; + addr = put_label->label->addr; + reg = *inst; + } + + if (flags & PATCH_ABS32) { + SLJIT_ASSERT(addr <= S32_MAX); + inst[0] = LU12I_W | RD(reg) | (sljit_ins)(((addr & 0xffffffff) >> 12) << 5); + } else if (flags & PATCH_ABS52) { + inst[0] = LU12I_W | RD(reg) | (sljit_ins)(((addr & 0xffffffff) >> 12) << 5); + inst[1] = LU32I_D | RD(reg) | (sljit_ins)(((addr >> 32) & 0xfffff) << 5); + inst += 1; + } else { + inst[0] = LU12I_W | RD(reg) | (sljit_ins)(((addr & 0xffffffff) >> 12) << 5); + inst[1] = LU32I_D | RD(reg) | (sljit_ins)(((addr >> 32) & 0xfffff) << 5); + inst[2] = LU52I_D | RD(reg) | RJ(reg) | IMM_I12(addr >> 52); + inst += 2; + } + + if (jump != NULL) { + SLJIT_ASSERT((inst[1] & OPC_2RI16(0x3f)) == JIRL); + inst[1] = (inst[1] & (OPC_2RI16(0x3f) | 0x3ff)) | IMM_I16((addr & 0xfff) >> 2); + } else + inst[1] = ORI | RD(reg) | RJ(reg) | IMM_I12(addr); +} + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) +{ + struct sljit_memory_fragment *buf; + sljit_ins *code; + sljit_ins *code_ptr; + sljit_ins *buf_ptr; + sljit_ins *buf_end; + sljit_uw word_count; + sljit_uw next_addr; + sljit_sw executable_offset; + sljit_uw addr; + + struct sljit_label *label; + struct sljit_jump *jump; + struct sljit_const *const_; + struct sljit_put_label *put_label; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_generate_code(compiler)); + reverse_buf(compiler); + + code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data); + PTR_FAIL_WITH_EXEC_IF(code); + buf = compiler->buf; + + code_ptr = code; + word_count = 0; + next_addr = 0; + executable_offset = SLJIT_EXEC_OFFSET(code); + + label = compiler->labels; + jump = compiler->jumps; + const_ = compiler->consts; + put_label = compiler->put_labels; + + do { + buf_ptr = (sljit_ins*)buf->memory; + buf_end = buf_ptr + (buf->used_size >> 2); + do { + *code_ptr = *buf_ptr++; + if (next_addr == word_count) { + SLJIT_ASSERT(!label || label->size >= word_count); + SLJIT_ASSERT(!jump || jump->addr >= word_count); + SLJIT_ASSERT(!const_ || const_->addr >= word_count); + SLJIT_ASSERT(!put_label || put_label->addr >= word_count); + + /* These structures are ordered by their address. */ + if (label && label->size == word_count) { + label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + label->size = (sljit_uw)(code_ptr - code); + label = label->next; + } + if (jump && jump->addr == word_count) { + word_count += 3; + jump->addr = (sljit_uw)code_ptr; + code_ptr = detect_jump_type(jump, code, executable_offset); + jump = jump->next; + } + if (const_ && const_->addr == word_count) { + const_->addr = (sljit_uw)code_ptr; + const_ = const_->next; + } + if (put_label && put_label->addr == word_count) { + SLJIT_ASSERT(put_label->label); + put_label->addr = (sljit_uw)code_ptr; + + code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size)); + word_count += 3; + + put_label = put_label->next; + } + next_addr = compute_next_addr(label, jump, const_, put_label); + } + code_ptr++; + word_count++; + } while (buf_ptr < buf_end); + + buf = buf->next; + } while (buf); + + if (label && label->size == word_count) { + label->addr = (sljit_uw)code_ptr; + label->size = (sljit_uw)(code_ptr - code); + label = label->next; + } + + SLJIT_ASSERT(!label); + SLJIT_ASSERT(!jump); + SLJIT_ASSERT(!const_); + SLJIT_ASSERT(!put_label); + SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size); + + jump = compiler->jumps; + while (jump) { + do { + if (!(jump->flags & (PATCH_B | PATCH_J | PATCH_REL32))) { + load_addr_to_reg(jump, TMP_REG1); + break; + } + + addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->addr; + buf_ptr = (sljit_ins *)jump->addr; + addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset); + + if (jump->flags & PATCH_B) { + SLJIT_ASSERT((sljit_sw)addr >= BRANCH16_MIN && (sljit_sw)addr <= BRANCH16_MAX); + buf_ptr[0] |= (sljit_ins)IMM_I16(addr >> 2); + break; + } + + if (jump->flags & PATCH_REL32) { + SLJIT_ASSERT((sljit_sw)addr >= S32_MIN && (sljit_sw)addr <= S32_MAX); + + buf_ptr[0] = PCADDU12I | RD(TMP_REG1) | (sljit_ins)((sljit_sw)addr & ~0xfff); + SLJIT_ASSERT((buf_ptr[1] & OPC_2RI16(0x3f)) == JIRL); + buf_ptr[1] |= IMM_I16((addr & 0xfff) >> 2); + break; + } + + SLJIT_ASSERT((sljit_sw)addr >= JUMP_MIN && (sljit_sw)addr <= JUMP_MAX); + if (jump->flags & IS_CALL) + buf_ptr[0] = BL | (sljit_ins)IMM_I26(addr >> 2); + else + buf_ptr[0] = B | (sljit_ins)IMM_I26(addr >> 2); + } while (0); + jump = jump->next; + } + + put_label = compiler->put_labels; + while (put_label) { + load_addr_to_reg(put_label, 0); + put_label = put_label->next; + } + + compiler->error = SLJIT_ERR_COMPILED; + compiler->executable_offset = executable_offset; + compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins); + + code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset); + code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + + SLJIT_CACHE_FLUSH(code, code_ptr); + SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1); + return code; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) +{ + switch (feature_type) + { + case SLJIT_HAS_FPU: +#ifdef SLJIT_IS_FPU_AVAILABLE + return (SLJIT_IS_FPU_AVAILABLE) != 0; +#else + /* Available by default. */ + return 1; +#endif + + case SLJIT_HAS_ATOMIC: + return (LOONGARCH_FEATURE_LAMCAS & get_cpu_features()); + + case SLJIT_HAS_CLZ: + case SLJIT_HAS_CTZ: + case SLJIT_HAS_REV: + case SLJIT_HAS_ROT: + case SLJIT_HAS_PREFETCH: + case SLJIT_HAS_COPY_F32: + case SLJIT_HAS_COPY_F64: + return 1; + + default: + return 0; + } +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) +{ + SLJIT_UNUSED_ARG(type); + + return 0; +} + +/* --------------------------------------------------------------------- */ +/* Entry, exit */ +/* --------------------------------------------------------------------- */ + +/* Creates an index in data_transfer_insts array. */ +#define LOAD_DATA 0x01 +#define WORD_DATA 0x00 +#define BYTE_DATA 0x02 +#define HALF_DATA 0x04 +#define INT_DATA 0x06 +#define SIGNED_DATA 0x08 +/* Separates integer and floating point registers */ +#define GPR_REG 0x0f +#define DOUBLE_DATA 0x10 +#define SINGLE_DATA 0x12 + +#define MEM_MASK 0x1f + +#define ARG_TEST 0x00020 +#define ALT_KEEP_CACHE 0x00040 +#define CUMULATIVE_OP 0x00080 +#define IMM_OP 0x00100 +#define MOVE_OP 0x00200 +#define SRC2_IMM 0x00400 + +#define UNUSED_DEST 0x00800 +#define REG_DEST 0x01000 +#define REG1_SOURCE 0x02000 +#define REG2_SOURCE 0x04000 +#define SLOW_SRC1 0x08000 +#define SLOW_SRC2 0x10000 +#define SLOW_DEST 0x20000 + +#define STACK_STORE ST_D +#define STACK_LOAD LD_D + +static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm) +{ + if (imm <= I12_MAX && imm >= I12_MIN) + return push_inst(compiler, ADDI_D | RD(dst_r) | RJ(TMP_ZERO) | IMM_I12(imm)); + + if (imm <= 0x7fffffffl && imm >= -0x80000000l) { + FAIL_IF(push_inst(compiler, LU12I_W | RD(dst_r) | (sljit_ins)(((imm & 0xffffffff) >> 12) << 5))); + return push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(imm)); + } else if (imm <= 0x7ffffffffffffl && imm >= -0x8000000000000l) { + FAIL_IF(push_inst(compiler, LU12I_W | RD(dst_r) | (sljit_ins)(((imm & 0xffffffff) >> 12) << 5))); + FAIL_IF(push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(imm))); + return push_inst(compiler, LU32I_D | RD(dst_r) | (sljit_ins)(((imm >> 32) & 0xfffff) << 5)); + } + FAIL_IF(push_inst(compiler, LU12I_W | RD(dst_r) | (sljit_ins)(((imm & 0xffffffff) >> 12) << 5))); + FAIL_IF(push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(imm))); + FAIL_IF(push_inst(compiler, LU32I_D | RD(dst_r) | (sljit_ins)(((imm >> 32) & 0xfffff) << 5))); + return push_inst(compiler, LU52I_D | RD(dst_r) | RJ(dst_r) | IMM_I12(imm >> 52)); +} + +#define STACK_MAX_DISTANCE (-I12_MIN) + +static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw); + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) +{ + sljit_s32 i, tmp, offset; + sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options); + + CHECK_ERROR(); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); + + local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1); + local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); + + local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf; + compiler->local_size = local_size; + + if (local_size <= STACK_MAX_DISTANCE) { + /* Frequent case. */ + FAIL_IF(push_inst(compiler, ADDI_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | IMM_I12(-local_size))); + offset = local_size - SSIZE_OF(sw); + local_size = 0; + } else { + FAIL_IF(push_inst(compiler, ADDI_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | IMM_I12(STACK_MAX_DISTANCE))); + local_size -= STACK_MAX_DISTANCE; + + if (local_size > STACK_MAX_DISTANCE) + FAIL_IF(load_immediate(compiler, TMP_REG1, local_size)); + offset = STACK_MAX_DISTANCE - SSIZE_OF(sw); + } + + FAIL_IF(push_inst(compiler, STACK_STORE | RD(RETURN_ADDR_REG) | RJ(SLJIT_SP) | IMM_I12(offset))); + + tmp = SLJIT_S0 - saveds; + for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) { + offset -= SSIZE_OF(sw); + FAIL_IF(push_inst(compiler, STACK_STORE | RD(i) | RJ(SLJIT_SP) | IMM_I12(offset))); + } + + for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { + offset -= SSIZE_OF(sw); + FAIL_IF(push_inst(compiler, STACK_STORE | RD(i) | RJ(SLJIT_SP) | IMM_I12(offset))); + } + + tmp = SLJIT_FS0 - fsaveds; + for (i = SLJIT_FS0; i > tmp; i--) { + offset -= SSIZE_OF(f64); + FAIL_IF(push_inst(compiler, FST_D | FRD(i) | RJ(SLJIT_SP) | IMM_I12(offset))); + } + + for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) { + offset -= SSIZE_OF(f64); + FAIL_IF(push_inst(compiler, FST_D | FRD(i) | RJ(SLJIT_SP) | IMM_I12(offset))); + } + + if (local_size > STACK_MAX_DISTANCE) + FAIL_IF(push_inst(compiler, SUB_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | RK(TMP_REG1))); + else if (local_size > 0) + FAIL_IF(push_inst(compiler, ADDI_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | IMM_I12(-local_size))); + + if (options & SLJIT_ENTER_REG_ARG) + return SLJIT_SUCCESS; + + arg_types >>= SLJIT_ARG_SHIFT; + saved_arg_count = 0; + tmp = SLJIT_R0; + + while (arg_types > 0) { + if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) { + if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) { + FAIL_IF(push_inst(compiler, ADDI_D | RD(SLJIT_S0 - saved_arg_count) | RJ(tmp) | IMM_I12(0))); + saved_arg_count++; + } + tmp++; + } + + arg_types >>= SLJIT_ARG_SHIFT; + } + + return SLJIT_SUCCESS; +} + +#undef STACK_MAX_DISTANCE + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) +{ + CHECK_ERROR(); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); + + local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1); + local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64); + + compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf; + + return SLJIT_SUCCESS; +} + +#define STACK_MAX_DISTANCE (-I12_MIN - 16) + +static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to) +{ + sljit_s32 i, tmp, offset; + sljit_s32 local_size = compiler->local_size; + + if (local_size > STACK_MAX_DISTANCE) { + local_size -= STACK_MAX_DISTANCE; + + if (local_size > STACK_MAX_DISTANCE) { + FAIL_IF(load_immediate(compiler, TMP_REG2, local_size)); + FAIL_IF(push_inst(compiler, ADD_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | RK(TMP_REG2))); + } else + FAIL_IF(push_inst(compiler, ADDI_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | IMM_I12(local_size))); + + local_size = STACK_MAX_DISTANCE; + } + + SLJIT_ASSERT(local_size > 0); + + offset = local_size - SSIZE_OF(sw); + if (!is_return_to) + FAIL_IF(push_inst(compiler, STACK_LOAD | RD(RETURN_ADDR_REG) | RJ(SLJIT_SP) | IMM_I12(offset))); + + tmp = SLJIT_S0 - compiler->saveds; + for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) { + offset -= SSIZE_OF(sw); + FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RJ(SLJIT_SP) | IMM_I12(offset))); + } + + for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { + offset -= SSIZE_OF(sw); + FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RJ(SLJIT_SP) | IMM_I12(offset))); + } + + tmp = SLJIT_FS0 - compiler->fsaveds; + for (i = SLJIT_FS0; i > tmp; i--) { + offset -= SSIZE_OF(f64); + FAIL_IF(push_inst(compiler, FLD_D | FRD(i) | RJ(SLJIT_SP) | IMM_I12(offset))); + } + + for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) { + offset -= SSIZE_OF(f64); + FAIL_IF(push_inst(compiler, FLD_D | FRD(i) | RJ(SLJIT_SP) | IMM_I12(offset))); + } + + return push_inst(compiler, ADDI_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | IMM_I12(local_size)); +} + +#undef STACK_MAX_DISTANCE + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_void(compiler)); + + FAIL_IF(emit_stack_frame_release(compiler, 0)); + return push_inst(compiler, JIRL | RD(TMP_ZERO) | RJ(RETURN_ADDR_REG) | IMM_I12(0)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_return_to(compiler, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); + src = TMP_REG1; + srcw = 0; + } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(src) | IMM_I12(0))); + src = TMP_REG1; + srcw = 0; + } + + FAIL_IF(emit_stack_frame_release(compiler, 1)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw); +} + +/* --------------------------------------------------------------------- */ +/* Operators */ +/* --------------------------------------------------------------------- */ + +static const sljit_ins data_transfer_insts[16 + 4] = { +/* u w s */ ST_D /* st.d */, +/* u w l */ LD_D /* ld.d */, +/* u b s */ ST_B /* st.b */, +/* u b l */ LD_BU /* ld.bu */, +/* u h s */ ST_H /* st.h */, +/* u h l */ LD_HU /* ld.hu */, +/* u i s */ ST_W /* st.w */, +/* u i l */ LD_WU /* ld.wu */, + +/* s w s */ ST_D /* st.d */, +/* s w l */ LD_D /* ld.d */, +/* s b s */ ST_B /* st.b */, +/* s b l */ LD_B /* ld.b */, +/* s h s */ ST_H /* st.h */, +/* s h l */ LD_H /* ld.h */, +/* s i s */ ST_W /* st.w */, +/* s i l */ LD_W /* ld.w */, + +/* d s */ FST_D /* fst.d */, +/* d l */ FLD_D /* fld.d */, +/* s s */ FST_S /* fst.s */, +/* s l */ FLD_S /* fld.s */, +}; + +static const sljit_ins data_transfer_insts_x[16 + 4] = { +/* u w s */ STX_D /* stx.d */, +/* u w l */ LDX_D /* ldx.d */, +/* u b s */ STX_B /* stx.b */, +/* u b l */ LDX_BU /* ldx.bu */, +/* u h s */ STX_H /* stx.h */, +/* u h l */ LDX_HU /* ldx.hu */, +/* u i s */ STX_W /* stx.w */, +/* u i l */ LDX_WU /* ldx.wu */, + +/* s w s */ STX_D /* stx.d */, +/* s w l */ LDX_D /* ldx.d */, +/* s b s */ STX_B /* stx.b */, +/* s b l */ LDX_B /* ldx.b */, +/* s h s */ STX_H /* stx.h */, +/* s h l */ LDX_H /* ldx.h */, +/* s i s */ STX_W /* stx.w */, +/* s i l */ LDX_W /* ldx.w */, + +/* d s */ FSTX_D /* fstx.d */, +/* d l */ FLDX_D /* fldx.d */, +/* s s */ FSTX_S /* fstx.s */, +/* s l */ FLDX_S /* fldx.s */, +}; + +static sljit_s32 push_mem_inst(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) +{ + sljit_ins ins; + sljit_s32 base = arg & REG_MASK; + + SLJIT_ASSERT(arg & SLJIT_MEM); + + if (arg & OFFS_REG_MASK) { + sljit_s32 offs = OFFS_REG(arg); + + SLJIT_ASSERT(!argw); + ins = data_transfer_insts_x[flags & MEM_MASK] | + ((flags & MEM_MASK) <= GPR_REG ? RD(reg) : FRD(reg)) | + RJ(base) | RK(offs); + } else { + SLJIT_ASSERT(argw <= 0xfff && argw >= I12_MIN); + + ins = data_transfer_insts[flags & MEM_MASK] | + ((flags & MEM_MASK) <= GPR_REG ? RD(reg) : FRD(reg)) | + RJ(base) | IMM_I12(argw); + } + return push_inst(compiler, ins); +} + +/* Can perform an operation using at most 1 instruction. */ +static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) +{ + SLJIT_ASSERT(arg & SLJIT_MEM); + + /* argw == 0 (ldx/stx rd, rj, rk) can be used. + * argw in [-2048, 2047] (ld/st rd, rj, imm) can be used. */ + if (!argw || (!(arg & OFFS_REG_MASK) && (argw <= I12_MAX && argw >= I12_MIN))) { + /* Works for both absolute and relative addresses. */ + if (SLJIT_UNLIKELY(flags & ARG_TEST)) + return 1; + + FAIL_IF(push_mem_inst(compiler, flags, reg, arg, argw)); + return -1; + } + return 0; +} + +#define TO_ARGW_HI(argw) (((argw) & ~0xfff) + (((argw) & 0x800) ? 0x1000 : 0)) + +/* See getput_arg below. + Note: can_cache is called only for binary operators. */ +static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) +{ + SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM)); + + if (arg & OFFS_REG_MASK) + return 0; + + if (arg == next_arg) { + if (((next_argw - argw) <= I12_MAX && (next_argw - argw) >= I12_MIN) + || TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw)) + return 1; + return 0; + } + + return 0; +} + +/* Emit the necessary instructions. See can_cache above. */ +static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) +{ + sljit_s32 base = arg & REG_MASK; + sljit_s32 tmp_r = TMP_REG1; + sljit_sw offset; + + SLJIT_ASSERT(arg & SLJIT_MEM); + if (!(next_arg & SLJIT_MEM)) { + next_arg = 0; + next_argw = 0; + } + + /* Since tmp can be the same as base or offset registers, + * these might be unavailable after modifying tmp. */ + if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) + tmp_r = reg; + + if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { + argw &= 0x3; + + if (SLJIT_UNLIKELY(argw)) + FAIL_IF(push_inst(compiler, SLLI_D | RD(TMP_REG3) | RJ(OFFS_REG(arg)) | IMM_I12(argw))); + return push_mem_inst(compiler, flags, reg, SLJIT_MEM2(base, TMP_REG3), 0); + } + + if (compiler->cache_arg == arg && argw - compiler->cache_argw <= I12_MAX && argw - compiler->cache_argw >= I12_MIN) + return push_mem_inst(compiler, flags, reg, SLJIT_MEM1(TMP_REG3), argw - compiler->cache_argw); + + if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw <= I12_MAX) && (argw - compiler->cache_argw >= I12_MIN)) { + offset = argw - compiler->cache_argw; + } else { + sljit_sw argw_hi=TO_ARGW_HI(argw); + compiler->cache_arg = SLJIT_MEM; + + if (next_arg && next_argw - argw <= I12_MAX && next_argw - argw >= I12_MIN && argw_hi != TO_ARGW_HI(next_argw)) { + FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); + compiler->cache_argw = argw; + offset = 0; + } else { + FAIL_IF(load_immediate(compiler, TMP_REG3, argw_hi)); + compiler->cache_argw = argw_hi; + offset = argw & 0xfff; + argw = argw_hi; + } + } + + if (!base) + return push_mem_inst(compiler, flags, reg, SLJIT_MEM1(TMP_REG3), offset); + + if (arg == next_arg && next_argw - argw <= I12_MAX && next_argw - argw >= I12_MIN) { + compiler->cache_arg = arg; + FAIL_IF(push_inst(compiler, ADD_D | RD(TMP_REG3) | RJ(TMP_REG3) | RK(base))); + return push_mem_inst(compiler, flags, reg, SLJIT_MEM1(TMP_REG3), offset); + } + + if (!offset) + return push_mem_inst(compiler, flags, reg, SLJIT_MEM2(base, TMP_REG3), 0); + + FAIL_IF(push_inst(compiler, ADD_D | RD(tmp_r) | RJ(TMP_REG3) | RK(base))); + return push_mem_inst(compiler, flags, reg, SLJIT_MEM1(tmp_r), offset); +} + +static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) +{ + sljit_s32 base = arg & REG_MASK; + sljit_s32 tmp_r = TMP_REG1; + + if (getput_arg_fast(compiler, flags, reg, arg, argw)) + return compiler->error; + + if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) + tmp_r = reg; + + if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { + argw &= 0x3; + + if (SLJIT_UNLIKELY(argw)) + FAIL_IF(push_inst(compiler, SLLI_D | RD(tmp_r) | RJ(OFFS_REG(arg)) | IMM_I12(argw))); + return push_mem_inst(compiler, flags, reg, SLJIT_MEM2(base, tmp_r), 0); + } else { + FAIL_IF(load_immediate(compiler, tmp_r, argw)); + + if (base != 0) + return push_mem_inst(compiler, flags, reg, SLJIT_MEM2(base, tmp_r), 0); + return push_mem_inst(compiler, flags, reg, SLJIT_MEM1(tmp_r), 0); + } +} + +static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w) +{ + if (getput_arg_fast(compiler, flags, reg, arg1, arg1w)) + return compiler->error; + return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w); +} + +#define IMM_EXTEND(v) (IMM_I12((op & SLJIT_32) ? (v) : (32 + (v)))) + +/* andi/ori/xori are zero-extended */ +#define EMIT_LOGICAL(op_imm, op_reg) \ + if (flags & SRC2_IMM) { \ + if (op & SLJIT_SET_Z) {\ + FAIL_IF(push_inst(compiler, ADDI_D | RD(EQUAL_FLAG) | RJ(TMP_ZERO) | IMM_I12(src2))); \ + FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RJ(src1) | RK(EQUAL_FLAG))); \ + } \ + if (!(flags & UNUSED_DEST)) { \ + if (dst == src1) { \ + FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(TMP_ZERO) | IMM_I12(src2))); \ + FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RJ(src1) | RK(TMP_REG1))); \ + } else { \ + FAIL_IF(push_inst(compiler, ADDI_D | RD(dst) | RJ(TMP_ZERO) | IMM_I12(src2))); \ + FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RJ(src1) | RK(dst))); \ + } \ + } \ + } \ + else { \ + if (op & SLJIT_SET_Z) \ + FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RJ(src1) | RK(src2))); \ + if (!(flags & UNUSED_DEST)) \ + FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RJ(src1) | RK(src2))); \ + } \ + while (0) + +#define EMIT_SHIFT(imm, reg) \ + op_imm = (imm); \ + op_reg = (reg) + +static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, + sljit_s32 dst, sljit_s32 src1, sljit_sw src2) +{ + sljit_s32 is_overflow, is_carry, carry_src_r, is_handled; + sljit_ins op_imm, op_reg; + sljit_ins word_size = ((op & SLJIT_32) ? 32 : 64); + + switch (GET_OPCODE(op)) { + case SLJIT_MOV: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if (dst != src2) + return push_inst(compiler, INST(ADD, op) | RD(dst) | RJ(src2) | IMM_I12(0)); + return SLJIT_SUCCESS; + + case SLJIT_MOV_U8: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) + return push_inst(compiler, ANDI | RD(dst) | RJ(src2) | IMM_I12(0xff)); + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; + + case SLJIT_MOV_S8: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) + return push_inst(compiler, EXT_W_B | RD(dst) | RJ(src2)); + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; + + case SLJIT_MOV_U16: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) + return push_inst(compiler, INST(BSTRPICK, op) | RD(dst) | RJ(src2) | (15 << 16)); + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; + + case SLJIT_MOV_S16: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) + return push_inst(compiler, EXT_W_H | RD(dst) | RJ(src2)); + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; + + case SLJIT_MOV_U32: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) + return push_inst(compiler, BSTRPICK_D | RD(dst) | RJ(src2) | (31 << 16)); + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; + + case SLJIT_MOV_S32: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) + return push_inst(compiler, SLLI_W | RD(dst) | RJ(src2) | IMM_I12(0)); + SLJIT_ASSERT(dst == src2); + return SLJIT_SUCCESS; + + case SLJIT_CLZ: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + return push_inst(compiler, INST(CLZ, op) | RD(dst) | RJ(src2)); + + case SLJIT_CTZ: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + return push_inst(compiler, INST(CTZ, op) | RD(dst) | RJ(src2)); + + case SLJIT_REV: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + return push_inst(compiler, ((op & SLJIT_32) ? REVB_2W : REVB_D) | RD(dst) | RJ(src2)); + + case SLJIT_REV_S16: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + FAIL_IF(push_inst(compiler, REVB_2H | RD(dst) | RJ(src2))); + return push_inst(compiler, EXT_W_H | RD(dst) | RJ(dst)); + + case SLJIT_REV_U16: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + FAIL_IF(push_inst(compiler, REVB_2H | RD(dst) | RJ(src2))); + return push_inst(compiler, INST(BSTRPICK, op) | RD(dst) | RJ(dst) | (15 << 16)); + + case SLJIT_REV_S32: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && dst != TMP_REG1); + FAIL_IF(push_inst(compiler, REVB_2W | RD(dst) | RJ(src2))); + return push_inst(compiler, SLLI_W | RD(dst) | RJ(dst) | IMM_I12(0)); + + case SLJIT_REV_U32: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && dst != TMP_REG1); + FAIL_IF(push_inst(compiler, REVB_2W | RD(dst) | RJ(src2))); + return push_inst(compiler, BSTRPICK_D | RD(dst) | RJ(dst) | (31 << 16)); + + case SLJIT_ADD: + /* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */ + is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; + carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY; + + if (flags & SRC2_IMM) { + if (is_overflow) { + if (src2 >= 0) + FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(0))); + else { + FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(TMP_ZERO) | IMM_I12(-1))); + FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RJ(src1) | RK(EQUAL_FLAG))); + } + } + else if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(src2))); + + /* Only the zero flag is needed. */ + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) + FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(dst) | RJ(src1) | IMM_I12(src2))); + } + else { + if (is_overflow) + FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RJ(src1) | RK(src2))); + else if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, INST(ADD, op) | RD(EQUAL_FLAG) | RJ(src1) | RK(src2))); + + if (is_overflow || carry_src_r != 0) { + if (src1 != dst) + carry_src_r = (sljit_s32)src1; + else if (src2 != dst) + carry_src_r = (sljit_s32)src2; + else { + FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(OTHER_FLAG) | RJ(src1) | IMM_I12(0))); + carry_src_r = OTHER_FLAG; + } + } + + /* Only the zero flag is needed. */ + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) + FAIL_IF(push_inst(compiler, INST(ADD, op) | RD(dst) | RJ(src1) | RK(src2))); + } + + /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */ + if (is_overflow || carry_src_r != 0) { + if (flags & SRC2_IMM) + FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RJ(dst) | IMM_I12(src2))); + else + FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RJ(dst) | RK(carry_src_r))); + } + + if (!is_overflow) + return SLJIT_SUCCESS; + + FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RJ(dst) | RK(EQUAL_FLAG))); + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, INST(ADD, op) | RD(EQUAL_FLAG) | RJ(dst) | IMM_I12(0))); + FAIL_IF(push_inst(compiler, INST(SRLI, op) | RD(TMP_REG1) | RJ(TMP_REG1) | IMM_EXTEND(31))); + return push_inst(compiler, XOR | RD(OTHER_FLAG) | RJ(TMP_REG1) | RK(OTHER_FLAG)); + + case SLJIT_ADDC: + carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY; + + if (flags & SRC2_IMM) { + FAIL_IF(push_inst(compiler, ADDI_D | RD(dst) | RJ(src1) | IMM_I12(src2))); + } else { + if (carry_src_r != 0) { + if (src1 != dst) + carry_src_r = (sljit_s32)src1; + else if (src2 != dst) + carry_src_r = (sljit_s32)src2; + else { + FAIL_IF(push_inst(compiler, ADDI_D | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(0))); + carry_src_r = EQUAL_FLAG; + } + } + + FAIL_IF(push_inst(compiler, ADD_D | RD(dst) | RJ(src1) | RK(src2))); + } + + /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */ + if (carry_src_r != 0) { + if (flags & SRC2_IMM) + FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RJ(dst) | IMM_I12(src2))); + else + FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RJ(dst) | RK(carry_src_r))); + } + + FAIL_IF(push_inst(compiler, ADD_D | RD(dst) | RJ(dst) | RK(OTHER_FLAG))); + + if (carry_src_r == 0) + return SLJIT_SUCCESS; + + /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */ + FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RJ(dst) | RK(OTHER_FLAG))); + /* Set carry flag. */ + return push_inst(compiler, OR | RD(OTHER_FLAG) | RJ(OTHER_FLAG) | RK(EQUAL_FLAG)); + + case SLJIT_SUB: + if ((flags & SRC2_IMM) && src2 == I12_MIN) { + FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG2) | RJ(TMP_ZERO) | IMM_I12(src2))); + src2 = TMP_REG2; + flags &= ~SRC2_IMM; + } + + is_handled = 0; + + if (flags & SRC2_IMM) { + if (GET_FLAG_TYPE(op) == SLJIT_LESS) { + FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RJ(src1) | IMM_I12(src2))); + is_handled = 1; + } + else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) { + FAIL_IF(push_inst(compiler, SLTI | RD(OTHER_FLAG) | RJ(src1) | IMM_I12(src2))); + is_handled = 1; + } + } + + if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) { + is_handled = 1; + + if (flags & SRC2_IMM) { + FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG2) | RJ(TMP_ZERO) | IMM_I12(src2))); + src2 = TMP_REG2; + flags &= ~SRC2_IMM; + } + + switch (GET_FLAG_TYPE(op)) { + case SLJIT_LESS: + FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RJ(src1) | RK(src2))); + break; + case SLJIT_GREATER: + FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RJ(src2) | RK(src1))); + break; + case SLJIT_SIG_LESS: + FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RJ(src1) | RK(src2))); + break; + case SLJIT_SIG_GREATER: + FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RJ(src2) | RK(src1))); + break; + } + } + + if (is_handled) { + if (flags & SRC2_IMM) { + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(-src2))); + if (!(flags & UNUSED_DEST)) + return push_inst(compiler, INST(ADDI, op) | RD(dst) | RJ(src1) | IMM_I12(-src2)); + } + else { + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(EQUAL_FLAG) | RJ(src1) | RK(src2))); + if (!(flags & UNUSED_DEST)) + return push_inst(compiler, INST(SUB, op) | RD(dst) | RJ(src1) | RK(src2)); + } + return SLJIT_SUCCESS; + } + + is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; + is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY; + + if (flags & SRC2_IMM) { + if (is_overflow) { + if (src2 >= 0) + FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(0))); + else { + FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(-1))); + FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RJ(src1) | RK(EQUAL_FLAG))); + } + } + else if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(-src2))); + + if (is_overflow || is_carry) + FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RJ(src1) | IMM_I12(src2))); + + /* Only the zero flag is needed. */ + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) + FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(dst) | RJ(src1) | IMM_I12(-src2))); + } + else { + if (is_overflow) + FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RJ(src1) | RK(src2))); + else if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(EQUAL_FLAG) | RJ(src1) | RK(src2))); + + if (is_overflow || is_carry) + FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RJ(src1) | RK(src2))); + + /* Only the zero flag is needed. */ + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) + FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(dst) | RJ(src1) | RK(src2))); + } + + if (!is_overflow) + return SLJIT_SUCCESS; + + FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RJ(dst) | RK(EQUAL_FLAG))); + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(dst) | IMM_I12(0))); + FAIL_IF(push_inst(compiler, INST(SRLI, op) | RD(TMP_REG1) | RJ(TMP_REG1) | IMM_EXTEND(31))); + return push_inst(compiler, XOR | RD(OTHER_FLAG) | RJ(TMP_REG1) | RK(OTHER_FLAG)); + + case SLJIT_SUBC: + if ((flags & SRC2_IMM) && src2 == I12_MIN) { + FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(TMP_REG2) | RJ(TMP_ZERO) | IMM_I12(src2))); + src2 = TMP_REG2; + flags &= ~SRC2_IMM; + } + + is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY; + + if (flags & SRC2_IMM) { + if (is_carry) + FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(src2))); + + FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(dst) | RJ(src1) | IMM_I12(-src2))); + } + else { + if (is_carry) + FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RJ(src1) | RK(src2))); + + FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(dst) | RJ(src1) | RK(src2))); + } + + if (is_carry) + FAIL_IF(push_inst(compiler, SLTU | RD(TMP_REG1) | RJ(dst) | RK(OTHER_FLAG))); + + FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(dst) | RJ(dst) | RK(OTHER_FLAG))); + + if (!is_carry) + return SLJIT_SUCCESS; + + return push_inst(compiler, OR | RD(OTHER_FLAG) | RJ(EQUAL_FLAG) | RK(TMP_REG1)); + + case SLJIT_MUL: + SLJIT_ASSERT(!(flags & SRC2_IMM)); + + if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW) + return push_inst(compiler, INST(MUL, op) | RD(dst) | RJ(src1) | RK(src2)); + + if (op & SLJIT_32) { + FAIL_IF(push_inst(compiler, MUL_D | RD(OTHER_FLAG) | RJ(src1) | RK(src2))); + FAIL_IF(push_inst(compiler, MUL_W | RD(dst) | RJ(src1) | RK(src2))); + return push_inst(compiler, SUB_D | RD(OTHER_FLAG) | RJ(dst) | RK(OTHER_FLAG)); + } + + FAIL_IF(push_inst(compiler, MULH_D | RD(EQUAL_FLAG) | RJ(src1) | RK(src2))); + FAIL_IF(push_inst(compiler, MUL_D | RD(dst) | RJ(src1) | RK(src2))); + FAIL_IF(push_inst(compiler, SRAI_D | RD(OTHER_FLAG) | RJ(dst) | IMM_I12((63)))); + return push_inst(compiler, SUB_D | RD(OTHER_FLAG) | RJ(EQUAL_FLAG) | RK(OTHER_FLAG)); + + case SLJIT_AND: + EMIT_LOGICAL(ANDI, AND); + return SLJIT_SUCCESS; + + case SLJIT_OR: + EMIT_LOGICAL(ORI, OR); + return SLJIT_SUCCESS; + + case SLJIT_XOR: + EMIT_LOGICAL(XORI, XOR); + return SLJIT_SUCCESS; + + case SLJIT_SHL: + case SLJIT_MSHL: + if (op & SLJIT_32) { + EMIT_SHIFT(SLLI_W, SLL_W); + } else { + EMIT_SHIFT(SLLI_D, SLL_D); + } + break; + + case SLJIT_LSHR: + case SLJIT_MLSHR: + if (op & SLJIT_32) { + EMIT_SHIFT(SRLI_W, SRL_W); + } else { + EMIT_SHIFT(SRLI_D, SRL_D); + } + break; + + case SLJIT_ASHR: + case SLJIT_MASHR: + if (op & SLJIT_32) { + EMIT_SHIFT(SRAI_W, SRA_W); + } else { + EMIT_SHIFT(SRAI_D, SRA_D); + } + break; + + case SLJIT_ROTL: + case SLJIT_ROTR: + if (flags & SRC2_IMM) { + SLJIT_ASSERT(src2 != 0); + + if (GET_OPCODE(op) == SLJIT_ROTL) + src2 = word_size - src2; + return push_inst(compiler, INST(ROTRI, op) | RD(dst) | RJ(src1) | IMM_I12(src2)); + + } + + if (src2 == TMP_ZERO) { + if (dst != src1) + return push_inst(compiler, INST(ADDI, op) | RD(dst) | RJ(src1) | IMM_I12(0)); + return SLJIT_SUCCESS; + } + + if (GET_OPCODE(op) == SLJIT_ROTL) { + FAIL_IF(push_inst(compiler, INST(SUB, op)| RD(OTHER_FLAG) | RJ(TMP_ZERO) | RK(src2))); + src2 = OTHER_FLAG; + } + return push_inst(compiler, INST(ROTR, op) | RD(dst) | RJ(src1) | RK(src2)); + + default: + SLJIT_UNREACHABLE(); + return SLJIT_SUCCESS; + } + + if (flags & SRC2_IMM) { + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, op_imm | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(src2))); + + if (flags & UNUSED_DEST) + return SLJIT_SUCCESS; + return push_inst(compiler, op_imm | RD(dst) | RJ(src1) | IMM_I12(src2)); + } + + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RJ(src1) | RK(src2))); + + if (flags & UNUSED_DEST) + return SLJIT_SUCCESS; + return push_inst(compiler, op_reg | RD(dst) | RJ(src1) | RK(src2)); +} + +#undef IMM_EXTEND + +static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + /* arg1 goes to TMP_REG1 or src reg + arg2 goes to TMP_REG2, imm or src reg + TMP_REG3 can be used for caching + result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */ + sljit_s32 dst_r = TMP_REG2; + sljit_s32 src1_r; + sljit_sw src2_r = 0; + sljit_s32 sugg_src2_r = TMP_REG2; + + if (!(flags & ALT_KEEP_CACHE)) { + compiler->cache_arg = 0; + compiler->cache_argw = 0; + } + + if (dst == 0) { + SLJIT_ASSERT(HAS_FLAGS(op)); + flags |= UNUSED_DEST; + dst = TMP_REG2; + } + else if (FAST_IS_REG(dst)) { + dst_r = dst; + flags |= REG_DEST; + if (flags & MOVE_OP) + sugg_src2_r = dst_r; + } + else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw)) + flags |= SLOW_DEST; + + if (flags & IMM_OP) { + if (src2 == SLJIT_IMM && src2w != 0 && src2w <= I12_MAX && src2w >= I12_MIN) { + flags |= SRC2_IMM; + src2_r = src2w; + } + else if ((flags & CUMULATIVE_OP) && src1 == SLJIT_IMM && src1w != 0 && src1w <= I12_MAX && src1w >= I12_MIN) { + flags |= SRC2_IMM; + src2_r = src1w; + + /* And swap arguments. */ + src1 = src2; + src1w = src2w; + src2 = SLJIT_IMM; + /* src2w = src2_r unneeded. */ + } + } + + /* Source 1. */ + if (FAST_IS_REG(src1)) { + src1_r = src1; + flags |= REG1_SOURCE; + } + else if (src1 == SLJIT_IMM) { + if (src1w) { + FAIL_IF(load_immediate(compiler, TMP_REG1, src1w)); + src1_r = TMP_REG1; + } + else + src1_r = TMP_ZERO; + } + else { + if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w)) + FAIL_IF(compiler->error); + else + flags |= SLOW_SRC1; + src1_r = TMP_REG1; + } + + /* Source 2. */ + if (FAST_IS_REG(src2)) { + src2_r = src2; + flags |= REG2_SOURCE; + if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP) + dst_r = (sljit_s32)src2_r; + } + else if (src2 == SLJIT_IMM) { + if (!(flags & SRC2_IMM)) { + if (src2w) { + FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w)); + src2_r = sugg_src2_r; + } + else { + src2_r = TMP_ZERO; + if (flags & MOVE_OP) { + if (dst & SLJIT_MEM) + dst_r = 0; + else + op = SLJIT_MOV; + } + } + } + } + else { + if (getput_arg_fast(compiler, flags | LOAD_DATA, sugg_src2_r, src2, src2w)) + FAIL_IF(compiler->error); + else + flags |= SLOW_SRC2; + + src2_r = sugg_src2_r; + } + + if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { + SLJIT_ASSERT(src2_r == TMP_REG2); + if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w)); + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw)); + } + else { + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w)); + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw)); + } + } + else if (flags & SLOW_SRC1) + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw)); + else if (flags & SLOW_SRC2) + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw)); + + FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r)); + + if (dst & SLJIT_MEM) { + if (!(flags & SLOW_DEST)) { + getput_arg_fast(compiler, flags, dst_r, dst, dstw); + return compiler->error; + } + return getput_arg(compiler, flags, dst_r, dst, dstw, 0, 0); + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_op0(compiler, op)); + + switch (GET_OPCODE(op)) { + case SLJIT_BREAKPOINT: + return push_inst(compiler, BREAK); + case SLJIT_NOP: + return push_inst(compiler, ANDI | RD(TMP_ZERO) | RJ(TMP_ZERO) | IMM_I12(0)); + case SLJIT_LMUL_UW: + FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(SLJIT_R1) | IMM_I12(0))); + FAIL_IF(push_inst(compiler, MULH_DU | RD(SLJIT_R1) | RJ(SLJIT_R0) | RK(SLJIT_R1))); + return push_inst(compiler, MUL_D | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(TMP_REG1)); + case SLJIT_LMUL_SW: + FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(SLJIT_R1) | IMM_I12(0))); + FAIL_IF(push_inst(compiler, MULH_D | RD(SLJIT_R1) | RJ(SLJIT_R0) | RK(SLJIT_R1))); + return push_inst(compiler, MUL_D | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(TMP_REG1)); + case SLJIT_DIVMOD_UW: + FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(TMP_REG1) | RJ(SLJIT_R0) | IMM_I12(0))); + FAIL_IF(push_inst(compiler, ((op & SLJIT_32)? DIV_WU: DIV_DU) | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(SLJIT_R1))); + return push_inst(compiler, ((op & SLJIT_32)? MOD_WU: MOD_DU) | RD(SLJIT_R1) | RJ(TMP_REG1) | RK(SLJIT_R1)); + case SLJIT_DIVMOD_SW: + FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(TMP_REG1) | RJ(SLJIT_R0) | IMM_I12(0))); + FAIL_IF(push_inst(compiler, INST(DIV, op) | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(SLJIT_R1))); + return push_inst(compiler, INST(MOD, op) | RD(SLJIT_R1) | RJ(TMP_REG1) | RK(SLJIT_R1)); + case SLJIT_DIV_UW: + return push_inst(compiler, ((op & SLJIT_32)? DIV_WU: DIV_DU) | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(SLJIT_R1)); + case SLJIT_DIV_SW: + return push_inst(compiler, INST(DIV, op) | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(SLJIT_R1)); + case SLJIT_ENDBR: + case SLJIT_SKIP_FRAMES_BEFORE_RETURN: + return SLJIT_SUCCESS; + } + + SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 flags = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + ADJUST_LOCAL_OFFSET(src, srcw); + + if (op & SLJIT_32) + flags = INT_DATA | SIGNED_DATA; + + switch (GET_OPCODE(op)) { + case SLJIT_MOV: + case SLJIT_MOV_P: + return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_MOV_U32: + return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u32)srcw : srcw); + + case SLJIT_MOV_S32: + /* Logical operators have no W variant, so sign extended input is necessary for them. */ + case SLJIT_MOV32: + return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s32)srcw : srcw); + + case SLJIT_MOV_U8: + return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw); + + case SLJIT_MOV_S8: + return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw); + + case SLJIT_MOV_U16: + return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw); + + case SLJIT_MOV_S16: + return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw); + + case SLJIT_CLZ: + case SLJIT_CTZ: + case SLJIT_REV: + return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_REV_U16: + case SLJIT_REV_S16: + return emit_op(compiler, op, HALF_DATA, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_REV_U32: + case SLJIT_REV_S32: + return emit_op(compiler, op | SLJIT_32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw); + } + + SLJIT_UNREACHABLE(); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_s32 flags = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w)); + ADJUST_LOCAL_OFFSET(dst, dstw); + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + if (op & SLJIT_32) { + flags |= INT_DATA | SIGNED_DATA; + if (src1 == SLJIT_IMM) + src1w = (sljit_s32)src1w; + if (src2 == SLJIT_IMM) + src2w = (sljit_s32)src2w; + } + + + switch (GET_OPCODE(op)) { + case SLJIT_ADD: + case SLJIT_ADDC: + compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD; + return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_SUB: + case SLJIT_SUBC: + compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB; + return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_MUL: + compiler->status_flags_state = 0; + return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_AND: + case SLJIT_OR: + case SLJIT_XOR: + return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_SHL: + case SLJIT_MSHL: + case SLJIT_LSHR: + case SLJIT_MLSHR: + case SLJIT_ASHR: + case SLJIT_MASHR: + case SLJIT_ROTL: + case SLJIT_ROTR: + if (src2 == SLJIT_IMM) { + if (op & SLJIT_32) + src2w &= 0x1f; + else + src2w &= 0x3f; + } + + return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w); + } + + SLJIT_UNREACHABLE(); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, op, 0, 0, src1, src1w, src2, src2w); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 src1_reg, + sljit_s32 src2_reg, + sljit_s32 src3, sljit_sw src3w) +{ + sljit_s32 is_left; + sljit_ins ins1, ins2, ins3; + sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; + sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64; + + + CHECK_ERROR(); + CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w)); + + is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL); + + if (src1_reg == src2_reg) { + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w); + } + + ADJUST_LOCAL_OFFSET(src3, src3w); + + if (src3 == SLJIT_IMM) { + src3w &= bit_length - 1; + + if (src3w == 0) + return SLJIT_SUCCESS; + + if (is_left) { + ins1 = INST(SLLI, op) | IMM_I12(src3w); + src3w = bit_length - src3w; + ins2 = INST(SRLI, op) | IMM_I12(src3w); + } else { + ins1 = INST(SRLI, op) | IMM_I12(src3w); + src3w = bit_length - src3w; + ins2 = INST(SLLI, op) | IMM_I12(src3w); + } + + FAIL_IF(push_inst(compiler, ins1 | RD(dst_reg) | RJ(src1_reg))); + FAIL_IF(push_inst(compiler, ins2 | RD(TMP_REG1) | RJ(src2_reg))); + return push_inst(compiler, OR | RD(dst_reg) | RJ(dst_reg) | RK(TMP_REG1)); + } + + if (src3 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src3, src3w)); + src3 = TMP_REG2; + } else if (dst_reg == src3) { + push_inst(compiler, INST(ADDI, op) | RD(TMP_REG2) | RJ(src3) | IMM_I12(0)); + src3 = TMP_REG2; + } + + if (is_left) { + ins1 = INST(SLL, op); + ins2 = INST(SRLI, op); + ins3 = INST(SRL, op); + } else { + ins1 = INST(SRL, op); + ins2 = INST(SLLI, op); + ins3 = INST(SLL, op); + } + + FAIL_IF(push_inst(compiler, ins1 | RD(dst_reg) | RJ(src1_reg) | RK(src3))); + + if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) { + FAIL_IF(push_inst(compiler, ins2 | RD(TMP_REG1) | RJ(src2_reg) | IMM_I12(1))); + FAIL_IF(push_inst(compiler, XORI | RD(TMP_REG2) | RJ(src3) | IMM_I12((sljit_ins)bit_length - 1))); + src2_reg = TMP_REG1; + } else + FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(TMP_REG2) | RJ(TMP_ZERO) | RK(src3))); + + FAIL_IF(push_inst(compiler, ins3 | RD(TMP_REG1) | RJ(src2_reg) | RK(TMP_REG2))); + return push_inst(compiler, OR | RD(dst_reg) | RJ(dst_reg) | RK(TMP_REG1)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 base = src & REG_MASK; + + CHECK_ERROR(); + CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); + ADJUST_LOCAL_OFFSET(src, srcw); + + switch (op) { + case SLJIT_FAST_RETURN: + if (FAST_IS_REG(src)) + FAIL_IF(push_inst(compiler, ADDI_D | RD(RETURN_ADDR_REG) | RJ(src) | IMM_I12(0))); + else + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw)); + + return push_inst(compiler, JIRL | RD(TMP_ZERO) | RJ(RETURN_ADDR_REG) | IMM_I12(0)); + case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: + return SLJIT_SUCCESS; + case SLJIT_PREFETCH_L1: + case SLJIT_PREFETCH_L2: + case SLJIT_PREFETCH_L3: + case SLJIT_PREFETCH_ONCE: + if (SLJIT_UNLIKELY(src & OFFS_REG_MASK)) { + srcw &= 0x3; + if (SLJIT_UNLIKELY(srcw)) + FAIL_IF(push_inst(compiler, SLLI_D | RD(TMP_REG1) | RJ(OFFS_REG(src)) | IMM_I12(srcw))); + FAIL_IF(push_inst(compiler, ADD_D | RD(TMP_REG1) | RJ(base) | RK(TMP_REG1))); + } else { + if (base && srcw <= I12_MAX && srcw >= I12_MIN) + return push_inst(compiler,PRELD | RJ(base) | IMM_I12(srcw)); + + FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); + if (base != 0) + FAIL_IF(push_inst(compiler, ADD_D | RD(TMP_REG1) | RJ(base) | RK(TMP_REG1))); + } + return push_inst(compiler, PRELD | RD(0) | RJ(TMP_REG1)); + } + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw) +{ + sljit_s32 dst_r; + + CHECK_ERROR(); + CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + switch (op) { + case SLJIT_FAST_ENTER: + if (FAST_IS_REG(dst)) + return push_inst(compiler, ADDI_D | RD(dst) | RJ(RETURN_ADDR_REG) | IMM_I12(0)); + + SLJIT_ASSERT(RETURN_ADDR_REG == TMP_REG2); + break; + case SLJIT_GET_RETURN_ADDRESS: + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size - SSIZE_OF(sw))); + break; + } + + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg) +{ + CHECK_REG_INDEX(check_sljit_get_register_index(type, reg)); + + if (type == SLJIT_GP_REGISTER) + return reg_map[reg]; + + if (type != SLJIT_FLOAT_REGISTER) + return -1; + + return freg_map[reg]; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, sljit_u32 size) +{ + SLJIT_UNUSED_ARG(size); + CHECK_ERROR(); + CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); + + return push_inst(compiler, *(sljit_ins*)instruction); +} + +/* --------------------------------------------------------------------- */ +/* Floating point operators */ +/* --------------------------------------------------------------------- */ +#define SET_COND(cond) (sljit_ins)(cond << 15) + +#define COND_CUN SET_COND(0x8) /* UN */ +#define COND_CEQ SET_COND(0x4) /* EQ */ +#define COND_CUEQ SET_COND(0xc) /* UN EQ */ +#define COND_CLT SET_COND(0x2) /* LT */ +#define COND_CULT SET_COND(0xa) /* UN LT */ +#define COND_CLE SET_COND(0x6) /* LT EQ */ +#define COND_CULE SET_COND(0xe) /* UN LT EQ */ +#define COND_CNE SET_COND(0x10) /* GT LT */ +#define COND_CUNE SET_COND(0x18) /* UN GT LT */ +#define COND_COR SET_COND(0x14) /* GT LT EQ */ + +#define FINST(inst, type) (sljit_ins)((type & SLJIT_32) ? inst##_S : inst##_D) +#define FCD(cd) (sljit_ins)(cd & 0x7) +#define FCJ(cj) (sljit_ins)((cj & 0x7) << 5) +#define FCA(ca) (sljit_ins)((ca & 0x7) << 15) +#define F_OTHER_FLAG 1 + +#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7)) + +/* convert to inter exact toward zero */ +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins inst; + sljit_u32 word_data = 0; + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + + switch (GET_OPCODE(op)) + { + case SLJIT_CONV_SW_FROM_F64: + word_data = 1; + inst = FINST(FTINTRZ_L, op); + break; + case SLJIT_CONV_S32_FROM_F64: + inst = FINST(FTINTRZ_W, op); + break; + default: + inst = BREAK; + SLJIT_UNREACHABLE(); + } + + if (src & SLJIT_MEM) { + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw)); + src = TMP_FREG1; + } + + FAIL_IF(push_inst(compiler, inst | FRD(TMP_FREG1) | FRJ(src))); + FAIL_IF(push_inst(compiler, FINST(MOVFR2GR, word_data) | RD(dst_r) | FRJ(TMP_FREG1))); + + if (dst & SLJIT_MEM) + return emit_op_mem2(compiler, word_data ? WORD_DATA : INT_DATA, TMP_REG2, dst, dstw, 0, 0); + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins inst; + sljit_u32 word_data = 0; + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; + + switch (GET_OPCODE(op)) + { + case SLJIT_CONV_F64_FROM_SW: + word_data = 1; + inst = (sljit_ins)((op & SLJIT_32) ? FFINT_S_L : FFINT_D_L); + break; + case SLJIT_CONV_F64_FROM_S32: + inst = (sljit_ins)((op & SLJIT_32) ? FFINT_S_W : FFINT_D_W); + break; + default: + inst = BREAK; + SLJIT_UNREACHABLE(); + } + + if (src & SLJIT_MEM) { + FAIL_IF(emit_op_mem2(compiler, (word_data ? WORD_DATA : INT_DATA) | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw)); + src = TMP_REG1; + } else if (src == SLJIT_IMM) { + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) + srcw = (sljit_s32)srcw; + + FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); + src = TMP_REG1; + } + FAIL_IF(push_inst(compiler, (word_data ? MOVGR2FR_D : MOVGR2FR_W) | FRD(dst_r) | RJ(src))); + FAIL_IF(push_inst(compiler, inst | FRD(dst_r) | FRJ(dst_r))); + + if (dst & SLJIT_MEM) + return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0); + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + return sljit_emit_fop1_conv_f64_from_w(compiler, op, dst, dstw, src, srcw); +} + +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins inst; + sljit_u32 word_data = 0; + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; + + switch (GET_OPCODE(op)) + { + case SLJIT_CONV_F64_FROM_UW: + word_data = 1; + inst = (sljit_ins)((op & SLJIT_32) ? FFINT_S_L : FFINT_D_L); + break; + case SLJIT_CONV_F64_FROM_U32: + inst = (sljit_ins)((op & SLJIT_32) ? FFINT_S_W : FFINT_D_W); + break; + default: + inst = BREAK; + SLJIT_UNREACHABLE(); + } + + if (src & SLJIT_MEM) { + FAIL_IF(emit_op_mem2(compiler, (word_data ? WORD_DATA : INT_DATA) | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw)); + src = TMP_REG1; + } else if (src == SLJIT_IMM) { + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) + srcw = (sljit_u32)srcw; + + FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); + src = TMP_REG1; + } + + if (!word_data) + FAIL_IF(push_inst(compiler, SRLI_W | RD(src) | RJ(src) | IMM_I12(0))); + + FAIL_IF(push_inst(compiler, BLT | RJ(src) | RD(TMP_ZERO) | IMM_I16(4))); + + FAIL_IF(push_inst(compiler, (word_data ? MOVGR2FR_D : MOVGR2FR_W) | FRD(dst_r) | RJ(src))); + FAIL_IF(push_inst(compiler, inst | FRD(dst_r) | FRJ(dst_r))); + FAIL_IF(push_inst(compiler, B | IMM_I26(7))); + + FAIL_IF(push_inst(compiler, ANDI | RD(TMP_REG2) | RJ(src) | IMM_I12(1))); + FAIL_IF(push_inst(compiler, (word_data ? SRLI_D : SRLI_W) | RD(TMP_REG1) | RJ(src) | IMM_I12(1))); + FAIL_IF(push_inst(compiler, OR | RD(TMP_REG1) | RJ(TMP_REG1) | RK(TMP_REG2))); + FAIL_IF(push_inst(compiler, INST(MOVGR2FR, (!word_data)) | FRD(dst_r) | RJ(TMP_REG1))); + FAIL_IF(push_inst(compiler, inst | FRD(dst_r) | FRJ(dst_r))); + FAIL_IF(push_inst(compiler, FINST(FADD, op) | FRD(dst_r) | FRJ(dst_r) | FRK(dst_r))); + + if (dst & SLJIT_MEM) + return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0); + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w)); + src1 = TMP_FREG1; + } + + if (src2 & SLJIT_MEM) { + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0)); + src2 = TMP_FREG2; + } + + FAIL_IF(push_inst(compiler, XOR | RD(OTHER_FLAG) | RJ(OTHER_FLAG) | RK(OTHER_FLAG))); + + switch (GET_FLAG_TYPE(op)) { + case SLJIT_F_EQUAL: + case SLJIT_ORDERED_EQUAL: + FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CEQ | FCD(F_OTHER_FLAG) | FRJ(src1) | FRK(src2))); + break; + case SLJIT_F_LESS: + case SLJIT_ORDERED_LESS: + FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CLT | FCD(F_OTHER_FLAG) | FRJ(src1) | FRK(src2))); + break; + case SLJIT_F_GREATER: + case SLJIT_ORDERED_GREATER: + FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CLT | FCD(F_OTHER_FLAG) | FRJ(src2) | FRK(src1))); + break; + case SLJIT_UNORDERED_OR_GREATER: + FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CULT | FCD(F_OTHER_FLAG) | FRJ(src2) | FRK(src1))); + break; + case SLJIT_UNORDERED_OR_LESS: + FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CULT | FCD(F_OTHER_FLAG) | FRJ(src1) | FRK(src2))); + break; + case SLJIT_UNORDERED_OR_EQUAL: + FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CUEQ | FCD(F_OTHER_FLAG) | FRJ(src1) | FRK(src2))); + break; + default: /* SLJIT_UNORDERED */ + FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CUN | FCD(F_OTHER_FLAG) | FRJ(src1) | FRK(src2))); + } + return push_inst(compiler, MOVCF2GR | RD(OTHER_FLAG) | FCJ(F_OTHER_FLAG)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 dst_r; + + CHECK_ERROR(); + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error); + SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw); + + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) + op ^= SLJIT_32; + + dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; + + if (src & SLJIT_MEM) { + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw)); + src = dst_r; + } + + switch (GET_OPCODE(op)) { + case SLJIT_MOV_F64: + if (src != dst_r) { + if (dst_r != TMP_FREG1) + FAIL_IF(push_inst(compiler, FINST(FMOV, op) | FRD(dst_r) | FRJ(src))); + else + dst_r = src; + } + break; + case SLJIT_NEG_F64: + FAIL_IF(push_inst(compiler, FINST(FNEG, op) | FRD(dst_r) | FRJ(src))); + break; + case SLJIT_ABS_F64: + FAIL_IF(push_inst(compiler, FINST(FABS, op) | FRD(dst_r) | FRJ(src))); + break; + case SLJIT_CONV_F64_FROM_F32: + /* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */ + FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? FCVT_D_S : FCVT_S_D) | FRD(dst_r) | FRJ(src))); + op ^= SLJIT_32; + break; + } + + if (dst & SLJIT_MEM) + return emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_s32 dst_r, flags = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); + ADJUST_LOCAL_OFFSET(dst, dstw); + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2; + + if (src1 & SLJIT_MEM) { + if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) { + FAIL_IF(compiler->error); + src1 = TMP_FREG1; + } else + flags |= SLOW_SRC1; + } + + if (src2 & SLJIT_MEM) { + if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) { + FAIL_IF(compiler->error); + src2 = TMP_FREG2; + } else + flags |= SLOW_SRC2; + } + + if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { + if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w)); + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw)); + } + else { + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w)); + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw)); + } + } + else if (flags & SLOW_SRC1) + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw)); + else if (flags & SLOW_SRC2) + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw)); + + if (flags & SLOW_SRC1) + src1 = TMP_FREG1; + if (flags & SLOW_SRC2) + src2 = TMP_FREG2; + + switch (GET_OPCODE(op)) { + case SLJIT_ADD_F64: + FAIL_IF(push_inst(compiler, FINST(FADD, op) | FRD(dst_r) | FRJ(src1) | FRK(src2))); + break; + case SLJIT_SUB_F64: + FAIL_IF(push_inst(compiler, FINST(FSUB, op) | FRD(dst_r) | FRJ(src1) | FRK(src2))); + break; + case SLJIT_MUL_F64: + FAIL_IF(push_inst(compiler, FINST(FMUL, op) | FRD(dst_r) | FRJ(src1) | FRK(src2))); + break; + case SLJIT_DIV_F64: + FAIL_IF(push_inst(compiler, FINST(FDIV, op) | FRD(dst_r) | FRJ(src1) | FRK(src2))); + break; + } + + if (dst_r == TMP_FREG2) + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0)); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_s32 reg; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fop2r(compiler, op, dst_freg, src1, src1w, src2, src2w)); + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + if (src2 & SLJIT_MEM) { + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src2, src2w, 0, 0)); + src2 = TMP_FREG1; + } + + if (src1 & SLJIT_MEM) { + reg = (dst_freg == src2) ? TMP_FREG1 : dst_freg; + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, reg, src1, src1w, 0, 0)); + src1 = reg; + } + + return push_inst(compiler, FINST(FCOPYSIGN, op) | FRD(dst_freg) | FRJ(src1) | FRK(src2)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f32 value) +{ + union { + sljit_s32 imm; + sljit_f32 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset32(compiler, freg, value)); + + u.value = value; + + if (u.imm == 0) + return push_inst(compiler, MOVGR2FR_W | RJ(TMP_ZERO) | FRD(freg)); + + FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm)); + return push_inst(compiler, MOVGR2FR_W | RJ(TMP_REG1) | FRD(freg)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f64 value) +{ + union { + sljit_sw imm; + sljit_f64 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset64(compiler, freg, value)); + + u.value = value; + + if (u.imm == 0) + return push_inst(compiler, MOVGR2FR_D | RJ(TMP_ZERO) | FRD(freg)); + + FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm)); + return push_inst(compiler, MOVGR2FR_D | RJ(TMP_REG1) | FRD(freg)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 freg, sljit_s32 reg) +{ + sljit_ins inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); + + if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) + inst = ((op & SLJIT_32) ? MOVGR2FR_W : MOVGR2FR_D) | FRD(freg) | RJ(reg); + else + inst = ((op & SLJIT_32) ? MOVFR2GR_S : MOVFR2GR_D) | RD(reg) | FRJ(freg); + return push_inst(compiler, inst); +} + +/* --------------------------------------------------------------------- */ +/* Conditional instructions */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) +{ + struct sljit_label *label; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_label(compiler)); + + if (compiler->last_label && compiler->last_label->size == compiler->size) + return compiler->last_label; + + label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); + PTR_FAIL_IF(!label); + set_label(label, compiler); + return label; +} + +static sljit_ins get_jump_instruction(sljit_s32 type) +{ + switch (type) { + case SLJIT_EQUAL: + case SLJIT_ATOMIC_NOT_STORED: + return BNE | RJ(EQUAL_FLAG) | RD(TMP_ZERO); + case SLJIT_NOT_EQUAL: + case SLJIT_ATOMIC_STORED: + return BEQ | RJ(EQUAL_FLAG) | RD(TMP_ZERO); + case SLJIT_LESS: + case SLJIT_GREATER: + case SLJIT_SIG_LESS: + case SLJIT_SIG_GREATER: + case SLJIT_OVERFLOW: + case SLJIT_CARRY: + return BEQ | RJ(OTHER_FLAG) | RD(TMP_ZERO); + case SLJIT_GREATER_EQUAL: + case SLJIT_LESS_EQUAL: + case SLJIT_SIG_GREATER_EQUAL: + case SLJIT_SIG_LESS_EQUAL: + case SLJIT_NOT_OVERFLOW: + case SLJIT_NOT_CARRY: + return BNE | RJ(OTHER_FLAG) | RD(TMP_ZERO); + case SLJIT_F_EQUAL: + case SLJIT_ORDERED_EQUAL: + case SLJIT_F_LESS: + case SLJIT_ORDERED_LESS: + case SLJIT_ORDERED_GREATER: + case SLJIT_UNORDERED_OR_GREATER: + case SLJIT_F_GREATER: + case SLJIT_UNORDERED_OR_LESS: + case SLJIT_UNORDERED_OR_EQUAL: + case SLJIT_UNORDERED: + return BEQ | RJ(OTHER_FLAG) | RD(TMP_ZERO); + case SLJIT_ORDERED_NOT_EQUAL: + case SLJIT_ORDERED_LESS_EQUAL: + case SLJIT_ORDERED_GREATER_EQUAL: + case SLJIT_F_NOT_EQUAL: + case SLJIT_UNORDERED_OR_NOT_EQUAL: + case SLJIT_UNORDERED_OR_GREATER_EQUAL: + case SLJIT_UNORDERED_OR_LESS_EQUAL: + case SLJIT_F_LESS_EQUAL: + case SLJIT_F_GREATER_EQUAL: + case SLJIT_ORDERED: + return BNE | RJ(OTHER_FLAG) | RD(TMP_ZERO); + default: + /* Not conditional branch. */ + return 0; + } +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) +{ + struct sljit_jump *jump; + sljit_ins inst; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_jump(compiler, type)); + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); + type &= 0xff; + + inst = get_jump_instruction(type); + + if (inst != 0) { + PTR_FAIL_IF(push_inst(compiler, inst)); + jump->flags |= IS_COND; + } + + jump->addr = compiler->size; + inst = JIRL | RJ(TMP_REG1) | IMM_I16(0); + + if (type >= SLJIT_FAST_CALL) { + jump->flags |= IS_CALL; + inst |= RD(RETURN_ADDR_REG); + } + + PTR_FAIL_IF(push_inst(compiler, inst)); + + /* Maximum number of instructions required for generating a constant. */ + compiler->size += 3; + + return jump; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types) +{ + SLJIT_UNUSED_ARG(arg_types); + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); + + if (type & SLJIT_CALL_RETURN) { + PTR_FAIL_IF(emit_stack_frame_release(compiler, 0)); + type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP); + } + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_jump(compiler, type); +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + struct sljit_jump *jump; + sljit_s32 flags; + sljit_ins inst; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w)); + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; + + if (src1 & SLJIT_MEM) { + PTR_FAIL_IF(emit_op_mem2(compiler, flags, TMP_REG1, src1, src1w, src2, src2w)); + src1 = TMP_REG1; + } + + if (src2 & SLJIT_MEM) { + PTR_FAIL_IF(emit_op_mem2(compiler, flags, TMP_REG2, src2, src2w, 0, 0)); + src2 = TMP_REG2; + } + + if (src1 == SLJIT_IMM) { + if (src1w != 0) { + PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, src1w)); + src1 = TMP_REG1; + } + else + src1 = TMP_ZERO; + } + + if (src2 == SLJIT_IMM) { + if (src2w != 0) { + PTR_FAIL_IF(load_immediate(compiler, TMP_REG2, src2w)); + src2 = TMP_REG2; + } + else + src2 = TMP_ZERO; + } + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_jump(jump, compiler, (sljit_u32)((type & SLJIT_REWRITABLE_JUMP) | IS_COND)); + type &= 0xff; + + switch (type) { + case SLJIT_EQUAL: + inst = BNE | RJ(src1) | RD(src2); + break; + case SLJIT_NOT_EQUAL: + inst = BEQ | RJ(src1) | RD(src2); + break; + case SLJIT_LESS: + inst = BGEU | RJ(src1) | RD(src2); + break; + case SLJIT_GREATER_EQUAL: + inst = BLTU | RJ(src1) | RD(src2); + break; + case SLJIT_GREATER: + inst = BGEU | RJ(src2) | RD(src1); + break; + case SLJIT_LESS_EQUAL: + inst = BLTU | RJ(src2) | RD(src1); + break; + case SLJIT_SIG_LESS: + inst = BGE | RJ(src1) | RD(src2); + break; + case SLJIT_SIG_GREATER_EQUAL: + inst = BLT | RJ(src1) | RD(src2); + break; + case SLJIT_SIG_GREATER: + inst = BGE | RJ(src2) | RD(src1); + break; + case SLJIT_SIG_LESS_EQUAL: + inst = BLT | RJ(src2) | RD(src1); + break; + default: + inst = BREAK; + SLJIT_UNREACHABLE(); + } + + PTR_FAIL_IF(push_inst(compiler, inst)); + + jump->addr = compiler->size; + PTR_FAIL_IF(push_inst(compiler, JIRL | RD(TMP_ZERO) | RJ(TMP_REG1) | IMM_I12(0))); + + /* Maximum number of instructions required for generating a constant. */ + compiler->size += 3; + + return jump; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) +{ + struct sljit_jump *jump; + + CHECK_ERROR(); + CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); + + if (src != SLJIT_IMM) { + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); + src = TMP_REG1; + } + return push_inst(compiler, JIRL | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RJ(src) | IMM_I12(0)); + } + + /* These jumps are converted to jump/call instructions when possible. */ + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + FAIL_IF(!jump); + set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_CALL : 0)); + jump->u.target = (sljit_uw)srcw; + + jump->addr = compiler->size; + FAIL_IF(push_inst(compiler, JIRL | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RJ(TMP_REG1) | IMM_I12(0))); + + /* Maximum number of instructions required for generating a constant. */ + compiler->size += 3; + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types, + sljit_s32 src, sljit_sw srcw) +{ + SLJIT_UNUSED_ARG(arg_types); + CHECK_ERROR(); + CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); + src = TMP_REG1; + } + + if (type & SLJIT_CALL_RETURN) { + if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) { + FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(src) | IMM_I12(0))); + src = TMP_REG1; + } + + FAIL_IF(emit_stack_frame_release(compiler, 0)); + type = SLJIT_JUMP; + } + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_ijump(compiler, type, src, srcw); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 type) +{ + sljit_s32 src_r, dst_r, invert; + sljit_s32 saved_op = op; + sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA; + + CHECK_ERROR(); + CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + op = GET_OPCODE(op); + dst_r = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2; + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + if (op >= SLJIT_ADD && (dst & SLJIT_MEM)) + FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw)); + + if (type < SLJIT_F_EQUAL) { + src_r = OTHER_FLAG; + invert = type & 0x1; + + switch (type) { + case SLJIT_EQUAL: + case SLJIT_NOT_EQUAL: + FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RJ(EQUAL_FLAG) | IMM_I12(1))); + src_r = dst_r; + break; + case SLJIT_ATOMIC_STORED: + case SLJIT_ATOMIC_NOT_STORED: + FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RJ(EQUAL_FLAG) | IMM_I12(1))); + src_r = dst_r; + invert ^= 0x1; + break; + case SLJIT_OVERFLOW: + case SLJIT_NOT_OVERFLOW: + if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) { + src_r = OTHER_FLAG; + break; + } + FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RJ(OTHER_FLAG) | IMM_I12(1))); + src_r = dst_r; + invert ^= 0x1; + break; + } + } else { + invert = 0; + src_r = OTHER_FLAG; + + switch (type) { + case SLJIT_ORDERED_NOT_EQUAL: + case SLJIT_ORDERED_LESS_EQUAL: + case SLJIT_ORDERED_GREATER_EQUAL: + case SLJIT_F_NOT_EQUAL: + case SLJIT_UNORDERED_OR_NOT_EQUAL: + case SLJIT_UNORDERED_OR_GREATER_EQUAL: + case SLJIT_UNORDERED_OR_LESS_EQUAL: + case SLJIT_F_LESS_EQUAL: + case SLJIT_F_GREATER_EQUAL: + case SLJIT_ORDERED: + invert = 1; + break; + } + } + + if (invert) { + FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RJ(src_r) | IMM_I12(1))); + src_r = dst_r; + } + + if (op < SLJIT_ADD) { + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, mem_type, src_r, dst, dstw); + + if (src_r != dst_r) + return push_inst(compiler, ADDI_D | RD(dst_r) | RJ(src_r) | IMM_I12(0)); + return SLJIT_SUCCESS; + } + + mem_type |= CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE; + + if (dst & SLJIT_MEM) + return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, src_r, 0); + return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, src_r, 0); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_reg) +{ + sljit_ins *ptr; + sljit_uw size; + sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; + + CHECK_ERROR(); + CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg)); + ADJUST_LOCAL_OFFSET(src1, src1w); + + if (dst_reg != src2_reg) { + if (dst_reg == src1) { + src1 = src2_reg; + src1w = 0; + type ^= 0x1; + } else { + if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) { + FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG2) | RJ(dst_reg) | IMM_I12(0))); + + if ((src1 & REG_MASK) == dst_reg) + src1 = (src1 & ~REG_MASK) | TMP_REG2; + + if (OFFS_REG(src1) == dst_reg) + src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG2); + } + + FAIL_IF(push_inst(compiler, ADDI_D | RD(dst_reg) | RJ(src2_reg) | IMM_I12(0))); + } + } + + size = compiler->size; + + ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); + FAIL_IF(!ptr); + compiler->size++; + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w)); + } else if (src1 == SLJIT_IMM) { + if (type & SLJIT_32) + src1w = (sljit_s32)src1w; + FAIL_IF(load_immediate(compiler, dst_reg, src1w)); + } else + FAIL_IF(push_inst(compiler, ADDI_D | RD(dst_reg) | RJ(src1) | IMM_I12(0))); + + *ptr = get_jump_instruction(type & ~SLJIT_32) | IMM_I16(compiler->size - size); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_freg) +{ + sljit_s32 invert = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg)); + + ADJUST_LOCAL_OFFSET(src1, src1w); + + if ((type & ~SLJIT_32) == SLJIT_EQUAL || (type & ~SLJIT_32) == SLJIT_NOT_EQUAL) { + if ((type & ~SLJIT_32) == SLJIT_EQUAL) + invert = 1; + FAIL_IF(push_inst(compiler, MOVGR2CF | FCD(F_OTHER_FLAG) | RJ(EQUAL_FLAG))); + } + else + FAIL_IF(push_inst(compiler, MOVGR2CF | FCD(F_OTHER_FLAG) | RJ(OTHER_FLAG))); + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, dst_freg, src1, src1w)); + if (invert) + return push_inst(compiler, FSEL | FRD(dst_freg) | FRJ(dst_freg) | FRK(src2_freg) | FCA(F_OTHER_FLAG)); + return push_inst(compiler, FSEL | FRD(dst_freg) | FRJ(src2_freg) | FRK(dst_freg) | FCA(F_OTHER_FLAG)); + } else { + if (invert) + return push_inst(compiler, FSEL | FRD(dst_freg) | FRJ(src1) | FRK(src2_freg) | FCA(F_OTHER_FLAG)); + return push_inst(compiler, FSEL | FRD(dst_freg) | FRJ(src2_freg) | FRK(src1) | FCA(F_OTHER_FLAG)); + } +} + +#undef FLOAT_DATA + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_s32 flags; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + + if (!(reg & REG_PAIR_MASK)) + return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw); + + if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { + memw &= 0x3; + + if (SLJIT_UNLIKELY(memw != 0)) { + FAIL_IF(push_inst(compiler, SLLI_D | RD(TMP_REG1) | RJ(OFFS_REG(mem)) | IMM_I12(memw))); + FAIL_IF(push_inst(compiler, ADD_D| RD(TMP_REG1) | RJ(TMP_REG1) | RK(mem & REG_MASK))); + } else + FAIL_IF(push_inst(compiler, ADD_D| RD(TMP_REG1) | RJ(mem & REG_MASK) | RK(OFFS_REG(mem)))); + + mem = TMP_REG1; + memw = 0; + } else if (memw > I12_MAX - SSIZE_OF(sw) || memw < I12_MIN) { + if (((memw + 0x800) & 0xfff) <= 0xfff - SSIZE_OF(sw)) { + FAIL_IF(load_immediate(compiler, TMP_REG1, TO_ARGW_HI(memw))); + memw &= 0xfff; + } else { + FAIL_IF(load_immediate(compiler, TMP_REG1, memw)); + memw = 0; + } + + if (mem & REG_MASK) + FAIL_IF(push_inst(compiler, ADD_D| RD(TMP_REG1) | RJ(TMP_REG1) | RK(mem & REG_MASK))); + + mem = TMP_REG1; + } else { + mem &= REG_MASK; + memw &= 0xfff; + } + + SLJIT_ASSERT((memw >= 0 && memw <= I12_MAX - SSIZE_OF(sw)) || (memw > I12_MAX && memw <= 0xfff)); + + if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) { + FAIL_IF(push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), (memw + SSIZE_OF(sw)) & 0xfff)); + return push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw); + } + + flags = WORD_DATA | (!(type & SLJIT_MEM_STORE) ? LOAD_DATA : 0); + + FAIL_IF(push_mem_inst(compiler, flags, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw)); + return push_mem_inst(compiler, flags, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), (memw + SSIZE_OF(sw)) & 0xfff); +} + +#undef TO_ARGW_HI + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, + sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 mem_reg) +{ + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); + + if (!(LOONGARCH_FEATURE_LAMCAS & get_cpu_features())) + return SLJIT_ERR_UNSUPPORTED; + + switch(GET_OPCODE(op)) { + case SLJIT_MOV_U8: + ins = LD_BU; + break; + case SLJIT_MOV_U16: + ins = LD_HU; + break; + case SLJIT_MOV32: + ins = LD_W; + break; + case SLJIT_MOV_U32: + ins = LD_WU; + break; + default: + ins = LD_D; + break; + } + + return push_inst(compiler, ins | RD(dst_reg) | RJ(mem_reg) | IMM_I12(0)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, + sljit_s32 op, + sljit_s32 src_reg, + sljit_s32 mem_reg, + sljit_s32 temp_reg) +{ + sljit_ins ins = 0; + sljit_ins unsign = 0; + sljit_s32 tmp = temp_reg; + + CHECK_ERROR(); + CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg)); + + if (!(LOONGARCH_FEATURE_LAMCAS & get_cpu_features())) + return SLJIT_ERR_UNSUPPORTED; + + switch (GET_OPCODE(op)) { + case SLJIT_MOV_U8: + ins = AMCAS_B; + unsign = BSTRPICK_D | (7 << 16); + break; + case SLJIT_MOV_U16: + ins = AMCAS_H; + unsign = BSTRPICK_D | (15 << 16); + break; + case SLJIT_MOV32: + ins = AMCAS_W; + break; + case SLJIT_MOV_U32: + ins = AMCAS_W; + unsign = BSTRPICK_D | (31 << 16); + break; + default: + ins = AMCAS_D; + break; + } + + if (op & SLJIT_SET_ATOMIC_STORED) { + FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RJ(temp_reg) | RK(TMP_ZERO))); + tmp = TMP_REG1; + } + FAIL_IF(push_inst(compiler, ins | RD(tmp) | RJ(mem_reg) | RK(src_reg))); + if (!(op & SLJIT_SET_ATOMIC_STORED)) + return SLJIT_SUCCESS; + + if (unsign) + FAIL_IF(push_inst(compiler, unsign | RD(tmp) | RJ(tmp))); + + FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RJ(tmp) | RK(temp_reg))); + return push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RJ(EQUAL_FLAG) | IMM_I12(1)); +} + +static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins) +{ + SLJIT_UNUSED_ARG(last_ins); + + FAIL_IF(push_inst(compiler, LU12I_W | RD(dst) | (sljit_ins)(((init_value & 0xffffffff) >> 12) << 5))); + FAIL_IF(push_inst(compiler, LU32I_D | RD(dst) | (sljit_ins)(((init_value >> 32) & 0xfffff) << 5))); + FAIL_IF(push_inst(compiler, LU52I_D | RD(dst) | RJ(dst) | (sljit_ins)(IMM_I12(init_value >> 52)))); + return push_inst(compiler, ORI | RD(dst) | RJ(dst) | IMM_I12(init_value)); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) +{ + sljit_ins *inst = (sljit_ins*)addr; + SLJIT_UNUSED_ARG(executable_offset); + + SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0); + + SLJIT_ASSERT((inst[0] & OPC_1RI20(0x7f)) == LU12I_W); + inst[0] = (inst[0] & (OPC_1RI20(0x7f) | 0x1f)) | (sljit_ins)(((new_target & 0xffffffff) >> 12) << 5); + + SLJIT_ASSERT((inst[1] & OPC_1RI20(0x7f)) == LU32I_D); + inst[1] = (inst[1] & (OPC_1RI20(0x7f) | 0x1f)) | (sljit_ins)(sljit_ins)(((new_target >> 32) & 0xfffff) << 5); + + SLJIT_ASSERT((inst[2] & OPC_2RI12(0x3ff)) == LU52I_D); + inst[2] = (inst[2] & (OPC_2RI12(0x3ff) | 0x3ff)) | IMM_I12(new_target >> 52); + + SLJIT_ASSERT((inst[3] & OPC_2RI12(0x3ff)) == ORI || (inst[3] & OPC_2RI16(0x3f)) == JIRL); + if ((inst[3] & OPC_2RI12(0x3ff)) == ORI) + inst[3] = (inst[3] & (OPC_2RI12(0x3ff) | 0x3ff)) | IMM_I12(new_target); + else + inst[3] = (inst[3] & (OPC_2RI16(0x3f) | 0x3ff)) | IMM_I12((new_target & 0xfff) >> 2); + + SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1); + + inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); + SLJIT_CACHE_FLUSH(inst, inst + 4); +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) +{ + struct sljit_const *const_; + sljit_s32 dst_r; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); + PTR_FAIL_IF(!const_); + set_const(const_, compiler); + + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + PTR_FAIL_IF(emit_const(compiler, dst_r, init_value, 0)); + + if (dst & SLJIT_MEM) + PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw)); + + return const_; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +{ + struct sljit_put_label *put_label; + sljit_s32 dst_r; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label)); + PTR_FAIL_IF(!put_label); + set_put_label(put_label, compiler, 0); + + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r)); + + compiler->size += 3; + + if (dst & SLJIT_MEM) + PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw)); + + return put_label; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) +{ + sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset); +} diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_32.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_32.c index 1691905db7f..9620b945f65 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_32.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_32.c @@ -26,6 +26,49 @@ /* mips 32-bit arch dependent functions. */ +static sljit_s32 emit_copysign(struct sljit_compiler *compiler, sljit_s32 op, + sljit_sw src1, sljit_sw src2, sljit_sw dst) +{ + int is_32 = (op & SLJIT_32); + sljit_ins mfhc = MFC1, mthc = MTC1; + sljit_ins src1_r = FS(src1), src2_r = FS(src2), dst_r = FS(dst); + + if (!is_32) { + switch (cpu_feature_list & CPU_FEATURE_FR) { +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 + case CPU_FEATURE_FR: + mfhc = MFHC1; + mthc = MTHC1; + break; +#endif /* SLJIT_MIPS_REV >= 2 */ + default: + src1_r |= (1 << 11); + src2_r |= (1 << 11); + dst_r |= (1 << 11); + break; + } + } + + FAIL_IF(push_inst(compiler, mfhc | T(TMP_REG1) | src1_r, DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, mfhc | T(TMP_REG2) | src2_r, DR(TMP_REG2))); + if (!is_32 && src1 != dst) + FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(src1) | FD(dst), MOVABLE_INS)); +#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1 + else + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif /* MIPS III */ + FAIL_IF(push_inst(compiler, XOR | T(TMP_REG1) | D(TMP_REG2) | S(TMP_REG2), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, SRL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, SLL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, XOR | T(TMP_REG2) | D(TMP_REG1) | S(TMP_REG1), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, mthc | T(TMP_REG1) | dst_r, MOVABLE_INS)); +#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1 + if (mthc == MTC1) + return push_inst(compiler, NOP, UNMOVABLE_INS); +#endif /* MIPS III */ + return SLJIT_SUCCESS; +} + static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm) { if (!(imm & ~0xffff)) @@ -44,33 +87,106 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_ return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f64 value) +{ + union { + struct { +#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN + sljit_s32 lo; + sljit_s32 hi; +#else /* !SLJIT_LITTLE_ENDIAN */ + sljit_s32 hi; + sljit_s32 lo; +#endif /* SLJIT_LITTLE_ENDIAN */ + } bin; + sljit_f64 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset64(compiler, freg, value)); + + u.value = value; + + if (u.bin.lo != 0) + FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.bin.lo)); + if (u.bin.hi != 0) + FAIL_IF(load_immediate(compiler, DR(TMP_REG2), u.bin.hi)); + + FAIL_IF(push_inst(compiler, MTC1 | (u.bin.lo != 0 ? T(TMP_REG1) : TA(0)) | FS(freg), MOVABLE_INS)); + switch (cpu_feature_list & CPU_FEATURE_FR) { +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 + case CPU_FEATURE_FR: + return push_inst(compiler, MTHC1 | (u.bin.hi != 0 ? T(TMP_REG2) : TA(0)) | FS(freg), MOVABLE_INS); +#endif /* SLJIT_MIPS_REV >= 2 */ + default: + FAIL_IF(push_inst(compiler, MTC1 | (u.bin.hi != 0 ? T(TMP_REG2) : TA(0)) | FS(freg) | (1 << 11), MOVABLE_INS)); + break; + } +#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1 + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif /* MIPS III */ + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 freg, sljit_s32 reg) { - sljit_s32 reg2; - sljit_ins inst; + sljit_s32 reg2 = 0; + sljit_ins inst = FS(freg); + sljit_ins mthc = MTC1, mfhc = MFC1; + int is_32 = (op & SLJIT_32); CHECK_ERROR(); CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg)); + op = GET_OPCODE(op); if (reg & REG_PAIR_MASK) { reg2 = REG_PAIR_SECOND(reg); reg = REG_PAIR_FIRST(reg); - inst = T(reg2) | FS(freg) | (1 << 11); + inst |= T(reg2); if (op == SLJIT_COPY_TO_F64) FAIL_IF(push_inst(compiler, MTC1 | inst, MOVABLE_INS)); else FAIL_IF(push_inst(compiler, MFC1 | inst, DR(reg2))); + + inst = FS(freg) | (1 << 11); +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 + if (cpu_feature_list & CPU_FEATURE_FR) { + mthc = MTHC1; + mfhc = MFHC1; + inst = FS(freg); + } +#endif /* SLJIT_MIPS_REV >= 2 */ } - inst = T(reg) | FS(freg); + inst |= T(reg); + if (!is_32 && !reg2) { + switch (cpu_feature_list & CPU_FEATURE_FR) { +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 + case CPU_FEATURE_FR: + mthc = MTHC1; + mfhc = MFHC1; + break; +#endif /* SLJIT_MIPS_REV >= 2 */ + default: + inst |= (1 << 11); + break; + } + } - if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) - return push_inst(compiler, MTC1 | inst, MOVABLE_INS); + if (op == SLJIT_COPY_TO_F64) + FAIL_IF(push_inst(compiler, mthc | inst, MOVABLE_INS)); + else + FAIL_IF(push_inst(compiler, mfhc | inst, DR(reg))); - return push_inst(compiler, MFC1 | inst, DR(reg)); +#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1 + if (mthc == MTC1 || mfhc == MFC1) + return push_inst(compiler, NOP, UNMOVABLE_INS); +#endif /* MIPS III */ + return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) @@ -103,6 +219,11 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t sljit_ins ins = NOP; sljit_u8 offsets[4]; sljit_u8 *offsets_ptr = offsets; +#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN + sljit_ins f64_hi = TA(7), f64_lo = TA(6); +#else + sljit_ins f64_hi = TA(6), f64_lo = TA(7); +#endif /* SLJIT_LITTLE_ENDIAN */ SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12); @@ -167,20 +288,28 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t switch (types & SLJIT_ARG_MASK) { case SLJIT_ARG_TYPE_F64: - if (*offsets_ptr < 4 * sizeof (sljit_sw)) { + if (*offsets_ptr < 4 * sizeof(sljit_sw)) { if (prev_ins != NOP) FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS)); /* Must be preceded by at least one other argument, * and its starting offset must be 8 because of alignment. */ SLJIT_ASSERT((*offsets_ptr >> 2) == 2); - - prev_ins = MFC1 | TA(6) | FS(float_arg_count) | (1 << 11); - ins = MFC1 | TA(7) | FS(float_arg_count); + switch (cpu_feature_list & CPU_FEATURE_FR) { +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 + case CPU_FEATURE_FR: + prev_ins = MFHC1 | f64_hi | FS(float_arg_count); + break; +#endif /* SLJIT_MIPS_REV >= 2 */ + default: + prev_ins = MFC1 | f64_hi | FS(float_arg_count) | (1 << 11); + break; + } + ins = MFC1 | f64_lo | FS(float_arg_count); } else if (*offsets_ptr < 254) ins = SDC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(*offsets_ptr); else if (*offsets_ptr == 254) - ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1); + ins = MOV_fmt(FMT_D) | FS(SLJIT_FR0) | FD(TMP_FREG1); float_arg_count--; break; @@ -190,7 +319,7 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t else if (*offsets_ptr < 254) ins = SWC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(*offsets_ptr); else if (*offsets_ptr == 254) - ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1); + ins = MOV_fmt(FMT_S) | FS(SLJIT_FR0) | FD(TMP_FREG1); float_arg_count--; break; @@ -314,7 +443,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); - if (src & SLJIT_IMM) + if (src == SLJIT_IMM) FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw)); else if (src != PIC_ADDR_REG) FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_64.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_64.c index a29fe0730da..52a0d3fb7ad 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_64.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_64.c @@ -26,6 +26,23 @@ /* mips 64-bit arch dependent functions. */ +static sljit_s32 emit_copysign(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src1, sljit_s32 src2, sljit_s32 dst) +{ + FAIL_IF(push_inst(compiler, SELECT_OP(DMFC1, MFC1) | T(TMP_REG1) | FS(src1), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, SELECT_OP(DMFC1, MFC1) | T(TMP_REG2) | FS(src2), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, XOR | S(TMP_REG2) | T(TMP_REG1) | D(TMP_REG2), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | T(TMP_REG2) | D(TMP_REG1), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, SELECT_OP(DMTC1, MTC1) | T(TMP_REG1) | FS(dst), MOVABLE_INS)); +#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1 + if (!(op & SLJIT_32)) + return push_inst(compiler, NOP, UNMOVABLE_INS); +#endif /* MIPS III */ + return SLJIT_SUCCESS; +} + static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm) { sljit_s32 shift = 32; @@ -128,6 +145,35 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_ return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f64 value) +{ + union { + sljit_sw imm; + sljit_f64 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset64(compiler, freg, value)); + + u.value = value; + + if (u.imm == 0) { + FAIL_IF(push_inst(compiler, DMTC1 | TA(0) | FS(freg), MOVABLE_INS)); +#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1 + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif /* MIPS III */ + return SLJIT_SUCCESS; + } + + FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.imm)); + FAIL_IF(push_inst(compiler, DMTC1 | T(TMP_REG1) | FS(freg), MOVABLE_INS)); +#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1 + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif /* MIPS III */ + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 freg, sljit_s32 reg) { @@ -139,9 +185,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compi inst = T(reg) | FS(freg); if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) - return push_inst(compiler, ((op & SLJIT_32) ? MTC1 : DMTC1) | inst, MOVABLE_INS); + FAIL_IF(push_inst(compiler, SELECT_OP(DMTC1, MTC1) | inst, MOVABLE_INS)); + else + FAIL_IF(push_inst(compiler, SELECT_OP(DMFC1, MFC1) | inst, DR(reg))); - return push_inst(compiler, ((op & SLJIT_32) ? MFC1 : DMFC1) | inst, DR(reg)); +#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1 + if (!(op & SLJIT_32)) + return push_inst(compiler, NOP, UNMOVABLE_INS); +#endif /* MIPS III */ + return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) @@ -199,17 +251,17 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t switch (types & SLJIT_ARG_MASK) { case SLJIT_ARG_TYPE_F64: if (arg_count != float_arg_count) - ins = MOV_S | FMT_D | FS(float_arg_count) | FD(arg_count); + ins = MOV_fmt(FMT_D) | FS(float_arg_count) | FD(arg_count); else if (arg_count == 1) - ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1); + ins = MOV_fmt(FMT_D) | FS(SLJIT_FR0) | FD(TMP_FREG1); arg_count--; float_arg_count--; break; case SLJIT_ARG_TYPE_F32: if (arg_count != float_arg_count) - ins = MOV_S | FMT_S | FS(float_arg_count) | FD(arg_count); + ins = MOV_fmt(FMT_S) | FS(float_arg_count) | FD(arg_count); else if (arg_count == 1) - ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1); + ins = MOV_fmt(FMT_S) | FS(SLJIT_FR0) | FD(TMP_FREG1); arg_count--; float_arg_count--; break; @@ -316,7 +368,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); - if (src & SLJIT_IMM) + if (src == SLJIT_IMM) FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw)); else if (src != PIC_ADDR_REG) FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_common.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_common.c index 2b00d4f16d4..eda4a1a64e4 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_common.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeMIPS_common.c @@ -26,9 +26,12 @@ /* Latest MIPS architecture. */ -#ifndef __mips_hard_float +#ifdef HAVE_PRCTL +#include +#endif + +#if !defined(__mips_hard_float) || defined(__mips_single_float) /* Disable automatic detection, covers both -msoft-float and -mno-float */ -#undef SLJIT_IS_FPU_AVAILABLE #define SLJIT_IS_FPU_AVAILABLE 0 #endif @@ -42,6 +45,14 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) return "MIPS64-R6" SLJIT_CPUINFO; #endif /* SLJIT_CONFIG_MIPS_32 */ +#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 5) + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + return "MIPS32-R5" SLJIT_CPUINFO; +#else /* !SLJIT_CONFIG_MIPS_32 */ + return "MIPS64-R5" SLJIT_CPUINFO; +#endif /* SLJIT_CONFIG_MIPS_32 */ + #elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -83,27 +94,31 @@ typedef sljit_u32 sljit_ins; #define EQUAL_FLAG 3 #define OTHER_FLAG 1 +static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = { + 0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 4, 25, 31, 3, 1 +}; + #define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) #define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) #define TMP_FREG3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3) -static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = { - 0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 4, 25, 31 -}; - #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) -static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { - 0, 0, 14, 2, 4, 6, 8, 18, 30, 28, 26, 24, 22, 20, 12, 10, 16 +static const sljit_u8 freg_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3) << 1) + 1] = { + 0, + 0, 14, 2, 4, 6, 8, 18, 30, 28, 26, 24, 22, 20, + 12, 10, 16, + 1, 15, 3, 5, 7, 9, 19, 31, 29, 27, 25, 23, 21, + 13, 11, 17 }; -#else +#else /* !SLJIT_CONFIG_MIPS_32 */ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 1, 2, 3, 4, 5, 6, 7, 8, 9, 31, 30, 29, 28, 27, 26, 25, 24, 12, 11, 10 }; -#endif +#endif /* SLJIT_CONFIG_MIPS_32 */ /* --------------------------------------------------------------------- */ /* Instrucion forms */ @@ -200,12 +215,18 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define DMULTU (HI(0) | LO(29)) #endif /* SLJIT_MIPS_REV >= 6 */ #define DIV_S (HI(17) | FMT_S | LO(3)) +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 #define DINSU (HI(31) | LO(6)) -#define DMFC1 (HI(17) | (1 << 21) | LO(0)) -#define DMTC1 (HI(17) | (5 << 21) | LO(0)) +#endif /* SLJIT_MIPS_REV >= 2 */ +#define DMFC1 (HI(17) | (1 << 21)) +#define DMTC1 (HI(17) | (5 << 21)) +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 #define DROTR (HI(0) | (1 << 21) | LO(58)) #define DROTR32 (HI(0) | (1 << 21) | LO(62)) #define DROTRV (HI(0) | (1 << 6) | LO(22)) +#define DSBH (HI(31) | (2 << 6) | LO(36)) +#define DSHD (HI(31) | (5 << 6) | LO(36)) +#endif /* SLJIT_MIPS_REV >= 2 */ #define DSLL (HI(0) | LO(56)) #define DSLL32 (HI(0) | LO(60)) #define DSLLV (HI(0) | LO(20)) @@ -233,7 +254,10 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define LWL (HI(34)) #define LWR (HI(38)) #define LWC1 (HI(49)) -#define MFC1 (HI(17) | (0 << 21)) +#define MFC1 (HI(17)) +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 +#define MFHC1 (HI(17) | (3 << 21)) +#endif /* SLJIT_MIPS_REV >= 2 */ #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) #define MOD (HI(0) | (3 << 6) | LO(26)) #define MODU (HI(0) | (3 << 6) | LO(27)) @@ -241,8 +265,10 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define MFHI (HI(0) | LO(16)) #define MFLO (HI(0) | LO(18)) #endif /* SLJIT_MIPS_REV >= 6 */ -#define MOV_S (HI(17) | FMT_S | LO(6)) #define MTC1 (HI(17) | (4 << 21)) +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 +#define MTHC1 (HI(17) | (7 << 21)) +#endif /* SLJIT_MIPS_REV >= 2 */ #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) #define MUH (HI(0) | (3 << 6) | LO(24)) #define MUHU (HI(0) | (3 << 6) | LO(25)) @@ -258,8 +284,10 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define NOR (HI(0) | LO(39)) #define OR (HI(0) | LO(37)) #define ORI (HI(13)) +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 #define ROTR (HI(0) | (1 << 21) | LO(2)) #define ROTRV (HI(0) | (1 << 6) | LO(6)) +#endif /* SLJIT_MIPS_REV >= 2 */ #define SD (HI(63)) #define SDL (HI(44)) #define SDR (HI(45)) @@ -281,6 +309,9 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define SWR (HI(46)) #define SWC1 (HI(57)) #define TRUNC_W_S (HI(17) | FMT_S | LO(13)) +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 +#define WSBH (HI(31) | (2 << 6) | LO(32)) +#endif /* SLJIT_MIPS_REV >= 2 */ #define XOR (HI(0) | LO(38)) #define XORI (HI(14)) @@ -291,15 +322,21 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #else /* SLJIT_MIPS_REV < 6 */ #define DCLZ (HI(28) | LO(36)) #define MOVF (HI(0) | (0 << 16) | LO(1)) +#define MOVF_S (HI(17) | FMT_S | (0 << 16) | LO(17)) #define MOVN (HI(0) | LO(11)) +#define MOVN_S (HI(17) | FMT_S | LO(19)) #define MOVT (HI(0) | (1 << 16) | LO(1)) +#define MOVT_S (HI(17) | FMT_S | (1 << 16) | LO(17)) #define MOVZ (HI(0) | LO(10)) +#define MOVZ_S (HI(17) | FMT_S | LO(18)) #define MUL (HI(28) | LO(2)) #endif /* SLJIT_MIPS_REV >= 6 */ #define PREF (HI(51)) #define PREFX (HI(19) | LO(15)) +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 #define SEB (HI(31) | (16 << 6) | LO(32)) #define SEH (HI(31) | (24 << 6) | LO(32)) +#endif /* SLJIT_MIPS_REV >= 2 */ #endif /* SLJIT_MIPS_REV >= 1 */ #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -320,10 +357,107 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define LOAD_W LD #endif +#define MOV_fmt(f) (HI(17) | f | LO(6)) + #define SIMM_MAX (0x7fff) #define SIMM_MIN (-0x8000) #define UIMM_MAX (0xffff) +#define CPU_FEATURE_DETECTED (1 << 0) +#define CPU_FEATURE_FPU (1 << 1) +#define CPU_FEATURE_FP64 (1 << 2) +#define CPU_FEATURE_FR (1 << 3) + +static sljit_u32 cpu_feature_list = 0; + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ + && (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + +static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32) +{ + if (compiler->scratches == -1) + return 0; + + if (is_32 && fr >= SLJIT_F64_SECOND(SLJIT_FR0)) + fr -= SLJIT_F64_SECOND(0); + + return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->fscratches)) + || (fr > (SLJIT_FS0 - compiler->fsaveds) && fr <= SLJIT_FS0) + || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)); +} + +#endif /* SLJIT_CONFIG_MIPS_32 && SLJIT_ARGUMENT_CHECKS */ + +static void get_cpu_features(void) +{ +#if !defined(SLJIT_IS_FPU_AVAILABLE) && defined(__GNUC__) + sljit_u32 fir = 0; +#endif /* !SLJIT_IS_FPU_AVAILABLE && __GNUC__ */ + sljit_u32 feature_list = CPU_FEATURE_DETECTED; + +#if defined(SLJIT_IS_FPU_AVAILABLE) +#if SLJIT_IS_FPU_AVAILABLE + feature_list |= CPU_FEATURE_FPU; +#if SLJIT_IS_FPU_AVAILABLE == 64 + feature_list |= CPU_FEATURE_FP64; +#endif /* SLJIT_IS_FPU_AVAILABLE == 64 */ +#endif /* SLJIT_IS_FPU_AVAILABLE */ +#elif defined(__GNUC__) + __asm__ ("cfc1 %0, $0" : "=r"(fir)); + if ((fir & (0x3 << 16)) == (0x3 << 16)) + feature_list |= CPU_FEATURE_FPU; + +#if (defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64) \ + && (!defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV < 2) + if ((feature_list & CPU_FEATURE_FPU)) + feature_list |= CPU_FEATURE_FP64; +#else /* SLJIT_CONFIG_MIPS32 || SLJIT_MIPS_REV >= 2 */ + if ((fir & (1 << 22))) + feature_list |= CPU_FEATURE_FP64; +#endif /* SLJIT_CONFIG_MIPS_64 && SLJIT_MIPS_REV < 2 */ +#endif /* SLJIT_IS_FPU_AVAILABLE */ + + if ((feature_list & CPU_FEATURE_FPU) && (feature_list & CPU_FEATURE_FP64)) { +#if defined(SLJIT_CONFIG_MIPS_32) && SLJIT_CONFIG_MIPS_32 +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 6 + feature_list |= CPU_FEATURE_FR; +#elif defined(SLJIT_DETECT_FR) && SLJIT_DETECT_FR == 0 +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 5 + feature_list |= CPU_FEATURE_FR; +#endif /* SLJIT_MIPS_REV >= 5 */ +#else + sljit_s32 flag = -1; +#ifndef FR_GET_FP_MODE + sljit_f64 zero = 0.0; +#else /* PR_GET_FP_MODE */ + flag = prctl(PR_GET_FP_MODE); + + if (flag > 0) + feature_list |= CPU_FEATURE_FR; +#endif /* FP_GET_PR_MODE */ +#if ((defined(SLJIT_DETECT_FR) && SLJIT_DETECT_FR == 2) \ + || (!defined(PR_GET_FP_MODE) && (!defined(SLJIT_DETECT_FR) || SLJIT_DETECT_FR >= 1))) \ + && (defined(__GNUC__) && (defined(__mips) && __mips >= 2)) + if (flag < 0) { + __asm__ (".set oddspreg\n" + "lwc1 $f17, %0\n" + "ldc1 $f16, %1\n" + "swc1 $f17, %0\n" + : "+m" (flag) : "m" (zero) : "$f16", "$f17"); + if (flag) + feature_list |= CPU_FEATURE_FR; + } +#endif /* (!PR_GET_FP_MODE || (PR_GET_FP_MODE && SLJIT_DETECT_FR == 2)) && __GNUC__ */ +#endif /* SLJIT_MIPS_REV >= 6 */ +#else /* !SLJIT_CONFIG_MIPS_32 */ + /* StatusFR=1 is the only mode supported by the code in MIPS64 */ + feature_list |= CPU_FEATURE_FR; +#endif /* SLJIT_CONFIG_MIPS_32 */ + } + + cpu_feature_list = feature_list; +} + /* dest_reg is the absolute name of the register Useful for reordering instructions in the delay slot. */ static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot) @@ -370,7 +504,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i if (jump->flags & JUMP_ADDR) target_addr = jump->u.target; else { - SLJIT_ASSERT(jump->flags & JUMP_LABEL); + SLJIT_ASSERT(jump->u.label != NULL); target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset; } @@ -501,72 +635,63 @@ static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_ #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) -static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label) +static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset) { - if (max_label < 0x80000000l) { - put_label->flags = PATCH_ABS32; + sljit_uw addr; + SLJIT_UNUSED_ARG(executable_offset); + + if (jump->flags & JUMP_ADDR) + addr = jump->u.target; + else + addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset); + + if (addr < 0x80000000l) { + jump->flags |= PATCH_ABS32; return 1; } - if (max_label < 0x800000000000l) { - put_label->flags = PATCH_ABS48; + if (addr < 0x800000000000l) { + jump->flags |= PATCH_ABS48; return 3; } - put_label->flags = 0; return 5; } #endif /* SLJIT_CONFIG_MIPS_64 */ -static SLJIT_INLINE void load_addr_to_reg(void *dst, sljit_u32 reg) +static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump) { - struct sljit_jump *jump; - struct sljit_put_label *put_label; - sljit_uw flags; - sljit_ins *inst; - sljit_uw addr; - - if (reg != 0) { - jump = (struct sljit_jump*)dst; - flags = jump->flags; - inst = (sljit_ins*)jump->addr; - addr = (flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; - } else { - put_label = (struct sljit_put_label*)dst; -#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) - flags = put_label->flags; -#endif - inst = (sljit_ins*)put_label->addr; - addr = put_label->label->addr; - reg = *inst; - } + sljit_uw flags = jump->flags; + sljit_ins *ins = (sljit_ins*)jump->addr; + sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr; + sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *ins : PIC_ADDR_REG; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - inst[0] = LUI | T(reg) | IMM(addr >> 16); + ins[0] = LUI | T(reg) | IMM(addr >> 16); #else /* !SLJIT_CONFIG_MIPS_32 */ if (flags & PATCH_ABS32) { SLJIT_ASSERT(addr < 0x80000000l); - inst[0] = LUI | T(reg) | IMM(addr >> 16); + ins[0] = LUI | T(reg) | IMM(addr >> 16); } else if (flags & PATCH_ABS48) { SLJIT_ASSERT(addr < 0x800000000000l); - inst[0] = LUI | T(reg) | IMM(addr >> 32); - inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff); - inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16); - inst += 2; + ins[0] = LUI | T(reg) | IMM(addr >> 32); + ins[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff); + ins[2] = DSLL | T(reg) | D(reg) | SH_IMM(16); + ins += 2; } else { - inst[0] = LUI | T(reg) | IMM(addr >> 48); - inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 32) & 0xffff); - inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16); - inst[3] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff); - inst[4] = DSLL | T(reg) | D(reg) | SH_IMM(16); - inst += 4; + ins[0] = LUI | T(reg) | IMM(addr >> 48); + ins[1] = ORI | S(reg) | T(reg) | IMM((addr >> 32) & 0xffff); + ins[2] = DSLL | T(reg) | D(reg) | SH_IMM(16); + ins[3] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff); + ins[4] = DSLL | T(reg) | D(reg) | SH_IMM(16); + ins += 4; } #endif /* SLJIT_CONFIG_MIPS_32 */ - inst[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff); + ins[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff); } SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) @@ -577,14 +702,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil sljit_ins *buf_ptr; sljit_ins *buf_end; sljit_uw word_count; - sljit_uw next_addr; + SLJIT_NEXT_DEFINE_TYPES; sljit_sw executable_offset; sljit_uw addr; - struct sljit_label *label; struct sljit_jump *jump; struct sljit_const *const_; - struct sljit_put_label *put_label; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_generate_code(compiler)); @@ -596,58 +719,61 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil code_ptr = code; word_count = 0; - next_addr = 0; executable_offset = SLJIT_EXEC_OFFSET(code); label = compiler->labels; jump = compiler->jumps; const_ = compiler->consts; - put_label = compiler->put_labels; + SLJIT_NEXT_INIT_TYPES(); + SLJIT_GET_NEXT_MIN(); do { buf_ptr = (sljit_ins*)buf->memory; buf_end = buf_ptr + (buf->used_size >> 2); do { *code_ptr = *buf_ptr++; - if (next_addr == word_count) { + if (next_min_addr == word_count) { SLJIT_ASSERT(!label || label->size >= word_count); SLJIT_ASSERT(!jump || jump->addr >= word_count); SLJIT_ASSERT(!const_ || const_->addr >= word_count); - SLJIT_ASSERT(!put_label || put_label->addr >= word_count); /* These structures are ordered by their address. */ - if (label && label->size == word_count) { - label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + if (next_min_addr == next_label_size) { + label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); label->size = (sljit_uw)(code_ptr - code); label = label->next; + next_label_size = SLJIT_GET_NEXT_SIZE(label); } - if (jump && jump->addr == word_count) { + + if (next_min_addr == next_jump_addr) { + if (!(jump->flags & JUMP_MOV_ADDR)) { #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - word_count += 2; -#else - word_count += 6; -#endif - jump->addr = (sljit_uw)(code_ptr - 1); - code_ptr = detect_jump_type(jump, code, executable_offset); + word_count += 2; +#else /* !SLJIT_CONFIG_MIPS_32 */ + word_count += 6; +#endif /* SLJIT_CONFIG_MIPS_32 */ + jump->addr = (sljit_uw)(code_ptr - 1); + code_ptr = detect_jump_type(jump, code, executable_offset); + } else { + jump->addr = (sljit_uw)code_ptr; +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + code_ptr += 1; + word_count += 1; +#else /* !SLJIT_CONFIG_MIPS_32 */ + code_ptr += mov_addr_get_length(jump, code, executable_offset); + word_count += 5; +#endif /* SLJIT_CONFIG_MIPS_32 */ + } + jump = jump->next; - } - if (const_ && const_->addr == word_count) { + next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); + } else if (next_min_addr == next_const_addr) { const_->addr = (sljit_uw)code_ptr; const_ = const_->next; + next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_); } - if (put_label && put_label->addr == word_count) { - SLJIT_ASSERT(put_label->label); - put_label->addr = (sljit_uw)code_ptr; -#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - code_ptr += 1; - word_count += 1; -#else - code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size)); - word_count += 5; -#endif - put_label = put_label->next; - } - next_addr = compute_next_addr(label, jump, const_, put_label); + + SLJIT_GET_NEXT_MIN(); } code_ptr++; word_count++; @@ -657,7 +783,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil } while (buf); if (label && label->size == word_count) { - label->addr = (sljit_uw)code_ptr; + label->u.addr = (sljit_uw)code_ptr; label->size = (sljit_uw)(code_ptr - code); label = label->next; } @@ -665,13 +791,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil SLJIT_ASSERT(!label); SLJIT_ASSERT(!jump); SLJIT_ASSERT(!const_); - SLJIT_ASSERT(!put_label); SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size); jump = compiler->jumps; while (jump) { do { - addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; + addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr; buf_ptr = (sljit_ins *)jump->addr; if (jump->flags & PATCH_B) { @@ -687,15 +812,10 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil break; } - load_addr_to_reg(jump, PIC_ADDR_REG); + load_addr_to_reg(jump); } while (0); - jump = jump->next; - } - put_label = compiler->put_labels; - while (put_label) { - load_addr_to_reg(put_label, 0); - put_label = put_label->next; + jump = jump->next; } compiler->error = SLJIT_ERR_COMPILED; @@ -717,20 +837,20 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) { -#if defined(__GNUC__) && !defined(SLJIT_IS_FPU_AVAILABLE) - sljit_sw fir = 0; -#endif /* __GNUC__ && !SLJIT_IS_FPU_AVAILABLE */ - switch (feature_type) { +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ + && (!defined(SLJIT_IS_FPU_AVAILABLE) || SLJIT_IS_FPU_AVAILABLE) + case SLJIT_HAS_F64_AS_F32_PAIR: + if (!cpu_feature_list) + get_cpu_features(); + + return (cpu_feature_list & CPU_FEATURE_FR) != 0; +#endif /* SLJIT_CONFIG_MIPS_32 && SLJIT_IS_FPU_AVAILABLE */ case SLJIT_HAS_FPU: -#ifdef SLJIT_IS_FPU_AVAILABLE - return SLJIT_IS_FPU_AVAILABLE; -#elif defined(__GNUC__) - __asm__ ("cfc1 %0, $0" : "=r"(fir)); - return (fir >> 22) & 0x1; -#else -#error "FIR check is not implemented for this architecture" -#endif + if (!cpu_feature_list) + get_cpu_features(); + + return (cpu_feature_list & CPU_FEATURE_FPU) != 0; case SLJIT_HAS_ZERO_REGISTER: case SLJIT_HAS_COPY_F32: case SLJIT_HAS_COPY_F64: @@ -745,6 +865,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) return 2; #endif /* SLJIT_MIPS_REV >= 1 */ #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) + case SLJIT_HAS_REV: case SLJIT_HAS_ROT: return 1; #endif /* SLJIT_MIPS_REV >= 2 */ @@ -755,7 +876,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) { - return (type >= SLJIT_ORDERED_EQUAL && type <= SLJIT_ORDERED_LESS_EQUAL); + SLJIT_UNUSED_ARG(type); + return 0; } /* --------------------------------------------------------------------- */ @@ -795,6 +917,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw); static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr); +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) +#define SELECT_OP(a, b) (b) +#else +#define SELECT_OP(a, b) (!(op & SLJIT_32) ? a : b) +#endif + #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) #include "sljitNativeMIPS_32.c" #else @@ -922,10 +1050,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi if (word_arg_count == 0 && float_arg_count <= 2) { if (float_arg_count == 1) - FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS)); } else if (arg_count < 4) { FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS)); - FAIL_IF(push_inst(compiler, MTC1 | TA(5 + arg_count) | FS(float_arg_count) | (1 << 11), MOVABLE_INS)); + switch (cpu_feature_list & CPU_FEATURE_FR) { +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 + case CPU_FEATURE_FR: + FAIL_IF(push_inst(compiler, MTHC1 | TA(5 + arg_count) | FS(float_arg_count), MOVABLE_INS)); + break; +#endif /* SLJIT_MIPS_REV >= 2 */ + default: + FAIL_IF(push_inst(compiler, MTC1 | TA(5 + arg_count) | FS(float_arg_count) | (1 << 11), MOVABLE_INS)); + break; + } } else FAIL_IF(push_inst(compiler, LDC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS)); arg_count++; @@ -935,7 +1072,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi if (word_arg_count == 0 && float_arg_count <= 2) { if (float_arg_count == 1) - FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS)); } else if (arg_count < 4) FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS)); else @@ -970,16 +1107,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi case SLJIT_ARG_TYPE_F64: float_arg_count++; if (arg_count != float_arg_count) - FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(arg_count) | FD(float_arg_count), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(arg_count) | FD(float_arg_count), MOVABLE_INS)); else if (arg_count == 1) - FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS)); break; case SLJIT_ARG_TYPE_F32: float_arg_count++; if (arg_count != float_arg_count) - FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(arg_count) | FD(float_arg_count), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(arg_count) | FD(float_arg_count), MOVABLE_INS)); else if (arg_count == 1) - FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS)); break; default: word_arg_count++; @@ -1142,7 +1279,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *c FAIL_IF(emit_stack_frame_release(compiler, 1, &ins)); - if (!(src & SLJIT_IMM)) { + if (src != SLJIT_IMM) { FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS)); return push_inst(compiler, ins, UNMOVABLE_INS); } @@ -1392,16 +1529,12 @@ static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, slji #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) -#define SELECT_OP(a, b) (b) - #define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \ op_imm = (imm); \ op_v = (v); #else /* !SLJIT_CONFIG_MIPS_32 */ -#define SELECT_OP(a, b) \ - (!(op & SLJIT_32) ? a : b) #define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \ op_dimm = (dimm); \ @@ -1418,10 +1551,10 @@ static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, slj { sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ); #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) - sljit_ins max = (op & SLJIT_32) ? 32 : 64; -#else /* !SLJIT_CONFIG_RISCV_64 */ - sljit_ins max = 32; -#endif /* SLJIT_CONFIG_RISCV_64 */ + sljit_ins word_size = (op & SLJIT_32) ? 32 : 64; +#else /* !SLJIT_CONFIG_MIPS_64 */ + sljit_ins word_size = 32; +#endif /* SLJIT_CONFIG_MIPS_64 */ /* The TMP_REG2 is the next value. */ if (src != TMP_REG2) @@ -1429,7 +1562,7 @@ static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, slj FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(is_clz ? 13 : 14), UNMOVABLE_INS)); /* The OTHER_FLAG is the counter. Delay slot. */ - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(max), OTHER_FLAG)); + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(word_size), OTHER_FLAG)); if (!is_clz) { FAIL_IF(push_inst(compiler, ANDI | S(TMP_REG2) | T(TMP_REG1) | IMM(1), DR(TMP_REG1))); @@ -1441,7 +1574,7 @@ static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, slj FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(0), OTHER_FLAG)); /* The TMP_REG1 is the next shift. */ - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(TMP_REG1) | IMM(max), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(TMP_REG1) | IMM(word_size), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(TMP_REG2) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); FAIL_IF(push_inst(compiler, SELECT_OP(DSRL, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1))); @@ -1465,18 +1598,39 @@ static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, slj static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src) { - SLJIT_UNUSED_ARG(op); +#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64 + int is_32 = (op & SLJIT_32); +#endif /* SLJIT_CONFIG_MIPS_64 */ + op = GET_OPCODE(op); +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 +#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64 + if (!is_32 && (op == SLJIT_REV)) { + FAIL_IF(push_inst(compiler, DSBH | T(src) | D(dst), DR(dst))); + return push_inst(compiler, DSHD | T(dst) | D(dst), DR(dst)); + } + if (op != SLJIT_REV && src != TMP_REG2) { + FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG1), DR(TMP_REG1))); + src = TMP_REG1; + } +#endif /* SLJIT_CONFIG_MIPS_64 */ + FAIL_IF(push_inst(compiler, WSBH | T(src) | D(dst), DR(dst))); + FAIL_IF(push_inst(compiler, ROTR | T(dst) | D(dst) | SH_IMM(16), DR(dst))); +#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64 + if (op == SLJIT_REV_U32 && dst != TMP_REG2 && dst != TMP_REG3) + FAIL_IF(push_inst(compiler, DINSU | T(dst) | SA(0) | (31 << 11), DR(dst))); +#endif /* SLJIT_CONFIG_MIPS_64 */ +#else /* SLJIT_MIPS_REV < 2 */ #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) - if (!(op & SLJIT_32)) { + if (!is_32) { FAIL_IF(push_inst(compiler, DSRL32 | T(src) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, ORI | SA(0) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG)); FAIL_IF(push_inst(compiler, DSLL32 | T(src) | D(dst) | SH_IMM(0), DR(dst))); FAIL_IF(push_inst(compiler, DSLL32 | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(0), OTHER_FLAG)); FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst))); - FAIL_IF(push_inst(compiler, ORI | SA(OTHER_FLAG) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG)); FAIL_IF(push_inst(compiler, DSRL | T(dst) | D(TMP_REG1) | SH_IMM(16), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, ORI | SA(OTHER_FLAG) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG)); FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, DSLL | TA(OTHER_FLAG) | DA(EQUAL_FLAG) | SH_IMM(8), EQUAL_FLAG)); @@ -1490,6 +1644,11 @@ static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(8), DR(dst))); return push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)); } + + if (op != SLJIT_REV && src != TMP_REG2) { + FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG2) | SH_IMM(0), DR(TMP_REG2))); + src = TMP_REG2; + } #endif /* SLJIT_CONFIG_MIPS_64 */ FAIL_IF(push_inst(compiler, SRL | T(src) | D(TMP_REG1) | SH_IMM(16), DR(TMP_REG1))); @@ -1502,7 +1661,37 @@ static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, SLL | T(dst) | D(dst) | SH_IMM(8), DR(dst))); + FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst))); + +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + if (op == SLJIT_REV_U32 && dst != TMP_REG2 && dst != TMP_REG3) { + FAIL_IF(push_inst(compiler, DSLL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst))); + FAIL_IF(push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst))); + } +#endif /* SLJIT_CONFIG_MIPS_64 */ +#endif /* SLJIT_MIPR_REV >= 2 */ + return SLJIT_SUCCESS; +} + +static sljit_s32 emit_rev16(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src) +{ +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 +#if defined(SLJIT_CONFIG_MIPS_32) && SLJIT_CONFIG_MIPS_32 + FAIL_IF(push_inst(compiler, WSBH | T(src) | D(dst), DR(dst))); +#else /* !SLJIT_CONFIG_MIPS_32 */ + FAIL_IF(push_inst(compiler, DSBH | T(src) | D(dst), DR(dst))); +#endif /* SLJIT_CONFIG_MIPS_32 */ + if (GET_OPCODE(op) == SLJIT_REV_U16) + return push_inst(compiler, ANDI | S(dst) | T(dst) | 0xffff, DR(dst)); + else + return push_inst(compiler, SEH | T(dst) | D(dst), DR(dst)); +#else /* SLJIT_MIPS_REV < 2 */ + FAIL_IF(push_inst(compiler, SELECT_OP(DSRL, SRL) | T(src) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | T(src) | D(dst) | SH_IMM(24), DR(dst))); + FAIL_IF(push_inst(compiler, ANDI | S(TMP_REG1) | T(TMP_REG1) | 0xff, DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SELECT_OP(DSRL32, SRL) : SELECT_OP(DSRA32, SRA)) | T(dst) | D(dst) | SH_IMM(16), DR(dst))); return push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)); +#endif /* SLJIT_MIPS_REV >= 2 */ } static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, @@ -1532,17 +1721,17 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst)); -#else /* SLJIT_MIPS_REV < 1 */ +#else /* SLJIT_MIPS_REV < 2 */ FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst))); return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst)); -#endif /* SLJIT_MIPS_REV >= 1 */ +#endif /* SLJIT_MIPS_REV >= 2 */ #else /* !SLJIT_CONFIG_MIPS_32 */ -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) if (op & SLJIT_32) return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst)); -#endif /* SLJIT_MIPS_REV >= 1 */ +#endif /* SLJIT_MIPS_REV >= 2 */ FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst))); return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst)); #endif /* SLJIT_CONFIG_MIPS_32 */ @@ -1561,17 +1750,17 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst)); -#else /* SLJIT_MIPS_REV < 1 */ +#else /* SLJIT_MIPS_REV < 2 */ FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst))); return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst)); -#endif /* SLJIT_MIPS_REV >= 1 */ +#endif /* SLJIT_MIPS_REV >= 2 */ #else /* !SLJIT_CONFIG_MIPS_32 */ -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) if (op & SLJIT_32) return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst)); -#endif /* SLJIT_MIPS_REV >= 1 */ +#endif /* SLJIT_MIPS_REV >= 2 */ FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst))); return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst)); #endif /* SLJIT_CONFIG_MIPS_32 */ @@ -1585,7 +1774,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) if (dst == src2) - return push_inst(compiler, DINSU | T(src2) | SA(0) | (31 << 11) | (0 << 11), DR(dst)); + return push_inst(compiler, DINSU | T(src2) | SA(0) | (31 << 11), DR(dst)); #endif /* SLJIT_MIPS_REV >= 2 */ FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst))); return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)); @@ -1630,9 +1819,16 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl #endif /* SLJIT_MIPS_REV >= 1 */ case SLJIT_REV: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + case SLJIT_REV_U32: + case SLJIT_REV_S32: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && src2 != TMP_REG1 && dst != TMP_REG1); return emit_rev(compiler, op, dst, src2); + case SLJIT_REV_U16: + case SLJIT_REV_S16: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + return emit_rev16(compiler, op, dst, src2); + case SLJIT_ADD: /* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; @@ -2080,9 +2276,10 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 compiler->cache_argw = 0; } - if (dst == TMP_REG2) { + if (dst == 0) { SLJIT_ASSERT(HAS_FLAGS(op)); flags |= UNUSED_DEST; + dst = TMP_REG2; } else if (FAST_IS_REG(dst)) { dst_r = dst; @@ -2094,10 +2291,10 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 flags |= SLOW_DEST; if (flags & IMM_OP) { - if ((src2 & SLJIT_IMM) && src2w != 0 && CHECK_IMM(flags, src2w)) { + if (src2 == SLJIT_IMM && src2w != 0 && CHECK_IMM(flags, src2w)) { flags |= SRC2_IMM; src2_r = src2w; - } else if ((flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w != 0 && CHECK_IMM(flags, src1w)) { + } else if ((flags & CUMULATIVE_OP) && src1 == SLJIT_IMM && src1w != 0 && CHECK_IMM(flags, src1w)) { flags |= SRC2_IMM; src2_r = src1w; @@ -2114,7 +2311,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 src1_r = src1; flags |= REG1_SOURCE; } - else if (src1 & SLJIT_IMM) { + else if (src1 == SLJIT_IMM) { if (src1w) { FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); src1_r = TMP_REG1; @@ -2137,7 +2334,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP) dst_r = (sljit_s32)src2_r; } - else if (src2 & SLJIT_IMM) { + else if (src2 == SLJIT_IMM) { if (!(flags & SRC2_IMM)) { if (src2w) { FAIL_IF(load_immediate(compiler, DR(sugg_src2_r), src2w)); @@ -2325,29 +2522,37 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) case SLJIT_MOV_U32: - return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw); + return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u32)srcw : srcw); case SLJIT_MOV_S32: case SLJIT_MOV32: - return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s32)srcw : srcw); + return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s32)srcw : srcw); #endif case SLJIT_MOV_U8: - return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw); + return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw); case SLJIT_MOV_S8: - return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw); + return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw); case SLJIT_MOV_U16: - return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw); + return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw); case SLJIT_MOV_S16: - return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); + return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw); case SLJIT_CLZ: case SLJIT_CTZ: case SLJIT_REV: return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_REV_U16: + case SLJIT_REV_S16: + return emit_op(compiler, op, HALF_DATA, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_REV_U32: + case SLJIT_REV_S32: + return emit_op(compiler, op | SLJIT_32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw); } SLJIT_UNREACHABLE(); @@ -2370,9 +2575,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) if (op & SLJIT_32) { flags |= INT_DATA | SIGNED_DATA; - if (src1 & SLJIT_IMM) + if (src1 == SLJIT_IMM) src1w = (sljit_s32)src1w; - if (src2 & SLJIT_IMM) + if (src2 == SLJIT_IMM) src2w = (sljit_s32)src2w; } #endif @@ -2393,7 +2598,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w); case SLJIT_XOR: - if (((src1 & SLJIT_IMM) && src1w == -1) || ((src2 & SLJIT_IMM) && src2w == -1)) { + if ((src1 == SLJIT_IMM && src1w == -1) || (src2 == SLJIT_IMM && src2w == -1)) { return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); } /* fallthrough */ @@ -2410,10 +2615,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile case SLJIT_ROTL: case SLJIT_ROTR: #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - if (src2 & SLJIT_IMM) + if (src2 == SLJIT_IMM) src2w &= 0x1f; #else - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { if (op & SLJIT_32) src2w &= 0x1f; else @@ -2435,7 +2640,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w)); SLJIT_SKIP_CHECKS(compiler); - return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w); + return sljit_emit_op2(compiler, op, 0, 0, src1, src1w, src2, src2w); } #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) @@ -2474,7 +2679,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * ADJUST_LOCAL_OFFSET(src3, src3w); - if (src3 & SLJIT_IMM) { + if (src3 == SLJIT_IMM) { src3w &= bit_length - 1; if (src3w == 0) @@ -2591,21 +2796,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg) { - CHECK_REG_INDEX(check_sljit_get_register_index(reg)); - return reg_map[reg]; -} + CHECK_REG_INDEX(check_sljit_get_register_index(type, reg)); + + if (type == SLJIT_GP_REGISTER) + return reg_map[reg]; + + if (type != SLJIT_FLOAT_REGISTER) + return -1; -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) -{ - CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); return FR(reg); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, void *instruction, sljit_u32 size) { + SLJIT_UNUSED_ARG(size); + CHECK_ERROR(); CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); @@ -2617,14 +2825,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c /* --------------------------------------------------------------------- */ #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7)) -#define FMT(op) ((((sljit_ins)op & SLJIT_32) ^ SLJIT_32) << (21 - 8)) +#define FMT(op) (FMT_S | (~(sljit_ins)op & SLJIT_32) << (21 - (5 + 3))) static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) -# define flags (sljit_u32)0 + sljit_u32 flags = 0; #else sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21; #endif @@ -2638,18 +2846,13 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp if (FAST_IS_REG(dst)) { FAIL_IF(push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS)); -#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) +#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1) FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); -#endif +#endif /* MIPS III */ return SLJIT_SUCCESS; } - /* Store the integer value from a VFP register. */ return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0); - -#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) -# undef flags -#endif } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, @@ -2657,43 +2860,158 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) -# define flags (sljit_u32)0 + sljit_u32 flags = 0; #else sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)) << 21; #endif - sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; - if (FAST_IS_REG(src)) { - FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS)); -#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) - FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); -#endif - } else if (src & SLJIT_MEM) { - /* Load the integer value into a VFP register. */ + if (src & SLJIT_MEM) FAIL_IF(emit_op_mem2(compiler, (flags ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw)); - } else { + if (src == SLJIT_IMM) { #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) - if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) - srcw = (sljit_s32)srcw; + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) + srcw = (sljit_s32)srcw; #endif - FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw)); - FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS)); -#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) + FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw)); + src = TMP_REG1; + } + + FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS)); +#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1) FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); -#endif +#endif /* MIPS III */ } - FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((((sljit_ins)op & SLJIT_32) ^ SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS)); if (dst & SLJIT_MEM) return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0); return SLJIT_SUCCESS; +} +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) -# undef flags + sljit_u32 flags = 0; +#else + sljit_u32 flags = 1 << 21; #endif + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; + + if (src & SLJIT_MEM) { + FAIL_IF(emit_op_mem2(compiler, (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_UW ? WORD_DATA : INT_DATA) | LOAD_DATA, DR(TMP_REG1), src, srcw, dst, dstw)); + src = TMP_REG1; + } else if (src == SLJIT_IMM) { +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) + srcw = (sljit_u32)srcw; +#endif + FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw)); + src = TMP_REG1; + } + +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) { + if (src != TMP_REG1) { + FAIL_IF(push_inst(compiler, DSLL32 | T(src) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, DSRL32 | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1))); + } + + FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS)); +#if !defined(SLJIT_MIPS_REV) + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif /* MIPS III */ + + FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS)); + + if (dst & SLJIT_MEM) + return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0); + return SLJIT_SUCCESS; + } +#else /* !SLJIT_CONFIG_MIPS_64 */ + if (!(op & SLJIT_32)) { + FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG2) | SH_IMM(1), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, SRL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(1), DR(TMP_REG2))); + + FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG2) | FS(TMP_FREG1), MOVABLE_INS)); +#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1 + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif /* MIPS III */ + + FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | 1 | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS)); + +#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1) + FAIL_IF(push_inst(compiler, BGEZ | S(src) | 5, UNMOVABLE_INS)); +#else /* SLJIT_MIPS_REV >= 1 */ + FAIL_IF(push_inst(compiler, BGEZ | S(src) | 4, UNMOVABLE_INS)); +#endif /* SLJIT_MIPS_REV < 1 */ + + FAIL_IF(push_inst(compiler, LUI | T(TMP_REG2) | IMM(0x41e0), UNMOVABLE_INS)); + FAIL_IF(push_inst(compiler, MTC1 | TA(0) | FS(TMP_FREG2), UNMOVABLE_INS)); + switch (cpu_feature_list & CPU_FEATURE_FR) { +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 + case CPU_FEATURE_FR: + FAIL_IF(push_inst(compiler, MTHC1 | T(TMP_REG2) | FS(TMP_FREG2), UNMOVABLE_INS)); + break; +#endif /* SLJIT_MIPS_REV >= 2 */ + default: + FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(TMP_FREG2) | (1 << 11), UNMOVABLE_INS)); +#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1 + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif /* MIPS III */ + break; + } + FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(TMP_FREG2) | FS(dst_r) | FD(dst_r), UNMOVABLE_INS)); + + if (dst & SLJIT_MEM) + return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0); + return SLJIT_SUCCESS; + } +#endif /* SLJIT_CONFIG_MIPS_64 */ + +#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1) + FAIL_IF(push_inst(compiler, BLTZ | S(src) | 5, UNMOVABLE_INS)); +#else /* SLJIT_MIPS_REV >= 1 */ + FAIL_IF(push_inst(compiler, BLTZ | S(src) | 4, UNMOVABLE_INS)); +#endif /* SLJIT_MIPS_REV < 1 */ + FAIL_IF(push_inst(compiler, ANDI | S(src) | T(TMP_REG2) | IMM(1), DR(TMP_REG2))); + + FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS)); +#if !defined(SLJIT_MIPS_REV) + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif /* !SLJIT_MIPS_REV */ + + FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS)); + +#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1) + FAIL_IF(push_inst(compiler, BEQ | 6, UNMOVABLE_INS)); +#else /* SLJIT_MIPS_REV >= 1 */ + FAIL_IF(push_inst(compiler, BEQ | 5, UNMOVABLE_INS)); +#endif /* SLJIT_MIPS_REV < 1 */ + +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + FAIL_IF(push_inst(compiler, DSRL | T(src) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1))); +#else /* !SLJIT_CONFIG_MIPS_64 */ + FAIL_IF(push_inst(compiler, SRL | T(src) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1))); +#endif /* SLJIT_CONFIG_MIPS_64 */ + + FAIL_IF(push_inst(compiler, OR | S(TMP_REG1) | T(TMP_REG2) | D(TMP_REG1), DR(TMP_REG1))); + + FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS)); +#if !defined(SLJIT_MIPS_REV) + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif /* !SLJIT_MIPS_REV */ + + FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(dst_r) | FS(dst_r) | FD(dst_r), UNMOVABLE_INS)); + + if (dst & SLJIT_MEM) + return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0); + return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, @@ -2772,7 +3090,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil case SLJIT_MOV_F64: if (src != dst_r) { if (dst_r != TMP_FREG1) - FAIL_IF(push_inst(compiler, MOV_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, MOV_fmt(FMT(op)) | FS(src) | FD(dst_r), MOVABLE_INS)); else dst_r = src; } @@ -2853,18 +3171,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil case SLJIT_ADD_F64: FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS)); break; - case SLJIT_SUB_F64: FAIL_IF(push_inst(compiler, SUB_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS)); break; - case SLJIT_MUL_F64: FAIL_IF(push_inst(compiler, MUL_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS)); break; - case SLJIT_DIV_F64: FAIL_IF(push_inst(compiler, DIV_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS)); break; + case SLJIT_COPYSIGN_F64: + return emit_copysign(compiler, op, src1, src2, dst_r); } if (dst_r == TMP_FREG2) @@ -2873,8 +3190,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil return SLJIT_SUCCESS; } -#undef FLOAT_DATA -#undef FMT +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f32 value) +{ + union { + sljit_s32 imm; + sljit_f32 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset32(compiler, freg, value)); + + u.value = value; + + if (u.imm == 0) + return push_inst(compiler, MTC1 | TA(0) | FS(freg), MOVABLE_INS); + + FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.imm)); + return push_inst(compiler, MTC1 | T(TMP_REG1) | FS(freg), MOVABLE_INS); +} /* --------------------------------------------------------------------- */ /* Conditional instructions */ @@ -3032,7 +3366,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile } #define RESOLVE_IMM1() \ - if (src1 & SLJIT_IMM) { \ + if (src1 == SLJIT_IMM) { \ if (src1w) { \ PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \ src1 = TMP_REG1; \ @@ -3042,7 +3376,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile } #define RESOLVE_IMM2() \ - if (src2 & SLJIT_IMM) { \ + if (src2 == SLJIT_IMM) { \ if (src2w) { \ PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG2), src2w)); \ src2 = TMP_REG2; \ @@ -3094,10 +3428,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2))) jump->flags |= IS_MOVABLE; PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | BRANCH_LENGTH, UNMOVABLE_INS)); - } - else if (type >= SLJIT_SIG_LESS && (((src1 & SLJIT_IMM) && (src1w == 0)) || ((src2 & SLJIT_IMM) && (src2w == 0)))) { + } else if (type >= SLJIT_SIG_LESS && ((src1 == SLJIT_IMM && src1w == 0) || (src2 == SLJIT_IMM && src2w == 0))) { inst = NOP; - if ((src1 & SLJIT_IMM) && (src1w == 0)) { + if (src1 == SLJIT_IMM && src1w == 0) { RESOLVE_IMM2(); switch (type) { case SLJIT_SIG_LESS: @@ -3145,7 +3478,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler else { if (type == SLJIT_LESS || type == SLJIT_GREATER_EQUAL || type == SLJIT_SIG_LESS || type == SLJIT_SIG_GREATER_EQUAL) { RESOLVE_IMM1(); - if ((src2 & SLJIT_IMM) && src2w <= SIMM_MAX && src2w >= SIMM_MIN) + if (src2 == SLJIT_IMM && src2w <= SIMM_MAX && src2w >= SIMM_MIN) PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src1) | T(TMP_REG1) | IMM(src2w), DR(TMP_REG1))); else { RESOLVE_IMM2(); @@ -3155,7 +3488,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler } else { RESOLVE_IMM2(); - if ((src1 & SLJIT_IMM) && src1w <= SIMM_MAX && src1w >= SIMM_MIN) + if (src1 == SLJIT_IMM && src1w <= SIMM_MAX && src1w >= SIMM_MIN) PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src2) | T(TMP_REG1) | IMM(src1w), DR(TMP_REG1))); else { RESOLVE_IMM1(); @@ -3190,9 +3523,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler #undef BR_T #undef BR_F -#undef FLOAT_DATA -#undef FMT - SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { struct sljit_jump *jump = NULL; @@ -3200,7 +3530,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); - if (src & SLJIT_IMM) { + if (src == SLJIT_IMM) { jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); FAIL_IF(!jump); set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0)); @@ -3232,8 +3562,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi #endif } - FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); - return SLJIT_SUCCESS; + return push_inst(compiler, NOP, UNMOVABLE_INS); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, @@ -3335,50 +3664,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, TMP_REG2, 0); } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 dst_reg, - sljit_s32 src, sljit_sw srcw) -{ -#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) - sljit_ins ins; -#endif /* SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6 */ - - CHECK_ERROR(); - CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); - #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) - if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { -#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) - if (type & SLJIT_32) - srcw = (sljit_s32)srcw; -#endif - FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw)); - src = TMP_REG1; - srcw = 0; - } - +static sljit_ins get_select_cc(sljit_s32 type, sljit_s32 is_float) +{ switch (type & ~SLJIT_32) { case SLJIT_EQUAL: - ins = MOVZ | TA(EQUAL_FLAG); - break; + return (is_float ? MOVZ_S : MOVZ) | TA(EQUAL_FLAG); case SLJIT_NOT_EQUAL: - ins = MOVN | TA(EQUAL_FLAG); - break; + return (is_float ? MOVN_S : MOVN) | TA(EQUAL_FLAG); case SLJIT_LESS: case SLJIT_GREATER: case SLJIT_SIG_LESS: case SLJIT_SIG_GREATER: case SLJIT_OVERFLOW: - ins = MOVN | TA(OTHER_FLAG); - break; + case SLJIT_CARRY: + return (is_float ? MOVN_S : MOVN) | TA(OTHER_FLAG); case SLJIT_GREATER_EQUAL: case SLJIT_LESS_EQUAL: case SLJIT_SIG_GREATER_EQUAL: case SLJIT_SIG_LESS_EQUAL: case SLJIT_NOT_OVERFLOW: - ins = MOVZ | TA(OTHER_FLAG); - break; + case SLJIT_NOT_CARRY: + return (is_float ? MOVZ_S : MOVZ) | TA(OTHER_FLAG); case SLJIT_F_EQUAL: case SLJIT_F_LESS: case SLJIT_F_LESS_EQUAL: @@ -3389,8 +3697,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil case SLJIT_UNORDERED_OR_LESS_EQUAL: case SLJIT_ORDERED_LESS_EQUAL: case SLJIT_UNORDERED: - ins = MOVT; - break; + return is_float ? MOVT_S : MOVT; case SLJIT_F_NOT_EQUAL: case SLJIT_F_GREATER_EQUAL: case SLJIT_F_GREATER: @@ -3401,21 +3708,159 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil case SLJIT_ORDERED_GREATER: case SLJIT_UNORDERED_OR_GREATER: case SLJIT_ORDERED: - ins = MOVF; - break; + return is_float ? MOVF_S : MOVF; default: - ins = MOVZ | TA(OTHER_FLAG); SLJIT_UNREACHABLE(); - break; + return (is_float ? MOVZ_S : MOVZ) | TA(OTHER_FLAG); + } +} + +#endif /* SLJIT_MIPS_REV >= 1 */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_reg) +{ +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; + sljit_ins mov_ins = (type & SLJIT_32) ? ADDU : DADDU; +#else /* !SLJIT_CONFIG_MIPS_64 */ + sljit_s32 inp_flags = WORD_DATA | LOAD_DATA; + sljit_ins mov_ins = ADDU; +#endif /* SLJIT_CONFIG_MIPS_64 */ + +#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) + struct sljit_label *label; + struct sljit_jump *jump; +#endif /* !(SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) */ + + CHECK_ERROR(); + CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg)); + ADJUST_LOCAL_OFFSET(src1, src1w); + +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG2), src1, src1w)); + src1 = TMP_REG2; + } else if (src1 == SLJIT_IMM) { +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + if (type & SLJIT_32) + src1w = (sljit_s32)src1w; +#endif + FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); + src1 = TMP_REG1; + } + + if (dst_reg != src2_reg) { + if (dst_reg == src1) { + src1 = src2_reg; + type ^= 0x1; + } else + FAIL_IF(push_inst(compiler, mov_ins | S(src2_reg) | TA(0) | D(dst_reg), DR(dst_reg))); + } + + return push_inst(compiler, get_select_cc(type, 0) | S(src1) | D(dst_reg), DR(dst_reg)); + +#else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */ + if (dst_reg != src2_reg) { + if (dst_reg == src1) { + src1 = src2_reg; + src1w = 0; + type ^= 0x1; + } else { + if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) { + FAIL_IF(push_inst(compiler, ADDU_W | S(dst_reg) | TA(0) | D(TMP_REG2), DR(TMP_REG2))); + + if ((src1 & REG_MASK) == dst_reg) + src1 = (src1 & ~REG_MASK) | TMP_REG2; + + if (OFFS_REG(src1) == dst_reg) + src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG2); + } + + FAIL_IF(push_inst(compiler, mov_ins | S(src2_reg) | TA(0) | D(dst_reg), DR(dst_reg))); + } + } + + SLJIT_SKIP_CHECKS(compiler); + jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1); + FAIL_IF(!jump); + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inp_flags, DR(dst_reg), src1, src1w)); + } else if (src1 == SLJIT_IMM) { +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + if (type & SLJIT_32) + src1w = (sljit_s32)src1w; +#endif /* SLJIT_CONFIG_MIPS_64 */ + FAIL_IF(load_immediate(compiler, DR(dst_reg), src1w)); + } else + FAIL_IF(push_inst(compiler, mov_ins | S(src1) | TA(0) | D(dst_reg), DR(dst_reg))); + + SLJIT_SKIP_CHECKS(compiler); + label = sljit_emit_label(compiler); + FAIL_IF(!label); + + sljit_set_label(jump, label); + return SLJIT_SUCCESS; +#endif /* SLJIT_MIPS_REV >= 1 */ +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_freg) +{ +#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) + struct sljit_label *label; + struct sljit_jump *jump; +#endif /* !(SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) */ + + CHECK_ERROR(); + CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg)); + + ADJUST_LOCAL_OFFSET(src1, src1w); + + if (dst_freg != src2_freg) { + if (dst_freg == src1) { + src1 = src2_freg; + src1w = 0; + type ^= 0x1; + } else + FAIL_IF(push_inst(compiler, MOV_fmt(FMT(type)) | FS(src2_freg) | FD(dst_freg), MOVABLE_INS)); + } + +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, FR(TMP_FREG1), src1, src1w)); + src1 = TMP_FREG1; } - return push_inst(compiler, ins | S(src) | D(dst_reg), DR(dst_reg)); + return push_inst(compiler, get_select_cc(type, 1) | FMT(type) | FS(src1) | FD(dst_freg), MOVABLE_INS); #else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */ - return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw); + SLJIT_SKIP_CHECKS(compiler); + jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1); + FAIL_IF(!jump); + + if (src1 & SLJIT_MEM) + FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, FR(dst_freg), src1, src1w)); + else + FAIL_IF(push_inst(compiler, MOV_fmt(FMT(type)) | FS(src1) | FD(dst_freg), MOVABLE_INS)); + + SLJIT_SKIP_CHECKS(compiler); + label = sljit_emit_label(compiler); + FAIL_IF(!label); + + sljit_set_label(jump, label); + return SLJIT_SUCCESS; #endif /* SLJIT_MIPS_REV >= 1 */ } +#undef FLOAT_DATA +#undef FMT + static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s16 max_offset) { sljit_s32 arg = *mem; @@ -3458,21 +3903,33 @@ static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem } #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) -#define MEM16_IMM_FIRST(memw) IMM((memw) + 1) -#define MEM16_IMM_SECOND(memw) IMM(memw) -#define MEMF64_FS_FIRST(freg) FS(freg) -#define MEMF64_FS_SECOND(freg) (FS(freg) | ((sljit_ins)1 << 11)) +#define IMM_LEFT(memw) IMM((memw) + SSIZE_OF(sw) - 1) +#define IMM_RIGHT(memw) IMM(memw) +#define IMM_32_LEFT(memw) IMM((memw) + SSIZE_OF(s32) - 1) +#define IMM_32_RIGHT(memw) IMM(memw) +#define IMM_F64_FIRST_LEFT(memw) IMM((memw) + SSIZE_OF(s32) - 1) +#define IMM_F64_FIRST_RIGHT(memw) IMM(memw) +#define IMM_F64_SECOND_LEFT(memw) IMM((memw) + SSIZE_OF(f64) - 1) +#define IMM_F64_SECOND_RIGHT(memw) IMM((memw) + SSIZE_OF(s32)) +#define IMM_16_FIRST(memw) IMM((memw) + 1) +#define IMM_16_SECOND(memw) IMM(memw) #else /* !SLJIT_LITTLE_ENDIAN */ -#define MEM16_IMM_FIRST(memw) IMM(memw) -#define MEM16_IMM_SECOND(memw) IMM((memw) + 1) -#define MEMF64_FS_FIRST(freg) (FS(freg) | ((sljit_ins)1 << 11)) -#define MEMF64_FS_SECOND(freg) FS(freg) +#define IMM_LEFT(memw) IMM(memw) +#define IMM_RIGHT(memw) IMM((memw) + SSIZE_OF(sw) - 1) +#define IMM_32_LEFT(memw) IMM(memw) +#define IMM_32_RIGHT(memw) IMM((memw) + SSIZE_OF(s32) - 1) +#define IMM_F64_FIRST_LEFT(memw) IMM((memw) + SSIZE_OF(s32)) +#define IMM_F64_FIRST_RIGHT(memw) IMM((memw) + SSIZE_OF(f64) - 1) +#define IMM_F64_SECOND_LEFT(memw) IMM(memw) +#define IMM_F64_SECOND_RIGHT(memw) IMM((memw) + SSIZE_OF(s32) - 1) +#define IMM_16_FIRST(memw) IMM(memw) +#define IMM_16_SECOND(memw) IMM((memw) + 1) #endif /* SLJIT_LITTLE_ENDIAN */ #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) -#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16)) +#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16)) #else /* !SLJIT_CONFIG_MIPS_32 */ -#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_UNALIGNED_16 | SLJIT_MEM_UNALIGNED_32)) +#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)) #endif /* SLJIT_CONFIG_MIPS_32 */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, @@ -3509,10 +3966,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile ins_right = ((type & SLJIT_MEM_STORE) ? SDR : LDR) | S(mem); #endif /* SLJIT_CONFIG_MIPS_32 */ - FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg)))); - FAIL_IF(push_inst(compiler, ins_right | T(REG_PAIR_FIRST(reg)) | IMM(memw + (SSIZE_OF(sw) - 1)), DR(REG_PAIR_FIRST(reg)))); - FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)))); - return push_inst(compiler, ins_right | T(REG_PAIR_SECOND(reg)) | IMM((memw + 2 * SSIZE_OF(sw) - 1)), DR(REG_PAIR_SECOND(reg))); + FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM_LEFT(memw), DR(REG_PAIR_FIRST(reg)))); + FAIL_IF(push_inst(compiler, ins_right | T(REG_PAIR_FIRST(reg)) | IMM_RIGHT(memw), DR(REG_PAIR_FIRST(reg)))); + FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM_LEFT(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)))); + return push_inst(compiler, ins_right | T(REG_PAIR_SECOND(reg)) | IMM_RIGHT(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg))); } #endif /* !(SLJIT_MIPS_REV >= 6) */ @@ -3553,8 +4010,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile if (type & SLJIT_MEM_STORE) { FAIL_IF(push_inst(compiler, SRA_W | T(reg) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2))); - FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(TMP_REG2) | MEM16_IMM_FIRST(memw), MOVABLE_INS)); - return push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(reg) | MEM16_IMM_SECOND(memw), MOVABLE_INS); + FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(TMP_REG2) | IMM_16_FIRST(memw), MOVABLE_INS)); + return push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(reg) | IMM_16_SECOND(memw), MOVABLE_INS); } flags = BYTE_DATA | LOAD_DATA; @@ -3562,15 +4019,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile if (op == SLJIT_MOV_S16) flags |= SIGNED_DATA; - FAIL_IF(push_inst(compiler, data_transfer_insts[flags] | S(mem) | T(TMP_REG2) | MEM16_IMM_FIRST(memw), DR(TMP_REG2))); - FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA | LOAD_DATA] | S(mem) | T(reg) | MEM16_IMM_SECOND(memw), DR(reg))); + FAIL_IF(push_inst(compiler, data_transfer_insts[flags] | S(mem) | T(TMP_REG2) | IMM_16_FIRST(memw), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA | LOAD_DATA] | S(mem) | T(reg) | IMM_16_SECOND(memw), DR(reg))); FAIL_IF(push_inst(compiler, SLL_W | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2))); return push_inst(compiler, OR | S(reg) | T(TMP_REG2) | D(reg), DR(reg)); case SLJIT_MOV: case SLJIT_MOV_P: #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - if (type & SLJIT_MEM_UNALIGNED_32) { + if (type & SLJIT_MEM_ALIGNED_32) { flags = WORD_DATA; if (!(type & SLJIT_MEM_STORE)) flags |= LOAD_DATA; @@ -3582,8 +4039,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2); if (type & SLJIT_MEM_STORE) { - FAIL_IF(push_inst(compiler, SDL | S(mem) | T(reg) | IMM(memw), MOVABLE_INS)); - return push_inst(compiler, SDR | S(mem) | T(reg) | IMM(memw + 7), MOVABLE_INS); + FAIL_IF(push_inst(compiler, SDL | S(mem) | T(reg) | IMM_LEFT(memw), MOVABLE_INS)); + return push_inst(compiler, SDR | S(mem) | T(reg) | IMM_RIGHT(memw), MOVABLE_INS); } if (mem == reg) { @@ -3591,8 +4048,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile mem = TMP_REG1; } - FAIL_IF(push_inst(compiler, LDL | S(mem) | T(reg) | IMM(memw), DR(reg))); - return push_inst(compiler, LDR | S(mem) | T(reg) | IMM(memw + 7), DR(reg)); + FAIL_IF(push_inst(compiler, LDL | S(mem) | T(reg) | IMM_LEFT(memw), DR(reg))); + return push_inst(compiler, LDR | S(mem) | T(reg) | IMM_RIGHT(memw), DR(reg)); #endif /* SLJIT_CONFIG_MIPS_32 */ } @@ -3600,8 +4057,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2); if (type & SLJIT_MEM_STORE) { - FAIL_IF(push_inst(compiler, SWL | S(mem) | T(reg) | IMM(memw), MOVABLE_INS)); - return push_inst(compiler, SWR | S(mem) | T(reg) | IMM(memw + 3), MOVABLE_INS); + FAIL_IF(push_inst(compiler, SWL | S(mem) | T(reg) | IMM_32_LEFT(memw), MOVABLE_INS)); + return push_inst(compiler, SWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), MOVABLE_INS); } if (mem == reg) { @@ -3609,18 +4066,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile mem = TMP_REG1; } - FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM(memw), DR(reg))); + FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM_32_LEFT(memw), DR(reg))); #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - return push_inst(compiler, LWR | S(mem) | T(reg) | IMM(memw + 3), DR(reg)); + return push_inst(compiler, LWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), DR(reg)); #else /* !SLJIT_CONFIG_MIPS_32 */ - FAIL_IF(push_inst(compiler, LWR | S(mem) | T(reg) | IMM(memw + 3), DR(reg))); + FAIL_IF(push_inst(compiler, LWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), DR(reg))); if (op != SLJIT_MOV_U32) return SLJIT_SUCCESS; #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2) - return push_inst(compiler, DINSU | T(reg) | SA(0) | (31 << 11) | (0 << 11), DR(reg)); -#else /* SLJIT_MIPS_REV < 1 */ + return push_inst(compiler, DINSU | T(reg) | SA(0) | (31 << 11), DR(reg)); +#else /* SLJIT_MIPS_REV < 2 */ FAIL_IF(push_inst(compiler, DSLL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg))); return push_inst(compiler, DSRL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg)); #endif /* SLJIT_MIPS_REV >= 2 */ @@ -3643,77 +4100,97 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil if (type & SLJIT_MEM_STORE) { if (type & SLJIT_32) { FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2))); -#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) +#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1) FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); -#endif - FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM(memw), MOVABLE_INS)); - return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), MOVABLE_INS); +#endif /* MIPS III */ + FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_32_LEFT(memw), MOVABLE_INS)); + return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_32_RIGHT(memw), MOVABLE_INS); } #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | MEMF64_FS_FIRST(freg), DR(TMP_REG2))); -#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) + FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2))); +#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif /* MIPS III */ + FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_LEFT(memw), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_RIGHT(memw), MOVABLE_INS)); + switch (cpu_feature_list & CPU_FEATURE_FR) { +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 + case CPU_FEATURE_FR: + FAIL_IF(push_inst(compiler, MFHC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2))); + break; +#endif /* SLJIT_MIPS_REV >= 2 */ + default: + FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg) | (1 << 11), DR(TMP_REG2))); +#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1 + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); #endif - FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM(memw), MOVABLE_INS)); - FAIL_IF(push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), MOVABLE_INS)); + break; + } - FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | MEMF64_FS_SECOND(freg), DR(TMP_REG2))); -#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) - FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); -#endif - FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM(memw + 4), MOVABLE_INS)); - return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM(memw + 7), MOVABLE_INS); + FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_LEFT(memw), MOVABLE_INS)); + return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_RIGHT(memw), MOVABLE_INS); #else /* !SLJIT_CONFIG_MIPS_32 */ - FAIL_IF(push_inst(compiler, MFC1 | (1 << 21) | T(TMP_REG2) | FS(freg), DR(TMP_REG2))); -#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) + FAIL_IF(push_inst(compiler, DMFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2))); +#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); -#endif - FAIL_IF(push_inst(compiler, SDL | S(mem) | T(TMP_REG2) | IMM(memw), MOVABLE_INS)); - return push_inst(compiler, SDR | S(mem) | T(TMP_REG2) | IMM(memw + 7), MOVABLE_INS); +#endif /* MIPS III */ + FAIL_IF(push_inst(compiler, SDL | S(mem) | T(TMP_REG2) | IMM_LEFT(memw), MOVABLE_INS)); + return push_inst(compiler, SDR | S(mem) | T(TMP_REG2) | IMM_RIGHT(memw), MOVABLE_INS); #endif /* SLJIT_CONFIG_MIPS_32 */ } if (type & SLJIT_32) { - FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM(memw), DR(TMP_REG2))); - FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_32_LEFT(memw), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_32_RIGHT(memw), DR(TMP_REG2))); FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS)); -#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) +#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1) FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); -#endif +#endif /* MIPS III */ return SLJIT_SUCCESS; } #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM(memw), DR(TMP_REG2))); - FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), DR(TMP_REG2))); - FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | MEMF64_FS_FIRST(freg), MOVABLE_INS)); - - FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM(memw + 4), DR(TMP_REG2))); - FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM(memw + 7), DR(TMP_REG2))); - FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | MEMF64_FS_SECOND(freg), MOVABLE_INS)); -#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) - FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); -#endif + FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_LEFT(memw), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_RIGHT(memw), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS)); + + FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_LEFT(memw), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_RIGHT(memw), DR(TMP_REG2))); + switch (cpu_feature_list & CPU_FEATURE_FR) { +#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2 + case CPU_FEATURE_FR: + return push_inst(compiler, MTHC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS); +#endif /* SLJIT_MIPS_REV >= 2 */ + default: + FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg) | (1 << 11), MOVABLE_INS)); + break; + } #else /* !SLJIT_CONFIG_MIPS_32 */ - FAIL_IF(push_inst(compiler, LDL | S(mem) | T(TMP_REG2) | IMM(memw), DR(TMP_REG2))); - FAIL_IF(push_inst(compiler, LDR | S(mem) | T(TMP_REG2) | IMM(memw + 7), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, LDL | S(mem) | T(TMP_REG2) | IMM_LEFT(memw), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, LDR | S(mem) | T(TMP_REG2) | IMM_RIGHT(memw), DR(TMP_REG2))); - FAIL_IF(push_inst(compiler, MTC1 | (1 << 21) | T(TMP_REG2) | FS(freg), MOVABLE_INS)); -#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3) - FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); -#endif + FAIL_IF(push_inst(compiler, DMTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS)); #endif /* SLJIT_CONFIG_MIPS_32 */ +#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1 + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif /* MIPS III */ return SLJIT_SUCCESS; } #endif /* !SLJIT_MIPS_REV || SLJIT_MIPS_REV < 6 */ -#undef MEM16_IMM_FIRST -#undef MEM16_IMM_SECOND -#undef MEMF64_FS_FIRST -#undef MEMF64_FS_SECOND +#undef IMM_16_SECOND +#undef IMM_16_FIRST +#undef IMM_F64_SECOND_RIGHT +#undef IMM_F64_SECOND_LEFT +#undef IMM_F64_FIRST_RIGHT +#undef IMM_F64_FIRST_LEFT +#undef IMM_32_RIGHT +#undef IMM_32_LEFT +#undef IMM_RIGHT +#undef IMM_LEFT #undef MEM_CHECK_UNALIGNED #undef TO_ARGW_HI @@ -3740,18 +4217,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi return const_; } -SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { - struct sljit_put_label *put_label; + struct sljit_jump *jump; sljit_s32 dst_r; CHECK_ERROR_PTR(); - CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw)); + CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); - put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label)); - PTR_FAIL_IF(!put_label); - set_put_label(put_label, compiler, 0); + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_mov_addr(jump, compiler, 0); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r, UNMOVABLE_INS)); @@ -3764,5 +4241,5 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct slj if (dst & SLJIT_MEM) PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw)); - return put_label; + return jump; } diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_32.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_32.c index 25cfcb90724..2352fad5d47 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_32.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_32.c @@ -325,6 +325,109 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_ return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value)); } +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; + sljit_s32 invert_sign = 1; + + if (src == SLJIT_IMM) { + FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ (sljit_sw)0x80000000)); + src = TMP_REG1; + invert_sign = 0; + } else if (!FAST_IS_REG(src)) { + FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); + src = TMP_REG1; + } + + /* First, a special double precision floating point value is constructed: + (2^53 + (src xor (2^31))) + The upper 32 bits of this number is a constant, and the lower 32 bits + is simply the value of the source argument. The xor 2^31 operation adds + 0x80000000 to the source argument, which moves it into the 0 - 0xffffffff + range. Finally we substract 2^53 + 2^31 to get the converted value. */ + FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330)); + if (invert_sign) + FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000)); + FAIL_IF(push_inst(compiler, STW | S(TMP_REG2) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI)); + FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO)); + FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000)); + FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO)); + FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG2) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + + FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2))); + + if (op & SLJIT_32) + FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r))); + + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1); + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; + + if (src == SLJIT_IMM) { + FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); + src = TMP_REG1; + } else if (!FAST_IS_REG(src)) { + FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); + src = TMP_REG1; + } + + /* First, a special double precision floating point value is constructed: + (2^53 + src) + The upper 32 bits of this number is a constant, and the lower 32 bits + is simply the value of the source argument. Finally we substract 2^53 + to get the converted value. */ + FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330)); + FAIL_IF(push_inst(compiler, STW | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO)); + FAIL_IF(push_inst(compiler, STW | S(TMP_REG2) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI)); + + FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + FAIL_IF(push_inst(compiler, STW | S(TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO)); + FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG2) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + + FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2))); + + if (op & SLJIT_32) + FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r))); + + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f64 value) +{ + union { + sljit_s32 imm[2]; + sljit_f64 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset64(compiler, freg, value)); + + u.value = value; + + if (u.imm[0] != 0) + FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0])); + if (u.imm[1] != 0) + FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1])); + + /* Saved in the same endianness. */ + FAIL_IF(push_inst(compiler, STW | S(u.imm[0] != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + FAIL_IF(push_inst(compiler, STW | S(u.imm[1] != 0 ? TMP_REG2 : TMP_ZERO) | A(SLJIT_SP) | (TMP_MEM_OFFSET + sizeof(sljit_s32)))); + return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 freg, sljit_s32 reg) { @@ -352,9 +455,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compi FAIL_IF(push_inst(compiler, STW | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI)); if (reg2 != 0) - FAIL_IF(push_inst(compiler, STW | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LOW)); + FAIL_IF(push_inst(compiler, STW | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO)); else - FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET_LOW)); + FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO)); return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET); } @@ -362,7 +465,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compi FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET)); if (reg2 != 0) - FAIL_IF(push_inst(compiler, LWZ | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LOW)); + FAIL_IF(push_inst(compiler, LWZ | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO)); return push_inst(compiler, LWZ | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI); } diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_64.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_64.c index 8d774cf57ad..b3cf9d074d5 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_64.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_64.c @@ -49,7 +49,7 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, if (imm <= SIMM_MAX && imm >= SIMM_MIN) return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm)); - if (!(imm & ~0xffff)) + if (((sljit_uw)imm >> 16) == 0) return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm)); if (imm <= 0x7fffffffl && imm >= -0x80000000l) { @@ -57,6 +57,11 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS; } + if (((sljit_uw)imm >> 32) == 0) { + FAIL_IF(push_inst(compiler, ORIS | S(TMP_ZERO) | A(reg) | IMM(imm >> 16))); + return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS; + } + /* Count leading zeroes. */ tmp = (sljit_uw)((imm >= 0) ? imm : ~imm); ASM_SLJIT_CLZ(tmp, shift); @@ -563,6 +568,126 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_ return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value)); } +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; + + if (src == SLJIT_IMM) { + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) + srcw = (sljit_s32)srcw; + + FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); + src = TMP_REG1; + } else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) { + if (FAST_IS_REG(src)) + FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1))); + else + FAIL_IF(emit_op_mem(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); + src = TMP_REG1; + } + + if (FAST_IS_REG(src)) { + FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + } else + FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1)); + + FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1))); + + if (op & SLJIT_32) + FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r))); + + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1); + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; + + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) { + if (src == SLJIT_IMM) { + FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_u32)srcw)); + src = TMP_REG1; + } else { + if (FAST_IS_REG(src)) + FAIL_IF(push_inst(compiler, CLRLDI(TMP_REG1, src, 32))); + else + FAIL_IF(emit_op_mem(compiler, INT_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); + src = TMP_REG1; + } + + FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1))); + } else { + if (src == SLJIT_IMM) { + FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); + src = TMP_REG1; + } else if (src & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); + src = TMP_REG1; + } + + FAIL_IF(push_inst(compiler, CMPI | CRD(0 | 1) | A(src) | 0)); + FAIL_IF(push_inst(compiler, BCx | (12 << 21) | (0 << 16) | 20)); + FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1))); + FAIL_IF(push_inst(compiler, Bx | ((op & SLJIT_32) ? 36 : 32))); + + if (op & SLJIT_32) + FAIL_IF(push_inst(compiler, RLWINM | S(src) | A(TMP_REG2) | RLWI_SH(10) | RLWI_MBE(10, 21))); + else + FAIL_IF(push_inst(compiler, ANDI | S(src) | A(TMP_REG2) | 0x1)); + + /* Shift right. */ + FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(63) | RLDI_MB(1))); + + if (op & SLJIT_32) + FAIL_IF(push_inst(compiler, RLDICR | S(TMP_REG1) | A(TMP_REG1) | RLDI_SH(0) | RLDI_ME(53))); + + FAIL_IF(push_inst(compiler, OR | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2))); + + FAIL_IF(push_inst(compiler, STD | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1))); + FAIL_IF(push_inst(compiler, FADD | FD(dst_r) | FA(dst_r) | FB(dst_r))); + } + + if (op & SLJIT_32) + FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r))); + + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f64 value) +{ + union { + sljit_sw imm; + sljit_f64 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset64(compiler, freg, value)); + + u.value = value; + + if (u.imm != 0) + FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm)); + + FAIL_IF(push_inst(compiler, STD | S(u.imm != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 freg, sljit_s32 reg) { diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_common.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_common.c index 81ba7d36b03..d40764826e9 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_common.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativePPC_common.c @@ -132,7 +132,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { OE and Rc flag (see ALT_SET_FLAGS). */ #define OE(flags) ((flags) & ALT_SET_FLAGS) /* Rc flag (see ALT_SET_FLAGS). */ -#define RC(flags) (((flags) & ALT_SET_FLAGS) >> 10) +#define RC(flags) ((sljit_ins)((flags) & ALT_SET_FLAGS) >> 10) #define HI(opcode) ((sljit_ins)(opcode) << 26) #define LO(opcode) ((sljit_ins)(opcode) << 1) @@ -150,6 +150,9 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define BCx (HI(16)) #define BCCTR (HI(19) | LO(528) | (3 << 11)) #define BLR (HI(19) | LO(16) | (0x14 << 21)) +#if defined(_ARCH_PWR10) && _ARCH_PWR10 +#define BRD (HI(31) | LO(187)) +#endif /* POWER10 */ #define CNTLZD (HI(31) | LO(58)) #define CNTLZW (HI(31) | LO(26)) #define CMP (HI(31) | LO(0)) @@ -184,6 +187,10 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define LD (HI(58) | 0) #define LFD (HI(50)) #define LFS (HI(48)) +#if defined(_ARCH_PWR7) && _ARCH_PWR7 +#define LDBRX (HI(31) | LO(532)) +#endif /* POWER7 */ +#define LHBRX (HI(31) | LO(790)) #define LWBRX (HI(31) | LO(534)) #define LWZ (HI(32)) #define MFCR (HI(31) | LO(19)) @@ -221,11 +228,15 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #define SRD (HI(31) | LO(539)) #define SRW (HI(31) | LO(536)) #define STD (HI(62) | 0) +#if defined(_ARCH_PWR7) && _ARCH_PWR7 +#define STDBRX (HI(31) | LO(660)) +#endif /* POWER7 */ #define STDU (HI(62) | 1) #define STDUX (HI(31) | LO(181)) #define STFD (HI(54)) #define STFIWX (HI(31) | LO(983)) #define STFS (HI(52)) +#define STHBRX (HI(31) | LO(918)) #define STW (HI(36)) #define STWBRX (HI(31) | LO(662)) #define STWU (HI(37)) @@ -264,11 +275,15 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { #endif /* SLJIT_CONFIG_PPC_32 */ #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) -#define TMP_MEM_OFFSET_LOW TMP_MEM_OFFSET -#define TMP_MEM_OFFSET_HI (TMP_MEM_OFFSET + sizeof(sljit_s32)) +#define TMP_MEM_OFFSET_LO (TMP_MEM_OFFSET) +#define TMP_MEM_OFFSET_HI (TMP_MEM_OFFSET + sizeof(sljit_s32)) +#define LWBRX_FIRST_REG S(TMP_REG1) +#define LWBRX_SECOND_REG S(dst) #else /* !SLJIT_LITTLE_ENDIAN */ -#define TMP_MEM_OFFSET_LOW (TMP_MEM_OFFSET + sizeof(sljit_s32)) -#define TMP_MEM_OFFSET_HI TMP_MEM_OFFSET +#define TMP_MEM_OFFSET_LO (TMP_MEM_OFFSET + sizeof(sljit_s32)) +#define TMP_MEM_OFFSET_HI (TMP_MEM_OFFSET) +#define LWBRX_FIRST_REG S(dst) +#define LWBRX_SECOND_REG S(TMP_REG1) #endif /* SLJIT_LITTLE_ENDIAN */ #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) @@ -295,24 +310,23 @@ static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins) return SLJIT_SUCCESS; } -static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) +static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) { sljit_sw diff; sljit_uw target_addr; - sljit_uw extra_jump_flags; #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL)) - return 0; + goto exit; #else if (jump->flags & SLJIT_REWRITABLE_JUMP) - return 0; + goto exit; #endif if (jump->flags & JUMP_ADDR) target_addr = jump->u.target; else { - SLJIT_ASSERT(jump->flags & JUMP_LABEL); + SLJIT_ASSERT(jump->u.label != NULL); target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset; } @@ -321,99 +335,254 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_in goto keep_address; #endif - diff = ((sljit_sw)target_addr - (sljit_sw)(code_ptr) - executable_offset) & ~0x3l; + diff = (sljit_sw)target_addr - (sljit_sw)code_ptr - executable_offset; - extra_jump_flags = 0; if (jump->flags & IS_COND) { if (diff <= 0x7fff && diff >= -0x8000) { jump->flags |= PATCH_B; - return 1; + return code_ptr; } if (target_addr <= 0xffff) { jump->flags |= PATCH_B | PATCH_ABS_B; - return 1; + return code_ptr; } - extra_jump_flags = REMOVE_COND; diff -= SSIZE_OF(ins); } if (diff <= 0x01ffffff && diff >= -0x02000000) { - jump->flags |= PATCH_B | extra_jump_flags; - return 1; + jump->flags |= PATCH_B; + } else if (target_addr <= 0x01ffffff) { + jump->flags |= PATCH_B | PATCH_ABS_B; } - if (target_addr <= 0x03ffffff) { - jump->flags |= PATCH_B | PATCH_ABS_B | extra_jump_flags; - return 1; + if (jump->flags & PATCH_B) { + if (!(jump->flags & IS_COND)) + return code_ptr; + + code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001); + code_ptr[1] = Bx; + jump->addr += sizeof(sljit_ins); + jump->flags -= IS_COND; + return code_ptr + 1; } #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) keep_address: -#endif - if (target_addr <= 0x7fffffff) { +#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */ + if (target_addr < 0x80000000l) { jump->flags |= PATCH_ABS32; - return 1; + code_ptr[2] = MTCTR | S(TMP_CALL_REG); + code_ptr[3] = code_ptr[0]; + return code_ptr + 3; } - if (target_addr <= 0x7fffffffffffl) { + if (target_addr < 0x800000000000l) { jump->flags |= PATCH_ABS48; - return 1; + code_ptr[4] = MTCTR | S(TMP_CALL_REG); + code_ptr[5] = code_ptr[0]; + return code_ptr + 5; } -#endif +#endif /* SLJIT_CONFIG_PPC_64 */ - return 0; +exit: +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + code_ptr[2] = MTCTR | S(TMP_CALL_REG); + code_ptr[3] = code_ptr[0]; +#else /* !SLJIT_CONFIG_PPC_32 */ + code_ptr[5] = MTCTR | S(TMP_CALL_REG); + code_ptr[6] = code_ptr[0]; +#endif /* SLJIT_CONFIG_PPC_32 */ + return code_ptr + JUMP_MAX_SIZE - 1; } #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) -static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label) +static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset) { - if (max_label < 0x100000000l) { - put_label->flags = 0; + sljit_uw addr; + SLJIT_UNUSED_ARG(executable_offset); + + SLJIT_ASSERT(jump->flags < ((sljit_uw)5 << JUMP_SIZE_SHIFT)); + if (jump->flags & JUMP_ADDR) + addr = jump->u.target; + else + addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset); + + if (addr < 0x80000000l) { + SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT)); + jump->flags |= PATCH_ABS32; return 1; } - if (max_label < 0x1000000000000l) { - put_label->flags = 1; + if (addr < 0x800000000000l) { + SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT)); + jump->flags |= PATCH_ABS48; return 3; } - put_label->flags = 2; + SLJIT_ASSERT(jump->flags >= ((sljit_uw)4 << JUMP_SIZE_SHIFT)); return 4; } -static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label) -{ - sljit_uw addr = put_label->label->addr; - sljit_ins *inst = (sljit_ins *)put_label->addr; - sljit_u32 reg = *inst; +#endif /* SLJIT_CONFIG_PPC_64 */ - if (put_label->flags == 0) { - SLJIT_ASSERT(addr < 0x100000000l); - inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 16); - } - else { - if (put_label->flags == 1) { - SLJIT_ASSERT(addr < 0x1000000000000l); - inst[0] = ORI | S(TMP_ZERO) | A(reg) | IMM(addr >> 32); +static void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executable_offset) +{ + sljit_uw flags = jump->flags; + sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr; + sljit_ins *ins = (sljit_ins*)jump->addr; + sljit_s32 reg; + SLJIT_UNUSED_ARG(executable_offset); + + if (flags & PATCH_B) { + if (flags & IS_COND) { + if (!(flags & PATCH_ABS_B)) { + addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset); + SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000); + ins[0] = BCx | ((sljit_ins)addr & 0xfffc) | (ins[0] & 0x03ff0001); + } else { + SLJIT_ASSERT(addr <= 0xffff); + ins[0] = BCx | ((sljit_ins)addr & 0xfffc) | 0x2 | ((*ins) & 0x03ff0001); + } + return; } - else { - inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 48); - inst[1] = ORI | S(reg) | A(reg) | IMM((addr >> 32) & 0xffff); - inst++; + + if (!(flags & PATCH_ABS_B)) { + addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset); + SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000); + ins[0] = Bx | ((sljit_ins)addr & 0x03fffffc) | (ins[0] & 0x1); + } else { + SLJIT_ASSERT(addr <= 0x03ffffff); + ins[0] = Bx | ((sljit_ins)addr & 0x03fffffc) | 0x2 | (ins[0] & 0x1); } + return; + } - inst[1] = SLDI(32) | S(reg) | A(reg); - inst[2] = ORIS | S(reg) | A(reg) | IMM((addr >> 16) & 0xffff); - inst += 2; + reg = (flags & JUMP_MOV_ADDR) ? (sljit_s32)ins[0] : TMP_CALL_REG; + +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 16); + ins[1] = ORI | S(reg) | A(reg) | IMM(addr); +#else /* !SLJIT_CONFIG_PPC_32 */ + + /* The TMP_ZERO cannot be used because it is restored for tail calls. */ + if (flags & PATCH_ABS32) { + SLJIT_ASSERT(addr < 0x80000000l); + ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 16); + ins[1] = ORI | S(reg) | A(reg) | IMM(addr); + return; } - inst[1] = ORI | S(reg) | A(reg) | IMM(addr & 0xffff); + if (flags & PATCH_ABS48) { + SLJIT_ASSERT(addr < 0x800000000000l); + ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 32); + ins[1] = ORI | S(reg) | A(reg) | IMM(addr >> 16); + ins[2] = SLDI(16) | S(reg) | A(reg); + ins[3] = ORI | S(reg) | A(reg) | IMM(addr); + return; + } + + ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 48); + ins[1] = ORI | S(reg) | A(reg) | IMM(addr >> 32); + ins[2] = SLDI(32) | S(reg) | A(reg); + ins[3] = ORIS | S(reg) | A(reg) | IMM(addr >> 16); + ins[4] = ORI | S(reg) | A(reg) | IMM(addr); +#endif /* SLJIT_CONFIG_PPC_32 */ } +static void reduce_code_size(struct sljit_compiler *compiler) +{ + struct sljit_label *label; + struct sljit_jump *jump; + struct sljit_const *const_; + SLJIT_NEXT_DEFINE_TYPES; + sljit_uw total_size; + sljit_uw size_reduce = 0; + sljit_sw diff; + + label = compiler->labels; + jump = compiler->jumps; + const_ = compiler->consts; + SLJIT_NEXT_INIT_TYPES(); + + while (1) { + SLJIT_GET_NEXT_MIN(); + + if (next_min_addr == SLJIT_MAX_ADDRESS) + break; + + if (next_min_addr == next_label_size) { + label->size -= size_reduce; + + label = label->next; + next_label_size = SLJIT_GET_NEXT_SIZE(label); + } + + if (next_min_addr == next_const_addr) { + const_->addr -= size_reduce; + const_ = const_->next; + next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_); + continue; + } + + if (next_min_addr != next_jump_addr) + continue; + + jump->addr -= size_reduce; + if (!(jump->flags & JUMP_MOV_ADDR)) { + total_size = JUMP_MAX_SIZE - 1; + + if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) { + if (jump->flags & JUMP_ADDR) { + if (jump->u.target <= 0x01ffffff) + total_size = 1 - 1; +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + else if (jump->u.target < 0x80000000l) + total_size = 4 - 1; + else if (jump->u.target < 0x800000000000l) + total_size = 6 - 1; +#endif /* SLJIT_CONFIG_PPC_64 */ + } else { + /* Unit size: instruction. */ + diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; + + if (jump->flags & IS_COND) { + if (diff <= (0x7fff / SSIZE_OF(ins)) && diff >= (-0x8000 / SSIZE_OF(ins))) + total_size = 1 - 1; + else if ((diff - 1) <= (0x01ffffff / SSIZE_OF(ins)) && (diff - 1) >= (-0x02000000 / SSIZE_OF(ins))) + total_size = 2 - 1; + } else if (diff <= (0x01ffffff / SSIZE_OF(ins)) && diff >= (-0x02000000 / SSIZE_OF(ins))) + total_size = 1 - 1; + } + } + + size_reduce += (JUMP_MAX_SIZE - 1) - total_size; + jump->flags |= total_size << JUMP_SIZE_SHIFT; +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + } else { + total_size = (sljit_uw)4 << JUMP_SIZE_SHIFT; + + if (jump->flags & JUMP_ADDR) { + if (jump->u.target < 0x80000000l) { + total_size = (sljit_uw)1 << JUMP_SIZE_SHIFT; + size_reduce += 3; + } else if (jump->u.target < 0x800000000000l) { + total_size = (sljit_uw)3 << JUMP_SIZE_SHIFT; + size_reduce += 1; + } + } + jump->flags |= total_size; #endif /* SLJIT_CONFIG_PPC_64 */ + } + + jump = jump->next; + next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); + } + + compiler->size -= size_reduce; +} SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) { @@ -423,20 +592,20 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil sljit_ins *buf_ptr; sljit_ins *buf_end; sljit_uw word_count; - sljit_uw next_addr; + SLJIT_NEXT_DEFINE_TYPES; sljit_sw executable_offset; - sljit_uw addr; struct sljit_label *label; struct sljit_jump *jump; struct sljit_const *const_; - struct sljit_put_label *put_label; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_generate_code(compiler)); - reverse_buf(compiler); + + reduce_code_size(compiler); #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) + /* add to compiler->size additional instruction space to hold the trampoline and padding */ #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins)); #else @@ -445,91 +614,64 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil #endif code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data); PTR_FAIL_WITH_EXEC_IF(code); + + reverse_buf(compiler); buf = compiler->buf; code_ptr = code; word_count = 0; - next_addr = 0; executable_offset = SLJIT_EXEC_OFFSET(code); label = compiler->labels; jump = compiler->jumps; const_ = compiler->consts; - put_label = compiler->put_labels; + SLJIT_NEXT_INIT_TYPES(); + SLJIT_GET_NEXT_MIN(); do { buf_ptr = (sljit_ins*)buf->memory; buf_end = buf_ptr + (buf->used_size >> 2); do { *code_ptr = *buf_ptr++; - if (next_addr == word_count) { + if (next_min_addr == word_count) { SLJIT_ASSERT(!label || label->size >= word_count); SLJIT_ASSERT(!jump || jump->addr >= word_count); SLJIT_ASSERT(!const_ || const_->addr >= word_count); - SLJIT_ASSERT(!put_label || put_label->addr >= word_count); /* These structures are ordered by their address. */ - if (label && label->size == word_count) { + if (next_min_addr == next_label_size) { /* Just recording the address. */ - label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); label->size = (sljit_uw)(code_ptr - code); label = label->next; + next_label_size = SLJIT_GET_NEXT_SIZE(label); } - if (jump && jump->addr == word_count) { -#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) - jump->addr = (sljit_uw)(code_ptr - 3); -#else - jump->addr = (sljit_uw)(code_ptr - 6); -#endif - if (detect_jump_type(jump, code_ptr, code, executable_offset)) { -#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) - code_ptr[-3] = code_ptr[0]; - code_ptr -= 3; -#else - if (jump->flags & PATCH_ABS32) { - code_ptr -= 3; - code_ptr[-1] = code_ptr[2]; - code_ptr[0] = code_ptr[3]; - } - else if (jump->flags & PATCH_ABS48) { - code_ptr--; - code_ptr[-1] = code_ptr[0]; - code_ptr[0] = code_ptr[1]; - /* rldicr rX,rX,32,31 -> rX,rX,16,47 */ - SLJIT_ASSERT((code_ptr[-3] & 0xfc00ffff) == 0x780007c6); - code_ptr[-3] ^= 0x8422; - /* oris -> ori */ - code_ptr[-2] ^= 0x4000000; - } - else { - code_ptr[-6] = code_ptr[0]; - code_ptr -= 6; - } -#endif - if (jump->flags & REMOVE_COND) { - code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001); - code_ptr++; - jump->addr += sizeof(sljit_ins); - code_ptr[0] = Bx; - jump->flags -= IS_COND; - } + + if (next_min_addr == next_jump_addr) { + if (!(jump->flags & JUMP_MOV_ADDR)) { + word_count += jump->flags >> JUMP_SIZE_SHIFT; + jump->addr = (sljit_uw)code_ptr; + code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset); + SLJIT_ASSERT(((sljit_uw)code_ptr - jump->addr <= (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins))); + } else { + jump->addr = (sljit_uw)code_ptr; +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + word_count += jump->flags >> JUMP_SIZE_SHIFT; + code_ptr += mov_addr_get_length(jump, code, executable_offset); +#else /* !SLJIT_CONFIG_PPC_64 */ + word_count++; + code_ptr++; +#endif /* SLJIT_CONFIG_PPC_64 */ } jump = jump->next; - } - if (const_ && const_->addr == word_count) { + next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); + } else if (next_min_addr == next_const_addr) { const_->addr = (sljit_uw)code_ptr; const_ = const_->next; + next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_); } - if (put_label && put_label->addr == word_count) { - SLJIT_ASSERT(put_label->label); - put_label->addr = (sljit_uw)code_ptr; -#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size)); - word_count += 4; -#endif - put_label = put_label->next; - } - next_addr = compute_next_addr(label, jump, const_, put_label); + + SLJIT_GET_NEXT_MIN(); } code_ptr++; word_count++; @@ -539,7 +681,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil } while (buf); if (label && label->size == word_count) { - label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); label->size = (sljit_uw)(code_ptr - code); label = label->next; } @@ -547,7 +689,6 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil SLJIT_ASSERT(!label); SLJIT_ASSERT(!jump); SLJIT_ASSERT(!const_); - SLJIT_ASSERT(!put_label); #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) SLJIT_ASSERT(code_ptr - code <= (sljit_sw)(compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins)))); @@ -557,87 +698,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil jump = compiler->jumps; while (jump) { - do { - addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; - buf_ptr = (sljit_ins *)jump->addr; - - if (jump->flags & PATCH_B) { - if (jump->flags & IS_COND) { - if (!(jump->flags & PATCH_ABS_B)) { - addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset); - SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000); - *buf_ptr = BCx | ((sljit_ins)addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001); - } - else { - SLJIT_ASSERT(addr <= 0xffff); - *buf_ptr = BCx | ((sljit_ins)addr & 0xfffc) | 0x2 | ((*buf_ptr) & 0x03ff0001); - } - } - else { - if (!(jump->flags & PATCH_ABS_B)) { - addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset); - SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000); - *buf_ptr = Bx | ((sljit_ins)addr & 0x03fffffc) | ((*buf_ptr) & 0x1); - } - else { - SLJIT_ASSERT(addr <= 0x03ffffff); - *buf_ptr = Bx | ((sljit_ins)addr & 0x03fffffc) | 0x2 | ((*buf_ptr) & 0x1); - } - } - break; - } - - /* Set the fields of immediate loads. */ -#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) - SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0); - buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff; - buf_ptr[1] |= (sljit_ins)addr & 0xffff; -#else - if (jump->flags & PATCH_ABS32) { - SLJIT_ASSERT(addr <= 0x7fffffff); - SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0); - buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff; - buf_ptr[1] |= (sljit_ins)addr & 0xffff; - break; - } - - if (jump->flags & PATCH_ABS48) { - SLJIT_ASSERT(addr <= 0x7fffffffffff); - SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3]) & 0xffff) == 0); - buf_ptr[0] |= (sljit_ins)(addr >> 32) & 0xffff; - buf_ptr[1] |= (sljit_ins)(addr >> 16) & 0xffff; - buf_ptr[3] |= (sljit_ins)addr & 0xffff; - break; - } - - SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3] | buf_ptr[4]) & 0xffff) == 0); - buf_ptr[0] |= (sljit_ins)(addr >> 48) & 0xffff; - buf_ptr[1] |= (sljit_ins)(addr >> 32) & 0xffff; - buf_ptr[3] |= (sljit_ins)(addr >> 16) & 0xffff; - buf_ptr[4] |= (sljit_ins)addr & 0xffff; -#endif - } while (0); + generate_jump_or_mov_addr(jump, executable_offset); jump = jump->next; } - put_label = compiler->put_labels; - while (put_label) { -#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) - addr = put_label->label->addr; - buf_ptr = (sljit_ins *)put_label->addr; - - SLJIT_ASSERT((buf_ptr[0] & 0xfc1f0000) == ADDIS && (buf_ptr[1] & 0xfc000000) == ORI); - buf_ptr[0] |= (addr >> 16) & 0xffff; - buf_ptr[1] |= addr & 0xffff; -#else - put_label_set(put_label); -#endif - put_label = put_label->next; - } - compiler->error = SLJIT_ERR_COMPILED; compiler->executable_offset = executable_offset; - compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins); code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset); @@ -655,8 +721,10 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1); #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) + compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins) + sizeof(struct sljit_function_context); return code_ptr; #else + compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins); return code; #endif } @@ -666,12 +734,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) switch (feature_type) { case SLJIT_HAS_FPU: #ifdef SLJIT_IS_FPU_AVAILABLE - return SLJIT_IS_FPU_AVAILABLE; + return (SLJIT_IS_FPU_AVAILABLE) != 0; #else /* Available by default. */ return 1; #endif - + case SLJIT_HAS_REV: +#if defined(_ARCH_PWR10) && _ARCH_PWR10 + return 1; +#else /* !POWER10 */ + return 2; +#endif /* POWER10 */ /* A saved register is set to a zero value. */ case SLJIT_HAS_ZERO_REGISTER: case SLJIT_HAS_CLZ: @@ -680,7 +753,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) return 1; case SLJIT_HAS_CTZ: - case SLJIT_HAS_REV: return 2; default: @@ -690,7 +762,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) { - return (type >= SLJIT_UNORDERED && type <= SLJIT_ORDERED_LESS_EQUAL); + switch (type) { + case SLJIT_UNORDERED_OR_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: + case SLJIT_UNORDERED_OR_LESS: + case SLJIT_ORDERED_GREATER_EQUAL: + case SLJIT_UNORDERED_OR_GREATER: + case SLJIT_ORDERED_LESS_EQUAL: + return 1; + } + + return 0; } /* --------------------------------------------------------------------- */ @@ -714,6 +796,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) #define MEM_MASK 0x7f +#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 6)) + /* Other inp_flags. */ /* Integer opertion and set flags -> requires exts on 64 bit systems. */ @@ -737,6 +821,9 @@ ALT_FORM1 0x001000 ... ALT_FORM5 0x010000 */ +static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, + sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg); + #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) #include "sljitNativePPC_32.c" #else @@ -759,9 +846,6 @@ ALT_FORM5 0x010000 */ #define STACK_MAX_DISTANCE (0x8000 - SSIZE_OF(sw) - LR_SAVE_OFFSET) -static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, - sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg); - SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) @@ -1237,7 +1321,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 src1_r = src1; flags |= REG1_SOURCE; } - else if (src1 & SLJIT_IMM) { + else if (src1 == SLJIT_IMM) { src1_r = TMP_ZERO; if (src1w != 0) { FAIL_IF(load_immediate(compiler, TMP_REG1, src1w)); @@ -1257,7 +1341,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P) dst_r = src2_r; } - else if (src2 & SLJIT_IMM) { + else if (src2 == SLJIT_IMM) { src2_r = TMP_ZERO; if (src2w != 0) { FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w)); @@ -1327,30 +1411,58 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile return SLJIT_SUCCESS; } -static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op_flags, +static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 mem, offs_reg, inp_flags; sljit_sw memw; - SLJIT_UNUSED_ARG(op_flags); +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + sljit_s32 is_32 = op & SLJIT_32; + + op = GET_OPCODE(op); +#endif /* SLJIT_CONFIG_PPC_64 */ if (!((dst | src) & SLJIT_MEM)) { /* Both are registers. */ + if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) { + if (src == dst) { + FAIL_IF(push_inst(compiler, RLWIMI | S(dst) | A(dst) | RLWI_SH(16) | RLWI_MBE(8, 15))); + FAIL_IF(push_inst(compiler, RLWINM | S(dst) | A(dst) | RLWI_SH(24) | RLWI_MBE(16, 31))); + } else { + FAIL_IF(push_inst(compiler, RLWINM | S(src) | A(dst) | RLWI_SH(8) | RLWI_MBE(16, 23))); + FAIL_IF(push_inst(compiler, RLWIMI | S(src) | A(dst) | RLWI_SH(24) | RLWI_MBE(24, 31))); + } + + if (op == SLJIT_REV_U16) + return SLJIT_SUCCESS; + return push_inst(compiler, EXTSH | S(dst) | A(dst)); + } + #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - if (!(op_flags & SLJIT_32)) { + if (!is_32) { +#if defined(_ARCH_PWR10) && _ARCH_PWR10 + return push_inst(compiler, BRD | S(src) | A(dst)); +#else /* !POWER10 */ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET_HI))); FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32))); FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(SLJIT_SP) | B(TMP_REG2))); - FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET_LOW))); + FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET_LO))); FAIL_IF(push_inst(compiler, STWBRX | S(TMP_REG1) | A(SLJIT_SP) | B(TMP_REG2))); return push_inst(compiler, LD | D(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET); +#endif /* POWER10 */ } #endif /* SLJIT_CONFIG_PPC_64 */ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET))); FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(SLJIT_SP) | B(TMP_REG2))); - return push_inst(compiler, LWZ | D(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET); + FAIL_IF(push_inst(compiler, LWZ | D(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if (op == SLJIT_REV_S32) + return push_inst(compiler, EXTSW | S(dst) | A(dst)); +#endif /* SLJIT_CONFIG_PPC_64 */ + return SLJIT_SUCCESS; } mem = src; @@ -1361,11 +1473,16 @@ static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op_flags, memw = dstw; if (src & SLJIT_MEM) { + inp_flags = HALF_DATA | LOAD_DATA; + + if (op != SLJIT_REV_U16 && op != SLJIT_REV_S16) { #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - inp_flags = ((op_flags & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; + inp_flags = (is_32 ? INT_DATA : WORD_DATA) | LOAD_DATA; #else /* !SLJIT_CONFIG_PPC_64 */ - inp_flags = WORD_DATA | LOAD_DATA; + inp_flags = WORD_DATA | LOAD_DATA; #endif /* SLJIT_CONFIG_PPC_64 */ + } + FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG1, src, srcw, TMP_REG2)); src = TMP_REG1; } @@ -1395,30 +1512,60 @@ static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op_flags, offs_reg = TMP_REG2; } + if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) { + if (dst & SLJIT_MEM) + return push_inst(compiler, STHBRX | S(src) | A(mem) | B(offs_reg)); + + FAIL_IF(push_inst(compiler, LHBRX | S(dst) | A(mem) | B(offs_reg))); + + if (op == SLJIT_REV_U16) + return SLJIT_SUCCESS; + return push_inst(compiler, EXTSH | S(dst) | A(dst)); + } + #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - if (!(op_flags & SLJIT_32)) { + if (!is_32) { if (dst & SLJIT_MEM) { +#if defined(_ARCH_PWR7) && _ARCH_PWR7 + return push_inst(compiler, STDBRX | S(src) | A(mem) | B(offs_reg)); +#else /* !POWER7 */ +#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN + FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32))); + FAIL_IF(push_inst(compiler, STWBRX | S(TMP_REG1) | A(mem) | B(offs_reg))); + FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32)))); + return push_inst(compiler, STWBRX | S(src) | A(mem) | B(TMP_REG2)); +#else /* !SLJIT_LITTLE_ENDIAN */ FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(mem) | B(offs_reg))); FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32))); FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32)))); return push_inst(compiler, STWBRX | S(TMP_REG1) | A(mem) | B(TMP_REG2)); +#endif /* SLJIT_LITTLE_ENDIAN */ +#endif /* POWER7 */ } - - FAIL_IF(push_inst(compiler, LWBRX | S(dst) | A(mem) | B(offs_reg))); +#if defined(_ARCH_PWR7) && _ARCH_PWR7 + return push_inst(compiler, LDBRX | S(dst) | A(mem) | B(offs_reg)); +#else /* !POWER7 */ + FAIL_IF(push_inst(compiler, LWBRX | LWBRX_FIRST_REG | A(mem) | B(offs_reg))); FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32)))); - FAIL_IF(push_inst(compiler, LWBRX | S(TMP_REG1) | A(mem) | B(TMP_REG2))); + FAIL_IF(push_inst(compiler, LWBRX | LWBRX_SECOND_REG | A(mem) | B(TMP_REG2))); return push_inst(compiler, RLDIMI | S(TMP_REG1) | A(dst) | RLDI_SH(32) | RLDI_MB(0)); +#endif /* POWER7 */ } #endif /* SLJIT_CONFIG_PPC_64 */ if (dst & SLJIT_MEM) return push_inst(compiler, STWBRX | S(src) | A(mem) | B(offs_reg)); - return push_inst(compiler, LWBRX | S(dst) | A(mem) | B(offs_reg)); + FAIL_IF(push_inst(compiler, LWBRX | S(dst) | A(mem) | B(offs_reg))); +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if (op == SLJIT_REV_S32) + return push_inst(compiler, EXTSW | S(dst) | A(dst)); +#endif /* SLJIT_CONFIG_PPC_64 */ + return SLJIT_SUCCESS; } #define EMIT_MOV(type, type_flags, type_cast) \ - emit_op(compiler, (src & SLJIT_IMM) ? SLJIT_MOV : type, flags | (type_flags), dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? type_cast srcw : srcw) + emit_op(compiler, (src == SLJIT_IMM) ? SLJIT_MOV : type, flags | (type_flags), dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? type_cast srcw : srcw) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, @@ -1449,7 +1596,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile if (op == SLJIT_MOV_S32) op = SLJIT_MOV_U32; } - else if (src & SLJIT_IMM) { + else if (src == SLJIT_IMM) { if (op == SLJIT_MOV_U32) op = SLJIT_MOV_S32; } @@ -1497,12 +1644,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile case SLJIT_CLZ: case SLJIT_CTZ: #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - return emit_op(compiler, op, flags | (!(op_flags & SLJIT_32) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw); -#else + if (op_flags & SLJIT_32) + flags |= ALT_FORM1; +#endif /* SLJIT_CONFIG_PPC_64 */ return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); -#endif + case SLJIT_REV_U32: + case SLJIT_REV_S32: +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + op |= SLJIT_32; +#endif /* SLJIT_CONFIG_PPC_64 */ + /* fallthrough */ case SLJIT_REV: - return emit_rev(compiler, op_flags, dst, dstw, src, srcw); + case SLJIT_REV_U16: + case SLJIT_REV_S16: +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + op |= (op_flags & SLJIT_32); +#endif /* SLJIT_CONFIG_PPC_64 */ + return emit_rev(compiler, op, dst, dstw, src, srcw); } return SLJIT_SUCCESS; @@ -1510,40 +1668,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile #undef EMIT_MOV +/* Macros for checking different operand types / values. */ #define TEST_SL_IMM(src, srcw) \ - (((src) & SLJIT_IMM) && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN) - + ((src) == SLJIT_IMM && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN) #define TEST_UL_IMM(src, srcw) \ - (((src) & SLJIT_IMM) && !((srcw) & ~0xffff)) - -#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) -#define TEST_SH_IMM(src, srcw) \ - (((src) & SLJIT_IMM) && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l) -#else -#define TEST_SH_IMM(src, srcw) \ - (((src) & SLJIT_IMM) && !((srcw) & 0xffff)) -#endif - + ((src) == SLJIT_IMM && !((srcw) & ~0xffff)) #define TEST_UH_IMM(src, srcw) \ - (((src) & SLJIT_IMM) && !((srcw) & ~(sljit_sw)0xffff0000)) + ((src) == SLJIT_IMM && !((srcw) & ~(sljit_sw)0xffff0000)) #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) +#define TEST_SH_IMM(src, srcw) \ + ((src) == SLJIT_IMM && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l) #define TEST_ADD_IMM(src, srcw) \ - (((src) & SLJIT_IMM) && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l) -#else -#define TEST_ADD_IMM(src, srcw) \ - ((src) & SLJIT_IMM) -#endif - -#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + ((src) == SLJIT_IMM && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l) #define TEST_UI_IMM(src, srcw) \ - (((src) & SLJIT_IMM) && !((srcw) & ~0xffffffff)) -#else -#define TEST_UI_IMM(src, srcw) \ - ((src) & SLJIT_IMM) -#endif + ((src) == SLJIT_IMM && !((srcw) & ~0xffffffff)) -#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) #define TEST_ADD_FORM1(op) \ (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \ || (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z | SLJIT_SET_CARRY)) @@ -1553,14 +1693,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile #define TEST_SUB_FORM3(op) \ (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \ || (op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z)) -#else + +#else /* !SLJIT_CONFIG_PPC_64 */ +#define TEST_SH_IMM(src, srcw) \ + ((src) == SLJIT_IMM && !((srcw) & 0xffff)) +#define TEST_ADD_IMM(src, srcw) \ + ((src) == SLJIT_IMM) +#define TEST_UI_IMM(src, srcw) \ + ((src) == SLJIT_IMM) + #define TEST_ADD_FORM1(op) \ (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW) #define TEST_SUB_FORM2(op) \ (GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) #define TEST_SUB_FORM3(op) \ (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW) -#endif +#endif /* SLJIT_CONFIG_PPC_64 */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, @@ -1579,9 +1727,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile if (op & SLJIT_32) { /* Most operations expect sign extended arguments. */ flags |= INT_DATA | SIGNED_DATA; - if (src1 & SLJIT_IMM) + if (src1 == SLJIT_IMM) src1w = (sljit_s32)(src1w); - if (src2 & SLJIT_IMM) + if (src2 == SLJIT_IMM) src2w = (sljit_s32)(src2w); if (HAS_FLAGS(op)) flags |= ALT_SIGN_EXT; @@ -1597,7 +1745,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile if (TEST_ADD_FORM1(op)) return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w); - if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) { + if (!HAS_FLAGS(op) && (src1 == SLJIT_IMM || src2 == SLJIT_IMM)) { if (TEST_SL_IMM(src2, src2w)) { compiler->imm = (sljit_ins)src2w & 0xffff; return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); @@ -1666,7 +1814,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w); } - if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= (SIMM_MAX + 1)) { + if (src2 == SLJIT_IMM && src2w >= 0 && src2w <= (SIMM_MAX + 1)) { compiler->imm = (sljit_ins)src2w; return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); } @@ -1682,7 +1830,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile } if (TEST_SUB_FORM2(op)) { - if ((src2 & SLJIT_IMM) && src2w >= -SIMM_MAX && src2w <= SIMM_MAX) { + if (src2 == SLJIT_IMM && src2w >= -SIMM_MAX && src2w <= SIMM_MAX) { compiler->imm = (sljit_ins)src2w & 0xffff; return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0); } @@ -1741,10 +1889,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w); case SLJIT_XOR: - if ((src2 & SLJIT_IMM) && src2w == -1) { + if (src2 == SLJIT_IMM && src2w == -1) { return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM4, dst, dstw, TMP_REG1, 0, src1, src1w); } - if ((src1 & SLJIT_IMM) && src1w == -1) { + if (src1 == SLJIT_IMM && src1w == -1) { return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM4, dst, dstw, TMP_REG1, 0, src2, src2w); } /* fallthrough */ @@ -1794,7 +1942,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile if (op & SLJIT_32) flags |= ALT_FORM2; #endif - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { compiler->imm = (sljit_ins)src2w; return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0); } @@ -1846,7 +1994,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * ADJUST_LOCAL_OFFSET(src3, src3w); - if (src3 & SLJIT_IMM) { + if (src3 == SLJIT_IMM) { src3w &= bit_length - 1; if (src3w == 0) @@ -1985,21 +2133,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg) { - CHECK_REG_INDEX(check_sljit_get_register_index(reg)); - return reg_map[reg]; -} + CHECK_REG_INDEX(check_sljit_get_register_index(type, reg)); + + if (type == SLJIT_GP_REGISTER) + return reg_map[reg]; + + if (type != SLJIT_FLOAT_REGISTER) + return -1; -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) -{ - CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); return freg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, void *instruction, sljit_u32 size) { + SLJIT_UNUSED_ARG(size); + CHECK_ERROR(); CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); @@ -2010,7 +2161,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c /* Floating point operators */ /* --------------------------------------------------------------------- */ -#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 6)) #define SELECT_FOP(op, single, double) ((sljit_ins)((op & SLJIT_32) ? single : double)) static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, @@ -2068,83 +2218,6 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw)); } -static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, - sljit_s32 dst, sljit_sw dstw, - sljit_s32 src, sljit_sw srcw) -{ -#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - - sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; - - if (src & SLJIT_IMM) { - if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) - srcw = (sljit_s32)srcw; - - FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); - src = TMP_REG1; - } else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) { - if (FAST_IS_REG(src)) - FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1))); - else - FAIL_IF(emit_op_mem(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); - src = TMP_REG1; - } - - if (FAST_IS_REG(src)) { - FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET)); - FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET)); - } else - FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1)); - - FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1))); - - if (dst & SLJIT_MEM) - return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1); - - if (op & SLJIT_32) - return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)); - return SLJIT_SUCCESS; - -#else /* !SLJIT_CONFIG_PPC_64 */ - - sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; - sljit_s32 invert_sign = 1; - - if (src & SLJIT_IMM) { - FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ (sljit_sw)0x80000000)); - src = TMP_REG1; - invert_sign = 0; - } else if (!FAST_IS_REG(src)) { - FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); - src = TMP_REG1; - } - - /* First, a special double floating point value is constructed: (2^53 + (input xor (2^31))) - The double precision format has exactly 53 bit precision, so the lower 32 bit represents - the lower 32 bit of such value. The result of xor 2^31 is the same as adding 0x80000000 - to the input, which shifts it into the 0 - 0xffffffff range. To get the converted floating - point value, we need to subtract 2^53 + 2^31 from the constructed value. */ - FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330)); - if (invert_sign) - FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000)); - FAIL_IF(push_inst(compiler, STW | S(TMP_REG2) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI)); - FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LOW)); - FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000)); - FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET)); - FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LOW)); - FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG2) | A(SLJIT_SP) | TMP_MEM_OFFSET)); - - FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2))); - - if (dst & SLJIT_MEM) - return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1); - if (op & SLJIT_32) - return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)); - return SLJIT_SUCCESS; - -#endif /* SLJIT_CONFIG_PPC_64 */ -} - static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) @@ -2252,18 +2325,30 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil case SLJIT_ADD_F64: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2))); break; - case SLJIT_SUB_F64: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2))); break; - case SLJIT_MUL_F64: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_r) | FA(src1) | FC(src2) /* FMUL use FC as src2 */)); break; - case SLJIT_DIV_F64: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2))); break; + case SLJIT_COPYSIGN_F64: + FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STFS : STFD) | FS(src2) | A(SLJIT_SP) | TMP_MEM_OFFSET)); +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + FAIL_IF(push_inst(compiler, LWZ | S(TMP_REG1) | A(SLJIT_SP) | ((op & SLJIT_32) ? TMP_MEM_OFFSET : TMP_MEM_OFFSET_HI))); +#else /* !SLJIT_CONFIG_PPC_32 */ + FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? LWZ : LD) | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET)); +#endif /* SLJIT_CONFIG_PPC_32 */ + FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src1))); +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(TMP_REG1) | 0)); +#else /* !SLJIT_CONFIG_PPC_32 */ + FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((op & SLJIT_32) ? 0 : 1)) | A(TMP_REG1) | 0)); +#endif /* SLJIT_CONFIG_PPC_32 */ + FAIL_IF(push_inst(compiler, BCx | (4 << 21) | (0 << 16) | 8)); + return push_inst(compiler, FNEG | FD(dst_r) | FB(dst_r)); } if (dst & SLJIT_MEM) @@ -2274,6 +2359,26 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil #undef SELECT_FOP +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f32 value) +{ + union { + sljit_s32 imm; + sljit_f32 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset32(compiler, freg, value)); + + u.value = value; + + if (u.imm != 0) + FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm)); + + FAIL_IF(push_inst(compiler, STW | S(u.imm != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET)); + return push_inst(compiler, LFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET); +} + /* --------------------------------------------------------------------- */ /* Conditional instructions */ /* --------------------------------------------------------------------- */ @@ -2394,7 +2499,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile set_jump(jump, compiler, (sljit_u32)type & SLJIT_REWRITABLE_JUMP); type &= 0xff; - if (type == SLJIT_CARRY || type == SLJIT_NOT_CARRY) + if ((type | 0x1) == SLJIT_NOT_CARRY) PTR_FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO) | B(TMP_ZERO))); /* In PPC, we don't need to touch the arguments. */ @@ -2405,16 +2510,19 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile jump->flags |= IS_CALL; #endif - PTR_FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0)); - PTR_FAIL_IF(push_inst(compiler, MTCTR | S(TMP_CALL_REG))); jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0))); + + /* Maximum number of instructions required for generating a constant. */ + compiler->size += JUMP_MAX_SIZE - 1; return jump; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types) { + SLJIT_UNUSED_ARG(arg_types); + CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); @@ -2440,18 +2548,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); - if (FAST_IS_REG(src)) { -#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) - if (type >= SLJIT_CALL && src != TMP_CALL_REG) { - FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src))); - src_r = TMP_CALL_REG; - } - else - src_r = src; -#else /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */ - src_r = src; -#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */ - } else if (src & SLJIT_IMM) { + if (src == SLJIT_IMM) { /* These jumps are converted to jump/call instructions when possible. */ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); FAIL_IF(!jump); @@ -2463,8 +2560,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi jump->flags |= IS_CALL; #endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */ - FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0)); - src_r = TMP_CALL_REG; + jump->addr = compiler->size; + FAIL_IF(push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0))); + + /* Maximum number of instructions required for generating a constant. */ + compiler->size += JUMP_MAX_SIZE - 1; + return SLJIT_SUCCESS; + } + + if (FAST_IS_REG(src)) { +#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) + if (type >= SLJIT_CALL && src != TMP_CALL_REG) { + FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src))); + src_r = TMP_CALL_REG; + } else + src_r = src; +#else /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */ + src_r = src; +#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */ } else { ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG)); @@ -2472,8 +2585,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi } FAIL_IF(push_inst(compiler, MTCTR | S(src_r))); - if (jump) - jump->addr = compiler->size; return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0)); } @@ -2481,6 +2592,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw) { + SLJIT_UNUSED_ARG(arg_types); + CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); @@ -2663,14 +2776,106 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0); } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, - sljit_s32 src, sljit_sw srcw) + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_reg) +{ + sljit_ins *ptr; + sljit_uw size; +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; +#else /* !SLJIT_CONFIG_PPC_64 */ + sljit_s32 inp_flags = WORD_DATA | LOAD_DATA; +#endif /* SLJIT_CONFIG_PPC_64 */ + + CHECK_ERROR(); + CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg)); + + ADJUST_LOCAL_OFFSET(src1, src1w); + + if (dst_reg != src2_reg) { + if (dst_reg == src1) { + src1 = src2_reg; + src1w = 0; + type ^= 0x1; + } else { + if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) { + FAIL_IF(push_inst(compiler, OR | S(dst_reg) | A(TMP_REG2) | B(dst_reg))); + + if ((src1 & REG_MASK) == dst_reg) + src1 = (src1 & ~REG_MASK) | TMP_REG2; + + if (OFFS_REG(src1) == dst_reg) + src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG2); + } + + FAIL_IF(push_inst(compiler, OR | S(src2_reg) | A(dst_reg) | B(src2_reg))); + } + } + + if (((type & ~SLJIT_32) | 0x1) == SLJIT_NOT_CARRY) + FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO) | B(TMP_ZERO))); + + size = compiler->size; + + ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); + FAIL_IF(!ptr); + compiler->size++; + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w, TMP_REG1)); + } else if (src1 == SLJIT_IMM) { +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + if (type & SLJIT_32) + src1w = (sljit_s32)src1w; +#endif /* SLJIT_CONFIG_RISCV_64 */ + FAIL_IF(load_immediate(compiler, dst_reg, src1w)); + } else + FAIL_IF(push_inst(compiler, OR | S(src1) | A(dst_reg) | B(src1))); + + *ptr = BCx | get_bo_bi_flags(compiler, (type ^ 0x1) & ~SLJIT_32) | (sljit_ins)((compiler->size - size) << 2); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_freg) { + sljit_ins *ptr; + sljit_uw size; + CHECK_ERROR(); - CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); + CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg)); + + ADJUST_LOCAL_OFFSET(src1, src1w); - return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);; + if (dst_freg != src2_freg) { + if (dst_freg == src1) { + src1 = src2_freg; + src1w = 0; + type ^= 0x1; + } else + FAIL_IF(push_inst(compiler, FMR | FD(dst_freg) | FB(src2_freg))); + } + + if (((type & ~SLJIT_32) | 0x1) == SLJIT_NOT_CARRY) + FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO) | B(TMP_ZERO))); + + size = compiler->size; + + ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); + FAIL_IF(!ptr); + compiler->size++; + + if (src1 & SLJIT_MEM) + FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, dst_freg, src1, src1w, TMP_REG1)); + else + FAIL_IF(push_inst(compiler, FMR | FD(dst_freg) | FB(src1))); + + *ptr = BCx | get_bo_bi_flags(compiler, (type ^ 0x1) & ~SLJIT_32) | (sljit_ins)((compiler->size - size) << 2); + return SLJIT_SUCCESS; } #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) @@ -2909,31 +3114,31 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi return const_; } -SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { - struct sljit_put_label *put_label; + struct sljit_jump *jump; sljit_s32 dst_r; CHECK_ERROR_PTR(); - CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw)); + CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); - put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label)); - PTR_FAIL_IF(!put_label); - set_put_label(put_label, compiler, 0); + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_mov_addr(jump, compiler, 0); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r)); #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) - PTR_FAIL_IF(emit_const(compiler, dst_r, 0)); + compiler->size++; #else - PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r)); compiler->size += 4; #endif if (dst & SLJIT_MEM) PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0)); - return put_label; + return jump; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_32.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_32.c index 4490be2aafb..396c956c197 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_32.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_32.c @@ -27,7 +27,6 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm, sljit_s32 tmp_r) { SLJIT_UNUSED_ARG(tmp_r); - SLJIT_ASSERT(dst_r != tmp_r); if (imm <= SIMM_MAX && imm >= SIMM_MIN) return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm)); @@ -43,6 +42,31 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f64 value) +{ + union { + sljit_s32 imm[2]; + sljit_f64 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset64(compiler, freg, value)); + + u.value = value; + + if (u.imm[0] != 0) + FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0], TMP_REG3)); + if (u.imm[1] != 0) + FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1], TMP_REG3)); + + FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-16))); + FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(u.imm[0] != 0 ? TMP_REG1 : TMP_ZERO) | (8 << 7))); + FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(u.imm[1] != 0 ? TMP_REG2 : TMP_ZERO) | (12 << 7))); + FAIL_IF(push_inst(compiler, FLD | FRD(freg) | RS1(SLJIT_SP) | IMM_I(8))); + return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(16)); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 freg, sljit_s32 reg) { diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_64.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_64.c index f93d6ff667f..7fcf2c52730 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_64.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_64.c @@ -28,8 +28,6 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r { sljit_sw high; - SLJIT_ASSERT(dst_r != tmp_r); - if (imm <= SIMM_MAX && imm >= SIMM_MIN) return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm)); @@ -81,6 +79,8 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r return SLJIT_SUCCESS; } + SLJIT_ASSERT(dst_r != tmp_r); + high = imm >> 32; imm = (sljit_s32)imm; @@ -126,6 +126,26 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r return push_inst(compiler, XOR | RD(dst_r) | RS1(dst_r) | RS2(tmp_r)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f64 value) +{ + union { + sljit_sw imm; + sljit_f64 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset64(compiler, freg, value)); + + u.value = value; + + if (u.imm == 0) + return push_inst(compiler, FMV_W_X | (1 << 25) | RS1(TMP_ZERO) | FRD(freg)); + + FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm, TMP_REG3)); + return push_inst(compiler, FMV_W_X | (1 << 25) | RS1(TMP_REG1) | FRD(freg)); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 freg, sljit_s32 reg) { diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_common.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_common.c index 473e06040af..a0996276a3a 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_common.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeRISCV_common.c @@ -100,6 +100,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { /* These conversion opcodes are partly defined. */ #define FCVT_S_D (F7(0x20) | OPC(0x53)) #define FCVT_S_W (F7(0x68) | OPC(0x53)) +#define FCVT_S_WU (F7(0x68) | F12(0x1) | OPC(0x53)) #define FCVT_W_S (F7(0x60) | F3(0x1) | OPC(0x53)) #define FMUL_S (F7(0x8) | F3(0x7) | OPC(0x53)) #define FMV_X_W (F7(0x70) | F3(0x0) | OPC(0x53)) @@ -180,24 +181,23 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i if (jump->flags & JUMP_ADDR) target_addr = jump->u.target; else { - SLJIT_ASSERT(jump->flags & JUMP_LABEL); + SLJIT_ASSERT(jump->u.label != NULL); target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset; } diff = (sljit_sw)target_addr - (sljit_sw)inst - executable_offset; if (jump->flags & IS_COND) { - inst--; diff += SSIZE_OF(ins); if (diff >= BRANCH_MIN && diff <= BRANCH_MAX) { - jump->flags |= PATCH_B; + inst--; inst[0] = (inst[0] & 0x1fff07f) ^ 0x1000; + jump->flags |= PATCH_B; jump->addr = (sljit_uw)inst; return inst; } - inst++; diff -= SSIZE_OF(ins); } @@ -264,113 +264,236 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) -static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label) +static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) { - if (max_label <= (sljit_uw)S32_MAX) { - put_label->flags = PATCH_ABS32; + sljit_uw addr; + sljit_sw diff; + SLJIT_UNUSED_ARG(executable_offset); + + SLJIT_ASSERT(jump->flags < ((sljit_uw)6 << JUMP_SIZE_SHIFT)); + if (jump->flags & JUMP_ADDR) + addr = jump->u.target; + else + addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset); + + diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + + if (diff >= S32_MIN && diff <= S32_MAX) { + SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT)); + jump->flags |= PATCH_REL32; return 1; } - if (max_label <= S44_MAX) { - put_label->flags = PATCH_ABS44; + if (addr <= S32_MAX) { + SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT)); + jump->flags |= PATCH_ABS32; + return 1; + } + + if (addr <= S44_MAX) { + SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT)); + jump->flags |= PATCH_ABS44; return 3; } - if (max_label <= S52_MAX) { - put_label->flags = PATCH_ABS52; + if (addr <= S52_MAX) { + SLJIT_ASSERT(jump->flags >= ((sljit_uw)4 << JUMP_SIZE_SHIFT)); + jump->flags |= PATCH_ABS52; return 4; } - put_label->flags = 0; + SLJIT_ASSERT(jump->flags >= ((sljit_uw)5 << JUMP_SIZE_SHIFT)); return 5; } #endif /* SLJIT_CONFIG_RISCV_64 */ -static SLJIT_INLINE void load_addr_to_reg(void *dst, sljit_u32 reg) +static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump, sljit_sw executable_offset) { - struct sljit_jump *jump = NULL; - struct sljit_put_label *put_label; - sljit_uw flags; - sljit_ins *inst; + sljit_uw flags = jump->flags; + sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr; + sljit_ins *ins = (sljit_ins*)jump->addr; + sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *ins : TMP_REG1; #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) sljit_sw high; #endif - sljit_uw addr; + SLJIT_UNUSED_ARG(executable_offset); - if (reg != 0) { - jump = (struct sljit_jump*)dst; - flags = jump->flags; - inst = (sljit_ins*)jump->addr; - addr = (flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; - } else { - put_label = (struct sljit_put_label*)dst; #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) - flags = put_label->flags; -#endif - inst = (sljit_ins*)put_label->addr; - addr = put_label->label->addr; - reg = *inst; + if (flags & PATCH_REL32) { + addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset); + + SLJIT_ASSERT((sljit_sw)addr >= S32_MIN && (sljit_sw)addr <= S32_MAX); + + if ((addr & 0x800) != 0) + addr += 0x1000; + + ins[0] = AUIPC | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff); + + if (!(flags & JUMP_MOV_ADDR)) { + SLJIT_ASSERT((ins[1] & 0x707f) == JALR); + ins[1] = (ins[1] & 0xfffff) | IMM_I(addr); + } else + ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(addr); + return; } +#endif if ((addr & 0x800) != 0) addr += 0x1000; #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) - inst[0] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff); + ins[0] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff); #else /* !SLJIT_CONFIG_RISCV_32 */ if (flags & PATCH_ABS32) { SLJIT_ASSERT(addr <= S32_MAX); - inst[0] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff); + ins[0] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff); } else if (flags & PATCH_ABS44) { high = (sljit_sw)addr >> 12; SLJIT_ASSERT((sljit_uw)high <= 0x7fffffff); if (high > S32_MAX) { SLJIT_ASSERT((high & 0x800) != 0); - inst[0] = LUI | RD(reg) | (sljit_ins)0x80000000u; - inst[1] = XORI | RD(reg) | RS1(reg) | IMM_I(high); + ins[0] = LUI | RD(reg) | (sljit_ins)0x80000000u; + ins[1] = XORI | RD(reg) | RS1(reg) | IMM_I(high); } else { if ((high & 0x800) != 0) high += 0x1000; - inst[0] = LUI | RD(reg) | (sljit_ins)(high & ~0xfff); - inst[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(high); + ins[0] = LUI | RD(reg) | (sljit_ins)(high & ~0xfff); + ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(high); } - inst[2] = SLLI | RD(reg) | RS1(reg) | IMM_I(12); - inst += 2; + ins[2] = SLLI | RD(reg) | RS1(reg) | IMM_I(12); + ins += 2; } else { high = (sljit_sw)addr >> 32; if ((addr & 0x80000000l) != 0) high = ~high; - if ((high & 0x800) != 0) - high += 0x1000; - if (flags & PATCH_ABS52) { SLJIT_ASSERT(addr <= S52_MAX); - inst[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high << 12); + ins[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high << 12); } else { - inst[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff); - inst[1] = ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high); - inst++; + if ((high & 0x800) != 0) + high += 0x1000; + ins[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff); + ins[1] = ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high); + ins++; } - inst[1] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff); - inst[2] = SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I((flags & PATCH_ABS52) ? 20 : 32); - inst[3] = XOR | RD(reg) | RS1(reg) | RS2(TMP_REG3); - inst += 3; + ins[1] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff); + ins[2] = SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I((flags & PATCH_ABS52) ? 20 : 32); + ins[3] = XOR | RD(reg) | RS1(reg) | RS2(TMP_REG3); + ins += 3; } #endif /* !SLJIT_CONFIG_RISCV_32 */ - if (jump != NULL) { - SLJIT_ASSERT((inst[1] & 0x707f) == JALR); - inst[1] = (inst[1] & 0xfffff) | IMM_I(addr); + if (!(flags & JUMP_MOV_ADDR)) { + SLJIT_ASSERT((ins[1] & 0x707f) == JALR); + ins[1] = (ins[1] & 0xfffff) | IMM_I(addr); } else - inst[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(addr); + ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(addr); +} + +static void reduce_code_size(struct sljit_compiler *compiler) +{ + struct sljit_label *label; + struct sljit_jump *jump; + struct sljit_const *const_; + SLJIT_NEXT_DEFINE_TYPES; + sljit_uw total_size; + sljit_uw size_reduce = 0; + sljit_sw diff; + + label = compiler->labels; + jump = compiler->jumps; + const_ = compiler->consts; + SLJIT_NEXT_INIT_TYPES(); + + while (1) { + SLJIT_GET_NEXT_MIN(); + + if (next_min_addr == SLJIT_MAX_ADDRESS) + break; + + if (next_min_addr == next_label_size) { + label->size -= size_reduce; + + label = label->next; + next_label_size = SLJIT_GET_NEXT_SIZE(label); + } + + if (next_min_addr == next_const_addr) { + const_->addr -= size_reduce; + const_ = const_->next; + next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_); + continue; + } + + if (next_min_addr != next_jump_addr) + continue; + + jump->addr -= size_reduce; + if (!(jump->flags & JUMP_MOV_ADDR)) { + total_size = JUMP_MAX_SIZE; + + if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) { + if (jump->flags & JUMP_ADDR) { +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + if (jump->u.target <= S32_MAX) + total_size = 2; + else if (jump->u.target <= S44_MAX) + total_size = 4; + else if (jump->u.target <= S52_MAX) + total_size = 5; +#endif /* SLJIT_CONFIG_RISCV_64 */ + } else { + /* Unit size: instruction. */ + diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; + + if ((jump->flags & IS_COND) && (diff + 1) <= (BRANCH_MAX / SSIZE_OF(ins)) && (diff + 1) >= (BRANCH_MIN / SSIZE_OF(ins))) + total_size = 0; + else if (diff >= (JUMP_MIN / SSIZE_OF(ins)) && diff <= (JUMP_MAX / SSIZE_OF(ins))) + total_size = 1; +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + else if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins))) + total_size = 2; +#endif /* SLJIT_CONFIG_RISCV_64 */ + } + } + + size_reduce += JUMP_MAX_SIZE - total_size; + jump->flags |= total_size << JUMP_SIZE_SHIFT; +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + } else { + total_size = 5; + + if (!(jump->flags & JUMP_ADDR)) { + /* Real size minus 1. Unit size: instruction. */ + diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr; + + if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins))) + total_size = 1; + } else if (jump->u.target < S32_MAX) + total_size = 1; + else if (jump->u.target < S44_MAX) + total_size = 3; + else if (jump->u.target <= S52_MAX) + total_size = 4; + + size_reduce += 5 - total_size; + jump->flags |= total_size << JUMP_SIZE_SHIFT; +#endif /* !SLJIT_CONFIG_RISCV_64 */ + } + + jump = jump->next; + next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); + } + + compiler->size -= size_reduce; } SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) @@ -381,77 +504,80 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil sljit_ins *buf_ptr; sljit_ins *buf_end; sljit_uw word_count; - sljit_uw next_addr; + SLJIT_NEXT_DEFINE_TYPES; sljit_sw executable_offset; sljit_uw addr; struct sljit_label *label; struct sljit_jump *jump; struct sljit_const *const_; - struct sljit_put_label *put_label; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_generate_code(compiler)); - reverse_buf(compiler); + + reduce_code_size(compiler); code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data); PTR_FAIL_WITH_EXEC_IF(code); + + reverse_buf(compiler); buf = compiler->buf; code_ptr = code; word_count = 0; - next_addr = 0; executable_offset = SLJIT_EXEC_OFFSET(code); label = compiler->labels; jump = compiler->jumps; const_ = compiler->consts; - put_label = compiler->put_labels; + SLJIT_NEXT_INIT_TYPES(); + SLJIT_GET_NEXT_MIN(); do { buf_ptr = (sljit_ins*)buf->memory; buf_end = buf_ptr + (buf->used_size >> 2); do { *code_ptr = *buf_ptr++; - if (next_addr == word_count) { + if (next_min_addr == word_count) { SLJIT_ASSERT(!label || label->size >= word_count); SLJIT_ASSERT(!jump || jump->addr >= word_count); SLJIT_ASSERT(!const_ || const_->addr >= word_count); - SLJIT_ASSERT(!put_label || put_label->addr >= word_count); /* These structures are ordered by their address. */ - if (label && label->size == word_count) { - label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + if (next_min_addr == next_label_size) { + label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); label->size = (sljit_uw)(code_ptr - code); label = label->next; + next_label_size = SLJIT_GET_NEXT_SIZE(label); } - if (jump && jump->addr == word_count) { + + if (next_min_addr == next_jump_addr) { + if (!(jump->flags & JUMP_MOV_ADDR)) { + word_count = word_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT); + jump->addr = (sljit_uw)code_ptr; + code_ptr = detect_jump_type(jump, code, executable_offset); + SLJIT_ASSERT((jump->flags & PATCH_B) || ((sljit_uw)code_ptr - jump->addr < (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins))); + } else { #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) - word_count += 1; -#else - word_count += 5; -#endif - jump->addr = (sljit_uw)code_ptr; - code_ptr = detect_jump_type(jump, code, executable_offset); + word_count += 1; + jump->addr = (sljit_uw)code_ptr; + code_ptr += 1; +#else /* !SLJIT_CONFIG_RISCV_32 */ + word_count += jump->flags >> JUMP_SIZE_SHIFT; + addr = (sljit_uw)code_ptr; + code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset); + jump->addr = addr; +#endif /* SLJIT_CONFIG_RISCV_32 */ + } jump = jump->next; - } - if (const_ && const_->addr == word_count) { + next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); + } else if (next_min_addr == next_const_addr) { const_->addr = (sljit_uw)code_ptr; const_ = const_->next; + next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_); } - if (put_label && put_label->addr == word_count) { - SLJIT_ASSERT(put_label->label); - put_label->addr = (sljit_uw)code_ptr; -#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) - code_ptr += 1; - word_count += 1; -#else - code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size)); - word_count += 5; -#endif - put_label = put_label->next; - } - next_addr = compute_next_addr(label, jump, const_, put_label); + + SLJIT_GET_NEXT_MIN(); } code_ptr++; word_count++; @@ -461,7 +587,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil } while (buf); if (label && label->size == word_count) { - label->addr = (sljit_uw)code_ptr; + label->u.addr = (sljit_uw)code_ptr; label->size = (sljit_uw)(code_ptr - code); label = label->next; } @@ -469,18 +595,17 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil SLJIT_ASSERT(!label); SLJIT_ASSERT(!jump); SLJIT_ASSERT(!const_); - SLJIT_ASSERT(!put_label); SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size); jump = compiler->jumps; while (jump) { do { - if (!(jump->flags & (PATCH_B | PATCH_J | PATCH_REL32))) { - load_addr_to_reg(jump, TMP_REG1); + if (!(jump->flags & (PATCH_B | PATCH_J)) || (jump->flags & JUMP_MOV_ADDR)) { + load_addr_to_reg(jump, executable_offset); break; } - addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; + addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr; buf_ptr = (sljit_ins *)jump->addr; addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset); @@ -491,31 +616,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil break; } -#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) - if (jump->flags & PATCH_REL32) { - SLJIT_ASSERT((sljit_sw)addr >= S32_MIN && (sljit_sw)addr <= S32_MAX); - - if ((addr & 0x800) != 0) - addr += 0x1000; - - buf_ptr[0] = AUIPC | RD(TMP_REG1) | (sljit_ins)((sljit_sw)addr & ~0xfff); - SLJIT_ASSERT((buf_ptr[1] & 0x707f) == JALR); - buf_ptr[1] |= IMM_I(addr); - break; - } -#endif - SLJIT_ASSERT((sljit_sw)addr >= JUMP_MIN && (sljit_sw)addr <= JUMP_MAX); addr = (addr & 0xff000) | ((addr & 0x800) << 9) | ((addr & 0x7fe) << 20) | ((addr & 0x100000) << 11); buf_ptr[0] = JAL | RD((jump->flags & IS_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | (sljit_ins)addr; } while (0); - jump = jump->next; - } - put_label = compiler->put_labels; - while (put_label) { - load_addr_to_reg(put_label, 0); - put_label = put_label->next; + jump = jump->next; } compiler->error = SLJIT_ERR_COMPILED; @@ -535,7 +641,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) switch (feature_type) { case SLJIT_HAS_FPU: #ifdef SLJIT_IS_FPU_AVAILABLE - return SLJIT_IS_FPU_AVAILABLE; + return (SLJIT_IS_FPU_AVAILABLE) != 0; #elif defined(__riscv_float_abi_soft) return 0; #else @@ -554,7 +660,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) { - return (type >= SLJIT_ORDERED_EQUAL && type <= SLJIT_ORDERED_LESS_EQUAL); + switch (type) { + case SLJIT_UNORDERED_OR_EQUAL: + case SLJIT_ORDERED_NOT_EQUAL: + return 2; + + case SLJIT_UNORDERED: + case SLJIT_ORDERED: + return 1; + } + + return 0; } /* --------------------------------------------------------------------- */ @@ -929,7 +1045,7 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl /* Since tmp can be the same as base or offset registers, * these might be unavailable after modifying tmp. */ - if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) + if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA) && reg == TMP_REG2) tmp_r = reg; if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { @@ -1057,16 +1173,16 @@ static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, slj { sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ); #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) - sljit_ins word = (op & SLJIT_32) >> 5; - sljit_ins max = (op & SLJIT_32) ? 32 : 64; + sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5; + sljit_ins word_size = (op & SLJIT_32) ? 32 : 64; #else /* !SLJIT_CONFIG_RISCV_64 */ - sljit_ins max = 32; + sljit_ins word_size = 32; #endif /* SLJIT_CONFIG_RISCV_64 */ SLJIT_ASSERT(WORD == 0 || WORD == 0x8); /* The OTHER_FLAG is the counter. */ - FAIL_IF(push_inst(compiler, ADDI | WORD | RD(OTHER_FLAG) | RS1(TMP_ZERO) | IMM_I(max))); + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(OTHER_FLAG) | RS1(TMP_ZERO) | IMM_I(word_size))); /* The TMP_REG2 is the next value. */ if (src != TMP_REG2) @@ -1082,7 +1198,7 @@ static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, slj FAIL_IF(push_inst(compiler, BLT | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)(2 * SSIZE_OF(ins)) << 7) | ((sljit_ins)(8 * SSIZE_OF(ins)) << 20))); /* The TMP_REG1 is the next shift. */ - FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG1) | RS1(TMP_ZERO) | IMM_I(max))); + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG1) | RS1(TMP_ZERO) | IMM_I(word_size))); FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(TMP_REG2) | IMM_I(0))); FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_I(1))); @@ -1140,6 +1256,22 @@ static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)); } +static sljit_s32 emit_rev16(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src) +{ +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5; + sljit_ins word_size = (op & SLJIT_32) ? 32 : 64; +#else /* !SLJIT_CONFIG_RISCV_64 */ + sljit_ins word_size = 32; +#endif /* SLJIT_CONFIG_RISCV_64 */ + + FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(src) | IMM_I(8))); + FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src) | IMM_I(word_size - 8))); + FAIL_IF(push_inst(compiler, ANDI | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_I(0xff))); + FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI) | WORD | RD(dst) | RS1(dst) | IMM_I(word_size - 16))); + return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)); +} + #define EMIT_LOGICAL(op_imm, op_reg) \ if (flags & SRC2_IMM) { \ if (op & SLJIT_SET_Z) \ @@ -1164,7 +1296,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl sljit_s32 is_overflow, is_carry, carry_src_r, is_handled; sljit_ins op_imm, op_reg; #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) - sljit_ins word = (op & SLJIT_32) >> 5; + sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5; #endif /* SLJIT_CONFIG_RISCV_64 */ SLJIT_ASSERT(WORD == 0 || WORD == 0x8); @@ -1234,9 +1366,28 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return emit_clz_ctz(compiler, op, dst, src2); case SLJIT_REV: + case SLJIT_REV_S32: +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + case SLJIT_REV_U32: +#endif /* SLJIT_CONFIG_RISCV_32 */ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); return emit_rev(compiler, op, dst, src2); + case SLJIT_REV_U16: + case SLJIT_REV_S16: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + return emit_rev16(compiler, op, dst, src2); + +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + case SLJIT_REV_U32: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && dst != TMP_REG1); + FAIL_IF(emit_rev(compiler, op, dst, src2)); + if (dst == TMP_REG2) + return SLJIT_SUCCESS; + FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(32))); + return push_inst(compiler, SRLI | RD(dst) | RS1(dst) | IMM_I(32)); +#endif /* SLJIT_CONFIG_RISCV_32 */ + case SLJIT_ADD: /* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; @@ -1593,9 +1744,10 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 compiler->cache_argw = 0; } - if (dst == TMP_REG2) { + if (dst == 0) { SLJIT_ASSERT(HAS_FLAGS(op)); flags |= UNUSED_DEST; + dst = TMP_REG2; } else if (FAST_IS_REG(dst)) { dst_r = dst; @@ -1607,11 +1759,11 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 flags |= SLOW_DEST; if (flags & IMM_OP) { - if ((src2 & SLJIT_IMM) && src2w != 0 && src2w <= SIMM_MAX && src2w >= SIMM_MIN) { + if (src2 == SLJIT_IMM && src2w != 0 && src2w <= SIMM_MAX && src2w >= SIMM_MIN) { flags |= SRC2_IMM; src2_r = src2w; } - else if ((flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w != 0 && src1w <= SIMM_MAX && src1w >= SIMM_MIN) { + else if ((flags & CUMULATIVE_OP) && src1 == SLJIT_IMM && src1w != 0 && src1w <= SIMM_MAX && src1w >= SIMM_MIN) { flags |= SRC2_IMM; src2_r = src1w; @@ -1628,7 +1780,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 src1_r = src1; flags |= REG1_SOURCE; } - else if (src1 & SLJIT_IMM) { + else if (src1 == SLJIT_IMM) { if (src1w) { FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3)); src1_r = TMP_REG1; @@ -1651,7 +1803,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP) dst_r = (sljit_s32)src2_r; } - else if (src2 & SLJIT_IMM) { + else if (src2 == SLJIT_IMM) { if (!(flags & SRC2_IMM)) { if (src2w) { FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w, TMP_REG3)); @@ -1708,7 +1860,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) - sljit_ins word = (op & SLJIT_32) >> 5; + sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5; SLJIT_ASSERT(word == 0 || word == 0x8); #endif /* SLJIT_CONFIG_RISCV_64 */ @@ -1777,30 +1929,38 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) case SLJIT_MOV_U32: - return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw); + return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u32)srcw : srcw); case SLJIT_MOV_S32: /* Logical operators have no W variant, so sign extended input is necessary for them. */ case SLJIT_MOV32: - return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s32)srcw : srcw); + return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s32)srcw : srcw); #endif case SLJIT_MOV_U8: - return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw); + return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw); case SLJIT_MOV_S8: - return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw); + return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw); case SLJIT_MOV_U16: - return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw); + return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw); case SLJIT_MOV_S16: - return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); + return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw); case SLJIT_CLZ: case SLJIT_CTZ: case SLJIT_REV: return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_REV_U16: + case SLJIT_REV_S16: + return emit_op(compiler, op, HALF_DATA, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_REV_U32: + case SLJIT_REV_S32: + return emit_op(compiler, op | SLJIT_32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw); } SLJIT_UNREACHABLE(); @@ -1823,9 +1983,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) if (op & SLJIT_32) { flags |= INT_DATA | SIGNED_DATA; - if (src1 & SLJIT_IMM) + if (src1 == SLJIT_IMM) src1w = (sljit_s32)src1w; - if (src2 & SLJIT_IMM) + if (src2 == SLJIT_IMM) src2w = (sljit_s32)src2w; } #endif @@ -1858,7 +2018,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile case SLJIT_MASHR: case SLJIT_ROTL: case SLJIT_ROTR: - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) src2w &= 0x1f; #else /* !SLJIT_CONFIG_RISCV_32 */ @@ -1884,7 +2044,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w)); SLJIT_SKIP_CHECKS(compiler); - return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w); + return sljit_emit_op2(compiler, op, 0, 0, src1, src1w, src2, src2w); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op, @@ -1896,7 +2056,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * sljit_s32 is_left; sljit_ins ins1, ins2, ins3; #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) - sljit_ins word = (op & SLJIT_32) >> 5; + sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5; sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64; #else /* !SLJIT_CONFIG_RISCV_64 */ @@ -1918,7 +2078,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * ADJUST_LOCAL_OFFSET(src3, src3w); - if (src3 & SLJIT_IMM) { + if (src3 == SLJIT_IMM) { src3w &= bit_length - 1; if (src3w == 0) @@ -1970,8 +2130,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1)); } -#undef WORD - SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { @@ -2027,21 +2185,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg) { - CHECK_REG_INDEX(check_sljit_get_register_index(reg)); - return reg_map[reg]; -} + CHECK_REG_INDEX(check_sljit_get_register_index(type, reg)); + + if (type == SLJIT_GP_REGISTER) + return reg_map[reg]; + + if (type != SLJIT_FLOAT_REGISTER) + return -1; -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) -{ - CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); return freg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, void *instruction, sljit_u32 size) { + SLJIT_UNUSED_ARG(size); + CHECK_ERROR(); CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); @@ -2088,51 +2249,73 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp #endif } -static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, +static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { - sljit_ins inst; -#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) - sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)) << 21; -#endif - sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src & SLJIT_MEM) { #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw)); -#else - FAIL_IF(emit_op_mem2(compiler, (flags ? WORD_DATA : INT_DATA) | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw)); -#endif +#else /* SLJIT_CONFIG_RISCV_32 */ + FAIL_IF(emit_op_mem2(compiler, ((ins & (1 << 21)) ? WORD_DATA : INT_DATA) | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw)); +#endif /* !SLJIT_CONFIG_RISCV_32 */ src = TMP_REG1; - } else if (src & SLJIT_IMM) { -#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) - if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) - srcw = (sljit_s32)srcw; -#endif - + } else if (src == SLJIT_IMM) { FAIL_IF(load_immediate(compiler, TMP_REG1, srcw, TMP_REG3)); src = TMP_REG1; } - inst = FCVT_S_W | FMT(op) | FRD(dst_r) | RS1(src); + FAIL_IF(push_inst(compiler, ins | FRD(dst_r) | RS1(src))); + + if (dst & SLJIT_MEM) + return emit_op_mem2(compiler, DOUBLE_DATA | ((sljit_s32)(~ins >> 24) & 0x2), TMP_FREG1, dst, dstw, 0, 0); + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins ins = FCVT_S_W | FMT(op); #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) if (op & SLJIT_32) - inst |= F3(0x7); -#else - inst |= flags; + ins |= F3(0x7); +#else /* !SLJIT_CONFIG_RISCV_32 */ + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW) + ins |= (1 << 21); + else if (src == SLJIT_IMM) + srcw = (sljit_s32)srcw; if (op != SLJIT_CONV_F64_FROM_S32) - inst |= F3(0x7); -#endif + ins |= F3(0x7); +#endif /* SLJIT_CONFIG_RISCV_32 */ + + return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw); +} - FAIL_IF(push_inst(compiler, inst)); +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins ins = FCVT_S_WU | FMT(op); - if (dst & SLJIT_MEM) - return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0); - return SLJIT_SUCCESS; +#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) + if (op & SLJIT_32) + ins |= F3(0x7); +#else /* !SLJIT_CONFIG_RISCV_32 */ + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_UW) + ins |= (1 << 21); + else if (src == SLJIT_IMM) + srcw = (sljit_u32)srcw; + + if (op != SLJIT_CONV_F64_FROM_S32) + ins |= F3(0x7); +#endif /* SLJIT_CONFIG_RISCV_32 */ + + return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw); } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, @@ -2170,14 +2353,19 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile case SLJIT_UNORDERED_OR_LESS: inst = FLE_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src2) | FRS2(src1); break; - case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */ + case SLJIT_UNORDERED_OR_EQUAL: FAIL_IF(push_inst(compiler, FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2))); FAIL_IF(push_inst(compiler, FLT_S | FMT(op) | RD(TMP_REG1) | FRS1(src2) | FRS2(src1))); inst = OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1); break; default: /* SLJIT_UNORDERED */ - FAIL_IF(push_inst(compiler, FADD_S | FMT(op) | FRD(TMP_FREG1) | FRS1(src1) | FRS2(src2))); - inst = FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(TMP_FREG1) | FRS2(TMP_FREG1); + if (src1 == src2) { + inst = FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src1); + break; + } + FAIL_IF(push_inst(compiler, FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src1))); + FAIL_IF(push_inst(compiler, FEQ_S | FMT(op) | RD(TMP_REG1) | FRS1(src2) | FRS2(src2))); + inst = AND | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1); break; } @@ -2304,6 +2492,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil case SLJIT_DIV_F64: FAIL_IF(push_inst(compiler, FDIV_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2))); break; + + case SLJIT_COPYSIGN_F64: + return push_inst(compiler, FSGNJ_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)); } if (dst_r == TMP_FREG2) @@ -2312,8 +2503,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil return SLJIT_SUCCESS; } -#undef FLOAT_DATA -#undef FMT +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f32 value) +{ + union { + sljit_s32 imm; + sljit_f32 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset32(compiler, freg, value)); + + u.value = value; + + if (u.imm == 0) + return push_inst(compiler, FMV_W_X | RS1(TMP_ZERO) | FRD(freg)); + + FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm, TMP_REG3)); + return push_inst(compiler, FMV_W_X | RS1(TMP_REG1) | FRD(freg)); +} /* --------------------------------------------------------------------- */ /* Conditional instructions */ @@ -2341,26 +2549,13 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi #define BRANCH_LENGTH ((sljit_ins)(7 * sizeof(sljit_ins)) << 7) #endif -SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) +static sljit_ins get_jump_instruction(sljit_s32 type) { - struct sljit_jump *jump; - sljit_ins inst; - - CHECK_ERROR_PTR(); - CHECK_PTR(check_sljit_emit_jump(compiler, type)); - - jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); - PTR_FAIL_IF(!jump); - set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); - type &= 0xff; - switch (type) { case SLJIT_EQUAL: - inst = BNE | RS1(EQUAL_FLAG) | RS2(TMP_ZERO) | BRANCH_LENGTH; - break; + return BNE | RS1(EQUAL_FLAG) | RS2(TMP_ZERO); case SLJIT_NOT_EQUAL: - inst = BEQ | RS1(EQUAL_FLAG) | RS2(TMP_ZERO) | BRANCH_LENGTH; - break; + return BEQ | RS1(EQUAL_FLAG) | RS2(TMP_ZERO); case SLJIT_LESS: case SLJIT_GREATER: case SLJIT_SIG_LESS: @@ -2369,7 +2564,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile case SLJIT_CARRY: case SLJIT_F_EQUAL: case SLJIT_ORDERED_EQUAL: - case SLJIT_ORDERED_NOT_EQUAL: /* Not supported. */ + case SLJIT_ORDERED_NOT_EQUAL: case SLJIT_F_LESS: case SLJIT_ORDERED_LESS: case SLJIT_ORDERED_GREATER: @@ -2377,7 +2572,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile case SLJIT_ORDERED_LESS_EQUAL: case SLJIT_ORDERED_GREATER_EQUAL: case SLJIT_ORDERED: - inst = BEQ | RS1(OTHER_FLAG) | RS2(TMP_ZERO) | BRANCH_LENGTH; + return BEQ | RS1(OTHER_FLAG) | RS2(TMP_ZERO); break; case SLJIT_GREATER_EQUAL: case SLJIT_LESS_EQUAL: @@ -2387,7 +2582,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile case SLJIT_NOT_CARRY: case SLJIT_F_NOT_EQUAL: case SLJIT_UNORDERED_OR_NOT_EQUAL: - case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */ + case SLJIT_UNORDERED_OR_EQUAL: case SLJIT_F_GREATER_EQUAL: case SLJIT_UNORDERED_OR_GREATER_EQUAL: case SLJIT_UNORDERED_OR_LESS_EQUAL: @@ -2395,16 +2590,30 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile case SLJIT_UNORDERED_OR_GREATER: case SLJIT_UNORDERED_OR_LESS: case SLJIT_UNORDERED: - inst = BNE | RS1(OTHER_FLAG) | RS2(TMP_ZERO) | BRANCH_LENGTH; - break; + return BNE | RS1(OTHER_FLAG) | RS2(TMP_ZERO); default: /* Not conditional branch. */ - inst = 0; - break; + return 0; } +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) +{ + struct sljit_jump *jump; + sljit_ins inst; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_jump(compiler, type)); + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); + type &= 0xff; + + inst = get_jump_instruction(type); if (inst != 0) { - PTR_FAIL_IF(push_inst(compiler, inst)); + PTR_FAIL_IF(push_inst(compiler, inst | BRANCH_LENGTH)); jump->flags |= IS_COND; } @@ -2419,11 +2628,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile PTR_FAIL_IF(push_inst(compiler, inst)); /* Maximum number of instructions required for generating a constant. */ -#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) - compiler->size += 1; -#else - compiler->size += 5; -#endif + compiler->size += JUMP_MAX_SIZE - 1; return jump; } @@ -2474,7 +2679,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler src2 = TMP_REG2; } - if (src1 & SLJIT_IMM) { + if (src1 == SLJIT_IMM) { if (src1w != 0) { PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3)); src1 = TMP_REG1; @@ -2483,7 +2688,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler src1 = TMP_ZERO; } - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { if (src2w != 0) { PTR_FAIL_IF(load_immediate(compiler, TMP_REG2, src2w, TMP_REG3)); src2 = TMP_REG2; @@ -2536,11 +2741,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler PTR_FAIL_IF(push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(TMP_REG1) | IMM_I(0))); /* Maximum number of instructions required for generating a constant. */ -#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) - compiler->size += 1; -#else - compiler->size += 5; -#endif + compiler->size += JUMP_MAX_SIZE - 1; return jump; } @@ -2553,7 +2754,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); - if (!(src & SLJIT_IMM)) { + if (src != SLJIT_IMM) { if (src & SLJIT_MEM) { ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); @@ -2572,11 +2773,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi FAIL_IF(push_inst(compiler, JALR | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RS1(TMP_REG1) | IMM_I(0))); /* Maximum number of instructions required for generating a constant. */ -#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) - compiler->size += 1; -#else - compiler->size += 5; -#endif + compiler->size += JUMP_MAX_SIZE - 1; return SLJIT_SUCCESS; } @@ -2695,16 +2892,110 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, src_r, 0); } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, - sljit_s32 src, sljit_sw srcw) + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_reg) { + sljit_ins *ptr; + sljit_uw size; +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + sljit_ins word = (sljit_ins)(type & SLJIT_32) >> 5; + sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA; +#else /* !SLJIT_CONFIG_RISCV_64 */ + sljit_s32 inp_flags = WORD_DATA | LOAD_DATA; +#endif /* SLJIT_CONFIG_RISCV_64 */ + + SLJIT_ASSERT(WORD == 0 || WORD == 0x8); + CHECK_ERROR(); - CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); + CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg)); - return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);; + ADJUST_LOCAL_OFFSET(src1, src1w); + + if (dst_reg != src2_reg) { + if (dst_reg == src1) { + src1 = src2_reg; + src1w = 0; + type ^= 0x1; + } else { + if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) { + FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(dst_reg) | IMM_I(0))); + + if ((src1 & REG_MASK) == dst_reg) + src1 = (src1 & ~REG_MASK) | TMP_REG2; + + if (OFFS_REG(src1) == dst_reg) + src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG2); + } + + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst_reg) | RS1(src2_reg) | IMM_I(0))); + } + } + + size = compiler->size; + + ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); + FAIL_IF(!ptr); + compiler->size++; + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w)); + } else if (src1 == SLJIT_IMM) { +#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) + if (word) + src1w = (sljit_s32)src1w; +#endif /* SLJIT_CONFIG_RISCV_64 */ + FAIL_IF(load_immediate(compiler, dst_reg, src1w, TMP_REG1)); + } else + FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst_reg) | RS1(src1) | IMM_I(0))); + + *ptr = get_jump_instruction(type & ~SLJIT_32) | (sljit_ins)((compiler->size - size) << 9); + return SLJIT_SUCCESS; } +#undef WORD + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_freg) +{ + sljit_ins *ptr; + sljit_uw size; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg)); + + ADJUST_LOCAL_OFFSET(src1, src1w); + + if (dst_freg != src2_freg) { + if (dst_freg == src1) { + src1 = src2_freg; + src1w = 0; + type ^= 0x1; + } else + FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(type) | FRD(dst_freg) | FRS1(src2_freg) | FRS2(src2_freg))); + } + + size = compiler->size; + + ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); + FAIL_IF(!ptr); + compiler->size++; + + if (src1 & SLJIT_MEM) + FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, dst_freg, src1, src1w)); + else + FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(type) | FRD(dst_freg) | FRS1(src1) | FRS2(src1))); + + *ptr = get_jump_instruction(type & ~SLJIT_32) | (sljit_ins)((compiler->size - size) << 9); + return SLJIT_SUCCESS; +} + +#undef FLOAT_DATA +#undef FMT + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) @@ -2783,31 +3074,31 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi return const_; } -SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { - struct sljit_put_label *put_label; + struct sljit_jump *jump; sljit_s32 dst_r; CHECK_ERROR_PTR(); - CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw)); + CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); - put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label)); - PTR_FAIL_IF(!put_label); - set_put_label(put_label, compiler, 0); + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_mov_addr(jump, compiler, 0); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r)); #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) compiler->size += 1; -#else +#else /* !SLJIT_CONFIG_RISCV_32 */ compiler->size += 5; -#endif +#endif /* SLJIT_CONFIG_RISCV_32 */ if (dst & SLJIT_MEM) PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw)); - return put_label; + return jump; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeS390X.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeS390X.c index 8d86d072b13..0a7df4a6844 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeS390X.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeS390X.c @@ -38,17 +38,14 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) return "s390x" SLJIT_CPUINFO; } -/* Instructions. */ +/* Instructions are stored as 64 bit values regardless their size. */ typedef sljit_uw sljit_ins; -/* Instruction tags (most significant halfword). */ -static const sljit_ins sljit_ins_const = (sljit_ins)1 << 48; - #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) -static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = { - 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 0, 1 +static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = { + 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 0, 1, 14 }; /* there are also a[2-15] available, but they are slower to access and @@ -83,7 +80,7 @@ static const sljit_gpr r10 = 10; /* reg_map[9] */ static const sljit_gpr r11 = 11; /* reg_map[10] */ static const sljit_gpr r12 = 12; /* reg_map[11]: GOT */ static const sljit_gpr r13 = 13; /* reg_map[12]: Literal Pool pointer */ -static const sljit_gpr r14 = 14; /* reg_map[0]: return address and flag register */ +static const sljit_gpr r14 = 14; /* reg_map[0]: return address */ static const sljit_gpr r15 = 15; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 1]: stack pointer */ /* WARNING: r12 and r13 shouldn't be used as per ABI recommendation */ @@ -96,20 +93,16 @@ static const sljit_gpr r15 = 15; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 1]: stac #define tmp0 r0 #define tmp1 r1 -/* TODO(carenas): flags should move to a different register so that - * link register doesn't need to change - */ - /* When reg cannot be unused. */ #define IS_GPR_REG(reg) ((reg > 0) && (reg) <= SLJIT_SP) /* Link register. */ static const sljit_gpr link_r = 14; /* r14 */ -#define TMP_FREG1 (0) +#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) -static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { - 1, 0, 2, 4, 6, 3, 5, 7, 15, 14, 13, 12, 11, 10, 9, 8, +static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2] = { + 0, 0, 2, 4, 6, 3, 5, 7, 15, 14, 13, 12, 11, 10, 9, 8, 1 }; #define R0A(r) (r) @@ -126,7 +119,10 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define F0(r) ((sljit_ins)freg_map[r]) #define F4(r) (R4A((sljit_ins)freg_map[r])) +#define F12(r) (R12A((sljit_ins)freg_map[r])) #define F20(r) (R20A((sljit_ins)freg_map[r])) +#define F28(r) (R28A((sljit_ins)freg_map[r])) +#define F32(r) (R32A((sljit_ins)freg_map[r])) #define F36(r) (R36A((sljit_ins)freg_map[r])) struct sljit_s390x_const { @@ -141,50 +137,21 @@ static SLJIT_INLINE sljit_gpr gpr(sljit_s32 r) return reg_map[r]; } -/* Size of instruction in bytes. Tags must already be cleared. */ -static SLJIT_INLINE sljit_uw sizeof_ins(sljit_ins ins) -{ - /* keep faulting instructions */ - if (ins == 0) - return 2; - - if ((ins & 0x00000000ffffL) == ins) - return 2; - if ((ins & 0x0000ffffffffL) == ins) - return 4; - if ((ins & 0xffffffffffffL) == ins) - return 6; - - SLJIT_UNREACHABLE(); - return (sljit_uw)-1; -} - static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins) { sljit_ins *ibuf = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!ibuf); *ibuf = ins; + + SLJIT_ASSERT(ins <= 0xffffffffffffL); + compiler->size++; - return SLJIT_SUCCESS; -} + if (ins & 0xffff00000000L) + compiler->size++; -static sljit_s32 encode_inst(void **ptr, sljit_ins ins) -{ - sljit_u16 *ibuf = (sljit_u16 *)*ptr; - sljit_uw size = sizeof_ins(ins); + if (ins & 0xffffffff0000L) + compiler->size++; - SLJIT_ASSERT((size & 6) == size); - switch (size) { - case 6: - *ibuf++ = (sljit_u16)(ins >> 32); - /* fallthrough */ - case 4: - *ibuf++ = (sljit_u16)(ins >> 16); - /* fallthrough */ - case 2: - *ibuf++ = (sljit_u16)(ins); - } - *ptr = (void*)ibuf; return SLJIT_SUCCESS; } @@ -211,6 +178,7 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t } /* fallthrough */ + case SLJIT_ATOMIC_STORED: case SLJIT_F_EQUAL: case SLJIT_ORDERED_EQUAL: return cc0; @@ -230,6 +198,7 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t return (cc1 | cc2 | cc3); case SLJIT_LESS: + case SLJIT_ATOMIC_NOT_STORED: return cc1; case SLJIT_GREATER_EQUAL: @@ -448,10 +417,12 @@ HAVE_FACILITY(have_misc2, MISCELLANEOUS_INSTRUCTION_EXTENSIONS_2_FACILITY) static SLJIT_INLINE sljit_ins disp_s20(sljit_s32 d) { + sljit_uw dh, dl; + SLJIT_ASSERT(is_s20(d)); - sljit_uw dh = (d >> 12) & 0xff; - sljit_uw dl = (d << 8) & 0xfff00; + dh = (d >> 12) & 0xff; + dl = ((sljit_uw)d << 8) & 0xfff00; return (dh | dl) << 8; } @@ -893,23 +864,17 @@ static sljit_s32 push_load_imm_inst(struct sljit_compiler *compiler, sljit_gpr t if (((sljit_uw)v & ~(sljit_uw)0xffff000000000000) == 0) return push_inst(compiler, llihh(target, (sljit_u16)(v >> 48))); - /* 6 byte instructions (requires extended immediate facility) */ - if (have_eimm()) { - if (is_s32(v)) - return push_inst(compiler, lgfi(target, (sljit_s32)v)); + if (is_s32(v)) + return push_inst(compiler, lgfi(target, (sljit_s32)v)); - if (((sljit_uw)v >> 32) == 0) - return push_inst(compiler, llilf(target, (sljit_u32)v)); + if (((sljit_uw)v >> 32) == 0) + return push_inst(compiler, llilf(target, (sljit_u32)v)); - if (((sljit_uw)v << 32) == 0) - return push_inst(compiler, llihf(target, (sljit_u32)((sljit_uw)v >> 32))); - - FAIL_IF(push_inst(compiler, llilf(target, (sljit_u32)v))); - return push_inst(compiler, iihf(target, (sljit_u32)(v >> 32))); - } + if (((sljit_uw)v << 32) == 0) + return push_inst(compiler, llihf(target, (sljit_u32)((sljit_uw)v >> 32))); - /* TODO(mundaym): instruction sequences that don't use extended immediates */ - abort(); + FAIL_IF(push_inst(compiler, llilf(target, (sljit_u32)v))); + return push_inst(compiler, iihf(target, (sljit_u32)(v >> 32))); } struct addr { @@ -989,24 +954,47 @@ static sljit_s32 make_addr_bx(struct sljit_compiler *compiler, (cond) ? EVAL(i1, r, addr) : EVAL(i2, r, addr) /* May clobber tmp1. */ -static sljit_s32 load_word(struct sljit_compiler *compiler, sljit_gpr dst_r, - sljit_s32 src, sljit_sw srcw, - sljit_s32 is_32bit) +static sljit_s32 load_store_op(struct sljit_compiler *compiler, sljit_gpr reg, + sljit_s32 mem, sljit_sw memw, + sljit_s32 is_32bit, const sljit_ins* forms) { struct addr addr; - sljit_ins ins; - SLJIT_ASSERT(src & SLJIT_MEM); + SLJIT_ASSERT(mem & SLJIT_MEM); - if (is_32bit && ((src & OFFS_REG_MASK) || is_u12(srcw) || !is_s20(srcw))) { - FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp1)); - return push_inst(compiler, 0x58000000 /* l */ | R20A(dst_r) | R16A(addr.index) | R12A(addr.base) | (sljit_ins)addr.offset); + if (is_32bit && ((mem & OFFS_REG_MASK) || is_u12(memw) || !is_s20(memw))) { + FAIL_IF(make_addr_bx(compiler, &addr, mem, memw, tmp1)); + return push_inst(compiler, forms[0] | R20A(reg) | R16A(addr.index) | R12A(addr.base) | (sljit_ins)addr.offset); } - FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1)); + FAIL_IF(make_addr_bxy(compiler, &addr, mem, memw, tmp1)); + return push_inst(compiler, (is_32bit ? forms[1] : forms[2]) | R36A(reg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)); +} - ins = is_32bit ? 0xe30000000058 /* ly */ : 0xe30000000004 /* lg */; - return push_inst(compiler, ins | R36A(dst_r) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)); +static const sljit_ins load_forms[3] = { + 0x58000000 /* l */, + 0xe30000000058 /* ly */, + 0xe30000000004 /* lg */ +}; + +static const sljit_ins store_forms[3] = { + 0x50000000 /* st */, + 0xe30000000050 /* sty */, + 0xe30000000024 /* stg */ +}; + +static const sljit_ins load_halfword_forms[3] = { + 0x48000000 /* lh */, + 0xe30000000078 /* lhy */, + 0xe30000000015 /* lgh */ +}; + +/* May clobber tmp1. */ +static SLJIT_INLINE sljit_s32 load_word(struct sljit_compiler *compiler, sljit_gpr dst_r, + sljit_s32 src, sljit_sw srcw, + sljit_s32 is_32bit) +{ + return load_store_op(compiler, dst_r, src, srcw, is_32bit, load_forms); } /* May clobber tmp1. */ @@ -1026,24 +1014,11 @@ static sljit_s32 load_unsigned_word(struct sljit_compiler *compiler, sljit_gpr d } /* May clobber tmp1. */ -static sljit_s32 store_word(struct sljit_compiler *compiler, sljit_gpr src_r, +static SLJIT_INLINE sljit_s32 store_word(struct sljit_compiler *compiler, sljit_gpr src_r, sljit_s32 dst, sljit_sw dstw, sljit_s32 is_32bit) { - struct addr addr; - sljit_ins ins; - - SLJIT_ASSERT(dst & SLJIT_MEM); - - if (is_32bit && ((dst & OFFS_REG_MASK) || is_u12(dstw) || !is_s20(dstw))) { - FAIL_IF(make_addr_bx(compiler, &addr, dst, dstw, tmp1)); - return push_inst(compiler, 0x50000000 /* st */ | R20A(src_r) | R16A(addr.index) | R12A(addr.base) | (sljit_ins)addr.offset); - } - - FAIL_IF(make_addr_bxy(compiler, &addr, dst, dstw, tmp1)); - - ins = is_32bit ? 0xe30000000050 /* sty */ : 0xe30000000024 /* stg */; - return push_inst(compiler, ins | R36A(src_r) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)); + return load_store_op(compiler, src_r, dst, dstw, is_32bit, store_forms); } #undef WHEN @@ -1052,15 +1027,17 @@ static sljit_s32 emit_move(struct sljit_compiler *compiler, sljit_gpr dst_r, sljit_s32 src, sljit_sw srcw) { + sljit_gpr src_r; + SLJIT_ASSERT(!IS_GPR_REG(src) || dst_r != gpr(src & REG_MASK)); - if (src & SLJIT_IMM) + if (src == SLJIT_IMM) return push_load_imm_inst(compiler, dst_r, srcw); if (src & SLJIT_MEM) return load_word(compiler, dst_r, src, srcw, (compiler->mode & SLJIT_32) != 0); - sljit_gpr src_r = gpr(src & REG_MASK); + src_r = gpr(src & REG_MASK); return push_inst(compiler, (compiler->mode & SLJIT_32) ? lr(dst_r, src_r) : lgr(dst_r, src_r)); } @@ -1253,10 +1230,10 @@ static sljit_s32 emit_siy(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 dst, sljit_sw dstw, sljit_sw srcw) { - SLJIT_ASSERT(dst & SLJIT_MEM); - sljit_gpr dst_r = tmp1; + SLJIT_ASSERT(dst & SLJIT_MEM); + if (dst & OFFS_REG_MASK) { sljit_gpr index = tmp1; @@ -1419,90 +1396,54 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil { struct sljit_label *label; struct sljit_jump *jump; - struct sljit_s390x_const *const_; - struct sljit_put_label *put_label; + struct sljit_const *const_; sljit_sw executable_offset; - sljit_uw ins_size = 0; /* instructions */ + sljit_uw ins_size = compiler->size << 1; sljit_uw pool_size = 0; /* literal pool */ sljit_uw pad_size; - sljit_uw i, j = 0; + sljit_uw half_count; + SLJIT_NEXT_DEFINE_TYPES; struct sljit_memory_fragment *buf; - void *code, *code_ptr; + sljit_ins *buf_ptr; + sljit_ins *buf_end; + sljit_u16 *code; + sljit_u16 *code_ptr; sljit_uw *pool, *pool_ptr; - sljit_sw source, offset; /* TODO(carenas): only need 32 bit */ + sljit_ins ins; + sljit_sw source, offset; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_generate_code(compiler)); reverse_buf(compiler); - /* branch handling */ - label = compiler->labels; jump = compiler->jumps; - put_label = compiler->put_labels; - - /* TODO(carenas): compiler->executable_size could be calculated - * before to avoid the following loop (except for - * pool_size) - */ - /* calculate the size of the code */ - for (buf = compiler->buf; buf != NULL; buf = buf->next) { - sljit_uw len = buf->used_size / sizeof(sljit_ins); - sljit_ins *ibuf = (sljit_ins *)buf->memory; - for (i = 0; i < len; ++i, ++j) { - sljit_ins ins = ibuf[i]; - - /* TODO(carenas): instruction tag vs size/addr == j - * using instruction tags for const is creative - * but unlike all other architectures, and is not - * done consistently for all other objects. - * This might need reviewing later. - */ - if (ins & sljit_ins_const) { - pool_size += sizeof(*pool); - ins &= ~sljit_ins_const; - } - if (label && label->size == j) { - label->size = ins_size; - label = label->next; - } - if (jump && jump->addr == j) { - if ((jump->flags & SLJIT_REWRITABLE_JUMP) || (jump->flags & JUMP_ADDR)) { - /* encoded: */ - /* brasl %r14, (or brcl , ) */ - /* replace with: */ - /* lgrl %r1, */ - /* bras %r14, %r1 (or bcr , %r1) */ - pool_size += sizeof(*pool); - ins_size += 2; - } - jump = jump->next; - } - if (put_label && put_label->addr == j) { - pool_size += sizeof(*pool); - put_label = put_label->next; - } - ins_size += sizeof_ins(ins); + while (jump != NULL) { + if (jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR | JUMP_MOV_ADDR)) { + /* encoded: */ + /* brasl %r14, (or brcl , ) */ + /* replace with: */ + /* lgrl %r1, */ + /* bras %r14, %r1 (or bcr , %r1) */ + pool_size += sizeof(*pool); + if (!(jump->flags & JUMP_MOV_ADDR)) + ins_size += 2; } + jump = jump->next; } - /* emit trailing label */ - if (label && label->size == j) { - label->size = ins_size; - label = label->next; + const_ = compiler->consts; + while (const_) { + pool_size += sizeof(*pool); + const_ = const_->next; } - SLJIT_ASSERT(!label); - SLJIT_ASSERT(!jump); - SLJIT_ASSERT(!put_label); - /* pad code size to 8 bytes so is accessible with half word offsets */ /* the literal pool needs to be doubleword aligned */ pad_size = ((ins_size + 7UL) & ~7UL) - ins_size; SLJIT_ASSERT(pad_size < 8UL); /* allocate target buffer */ - code = SLJIT_MALLOC_EXEC(ins_size + pad_size + pool_size, - compiler->exec_allocator_data); + code = SLJIT_MALLOC_EXEC(ins_size + pad_size + pool_size, compiler->exec_allocator_data); PTR_FAIL_WITH_EXEC_IF(code); code_ptr = code; executable_offset = SLJIT_EXEC_OFFSET(code); @@ -1514,126 +1455,158 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil */ pool = (sljit_uw *)((sljit_uw)code + ins_size + pad_size); pool_ptr = pool; - const_ = (struct sljit_s390x_const *)compiler->consts; + buf = compiler->buf; + half_count = 0; - /* update label addresses */ label = compiler->labels; - while (label) { - label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET( - (sljit_uw)code_ptr + label->size, executable_offset); - label = label->next; - } - - /* reset jumps */ jump = compiler->jumps; - put_label = compiler->put_labels; + const_ = compiler->consts; + SLJIT_NEXT_INIT_TYPES(); + SLJIT_GET_NEXT_MIN(); - /* emit the code */ - j = 0; - for (buf = compiler->buf; buf != NULL; buf = buf->next) { - sljit_uw len = buf->used_size / sizeof(sljit_ins); - sljit_ins *ibuf = (sljit_ins *)buf->memory; - for (i = 0; i < len; ++i, ++j) { - sljit_ins ins = ibuf[i]; - if (ins & sljit_ins_const) { - /* clear the const tag */ - ins &= ~sljit_ins_const; + do { + buf_ptr = (sljit_ins*)buf->memory; + buf_end = buf_ptr + (buf->used_size >> 3); + do { + ins = *buf_ptr++; + + if (next_min_addr == half_count) { + SLJIT_ASSERT(!label || label->size >= half_count); + SLJIT_ASSERT(!jump || jump->addr >= half_count); + SLJIT_ASSERT(!const_ || const_->addr >= half_count); + + if (next_min_addr == next_label_size) { + label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + label = label->next; + next_label_size = SLJIT_GET_NEXT_SIZE(label); + } - /* update instruction with relative address of constant */ - source = (sljit_sw)code_ptr; - offset = (sljit_sw)pool_ptr - source; + if (next_min_addr == next_jump_addr) { + if (SLJIT_UNLIKELY(jump->flags & JUMP_MOV_ADDR)) { + source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + + jump->addr = (sljit_uw)pool_ptr; + + /* store target into pool */ + offset = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source; + pool_ptr++; + + SLJIT_ASSERT(!(offset & 1)); + offset >>= 1; + SLJIT_ASSERT(is_s32(offset)); + ins |= (sljit_ins)offset & 0xffffffff; + } else if (jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR)) { + sljit_ins arg; + + jump->addr = (sljit_uw)pool_ptr; + + /* load address into tmp1 */ + source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + offset = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source; + + SLJIT_ASSERT(!(offset & 1)); + offset >>= 1; + SLJIT_ASSERT(is_s32(offset)); + + code_ptr[0] = (sljit_u16)(0xc408 | R4A(tmp1) /* lgrl */); + code_ptr[1] = (sljit_u16)(offset >> 16); + code_ptr[2] = (sljit_u16)offset; + code_ptr += 3; + pool_ptr++; + + /* branch to tmp1 */ + arg = (ins >> 36) & 0xf; + if (((ins >> 32) & 0xf) == 4) { + /* brcl -> bcr */ + ins = bcr(arg, tmp1); + } else { + SLJIT_ASSERT(((ins >> 32) & 0xf) == 5); + /* brasl -> basr */ + ins = basr(arg, tmp1); + } + + /* Adjust half_count. */ + half_count += 2; + } else + jump->addr = (sljit_uw)code_ptr; + + jump = jump->next; + next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); + } else if (next_min_addr == next_const_addr) { + /* update instruction with relative address of constant */ + source = (sljit_sw)code_ptr; + offset = (sljit_sw)pool_ptr - source; + + SLJIT_ASSERT(!(offset & 0x1)); + offset >>= 1; /* halfword (not byte) offset */ + SLJIT_ASSERT(is_s32(offset)); - SLJIT_ASSERT(!(offset & 1)); - offset >>= 1; /* halfword (not byte) offset */ - SLJIT_ASSERT(is_s32(offset)); + ins |= (sljit_ins)offset & 0xffffffff; - ins |= (sljit_ins)offset & 0xffffffff; + /* update address */ + const_->addr = (sljit_uw)pool_ptr; - /* update address */ - const_->const_.addr = (sljit_uw)pool_ptr; + /* store initial value into pool and update pool address */ + *(pool_ptr++) = (sljit_uw)(((struct sljit_s390x_const*)const_)->init_value); - /* store initial value into pool and update pool address */ - *(pool_ptr++) = (sljit_uw)const_->init_value; + /* move to next constant */ + const_ = const_->next; + next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_); + } - /* move to next constant */ - const_ = (struct sljit_s390x_const *)const_->const_.next; + SLJIT_GET_NEXT_MIN(); } - if (jump && jump->addr == j) { - sljit_sw target = (sljit_sw)((jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target); - if ((jump->flags & SLJIT_REWRITABLE_JUMP) || (jump->flags & JUMP_ADDR)) { - jump->addr = (sljit_uw)pool_ptr; - /* load address into tmp1 */ - source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); - offset = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source; + if (ins & 0xffff00000000L) { + *code_ptr++ = (sljit_u16)(ins >> 32); + half_count++; + } - SLJIT_ASSERT(!(offset & 1)); - offset >>= 1; - SLJIT_ASSERT(is_s32(offset)); + if (ins & 0xffffffff0000L) { + *code_ptr++ = (sljit_u16)(ins >> 16); + half_count++; + } - encode_inst(&code_ptr, lgrl(tmp1, offset & 0xffffffff)); - - /* store jump target into pool and update pool address */ - *(pool_ptr++) = (sljit_uw)target; - - /* branch to tmp1 */ - sljit_ins op = (ins >> 32) & 0xf; - sljit_ins arg = (ins >> 36) & 0xf; - switch (op) { - case 4: /* brcl -> bcr */ - ins = bcr(arg, tmp1); - break; - case 5: /* brasl -> basr */ - ins = basr(arg, tmp1); - break; - default: - abort(); - } - } - else { - jump->addr = (sljit_uw)code_ptr + 2; - source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); - offset = target - source; + *code_ptr++ = (sljit_u16)ins; + half_count++; + } while (buf_ptr < buf_end); - /* offset must be halfword aligned */ - SLJIT_ASSERT(!(offset & 1)); - offset >>= 1; - SLJIT_ASSERT(is_s32(offset)); /* TODO(mundaym): handle arbitrary offsets */ + buf = buf->next; + } while (buf); - /* patch jump target */ - ins |= (sljit_ins)offset & 0xffffffff; - } - jump = jump->next; - } - if (put_label && put_label->addr == j) { - source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + SLJIT_ASSERT(code + (ins_size >> 1) == code_ptr); + SLJIT_ASSERT((sljit_u8 *)pool + pool_size == (sljit_u8 *)pool_ptr); - SLJIT_ASSERT(put_label->label); - put_label->addr = (sljit_uw)code_ptr; + jump = compiler->jumps; + while (jump != NULL) { + offset = (sljit_sw)((jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr); - /* store target into pool */ - *pool_ptr = put_label->label->addr; - offset = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source; - pool_ptr++; + if (jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR | JUMP_MOV_ADDR)) { + /* Store jump target into pool. */ + *(sljit_uw*)(jump->addr) = (sljit_uw)offset; + } else { + code_ptr = (sljit_u16*)jump->addr; + offset -= (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); - SLJIT_ASSERT(!(offset & 1)); - offset >>= 1; - SLJIT_ASSERT(is_s32(offset)); - ins |= (sljit_ins)offset & 0xffffffff; + /* offset must be halfword aligned */ + SLJIT_ASSERT(!(offset & 1)); + offset >>= 1; + SLJIT_ASSERT(is_s32(offset)); /* TODO(mundaym): handle arbitrary offsets */ - put_label = put_label->next; - } - encode_inst(&code_ptr, ins); + code_ptr[1] = (sljit_u16)(offset >> 16); + code_ptr[2] = (sljit_u16)offset; } + jump = jump->next; } - SLJIT_ASSERT((sljit_u8 *)code + ins_size == code_ptr); - SLJIT_ASSERT((sljit_u8 *)pool + pool_size == (sljit_u8 *)pool_ptr); compiler->error = SLJIT_ERR_COMPILED; compiler->executable_offset = executable_offset; compiler->executable_size = ins_size; - code = SLJIT_ADD_EXEC_OFFSET(code, executable_offset); - code_ptr = SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + if (pool_size) + compiler->executable_size += (pad_size + pool_size); + + code = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset); + code_ptr = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); SLJIT_CACHE_FLUSH(code, code_ptr); SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1); return code; @@ -1644,15 +1617,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) /* TODO(mundaym): implement all */ switch (feature_type) { case SLJIT_HAS_FPU: +#ifdef SLJIT_IS_FPU_AVAILABLE + return (SLJIT_IS_FPU_AVAILABLE) != 0; +#else + return 1; +#endif /* SLJIT_IS_FPU_AVAILABLE */ + case SLJIT_HAS_CLZ: case SLJIT_HAS_REV: case SLJIT_HAS_ROT: case SLJIT_HAS_PREFETCH: case SLJIT_HAS_COPY_F32: case SLJIT_HAS_COPY_F64: + case SLJIT_HAS_SIMD: + case SLJIT_HAS_ATOMIC: return 1; + case SLJIT_HAS_CTZ: return 2; + case SLJIT_HAS_CMOV: return have_lscond1() ? 1 : 0; } @@ -1661,7 +1644,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) { - return (type >= SLJIT_UNORDERED && type <= SLJIT_ORDERED_LESS_EQUAL); + SLJIT_UNUSED_ARG(type); + return 0; } /* --------------------------------------------------------------------- */ @@ -1738,7 +1722,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi local_size = (local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE + 0xf) & ~0xf; compiler->local_size = local_size; - FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(-local_size))); + if (is_s20(-local_size)) + FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(-local_size))); + else + FAIL_IF(push_inst(compiler, 0xc20400000000 /* slgfi */ | R36A(r15) | (sljit_ins)local_size)); if (options & SLJIT_ENTER_REG_ARG) return SLJIT_SUCCESS; @@ -1783,8 +1770,10 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit if (is_u12(local_size)) FAIL_IF(push_inst(compiler, 0x41000000 /* ly */ | R20A(r15) | R12A(r15) | (sljit_ins)local_size)); - else + else if (is_s20(local_size)) FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(local_size))); + else + FAIL_IF(push_inst(compiler, 0xc20a00000000 /* algfi */ | R36A(r15) | (sljit_ins)local_size)); offset = 2 * SSIZE_OF(sw); if (saveds + scratches >= SLJIT_NUMBER_OF_REGISTERS) { @@ -2015,16 +2004,23 @@ static sljit_s32 sljit_emit_rev(struct sljit_compiler *compiler, sljit_s32 op, struct addr addr; sljit_gpr reg; sljit_ins ins; + sljit_s32 opcode = GET_OPCODE(op); + sljit_s32 is_16bit = (opcode == SLJIT_REV_U16 || opcode == SLJIT_REV_S16); if (dst & SLJIT_MEM) { if (src & SLJIT_MEM) { - FAIL_IF(load_word(compiler, tmp0, src, srcw, op & SLJIT_32)); + FAIL_IF(load_store_op(compiler, tmp0, src, srcw, op & SLJIT_32, is_16bit ? load_halfword_forms : load_forms)); reg = tmp0; } else reg = gpr(src); FAIL_IF(make_addr_bxy(compiler, &addr, dst, dstw, tmp1)); - ins = (op & SLJIT_32) ? 0xe3000000003e /* strv */ : 0xe3000000002f /* strvg */; + + if (is_16bit) + ins = 0xe3000000003f /* strvh */; + else + ins = (op & SLJIT_32) ? 0xe3000000003e /* strv */ : 0xe3000000002f /* strvg */; + return push_inst(compiler, ins | R36A(reg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)); } @@ -2032,12 +2028,46 @@ static sljit_s32 sljit_emit_rev(struct sljit_compiler *compiler, sljit_s32 op, if (src & SLJIT_MEM) { FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1)); - ins = (op & SLJIT_32) ? 0xe3000000001e /* lrv */ : 0xe3000000000f /* lrvg */; - return push_inst(compiler, ins | R36A(reg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)); + + if (is_16bit) + ins = 0xe3000000001f /* lrvh */; + else + ins = (op & SLJIT_32) ? 0xe3000000001e /* lrv */ : 0xe3000000000f /* lrvg */; + + FAIL_IF(push_inst(compiler, ins | R36A(reg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset))); + + if (opcode == SLJIT_REV) + return SLJIT_SUCCESS; + + if (is_16bit) { + if (op & SLJIT_32) + ins = (opcode == SLJIT_REV_U16) ? 0xb9950000 /* llhr */ : 0xb9270000 /* lhr */; + else + ins = (opcode == SLJIT_REV_U16) ? 0xb9850000 /* llghr */ : 0xb9070000 /* lghr */; + } else + ins = (opcode == SLJIT_REV_U32) ? 0xb9160000 /* llgfr */ : 0xb9140000 /* lgfr */; + + return push_inst(compiler, ins | R4A(reg) | R0A(reg)); } ins = (op & SLJIT_32) ? 0xb91f0000 /* lrvr */ : 0xb90f0000 /* lrvgr */; - return push_inst(compiler, ins | R4A(reg) | R0A(gpr(src))); + FAIL_IF(push_inst(compiler, ins | R4A(reg) | R0A(gpr(src)))); + + if (opcode == SLJIT_REV) + return SLJIT_SUCCESS; + + if (!is_16bit) { + ins = (opcode == SLJIT_REV_U32) ? 0xb9160000 /* llgfr */ : 0xb9140000 /* lgfr */; + return push_inst(compiler, ins | R4A(reg) | R0A(reg)); + } + + if (op & SLJIT_32) { + ins = (opcode == SLJIT_REV_U16) ? 0x88000000 /* srl */ : 0x8a000000 /* sra */; + return push_inst(compiler, ins | R20A(reg) | 16); + } + + ins = (opcode == SLJIT_REV_U16) ? 0xeb000000000c /* srlg */ : 0xeb000000000a /* srag */; + return push_inst(compiler, ins | R36A(reg) | R32A(reg) | (48 << 16)); } /* LEVAL will be defined later with different parameters as needed */ @@ -2116,7 +2146,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile return SLJIT_SUCCESS; } /* LOAD IMMEDIATE */ - if (FAST_IS_REG(dst) && (src & SLJIT_IMM)) { + if (FAST_IS_REG(dst) && src == SLJIT_IMM) { switch (opcode) { case SLJIT_MOV_U8: srcw = (sljit_sw)((sljit_u8)(srcw)); @@ -2195,14 +2225,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile return SLJIT_SUCCESS; } /* STORE and STORE IMMEDIATE */ - if ((dst & SLJIT_MEM) - && (FAST_IS_REG(src) || (src & SLJIT_IMM))) { + if ((dst & SLJIT_MEM) && (FAST_IS_REG(src) || src == SLJIT_IMM)) { + struct addr mem; sljit_gpr reg = FAST_IS_REG(src) ? gpr(src) : tmp0; - if (src & SLJIT_IMM) { + + if (src == SLJIT_IMM) { /* TODO(mundaym): MOVE IMMEDIATE? */ FAIL_IF(push_load_imm_inst(compiler, reg, srcw)); } - struct addr mem; FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1)); switch (opcode) { case SLJIT_MOV_U8: @@ -2269,7 +2299,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile SLJIT_UNREACHABLE(); } - SLJIT_ASSERT((src & SLJIT_IMM) == 0); /* no immediates */ + SLJIT_ASSERT(src != SLJIT_IMM); dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0; src_r = FAST_IS_REG(src) ? gpr(src) : tmp0; @@ -2285,7 +2315,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile FAIL_IF(sljit_emit_clz_ctz(compiler, op, dst_r, src_r)); break; + case SLJIT_REV_U32: + case SLJIT_REV_S32: + op |= SLJIT_32; + /* fallthrough */ case SLJIT_REV: + case SLJIT_REV_U16: + case SLJIT_REV_S16: return sljit_emit_rev(compiler, op, dst, dstw, src, srcw); default: SLJIT_UNREACHABLE(); @@ -2341,7 +2377,7 @@ static sljit_s32 sljit_emit_add(struct sljit_compiler *compiler, sljit_s32 op, const struct ins_forms *forms; sljit_ins ins; - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { if (!sets_zero_overflow && is_s8(src2w) && (src1 & SLJIT_MEM) && (dst == src1 && dstw == src1w)) { if (sets_overflow) ins = (op & SLJIT_32) ? 0xeb000000006a /* asi */ : 0xeb000000007a /* agsi */; @@ -2426,9 +2462,8 @@ static sljit_s32 sljit_emit_sub(struct sljit_compiler *compiler, sljit_s32 op, compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_COMPARE; - if (src2 & SLJIT_IMM) { - if (compare_signed || ((op & VARIABLE_FLAG_MASK) == 0 && is_s32(src2w))) - { + if (src2 == SLJIT_IMM) { + if (compare_signed || ((op & VARIABLE_FLAG_MASK) == 0 && is_s32(src2w))) { if ((op & SLJIT_32) || is_s32(src2w)) { ins = (op & SLJIT_32) ? 0xc20d00000000 /* cfi */ : 0xc20c00000000 /* cgfi */; return emit_ri(compiler, ins, src1, src1, src1w, src2w, RIL_A); @@ -2469,7 +2504,7 @@ static sljit_s32 sljit_emit_sub(struct sljit_compiler *compiler, sljit_s32 op, goto done; } - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { sljit_sw neg_src2w = -src2w; if (sets_signed || neg_src2w != 0 || (op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == 0) { @@ -2577,7 +2612,7 @@ static sljit_s32 sljit_emit_multiply(struct sljit_compiler *compiler, sljit_s32 return emit_commutative(compiler, &multiply_overflow_forms, dst, src1, src1w, src2, src2w); } - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { if (is_s16(src2w)) { ins = (op & SLJIT_32) ? 0xa70c0000 /* mhi */ : 0xa70d0000 /* mghi */; return emit_ri(compiler, ins, dst, src1, src1w, src2w, RI_A); @@ -2684,7 +2719,7 @@ static sljit_s32 sljit_emit_bitwise(struct sljit_compiler *compiler, sljit_s32 o sljit_s32 type = GET_OPCODE(op); const struct ins_forms *forms; - if ((src2 & SLJIT_IMM) && (!(op & SLJIT_SET_Z) || (type == SLJIT_AND && dst == (sljit_s32)tmp0))) { + if (src2 == SLJIT_IMM && (!(op & SLJIT_SET_Z) || (type == SLJIT_AND && dst == (sljit_s32)tmp0))) { sljit_s32 count16 = 0; sljit_uw imm = (sljit_uw)src2w; @@ -2748,7 +2783,7 @@ static sljit_s32 sljit_emit_shift(struct sljit_compiler *compiler, sljit_s32 op, else FAIL_IF(emit_move(compiler, tmp0, src1, src1w)); - if (!(src2 & SLJIT_IMM)) { + if (src2 != SLJIT_IMM) { if (FAST_IS_REG(src2)) base_r = gpr(src2); else { @@ -2808,7 +2843,7 @@ static sljit_s32 sljit_emit_rotate(struct sljit_compiler *compiler, sljit_s32 op else FAIL_IF(emit_move(compiler, tmp0, src1, src1w)); - if (!(src2 & SLJIT_IMM)) { + if (src2 != SLJIT_IMM) { if (FAST_IS_REG(src2)) base_r = gpr(src2); else { @@ -2818,7 +2853,7 @@ static sljit_s32 sljit_emit_rotate(struct sljit_compiler *compiler, sljit_s32 op } if (GET_OPCODE(op) == SLJIT_ROTR) { - if (!(src2 & SLJIT_IMM)) { + if (src2 != SLJIT_IMM) { ins = (op & SLJIT_32) ? 0x1300 /* lcr */ : 0xb9030000 /* lcgr */; FAIL_IF(push_inst(compiler, ins | R4A(tmp1) | R0A(base_r))); base_r = tmp1; @@ -2826,7 +2861,7 @@ static sljit_s32 sljit_emit_rotate(struct sljit_compiler *compiler, sljit_s32 op src2w = -src2w; } - if (src2 & SLJIT_IMM) + if (src2 == SLJIT_IMM) imm = (sljit_ins)(src2w & ((op & SLJIT_32) ? 0x1f : 0x3f)); ins = (op & SLJIT_32) ? 0xeb000000001d /* rll */ : 0xeb000000001c /* rllg */; @@ -2867,7 +2902,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile compiler->mode = op & SLJIT_32; compiler->status_flags_state = op & (VARIABLE_FLAG_MASK | SLJIT_SET_Z); - if (is_commutative(op) && (src1 & SLJIT_IMM) && !(src2 & SLJIT_IMM)) { + if (is_commutative(op) && src1 == SLJIT_IMM && src2 != SLJIT_IMM) { src1 ^= src2; src2 ^= src1; src1 ^= src2; @@ -2960,7 +2995,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * ADJUST_LOCAL_OFFSET(src3, src3w); - if (src3 & SLJIT_IMM) { + if (src3 == SLJIT_IMM) { src3w &= bit_length - 1; if (src3w == 0) @@ -3113,15 +3148,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg) { - CHECK_REG_INDEX(check_sljit_get_register_index(reg)); - return (sljit_s32)gpr(reg); -} + CHECK_REG_INDEX(check_sljit_get_register_index(type, reg)); + + if (type == SLJIT_GP_REGISTER) + return (sljit_s32)gpr(reg); + + if (type != SLJIT_FLOAT_REGISTER) + return -1; -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) -{ - CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); return (sljit_s32)freg_map[reg]; } @@ -3213,33 +3249,61 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp return SLJIT_SUCCESS; } -static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, +static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; - sljit_ins ins; - if (src & SLJIT_IMM) { + if (src == SLJIT_IMM) { FAIL_IF(push_load_imm_inst(compiler, tmp0, srcw)); src = (sljit_s32)tmp0; } else if (src & SLJIT_MEM) { - FAIL_IF(load_word(compiler, tmp0, src, srcw, GET_OPCODE(op) >= SLJIT_CONV_F64_FROM_S32)); + FAIL_IF(load_word(compiler, tmp0, src, srcw, ins & 0x100000)); src = (sljit_s32)tmp0; } + FAIL_IF(push_inst(compiler, ins | F4(dst_r) | R0(src))); + + if (dst & SLJIT_MEM) + return float_mem(compiler, FLOAT_STORE | ((ins & 0x10000) ? 0 : SLJIT_32), TMP_FREG1, dst, dstw); + + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins ins; + + if (src == SLJIT_IMM && GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) + srcw = (sljit_s32)srcw; + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW) ins = (op & SLJIT_32) ? 0xb3a40000 /* cegbr */ : 0xb3a50000 /* cdgbr */; else ins = (op & SLJIT_32) ? 0xb3940000 /* cefbr */ : 0xb3950000 /* cdfbr */; - FAIL_IF(push_inst(compiler, ins | F4(dst_r) | R0(src))); + return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw); +} - if (dst & SLJIT_MEM) - return float_mem(compiler, FLOAT_STORE | (op & SLJIT_32), TMP_FREG1, dst, dstw); +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins ins; - return SLJIT_SUCCESS; + if (src == SLJIT_IMM && GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) + srcw = (sljit_u32)srcw; + + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_UW) + ins = (op & SLJIT_32) ? 0xb3a00000 /* celgbr */ : 0xb3a10000 /* cdlgbr */; + else + ins = (op & SLJIT_32) ? 0xb3900000 /* celfbr */ : 0xb3910000 /* cdlfbr */; + + return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw); } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, @@ -3391,6 +3455,66 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_s32 reg; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fop2r(compiler, op, dst_freg, src1, src1w, src2, src2w)); + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + if (src2 & SLJIT_MEM) { + FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), TMP_FREG1, src2, src2w)); + src2 = TMP_FREG1; + } + + if (src1 & SLJIT_MEM) { + reg = (dst_freg == src2) ? TMP_FREG1 : dst_freg; + FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), reg, src1, src1w)); + src1 = reg; + } + + return push_inst(compiler, 0xb3720000 /* cpsdr */ | F12(src2) | F4(dst_freg) | F0(src1)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f32 value) +{ + union { + sljit_s32 imm; + sljit_f32 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset32(compiler, freg, value)); + + u.value = value; + + FAIL_IF(push_load_imm_inst(compiler, tmp1, (sljit_sw)(((sljit_uw)u.imm << 32)))); + return push_inst(compiler, 0xb3c10000 /* ldgr */ | F4(freg) | R0A(tmp1)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f64 value) +{ + union { + sljit_sw imm; + sljit_f64 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset64(compiler, freg, value)); + + u.value = value; + + FAIL_IF(push_load_imm_inst(compiler, tmp1, (sljit_sw)u.imm)); + return push_inst(compiler, 0xb3c10000 /* ldgr */ | F4(freg) | R0A(tmp1)); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 freg, sljit_s32 reg) { @@ -3440,14 +3564,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) { + struct sljit_jump *jump; sljit_u8 mask = ((type & 0xff) < SLJIT_JUMP) ? get_cc(compiler, type & 0xff) : 0xf; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_jump(compiler, type)); /* record jump */ - struct sljit_jump *jump = (struct sljit_jump *) - ensure_abuf(compiler, sizeof(struct sljit_jump)); + jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF(!jump); set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); jump->addr = compiler->size; @@ -3485,7 +3609,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); - if (src & SLJIT_IMM) { + if (src == SLJIT_IMM) { SLJIT_ASSERT(!(srcw & 1)); /* target address must be even */ FAIL_IF(push_load_imm_inst(compiler, src_r, srcw)); } @@ -3505,6 +3629,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw) { + SLJIT_UNUSED_ARG(arg_types); + CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); @@ -3536,13 +3662,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co sljit_s32 dst, sljit_sw dstw, sljit_s32 type) { + sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0; + sljit_gpr loc_r = tmp1; sljit_u8 mask = get_cc(compiler, type); CHECK_ERROR(); CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); - sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0; - sljit_gpr loc_r = tmp1; switch (GET_OPCODE(op)) { case SLJIT_AND: case SLJIT_OR: @@ -3602,37 +3728,125 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, - sljit_s32 src, sljit_sw srcw) + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_reg) { - sljit_ins mask = get_cc(compiler, type & ~SLJIT_32); + sljit_ins mask; sljit_gpr src_r; + sljit_gpr dst_r = gpr(dst_reg); sljit_ins ins; CHECK_ERROR(); - CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); + CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg)); - if (type & SLJIT_32) - srcw = (sljit_s32)srcw; + ADJUST_LOCAL_OFFSET(src1, src1w); - if (have_lscond2() && (src & SLJIT_IMM) && is_s16(srcw)) { - ins = (type & SLJIT_32) ? 0xec0000000042 /* lochi */ : 0xec0000000046 /* locghi */; - return push_inst(compiler, ins | R36A(gpr(dst_reg)) | (mask << 32) | (sljit_ins)(srcw & 0xffff) << 16); + if (dst_reg != src2_reg) { + if (src1 == dst_reg) { + src1 = src2_reg; + src1w = 0; + type ^= 0x1; + } else { + if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) { + FAIL_IF(load_word(compiler, dst_r, src1, src1w, type & SLJIT_32)); + src1 = src2_reg; + src1w = 0; + type ^= 0x1; + } else + FAIL_IF(push_inst(compiler, ((type & SLJIT_32) ? 0x1800 /* lr */ : 0xb9040000 /* lgr */) | R4A(dst_r) | R0A(gpr(src2_reg)))); + } } - if (src & SLJIT_IMM) { - FAIL_IF(push_load_imm_inst(compiler, tmp0, srcw)); + mask = get_cc(compiler, type & ~SLJIT_32); + + if (src1 & SLJIT_MEM) { + if (src1 & OFFS_REG_MASK) { + src_r = gpr(OFFS_REG(src1)); + + if (src1w != 0) { + FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp1) | R32A(src_r) | ((sljit_ins)(src1w & 0x3) << 16))); + src_r = tmp1; + } + + FAIL_IF(push_inst(compiler, 0xb9e80000 /* agrk */ | R12A(src_r) | R4A(tmp1) | R0A(gpr(src1 & REG_MASK)))); + src_r = tmp1; + src1w = 0; + } else if (!is_s20(src1w)) { + FAIL_IF(push_load_imm_inst(compiler, tmp1, src1w)); + + if (src1 & REG_MASK) + FAIL_IF(push_inst(compiler, 0xb9e80000 /* agrk */ | R12A(tmp1) | R4A(tmp1) | R0A(gpr(src1 & REG_MASK)))); + + src_r = tmp1; + src1w = 0; + } else + src_r = gpr(src1 & REG_MASK); + + ins = (type & SLJIT_32) ? 0xeb00000000f2 /* loc */ : 0xeb00000000e2 /* locg */; + return push_inst(compiler, ins | R36A(dst_r) | (mask << 32) | R28A(src_r) | disp_s20((sljit_s32)src1w)); + } + + if (src1 == SLJIT_IMM) { + if (type & SLJIT_32) + src1w = (sljit_s32)src1w; + + if (have_lscond2() && is_s16(src1w)) { + ins = (type & SLJIT_32) ? 0xec0000000042 /* lochi */ : 0xec0000000046 /* locghi */; + return push_inst(compiler, ins | R36A(dst_r) | (mask << 32) | (sljit_ins)(src1w & 0xffff) << 16); + } + + FAIL_IF(push_load_imm_inst(compiler, tmp0, src1w)); src_r = tmp0; } else - src_r = gpr(src); + src_r = gpr(src1); + + ins = (type & SLJIT_32) ? 0xb9f20000 /* locr */ : 0xb9e20000 /* locgr */; + return push_inst(compiler, ins | (mask << 12) | R4A(dst_r) | R0A(src_r)); +} - if (have_lscond1()) { - ins = (type & SLJIT_32) ? 0xb9f20000 /* locr */ : 0xb9e20000 /* locgr */; - return push_inst(compiler, ins | (mask << 12) | R4A(gpr(dst_reg)) | R0A(src_r)); +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_freg) +{ + sljit_ins ins; + struct sljit_label *label; + struct sljit_jump *jump; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg)); + + ADJUST_LOCAL_OFFSET(src1, src1w); + + if (dst_freg != src2_freg) { + if (dst_freg == src1) { + src1 = src2_freg; + src1w = 0; + type ^= 0x1; + } else { + ins = (type & SLJIT_32) ? 0x3800 /* ler */ : 0x2800 /* ldr */; + FAIL_IF(push_inst(compiler, ins | F4(dst_freg) | F0(src2_freg))); + } } - return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw); + SLJIT_SKIP_CHECKS(compiler); + jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1); + FAIL_IF(!jump); + + if (!(src1 & SLJIT_MEM)) { + ins = (type & SLJIT_32) ? 0x3800 /* ler */ : 0x2800 /* ldr */; + FAIL_IF(push_inst(compiler, ins | F4(dst_freg) | F0(src1))); + } else + FAIL_IF(float_mem(compiler, FLOAT_LOAD | (type & SLJIT_32), dst_freg, src1, src1w)); + + SLJIT_SKIP_CHECKS(compiler); + label = sljit_emit_label(compiler); + FAIL_IF(!label); + + sljit_set_label(jump, label); + return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, @@ -3694,6 +3908,502 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile return push_inst(compiler, ins | R36A(reg2) | disp_s20((sljit_s32)memw + SSIZE_OF(sw))); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 srcdst, sljit_sw srcdstw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_s32 alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type); + struct addr addr; + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw)); + + ADJUST_LOCAL_OFFSET(srcdst, srcdstw); + + if (reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (!(srcdst & SLJIT_MEM)) { + if (type & SLJIT_SIMD_STORE) + ins = F36(srcdst) | F32(freg); + else + ins = F36(freg) | F32(srcdst); + + return push_inst(compiler, 0xe70000000056 /* vlr */ | ins); + } + + FAIL_IF(make_addr_bx(compiler, &addr, srcdst, srcdstw, tmp1)); + ins = F36(freg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset); + + if (alignment >= 4) + ins |= 4 << 12; + else if (alignment == 3) + ins |= 3 << 12; + + return push_inst(compiler, ((type & SLJIT_SIMD_STORE) ? 0xe7000000000e /* vst */ : 0xe70000000006 /* vl */) | ins); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + struct addr addr; + sljit_gpr reg; + sljit_sw sign_ext; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw)); + + ADJUST_LOCAL_OFFSET(src, srcw); + + if (reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && elem_size < 2) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (src & SLJIT_MEM) { + FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp1)); + return push_inst(compiler, 0xe70000000005 /* vlrep */ | F36(freg) + | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset) | ((sljit_ins)elem_size << 12)); + } + + if (type & SLJIT_SIMD_FLOAT) { + if (src == SLJIT_IMM) + return push_inst(compiler, 0xe70000000044 /* vgbm */ | F36(freg)); + + return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(freg) | F32(src) | ((sljit_ins)elem_size << 12)); + } + + if (src == SLJIT_IMM) { + sign_ext = 0x10000; + + switch (elem_size) { + case 0: + srcw &= 0xff; + sign_ext = (sljit_s8)srcw; + break; + case 1: + srcw &= 0xffff; + sign_ext = (sljit_s16)srcw; + break; + case 2: + if ((sljit_s32)srcw == (sljit_s16)srcw) { + srcw &= 0xffff; + sign_ext = (sljit_s16)srcw; + } else + srcw &= 0xffffffff; + break; + default: + if (srcw == (sljit_s16)srcw) { + srcw &= 0xffff; + sign_ext = (sljit_s16)srcw; + } + break; + } + + if (sign_ext != 0x10000) { + if (sign_ext == 0 || sign_ext == -1) + return push_inst(compiler, 0xe70000000044 /* vgbm */ | F36(freg) + | (sign_ext == 0 ? 0 : ((sljit_ins)0xffff << 16))); + + return push_inst(compiler, 0xe70000000045 /* vrepi */ | F36(freg) + | ((sljit_ins)srcw << 16) | ((sljit_ins)elem_size << 12)); + } + + push_load_imm_inst(compiler, tmp0, srcw); + reg = tmp0; + } else + reg = gpr(src); + + FAIL_IF(push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(freg) | R32A(reg) | ((sljit_ins)elem_size << 12))); + return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(freg) | F32(freg) | ((sljit_ins)elem_size << 12)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, sljit_s32 lane_index, + sljit_s32 srcdst, sljit_sw srcdstw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + struct addr addr; + sljit_gpr reg; + sljit_ins ins = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw)); + + ADJUST_LOCAL_OFFSET(srcdst, srcdstw); + + if (reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && elem_size < 2) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (srcdst & SLJIT_MEM) { + FAIL_IF(make_addr_bx(compiler, &addr, srcdst, srcdstw, tmp1)); + ins = F36(freg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset); + } + + if (type & SLJIT_SIMD_LANE_ZERO) { + if ((srcdst & SLJIT_MEM) && lane_index == ((1 << (3 - elem_size)) - 1)) + return push_inst(compiler, 0xe70000000004 /* vllez */ | ins | ((sljit_ins)elem_size << 12)); + + if ((type & SLJIT_SIMD_FLOAT) && freg == srcdst) { + FAIL_IF(push_inst(compiler, 0xe70000000056 /* vlr */ | F36(TMP_FREG1) | F32(freg))); + srcdst = TMP_FREG1; + srcdstw = 0; + } + + FAIL_IF(push_inst(compiler, 0xe70000000044 /* vgbm */ | F36(freg))); + } + + if (srcdst & SLJIT_MEM) { + switch (elem_size) { + case 0: + ins |= 0xe70000000000 /* vleb */; + break; + case 1: + ins |= 0xe70000000001 /* vleh */; + break; + case 2: + ins |= 0xe70000000003 /* vlef */; + break; + default: + ins |= 0xe70000000002 /* vleg */; + break; + } + + /* Convert to vsteb - vsteg */ + if (type & SLJIT_SIMD_STORE) + ins |= 0x8; + + return push_inst(compiler, ins | ((sljit_ins)lane_index << 12)); + } + + if (type & SLJIT_SIMD_FLOAT) { + if (type & SLJIT_SIMD_STORE) + return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(srcdst) | F32(freg) | ((sljit_ins)lane_index << 16) | ((sljit_ins)elem_size << 12)); + + if (elem_size == 3) { + if (lane_index == 0) + ins = F32(srcdst) | F28(freg) | (1 << 12); + else + ins = F32(freg) | F28(srcdst); + + return push_inst(compiler, 0xe70000000084 /* vpdi */ | F36(freg) | ins); + } + + FAIL_IF(push_inst(compiler, 0xe70000000021 /* vlgv */ | R36A(tmp0) | F32(srcdst) | ((sljit_ins)2 << 12))); + return push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(freg) | R32A(tmp0) | ((sljit_ins)lane_index << 16) | ((sljit_ins)2 << 12)); + } + + if (srcdst == SLJIT_IMM) { + switch (elem_size) { + case 0: + ins = 0xe70000000040 /* vleib */; + srcdstw &= 0xff; + break; + case 1: + ins = 0xe70000000041 /* vleih */; + srcdstw &= 0xffff; + break; + case 2: + if ((sljit_s32)srcdstw == (sljit_s16)srcdstw) { + srcdstw &= 0xffff; + ins = 0xe70000000043 /* vleif */; + } else + srcdstw &= 0xffffffff; + break; + default: + if (srcdstw == (sljit_s16)srcdstw) { + srcdstw &= 0xffff; + ins = 0xe70000000042 /* vleig */; + } + break; + } + + if (ins != 0) + return push_inst(compiler, ins | F36(freg) | ((sljit_ins)srcdstw << 16) | ((sljit_ins)lane_index << 12)); + + push_load_imm_inst(compiler, tmp0, srcdstw); + reg = tmp0; + } else + reg = gpr(srcdst); + + ins = ((sljit_ins)lane_index << 16) | ((sljit_ins)elem_size << 12); + + if (!(type & SLJIT_SIMD_STORE)) + return push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(freg) | R32A(reg) | ins); + + FAIL_IF(push_inst(compiler, 0xe70000000021 /* vlgv */ | R36A(reg) | F32(freg) | ins)); + + if (!(type & SLJIT_SIMD_LANE_SIGNED) || elem_size >= 3) + return SLJIT_SUCCESS; + + switch (elem_size) { + case 0: + ins = 0xb9060000 /* lgbr */; + break; + case 1: + ins = 0xb9070000 /* lghr */; + break; + default: + ins = 0xb9140000 /* lgfr */; + break; + } + + return push_inst(compiler, ins | R4A(reg) | R0A(reg)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_s32 src_lane_index) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index)); + + if (reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && elem_size < 2) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(freg) | F32(src) + | ((sljit_ins)src_lane_index << 16) | ((sljit_ins)elem_size << 12)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type); + struct addr addr; + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw)); + + ADJUST_LOCAL_OFFSET(src, srcw); + + if (reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && elem_size < 2) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (src & SLJIT_MEM) { + FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp1)); + ins = F36(freg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset); + + switch (elem2_size - elem_size) { + case 1: + ins |= 0xe70000000002 /* vleg */; + break; + case 2: + ins |= 0xe70000000003 /* vlef */; + break; + default: + ins |= 0xe70000000001 /* vleh */; + break; + } + + FAIL_IF(push_inst(compiler, ins)); + src = freg; + } + + if (type & SLJIT_SIMD_FLOAT) { + FAIL_IF(push_inst(compiler, 0xe700000000d5 /* vuplh */ | F36(freg) | F32(src) | (2 << 12))); + FAIL_IF(push_inst(compiler, 0xe70000000030 /* vesl */ | F36(freg) | F32(freg) | (32 << 16) | (3 << 12))); + return push_inst(compiler, 0xe700000000c4 /* vfll */ | F36(freg) | F32(freg) | (2 << 12)); + } + + ins = ((type & SLJIT_SIMD_EXTEND_SIGNED) ? 0xe700000000d7 /* vuph */ : 0xe700000000d5 /* vuplh */) | F36(freg); + + do { + FAIL_IF(push_inst(compiler, ins | F32(src) | ((sljit_ins)elem_size << 12))); + src = freg; + } while (++elem_size < elem2_size); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 dst, sljit_sw dstw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_gpr dst_r; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw)); + + ADJUST_LOCAL_OFFSET(dst, dstw); + + if (reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && elem_size < 2) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + switch (elem_size) { + case 0: + push_load_imm_inst(compiler, tmp0, (sljit_sw)0x4048505860687078); + push_load_imm_inst(compiler, tmp1, (sljit_sw)0x0008101820283038); + FAIL_IF(push_inst(compiler, 0xe70000000062 /* vlvgp */ | F36(TMP_FREG1) | R32A(tmp1) | R28A(tmp0))); + break; + case 1: + push_load_imm_inst(compiler, tmp0, (sljit_sw)0x0010203040506070); + break; + case 2: + push_load_imm_inst(compiler, tmp0, (sljit_sw)0x8080808000204060); + break; + default: + push_load_imm_inst(compiler, tmp0, (sljit_sw)0x8080808080800040); + break; + } + + if (elem_size != 0) + FAIL_IF(push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(TMP_FREG1) | R32A(tmp0) | (1 << 16) | (3 << 12))); + + FAIL_IF(push_inst(compiler, 0xe70000000085 /* vbperm */ | F36(TMP_FREG1) | F32(freg) | F28(TMP_FREG1))); + + dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0; + FAIL_IF(push_inst(compiler, 0xe70000000021 /* vlgv */ | R36A(dst_r) | F32(TMP_FREG1) + | (elem_size == 0 ? ((3 << 16) | (1 << 12)) : (7 << 16)))); + + if (dst_r == tmp0) + return store_word(compiler, tmp0, dst, dstw, type & SLJIT_32); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_ins ins = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg)); + + if (reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + switch (SLJIT_SIMD_GET_OPCODE(type)) { + case SLJIT_SIMD_OP2_AND: + ins = 0xe70000000068 /* vn */; + break; + case SLJIT_SIMD_OP2_OR: + ins = 0xe7000000006a /* vo */; + break; + case SLJIT_SIMD_OP2_XOR: + ins = 0xe7000000006d /* vx */; + break; + } + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + return push_inst(compiler, ins | F36(dst_freg) | F32(src1_freg) | F28(src2_freg)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 mem_reg) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op1(compiler, op, dst_reg, 0, SLJIT_MEM1(mem_reg), 0); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_reg, + sljit_s32 mem_reg, + sljit_s32 temp_reg) +{ + sljit_ins mask; + sljit_gpr tmp_r = gpr(temp_reg); + sljit_gpr mem_r = gpr(mem_reg); + + CHECK_ERROR(); + CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg)); + + switch (GET_OPCODE(op)) { + case SLJIT_MOV32: + case SLJIT_MOV_U32: + return push_inst(compiler, 0xba000000 /* cs */ | R20A(tmp_r) | R16A(gpr(src_reg)) | R12A(mem_r)); + case SLJIT_MOV_U8: + mask = 0xff; + break; + case SLJIT_MOV_U16: + mask = 0xffff; + break; + default: + return push_inst(compiler, 0xeb0000000030 /* csg */ | R36A(tmp_r) | R32A(gpr(src_reg)) | R28A(mem_r)); + } + + /* tmp0 = (src_reg ^ tmp_r) & mask */ + FAIL_IF(push_inst(compiler, 0xa50f0000 /* llill */ | R20A(tmp1) | mask)); + FAIL_IF(push_inst(compiler, 0xb9e70000 /* xgrk */ | R4A(tmp0) | R0A(gpr(src_reg)) | R12A(tmp_r))); + FAIL_IF(push_inst(compiler, 0xa7090000 /* lghi */ | R20A(tmp_r) | 0xfffc)); + FAIL_IF(push_inst(compiler, 0xb9800000 /* ngr */ | R4A(tmp0) | R0A(tmp1))); + + /* tmp0 = tmp0 << (((mem_r ^ 0x3) & 0x3) << 3) */ + FAIL_IF(push_inst(compiler, 0xa50f0000 /* llill */ | R20A(tmp1) | (sljit_ins)((mask == 0xff) ? 0x18 : 0x10))); + FAIL_IF(push_inst(compiler, 0xb9800000 /* ngr */ | R4A(tmp_r) | R0A(mem_r))); + FAIL_IF(push_inst(compiler, 0xec0000000057 /* rxsbg */ | R36A(tmp1) | R32A(mem_r) | (59 << 24) | (60 << 16) | (3 << 8))); + FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp0) | R32A(tmp0) | R28A(tmp1))); + + /* Already computed: tmp_r = mem_r & ~0x3 */ + + FAIL_IF(push_inst(compiler, 0x58000000 /* l */ | R20A(tmp1) | R12A(tmp_r))); + FAIL_IF(push_inst(compiler, 0x1700 /* x */ | R4A(tmp0) | R0A(tmp1))); + return push_inst(compiler, 0xba000000 /* cs */ | R20A(tmp1) | R16A(tmp0) | R12A(tmp_r)); +} + /* --------------------------------------------------------------------- */ /* Other instructions */ /* --------------------------------------------------------------------- */ @@ -3724,9 +4434,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0; if (have_genext()) - PTR_FAIL_IF(push_inst(compiler, sljit_ins_const | lgrl(dst_r, 0))); + PTR_FAIL_IF(push_inst(compiler, lgrl(dst_r, 0))); else { - PTR_FAIL_IF(push_inst(compiler, sljit_ins_const | larl(tmp1, 0))); + PTR_FAIL_IF(push_inst(compiler, larl(tmp1, 0))); PTR_FAIL_IF(push_inst(compiler, lg(dst_r, 0, r0, tmp1))); } @@ -3753,20 +4463,18 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset); } -SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label *sljit_emit_put_label( - struct sljit_compiler *compiler, - sljit_s32 dst, sljit_sw dstw) +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { - struct sljit_put_label *put_label; + struct sljit_jump *jump; sljit_gpr dst_r; CHECK_ERROR_PTR(); - CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw)); + CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); - put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label)); - PTR_FAIL_IF(!put_label); - set_put_label(put_label, compiler, 0); + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_mov_addr(jump, compiler, 0); dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0; @@ -3780,7 +4488,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label *sljit_emit_put_label( if (dst & SLJIT_MEM) PTR_FAIL_IF(store_word(compiler, dst_r, dst, dstw, 0)); - return put_label; + return jump; } /* TODO(carenas): EVAL probably should move up or be refactored */ diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_32.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_32.c index 69c917101f1..d7399f8210e 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_32.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_32.c @@ -62,21 +62,19 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw /* Both size flags cannot be switched on. */ SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG)); /* SSE2 and immediate is not possible. */ - SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2)); - SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3) - && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66) - && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66)); + SLJIT_ASSERT(a != SLJIT_IMM || !(flags & EX86_SSE2)); + SLJIT_ASSERT(((flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) + & ((flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) - 1)) == 0); + SLJIT_ASSERT((flags & (EX86_VEX_EXT | EX86_REX)) != EX86_VEX_EXT); size &= 0xf; - inst_size = size; + /* The mod r/m byte is always present. */ + inst_size = size + 1; - if (flags & (EX86_PREF_F2 | EX86_PREF_F3)) - inst_size++; - if (flags & EX86_PREF_66) + if (flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) inst_size++; /* Calculate size of b. */ - inst_size += 1; /* mod r/m byte. */ if (b & SLJIT_MEM) { if (!(b & REG_MASK)) inst_size += sizeof(sljit_sw); @@ -87,8 +85,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw inst_size += sizeof(sljit_s8); else inst_size += sizeof(sljit_sw); - } - else if (reg_map[b & REG_MASK] == 5) { + } else if (reg_map[b & REG_MASK] == 5) { /* Swap registers if possible. */ if ((b & OFFS_REG_MASK) && (immb & 0x3) == 0 && reg_map[OFFS_REG(b)] != 5) b = SLJIT_MEM | OFFS_REG(b) | TO_OFFS_REG(b & REG_MASK); @@ -105,15 +102,14 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw } /* Calculate size of a. */ - if (a & SLJIT_IMM) { + if (a == SLJIT_IMM) { if (flags & EX86_BIN_INS) { if (imma <= 127 && imma >= -128) { inst_size += 1; flags |= EX86_BYTE_ARG; } else inst_size += 4; - } - else if (flags & EX86_SHIFT_INS) { + } else if (flags & EX86_SHIFT_INS) { SLJIT_ASSERT(imma <= 0x1f); if (imma != 1) { inst_size++; @@ -125,8 +121,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw inst_size += sizeof(short); else inst_size += sizeof(sljit_sw); - } - else + } else SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG); inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size); @@ -136,27 +131,26 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw INC_SIZE(inst_size); if (flags & EX86_PREF_F2) *inst++ = 0xf2; - if (flags & EX86_PREF_F3) + else if (flags & EX86_PREF_F3) *inst++ = 0xf3; - if (flags & EX86_PREF_66) + else if (flags & EX86_PREF_66) *inst++ = 0x66; buf_ptr = inst + size; /* Encode mod/rm byte. */ if (!(flags & EX86_SHIFT_INS)) { - if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM)) + if ((flags & EX86_BIN_INS) && a == SLJIT_IMM) *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81; - if (a & SLJIT_IMM) + if (a == SLJIT_IMM) *buf_ptr = 0; else if (!(flags & EX86_SSE2_OP1)) *buf_ptr = U8(reg_map[a] << 3); else - *buf_ptr = U8(a << 3); - } - else { - if (a & SLJIT_IMM) { + *buf_ptr = U8(freg_map[a] << 3); + } else { + if (a == SLJIT_IMM) { if (imma == 1) *inst = GROUP_SHIFT_1; else @@ -167,7 +161,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw } if (!(b & SLJIT_MEM)) { - *buf_ptr = U8(*buf_ptr | MOD_REG | (!(flags & EX86_SSE2_OP2) ? reg_map[b] : b)); + *buf_ptr = U8(*buf_ptr | MOD_REG | (!(flags & EX86_SSE2_OP2) ? reg_map[b] : freg_map[b])); buf_ptr++; } else if (b & REG_MASK) { reg_map_b = reg_map[b & REG_MASK]; @@ -183,8 +177,9 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw if (!(b & OFFS_REG_MASK)) *buf_ptr++ |= reg_map_b; else { - *buf_ptr++ |= 0x04; - *buf_ptr++ = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3)); + buf_ptr[0] |= 0x04; + buf_ptr[1] = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3)); + buf_ptr += 2; } if (immb != 0 || reg_map_b == 5) { @@ -195,25 +190,24 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw buf_ptr += sizeof(sljit_sw); } } - } - else { + } else { if (reg_map_b == 5) *buf_ptr |= 0x40; - *buf_ptr++ |= 0x04; - *buf_ptr++ = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3) | (immb << 6)); + buf_ptr[0] |= 0x04; + buf_ptr[1] = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3) | (immb << 6)); + buf_ptr += 2; if (reg_map_b == 5) *buf_ptr++ = 0; } - } - else { + } else { *buf_ptr++ |= 0x05; sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */ buf_ptr += sizeof(sljit_sw); } - if (a & SLJIT_IMM) { + if (a == SLJIT_IMM) { if (flags & EX86_BYTE_ARG) *buf_ptr = U8(imma); else if (flags & EX86_HALF_ARG) @@ -222,35 +216,92 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw sljit_unaligned_store_sw(buf_ptr, imma); } - return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1); + return inst; +} + +static sljit_s32 emit_vex_instruction(struct sljit_compiler *compiler, sljit_uw op, + /* The first and second register operand. */ + sljit_s32 a, sljit_s32 v, + /* The general operand (not immediate). */ + sljit_s32 b, sljit_sw immb) +{ + sljit_u8 *inst; + sljit_u8 vex = 0; + sljit_u8 vex_m = 0; + sljit_uw size; + + SLJIT_ASSERT(((op & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) + & ((op & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) - 1)) == 0); + + if (op & VEX_OP_0F38) + vex_m = 0x2; + else if (op & VEX_OP_0F3A) + vex_m = 0x3; + + if (op & VEX_W) { + if (vex_m == 0) + vex_m = 0x1; + + vex |= 0x80; + } + + if (op & EX86_PREF_66) + vex |= 0x1; + else if (op & EX86_PREF_F2) + vex |= 0x3; + else if (op & EX86_PREF_F3) + vex |= 0x2; + + op &= ~(EX86_PREF_66 | EX86_PREF_F2 | EX86_PREF_F3); + + if (op & VEX_256) + vex |= 0x4; + + vex = U8(vex | ((((op & VEX_SSE2_OPV) ? freg_map[v] : reg_map[v]) ^ 0xf) << 3)); + + size = op & ~(sljit_uw)0xff; + size |= (vex_m == 0) ? 3 : 4; + + inst = emit_x86_instruction(compiler, size, a, 0, b, immb); + FAIL_IF(!inst); + + if (vex_m == 0) { + inst[0] = 0xc5; + inst[1] = U8(vex | 0x80); + inst[2] = U8(op); + return SLJIT_SUCCESS; + } + + inst[0] = 0xc4; + inst[1] = U8(vex_m | 0xe0); + inst[2] = vex; + inst[3] = U8(op); + return SLJIT_SUCCESS; } /* --------------------------------------------------------------------- */ /* Enter / return */ /* --------------------------------------------------------------------- */ -static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset) +static sljit_u8* detect_far_jump_type(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset) { sljit_uw type = jump->flags >> TYPE_SHIFT; if (type == SLJIT_JUMP) { *code_ptr++ = JMP_i32; - jump->addr++; - } - else if (type >= SLJIT_FAST_CALL) { + } else if (type >= SLJIT_FAST_CALL) { *code_ptr++ = CALL_i32; - jump->addr++; - } - else { + } else { *code_ptr++ = GROUP_0F; *code_ptr++ = get_jump_code(type); - jump->addr += 2; } - if (jump->flags & JUMP_LABEL) - jump->flags |= PATCH_MW; - else + jump->addr = (sljit_uw)code_ptr; + + if (jump->flags & JUMP_ADDR) sljit_unaligned_store_sw(code_ptr, (sljit_sw)(jump->u.target - (jump->addr + 4) - (sljit_uw)executable_offset)); + else + jump->flags |= PATCH_MW; code_ptr += 4; return code_ptr; @@ -578,8 +629,6 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) { - sljit_u8 *inst; - CHECK_ERROR(); CHECK(check_sljit_emit_return_void(compiler)); @@ -588,11 +637,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler FAIL_IF(emit_stack_frame_release(compiler, 0)); - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); - FAIL_IF(!inst); - INC_SIZE(1); - RET(); - return SLJIT_SUCCESS; + return emit_byte(compiler, RET_near); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, @@ -782,7 +827,7 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler, offset = stack_size + compiler->local_size; - if (!(src & SLJIT_IMM) && src != SLJIT_R0) { + if (src != SLJIT_IMM && src != SLJIT_R0) { if (word_arg_count >= 1) { EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R0, 0); r2_offset = sizeof(sljit_sw); @@ -836,7 +881,7 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler, stack_size = args_size + SSIZE_OF(sw); - if (word_arg_count >= 1 && !(src & SLJIT_IMM) && src != SLJIT_R0) { + if (word_arg_count >= 1 && src != SLJIT_IMM && src != SLJIT_R0) { r2_offset = SSIZE_OF(sw); stack_size += SSIZE_OF(sw); } @@ -865,7 +910,7 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler, EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), word_arg4_offset); } - if (!(src & SLJIT_IMM) && src != SLJIT_R0) { + if (src != SLJIT_IMM && src != SLJIT_R0) { if (word_arg_count >= 1) { SLJIT_ASSERT(r2_offset == sizeof(sljit_sw)); EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R0, 0); @@ -952,13 +997,7 @@ static sljit_s32 emit_tail_call_end(struct sljit_compiler *compiler, sljit_s32 e sljit_u8 *inst; BINARY_IMM32(ADD, extra_space, SLJIT_SP, 0); - - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); - FAIL_IF(!inst); - INC_SIZE(1); - RET(); - - return SLJIT_SUCCESS; + return emit_byte(compiler, RET_near); } static sljit_s32 tail_call_reg_arg_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types) @@ -1075,7 +1114,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi stack_size = type; FAIL_IF(tail_call_with_args(compiler, &stack_size, arg_types, src, srcw)); - if (!(src & SLJIT_IMM)) { + if (src != SLJIT_IMM) { src = SLJIT_R0; srcw = 0; } @@ -1148,15 +1187,9 @@ static sljit_s32 emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, CHECK_EXTRA_REGS(dst, dstw, (void)0); - if (FAST_IS_REG(dst)) { - /* Unused dest is possible here. */ - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); - FAIL_IF(!inst); - - INC_SIZE(1); - POP_REG(reg_map[dst]); - return SLJIT_SUCCESS; - } + /* Unused dest is possible here. */ + if (FAST_IS_REG(dst)) + return emit_byte(compiler, U8(POP_r + reg_map[dst])); /* Memory. */ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); @@ -1291,6 +1324,201 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile return SLJIT_SUCCESS; } +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG; + sljit_u8 *inst, *jump_inst1, *jump_inst2; + sljit_uw size1, size2; + + /* Binary representation of 0x80000000. */ + static const sljit_f64 f64_high_bit = (sljit_f64)0x80000000ul; + + CHECK_EXTRA_REGS(src, srcw, (void)0); + + if (!(op & SLJIT_32)) { + EMIT_MOV(compiler, TMP_REG1, 0, src, srcw); + + inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 1, TMP_REG1, 0); + FAIL_IF(!inst); + inst[1] |= ROL; + + inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 1, TMP_REG1, 0); + FAIL_IF(!inst); + inst[1] |= SHR; + + FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_PREF_F2 | EX86_SSE2_OP1, dst_r, TMP_REG1, 0)); + + inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!inst); + INC_SIZE(2); + inst[0] = U8(get_jump_code(SLJIT_NOT_CARRY) - 0x10); + + size1 = compiler->size; + FAIL_IF(emit_groupf(compiler, ADDSD_x_xm | EX86_PREF_F2 | EX86_SSE2, dst_r, SLJIT_MEM0(), (sljit_sw)&f64_high_bit)); + + inst[1] = U8(compiler->size - size1); + + if (dst_r == TMP_FREG) + return emit_sse2_store(compiler, 0, dst, dstw, TMP_FREG); + return SLJIT_SUCCESS; + } + + if (!FAST_IS_REG(src)) { + EMIT_MOV(compiler, TMP_REG1, 0, src, srcw); + src = TMP_REG1; + } + + BINARY_IMM32(CMP, 0, src, 0); + + inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!inst); + INC_SIZE(2); + inst[0] = JL_i8; + jump_inst1 = inst; + + size1 = compiler->size; + + FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, src, 0)); + + inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!inst); + INC_SIZE(2); + inst[0] = JMP_i8; + jump_inst2 = inst; + + size2 = compiler->size; + + jump_inst1[1] = U8(size2 - size1); + + if (src != TMP_REG1) + EMIT_MOV(compiler, TMP_REG1, 0, src, 0); + + inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 1, TMP_REG1, 0); + FAIL_IF(!inst); + inst[1] |= SHR; + + inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!inst); + INC_SIZE(2); + inst[0] = JNC_i8; + jump_inst1 = inst; + + size1 = compiler->size; + + BINARY_IMM32(OR, 1, TMP_REG1, 0); + jump_inst1[1] = U8(compiler->size - size1); + + FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, TMP_REG1, 0)); + FAIL_IF(emit_groupf(compiler, ADDSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, dst_r, 0)); + + jump_inst2[1] = U8(compiler->size - size2); + + if (dst_r == TMP_FREG) + return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f32 value) +{ + sljit_u8 *inst; + union { + sljit_s32 imm; + sljit_f32 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset32(compiler, freg, value)); + + u.value = value; + + if (u.imm != 0) + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm); + + inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); + FAIL_IF(!inst); + INC_SIZE(4); + + inst[0] = GROUP_66; + inst[1] = GROUP_0F; + + if (u.imm == 0) { + inst[2] = PXOR_x_xm; + inst[3] = U8(freg | (freg << 3) | MOD_REG); + } else { + inst[2] = MOVD_x_rm; + inst[3] = U8(reg_map[TMP_REG1] | (freg << 3) | MOD_REG); + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f64 value) +{ + sljit_u8 *inst; + sljit_s32 tmp_freg = freg; + union { + sljit_s32 imm[2]; + sljit_f64 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset64(compiler, freg, value)); + + u.value = value; + + if (u.imm[0] == 0) { + if (u.imm[1] == 0) + return emit_groupf(compiler, PXOR_x_xm | EX86_PREF_66 | EX86_SSE2, freg, freg, 0); + + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm[1]); + } else + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm[0]); + + FAIL_IF(emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, freg, TMP_REG1, 0)); + + if (u.imm[1] == 0) + return SLJIT_SUCCESS; + + if (u.imm[0] == 0) { + inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); + FAIL_IF(!inst); + INC_SIZE(4); + + inst[0] = GROUP_0F; + inst[1] = SHUFPS_x_xm; + inst[2] = U8(MOD_REG | (freg << 3) | freg); + inst[3] = 0x51; + return SLJIT_SUCCESS; + } + + if (u.imm[0] != u.imm[1]) { + SLJIT_ASSERT(u.imm[1] != 0 && cpu_feature_list != 0); + + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm[1]); + + if (cpu_feature_list & CPU_FEATURE_SSE41) { + FAIL_IF(emit_groupf_ext(compiler, PINSRD_x_rm_i8 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2_OP1, freg, TMP_REG1, 0)); + return emit_byte(compiler, 1); + } + + FAIL_IF(emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, TMP_FREG, TMP_REG1, 0)); + tmp_freg = TMP_FREG; + } + + inst = (sljit_u8*)ensure_buf(compiler, 1 + 3); + FAIL_IF(!inst); + INC_SIZE(3); + + inst[0] = GROUP_0F; + inst[1] = UNPCKLPS_x_xm; + inst[2] = U8(MOD_REG | (freg << 3) | tmp_freg); + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 freg, sljit_s32 reg) { @@ -1305,6 +1533,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compi reg2 = 0; reg2w = 0; + SLJIT_ASSERT(cpu_feature_list != 0); + + if (!(op & SLJIT_32) && (cpu_feature_list & CPU_FEATURE_SSE41)) { + if (reg & REG_PAIR_MASK) { + reg2 = REG_PAIR_FIRST(reg); + reg = REG_PAIR_SECOND(reg); + + CHECK_EXTRA_REGS(reg, regw, (void)0); + + FAIL_IF(emit_groupf(compiler, (GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x) + | EX86_PREF_66 | EX86_SSE2_OP1, freg, reg, regw)); + } else + reg2 = reg; + + CHECK_EXTRA_REGS(reg2, reg2w, (void)0); + + FAIL_IF(emit_groupf_ext(compiler, (GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? PINSRD_x_rm_i8 : PEXTRD_rm_x_i8) + | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2_OP1, freg, reg2, reg2w)); + return emit_byte(compiler, 1); + } + if (reg & REG_PAIR_MASK) { reg2 = REG_PAIR_SECOND(reg); reg = REG_PAIR_FIRST(reg); @@ -1317,12 +1566,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compi CHECK_EXTRA_REGS(reg, regw, (void)0); - if (op & SLJIT_32) { - inst = emit_x86_instruction(compiler, 2 | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, reg, regw); - inst[0] = GROUP_0F; - inst[1] = GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x; - return SLJIT_SUCCESS; - } + if (op & SLJIT_32) + return emit_groupf(compiler, (GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x) + | EX86_PREF_66 | EX86_SSE2_OP1, freg, reg, regw); if (op == SLJIT_COPY_FROM_F64) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 5); @@ -1334,32 +1580,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compi inst[2] = PSHUFD_x_xm; inst[3] = U8(MOD_REG | (TMP_FREG << 3) | freg); inst[4] = 1; - } else if (reg != 0) { - inst = emit_x86_instruction(compiler, 2 | EX86_PREF_66 | EX86_SSE2_OP1, TMP_FREG, 0, reg, regw); - inst[0] = GROUP_0F; - inst[1] = MOVD_x_rm; - } + } else if (reg != 0) + FAIL_IF(emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, TMP_FREG, reg, regw)); - if (reg2 != 0) { - inst = emit_x86_instruction(compiler, 2 | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, reg2, reg2w); - inst[0] = GROUP_0F; - inst[1] = GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x; - } + if (reg2 != 0) + FAIL_IF(emit_groupf(compiler, (GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x) + | EX86_PREF_66 | EX86_SSE2_OP1, freg, reg2, reg2w)); if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); + inst = (sljit_u8*)ensure_buf(compiler, 1 + 3); FAIL_IF(!inst); - INC_SIZE(4); + INC_SIZE(3); - inst[0] = GROUP_66; - inst[1] = GROUP_0F; - inst[2] = PUNPCKLDQ_x_xm; - inst[3] = U8(MOD_REG | (freg << 3) | (reg == 0 ? freg : TMP_FREG)); - } else { - inst = emit_x86_instruction(compiler, 2 | EX86_PREF_66 | EX86_SSE2_OP1, TMP_FREG, 0, reg, regw); inst[0] = GROUP_0F; - inst[1] = MOVD_rm_x; - } + inst[1] = UNPCKLPS_x_xm; + inst[2] = U8(MOD_REG | (freg << 3) | (reg == 0 ? freg : TMP_FREG)); + } else + FAIL_IF(emit_groupf(compiler, MOVD_rm_x | EX86_PREF_66 | EX86_SSE2_OP1, TMP_FREG, reg, regw)); return SLJIT_SUCCESS; } diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_64.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_64.c index b5efc1fda13..b537a1a3f8f 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_64.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_64.c @@ -38,7 +38,7 @@ static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg, FAIL_IF(!inst); INC_SIZE(2 + sizeof(sljit_sw)); inst[0] = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B); - inst[1] = U8(MOV_r_i32 | (reg_map[reg] & 0x7)); + inst[1] = U8(MOV_r_i32 | reg_lmap[reg]); sljit_unaligned_store_sw(inst + 2, imm); return SLJIT_SUCCESS; } @@ -72,7 +72,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw sljit_uw inst_size; /* The immediate operand must be 32 bit. */ - SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma)); + SLJIT_ASSERT(a != SLJIT_IMM || compiler->mode32 || IS_HALFWORD(imma)); /* Both cannot be switched on. */ SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS)); /* Size flags not allowed for typed instructions. */ @@ -80,26 +80,24 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw /* Both size flags cannot be switched on. */ SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG)); /* SSE2 and immediate is not possible. */ - SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2)); - SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3) - && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66) - && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66)); + SLJIT_ASSERT(a != SLJIT_IMM || !(flags & EX86_SSE2)); + SLJIT_ASSERT(((flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) + & ((flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) - 1)) == 0); + SLJIT_ASSERT((flags & (EX86_VEX_EXT | EX86_REX)) != EX86_VEX_EXT); size &= 0xf; - inst_size = size; + /* The mod r/m byte is always present. */ + inst_size = size + 1; if (!compiler->mode32 && !(flags & EX86_NO_REXW)) rex |= REX_W; else if (flags & EX86_REX) rex |= REX; - if (flags & (EX86_PREF_F2 | EX86_PREF_F3)) - inst_size++; - if (flags & EX86_PREF_66) + if (flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) inst_size++; /* Calculate size of b. */ - inst_size += 1; /* mod r/m byte. */ if (b & SLJIT_MEM) { if (!(b & OFFS_REG_MASK) && NOT_HALFWORD(immb)) { PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb)); @@ -119,8 +117,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw inst_size += sizeof(sljit_s8); else inst_size += sizeof(sljit_s32); - } - else if (reg_lmap[b & REG_MASK] == 5) { + } else if (reg_lmap[b & REG_MASK] == 5) { /* Swap registers if possible. */ if ((b & OFFS_REG_MASK) && (immb & 0x3) == 0 && reg_lmap[OFFS_REG(b)] != 5) b = SLJIT_MEM | OFFS_REG(b) | TO_OFFS_REG(b & REG_MASK); @@ -140,23 +137,26 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw rex |= REX_X; } } - } - else if (!(flags & EX86_SSE2_OP2)) { + } else if (!(flags & EX86_SSE2_OP2)) { if (reg_map[b] >= 8) rex |= REX_B; - } - else if (freg_map[b] >= 8) + } else if (freg_map[b] >= 8) rex |= REX_B; - if (a & SLJIT_IMM) { + if ((flags & EX86_VEX_EXT) && (rex & 0x3)) { + SLJIT_ASSERT(size == 2); + size++; + inst_size++; + } + + if (a == SLJIT_IMM) { if (flags & EX86_BIN_INS) { if (imma <= 127 && imma >= -128) { inst_size += 1; flags |= EX86_BYTE_ARG; } else inst_size += 4; - } - else if (flags & EX86_SHIFT_INS) { + } else if (flags & EX86_SHIFT_INS) { SLJIT_ASSERT(imma <= (compiler->mode32 ? 0x1f : 0x3f)); if (imma != 1) { inst_size++; @@ -168,8 +168,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw inst_size += sizeof(short); else inst_size += sizeof(sljit_s32); - } - else { + } else { SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG); /* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */ if (!(flags & EX86_SSE2_OP1)) { @@ -186,14 +185,16 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size); PTR_FAIL_IF(!inst); - /* Encoding the byte. */ + /* Encoding prefixes. */ INC_SIZE(inst_size); if (flags & EX86_PREF_F2) *inst++ = 0xf2; - if (flags & EX86_PREF_F3) + else if (flags & EX86_PREF_F3) *inst++ = 0xf3; - if (flags & EX86_PREF_66) + else if (flags & EX86_PREF_66) *inst++ = 0x66; + + /* Rex is always the last prefix. */ if (rex) *inst++ = rex; @@ -201,18 +202,17 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw /* Encode mod/rm byte. */ if (!(flags & EX86_SHIFT_INS)) { - if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM)) + if ((flags & EX86_BIN_INS) && a == SLJIT_IMM) *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81; - if (a & SLJIT_IMM) + if (a == SLJIT_IMM) *buf_ptr = 0; else if (!(flags & EX86_SSE2_OP1)) *buf_ptr = U8(reg_lmap[a] << 3); else *buf_ptr = U8(freg_lmap[a] << 3); - } - else { - if (a & SLJIT_IMM) { + } else { + if (a == SLJIT_IMM) { if (imma == 1) *inst = GROUP_SHIFT_1; else @@ -239,8 +239,9 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw if (!(b & OFFS_REG_MASK)) *buf_ptr++ |= reg_lmap_b; else { - *buf_ptr++ |= 0x04; - *buf_ptr++ = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3)); + buf_ptr[0] |= 0x04; + buf_ptr[1] = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3)); + buf_ptr += 2; } if (immb != 0 || reg_lmap_b == 5) { @@ -251,26 +252,26 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw buf_ptr += sizeof(sljit_s32); } } - } - else { + } else { if (reg_lmap_b == 5) *buf_ptr |= 0x40; - *buf_ptr++ |= 0x04; - *buf_ptr++ = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6)); + buf_ptr[0] |= 0x04; + buf_ptr[1] = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6)); + buf_ptr += 2; if (reg_lmap_b == 5) *buf_ptr++ = 0; } - } - else { - *buf_ptr++ |= 0x04; - *buf_ptr++ = 0x25; + } else { + buf_ptr[0] |= 0x04; + buf_ptr[1] = 0x25; + buf_ptr += 2; sljit_unaligned_store_s32(buf_ptr, (sljit_s32)immb); /* 32 bit displacement. */ buf_ptr += sizeof(sljit_s32); } - if (a & SLJIT_IMM) { + if (a == SLJIT_IMM) { if (flags & EX86_BYTE_ARG) *buf_ptr = U8(imma); else if (flags & EX86_HALF_ARG) @@ -279,33 +280,106 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw sljit_unaligned_store_s32(buf_ptr, (sljit_s32)imma); } - return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1); + return inst; +} + +static sljit_s32 emit_vex_instruction(struct sljit_compiler *compiler, sljit_uw op, + /* The first and second register operand. */ + sljit_s32 a, sljit_s32 v, + /* The general operand (not immediate). */ + sljit_s32 b, sljit_sw immb) +{ + sljit_u8 *inst; + sljit_u8 vex = 0; + sljit_u8 vex_m = 0; + sljit_uw size; + + SLJIT_ASSERT(((op & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) + & ((op & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) - 1)) == 0); + + op |= EX86_REX; + + if (op & VEX_OP_0F38) + vex_m = 0x2; + else if (op & VEX_OP_0F3A) + vex_m = 0x3; + + if ((op & VEX_W) || ((op & VEX_AUTO_W) && !compiler->mode32)) { + if (vex_m == 0) + vex_m = 0x1; + + vex |= 0x80; + } + + if (op & EX86_PREF_66) + vex |= 0x1; + else if (op & EX86_PREF_F2) + vex |= 0x3; + else if (op & EX86_PREF_F3) + vex |= 0x2; + + op &= ~(EX86_PREF_66 | EX86_PREF_F2 | EX86_PREF_F3); + + if (op & VEX_256) + vex |= 0x4; + + vex = U8(vex | ((((op & VEX_SSE2_OPV) ? freg_map[v] : reg_map[v]) ^ 0xf) << 3)); + + size = op & ~(sljit_uw)0xff; + size |= (vex_m == 0) ? (EX86_VEX_EXT | 2) : 3; + + inst = emit_x86_instruction(compiler, size, a, 0, b, immb); + FAIL_IF(!inst); + + SLJIT_ASSERT((inst[-1] & 0xf0) == REX); + + /* If X or B is present in REX prefix. */ + if (vex_m == 0 && inst[-1] & 0x3) + vex_m = 0x1; + + if (vex_m == 0) { + vex |= U8(((inst[-1] >> 2) ^ 0x1) << 7); + + inst[-1] = 0xc5; + inst[0] = vex; + inst[1] = U8(op); + return SLJIT_SUCCESS; + } + + vex_m |= U8((inst[-1] ^ 0x7) << 5); + inst[-1] = 0xc4; + inst[0] = vex_m; + inst[1] = vex; + inst[2] = U8(op); + return SLJIT_SUCCESS; } /* --------------------------------------------------------------------- */ /* Enter / return */ /* --------------------------------------------------------------------- */ -static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr) +static sljit_u8* detect_far_jump_type(struct sljit_jump *jump, sljit_u8 *code_ptr) { sljit_uw type = jump->flags >> TYPE_SHIFT; - int short_addr = !(jump->flags & SLJIT_REWRITABLE_JUMP) && !(jump->flags & JUMP_LABEL) && (jump->u.target <= 0xffffffff); + int short_addr = !(jump->flags & SLJIT_REWRITABLE_JUMP) && (jump->flags & JUMP_ADDR) && (jump->u.target <= 0xffffffff); /* The relative jump below specialized for this case. */ SLJIT_ASSERT(reg_map[TMP_REG2] >= 8); if (type < SLJIT_JUMP) { /* Invert type. */ - *code_ptr++ = U8(get_jump_code(type ^ 0x1) - 0x10); - *code_ptr++ = short_addr ? (6 + 3) : (10 + 3); + code_ptr[0] = U8(get_jump_code(type ^ 0x1) - 0x10); + code_ptr[1] = short_addr ? (6 + 3) : (10 + 3); + code_ptr += 2; } - *code_ptr++ = short_addr ? REX_B : (REX_W | REX_B); - *code_ptr++ = MOV_r_i32 | reg_lmap[TMP_REG2]; + code_ptr[0] = short_addr ? REX_B : (REX_W | REX_B); + code_ptr[1] = MOV_r_i32 | reg_lmap[TMP_REG2]; + code_ptr += 2; jump->addr = (sljit_uw)code_ptr; - if (jump->flags & JUMP_LABEL) + if (!(jump->flags & JUMP_ADDR)) jump->flags |= PATCH_MD; else if (short_addr) sljit_unaligned_store_s32(code_ptr, (sljit_s32)jump->u.target); @@ -314,60 +388,62 @@ static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ code_ptr += short_addr ? sizeof(sljit_s32) : sizeof(sljit_sw); - *code_ptr++ = REX_B; - *code_ptr++ = GROUP_FF; - *code_ptr++ = U8(MOD_REG | (type >= SLJIT_FAST_CALL ? CALL_rm : JMP_rm) | reg_lmap[TMP_REG2]); + code_ptr[0] = REX_B; + code_ptr[1] = GROUP_FF; + code_ptr[2] = U8(MOD_REG | (type >= SLJIT_FAST_CALL ? CALL_rm : JMP_rm) | reg_lmap[TMP_REG2]); - return code_ptr; + return code_ptr + 3; } -static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, sljit_u8 *code_ptr, sljit_uw max_label) +static sljit_u8* generate_mov_addr_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset) { - if (max_label > HALFWORD_MAX) { - put_label->addr -= put_label->flags; - put_label->flags = PATCH_MD; - return code_ptr; - } + sljit_uw addr; + sljit_sw diff; + SLJIT_UNUSED_ARG(executable_offset); + + SLJIT_ASSERT(((jump->flags >> JUMP_SIZE_SHIFT) & 0x1f) <= 10); + if (jump->flags & JUMP_ADDR) + addr = jump->u.target; + else + addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + jump->u.label->size; - if (put_label->flags == 0) { - /* Destination is register. */ - code_ptr = (sljit_u8*)put_label->addr - 2 - sizeof(sljit_uw); + if (addr > 0xffffffffl) { + diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); - SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W); - SLJIT_ASSERT((code_ptr[1] & 0xf8) == MOV_r_i32); + if (diff <= HALFWORD_MAX && diff >= HALFWORD_MIN) { + SLJIT_ASSERT(((jump->flags >> JUMP_SIZE_SHIFT) & 0x1f) >= 7); + code_ptr -= SSIZE_OF(s32) - 1; - if ((code_ptr[0] & 0x07) != 0) { - code_ptr[0] = U8(code_ptr[0] & ~0x08); - code_ptr += 2 + sizeof(sljit_s32); - } - else { - code_ptr[0] = code_ptr[1]; - code_ptr += 1 + sizeof(sljit_s32); + SLJIT_ASSERT((code_ptr[-3 - SSIZE_OF(s32)] & 0xf8) == REX_W); + SLJIT_ASSERT((code_ptr[-2 - SSIZE_OF(s32)] & 0xf8) == MOV_r_i32); + + code_ptr[-3 - SSIZE_OF(s32)] = U8(REX_W | ((code_ptr[-3 - SSIZE_OF(s32)] & 0x1) << 2)); + code_ptr[-1 - SSIZE_OF(s32)] = U8(((code_ptr[-2 - SSIZE_OF(s32)] & 0x7) << 3) | 0x5); + code_ptr[-2 - SSIZE_OF(s32)] = LEA_r_m; + + jump->flags |= PATCH_MW; + return code_ptr; } - put_label->addr = (sljit_uw)code_ptr; + jump->flags |= PATCH_MD; return code_ptr; } - code_ptr -= put_label->flags + (2 + sizeof(sljit_uw)); - SLJIT_MEMMOVE(code_ptr, code_ptr + (2 + sizeof(sljit_uw)), put_label->flags); + code_ptr -= 2 + sizeof(sljit_uw); SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W); - - if ((code_ptr[1] & 0xf8) == MOV_r_i32) { - code_ptr += 2 + sizeof(sljit_uw); - SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W); + SLJIT_ASSERT((code_ptr[1] & 0xf8) == MOV_r_i32); + + if ((code_ptr[0] & 0x07) != 0) { + SLJIT_ASSERT(((jump->flags >> JUMP_SIZE_SHIFT) & 0x1f) >= 6); + code_ptr[0] = U8(code_ptr[0] & ~0x08); + code_ptr += 2 + sizeof(sljit_s32); + } else { + SLJIT_ASSERT(((jump->flags >> JUMP_SIZE_SHIFT) & 0x1f) >= 5); + code_ptr[0] = code_ptr[1]; + code_ptr += 1 + sizeof(sljit_s32); } - SLJIT_ASSERT(code_ptr[1] == MOV_rm_r); - - code_ptr[0] = U8(code_ptr[0] & ~0x4); - code_ptr[1] = MOV_rm_i32; - code_ptr[2] = U8(code_ptr[2] & ~(0x7 << 3)); - - code_ptr = (sljit_u8*)(put_label->addr - (2 + sizeof(sljit_uw)) + sizeof(sljit_s32)); - put_label->addr = (sljit_uw)code_ptr; - put_label->flags = 0; return code_ptr; } @@ -539,16 +615,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi tmp = SLJIT_FS0 - fsaveds; for (i = SLJIT_FS0; i > tmp; i--) { - inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset); - inst[0] = GROUP_0F; - inst[1] = MOVAPS_xm_x; + FAIL_IF(emit_groupf(compiler, MOVAPS_xm_x | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset)); saved_float_regs_offset += 16; } for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) { - inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset); - inst[0] = GROUP_0F; - inst[1] = MOVAPS_xm_x; + FAIL_IF(emit_groupf(compiler, MOVAPS_xm_x | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset)); saved_float_regs_offset += 16; } } @@ -606,16 +678,12 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit tmp = SLJIT_FS0 - fsaveds; for (i = SLJIT_FS0; i > tmp; i--) { - inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset); - inst[0] = GROUP_0F; - inst[1] = MOVAPS_x_xm; + FAIL_IF(emit_groupf(compiler, MOVAPS_x_xm | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset)); saved_float_regs_offset += 16; } for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) { - inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset); - inst[0] = GROUP_0F; - inst[1] = MOVAPS_x_xm; + FAIL_IF(emit_groupf(compiler, MOVAPS_x_xm | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset)); saved_float_regs_offset += 16; } @@ -663,20 +731,13 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler) { - sljit_u8 *inst; - CHECK_ERROR(); CHECK(check_sljit_emit_return_void(compiler)); compiler->mode32 = 0; FAIL_IF(emit_stack_frame_release(compiler, 0)); - - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); - FAIL_IF(!inst); - INC_SIZE(1); - RET(); - return SLJIT_SUCCESS; + return emit_byte(compiler, RET_near); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, @@ -875,13 +936,8 @@ static sljit_s32 emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_u8 *inst; if (FAST_IS_REG(dst)) { - if (reg_map[dst] < 8) { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); - FAIL_IF(!inst); - INC_SIZE(1); - POP_REG(reg_lmap[dst]); - return SLJIT_SUCCESS; - } + if (reg_map[dst] < 8) + return emit_byte(compiler, U8(POP_r + reg_lmap[dst])); inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); FAIL_IF(!inst); @@ -1040,15 +1096,15 @@ static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign, compiler->mode32 = 0; - if (src & SLJIT_IMM) { + if (src == SLJIT_IMM) { if (FAST_IS_REG(dst)) { - if (sign || ((sljit_uw)srcw <= 0x7fffffff)) { - inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw); - FAIL_IF(!inst); - *inst = MOV_rm_i32; - return SLJIT_SUCCESS; - } - return emit_load_imm64(compiler, dst, srcw); + if (!sign || ((sljit_u32)srcw <= 0x7fffffff)) + return emit_do_imm32(compiler, reg_map[dst] <= 7 ? 0 : REX_B, U8(MOV_r_i32 | reg_lmap[dst]), srcw); + + inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw); + FAIL_IF(!inst); + *inst = MOV_rm_i32; + return SLJIT_SUCCESS; } compiler->mode32 = 1; inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw); @@ -1069,7 +1125,7 @@ static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign, *inst = MOVSXD_r_rm; } else { compiler->mode32 = 1; - FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw)); + EMIT_MOV(compiler, dst_r, 0, src, srcw); compiler->mode32 = 0; } } @@ -1085,6 +1141,168 @@ static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign, return SLJIT_SUCCESS; } +static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG; + sljit_u8 *inst, *jump_inst1, *jump_inst2; + sljit_uw size1, size2; + + compiler->mode32 = 0; + + if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) { + if (src != SLJIT_IMM) { + compiler->mode32 = 1; + EMIT_MOV(compiler, TMP_REG1, 0, src, srcw); + compiler->mode32 = 0; + } else + FAIL_IF(emit_do_imm32(compiler, reg_map[TMP_REG1] <= 7 ? 0 : REX_B, U8(MOV_r_i32 | reg_lmap[TMP_REG1]), srcw)); + + FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, TMP_REG1, 0)); + + compiler->mode32 = 1; + + if (dst_r == TMP_FREG) + return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG); + return SLJIT_SUCCESS; + } + + if (!FAST_IS_REG(src)) { + EMIT_MOV(compiler, TMP_REG1, 0, src, srcw); + src = TMP_REG1; + } + + BINARY_IMM32(CMP, 0, src, 0); + + inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!inst); + INC_SIZE(2); + inst[0] = JL_i8; + jump_inst1 = inst; + + size1 = compiler->size; + + compiler->mode32 = 0; + FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, src, 0)); + + inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!inst); + INC_SIZE(2); + inst[0] = JMP_i8; + jump_inst2 = inst; + + size2 = compiler->size; + + jump_inst1[1] = U8(size2 - size1); + + if (src != TMP_REG1) + EMIT_MOV(compiler, TMP_REG1, 0, src, 0); + + EMIT_MOV(compiler, TMP_REG2, 0, src, 0); + + inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 1, TMP_REG1, 0); + FAIL_IF(!inst); + inst[1] |= SHR; + + compiler->mode32 = 1; + BINARY_IMM32(AND, 1, TMP_REG2, 0); + + compiler->mode32 = 0; + inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG2, 0); + FAIL_IF(!inst); + inst[0] = OR_r_rm; + + FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, TMP_REG1, 0)); + compiler->mode32 = 1; + FAIL_IF(emit_groupf(compiler, ADDSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, dst_r, 0)); + + jump_inst2[1] = U8(compiler->size - size2); + + if (dst_r == TMP_FREG) + return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG); + return SLJIT_SUCCESS; +} + +static sljit_s32 sljit_emit_fset(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_u8 rex, sljit_s32 is_zero) +{ + sljit_u8 *inst; + sljit_u32 size; + + if (is_zero) { + rex = freg_map[freg] >= 8 ? (REX_R | REX_B) : 0; + } else { + if (freg_map[freg] >= 8) + rex |= REX_R; + if (reg_map[TMP_REG1] >= 8) + rex |= REX_B; + } + + size = (rex != 0) ? 5 : 4; + + inst = (sljit_u8*)ensure_buf(compiler, 1 + size); + FAIL_IF(!inst); + INC_SIZE(size); + + *inst++ = GROUP_66; + if (rex != 0) + *inst++ = rex; + inst[0] = GROUP_0F; + + if (is_zero) { + inst[1] = PXOR_x_xm; + inst[2] = U8(freg_lmap[freg] | (freg_lmap[freg] << 3) | MOD_REG); + } else { + inst[1] = MOVD_x_rm; + inst[2] = U8(reg_lmap[TMP_REG1] | (freg_lmap[freg] << 3) | MOD_REG); + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f32 value) +{ + union { + sljit_s32 imm; + sljit_f32 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset32(compiler, freg, value)); + + u.value = value; + + if (u.imm != 0) { + compiler->mode32 = 1; + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm); + } + + return sljit_emit_fset(compiler, freg, 0, u.imm == 0); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler, + sljit_s32 freg, sljit_f64 value) +{ + union { + sljit_sw imm; + sljit_f64 value; + } u; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fset64(compiler, freg, value)); + + u.value = value; + + if (u.imm != 0) { + compiler->mode32 = 0; + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm); + } + + return sljit_emit_fset(compiler, freg, REX_W, u.imm == 0); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 freg, sljit_s32 reg) { diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_common.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_common.c index a9645bc1753..5e630671240 100644 --- a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_common.c +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitNativeX86_common.c @@ -61,17 +61,20 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) 15 - R15 */ -#define TMP_FREG (0) +#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) +#define TMP_FREG (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) -/* Last register + 1. */ -#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = { 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 5, 7, 6, 4, 3 }; +static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2] = { + 0, 1, 2, 3, 4, 5, 6, 7, 0 +}; + #define CHECK_EXTRA_REGS(p, w, do) \ if (p >= SLJIT_R3 && p <= SLJIT_S3) { \ w = (2 * SSIZE_OF(sw)) + ((p) - SLJIT_R3) * SSIZE_OF(sw); \ @@ -81,12 +84,10 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = { #else /* SLJIT_CONFIG_X86_32 */ -/* Last register + 1. */ -#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) /* Note: r12 & 0x7 == 0b100, which decoded as SIB byte present - Note: avoid to use r12 and r13 for memory addessing + Note: avoid to use r12 and r13 for memory addressing therefore r12 is better to be a higher saved register. */ #ifndef _WIN64 /* Args: rdi(=7), rsi(=6), rdx(=2), rcx(=1), r8, r9. Scratches: rax(=0), r10, r11 */ @@ -95,7 +96,7 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = { }; /* low-map. reg_map & 0x7. */ static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = { - 0, 0, 6, 7, 1, 0, 3, 2, 4, 5, 5, 6, 7, 3, 4, 2, 1 + 0, 0, 6, 7, 1, 0, 3, 2, 4, 5, 5, 6, 7, 3, 4, 2, 1 }; #else /* Args: rcx(=1), rdx(=2), r8, r9. Scratches: rax(=0), r10, r11 */ @@ -109,12 +110,12 @@ static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = { #endif /* Args: xmm0-xmm3 */ -static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { - 4, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2] = { + 0, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 4 }; /* low-map. freg_map & 0x7. */ -static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { - 4, 0, 1, 2, 3, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7 +static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2] = { + 0, 0, 1, 2, 3, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 4 }; #define REX_W 0x48 @@ -140,161 +141,242 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #define U8(v) ((sljit_u8)(v)) - /* Size flags for emit_x86_instruction: */ -#define EX86_BIN_INS 0x0010 -#define EX86_SHIFT_INS 0x0020 -#define EX86_REX 0x0040 -#define EX86_NO_REXW 0x0080 -#define EX86_BYTE_ARG 0x0100 -#define EX86_HALF_ARG 0x0200 -#define EX86_PREF_66 0x0400 -#define EX86_PREF_F2 0x0800 -#define EX86_PREF_F3 0x1000 -#define EX86_SSE2_OP1 0x2000 -#define EX86_SSE2_OP2 0x4000 +#define EX86_BIN_INS ((sljit_uw)0x000010) +#define EX86_SHIFT_INS ((sljit_uw)0x000020) +#define EX86_BYTE_ARG ((sljit_uw)0x000040) +#define EX86_HALF_ARG ((sljit_uw)0x000080) +/* Size flags for both emit_x86_instruction and emit_vex_instruction: */ +#define EX86_REX ((sljit_uw)0x000100) +#define EX86_NO_REXW ((sljit_uw)0x000200) +#define EX86_PREF_66 ((sljit_uw)0x000400) +#define EX86_PREF_F2 ((sljit_uw)0x000800) +#define EX86_PREF_F3 ((sljit_uw)0x001000) +#define EX86_SSE2_OP1 ((sljit_uw)0x002000) +#define EX86_SSE2_OP2 ((sljit_uw)0x004000) #define EX86_SSE2 (EX86_SSE2_OP1 | EX86_SSE2_OP2) +#define EX86_VEX_EXT ((sljit_uw)0x008000) +/* Op flags for emit_vex_instruction: */ +#define VEX_OP_0F38 ((sljit_uw)0x010000) +#define VEX_OP_0F3A ((sljit_uw)0x020000) +#define VEX_SSE2_OPV ((sljit_uw)0x040000) +#define VEX_AUTO_W ((sljit_uw)0x080000) +#define VEX_W ((sljit_uw)0x100000) +#define VEX_256 ((sljit_uw)0x200000) + +#define EX86_SELECT_66(op) (((op) & SLJIT_32) ? 0 : EX86_PREF_66) +#define EX86_SELECT_F2_F3(op) (((op) & SLJIT_32) ? EX86_PREF_F3 : EX86_PREF_F2) /* --------------------------------------------------------------------- */ -/* Instrucion forms */ +/* Instruction forms */ /* --------------------------------------------------------------------- */ -#define ADD (/* BINARY */ 0 << 3) -#define ADD_EAX_i32 0x05 -#define ADD_r_rm 0x03 -#define ADD_rm_r 0x01 -#define ADDSD_x_xm 0x58 -#define ADC (/* BINARY */ 2 << 3) -#define ADC_EAX_i32 0x15 -#define ADC_r_rm 0x13 -#define ADC_rm_r 0x11 -#define AND (/* BINARY */ 4 << 3) -#define AND_EAX_i32 0x25 -#define AND_r_rm 0x23 -#define AND_rm_r 0x21 -#define ANDPD_x_xm 0x54 -#define BSR_r_rm (/* GROUP_0F */ 0xbd) -#define BSF_r_rm (/* GROUP_0F */ 0xbc) -#define BSWAP_r (/* GROUP_0F */ 0xc8) -#define CALL_i32 0xe8 -#define CALL_rm (/* GROUP_FF */ 2 << 3) -#define CDQ 0x99 -#define CMOVE_r_rm (/* GROUP_0F */ 0x44) -#define CMP (/* BINARY */ 7 << 3) -#define CMP_EAX_i32 0x3d -#define CMP_r_rm 0x3b -#define CMP_rm_r 0x39 -#define CVTPD2PS_x_xm 0x5a -#define CVTSI2SD_x_rm 0x2a -#define CVTTSD2SI_r_xm 0x2c -#define DIV (/* GROUP_F7 */ 6 << 3) -#define DIVSD_x_xm 0x5e -#define FLDS 0xd9 -#define FLDL 0xdd -#define FSTPS 0xd9 -#define FSTPD 0xdd -#define INT3 0xcc -#define IDIV (/* GROUP_F7 */ 7 << 3) -#define IMUL (/* GROUP_F7 */ 5 << 3) -#define IMUL_r_rm (/* GROUP_0F */ 0xaf) -#define IMUL_r_rm_i8 0x6b -#define IMUL_r_rm_i32 0x69 -#define JE_i8 0x74 -#define JNE_i8 0x75 -#define JMP_i8 0xeb -#define JMP_i32 0xe9 -#define JMP_rm (/* GROUP_FF */ 4 << 3) -#define LEA_r_m 0x8d -#define LOOP_i8 0xe2 -#define LZCNT_r_rm (/* GROUP_F3 */ /* GROUP_0F */ 0xbd) -#define MOV_r_rm 0x8b -#define MOV_r_i32 0xb8 -#define MOV_rm_r 0x89 -#define MOV_rm_i32 0xc7 -#define MOV_rm8_i8 0xc6 -#define MOV_rm8_r8 0x88 -#define MOVAPS_x_xm 0x28 -#define MOVAPS_xm_x 0x29 -#define MOVD_x_rm 0x6e -#define MOVD_rm_x 0x7e -#define MOVSD_x_xm 0x10 -#define MOVSD_xm_x 0x11 -#define MOVSXD_r_rm 0x63 -#define MOVSX_r_rm8 (/* GROUP_0F */ 0xbe) -#define MOVSX_r_rm16 (/* GROUP_0F */ 0xbf) -#define MOVZX_r_rm8 (/* GROUP_0F */ 0xb6) -#define MOVZX_r_rm16 (/* GROUP_0F */ 0xb7) -#define MUL (/* GROUP_F7 */ 4 << 3) -#define MULSD_x_xm 0x59 -#define NEG_rm (/* GROUP_F7 */ 3 << 3) -#define NOP 0x90 -#define NOT_rm (/* GROUP_F7 */ 2 << 3) -#define OR (/* BINARY */ 1 << 3) -#define OR_r_rm 0x0b -#define OR_EAX_i32 0x0d -#define OR_rm_r 0x09 -#define OR_rm8_r8 0x08 -#define POP_r 0x58 -#define POP_rm 0x8f -#define POPF 0x9d -#define PREFETCH 0x18 -#define PSHUFD_x_xm 0x70 -#define PUNPCKLDQ_x_xm 0x62 -#define PUSH_i32 0x68 -#define PUSH_r 0x50 -#define PUSH_rm (/* GROUP_FF */ 6 << 3) -#define PUSHF 0x9c -#define ROL (/* SHIFT */ 0 << 3) -#define ROR (/* SHIFT */ 1 << 3) -#define RET_near 0xc3 -#define RET_i16 0xc2 -#define SBB (/* BINARY */ 3 << 3) -#define SBB_EAX_i32 0x1d -#define SBB_r_rm 0x1b -#define SBB_rm_r 0x19 -#define SAR (/* SHIFT */ 7 << 3) -#define SHL (/* SHIFT */ 4 << 3) -#define SHLD (/* GROUP_0F */ 0xa5) -#define SHRD (/* GROUP_0F */ 0xad) -#define SHR (/* SHIFT */ 5 << 3) -#define SUB (/* BINARY */ 5 << 3) -#define SUB_EAX_i32 0x2d -#define SUB_r_rm 0x2b -#define SUB_rm_r 0x29 -#define SUBSD_x_xm 0x5c -#define TEST_EAX_i32 0xa9 -#define TEST_rm_r 0x85 -#define TZCNT_r_rm (/* GROUP_F3 */ /* GROUP_0F */ 0xbc) -#define UCOMISD_x_xm 0x2e -#define UNPCKLPD_x_xm 0x14 -#define XCHG_EAX_r 0x90 -#define XCHG_r_rm 0x87 -#define XOR (/* BINARY */ 6 << 3) -#define XOR_EAX_i32 0x35 -#define XOR_r_rm 0x33 -#define XOR_rm_r 0x31 -#define XORPD_x_xm 0x57 - -#define GROUP_0F 0x0f -#define GROUP_66 0x66 -#define GROUP_F3 0xf3 -#define GROUP_F7 0xf7 -#define GROUP_FF 0xff -#define GROUP_BINARY_81 0x81 -#define GROUP_BINARY_83 0x83 -#define GROUP_SHIFT_1 0xd1 -#define GROUP_SHIFT_N 0xc1 -#define GROUP_SHIFT_CL 0xd3 - -#define MOD_REG 0xc0 -#define MOD_DISP8 0x40 - -#define INC_SIZE(s) (*inst++ = U8(s), compiler->size += (s)) - -#define PUSH_REG(r) (*inst++ = U8(PUSH_r + (r))) -#define POP_REG(r) (*inst++ = U8(POP_r + (r))) -#define RET() (*inst++ = RET_near) -#define RET_I16(n) (*inst++ = RET_i16, *inst++ = U8(n), *inst++ = 0) +#define ADD (/* BINARY */ 0 << 3) +#define ADD_EAX_i32 0x05 +#define ADD_r_rm 0x03 +#define ADD_rm_r 0x01 +#define ADDSD_x_xm 0x58 +#define ADC (/* BINARY */ 2 << 3) +#define ADC_EAX_i32 0x15 +#define ADC_r_rm 0x13 +#define ADC_rm_r 0x11 +#define AND (/* BINARY */ 4 << 3) +#define AND_EAX_i32 0x25 +#define AND_r_rm 0x23 +#define AND_rm_r 0x21 +#define ANDPD_x_xm 0x54 +#define BSR_r_rm (/* GROUP_0F */ 0xbd) +#define BSF_r_rm (/* GROUP_0F */ 0xbc) +#define BSWAP_r (/* GROUP_0F */ 0xc8) +#define CALL_i32 0xe8 +#define CALL_rm (/* GROUP_FF */ 2 << 3) +#define CDQ 0x99 +#define CMOVE_r_rm (/* GROUP_0F */ 0x44) +#define CMP (/* BINARY */ 7 << 3) +#define CMP_EAX_i32 0x3d +#define CMP_r_rm 0x3b +#define CMP_rm_r 0x39 +#define CMPS_x_xm 0xc2 +#define CMPXCHG_rm_r 0xb1 +#define CMPXCHG_rm8_r 0xb0 +#define CVTPD2PS_x_xm 0x5a +#define CVTPS2PD_x_xm 0x5a +#define CVTSI2SD_x_rm 0x2a +#define CVTTSD2SI_r_xm 0x2c +#define DIV (/* GROUP_F7 */ 6 << 3) +#define DIVSD_x_xm 0x5e +#define EXTRACTPS_x_xm 0x17 +#define FLDS 0xd9 +#define FLDL 0xdd +#define FSTPS 0xd9 +#define FSTPD 0xdd +#define INSERTPS_x_xm 0x21 +#define INT3 0xcc +#define IDIV (/* GROUP_F7 */ 7 << 3) +#define IMUL (/* GROUP_F7 */ 5 << 3) +#define IMUL_r_rm (/* GROUP_0F */ 0xaf) +#define IMUL_r_rm_i8 0x6b +#define IMUL_r_rm_i32 0x69 +#define JL_i8 0x7c +#define JE_i8 0x74 +#define JNC_i8 0x73 +#define JNE_i8 0x75 +#define JMP_i8 0xeb +#define JMP_i32 0xe9 +#define JMP_rm (/* GROUP_FF */ 4 << 3) +#define LEA_r_m 0x8d +#define LOOP_i8 0xe2 +#define LZCNT_r_rm (/* GROUP_F3 */ /* GROUP_0F */ 0xbd) +#define MOV_r_rm 0x8b +#define MOV_r_i32 0xb8 +#define MOV_rm_r 0x89 +#define MOV_rm_i32 0xc7 +#define MOV_rm8_i8 0xc6 +#define MOV_rm8_r8 0x88 +#define MOVAPS_x_xm 0x28 +#define MOVAPS_xm_x 0x29 +#define MOVD_x_rm 0x6e +#define MOVD_rm_x 0x7e +#define MOVDDUP_x_xm 0x12 +#define MOVDQA_x_xm 0x6f +#define MOVDQA_xm_x 0x7f +#define MOVHLPS_x_x 0x12 +#define MOVHPD_m_x 0x17 +#define MOVHPD_x_m 0x16 +#define MOVLHPS_x_x 0x16 +#define MOVLPD_m_x 0x13 +#define MOVLPD_x_m 0x12 +#define MOVMSKPS_r_x (/* GROUP_0F */ 0x50) +#define MOVQ_x_xm (/* GROUP_0F */ 0x7e) +#define MOVSD_x_xm 0x10 +#define MOVSD_xm_x 0x11 +#define MOVSHDUP_x_xm 0x16 +#define MOVSXD_r_rm 0x63 +#define MOVSX_r_rm8 (/* GROUP_0F */ 0xbe) +#define MOVSX_r_rm16 (/* GROUP_0F */ 0xbf) +#define MOVUPS_x_xm 0x10 +#define MOVZX_r_rm8 (/* GROUP_0F */ 0xb6) +#define MOVZX_r_rm16 (/* GROUP_0F */ 0xb7) +#define MUL (/* GROUP_F7 */ 4 << 3) +#define MULSD_x_xm 0x59 +#define NEG_rm (/* GROUP_F7 */ 3 << 3) +#define NOP 0x90 +#define NOT_rm (/* GROUP_F7 */ 2 << 3) +#define OR (/* BINARY */ 1 << 3) +#define OR_r_rm 0x0b +#define OR_EAX_i32 0x0d +#define OR_rm_r 0x09 +#define OR_rm8_r8 0x08 +#define ORPD_x_xm 0x56 +#define PACKSSWB_x_xm (/* GROUP_0F */ 0x63) +#define PAND_x_xm 0xdb +#define PCMPEQD_x_xm 0x76 +#define PINSRB_x_rm_i8 0x20 +#define PINSRW_x_rm_i8 0xc4 +#define PINSRD_x_rm_i8 0x22 +#define PEXTRB_rm_x_i8 0x14 +#define PEXTRW_rm_x_i8 0x15 +#define PEXTRD_rm_x_i8 0x16 +#define PMOVMSKB_r_x (/* GROUP_0F */ 0xd7) +#define PMOVSXBD_x_xm 0x21 +#define PMOVSXBQ_x_xm 0x22 +#define PMOVSXBW_x_xm 0x20 +#define PMOVSXDQ_x_xm 0x25 +#define PMOVSXWD_x_xm 0x23 +#define PMOVSXWQ_x_xm 0x24 +#define PMOVZXBD_x_xm 0x31 +#define PMOVZXBQ_x_xm 0x32 +#define PMOVZXBW_x_xm 0x30 +#define PMOVZXDQ_x_xm 0x35 +#define PMOVZXWD_x_xm 0x33 +#define PMOVZXWQ_x_xm 0x34 +#define POP_r 0x58 +#define POP_rm 0x8f +#define POPF 0x9d +#define POR_x_xm 0xeb +#define PREFETCH 0x18 +#define PSHUFB_x_xm 0x00 +#define PSHUFD_x_xm 0x70 +#define PSHUFLW_x_xm 0x70 +#define PSRLDQ_x 0x73 +#define PSLLD_x_i8 0x72 +#define PSLLQ_x_i8 0x73 +#define PUSH_i32 0x68 +#define PUSH_r 0x50 +#define PUSH_rm (/* GROUP_FF */ 6 << 3) +#define PUSHF 0x9c +#define PXOR_x_xm 0xef +#define ROL (/* SHIFT */ 0 << 3) +#define ROR (/* SHIFT */ 1 << 3) +#define RET_near 0xc3 +#define RET_i16 0xc2 +#define SBB (/* BINARY */ 3 << 3) +#define SBB_EAX_i32 0x1d +#define SBB_r_rm 0x1b +#define SBB_rm_r 0x19 +#define SAR (/* SHIFT */ 7 << 3) +#define SHL (/* SHIFT */ 4 << 3) +#define SHLD (/* GROUP_0F */ 0xa5) +#define SHRD (/* GROUP_0F */ 0xad) +#define SHR (/* SHIFT */ 5 << 3) +#define SHUFPS_x_xm 0xc6 +#define SUB (/* BINARY */ 5 << 3) +#define SUB_EAX_i32 0x2d +#define SUB_r_rm 0x2b +#define SUB_rm_r 0x29 +#define SUBSD_x_xm 0x5c +#define TEST_EAX_i32 0xa9 +#define TEST_rm_r 0x85 +#define TZCNT_r_rm (/* GROUP_F3 */ /* GROUP_0F */ 0xbc) +#define UCOMISD_x_xm 0x2e +#define UNPCKLPD_x_xm 0x14 +#define UNPCKLPS_x_xm 0x14 +#define VBROADCASTSD_x_xm 0x19 +#define VBROADCASTSS_x_xm 0x18 +#define VEXTRACTF128_x_ym 0x19 +#define VEXTRACTI128_x_ym 0x39 +#define VINSERTF128_y_y_xm 0x18 +#define VINSERTI128_y_y_xm 0x38 +#define VPBROADCASTB_x_xm 0x78 +#define VPBROADCASTD_x_xm 0x58 +#define VPBROADCASTQ_x_xm 0x59 +#define VPBROADCASTW_x_xm 0x79 +#define VPERMPD_y_ym 0x01 +#define VPERMQ_y_ym 0x00 +#define XCHG_EAX_r 0x90 +#define XCHG_r_rm 0x87 +#define XOR (/* BINARY */ 6 << 3) +#define XOR_EAX_i32 0x35 +#define XOR_r_rm 0x33 +#define XOR_rm_r 0x31 +#define XORPD_x_xm 0x57 + +#define GROUP_0F 0x0f +#define GROUP_66 0x66 +#define GROUP_F3 0xf3 +#define GROUP_F7 0xf7 +#define GROUP_FF 0xff +#define GROUP_BINARY_81 0x81 +#define GROUP_BINARY_83 0x83 +#define GROUP_SHIFT_1 0xd1 +#define GROUP_SHIFT_N 0xc1 +#define GROUP_SHIFT_CL 0xd3 +#define GROUP_LOCK 0xf0 + +#define MOD_REG 0xc0 +#define MOD_DISP8 0x40 + +#define INC_SIZE(s) (*inst++ = U8(s), compiler->size += (s)) + +#define PUSH_REG(r) (*inst++ = U8(PUSH_r + (r))) +#define POP_REG(r) (*inst++ = U8(POP_r + (r))) +#define RET() (*inst++ = RET_near) +#define RET_I16(n) (*inst++ = RET_i16, *inst++ = U8(n), *inst++ = 0) + +#define SLJIT_INST_LABEL 255 +#define SLJIT_INST_JUMP 254 +#define SLJIT_INST_MOV_ADDR 253 +#define SLJIT_INST_CONST 252 /* Multithreading does not affect these static variables, since they store built-in CPU features. Therefore they can be overwritten by different threads @@ -303,9 +385,12 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) #define CPU_FEATURE_SSE2 0x002 #endif -#define CPU_FEATURE_LZCNT 0x004 -#define CPU_FEATURE_TZCNT 0x008 -#define CPU_FEATURE_CMOV 0x010 +#define CPU_FEATURE_SSE41 0x004 +#define CPU_FEATURE_LZCNT 0x008 +#define CPU_FEATURE_TZCNT 0x010 +#define CPU_FEATURE_CMOV 0x020 +#define CPU_FEATURE_AVX 0x040 +#define CPU_FEATURE_AVX2 0x080 static sljit_u32 cpu_feature_list = 0; @@ -338,124 +423,117 @@ static SLJIT_INLINE void sljit_unaligned_store_sw(void *addr, sljit_sw value) /* Utility functions */ /******************************************************/ -static void get_cpu_features(void) +static void execute_cpu_id(sljit_u32 info[4]) { - sljit_u32 feature_list = CPU_FEATURE_DETECTED; - sljit_u32 value; - #if defined(_MSC_VER) && _MSC_VER >= 1400 - int CPUInfo[4]; - - __cpuid(CPUInfo, 0); - if (CPUInfo[0] >= 7) { - __cpuidex(CPUInfo, 7, 0); - if (CPUInfo[1] & 0x8) - feature_list |= CPU_FEATURE_TZCNT; - } - - __cpuid(CPUInfo, (int)0x80000001); - if (CPUInfo[2] & 0x20) - feature_list |= CPU_FEATURE_LZCNT; - - __cpuid(CPUInfo, 1); - value = (sljit_u32)CPUInfo[3]; + __cpuidex((int*)info, (int)info[0], (int)info[2]); #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C) || defined(__TINYC__) /* AT&T syntax. */ __asm__ ( - "movl $0x0, %%eax\n" - "lzcnt %%eax, %%eax\n" - "setnz %%al\n" - "movl %%eax, %0\n" - : "=g" (value) - : -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - : "eax" -#else - : "rax" -#endif - ); - - if (value & 0x1) - feature_list |= CPU_FEATURE_LZCNT; - - __asm__ ( - "movl $0x0, %%eax\n" - "tzcnt %%eax, %%eax\n" - "setnz %%al\n" - "movl %%eax, %0\n" - : "=g" (value) - : -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - : "eax" -#else - : "rax" -#endif - ); - - if (value & 0x1) - feature_list |= CPU_FEATURE_TZCNT; - - __asm__ ( - "movl $0x1, %%eax\n" #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - /* On x86-32, there is no red zone, so this - should work (no need for a local variable). */ - "push %%ebx\n" -#endif + "movl %0, %%esi\n" + "movl (%%esi), %%eax\n" + "movl 8(%%esi), %%ecx\n" + "pushl %%ebx\n" "cpuid\n" -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - "pop %%ebx\n" -#endif - "movl %%edx, %0\n" - : "=g" (value) + "movl %%eax, (%%esi)\n" + "movl %%ebx, 4(%%esi)\n" + "popl %%ebx\n" + "movl %%ecx, 8(%%esi)\n" + "movl %%edx, 12(%%esi)\n" +#else /* !SLJIT_CONFIG_X86_32 */ + "movq %0, %%rsi\n" + "movl (%%rsi), %%eax\n" + "movl 8(%%rsi), %%ecx\n" + "cpuid\n" + "movl %%eax, (%%rsi)\n" + "movl %%ebx, 4(%%rsi)\n" + "movl %%ecx, 8(%%rsi)\n" + "movl %%edx, 12(%%rsi)\n" +#endif /* SLJIT_CONFIG_X86_32 */ : + : "r" (info) #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - : "eax", "ecx", "edx" -#else - : "rax", "rbx", "rcx", "rdx" -#endif + : "memory", "eax", "ecx", "edx", "esi" +#else /* !SLJIT_CONFIG_X86_32 */ + : "memory", "rax", "rbx", "rcx", "rdx", "rsi" +#endif /* SLJIT_CONFIG_X86_32 */ ); -#else /* _MSC_VER && _MSC_VER >= 1400 */ +#else /* _MSC_VER < 1400 */ /* Intel syntax. */ __asm { - mov eax, 0 - lzcnt eax, eax - setnz al - mov value, eax +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + mov esi, info + mov eax, [esi] + mov ecx, [esi + 8] + cpuid + mov [esi], eax + mov [esi + 4], ebx + mov [esi + 8], ecx + mov [esi + 12], edx +#else /* !SLJIT_CONFIG_X86_32 */ + mov rsi, info + mov eax, [rsi] + mov ecx, [rsi + 8] + cpuid + mov [rsi], eax + mov [rsi + 4], ebx + mov [rsi + 8], ecx + mov [rsi + 12], edx +#endif /* SLJIT_CONFIG_X86_32 */ } - if (value & 0x1) - feature_list |= CPU_FEATURE_LZCNT; +#endif /* _MSC_VER && _MSC_VER >= 1400 */ +} - __asm { - mov eax, 0 - tzcnt eax, eax - setnz al - mov value, eax - } +static void get_cpu_features(void) +{ + sljit_u32 feature_list = CPU_FEATURE_DETECTED; + sljit_u32 info[4]; + sljit_u32 max_id; - if (value & 0x1) - feature_list |= CPU_FEATURE_TZCNT; + info[0] = 0; + execute_cpu_id(info); + max_id = info[0]; - __asm { - mov eax, 1 - cpuid - mov value, edx + if (max_id >= 7) { + info[0] = 7; + info[2] = 0; + execute_cpu_id(info); + + if (info[1] & 0x8) + feature_list |= CPU_FEATURE_TZCNT; + if (info[1] & 0x20) + feature_list |= CPU_FEATURE_AVX2; } -#endif /* _MSC_VER && _MSC_VER >= 1400 */ + if (max_id >= 1) { + info[0] = 1; + execute_cpu_id(info); + if (info[2] & 0x80000) + feature_list |= CPU_FEATURE_SSE41; + if (info[2] & 0x10000000) + feature_list |= CPU_FEATURE_AVX; #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) - if (value & 0x4000000) - feature_list |= CPU_FEATURE_SSE2; + if (info[3] & 0x4000000) + feature_list |= CPU_FEATURE_SSE2; #endif - if (value & 0x8000) - feature_list |= CPU_FEATURE_CMOV; + if (info[3] & 0x8000) + feature_list |= CPU_FEATURE_CMOV; + } + + info[0] = 0x80000001; + info[2] = 0; /* Silences an incorrect compiler warning. */ + execute_cpu_id(info); + + if (info[2] & 0x20) + feature_list |= CPU_FEATURE_LZCNT; cpu_feature_list = feature_list; } @@ -464,15 +542,15 @@ static sljit_u8 get_jump_code(sljit_uw type) { switch (type) { case SLJIT_EQUAL: + case SLJIT_ATOMIC_STORED: case SLJIT_F_EQUAL: case SLJIT_UNORDERED_OR_EQUAL: - case SLJIT_ORDERED_EQUAL: /* Not supported. */ return 0x84 /* je */; case SLJIT_NOT_EQUAL: + case SLJIT_ATOMIC_NOT_STORED: case SLJIT_F_NOT_EQUAL: case SLJIT_ORDERED_NOT_EQUAL: - case SLJIT_UNORDERED_OR_NOT_EQUAL: /* Not supported. */ return 0x85 /* jne */; case SLJIT_LESS: @@ -520,61 +598,58 @@ static sljit_u8 get_jump_code(sljit_uw type) return 0x81 /* jno */; case SLJIT_UNORDERED: + case SLJIT_ORDERED_EQUAL: /* NaN. */ return 0x8a /* jp */; case SLJIT_ORDERED: + case SLJIT_UNORDERED_OR_NOT_EQUAL: /* Not NaN. */ return 0x8b /* jpo */; } return 0; } #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) -static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset); -#else -static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr); -static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, sljit_u8 *code_ptr, sljit_uw max_label); -#endif +static sljit_u8* detect_far_jump_type(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset); +#else /* !SLJIT_CONFIG_X86_32 */ +static sljit_u8* detect_far_jump_type(struct sljit_jump *jump, sljit_u8 *code_ptr); +static sljit_u8* generate_mov_addr_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset); +#endif /* SLJIT_CONFIG_X86_32 */ -static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset) +static sljit_u8* detect_near_jump_type(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset) { sljit_uw type = jump->flags >> TYPE_SHIFT; sljit_s32 short_jump; sljit_uw label_addr; - if (jump->flags & JUMP_LABEL) - label_addr = (sljit_uw)(code + jump->u.label->size); - else + if (jump->flags & JUMP_ADDR) label_addr = jump->u.target - (sljit_uw)executable_offset; + else + label_addr = (sljit_uw)(code + jump->u.label->size); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - if ((sljit_sw)(label_addr - (jump->addr + 1)) > HALFWORD_MAX || (sljit_sw)(label_addr - (jump->addr + 1)) < HALFWORD_MIN) - return generate_far_jump_code(jump, code_ptr); -#endif + if ((sljit_sw)(label_addr - (sljit_uw)(code_ptr + 6)) > HALFWORD_MAX || (sljit_sw)(label_addr - (sljit_uw)(code_ptr + 5)) < HALFWORD_MIN) + return detect_far_jump_type(jump, code_ptr); +#endif /* SLJIT_CONFIG_X86_64 */ - short_jump = (sljit_sw)(label_addr - (jump->addr + 2)) >= -128 && (sljit_sw)(label_addr - (jump->addr + 2)) <= 127; + short_jump = (sljit_sw)(label_addr - (sljit_uw)(code_ptr + 2)) >= -0x80 && (sljit_sw)(label_addr - (sljit_uw)(code_ptr + 2)) <= 0x7f; if (type == SLJIT_JUMP) { if (short_jump) *code_ptr++ = JMP_i8; else *code_ptr++ = JMP_i32; - jump->addr++; - } - else if (type >= SLJIT_FAST_CALL) { + } else if (type > SLJIT_JUMP) { short_jump = 0; *code_ptr++ = CALL_i32; - jump->addr++; - } - else if (short_jump) { + } else if (short_jump) { *code_ptr++ = U8(get_jump_code(type) - 0x10); - jump->addr++; - } - else { + } else { *code_ptr++ = GROUP_0F; *code_ptr++ = get_jump_code(type); - jump->addr += 2; } + jump->addr = (sljit_uw)code_ptr; + if (short_jump) { jump->flags |= PATCH_MB; code_ptr += sizeof(sljit_s8); @@ -586,6 +661,171 @@ static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code return code_ptr; } +static void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executable_offset) +{ + sljit_uw flags = jump->flags; + sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr; + sljit_uw jump_addr = jump->addr; + SLJIT_UNUSED_ARG(executable_offset); + + if (SLJIT_UNLIKELY(flags & JUMP_MOV_ADDR)) { +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + sljit_unaligned_store_sw((void*)(jump_addr - sizeof(sljit_sw)), (sljit_sw)addr); +#else /* SLJIT_CONFIG_X86_32 */ + if (flags & PATCH_MD) { + SLJIT_ASSERT(addr > HALFWORD_MAX); + sljit_unaligned_store_sw((void*)(jump_addr - sizeof(sljit_sw)), (sljit_sw)addr); + return; + } + + if (flags & PATCH_MW) { + addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET((sljit_u8*)jump_addr, executable_offset); + SLJIT_ASSERT((sljit_sw)addr <= HALFWORD_MAX && (sljit_sw)addr >= HALFWORD_MIN); + } else { + SLJIT_ASSERT(addr <= HALFWORD_MAX); + } + sljit_unaligned_store_s32((void*)(jump_addr - sizeof(sljit_s32)), (sljit_s32)addr); +#endif /* !SLJIT_CONFIG_X86_32 */ + return; + } + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (SLJIT_UNLIKELY(flags & PATCH_MD)) { + SLJIT_ASSERT(!(flags & JUMP_ADDR)); + sljit_unaligned_store_sw((void*)jump_addr, (sljit_sw)addr); + return; + } +#endif /* SLJIT_CONFIG_X86_64 */ + + addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET((sljit_u8*)jump_addr, executable_offset); + + if (flags & PATCH_MB) { + addr -= sizeof(sljit_s8); + SLJIT_ASSERT((sljit_sw)addr <= 0x7f && (sljit_sw)addr >= -0x80); + *(sljit_u8*)jump_addr = U8(addr); + return; + } else if (flags & PATCH_MW) { + addr -= sizeof(sljit_s32); +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + sljit_unaligned_store_sw((void*)jump_addr, (sljit_sw)addr); +#else /* !SLJIT_CONFIG_X86_32 */ + SLJIT_ASSERT((sljit_sw)addr <= HALFWORD_MAX && (sljit_sw)addr >= HALFWORD_MIN); + sljit_unaligned_store_s32((void*)jump_addr, (sljit_s32)addr); +#endif /* SLJIT_CONFIG_X86_32 */ + } +} + +static void reduce_code_size(struct sljit_compiler *compiler) +{ + struct sljit_label *label; + struct sljit_jump *jump; + sljit_uw next_label_size; + sljit_uw next_jump_addr; + sljit_uw next_min_addr; + sljit_uw size_reduce = 0; + sljit_sw diff; + sljit_uw type; +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + sljit_uw size_reduce_max; +#endif /* SLJIT_DEBUG */ + + label = compiler->labels; + jump = compiler->jumps; + + next_label_size = SLJIT_GET_NEXT_SIZE(label); + next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); + + while (1) { + next_min_addr = next_label_size; + if (next_jump_addr < next_min_addr) + next_min_addr = next_jump_addr; + + if (next_min_addr == SLJIT_MAX_ADDRESS) + break; + + if (next_min_addr == next_label_size) { + label->size -= size_reduce; + + label = label->next; + next_label_size = SLJIT_GET_NEXT_SIZE(label); + } + + if (next_min_addr != next_jump_addr) + continue; + + if (!(jump->flags & JUMP_MOV_ADDR)) { +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + size_reduce_max = size_reduce + (((jump->flags >> TYPE_SHIFT) < SLJIT_JUMP) ? CJUMP_MAX_SIZE : JUMP_MAX_SIZE); +#endif /* SLJIT_DEBUG */ + + if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) { + if (jump->flags & JUMP_ADDR) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (jump->u.target <= 0xffffffffl) + size_reduce += sizeof(sljit_s32); +#endif /* SLJIT_CONFIG_X86_64 */ + } else { + /* Unit size: instruction. */ + diff = (sljit_sw)jump->u.label->size - (sljit_sw)(jump->addr - size_reduce); + type = jump->flags >> TYPE_SHIFT; + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (type == SLJIT_JUMP) { + if (diff <= 0x7f + 2 && diff >= -0x80 + 2) + size_reduce += JUMP_MAX_SIZE - 2; + else if (diff <= HALFWORD_MAX + 5 && diff >= HALFWORD_MIN + 5) + size_reduce += JUMP_MAX_SIZE - 5; + } else if (type < SLJIT_JUMP) { + if (diff <= 0x7f + 2 && diff >= -0x80 + 2) + size_reduce += CJUMP_MAX_SIZE - 2; + else if (diff <= HALFWORD_MAX + 6 && diff >= HALFWORD_MIN + 6) + size_reduce += CJUMP_MAX_SIZE - 6; + } else { + if (diff <= HALFWORD_MAX + 5 && diff >= HALFWORD_MIN + 5) + size_reduce += JUMP_MAX_SIZE - 5; + } +#else /* !SLJIT_CONFIG_X86_64 */ + if (type == SLJIT_JUMP) { + if (diff <= 0x7f + 2 && diff >= -0x80 + 2) + size_reduce += JUMP_MAX_SIZE - 2; + } else if (type < SLJIT_JUMP) { + if (diff <= 0x7f + 2 && diff >= -0x80 + 2) + size_reduce += CJUMP_MAX_SIZE - 2; + } +#endif /* SLJIT_CONFIG_X86_64 */ + } + } + +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + jump->flags |= (size_reduce_max - size_reduce) << JUMP_SIZE_SHIFT; +#endif /* SLJIT_DEBUG */ +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + } else { +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + size_reduce_max = size_reduce + 10; +#endif /* SLJIT_DEBUG */ + + if (!(jump->flags & JUMP_ADDR)) { + diff = (sljit_sw)jump->u.label->size - (sljit_sw)(jump->addr - size_reduce - 3); + + if (diff <= HALFWORD_MAX && diff >= HALFWORD_MIN) + size_reduce += 3; + } else if (jump->u.target <= 0xffffffffl) + size_reduce += (jump->flags & MOV_ADDR_HI) ? 4 : 5; + +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + jump->flags |= (size_reduce_max - size_reduce) << JUMP_SIZE_SHIFT; +#endif /* SLJIT_DEBUG */ +#endif /* SLJIT_CONFIG_X86_64 */ + } + + jump = jump->next; + next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); + } + + compiler->size -= size_reduce; +} + SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) { struct sljit_memory_fragment *buf; @@ -595,27 +835,30 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil sljit_u8 *buf_end; sljit_u8 len; sljit_sw executable_offset; - sljit_uw jump_addr; +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + sljit_uw addr; +#endif /* SLJIT_DEBUG */ struct sljit_label *label; struct sljit_jump *jump; struct sljit_const *const_; - struct sljit_put_label *put_label; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_generate_code(compiler)); - reverse_buf(compiler); + + reduce_code_size(compiler); /* Second code generation pass. */ code = (sljit_u8*)SLJIT_MALLOC_EXEC(compiler->size, compiler->exec_allocator_data); PTR_FAIL_WITH_EXEC_IF(code); + + reverse_buf(compiler); buf = compiler->buf; code_ptr = code; label = compiler->labels; jump = compiler->jumps; const_ = compiler->consts; - put_label = compiler->put_labels; executable_offset = SLJIT_EXEC_OFFSET(code); do { @@ -623,49 +866,52 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil buf_end = buf_ptr + buf->used_size; do { len = *buf_ptr++; - if (len > 0) { + SLJIT_ASSERT(len > 0); + if (len < SLJIT_INST_CONST) { /* The code is already generated. */ SLJIT_MEMCPY(code_ptr, buf_ptr, len); code_ptr += len; buf_ptr += len; - } - else { - switch (*buf_ptr) { - case 0: - label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + } else { + switch (len) { + case SLJIT_INST_LABEL: + label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); label->size = (sljit_uw)(code_ptr - code); label = label->next; break; - case 1: - jump->addr = (sljit_uw)code_ptr; + case SLJIT_INST_JUMP: +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + addr = (sljit_uw)code_ptr; +#endif /* SLJIT_DEBUG */ if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) - code_ptr = generate_near_jump_code(jump, code_ptr, code, executable_offset); + code_ptr = detect_near_jump_type(jump, code_ptr, code, executable_offset); else { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - code_ptr = generate_far_jump_code(jump, code_ptr, executable_offset); -#else - code_ptr = generate_far_jump_code(jump, code_ptr); -#endif + code_ptr = detect_far_jump_type(jump, code_ptr, executable_offset); +#else /* !SLJIT_CONFIG_X86_32 */ + code_ptr = detect_far_jump_type(jump, code_ptr); +#endif /* SLJIT_CONFIG_X86_32 */ } + + SLJIT_ASSERT((sljit_uw)code_ptr - addr <= ((jump->flags >> JUMP_SIZE_SHIFT) & 0x1f)); jump = jump->next; break; - case 2: - const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_sw); - const_ = const_->next; + case SLJIT_INST_MOV_ADDR: +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + code_ptr = generate_mov_addr_code(jump, code_ptr, code, executable_offset); +#endif /* SLJIT_CONFIG_X86_64 */ + jump->addr = (sljit_uw)code_ptr; + jump = jump->next; break; default: - SLJIT_ASSERT(*buf_ptr == 3); - SLJIT_ASSERT(put_label->label); - put_label->addr = (sljit_uw)code_ptr; -#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - code_ptr = generate_put_label_code(put_label, code_ptr, (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size); -#endif - put_label = put_label->next; + SLJIT_ASSERT(len == SLJIT_INST_CONST); + const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_sw); + const_ = const_->next; break; } - buf_ptr++; } } while (buf_ptr < buf_end); + SLJIT_ASSERT(buf_ptr == buf_end); buf = buf->next; } while (buf); @@ -673,61 +919,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil SLJIT_ASSERT(!label); SLJIT_ASSERT(!jump); SLJIT_ASSERT(!const_); - SLJIT_ASSERT(!put_label); SLJIT_ASSERT(code_ptr <= code + compiler->size); jump = compiler->jumps; while (jump) { - if (jump->flags & (PATCH_MB | PATCH_MW)) { - if (jump->flags & JUMP_LABEL) - jump_addr = jump->u.label->addr; - else - jump_addr = jump->u.target; - - jump_addr -= jump->addr + (sljit_uw)executable_offset; - - if (jump->flags & PATCH_MB) { - jump_addr -= sizeof(sljit_s8); - SLJIT_ASSERT((sljit_sw)jump_addr >= -128 && (sljit_sw)jump_addr <= 127); - *(sljit_u8*)jump->addr = U8(jump_addr); - } else { - jump_addr -= sizeof(sljit_s32); -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)jump_addr); -#else - SLJIT_ASSERT((sljit_sw)jump_addr >= HALFWORD_MIN && (sljit_sw)jump_addr <= HALFWORD_MAX); - sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)jump_addr); -#endif - } - } -#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - else if (jump->flags & PATCH_MD) { - SLJIT_ASSERT(jump->flags & JUMP_LABEL); - sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)jump->u.label->addr); - } -#endif - + generate_jump_or_mov_addr(jump, executable_offset); jump = jump->next; } - put_label = compiler->put_labels; - while (put_label) { -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - sljit_unaligned_store_sw((void*)(put_label->addr - sizeof(sljit_sw)), (sljit_sw)put_label->label->addr); -#else - if (put_label->flags & PATCH_MD) { - SLJIT_ASSERT(put_label->label->addr > HALFWORD_MAX); - sljit_unaligned_store_sw((void*)(put_label->addr - sizeof(sljit_sw)), (sljit_sw)put_label->label->addr); - } - else { - SLJIT_ASSERT(put_label->label->addr <= HALFWORD_MAX); - sljit_unaligned_store_s32((void*)(put_label->addr - sizeof(sljit_s32)), (sljit_s32)put_label->label->addr); - } -#endif - - put_label = put_label->next; - } - compiler->error = SLJIT_ERR_COMPILED; compiler->executable_offset = executable_offset; compiler->executable_size = (sljit_uw)(code_ptr - code); @@ -743,7 +942,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) switch (feature_type) { case SLJIT_HAS_FPU: #ifdef SLJIT_IS_FPU_AVAILABLE - return SLJIT_IS_FPU_AVAILABLE; + return (SLJIT_IS_FPU_AVAILABLE) != 0; #elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) if (cpu_feature_list == 0) get_cpu_features(); @@ -779,17 +978,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) case SLJIT_HAS_PREFETCH: case SLJIT_HAS_COPY_F32: case SLJIT_HAS_COPY_F64: + case SLJIT_HAS_ATOMIC: return 1; - case SLJIT_HAS_SSE2: -#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) +#if !(defined SLJIT_IS_FPU_AVAILABLE) || SLJIT_IS_FPU_AVAILABLE + case SLJIT_HAS_AVX: if (cpu_feature_list == 0) get_cpu_features(); - return (cpu_feature_list & CPU_FEATURE_SSE2) != 0; -#else /* !SLJIT_DETECT_SSE2 */ - return 1; -#endif /* SLJIT_DETECT_SSE2 */ - + return (cpu_feature_list & CPU_FEATURE_AVX) != 0; + case SLJIT_HAS_AVX2: + if (cpu_feature_list == 0) + get_cpu_features(); + return (cpu_feature_list & CPU_FEATURE_AVX2) != 0; + case SLJIT_HAS_SIMD: + if (cpu_feature_list == 0) + get_cpu_features(); + return (cpu_feature_list & CPU_FEATURE_SSE41) != 0; +#endif /* SLJIT_IS_FPU_AVAILABLE */ default: return 0; } @@ -797,16 +1002,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) { - if (type < SLJIT_UNORDERED || type > SLJIT_ORDERED_LESS_EQUAL) - return 0; - switch (type) { case SLJIT_ORDERED_EQUAL: case SLJIT_UNORDERED_OR_NOT_EQUAL: - return 0; + return 2; } - return 1; + return 0; } /* --------------------------------------------------------------------- */ @@ -850,6 +1052,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type) #endif /* SLJIT_CONFIG_X86_64 */ +static sljit_s32 emit_byte(struct sljit_compiler *compiler, sljit_u8 byte) +{ + sljit_u8 *inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!inst); + INC_SIZE(1); + *inst = byte; + return SLJIT_SUCCESS; +} + static sljit_s32 emit_mov(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw); @@ -857,6 +1068,14 @@ static sljit_s32 emit_mov(struct sljit_compiler *compiler, #define EMIT_MOV(compiler, dst, dstw, src, srcw) \ FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw)); +static sljit_s32 emit_groupf(struct sljit_compiler *compiler, + sljit_uw op, + sljit_s32 dst, sljit_s32 src, sljit_sw srcw); + +static sljit_s32 emit_groupf_ext(struct sljit_compiler *compiler, + sljit_uw op, + sljit_s32 dst, sljit_s32 src, sljit_sw srcw); + static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler, sljit_s32 single, sljit_s32 dst, sljit_sw dstw, sljit_s32 src); @@ -867,6 +1086,10 @@ static sljit_s32 emit_cmp_binary(struct sljit_compiler *compiler, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w); +static sljit_s32 emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src, sljit_sw srcw); + static SLJIT_INLINE sljit_s32 emit_endbranch(struct sljit_compiler *compiler) { #if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) @@ -911,7 +1134,11 @@ static SLJIT_INLINE sljit_s32 emit_rdssp(struct sljit_compiler *compiler, sljit_ #endif inst[0] = GROUP_0F; inst[1] = 0x1e; +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) inst[2] = U8(MOD_REG | (0x1 << 3) | reg_lmap[reg]); +#else + inst[2] = U8(MOD_REG | (0x1 << 3) | reg_map[reg]); +#endif return SLJIT_SUCCESS; } @@ -1021,7 +1248,8 @@ static sljit_s32 emit_mov(struct sljit_compiler *compiler, *inst = MOV_rm_r; return SLJIT_SUCCESS; } - if (src & SLJIT_IMM) { + + if (src == SLJIT_IMM) { if (FAST_IS_REG(dst)) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) return emit_do_imm(compiler, MOV_r_i32 | reg_map[dst], srcw); @@ -1068,6 +1296,27 @@ static sljit_s32 emit_mov(struct sljit_compiler *compiler, return SLJIT_SUCCESS; } +static sljit_s32 emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src, sljit_sw srcw) +{ + sljit_u8* inst; + sljit_uw size; + + SLJIT_ASSERT(type >= SLJIT_EQUAL && type <= SLJIT_ORDERED_LESS_EQUAL); + + inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!inst); + INC_SIZE(2); + inst[0] = U8(get_jump_code((sljit_uw)type ^ 0x1) - 0x10); + + size = compiler->size; + EMIT_MOV(compiler, dst_reg, 0, src, srcw); + + inst[1] = U8(compiler->size - size); + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { sljit_u8 *inst; @@ -1080,17 +1329,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile switch (GET_OPCODE(op)) { case SLJIT_BREAKPOINT: - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); - FAIL_IF(!inst); - INC_SIZE(1); - *inst = INT3; - break; + return emit_byte(compiler, INT3); case SLJIT_NOP: - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); - FAIL_IF(!inst); - INC_SIZE(1); - *inst = NOP; - break; + return emit_byte(compiler, NOP); case SLJIT_LMUL_UW: case SLJIT_LMUL_SW: case SLJIT_DIVMOD_UW: @@ -1131,23 +1372,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile #endif #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); - FAIL_IF(!inst); - INC_SIZE(1); - *inst = CDQ; + FAIL_IF(emit_byte(compiler, CDQ)); #else - if (compiler->mode32) { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); - FAIL_IF(!inst); - INC_SIZE(1); - *inst = CDQ; - } else { + if (!compiler->mode32) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); FAIL_IF(!inst); INC_SIZE(2); inst[0] = REX_W; inst[1] = CDQ; - } + } else + FAIL_IF(emit_byte(compiler, CDQ)); #endif } @@ -1213,29 +1447,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile return SLJIT_SUCCESS; } -#define ENCODE_PREFIX(prefix) \ - do { \ - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); \ - FAIL_IF(!inst); \ - INC_SIZE(1); \ - *inst = U8(prefix); \ - } while (0) - static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_u8* inst; sljit_s32 dst_r; -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - sljit_s32 work_r; -#endif #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 0; #endif - if (src & SLJIT_IMM) { + if (src == SLJIT_IMM) { if (FAST_IS_REG(dst)) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) return emit_do_imm(compiler, MOV_r_i32 | reg_map[dst], srcw); @@ -1264,100 +1487,33 @@ static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign, #else dst_r = src; #endif - } + } else { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - else if (FAST_IS_REG(src) && reg_map[src] >= 4) { - /* src, dst are registers. */ - SLJIT_ASSERT(FAST_IS_REG(dst)); - if (reg_map[dst] < 4) { - if (dst != src) - EMIT_MOV(compiler, dst, 0, src, 0); - inst = emit_x86_instruction(compiler, 2, dst, 0, dst, 0); - FAIL_IF(!inst); - inst[0] = GROUP_0F; - inst[1] = sign ? MOVSX_r_rm8 : MOVZX_r_rm8; - } - else { - if (dst != src) - EMIT_MOV(compiler, dst, 0, src, 0); - if (sign) { - /* shl reg, 24 */ - inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0); - FAIL_IF(!inst); - *inst |= SHL; - /* sar reg, 24 */ - inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0); - FAIL_IF(!inst); - *inst |= SAR; - } - else { + if (FAST_IS_REG(src) && reg_map[src] >= 4) { + /* Both src and dst are registers. */ + SLJIT_ASSERT(FAST_IS_REG(dst)); + + if (src == dst && !sign) { inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 0xff, dst, 0); FAIL_IF(!inst); *(inst + 1) |= AND; + return SLJIT_SUCCESS; } + + EMIT_MOV(compiler, TMP_REG1, 0, src, 0); + src = TMP_REG1; + srcw = 0; } - return SLJIT_SUCCESS; - } -#endif - else { +#endif /* !SLJIT_CONFIG_X86_32 */ + /* src can be memory addr or reg_map[src] < 4 on x86_32 architectures. */ - inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw); - FAIL_IF(!inst); - inst[0] = GROUP_0F; - inst[1] = sign ? MOVSX_r_rm8 : MOVZX_r_rm8; + FAIL_IF(emit_groupf(compiler, sign ? MOVSX_r_rm8 : MOVZX_r_rm8, dst_r, src, srcw)); } if (dst & SLJIT_MEM) { -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - if (dst_r == TMP_REG1) { - /* Find a non-used register, whose reg_map[src] < 4. */ - if ((dst & REG_MASK) == SLJIT_R0) { - if ((dst & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_R1)) - work_r = SLJIT_R2; - else - work_r = SLJIT_R1; - } - else { - if ((dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_R0)) - work_r = SLJIT_R0; - else if ((dst & REG_MASK) == SLJIT_R1) - work_r = SLJIT_R2; - else - work_r = SLJIT_R1; - } - - if (work_r == SLJIT_R0) { - ENCODE_PREFIX(XCHG_EAX_r | reg_map[TMP_REG1]); - } - else { - inst = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0); - FAIL_IF(!inst); - *inst = XCHG_r_rm; - } - - inst = emit_x86_instruction(compiler, 1, work_r, 0, dst, dstw); - FAIL_IF(!inst); - *inst = MOV_rm8_r8; - - if (work_r == SLJIT_R0) { - ENCODE_PREFIX(XCHG_EAX_r | reg_map[TMP_REG1]); - } - else { - inst = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0); - FAIL_IF(!inst); - *inst = XCHG_r_rm; - } - } - else { - inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw); - FAIL_IF(!inst); - *inst = MOV_rm8_r8; - } -#else inst = emit_x86_instruction(compiler, 1 | EX86_REX | EX86_NO_REXW, dst_r, 0, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm8_r8; -#endif } return SLJIT_SUCCESS; @@ -1398,7 +1554,7 @@ static sljit_s32 emit_mov_half(struct sljit_compiler *compiler, sljit_s32 sign, compiler->mode32 = 0; #endif - if (src & SLJIT_IMM) { + if (src == SLJIT_IMM) { if (FAST_IS_REG(dst)) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) return emit_do_imm(compiler, MOV_r_i32 | reg_map[dst], srcw); @@ -1419,12 +1575,8 @@ static sljit_s32 emit_mov_half(struct sljit_compiler *compiler, sljit_s32 sign, if ((dst & SLJIT_MEM) && FAST_IS_REG(src)) dst_r = src; - else { - inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw); - FAIL_IF(!inst); - inst[0] = GROUP_0F; - inst[1] = sign ? MOVSX_r_rm16 : MOVZX_r_rm16; - } + else + FAIL_IF(emit_groupf(compiler, sign ? MOVSX_r_rm16 : MOVZX_r_rm16, dst_r, src, srcw)); if (dst & SLJIT_MEM) { inst = emit_x86_instruction(compiler, 1 | EX86_NO_REXW | EX86_PREF_66, dst_r, 0, dst, dstw); @@ -1481,26 +1633,19 @@ static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 is_clz, sljit_s32 dst_r; sljit_sw max; - if (cpu_feature_list == 0) - get_cpu_features(); + SLJIT_ASSERT(cpu_feature_list != 0); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; if (is_clz ? (cpu_feature_list & CPU_FEATURE_LZCNT) : (cpu_feature_list & CPU_FEATURE_TZCNT)) { - inst = emit_x86_instruction(compiler, 2 | EX86_PREF_F3, dst_r, 0, src, srcw); - FAIL_IF(!inst); - inst[0] = GROUP_0F; - inst[1] = is_clz ? LZCNT_r_rm : TZCNT_r_rm; + FAIL_IF(emit_groupf(compiler, (is_clz ? LZCNT_r_rm : TZCNT_r_rm) | EX86_PREF_F3, dst_r, src, srcw)); if (dst & SLJIT_MEM) EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); return SLJIT_SUCCESS; } - inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw); - FAIL_IF(!inst); - inst[0] = GROUP_0F; - inst[1] = is_clz ? BSR_r_rm : BSF_r_rm; + FAIL_IF(emit_groupf(compiler, is_clz ? BSR_r_rm : BSF_r_rm, dst_r, src, srcw)); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) max = is_clz ? (32 + 31) : 32; @@ -1518,7 +1663,7 @@ static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 is_clz, inst[1] = CMOVE_r_rm; } else - FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, max)); + FAIL_IF(emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, max)); if (is_clz) { inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0); @@ -1533,14 +1678,9 @@ static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 is_clz, if (cpu_feature_list & CPU_FEATURE_CMOV) { EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, max); - - inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0); - FAIL_IF(!inst); - inst[0] = GROUP_0F; - inst[1] = CMOVE_r_rm; - } - else - FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, max)); + FAIL_IF(emit_groupf(compiler, CMOVE_r_rm, dst_r, TMP_REG2, 0)); + } else + FAIL_IF(emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, max)); if (is_clz) { inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, max >> 1, dst_r, 0); @@ -1555,6 +1695,7 @@ static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 is_clz, } static sljit_s32 emit_bswap(struct sljit_compiler *compiler, + sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { @@ -1563,10 +1704,24 @@ static sljit_s32 emit_bswap(struct sljit_compiler *compiler, sljit_uw size; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) sljit_u8 rex = 0; +#else /* !SLJIT_CONFIG_X86_64 */ + sljit_s32 dst_is_ereg = op & SLJIT_32; #endif /* SLJIT_CONFIG_X86_64 */ - if (src != dst_r) - EMIT_MOV(compiler, dst_r, 0, src, srcw); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (op == SLJIT_REV_U32 || op == SLJIT_REV_S32) + compiler->mode32 = 1; +#else /* !SLJIT_CONFIG_X86_64 */ + op &= ~SLJIT_32; +#endif /* SLJIT_CONFIG_X86_64 */ + + if (src != dst_r) { + /* Only the lower 16 bit is read for eregs. */ + if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) + FAIL_IF(emit_mov_half(compiler, 0, dst_r, 0, src, srcw)); + else + EMIT_MOV(compiler, dst_r, 0, src, srcw); + } size = 2; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) @@ -1595,8 +1750,41 @@ static sljit_s32 emit_bswap(struct sljit_compiler *compiler, inst[1] = BSWAP_r | reg_map[dst_r]; #endif /* SLJIT_CONFIG_X86_64 */ - if (dst & SLJIT_MEM) - EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); + if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + size = compiler->mode32 ? 16 : 48; +#else /* !SLJIT_CONFIG_X86_64 */ + size = 16; +#endif /* SLJIT_CONFIG_X86_64 */ + + inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, (sljit_sw)size, dst_r, 0); + FAIL_IF(!inst); + if (op == SLJIT_REV_U16) + inst[1] |= SHR; + else + inst[1] |= SAR; + } + + if (dst & SLJIT_MEM) { +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if (dst_is_ereg) + op = SLJIT_REV; +#endif /* SLJIT_CONFIG_X86_32 */ + if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) + return emit_mov_half(compiler, 0, dst, dstw, TMP_REG1, 0); + + return emit_mov(compiler, dst, dstw, TMP_REG1, 0); + } + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (op == SLJIT_REV_S32) { + compiler->mode32 = 0; + inst = emit_x86_instruction(compiler, 1, dst, 0, dst, 0); + FAIL_IF(!inst); + *inst = MOVSXD_r_rm; + } +#endif /* SLJIT_CONFIG_X86_64 */ + return SLJIT_SUCCESS; } @@ -1639,14 +1827,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile if (op == SLJIT_MOV_S32) op = SLJIT_MOV_U32; } - else if (src & SLJIT_IMM) { + else if (src == SLJIT_IMM) { if (op == SLJIT_MOV_U32) op = SLJIT_MOV_S32; } } #endif /* SLJIT_CONFIG_X86_64 */ - if (src & SLJIT_IMM) { + if (src == SLJIT_IMM) { switch (op) { case SLJIT_MOV_U8: srcw = (sljit_u8)srcw; @@ -1731,7 +1919,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile case SLJIT_CTZ: return emit_clz_ctz(compiler, (op == SLJIT_CLZ), dst, dstw, src, srcw); case SLJIT_REV: - return emit_bswap(compiler, dst, dstw, src, srcw); + case SLJIT_REV_U16: + case SLJIT_REV_S16: + case SLJIT_REV_U32: + case SLJIT_REV_S32: +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if (dst_is_ereg) + op |= SLJIT_32; +#endif /* SLJIT_CONFIG_X86_32 */ + return emit_bswap(compiler, op, dst, dstw, src, srcw); } return SLJIT_SUCCESS; @@ -1750,7 +1946,7 @@ static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler, sljit_u8 op_imm = U8(op_types & 0xff); if (dst == src1 && dstw == src1w) { - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) { #else @@ -1784,7 +1980,7 @@ static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler, /* Only for cumulative operations. */ if (dst == src2 && dstw == src2w) { - if (src1 & SLJIT_IMM) { + if (src1 == SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if ((dst == SLJIT_R0) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) { #else @@ -1818,7 +2014,7 @@ static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler, /* General version. */ if (FAST_IS_REG(dst)) { EMIT_MOV(compiler, dst, 0, src1, src1w); - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { BINARY_IMM(op_imm, op_mr, src2w, dst, 0); } else { @@ -1830,7 +2026,7 @@ static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler, else { /* This version requires less memory writing. */ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0); } else { @@ -1857,7 +2053,7 @@ static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler, sljit_u8 op_imm = U8(op_types & 0xff); if (dst == src1 && dstw == src1w) { - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) { #else @@ -1891,7 +2087,7 @@ static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler, /* General version. */ if (FAST_IS_REG(dst) && dst != src2) { EMIT_MOV(compiler, dst, 0, src1, src1w); - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { BINARY_IMM(op_imm, op_mr, src2w, dst, 0); } else { @@ -1903,7 +2099,7 @@ static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler, else { /* This version requires less memory writing. */ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0); } else { @@ -1926,20 +2122,12 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler, sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; /* Register destination. */ - if (dst_r == src1 && !(src2 & SLJIT_IMM)) { - inst = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w); - FAIL_IF(!inst); - inst[0] = GROUP_0F; - inst[1] = IMUL_r_rm; - } - else if (dst_r == src2 && !(src1 & SLJIT_IMM)) { - inst = emit_x86_instruction(compiler, 2, dst_r, 0, src1, src1w); - FAIL_IF(!inst); - inst[0] = GROUP_0F; - inst[1] = IMUL_r_rm; - } - else if (src1 & SLJIT_IMM) { - if (src2 & SLJIT_IMM) { + if (dst_r == src1 && src2 != SLJIT_IMM) { + FAIL_IF(emit_groupf(compiler, IMUL_r_rm, dst_r, src2, src2w)); + } else if (dst_r == src2 && src1 != SLJIT_IMM) { + FAIL_IF(emit_groupf(compiler, IMUL_r_rm, dst_r, src1, src1w)); + } else if (src1 == SLJIT_IMM) { + if (src2 == SLJIT_IMM) { EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, src2w); src2 = dst_r; src2w = 0; @@ -1949,10 +2137,8 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler, inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w); FAIL_IF(!inst); *inst = IMUL_r_rm_i8; - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); - FAIL_IF(!inst); - INC_SIZE(1); - *inst = U8(src1w); + + FAIL_IF(emit_byte(compiler, U8(src1w))); } #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) else { @@ -1978,30 +2164,26 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler, if (dst_r != src2) EMIT_MOV(compiler, dst_r, 0, src2, src2w); FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w)); - inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0); - FAIL_IF(!inst); - inst[0] = GROUP_0F; - inst[1] = IMUL_r_rm; + FAIL_IF(emit_groupf(compiler, IMUL_r_rm, dst_r, TMP_REG2, 0)); } #endif } - else if (src2 & SLJIT_IMM) { + else if (src2 == SLJIT_IMM) { /* Note: src1 is NOT immediate. */ if (src2w <= 127 && src2w >= -128) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w); FAIL_IF(!inst); *inst = IMUL_r_rm_i8; - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); - FAIL_IF(!inst); - INC_SIZE(1); - *inst = U8(src2w); + + FAIL_IF(emit_byte(compiler, U8(src2w))); } #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) else { inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w); FAIL_IF(!inst); *inst = IMUL_r_rm_i32; + inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); FAIL_IF(!inst); INC_SIZE(4); @@ -2012,31 +2194,24 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler, inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w); FAIL_IF(!inst); *inst = IMUL_r_rm_i32; + inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); FAIL_IF(!inst); INC_SIZE(4); sljit_unaligned_store_s32(inst, (sljit_s32)src2w); - } - else { + } else { if (dst_r != src1) EMIT_MOV(compiler, dst_r, 0, src1, src1w); FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w)); - inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0); - FAIL_IF(!inst); - inst[0] = GROUP_0F; - inst[1] = IMUL_r_rm; + FAIL_IF(emit_groupf(compiler, IMUL_r_rm, dst_r, TMP_REG2, 0)); } #endif - } - else { + } else { /* Neither argument is immediate. */ if (ADDRESSING_DEPENDS_ON(src2, dst_r)) dst_r = TMP_REG1; EMIT_MOV(compiler, dst_r, 0, src1, src1w); - inst = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w); - FAIL_IF(!inst); - inst[0] = GROUP_0F; - inst[1] = IMUL_r_rm; + FAIL_IF(emit_groupf(compiler, IMUL_r_rm, dst_r, src2, src2w)); } if (dst & SLJIT_MEM) @@ -2069,10 +2244,10 @@ static sljit_s32 emit_lea_binary(struct sljit_compiler *compiler, done = 1; } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - if ((src2 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src2w))) { + if (src2 == SLJIT_IMM && (compiler->mode32 || IS_HALFWORD(src2w))) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), (sljit_s32)src2w); #else - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), src2w); #endif FAIL_IF(!inst); @@ -2082,10 +2257,10 @@ static sljit_s32 emit_lea_binary(struct sljit_compiler *compiler, } else if (FAST_IS_REG(src2)) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - if ((src1 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src1w))) { + if (src1 == SLJIT_IMM && (compiler->mode32 || IS_HALFWORD(src1w))) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), (sljit_s32)src1w); #else - if (src1 & SLJIT_IMM) { + if (src1 == SLJIT_IMM) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), src1w); #endif FAIL_IF(!inst); @@ -2109,16 +2284,16 @@ static sljit_s32 emit_cmp_binary(struct sljit_compiler *compiler, sljit_u8* inst; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) { + if (src1 == SLJIT_R0 && src2 == SLJIT_IMM && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) { #else - if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) { + if (src1 == SLJIT_R0 && src2 == SLJIT_IMM && (src2w > 127 || src2w < -128)) { #endif BINARY_EAX_IMM(CMP_EAX_i32, src2w); return SLJIT_SUCCESS; } if (FAST_IS_REG(src1)) { - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { BINARY_IMM(CMP, CMP_rm_r, src2w, src1, 0); } else { @@ -2129,15 +2304,15 @@ static sljit_s32 emit_cmp_binary(struct sljit_compiler *compiler, return SLJIT_SUCCESS; } - if (FAST_IS_REG(src2) && !(src1 & SLJIT_IMM)) { + if (FAST_IS_REG(src2) && src1 != SLJIT_IMM) { inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w); FAIL_IF(!inst); *inst = CMP_rm_r; return SLJIT_SUCCESS; } - if (src2 & SLJIT_IMM) { - if (src1 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { + if (src1 == SLJIT_IMM) { EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); src1 = TMP_REG1; src1w = 0; @@ -2160,25 +2335,25 @@ static sljit_s32 emit_test_binary(struct sljit_compiler *compiler, sljit_u8* inst; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) { + if (src1 == SLJIT_R0 && src2 == SLJIT_IMM && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) { #else - if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) { + if (src1 == SLJIT_R0 && src2 == SLJIT_IMM && (src2w > 127 || src2w < -128)) { #endif BINARY_EAX_IMM(TEST_EAX_i32, src2w); return SLJIT_SUCCESS; } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - if (src2 == SLJIT_R0 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) { + if (src2 == SLJIT_R0 && src1 == SLJIT_IMM && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) { #else - if (src2 == SLJIT_R0 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128)) { + if (src2 == SLJIT_R0 && src1 == SLJIT_IMM && (src1w > 127 || src1w < -128)) { #endif BINARY_EAX_IMM(TEST_EAX_i32, src1w); return SLJIT_SUCCESS; } - if (!(src1 & SLJIT_IMM)) { - if (src2 & SLJIT_IMM) { + if (src1 != SLJIT_IMM) { + if (src2 == SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (IS_HALFWORD(src2w) || compiler->mode32) { inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w); @@ -2206,8 +2381,8 @@ static sljit_s32 emit_test_binary(struct sljit_compiler *compiler, } } - if (!(src2 & SLJIT_IMM)) { - if (src1 & SLJIT_IMM) { + if (src2 != SLJIT_IMM) { + if (src1 == SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (IS_HALFWORD(src1w) || compiler->mode32) { inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, src2w); @@ -2236,7 +2411,7 @@ static sljit_s32 emit_test_binary(struct sljit_compiler *compiler, } EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (IS_HALFWORD(src2w) || compiler->mode32) { inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REG1, 0); @@ -2274,18 +2449,18 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler, #endif sljit_u8* inst; - if ((src2 & SLJIT_IMM) || (src2 == SLJIT_PREF_SHIFT_REG)) { + if (src2 == SLJIT_IMM || src2 == SLJIT_PREF_SHIFT_REG) { if (dst == src1 && dstw == src1w) { inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, dstw); FAIL_IF(!inst); - *inst |= mode; + inst[1] |= mode; return SLJIT_SUCCESS; } if (dst == SLJIT_PREF_SHIFT_REG && src2 == SLJIT_PREF_SHIFT_REG) { EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); FAIL_IF(!inst); - *inst |= mode; + inst[1] |= mode; EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); return SLJIT_SUCCESS; } @@ -2293,14 +2468,14 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler, EMIT_MOV(compiler, dst, 0, src1, src1w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, 0); FAIL_IF(!inst); - *inst |= mode; + inst[1] |= mode; return SLJIT_SUCCESS; } EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REG1, 0); FAIL_IF(!inst); - *inst |= mode; + inst[1] |= mode; EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); return SLJIT_SUCCESS; } @@ -2310,7 +2485,7 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler, EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); FAIL_IF(!inst); - *inst |= mode; + inst[1] |= mode; return emit_mov(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); } @@ -2328,7 +2503,7 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler, EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, dst, 0); FAIL_IF(!inst); - *inst |= mode; + inst[1] |= mode; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 0; #endif @@ -2354,7 +2529,7 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler, EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); FAIL_IF(!inst); - *inst |= mode; + inst[1] |= mode; #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), 0); @@ -2377,7 +2552,7 @@ static sljit_s32 emit_shift_with_flags(struct sljit_compiler *compiler, sljit_s32 src2, sljit_sw src2w) { /* The CPU does not set flags if the shift count is 0. */ - if (src2 & SLJIT_IMM) { + if (src2 == SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) src2w &= compiler->mode32 ? 0x1f : 0x3f; #else /* !SLJIT_CONFIG_X86_64 */ @@ -2442,7 +2617,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_unary(compiler, NEG_rm, dst, dstw, src2, src2w); if (!HAS_FLAGS(op)) { - if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED) + if (src2 == SLJIT_IMM && emit_lea_binary(compiler, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED) return compiler->error; if (FAST_IS_REG(dst) && src2 == dst) { FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), dst, 0, dst, 0, src1, src1w)); @@ -2465,9 +2640,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile dst, dstw, src1, src1w, src2, src2w); case SLJIT_XOR: if (!HAS_FLAGS(op)) { - if ((src2 & SLJIT_IMM) && src2w == -1) + if (src2 == SLJIT_IMM && src2w == -1) return emit_unary(compiler, NOT_rm, dst, dstw, src1, src1w); - if ((src1 & SLJIT_IMM) && src1w == -1) + if (src1 == SLJIT_IMM && src1w == -1) return emit_unary(compiler, NOT_rm, dst, dstw, src2, src2w); } @@ -2553,7 +2728,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * compiler->mode32 = op & SLJIT_32; #endif /* SLJIT_CONFIG_X86_64 */ - if (src3 & SLJIT_IMM) { + if (src3 == SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) src3w &= 0x1f; #else /* !SLJIT_CONFIG_X86_32 */ @@ -2580,7 +2755,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * } #endif /* SLJIT_CONFIG_X86_32 */ - if (dst_reg == SLJIT_PREF_SHIFT_REG && !(src3 & SLJIT_IMM) && (src3 != SLJIT_PREF_SHIFT_REG || src1_reg != SLJIT_PREF_SHIFT_REG)) { + if (dst_reg == SLJIT_PREF_SHIFT_REG && src3 != SLJIT_IMM && (src3 != SLJIT_PREF_SHIFT_REG || src1_reg != SLJIT_PREF_SHIFT_REG)) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) EMIT_MOV(compiler, TMP_REG1, 0, src1_reg, src1w); src1_reg = TMP_REG1; @@ -2605,7 +2780,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * if (src3 != SLJIT_PREF_SHIFT_REG) EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src3, src3w); } else { - if (src2_reg == SLJIT_PREF_SHIFT_REG && !(src3 & SLJIT_IMM) && src3 != SLJIT_PREF_SHIFT_REG) { + if (src2_reg == SLJIT_PREF_SHIFT_REG && src3 != SLJIT_IMM && src3 != SLJIT_PREF_SHIFT_REG) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 0; #endif /* SLJIT_CONFIG_X86_64 */ @@ -2653,7 +2828,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * } #endif /* SLJIT_CONFIG_X86_64 */ - if (!(src3 & SLJIT_IMM) && src3 != SLJIT_PREF_SHIFT_REG) { + if (src3 != SLJIT_IMM && src3 != SLJIT_PREF_SHIFT_REG) { if (!restore_ecx) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 0; @@ -2684,14 +2859,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler * FAIL_IF(!inst); inst[0] = GROUP_0F; - if (src3 & SLJIT_IMM) { + if (src3 == SLJIT_IMM) { inst[1] = U8((is_left ? SHLD : SHRD) - 1); - /* Immedate argument is added separately. */ - inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); - FAIL_IF(!inst); - INC_SIZE(1); - *inst = U8(src3w); + /* Immediate argument is added separately. */ + FAIL_IF(emit_byte(compiler, U8(src3w))); } else inst[1] = U8(is_left ? SHLD : SHRD); @@ -2765,24 +2937,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg) { - CHECK_REG_INDEX(check_sljit_get_register_index(reg)); + CHECK_REG_INDEX(check_sljit_get_register_index(type, reg)); + + if (type == SLJIT_GP_REGISTER) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - if (reg >= SLJIT_R3 && reg <= SLJIT_R8) + if (reg >= SLJIT_R3 && reg <= SLJIT_R8) + return -1; +#endif /* SLJIT_CONFIG_X86_32 */ + return reg_map[reg]; + } + + if (type != SLJIT_FLOAT_REGISTER && type != SLJIT_SIMD_REG_128 && type != SLJIT_SIMD_REG_256 && type != SLJIT_SIMD_REG_512) return -1; -#endif - return reg_map[reg]; -} -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) -{ - CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - return reg; -#else return freg_map[reg]; -#endif } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, @@ -2810,6 +2980,8 @@ static sljit_u32 *sse2_buffer; static void init_compiler(void) { + get_cpu_features(); + /* Align to 16 bytes. */ sse2_buffer = (sljit_u32*)(((sljit_uw)sse2_data + 15) & ~(sljit_uw)0xf); @@ -2823,40 +2995,43 @@ static void init_compiler(void) sse2_buffer[13] = 0x7fffffff; } -static sljit_s32 emit_sse2(struct sljit_compiler *compiler, sljit_u8 opcode, - sljit_s32 single, sljit_s32 xmm1, sljit_s32 xmm2, sljit_sw xmm2w) +static sljit_s32 emit_groupf(struct sljit_compiler *compiler, + sljit_uw op, + sljit_s32 dst, sljit_s32 src, sljit_sw srcw) { - sljit_u8 *inst; - - inst = emit_x86_instruction(compiler, 2 | (single ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, xmm1, 0, xmm2, xmm2w); + sljit_u8 *inst = emit_x86_instruction(compiler, 2 | (op & ~(sljit_uw)0xff), dst, 0, src, srcw); FAIL_IF(!inst); inst[0] = GROUP_0F; - inst[1] = opcode; + inst[1] = op & 0xff; return SLJIT_SUCCESS; } -static sljit_s32 emit_sse2_logic(struct sljit_compiler *compiler, sljit_u8 opcode, - sljit_s32 pref66, sljit_s32 xmm1, sljit_s32 xmm2, sljit_sw xmm2w) +static sljit_s32 emit_groupf_ext(struct sljit_compiler *compiler, + sljit_uw op, + sljit_s32 dst, sljit_s32 src, sljit_sw srcw) { sljit_u8 *inst; - inst = emit_x86_instruction(compiler, 2 | (pref66 ? EX86_PREF_66 : 0) | EX86_SSE2, xmm1, 0, xmm2, xmm2w); + SLJIT_ASSERT((op & EX86_SSE2) && ((op & VEX_OP_0F38) || (op & VEX_OP_0F3A))); + + inst = emit_x86_instruction(compiler, 3 | (op & ~((sljit_uw)0xff | VEX_OP_0F38 | VEX_OP_0F3A)), dst, 0, src, srcw); FAIL_IF(!inst); inst[0] = GROUP_0F; - inst[1] = opcode; + inst[1] = U8((op & VEX_OP_0F38) ? 0x38 : 0x3A); + inst[2] = op & 0xff; return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 emit_sse2_load(struct sljit_compiler *compiler, sljit_s32 single, sljit_s32 dst, sljit_s32 src, sljit_sw srcw) { - return emit_sse2(compiler, MOVSD_x_xm, single, dst, src, srcw); + return emit_groupf(compiler, MOVSD_x_xm | (single ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, dst, src, srcw); } static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler, sljit_s32 single, sljit_s32 dst, sljit_sw dstw, sljit_s32 src) { - return emit_sse2(compiler, MOVSD_xm_x, single, src, dst, dstw); + return emit_groupf(compiler, MOVSD_xm_x | (single ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, src, dst, dstw); } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, @@ -2864,7 +3039,6 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r; - sljit_u8 *inst; CHECK_EXTRA_REGS(dst, dstw, (void)0); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; @@ -2874,10 +3048,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp compiler->mode32 = 0; #endif - inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_32) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP2, dst_r, 0, src, srcw); - FAIL_IF(!inst); - inst[0] = GROUP_0F; - inst[1] = CVTTSD2SI_r_xm; + FAIL_IF(emit_groupf(compiler, CVTTSD2SI_r_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP2, dst_r, src, srcw)); if (dst & SLJIT_MEM) return emit_mov(compiler, dst, dstw, TMP_REG1, 0); @@ -2889,7 +3060,6 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG; - sljit_u8 *inst; CHECK_EXTRA_REGS(src, srcw, (void)0); @@ -2898,7 +3068,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp compiler->mode32 = 0; #endif - if (src & SLJIT_IMM) { + if (src == SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) srcw = (sljit_s32)srcw; @@ -2908,10 +3078,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp srcw = 0; } - inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_32) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP1, dst_r, 0, src, srcw); - FAIL_IF(!inst); - inst[0] = GROUP_0F; - inst[1] = CVTSI2SD_x_rm; + FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, src, srcw)); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 1; @@ -2926,14 +3093,28 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile sljit_s32 src2, sljit_sw src2w) { switch (GET_FLAG_TYPE(op)) { + case SLJIT_ORDERED_EQUAL: + /* Also: SLJIT_UNORDERED_OR_NOT_EQUAL */ + FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w)); + FAIL_IF(emit_groupf(compiler, CMPS_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, TMP_FREG, src2, src2w)); + + /* EQ */ + FAIL_IF(emit_byte(compiler, 0)); + + src1 = TMP_FREG; + src2 = TMP_FREG; + src2w = 0; + break; + case SLJIT_ORDERED_LESS: case SLJIT_UNORDERED_OR_GREATER: + /* Also: SLJIT_UNORDERED_OR_GREATER_EQUAL, SLJIT_ORDERED_LESS_EQUAL */ if (!FAST_IS_REG(src2)) { FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src2, src2w)); src2 = TMP_FREG; } - return emit_sse2_logic(compiler, UCOMISD_x_xm, !(op & SLJIT_32), src2, src1, src1w); + return emit_groupf(compiler, UCOMISD_x_xm | EX86_SELECT_66(op) | EX86_SSE2, src2, src1, src1w); } if (!FAST_IS_REG(src1)) { @@ -2941,7 +3122,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile src1 = TMP_FREG; } - return emit_sse2_logic(compiler, UCOMISD_x_xm, !(op & SLJIT_32), src1, src2, src2w); + return emit_groupf(compiler, UCOMISD_x_xm | EX86_SELECT_66(op) | EX86_SSE2, src1, src2, src2w); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, @@ -2949,6 +3130,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r; + sljit_u8 *inst; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 1; @@ -2972,42 +3154,57 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil /* We overwrite the high bits of source. From SLJIT point of view, this is not an issue. Note: In SSE3, we could also use MOVDDUP and MOVSLDUP. */ - FAIL_IF(emit_sse2_logic(compiler, UNPCKLPD_x_xm, op & SLJIT_32, src, src, 0)); - } - else { + FAIL_IF(emit_groupf(compiler, UNPCKLPD_x_xm | ((op & SLJIT_32) ? EX86_PREF_66 : 0) | EX86_SSE2, src, src, 0)); + } else { FAIL_IF(emit_sse2_load(compiler, !(op & SLJIT_32), TMP_FREG, src, srcw)); src = TMP_FREG; } - FAIL_IF(emit_sse2_logic(compiler, CVTPD2PS_x_xm, op & SLJIT_32, dst_r, src, 0)); + FAIL_IF(emit_groupf(compiler, CVTPD2PS_x_xm | ((op & SLJIT_32) ? EX86_PREF_66 : 0) | EX86_SSE2, dst_r, src, 0)); if (dst_r == TMP_FREG) return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG); return SLJIT_SUCCESS; } if (FAST_IS_REG(dst)) { - dst_r = dst; - if (dst != src) - FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, dst_r, src, srcw)); - } - else { - dst_r = TMP_FREG; - FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, dst_r, src, srcw)); + dst_r = (dst == src) ? TMP_FREG : dst; + + if (src & SLJIT_MEM) + FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src, srcw)); + + FAIL_IF(emit_groupf(compiler, PCMPEQD_x_xm | EX86_PREF_66 | EX86_SSE2, dst_r, dst_r, 0)); + + inst = emit_x86_instruction(compiler, 2 | EX86_PREF_66 | EX86_SSE2_OP2, 0, 0, dst_r, 0); + inst[0] = GROUP_0F; + /* Same as PSRLD_x / PSRLQ_x */ + inst[1] = (op & SLJIT_32) ? PSLLD_x_i8 : PSLLQ_x_i8; + + if (GET_OPCODE(op) == SLJIT_ABS_F64) { + inst[2] |= 2 << 3; + FAIL_IF(emit_byte(compiler, 1)); + } else { + inst[2] |= 6 << 3; + FAIL_IF(emit_byte(compiler, ((op & SLJIT_32) ? 31 : 63))); + } + + if (dst_r != TMP_FREG) + dst_r = (src & SLJIT_MEM) ? TMP_FREG : src; + return emit_groupf(compiler, (GET_OPCODE(op) == SLJIT_NEG_F64 ? XORPD_x_xm : ANDPD_x_xm) | EX86_SSE2, dst, dst_r, 0); } + FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src, srcw)); + switch (GET_OPCODE(op)) { case SLJIT_NEG_F64: - FAIL_IF(emit_sse2_logic(compiler, XORPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_32 ? sse2_buffer : sse2_buffer + 8))); + FAIL_IF(emit_groupf(compiler, XORPD_x_xm | EX86_SELECT_66(op) | EX86_SSE2, TMP_FREG, SLJIT_MEM0(), (sljit_sw)((op & SLJIT_32) ? sse2_buffer : sse2_buffer + 8))); break; case SLJIT_ABS_F64: - FAIL_IF(emit_sse2_logic(compiler, ANDPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_32 ? sse2_buffer + 4 : sse2_buffer + 12))); + FAIL_IF(emit_groupf(compiler, ANDPD_x_xm | EX86_SELECT_66(op) | EX86_SSE2, TMP_FREG, SLJIT_MEM0(), (sljit_sw)((op & SLJIT_32) ? sse2_buffer + 4 : sse2_buffer + 12))); break; } - if (dst_r == TMP_FREG) - return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG); - return SLJIT_SUCCESS; + return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, @@ -3050,19 +3247,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil switch (GET_OPCODE(op)) { case SLJIT_ADD_F64: - FAIL_IF(emit_sse2(compiler, ADDSD_x_xm, op & SLJIT_32, dst_r, src2, src2w)); + FAIL_IF(emit_groupf(compiler, ADDSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, src2, src2w)); break; case SLJIT_SUB_F64: - FAIL_IF(emit_sse2(compiler, SUBSD_x_xm, op & SLJIT_32, dst_r, src2, src2w)); + FAIL_IF(emit_groupf(compiler, SUBSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, src2, src2w)); break; case SLJIT_MUL_F64: - FAIL_IF(emit_sse2(compiler, MULSD_x_xm, op & SLJIT_32, dst_r, src2, src2w)); + FAIL_IF(emit_groupf(compiler, MULSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, src2, src2w)); break; case SLJIT_DIV_F64: - FAIL_IF(emit_sse2(compiler, DIVSD_x_xm, op & SLJIT_32, dst_r, src2, src2w)); + FAIL_IF(emit_groupf(compiler, DIVSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, src2, src2w)); break; } @@ -3071,6 +3268,45 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w) +{ + sljit_uw pref; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fop2r(compiler, op, dst_freg, src1, src1w, src2, src2w)); + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 1; +#endif + + if (dst_freg == src1) { + FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src2, src2w)); + pref = EX86_SELECT_66(op) | EX86_SSE2; + FAIL_IF(emit_groupf(compiler, XORPD_x_xm | pref, TMP_FREG, src1, src1w)); + FAIL_IF(emit_groupf(compiler, ANDPD_x_xm | pref, TMP_FREG, SLJIT_MEM0(), (sljit_sw)((op & SLJIT_32) ? sse2_buffer : sse2_buffer + 8))); + return emit_groupf(compiler, XORPD_x_xm | pref, dst_freg, TMP_FREG, 0); + } + + if (src1 & SLJIT_MEM) { + FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w)); + src1 = TMP_FREG; + src1w = 0; + } + + if (dst_freg != src2) + FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, dst_freg, src2, src2w)); + + pref = EX86_SELECT_66(op) | EX86_SSE2; + FAIL_IF(emit_groupf(compiler, XORPD_x_xm | pref, dst_freg, src1, src1w)); + FAIL_IF(emit_groupf(compiler, ANDPD_x_xm | pref, dst_freg, SLJIT_MEM0(), (sljit_sw)((op & SLJIT_32) ? sse2_buffer : sse2_buffer + 8))); + return emit_groupf(compiler, XORPD_x_xm | pref, dst_freg, src1, src1w); +} + /* --------------------------------------------------------------------- */ /* Conditional instructions */ /* --------------------------------------------------------------------- */ @@ -3090,10 +3326,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi PTR_FAIL_IF(!label); set_label(label, compiler); - inst = (sljit_u8*)ensure_buf(compiler, 2); + inst = (sljit_u8*)ensure_buf(compiler, 1); PTR_FAIL_IF(!inst); - inst[0] = 0; - inst[1] = 0; + inst[0] = SLJIT_INST_LABEL; return label; } @@ -3111,18 +3346,13 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile set_jump(jump, compiler, (sljit_u32)((type & SLJIT_REWRITABLE_JUMP) | ((type & 0xff) << TYPE_SHIFT))); type &= 0xff; + jump->addr = compiler->size; /* Worst case size. */ -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - compiler->size += (type >= SLJIT_JUMP) ? 5 : 6; -#else - compiler->size += (type >= SLJIT_JUMP) ? (10 + 3) : (2 + 10 + 3); -#endif - - inst = (sljit_u8*)ensure_buf(compiler, 2); + compiler->size += (type >= SLJIT_JUMP) ? JUMP_MAX_SIZE : CJUMP_MAX_SIZE; + inst = (sljit_u8*)ensure_buf(compiler, 1); PTR_FAIL_IF_NULL(inst); - inst[0] = 0; - inst[1] = 1; + inst[0] = SLJIT_INST_JUMP; return jump; } @@ -3143,20 +3373,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi set_jump(jump, compiler, (sljit_u32)(JUMP_ADDR | (type << TYPE_SHIFT))); jump->u.target = (sljit_uw)srcw; + jump->addr = compiler->size; /* Worst case size. */ -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - compiler->size += 5; -#else - compiler->size += 10 + 3; -#endif - - inst = (sljit_u8*)ensure_buf(compiler, 2); + compiler->size += JUMP_MAX_SIZE; + inst = (sljit_u8*)ensure_buf(compiler, 1); FAIL_IF_NULL(inst); - inst[0] = 0; - inst[1] = 1; - } - else { + inst[0] = SLJIT_INST_JUMP; + } else { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) /* REX_W is not necessary (src is not immediate). */ compiler->mode32 = 1; @@ -3289,53 +3513,1266 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co #endif /* SLJIT_CONFIG_X86_64 */ } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, - sljit_s32 src, sljit_sw srcw) + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_reg) { - sljit_u8* inst; +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + sljit_s32 dst = dst_reg; + sljit_sw dstw = 0; +#endif /* SLJIT_CONFIG_X86_32 */ + sljit_sw src2w = 0; CHECK_ERROR(); - CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); - -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - type &= ~SLJIT_32; + CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg)); - if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV) || (dst_reg >= SLJIT_R3 && dst_reg <= SLJIT_S3)) - return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw); -#else - if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV)) - return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw); -#endif + ADJUST_LOCAL_OFFSET(src1, src1w); - /* ADJUST_LOCAL_OFFSET is not needed. */ - CHECK_EXTRA_REGS(src, srcw, (void)0); + CHECK_EXTRA_REGS(dst, dstw, (void)0); + CHECK_EXTRA_REGS(src1, src1w, (void)0); + CHECK_EXTRA_REGS(src2_reg, src2w, (void)0); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = type & SLJIT_32; +#endif /* SLJIT_CONFIG_X86_64 */ type &= ~SLJIT_32; -#endif - if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { - EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw); - src = TMP_REG1; - srcw = 0; +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if (dst & SLJIT_MEM) { + if (src1 == SLJIT_IMM || (!(src1 & SLJIT_MEM) && (src2_reg & SLJIT_MEM))) { + EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); + src1 = src2_reg; + src1w = src2w; + type ^= 0x1; + } else + EMIT_MOV(compiler, TMP_REG1, 0, src2_reg, src2w); + + dst_reg = TMP_REG1; + } else { +#endif /* SLJIT_CONFIG_X86_32 */ + if (dst_reg != src2_reg) { + if (dst_reg == src1) { + src1 = src2_reg; + src1w = src2w; + type ^= 0x1; + } else { + if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) { + EMIT_MOV(compiler, dst_reg, 0, src1, src1w); + src1 = src2_reg; + src1w = src2w; + type ^= 0x1; + } else + EMIT_MOV(compiler, dst_reg, 0, src2_reg, src2w); + } + } + + if (SLJIT_UNLIKELY(src1 == SLJIT_IMM)) { + SLJIT_ASSERT(dst_reg != TMP_REG1); + EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); + src1 = TMP_REG1; + src1w = 0; + } +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) } +#endif /* SLJIT_CONFIG_X86_32 */ - inst = emit_x86_instruction(compiler, 2, dst_reg, 0, src, srcw); - FAIL_IF(!inst); - inst[0] = GROUP_0F; - inst[1] = U8(get_jump_code((sljit_uw)type) - 0x40); + if (sljit_has_cpu_feature(SLJIT_HAS_CMOV)) + FAIL_IF(emit_groupf(compiler, U8(get_jump_code((sljit_uw)type) - 0x40), dst_reg, src1, src1w)); + else + FAIL_IF(emit_cmov_generic(compiler, type, dst_reg, src1, src1w)); + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if (dst_reg == TMP_REG1) + return emit_mov(compiler, dst, dstw, TMP_REG1, 0); +#endif /* SLJIT_CONFIG_X86_32 */ return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2_freg) { + sljit_u8* inst; + sljit_uw size; + CHECK_ERROR(); - CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset)); - ADJUST_LOCAL_OFFSET(dst, dstw); + CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg)); - CHECK_EXTRA_REGS(dst, dstw, (void)0); + ADJUST_LOCAL_OFFSET(src1, src1w); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 1; +#endif /* SLJIT_CONFIG_X86_64 */ + + if (dst_freg != src2_freg) { + if (dst_freg == src1) { + src1 = src2_freg; + src1w = 0; + type ^= 0x1; + } else + FAIL_IF(emit_sse2_load(compiler, type & SLJIT_32, dst_freg, src2_freg, 0)); + } + + inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!inst); + INC_SIZE(2); + inst[0] = U8(get_jump_code((sljit_uw)(type & ~SLJIT_32) ^ 0x1) - 0x10); + + size = compiler->size; + FAIL_IF(emit_sse2_load(compiler, type & SLJIT_32, dst_freg, src1, src1w)); + + inst[1] = U8(compiler->size - size); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 srcdst, sljit_sw srcdstw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_s32 alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type); + sljit_uw op; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw)); + + ADJUST_LOCAL_OFFSET(srcdst, srcdstw); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 1; +#endif /* SLJIT_CONFIG_X86_64 */ + + switch (reg_size) { + case 4: + op = EX86_SSE2; + break; + case 5: + if (!(cpu_feature_list & CPU_FEATURE_AVX2)) + return SLJIT_ERR_UNSUPPORTED; + op = EX86_SSE2 | VEX_256; + break; + default: + return SLJIT_ERR_UNSUPPORTED; + } + + if (!(srcdst & SLJIT_MEM)) + alignment = reg_size; + + if (type & SLJIT_SIMD_FLOAT) { + if (elem_size == 2 || elem_size == 3) { + op |= alignment >= reg_size ? MOVAPS_x_xm : MOVUPS_x_xm; + + if (elem_size == 3) + op |= EX86_PREF_66; + + if (type & SLJIT_SIMD_STORE) + op += 1; + } else + return SLJIT_ERR_UNSUPPORTED; + } else { + op |= ((type & SLJIT_SIMD_STORE) ? MOVDQA_xm_x : MOVDQA_x_xm) + | (alignment >= reg_size ? EX86_PREF_66 : EX86_PREF_F3); + } + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (op & VEX_256) + return emit_vex_instruction(compiler, op, freg, 0, srcdst, srcdstw); + + return emit_groupf(compiler, op, freg, srcdst, srcdstw); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_u8 *inst; + sljit_u8 opcode = 0; + sljit_uw size; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw)); + + ADJUST_LOCAL_OFFSET(src, srcw); + + if (!(type & SLJIT_SIMD_FLOAT)) { + CHECK_EXTRA_REGS(src, srcw, (void)0); + } + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2)) + return SLJIT_ERR_UNSUPPORTED; +#else /* !SLJIT_CONFIG_X86_32 */ + compiler->mode32 = 1; + + if (elem_size > 3 || ((type & SLJIT_SIMD_FLOAT) && elem_size < 2)) + return SLJIT_ERR_UNSUPPORTED; +#endif /* SLJIT_CONFIG_X86_32 */ + + if (cpu_feature_list & CPU_FEATURE_AVX2) { + if (reg_size < 4 || reg_size > 5) + return SLJIT_ERR_UNSUPPORTED; + + if (src != SLJIT_IMM && (reg_size == 5 || elem_size < 3 || !(type & SLJIT_SIMD_FLOAT))) { + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (!(src & SLJIT_MEM) && !(type & SLJIT_SIMD_FLOAT)) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (elem_size >= 3) + compiler->mode32 = 0; +#endif /* SLJIT_CONFIG_X86_64 */ + FAIL_IF(emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, freg, src, srcw)); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 1; +#endif /* SLJIT_CONFIG_X86_64 */ + src = freg; + srcw = 0; + } + + switch (elem_size) { + case 0: + size = VPBROADCASTB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2; + break; + case 1: + size = VPBROADCASTW_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2; + break; + case 2: + size = ((type & SLJIT_SIMD_FLOAT) ? VBROADCASTSS_x_xm : VPBROADCASTD_x_xm) | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2; + break; + default: +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + size = VBROADCASTSD_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2; +#else /* !SLJIT_CONFIG_X86_32 */ + size = ((type & SLJIT_SIMD_FLOAT) ? VBROADCASTSD_x_xm : VPBROADCASTQ_x_xm) | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2; +#endif /* SLJIT_CONFIG_X86_32 */ + break; + } + + if (reg_size == 5) + size |= VEX_256; + + return emit_vex_instruction(compiler, size, freg, 0, src, srcw); + } + } else if (reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (type & SLJIT_SIMD_FLOAT) { + if (src == SLJIT_IMM) { + if (reg_size == 5) + return emit_vex_instruction(compiler, XORPD_x_xm | VEX_256 | (elem_size == 3 ? EX86_PREF_66 : 0) | EX86_SSE2 | VEX_SSE2_OPV, freg, freg, freg, 0); + + return emit_groupf(compiler, XORPD_x_xm | (elem_size == 3 ? EX86_PREF_66 : 0) | EX86_SSE2, freg, freg, 0); + } + + if (elem_size == 2 && freg != src) { + FAIL_IF(emit_sse2_load(compiler, 1, freg, src, srcw)); + src = freg; + srcw = 0; + } + + FAIL_IF(emit_groupf(compiler, (elem_size == 2 ? SHUFPS_x_xm : MOVDDUP_x_xm) | (elem_size == 2 ? 0 : EX86_PREF_F2) | EX86_SSE2, freg, src, srcw)); + + if (elem_size == 2) + return emit_byte(compiler, 0); + return SLJIT_SUCCESS; + } + + if (src == SLJIT_IMM) { + if (elem_size == 0) { + srcw = (sljit_u8)srcw; + srcw |= srcw << 8; + srcw |= srcw << 16; + elem_size = 2; + } else if (elem_size == 1) { + srcw = (sljit_u16)srcw; + srcw |= srcw << 16; + elem_size = 2; + } + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (elem_size == 2 && (sljit_s32)srcw == -1) + srcw = -1; +#endif /* SLJIT_CONFIG_X86_64 */ + + if (srcw == 0 || srcw == -1) { + if (reg_size == 5) + return emit_vex_instruction(compiler, (srcw == 0 ? PXOR_x_xm : PCMPEQD_x_xm) | VEX_256 | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, freg, freg, freg, 0); + + return emit_groupf(compiler, (srcw == 0 ? PXOR_x_xm : PCMPEQD_x_xm) | EX86_PREF_66 | EX86_SSE2, freg, freg, 0); + } + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (elem_size == 3) + FAIL_IF(emit_load_imm64(compiler, TMP_REG1, srcw)); + else +#endif /* SLJIT_CONFIG_X86_64 */ + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw); + + src = TMP_REG1; + srcw = 0; + } + + size = 2; + opcode = MOVD_x_rm; + + switch (elem_size) { + case 0: + if (!FAST_IS_REG(src)) { + opcode = 0x3a /* Prefix of PINSRB_x_rm_i8. */; + size = 3; + } + break; + case 1: + if (!FAST_IS_REG(src)) + opcode = PINSRW_x_rm_i8; + break; + case 2: + break; +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + case 3: + /* MOVQ */ + compiler->mode32 = 0; + break; +#endif /* SLJIT_CONFIG_X86_64 */ + } + + inst = emit_x86_instruction(compiler, size | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, src, srcw); + FAIL_IF(!inst); + inst[0] = GROUP_0F; + inst[1] = opcode; + + if (reg_size == 5) { + SLJIT_ASSERT(opcode == MOVD_x_rm); +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + size = VPBROADCASTD_x_xm; +#else /* !SLJIT_CONFIG_X86_32 */ + size = (elem_size == 3) ? VPBROADCASTQ_x_xm : VPBROADCASTD_x_xm; +#endif /* SLJIT_CONFIG_X86_32 */ + return emit_vex_instruction(compiler, size | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, freg, 0); + } + + if (size == 3) { + SLJIT_ASSERT(opcode == 0x3a); + inst[2] = PINSRB_x_rm_i8; + } + + if (opcode != MOVD_x_rm) + FAIL_IF(emit_byte(compiler, 0)); + + switch (elem_size) { + case 0: + FAIL_IF(emit_groupf(compiler, PXOR_x_xm | EX86_PREF_66 | EX86_SSE2, TMP_FREG, TMP_FREG, 0)); + return emit_groupf_ext(compiler, PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, TMP_FREG, 0); + case 1: + FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | EX86_PREF_F2 | EX86_SSE2, freg, freg, 0)); + FAIL_IF(emit_byte(compiler, 0)); + /* fallthrough */ + default: + FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, freg, freg, 0)); + return emit_byte(compiler, 0); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + case 3: + compiler->mode32 = 1; + FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, freg, freg, 0)); + return emit_byte(compiler, 0x44); +#endif /* SLJIT_CONFIG_X86_64 */ + } +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, sljit_s32 lane_index, + sljit_s32 srcdst, sljit_sw srcdstw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_u8 *inst; + sljit_u8 opcode = 0; + sljit_uw size; + sljit_s32 freg_orig = freg; +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + sljit_s32 srcdst_is_ereg = 0; + sljit_s32 srcdst_orig = 0; + sljit_sw srcdstw_orig = 0; +#endif /* SLJIT_CONFIG_X86_32 */ + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw)); + + ADJUST_LOCAL_OFFSET(srcdst, srcdstw); + + if (reg_size == 5) { + if (!(cpu_feature_list & CPU_FEATURE_AVX2)) + return SLJIT_ERR_UNSUPPORTED; + } else if (reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : elem_size > 2) + return SLJIT_ERR_UNSUPPORTED; +#else /* SLJIT_CONFIG_X86_32 */ + if (elem_size > 3 || ((type & SLJIT_SIMD_FLOAT) && elem_size < 2)) + return SLJIT_ERR_UNSUPPORTED; +#endif /* SLJIT_CONFIG_X86_32 */ + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 1; +#else /* !SLJIT_CONFIG_X86_64 */ + if (!(type & SLJIT_SIMD_FLOAT)) { + CHECK_EXTRA_REGS(srcdst, srcdstw, srcdst_is_ereg = 1); + + if ((type & SLJIT_SIMD_STORE) && ((srcdst_is_ereg && elem_size < 2) || (elem_size == 0 && (type & SLJIT_SIMD_LANE_SIGNED) && FAST_IS_REG(srcdst) && reg_map[srcdst] >= 4))) { + srcdst_orig = srcdst; + srcdstw_orig = srcdstw; + srcdst = TMP_REG1; + srcdstw = 0; + } + } +#endif /* SLJIT_CONFIG_X86_64 */ + + if (type & SLJIT_SIMD_LANE_ZERO) { + if (lane_index == 0) { + if (!(type & SLJIT_SIMD_FLOAT)) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (elem_size == 3) { + compiler->mode32 = 0; + elem_size = 2; + } +#endif /* SLJIT_CONFIG_X86_64 */ + if (srcdst == SLJIT_IMM) { + if (elem_size == 0) + srcdstw = (sljit_u8)srcdstw; + else if (elem_size == 1) + srcdstw = (sljit_u16)srcdstw; + + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcdstw); + srcdst = TMP_REG1; + srcdstw = 0; + elem_size = 2; + } + + if (elem_size == 2) { + if (reg_size == 4) + return emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, freg, srcdst, srcdstw); + return emit_vex_instruction(compiler, MOVD_x_rm | VEX_AUTO_W | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, srcdst, srcdstw); + } + } else if (srcdst & SLJIT_MEM) { + SLJIT_ASSERT(elem_size == 2 || elem_size == 3); + + if (reg_size == 4) + return emit_groupf(compiler, MOVSD_x_xm | (elem_size == 2 ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, freg, srcdst, srcdstw); + return emit_vex_instruction(compiler, MOVSD_x_xm | (elem_size == 2 ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, freg, 0, srcdst, srcdstw); + } else if (elem_size == 3) { + if (reg_size == 4) + return emit_groupf(compiler, MOVQ_x_xm | EX86_PREF_F3 | EX86_SSE2, freg, srcdst, 0); + return emit_vex_instruction(compiler, MOVQ_x_xm | EX86_PREF_F3 | EX86_SSE2, freg, 0, srcdst, 0); + } + } + + if (reg_size == 5 && lane_index >= (1 << (4 - elem_size))) { + freg = TMP_FREG; + lane_index -= (1 << (4 - elem_size)); + } else if ((type & SLJIT_SIMD_FLOAT) && freg == srcdst) { + FAIL_IF(emit_sse2_load(compiler, elem_size == 2, TMP_FREG, srcdst, srcdstw)); + srcdst = TMP_FREG; + srcdstw = 0; + } + + size = ((!(type & SLJIT_SIMD_FLOAT) || elem_size != 2) ? EX86_PREF_66 : 0) + | ((type & SLJIT_SIMD_FLOAT) ? XORPD_x_xm : PXOR_x_xm) | EX86_SSE2; + + if (reg_size == 5) + FAIL_IF(emit_vex_instruction(compiler, size | VEX_256 | VEX_SSE2_OPV, freg, freg, freg, 0)); + else + FAIL_IF(emit_groupf(compiler, size, freg, freg, 0)); + } else if (reg_size == 5 && lane_index >= (1 << (4 - elem_size))) { + FAIL_IF(emit_vex_instruction(compiler, ((type & SLJIT_SIMD_FLOAT) ? VEXTRACTF128_x_ym : VEXTRACTI128_x_ym) | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, freg, 0, TMP_FREG, 0)); + FAIL_IF(emit_byte(compiler, 1)); + + freg = TMP_FREG; + lane_index -= (1 << (4 - elem_size)); + } + + if (type & SLJIT_SIMD_FLOAT) { + if (elem_size == 3) { + if (srcdst & SLJIT_MEM) { + if (type & SLJIT_SIMD_STORE) + size = lane_index == 0 ? MOVLPD_m_x : MOVHPD_m_x; + else + size = lane_index == 0 ? MOVLPD_x_m : MOVHPD_x_m; + + FAIL_IF(emit_groupf(compiler, size | EX86_PREF_66 | EX86_SSE2, freg, srcdst, srcdstw)); + + /* In case of store, freg is not TMP_FREG. */ + } else if (type & SLJIT_SIMD_STORE) { + if (lane_index == 1) + return emit_groupf(compiler, MOVHLPS_x_x | EX86_SSE2, srcdst, freg, 0); + return emit_sse2_load(compiler, 0, srcdst, freg, 0); + } else { + if (lane_index == 1) + FAIL_IF(emit_groupf(compiler, MOVLHPS_x_x | EX86_SSE2, freg, srcdst, 0)); + else + FAIL_IF(emit_sse2_store(compiler, 0, freg, 0, srcdst)); + } + } else if (type & SLJIT_SIMD_STORE) { + if (lane_index == 0) + return emit_sse2_store(compiler, 1, srcdst, srcdstw, freg); + + if (srcdst & SLJIT_MEM) { + FAIL_IF(emit_groupf_ext(compiler, EXTRACTPS_x_xm | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, freg, srcdst, srcdstw)); + return emit_byte(compiler, U8(lane_index)); + } + + if (srcdst == freg) + size = SHUFPS_x_xm | EX86_SSE2; + else { + if (cpu_feature_list & CPU_FEATURE_AVX) { + FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | EX86_SSE2 | VEX_SSE2_OPV, srcdst, freg, freg, 0)); + return emit_byte(compiler, U8(lane_index)); + } + + switch (lane_index) { + case 1: + size = MOVSHDUP_x_xm | EX86_PREF_F3 | EX86_SSE2; + break; + case 2: + size = MOVHLPS_x_x | EX86_SSE2; + break; + default: + SLJIT_ASSERT(lane_index == 3); + size = PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2; + break; + } + } + + FAIL_IF(emit_groupf(compiler, size, srcdst, freg, 0)); + + size &= 0xff; + if (size == SHUFPS_x_xm || size == PSHUFD_x_xm) + return emit_byte(compiler, U8(lane_index)); + + return SLJIT_SUCCESS; + } else { + if (lane_index != 0 || (srcdst & SLJIT_MEM)) { + FAIL_IF(emit_groupf_ext(compiler, INSERTPS_x_xm | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, freg, srcdst, srcdstw)); + FAIL_IF(emit_byte(compiler, U8(lane_index << 4))); + } else + FAIL_IF(emit_sse2_store(compiler, 1, freg, 0, srcdst)); + } + + if (freg != TMP_FREG || (type & SLJIT_SIMD_STORE)) + return SLJIT_SUCCESS; + + SLJIT_ASSERT(reg_size == 5); + + if (type & SLJIT_SIMD_LANE_ZERO) { + FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg_orig, 0, TMP_FREG, 0)); + return emit_byte(compiler, 0x4e); + } + + FAIL_IF(emit_vex_instruction(compiler, VINSERTF128_y_y_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2 | VEX_SSE2_OPV, freg_orig, freg_orig, TMP_FREG, 0)); + return emit_byte(compiler, 1); + } + + if (srcdst == SLJIT_IMM) { + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcdstw); + srcdst = TMP_REG1; + srcdstw = 0; + } + + size = 3; + + switch (elem_size) { + case 0: + opcode = (type & SLJIT_SIMD_STORE) ? PEXTRB_rm_x_i8 : PINSRB_x_rm_i8; + break; + case 1: + if (!(type & SLJIT_SIMD_STORE)) { + size = 2; + opcode = PINSRW_x_rm_i8; + } else + opcode = PEXTRW_rm_x_i8; + break; + case 2: + opcode = (type & SLJIT_SIMD_STORE) ? PEXTRD_rm_x_i8 : PINSRD_x_rm_i8; + break; +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + case 3: + /* PINSRQ / PEXTRQ */ + opcode = (type & SLJIT_SIMD_STORE) ? PEXTRD_rm_x_i8 : PINSRD_x_rm_i8; + compiler->mode32 = 0; + break; +#endif /* SLJIT_CONFIG_X86_64 */ + } + + inst = emit_x86_instruction(compiler, size | EX86_PREF_66 | EX86_SSE2_OP1, freg, 0, srcdst, srcdstw); + FAIL_IF(!inst); + inst[0] = GROUP_0F; + + if (size == 3) { + inst[1] = 0x3a; + inst[2] = opcode; + } else + inst[1] = opcode; + + FAIL_IF(emit_byte(compiler, U8(lane_index))); + + if (!(type & SLJIT_SIMD_LANE_SIGNED) || (srcdst & SLJIT_MEM)) { + if (freg == TMP_FREG && !(type & SLJIT_SIMD_STORE)) { + SLJIT_ASSERT(reg_size == 5); + + if (type & SLJIT_SIMD_LANE_ZERO) { + FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg_orig, 0, TMP_FREG, 0)); + return emit_byte(compiler, 0x4e); + } + + FAIL_IF(emit_vex_instruction(compiler, VINSERTI128_y_y_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2 | VEX_SSE2_OPV, freg_orig, freg_orig, TMP_FREG, 0)); + return emit_byte(compiler, 1); + } + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if (srcdst_orig & SLJIT_MEM) + return emit_mov(compiler, srcdst_orig, srcdstw_orig, TMP_REG1, 0); +#endif /* SLJIT_CONFIG_X86_32 */ + return SLJIT_SUCCESS; + } + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (elem_size >= 3) + return SLJIT_SUCCESS; + + compiler->mode32 = (type & SLJIT_32); + + size = 2; + + if (elem_size == 0) + size |= EX86_REX; + + if (elem_size == 2) { + if (type & SLJIT_32) + return SLJIT_SUCCESS; + + SLJIT_ASSERT(!(compiler->mode32)); + size = 1; + } + + inst = emit_x86_instruction(compiler, size, srcdst, 0, srcdst, 0); + FAIL_IF(!inst); + + if (size != 1) { + inst[0] = GROUP_0F; + inst[1] = U8((elem_size == 0) ? MOVSX_r_rm8 : MOVSX_r_rm16); + } else + inst[0] = MOVSXD_r_rm; +#else /* !SLJIT_CONFIG_X86_64 */ + if (elem_size >= 2) + return SLJIT_SUCCESS; + + FAIL_IF(emit_groupf(compiler, (elem_size == 0) ? MOVSX_r_rm8 : MOVSX_r_rm16, + (srcdst_orig != 0 && FAST_IS_REG(srcdst_orig)) ? srcdst_orig : srcdst, srcdst, 0)); + + if (srcdst_orig & SLJIT_MEM) + return emit_mov(compiler, srcdst_orig, srcdstw_orig, TMP_REG1, 0); +#endif /* SLJIT_CONFIG_X86_64 */ + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_s32 src_lane_index) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_uw pref; + sljit_u8 byte; +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + sljit_s32 opcode3 = TMP_REG1; +#else /* !SLJIT_CONFIG_X86_32 */ + sljit_s32 opcode3 = SLJIT_S0; +#endif /* SLJIT_CONFIG_X86_32 */ + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index)); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 1; +#endif /* SLJIT_CONFIG_X86_64 */ + SLJIT_ASSERT(reg_map[opcode3] == 3); + + if (reg_size == 5) { + if (!(cpu_feature_list & CPU_FEATURE_AVX2)) + return SLJIT_ERR_UNSUPPORTED; + } else if (reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_FLOAT) { + pref = 0; + byte = U8(src_lane_index); + + if (elem_size == 3) { + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 5) { + if (src_lane_index == 0) + return emit_vex_instruction(compiler, VBROADCASTSD_x_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, src, 0); + + FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg, 0, src, 0)); + + byte = U8(byte | (byte << 2)); + return emit_byte(compiler, U8(byte | (byte << 4))); + } + + if (src_lane_index == 0) + return emit_groupf(compiler, MOVDDUP_x_xm | EX86_PREF_F2 | EX86_SSE2, freg, src, 0); + + /* Changes it to SHUFPD_x_xm. */ + pref = EX86_PREF_66; + } else if (elem_size != 2) + return SLJIT_ERR_UNSUPPORTED; + else if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 5) { + SLJIT_ASSERT(elem_size == 2); + + if (src_lane_index == 0) + return emit_vex_instruction(compiler, VBROADCASTSS_x_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, src, 0); + + FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg, 0, src, 0)); + + byte = 0x44; + if (src_lane_index >= 4) { + byte = 0xee; + src_lane_index -= 4; + } + + FAIL_IF(emit_byte(compiler, byte)); + FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | VEX_256 | pref | EX86_SSE2 | VEX_SSE2_OPV, freg, freg, freg, 0)); + byte = U8(src_lane_index); + } else if (freg != src && (cpu_feature_list & CPU_FEATURE_AVX)) { + FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | pref | EX86_SSE2 | VEX_SSE2_OPV, freg, src, src, 0)); + } else { + if (freg != src) + FAIL_IF(emit_groupf(compiler, MOVAPS_x_xm | pref | EX86_SSE2, freg, src, 0)); + + FAIL_IF(emit_groupf(compiler, SHUFPS_x_xm | pref | EX86_SSE2, freg, freg, 0)); + } + + if (elem_size == 2) { + byte = U8(byte | (byte << 2)); + byte = U8(byte | (byte << 4)); + } else + byte = U8(byte | (byte << 1)); + + return emit_byte(compiler, U8(byte)); + } + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (elem_size == 0) { + if (reg_size == 5 && src_lane_index >= 16) { + FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg, 0, src, 0)); + FAIL_IF(emit_byte(compiler, src_lane_index >= 24 ? 0xff : 0xaa)); + src_lane_index &= 0x7; + src = freg; + } + + if ((freg != src && !(cpu_feature_list & CPU_FEATURE_AVX2)) || src_lane_index != 0) { + pref = 0; + + if ((src_lane_index & 0x3) == 0) { + pref = EX86_PREF_66; + byte = U8(src_lane_index >> 2); + } else if (src_lane_index < 8 && (src_lane_index & 0x1) == 0) { + pref = EX86_PREF_F2; + byte = U8(src_lane_index >> 1); + } else { + if (freg == src || !(cpu_feature_list & CPU_FEATURE_AVX2)) { + if (freg != src) + FAIL_IF(emit_groupf(compiler, MOVDQA_x_xm | EX86_PREF_66 | EX86_SSE2, freg, src, 0)); + + FAIL_IF(emit_groupf(compiler, PSRLDQ_x | EX86_PREF_66 | EX86_SSE2_OP2, opcode3, freg, 0)); + } else + FAIL_IF(emit_vex_instruction(compiler, PSRLDQ_x | EX86_PREF_66 | EX86_SSE2_OP2 | VEX_SSE2_OPV, opcode3, freg, src, 0)); + + FAIL_IF(emit_byte(compiler, U8(src_lane_index))); + } + + if (pref != 0) { + FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, freg, src, 0)); + FAIL_IF(emit_byte(compiler, byte)); + } + + src = freg; + } + + if (cpu_feature_list & CPU_FEATURE_AVX2) + return emit_vex_instruction(compiler, VPBROADCASTB_x_xm | (reg_size == 5 ? VEX_256 : 0) | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, src, 0); + + SLJIT_ASSERT(reg_size == 4); + FAIL_IF(emit_groupf(compiler, PXOR_x_xm | EX86_PREF_66 | EX86_SSE2, TMP_FREG, TMP_FREG, 0)); + return emit_groupf_ext(compiler, PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, TMP_FREG, 0); + } + + if ((cpu_feature_list & CPU_FEATURE_AVX2) && src_lane_index == 0 && elem_size <= 3) { + switch (elem_size) { + case 1: + pref = VPBROADCASTW_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2; + break; + case 2: + pref = VPBROADCASTD_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2; + break; + default: + pref = VPBROADCASTQ_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2; + break; + } + + if (reg_size == 5) + pref |= VEX_256; + + return emit_vex_instruction(compiler, pref, freg, 0, src, 0); + } + + if (reg_size == 5) { + switch (elem_size) { + case 1: + byte = U8(src_lane_index & 0x3); + src_lane_index >>= 2; + pref = PSHUFLW_x_xm | VEX_256 | ((src_lane_index & 1) == 0 ? EX86_PREF_F2 : EX86_PREF_F3) | EX86_SSE2; + break; + case 2: + byte = U8(src_lane_index & 0x3); + src_lane_index >>= 1; + pref = PSHUFD_x_xm | VEX_256 | EX86_PREF_66 | EX86_SSE2; + break; + case 3: + pref = 0; + break; + default: + FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg, 0, src, 0)); + return emit_byte(compiler, U8(src_lane_index == 0 ? 0x44 : 0xee)); + } + + if (pref != 0) { + FAIL_IF(emit_vex_instruction(compiler, pref, freg, 0, src, 0)); + byte = U8(byte | (byte << 2)); + FAIL_IF(emit_byte(compiler, U8(byte | (byte << 4)))); + + if (src_lane_index == 0) + return emit_vex_instruction(compiler, VPBROADCASTQ_x_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, freg, 0); + + src = freg; + } + + FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, freg, 0, src, 0)); + byte = U8(src_lane_index); + byte = U8(byte | (byte << 2)); + return emit_byte(compiler, U8(byte | (byte << 4))); + } + + switch (elem_size) { + case 1: + byte = U8(src_lane_index & 0x3); + src_lane_index >>= 1; + pref = (src_lane_index & 2) == 0 ? EX86_PREF_F2 : EX86_PREF_F3; + + FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, freg, src, 0)); + byte = U8(byte | (byte << 2)); + FAIL_IF(emit_byte(compiler, U8(byte | (byte << 4)))); + + if ((cpu_feature_list & CPU_FEATURE_AVX2) && pref == EX86_PREF_F2) + return emit_vex_instruction(compiler, VPBROADCASTD_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, freg, 0); + + src = freg; + /* fallthrough */ + case 2: + byte = U8(src_lane_index); + byte = U8(byte | (byte << 2)); + break; + default: + byte = U8(src_lane_index << 1); + byte = U8(byte | (byte << 2) | 0x4); + break; + } + + FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, freg, src, 0)); + return emit_byte(compiler, U8(byte | (byte << 4))); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type); + sljit_u8 opcode; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw)); + + ADJUST_LOCAL_OFFSET(src, srcw); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 1; +#endif /* SLJIT_CONFIG_X86_64 */ + + if (reg_size == 5) { + if (!(cpu_feature_list & CPU_FEATURE_AVX2)) + return SLJIT_ERR_UNSUPPORTED; + } else if (reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_FLOAT) { + if (elem_size != 2 || elem2_size != 3) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 4) + return emit_groupf(compiler, CVTPS2PD_x_xm | EX86_SSE2, freg, src, srcw); + return emit_vex_instruction(compiler, CVTPS2PD_x_xm | VEX_256 | EX86_SSE2, freg, 0, src, srcw); + } + + switch (elem_size) { + case 0: + if (elem2_size == 1) + opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXBW_x_xm : PMOVZXBW_x_xm; + else if (elem2_size == 2) + opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXBD_x_xm : PMOVZXBD_x_xm; + else if (elem2_size == 3) + opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXBQ_x_xm : PMOVZXBQ_x_xm; + else + return SLJIT_ERR_UNSUPPORTED; + break; + case 1: + if (elem2_size == 2) + opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXWD_x_xm : PMOVZXWD_x_xm; + else if (elem2_size == 3) + opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXWQ_x_xm : PMOVZXWQ_x_xm; + else + return SLJIT_ERR_UNSUPPORTED; + break; + case 2: + if (elem2_size == 3) + opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXDQ_x_xm : PMOVZXDQ_x_xm; + else + return SLJIT_ERR_UNSUPPORTED; + break; + default: + return SLJIT_ERR_UNSUPPORTED; + } + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + if (reg_size == 4) + return emit_groupf_ext(compiler, opcode | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, src, srcw); + return emit_vex_instruction(compiler, opcode | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, freg, 0, src, srcw); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 dst, sljit_sw dstw) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_s32 dst_r; + sljit_uw pref; + sljit_u8 *inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw)); + + ADJUST_LOCAL_OFFSET(dst, dstw); + + CHECK_EXTRA_REGS(dst, dstw, (void)0); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 1; +#endif /* SLJIT_CONFIG_X86_64 */ + + if (elem_size > 3 || ((type & SLJIT_SIMD_FLOAT) && elem_size < 2)) + return SLJIT_ERR_UNSUPPORTED; + + if (reg_size == 4) { + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + pref = EX86_PREF_66 | EX86_SSE2_OP2; + + switch (elem_size) { + case 1: + FAIL_IF(emit_groupf(compiler, PACKSSWB_x_xm | EX86_PREF_66 | EX86_SSE2, TMP_FREG, freg, 0)); + freg = TMP_FREG; + break; + case 2: + pref = EX86_SSE2_OP2; + break; + } + + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; + FAIL_IF(emit_groupf(compiler, (elem_size < 2 ? PMOVMSKB_r_x : MOVMSKPS_r_x) | pref, dst_r, freg, 0)); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = type & SLJIT_32; +#endif /* SLJIT_CONFIG_X86_64 */ + + if (elem_size == 1) { + inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 8, dst_r, 0); + FAIL_IF(!inst); + inst[1] |= SHR; + } + + if (dst_r == TMP_REG1) + return emit_mov(compiler, dst, dstw, TMP_REG1, 0); + + return SLJIT_SUCCESS; + } + + if (reg_size != 5 || !(cpu_feature_list & CPU_FEATURE_AVX2)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; + + if (elem_size == 1) { + FAIL_IF(emit_vex_instruction(compiler, VEXTRACTI128_x_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, freg, 0, TMP_FREG, 0)); + FAIL_IF(emit_byte(compiler, 1)); + FAIL_IF(emit_vex_instruction(compiler, PACKSSWB_x_xm | VEX_256 | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, freg, TMP_FREG, 0)); + FAIL_IF(emit_groupf(compiler, PMOVMSKB_r_x | EX86_PREF_66 | EX86_SSE2_OP2, dst_r, TMP_FREG, 0)); + } else { + pref = MOVMSKPS_r_x | VEX_256 | EX86_SSE2_OP2; + + if (elem_size == 0) + pref = PMOVMSKB_r_x | VEX_256 | EX86_PREF_66 | EX86_SSE2_OP2; + else if (elem_size == 3) + pref |= EX86_PREF_66; + + FAIL_IF(emit_vex_instruction(compiler, pref, dst_r, 0, freg, 0)); + } + + if (dst_r == TMP_REG1) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = type & SLJIT_32; +#endif /* SLJIT_CONFIG_X86_64 */ + return emit_mov(compiler, dst, dstw, TMP_REG1, 0); + } + + return SLJIT_SUCCESS; +} + +static sljit_s32 emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, sljit_s32 src_freg) +{ + sljit_uw op = ((type & SLJIT_SIMD_FLOAT) ? MOVAPS_x_xm : MOVDQA_x_xm) | EX86_SSE2; + + SLJIT_ASSERT(SLJIT_SIMD_GET_REG_SIZE(type) == 4); + + if (!(type & SLJIT_SIMD_FLOAT) || SLJIT_SIMD_GET_ELEM_SIZE(type) == 3) + op |= EX86_PREF_66; + + return emit_groupf(compiler, op, dst_freg, src_freg, 0); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg) +{ + sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type); + sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type); + sljit_s32 needs_move = 0; + sljit_uw op = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg)); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 1; +#endif /* SLJIT_CONFIG_X86_64 */ + + if (reg_size == 5) { + if (!(cpu_feature_list & CPU_FEATURE_AVX2)) + return SLJIT_ERR_UNSUPPORTED; + } else if (reg_size != 4) + return SLJIT_ERR_UNSUPPORTED; + + if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3)) + return SLJIT_ERR_UNSUPPORTED; + + switch (SLJIT_SIMD_GET_OPCODE(type)) { + case SLJIT_SIMD_OP2_AND: + op = (type & SLJIT_SIMD_FLOAT) ? ANDPD_x_xm : PAND_x_xm; + + if (!(type & SLJIT_SIMD_FLOAT) || elem_size == 3) + op |= EX86_PREF_66; + break; + case SLJIT_SIMD_OP2_OR: + op = (type & SLJIT_SIMD_FLOAT) ? ORPD_x_xm : POR_x_xm; + + if (!(type & SLJIT_SIMD_FLOAT) || elem_size == 3) + op |= EX86_PREF_66; + break; + case SLJIT_SIMD_OP2_XOR: + op = (type & SLJIT_SIMD_FLOAT) ? XORPD_x_xm : PXOR_x_xm; + + if (!(type & SLJIT_SIMD_FLOAT) || elem_size == 3) + op |= EX86_PREF_66; + break; + } + + if (type & SLJIT_SIMD_TEST) + return SLJIT_SUCCESS; + + needs_move = dst_freg != src1_freg && dst_freg != src2_freg; + + if (reg_size == 5 || (needs_move && (cpu_feature_list & CPU_FEATURE_AVX2))) { + if (reg_size == 5) + op |= VEX_256; + + return emit_vex_instruction(compiler, op | EX86_SSE2 | VEX_SSE2_OPV, dst_freg, src1_freg, src2_freg, 0); + } + + if (needs_move) { + FAIL_IF(emit_simd_mov(compiler, type, dst_freg, src1_freg)); + } else if (dst_freg != src1_freg) { + SLJIT_ASSERT(dst_freg == src2_freg); + src2_freg = src1_freg; + } + + FAIL_IF(emit_groupf(compiler, op | EX86_SSE2, dst_freg, src2_freg, 0)); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst_reg, + sljit_s32 mem_reg) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg)); + + SLJIT_SKIP_CHECKS(compiler); + return sljit_emit_op1(compiler, op, dst_reg, 0, SLJIT_MEM1(mem_reg), 0); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src_reg, + sljit_s32 mem_reg, + sljit_s32 temp_reg) +{ + sljit_uw pref; + sljit_s32 free_reg = TMP_REG1; +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + sljit_sw srcw = 0; + sljit_sw tempw = 0; +#endif /* SLJIT_CONFIG_X86_32 */ + + CHECK_ERROR(); + CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg)); + CHECK_EXTRA_REGS(src_reg, srcw, (void)0); + CHECK_EXTRA_REGS(temp_reg, tempw, (void)0); + + SLJIT_ASSERT(FAST_IS_REG(src_reg) || src_reg == SLJIT_MEM1(SLJIT_SP)); + SLJIT_ASSERT(FAST_IS_REG(temp_reg) || temp_reg == SLJIT_MEM1(SLJIT_SP)); + + op = GET_OPCODE(op); +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if ((src_reg & SLJIT_MEM) || (op == SLJIT_MOV_U8 && reg_map[src_reg] >= 4)) { + /* Src is virtual register or its low byte is not accessible. */ + SLJIT_ASSERT(src_reg != SLJIT_R1); + free_reg = src_reg; + + EMIT_MOV(compiler, TMP_REG1, 0, src_reg, srcw); + src_reg = TMP_REG1; + + if (mem_reg == src_reg) + mem_reg = TMP_REG1; + } +#endif /* SLJIT_CONFIG_X86_32 */ + + if (temp_reg != SLJIT_R0) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 0; + + EMIT_MOV(compiler, free_reg, 0, SLJIT_R0, 0); + EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, 0); + + if (src_reg == SLJIT_R0) + src_reg = free_reg; + if (mem_reg == SLJIT_R0) + mem_reg = free_reg; +#else /* !SLJIT_CONFIG_X86_64 */ + if (src_reg == TMP_REG1 && mem_reg == SLJIT_R0 && (free_reg & SLJIT_MEM)) { + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R1, 0); + EMIT_MOV(compiler, SLJIT_R1, 0, SLJIT_R0, 0); + EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, tempw); + + mem_reg = SLJIT_R1; + free_reg = SLJIT_R1; + } else { + EMIT_MOV(compiler, free_reg, 0, SLJIT_R0, 0); + EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, tempw); + + if (src_reg == SLJIT_R0) + src_reg = free_reg; + if (mem_reg == SLJIT_R0) + mem_reg = free_reg; + } +#endif /* SLJIT_CONFIG_X86_64 */ + } + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = op != SLJIT_MOV && op != SLJIT_MOV_P; +#endif /* SLJIT_CONFIG_X86_64 */ + + /* Lock prefix. */ + FAIL_IF(emit_byte(compiler, GROUP_LOCK)); + + pref = 0; + if (op == SLJIT_MOV_U16) + pref = EX86_HALF_ARG | EX86_PREF_66; +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (op == SLJIT_MOV_U8) + pref = EX86_REX; +#endif /* SLJIT_CONFIG_X86_64 */ + + FAIL_IF(emit_groupf(compiler, (op == SLJIT_MOV_U8 ? CMPXCHG_rm8_r : CMPXCHG_rm_r) | pref, src_reg, SLJIT_MEM1(mem_reg), 0)); + + if (temp_reg != SLJIT_R0) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 0; + return emit_mov(compiler, SLJIT_R0, 0, TMP_REG1, 0); +#else /* !SLJIT_CONFIG_X86_64 */ + EMIT_MOV(compiler, SLJIT_R0, 0, free_reg, 0); + if (free_reg != TMP_REG1) + return emit_mov(compiler, free_reg, 0, (free_reg == SLJIT_R1) ? SLJIT_MEM1(SLJIT_SP) : TMP_REG1, 0); +#endif /* SLJIT_CONFIG_X86_64 */ + } + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) +{ + CHECK_ERROR(); + CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + CHECK_EXTRA_REGS(dst, dstw, (void)0); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 0; @@ -3389,11 +4826,10 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi return NULL; #endif - inst = (sljit_u8*)ensure_buf(compiler, 2); + inst = (sljit_u8*)ensure_buf(compiler, 1); PTR_FAIL_IF(!inst); - inst[0] = 0; - inst[1] = 2; + inst[0] = SLJIT_INST_CONST; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (dst & SLJIT_MEM) @@ -3404,52 +4840,48 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi return const_; } -SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { - struct sljit_put_label *put_label; + struct sljit_jump *jump; sljit_u8 *inst; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) sljit_s32 reg; - sljit_uw start_size; -#endif +#endif /* SLJIT_CONFIG_X86_64 */ CHECK_ERROR_PTR(); - CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw)); + CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); CHECK_EXTRA_REGS(dst, dstw, (void)0); - put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label)); - PTR_FAIL_IF(!put_label); - set_put_label(put_label, compiler, 0); + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_mov_addr(jump, compiler, 0); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 0; reg = FAST_IS_REG(dst) ? dst : TMP_REG1; - if (emit_load_imm64(compiler, reg, 0)) - return NULL; -#else - if (emit_mov(compiler, dst, dstw, SLJIT_IMM, 0)) - return NULL; -#endif + PTR_FAIL_IF(emit_load_imm64(compiler, reg, 0)); + jump->addr = compiler->size; -#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - if (dst & SLJIT_MEM) { - start_size = compiler->size; - if (emit_mov(compiler, dst, dstw, TMP_REG1, 0)) - return NULL; - put_label->flags = compiler->size - start_size; - } -#endif + if (reg_map[reg] >= 8) + jump->flags |= MOV_ADDR_HI; +#else /* !SLJIT_CONFIG_X86_64 */ + PTR_FAIL_IF(emit_mov(compiler, dst, dstw, SLJIT_IMM, 0)); +#endif /* SLJIT_CONFIG_X86_64 */ - inst = (sljit_u8*)ensure_buf(compiler, 2); + inst = (sljit_u8*)ensure_buf(compiler, 1); PTR_FAIL_IF(!inst); - inst[0] = 0; - inst[1] = 3; + inst[0] = SLJIT_INST_MOV_ADDR; + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (dst & SLJIT_MEM) + PTR_FAIL_IF(emit_mov(compiler, dst, dstw, TMP_REG1, 0)); +#endif /* SLJIT_CONFIG_X86_64 */ - return put_label; + return jump; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) diff --git a/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitSerialize.c b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitSerialize.c new file mode 100644 index 00000000000..4392b2da9a5 --- /dev/null +++ b/waterbox/ares64/ares/thirdparty/sljit/sljit_src/sljitSerialize.c @@ -0,0 +1,516 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_label(struct sljit_jump *jump) +{ + return !(jump->flags & JUMP_ADDR) && (jump->u.label != NULL); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_target(struct sljit_jump *jump) +{ + return (jump->flags & JUMP_ADDR) != 0; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_is_mov_addr(struct sljit_jump *jump) +{ + return (jump->flags & JUMP_MOV_ADDR) != 0; +} + +#define SLJIT_SERIALIZE_DEBUG ((sljit_u16)0x1) + +struct sljit_serialized_compiler { + sljit_u32 signature; + sljit_u16 version; + sljit_u16 cpu_type; + + sljit_uw buf_segment_count; + sljit_uw label_count; + sljit_uw jump_count; + sljit_uw const_count; + + sljit_s32 options; + sljit_s32 scratches; + sljit_s32 saveds; + sljit_s32 fscratches; + sljit_s32 fsaveds; + sljit_s32 local_size; + sljit_uw size; + +#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE) + sljit_s32 status_flags_state; +#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */ + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + sljit_s32 args_size; +#endif /* SLJIT_CONFIG_X86_32 */ + +#if ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \ + || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + sljit_uw args_size; +#endif /* (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */ + +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + sljit_uw cpool_diff; + sljit_uw cpool_fill; + sljit_uw patches; +#endif /* SLJIT_CONFIG_ARM_V6 */ + +#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) + sljit_s32 delay_slot; +#endif /* SLJIT_CONFIG_MIPS */ + +}; + +struct sljit_serialized_debug_info { + sljit_sw last_flags; + sljit_s32 last_return; + sljit_s32 logical_local_size; +}; + +struct sljit_serialized_label { + sljit_uw size; +}; + +struct sljit_serialized_jump { + sljit_uw addr; + sljit_uw flags; + sljit_uw value; +}; + +struct sljit_serialized_const { + sljit_uw addr; +}; + +#define SLJIT_SERIALIZE_ALIGN(v) (((v) + sizeof(sljit_uw) - 1) & ~(sljit_uw)(sizeof(sljit_uw) - 1)) +#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) +#define SLJIT_SERIALIZE_SIGNATURE 0x534c4a54 +#else /* !SLJIT_LITTLE_ENDIAN */ +#define SLJIT_SERIALIZE_SIGNATURE 0x544a4c53 +#endif /* SLJIT_LITTLE_ENDIAN */ +#define SLJIT_SERIALIZE_VERSION 1 + +SLJIT_API_FUNC_ATTRIBUTE sljit_uw* sljit_serialize_compiler(struct sljit_compiler *compiler, + sljit_s32 options, sljit_uw *size) +{ + sljit_uw total_size = sizeof(struct sljit_serialized_compiler); + struct sljit_memory_fragment *buf; + struct sljit_label *label; + struct sljit_jump *jump; + struct sljit_const *const_; + struct sljit_serialized_compiler *serialized_compiler; + struct sljit_serialized_label *serialized_label; + struct sljit_serialized_jump *serialized_jump; + struct sljit_serialized_const *serialized_const; +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ + || (defined SLJIT_DEBUG && SLJIT_DEBUG) + struct sljit_serialized_debug_info *serialized_debug_info; +#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */ + sljit_uw counter, used_size; + sljit_u8 *result; + sljit_u8 *ptr; + SLJIT_UNUSED_ARG(options); + + if (size != NULL) + *size = 0; + + PTR_FAIL_IF(compiler->error); + +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ + || (defined SLJIT_DEBUG && SLJIT_DEBUG) + if (!(options & SLJIT_SERIALIZE_IGNORE_DEBUG)) + total_size += sizeof(struct sljit_serialized_debug_info); +#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */ + +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + total_size += SLJIT_SERIALIZE_ALIGN(compiler->cpool_fill * (sizeof(sljit_uw) + 1)); +#endif /* SLJIT_CONFIG_ARM_V6 */ + + /* Compute the size of the data. */ + buf = compiler->buf; + while (buf != NULL) { + total_size += sizeof(sljit_uw) + SLJIT_SERIALIZE_ALIGN(buf->used_size); + buf = buf->next; + } + + total_size += compiler->label_count * sizeof(struct sljit_serialized_label); + + jump = compiler->jumps; + while (jump != NULL) { + total_size += sizeof(struct sljit_serialized_jump); + jump = jump->next; + } + + const_ = compiler->consts; + while (const_ != NULL) { + total_size += sizeof(struct sljit_serialized_const); + const_ = const_->next; + } + + result = (sljit_u8*)SLJIT_MALLOC(total_size, compiler->allocator_data); + PTR_FAIL_IF_NULL(result); + + if (size != NULL) + *size = total_size; + + ptr = result; + serialized_compiler = (struct sljit_serialized_compiler*)ptr; + ptr += sizeof(struct sljit_serialized_compiler); + + serialized_compiler->signature = SLJIT_SERIALIZE_SIGNATURE; + serialized_compiler->version = SLJIT_SERIALIZE_VERSION; + serialized_compiler->cpu_type = 0; + serialized_compiler->label_count = compiler->label_count; + serialized_compiler->options = compiler->options; + serialized_compiler->scratches = compiler->scratches; + serialized_compiler->saveds = compiler->saveds; + serialized_compiler->fscratches = compiler->fscratches; + serialized_compiler->fsaveds = compiler->fsaveds; + serialized_compiler->local_size = compiler->local_size; + serialized_compiler->size = compiler->size; + +#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE) + serialized_compiler->status_flags_state = compiler->status_flags_state; +#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */ + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ + || ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \ + || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + serialized_compiler->args_size = compiler->args_size; +#endif /* SLJIT_CONFIG_X86_32 || (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */ + +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + serialized_compiler->cpool_diff = compiler->cpool_diff; + serialized_compiler->cpool_fill = compiler->cpool_fill; + serialized_compiler->patches = compiler->patches; + + SLJIT_MEMCPY(ptr, compiler->cpool, compiler->cpool_fill * sizeof(sljit_uw)); + SLJIT_MEMCPY(ptr + compiler->cpool_fill * sizeof(sljit_uw), compiler->cpool_unique, compiler->cpool_fill); + ptr += SLJIT_SERIALIZE_ALIGN(compiler->cpool_fill * (sizeof(sljit_uw) + 1)); +#endif /* SLJIT_CONFIG_ARM_V6 */ + +#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) + serialized_compiler->delay_slot = compiler->delay_slot; +#endif /* SLJIT_CONFIG_MIPS */ + + buf = compiler->buf; + counter = 0; + while (buf != NULL) { + used_size = buf->used_size; + *(sljit_uw*)ptr = used_size; + ptr += sizeof(sljit_uw); + SLJIT_MEMCPY(ptr, buf->memory, used_size); + ptr += SLJIT_SERIALIZE_ALIGN(used_size); + buf = buf->next; + counter++; + } + serialized_compiler->buf_segment_count = counter; + + label = compiler->labels; + while (label != NULL) { + serialized_label = (struct sljit_serialized_label*)ptr; + serialized_label->size = label->size; + ptr += sizeof(struct sljit_serialized_label); + label = label->next; + } + + jump = compiler->jumps; + counter = 0; + while (jump != NULL) { + serialized_jump = (struct sljit_serialized_jump*)ptr; + serialized_jump->addr = jump->addr; + serialized_jump->flags = jump->flags; + + if (jump->flags & JUMP_ADDR) + serialized_jump->value = jump->u.target; + else if (jump->u.label != NULL) + serialized_jump->value = jump->u.label->u.index; + else + serialized_jump->value = SLJIT_MAX_ADDRESS; + + ptr += sizeof(struct sljit_serialized_jump); + jump = jump->next; + counter++; + } + serialized_compiler->jump_count = counter; + + const_ = compiler->consts; + counter = 0; + while (const_ != NULL) { + serialized_const = (struct sljit_serialized_const*)ptr; + serialized_const->addr = const_->addr; + ptr += sizeof(struct sljit_serialized_const); + const_ = const_->next; + counter++; + } + serialized_compiler->const_count = counter; + +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ + || (defined SLJIT_DEBUG && SLJIT_DEBUG) + if (!(options & SLJIT_SERIALIZE_IGNORE_DEBUG)) { + serialized_debug_info = (struct sljit_serialized_debug_info*)ptr; + serialized_debug_info->last_flags = compiler->last_flags; + serialized_debug_info->last_return = compiler->last_return; + serialized_debug_info->logical_local_size = compiler->logical_local_size; + serialized_compiler->cpu_type |= SLJIT_SERIALIZE_DEBUG; +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + ptr += sizeof(struct sljit_serialized_debug_info); +#endif /* SLJIT_DEBUG */ + } +#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */ + + SLJIT_ASSERT((sljit_uw)(ptr - result) == total_size); + return (sljit_uw*)result; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler *sljit_deserialize_compiler(sljit_uw* buffer, sljit_uw size, + sljit_s32 options, void *allocator_data, void *exec_allocator_data) +{ + struct sljit_compiler *compiler; + struct sljit_serialized_compiler *serialized_compiler; + struct sljit_serialized_label *serialized_label; + struct sljit_serialized_jump *serialized_jump; + struct sljit_serialized_const *serialized_const; +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ + || (defined SLJIT_DEBUG && SLJIT_DEBUG) + struct sljit_serialized_debug_info *serialized_debug_info; +#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */ + struct sljit_memory_fragment *buf; + struct sljit_memory_fragment *last_buf; + struct sljit_label *label; + struct sljit_label *last_label; + struct sljit_label **label_list = NULL; + struct sljit_jump *jump; + struct sljit_jump *last_jump; + struct sljit_const *const_; + struct sljit_const *last_const; + sljit_u8 *ptr = (sljit_u8*)buffer; + sljit_u8 *end = ptr + size; + sljit_uw i, used_size, aligned_size, label_count; + SLJIT_UNUSED_ARG(options); + + if (size < sizeof(struct sljit_serialized_compiler) || (size & (sizeof(sljit_uw) - 1)) != 0) + return NULL; + + serialized_compiler = (struct sljit_serialized_compiler*)ptr; + + if (serialized_compiler->signature != SLJIT_SERIALIZE_SIGNATURE || serialized_compiler->version != SLJIT_SERIALIZE_VERSION) + return NULL; + + compiler = sljit_create_compiler(allocator_data, exec_allocator_data); + PTR_FAIL_IF(compiler == NULL); + + compiler->label_count = serialized_compiler->label_count; + compiler->options = serialized_compiler->options; + compiler->scratches = serialized_compiler->scratches; + compiler->saveds = serialized_compiler->saveds; + compiler->fscratches = serialized_compiler->fscratches; + compiler->fsaveds = serialized_compiler->fsaveds; + compiler->local_size = serialized_compiler->local_size; + compiler->size = serialized_compiler->size; + +#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE) + compiler->status_flags_state = serialized_compiler->status_flags_state; +#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */ + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ + || ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \ + || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + compiler->args_size = serialized_compiler->args_size; +#endif /* SLJIT_CONFIG_X86_32 || (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */ + +#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) + used_size = serialized_compiler->cpool_fill; + aligned_size = SLJIT_SERIALIZE_ALIGN(used_size * (sizeof(sljit_uw) + 1)); + compiler->cpool_diff = serialized_compiler->cpool_diff; + compiler->cpool_fill = used_size; + compiler->patches = serialized_compiler->patches; + + if ((sljit_uw)(end - ptr) < aligned_size) + goto error; + + SLJIT_MEMCPY(compiler->cpool, ptr, used_size * sizeof(sljit_uw)); + SLJIT_MEMCPY(compiler->cpool_unique, ptr + used_size * sizeof(sljit_uw), used_size); + ptr += aligned_size; +#endif /* SLJIT_CONFIG_ARM_V6 */ + +#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) + compiler->delay_slot = serialized_compiler->delay_slot; +#endif /* SLJIT_CONFIG_MIPS */ + +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ + || (defined SLJIT_DEBUG && SLJIT_DEBUG) + if (!(serialized_compiler->cpu_type & SLJIT_SERIALIZE_DEBUG)) + goto error; +#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */ + + ptr += sizeof(struct sljit_serialized_compiler); + i = serialized_compiler->buf_segment_count; + last_buf = NULL; + while (i > 0) { + if ((sljit_uw)(end - ptr) < sizeof(sljit_uw)) + goto error; + + used_size = *(sljit_uw*)ptr; + aligned_size = SLJIT_SERIALIZE_ALIGN(used_size); + ptr += sizeof(sljit_uw); + + if ((sljit_uw)(end - ptr) < aligned_size) + goto error; + + if (last_buf == NULL) { + SLJIT_ASSERT(compiler->buf != NULL && compiler->buf->next == NULL); + buf = compiler->buf; + } else { + buf = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, allocator_data); + if (!buf) + goto error; + buf->next = NULL; + } + + buf->used_size = used_size; + SLJIT_MEMCPY(buf->memory, ptr, used_size); + + if (last_buf != NULL) + last_buf->next = buf; + last_buf = buf; + + ptr += aligned_size; + i--; + } + + last_label = NULL; + label_count = serialized_compiler->label_count; + if ((sljit_uw)(end - ptr) < label_count * sizeof(struct sljit_serialized_label)) + goto error; + + label_list = (struct sljit_label **)SLJIT_MALLOC(label_count * sizeof(struct sljit_label*), allocator_data); + if (label_list == NULL) + goto error; + + for (i = 0; i < label_count; i++) { + label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); + if (label == NULL) + goto error; + + serialized_label = (struct sljit_serialized_label*)ptr; + label->next = NULL; + label->u.index = i; + label->size = serialized_label->size; + + if (last_label != NULL) + last_label->next = label; + else + compiler->labels = label; + last_label = label; + + label_list[i] = label; + ptr += sizeof(struct sljit_serialized_label); + } + compiler->last_label = last_label; + + last_jump = NULL; + i = serialized_compiler->jump_count; + if ((sljit_uw)(end - ptr) < i * sizeof(struct sljit_serialized_jump)) + goto error; + + while (i > 0) { + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + if (jump == NULL) + goto error; + + serialized_jump = (struct sljit_serialized_jump*)ptr; + jump->next = NULL; + jump->addr = serialized_jump->addr; + jump->flags = serialized_jump->flags; + + if (!(serialized_jump->flags & JUMP_ADDR)) { + if (serialized_jump->value != SLJIT_MAX_ADDRESS) { + if (serialized_jump->value >= label_count) + goto error; + jump->u.label = label_list[serialized_jump->value]; + } else + jump->u.label = NULL; + } else + jump->u.target = serialized_jump->value; + + if (last_jump != NULL) + last_jump->next = jump; + else + compiler->jumps = jump; + last_jump = jump; + + ptr += sizeof(struct sljit_serialized_jump); + i--; + } + compiler->last_jump = last_jump; + + SLJIT_FREE(label_list, allocator_data); + label_list = NULL; + + last_const = NULL; + i = serialized_compiler->const_count; + if ((sljit_uw)(end - ptr) < i * sizeof(struct sljit_serialized_const)) + goto error; + + while (i > 0) { + const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); + if (const_ == NULL) + goto error; + + serialized_const = (struct sljit_serialized_const*)ptr; + const_->next = NULL; + const_->addr = serialized_const->addr; + + if (last_const != NULL) + last_const->next = const_; + else + compiler->consts = const_; + last_const = const_; + + ptr += sizeof(struct sljit_serialized_const); + i--; + } + compiler->last_const = last_const; + +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ + || (defined SLJIT_DEBUG && SLJIT_DEBUG) + if ((sljit_uw)(end - ptr) < sizeof(struct sljit_serialized_debug_info)) + goto error; + + serialized_debug_info = (struct sljit_serialized_debug_info*)ptr; + compiler->last_flags = (sljit_s32)serialized_debug_info->last_flags; + compiler->last_return = serialized_debug_info->last_return; + compiler->logical_local_size = serialized_debug_info->logical_local_size; +#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */ + + return compiler; + +error: + sljit_free_compiler(compiler); + if (label_list != NULL) + SLJIT_FREE(label_list, allocator_data); + return NULL; +} diff --git a/waterbox/ares64/ares/thirdparty/sljit/test_src/sljitConfigPost.h b/waterbox/ares64/ares/thirdparty/sljit/test_src/sljitConfigPost.h deleted file mode 100644 index 04f003e00f8..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/test_src/sljitConfigPost.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Stack-less Just-In-Time compiler - * - * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SLJIT_CONFIG_POST_H_ -#define SLJIT_CONFIG_POST_H_ - -void *sljit_test_malloc_exec(sljit_uw size, void *exec_allocator_data); -void sljit_test_free_code(void* code, void *exec_allocator_data); - -#endif /* SLJIT_CONFIG_POST_H_ */ diff --git a/waterbox/ares64/ares/thirdparty/sljit/test_src/sljitConfigPre.h b/waterbox/ares64/ares/thirdparty/sljit/test_src/sljitConfigPre.h deleted file mode 100644 index c2c86d6b433..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/test_src/sljitConfigPre.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Stack-less Just-In-Time compiler - * - * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SLJIT_CONFIG_PRE_H_ -#define SLJIT_CONFIG_PRE_H_ - -#define SLJIT_HAVE_CONFIG_POST 1 - -#define SLJIT_MALLOC_EXEC(size, exec_allocator_data) sljit_test_malloc_exec((size), (exec_allocator_data)) -#define SLJIT_FREE_EXEC(ptr, exec_allocator_data) sljit_test_free_code((ptr), (exec_allocator_data)) - -#endif /* SLJIT_CONFIG_PRE_H_ */ diff --git a/waterbox/ares64/ares/thirdparty/sljit/test_src/sljitMain.c b/waterbox/ares64/ares/thirdparty/sljit/test_src/sljitMain.c deleted file mode 100644 index 897922a7548..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/test_src/sljitMain.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Stack-less Just-In-Time compiler - * - * Copyright 2009-2010 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "sljitLir.h" - -#include -#include - -int sljit_test(int argc, char* argv[]); - -union executable_code { - void* code; - sljit_sw (SLJIT_FUNC *func)(sljit_sw* a); -}; -typedef union executable_code executable_code; - -static void error(const char* str) -{ - printf("An error occured: %s\n", str); - exit(-1); -} - -void devel(void) -{ - executable_code code; - - struct sljit_compiler *compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[4]; - - if (!compiler) - error("Not enough of memory"); - buf[0] = 5; - buf[1] = 12; - buf[2] = 0; - buf[3] = 0; - -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) - sljit_compiler_verbose(compiler, stdout); -#endif - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 4, 5, 4, 0, 2 * sizeof(sljit_sw)); - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code.code = sljit_generate_code(compiler); - sljit_free_compiler(compiler); - - printf("Code at: %p\n", (void*)SLJIT_FUNC_ADDR(code.code)); - - printf("Function returned with %ld\n", (long)code.func((sljit_sw*)buf)); - printf("buf[0] = %ld\n", (long)buf[0]); - printf("buf[1] = %ld\n", (long)buf[1]); - printf("buf[2] = %ld\n", (long)buf[2]); - printf("buf[3] = %ld\n", (long)buf[3]); - sljit_free_code(code.code, NULL); -} - -int main(int argc, char* argv[]) -{ - /* devel(); */ - return sljit_test(argc, argv); -} diff --git a/waterbox/ares64/ares/thirdparty/sljit/test_src/sljitTest.c b/waterbox/ares64/ares/thirdparty/sljit/test_src/sljitTest.c deleted file mode 100644 index 1a133a7a4d7..00000000000 --- a/waterbox/ares64/ares/thirdparty/sljit/test_src/sljitTest.c +++ /dev/null @@ -1,11223 +0,0 @@ -/* - * Stack-less Just-In-Time compiler - * - * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* Must be the first one. Must not depend on any other include. */ -#include "sljitLir.h" - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable: 4127) /* conditional expression is constant */ -#endif - -#if defined _WIN32 || defined _WIN64 -#define COLOR_RED -#define COLOR_GREEN -#define COLOR_ARCH -#define COLOR_DEFAULT -#else -#define COLOR_RED "\33[31m" -#define COLOR_GREEN "\33[32m" -#define COLOR_ARCH "\33[33m" -#define COLOR_DEFAULT "\33[0m" -#endif - -union executable_code { - void* code; - sljit_sw (SLJIT_FUNC *func0)(void); - sljit_sw (SLJIT_FUNC *func1)(sljit_sw a); - sljit_sw (SLJIT_FUNC *func2)(sljit_sw a, sljit_sw b); - sljit_sw (SLJIT_FUNC *func3)(sljit_sw a, sljit_sw b, sljit_sw c); - - void (SLJIT_FUNC *test70_f1)(sljit_s32 a, sljit_uw b, sljit_u32 c, sljit_sw d); - void (SLJIT_FUNC *test70_f2)(sljit_s32 a, sljit_u32 b, sljit_sw c, sljit_sw d); - void (SLJIT_FUNC *test70_f3)(sljit_s32 a, sljit_f32 b, sljit_uw c, sljit_f64 d); - void (SLJIT_FUNC *test70_f4)(sljit_f32 a, sljit_f64 b, sljit_f32 c, sljit_s32 d); - void (SLJIT_FUNC *test70_f5)(sljit_f64 a, sljit_f32 b, sljit_u32 c, sljit_f32 d); - void (SLJIT_FUNC *test70_f6)(sljit_f64 a, sljit_s32 b, sljit_f32 c, sljit_f64 d); - void (SLJIT_FUNC *test70_f7)(sljit_f32 a, sljit_s32 b, sljit_uw c, sljit_u32 d); - void (SLJIT_FUNC *test70_f8)(sljit_f64 a, sljit_f64 b, sljit_uw c, sljit_sw d); - void (SLJIT_FUNC *test70_f9)(sljit_f64 a, sljit_f64 b, sljit_uw c, sljit_f64 d); - void (SLJIT_FUNC *test70_f10)(sljit_f64 a, sljit_f64 b, sljit_f64 c, sljit_s32 d); - - sljit_sw (SLJIT_FUNC *test71_f1)(sljit_f32 a, sljit_f64 b); - sljit_sw (SLJIT_FUNC *test71_f2)(sljit_f64 a, sljit_f64 b, sljit_f64 c, sljit_f64 d); - sljit_sw (SLJIT_FUNC *test71_f3)(sljit_f64 a, sljit_f64 b, sljit_f64 c); - - void (SLJIT_FUNC *test73_f1)(sljit_s32 a, sljit_sw b, sljit_sw c, sljit_s32 d); - void (SLJIT_FUNC *test73_f2)(sljit_sw a, sljit_sw b, sljit_s32 c, sljit_s32 d); - void (SLJIT_FUNC *test73_f3)(sljit_f64 a, sljit_f64 b, sljit_f64 c, sljit_sw d); - void (SLJIT_FUNC *test73_f4)(sljit_f64 a, sljit_f64 b, sljit_sw c, sljit_sw d); - - sljit_f32 (SLJIT_FUNC *test81_f1)(sljit_sw a); - sljit_f64 (SLJIT_FUNC *test81_f2)(sljit_sw a); -}; -typedef union executable_code executable_code; - -static sljit_s32 successful_tests = 0; -static sljit_s32 verbose = 0; -static sljit_s32 silent = 0; - -#define FAILED(cond, text) \ - if (SLJIT_UNLIKELY(cond)) { \ - printf(text); \ - return; \ - } - -#define CHECK(compiler) \ - if (sljit_get_compiler_error(compiler) != SLJIT_ERR_COMPILED) { \ - printf("Compiler error: %d\n", sljit_get_compiler_error(compiler)); \ - sljit_free_compiler(compiler); \ - return; \ - } - -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) -#define WCONST(const64, const32) ((sljit_sw)SLJIT_W(const64)) -#else /* !SLJIT_64BIT_ARCHITECTURE */ -#define WCONST(const64, const32) ((sljit_sw)const32) -#endif /* SLJIT_64BIT_ARCHITECTURE */ - -static void cond_set(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_s32 type) -{ - /* Testing both sljit_emit_op_flags and sljit_emit_jump. */ - struct sljit_jump* jump; - struct sljit_label* label; - - sljit_emit_op_flags(compiler, SLJIT_MOV, dst, dstw, type); - jump = sljit_emit_jump(compiler, type); - sljit_emit_op2(compiler, SLJIT_ADD, dst, dstw, dst, dstw, SLJIT_IMM, 2); - label = sljit_emit_label(compiler); - sljit_set_label(jump, label); -} - -#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) - -/* For interface testing and for test64. */ -void *sljit_test_malloc_exec(sljit_uw size, void *exec_allocator_data) -{ - if (exec_allocator_data) - return exec_allocator_data; - - return SLJIT_BUILTIN_MALLOC_EXEC(size, exec_allocator_data); -} - -/* For interface testing. */ -void sljit_test_free_code(void* code, void *exec_allocator_data) -{ - SLJIT_UNUSED_ARG(exec_allocator_data); - SLJIT_BUILTIN_FREE_EXEC(code, exec_allocator_data); -} - -#define MALLOC_EXEC(result, size) \ - result = SLJIT_MALLOC_EXEC(size, NULL); \ - if (!result) { \ - printf("Cannot allocate executable memory\n"); \ - return; \ - } \ - memset(result, 255, size); - -#define FREE_EXEC(ptr) \ - SLJIT_FREE_EXEC(((sljit_u8*)(ptr)) + SLJIT_EXEC_OFFSET(ptr), NULL); - -static void test_exec_allocator(void) -{ - /* This is not an sljit test. */ - void *ptr1; - void *ptr2; - void *ptr3; - - if (verbose) - printf("Run executable allocator test\n"); - - MALLOC_EXEC(ptr1, 32); - MALLOC_EXEC(ptr2, 512); - MALLOC_EXEC(ptr3, 512); - FREE_EXEC(ptr2); - FREE_EXEC(ptr3); - FREE_EXEC(ptr1); - MALLOC_EXEC(ptr1, 262104); - MALLOC_EXEC(ptr2, 32000); - FREE_EXEC(ptr1); - MALLOC_EXEC(ptr1, 262104); - FREE_EXEC(ptr1); - FREE_EXEC(ptr2); - MALLOC_EXEC(ptr1, 512); - MALLOC_EXEC(ptr2, 512); - MALLOC_EXEC(ptr3, 512); - FREE_EXEC(ptr2); - MALLOC_EXEC(ptr2, 512); -#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) - sljit_free_unused_memory_exec(); -#endif - FREE_EXEC(ptr3); - FREE_EXEC(ptr1); - FREE_EXEC(ptr2); - -#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) - sljit_free_unused_memory_exec(); -#endif -} - -#undef MALLOC_EXEC - -#endif /* !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) */ - -static void test1(void) -{ - /* Enter and return from an sljit function. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - - if (verbose) - printf("Run test1\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - /* 3 arguments passed, 3 arguments used. */ - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(W, W, W, W), 3, 3, 0, 0, 0); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_S1, 0); - - SLJIT_ASSERT(sljit_get_generated_code_size(compiler) == 0); - code.code = sljit_generate_code(compiler); - CHECK(compiler); - SLJIT_ASSERT(compiler->error == SLJIT_ERR_COMPILED); - SLJIT_ASSERT(sljit_get_generated_code_size(compiler) > 0); - sljit_free_compiler(compiler); - - FAILED(code.func3(3, -21, 86) != -21, "test1 case 1 failed\n"); - FAILED(code.func3(4789, 47890, 997) != 47890, "test1 case 2 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test2(void) -{ - /* Test mov. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[10]; - static sljit_sw data[2] = { 0, -9876 }; - - if (verbose) - printf("Run test2\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - buf[0] = 5678; - buf[1] = 0; - buf[2] = 0; - buf[3] = 0; - buf[4] = 0; - buf[5] = 0; - buf[6] = 0; - buf[7] = 0; - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 2, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 9999); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_S0, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 2); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_S1, SLJIT_S0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 3); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_S1, SLJIT_S0), SLJIT_WORD_SHIFT, SLJIT_MEM0(), (sljit_sw)&buf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), (sljit_sw)&data); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf - 0x12345678); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), 0x12345678); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3456); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf - 0xff890 + 6 * (sljit_sw)sizeof(sljit_sw)); - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0xff890, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf + 0xff890 + 7 * (sljit_sw)sizeof(sljit_sw)); - /* buf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), -0xff890, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf - 0xfff0ff + 8 * (sljit_sw)sizeof(sljit_sw)); - /* buf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0xfff0ff, SLJIT_IMM, 7896); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf + 0xfff100 + 9 * (sljit_sw)sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -2450); - /* buf[9] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), -0xfff100, SLJIT_R1, 0); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R2, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func1((sljit_sw)&buf) != 9999, "test2 case 1 failed\n"); - FAILED(buf[1] != 9999, "test2 case 2 failed\n"); - FAILED(buf[2] != 9999, "test2 case 3 failed\n"); - FAILED(buf[3] != 5678, "test2 case 4 failed\n"); - FAILED(buf[4] != -9876, "test2 case 5 failed\n"); - FAILED(buf[5] != 5678, "test2 case 6 failed\n"); - FAILED(buf[6] != 3456, "test2 case 7 failed\n"); - FAILED(buf[7] != 3456, "test2 case 8 failed\n"); - FAILED(buf[8] != 7896, "test2 case 9 failed\n"); - FAILED(buf[9] != -2450, "test2 case 10 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test3(void) -{ - /* Test not. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[5]; - - if (verbose) - printf("Run test3\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 1234; - buf[1] = 0; - buf[2] = 9876; - buf[3] = 0; - buf[4] = 0x12345678; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0, 0, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM0(), (sljit_sw)&buf[1], SLJIT_MEM0(), (sljit_sw)&buf[1], SLJIT_IMM, -1); - /* buf[3] */ - sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_RETURN_REG, 0, SLJIT_IMM, -1, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_IMM, -1); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf[4] - 0xff0000 - 0x20); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)&buf[4] - 0xff0000); - sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_R1), 0xff0000 + 0x20, SLJIT_IMM, -1, SLJIT_MEM1(SLJIT_R2), 0xff0000); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func1((sljit_sw)&buf) != ~1234, "test3 case 1 failed\n"); - FAILED(buf[1] != ~1234, "test3 case 2 failed\n"); - FAILED(buf[3] != ~9876, "test3 case 3 failed\n"); - FAILED(buf[4] != ~0x12345678, "test3 case 4 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test4(void) -{ - /* Test negate. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[4]; - - if (verbose) - printf("Run test4\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 0; - buf[1] = 1234; - buf[2] = 0; - buf[3] = 0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(W, P, W), 3, 2, 0, 0, 0); - /* buf[0] */ - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM0(), (sljit_sw)&buf[0], SLJIT_IMM, 0, SLJIT_MEM0(), (sljit_sw)&buf[1]); - /* buf[2] */ - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_IMM, 0, SLJIT_S1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 299); - /* buf[3] */ - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_IMM, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func2((sljit_sw)&buf, 4567) != -4567, "test4 case 1 failed\n"); - FAILED(buf[0] != -1234, "test4 case 2 failed\n"); - FAILED(buf[2] != -4567, "test4 case 3 failed\n"); - FAILED(buf[3] != -299, "test4 case 4 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test5(void) -{ - /* Test add. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[9]; - - if (verbose) - printf("Run test5\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 100; - buf[1] = 200; - buf[2] = 300; - buf[3] = 0; - buf[4] = 0; - buf[5] = 0; - buf[6] = 0; - buf[7] = 0; - buf[8] = 313; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 2, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 50); - /* buf[2] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 1, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 1, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0); - /* buf[0] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw) + 2); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 50); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - /* buf[5] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_IMM, 4, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_IMM, 50, SLJIT_R1, 0); - /* buf[4] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_IMM, 50, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw)); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R1, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw)); - /* buf[5] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw)); - /* buf[3] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x1e7d39f2); - /* buf[6] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R1, 0, SLJIT_IMM, 0x23de7c06); - /* buf[7] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_IMM, 0x3d72e452, SLJIT_R1, 0); - /* buf[8] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_IMM, -43, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw)); - /* Return value */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_IMM, 1000, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1430); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_IMM, -99, SLJIT_R0, 0); - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func1((sljit_sw)&buf) != 2437 + 2 * sizeof(sljit_sw), "test5 case 1 failed\n"); - FAILED(buf[0] != 202 + 2 * sizeof(sljit_sw), "test5 case 2 failed\n"); - FAILED(buf[2] != 500, "test5 case 3 failed\n"); - FAILED(buf[3] != 400, "test5 case 4 failed\n"); - FAILED(buf[4] != 200, "test5 case 5 failed\n"); - FAILED(buf[5] != 250, "test5 case 6 failed\n"); - FAILED(buf[6] != 0x425bb5f8, "test5 case 7 failed\n"); - FAILED(buf[7] != 0x5bf01e44, "test5 case 8 failed\n"); - FAILED(buf[8] != 270, "test5 case 9 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test6(void) -{ - /* Test addc, sub, subc. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[11]; - - if (verbose) - printf("Run test6\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 0; - buf[1] = 0; - buf[2] = 0; - buf[3] = 0; - buf[4] = 0; - buf[5] = 0; - buf[6] = 0; - buf[7] = 0; - buf[8] = 0; - buf[9] = 0; - buf[10] = 4000; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); - sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -1); - /* buf[0] */ - sljit_emit_op2(compiler, SLJIT_ADDC, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 0, SLJIT_IMM, 0); - sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R0, 0); - /* buf[1] */ - sljit_emit_op2(compiler, SLJIT_ADDC, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 4); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 100); - /* buf[2] */ - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_R0, 0, SLJIT_IMM, 50); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 6000); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_IMM, 10); - sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_IMM, 5); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 100); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5000); - sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_R1, 0); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5000); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_IMM, 6000, SLJIT_R0, 0); - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 100); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 32768); - /* buf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_R1, 0); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -32767); - /* buf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 8, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x52cd3bf4); - /* buf[9] */ - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 9, SLJIT_R0, 0, SLJIT_IMM, 0x3da297c6); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 6000); - /* buf[10] */ - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 10); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 5); - sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 2); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, -2220); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func1((sljit_sw)&buf) != 2223, "test6 case 1 failed\n"); - FAILED(buf[0] != 1, "test6 case 2 failed\n"); - FAILED(buf[1] != 5, "test6 case 3 failed\n"); - FAILED(buf[2] != 50, "test6 case 4 failed\n"); - FAILED(buf[3] != 4, "test6 case 5 failed\n"); - FAILED(buf[4] != 50, "test6 case 6 failed\n"); - FAILED(buf[5] != 50, "test6 case 7 failed\n"); - FAILED(buf[6] != 1000, "test6 case 8 failed\n"); - FAILED(buf[7] != 100 - 32768, "test6 case 9 failed\n"); - FAILED(buf[8] != 100 + 32767, "test6 case 10 failed\n"); - FAILED(buf[9] != 0x152aa42e, "test6 case 11 failed\n"); - FAILED(buf[10] != -2000, "test6 case 12 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test7(void) -{ - /* Test logical operators. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[8]; - - if (verbose) - printf("Run test7\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 0xff80; - buf[1] = 0x0f808080; - buf[2] = 0; - buf[3] = 0xaaaaaa; - buf[4] = 0; - buf[5] = 0x4040; - buf[6] = 0; - buf[7] = (sljit_sw)0xc43a7f95; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xf0C000); - /* buf[2] */ - sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_R0, 0, SLJIT_IMM, 0x308f); - /* buf[0] */ - sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)); - /* buf[3] */ - sljit_emit_op2(compiler, SLJIT_AND, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_IMM, 0xf0f0f0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xC0F0); - sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5); - sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0xff0000); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R0, 0); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0xC0F0); - sljit_emit_op2(compiler, SLJIT_AND, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5); - sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_R2, 0, SLJIT_IMM, 0xff0000); - /* buf[1] */ - sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 0xFFFFFF, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)); - /* buf[6] */ - sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_IMM, (sljit_sw)0xa56c82c0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6); - /* buf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7); - sljit_emit_op2(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_IMM, (sljit_sw)0xff00ff00, SLJIT_R0, 0); - /* Return vaue */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xff00ff00); - sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 0x0f); - sljit_emit_op2(compiler, SLJIT_AND, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0x888888, SLJIT_R1, 0); - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func1((sljit_sw)&buf) != 0x8808, "test7 case 1 failed\n"); - FAILED(buf[0] != 0x0F807F00, "test7 case 2 failed\n"); - FAILED(buf[1] != 0x0F7F7F7F, "test7 case 3 failed\n"); - FAILED(buf[2] != 0x00F0F08F, "test7 case 4 failed\n"); - FAILED(buf[3] != 0x00A0A0A0, "test7 case 5 failed\n"); - FAILED(buf[4] != 0x00FF80B0, "test7 case 6 failed\n"); - FAILED(buf[5] != 0x00FF4040, "test7 case 7 failed\n"); - FAILED(buf[6] != (sljit_sw)0xa56c82c0, "test7 case 8 failed\n"); - FAILED(buf[7] != 0x3b3a8095, "test7 case 9 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test8(void) -{ - /* Test flags (neg, cmp, test). */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[22]; - sljit_s32 i; - - if (verbose) - printf("Run test8\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 100; - for (i = 1; i < 21; i++) - buf[i] = 3; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 2, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 20); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 10); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_IMM, 6, SLJIT_IMM, 5); - /* buf[1] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_NOT_EQUAL); - /* buf[2] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_EQUAL); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_IMM, 3000); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_GREATER); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 3000); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_S1, 0); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_LESS); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R2, 0); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_IMM, -15); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_SIG_GREATER); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_R2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -(sljit_sw)(~(sljit_uw)0 >> 1) - 1); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_OVERFLOW, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_IMM, 0, SLJIT_R0, 0); - /* buf[6] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_OVERFLOW); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); - sljit_emit_op2(compiler, SLJIT_XOR | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -1); - /* buf[7] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_ZERO); - sljit_emit_op2(compiler, SLJIT_XOR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, -1, SLJIT_R1, 0); - /* buf[8] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 8, SLJIT_ZERO); - sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_IMM, 0xffff, SLJIT_R0, 0); - sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 0xffff); - /* buf[9] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 9, SLJIT_NOT_ZERO); - sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_IMM, 0xffff, SLJIT_R1, 0); - sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_IMM, 0xffff); - sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0); - sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 0x1); - /* buf[10] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, SLJIT_NOT_ZERO); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -(sljit_sw)(~(sljit_uw)0 >> 1) - 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R0, 0); - /* buf[11] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 11, SLJIT_OVERFLOW); - sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R0, 0); - /* buf[12] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 12, SLJIT_OVERFLOW); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 9); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 0, SLJIT_R0, 0); - /* buf[13] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 13, SLJIT_LESS); - /* buf[14] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 14, SLJIT_ZERO); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 0, SLJIT_R0, 0); - /* buf[15] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 15, SLJIT_LESS); - /* buf[16] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 16, SLJIT_ZERO); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -9); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R0, 0, SLJIT_IMM, 0, SLJIT_R0, 0); - /* buf[17] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 17, SLJIT_SIG_LESS); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -9); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_IMM, 0, SLJIT_R0, 0); - /* buf[18] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 18, SLJIT_SIG_GREATER); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op2(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0); - /* buf[19] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 19, SLJIT_ZERO); - /* buf[20] */ - sljit_emit_op2u(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 20, SLJIT_ZERO); - sljit_emit_op2(compiler, SLJIT_XOR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0); - /* buf[21] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 21, SLJIT_ZERO); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - FAILED(buf[1] != 1, "test8 case 1 failed\n"); - FAILED(buf[2] != 0, "test8 case 2 failed\n"); - FAILED(buf[3] != 0, "test8 case 3 failed\n"); - FAILED(buf[4] != 1, "test8 case 4 failed\n"); - FAILED(buf[5] != 1, "test8 case 5 failed\n"); - FAILED(buf[6] != 1, "test8 case 6 failed\n"); - FAILED(buf[7] != 1, "test8 case 7 failed\n"); - FAILED(buf[8] != 0, "test8 case 8 failed\n"); - FAILED(buf[9] != 1, "test8 case 9 failed\n"); - FAILED(buf[10] != 0, "test8 case 10 failed\n"); - FAILED(buf[11] != 1, "test8 case 11 failed\n"); - FAILED(buf[12] != 0, "test8 case 12 failed\n"); - FAILED(buf[13] != 1, "test8 case 13 failed\n"); - FAILED(buf[14] != 0, "test8 case 14 failed\n"); - FAILED(buf[15] != 0, "test8 case 15 failed\n"); - FAILED(buf[16] != 1, "test8 case 16 failed\n"); - FAILED(buf[17] != 0, "test8 case 17 failed\n"); - FAILED(buf[18] != 1, "test8 case 18 failed\n"); - FAILED(buf[19] != 1, "test8 case 19 failed\n"); - FAILED(buf[20] != 0, "test8 case 20 failed\n"); - FAILED(buf[21] != 1, "test8 case 21 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test9(void) -{ - /* Test shift. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[15]; - sljit_s32 i; -#ifdef SLJIT_PREF_SHIFT_REG - sljit_s32 shift_reg = SLJIT_PREF_SHIFT_REG; -#else - sljit_s32 shift_reg = SLJIT_R2; -#endif - - SLJIT_ASSERT(shift_reg >= SLJIT_R2 && shift_reg <= SLJIT_R3); - - if (verbose) - printf("Run test9\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - for (i = 0; i < 15; i++) - buf[i] = -1; - - buf[4] = 1 << 10; - buf[9] = 3; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 4, 2, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xf); - sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 3); - sljit_emit_op2(compiler, SLJIT_LSHR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 1); - /* buf[1] */ - sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -64); - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 2); - /* buf[2] */ - sljit_emit_op2(compiler, SLJIT_ASHR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_R0, 0, shift_reg, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0xff); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4); - sljit_emit_op2(compiler, SLJIT_SHL, shift_reg, 0, shift_reg, 0, SLJIT_R0, 0); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, shift_reg, 0); - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0xff); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8); - /* buf[4] */ - sljit_emit_op2(compiler, SLJIT_LSHR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R0, 0); - /* buf[5] */ - sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, shift_reg, 0, SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 0xf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2); - sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_R0, 0); - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_S1, 0); - sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_R0, 0); - /* buf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0xf00); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4); - sljit_emit_op2(compiler, SLJIT_LSHR, SLJIT_R1, 0, SLJIT_R2, 0, SLJIT_R0, 0); - /* buf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 8, SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)buf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 9); - /* buf[9] */ - sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), SLJIT_WORD_SHIFT); - - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 4); - sljit_emit_op2(compiler, SLJIT_SHL, shift_reg, 0, SLJIT_IMM, 2, shift_reg, 0); - /* buf[10] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, shift_reg, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xa9); - sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x7d00); - sljit_emit_op2(compiler, SLJIT_LSHR32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 32); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_R0, 0); -#endif - sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xe30000); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_op2(compiler, SLJIT_ASHR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0xffc0); -#else - sljit_emit_op2(compiler, SLJIT_ASHR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0xffe0); -#endif - sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x25000000); - sljit_emit_op2(compiler, SLJIT_SHL32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0xfffe1); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_R0, 0); -#endif - /* buf[11] */ - sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 11, SLJIT_R1, 0, SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x5c); - sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R1, 0, SLJIT_R0, 0, shift_reg, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0xf600); - sljit_emit_op2(compiler, SLJIT_LSHR32, SLJIT_R0, 0, SLJIT_R0, 0, shift_reg, 0); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - /* Alternative form of uint32 type cast. */ - sljit_emit_op2(compiler, SLJIT_AND, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0xffffffff); -#endif - sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x630000); - sljit_emit_op2(compiler, SLJIT_ASHR, SLJIT_R0, 0, SLJIT_R0, 0, shift_reg, 0); - /* buf[12] */ - sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 12, SLJIT_R1, 0, SLJIT_R0, 0); - - /* Test shift_reg keeps 64 bit value after 32 bit operation. */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -3062); - sljit_emit_op2(compiler, SLJIT_ASHR32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0); - /* buf[13] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 13, shift_reg, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -4691); - sljit_emit_op2(compiler, SLJIT_LSHR32, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_R0, 0); - /* buf[14] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 14, shift_reg, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - FAILED(buf[0] != 0x3c, "test9 case 1 failed\n"); - FAILED(buf[1] != 0xf0, "test9 case 2 failed\n"); - FAILED(buf[2] != -16, "test9 case 3 failed\n"); - FAILED(buf[3] != 0xff0, "test9 case 4 failed\n"); - FAILED(buf[4] != 4, "test9 case 5 failed\n"); - FAILED(buf[5] != 0xff00, "test9 case 6 failed\n"); - FAILED(buf[6] != 0x3c, "test9 case 7 failed\n"); - FAILED(buf[7] != 0xf0, "test9 case 8 failed\n"); - FAILED(buf[8] != 0xf0, "test9 case 9 failed\n"); - FAILED(buf[9] != 0x18, "test9 case 10 failed\n"); - FAILED(buf[10] != 32, "test9 case 11 failed\n"); - FAILED(buf[11] != 0x4ae37da9, "test9 case 12 failed\n"); - FAILED(buf[12] != 0x63f65c, "test9 case 13 failed\n"); - FAILED(buf[13] != -3062, "test9 case 14 failed\n"); - FAILED(buf[14] != -4691, "test9 case 15 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test10(void) -{ - /* Test multiplications. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[7]; - - if (verbose) - printf("Run test10\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 3; - buf[1] = 0; - buf[2] = 0; - buf[3] = 6; - buf[4] = -10; - buf[5] = 0; - buf[6] = 0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5); - sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 7); - sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_R2, 0, SLJIT_IMM, 8); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_IMM, -3, SLJIT_IMM, -4); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -2); - /* buf[3] */ - sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw) / 2); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf[3]); - /* buf[4] */ - sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 1, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 1, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 9); - sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R0, 0); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_R0, 0); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3); - sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x123456789)); - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_R0, 0); -#endif - sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 11, SLJIT_IMM, 10); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func1((sljit_sw)&buf) != 110, "test10 case 1 failed\n"); - FAILED(buf[0] != 15, "test10 case 2 failed\n"); - FAILED(buf[1] != 56, "test10 case 3 failed\n"); - FAILED(buf[2] != 12, "test10 case 4 failed\n"); - FAILED(buf[3] != -12, "test10 case 5 failed\n"); - FAILED(buf[4] != 100, "test10 case 6 failed\n"); - FAILED(buf[5] != 81, "test10 case 7 failed\n"); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - FAILED(buf[6] != SLJIT_W(0x123456789) * 3, "test10 case 8 failed\n"); -#endif - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test11(void) -{ - /* Test rewritable constants. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - struct sljit_const* const1; - struct sljit_const* const2; - struct sljit_const* const3; - struct sljit_const* const4; - void* value; - sljit_sw executable_offset; - sljit_uw const1_addr; - sljit_uw const2_addr; - sljit_uw const3_addr; - sljit_uw const4_addr; -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_sw word_value1 = (sljit_sw)SLJIT_W(0xaaaaaaaaaaaaaaaa); - sljit_sw word_value2 = (sljit_sw)SLJIT_W(0xfee1deadfbadf00d); -#else - sljit_sw word_value1 = (sljit_sw)0xaaaaaaaal; - sljit_sw word_value2 = (sljit_sw)0xfbadf00dl; -#endif - sljit_sw buf[3]; - - if (verbose) - printf("Run test11\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 0; - buf[1] = 0; - buf[2] = 0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0, 0, 0); - - SLJIT_ASSERT(!sljit_alloc_memory(compiler, 0)); - SLJIT_ASSERT(!sljit_alloc_memory(compiler, 16 * sizeof(sljit_sw) + 1)); - - /* buf[0] */ - const1 = sljit_emit_const(compiler, SLJIT_MEM0(), (sljit_sw)&buf[0], -0x81b9); - - value = sljit_alloc_memory(compiler, 16 * sizeof(sljit_sw)); - if (value != NULL) - { - SLJIT_ASSERT(!((sljit_sw)value & ((sljit_sw)sizeof(sljit_sw) - 1))); - memset(value, 255, 16 * sizeof(sljit_sw)); - } - - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2); - const2 = sljit_emit_const(compiler, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT - 1, -65535); - /* buf[2] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf[0] + 2 * (sljit_sw)sizeof(sljit_sw) - 2); - const3 = sljit_emit_const(compiler, SLJIT_MEM1(SLJIT_R0), 0, word_value1); - - value = sljit_alloc_memory(compiler, 17); - if (value != NULL) - { - SLJIT_ASSERT(!((sljit_sw)value & ((sljit_sw)sizeof(sljit_sw) - 1))); - memset(value, 255, 16); - } - - /* Return vaue */ - const4 = sljit_emit_const(compiler, SLJIT_RETURN_REG, 0, (sljit_sw)0xf7afcdb7); - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - executable_offset = sljit_get_executable_offset(compiler); - const1_addr = sljit_get_const_addr(const1); - const2_addr = sljit_get_const_addr(const2); - const3_addr = sljit_get_const_addr(const3); - const4_addr = sljit_get_const_addr(const4); - sljit_free_compiler(compiler); - - FAILED(code.func1((sljit_sw)&buf) != (sljit_sw)0xf7afcdb7, "test11 case 1 failed\n"); - FAILED(buf[0] != -0x81b9, "test11 case 2 failed\n"); - FAILED(buf[1] != -65535, "test11 case 3 failed\n"); - FAILED(buf[2] != word_value1, "test11 case 4 failed\n"); - - /* buf[0] */ - sljit_set_const(const1_addr, -1, executable_offset); - /* buf[1] */ - sljit_set_const(const2_addr, word_value2, executable_offset); - /* buf[2] */ - sljit_set_const(const3_addr, (sljit_sw)0xbab0fea1, executable_offset); - /* Return vaue */ - sljit_set_const(const4_addr, -60089, executable_offset); - - FAILED(code.func1((sljit_sw)&buf) != -60089, "test11 case 5 failed\n"); - FAILED(buf[0] != -1, "test11 case 6 failed\n"); - FAILED(buf[1] != word_value2, "test11 case 7 failed\n"); - FAILED(buf[2] != (sljit_sw)0xbab0fea1, "test11 case 8 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test12(void) -{ - /* Test rewriteable jumps. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - struct sljit_label *label1; - struct sljit_label *label2; - struct sljit_label *label3; - struct sljit_jump *jump1; - struct sljit_jump *jump2; - struct sljit_jump *jump3; - sljit_sw executable_offset; - void* value; - sljit_uw jump1_addr; - sljit_uw label1_addr; - sljit_uw label2_addr; - sljit_sw buf[1]; - - if (verbose) - printf("Run test12\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P, W), 3, 2, 0, 0, 0); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_S1, 0, SLJIT_IMM, 10); - jump1 = sljit_emit_jump(compiler, SLJIT_REWRITABLE_JUMP | SLJIT_SIG_GREATER); - /* Default handler. */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 5); - jump2 = sljit_emit_jump(compiler, SLJIT_JUMP); - - value = sljit_alloc_memory(compiler, 15); - if (value != NULL) - { - SLJIT_ASSERT(!((sljit_sw)value & ((sljit_sw)sizeof(sljit_sw) - 1))); - memset(value, 255, 15); - } - - /* Handler 1. */ - label1 = sljit_emit_label(compiler); - sljit_emit_op0(compiler, SLJIT_ENDBR); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 6); - jump3 = sljit_emit_jump(compiler, SLJIT_JUMP); - /* Handler 2. */ - label2 = sljit_emit_label(compiler); - sljit_emit_op0(compiler, SLJIT_ENDBR); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 7); - /* Exit. */ - label3 = sljit_emit_label(compiler); - sljit_emit_op0(compiler, SLJIT_ENDBR); - sljit_set_label(jump2, label3); - sljit_set_label(jump3, label3); - /* By default, set to handler 1. */ - sljit_set_label(jump1, label1); - sljit_emit_return_void(compiler); - - value = sljit_alloc_memory(compiler, 8); - if (value != NULL) - { - SLJIT_ASSERT(!((sljit_sw)value & ((sljit_sw)sizeof(sljit_sw) - 1))); - memset(value, 255, 8); - } - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - executable_offset = sljit_get_executable_offset(compiler); - jump1_addr = sljit_get_jump_addr(jump1); - label1_addr = sljit_get_label_addr(label1); - label2_addr = sljit_get_label_addr(label2); - sljit_free_compiler(compiler); - - code.func2((sljit_sw)&buf, 4); - FAILED(buf[0] != 5, "test12 case 1 failed\n"); - - code.func2((sljit_sw)&buf, 11); - FAILED(buf[0] != 6, "test12 case 2 failed\n"); - - sljit_set_jump_addr(jump1_addr, label2_addr, executable_offset); - code.func2((sljit_sw)&buf, 12); - FAILED(buf[0] != 7, "test12 case 3 failed\n"); - - sljit_set_jump_addr(jump1_addr, label1_addr, executable_offset); - code.func2((sljit_sw)&buf, 13); - FAILED(buf[0] != 6, "test12 case 4 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test13(void) -{ - /* Test fpu monadic functions. */ - executable_code code; - struct sljit_compiler* compiler; - sljit_f64 buf[7]; - sljit_sw buf2[6]; - - if (verbose) - printf("Run test13\n"); - - if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - if (verbose) - printf("no fpu available, test13 skipped\n"); - successful_tests++; - return; - } - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - buf[0] = 7.75; - buf[1] = -4.5; - buf[2] = 0.0; - buf[3] = 0.0; - buf[4] = 0.0; - buf[5] = 0.0; - buf[6] = 0.0; - - buf2[0] = 10; - buf2[1] = 10; - buf2[2] = 10; - buf2[3] = 10; - buf2[4] = 10; - buf2[5] = 10; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P, P), 3, 2, 6, 0, 0); - /* buf[2] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM0(), (sljit_sw)&buf[2], SLJIT_MEM0(), (sljit_sw)&buf[1]); - /* buf[3] */ - sljit_emit_fop1(compiler, SLJIT_ABS_F64, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64)); - /* buf[4] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM0(), (sljit_sw)&buf[0]); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2 * sizeof(sljit_f64)); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0); - sljit_emit_fop1(compiler, SLJIT_NEG_F64, SLJIT_FR2, 0, SLJIT_FR0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR3, 0, SLJIT_FR2, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM0(), (sljit_sw)&buf[4], SLJIT_FR3, 0); - /* buf[5] */ - sljit_emit_fop1(compiler, SLJIT_ABS_F64, SLJIT_FR4, 0, SLJIT_FR1, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f64), SLJIT_FR4, 0); - /* buf[6] */ - sljit_emit_fop1(compiler, SLJIT_NEG_F64, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f64), SLJIT_FR4, 0); - - /* buf2[0] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_GREATER, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64)); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_F_GREATER); - /* buf2[1] */ - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_GREATER, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64), SLJIT_FR5, 0); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_sw), SLJIT_F_GREATER); - /* buf2[2] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_FR5, 0); - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_FR1, 0); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_sw), SLJIT_F_EQUAL); - /* buf2[3] */ - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_LESS, SLJIT_FR1, 0, SLJIT_FR1, 0); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw), SLJIT_F_LESS); - /* buf2[4] */ - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64)); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_F_EQUAL); - /* buf2[5] */ - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_NOT_EQUAL, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64)); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_F_NOT_EQUAL); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func2((sljit_sw)&buf, (sljit_sw)&buf2); - FAILED(buf[2] != -4.5, "test13 case 1 failed\n"); - FAILED(buf[3] != 4.5, "test13 case 2 failed\n"); - FAILED(buf[4] != -7.75, "test13 case 3 failed\n"); - FAILED(buf[5] != 4.5, "test13 case 4 failed\n"); - FAILED(buf[6] != -4.5, "test13 case 5 failed\n"); - - FAILED(buf2[0] != 1, "test13 case 6 failed\n"); - FAILED(buf2[1] != 0, "test13 case 7 failed\n"); - FAILED(buf2[2] != 1, "test13 case 8 failed\n"); - FAILED(buf2[3] != 0, "test13 case 9 failed\n"); - FAILED(buf2[4] != 0, "test13 case 10 failed\n"); - FAILED(buf2[5] != 1, "test13 case 11 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test14(void) -{ - /* Test fpu diadic functions. */ - executable_code code; - struct sljit_compiler* compiler; - sljit_f64 buf[15]; - - if (verbose) - printf("Run test14\n"); - - if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - if (verbose) - printf("no fpu available, test14 skipped\n"); - successful_tests++; - return; - } - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - buf[0] = 7.25; - buf[1] = 3.5; - buf[2] = 1.75; - buf[3] = 0.0; - buf[4] = 0.0; - buf[5] = 0.0; - buf[6] = 0.0; - buf[7] = 0.0; - buf[8] = 0.0; - buf[9] = 0.0; - buf[10] = 0.0; - buf[11] = 0.0; - buf[12] = 8.0; - buf[13] = 4.0; - buf[14] = 0.0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 1, 6, 0, 0); - - /* ADD */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_f64)); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64)); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 2); - /* buf[3] */ - sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 3, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_FR0, 0, SLJIT_FR0, 0, SLJIT_FR1, 0); - sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_FR1, 0, SLJIT_FR0, 0, SLJIT_FR1, 0); - /* buf[4] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 4, SLJIT_FR0, 0); - /* buf[5] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 5, SLJIT_FR1, 0); - - /* SUB */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 2); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 2); - /* buf[6] */ - sljit_emit_fop2(compiler, SLJIT_SUB_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 6, SLJIT_FR3, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), SLJIT_F64_SHIFT); - sljit_emit_fop2(compiler, SLJIT_SUB_F64, SLJIT_FR2, 0, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 2); - sljit_emit_fop2(compiler, SLJIT_SUB_F64, SLJIT_FR3, 0, SLJIT_FR2, 0, SLJIT_FR3, 0); - /* buf[7] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 7, SLJIT_FR2, 0); - /* buf[8] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 8, SLJIT_FR3, 0); - - /* MUL */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1); - /* buf[9] */ - sljit_emit_fop2(compiler, SLJIT_MUL_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 9, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), SLJIT_F64_SHIFT, SLJIT_FR1, 0); - sljit_emit_fop2(compiler, SLJIT_MUL_F64, SLJIT_FR1, 0, SLJIT_FR1, 0, SLJIT_FR2, 0); - sljit_emit_fop2(compiler, SLJIT_MUL_F64, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 2, SLJIT_FR2, 0); - /* buf[10] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 10, SLJIT_FR1, 0); - /* buf[11] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 11, SLJIT_FR5, 0); - - /* DIV */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 12); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 13); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR4, 0, SLJIT_FR5, 0); - /* buf[12] */ - sljit_emit_fop2(compiler, SLJIT_DIV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 12, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 12, SLJIT_FR1, 0); - sljit_emit_fop2(compiler, SLJIT_DIV_F64, SLJIT_FR5, 0, SLJIT_FR5, 0, SLJIT_FR1, 0); - sljit_emit_fop2(compiler, SLJIT_DIV_F64, SLJIT_FR4, 0, SLJIT_FR1, 0, SLJIT_FR4, 0); - /* buf[13] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 13, SLJIT_FR5, 0); - /* buf[14] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64) * 14, SLJIT_FR4, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - FAILED(buf[3] != 10.75, "test14 case 1 failed\n"); - FAILED(buf[4] != 5.25, "test14 case 2 failed\n"); - FAILED(buf[5] != 7.0, "test14 case 3 failed\n"); - FAILED(buf[6] != 0.0, "test14 case 4 failed\n"); - FAILED(buf[7] != 5.5, "test14 case 5 failed\n"); - FAILED(buf[8] != 3.75, "test14 case 6 failed\n"); - FAILED(buf[9] != 24.5, "test14 case 7 failed\n"); - FAILED(buf[10] != 38.5, "test14 case 8 failed\n"); - FAILED(buf[11] != 9.625, "test14 case 9 failed\n"); - FAILED(buf[12] != 2.0, "test14 case 10 failed\n"); - FAILED(buf[13] != 2.0, "test14 case 11 failed\n"); - FAILED(buf[14] != 0.5, "test14 case 12 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static sljit_sw func(sljit_sw a, sljit_sw b, sljit_sw c) -{ - return a + b + c + 5; -} - -static sljit_sw func4(sljit_sw a, sljit_sw b, sljit_sw c, sljit_sw d) -{ - return func(a, b, c) + d; -} - -static void test15(void) -{ - /* Test function call. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - struct sljit_jump* jump = NULL; - sljit_sw buf[9]; - - if (verbose) - printf("Run test15\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 0; - buf[1] = 0; - buf[2] = 0; - buf[3] = 0; - buf[4] = 0; - buf[5] = 0; - buf[6] = 0; - buf[7] = 0; - buf[8] = SLJIT_FUNC_ADDR(func); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 4, 2, 0, 0, 0); - - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 7); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -3); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(func)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_RETURN_REG, 0); - - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -5); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -10); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2); - jump = sljit_emit_call(compiler, SLJIT_CALL | SLJIT_REWRITABLE_JUMP, SLJIT_ARGS3(W, W, W, W)); - sljit_set_target(jump, (sljit_uw)-1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_RETURN_REG, 0); - - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 40); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -3); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0); - - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -60); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -30); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0); - - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 10); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 16); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func)); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_R2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0); - - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 100); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 110); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 120); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func)); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_R3, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0); - - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 2); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 3); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func)); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_S1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0); - - /* buf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 2); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 3); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -6); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(func4)); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W), SLJIT_S1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0); - - /* buf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -10); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -16); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 6); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(W, W, W, W), SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_RETURN_REG, 0); - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_set_jump_addr(sljit_get_jump_addr(jump), SLJIT_FUNC_UADDR(func), sljit_get_executable_offset(compiler)); - sljit_free_compiler(compiler); - - FAILED(code.func1((sljit_sw)&buf) != -15, "test15 case 1 failed\n"); - FAILED(buf[0] != 14, "test15 case 2 failed\n"); - FAILED(buf[1] != -8, "test15 case 3 failed\n"); - FAILED(buf[2] != SLJIT_FUNC_ADDR(func) + 42, "test15 case 4 failed\n"); - FAILED(buf[3] != SLJIT_FUNC_ADDR(func) - 85, "test15 case 5 failed\n"); - FAILED(buf[4] != SLJIT_FUNC_ADDR(func) + 31, "test15 case 6 failed\n"); - FAILED(buf[5] != 335, "test15 case 7 failed\n"); - FAILED(buf[6] != 11, "test15 case 8 failed\n"); - FAILED(buf[7] != 5, "test15 case 9 failed\n"); - FAILED(buf[8] != -15, "test15 case 10 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test16(void) -{ - /* Ackermann benchmark. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - struct sljit_label *entry; - struct sljit_label *label; - struct sljit_jump *jump; - struct sljit_jump *jump1; - struct sljit_jump *jump2; - - if (verbose) - printf("Run test16\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - entry = sljit_emit_label(compiler); - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(W, W, W), 3, 2, 0, 0, 0); - /* If x == 0. */ - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_S0, 0, SLJIT_IMM, 0); - jump1 = sljit_emit_jump(compiler, SLJIT_EQUAL); - /* If y == 0. */ - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_S1, 0, SLJIT_IMM, 0); - jump2 = sljit_emit_jump(compiler, SLJIT_EQUAL); - - /* Ack(x,y-1). */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 1); - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W)); - sljit_set_label(jump, entry); - - /* Returns with Ack(x-1, Ack(x,y-1)). */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_RETURN_REG, 0); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 1); - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W)); - sljit_set_label(jump, entry); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - /* Returns with y+1. */ - label = sljit_emit_label(compiler); - sljit_set_label(jump1, label); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1, SLJIT_S1, 0); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - /* Returns with Ack(x-1,1) */ - label = sljit_emit_label(compiler); - sljit_set_label(jump2, label); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1); - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W)); - sljit_set_label(jump, entry); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func2(3, 3) != 61, "test16 case 1 failed\n"); - /* For benchmarking. */ - /* FAILED(code.func2(3, 11) != 16381, "test16 case 1 failed\n"); */ - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test17(void) -{ - /* Test arm constant pool. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_s32 i; - sljit_sw buf[5]; - - if (verbose) - printf("Run test17\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - for (i = 0; i < 5; i++) - buf[i] = 0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 1, 0, 0, 0); - for (i = 0; i <= 0xfff; i++) { - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x81818000 | i); - if ((i & 0x3ff) == 0) - /* buf[0-3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), (i >> 10) * (sljit_sw)sizeof(sljit_sw), SLJIT_R0, 0); - } - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - FAILED((sljit_uw)buf[0] != 0x81818000, "test17 case 1 failed\n"); - FAILED((sljit_uw)buf[1] != 0x81818400, "test17 case 2 failed\n"); - FAILED((sljit_uw)buf[2] != 0x81818800, "test17 case 3 failed\n"); - FAILED((sljit_uw)buf[3] != 0x81818c00, "test17 case 4 failed\n"); - FAILED((sljit_uw)buf[4] != 0x81818fff, "test17 case 5 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test18(void) -{ - /* Test 64 bit. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[11]; - - if (verbose) - printf("Run test18\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 0; - buf[1] = 0; - buf[2] = 0; - buf[3] = 0; - buf[4] = 0; - buf[5] = 100; - buf[6] = 100; - buf[7] = 100; - buf[8] = 100; - buf[9] = 0; -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) && (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) - buf[10] = SLJIT_W(1) << 32; -#else - buf[10] = 1; -#endif - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 2, 0, 0, 0); - -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, SLJIT_W(0x1122334455667788)); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0x1122334455667788)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(1000000000000)); - /* buf[2] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(1000000000000)); - /* buf[3] */ - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_IMM, SLJIT_W(5000000000000), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x1108080808)); - /* buf[4] */ - sljit_emit_op2(compiler, SLJIT_ADD32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x1120202020)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x1108080808)); - sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x1120202020)); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_ZERO); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_S1, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op2u(compiler, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x1120202020)); - /* buf[6] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_ZERO); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x1108080808)); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x2208080808)); - /* buf[7] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_LESS); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op2u(compiler, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x1104040404)); - /* buf[8] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 8, SLJIT_NOT_ZERO); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 4); - /* buf[9] */ - sljit_emit_op2(compiler, SLJIT_SHL32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 9, SLJIT_IMM, SLJIT_W(0xffff0000), SLJIT_R0, 0); - /* buf[10] */ - sljit_emit_op2(compiler, SLJIT_MUL32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 10, SLJIT_IMM, -1); -#else /* !SLJIT_64BIT_ARCHITECTURE */ - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 0x11223344); - /* buf[1] */ - sljit_emit_op2(compiler, SLJIT_ADD32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 0x44332211); -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - FAILED(buf[0] != SLJIT_W(0x1122334455667788), "test18 case 1 failed\n"); -#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) - FAILED(buf[1] != 0x55667788, "test18 case 2 failed\n"); -#else /* !SLJIT_LITTLE_ENDIAN */ - FAILED(buf[1] != SLJIT_W(0x5566778800000000), "test18 case 2 failed\n"); -#endif /* SLJIT_LITTLE_ENDIAN */ - FAILED(buf[2] != SLJIT_W(2000000000000), "test18 case 3 failed\n"); - FAILED(buf[3] != SLJIT_W(4000000000000), "test18 case 4 failed\n"); -#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) - FAILED(buf[4] != 0x28282828, "test18 case 5 failed\n"); -#else /* !SLJIT_LITTLE_ENDIAN */ - FAILED(buf[4] != SLJIT_W(0x2828282800000000), "test18 case 5 failed\n"); -#endif /* SLJIT_LITTLE_ENDIAN */ - FAILED(buf[5] != 0, "test18 case 6 failed\n"); - FAILED(buf[6] != 1, "test18 case 7 failed\n"); - FAILED(buf[7] != 1, "test18 case 8 failed\n"); - FAILED(buf[8] != 0, "test18 case 9 failed\n"); -#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) - FAILED(buf[9] != (sljit_sw)0xfff00000, "test18 case 10 failed\n"); - FAILED(buf[10] != (sljit_sw)0xffffffff, "test18 case 11 failed\n"); -#else /* !SLJIT_LITTLE_ENDIAN */ - FAILED(buf[9] != (sljit_sw)SLJIT_W(0xfff0000000000000), "test18 case 10 failed\n"); - FAILED(buf[10] != (sljit_sw)SLJIT_W(0xffffffff00000000), "test18 case 11 failed\n"); -#endif /* SLJIT_LITTLE_ENDIAN */ -#else /* !SLJIT_64BIT_ARCHITECTURE */ - FAILED(buf[0] != 0x11223344, "test18 case 1 failed\n"); - FAILED(buf[1] != 0x44332211, "test18 case 2 failed\n"); -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test19(void) -{ - /* Test arm partial instruction caching. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[10]; - - if (verbose) - printf("Run test19\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 6; - buf[1] = 4; - buf[2] = 0; - buf[3] = 0; - buf[4] = 0; - buf[5] = 0; - buf[6] = 2; - buf[7] = 0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 1, 0, 0, 0); - /* buf[0] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)); - /* buf[2] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM0(), (sljit_sw)&buf[2], SLJIT_MEM0(), (sljit_sw)&buf[1], SLJIT_MEM0(), (sljit_sw)&buf[0]); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw)); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_MEM1(SLJIT_R0), (sljit_sw)&buf[0], SLJIT_MEM1(SLJIT_R1), (sljit_sw)&buf[0]); - /* buf[4] */ - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_MEM0(), (sljit_sw)&buf[0], SLJIT_IMM, 2); - /* buf[5] */ - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_R0), (sljit_sw)&buf[0] + 4 * (sljit_sw)sizeof(sljit_sw)); - /* buf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_IMM, 10); - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 7); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_R1), (sljit_sw)&buf[5], SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM1(SLJIT_R1), (sljit_sw)&buf[5]); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - FAILED(buf[0] != 10, "test19 case 1 failed\n"); - FAILED(buf[1] != 4, "test19 case 2 failed\n"); - FAILED(buf[2] != 14, "test19 case 3 failed\n"); - FAILED(buf[3] != 14, "test19 case 4 failed\n"); - FAILED(buf[4] != 8, "test19 case 5 failed\n"); - FAILED(buf[5] != 6, "test19 case 6 failed\n"); - FAILED(buf[6] != 12, "test19 case 7 failed\n"); - FAILED(buf[7] != 10, "test19 case 8 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test20(void) -{ - /* Test stack. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - struct sljit_jump* jump; - struct sljit_label* label; - sljit_sw buf[6]; -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_sw offset_value = SLJIT_W(0x1234567812345678); -#else - sljit_sw offset_value = SLJIT_W(0x12345678); -#endif - - if (verbose) - printf("Run test20\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 5; - buf[1] = 12; - buf[2] = 0; - buf[3] = 0; - buf[4] = 111; - buf[5] = -12345; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 5, 5, 0, 0, 4 * sizeof(sljit_sw)); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw), SLJIT_MEM1(SLJIT_S0), 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_uw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, -1); - /* buf[2] */ - sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_uw), SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw)); - /* buf[3] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_uw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw), SLJIT_MEM1(SLJIT_SP), 0); - sljit_get_local_base(compiler, SLJIT_R0, 0, -offset_value); - sljit_get_local_base(compiler, SLJIT_MEM1(SLJIT_S0), 0, -0x1234); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), 0); - /* buf[4] */ - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_uw), SLJIT_MEM1(SLJIT_R0), offset_value, SLJIT_MEM1(SLJIT_R1), 0x1234 + sizeof(sljit_sw)); - /* buf[5] */ - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_uw)); - /* Dummy last instructions. */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 23); - sljit_emit_label(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func1((sljit_sw)&buf) != -12345, "test20 case 1 failed\n") - - FAILED(buf[2] != 60, "test20 case 2 failed\n"); - FAILED(buf[3] != 17, "test20 case 3 failed\n"); - FAILED(buf[4] != 7, "test20 case 4 failed\n"); - - sljit_free_code(code.code, NULL); - - compiler = sljit_create_compiler(NULL, NULL); - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(W, W, W, W), 3, 3, 0, 0, SLJIT_MAX_LOCAL_SIZE); - - sljit_get_local_base(compiler, SLJIT_R0, 0, SLJIT_MAX_LOCAL_SIZE - sizeof(sljit_sw)); - sljit_get_local_base(compiler, SLJIT_R1, 0, -(sljit_sw)sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -1); - label = sljit_emit_label(compiler); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R2, 0); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R0, 0); - jump = sljit_emit_jump(compiler, SLJIT_NOT_EQUAL); - sljit_set_label(jump, label); - - /* Saved registers should keep their value. */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_S1, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_S2, 0); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func3(1234, 5678, 9012) != 15924, "test20 case 5 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test21(void) -{ - /* Test set context. The parts of the jit code can be separated in the memory. */ - executable_code code1; - executable_code code2; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - struct sljit_jump* jump = NULL; - sljit_uw addr; - sljit_sw executable_offset; - sljit_sw buf[4]; - - if (verbose) - printf("Run test21\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 9; - buf[1] = -6; - buf[2] = 0; - buf[3] = 0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 2, 0, 0, 2 * sizeof(sljit_sw)); - - /* Return value */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 10); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_SP), 0); - - jump = sljit_emit_jump(compiler, SLJIT_JUMP | SLJIT_REWRITABLE_JUMP); - sljit_set_target(jump, 0); - - code1.code = sljit_generate_code(compiler); - CHECK(compiler); - - executable_offset = sljit_get_executable_offset(compiler); - addr = sljit_get_jump_addr(jump); - - sljit_free_compiler(compiler); - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - /* Other part of the jit code. */ - sljit_set_context(compiler, 0, 1, 3, 2, 0, 0, 2 * sizeof(sljit_sw)); - - sljit_emit_op0(compiler, SLJIT_ENDBR); - /* buf[2] */ - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 0); - /* buf[3] */ - sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw)); - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code2.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - sljit_set_jump_addr(addr, SLJIT_FUNC_UADDR(code2.code), executable_offset); - - FAILED(code1.func1((sljit_sw)&buf) != 19, "test21 case 1 failed\n"); - FAILED(buf[2] != -16, "test21 case 2 failed\n"); - FAILED(buf[3] != 100, "test21 case 3 failed\n"); - - sljit_free_code(code1.code, NULL); - sljit_free_code(code2.code, NULL); - successful_tests++; -} - -static void test22(void) -{ - /* Test simple byte and half-int data transfers. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[4]; - sljit_s16 sbuf[9]; - sljit_s8 bbuf[5]; - - if (verbose) - printf("Run test22\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 0; - buf[1] = 0; - buf[2] = -1; - buf[3] = -1; - - sbuf[0] = 0; - sbuf[1] = 0; - sbuf[2] = -9; - sbuf[3] = 0; - sbuf[4] = 0; - sbuf[5] = 0; - sbuf[6] = 0; - - bbuf[0] = 0; - bbuf[1] = 0; - bbuf[2] = -56; - bbuf[3] = 0; - bbuf[4] = 0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(VOID, P, P, P), 3, 3, 0, 0, 0); - - /* sbuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_IMM, -13); - /* sbuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s16), SLJIT_IMM, 0x1234); - sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s16)); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, 2 * sizeof(sljit_s16)); - /* sbuf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s16), SLJIT_MEM1(SLJIT_S1), -(sljit_sw)sizeof(sljit_s16)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xff0000 + 8000); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 2); - /* sbuf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 1, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 0x1234 - 3 * sizeof(sljit_s16)); - /* sbuf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_R2), 0x1234, SLJIT_IMM, -9317); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 0x1234 + 4 * sizeof(sljit_s16)); - /* sbuf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_R2), -0x1234, SLJIT_IMM, -9317); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 0x12348 - 5 * sizeof(sljit_s16)); - /* sbuf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_R2), 0x12348, SLJIT_IMM, -8888); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 0x12348 + 6 * sizeof(sljit_s16)); - /* sbuf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_R2), -0x12348, SLJIT_IMM, -8888); - - /* bbuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_MEM1(SLJIT_S2), 0, SLJIT_IMM, -45); - /* sbuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_s8), SLJIT_IMM, 0x12); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4 * sizeof(sljit_s8)); - sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_s8)); - sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_S1, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_S1, 0, SLJIT_S1, 0); - sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R2, 0, SLJIT_S1, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R2, 0); - /* bbuf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S2), 3 * sizeof(sljit_s8), SLJIT_S1, 0); - /* bbuf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM2(SLJIT_S2, SLJIT_R0), 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_R0, 0, SLJIT_IMM, 0); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func3((sljit_sw)&buf, (sljit_sw)&sbuf, (sljit_sw)&bbuf); - FAILED(buf[0] != -9, "test22 case 1 failed\n"); - FAILED(buf[1] != -56, "test22 case 2 failed\n"); - FAILED(buf[2] != 0, "test22 case 3 failed\n"); - FAILED(buf[3] != 0, "test22 case 4 failed\n"); - - FAILED(sbuf[0] != -13, "test22 case 5 failed\n"); - FAILED(sbuf[1] != 0x1234, "test22 case 6 failed\n"); - FAILED(sbuf[3] != 0x1234, "test22 case 7 failed\n"); - FAILED(sbuf[4] != 8000, "test22 case 8 failed\n"); - FAILED(sbuf[5] != -9317, "test22 case 9 failed\n"); - FAILED(sbuf[6] != -9317, "test22 case 10 failed\n"); - FAILED(sbuf[7] != -8888, "test22 case 11 failed\n"); - FAILED(sbuf[8] != -8888, "test22 case 12 failed\n"); - - FAILED(bbuf[0] != -45, "test22 case 13 failed\n"); - FAILED(bbuf[1] != 0x12, "test22 case 14 failed\n"); - FAILED(bbuf[3] != -56, "test22 case 15 failed\n"); - FAILED(bbuf[4] != 4, "test22 case 16 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test23(void) -{ - /* Test 32 bit / 64 bit signed / unsigned int transfer and conversion. - This test has do real things on 64 bit systems, but works on 32 bit systems as well. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[9]; - sljit_s32 ibuf[5]; - union { - sljit_s32 asint; - sljit_u8 asbytes[4]; - } u; -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_sw garbage = SLJIT_W(0x1234567812345678); -#else - sljit_sw garbage = 0x12345678; -#endif - - if (verbose) - printf("Run test23\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 0; - buf[1] = 0; - buf[2] = 0; - buf[3] = 0; - buf[4] = 0; - buf[5] = 0; - buf[6] = 0; - buf[7] = 0; - buf[8] = 0; - - ibuf[0] = 0; - ibuf[1] = 0; - ibuf[2] = -5791; - ibuf[3] = 43579; - ibuf[4] = 658923; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(W, P, P), 3, 3, 0, 0, 0); - /* ibuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_IMM, 34567); - /* ibuf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4); - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 0, SLJIT_IMM, -7654); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, garbage); - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, garbage); - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, garbage); - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32)); - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x0f00f00); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 0x7777); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0x7777 + 3 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[4] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 0x7777); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), -0x7777 + 4 * (sljit_sw)sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[5] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 5 * sizeof(sljit_sw)); - sljit_emit_op2(compiler, SLJIT_LSHR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_R1, SLJIT_R1), 0, SLJIT_IMM, 16); - /* buf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1, SLJIT_IMM, 64, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)&buf[7], SLJIT_IMM, 0x123456); - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), (sljit_sw)&buf[6], SLJIT_MEM0(), (sljit_sw)&buf[7]); - /* buf[7] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 5 * sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_R1, 0); - /* buf[8] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 7 * sizeof(sljit_sw)); - sljit_emit_op2(compiler, SLJIT_LSHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM2(SLJIT_R2, SLJIT_R2), 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf[8] - 0x12340); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0x12340, SLJIT_R2, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_R0), 0x12340, SLJIT_MEM1(SLJIT_R2), 3 * sizeof(sljit_sw), SLJIT_IMM, 6); - /* ibuf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_IMM, 0x12345678); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x2bd700 | 243); - sljit_emit_return(compiler, SLJIT_MOV_S8, SLJIT_R1, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func2((sljit_sw)&buf, (sljit_sw)&ibuf) != -13, "test23 case 1 failed\n"); - FAILED(buf[0] != -5791, "test23 case 2 failed\n"); - FAILED(buf[1] != 43579, "test23 case 3 failed\n"); - FAILED(buf[2] != 658923, "test23 case 4 failed\n"); - FAILED(buf[3] != 0x0f00f00, "test23 case 5 failed\n"); - FAILED(buf[4] != 0x0f00f00, "test23 case 6 failed\n"); - FAILED(buf[5] != 80, "test23 case 7 failed\n"); - FAILED(buf[6] != 0x123456, "test23 case 8 failed\n"); - FAILED(buf[7] != (sljit_sw)&buf[5], "test23 case 9 failed\n"); - FAILED(buf[8] != (sljit_sw)&buf[5] + 6, "test23 case 10 failed\n"); - - FAILED(ibuf[0] != 34567, "test23 case 11 failed\n"); - FAILED(ibuf[1] != -7654, "test23 case 12 failed\n"); - u.asint = ibuf[4]; -#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) - FAILED(u.asbytes[0] != 0x78, "test23 case 13 failed\n"); - FAILED(u.asbytes[1] != 0x56, "test23 case 14 failed\n"); - FAILED(u.asbytes[2] != 0x34, "test23 case 15 failed\n"); - FAILED(u.asbytes[3] != 0x12, "test23 case 16 failed\n"); -#else - FAILED(u.asbytes[0] != 0x12, "test23 case 13 failed\n"); - FAILED(u.asbytes[1] != 0x34, "test23 case 14 failed\n"); - FAILED(u.asbytes[2] != 0x56, "test23 case 15 failed\n"); - FAILED(u.asbytes[3] != 0x78, "test23 case 16 failed\n"); -#endif - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test24(void) -{ - /* Some complicated addressing modes. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[9]; - sljit_s16 sbuf[5]; - sljit_s8 bbuf[7]; - - if (verbose) - printf("Run test24\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - buf[0] = 100567; - buf[1] = 75799; - buf[2] = 0; - buf[3] = -8; - buf[4] = -50; - buf[5] = 0; - buf[6] = 0; - buf[7] = 0; - buf[8] = 0; - - sbuf[0] = 30000; - sbuf[1] = 0; - sbuf[2] = 0; - sbuf[3] = -12345; - sbuf[4] = 0; - - bbuf[0] = -128; - bbuf[1] = 0; - bbuf[2] = 0; - bbuf[3] = 99; - bbuf[4] = 0; - bbuf[5] = 0; - bbuf[6] = 0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(VOID, P, P, P), 3, 3, 0, 0, 0); - - /* Nothing should be updated. */ - /* sbuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM0(), (sljit_sw)&sbuf[1], SLJIT_MEM0(), (sljit_sw)&sbuf[0]); - /* bbuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_MEM0(), (sljit_sw)&bbuf[1], SLJIT_MEM0(), (sljit_sw)&bbuf[0]); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2); - /* sbuf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 1, SLJIT_MEM0(), (sljit_sw)&sbuf[3]); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf[0]); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2); - /* buf[2] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM2(SLJIT_R0, SLJIT_R2), SLJIT_WORD_SHIFT, SLJIT_MEM0(), (sljit_sw)&buf[0], SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_s8)); - /* bbuf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_R0), (sljit_sw)&bbuf[1], SLJIT_MEM1(SLJIT_R0), (sljit_sw)&bbuf[2]); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_s16)); - /* sbuf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_MEM1(SLJIT_R1), (sljit_sw)&sbuf[3], SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3); - /* buf[3] */ - sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S0, 0); - /* buf[4] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT); - - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 9 * sizeof(sljit_sw)); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 4 * sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -(4 << SLJIT_WORD_SHIFT)); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_R0, SLJIT_R2), 0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf - 0x7fff8000 + 6 * (sljit_sw)sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 952467); - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0x7fff8000, SLJIT_R1, 0); - /* buf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0x7fff8000 + sizeof(sljit_sw), SLJIT_MEM1(SLJIT_R0), 0x7fff8000); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf + 0x7fff7fff + 6 * (sljit_sw)sizeof(sljit_sw)); - /* buf[8] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_R0), -0x7fff7fff + 2 * (sljit_sw)sizeof(sljit_sw), SLJIT_MEM1(SLJIT_R0), -0x7fff7fff + (sljit_sw)sizeof(sljit_sw), SLJIT_MEM1(SLJIT_R0), -0x7fff7fff); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&bbuf - 0x7fff7ffe + 3 * (sljit_sw)sizeof(sljit_s8)); - /* bbuf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_MEM1(SLJIT_R0), 0x7fff7fff, SLJIT_MEM1(SLJIT_R0), 0x7fff7ffe); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&bbuf + 0x7fff7fff + 5 * (sljit_sw)sizeof(sljit_s8)); - /* bbuf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_MEM1(SLJIT_R0), -0x7fff7fff, SLJIT_MEM1(SLJIT_R0), -0x7fff8000); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&bbuf - SLJIT_W(0x123456123456)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&bbuf - SLJIT_W(0x123456123456)); - /* bbuf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_MEM1(SLJIT_R0), SLJIT_W(0x123456123456) + 6 * sizeof(sljit_s8), SLJIT_MEM1(SLJIT_R1), SLJIT_W(0x123456123456)); -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func3((sljit_sw)&buf, (sljit_sw)&sbuf, (sljit_sw)&bbuf); - FAILED(buf[2] != 176366, "test24 case 1 failed\n"); - FAILED(buf[3] != 64, "test24 case 2 failed\n"); - FAILED(buf[4] != -100, "test24 case 3 failed\n"); - FAILED(buf[5] != 100567, "test24 case 4 failed\n"); - FAILED(buf[6] != 952467, "test24 case 5 failed\n"); - FAILED(buf[7] != 952467, "test24 case 6 failed\n"); - FAILED(buf[8] != 952467 * 2, "test24 case 7 failed\n"); - - FAILED(sbuf[1] != 30000, "test24 case 8 failed\n"); - FAILED(sbuf[2] != -12345, "test24 case 9 failed\n"); - FAILED(sbuf[4] != sizeof(sljit_s16), "test24 case 10 failed\n"); - - FAILED(bbuf[1] != -128, "test24 case 11 failed\n"); - FAILED(bbuf[2] != 99, "test24 case 12 failed\n"); - FAILED(bbuf[4] != 99, "test24 case 13 failed\n"); - FAILED(bbuf[5] != 99, "test24 case 14 failed\n"); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - FAILED(bbuf[6] != -128, "test24 case 15 failed\n"); -#endif - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test25(void) -{ -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - /* 64 bit loads. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[14]; - - if (verbose) - printf("Run test25\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 7; - buf[1] = 0; - buf[2] = 0; - buf[3] = 0; - buf[4] = 0; - buf[5] = 0; - buf[6] = 0; - buf[7] = 0; - buf[8] = 0; - buf[9] = 0; - buf[10] = 0; - buf[11] = 0; - buf[12] = 0; - buf[13] = 0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 1, 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 1 * sizeof(sljit_sw), SLJIT_IMM, 0x7fff); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_IMM, -0x8000); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_IMM, 0x7fffffff); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(-0x80000000)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0x1234567887654321)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0xff80000000)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0x3ff0000000)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_IMM, (sljit_sw)SLJIT_W(0xfffffff800100000)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_IMM, (sljit_sw)SLJIT_W(0xfffffff80010f000)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0x07fff00000008001)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0x07fff00080010000)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0x07fff00080018001)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_IMM, SLJIT_W(0x07fff00ffff00000)); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - FAILED(buf[0] != 0, "test25 case 1 failed\n"); - FAILED(buf[1] != 0x7fff, "test25 case 2 failed\n"); - FAILED(buf[2] != -0x8000, "test25 case 3 failed\n"); - FAILED(buf[3] != 0x7fffffff, "test25 case 4 failed\n"); - FAILED(buf[4] != SLJIT_W(-0x80000000), "test25 case 5 failed\n"); - FAILED(buf[5] != SLJIT_W(0x1234567887654321), "test25 case 6 failed\n"); - FAILED(buf[6] != SLJIT_W(0xff80000000), "test25 case 7 failed\n"); - FAILED(buf[7] != SLJIT_W(0x3ff0000000), "test25 case 8 failed\n"); - FAILED((sljit_uw)buf[8] != SLJIT_W(0xfffffff800100000), "test25 case 9 failed\n"); - FAILED((sljit_uw)buf[9] != SLJIT_W(0xfffffff80010f000), "test25 case 10 failed\n"); - FAILED(buf[10] != SLJIT_W(0x07fff00000008001), "test25 case 11 failed\n"); - FAILED(buf[11] != SLJIT_W(0x07fff00080010000), "test25 case 12 failed\n"); - FAILED(buf[12] != SLJIT_W(0x07fff00080018001), "test25 case 13 failed\n"); - FAILED(buf[13] != SLJIT_W(0x07fff00ffff00000), "test25 case 14 failed\n"); - - sljit_free_code(code.code, NULL); -#endif /* SLJIT_64BIT_ARCHITECTURE */ - successful_tests++; -} - -static void test26(void) -{ - /* Aligned access without aligned offsets. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[4]; - sljit_s32 ibuf[4]; - sljit_f64 dbuf[4]; - - if (verbose) - printf("Run test26\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - buf[0] = -2789; - buf[1] = 0; - buf[2] = 4; - buf[3] = -4; - - ibuf[0] = -689; - ibuf[1] = 0; - ibuf[2] = -6; - ibuf[3] = 3; - - dbuf[0] = 5.75; - dbuf[1] = 0.0; - dbuf[2] = 0.0; - dbuf[3] = -4.0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(VOID, P, P, P), 3, 3, 0, 0, 0); - - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 3); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), -3); - /* ibuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32) - 1, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), -1); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) - 3, SLJIT_R0, 0); - - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 100); - /* buf[2] */ - sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_MEM1(SLJIT_R0), (sljit_sw)sizeof(sljit_sw) * 2 - 103, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2 - 3, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 3 - 3); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, 100); - /* ibuf[2] */ - sljit_emit_op2(compiler, SLJIT_MUL32, SLJIT_MEM1(SLJIT_R0), (sljit_sw)sizeof(sljit_s32) * 2 - 101, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32) * 2 - 1, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32) * 3 - 1); - - if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S2, 0, SLJIT_S2, 0, SLJIT_IMM, 3); - /* dbuf[1] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f64) - 3, SLJIT_MEM1(SLJIT_S2), -3); - /* dbuf[2] */ - sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f64) * 2 - 3, SLJIT_MEM1(SLJIT_S2), -3, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f64) - 3); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S2, 0, SLJIT_IMM, 2); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sizeof(sljit_f64) * 3 - 4) >> 1); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S2, 0, SLJIT_IMM, 1); - /* dbuf[3] */ - sljit_emit_fop2(compiler, SLJIT_DIV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64) * 3 - 5, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f64) * 2 - 3, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 1); - } - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func3((sljit_sw)&buf, (sljit_sw)&ibuf, (sljit_sw)&dbuf); - - FAILED(buf[1] != -689, "test26 case 1 failed\n"); - FAILED(buf[2] != -16, "test26 case 2 failed\n"); - FAILED(ibuf[1] != -2789, "test26 case 3 failed\n"); - FAILED(ibuf[2] != -18, "test26 case 4 failed\n"); - - if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - FAILED(dbuf[1] != 5.75, "test26 case 5 failed\n"); - FAILED(dbuf[2] != 11.5, "test26 case 6 failed\n"); - FAILED(dbuf[3] != -2.875, "test26 case 7 failed\n"); - } - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test27(void) -{ -#define SET_NEXT_BYTE(type) \ - cond_set(compiler, SLJIT_R2, 0, type); \ - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 1, SLJIT_R2, 0); \ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) -#define RESULT(i) i -#else -#define RESULT(i) (3 - i) -#endif - - /* Playing with conditional flags. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_u8 buf[41]; - sljit_u32 i; -#ifdef SLJIT_PREF_SHIFT_REG - sljit_s32 shift_reg = SLJIT_PREF_SHIFT_REG; -#else - sljit_s32 shift_reg = SLJIT_R2; -#endif - - SLJIT_ASSERT(shift_reg >= SLJIT_R2 && shift_reg <= SLJIT_R3); - - if (verbose) - printf("Run test27\n"); - - for (i = 0; i < sizeof(buf); ++i) - buf[i] = 10; - - FAILED(!compiler, "cannot create compiler\n"); - - /* 3 arguments passed, 3 arguments used. */ - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 4, 3, 0, 0, 0); - - /* buf[0] */ - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x1001); - sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 20); - /* 0x100100000 on 64 bit machines, 0x100000 on 32 bit machines. */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x800000); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_op0(compiler, SLJIT_ENDBR); /* ENDBR should keep the flags. */ - sljit_emit_op0(compiler, SLJIT_NOP); /* Nop should keep the flags. */ - SET_NEXT_BYTE(SLJIT_GREATER); - /* buf[2] */ - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_R1, 0); - SET_NEXT_BYTE(SLJIT_LESS); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_R1, 0); - sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_op0(compiler, SLJIT_ENDBR); /* ENDBR should keep the flags. */ - sljit_emit_op0(compiler, SLJIT_NOP); /* Nop should keep the flags. */ - SET_NEXT_BYTE(SLJIT_GREATER); - /* buf[4] */ - sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_R1, 0); - SET_NEXT_BYTE(SLJIT_LESS); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x1000); - sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 20); - sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0x10); - /* 0x100000010 on 64 bit machines, 0x10 on 32 bit machines. */ - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_IMM, 0x80); - SET_NEXT_BYTE(SLJIT_GREATER); - /* buf[6] */ - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 0x80); - SET_NEXT_BYTE(SLJIT_LESS); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_IMM, 0x80); - SET_NEXT_BYTE(SLJIT_GREATER); - /* buf[7] */ - sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 0x80); - SET_NEXT_BYTE(SLJIT_LESS); - - /* buf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1); - /* 0xff..ff on all machines. */ - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 1); - SET_NEXT_BYTE(SLJIT_LESS_EQUAL); - /* buf[9] */ - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 1); - SET_NEXT_BYTE(SLJIT_GREATER_EQUAL); - /* buf[10] */ - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R2, 0, SLJIT_R1, 0, SLJIT_IMM, -1); - SET_NEXT_BYTE(SLJIT_SIG_GREATER); - /* buf[12] */ - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, -1); - SET_NEXT_BYTE(SLJIT_SIG_LESS); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R1, 0, SLJIT_R0, 0); - SET_NEXT_BYTE(SLJIT_EQUAL); - /* buf[14] */ - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_R0, 0); - SET_NEXT_BYTE(SLJIT_NOT_EQUAL); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, -2); - SET_NEXT_BYTE(SLJIT_OVERFLOW); - /* buf[16] */ - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, -2); - SET_NEXT_BYTE(SLJIT_NOT_OVERFLOW); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, -2); - SET_NEXT_BYTE(SLJIT_GREATER_EQUAL); - /* buf[17] */ - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, -2); - SET_NEXT_BYTE(SLJIT_LESS_EQUAL); - /* buf[20] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)((sljit_uw)1 << ((8 * sizeof(sljit_uw)) - 1))); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, 1); - SET_NEXT_BYTE(SLJIT_SIG_LESS); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -1); - SET_NEXT_BYTE(SLJIT_SIG_GREATER); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, 1); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -2); - SET_NEXT_BYTE(SLJIT_SIG_GREATER_EQUAL); - /* buf[21] */ - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2); - SET_NEXT_BYTE(SLJIT_SIG_GREATER); - - /* buf[22] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x80000000); - sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 16); - sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 16); - /* 0x80..0 on 64 bit machines, 0 on 32 bit machines. */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0xffffffff); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0); - SET_NEXT_BYTE(SLJIT_OVERFLOW); - /* buf[24] */ - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0); - SET_NEXT_BYTE(SLJIT_NOT_OVERFLOW); - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_R1, 0); - sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0); - SET_NEXT_BYTE(SLJIT_OVERFLOW); - /* buf[25] */ - sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R1, 0); - SET_NEXT_BYTE(SLJIT_NOT_OVERFLOW); - - /* buf[26] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op2u(compiler, SLJIT_SUBC | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_R0, 0, SLJIT_IMM, 6, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 1, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1); - - /* buf[27] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); - sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op2u(compiler, SLJIT_ADDC | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op2(compiler, SLJIT_ADDC, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 9); - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 1, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1); - - /* buf[28] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, (8 * sizeof(sljit_sw)) - 1); - sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 0); - SET_NEXT_BYTE(SLJIT_EQUAL); - /* buf[34] */ - sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R0, 0); - SET_NEXT_BYTE(SLJIT_EQUAL); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op2(compiler, SLJIT_ASHR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0); - SET_NEXT_BYTE(SLJIT_EQUAL); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op2(compiler, SLJIT_LSHR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0xffffc0); - SET_NEXT_BYTE(SLJIT_NOT_EQUAL); - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op2(compiler, SLJIT_ASHR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R0, 0, shift_reg, 0); - SET_NEXT_BYTE(SLJIT_EQUAL); - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op2(compiler, SLJIT_LSHR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R0, 0, shift_reg, 0); - SET_NEXT_BYTE(SLJIT_NOT_EQUAL); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_SUBC | SLJIT_SET_CARRY, SLJIT_R2, 0, SLJIT_IMM, 1, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 1, SLJIT_R2, 0); - /* buf[35] */ - sljit_emit_op2u(compiler, SLJIT_SUBC | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_op2(compiler, SLJIT_SUBC, SLJIT_R2, 0, SLJIT_IMM, 1, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 2, SLJIT_R2, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 2); - - /* buf[36] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -34); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 0x1234); - SET_NEXT_BYTE(SLJIT_LESS); - /* buf[37] */ - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R0, 0, SLJIT_IMM, 0x1234); - SET_NEXT_BYTE(SLJIT_SIG_LESS); - /* buf[38] */ -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x12300000000) - 43); -#else - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -43); -#endif - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, -96); - sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_R1, 0); - SET_NEXT_BYTE(SLJIT_LESS); - /* buf[39] */ - sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_R1, 0); - SET_NEXT_BYTE(SLJIT_SIG_GREATER); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - - FAILED(buf[0] != RESULT(1), "test27 case 1 failed\n"); - FAILED(buf[1] != RESULT(2), "test27 case 2 failed\n"); - FAILED(buf[2] != 2, "test27 case 3 failed\n"); - FAILED(buf[3] != 1, "test27 case 4 failed\n"); - FAILED(buf[4] != RESULT(1), "test27 case 5 failed\n"); - FAILED(buf[5] != RESULT(2), "test27 case 6 failed\n"); - FAILED(buf[6] != 2, "test27 case 7 failed\n"); - FAILED(buf[7] != 1, "test27 case 8 failed\n"); - - FAILED(buf[8] != 2, "test27 case 9 failed\n"); - FAILED(buf[9] != 1, "test27 case 10 failed\n"); - FAILED(buf[10] != 2, "test27 case 11 failed\n"); - FAILED(buf[11] != 1, "test27 case 12 failed\n"); - FAILED(buf[12] != 1, "test27 case 13 failed\n"); - FAILED(buf[13] != 2, "test27 case 14 failed\n"); - FAILED(buf[14] != 2, "test27 case 15 failed\n"); - FAILED(buf[15] != 1, "test27 case 16 failed\n"); - FAILED(buf[16] != 1, "test27 case 17 failed\n"); - FAILED(buf[17] != 2, "test27 case 18 failed\n"); - FAILED(buf[18] != 1, "test27 case 19 failed\n"); - FAILED(buf[19] != 1, "test27 case 20 failed\n"); - FAILED(buf[20] != 1, "test27 case 21 failed\n"); - FAILED(buf[21] != 2, "test27 case 22 failed\n"); - - FAILED(buf[22] != RESULT(1), "test27 case 23 failed\n"); - FAILED(buf[23] != RESULT(2), "test27 case 24 failed\n"); - FAILED(buf[24] != 2, "test27 case 25 failed\n"); - FAILED(buf[25] != 1, "test27 case 26 failed\n"); - - FAILED(buf[26] != 5, "test27 case 27 failed\n"); - FAILED(buf[27] != 9, "test27 case 28 failed\n"); - - FAILED(buf[28] != 2, "test27 case 29 failed\n"); - FAILED(buf[29] != 1, "test27 case 30 failed\n"); - - FAILED(buf[30] != 1, "test27 case 31 failed\n"); - FAILED(buf[31] != 1, "test27 case 32 failed\n"); - FAILED(buf[32] != 1, "test27 case 33 failed\n"); - FAILED(buf[33] != 1, "test27 case 34 failed\n"); - - FAILED(buf[34] != 1, "test27 case 35 failed\n"); - FAILED(buf[35] != 0, "test27 case 36 failed\n"); - - FAILED(buf[36] != 2, "test27 case 37 failed\n"); - FAILED(buf[37] != 1, "test27 case 38 failed\n"); - FAILED(buf[38] != 2, "test27 case 39 failed\n"); - FAILED(buf[39] != 1, "test27 case 40 failed\n"); - FAILED(buf[40] != 10, "test27 case 41 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -#undef SET_NEXT_BYTE -#undef RESULT -} - -static void test28(void) -{ - /* Test mov. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - struct sljit_const* const1 = NULL; - struct sljit_label* label = NULL; - sljit_uw label_addr = 0; - sljit_sw buf[5]; - - if (verbose) - printf("Run test28\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - buf[0] = -36; - buf[1] = 8; - buf[2] = 0; - buf[3] = 10; - buf[4] = 0; - - FAILED(!compiler, "cannot create compiler\n"); - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 5, 5, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -234); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)); - sljit_emit_op2(compiler, SLJIT_MUL, SLJIT_S3, 0, SLJIT_R3, 0, SLJIT_R4, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_S3, 0); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_S3, 0, SLJIT_IMM, 0); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_NOT_ZERO); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_S3, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw)); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_S4, 0, SLJIT_S4, 0, SLJIT_R4, 0); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_S4, 0); - - const1 = sljit_emit_const(compiler, SLJIT_S3, 0, 0); - sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_S3, 0); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_S3, 0, SLJIT_S3, 0, SLJIT_IMM, 100); - label = sljit_emit_label(compiler); - sljit_emit_op0(compiler, SLJIT_ENDBR); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_S3, 0); - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R4, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - - label_addr = sljit_get_label_addr(label); - sljit_set_const(sljit_get_const_addr(const1), (sljit_sw)label_addr, sljit_get_executable_offset(compiler)); - - sljit_free_compiler(compiler); - - FAILED(code.func1((sljit_sw)&buf) != 8, "test28 case 1 failed\n"); - FAILED(buf[1] != -1872, "test28 case 2 failed\n"); - FAILED(buf[2] != 1, "test28 case 3 failed\n"); - FAILED(buf[3] != 2, "test28 case 4 failed\n"); - FAILED(buf[4] != (sljit_sw)label_addr, "test28 case 5 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test29(void) -{ - /* Test signed/unsigned bytes and halfs. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[25]; - sljit_s32 i; - - if (verbose) - printf("Run test29\n"); - - for (i = 0; i < 25; i++) - buf[i] = 0; - - FAILED(!compiler, "cannot create compiler\n"); - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 5, 5, 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R0, 0, SLJIT_IMM, -187); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R0, 0, SLJIT_IMM, -605); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_R0, 0, SLJIT_IMM, -56); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_R4, 0, SLJIT_IMM, 0xcde5); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_uw), SLJIT_R4, 0); - - sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_R0, 0, SLJIT_IMM, -45896); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_R0, 0, SLJIT_IMM, -1472797); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_R0, 0, SLJIT_IMM, -12890); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_R4, 0, SLJIT_IMM, 0x9cb0a6); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_uw), SLJIT_R4, 0); - -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-3580429715)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-100722768662)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-1457052677972)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R4, 0, SLJIT_IMM, SLJIT_W(0xcef97a70b5)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_uw), SLJIT_R4, 0); -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -187); - sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -605); - sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R0, 0, SLJIT_S2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -56); - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_R0, 0, SLJIT_R2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 0xcde5); - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_R4, 0, SLJIT_R3, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_uw), SLJIT_R4, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -45896); - sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1472797); - sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_R0, 0, SLJIT_S2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -12890); - sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_R0, 0, SLJIT_R2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 0x9cb0a6); - sljit_emit_op1(compiler, SLJIT_MOV_U16, SLJIT_R4, 0, SLJIT_R3, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 19 * sizeof(sljit_uw), SLJIT_R4, 0); - -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(-3580429715)); - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 20 * sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, SLJIT_W(-100722768662)); - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_S2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 21 * sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, SLJIT_W(-1457052677972)); - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_R2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 22 * sizeof(sljit_uw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, SLJIT_W(0xcef97a70b5)); - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R4, 0, SLJIT_R3, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 23 * sizeof(sljit_uw), SLJIT_R4, 0); -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 0x9faa5); - sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_S2, 0, SLJIT_S2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 24 * sizeof(sljit_uw), SLJIT_S2, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - FAILED(buf[0] != 69, "test29 case 1 failed\n"); - FAILED(buf[1] != -93, "test29 case 2 failed\n"); - FAILED(buf[2] != 200, "test29 case 3 failed\n"); - FAILED(buf[3] != 0xe5, "test29 case 4 failed\n"); - FAILED(buf[4] != 19640, "test29 case 5 failed\n"); - FAILED(buf[5] != -31005, "test29 case 6 failed\n"); - FAILED(buf[6] != 52646, "test29 case 7 failed\n"); - FAILED(buf[7] != 0xb0a6, "test29 case 8 failed\n"); - -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - FAILED(buf[8] != SLJIT_W(714537581), "test29 case 9 failed\n"); - FAILED(buf[9] != SLJIT_W(-1938520854), "test29 case 10 failed\n"); - FAILED(buf[10] != SLJIT_W(3236202668), "test29 case 11 failed\n"); - FAILED(buf[11] != SLJIT_W(0xf97a70b5), "test29 case 12 failed\n"); -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - FAILED(buf[12] != 69, "test29 case 13 failed\n"); - FAILED(buf[13] != -93, "test29 case 14 failed\n"); - FAILED(buf[14] != 200, "test29 case 15 failed\n"); - FAILED(buf[15] != 0xe5, "test29 case 16 failed\n"); - FAILED(buf[16] != 19640, "test29 case 17 failed\n"); - FAILED(buf[17] != -31005, "test29 case 18 failed\n"); - FAILED(buf[18] != 52646, "test29 case 19 failed\n"); - FAILED(buf[19] != 0xb0a6, "test29 case 20 failed\n"); - -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - FAILED(buf[20] != SLJIT_W(714537581), "test29 case 21 failed\n"); - FAILED(buf[21] != SLJIT_W(-1938520854), "test29 case 22 failed\n"); - FAILED(buf[22] != SLJIT_W(3236202668), "test29 case 23 failed\n"); - FAILED(buf[23] != SLJIT_W(0xf97a70b5), "test29 case 24 failed\n"); -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - FAILED(buf[24] != -91, "test29 case 25 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test30(void) -{ - /* Test unused results. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[1]; - - if (verbose) - printf("Run test30\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 0; - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 5, 5, 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 1); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S1, 0, SLJIT_IMM, SLJIT_W(-0x123ffffffff)); -#else - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S1, 0, SLJIT_IMM, 1); -#endif - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, 1); - - /* Some calculations with unused results. */ - sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_GREATER_EQUAL, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_op2u(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_op2u(compiler, SLJIT_SHL | SLJIT_SET_Z, SLJIT_S3, 0, SLJIT_R2, 0); - sljit_emit_op2u(compiler, SLJIT_LSHR | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 5); - sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_IMM, 0xff); - - /* Testing that any change happens. */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R2, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R3, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R4, 0); - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_S1, 0, SLJIT_S1, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S1, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S2, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S3, 0); - /* buf[0] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0, SLJIT_S4, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - FAILED(buf[0] != 9, "test30 case 1 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test31(void) -{ - /* Integer mul and set flags. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[12]; - sljit_s32 i; -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_sw big_word = SLJIT_W(0x7fffffff00000000); - sljit_sw big_word2 = SLJIT_W(0x7fffffff00000012); -#else - sljit_sw big_word = 0x7fffffff; - sljit_sw big_word2 = 0x00000012; -#endif - - if (verbose) - printf("Run test31\n"); - - for (i = 0; i < 12; i++) - buf[i] = 3; - - FAILED(!compiler, "cannot create compiler\n"); - - /* buf[0] */ - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 5, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0); - sljit_emit_op2u(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_IMM, -45); - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_NOT_OVERFLOW); - /* buf[1] */ - sljit_emit_op2u(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_IMM, -45); - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_OVERFLOW); - - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, big_word); - sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_S2, 0, SLJIT_IMM, -2); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 33); /* Should not change flags. */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0); /* Should not change flags. */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_OVERFLOW); - /* buf[3] */ - sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_S2, 0, SLJIT_IMM, -2); - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_NOT_OVERFLOW); - - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S3, 0, SLJIT_IMM, 0x3f6b0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S4, 0, SLJIT_IMM, 0x2a783); - sljit_emit_op2(compiler, SLJIT_MUL32 | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_S3, 0, SLJIT_S4, 0); - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_OVERFLOW); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R1, 0); - - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, big_word2); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_R1, 0); - sljit_emit_op2(compiler, SLJIT_MUL32 | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 23); - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_OVERFLOW); - - /* buf[7] */ - sljit_emit_op2u(compiler, SLJIT_MUL32 | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_IMM, -23); - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_NOT_OVERFLOW); - /* buf[8] */ - sljit_emit_op2u(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_IMM, -23); - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_NOT_OVERFLOW); - - /* buf[9] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 67); - sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, -23); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - - FAILED(buf[0] != 1, "test31 case 1 failed\n"); - FAILED(buf[1] != 2, "test31 case 2 failed\n"); -/* Qemu issues for 64 bit muls. */ -#if !(defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - FAILED(buf[2] != 1, "test31 case 3 failed\n"); - FAILED(buf[3] != 2, "test31 case 4 failed\n"); -#endif - FAILED(buf[4] != 1, "test31 case 5 failed\n"); - FAILED((buf[5] & (sljit_sw)0xffffffff) != (sljit_sw)0x85540c10, "test31 case 6 failed\n"); - FAILED(buf[6] != 2, "test31 case 7 failed\n"); - FAILED(buf[7] != 1, "test31 case 8 failed\n"); -#if !(defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - FAILED(buf[8] != 1, "test31 case 9 failed\n"); -#endif - FAILED(buf[9] != -1541, "test31 case 10 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test32(void) -{ - /* Floating point set flags. */ - executable_code code; - struct sljit_compiler* compiler; - sljit_s32 i; - - sljit_sw buf[16]; - union { - sljit_f64 value; - struct { - sljit_s32 value1; - sljit_s32 value2; - } u; - } dbuf[4]; - - if (verbose) - printf("Run test32\n"); - - if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - if (verbose) - printf("no fpu available, test32 skipped\n"); - successful_tests++; - return; - } - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - for (i = 0; i < 16; i++) - buf[i] = 5; - - /* Two NaNs */ - dbuf[0].u.value1 = 0x7fffffff; - dbuf[0].u.value2 = 0x7fffffff; - dbuf[1].u.value1 = 0x7fffffff; - dbuf[1].u.value2 = 0x7fffffff; - dbuf[2].value = -13.0; - dbuf[3].value = 27.0; - - SLJIT_ASSERT(sizeof(sljit_f64) == 8 && sizeof(sljit_s32) == 4 && sizeof(dbuf[0]) == 8); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P, P), 1, 2, 4, 0, 0); - - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0); - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_UNORDERED, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64), SLJIT_FR0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f64)); - /* buf[0] */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_UNORDERED); - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_ORDERED, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64), SLJIT_FR0, 0); - /* buf[1] */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_ORDERED); - - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64)); - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_UNORDERED, SLJIT_FR1, 0, SLJIT_FR2, 0); - /* buf[2] */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_UNORDERED); - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_ORDERED, SLJIT_FR1, 0, SLJIT_FR2, 0); - /* buf[3] */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_ORDERED); - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_LESS, SLJIT_FR1, 0, SLJIT_FR2, 0); - /* buf[4] */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_F_LESS); - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_GREATER_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); - /* buf[5] */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_F_GREATER_EQUAL); - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_GREATER, SLJIT_FR1, 0, SLJIT_FR2, 0); - /* buf[6] */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_F_GREATER); - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_LESS_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); - /* buf[7] */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_F_LESS_EQUAL); - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); - /* buf[8] */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_F_EQUAL); - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_NOT_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); - /* buf[9] */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_F_NOT_EQUAL); - - sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_FR3, 0, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64)); - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_UNORDERED, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64)); - /* buf[10] */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_UNORDERED); - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_F_EQUAL, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64)); - /* buf[11] */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_F_EQUAL); - - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_ORDERED, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64), SLJIT_FR0, 0); - /* buf[12] */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_ORDERED); - - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | SLJIT_SET_UNORDERED, SLJIT_FR3, 0, SLJIT_FR2, 0); - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 0); - /* buf[13] */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_UNORDERED); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func2((sljit_sw)&buf, (sljit_sw)&dbuf); - - FAILED(buf[0] != 1, "test32 case 1 failed\n"); - FAILED(buf[1] != 2, "test32 case 2 failed\n"); - FAILED(buf[2] != 2, "test32 case 3 failed\n"); - FAILED(buf[3] != 1, "test32 case 4 failed\n"); - FAILED(buf[4] != 1, "test32 case 5 failed\n"); - FAILED(buf[5] != 2, "test32 case 6 failed\n"); - FAILED(buf[6] != 2, "test32 case 7 failed\n"); - FAILED(buf[7] != 1, "test32 case 8 failed\n"); - FAILED(buf[8] != 2, "test32 case 9 failed\n"); - FAILED(buf[9] != 1, "test32 case 10 failed\n"); - FAILED(buf[10] != 2, "test32 case 11 failed\n"); - FAILED(buf[11] != 1, "test32 case 12 failed\n"); - FAILED(buf[12] != 2, "test32 case 13 failed\n"); - FAILED(buf[13] != 1, "test32 case 14 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test33(void) -{ - /* Test setting multiple flags. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - struct sljit_jump* jump; - sljit_sw buf[10]; - - if (verbose) - printf("Run test33\n"); - - buf[0] = 3; - buf[1] = 3; - buf[2] = 3; - buf[3] = 3; - buf[4] = 3; - buf[5] = 3; - buf[6] = 3; - buf[7] = 3; - buf[8] = 3; - buf[9] = 3; - - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 3, 0, 0, 0); - - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 20); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 10); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_ZERO); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -10); - jump = sljit_emit_jump(compiler, SLJIT_LESS); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_IMM, 11); - sljit_set_label(jump, sljit_emit_label(compiler)); - - /* buf[2] */ - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_SIG_GREATER); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_IMM, 45); - jump = sljit_emit_jump(compiler, SLJIT_NOT_EQUAL); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_IMM, 55); - sljit_set_label(jump, sljit_emit_label(compiler)); - - /* buf[4-5] */ -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)SLJIT_W(0x8000000000000000)); -#else - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)SLJIT_W(0x80000000)); -#endif - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_IMM, 33); - jump = sljit_emit_jump(compiler, SLJIT_NOT_OVERFLOW); - /* buf[5] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_ZERO); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_IMM, 13); - sljit_set_label(jump, sljit_emit_label(compiler)); - - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x80000000); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_SUB32 | SLJIT_SET_Z | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_NOT_ZERO); - /* buf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_IMM, 78); - jump = sljit_emit_jump(compiler, SLJIT_OVERFLOW); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_IMM, 48); - sljit_set_label(jump, sljit_emit_label(compiler)); - - /* buf[8] */ -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)SLJIT_W(0x8000000000000000)); -#else - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)SLJIT_W(0x80000000)); -#endif - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_Z | SLJIT_SET_OVERFLOW, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_IMM, 30); - jump = sljit_emit_jump(compiler, SLJIT_NOT_OVERFLOW); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_IMM, 50); - /* buf[9] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_ZERO); - sljit_set_label(jump, sljit_emit_label(compiler)); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - - FAILED(buf[0] != 0, "test33 case 1 failed\n"); - FAILED(buf[1] != 11, "test33 case 2 failed\n"); - FAILED(buf[2] != 1, "test33 case 3 failed\n"); - FAILED(buf[3] != 45, "test33 case 4 failed\n"); - FAILED(buf[4] != 13, "test33 case 5 failed\n"); - FAILED(buf[5] != 0, "test33 case 6 failed\n"); - FAILED(buf[6] != 0, "test33 case 7 failed\n"); - FAILED(buf[7] != 48, "test33 case 8 failed\n"); - FAILED(buf[8] != 50, "test33 case 9 failed\n"); - FAILED(buf[9] != 1, "test33 case 10 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test34(void) -{ - /* Test fast calls. */ - executable_code codeA; - executable_code codeB; - executable_code codeC; - executable_code codeD; - executable_code codeE; - executable_code codeF; - struct sljit_compiler* compiler; - struct sljit_jump *jump; - struct sljit_label* label; - sljit_uw addr; - sljit_p buf[2]; - - if (verbose) - printf("Run test34\n"); - - buf[0] = 0; - buf[1] = 0; - - /* A */ - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - sljit_set_context(compiler, 0, 1, 5, 5, 0, 0, 2 * sizeof(sljit_p)); - - sljit_emit_op0(compiler, SLJIT_ENDBR); - sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R1, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 4); - sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_R1, 0); - - codeA.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - /* B */ - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - sljit_set_context(compiler, 0, 1, 5, 5, 0, 0, 2 * sizeof(sljit_p)); - - sljit_emit_op0(compiler, SLJIT_ENDBR); - sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R4, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 6); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(codeA.code)); - sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_R1, 0); - sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_R4, 0); - - codeB.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - /* C */ - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - sljit_set_context(compiler, 0, 1, 5, 5, 0, 0, 2 * sizeof(sljit_p)); - - sljit_emit_op0(compiler, SLJIT_ENDBR); - sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_p)); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 8); - jump = sljit_emit_jump(compiler, SLJIT_FAST_CALL | SLJIT_REWRITABLE_JUMP); - sljit_set_target(jump, SLJIT_FUNC_UADDR(codeB.code)); - sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_p)); - - codeC.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - /* D */ - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - sljit_set_context(compiler, 0, 1, 5, 5, 0, 0, 2 * sizeof(sljit_p)); - - sljit_emit_op0(compiler, SLJIT_ENDBR); - sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_SP), 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 10); - sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, SLJIT_FUNC_ADDR(codeC.code)); - sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_MEM1(SLJIT_SP), 0); - - codeD.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - /* E */ - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - sljit_set_context(compiler, 0, 1, 5, 5, 0, 0, 2 * sizeof(sljit_p)); - - sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 12); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_p), SLJIT_IMM, SLJIT_FUNC_ADDR(codeD.code)); - sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_p)); - sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_MEM1(SLJIT_S0), 0); - - codeE.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - /* F */ - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 5, 5, 0, 0, 2 * sizeof(sljit_p)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, SLJIT_FUNC_ADDR(codeE.code)); - label = sljit_emit_label(compiler); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0); - - codeF.code = sljit_generate_code(compiler); - CHECK(compiler); - addr = sljit_get_label_addr(label); - sljit_free_compiler(compiler); - - FAILED(codeF.func1((sljit_sw)&buf) != 40, "test34 case 1 failed\n"); - FAILED(buf[0] != addr - SLJIT_RETURN_ADDRESS_OFFSET, "test34 case 2 failed\n"); - - sljit_free_code(codeA.code, NULL); - sljit_free_code(codeB.code, NULL); - sljit_free_code(codeC.code, NULL); - sljit_free_code(codeD.code, NULL); - sljit_free_code(codeE.code, NULL); - sljit_free_code(codeF.code, NULL); - successful_tests++; -} - -static void test35(void) -{ - /* More complicated tests for fast calls. */ - executable_code codeA; - executable_code codeB; - executable_code codeC; - struct sljit_compiler* compiler; - struct sljit_jump *jump = NULL; - struct sljit_label* label; - sljit_sw executable_offset; - sljit_uw return_addr; - sljit_uw jump_addr = 0; - sljit_p buf[1]; - - if (verbose) - printf("Run test35\n"); - - buf[0] = 0; - - /* A */ - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - sljit_set_context(compiler, 0, 0, 2, 2, 0, 0, 0); - - sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_MEM0(), (sljit_sw)&buf[0]); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 5); - - jump = sljit_emit_jump(compiler, SLJIT_FAST_CALL | SLJIT_REWRITABLE_JUMP); - sljit_set_target(jump, 0); - - label = sljit_emit_label(compiler); - sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_MEM0(), (sljit_sw)&buf[0]); - - codeA.code = sljit_generate_code(compiler); - CHECK(compiler); - executable_offset = sljit_get_executable_offset(compiler); - jump_addr = sljit_get_jump_addr(jump); - sljit_free_compiler(compiler); - - /* B */ - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - sljit_set_context(compiler, 0, 0, 2, 2, 0, 0, 0); - - sljit_emit_op0(compiler, SLJIT_ENDBR); - sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R1, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 7); - sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_R1, 0); - - codeB.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - sljit_set_jump_addr(jump_addr, SLJIT_FUNC_UADDR(codeB.code), executable_offset); - - /* C */ - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 2, 2, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, SLJIT_FUNC_ADDR(codeA.code)); - label = sljit_emit_label(compiler); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0); - - codeC.code = sljit_generate_code(compiler); - CHECK(compiler); - return_addr = sljit_get_label_addr(label); - sljit_free_compiler(compiler); - - FAILED(codeC.func0() != 12, "test35 case 1 failed\n"); - FAILED(buf[0] != return_addr - SLJIT_RETURN_ADDRESS_OFFSET, "test35 case 2 failed\n"); - - sljit_free_code(codeA.code, NULL); - sljit_free_code(codeB.code, NULL); - sljit_free_code(codeC.code, NULL); - successful_tests++; -} - -static void cmp_test(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) -{ - /* 2 = true, 1 = false */ - struct sljit_jump* jump; - struct sljit_label* label; - - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 1, SLJIT_IMM, 2); - jump = sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w); - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 1, SLJIT_IMM, 1); - label = sljit_emit_label(compiler); - sljit_emit_op0(compiler, SLJIT_ENDBR); - sljit_set_label(jump, label); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1); -} - -#define TEST_CASES (7 + 10 + 12 + 11 + 4) -static void test36(void) -{ - /* Compare instruction. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - - sljit_s8 buf[TEST_CASES]; - sljit_s8 compare_buf[TEST_CASES] = { - 1, 1, 2, 2, 1, 2, 2, - 1, 1, 2, 2, 2, 1, 2, 2, 1, 1, - 2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, - 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, - 2, 1, 1, 2 - }; - sljit_sw data[4]; - sljit_s32 i; - - if (verbose) - printf("Run test36\n"); - - FAILED(!compiler, "cannot create compiler\n"); - for (i = 0; i < TEST_CASES; ++i) - buf[i] = 100; - data[0] = 32; - data[1] = -9; - data[2] = 43; - data[3] = -13; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P, P), 3, 2, 0, 0, 0); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 13); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 15); - /* buf[0], compare_buf[0-6] */ - cmp_test(compiler, SLJIT_EQUAL, SLJIT_IMM, 9, SLJIT_R0, 0); - /* buf[1] */ - cmp_test(compiler, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3); - /* buf[2] */ - cmp_test(compiler, SLJIT_EQUAL, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_IMM, -13); - /* buf[3] */ - cmp_test(compiler, SLJIT_NOT_EQUAL, SLJIT_IMM, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - /* buf[4] */ - cmp_test(compiler, SLJIT_NOT_EQUAL | SLJIT_REWRITABLE_JUMP, SLJIT_IMM, 0, SLJIT_R0, 0); - /* buf[5] */ - cmp_test(compiler, SLJIT_EQUAL, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT); - /* buf[6] */ - cmp_test(compiler, SLJIT_EQUAL | SLJIT_REWRITABLE_JUMP, SLJIT_R0, 0, SLJIT_IMM, 0); - - /* buf[7-16], compare_buf[7-16] */ - cmp_test(compiler, SLJIT_SIG_LESS, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -8); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0); - cmp_test(compiler, SLJIT_SIG_GREATER, SLJIT_R0, 0, SLJIT_IMM, 0); - cmp_test(compiler, SLJIT_SIG_LESS_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0); - cmp_test(compiler, SLJIT_SIG_LESS | SLJIT_REWRITABLE_JUMP, SLJIT_R0, 0, SLJIT_IMM, 0); - cmp_test(compiler, SLJIT_SIG_GREATER_EQUAL, SLJIT_R1, 0, SLJIT_IMM, 0); - cmp_test(compiler, SLJIT_SIG_GREATER, SLJIT_IMM, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_sw)); - cmp_test(compiler, SLJIT_SIG_LESS_EQUAL, SLJIT_IMM, 0, SLJIT_R1, 0); - cmp_test(compiler, SLJIT_SIG_LESS, SLJIT_IMM, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_sw)); - cmp_test(compiler, SLJIT_SIG_LESS, SLJIT_IMM, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw)); - cmp_test(compiler, SLJIT_SIG_LESS | SLJIT_REWRITABLE_JUMP, SLJIT_IMM, 0, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw)); - - /* buf[17-28], compare_buf[17-28] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0); - cmp_test(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_sw)); - cmp_test(compiler, SLJIT_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 8); - cmp_test(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_IMM, -10); - cmp_test(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_IMM, 8); - cmp_test(compiler, SLJIT_GREATER_EQUAL, SLJIT_IMM, 8, SLJIT_R1, 0); - cmp_test(compiler, SLJIT_GREATER_EQUAL | SLJIT_REWRITABLE_JUMP, SLJIT_IMM, 8, SLJIT_R1, 0); - cmp_test(compiler, SLJIT_GREATER, SLJIT_IMM, 8, SLJIT_R1, 0); - cmp_test(compiler, SLJIT_LESS_EQUAL, SLJIT_IMM, 7, SLJIT_R0, 0); - cmp_test(compiler, SLJIT_GREATER, SLJIT_IMM, 1, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw)); - cmp_test(compiler, SLJIT_LESS_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0); - cmp_test(compiler, SLJIT_GREATER, SLJIT_R0, 0, SLJIT_R1, 0); - cmp_test(compiler, SLJIT_GREATER | SLJIT_REWRITABLE_JUMP, SLJIT_R0, 0, SLJIT_R1, 0); - - /* buf[29-39], compare_buf[29-39] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -3); - cmp_test(compiler, SLJIT_SIG_LESS, SLJIT_R0, 0, SLJIT_R1, 0); - cmp_test(compiler, SLJIT_SIG_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0); - cmp_test(compiler, SLJIT_SIG_LESS, SLJIT_R0, 0, SLJIT_IMM, -1); - cmp_test(compiler, SLJIT_SIG_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 1); - cmp_test(compiler, SLJIT_SIG_LESS, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_IMM, -1); - cmp_test(compiler, SLJIT_SIG_LESS | SLJIT_REWRITABLE_JUMP, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_IMM, -1); - cmp_test(compiler, SLJIT_SIG_LESS_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0); - cmp_test(compiler, SLJIT_SIG_GREATER, SLJIT_R0, 0, SLJIT_R1, 0); - cmp_test(compiler, SLJIT_SIG_LESS_EQUAL, SLJIT_IMM, -4, SLJIT_R0, 0); - cmp_test(compiler, SLJIT_SIG_GREATER, SLJIT_IMM, -1, SLJIT_R1, 0); - cmp_test(compiler, SLJIT_SIG_GREATER | SLJIT_REWRITABLE_JUMP, SLJIT_R1, 0, SLJIT_IMM, -1); - -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0xf00000004)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_R1, 0); - /* buf[40-43] */ - cmp_test(compiler, SLJIT_LESS | SLJIT_32, SLJIT_R1, 0, SLJIT_IMM, 5); - cmp_test(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_IMM, 5); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0xff0000004)); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_R0, 0); - cmp_test(compiler, SLJIT_SIG_GREATER | SLJIT_32, SLJIT_R1, 0, SLJIT_IMM, 5); - cmp_test(compiler, SLJIT_SIG_GREATER, SLJIT_R0, 0, SLJIT_IMM, 5); -#else /* !SLJIT_64BIT_ARCHITECTURE */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 4); - /* buf[40-43] */ - cmp_test(compiler, SLJIT_LESS | SLJIT_32, SLJIT_R0, 0, SLJIT_IMM, 5); - cmp_test(compiler, SLJIT_GREATER | SLJIT_32, SLJIT_R0, 0, SLJIT_IMM, 5); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xf0000004); - cmp_test(compiler, SLJIT_SIG_GREATER | SLJIT_32, SLJIT_R0, 0, SLJIT_IMM, 5); - cmp_test(compiler, SLJIT_SIG_LESS | SLJIT_32, SLJIT_R0, 0, SLJIT_IMM, 5); -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func2((sljit_sw)&buf, (sljit_sw)&data); - - for (i = 0; i < TEST_CASES; ++i) - if (SLJIT_UNLIKELY(buf[i] != compare_buf[i])) { - printf("test36 case %d failed\n", i + 1); - return; - } - - sljit_free_code(code.code, NULL); - successful_tests++; -} -#undef TEST_CASES - -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) -#define BITN(n) (SLJIT_W(1) << (63 - (n))) -#else /* !SLJIT_64BIT_ARCHITECTURE */ -#define BITN(n) (1 << (31 - ((n) & 0x1f))) -#endif /* SLJIT_64BIT_ARCHITECTURE */ - -static void test37(void) -{ - /* Test count leading zeroes. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[9]; - sljit_s32 ibuf[3]; - sljit_s32 i; - - if (verbose) - printf("Run test37\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - for (i = 0; i < 9; i++) - buf[i] = -1; - for (i = 0; i < 3; i++) - ibuf[i] = -1; - buf[2] = 0; - buf[4] = BITN(13); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P, P), 2, 3, 0, 0, 0); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, BITN(27)); - sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, BITN(47)); - sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_R0, 0, SLJIT_S2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw)); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0); - /* ibuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_CLZ32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R0, 0); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, BITN(58)); - sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_CLZ, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R0, 0); - /* ibuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xff08a00000, 0x08a00000)); - sljit_emit_op1(compiler, SLJIT_CLZ32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R0, 0); - /* buf[7] */ - sljit_emit_op1(compiler, SLJIT_CLZ32, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xffc8a00000, 0xc8a00000)); - sljit_emit_op1(compiler, SLJIT_CLZ32, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0xa00a); - sljit_emit_op2(compiler, SLJIT_SHL32, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, 8); - /* ibuf[2] */ - sljit_emit_op1(compiler, SLJIT_CLZ32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_R0, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func2((sljit_sw)&buf, (sljit_sw)&ibuf); - FAILED(buf[0] != 27, "test37 case 1 failed\n"); - FAILED(buf[1] != WCONST(47, 15), "test37 case 2 failed\n"); - FAILED(buf[2] != WCONST(64, 32), "test37 case 3 failed\n"); - FAILED(buf[3] != 0, "test37 case 4 failed\n"); - FAILED(ibuf[0] != 32, "test37 case 5 failed\n"); - FAILED(buf[4] != 13, "test37 case 6 failed\n"); - FAILED(buf[5] != WCONST(58, 26), "test37 case 7 failed\n"); - FAILED(buf[6] != WCONST(64, 32), "test37 case 8 failed\n"); - FAILED(ibuf[1] != 4, "test37 case 9 failed\n"); - FAILED((buf[7] & (sljit_sw)0xffffffff) != 4, "test37 case 10 failed\n"); - FAILED((buf[8] & (sljit_sw)0xffffffff) != 0, "test37 case 11 failed\n"); - FAILED(ibuf[2] != 8, "test37 case 12 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -#undef BITN - -static void test38(void) -{ -#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) - /* Test stack utility. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - struct sljit_jump* alloc1_fail; - struct sljit_jump* alloc2_fail; - struct sljit_jump* alloc3_fail; - struct sljit_jump* sanity1_fail; - struct sljit_jump* sanity2_fail; - struct sljit_jump* sanity3_fail; - struct sljit_jump* sanity4_fail; - struct sljit_jump* jump; - struct sljit_label* label; - - if (verbose) - printf("Run test38\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 3, 1, 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8192); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 65536); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(P, W, W, P), SLJIT_IMM, SLJIT_FUNC_ADDR(sljit_allocate_stack)); - alloc1_fail = sljit_emit_cmp(compiler, SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_RETURN_REG, 0); - - /* Write 8k data. */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, start)); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 8192); - label = sljit_emit_label(compiler); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_IMM, -1); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw)); - jump = sljit_emit_cmp(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_set_label(jump, label); - - /* Grow stack. */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, end), SLJIT_IMM, 65536); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(P, P, P), SLJIT_IMM, SLJIT_FUNC_ADDR(sljit_stack_resize)); - alloc2_fail = sljit_emit_cmp(compiler, SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); - sanity1_fail = sljit_emit_cmp(compiler, SLJIT_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, start)); - - /* Write 64k data. */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, start)); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 65536); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, min_start)); - sanity2_fail = sljit_emit_cmp(compiler, SLJIT_NOT_EQUAL, SLJIT_R0, 0, SLJIT_R2, 0); - label = sljit_emit_label(compiler); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_IMM, -1); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw)); - jump = sljit_emit_cmp(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_set_label(jump, label); - - /* Shrink stack. */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, end), SLJIT_IMM, 32768); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(P, P, P), SLJIT_IMM, SLJIT_FUNC_ADDR(sljit_stack_resize)); - alloc3_fail = sljit_emit_cmp(compiler, SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); - sanity3_fail = sljit_emit_cmp(compiler, SLJIT_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, start)); - - /* Write 32k data. */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, start)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct sljit_stack, end)); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R2, 0, SLJIT_R1, 0, SLJIT_IMM, 32768); - sanity4_fail = sljit_emit_cmp(compiler, SLJIT_NOT_EQUAL, SLJIT_R0, 0, SLJIT_R2, 0); - label = sljit_emit_label(compiler); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_IMM, -1); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_sw)); - jump = sljit_emit_cmp(compiler, SLJIT_LESS, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_set_label(jump, label); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(VOID, P, P), SLJIT_IMM, SLJIT_FUNC_ADDR(sljit_free_stack)); - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_IMM, 4567); - - label = sljit_emit_label(compiler); - sljit_set_label(alloc1_fail, label); - sljit_set_label(alloc2_fail, label); - sljit_set_label(alloc3_fail, label); - sljit_set_label(sanity1_fail, label); - sljit_set_label(sanity2_fail, label); - sljit_set_label(sanity3_fail, label); - sljit_set_label(sanity4_fail, label); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_IMM, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - /* Just survive this. */ - FAILED(code.func0() != 4567, "test38 case 1 failed\n"); - - sljit_free_code(code.code, NULL); -#endif - successful_tests++; -} - -static void test39(void) -{ - /* Test error handling. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - struct sljit_jump* jump; - - if (verbose) - printf("Run test39\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - /* Such assignment should never happen in a regular program. */ - compiler->error = -3967; - - SLJIT_ASSERT(sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W, W), 5, 5, 6, 0, 32) == -3967); - SLJIT_ASSERT(sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R1, 0) == -3967); - SLJIT_ASSERT(sljit_emit_op0(compiler, SLJIT_NOP) == -3967); - SLJIT_ASSERT(sljit_emit_op0(compiler, SLJIT_ENDBR) == -3967); - SLJIT_ASSERT(sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1) == -3967); - SLJIT_ASSERT(sljit_emit_op2(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), 64, SLJIT_MEM1(SLJIT_S0), -64) == -3967); - SLJIT_ASSERT(sljit_emit_fop1(compiler, SLJIT_ABS_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_R1), 0) == -3967); - SLJIT_ASSERT(sljit_emit_fop2(compiler, SLJIT_DIV_F64, SLJIT_FR2, 0, SLJIT_MEM2(SLJIT_R0, SLJIT_S0), 0, SLJIT_FR2, 0) == -3967); - SLJIT_ASSERT(!sljit_emit_label(compiler)); - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS4(W, 32, P, F32, F64)); - SLJIT_ASSERT(!jump); - sljit_set_label(jump, (struct sljit_label*)0x123450); - sljit_set_target(jump, 0x123450); - jump = sljit_emit_cmp(compiler, SLJIT_SIG_LESS_EQUAL, SLJIT_R0, 0, SLJIT_R1, 0); - SLJIT_ASSERT(!jump); - SLJIT_ASSERT(sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM1(SLJIT_R0), 8) == -3967); - SLJIT_ASSERT(sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_OVERFLOW) == -3967); - SLJIT_ASSERT(!sljit_emit_const(compiler, SLJIT_R0, 0, 99)); - - SLJIT_ASSERT(!compiler->labels && !compiler->jumps && !compiler->consts); - SLJIT_ASSERT(!compiler->last_label && !compiler->last_jump && !compiler->last_const); - SLJIT_ASSERT(!compiler->buf->next && !compiler->buf->used_size); - SLJIT_ASSERT(!compiler->abuf->next && !compiler->abuf->used_size); - - sljit_set_compiler_memory_error(compiler); - FAILED(sljit_get_compiler_error(compiler) != -3967, "test39 case 1 failed\n"); - - code.code = sljit_generate_code(compiler); - FAILED(sljit_get_compiler_error(compiler) != -3967, "test39 case 2 failed\n"); - FAILED(!!code.code, "test39 case 3 failed\n"); - sljit_free_compiler(compiler); - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - FAILED(sljit_get_compiler_error(compiler) != SLJIT_SUCCESS, "test39 case 4 failed\n"); - sljit_set_compiler_memory_error(compiler); - FAILED(sljit_get_compiler_error(compiler) != SLJIT_ERR_ALLOC_FAILED, "test39 case 5 failed\n"); - sljit_free_compiler(compiler); - - successful_tests++; -} - -static void test40(void) -{ - /* Test emit_op_flags. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[10]; - - if (verbose) - printf("Run test40\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = -100; - buf[1] = -100; - buf[2] = -100; - buf[3] = -8; - buf[4] = -100; - buf[5] = -100; - buf[6] = 0; - buf[7] = 0; - buf[8] = -100; - buf[9] = -100; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 4, 0, 0, sizeof(sljit_sw)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -5); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_IMM, -6, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x123456); - sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_R1, 0, SLJIT_SIG_LESS); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -13); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_IMM, -13, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 0); - sljit_emit_op_flags(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_EQUAL); - /* buf[1] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_NOT_EQUAL); - sljit_emit_op2(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 0); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_IMM, -13, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0); - sljit_emit_op_flags(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_EQUAL); - /* buf[2] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 2, SLJIT_EQUAL); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -13); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0); - /* buf[3] */ - sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), SLJIT_WORD_SHIFT, SLJIT_SIG_LESS); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -8); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 33); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 0); - sljit_emit_op_flags(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_GREATER); - sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_S1, 0, SLJIT_EQUAL); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, 0x88); - sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_S3, 0, SLJIT_NOT_EQUAL); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 4, SLJIT_S1, 0); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 5, SLJIT_S3, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x84); - sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_IMM, 0x180, SLJIT_R0, 0); - /* buf[6] */ - sljit_emit_op_flags(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 6, SLJIT_EQUAL); - /* buf[7] */ - sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 7, SLJIT_EQUAL); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op_flags(compiler, SLJIT_OR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_NOT_EQUAL); - /* buf[8] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 8, SLJIT_NOT_EQUAL); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x123456); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_R0, 0, SLJIT_GREATER); - /* buf[9] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw) * 9, SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 0xbaddead); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func1((sljit_sw)&buf) != 0xbaddead, "test40 case 1 failed\n"); - FAILED(buf[0] != 0x123457, "test40 case 2 failed\n"); - FAILED(buf[1] != 1, "test40 case 3 failed\n"); - FAILED(buf[2] != 0, "test40 case 4 failed\n"); - FAILED(buf[3] != -7, "test40 case 5 failed\n"); - FAILED(buf[4] != 0, "test40 case 6 failed\n"); - FAILED(buf[5] != 0x89, "test40 case 7 failed\n"); - FAILED(buf[6] != 0, "test40 case 8 failed\n"); - FAILED(buf[7] != 1, "test40 case 9 failed\n"); - FAILED(buf[8] != 1, "test40 case 10 failed\n"); - FAILED(buf[9] != 0x123457, "test40 case 11 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test41(void) -{ - /* Test inline assembly. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_s32 i; - sljit_f64 buf[3]; -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - sljit_u8 inst[16]; -#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - sljit_u8 inst[16]; - sljit_s32 reg; -#else - sljit_u32 inst; -#endif - - if (verbose) - printf("Run test41\n"); - -#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - SLJIT_ASSERT(sljit_has_cpu_feature(SLJIT_HAS_VIRTUAL_REGISTERS) == 0); -#endif - - for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++) { -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - if (SLJIT_R(i) >= SLJIT_R3 && SLJIT_R(i) <= SLJIT_R8) { - SLJIT_ASSERT(sljit_get_register_index(SLJIT_R(i)) == -1); - continue; - } -#endif - SLJIT_ASSERT(sljit_get_register_index(SLJIT_R(i)) >= 0 && sljit_get_register_index(SLJIT_R(i)) < 64); - } - - FAILED(!compiler, "cannot create compiler\n"); - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(W, W, W), 3, 3, 0, 0, 0); - - /* Returns with the sum of SLJIT_S0 and SLJIT_S1. */ -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - /* lea SLJIT_RETURN_REG, [SLJIT_S0, SLJIT_S1] */ - inst[0] = 0x48; - inst[1] = 0x8d; - inst[2] = (sljit_u8)(0x04 | ((sljit_get_register_index(SLJIT_RETURN_REG) & 0x7) << 3)); - inst[3] = (sljit_u8)((sljit_get_register_index(SLJIT_S0) & 0x7) - | ((sljit_get_register_index(SLJIT_S1) & 0x7) << 3)); - sljit_emit_op_custom(compiler, inst, 4); -#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - /* lea SLJIT_RETURN_REG, [SLJIT_S0, SLJIT_S1] */ - inst[0] = 0x48; /* REX_W */ - inst[1] = 0x8d; - reg = sljit_get_register_index(SLJIT_RETURN_REG); - inst[2] = (sljit_u8)(0x04 | ((reg & 0x7) << 3)); - if (reg > 7) - inst[0] |= 0x04; /* REX_R */ - reg = sljit_get_register_index(SLJIT_S0); - inst[3] = (sljit_u8)(reg & 0x7); - if (reg > 7) - inst[0] |= 0x01; /* REX_B */ - reg = sljit_get_register_index(SLJIT_S1); - inst[3] = (sljit_u8)(inst[3] | ((reg & 0x7) << 3)); - if (reg > 7) - inst[0] |= 0x02; /* REX_X */ - sljit_emit_op_custom(compiler, inst, 4); -#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) - /* add rd, rn, rm */ - inst = 0xe0800000 | ((sljit_u32)sljit_get_register_index(SLJIT_RETURN_REG) << 12) - | ((sljit_u32)sljit_get_register_index(SLJIT_S0) << 16) - | (sljit_u32)sljit_get_register_index(SLJIT_S1); - sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32)); -#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) - /* add rd, rn, rm */ - inst = 0xeb000000 | ((sljit_u32)sljit_get_register_index(SLJIT_RETURN_REG) << 8) - | ((sljit_u32)sljit_get_register_index(SLJIT_S0) << 16) - | (sljit_u32)sljit_get_register_index(SLJIT_S1); - sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32)); -#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) - /* add rd, rn, rm */ - inst = 0x8b000000 | (sljit_u32)sljit_get_register_index(SLJIT_RETURN_REG) - | ((sljit_u32)sljit_get_register_index(SLJIT_S0) << 5) - | ((sljit_u32)sljit_get_register_index(SLJIT_S1) << 16); - sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32)); -#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) - /* add rD, rA, rB */ - inst = (31 << 26) | (266 << 1) | ((sljit_u32)sljit_get_register_index(SLJIT_RETURN_REG) << 21) - | ((sljit_u32)sljit_get_register_index(SLJIT_S0) << 16) - | ((sljit_u32)sljit_get_register_index(SLJIT_S1) << 11); - sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32)); -#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - /* addu rd, rs, rt */ - inst = 33 | ((sljit_u32)sljit_get_register_index(SLJIT_RETURN_REG) << 11) - | ((sljit_u32)sljit_get_register_index(SLJIT_S0) << 21) - | ((sljit_u32)sljit_get_register_index(SLJIT_S1) << 16); - sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32)); -#elif (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) - /* daddu rd, rs, rt */ - inst = 45 | ((sljit_u32)sljit_get_register_index(SLJIT_RETURN_REG) << 11) - | ((sljit_u32)sljit_get_register_index(SLJIT_S0) << 21) - | ((sljit_u32)sljit_get_register_index(SLJIT_S1) << 16); - sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32)); -#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) - /* add rd, rs1, rs2 */ - inst = 0x33 | (0 << 12) | (0 << 25) | ((sljit_u32)sljit_get_register_index(SLJIT_RETURN_REG) << 7) - | ((sljit_u32)sljit_get_register_index(SLJIT_S0) << 15) - | ((sljit_u32)sljit_get_register_index(SLJIT_S1) << 20); - sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32)); -#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) - /* add rd, rs1, rs2 */ - inst = (0x2u << 30) | ((sljit_u32)sljit_get_register_index(SLJIT_RETURN_REG) << 25) - | ((sljit_u32)sljit_get_register_index(SLJIT_S0) << 14) - | (sljit_u32)sljit_get_register_index(SLJIT_S1); - sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32)); -#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) - /* agrk rd, rs1, rs2 */ - inst = (0xb9e8u << 16) - | ((sljit_u32)sljit_get_register_index(SLJIT_RETURN_REG) << 4) - | ((sljit_u32)sljit_get_register_index(SLJIT_S0) << 12) - | (sljit_u32)sljit_get_register_index(SLJIT_S1); - sljit_emit_op_custom(compiler, &inst, sizeof(inst)); -#else - inst = 0; - sljit_emit_op_custom(compiler, &inst, 0); -#endif - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func2(32, -11) != 21, "test41 case 1 failed\n"); - FAILED(code.func2(1000, 234) != 1234, "test41 case 2 failed\n"); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - FAILED(code.func2(SLJIT_W(0x20f0a04090c06070), SLJIT_W(0x020f0a04090c0607)) != SLJIT_W(0x22ffaa4499cc6677), "test41 case 3 failed\n"); -#endif - - sljit_free_code(code.code, NULL); - - if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - buf[0] = 13.5; - buf[1] = -2.25; - buf[2] = 0.0; - - compiler = sljit_create_compiler(NULL, NULL); - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 0, 1, 2, 0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64)); -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - /* addsd x, xm */ - inst[0] = 0xf2; - inst[1] = 0x0f; - inst[2] = 0x58; - inst[3] = (sljit_u8)(0xc0 | (sljit_get_float_register_index(SLJIT_FR0) << 3) - | sljit_get_float_register_index(SLJIT_FR1)); - sljit_emit_op_custom(compiler, inst, 4); -#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - /* addsd x, xm */ - if (sljit_get_float_register_index(SLJIT_FR0) > 7 || sljit_get_float_register_index(SLJIT_FR1) > 7) { - inst[0] = 0; - if (sljit_get_float_register_index(SLJIT_FR0) > 7) - inst[0] |= 0x04; /* REX_R */ - if (sljit_get_float_register_index(SLJIT_FR1) > 7) - inst[0] |= 0x01; /* REX_B */ - inst[1] = 0xf2; - inst[2] = 0x0f; - inst[3] = 0x58; - inst[4] = (sljit_u8)(0xc0 | ((sljit_get_float_register_index(SLJIT_FR0) & 0x7) << 3) - | (sljit_get_float_register_index(SLJIT_FR1) & 0x7)); - sljit_emit_op_custom(compiler, inst, 5); - } - else { - inst[0] = 0xf2; - inst[1] = 0x0f; - inst[2] = 0x58; - inst[3] = (sljit_u8)(0xc0 | (sljit_get_float_register_index(SLJIT_FR0) << 3) - | sljit_get_float_register_index(SLJIT_FR1)); - sljit_emit_op_custom(compiler, inst, 4); - } -#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) - /* vadd.f64 dd, dn, dm */ - inst = 0xee300b00 | (((sljit_u32)sljit_get_float_register_index(SLJIT_FR0) >> 1) << 12) - | (((sljit_u32)sljit_get_float_register_index(SLJIT_FR0) >> 1) << 16) - | ((sljit_u32)sljit_get_float_register_index(SLJIT_FR1) >> 1); - sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32)); -#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) - /* fadd rd, rn, rm */ - inst = 0x1e602800 | (sljit_u32)sljit_get_float_register_index(SLJIT_FR0) - | ((sljit_u32)sljit_get_float_register_index(SLJIT_FR0) << 5) - | ((sljit_u32)sljit_get_float_register_index(SLJIT_FR1) << 16); - sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32)); -#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) - /* fadd frD, frA, frB */ - inst = (63u << 26) | (21u << 1) | ((sljit_u32)sljit_get_float_register_index(SLJIT_FR0) << 21) - | ((sljit_u32)sljit_get_float_register_index(SLJIT_FR0) << 16) - | ((sljit_u32)sljit_get_float_register_index(SLJIT_FR1) << 11); - sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32)); -#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) - /* add.d fd, fs, ft */ - inst = (17u << 26) | (17u << 21) | ((sljit_u32)sljit_get_float_register_index(SLJIT_FR0) << 6) - | ((sljit_u32)sljit_get_float_register_index(SLJIT_FR0) << 11) - | ((sljit_u32)sljit_get_float_register_index(SLJIT_FR1) << 16); - sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32)); -#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) - /* fadd.d rd, rs1, rs2 */ - inst = (0x1u << 25) | (0x7u << 12) | (0x53u) - | ((sljit_u32)sljit_get_float_register_index(SLJIT_FR0) << 7) - | ((sljit_u32)sljit_get_float_register_index(SLJIT_FR0) << 15) - | (sljit_u32)sljit_get_float_register_index(SLJIT_FR1) << 20; - sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32)); -#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) - /* faddd rd, rs1, rs2 */ - inst = (0x2u << 30) | (0x34u << 19) | (0x42u << 5) - | ((sljit_u32)sljit_get_float_register_index(SLJIT_FR0) << 25) - | ((sljit_u32)sljit_get_float_register_index(SLJIT_FR0) << 14) - | (sljit_u32)sljit_get_float_register_index(SLJIT_FR1); - sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32)); -#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) - /* adbr r1, r2 */ - inst = 0xb31a0000 - | ((sljit_u32)sljit_get_float_register_index(SLJIT_FR0) << 4) - | (sljit_u32)sljit_get_float_register_index(SLJIT_FR1); - sljit_emit_op_custom(compiler, &inst, sizeof(sljit_u32)); -#endif - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR0, 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - FAILED(buf[2] != 11.25, "test41 case 4 failed\n"); - - sljit_free_code(code.code, NULL); - } - - successful_tests++; -} - -static void test42(void) -{ - /* Test long multiply and division. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_s32 i; - sljit_sw buf[7 + 4 + 8 + 8]; - - if (verbose) - printf("Run test42\n"); - - FAILED(!compiler, "cannot create compiler\n"); - for (i = 0; i < 7 + 4 + 8 + 8; i++) - buf[i] = -1; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 5, 5, 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -0x1fb308a); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 0xf50c873); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 0x8a0475b); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 0x9dc849b); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -0x7c69a35); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, 0x5a4d0c4); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, 0x9a3b06d); - -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - /* buf[7-26] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-0x5dc4f897b8cd67f5)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x3f8b5c026cb088df)); - sljit_emit_op0(compiler, SLJIT_LMUL_UW); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-0x5dc4f897b8cd67f5)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x3f8b5c026cb088df)); - sljit_emit_op0(compiler, SLJIT_LMUL_SW); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-0x5dc4f897b8cd67f5)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x3f8b5c026cb088df)); - sljit_emit_op0(compiler, SLJIT_DIVMOD_UW); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-0x5dc4f897b8cd67f5)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x3f8b5c026cb088df)); - sljit_emit_op0(compiler, SLJIT_DIVMOD_SW); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x5cf783d3cf0a74b0)); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x3d5df42d03a28fc7)); - sljit_emit_op0(compiler, SLJIT_DIVMOD_U32); - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x371df5197ba26a28)); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x46c78a5cfd6a420c)); - sljit_emit_op0(compiler, SLJIT_DIVMOD_S32); - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)SLJIT_W(0xc456f048c28a611b)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x3d4af2c543)); - sljit_emit_op0(compiler, SLJIT_DIV_UW); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 19 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 20 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(-0x720fa4b74c329b14)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0xa64ae42b7d6)); - sljit_emit_op0(compiler, SLJIT_DIV_SW); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 21 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 22 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x4af51c027b34)); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(0x9ba4ff2906b14)); - sljit_emit_op0(compiler, SLJIT_DIV_U32); - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 23 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 24 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0xc40b58a3f20d)); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, SLJIT_W(-0xa63c923)); - sljit_emit_op0(compiler, SLJIT_DIV_S32); - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 25 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 26 * sizeof(sljit_sw), SLJIT_R1, 0); - -#else /* !SLJIT_64BIT_ARCHITECTURE */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -0x58cd67f5); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x3cb088df); - sljit_emit_op0(compiler, SLJIT_LMUL_UW); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -0x58cd67f5); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x3cb088df); - sljit_emit_op0(compiler, SLJIT_LMUL_SW); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -0x58cd67f5); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x3cb088df); - sljit_emit_op0(compiler, SLJIT_DIVMOD_UW); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -0x58cd67f5); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0x3cb088df); - sljit_emit_op0(compiler, SLJIT_DIVMOD_SW); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xcf0a74b0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0x03a28fc7); - sljit_emit_op0(compiler, SLJIT_DIVMOD_U32); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x7ba26a28); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0xfd6a420c); - sljit_emit_op0(compiler, SLJIT_DIVMOD_S32); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x9d4b7036); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0xb86d0); - sljit_emit_op0(compiler, SLJIT_DIV_UW); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 19 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 20 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -0x58b0692c); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0xd357); - sljit_emit_op0(compiler, SLJIT_DIV_SW); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 21 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 22 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x1c027b34); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0xf2906b14); - sljit_emit_op0(compiler, SLJIT_DIV_U32); - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 23 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 24 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x58a3f20d); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, -0xa63c923); - sljit_emit_op0(compiler, SLJIT_DIV_S32); - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 25 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 26 * sizeof(sljit_sw), SLJIT_R1, 0); -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - /* buf[0-6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R3, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R4, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_S1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_S2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_S3, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_S4, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - - FAILED(buf[0] != -0x1fb308a, "test42 case 1 failed\n"); - FAILED(buf[1] != 0xf50c873, "test42 case 2 failed\n"); - FAILED(buf[2] != 0x8a0475b, "test42 case 3 failed\n"); - FAILED(buf[3] != 0x9dc849b, "test42 case 4 failed\n"); - FAILED(buf[4] != -0x7c69a35, "test42 case 5 failed\n"); - FAILED(buf[5] != 0x5a4d0c4, "test42 case 6 failed\n"); - FAILED(buf[6] != 0x9a3b06d, "test42 case 7 failed\n"); - -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - FAILED(buf[7] != SLJIT_W(-4388959407985636971), "test42 case 8 failed\n"); - FAILED(buf[8] != SLJIT_W(2901680654366567099), "test42 case 9 failed\n"); - FAILED(buf[9] != SLJIT_W(-4388959407985636971), "test42 case 10 failed\n"); - FAILED(buf[10] != SLJIT_W(-1677173957268872740), "test42 case 11 failed\n"); - FAILED(buf[11] != SLJIT_W(2), "test42 case 12 failed\n"); - FAILED(buf[12] != SLJIT_W(2532236178951865933), "test42 case 13 failed\n"); - FAILED(buf[13] != SLJIT_W(-1), "test42 case 14 failed\n"); - FAILED(buf[14] != SLJIT_W(-2177944059851366166), "test42 case 15 failed\n"); -#else /* !SLJIT_64BIT_ARCHITECTURE */ - FAILED(buf[7] != -1587000939, "test42 case 8 failed\n"); - FAILED(buf[8] != 665003983, "test42 case 9 failed\n"); - FAILED(buf[9] != -1587000939, "test42 case 10 failed\n"); - FAILED(buf[10] != -353198352, "test42 case 11 failed\n"); - FAILED(buf[11] != 2, "test42 case 12 failed\n"); - FAILED(buf[12] != 768706125, "test42 case 13 failed\n"); - FAILED(buf[13] != -1, "test42 case 14 failed\n"); - FAILED(buf[14] != -471654166, "test42 case 15 failed\n"); -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - FAILED(buf[15] != 56, "test42 case 16 failed\n"); - FAILED(buf[16] != 58392872, "test42 case 17 failed\n"); - FAILED(buf[17] != -47, "test42 case 18 failed\n"); - FAILED(buf[18] != 35949148, "test42 case 19 failed\n"); - -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - FAILED(buf[19] != SLJIT_W(0x3340bfc), "test42 case 20 failed\n"); - FAILED(buf[20] != SLJIT_W(0x3d4af2c543), "test42 case 21 failed\n"); - FAILED(buf[21] != SLJIT_W(-0xaf978), "test42 case 22 failed\n"); - FAILED(buf[22] != SLJIT_W(0xa64ae42b7d6), "test42 case 23 failed\n"); -#else /* !SLJIT_64BIT_ARCHITECTURE */ - FAILED(buf[19] != SLJIT_W(0xda5), "test42 case 20 failed\n"); - FAILED(buf[20] != SLJIT_W(0xb86d0), "test42 case 21 failed\n"); - FAILED(buf[21] != SLJIT_W(-0x6b6e), "test42 case 22 failed\n"); - FAILED(buf[22] != SLJIT_W(0xd357), "test42 case 23 failed\n"); -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - FAILED(buf[23] != 0x0, "test42 case 24 failed\n"); - FAILED(buf[24] != (sljit_sw)0xf2906b14, "test42 case 25 failed\n"); - FAILED(buf[25] != -0x8, "test42 case 26 failed\n"); - FAILED(buf[26] != -0xa63c923, "test42 case 27 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test43(void) -{ - /* Test floating point compare. */ - executable_code code; - struct sljit_compiler* compiler; - struct sljit_jump* jump; - - union { - sljit_f64 value; - struct { - sljit_u32 value1; - sljit_u32 value2; - } u; - } dbuf[4]; - - if (verbose) - printf("Run test43\n"); - - if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - if (verbose) - printf("no fpu available, test43 skipped\n"); - successful_tests++; - return; - } - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - dbuf[0].value = 12.125; - /* a NaN */ - dbuf[1].u.value1 = 0x7fffffff; - dbuf[1].u.value2 = 0x7fffffff; - dbuf[2].value = -13.5; - dbuf[3].value = 12.125; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 1, 1, 3, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2); - /* dbuf[0] < dbuf[2] -> -2 */ - jump = sljit_emit_fcmp(compiler, SLJIT_F_GREATER_EQUAL, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_F64_SHIFT); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_IMM, -2); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0); - /* dbuf[0] and dbuf[1] is not NaN -> 5 */ - jump = sljit_emit_fcmp(compiler, SLJIT_UNORDERED, SLJIT_MEM0(), (sljit_sw)&dbuf[1], SLJIT_FR1, 0); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_IMM, 5); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 11); - /* dbuf[0] == dbuf[3] -> 11 */ - jump = sljit_emit_fcmp(compiler, SLJIT_F_EQUAL, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_FR2, 0); - - /* else -> -17 */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, -17); - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func1((sljit_sw)&dbuf) != 11, "test43 case 1 failed\n"); - dbuf[3].value = 12; - FAILED(code.func1((sljit_sw)&dbuf) != -17, "test43 case 2 failed\n"); - dbuf[1].value = 0; - FAILED(code.func1((sljit_sw)&dbuf) != 5, "test43 case 3 failed\n"); - dbuf[2].value = 20; - FAILED(code.func1((sljit_sw)&dbuf) != -2, "test43 case 4 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test44(void) -{ - /* Test mov. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - void *buf[5]; - - if (verbose) - printf("Run test44\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - buf[0] = buf + 2; - buf[1] = NULL; - buf[2] = NULL; - buf[3] = NULL; - buf[4] = NULL; - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(P, P), 3, 2, 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_p), SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_p)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 2); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_MEM2(SLJIT_S0, SLJIT_R1), SLJIT_POINTER_SHIFT, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, sizeof(sljit_p)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3 << SLJIT_POINTER_SHIFT); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_S0, 0); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 0, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2 * sizeof(sljit_p)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1 << SLJIT_POINTER_SHIFT); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 2, SLJIT_R0, 0); - - sljit_emit_return(compiler, SLJIT_MOV_P, SLJIT_R0, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func1((sljit_sw)&buf) != (sljit_sw)(buf + 2), "test44 case 1 failed\n"); - FAILED(buf[1] != buf + 2, "test44 case 2 failed\n"); - FAILED(buf[2] != buf + 3, "test44 case 3 failed\n"); - FAILED(buf[3] != buf + 4, "test44 case 4 failed\n"); - FAILED(buf[4] != buf + 2, "test44 case 5 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test45(void) -{ - /* Test single precision floating point. */ - - executable_code code; - struct sljit_compiler* compiler; - sljit_f32 buf[12]; - sljit_sw buf2[6]; - struct sljit_jump* jump; - - if (verbose) - printf("Run test45\n"); - - if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - if (verbose) - printf("no fpu available, test45 skipped\n"); - successful_tests++; - return; - } - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - buf[0] = 5.5; - buf[1] = -7.25; - buf[2] = 0; - buf[3] = 0; - buf[4] = 0; - buf[5] = 0; - buf[6] = 0; - buf[7] = 8.75; - buf[8] = 0; - buf[9] = 16.5; - buf[10] = 0; - buf[11] = 0; - - buf2[0] = -1; - buf2[1] = -1; - buf2[2] = -1; - buf2[3] = -1; - buf2[4] = -1; - buf2[5] = -1; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P, P), 3, 2, 6, 0, 0); - - /* buf[2] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_NEG_F32, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f32), SLJIT_FR0, 0); - /* buf[3] */ - sljit_emit_fop1(compiler, SLJIT_ABS_F32, SLJIT_FR1, 0, SLJIT_FR5, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f32), SLJIT_FR1, 0); - /* buf[4] */ - sljit_emit_fop1(compiler, SLJIT_ABS_F32, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f32), SLJIT_FR5, 0); - /* buf[5] */ - sljit_emit_fop1(compiler, SLJIT_NEG_F32, SLJIT_FR4, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f32), SLJIT_FR4, 0); - - /* buf[6] */ - sljit_emit_fop2(compiler, SLJIT_ADD_F32, SLJIT_FR0, 0, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f32), SLJIT_FR0, 0); - /* buf[7] */ - sljit_emit_fop2(compiler, SLJIT_SUB_F32, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_f32), SLJIT_FR5, 0); - /* buf[8] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_fop2(compiler, SLJIT_MUL_F32, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_f32), SLJIT_FR0, 0, SLJIT_FR0, 0); - /* buf[9] */ - sljit_emit_fop2(compiler, SLJIT_DIV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_f32), SLJIT_FR0, 0); - sljit_emit_fop1(compiler, SLJIT_ABS_F32, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_f32), SLJIT_FR2, 0); - /* buf[10] */ - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 0x3d0ac); - sljit_emit_fop1(compiler, SLJIT_NEG_F32, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_R0), 0x3d0ac); - /* buf[11] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 0x3d0ac + sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_ABS_F32, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_R0), -0x3d0ac); - - /* buf2[0] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0); - cond_set(compiler, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_F_EQUAL); - /* buf2[1] */ - sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_LESS, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0); - cond_set(compiler, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_sw), SLJIT_F_LESS); - /* buf2[2] */ - sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); - cond_set(compiler, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_sw), SLJIT_F_EQUAL); - /* buf2[3] */ - sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_GREATER_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); - cond_set(compiler, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw), SLJIT_F_GREATER_EQUAL); - - /* buf2[4] */ - jump = sljit_emit_fcmp(compiler, SLJIT_F_LESS_EQUAL | SLJIT_32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_IMM, 7); - sljit_set_label(jump, sljit_emit_label(compiler)); - - /* buf2[5] */ - jump = sljit_emit_fcmp(compiler, SLJIT_F_GREATER | SLJIT_32, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_FR2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_IMM, 6); - sljit_set_label(jump, sljit_emit_label(compiler)); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func2((sljit_sw)&buf, (sljit_sw)&buf2); - FAILED(buf[2] != -5.5, "test45 case 1 failed\n"); - FAILED(buf[3] != 7.25, "test45 case 2 failed\n"); - FAILED(buf[4] != 7.25, "test45 case 3 failed\n"); - FAILED(buf[5] != -5.5, "test45 case 4 failed\n"); - FAILED(buf[6] != -1.75, "test45 case 5 failed\n"); - FAILED(buf[7] != 16.0, "test45 case 6 failed\n"); - FAILED(buf[8] != 30.25, "test45 case 7 failed\n"); - FAILED(buf[9] != 3, "test45 case 8 failed\n"); - FAILED(buf[10] != -5.5, "test45 case 9 failed\n"); - FAILED(buf[11] != 7.25, "test45 case 10 failed\n"); - FAILED(buf2[0] != 1, "test45 case 11 failed\n"); - FAILED(buf2[1] != 2, "test45 case 12 failed\n"); - FAILED(buf2[2] != 2, "test45 case 13 failed\n"); - FAILED(buf2[3] != 1, "test45 case 14 failed\n"); - FAILED(buf2[4] != 7, "test45 case 15 failed\n"); - FAILED(buf2[5] != -1, "test45 case 16 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test46(void) -{ - /* Test sljit_emit_op_flags with 32 bit operations. */ - - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_s32 buf[24]; - sljit_sw buf2[6]; - sljit_s32 i; - - if (verbose) - printf("Run test46\n"); - - for (i = 0; i < 24; ++i) - buf[i] = -17; - buf[16] = 0; - for (i = 0; i < 6; ++i) - buf2[i] = -13; - buf2[4] = -124; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P, P), 3, 3, 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -7); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_R2, 0, SLJIT_IMM, 13); - /* buf[0] */ - sljit_emit_op_flags(compiler, SLJIT_MOV32, SLJIT_MEM0(), (sljit_sw)&buf, SLJIT_LESS); - /* buf[2] */ - sljit_emit_op_flags(compiler, SLJIT_AND32, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_s32), SLJIT_NOT_ZERO); - - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_IMM, -7); - /* buf[4] */ - sljit_emit_op_flags(compiler, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_s32), SLJIT_EQUAL); - /* buf[6] */ - sljit_emit_op_flags(compiler, SLJIT_AND32, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_s32), SLJIT_NOT_EQUAL); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x1235); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 0x1235); - sljit_emit_op_flags(compiler, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_ZERO); - /* buf[8] */ - sljit_emit_op_flags(compiler, SLJIT_AND32, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_s32), SLJIT_ZERO); - /* buf[10] */ - sljit_emit_op1(compiler, SLJIT_MOV_U32, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_s32), SLJIT_R0, 0); - - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_IMM, -7); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 12); - /* buf[12] */ - sljit_emit_op_flags(compiler, SLJIT_MOV32, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 2, SLJIT_EQUAL); - sljit_emit_op_flags(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_EQUAL); - /* buf[14] */ - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_s32), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 16); - /* buf[16] */ - sljit_emit_op_flags(compiler, SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 2, SLJIT_EQUAL); - /* buf[18] */ - sljit_emit_op_flags(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_s32), SLJIT_NOT_EQUAL); - - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_IMM, -7); - /* buf[20] */ - sljit_emit_op_flags(compiler, SLJIT_XOR32 | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S0), 20 * sizeof(sljit_s32), SLJIT_ZERO); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 39); - sljit_emit_op_flags(compiler, SLJIT_XOR32, SLJIT_R0, 0, SLJIT_NOT_ZERO); - /* buf[22] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 22 * sizeof(sljit_s32), SLJIT_R0, 0); - - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R2, 0, SLJIT_IMM, -7); - /* buf2[0] */ - sljit_emit_op_flags(compiler, SLJIT_AND, SLJIT_MEM0(), (sljit_sw)&buf2, SLJIT_GREATER); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 5); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); - /* buf2[1] */ - sljit_emit_op_flags(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_SIG_LESS); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_R2, 0, SLJIT_IMM, 5); - /* buf2[2] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_LESS); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_NOT_EQUAL); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 5); - /* buf2[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw), SLJIT_S2, 0); - sljit_emit_op_flags(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_SIG_LESS); - /* buf2[4] */ - sljit_emit_op_flags(compiler, SLJIT_OR, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_ZERO); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R2, 0, SLJIT_IMM, 0); - /* buf2[5] */ - sljit_emit_op_flags(compiler, SLJIT_XOR, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_GREATER); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func2((sljit_sw)&buf, (sljit_sw)&buf2); - FAILED(buf[0] != 0, "test46 case 1 failed\n"); - FAILED(buf[1] != -17, "test46 case 2 failed\n"); - FAILED(buf[2] != 1, "test46 case 3 failed\n"); - FAILED(buf[3] != -17, "test46 case 4 failed\n"); - FAILED(buf[4] != 1, "test46 case 5 failed\n"); - FAILED(buf[5] != -17, "test46 case 6 failed\n"); - FAILED(buf[6] != 1, "test46 case 7 failed\n"); - FAILED(buf[7] != -17, "test46 case 8 failed\n"); - FAILED(buf[8] != 0, "test46 case 9 failed\n"); - FAILED(buf[9] != -17, "test46 case 10 failed\n"); - FAILED(buf[10] != 1, "test46 case 11 failed\n"); - FAILED(buf[11] != -17, "test46 case 12 failed\n"); - FAILED(buf[12] != 1, "test46 case 13 failed\n"); - FAILED(buf[13] != -17, "test46 case 14 failed\n"); - FAILED(buf[14] != 1, "test46 case 15 failed\n"); - FAILED(buf[15] != -17, "test46 case 16 failed\n"); - FAILED(buf[16] != 0, "test46 case 17 failed\n"); - FAILED(buf[17] != -17, "test46 case 18 failed\n"); - FAILED(buf[18] != 0, "test46 case 19 failed\n"); - FAILED(buf[19] != -17, "test46 case 20 failed\n"); - FAILED(buf[20] != -18, "test46 case 21 failed\n"); - FAILED(buf[21] != -17, "test46 case 22 failed\n"); - FAILED(buf[22] != 38, "test46 case 23 failed\n"); - FAILED(buf[23] != -17, "test46 case 24 failed\n"); - - FAILED(buf2[0] != 0, "test46 case 25 failed\n"); - FAILED(buf2[1] != 1, "test46 case 26 failed\n"); - FAILED(buf2[2] != 0, "test46 case 27 failed\n"); - FAILED(buf2[3] != 1, "test46 case 28 failed\n"); - FAILED(buf2[4] != -123, "test46 case 29 failed\n"); - FAILED(buf2[5] != -14, "test46 case 30 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test47(void) -{ - /* Test jump optimizations. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[3]; - - if (verbose) - printf("Run test47\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 0; - buf[1] = 0; - buf[2] = 0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0, 0, 0); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x3a5c6f); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 3); - sljit_set_target(sljit_emit_jump(compiler, SLJIT_LESS), 0x11223344); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0xd37c10); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_set_target(sljit_emit_jump(compiler, SLJIT_LESS), SLJIT_W(0x112233445566)); -#endif - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x59b48e); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_set_target(sljit_emit_jump(compiler, SLJIT_LESS), SLJIT_W(0x1122334455667788)); -#endif - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func1((sljit_sw)&buf) != 0x59b48e, "test47 case 1 failed\n"); - FAILED(buf[0] != 0x3a5c6f, "test47 case 2 failed\n"); - FAILED(buf[1] != 0xd37c10, "test47 case 3 failed\n"); - FAILED(buf[2] != 0x59b48e, "test47 case 4 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test48(void) -{ - /* Test floating point conversions. */ - executable_code code; - struct sljit_compiler* compiler; - int i; - sljit_f64 dbuf[10]; - sljit_f32 sbuf[10]; - sljit_sw wbuf[10]; - sljit_s32 ibuf[10]; - - if (verbose) - printf("Run test48\n"); - - if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - if (verbose) - printf("no fpu available, test48 skipped\n"); - successful_tests++; - return; - } - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - for (i = 0; i < 10; i++) { - dbuf[i] = 0.0; - sbuf[i] = 0.0; - wbuf[i] = 0; - ibuf[i] = 0; - } - - dbuf[0] = 123.5; - dbuf[1] = -367; - dbuf[2] = 917.75; - - sbuf[0] = 476.25; - sbuf[1] = -1689.75; - - wbuf[0] = 2345; - - ibuf[0] = 312; - ibuf[1] = -9324; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 3, 3, 6, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&dbuf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)&sbuf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, (sljit_sw)&wbuf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)&ibuf); - - /* sbuf[2] */ - sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_F64, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3); - /* sbuf[3] */ - sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_F64, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_F32_SHIFT, SLJIT_FR5, 0); - sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_F32, SLJIT_FR4, 0, SLJIT_MEM1(SLJIT_S1), 0); - /* dbuf[3] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64), SLJIT_FR4, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S1), 0); - sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_F32, SLJIT_FR2, 0, SLJIT_FR3, 0); - /* dbuf[4] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f64), SLJIT_FR2, 0); - /* sbuf[4] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_f32), SLJIT_FR3, 0); - - /* wbuf[1] */ - sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F64, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2); - sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F64, SLJIT_R0, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_F64_SHIFT); - /* wbuf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR5, 0, SLJIT_MEM1(SLJIT_S1), 0); - /* wbuf[3] */ - sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F32, SLJIT_MEM1(SLJIT_S2), 3 * sizeof(sljit_sw), SLJIT_FR5, 0); - sljit_emit_fop1(compiler, SLJIT_NEG_F32, SLJIT_FR0, 0, SLJIT_FR5, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 4); - /* wbuf[4] */ - sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F32, SLJIT_MEM2(SLJIT_S2, SLJIT_R1), SLJIT_WORD_SHIFT, SLJIT_FR0, 0); - sljit_emit_fop1(compiler, SLJIT_NEG_F64, SLJIT_FR4, 0, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64)); - /* ibuf[2] */ - sljit_emit_fop1(compiler, SLJIT_CONV_S32_FROM_F64, SLJIT_MEM1(SLJIT_R2), 2 * sizeof(sljit_s32), SLJIT_FR4, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_CONV_S32_FROM_F32, SLJIT_R0, 0, SLJIT_FR1, 0); - /* ibuf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R2), 3 * sizeof(sljit_s32), SLJIT_R0, 0); - - /* dbuf[5] */ - sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_SW, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S2), 0); - sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_SW, SLJIT_FR2, 0, SLJIT_IMM, -6213); - /* dbuf[6] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f64), SLJIT_FR2, 0); - /* dbuf[7] */ - sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_S32, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_f64), SLJIT_MEM0(), (sljit_sw)&ibuf[0]); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R2), sizeof(sljit_s32)); - sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_S32, SLJIT_FR1, 0, SLJIT_R0, 0); - /* dbuf[8] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_f64), SLJIT_FR1, 0); - /* dbuf[9] */ - sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_SW, SLJIT_MEM0(), (sljit_sw)(dbuf + 9), SLJIT_IMM, -77); - /* sbuf[5] */ - sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_SW, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_f32), SLJIT_IMM, -123); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 7190); - sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_SW, SLJIT_FR3, 0, SLJIT_R0, 0); - /* sbuf[6] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_f32), SLJIT_FR3, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 123); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_R2, 0, SLJIT_IMM, 123 * sizeof(sljit_s32)); - sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_S32, SLJIT_FR1, 0, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 2); - /* sbuf[7] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 7 * sizeof(sljit_f32), SLJIT_FR1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 3812); - /* sbuf[8] */ - sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_S32, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), SLJIT_F32_SHIFT, SLJIT_R1, 0); - /* sbuf[9] */ - sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_SW, SLJIT_MEM0(), (sljit_sw)(sbuf + 9), SLJIT_IMM, -79); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func0(); - FAILED(dbuf[3] != 476.25, "test48 case 1 failed\n"); - FAILED(dbuf[4] != 476.25, "test48 case 2 failed\n"); - FAILED(dbuf[5] != 2345.0, "test48 case 3 failed\n"); - FAILED(dbuf[6] != -6213.0, "test48 case 4 failed\n"); - FAILED(dbuf[7] != 312.0, "test48 case 5 failed\n"); - FAILED(dbuf[8] != -9324.0, "test48 case 6 failed\n"); - FAILED(dbuf[9] != -77.0, "test48 case 7 failed\n"); - - FAILED(sbuf[2] != 123.5, "test48 case 8 failed\n"); - FAILED(sbuf[3] != 123.5, "test48 case 9 failed\n"); - FAILED(sbuf[4] != 476.25, "test48 case 10 failed\n"); - FAILED(sbuf[5] != -123, "test48 case 11 failed\n"); - FAILED(sbuf[6] != 7190, "test48 case 12 failed\n"); - FAILED(sbuf[7] != 312, "test48 case 13 failed\n"); - FAILED(sbuf[8] != 3812, "test48 case 14 failed\n"); - FAILED(sbuf[9] != -79.0, "test48 case 15 failed\n"); - - FAILED(wbuf[1] != -367, "test48 case 16 failed\n"); - FAILED(wbuf[2] != 917, "test48 case 17 failed\n"); - FAILED(wbuf[3] != 476, "test48 case 18 failed\n"); - FAILED(wbuf[4] != -476, "test48 case 19 failed\n"); - - FAILED(ibuf[2] != -917, "test48 case 20 failed\n"); - FAILED(ibuf[3] != -1689, "test48 case 21 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test49(void) -{ - /* Test floating point conversions. */ - executable_code code; - struct sljit_compiler* compiler; - int i; - sljit_f64 dbuf[10]; - sljit_f32 sbuf[9]; - sljit_sw wbuf[9]; - sljit_s32 ibuf[9]; - sljit_s32* dbuf_ptr = (sljit_s32*)dbuf; - sljit_s32* sbuf_ptr = (sljit_s32*)sbuf; - - if (verbose) - printf("Run test49\n"); - - if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - if (verbose) - printf("no fpu available, test49 skipped\n"); - successful_tests++; - return; - } - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - for (i = 0; i < 9; i++) { - dbuf_ptr[i << 1] = -1; - dbuf_ptr[(i << 1) + 1] = -1; - sbuf_ptr[i] = -1; - wbuf[i] = -1; - ibuf[i] = -1; - } - -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - dbuf[9] = (sljit_f64)SLJIT_W(0x1122334455); -#endif - dbuf[0] = 673.75; - sbuf[0] = -879.75; - wbuf[0] = 345; - ibuf[0] = -249; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 3, 3, 3, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&dbuf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)&sbuf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, (sljit_sw)&wbuf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)&ibuf); - - /* dbuf[2] */ - sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_F32, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S1), 0); - /* sbuf[2] */ - sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_F64, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_S0), 0); - /* wbuf[2] */ - sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F64, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 0); - /* wbuf[4] */ - sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F32, SLJIT_MEM1(SLJIT_S2), 4 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S1), 0); - /* ibuf[2] */ - sljit_emit_fop1(compiler, SLJIT_CONV_S32_FROM_F64, SLJIT_MEM1(SLJIT_R2), 2 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_S0), 0); - /* ibuf[4] */ - sljit_emit_fop1(compiler, SLJIT_CONV_S32_FROM_F32, SLJIT_MEM1(SLJIT_R2), 4 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_S1), 0); - /* dbuf[4] */ - sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_SW, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S2), 0); - /* sbuf[4] */ - sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_SW, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_S2), 0); - /* dbuf[6] */ - sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_S32, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f64), SLJIT_MEM1(SLJIT_R2), 0); - /* sbuf[6] */ - sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_S32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_R2), 0); - -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_fop1(compiler, SLJIT_CONV_SW_FROM_F64, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_f64)); - /* wbuf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 8 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_f64)); - sljit_emit_fop1(compiler, SLJIT_CONV_S32_FROM_F64, SLJIT_R0, 0, SLJIT_FR2, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_AND32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0xffff); - /* ibuf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R2), 8 * sizeof(sljit_s32), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_W(0x4455667788)); - /* dbuf[8] */ - sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_SW, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_f64), SLJIT_R0, 0); - /* dbuf[9] */ - sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_S32, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_f64), SLJIT_IMM, SLJIT_W(0x7766554433)); -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func0(); - - FAILED(dbuf_ptr[(1 * 2) + 0] != -1, "test49 case 1 failed\n"); - FAILED(dbuf_ptr[(1 * 2) + 1] != -1, "test49 case 2 failed\n"); - FAILED(dbuf[2] != -879.75, "test49 case 3 failed\n"); - FAILED(dbuf_ptr[(3 * 2) + 0] != -1, "test49 case 4 failed\n"); - FAILED(dbuf_ptr[(3 * 2) + 1] != -1, "test49 case 5 failed\n"); - FAILED(dbuf[4] != 345, "test49 case 6 failed\n"); - FAILED(dbuf_ptr[(5 * 2) + 0] != -1, "test49 case 7 failed\n"); - FAILED(dbuf_ptr[(5 * 2) + 1] != -1, "test49 case 8 failed\n"); - FAILED(dbuf[6] != -249, "test49 case 9 failed\n"); - FAILED(dbuf_ptr[(7 * 2) + 0] != -1, "test49 case 10 failed\n"); - FAILED(dbuf_ptr[(7 * 2) + 1] != -1, "test49 case 11 failed\n"); - - FAILED(sbuf_ptr[1] != -1, "test49 case 12 failed\n"); - FAILED(sbuf[2] != 673.75, "test49 case 13 failed\n"); - FAILED(sbuf_ptr[3] != -1, "test49 case 14 failed\n"); - FAILED(sbuf[4] != 345, "test49 case 15 failed\n"); - FAILED(sbuf_ptr[5] != -1, "test49 case 16 failed\n"); - FAILED(sbuf[6] != -249, "test49 case 17 failed\n"); - FAILED(sbuf_ptr[7] != -1, "test49 case 18 failed\n"); - - FAILED(wbuf[1] != -1, "test49 case 19 failed\n"); - FAILED(wbuf[2] != 673, "test49 case 20 failed\n"); - FAILED(wbuf[3] != -1, "test49 case 21 failed\n"); - FAILED(wbuf[4] != -879, "test49 case 22 failed\n"); - FAILED(wbuf[5] != -1, "test49 case 23 failed\n"); - - FAILED(ibuf[1] != -1, "test49 case 24 failed\n"); - FAILED(ibuf[2] != 673, "test49 case 25 failed\n"); - FAILED(ibuf[3] != -1, "test49 case 26 failed\n"); - FAILED(ibuf[4] != -879, "test49 case 27 failed\n"); - FAILED(ibuf[5] != -1, "test49 case 28 failed\n"); - -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - FAILED(dbuf[8] != (sljit_f64)SLJIT_W(0x4455667788), "test49 case 29 failed\n"); - FAILED(dbuf[9] != (sljit_f64)SLJIT_W(0x66554433), "test49 case 30 failed\n"); - FAILED(wbuf[8] != SLJIT_W(0x1122334455), "test48 case 31 failed\n"); - FAILED(ibuf[8] == 0x4455, "test48 case 32 failed\n"); -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test50(void) -{ - /* Test stack and floating point operations. */ - executable_code code; - struct sljit_compiler* compiler; -#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) - sljit_uw size1, size2, size3; - int result; -#endif - sljit_f32 sbuf[7]; - - if (verbose) - printf("Run test50\n"); - - if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - if (verbose) - printf("no fpu available, test50 skipped\n"); - successful_tests++; - return; - } - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sbuf[0] = 245.5; - sbuf[1] = -100.25; - sbuf[2] = 713.75; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 3, 6, 0, 8 * sizeof(sljit_f32)); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f32), SLJIT_MEM1(SLJIT_SP), 0); - /* sbuf[3] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f32)); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f32), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f32)); - sljit_emit_fop2(compiler, SLJIT_ADD_F32, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f32)); - /* sbuf[4] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_f32)); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_f32), SLJIT_IMM, 5934); - sljit_emit_fop1(compiler, SLJIT_CONV_F32_FROM_S32, SLJIT_MEM1(SLJIT_SP), 3 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_f32)); - /* sbuf[5] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f32), SLJIT_MEM1(SLJIT_SP), 3 * sizeof(sljit_f32)); - -#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) - size1 = compiler->size; -#endif - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f32)); -#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) - size2 = compiler->size; -#endif - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR5, 0, SLJIT_FR2, 0); -#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) - size3 = compiler->size; -#endif - /* sbuf[6] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f32), SLJIT_FR5, 0); -#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) - result = (compiler->size - size3) == (size3 - size2) && (size3 - size2) == (size2 - size1); -#endif - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&sbuf); - - FAILED(sbuf[3] != 245.5, "test50 case 1 failed\n"); - FAILED(sbuf[4] != 145.25, "test50 case 2 failed\n"); - FAILED(sbuf[5] != 5934, "test50 case 3 failed\n"); - FAILED(sbuf[6] != 713.75, "test50 case 4 failed\n"); -#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) - FAILED(!result, "test50 case 5 failed\n"); -#endif - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test51(void) -{ - /* Test all registers provided by the CPU. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - struct sljit_jump* jump; - sljit_sw buf[2]; - sljit_s32 i; - - if (verbose) - printf("Run test51\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - buf[0] = 39; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), SLJIT_NUMBER_OF_REGISTERS, 0, 0, 0, 0); - - for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 32); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)buf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0); - - for (i = 2; i < SLJIT_NUMBER_OF_REGISTERS; i++) { - if (sljit_get_register_index(SLJIT_R(i)) >= 0) { - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R(i)), 0); - } else - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, buf[0]); - } - - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 32); - for (i = 2; i < SLJIT_NUMBER_OF_REGISTERS; i++) { - if (sljit_get_register_index(SLJIT_R(i)) >= 0) { - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R(i)), 32); - } else - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, buf[0]); - } - - for (i = 2; i < SLJIT_NUMBER_OF_REGISTERS; i++) { - if (sljit_get_register_index(SLJIT_R(i)) >= 0) { - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 32); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_MEM2(SLJIT_R(i), SLJIT_R0), 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_MEM2(SLJIT_R0, SLJIT_R(i)), 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 8); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_MEM2(SLJIT_R0, SLJIT_R(i)), 2); - } else - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 3 * buf[0]); - } - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 32 + sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func0(); - - FAILED(buf[1] != (39 * 5 * (SLJIT_NUMBER_OF_REGISTERS - 2)), "test51 case 1 failed\n"); - - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), SLJIT_NUMBER_OF_SCRATCH_REGISTERS, SLJIT_NUMBER_OF_SAVED_REGISTERS, 0, 0, 0); - - for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 17); - - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0(W)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - for (i = 0; i < SLJIT_NUMBER_OF_SAVED_REGISTERS; i++) - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S(i), 0); - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), SLJIT_NUMBER_OF_REGISTERS, 0, 0, 0, 0); - for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 35); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func0() != (SLJIT_NUMBER_OF_SAVED_REGISTERS * 17), "test51 case 2 failed\n"); - - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), SLJIT_NUMBER_OF_SCRATCH_REGISTERS, SLJIT_NUMBER_OF_SAVED_REGISTERS, 0, 0, 0); - - for (i = 0; i < SLJIT_NUMBER_OF_SAVED_REGISTERS; i++) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S(i), 0, SLJIT_IMM, 68); - for (i = 0; i < SLJIT_NUMBER_OF_SCRATCH_REGISTERS; i++) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 0); - - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0(W)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - for (i = 0; i < SLJIT_NUMBER_OF_SAVED_REGISTERS; i++) - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S(i), 0); - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), SLJIT_NUMBER_OF_REGISTERS, 0, 0, 0, 0); - for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 43); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func0() != (SLJIT_NUMBER_OF_SAVED_REGISTERS * 68), "test51 case 3 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test52(void) -{ - /* Test all registers provided by the CPU. */ - executable_code code; - struct sljit_compiler* compiler; - struct sljit_jump* jump; - sljit_f64 buf[3]; - sljit_s32 i; - - if (verbose) - printf("Run test52\n"); - - if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - if (verbose) - printf("no fpu available, test52 skipped\n"); - successful_tests++; - return; - } - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 6.25; - buf[1] = 17.75; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 0, 1, SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS, SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS, 0); - - for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++) - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_MEM1(SLJIT_S0), 0); - - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0(VOID)); - /* SLJIT_FR0 contains the first value. */ - for (i = 1; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++) - sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_FR0, 0, SLJIT_FR0, 0, SLJIT_FR(i), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR0, 0); - - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 1, 0, SLJIT_NUMBER_OF_FLOAT_REGISTERS, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf[1]); - for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++) - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_MEM1(SLJIT_R0), 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - FAILED(buf[2] != (SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS * 17.75 + SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS * 6.25), "test52 case 1 failed\n"); - - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = -32.5; - buf[1] = -11.25; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 0, 1, SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS, SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS, 0); - - for (i = 0; i < SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS; i++) - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_MEM1(SLJIT_S0), 0); - for (i = 0; i < SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS; i++) - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FS(i), 0, SLJIT_MEM1(SLJIT_S0), 0); - - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0(VOID)); - /* SLJIT_FR0 contains the first value. */ - for (i = 1; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++) - sljit_emit_fop2(compiler, SLJIT_ADD_F64, SLJIT_FR0, 0, SLJIT_FR0, 0, SLJIT_FR(i), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR0, 0); - - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 1, 0, SLJIT_NUMBER_OF_FLOAT_REGISTERS, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf[1]); - for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++) - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_MEM1(SLJIT_R0), 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - FAILED(buf[2] != (SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS * -11.25 + SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS * -32.5), "test52 case 2 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test53(void) -{ - /* Test addressing modes. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_u8 buf[3 + SLJIT_NUMBER_OF_REGISTERS * 3]; - sljit_u8 *buf_start; - sljit_uw addr = (sljit_uw)&buf; - sljit_s32 i; - - addr = addr + 3 - (addr % 3); - buf_start = (sljit_u8*)addr; - - SLJIT_ASSERT((addr % 3) == 0); - - for (i = 0; i < (sljit_s32)sizeof(buf); i++) - buf[i] = 0; - - if (verbose) - printf("Run test53\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), SLJIT_NUMBER_OF_REGISTERS, 0, 0, 0, 0); - - addr /= 3; - for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++, addr++) { - if (sljit_get_register_index(SLJIT_R(i)) == -1) - continue; - /* buf_start[i * 3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, (sljit_sw)addr); - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM2(SLJIT_R(i), SLJIT_R(i)), 1, SLJIT_IMM, 88 + i); - /* buf_start[i * 3 + 1] */ - if (i != 0) { - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(addr * 2 + 1)); - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM2(SLJIT_R(i), SLJIT_R0), 0, SLJIT_IMM, 147 + i); - } - /* buf_start[i * 3 + 2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, (sljit_sw)(addr * 3 + 2)); - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_R(i)), 0, SLJIT_IMM, 191 + i); - } - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R2, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func0(); - - for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++) { - if (sljit_get_register_index(SLJIT_R(i)) == -1) - continue; - - FAILED(buf_start[i * 3] != 88 + i, "test78 case 1 failed\n"); - if (i != 0) { - FAILED(buf_start[i * 3 + 1] != 147 + i, "test78 case 2 failed\n"); - } - FAILED(buf_start[i * 3 + 2] != 191 + i, "test78 case 3 failed\n"); - } - - sljit_free_code(code.code, NULL); - - successful_tests++; -} - -static void test54(void) -{ - /* Check cmov. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_sw large_num = SLJIT_W(0x1234567812345678); -#else - sljit_sw large_num = SLJIT_W(0x12345678); -#endif - int i; - sljit_sw buf[19]; - sljit_s32 ibuf[4]; - - union { - sljit_f32 value; - sljit_s32 s32_value; - } sbuf[3]; - - sbuf[0].s32_value = 0x7fffffff; - sbuf[1].value = 7.5; - sbuf[2].value = -14.75; - - if (verbose) - printf("Run test54\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - for (i = 0; i < 19; i++) - buf[i] = 0; - for (i = 0; i < 4; i++) - ibuf[i] = 0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(VOID, P, P, P), 5, 3, 3, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 17); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 34); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R0, 0, SLJIT_IMM, -10); - sljit_emit_cmov(compiler, SLJIT_SIG_LESS, SLJIT_R0, SLJIT_R1, 0); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_IMM, -10); - sljit_emit_cmov(compiler, SLJIT_SIG_GREATER, SLJIT_R0, SLJIT_R1, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 24); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 24); - sljit_emit_cmov(compiler, SLJIT_NOT_EQUAL, SLJIT_R0, SLJIT_IMM, 66); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_cmov(compiler, SLJIT_EQUAL, SLJIT_R0, SLJIT_IMM, 78); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_cmov(compiler, SLJIT_EQUAL, SLJIT_R0, SLJIT_IMM, large_num); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0); - -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - SLJIT_ASSERT(sljit_get_register_index(SLJIT_R3) == -1 && sljit_get_register_index(SLJIT_R4) == -1); -#endif - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 7); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -45); - sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 8); - sljit_emit_cmov(compiler, SLJIT_OVERFLOW, SLJIT_R3, SLJIT_IMM, 35); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R3, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, large_num); - sljit_emit_op2u(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_IMM, large_num); - sljit_emit_cmov(compiler, SLJIT_OVERFLOW, SLJIT_R3, SLJIT_IMM, 35); - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R3, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 71); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 13); - sljit_emit_op2(compiler, SLJIT_LSHR | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 8); - sljit_emit_cmov(compiler, SLJIT_EQUAL, SLJIT_R3, SLJIT_R0, 0); - /* buf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R3, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 12); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -29); - sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 8); - sljit_emit_cmov(compiler, SLJIT_NOT_OVERFLOW, SLJIT_R0, SLJIT_R3, 0); - /* buf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R3, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 16); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -12); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 21); - sljit_emit_op2u(compiler, SLJIT_AND | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_IMM, 8); - sljit_emit_cmov(compiler, SLJIT_NOT_EQUAL, SLJIT_R3, SLJIT_R4, 0); - /* buf[9] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R3, 0); - sljit_emit_cmov(compiler, SLJIT_EQUAL, SLJIT_R3, SLJIT_R4, 0); - /* buf[10] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R3, 0); - - if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S2), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_f32)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 16); - sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); - sljit_emit_cmov(compiler, SLJIT_F_EQUAL, SLJIT_R0, SLJIT_IMM, -45); - /* buf[11] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_GREATER, SLJIT_FR1, 0, SLJIT_FR2, 0); - sljit_emit_cmov(compiler, SLJIT_F_GREATER, SLJIT_R0, SLJIT_IMM, -45); - /* buf[12] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_GREATER_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); - sljit_emit_cmov(compiler, SLJIT_F_GREATER_EQUAL, SLJIT_R0, SLJIT_IMM, 33); - /* buf[13] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8); - sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_LESS, SLJIT_FR1, 0, SLJIT_FR2, 0); - sljit_emit_cmov(compiler, SLJIT_F_LESS, SLJIT_R0, SLJIT_IMM, -70); - /* buf[14] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_LESS_EQUAL, SLJIT_FR2, 0, SLJIT_FR1, 0); - sljit_emit_cmov(compiler, SLJIT_F_LESS_EQUAL, SLJIT_R0, SLJIT_IMM, -60); - /* buf[15] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_F_NOT_EQUAL, SLJIT_FR1, 0, SLJIT_FR2, 0); - sljit_emit_cmov(compiler, SLJIT_F_NOT_EQUAL, SLJIT_R0, SLJIT_IMM, 31); - /* buf[16] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 53); - sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_ORDERED, SLJIT_FR1, 0, SLJIT_FR0, 0); - sljit_emit_cmov(compiler, SLJIT_ORDERED, SLJIT_R0, SLJIT_IMM, 17); - /* buf[17] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_fop1(compiler, SLJIT_CMP_F32 | SLJIT_SET_UNORDERED, SLJIT_FR1, 0, SLJIT_FR0, 0); - sljit_emit_cmov(compiler, SLJIT_UNORDERED, SLJIT_R0, SLJIT_IMM, 59); - /* buf[18] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_R0, 0); - } - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 177); - sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_LESS, SLJIT_R0, 0, SLJIT_IMM, 178); - sljit_emit_cmov(compiler, SLJIT_LESS | SLJIT_32, SLJIT_R0, SLJIT_IMM, 200); - /* ibuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 95); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_IMM, 177); - sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_LESS_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 95); - sljit_emit_cmov(compiler, SLJIT_LESS_EQUAL | SLJIT_32, SLJIT_R3, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0); - /* ibuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R3, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_IMM, 56); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, -63); - sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_SIG_LESS, SLJIT_R3, 0, SLJIT_R4, 0); - sljit_emit_cmov(compiler, SLJIT_SIG_LESS | SLJIT_32, SLJIT_R3, SLJIT_R4, 0); - /* ibuf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_R3, 0); - sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_SIG_GREATER, SLJIT_R3, 0, SLJIT_R4, 0); - sljit_emit_cmov(compiler, SLJIT_SIG_GREATER | SLJIT_32, SLJIT_R3, SLJIT_R4, 0); - /* ibuf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_R3, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func3((sljit_sw)&buf, (sljit_sw)&ibuf, (sljit_sw)&sbuf); - - FAILED(buf[0] != 17, "test54 case 1 failed\n"); - FAILED(buf[1] != 34, "test54 case 2 failed\n"); - FAILED(buf[2] != 24, "test54 case 3 failed\n"); - FAILED(buf[3] != 78, "test54 case 4 failed\n"); - FAILED(buf[4] != large_num, "test54 case 5 failed\n"); - FAILED(buf[5] != -45, "test54 case 6 failed\n"); - FAILED(buf[6] != 35, "test54 case 7 failed\n"); - FAILED(buf[7] != 71, "test54 case 8 failed\n"); - FAILED(buf[8] != -29, "test54 case 9 failed\n"); - FAILED(buf[9] != -12, "test54 case 10 failed\n"); - FAILED(buf[10] != 21, "test54 case 11 failed\n"); - - if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - FAILED(buf[11] != 16, "test54 case 12 failed\n"); - FAILED(buf[12] != -45, "test54 case 13 failed\n"); - FAILED(buf[13] != 33, "test54 case 14 failed\n"); - FAILED(buf[14] != 8, "test54 case 15 failed\n"); - FAILED(buf[15] != -60, "test54 case 16 failed\n"); - FAILED(buf[16] != 31, "test54 case 17 failed\n"); - FAILED(buf[17] != 53, "test54 case 18 failed\n"); - FAILED(buf[18] != 59, "test54 case 19 failed\n"); - } - - FAILED(ibuf[0] != 200, "test54 case 12 failed\n"); - FAILED(ibuf[1] != 95, "test54 case 13 failed\n"); - FAILED(ibuf[2] != 56, "test54 case 14 failed\n"); - FAILED(ibuf[3] != -63, "test54 case 15 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test55(void) -{ - /* Check value preservation. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[2]; - sljit_s32 i; - - if (verbose) - printf("Run test55\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 0; - buf[1] = 0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), SLJIT_NUMBER_OF_REGISTERS, 0, 0, 0, sizeof (sljit_sw)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 217); - - /* Check 1 */ - for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 118); - - sljit_emit_op0(compiler, SLJIT_DIVMOD_SW); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - - for (i = 2; i < SLJIT_NUMBER_OF_REGISTERS; i++) - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R(i), 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 0), SLJIT_R0, 0); - - /* Check 2 */ - for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS; i++) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 146); - - sljit_emit_op0(compiler, SLJIT_DIV_SW); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - - for (i = 1; i < SLJIT_NUMBER_OF_REGISTERS; i++) - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R(i), 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 1), SLJIT_R0, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func0(); - - FAILED(buf[0] != (SLJIT_NUMBER_OF_REGISTERS - 2) * 118 + 217, "test55 case 1 failed\n"); - FAILED(buf[1] != (SLJIT_NUMBER_OF_REGISTERS - 1) * 146 + 217, "test55 case 2 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test56(void) -{ - /* Check integer subtraction with negative immediate. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[13]; - sljit_s32 i; - - if (verbose) - printf("Run test56\n"); - - for (i = 0; i < 13; i++) - buf[i] = 77; - - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 1, 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 90 << 12); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12)); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0); - /* buf[1] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_SIG_GREATER); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12)); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R1, 0); - /* buf[3] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_LESS); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER_EQUAL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12)); - /* buf[4] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_SIG_GREATER_EQUAL); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12)); - /* buf[5] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_LESS_EQUAL); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12)); - /* buf[6] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_GREATER); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_LESS, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12)); - /* buf[7] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_SIG_LESS); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 90); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_SIG_GREATER, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -91); - /* buf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[9] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_SIG_GREATER); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 90); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -91); - /* buf[10] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_LESS_EQUAL); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -0x7fffffff); - sljit_emit_op2(compiler, SLJIT_ADD32 | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -(91 << 12)); - /* buf[11] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_OVERFLOW); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -0x7fffffff-1); - sljit_emit_op2(compiler, SLJIT_SUB32 | SLJIT_SET_OVERFLOW, SLJIT_R0, 0, SLJIT_IMM, 0, SLJIT_R0, 0); - /* buf[12] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_OVERFLOW); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - - FAILED(buf[0] != (181 << 12), "test56 case 1 failed\n"); - FAILED(buf[1] != 1, "test56 case 2 failed\n"); - FAILED(buf[2] != (181 << 12), "test56 case 3 failed\n"); - FAILED(buf[3] != 1, "test56 case 4 failed\n"); - FAILED(buf[4] != 1, "test56 case 5 failed\n"); - FAILED(buf[5] != 1, "test56 case 6 failed\n"); - FAILED(buf[6] != 0, "test56 case 7 failed\n"); - FAILED(buf[7] != 0, "test56 case 8 failed\n"); - FAILED(buf[8] != 181, "test56 case 9 failed\n"); - FAILED(buf[9] != 1, "test56 case 10 failed\n"); - FAILED(buf[10] != 1, "test56 case 11 failed\n"); - FAILED(buf[11] != 1, "test56 case 12 failed\n"); - FAILED(buf[12] != 1, "test56 case 13 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test57(void) -{ - /* Check prefetch instructions. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - struct sljit_label* labels[5]; - sljit_p addr[5]; - int i; - - if (verbose) - printf("Run test57\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 3, 1, 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - labels[0] = sljit_emit_label(compiler); - /* Should never crash. */ - sljit_emit_op_src(compiler, SLJIT_PREFETCH_L1, SLJIT_MEM2(SLJIT_R0, SLJIT_R0), 2); - labels[1] = sljit_emit_label(compiler); - sljit_emit_op_src(compiler, SLJIT_PREFETCH_L2, SLJIT_MEM0(), 0); - labels[2] = sljit_emit_label(compiler); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_op_src(compiler, SLJIT_PREFETCH_L3, SLJIT_MEM1(SLJIT_R0), SLJIT_W(0x1122334455667788)); -#else - sljit_emit_op_src(compiler, SLJIT_PREFETCH_L3, SLJIT_MEM1(SLJIT_R0), 0x11223344); -#endif - labels[3] = sljit_emit_label(compiler); - sljit_emit_op_src(compiler, SLJIT_PREFETCH_ONCE, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw)); - labels[4] = sljit_emit_label(compiler); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - - for (i = 0; i < 5; i++) - addr[i] = sljit_get_label_addr(labels[i]); - - sljit_free_compiler(compiler); - - code.func0(); - - if (sljit_has_cpu_feature(SLJIT_HAS_PREFETCH)) { - FAILED(addr[0] == addr[1], "test57 case 1 failed\n"); - FAILED(addr[1] == addr[2], "test57 case 2 failed\n"); - FAILED(addr[2] == addr[3], "test57 case 3 failed\n"); - FAILED(addr[3] == addr[4], "test57 case 4 failed\n"); - } - else { - FAILED(addr[0] != addr[1], "test57 case 1 failed\n"); - FAILED(addr[1] != addr[2], "test57 case 2 failed\n"); - FAILED(addr[2] != addr[3], "test57 case 3 failed\n"); - FAILED(addr[3] != addr[4], "test57 case 4 failed\n"); - } - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static sljit_f64 test58_f1(sljit_f32 a, sljit_f32 b, sljit_f64 c) -{ - return (sljit_f64)a + (sljit_f64)b + c; -} - -static sljit_f32 test58_f2(sljit_sw a, sljit_f64 b, sljit_f32 c) -{ - return (sljit_f32)((sljit_f64)a + b + (sljit_f64)c); -} - -static sljit_f64 test58_f3(sljit_sw a, sljit_f32 b, sljit_sw c) -{ - return (sljit_f64)a + (sljit_f64)b + (sljit_f64)c; -} - -static sljit_f64 test58_f4(sljit_f32 a, sljit_sw b) -{ - return (sljit_f64)a + (sljit_f64)b; -} - -static sljit_f32 test58_f5(sljit_f32 a, sljit_f64 b, sljit_s32 c) -{ - return (sljit_f32)((sljit_f64)a + b + (sljit_f64)c); -} - -static sljit_sw test58_f6(sljit_f64 a, sljit_sw b) -{ - return (sljit_sw)(a + (sljit_f64)b); -} - -static void test58(void) -{ - /* Check function calls with floating point arguments. */ - executable_code code; - struct sljit_compiler* compiler; - struct sljit_jump* jump = NULL; - sljit_f64 dbuf[7]; - sljit_f32 sbuf[7]; - sljit_sw wbuf[2]; - - if (verbose) - printf("Run test58\n"); - - if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - if (verbose) - printf("no fpu available, test58 skipped\n"); - successful_tests++; - return; - } - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - dbuf[0] = 5.25; - dbuf[1] = 0.0; - dbuf[2] = 2.5; - dbuf[3] = 0.0; - dbuf[4] = 0.0; - dbuf[5] = 0.0; - dbuf[6] = -18.0; - - sbuf[0] = 6.75; - sbuf[1] = -3.5; - sbuf[2] = 1.5; - sbuf[3] = 0.0; - sbuf[4] = 0.0; - - wbuf[0] = 0; - wbuf[1] = 0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(VOID, P, P, P), 3, 3, 4, 0, sizeof(sljit_sw)); - - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(F64, F32, F32, F64), SLJIT_IMM, SLJIT_FUNC_ADDR(test58_f1)); - /* dbuf[1] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64), SLJIT_FR0, 0); - - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64)); - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS3(F64, F32, F32, F64)); - sljit_set_target(jump, SLJIT_FUNC_UADDR(test58_f1)); - /* dbuf[3] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64), SLJIT_FR0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test58_f2)); - sljit_get_local_base(compiler, SLJIT_R1, 0, -16); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 16); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32)); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(F32, W, F64, F32), SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0); - /* sbuf[3] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f32), SLJIT_FR0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -4); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 9); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0); - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS3(F64, W, F32, W)); - sljit_set_target(jump, SLJIT_FUNC_UADDR(test58_f3)); - /* dbuf[4] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f64), SLJIT_FR0, 0); - - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -6); - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS2(F64, F32, W)); - sljit_set_target(jump, SLJIT_FUNC_UADDR(test58_f4)); - /* dbuf[5] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_f64), SLJIT_FR0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test58_f5)); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(F32, F32, F64, 32), SLJIT_MEM1(SLJIT_SP), 0); - /* sbuf[4] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_f32), SLJIT_FR0, 0); - - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f64)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test58_f6)); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, F64, W), SLJIT_R0, 0); - /* wbuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 0, SLJIT_R0, 0); - - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_f64)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 319); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test58_f6)); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, F64, W), SLJIT_R1, 0); - /* wbuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func3((sljit_sw)&dbuf, (sljit_sw)&sbuf, (sljit_sw)&wbuf); - - FAILED(dbuf[1] != 8.5, "test58 case 1 failed\n"); - FAILED(dbuf[3] != 0.5, "test58 case 2 failed\n"); - FAILED(sbuf[3] != 17.75, "test58 case 3 failed\n"); - FAILED(dbuf[4] != 11.75, "test58 case 4 failed\n"); - FAILED(dbuf[5] != -9.5, "test58 case 5 failed\n"); - FAILED(sbuf[4] != 12, "test58 case 6 failed\n"); - FAILED(wbuf[0] != SLJIT_FUNC_ADDR(test58_f6) - 18, "test58 case 7 failed\n"); - FAILED(wbuf[1] != 301, "test58 case 8 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static sljit_sw test59_f1(sljit_sw a, sljit_s32 b, sljit_sw c, sljit_sw d) -{ - return (sljit_sw)(a + b + c + d - SLJIT_FUNC_ADDR(test59_f1)); -} - -static sljit_s32 test59_f2(sljit_f64 a, sljit_f32 b, sljit_f64 c, sljit_sw d) -{ - return (sljit_s32)(a + b + c + (sljit_f64)d); -} - -static sljit_f32 test59_f3(sljit_f32 a, sljit_s32 b, sljit_f64 c, sljit_sw d) -{ - return (sljit_f32)(a + (sljit_f64)b + c + (sljit_f64)d); -} - -static sljit_f32 test59_f4(sljit_f32 a, sljit_f64 b, sljit_f32 c, sljit_f64 d) -{ - return (sljit_f32)(a + b + c + (sljit_f64)d); -} - -static void test59(void) -{ - /* Check function calls with four arguments. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - struct sljit_jump* jump = NULL; - sljit_sw wbuf[5]; - sljit_f64 dbuf[3]; - sljit_f32 sbuf[4]; - - if (verbose) - printf("Run test59\n"); - - wbuf[0] = 0; - wbuf[1] = 0; - wbuf[2] = SLJIT_FUNC_ADDR(test59_f1); - wbuf[3] = 0; - wbuf[4] = 0; - - if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - dbuf[0] = 5.125; - dbuf[1] = 6.125; - dbuf[2] = 4.25; - - sbuf[0] = 0.75; - sbuf[1] = -1.5; - sbuf[2] = 0.0; - sbuf[3] = 0.0; - } - - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(VOID, P, P, P), 4, 3, 4, 0, sizeof(sljit_sw)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 33); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, -20); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test59_f1)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -40); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, 32, W, W), SLJIT_R2, 0); - /* wbuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test59_f1)); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, -25); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 100); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -10); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, 32, W, W), SLJIT_R0, 0); - /* wbuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 231); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test59_f1) - 100); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, 32, W, W), SLJIT_MEM2(SLJIT_R0, SLJIT_R2), SLJIT_WORD_SHIFT); - /* wbuf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0); - - if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S2), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -100); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(32, F64, F32, F64, W), SLJIT_IMM, SLJIT_FUNC_ADDR(test59_f2)); - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_R0, 0); - /* wbuf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f64)); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 36); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 41); - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS4(F32, F32, 32, F64, W)); - sljit_set_target(jump, SLJIT_FUNC_UADDR(test59_f3)); - /* sbuf[2] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_f32), SLJIT_FR0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test59_f4)); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S2), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f64)); - sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(F32, F32, F64, F32, F64), SLJIT_R0, 0); - /* sbuf[2] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S2), 3 * sizeof(sljit_f32), SLJIT_FR0, 0); - } - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func3((sljit_sw)&wbuf, (sljit_sw)&dbuf, (sljit_sw)&sbuf); - - FAILED(wbuf[0] != -27, "test59 case 1 failed\n"); - FAILED(wbuf[1] != 65, "test59 case 2 failed\n"); - FAILED(wbuf[3] != (sljit_sw)wbuf + 133, "test59 case 3 failed\n"); - - if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - FAILED(wbuf[4] != -88, "test59 case 4 failed\n"); - FAILED(sbuf[2] != 79.75, "test59 case 5 failed\n"); - FAILED(sbuf[3] != 8.625, "test59 case 6 failed\n"); - } - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test60(void) -{ - /* Test memory accesses with pre/post updates. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_u32 i; - sljit_s32 supported[10]; - sljit_sw wbuf[18]; - sljit_s8 bbuf[4]; - sljit_s32 ibuf[4]; - -#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) - static sljit_u8 expected[10] = { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }; -#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) - static sljit_u8 expected[10] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; -#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) - static sljit_u8 expected[10] = { 1, 0, 1, 1, 0, 1, 1, 1, 0, 0 }; -#elif (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - static sljit_u8 expected[10] = { 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 }; -#else - static sljit_u8 expected[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -#endif - - if (verbose) - printf("Run test60\n"); - - for (i = 0; i < 18; i++) - wbuf[i] = 0; - wbuf[2] = -887766; - - bbuf[0] = 0; - bbuf[1] = 0; - bbuf[2] = -13; - - ibuf[0] = -5678; - ibuf[1] = 0; - ibuf[2] = 0; - - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(VOID, P, P, P), 4, 3, 4, 0, sizeof(sljit_sw)); - - supported[0] = sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_sw)); - if (supported[0] == SLJIT_SUCCESS) { - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0); - sljit_emit_mem_update(compiler, SLJIT_MOV, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_sw)); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0); - } - - supported[1] = sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM1(SLJIT_R2), -2 * (sljit_sw)sizeof(sljit_s8)); - if (supported[1] == SLJIT_SUCCESS) { - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 2 * sizeof(sljit_s8)); - sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM1(SLJIT_R2), -2 * (sljit_sw)sizeof(sljit_s8)); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R2, 0); - } - - supported[2] = sljit_emit_mem_update(compiler, SLJIT_MOV_S32 | SLJIT_MEM_SUPP, SLJIT_R2, SLJIT_MEM1(SLJIT_R1), -2 * (sljit_sw)sizeof(sljit_s32)); - if (supported[2] == SLJIT_SUCCESS) { - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S2, 0, SLJIT_IMM, 2 * sizeof(sljit_s32)); - sljit_emit_mem_update(compiler, SLJIT_MOV_S32, SLJIT_R2, SLJIT_MEM1(SLJIT_R1), -2 * (sljit_sw)sizeof(sljit_s32)); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R2, 0); - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R1, 0); - } - - supported[3] = sljit_emit_mem_update(compiler, SLJIT_MOV32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE, SLJIT_R1, SLJIT_MEM1(SLJIT_R2), 2 * sizeof(sljit_s32)); - if (supported[3] == SLJIT_SUCCESS) { - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, -8765); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R2, 0, SLJIT_S2, 0, SLJIT_IMM, sizeof(sljit_s32)); - sljit_emit_mem_update(compiler, SLJIT_MOV32 | SLJIT_MEM_STORE, SLJIT_R1, SLJIT_MEM1(SLJIT_R2), 2 * sizeof(sljit_s32)); - /* buf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R2, 0); - } - - supported[4] = sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_R1, SLJIT_MEM1(SLJIT_R2), -128 * (sljit_sw)sizeof(sljit_s8)); - if (supported[4] == SLJIT_SUCCESS) { - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -121); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_S1, 0); - sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_R1, SLJIT_MEM1(SLJIT_R2), -128 * (sljit_sw)sizeof(sljit_s8)); - /* buf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R2, 0); - } - - supported[5] = sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 1); - if (supported[5] == SLJIT_SUCCESS) { - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 9 * sizeof(sljit_sw) - 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -881199); - sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_STORE, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 1); - /* buf[10] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R0, 0); - } - - supported[6] = sljit_emit_mem_update(compiler, SLJIT_MOV_S32 | SLJIT_MEM_SUPP, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); - if (supported[6] == SLJIT_SUCCESS) { - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S2, 0, SLJIT_IMM, 213); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -213); - sljit_emit_mem_update(compiler, SLJIT_MOV_S32, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); - /* buf[11] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[12] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R1, 0); - } - - supported[7] = sljit_emit_mem_update(compiler, SLJIT_MOV_S32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); - if (supported[7] == SLJIT_SUCCESS) { - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2 * sizeof(sljit_s32)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -7890); - sljit_emit_mem_update(compiler, SLJIT_MOV_S32 | SLJIT_MEM_STORE, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); - /* buf[13] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R1, 0); - } - - supported[8] = sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 2); - if (supported[8] == SLJIT_SUCCESS) { - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 2 * sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2 * sizeof(sljit_sw)); - sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 2); - /* buf[14] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[15] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_R1, 0); - } - - supported[9] = sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); - if (supported[9] == SLJIT_SUCCESS) { - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 2 * sizeof(sljit_s8)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -2 * (sljit_sw)sizeof(sljit_s8)); - sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_POST, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0); - /* buf[16] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[17] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_R1, 0); - } - - SLJIT_ASSERT(sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 1) == SLJIT_ERR_UNSUPPORTED); - SLJIT_ASSERT(sljit_emit_mem_update(compiler, SLJIT_MOV_S8 | SLJIT_MEM_SUPP, SLJIT_R0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 1) == SLJIT_ERR_UNSUPPORTED); - -#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) - /* TODO: at least for ARM (both V5 and V7) the range below needs further fixing */ - SLJIT_ASSERT(sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), 256) == SLJIT_ERR_UNSUPPORTED); - SLJIT_ASSERT(sljit_emit_mem_update(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_R1, SLJIT_MEM1(SLJIT_R0), -257) == SLJIT_ERR_UNSUPPORTED); -#endif - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func3((sljit_sw)&wbuf, (sljit_sw)&bbuf, (sljit_sw)&ibuf); - - FAILED(sizeof(expected) != sizeof(supported) / sizeof(sljit_s32), "test60 case 1 failed\n"); - - for (i = 0; i < sizeof(expected); i++) { - if (expected[i]) { - if (supported[i] != SLJIT_SUCCESS) { - printf("tast60 case %d should be supported\n", i + 1); - return; - } - } else { - if (supported[i] == SLJIT_SUCCESS) { - printf("test60 case %d should not be supported\n", i + 1); - return; - } - } - } - - FAILED(supported[0] == SLJIT_SUCCESS && wbuf[0] != -887766, "test60 case 2 failed\n"); - FAILED(supported[0] == SLJIT_SUCCESS && wbuf[1] != (sljit_sw)(wbuf + 2), "test60 case 3 failed\n"); - FAILED(supported[1] == SLJIT_SUCCESS && wbuf[3] != -13, "test60 case 4 failed\n"); - FAILED(supported[1] == SLJIT_SUCCESS && wbuf[4] != (sljit_sw)(bbuf), "test60 case 5 failed\n"); - FAILED(supported[2] == SLJIT_SUCCESS && wbuf[5] != -5678, "test60 case 6 failed\n"); - FAILED(supported[2] == SLJIT_SUCCESS && wbuf[6] != (sljit_sw)(ibuf), "test60 case 7 failed\n"); - FAILED(supported[3] == SLJIT_SUCCESS && ibuf[1] != -8765, "test60 case 8 failed\n"); - FAILED(supported[3] == SLJIT_SUCCESS && wbuf[7] != (sljit_sw)(ibuf + 1), "test60 case 9 failed\n"); - FAILED(supported[4] == SLJIT_SUCCESS && bbuf[0] != -121, "test60 case 10 failed\n"); - FAILED(supported[4] == SLJIT_SUCCESS && wbuf[8] != (sljit_sw)(bbuf) - 128 * (sljit_sw)sizeof(sljit_s8), "test60 case 11 failed\n"); - FAILED(supported[5] == SLJIT_SUCCESS && wbuf[9] != -881199, "test60 case 12 failed\n"); - FAILED(supported[5] == SLJIT_SUCCESS && wbuf[10] != (sljit_sw)(wbuf + 9), "test60 case 13 failed\n"); - FAILED(supported[6] == SLJIT_SUCCESS && wbuf[11] != -5678, "test60 case 14 failed\n"); - FAILED(supported[6] == SLJIT_SUCCESS && wbuf[12] != (sljit_sw)(ibuf), "test60 case 15 failed\n"); - FAILED(supported[7] == SLJIT_SUCCESS && ibuf[2] != -7890, "test60 case 16 failed\n"); - FAILED(supported[7] == SLJIT_SUCCESS && wbuf[13] != (sljit_sw)(ibuf + 2), "test60 case 17 failed\n"); - FAILED(supported[8] == SLJIT_SUCCESS && wbuf[14] != -887766, "test60 case 18 failed\n"); - FAILED(supported[8] == SLJIT_SUCCESS && wbuf[15] != (sljit_sw)(wbuf + 10), "test60 case 19 failed\n"); - FAILED(supported[9] == SLJIT_SUCCESS && wbuf[16] != -13, "test60 case 20 failed\n"); - FAILED(supported[9] == SLJIT_SUCCESS && wbuf[17] != (sljit_sw)(bbuf), "test60 case 21 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test61(void) -{ - /* Test float memory accesses with pre/post updates. */ - executable_code code; - struct sljit_compiler* compiler; - sljit_u32 i; - sljit_s32 supported[6]; - sljit_sw wbuf[6]; - sljit_f64 dbuf[4]; - sljit_f32 sbuf[4]; -#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) - static sljit_u8 expected[6] = { 1, 1, 1, 1, 0, 0 }; -#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) - static sljit_u8 expected[6] = { 1, 0, 1, 0, 1, 1 }; -#else - static sljit_u8 expected[6] = { 0, 0, 0, 0, 0, 0 }; -#endif - - if (verbose) - printf("Run test61\n"); - - if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - if (verbose) - printf("no fpu available, test61 skipped\n"); - successful_tests++; - return; - } - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - for (i = 0; i < 6; i++) - wbuf[i] = 0; - - dbuf[0] = 66.725; - dbuf[1] = 0.0; - dbuf[2] = 0.0; - dbuf[3] = 0.0; - - sbuf[0] = 0.0; - sbuf[1] = -22.125; - sbuf[2] = 0.0; - sbuf[3] = 0.0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(VOID, P, P, P), 4, 3, 4, 0, sizeof(sljit_sw)); - - supported[0] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_f64)); - if (supported[0] == SLJIT_SUCCESS) { - /* dbuf[1] */ - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, 4 * sizeof(sljit_f64)); - sljit_emit_fmem_update(compiler, SLJIT_MOV_F64, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_f64)); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64), SLJIT_FR0, 0); - /* wbuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - } - - supported[1] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_FR2, SLJIT_MEM1(SLJIT_R0), -(sljit_sw)sizeof(sljit_f64)); - if (supported[1] == SLJIT_SUCCESS) { - /* dbuf[2] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, 2 * sizeof(sljit_f64)); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), 0); - sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_FR2, SLJIT_MEM1(SLJIT_R0), -(sljit_sw)sizeof(sljit_f64)); - /* wbuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0); - } - - supported[2] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE, SLJIT_FR1, SLJIT_MEM1(SLJIT_R2), -4 * (sljit_sw)sizeof(sljit_f32)); - if (supported[2] == SLJIT_SUCCESS) { - /* sbuf[0] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S2, 0, SLJIT_IMM, 4 * sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f32)); - sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_STORE, SLJIT_FR1, SLJIT_MEM1(SLJIT_R2), -4 * (sljit_sw)sizeof(sljit_f32)); - /* wbuf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R2, 0); - } - - supported[3] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_FR1, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_f32)); - if (supported[3] == SLJIT_SUCCESS) { - /* sbuf[2] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S2, 0, SLJIT_IMM, sizeof(sljit_f32)); - sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_POST, SLJIT_FR1, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_f32), SLJIT_FR1, 0); - /* wbuf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R1, 0); - } - - supported[4] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP, SLJIT_FR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0); - if (supported[4] == SLJIT_SUCCESS) { - /* dbuf[3] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 8 * sizeof(sljit_f64)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -8 * (sljit_sw)sizeof(sljit_f64)); - sljit_emit_fmem_update(compiler, SLJIT_MOV_F64, SLJIT_FR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_f64), SLJIT_FR0, 0); - /* wbuf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0); - } - - supported[5] = sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE, SLJIT_FR2, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 0); - if (supported[5] == SLJIT_SUCCESS) { - /* sbuf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_S2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 3 * sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f32)); - sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_STORE, SLJIT_FR2, SLJIT_MEM2(SLJIT_R2, SLJIT_R1), 0); - /* wbuf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R2, 0); - } - - SLJIT_ASSERT(sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_FR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0) == SLJIT_ERR_UNSUPPORTED); - SLJIT_ASSERT(sljit_emit_fmem_update(compiler, SLJIT_MOV_F32 | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_POST, SLJIT_FR0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0) == SLJIT_ERR_UNSUPPORTED); - -#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) - /* TODO: at least for ARM (both V5 and V7) the range below needs further fixing */ - SLJIT_ASSERT(sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 256) == SLJIT_ERR_UNSUPPORTED); - SLJIT_ASSERT(sljit_emit_fmem_update(compiler, SLJIT_MOV_F64 | SLJIT_MEM_SUPP | SLJIT_MEM_POST, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), -257) == SLJIT_ERR_UNSUPPORTED); -#endif - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func3((sljit_sw)&wbuf, (sljit_sw)&dbuf, (sljit_sw)&sbuf); - - FAILED(sizeof(expected) != sizeof(supported) / sizeof(sljit_s32), "test61 case 1 failed\n"); - - for (i = 0; i < sizeof(expected); i++) { - if (expected[i]) { - if (supported[i] != SLJIT_SUCCESS) { - printf("tast61 case %d should be supported\n", i + 1); - return; - } - } else { - if (supported[i] == SLJIT_SUCCESS) { - printf("test61 case %d should not be supported\n", i + 1); - return; - } - } - } - - FAILED(supported[0] == SLJIT_SUCCESS && dbuf[1] != 66.725, "test61 case 2 failed\n"); - FAILED(supported[0] == SLJIT_SUCCESS && wbuf[0] != (sljit_sw)(dbuf), "test61 case 3 failed\n"); - FAILED(supported[1] == SLJIT_SUCCESS && dbuf[2] != 66.725, "test61 case 4 failed\n"); - FAILED(supported[1] == SLJIT_SUCCESS && wbuf[1] != (sljit_sw)(dbuf + 1), "test61 case 5 failed\n"); - FAILED(supported[2] == SLJIT_SUCCESS && sbuf[0] != -22.125, "test61 case 6 failed\n"); - FAILED(supported[2] == SLJIT_SUCCESS && wbuf[2] != (sljit_sw)(sbuf), "test61 case 7 failed\n"); - FAILED(supported[3] == SLJIT_SUCCESS && sbuf[2] != -22.125, "test61 case 8 failed\n"); - FAILED(supported[3] == SLJIT_SUCCESS && wbuf[3] != (sljit_sw)(sbuf + 2), "test61 case 9 failed\n"); - FAILED(supported[4] == SLJIT_SUCCESS && dbuf[3] != 66.725, "test61 case 10 failed\n"); - FAILED(supported[4] == SLJIT_SUCCESS && wbuf[4] != (sljit_sw)(dbuf), "test61 case 11 failed\n"); - FAILED(supported[5] == SLJIT_SUCCESS && sbuf[3] != -22.125, "test61 case 12 failed\n"); - FAILED(supported[5] == SLJIT_SUCCESS && wbuf[5] != (sljit_sw)(sbuf + 3), "test61 case 13 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test62(void) -{ - /* Test fast calls flag preservation. */ - executable_code code1; - executable_code code2; - struct sljit_compiler* compiler; - - if (verbose) - printf("Run test62\n"); - - /* A */ - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - sljit_set_context(compiler, 0, SLJIT_ARGS1(W, W), 1, 1, 0, 0, 0); - - sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R0, 0); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_S0, 0, SLJIT_IMM, 42); - sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_R0, 0); - - code1.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - /* B */ - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, W), 1, 1, 0, 0, 0); - sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, SLJIT_FUNC_ADDR(code1.code)); - sljit_set_current_flags(compiler, SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE | SLJIT_SET_Z | SLJIT_SET_LESS); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_ZERO); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_LESS); - sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, 1); - sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S0, 0); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0); - - code2.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code2.func1(88) != 0, "test62 case 1 failed\n"); - FAILED(code2.func1(42) != 1, "test62 case 2 failed\n"); - FAILED(code2.func1(0) != 2, "test62 case 3 failed\n"); - - sljit_free_code(code1.code, NULL); - sljit_free_code(code2.code, NULL); - successful_tests++; -} - -static void test63(void) -{ - /* Test put label. */ - executable_code code; - struct sljit_label *label[2]; - struct sljit_put_label *put_label[5]; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_uw addr[2]; - sljit_uw buf[4]; -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_sw offs = SLJIT_W(0x123456789012); -#else - sljit_sw offs = 0x12345678; -#endif - - if (verbose) - printf("Run test63\n"); - - FAILED(!compiler, "cannot create compiler\n"); - buf[0] = 0; - buf[1] = 0; - buf[2] = 0; - buf[3] = 0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0, 0, 2 * sizeof(sljit_sw)); - - /* buf[0-1] */ - put_label[0] = sljit_emit_put_label(compiler, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - - put_label[1] = sljit_emit_put_label(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_uw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw)); - - label[0] = sljit_emit_label(compiler); - sljit_set_put_label(put_label[0], label[0]); - sljit_set_put_label(put_label[1], label[0]); - - /* buf[2-3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(buf + 2) - offs); - put_label[2] = sljit_emit_put_label(compiler, SLJIT_MEM1(SLJIT_R0), offs); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (offs + (sljit_sw)sizeof(sljit_uw)) >> 1); - put_label[3] = sljit_emit_put_label(compiler, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1); - - label[1] = sljit_emit_label(compiler); - sljit_set_put_label(put_label[2], label[1]); - sljit_set_put_label(put_label[3], label[1]); - - /* Return value */ - put_label[4] = sljit_emit_put_label(compiler, SLJIT_RETURN_REG, 0); - sljit_set_put_label(put_label[4], label[0]); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - - addr[0] = sljit_get_label_addr(label[0]); - addr[1] = sljit_get_label_addr(label[1]); - - sljit_free_compiler(compiler); - - FAILED(code.func1((sljit_sw)&buf) != (sljit_sw)addr[0], "test63 case 1 failed\n"); - FAILED(buf[0] != addr[0], "test63 case 2 failed\n"); - FAILED(buf[1] != addr[0], "test63 case 3 failed\n"); - FAILED(buf[2] != addr[1], "test63 case 4 failed\n"); - FAILED(buf[3] != addr[1], "test63 case 5 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test64(void) -{ - /* Test put label with absolute label addresses */ - executable_code code; - sljit_uw malloc_addr; - struct sljit_label label[6]; - struct sljit_put_label *put_label[2]; - struct sljit_compiler* compiler; - sljit_uw buf[7]; - sljit_s32 i; -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - /* Must be even because it is also used for addressing. */ - sljit_sw offs1 = SLJIT_W(0x1234567812); - sljit_sw offs2 = SLJIT_W(0x123456781122); - sljit_sw offs3 = SLJIT_W(0x7fffffff7ff); - sljit_sw offs4 = SLJIT_W(0x1234567811223344); -#else /* !SLJIT_64BIT_ARCHITECTURE */ - sljit_sw offs1 = (sljit_sw)0x80000000; - sljit_sw offs2 = (sljit_sw)0xe0000000; - sljit_sw offs3 = (sljit_sw)0x87654321; - sljit_sw offs4 = (sljit_sw)0xffffffff; -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - if (verbose) - printf("Run test64\n"); - - /* lock next allocation; see sljit_test_malloc_exec() */ -#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) - malloc_addr = (sljit_uw)SLJIT_MALLOC_EXEC(1024, NULL); - - if (!malloc_addr) { - printf("Cannot allocate executable memory\n"); - return; - } - - compiler = sljit_create_compiler(NULL, (void*)malloc_addr); - malloc_addr += (sljit_uw)SLJIT_EXEC_OFFSET((void*)malloc_addr); -#else /* SLJIT_CONFIG_UNSUPPORTED */ - malloc_addr = 0; - compiler = sljit_create_compiler(NULL, (void*)malloc_addr); -#endif /* !SLJIT_CONFIG_UNSUPPORTED */ - - label[0].addr = 0x1234; - label[0].size = (sljit_uw)0x1234 - malloc_addr; - - label[1].addr = 0x12345678; - label[1].size = (sljit_uw)0x12345678 - malloc_addr; - - label[2].addr = (sljit_uw)offs1; - label[2].size = (sljit_uw)offs1 - malloc_addr; - - label[3].addr = (sljit_uw)offs2; - label[3].size = (sljit_uw)offs2 - malloc_addr; - - label[4].addr = (sljit_uw)offs3; - label[4].size = (sljit_uw)offs3 - malloc_addr; - - label[5].addr = (sljit_uw)offs4; - label[5].size = (sljit_uw)offs4 - malloc_addr; - - FAILED(!compiler, "cannot create compiler\n"); - - for (i = 0; i < 6; i++) - buf[i] = 0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, P), 3, 1, 0, 0, 2 * sizeof(sljit_sw)); - - /* buf[0] */ - put_label[0] = sljit_emit_put_label(compiler, SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - - /* buf[1] */ - put_label[1] = sljit_emit_put_label(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_uw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_uw)); - - sljit_set_put_label(put_label[0], &label[0]); - sljit_set_put_label(put_label[1], &label[0]); - - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)(buf + 2) - offs1); - put_label[0] = sljit_emit_put_label(compiler, SLJIT_MEM1(SLJIT_R0), offs1); - - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (offs1 + (sljit_sw)sizeof(sljit_uw)) >> 1); - put_label[1] = sljit_emit_put_label(compiler, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1); - - sljit_set_put_label(put_label[0], &label[1]); - sljit_set_put_label(put_label[1], &label[1]); - - /* buf[4] */ - put_label[0] = sljit_emit_put_label(compiler, SLJIT_R1, 0); - sljit_set_put_label(put_label[0], &label[2]); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_uw), SLJIT_R1, 0); - - /* buf[5] */ - put_label[0] = sljit_emit_put_label(compiler, SLJIT_R2, 0); - sljit_set_put_label(put_label[0], &label[3]); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_uw), SLJIT_R2, 0); - - /* buf[6] */ - put_label[0] = sljit_emit_put_label(compiler, SLJIT_R1, 0); - sljit_set_put_label(put_label[0], &label[4]); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_uw), SLJIT_R1, 0); - - /* buf[7] */ - put_label[0] = sljit_emit_put_label(compiler, SLJIT_RETURN_REG, 0); - sljit_set_put_label(put_label[0], &label[5]); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - SLJIT_ASSERT(SLJIT_FUNC_UADDR(code.code) >= malloc_addr && SLJIT_FUNC_UADDR(code.code) <= malloc_addr + 8); - - FAILED(code.func1((sljit_sw)&buf) != (sljit_sw)label[5].addr, "test64 case 1 failed\n"); - FAILED(buf[0] != label[0].addr, "test64 case 2 failed\n"); - FAILED(buf[1] != label[0].addr, "test64 case 3 failed\n"); - FAILED(buf[2] != label[1].addr, "test64 case 4 failed\n"); - FAILED(buf[3] != label[1].addr, "test64 case 5 failed\n"); - FAILED(buf[4] != label[2].addr, "test64 case 6 failed\n"); - FAILED(buf[5] != label[3].addr, "test64 case 7 failed\n"); - FAILED(buf[6] != label[4].addr, "test64 case 8 failed\n"); - - sljit_free_code(code.code, NULL); - - successful_tests++; -} - -static void test65(void) -{ - /* Test jump tables. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_s32 i; - /* Normally this table is allocated on the heap. */ - sljit_uw addr[64]; - struct sljit_label *labels[64]; - struct sljit_jump *jump; - - if (verbose) - printf("Run test65\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(W, W, W), 1, 2, 0, 0, 0); - - jump = sljit_emit_cmp(compiler, SLJIT_GREATER_EQUAL, SLJIT_S0, 0, SLJIT_IMM, 64); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)addr); - sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM2(SLJIT_R0, SLJIT_S0), SLJIT_WORD_SHIFT); - - for (i = 0; i < 64; i++) { - labels[i] = sljit_emit_label(compiler); - sljit_emit_op0(compiler, SLJIT_ENDBR); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, i * 2); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - } - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_IMM, -1); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - - for (i = 0; i < 64; i++) { - addr[i] = sljit_get_label_addr(labels[i]); - } - - sljit_free_compiler(compiler); - - FAILED(code.func2(64, 0) != -1, "test65 case 1 failed\n"); - - for (i = 0; i < 64; i++) { - FAILED(code.func2(i, i * 2) != i * 4, "test65 case 2 failed\n"); - } - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test66(void) -{ - /* Test direct jumps (computed goto). */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_s32 i; - sljit_uw addr[64]; - struct sljit_label *labels[64]; - - if (verbose) - printf("Run test66\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(W, W, W), 1, 2, 0, 0, 0); - sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_S0, 0); - - for (i = 0; i < 64; i++) { - labels[i] = sljit_emit_label(compiler); - sljit_emit_op0(compiler, SLJIT_ENDBR); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, i * 2); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - } - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - - for (i = 0; i < 64; i++) { - addr[i] = sljit_get_label_addr(labels[i]); - } - - sljit_free_compiler(compiler); - - for (i = 0; i < 64; i++) { - FAILED(code.func2((sljit_sw)addr[i], i) != i * 3, "test66 case 1 failed\n"); - } - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test67(void) -{ - /* Test skipping returns from fast calls (return type is fast). */ - executable_code code; - struct sljit_compiler *compiler = sljit_create_compiler(NULL, NULL); - struct sljit_jump *call, *jump; - struct sljit_label *label; - - if (verbose) - printf("Run test67\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 3, 1, 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - call = sljit_emit_jump(compiler, SLJIT_FAST_CALL); - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0); - - /* First function, never returns. */ - label = sljit_emit_label(compiler); - sljit_set_label(call, label); - sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R1, 0); - - call = sljit_emit_jump(compiler, SLJIT_FAST_CALL); - - /* Should never return here, marked by a segmentation fault if it does. */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - - /* Second function, skips the first function. */ - sljit_set_label(call, sljit_emit_label(compiler)); - sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R2, 0); - - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1); - - jump = sljit_emit_cmp(compiler, SLJIT_NOT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 1); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_R1, 0); - sljit_set_label(sljit_emit_jump(compiler, SLJIT_FAST_CALL), label); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op_src(compiler, SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN, SLJIT_S0, 0); - sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_S0, 0); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_op_src(compiler, SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN, SLJIT_R1, 0); - sljit_emit_op_src(compiler, SLJIT_FAST_RETURN, SLJIT_R1, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - - sljit_free_compiler(compiler); - - FAILED(code.func0() != 3, "test67 case 1 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test68(void) -{ - /* Test skipping returns from fast calls (return type is normal). */ - executable_code code; - struct sljit_compiler *compiler; - struct sljit_jump *call, *jump; - struct sljit_label *label; - int i; - - if (verbose) - printf("Run test68\n"); - - for (i = 0; i < 6; i++) { - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 2 + (i % 6), (i % 6), 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - call = sljit_emit_jump(compiler, SLJIT_FAST_CALL); - - /* Should never return here, marked by a segmentation fault if it does. */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - - /* Recursive fast call. */ - label = sljit_emit_label(compiler); - sljit_set_label(call, label); - sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, SLJIT_R1, 0); - - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1); - - jump = sljit_emit_cmp(compiler, SLJIT_GREATER_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 4); - - sljit_set_label(sljit_emit_jump(compiler, SLJIT_FAST_CALL), label); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - - sljit_free_compiler(compiler); - - if (SLJIT_UNLIKELY(code.func0() != 4)) { - printf("test68 case %d failed\n", i + 1); - return; - } - sljit_free_code(code.code, NULL); - } - - successful_tests++; -} - -static void test69(void) -{ - /* Test sljit_set_current_flags. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[8]; - sljit_s32 i; - - if (verbose) - printf("Run test69\n"); - - for (i = 0; i < 8; i++) - buf[i] = 4; - - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 3, 1, 0, 0, 0); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)1 << ((sizeof (sljit_sw) * 8) - 2)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_label(compiler); - sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW | SLJIT_CURRENT_FLAGS_ADD); - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_OVERFLOW); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 5); - sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_label(compiler); - sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW | SLJIT_CURRENT_FLAGS_ADD); - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_OVERFLOW); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_R1, 0); - sljit_emit_label(compiler); - sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW); - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_OVERFLOW); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 5); - sljit_emit_op2(compiler, SLJIT_MUL | SLJIT_SET_OVERFLOW, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R1, 0); - sljit_emit_label(compiler); - sljit_set_current_flags(compiler, SLJIT_SET_OVERFLOW); - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_OVERFLOW); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 6); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 5); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_R1, 0, SLJIT_R2, 0); - sljit_emit_label(compiler); - sljit_set_current_flags(compiler, SLJIT_SET_GREATER | SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE); - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_GREATER); - /* buf[5] */ - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R2, 0); - sljit_emit_label(compiler); - sljit_set_current_flags(compiler, SLJIT_SET_Z | SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE); - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_ZERO); - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(1u << 31)); - sljit_emit_op2u(compiler, SLJIT_ADD32 | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R1, 0); - sljit_emit_label(compiler); - sljit_set_current_flags(compiler, SLJIT_SET_Z | SLJIT_CURRENT_FLAGS_32 | SLJIT_CURRENT_FLAGS_ADD); - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_ZERO); - /* buf[7] */ - sljit_emit_op2u(compiler, SLJIT_SHL32 | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_IMM, 1); - sljit_emit_label(compiler); - sljit_set_current_flags(compiler, SLJIT_SET_Z | SLJIT_CURRENT_FLAGS_32); - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_NOT_ZERO); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - - FAILED(buf[0] != 1, "test69 case 1 failed\n"); - FAILED(buf[1] != 2, "test69 case 2 failed\n"); - FAILED(buf[2] != 1, "test69 case 3 failed\n"); - FAILED(buf[3] != 2, "test69 case 4 failed\n"); - FAILED(buf[4] != 1, "test69 case 5 failed\n"); - FAILED(buf[5] != 2, "test69 case 6 failed\n"); - FAILED(buf[6] != 1, "test69 case 7 failed\n"); - FAILED(buf[7] != 2, "test69 case 8 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test70(void) -{ - /* Test argument passing to sljit_emit_enter. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw wbuf[2]; - sljit_s32 ibuf[2]; - sljit_f64 dbuf[3]; - sljit_f32 fbuf[2]; - - if (verbose) - printf("Run test70\n"); - - wbuf[0] = 0; - wbuf[1] = 0; - ibuf[0] = 0; - ibuf[1] = 0; - - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, 32, W, 32, W), 1, 4, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&wbuf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_S3, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&ibuf); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_s32), SLJIT_S2, 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.test70_f1(-1478, 9476, 4928, -6832); - - FAILED(wbuf[0] != 9476, "test70 case 1 failed\n"); - FAILED(wbuf[1] != -6832, "test70 case 2 failed\n"); - FAILED(ibuf[0] != -1478, "test70 case 3 failed\n"); - FAILED(ibuf[1] != 4928, "test70 case 4 failed\n"); - - sljit_free_code(code.code, NULL); - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, 32, 32, W, W), 1, 4, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&wbuf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_S1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&ibuf); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S2, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_s32), SLJIT_S3, 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.test70_f2(4721, 7892, -3579, -4830); - - FAILED(wbuf[0] != 4721, "test70 case 5 failed\n"); - FAILED(wbuf[1] != 7892, "test70 case 6 failed\n"); - FAILED(ibuf[0] != -3579, "test70 case 7 failed\n"); - FAILED(ibuf[1] != -4830, "test70 case 8 failed\n"); - - sljit_free_code(code.code, NULL); - - if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - wbuf[0] = 0; - ibuf[0] = 0; - dbuf[0] = 0; - fbuf[0] = 0; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, 32, F32, W, F64), 2, 2, 2, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)&wbuf, SLJIT_S1, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM0(), (sljit_sw)&ibuf, SLJIT_S0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM0(), (sljit_sw)&dbuf, SLJIT_FR1, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM0(), (sljit_sw)&fbuf, SLJIT_FR0, 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.test70_f3(-6834, 674.5, 2789, -895.25); - - FAILED(wbuf[0] != 2789, "test70 case 9 failed\n"); - FAILED(ibuf[0] != -6834, "test70 case 10 failed\n"); - FAILED(dbuf[0] != -895.25, "test70 case 11 failed\n"); - FAILED(fbuf[0] != 674.5, "test70 case 12 failed\n"); - - ibuf[0] = 0; - dbuf[0] = 0; - fbuf[0] = 0; - fbuf[1] = 0; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, F32, F64, F32, 32), 1, 1, 3, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM0(), (sljit_sw)&ibuf, SLJIT_S0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM0(), (sljit_sw)&dbuf, SLJIT_FR1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&fbuf); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f32), SLJIT_FR2, 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.test70_f4(-4712.5, 5342.25, 2904.25, -4607); - - FAILED(ibuf[0] != -4607, "test70 case 13 failed\n"); - FAILED(dbuf[0] != 5342.25, "test70 case 14 failed\n"); - FAILED(fbuf[0] != -4712.5, "test70 case 15 failed\n"); - FAILED(fbuf[1] != 2904.25, "test70 case 16 failed\n"); - - ibuf[0] = 0; - dbuf[0] = 0; - fbuf[0] = 0; - fbuf[1] = 0; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, F64, F32, 32, F32), 1, 1, 3, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM0(), (sljit_sw)&ibuf, SLJIT_S0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM0(), (sljit_sw)&dbuf, SLJIT_FR0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&fbuf); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR1, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f32), SLJIT_FR2, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.test70_f5(3578.5, 4619.25, 6859, -1807.75); - - FAILED(ibuf[0] != 6859, "test70 case 17 failed\n"); - FAILED(dbuf[0] != 3578.5, "test70 case 18 failed\n"); - FAILED(fbuf[0] != 4619.25, "test70 case 19 failed\n"); - FAILED(fbuf[1] != -1807.75, "test70 case 20 failed\n"); - - ibuf[0] = 0; - dbuf[0] = 0; - dbuf[1] = 0; - fbuf[0] = 0; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, F64, 32, F32, F64), SLJIT_NUMBER_OF_SCRATCH_REGISTERS + 2, 1, 3, 0, 33); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM0(), (sljit_sw)&ibuf, SLJIT_S0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR2, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM0(), (sljit_sw)&fbuf, SLJIT_FR1, 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.test70_f6(2740.75, -2651, -7909.25, 3671.5); - - FAILED(ibuf[0] != -2651, "test70 case 21 failed\n"); - FAILED(dbuf[0] != 2740.75, "test70 case 22 failed\n"); - FAILED(dbuf[1] != 3671.5, "test70 case 23 failed\n"); - FAILED(fbuf[0] != -7909.25, "test70 case 24 failed\n"); - - wbuf[0] = 0; - ibuf[0] = 0; - ibuf[1] = 0; - fbuf[0] = 0; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, F32, 32, W, 32), 1, 3, 1, 0, 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)&wbuf, SLJIT_S1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&ibuf); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_s32), SLJIT_S2, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM0(), (sljit_sw)&fbuf, SLJIT_FR0, 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.test70_f7(-5219.25, -4530, 7214, 6741); - - FAILED(wbuf[0] != 7214, "test70 case 25 failed\n"); - FAILED(ibuf[0] != -4530, "test70 case 26 failed\n"); - FAILED(ibuf[1] != 6741, "test70 case 27 failed\n"); - FAILED(fbuf[0] != -5219.25, "test70 case 28 failed\n"); - - wbuf[0] = 0; - wbuf[1] = 0; - dbuf[0] = 0; - dbuf[1] = 0; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, F64, F64, W, W), 1, 5, 2, 0, SLJIT_MAX_LOCAL_SIZE - 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_S0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_SP), SLJIT_MAX_LOCAL_SIZE - 2 * sizeof(sljit_f64), SLJIT_FR0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&wbuf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_S1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR1, 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.test70_f8(-3749.75, 5280.5, 9134, -6506); - - FAILED(wbuf[0] != 9134, "test70 case 29 failed\n"); - FAILED(wbuf[1] != -6506, "test70 case 30 failed\n"); - FAILED(dbuf[0] != -3749.75, "test70 case 31 failed\n"); - FAILED(dbuf[1] != 5280.5, "test70 case 32 failed\n"); - - wbuf[0] = 0; - dbuf[0] = 0; - dbuf[1] = 0; - dbuf[2] = 0; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, F64, F64, W, F64), 1, 1, 3, 0, SLJIT_MAX_LOCAL_SIZE); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)&wbuf, SLJIT_S0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR1, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_f64), SLJIT_FR2, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.test70_f9(-6049.25, 7301.5, 4610, -4312.75); - - FAILED(wbuf[0] != 4610, "test70 case 33 failed\n"); - FAILED(dbuf[0] != -6049.25, "test70 case 34 failed\n"); - FAILED(dbuf[1] != 7301.5, "test70 case 35 failed\n"); - FAILED(dbuf[2] != -4312.75, "test70 case 36 failed\n"); - - ibuf[0] = 0; - dbuf[0] = 0; - dbuf[1] = 0; - dbuf[2] = 0; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, F64, F64, F64, 32), 1, 1, 3, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM0(), (sljit_sw)&ibuf, SLJIT_S0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR1, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_f64), SLJIT_FR2, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.test70_f10(4810.5, -9148.75, 8601.25, 6703); - - FAILED(ibuf[0] != 6703, "test70 case 37 failed\n"); - FAILED(dbuf[0] != 4810.5, "test70 case 38 failed\n"); - FAILED(dbuf[1] != -9148.75, "test70 case 39 failed\n"); - FAILED(dbuf[2] != 8601.25, "test70 case 40 failed\n"); - } - - successful_tests++; -} - -static sljit_sw test71_f1(sljit_sw a) -{ - return a + 10000; -} - -static sljit_sw test71_f2(sljit_sw a, sljit_s32 b, sljit_s32 c, sljit_sw d) -{ - return a | b | c | d; -} - -static sljit_sw test71_f3(sljit_sw a, sljit_s32 b, sljit_s32 c, sljit_sw d) -{ - SLJIT_UNUSED_ARG(a); - return b | c | d; -} - -static sljit_sw test71_f4(void) -{ - return 7461932; -} - -static sljit_sw test71_f5(sljit_f64 a, sljit_f64 b, sljit_f64 c, sljit_f64 d) -{ - if (a == 1345.5 && b == -8724.25 && c == 9034.75 && d == 6307.5) - return 8920567; - return 0; -} - -static sljit_sw test71_f6(sljit_f64 a, sljit_f64 b, sljit_f64 c, sljit_sw d) -{ - if (a == 4061.25 && b == -3291.75 && c == 8703.5 && d == 1706) - return 5074526; - return 0; -} - -static void test71(void) -{ - /* Test tail calls. */ - executable_code code; - struct sljit_compiler* compiler; - struct sljit_jump *jump; - sljit_uw jump_addr; - sljit_sw executable_offset; - sljit_sw wbuf[1]; - sljit_f64 dbuf[4]; - - if (verbose) - printf("Run test71\n"); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, W), 4, 4, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, -1); - sljit_emit_icall(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS1(W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(test71_f1)); - /* Should crash. */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func1(7987) != 17987, "test71 case 1 failed\n"); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, W), 1, 4, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, -1); - jump = sljit_emit_call(compiler, SLJIT_CALL | SLJIT_REWRITABLE_JUMP | SLJIT_CALL_RETURN, SLJIT_ARGS1(W, W)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - - sljit_set_target(jump, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - - executable_offset = sljit_get_executable_offset(compiler); - jump_addr = sljit_get_jump_addr(jump); - sljit_free_compiler(compiler); - - sljit_set_jump_addr(jump_addr, SLJIT_FUNC_UADDR(test71_f1), executable_offset); - - FAILED(code.func1(3903) != 13903, "test71 case 2 failed\n"); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 4, 2, 0, 0, SLJIT_MAX_LOCAL_SIZE); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test71_f2)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x28000000); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0x00140000); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, 0x00002800); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 0x00000041); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1); - sljit_emit_icall(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, W, 32, 32, W), SLJIT_MEM1(SLJIT_SP), 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func0() != 0x28142841, "test71 case 3 failed\n"); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 4, 4, 0, 0, SLJIT_MAX_LOCAL_SIZE); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test71_f2)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x81000000); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0x00480000); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, 0x00002100); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 0x00000014); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1); - sljit_emit_icall(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, W, 32, 32, W), SLJIT_S3, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func0() != (sljit_sw)0x81482114, "test71 case 4 failed\n"); - - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 4, 0, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, SLJIT_FUNC_ADDR(test71_f3)); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0x342); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, 0x451000); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 0x21000000); - sljit_emit_icall(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, W, 32, 32, W), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func0() != 0x21451342, "test71 case 5 failed\n"); - - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 1, 0, 0, 0, 9); - sljit_emit_icall(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS0(W), SLJIT_IMM, SLJIT_FUNC_ADDR(test71_f4)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.func0() != 7461932, "test71 case 6 failed\n"); - - sljit_free_code(code.code, NULL); - - if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - /* Next test. */ - - dbuf[0] = 9034.75; - dbuf[1] = 6307.5; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(W, F32, F64), 1, 1, 4, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf); - sljit_emit_fop1(compiler, SLJIT_CONV_F64_FROM_F32, SLJIT_FR0, 0, SLJIT_FR0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_R0), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64)); - sljit_emit_icall(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, F64, F64, F64, F64), SLJIT_IMM, SLJIT_FUNC_ADDR(test71_f5)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.test71_f1(1345.5, -8724.25) != 8920567, "test71 case 7 failed\n"); - - sljit_free_code(code.code, NULL); - - /* Next test. */ - - wbuf[0] = SLJIT_FUNC_ADDR(test71_f5); - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(W, F64, F64, F64, F64), 1, 0, 4, 0, 0); - sljit_emit_icall(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, F64, F64, F64, F64), SLJIT_MEM0(), (sljit_sw)wbuf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.test71_f2(1345.5, -8724.25, 9034.75, 6307.5) != 8920567, "test71 case 8 failed\n"); - - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(W, F64, F64, F64), 1, 0, 4, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1706); - jump = sljit_emit_call(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, F64, F64, F64, W)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - - sljit_set_target(jump, SLJIT_FUNC_UADDR(test71_f6)); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.test71_f3(4061.25, -3291.75, 8703.5) != 5074526, "test71 case 9 failed\n"); - - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(W, F64, F64, F64), SLJIT_NUMBER_OF_SCRATCH_REGISTERS + 1, 0, 4, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1706); - jump = sljit_emit_call(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, F64, F64, F64, W)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - - sljit_set_target(jump, SLJIT_FUNC_UADDR(test71_f6)); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.test71_f3(4061.25, -3291.75, 8703.5) != 5074526, "test71 case 10 failed\n"); - - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(W, F64, F64, F64), SLJIT_NUMBER_OF_SCRATCH_REGISTERS + 1, 1, 3, 0, SLJIT_MAX_LOCAL_SIZE); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1706); - jump = sljit_emit_call(compiler, SLJIT_CALL | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, F64, F64, F64, W)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - - sljit_set_target(jump, SLJIT_FUNC_UADDR(test71_f6)); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - FAILED(code.test71_f3(4061.25, -3291.75, 8703.5) != 5074526, "test71 case 11 failed\n"); - - sljit_free_code(code.code, NULL); - } - - successful_tests++; -} - -static void test72(void) -{ - /* Test using all fpu registers. */ - executable_code code; - struct sljit_compiler* compiler; - sljit_f64 buf[SLJIT_NUMBER_OF_FLOAT_REGISTERS]; - sljit_f64 buf2[2]; - struct sljit_jump *jump; - sljit_s32 i; - - if (verbose) - printf("Run test72\n"); - - if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - if (verbose) - printf("no fpu available, test72 skipped\n"); - successful_tests++; - return; - } - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - buf2[0] = 7.75; - buf2[1] = -8.25; - - for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++) - buf[i] = 0.0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P, P), 1, 2, SLJIT_NUMBER_OF_FLOAT_REGISTERS, 0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0); - for (i = 1; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++) - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_FR0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S1, 0); - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS1(VOID, W)); - - for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++) - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), i * (sljit_sw)sizeof(sljit_f64), SLJIT_FR(i), 0); - sljit_emit_return_void(compiler); - - /* Called function. */ - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 0, 1, SLJIT_NUMBER_OF_FLOAT_REGISTERS, 0, 0); - - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64)); - for (i = 1; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++) - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_FR0, 0); - - sljit_set_context(compiler, 0, SLJIT_ARGS1(VOID, P), 0, 1, SLJIT_NUMBER_OF_FLOAT_REGISTERS, 0, 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func2((sljit_sw)buf, (sljit_sw)buf2); - - for (i = 0; i < SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS; i++) { - FAILED(buf[i] != -8.25, "test72 case 1 failed\n"); - } - - for (i = SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++) { - FAILED(buf[i] != 7.75, "test72 case 2 failed\n"); - } - - sljit_free_code(code.code, NULL); - - /* Next test. */ - if (SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS >= 3) { - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - buf2[0] = -6.25; - buf2[1] = 3.75; - - for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++) - buf[i] = 0.0; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P, P), 1, 2, SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2, 1, SLJIT_MAX_LOCAL_SIZE); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FS0, 0, SLJIT_MEM1(SLJIT_S1), 0); - for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2; i++) - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_FS0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S1, 0); - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS1(VOID, W)); - - for (i = 0; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2; i++) - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), i * (sljit_sw)sizeof(sljit_f64), SLJIT_FR(i), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 1) * (sljit_sw)sizeof(sljit_f64), SLJIT_FS0, 0); - sljit_emit_return_void(compiler); - - /* Called function. */ - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 0, 1, SLJIT_NUMBER_OF_FLOAT_REGISTERS, 0, SLJIT_MAX_LOCAL_SIZE); - - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64)); - for (i = 1; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS; i++) - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR(i), 0, SLJIT_FR0, 0); - - sljit_set_context(compiler, 0, SLJIT_ARGS1(VOID, P), 0, 1, SLJIT_NUMBER_OF_FLOAT_REGISTERS, 0, SLJIT_MAX_LOCAL_SIZE); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func2((sljit_sw)buf, (sljit_sw)buf2); - - for (i = 0; i < SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS; i++) { - FAILED(buf[i] != 3.75, "test72 case 3 failed\n"); - } - - for (i = SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS; i < SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2; i++) { - FAILED(buf[i] != -6.25, "test72 case 4 failed\n"); - } - - FAILED(buf[SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2] != 0, "test72 case 5 failed\n"); - FAILED(buf[SLJIT_NUMBER_OF_FLOAT_REGISTERS - 1] != -6.25, "test72 case 6 failed\n"); - - sljit_free_code(code.code, NULL); - } - successful_tests++; -} - -static void test73(void) -{ - /* Test pasing arguments in registers. */ - executable_code code; - struct sljit_compiler* compiler; - sljit_sw wbuf[2]; - sljit_s32 ibuf[2]; - sljit_f64 dbuf[3]; - - if (verbose) - printf("Run test73\n"); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, 32_R, W, W_R, 32), 3, 2, 0, 0, 0); - /* wbuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&wbuf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_S0, 0); - /* wbuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_R2, 0); - /* ibuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&ibuf); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0); - /* ibuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_s32), SLJIT_S1, 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.test73_f1(3467, -6781, 5038, 6310); - - FAILED(wbuf[0] != -6781, "test73 case 1 failed\n"); - FAILED(wbuf[1] != 5038, "test73 case 2 failed\n"); - FAILED(ibuf[0] != 3467, "test73 case 3 failed\n"); - FAILED(ibuf[1] != 6310, "test73 case 4 failed\n"); - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, 32, W_R, W, 32_R), 4, 2, 0, 0, 8192); - /* wbuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&wbuf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_R1, 0); - /* wbuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_S1, 0); - /* ibuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&ibuf); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0); - /* ibuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_s32), SLJIT_R3, 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.test73_f1(-9723, 5208, 4761, 5084); - - FAILED(wbuf[0] != 5208, "test73 case 5 failed\n"); - FAILED(wbuf[1] != 4761, "test73 case 6 failed\n"); - FAILED(ibuf[0] != -9723, "test73 case 7 failed\n"); - FAILED(ibuf[1] != 5084, "test73 case 8 failed\n"); - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, 32_R, W_R, W_R, 32_R), 4, 1, 0, 0, SLJIT_MAX_LOCAL_SIZE); - /* wbuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&wbuf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0); - /* wbuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R2, 0); - /* ibuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&ibuf); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - /* ibuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_s32), SLJIT_R3, 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.test73_f1(5934, 6043, -8572, -3861); - - FAILED(wbuf[0] != 6043, "test73 case 9 failed\n"); - FAILED(wbuf[1] != -8572, "test73 case 10 failed\n"); - FAILED(ibuf[0] != 5934, "test73 case 11 failed\n"); - FAILED(ibuf[1] != -3861, "test73 case 12 failed\n"); - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, W_R, W_R, 32_R, 32_R), 4, 1, 0, 0, SLJIT_MAX_LOCAL_SIZE); - sljit_set_context(compiler, 0, SLJIT_ARGS4(VOID, W_R, W_R, 32_R, 32_R), 4, 1, 0, 0, SLJIT_MAX_LOCAL_SIZE); - /* wbuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&wbuf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - /* wbuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0); - /* ibuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&ibuf); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R2, 0); - /* ibuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_s32), SLJIT_R3, 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.test73_f2(6732, -5916, 2740, -3621); - - FAILED(wbuf[0] != 6732, "test73 case 13 failed\n"); - FAILED(wbuf[1] != -5916, "test73 case 14 failed\n"); - FAILED(ibuf[0] != 2740, "test73 case 15 failed\n"); - FAILED(ibuf[1] != -3621, "test73 case 16 failed\n"); - sljit_free_code(code.code, NULL); - - if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, F64, F64, F64, W_R), 1, 0, 3, 0, SLJIT_MAX_LOCAL_SIZE); - /* wbuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)&wbuf, SLJIT_R0, 0); - /* dbuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR0, 0); - /* dbuf[1] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR1, 0); - /* dbuf[2] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_f64), SLJIT_FR2, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.test73_f3(7390.25, -8045.5, 1390.75, 8201); - - FAILED(wbuf[0] != 8201, "test73 case 17 failed\n"); - FAILED(dbuf[0] != 7390.25, "test73 case 18 failed\n"); - FAILED(dbuf[1] != -8045.5, "test73 case 19 failed\n"); - FAILED(dbuf[2] != 1390.75, "test73 case 20 failed\n"); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS4(VOID, F64, F64, W, W_R), 2, 1, 2, 0, SLJIT_MAX_LOCAL_SIZE); - /* wbuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&wbuf); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0); - /* wbuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_R1, 0); - /* dbuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR0, 0); - /* dbuf[1] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR1, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.test73_f4(4892.75, -3702.5, 4731, 8530); - - FAILED(wbuf[0] != 4731, "test73 case 21 failed\n"); - FAILED(wbuf[1] != 8530, "test73 case 22 failed\n"); - FAILED(dbuf[0] != 4892.75, "test73 case 23 failed\n"); - FAILED(dbuf[1] != -3702.5, "test73 case 24 failed\n"); - } - - successful_tests++; -} - -static void test74(void) -{ - /* Test carry flag. */ - executable_code code; - struct sljit_compiler* compiler; - sljit_sw wbuf[15]; - sljit_s32 i; - - if (verbose) - printf("Run test74\n"); - - for (i = 0; i < 15; i++) - wbuf[i] = -1; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, W), 3, 2, 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); - sljit_emit_op2u(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_CARRY); - /* wbuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R1, 0); - cond_set(compiler, SLJIT_R1, 0, SLJIT_CARRY); - /* wbuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2); - sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -1); - sljit_set_current_flags(compiler, SLJIT_SET_CARRY | SLJIT_CURRENT_FLAGS_ADD); - /* wbuf[2] */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_NOT_CARRY); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op2(compiler, SLJIT_SHL32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 31); - sljit_emit_op2u(compiler, SLJIT_ADD32 | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0); - cond_set(compiler, SLJIT_R1, 0, SLJIT_CARRY); - /* wbuf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 5); - sljit_emit_op2(compiler, SLJIT_ADD32 | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 5); - cond_set(compiler, SLJIT_R1, 0, SLJIT_CARRY); - /* wbuf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1); - cond_set(compiler, SLJIT_R1, 0, SLJIT_CARRY); - /* wbuf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op2u(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1); - cond_set(compiler, SLJIT_R1, 0, SLJIT_NOT_CARRY); - /* wbuf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1); - /* wbuf[7] */ - cond_set(compiler, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_CARRY); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op2u(compiler, SLJIT_SUB32 | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_set_current_flags(compiler, SLJIT_SET_CARRY | SLJIT_CURRENT_FLAGS_32 | SLJIT_CURRENT_FLAGS_SUB); - cond_set(compiler, SLJIT_R1, 0, SLJIT_NOT_CARRY); - /* wbuf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op2(compiler, SLJIT_SHL32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 31); - sljit_emit_op2(compiler, SLJIT_SUB32, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op2(compiler, SLJIT_SUB32 | SLJIT_SET_CARRY, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R0, 0); - cond_set(compiler, SLJIT_R1, 0, SLJIT_NOT_CARRY); - /* wbuf[9] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, -2); - cond_set(compiler, SLJIT_R1, 0, SLJIT_NOT_CARRY); - /* wbuf[10] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op2(compiler, SLJIT_ADDC | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R0, 0); - cond_set(compiler, SLJIT_R1, 0, SLJIT_CARRY); - /* wbuf[11] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op2(compiler, SLJIT_SHL32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 31); - sljit_emit_op2(compiler, SLJIT_ADD32 | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op2(compiler, SLJIT_ADDC32 | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R0, 0); - cond_set(compiler, SLJIT_R1, 0, SLJIT_CARRY); - /* wbuf[12] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op2(compiler, SLJIT_SUB | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op2(compiler, SLJIT_SUBC | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1); - cond_set(compiler, SLJIT_R1, 0, SLJIT_CARRY); - /* wbuf[13] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op2(compiler, SLJIT_SUB32 | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op2(compiler, SLJIT_SUBC32 | SLJIT_SET_CARRY, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 1); - cond_set(compiler, SLJIT_R1, 0, SLJIT_NOT_CARRY); - /* wbuf[14] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&wbuf); - - FAILED(wbuf[0] != 1, "test74 case 1 failed\n"); - FAILED(wbuf[1] != 1, "test74 case 2 failed\n"); - FAILED(wbuf[2] != 2, "test74 case 3 failed\n"); - FAILED(wbuf[3] != 1, "test74 case 4 failed\n"); - FAILED(wbuf[4] != 2, "test74 case 5 failed\n"); - FAILED(wbuf[5] != 1, "test74 case 6 failed\n"); - FAILED(wbuf[6] != 1, "test74 case 7 failed\n"); - FAILED(wbuf[7] != 1, "test74 case 8 failed\n"); - FAILED(wbuf[8] != 2, "test74 case 9 failed\n"); - FAILED(wbuf[9] != 2, "test74 case 10 failed\n"); - FAILED(wbuf[10] != 1, "test74 case 11 failed\n"); - FAILED(wbuf[11] != 2, "test74 case 12 failed\n"); - FAILED(wbuf[12] != 1, "test74 case 13 failed\n"); - FAILED(wbuf[13] != 1, "test74 case 14 failed\n"); - FAILED(wbuf[14] != 1, "test74 case 15 failed\n"); - - successful_tests++; -} - -static void test75_set(struct sljit_compiler *compiler, sljit_s32 compare, sljit_s32 type, sljit_s32 left_fr, sljit_s32 right_fr) -{ - /* Testing both sljit_emit_op_flags and sljit_emit_jump. */ - struct sljit_jump* jump1; - struct sljit_jump* jump2; - sljit_s32 is_ordered; - - if (sljit_cmp_info(type)) { - sljit_emit_fop1(compiler, compare | SLJIT_SET(type & 0xfe), left_fr, 0, right_fr, 0); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R0, 0, type); - jump1 = sljit_emit_jump(compiler, type); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2); - sljit_set_label(jump1, sljit_emit_label(compiler)); - } else { - if (type < SLJIT_UNORDERED_OR_EQUAL) { - is_ordered = (type & 0x1) ^ 0x1; - type += SLJIT_UNORDERED_OR_EQUAL - SLJIT_ORDERED_EQUAL; - } else { - is_ordered = type & 0x1; - type -= SLJIT_UNORDERED_OR_EQUAL - SLJIT_ORDERED_EQUAL; - } - SLJIT_ASSERT(sljit_cmp_info(type) && sljit_cmp_info(SLJIT_UNORDERED) && sljit_cmp_info(SLJIT_ORDERED)); - - sljit_emit_fop1(compiler, compare | SLJIT_SET(type & 0xfe), left_fr, 0, right_fr, 0); - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R0, 0, type); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0); - - if (is_ordered) { - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_ORDERED); - - jump1 = sljit_emit_jump(compiler, SLJIT_UNORDERED); - jump2 = sljit_emit_jump(compiler, type); - sljit_set_label(jump1, sljit_emit_label(compiler)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2); - sljit_set_label(jump2, sljit_emit_label(compiler)); - - sljit_emit_op2(compiler, SLJIT_AND, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0); - } else { - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_UNORDERED); - - jump1 = sljit_emit_jump(compiler, SLJIT_UNORDERED); - jump2 = sljit_emit_jump(compiler, type); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2); - sljit_set_label(jump1, sljit_emit_label(compiler)); - sljit_set_label(jump2, sljit_emit_label(compiler)); - - sljit_emit_op2(compiler, SLJIT_OR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R1, 0); - } - - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R2, 0); - } - - sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_s8)); -} - -static void test75(void) -{ - /* Test floating point comparison. */ - executable_code code; - struct sljit_compiler* compiler; - sljit_s8 bbuf[96]; - sljit_s32 i; - - union { - sljit_f64 value; - struct { - sljit_s32 value1; - sljit_s32 value2; - } u; - } dbuf[3]; - - union { - sljit_f32 value; - sljit_s32 value1; - } sbuf[3]; - - if (verbose) - printf("Run test75\n"); - - if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - if (verbose) - printf("no fpu available, test75 skipped\n"); - successful_tests++; - return; - } - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - dbuf[0].u.value1 = 0x7fffffff; - dbuf[0].u.value2 = 0x7fffffff; - dbuf[1].value = -13.0; - dbuf[2].value = 27.0; - - sbuf[0].value1 = 0x7fffffff; - sbuf[1].value = -13.0; - sbuf[2].value = 27.0; - - for (i = 0; i < 96; i++) - bbuf[i] = -3; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(VOID, P, P, P), 3, 3, 6, 0, 0); - - i = SLJIT_CMP_F64; - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S1), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64)); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64)); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR4, 0, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f64)); - - while (1) { - /* bbuf[0] and bbuf[48] */ - test75_set(compiler, i, SLJIT_ORDERED_EQUAL, SLJIT_FR2, SLJIT_FR3); - /* bbuf[1] and bbuf[49] */ - test75_set(compiler, i, SLJIT_ORDERED_EQUAL, SLJIT_FR2, SLJIT_FR4); - /* bbuf[2] and bbuf[50] */ - test75_set(compiler, i, SLJIT_ORDERED_EQUAL, SLJIT_FR0, SLJIT_FR1); - /* bbuf[3] and bbuf[51] */ - test75_set(compiler, i, SLJIT_ORDERED_EQUAL, SLJIT_FR0, SLJIT_FR2); - - /* bbuf[4] and bbuf[52] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_NOT_EQUAL, SLJIT_FR2, SLJIT_FR3); - /* bbuf[5] and bbuf[53] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_NOT_EQUAL, SLJIT_FR2, SLJIT_FR4); - /* bbuf[6] and bbuf[54] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_NOT_EQUAL, SLJIT_FR0, SLJIT_FR1); - /* bbuf[7] and bbuf[55] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_NOT_EQUAL, SLJIT_FR0, SLJIT_FR2); - - /* bbuf[8] and bbuf[56] */ - test75_set(compiler, i, SLJIT_ORDERED_LESS, SLJIT_FR2, SLJIT_FR3); - /* bbuf[9] and bbuf[57] */ - test75_set(compiler, i, SLJIT_ORDERED_LESS, SLJIT_FR2, SLJIT_FR4); - /* bbuf[10] and bbuf[58] */ - test75_set(compiler, i, SLJIT_ORDERED_LESS, SLJIT_FR0, SLJIT_FR1); - /* bbuf[11] and bbuf[59] */ - test75_set(compiler, i, SLJIT_ORDERED_LESS, SLJIT_FR0, SLJIT_FR2); - - /* bbuf[12] and bbuf[60] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_GREATER_EQUAL, SLJIT_FR2, SLJIT_FR4); - /* bbuf[13] and bbuf[61] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_GREATER_EQUAL, SLJIT_FR4, SLJIT_FR2); - /* bbuf[14] and bbuf[62] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_GREATER_EQUAL, SLJIT_FR0, SLJIT_FR1); - /* bbuf[15] and bbuf[63] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_GREATER_EQUAL, SLJIT_FR0, SLJIT_FR2); - - /* bbuf[16] and bbuf[64] */ - test75_set(compiler, i, SLJIT_ORDERED_GREATER, SLJIT_FR2, SLJIT_FR4); - /* bbuf[17] and bbuf[65] */ - test75_set(compiler, i, SLJIT_ORDERED_GREATER, SLJIT_FR4, SLJIT_FR2); - /* bbuf[18] and bbuf[66] */ - test75_set(compiler, i, SLJIT_ORDERED_GREATER, SLJIT_FR0, SLJIT_FR1); - /* bbuf[19] and bbuf[67] */ - test75_set(compiler, i, SLJIT_ORDERED_GREATER, SLJIT_FR0, SLJIT_FR2); - - /* bbuf[20] and bbuf[68] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_LESS_EQUAL, SLJIT_FR2, SLJIT_FR4); - /* bbuf[21] and bbuf[69] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_LESS_EQUAL, SLJIT_FR4, SLJIT_FR2); - /* bbuf[22] and bbuf[70] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_LESS_EQUAL, SLJIT_FR0, SLJIT_FR1); - /* bbuf[23] and bbuf[71] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_LESS_EQUAL, SLJIT_FR0, SLJIT_FR2); - - /* bbuf[24] and bbuf[72] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_EQUAL, SLJIT_FR2, SLJIT_FR4); - /* bbuf[25] and bbuf[73] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_EQUAL, SLJIT_FR2, SLJIT_FR3); - /* bbuf[26] and bbuf[74] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_EQUAL, SLJIT_FR0, SLJIT_FR1); - /* bbuf[27] and bbuf[75] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_EQUAL, SLJIT_FR0, SLJIT_FR2); - - /* bbuf[28] and bbuf[76] */ - test75_set(compiler, i, SLJIT_ORDERED_NOT_EQUAL, SLJIT_FR2, SLJIT_FR3); - /* bbuf[29] and bbuf[77] */ - test75_set(compiler, i, SLJIT_ORDERED_NOT_EQUAL, SLJIT_FR2, SLJIT_FR4); - /* bbuf[30] and bbuf[78] */ - test75_set(compiler, i, SLJIT_ORDERED_NOT_EQUAL, SLJIT_FR0, SLJIT_FR1); - /* bbuf[31] and bbuf[79] */ - test75_set(compiler, i, SLJIT_ORDERED_NOT_EQUAL, SLJIT_FR0, SLJIT_FR2); - - /* bbuf[32] and bbuf[80] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_LESS, SLJIT_FR2, SLJIT_FR4); - /* bbuf[33] and bbuf[81] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_LESS, SLJIT_FR2, SLJIT_FR3); - /* bbuf[34] and bbuf[82] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_LESS, SLJIT_FR0, SLJIT_FR1); - /* bbuf[35] and bbuf[83] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_LESS, SLJIT_FR0, SLJIT_FR2); - - /* bbuf[36] and bbuf[84] */ - test75_set(compiler, i, SLJIT_ORDERED_GREATER_EQUAL, SLJIT_FR2, SLJIT_FR4); - /* bbuf[37] and bbuf[85] */ - test75_set(compiler, i, SLJIT_ORDERED_GREATER_EQUAL, SLJIT_FR4, SLJIT_FR2); - /* bbuf[38] and bbuf[86] */ - test75_set(compiler, i, SLJIT_ORDERED_GREATER_EQUAL, SLJIT_FR0, SLJIT_FR1); - /* bbuf[39] and bbuf[87] */ - test75_set(compiler, i, SLJIT_ORDERED_GREATER_EQUAL, SLJIT_FR0, SLJIT_FR2); - - /* bbuf[40] and bbuf[88] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_GREATER, SLJIT_FR2, SLJIT_FR4); - /* bbuf[41] and bbuf[89] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_GREATER, SLJIT_FR4, SLJIT_FR2); - /* bbuf[42] and bbuf[90] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_GREATER, SLJIT_FR0, SLJIT_FR1); - /* bbuf[43] and bbuf[91] */ - test75_set(compiler, i, SLJIT_UNORDERED_OR_GREATER, SLJIT_FR0, SLJIT_FR2); - - /* bbuf[44] and bbuf[92] */ - test75_set(compiler, i, SLJIT_ORDERED_LESS_EQUAL, SLJIT_FR2, SLJIT_FR3); - /* bbuf[45] and bbuf[93] */ - test75_set(compiler, i, SLJIT_ORDERED_LESS_EQUAL, SLJIT_FR4, SLJIT_FR2); - /* bbuf[46] and bbuf[94] */ - test75_set(compiler, i, SLJIT_ORDERED_LESS_EQUAL, SLJIT_FR0, SLJIT_FR1); - /* bbuf[47] and bbuf[95] */ - test75_set(compiler, i, SLJIT_ORDERED_LESS_EQUAL, SLJIT_FR0, SLJIT_FR2); - - if (i == SLJIT_CMP_F32) - break; - - i = SLJIT_CMP_F32; - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S2), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S2), 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR3, 0, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR4, 0, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_f32)); - } - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func3((sljit_sw)&bbuf, (sljit_sw)&dbuf, (sljit_sw)&sbuf); - - /* SLJIT_CMP_F64 */ - FAILED(bbuf[0] != 1, "test75 case 1 failed\n"); - FAILED(bbuf[1] != 2, "test75 case 2 failed\n"); - FAILED(bbuf[2] != 2, "test75 case 3 failed\n"); - FAILED(bbuf[3] != 2, "test75 case 4 failed\n"); - - FAILED(bbuf[4] != 2, "test75 case 5 failed\n"); - FAILED(bbuf[5] != 1, "test75 case 6 failed\n"); - FAILED(bbuf[6] != 1, "test75 case 7 failed\n"); - FAILED(bbuf[7] != 1, "test75 case 8 failed\n"); - - FAILED(bbuf[8] != 2, "test75 case 9 failed\n"); - FAILED(bbuf[9] != 1, "test75 case 10 failed\n"); - FAILED(bbuf[10] != 2, "test75 case 11 failed\n"); - FAILED(bbuf[11] != 2, "test75 case 12 failed\n"); - - FAILED(bbuf[12] != 2, "test75 case 13 failed\n"); - FAILED(bbuf[13] != 1, "test75 case 14 failed\n"); - FAILED(bbuf[14] != 1, "test75 case 15 failed\n"); - FAILED(bbuf[15] != 1, "test75 case 16 failed\n"); - - FAILED(bbuf[16] != 2, "test75 case 17 failed\n"); - FAILED(bbuf[17] != 1, "test75 case 18 failed\n"); - FAILED(bbuf[18] != 2, "test75 case 19 failed\n"); - FAILED(bbuf[19] != 2, "test75 case 20 failed\n"); - - FAILED(bbuf[20] != 1, "test75 case 21 failed\n"); - FAILED(bbuf[21] != 2, "test75 case 22 failed\n"); - FAILED(bbuf[22] != 1, "test75 case 23 failed\n"); - FAILED(bbuf[23] != 1, "test75 case 24 failed\n"); - - FAILED(bbuf[24] != 2, "test75 case 25 failed\n"); - FAILED(bbuf[25] != 1, "test75 case 26 failed\n"); - FAILED(bbuf[26] != 1, "test75 case 27 failed\n"); - FAILED(bbuf[27] != 1, "test75 case 28 failed\n"); - - FAILED(bbuf[28] != 2, "test75 case 29 failed\n"); - FAILED(bbuf[29] != 1, "test75 case 30 failed\n"); - FAILED(bbuf[30] != 2, "test75 case 31 failed\n"); - FAILED(bbuf[31] != 2, "test75 case 32 failed\n"); - - FAILED(bbuf[32] != 1, "test75 case 33 failed\n"); - FAILED(bbuf[33] != 2, "test75 case 34 failed\n"); - FAILED(bbuf[34] != 1, "test75 case 35 failed\n"); - FAILED(bbuf[35] != 1, "test75 case 36 failed\n"); - - FAILED(bbuf[36] != 2, "test75 case 37 failed\n"); - FAILED(bbuf[37] != 1, "test75 case 38 failed\n"); - FAILED(bbuf[38] != 2, "test75 case 39 failed\n"); - FAILED(bbuf[39] != 2, "test75 case 40 failed\n"); - - FAILED(bbuf[40] != 2, "test75 case 41 failed\n"); - FAILED(bbuf[41] != 1, "test75 case 42 failed\n"); - FAILED(bbuf[42] != 1, "test75 case 43 failed\n"); - FAILED(bbuf[43] != 1, "test75 case 44 failed\n"); - - FAILED(bbuf[44] != 1, "test75 case 45 failed\n"); - FAILED(bbuf[45] != 2, "test75 case 46 failed\n"); - FAILED(bbuf[46] != 2, "test75 case 47 failed\n"); - FAILED(bbuf[47] != 2, "test75 case 48 failed\n"); - - /* SLJIT_CMP_F32 */ - FAILED(bbuf[48] != 1, "test75 case 49 failed\n"); - FAILED(bbuf[49] != 2, "test75 case 50 failed\n"); - FAILED(bbuf[50] != 2, "test75 case 51 failed\n"); - FAILED(bbuf[51] != 2, "test75 case 52 failed\n"); - - FAILED(bbuf[52] != 2, "test75 case 53 failed\n"); - FAILED(bbuf[53] != 1, "test75 case 54 failed\n"); - FAILED(bbuf[54] != 1, "test75 case 55 failed\n"); - FAILED(bbuf[55] != 1, "test75 case 56 failed\n"); - - FAILED(bbuf[56] != 2, "test75 case 57 failed\n"); - FAILED(bbuf[57] != 1, "test75 case 58 failed\n"); - FAILED(bbuf[58] != 2, "test75 case 59 failed\n"); - FAILED(bbuf[59] != 2, "test75 case 60 failed\n"); - - FAILED(bbuf[60] != 2, "test75 case 61 failed\n"); - FAILED(bbuf[61] != 1, "test75 case 62 failed\n"); - FAILED(bbuf[62] != 1, "test75 case 63 failed\n"); - FAILED(bbuf[63] != 1, "test75 case 64 failed\n"); - - FAILED(bbuf[64] != 2, "test75 case 65 failed\n"); - FAILED(bbuf[65] != 1, "test75 case 66 failed\n"); - FAILED(bbuf[66] != 2, "test75 case 67 failed\n"); - FAILED(bbuf[67] != 2, "test75 case 68 failed\n"); - - FAILED(bbuf[68] != 1, "test75 case 69 failed\n"); - FAILED(bbuf[69] != 2, "test75 case 70 failed\n"); - FAILED(bbuf[70] != 1, "test75 case 71 failed\n"); - FAILED(bbuf[71] != 1, "test75 case 72 failed\n"); - - FAILED(bbuf[72] != 2, "test75 case 73 failed\n"); - FAILED(bbuf[73] != 1, "test75 case 74 failed\n"); - FAILED(bbuf[74] != 1, "test75 case 75 failed\n"); - FAILED(bbuf[75] != 1, "test75 case 76 failed\n"); - - FAILED(bbuf[76] != 2, "test75 case 77 failed\n"); - FAILED(bbuf[77] != 1, "test75 case 78 failed\n"); - FAILED(bbuf[78] != 2, "test75 case 79 failed\n"); - FAILED(bbuf[79] != 2, "test75 case 80 failed\n"); - - FAILED(bbuf[80] != 1, "test75 case 81 failed\n"); - FAILED(bbuf[81] != 2, "test75 case 82 failed\n"); - FAILED(bbuf[82] != 1, "test75 case 83 failed\n"); - FAILED(bbuf[83] != 1, "test75 case 84 failed\n"); - - FAILED(bbuf[84] != 2, "test75 case 85 failed\n"); - FAILED(bbuf[85] != 1, "test75 case 86 failed\n"); - FAILED(bbuf[86] != 2, "test75 case 87 failed\n"); - FAILED(bbuf[87] != 2, "test75 case 88 failed\n"); - - FAILED(bbuf[88] != 2, "test75 case 89 failed\n"); - FAILED(bbuf[89] != 1, "test75 case 90 failed\n"); - FAILED(bbuf[90] != 1, "test75 case 91 failed\n"); - FAILED(bbuf[91] != 1, "test75 case 92 failed\n"); - - FAILED(bbuf[92] != 1, "test75 case 93 failed\n"); - FAILED(bbuf[93] != 2, "test75 case 94 failed\n"); - FAILED(bbuf[94] != 2, "test75 case 95 failed\n"); - FAILED(bbuf[95] != 2, "test75 case 96 failed\n"); - - successful_tests++; -} - -static void test76(void) -{ - /* Test register argument and keep saved registers. */ - executable_code code; - struct sljit_compiler* compiler; - struct sljit_jump* jump; - sljit_sw buf[9]; - sljit_f64 dbuf[3]; - sljit_s32 i; - - if (verbose) - printf("Run test76\n"); - - for (i = 0; i < 9; i++) - buf[i] = -1; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 4, 2, 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 7945); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -9267); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 4309); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -8321); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 6803); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -5497); - - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4(W, W, W, W, W)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_S0, 0); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S1, 0); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS4(W, W_R, W_R, W_R, W_R), 4, 2, 0, 0, 32); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&buf); - /* buf[3-6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R3, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 6028); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 4982); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1289); - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - - FAILED(buf[0] != 6028, "test76 case 1 failed\n"); - FAILED(buf[1] != 6803, "test76 case 2 failed\n"); - FAILED(buf[2] != -5497, "test76 case 3 failed\n"); - FAILED(buf[3] != 7945, "test76 case 4 failed\n"); - FAILED(buf[4] != -9267, "test76 case 5 failed\n"); - FAILED(buf[5] != 4309, "test76 case 6 failed\n"); - FAILED(buf[6] != -8321, "test76 case 7 failed\n"); - - /* Next test. */ - - for (i = 0; i < 9; i++) - buf[i] = -1; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 4, 2, 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -2608); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 4751); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 5740); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -9704); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -8749); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 9213); - - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4(W, W, W, W, W)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_S0, 0); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S1, 0); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(1), SLJIT_ARGS4(W, W_R, W_R, W_R, W_R), 6, 2, 0, 0, SLJIT_MAX_LOCAL_SIZE); - sljit_set_context(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(1), SLJIT_ARGS4(W, W_R, W_R, W_R, W_R), 6, 2, 0, 0, SLJIT_MAX_LOCAL_SIZE); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)&buf); - /* buf[3-7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_sw), SLJIT_S0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_sw), SLJIT_R2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 7 * sizeof(sljit_sw), SLJIT_R3, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -7351); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 3628); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 0); - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - - FAILED(buf[0] != -7351, "test76 case 8 failed\n"); - FAILED(buf[1] != 3628, "test76 case 9 failed\n"); - FAILED(buf[2] != 9213, "test76 case 10 failed\n"); - FAILED(buf[3] != -8749, "test76 case 11 failed\n"); - FAILED(buf[4] != -2608, "test76 case 12 failed\n"); - FAILED(buf[5] != 4751, "test76 case 13 failed\n"); - FAILED(buf[6] != 5740, "test76 case 14 failed\n"); - FAILED(buf[7] != -9704, "test76 case 15 failed\n"); - FAILED(buf[8] != -1, "test76 case 16 failed\n"); - - /* Next test. */ - - for (i = 0; i < 9; i++) - buf[i] = -1; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 4, 2, 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8653); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 7245); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -3610); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 4591); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -2865); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 2510); - - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4(VOID, W, W, W, W)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_S1, 0); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(2), SLJIT_ARGS4(W, W_R, W_R, W_R, W_R), 4, 3, 0, 0, SLJIT_MAX_LOCAL_SIZE); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, (sljit_sw)&buf); - /* buf[2-7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 2 * sizeof(sljit_sw), SLJIT_S0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 3 * sizeof(sljit_sw), SLJIT_S1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 4 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 5 * sizeof(sljit_sw), SLJIT_R1, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 6 * sizeof(sljit_sw), SLJIT_R2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 7 * sizeof(sljit_sw), SLJIT_R3, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 5789); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -9214); - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - - FAILED(buf[0] != 5789, "test76 case 17 failed\n"); - FAILED(buf[1] != -9214, "test76 case 18 failed\n"); - FAILED(buf[2] != -2865, "test76 case 19 failed\n"); - FAILED(buf[3] != 2510, "test76 case 20 failed\n"); - FAILED(buf[4] != 8653, "test76 case 21 failed\n"); - FAILED(buf[5] != 7245, "test76 case 22 failed\n"); - FAILED(buf[6] != -3610, "test76 case 23 failed\n"); - FAILED(buf[7] != 4591, "test76 case 24 failed\n"); - FAILED(buf[8] != -1, "test76 case 25 failed\n"); - - /* Next test. */ - - for (i = 0; i < 9; i++) - buf[i] = -1; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 2, 3, 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 6071); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -3817); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 9250); - - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS0(W)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_S0, 0); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S1, 0); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 3 * sizeof(sljit_sw), SLJIT_S2, 0); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(2), SLJIT_ARGS0(W), 4, 3, 0, 0, SLJIT_MAX_LOCAL_SIZE); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_sw), SLJIT_S0, 0); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 5 * sizeof(sljit_sw), SLJIT_S1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -6278); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 1467); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 7150 - 1467); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 8413); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 4892); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -7513); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1); - - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, W, W, W, W)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS4(W, W_R, W_R, W_R, W_R), 4, 2, 0, 0, 256); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, (sljit_sw)&buf); - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_R1, 0); - /* buf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R2, 0); - /* buf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R3, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_IMM, 6923); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - - FAILED(buf[0] != 6923, "test76 case 26 failed\n"); - FAILED(buf[1] != 4892, "test76 case 27 failed\n"); - FAILED(buf[2] != -7513, "test76 case 28 failed\n"); - FAILED(buf[3] != 9250, "test76 case 29 failed\n"); - FAILED(buf[4] != 6071, "test76 case 30 failed\n"); - FAILED(buf[5] != -3817, "test76 case 31 failed\n"); - FAILED(buf[6] != -6278, "test76 case 32 failed\n"); - FAILED(buf[7] != 7150, "test76 case 33 failed\n"); - FAILED(buf[8] != 8413, "test76 case 34 failed\n"); - - if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - /* Next test. */ - - for (i = 0; i < 9; i++) - buf[i] = -1; - - dbuf[0] = 4061.25; - dbuf[1] = -3291.75; - dbuf[2] = 8703.5; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 2, 3, 3, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&dbuf); - /* dbuf[0] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_R1), 0); - /* dbuf[1] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_f64)); - /* dbuf[2] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_f64)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1706); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -8956); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 4381); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -5314); - - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4(W, F64, F64, F64, W)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_S0, 0); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S1, 0); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 3 * sizeof(sljit_sw), SLJIT_S2, 0); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(1), SLJIT_ARGS4(W, F64, F64, F64, W_R), 1, 3, 3, 0, SLJIT_MAX_LOCAL_SIZE); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)&buf); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_sw), SLJIT_S0, 0); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)&dbuf); - /* dbuf[0] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_FR2, 0); - /* dbuf[1] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f64), SLJIT_FR0, 0); - /* dbuf[2] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f64), SLJIT_FR1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2784); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 1503); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1); - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_R0, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - - FAILED(buf[0] != 2784, "test76 case 35 failed\n"); - FAILED(buf[1] != 1503, "test76 case 36 failed\n"); - FAILED(buf[2] != 4381, "test76 case 37 failed\n"); - FAILED(buf[3] != -5314, "test76 case 38 failed\n"); - FAILED(buf[4] != -8956, "test76 case 39 failed\n"); - FAILED(buf[5] != 1706, "test76 case 40 failed\n"); - FAILED(buf[6] != -1, "test76 case 41 failed\n"); - FAILED(dbuf[0] != 8703.5, "test76 case 42 failed\n"); - FAILED(dbuf[1] != 4061.25, "test76 case 43 failed\n"); - FAILED(dbuf[2] != -3291.75, "test76 case 44 failed\n"); - - /* Next test. */ - - for (i = 0; i < 9; i++) - buf[i] = -1; - - dbuf[0] = 4061.25; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 3, 3, 1, 0, 0); - - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM0(), (sljit_sw)&dbuf); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8793); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -4027); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 2910); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 4619); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -1502); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 5316); - - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4(VOID, F64, W, W, W)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_S0, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_S1, 0); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_sw), SLJIT_S2, 0); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(2), SLJIT_ARGS4(VOID, F64, W_R, W_R, W_R), 3, 3, 3, 0, SLJIT_MAX_LOCAL_SIZE); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, (sljit_sw)&buf); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 3 * sizeof(sljit_sw), SLJIT_S0, 0); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 4 * sizeof(sljit_sw), SLJIT_S1, 0); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 5 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 6 * sizeof(sljit_sw), SLJIT_R1, 0); - /* buf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), 7 * sizeof(sljit_sw), SLJIT_R2, 0); - - sljit_emit_fop1(compiler, SLJIT_NEG_F64, SLJIT_MEM0(), (sljit_sw)&dbuf, SLJIT_FR0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 7839); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -9215); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - - FAILED(buf[0] != 7839, "test76 case 45 failed\n"); - FAILED(buf[1] != -9215, "test76 case 46 failed\n"); - FAILED(buf[2] != 5316, "test76 case 47 failed\n"); - FAILED(buf[3] != 4619, "test76 case 48 failed\n"); - FAILED(buf[4] != -1502, "test76 case 49 failed\n"); - FAILED(buf[5] != 8793, "test76 case 50 failed\n"); - FAILED(buf[6] != -4027, "test76 case 51 failed\n"); - FAILED(buf[7] != 2910, "test76 case 52 failed\n"); - FAILED(buf[8] != -1, "test76 case 53 failed\n"); - FAILED(dbuf[0] != -4061.25, "test76 case 54 failed\n"); - - /* Next test. */ - - for (i = 0; i < 9; i++) - buf[i] = -1; - - dbuf[0] = 4061.25; - dbuf[1] = -3291.75; - dbuf[2] = 8703.5; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 2, 3, 0, 0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 7869); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -5406); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 4951); - - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS0(W)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)&buf); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_S0, 0); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S1, 0); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 3 * sizeof(sljit_sw), SLJIT_S2, 0); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(2), SLJIT_ARGS0(W), 1, 3, 3, 0, SLJIT_MAX_LOCAL_SIZE); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_sw), SLJIT_S0, 0); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 5 * sizeof(sljit_sw), SLJIT_S1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf); - /* dbuf[0] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_R0), 0); - /* dbuf[1] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64)); - /* dbuf[2] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_f64)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1706); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 4713); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, -2078); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1); - - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG | SLJIT_CALL_RETURN, SLJIT_ARGS4(W, F64, F64, F64, W)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS4(W, F64, F64, F64, W_R), 1, 0, 3, 0, 256); - - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)&buf[6], SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&dbuf); - /* dbuf[0] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_FR2, 0); - /* dbuf[1] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_FR0, 0); - /* dbuf[2] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 2 * sizeof(sljit_f64), SLJIT_FR1, 0); - - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_IMM, 5074); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)&buf); - - FAILED(buf[0] != 5074, "test76 case 55 failed\n"); - FAILED(buf[1] != 4713, "test76 case 56 failed\n"); - FAILED(buf[2] != -2078, "test76 case 57 failed\n"); - FAILED(buf[3] != 4951, "test76 case 58 failed\n"); - FAILED(buf[4] != 7869, "test76 case 59 failed\n"); - FAILED(buf[5] != -5406, "test76 case 60 failed\n"); - FAILED(buf[6] != 1706, "test76 case 61 failed\n"); - FAILED(buf[7] != -1, "test76 case 62 failed\n"); - FAILED(dbuf[0] != 8703.5, "test76 case 63 failed\n"); - FAILED(dbuf[1] != 4061.25, "test76 case 64 failed\n"); - FAILED(dbuf[2] != -3291.75, "test76 case 65 failed\n"); - } - - successful_tests++; -} - -static void copy_u8(void *dst, sljit_sw offset, const void *src, sljit_uw length) -{ - sljit_u8 *dst_p = (sljit_u8 *)dst + offset; - const sljit_u8 *src_p = (sljit_u8 *)src; - - while (length-- != 0) - *dst_p++ = *src_p++; -} - -static int cmp_u8(const void *src1, sljit_sw offset, const void *src2, sljit_uw length) -{ - const sljit_u8 *src1_p = (sljit_u8 *)src1 + offset; - const sljit_u8 *src2_p = (sljit_u8 *)src2; - - while (--length != 0) { - if (*src1_p != *src2_p) - return 0; - src1_p++; - src2_p++; - } - return 1; -} - -static void test77(void) -{ - /* Test unaligned accesses. */ - executable_code code; - struct sljit_compiler* compiler; - sljit_sw i; - sljit_sw wbuf[13]; - sljit_s32 ibuf[1]; - sljit_s16 hbuf[1]; - sljit_f64 dbuf[5]; - sljit_f32 sbuf[3]; - sljit_s8 bbuf_start[40 + 8 /* for alignment */]; - sljit_s8 *bbuf = (sljit_s8 *)(((sljit_uw)bbuf_start + 7) & ~(sljit_uw)7); - - SLJIT_ASSERT(((sljit_uw)bbuf & 0x7) == 0); - - if (verbose) - printf("Run test77\n"); - - for (i = 0; i < 13; i++) - wbuf[i] = -3; - - for (i = 0; i < 40; i++) - bbuf[i] = -3; - - wbuf[0] = -46870; - ibuf[0] = -38512; - hbuf[0] = -28531; - copy_u8(bbuf, 3, hbuf, sizeof(sljit_s16)); - copy_u8(bbuf, 5, ibuf, sizeof(sljit_s32)); - copy_u8(bbuf, 9, wbuf, sizeof(sljit_sw)); - copy_u8(bbuf, 18, ibuf, sizeof(sljit_s32)); - copy_u8(bbuf, 22, wbuf, sizeof(sljit_sw)); - copy_u8(bbuf, 32, wbuf, sizeof(sljit_sw)); - - wbuf[0] = -62945; - ibuf[0] = -90678; - hbuf[0] = -17249; - bbuf[0] = -73; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P, P), 2, 2, 0, 0, 0); - - sljit_emit_mem(compiler, SLJIT_MOV_S8 | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM0(), (sljit_sw)bbuf); - /* wbuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_mem(compiler, SLJIT_MOV_U8 | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 0); - /* wbuf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV_S8, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 0); - /* bbuf[1] */ - sljit_emit_mem(compiler, SLJIT_MOV_U8 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s8)); - - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 100000); - sljit_emit_mem(compiler, SLJIT_MOV_S16 | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), 100000 + 3); - /* wbuf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 1000); - sljit_emit_mem(compiler, SLJIT_MOV_U16 | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), -1000 + 3); - /* wbuf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV_S16, SLJIT_R0, 0, SLJIT_MEM0(), (sljit_sw)&hbuf); - /* bbuf[3] */ - sljit_emit_mem(compiler, SLJIT_MOV_S16 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_S1), 3); - - sljit_emit_mem(compiler, SLJIT_MOV_S32 | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_S1), 5); - /* wbuf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5); - sljit_emit_mem(compiler, SLJIT_MOV_U32 | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM2(SLJIT_R0, SLJIT_S1), 0); - /* wbuf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 100000); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_MEM0(), (sljit_sw)&ibuf); - /* bbuf[5] */ - sljit_emit_mem(compiler, SLJIT_MOV32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), 100000 + 5); - - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 100000); -#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), -100000 + 9); -#else /* !SLJIT_UNALIGNED */ - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), -100000 + 9); -#endif /* SLJIT_UNALIGNED */ - /* wbuf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0); - /* bbuf[9] */ -#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), -100000 + 9, SLJIT_R0, 0); -#else /* !SLJIT_UNALIGNED */ - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), -100000 + 9); -#endif /* SLJIT_UNALIGNED */ - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 18 >> 1); - sljit_emit_mem(compiler, SLJIT_MOV_S32 | SLJIT_MEM_UNALIGNED_16, SLJIT_R0, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 1); - /* wbuf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM0(), (sljit_sw)&ibuf); - /* bbuf[18] */ - sljit_emit_mem(compiler, SLJIT_MOV_S32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_16, SLJIT_R0, SLJIT_MEM2(SLJIT_S1, SLJIT_R1), 1); - - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_UNALIGNED_16, SLJIT_R0, SLJIT_MEM0(), (sljit_sw)bbuf + 22); - /* wbuf[9] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0); - /* bbuf[22] */ - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_16, SLJIT_R0, SLJIT_MEM0(), (sljit_sw)bbuf + 22); - - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, 128); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_UNALIGNED_32, SLJIT_R0, SLJIT_MEM1(SLJIT_R0), -128 + 32); - /* wbuf[10] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 128); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), 0); - /* bbuf[32] */ - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_32, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), -128 + 32); - - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_S0), 0); - /* wbuf[11] */ - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_R0, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw)); - /* wbuf[12] */ - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_S0, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw)); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func2((sljit_sw)&wbuf, (sljit_sw)bbuf); - - FAILED(wbuf[1] != -73, "test77 case 1 failed\n"); - FAILED(wbuf[2] != (sljit_u8)-73, "test77 case 2 failed\n"); - FAILED(bbuf[1] != -73, "test77 case 3 failed\n"); - FAILED(wbuf[3] != -28531, "test77 case 4 failed\n"); - FAILED(wbuf[4] != (sljit_u16)-28531, "test77 case 5 failed\n"); - FAILED(cmp_u8(bbuf, 3, hbuf, sizeof(sljit_s16)) != 1, "test77 case 6 failed\n"); - FAILED(wbuf[5] != -38512, "test77 case 7 failed\n"); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - FAILED(wbuf[6] != (sljit_u32)-38512, "test77 case 8 failed\n"); -#else - FAILED(wbuf[6] != -38512, "test77 case 8 failed\n"); -#endif - FAILED(cmp_u8(bbuf, 5, ibuf, sizeof(sljit_s32)) != 1, "test77 case 9 failed\n"); - FAILED(wbuf[7] != -46870, "test77 case 10 failed\n"); - FAILED(cmp_u8(bbuf, 9, wbuf, sizeof(sljit_sw)) != 1, "test77 case 11 failed\n"); - FAILED(wbuf[8] != -38512, "test77 case 12 failed\n"); - FAILED(cmp_u8(bbuf, 18, ibuf, sizeof(sljit_s32)) != 1, "test77 case 13 failed\n"); - FAILED(wbuf[9] != -46870, "test77 case 14 failed\n"); - FAILED(cmp_u8(bbuf, 22, wbuf, sizeof(sljit_sw)) != 1, "test77 case 15 failed\n"); - FAILED(wbuf[10] != -46870, "test77 case 16 failed\n"); - FAILED(cmp_u8(bbuf, 32, wbuf, sizeof(sljit_sw)) != 1, "test77 case 17 failed\n"); - FAILED(wbuf[11] != -62945, "test77 case 18 failed\n"); - FAILED(wbuf[12] != (sljit_sw)&wbuf, "test77 case 19 failed\n"); - - sljit_free_code(code.code, NULL); - - if (sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - for (i = 0; i < 40; i++) - bbuf[i] = -3; - - for (i = 0; i < 5; i++) - dbuf[i] = 0; - - dbuf[0] = 6897.75; - sbuf[0] = -8812.25; - copy_u8(bbuf, 1, sbuf, sizeof(sljit_f32)); - copy_u8(bbuf, 5, dbuf, sizeof(sljit_f64)); - copy_u8(bbuf, 14, sbuf, sizeof(sljit_f32)); - copy_u8(bbuf, 18, dbuf, sizeof(sljit_f64)); - copy_u8(bbuf, 28, dbuf, sizeof(sljit_f64)); - - dbuf[0] = -18046.5; - sbuf[0] = 3751.75; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS3(VOID, P, P, P), 1, 3, 1, 0, 0); - - sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_UNALIGNED, SLJIT_FR0, SLJIT_MEM0(), (sljit_sw)bbuf + 1); - /* sbuf[1] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32), SLJIT_FR0, 0); - - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0); - /* bbuf[1] */ - sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_FR0, SLJIT_MEM0(), (sljit_sw)bbuf + 1); - - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S2, 0, SLJIT_IMM, 100000); -#if (defined SLJIT_FPU_UNALIGNED && SLJIT_FPU_UNALIGNED) - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_R0), 100000 + 5); -#else /* !SLJIT_FPU_UNALIGNED */ - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_UNALIGNED, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 100000 + 5); -#endif /* SLJIT_FPU_UNALIGNED */ - /* dbuf[1] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64), SLJIT_FR0, 0); - - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0); - /* bbuf[5] */ -#if (defined SLJIT_FPU_UNALIGNED && SLJIT_FPU_UNALIGNED) - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 100000 + 5, SLJIT_FR0, 0); -#else /* !SLJIT_FPU_UNALIGNED */ - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), 100000 + 5); -#endif /* SLJIT_FPU_UNALIGNED */ - - sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_UNALIGNED_16, SLJIT_FR0, SLJIT_MEM1(SLJIT_S2), 14); - /* sbuf[2] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_f32), SLJIT_FR0, 0); - - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S1), 0); - /* bbuf[14] */ - sljit_emit_fmem(compiler, SLJIT_MOV_F32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_16, SLJIT_FR0, SLJIT_MEM1(SLJIT_S2), 14); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 18 >> 1); - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_UNALIGNED_16, SLJIT_FR0, SLJIT_MEM2(SLJIT_S2, SLJIT_R0), 1); - /* dbuf[2] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR0, 0); - - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0); - /* bbuf[18] */ - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_16, SLJIT_FR0, SLJIT_MEM2(SLJIT_S2, SLJIT_R0), 1); - - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R0, 0, SLJIT_S2, 0, SLJIT_IMM, 128); - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_UNALIGNED_32, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), -128 + 28); - /* dbuf[3] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64), SLJIT_FR0, 0); - - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR0, 0, SLJIT_MEM1(SLJIT_S0), 0); - /* bbuf[28] */ - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_32, SLJIT_FR0, SLJIT_MEM1(SLJIT_R0), -128 + 28); - - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_UNALIGNED_32, SLJIT_FR0, SLJIT_MEM1(SLJIT_S0), 0); - /* dbuf[4] */ - sljit_emit_fmem(compiler, SLJIT_MOV_F64 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_32, SLJIT_FR0, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_f64)); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func3((sljit_sw)&dbuf, (sljit_sw)&sbuf, (sljit_sw)bbuf); - - FAILED(sbuf[1] != -8812.25, "test77 case 20 failed\n"); - FAILED(cmp_u8(bbuf, 1, sbuf, sizeof(sljit_f32)) != 1, "test77 case 21 failed\n"); - FAILED(dbuf[1] != 6897.75, "test77 case 22 failed\n"); - FAILED(cmp_u8(bbuf, 5, dbuf, sizeof(sljit_f64)) != 1, "test77 case 23 failed\n"); - FAILED(sbuf[2] != -8812.25, "test77 case 24 failed\n"); - FAILED(cmp_u8(bbuf, 14, sbuf, sizeof(sljit_f32)) != 1, "test77 case 25 failed\n"); - FAILED(dbuf[2] != 6897.75, "test77 case 26 failed\n"); - FAILED(cmp_u8(bbuf, 18, dbuf, sizeof(sljit_f64)) != 1, "test77 case 27 failed\n"); - FAILED(dbuf[3] != 6897.75, "test77 case 28 failed\n"); - FAILED(cmp_u8(bbuf, 28, dbuf, sizeof(sljit_f64)) != 1, "test77 case 29 failed\n"); - FAILED(dbuf[4] != -18046.5, "test77 case 30 failed\n"); - - sljit_free_code(code.code, NULL); - } - - successful_tests++; -} - -static void test78(void) -{ - /* Test register register preservation in keep saveds mode. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[6 + SLJIT_NUMBER_OF_REGISTERS]; - struct sljit_jump* jump; - sljit_s32 i; - - if (verbose) - printf("Run test78\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), SLJIT_NUMBER_OF_REGISTERS - 3, 3, 0, 0, 0); - - for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS - 3; i++) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R(i), 0, SLJIT_IMM, 8469 + 1805 * i); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 3671); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 2418); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 1597); - - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS4(VOID, W, W, W, W)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 6), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)&buf); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 3 * sizeof(sljit_sw), SLJIT_S0, 0); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 4 * sizeof(sljit_sw), SLJIT_S1, 0); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 5 * sizeof(sljit_sw), SLJIT_S2, 0); - - for (i = 1; i < SLJIT_NUMBER_OF_REGISTERS - 3; i++) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), (6 + i) * (sljit_sw)sizeof(sljit_sw), SLJIT_R(i), 0); - - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(3), SLJIT_ARGS4(VOID, W_R, W_R, W_R, W_R), 4, 3, 0, 0, SLJIT_MAX_LOCAL_SIZE); - sljit_set_context(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(3), SLJIT_ARGS4(VOID, W_R, W_R, W_R, W_R), 4, 3, 0, 0, SLJIT_MAX_LOCAL_SIZE); - - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 0), SLJIT_S0, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 1), SLJIT_S1, 0); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM0(), (sljit_sw)(buf + 2), SLJIT_S2, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 6501); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 7149); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 5732); - - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG | SLJIT_CALL_RETURN, SLJIT_ARGS0(VOID)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM0(), 0); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(3), SLJIT_ARGS0(VOID), 4, 3, 0, 0, SLJIT_MAX_LOCAL_SIZE / 2); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func0(); - - FAILED(buf[0] != 3671, "test78 case 1 failed\n"); - FAILED(buf[1] != 2418, "test78 case 2 failed\n"); - FAILED(buf[2] != 1597, "test78 case 3 failed\n"); - FAILED(buf[3] != 6501, "test78 case 4 failed\n"); - FAILED(buf[4] != 7149, "test78 case 5 failed\n"); - FAILED(buf[5] != 5732, "test78 case 6 failed\n"); - - for (i = 0; i < SLJIT_NUMBER_OF_REGISTERS - 3; i++) { - FAILED(buf[6 + i] != 8469 + 1805 * i, "test78 case 7 failed\n"); - } - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test79(void) -{ - /* Test register pair movement. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[33]; - sljit_s8 bbuf_start[66 + 8 /* for alignment */]; - sljit_s8 *bbuf = (sljit_s8 *)(((sljit_uw)bbuf_start + 7) & ~(sljit_uw)7); - sljit_s32 i; - - if (verbose) - printf("Run test79\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - for (i = 0; i < 33; i++) - buf[i] = -1; - for (i = 0; i < 66 + 8; i++) - bbuf_start[i] = -1; - - buf[0] = -5836; - buf[1] = 3724; - buf[2] = -9035; - buf[3] = (sljit_sw)bbuf + 50 + 0xfff; - - copy_u8(bbuf, 1, buf, sizeof(sljit_sw)); - copy_u8(bbuf, 1 + sizeof(sljit_sw), buf + 1, sizeof(sljit_sw)); - copy_u8(bbuf, 34, buf + 2, sizeof(sljit_sw)); - copy_u8(bbuf, 34 + sizeof(sljit_sw), buf + 3, sizeof(sljit_sw)); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, W), 5, 5, 0, 0, 3 * sizeof(sljit_sw)); - - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 5814); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 7201); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 6 * sizeof(sljit_sw) + 77); - /* buf[6-7] */ - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), SLJIT_MEM1(SLJIT_R2), -77); - - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 36); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 9); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 2); - /* buf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[9] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw)); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD, SLJIT_REG_PAIR(SLJIT_R1, SLJIT_R0), SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1); - /* buf[10] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R1, 0); - /* buf[11] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, -8402); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 6257); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE, SLJIT_REG_PAIR(SLJIT_R2, SLJIT_R3), SLJIT_MEM1(SLJIT_SP), 0); - /* buf[12] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 0); - /* buf[13] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, 6139); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_sw), SLJIT_IMM, -7049); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD, SLJIT_REG_PAIR(SLJIT_R4, SLJIT_S4), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw)); - /* buf[14] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_R4, 0); - /* buf[15] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_S4, 0); - - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R2, 0, SLJIT_S0, 0, SLJIT_IMM, 0x7f404); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD, SLJIT_REG_PAIR(SLJIT_R2, SLJIT_S4), SLJIT_MEM1(SLJIT_R2), 0x7f404); - /* buf[16] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R2, 0); - /* buf[17] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_S4, 0); - - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 0x7f400 - sizeof(sljit_sw)); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD, SLJIT_REG_PAIR(SLJIT_S2, SLJIT_S3), SLJIT_MEM1(SLJIT_R1), 0x7f400); - /* buf[18] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_S2, 0); - /* buf[19] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 19 * sizeof(sljit_sw), SLJIT_S3, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, 3065); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 7481); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_S2, 0, SLJIT_S0, 0, SLJIT_IMM, 0x7f7f0 + 20 * sizeof(sljit_sw)); - /* buf[20-21] */ - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE, SLJIT_REG_PAIR(SLJIT_R3, SLJIT_R4), SLJIT_MEM1(SLJIT_S2), -0x7f7f0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 3275); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, -8714); - /* buf[22-23] */ - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE, SLJIT_REG_PAIR(SLJIT_S1, SLJIT_S3), SLJIT_MEM0(), (sljit_sw)(buf + 22)); - - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD | SLJIT_MEM_UNALIGNED, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), SLJIT_MEM0(), (sljit_sw)bbuf + 1); - /* buf[24] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 24 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[25] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 25 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 3724); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, -9035); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)bbuf + 18 - 0x7f0f); - /* bbuf[18], buf[18] + sizeof(sljit_sw) */ - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_16, SLJIT_REG_PAIR(SLJIT_R4, SLJIT_S4), SLJIT_MEM1(SLJIT_R0), 0x7f0f); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)bbuf + 34 - 0xfff); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD | SLJIT_MEM_UNALIGNED_16, SLJIT_REG_PAIR(SLJIT_S1, SLJIT_R0), SLJIT_MEM1(SLJIT_S1), 0xfff); - /* buf[26] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 26 * sizeof(sljit_sw), SLJIT_S1, 0); - /* buf[27] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 27 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, (sljit_sw)bbuf + 34); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD | SLJIT_MEM_UNALIGNED, SLJIT_REG_PAIR(SLJIT_S1, SLJIT_R0), SLJIT_MEM1(SLJIT_S1), 0); - /* buf[28] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 28 * sizeof(sljit_sw), SLJIT_S1, 0); - /* buf[29] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 29 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)bbuf + 1 + 0x8004); - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_LOAD | SLJIT_MEM_UNALIGNED, SLJIT_REG_PAIR(SLJIT_S1, SLJIT_R0), SLJIT_MEM1(SLJIT_R0), -0x8004); - /* buf[30] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 30 * sizeof(sljit_sw), SLJIT_S1, 0); - /* buf[31] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 31 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)bbuf + 50 + 0xfff); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -9035); - /* bbuf[50], buf[50] + sizeof(sljit_sw) */ - sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED_16, SLJIT_REG_PAIR(SLJIT_R2, SLJIT_R3), SLJIT_MEM1(SLJIT_R2), -0xfff); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)buf); - - FAILED(buf[3] != (sljit_sw)bbuf + 50 + 0xfff, "test79 case 1 failed\n"); - FAILED(buf[4] != 3724, "test79 case 1 failed\n"); - FAILED(buf[5] != -9035, "test79 case 2 failed\n"); - FAILED(buf[6] != 5814, "test79 case 3 failed\n"); - FAILED(buf[7] != 7201, "test79 case 4 failed\n"); - FAILED(buf[8] != -5836, "test79 case 5 failed\n"); - FAILED(buf[9] != 3724, "test79 case 6 failed\n"); - FAILED(buf[10] != -9035, "test79 case 7 failed\n"); - FAILED(buf[11] != buf[3], "test79 case 8 failed\n"); - FAILED(buf[12] != -8402, "test79 case 9 failed\n"); - FAILED(buf[13] != 6257, "test79 case 10 failed\n"); - FAILED(buf[14] != 6139, "test79 case 11 failed\n"); - FAILED(buf[15] != -7049, "test79 case 12 failed\n"); - FAILED(buf[16] != -5836, "test79 case 13 failed\n"); - FAILED(buf[17] != 3724, "test79 case 14 failed\n"); - FAILED(buf[18] != 3724, "test79 case 15 failed\n"); - FAILED(buf[19] != -9035, "test79 case 16 failed\n"); - FAILED(buf[20] != 3065, "test79 case 17 failed\n"); - FAILED(buf[21] != 7481, "test79 case 18 failed\n"); - FAILED(buf[22] != 3275, "test79 case 19 failed\n"); - FAILED(buf[23] != -8714, "test79 case 20 failed\n"); - FAILED(buf[24] != -5836, "test79 case 21 failed\n"); - FAILED(buf[25] != 3724, "test79 case 22 failed\n"); - FAILED(cmp_u8(bbuf, 18, buf + 1, sizeof(sljit_sw)) != 1, "test79 case 23 failed\n"); - FAILED(cmp_u8(bbuf, 18 + sizeof(sljit_sw), buf + 2, sizeof(sljit_sw)) != 1, "test79 case 24 failed\n"); - FAILED(buf[26] != -9035, "test79 case 25 failed\n"); - FAILED(buf[27] != buf[3], "test79 case 26 failed\n"); - FAILED(buf[28] != -9035, "test79 case 27 failed\n"); - FAILED(buf[29] != buf[3], "test79 case 28 failed\n"); - FAILED(buf[30] != -5836, "test79 case 29 failed\n"); - FAILED(buf[31] != 3724, "test79 case 30 failed\n"); - FAILED(cmp_u8(bbuf, 50, buf + 3, sizeof(sljit_sw)) != 1, "test79 case 31 failed\n"); - FAILED(cmp_u8(bbuf, 50 + sizeof(sljit_sw), buf + 2, sizeof(sljit_sw)) != 1, "test79 case 32 failed\n"); - FAILED(buf[32] != -1, "test79 case 33 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test80(void) -{ - /* Test masked shift. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[8]; - sljit_s32 ibuf[8]; - sljit_s32 i; - - if (verbose) - printf("Run test80\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - for (i = 0; i < 8; i++) - buf[i] = -1; - for (i = 0; i < 8; i++) - ibuf[i] = -1; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W, W), 5, 5, 0, 0, 2 * sizeof(sljit_sw)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x1234); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 8 * sizeof(sljit_sw) + 4); - sljit_emit_op2(compiler, SLJIT_MSHL, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R2, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 8 * sizeof(sljit_sw)); - /* buf[1] */ - sljit_emit_op2(compiler, SLJIT_MSHL, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x5678); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 32 + 8); - sljit_emit_op2(compiler, SLJIT_MSHL32, SLJIT_R2, 0, SLJIT_R0, 0, SLJIT_R1, 0); - /* ibuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R2, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, -2); - /* ibuf[1] */ - sljit_emit_op2(compiler, SLJIT_MSHL32 | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R3, 0, SLJIT_R4, 0); - /* buf[2] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_NOT_ZERO); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 8 * sizeof(sljit_sw) + 4); - sljit_emit_op2(compiler, SLJIT_MLSHR | SLJIT_SET_Z, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_R2, 0); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[4] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_NOT_ZERO); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 0x5678); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_IMM, -32); - sljit_emit_op2(compiler, SLJIT_MLSHR32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32)); - /* ibuf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_SP), 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0x345678); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S1, 0, SLJIT_IMM, 0x123000 - 3 * sizeof(sljit_s32)); - /* ibuf[3] */ - sljit_emit_op2(compiler, SLJIT_MLSHR32, SLJIT_MEM1(SLJIT_R1), 0x123000, SLJIT_R0, 0, SLJIT_IMM, 32 + 4); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, -0x100); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 8 * sizeof(sljit_sw) + 4); - sljit_emit_op2(compiler, SLJIT_MASHR, SLJIT_R1, 0, SLJIT_R3, 0, SLJIT_R2, 0); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_IMM, -0x100); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, -32 + 1); - sljit_emit_op2(compiler, SLJIT_MASHR32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_R2, 0); - /* ibuf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32)); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_IMM, 0x7fffffff); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -1); - /* ibuf[5] */ - sljit_emit_op2(compiler, SLJIT_MLSHR32 | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_R0, 0); - /* buf[6] */ - sljit_emit_op_flags(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_NOT_ZERO); - -#if (defined SLJIT_MASKED_SHIFT && SLJIT_MASKED_SHIFT) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 12344321); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (8 * sizeof(sljit_sw)) + 1); - /* buf[7] */ - sljit_emit_op2(compiler, SLJIT_SHL, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R1, 0, SLJIT_R2, 0); -#endif /* SLJIT_MASKED_SHIFT */ -#if (defined SLJIT_MASKED_SHIFT32 && SLJIT_MASKED_SHIFT32) - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 24688643); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, (8 * sizeof(sljit_s32)) + 1); - /* ibuf[6] */ - sljit_emit_op2(compiler, SLJIT_LSHR32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_s32), SLJIT_R1, 0, SLJIT_R2, 0); -#endif /* SLJIT_MASKED_SHIFT32 */ - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func2((sljit_sw)buf, (sljit_sw)ibuf); - - FAILED(buf[0] != 0x12340, "test80 case 1 failed\n"); - FAILED(buf[1] != 0x1234, "test80 case 2 failed\n"); - FAILED(ibuf[0] != 0x567800, "test80 case 3 failed\n"); - FAILED(ibuf[1] != (sljit_sw)1 << 30, "test80 case 4 failed\n"); - FAILED(buf[2] != 1, "test80 case 5 failed\n"); - FAILED(buf[3] != ((sljit_uw)-1 >> 4), "test80 case 6 failed\n"); - FAILED(buf[4] != 1, "test80 case 7 failed\n"); - FAILED(ibuf[2] != 0x5678, "test80 case 8 failed\n"); - FAILED(ibuf[3] != 0x34567, "test80 case 9 failed\n"); - FAILED(buf[5] != -0x10, "test80 case 10 failed\n"); - FAILED(ibuf[4] != -0x80, "test80 case 11 failed\n"); - FAILED(ibuf[5] != 0, "test80 case 12 failed\n"); - FAILED(buf[6] != 0, "test80 case 13 failed\n"); -#if (defined SLJIT_MASKED_SHIFT && SLJIT_MASKED_SHIFT) - FAILED(buf[7] != 24688642, "test80 case 14 failed\n"); -#endif /* SLJIT_MASKED_SHIFT */ -#if (defined SLJIT_MASKED_SHIFT32 && SLJIT_MASKED_SHIFT32) - FAILED(ibuf[6] != 12344321, "test80 case 15 failed\n"); -#endif /* SLJIT_MASKED_SHIFT32 */ - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test81(void) -{ - /* Test return with floating point value. */ - executable_code code; - struct sljit_compiler* compiler; - struct sljit_jump* jump; - sljit_f64 dbuf[2]; - sljit_f32 sbuf[2]; - - if (verbose) - printf("Run test81\n"); - - if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - if (verbose) - printf("no fpu available, test81 skipped\n"); - successful_tests++; - return; - } - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(F64, W), 0, 1, 3, 0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_return(compiler, SLJIT_MOV_F64, SLJIT_FR2, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - dbuf[0] = 35.125; - FAILED(code.test81_f2((sljit_sw)dbuf) != 35.125, "test81 case 1 failed\n"); - - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(F32, W), 0, 1, 1, 0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_RETURN_FREG, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_return(compiler, SLJIT_MOV_F32, SLJIT_RETURN_FREG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - sbuf[0] = -9027.5; - FAILED(code.test81_f1((sljit_sw)sbuf) != -9027.5, "test81 case 2 failed\n"); - - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(F32, W), 0, 1, 1, 0, sizeof(sljit_f32)); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_return(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_SP), 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - sbuf[0] = -6.75; - FAILED(code.test81_f1((sljit_sw)sbuf) != -6.75, "test81 case 3 failed\n"); - - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(F64, W), 0, 1, 1, 0, 2 * sizeof(sljit_f64)); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f64), SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_return(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_f64)); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - dbuf[0] = 45.125; - FAILED(code.test81_f2((sljit_sw)dbuf) != 45.125, "test81 case 4 failed\n"); - - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 1, 0, 1, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)dbuf - 33); - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS1(F64, W)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)dbuf); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f64), SLJIT_RETURN_FREG, 0); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS1(F64, W_R), 1, 0, 1, 0, 0); - sljit_emit_return(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_R0), 33); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - dbuf[0] = 2571.75; - dbuf[1] = 0; - code.func0(); - FAILED(dbuf[1] != 2571.75, "test81 case 5 failed\n"); - - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 1, 0, 1, 0, 0); - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS0(F32)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)sbuf); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_f32), SLJIT_RETURN_FREG, 0); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS0(F32), 0, 0, 1, 0, 0); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_RETURN_FREG, 0, SLJIT_MEM0(), (sljit_sw)sbuf); - sljit_emit_return(compiler, SLJIT_MOV_F32, SLJIT_RETURN_FREG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - sbuf[0] = 6310.25; - sbuf[1] = 0; - code.func0(); - FAILED(sbuf[1] != 6310.25, "test81 case 6 failed\n"); - - sljit_free_code(code.code, NULL); - - successful_tests++; -} - -static void test82(void) -{ - /* Test return_to operation. */ - executable_code code, code2; - struct sljit_compiler* compiler; - struct sljit_jump* jump; - struct sljit_label* label; - sljit_s32 i; - sljit_sw buf[3]; - - if (verbose) - printf("Run test82\n"); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 2, 1, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -7602); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_S0, 0); - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - label = sljit_emit_label(compiler); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_RETURN_REG, 0); - sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W_R, W_R), 2, 0, 0, 0, 256); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 256 - sizeof(sljit_sw), SLJIT_IMM, -1); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 8945); - sljit_emit_return_to(compiler, SLJIT_MEM1(SLJIT_R1), 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - - buf[0] = (sljit_sw)sljit_get_label_addr(label); - buf[1] = 0; - - sljit_free_compiler(compiler); - - code.func1((sljit_sw)buf); - FAILED(buf[0] != 8945, "test82 case 1 failed\n"); - FAILED(buf[1] != -7602, "test82 case 2 failed\n"); - - sljit_free_code(code.code, NULL); - - /* Next test. */ - - for (i = 0; i < 3; i++) { - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 2, 1, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 6032); - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS1(W, W)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - label = sljit_emit_label(compiler); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)buf); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_RETURN_REG, 0); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S0, 0); - sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(1), SLJIT_ARGS1(VOID, W_R), 2, i == 1 ? 2 : 1, 0, 0, SLJIT_MAX_LOCAL_SIZE); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw)); - if (i == 2) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_S0), 0); - else - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S(i), 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), SLJIT_MAX_LOCAL_SIZE - sizeof(sljit_sw), SLJIT_IMM, -1); - if (i != 0) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -3890); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 7145); - if (i == 2) - sljit_emit_return_to(compiler, SLJIT_MEM1(SLJIT_SP), 2 * sizeof(sljit_sw)); - else - sljit_emit_return_to(compiler, SLJIT_S(i), 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - - buf[0] = (sljit_sw)sljit_get_label_addr(label); - buf[1] = 0; - buf[2] = 0; - - sljit_free_compiler(compiler); - - code.func1((sljit_sw)buf); - FAILED(buf[0] != 7145, "test82 case 3 failed\n"); - FAILED(buf[1] != 6032, "test82 case 4 failed\n"); - if (i != 0) - FAILED(buf[2] != -3890, "test82 case 5 failed\n"); - - sljit_free_code(code.code, NULL); - } - - /* Next test. */ - - for (i = 0; i < 3; i++) { - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P_R), 2, 1, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_R0, 0); - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS1(W, W)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - label = sljit_emit_label(compiler); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)buf); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_RETURN_REG, 0); - sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, W_R), 2, 1, 0, 0, (i == 0) ? 0 : (i == 1) ? 512 : 32768); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), sizeof(sljit_sw), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, -1); - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 0x1000); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, -4502); - sljit_emit_return_to(compiler, SLJIT_MEM1(SLJIT_R1), -0x1000); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - - buf[0] = (sljit_sw)sljit_get_label_addr(label); - buf[1] = 0; - - sljit_free_compiler(compiler); - - code.func1((sljit_sw)buf); - FAILED(buf[0] != -4502, "test82 case 6 failed\n"); - FAILED(buf[1] != (sljit_sw)buf, "test82 case 7 failed\n"); - - sljit_free_code(code.code, NULL); - } - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - i = SLJIT_S2; -#else - i = SLJIT_S(SLJIT_NUMBER_OF_SAVED_REGISTERS - 1); -#endif - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 2, SLJIT_NUMBER_OF_SAVED_REGISTERS, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, i, 0, SLJIT_IMM, 2 * sizeof(sljit_sw)); - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0(W)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - label = sljit_emit_label(compiler); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_S0, i), 0, SLJIT_RETURN_REG, 0); - sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 2, SLJIT_NUMBER_OF_SAVED_REGISTERS, 0, 0, 16); - for (i = 0; i < SLJIT_NUMBER_OF_SAVED_REGISTERS; i++) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S(i), 0, SLJIT_IMM, -1); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, (sljit_sw)(buf + 3)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -3); - sljit_emit_return_to(compiler, SLJIT_MEM2(SLJIT_RETURN_REG, SLJIT_R1), SLJIT_WORD_SHIFT); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - - buf[0] = (sljit_sw)sljit_get_label_addr(label); - buf[1] = 0; - buf[2] = 0; - - sljit_free_compiler(compiler); - - code.func1((sljit_sw)buf); - FAILED(buf[2] != (sljit_sw)(buf + 3), "test82 case 8 failed\n"); - - sljit_free_code(code.code, NULL); - - /* Next test. */ - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, P_R, P), 2, SLJIT_NUMBER_OF_SAVED_REGISTERS, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_S0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 586000); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 392); - sljit_emit_icall(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS0(W), SLJIT_R0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM0(), 0); - label = sljit_emit_label(compiler); - /* buf[0] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM1(SLJIT_S2), 0, SLJIT_S0, 0, SLJIT_S1, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S2), sizeof(sljit_sw), SLJIT_RETURN_REG, 0); - sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - - buf[0] = (sljit_sw)sljit_get_label_addr(label); - - sljit_free_compiler(compiler); - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(2), SLJIT_ARGS0(VOID), 2, SLJIT_NUMBER_OF_SAVED_REGISTERS, 0, 0, 16); - for (i = 2; i < SLJIT_NUMBER_OF_SAVED_REGISTERS; i++) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S(i), 0, SLJIT_IMM, -1); - /* buf[2] */ - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_MEM0(), (sljit_sw)(buf + 2), SLJIT_S0, 0, SLJIT_S1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S0, 0, SLJIT_IMM, 416000); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S1, 0, SLJIT_IMM, 931); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 2906); - sljit_emit_return_to(compiler, SLJIT_IMM, buf[0]); - - code2.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - buf[0] = 0; - buf[1] = 0; - buf[2] = 0; - - code.func2(SLJIT_FUNC_ADDR(code2.func0), (sljit_sw)buf); - FAILED(buf[0] != 416931, "test82 case 9 failed\n"); - FAILED(buf[1] != 2906, "test82 case 10 failed\n"); - FAILED(buf[2] != 586392, "test82 case 11 failed\n"); - - sljit_free_code(code.code, NULL); - sljit_free_code(code2.code, NULL); - - successful_tests++; -} - -static void test83(void) -{ - /* Test rotate. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[13]; - sljit_s32 ibuf[8]; - sljit_s32 i; -#ifdef SLJIT_PREF_SHIFT_REG - sljit_s32 shift_reg = SLJIT_PREF_SHIFT_REG; -#else - sljit_s32 shift_reg = SLJIT_R2; -#endif - - if (verbose) - printf("Run test83\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - for (i = 0; i < 13; i++) - buf[i] = -1; - for (i = 0; i < 8; i++) - ibuf[i] = -1; - - ibuf[0] = 8; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W, W), 5, 5, 0, 0, 2 * sizeof(sljit_sw)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678)); - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 12); - sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_R0, 0, SLJIT_R0, 0, shift_reg, 0); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xfedcba0987654321, 0x87654321)); - sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_R1, 0, SLJIT_R0, 0, SLJIT_IMM, 1); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, WCONST(0xfedcba0987654321, 0x87654321)); - sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_S2, 0, SLJIT_R4, 0, SLJIT_IMM, 0xffff00); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_S2, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -1); - /* buf[3] */ - sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_IMM, WCONST(0x9876543210abcdef, 0x87654321), shift_reg, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_IMM, WCONST(0x9876543210abcdc0, 0x876543e0)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 4); - sljit_emit_op2(compiler, SLJIT_ROTL, SLJIT_R0, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw)); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678)); - sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, 4); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 20); - sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x1234567887654341, 0x17654321)); - sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_R0, 0); - /* buf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8 * sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0xfedcba0987654321, 0x87654321)); - /* buf[8] */ - sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), 0, SLJIT_R1, 0, SLJIT_IMM, 0xff00); - - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0xffc0); - sljit_emit_op2(compiler, SLJIT_ROTR, SLJIT_R1, 0, SLJIT_R1, 0, shift_reg, 0); - /* buf[9] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -7834); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x87654321); - sljit_emit_op2(compiler, SLJIT_ROTL32, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 0); - /* ibuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R0, 0); - /* buf[10] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), shift_reg, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_sw)0xabc89def); - sljit_emit_op2(compiler, SLJIT_ROTL32, SLJIT_S4, 0, SLJIT_R4, 0, SLJIT_IMM, 0xfffe1); - /* ibuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_S4, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_sw)0xabc89def); - sljit_emit_op2(compiler, SLJIT_ROTL32, SLJIT_S4, 0, SLJIT_R4, 0, SLJIT_IMM, 0xfffe0); - /* ibuf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_S4, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -6512); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, 0xfffe0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_IMM, (sljit_sw)0xabc89def); - /* ibuf[3] */ - sljit_emit_op2(compiler, SLJIT_ROTL32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_R4, 0); - /* buf[11] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), shift_reg, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 30); - sljit_emit_op2(compiler, SLJIT_ROTR32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0x87654321, SLJIT_R0, 0); - /* ibuf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_IMM, (sljit_sw)0xfedccdef); - sljit_emit_op2(compiler, SLJIT_ROTR32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_IMM, 4); - /* ibuf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_SP), 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_s32), SLJIT_IMM, (sljit_sw)0x89abcdef); - sljit_emit_op2(compiler, SLJIT_ROTR32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_s32), SLJIT_IMM, 0xfffe0); - /* ibuf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_s32), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -2647); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0x89abcde0); - /* ibuf[7] */ - sljit_emit_op2(compiler, SLJIT_ROTR32, SLJIT_MEM1(SLJIT_S1), 7 * sizeof(sljit_s32), SLJIT_R1, 0, SLJIT_R1, 0); - /* buf[12] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), shift_reg, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func2((sljit_sw)buf, (sljit_sw)ibuf); - - FAILED(buf[0] != WCONST(0x4567812345678123, 0x45678123), "test83 case 1 failed\n"); - FAILED(buf[1] != WCONST(0xfdb974130eca8643, 0xeca8643), "test83 case 2 failed\n"); - FAILED(buf[2] != WCONST(0xfedcba0987654321, 0x87654321), "test83 case 3 failed\n"); - FAILED(buf[3] != WCONST(0xcc3b2a190855e6f7, 0xc3b2a190), "test83 case 4 failed\n"); - FAILED(buf[4] != WCONST(0x9876543210abcdc0, 0x876543e0), "test83 case 5 failed\n"); - FAILED(buf[5] != WCONST(0x8123456781234567, 0x81234567), "test83 case 6 failed\n"); - FAILED(buf[6] != WCONST(0x4567812345678123, 0x45678123), "test83 case 7 failed\n"); - FAILED(buf[7] != WCONST(0x891a2b3c43b2a1a0, 0x8bb2a190), "test83 case 8 failed\n"); - FAILED(buf[8] != WCONST(0xfedcba0987654321, 0x87654321), "test83 case 9 failed\n"); - FAILED(buf[9] != WCONST(0xfedcba0987654321, 0x87654321), "test83 case 10 failed\n"); - FAILED(ibuf[0] != (sljit_s32)0x65432187, "test83 case 11 failed\n"); - FAILED(buf[10] != -7834, "test83 case 12 failed\n"); - FAILED(ibuf[1] != (sljit_s32)0x57913bdf, "test83 case 13 failed\n"); - FAILED(ibuf[2] != (sljit_s32)0xabc89def, "test83 case 14 failed\n"); - FAILED(ibuf[3] != (sljit_s32)0xabc89def, "test83 case 15 failed\n"); - FAILED(buf[11] != -6512, "test83 case 16 failed\n"); - FAILED(ibuf[4] != (sljit_s32)0x1d950c86, "test83 case 17 failed\n"); - FAILED(ibuf[5] != (sljit_s32)0xffedccde, "test83 case 18 failed\n"); - FAILED(ibuf[6] != (sljit_s32)0x89abcdef, "test83 case 19 failed\n"); - FAILED(ibuf[7] != (sljit_s32)0x89abcde0, "test83 case 20 failed\n"); - FAILED(buf[12] != -2647, "test83 case 21 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test84(void) -{ - /* Test "shift into". */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[19]; - sljit_s32 ibuf[10]; - sljit_s32 i; -#ifdef SLJIT_PREF_SHIFT_REG - sljit_s32 shift_reg = SLJIT_PREF_SHIFT_REG; -#else - sljit_s32 shift_reg = SLJIT_R2; -#endif - - if (verbose) - printf("Run test84\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - for (i = 0; i < 19; i++) - buf[i] = -1; - for (i = 0; i < 10; i++) - ibuf[i] = -1; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W, W), 5, 5, 0, 0, 2 * sizeof(sljit_sw)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678)); - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 12); - sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_R0, SLJIT_R1, SLJIT_R1, shift_reg, 0); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678)); - sljit_emit_shift_into(compiler, SLJIT_MLSHR, SLJIT_R4, SLJIT_R3, SLJIT_R3, SLJIT_IMM, 0xffd4 /* 20 */); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R4, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, shift_reg, 0, SLJIT_IMM, (sljit_s32)0x86421357); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 0xffeb /* 11 */); - sljit_emit_shift_into(compiler, SLJIT_MSHL32, SLJIT_R0, shift_reg, shift_reg, SLJIT_MEM1(SLJIT_SP), 0); - /* ibuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -8762); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_s32)0x89abcdef); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_IMM, 0xffff); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R0, 0, SLJIT_S1, 0, SLJIT_IMM, 16 * sizeof(sljit_s32)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, 17); - sljit_emit_shift_into(compiler, SLJIT_MLSHR32, SLJIT_S2, SLJIT_R4, SLJIT_R4, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 2); - /* ibuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_S2, 0); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), shift_reg, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, WCONST(0x1234567812345678, 0x12345678)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xabcd000000000000, 0xabcd0000)); - sljit_emit_shift_into(compiler, SLJIT_MSHL, SLJIT_S4, SLJIT_S4, SLJIT_R0, SLJIT_IMM, 12); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_S4, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xaabbccddeeff8899, 0xabcdef89)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 0xfedcba); - sljit_emit_shift_into(compiler, SLJIT_LSHR, SLJIT_R1, SLJIT_R0, SLJIT_R4, SLJIT_IMM, 19); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0xfedcba0987654321, 0xfedcba09)); - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, WCONST(0x7fffffffffffffff, 0x7fffffff)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 1); - sljit_emit_shift_into(compiler, SLJIT_SHL | SLJIT_SHIFT_INTO_NON_ZERO, SLJIT_R4, SLJIT_R1, shift_reg, SLJIT_MEM1(SLJIT_SP), 0); - /* buf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 5 * sizeof(sljit_sw), SLJIT_R4, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0xdeadbeaf); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_sw)0xfedcba09); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -5); - sljit_emit_shift_into(compiler, SLJIT_MLSHR32 | SLJIT_SHIFT_INTO_NON_ZERO, shift_reg, SLJIT_R1, SLJIT_R4, SLJIT_R0, 0); - /* ibuf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), shift_reg, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_IMM, (sljit_sw)0xabcd6543); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_s32)0xc9000000); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0xffe8); - sljit_emit_shift_into(compiler, SLJIT_MSHL32, shift_reg, SLJIT_R3, SLJIT_R4, SLJIT_R0, 0); - /* ibuf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), shift_reg, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, -6032); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, 0x7cadcad7); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_S3, 0, SLJIT_IMM, (sljit_s32)0xfffffff5); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 3); - sljit_emit_shift_into(compiler, SLJIT_LSHR32, SLJIT_R4, SLJIT_R4, SLJIT_S3, SLJIT_R0, 0); - /* ibuf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_R4, 0); - /* buf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 6 * sizeof(sljit_sw), shift_reg, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -9740); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -5182); - sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_IMM, 0); - /* buf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 7 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 8 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, -4072); - sljit_emit_op1(compiler, SLJIT_MOV32, shift_reg, 0, SLJIT_IMM, -2813); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0); - sljit_emit_shift_into(compiler, SLJIT_LSHR32, SLJIT_R0, SLJIT_R0, shift_reg, SLJIT_R1, 0); - /* ibuf[5] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 5 * sizeof(sljit_s32), SLJIT_R0, 0); - /* ibuf[6] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 6 * sizeof(sljit_s32), shift_reg, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -3278); - sljit_emit_op1(compiler, SLJIT_MOV, shift_reg, 0, SLJIT_IMM, 0); - sljit_emit_shift_into(compiler, SLJIT_LSHR, SLJIT_R1, SLJIT_R0, SLJIT_R0, shift_reg, 0); - /* buf[9] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 9 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, WCONST(0x1234567890abcdef, 0x12345678)); - sljit_emit_shift_into(compiler, SLJIT_LSHR, SLJIT_R0, SLJIT_S3, SLJIT_S3, SLJIT_IMM, 0xfff8 /* 24/56 */); - /* buf[10] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 10 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S3, 0, SLJIT_IMM, WCONST(0x1234567890abcdef, 0x12345678)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S4, 0, SLJIT_IMM, WCONST(0xba9876fedcba9800, 0xfedcba00)); - sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_S3, SLJIT_S3, SLJIT_S4, SLJIT_IMM, 0xfff8 /* 24/56 */); - /* buf[11] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 11 * sizeof(sljit_sw), SLJIT_S3, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0x1234567890abcdef, 0x12345678)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -4986); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, 0); - sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_R4, 0); - /* buf[12] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 12 * sizeof(sljit_sw), SLJIT_R0, 0); - /* buf[13] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 13 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x12345678fedcba09, 0x12348765)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), SLJIT_IMM, -1); - sljit_emit_shift_into(compiler, SLJIT_MLSHR, shift_reg, SLJIT_R0, SLJIT_R1, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw)); - /* buf[14] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 14 * sizeof(sljit_sw), shift_reg, 0); - /* buf[15] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 15 * sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x8000000000000005, 0x80000005)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R1, 0); - sljit_emit_shift_into(compiler, SLJIT_MSHL, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_MEM0(), (sljit_sw)(buf + 16)); - /* buf[16] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 16 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, WCONST(0x2345678923456789, 0x23456789)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, -1); - sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_R0, SLJIT_R1, SLJIT_S2, SLJIT_R0, 0); - /* buf[17] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 17 * sizeof(sljit_sw), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xabc23456); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0xef000000); - sljit_emit_shift_into(compiler, SLJIT_SHL32, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_IMM, 4); - /* ibuf[7] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 7 * sizeof(sljit_s32), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_sw)0xabc23456); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)0xfe); - sljit_emit_shift_into(compiler, SLJIT_LSHR32, SLJIT_S2, SLJIT_R0, SLJIT_R1, SLJIT_IMM, 4); - /* ibuf[8] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 8 * sizeof(sljit_s32), SLJIT_S2, 0); - -#if (defined SLJIT_MASKED_SHIFT && SLJIT_MASKED_SHIFT) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 12344321); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (8 * sizeof(sljit_sw)) + 1); - sljit_emit_shift_into(compiler, SLJIT_SHL, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_R2, 0); - /* buf[18] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 18 * sizeof(sljit_sw), SLJIT_R0, 0); -#endif /* SLJIT_MASKED_SHIFT */ -#if (defined SLJIT_MASKED_SHIFT32 && SLJIT_MASKED_SHIFT32) - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 24688642); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 1); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R2, 0, SLJIT_IMM, (8 * sizeof(sljit_s32)) + 1); - sljit_emit_shift_into(compiler, SLJIT_LSHR32, SLJIT_R0, SLJIT_R0, SLJIT_R1, SLJIT_R2, 0); - /* ibuf[9] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 9 * sizeof(sljit_s32), SLJIT_R0, 0); -#endif /* SLJIT_MASKED_SHIFT32 */ - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func2((sljit_sw)buf, (sljit_sw)ibuf); - - FAILED(buf[0] != WCONST(0x4567812345678123, 0x45678123), "test84 case 1 failed\n"); - FAILED(buf[1] != WCONST(0x4567812345678123, 0x45678123), "test84 case 2 failed\n"); - FAILED(ibuf[0] != 0x109abc32, "test84 case 3 failed\n"); - FAILED(ibuf[1] != 0x13579bdf, "test84 case 4 failed\n"); - FAILED(buf[2] != -8762, "test84 case 5 failed\n"); - FAILED(buf[3] != WCONST(0x4567812345678abc, 0x45678abc), "test84 case 6 failed\n"); - FAILED(buf[4] != WCONST(0xdb975557799bbddf, 0xdb975579), "test84 case 7 failed\n"); - FAILED(buf[5] != WCONST(0xfdb974130eca8642, 0xfdb97412), "test84 case 8 failed\n"); - FAILED(ibuf[2] != (sljit_s32)0xdb97413b, "test84 case 9 failed\n"); - FAILED(ibuf[3] != (sljit_s32)0xcd6543c9, "test84 case 10 failed\n"); - FAILED(ibuf[4] != (sljit_s32)0xaf95b95a, "test84 case 11 failed\n"); - FAILED(buf[6] != -6032, "test84 case 12 failed\n"); - FAILED(buf[7] != -9740, "test84 case 13 failed\n"); - FAILED(buf[8] != -5182, "test84 case 14 failed\n"); - FAILED(ibuf[5] != -4072, "test84 case 15 failed\n"); - FAILED(ibuf[6] != -2813, "test84 case 16 failed\n"); - FAILED(buf[9] != -3278, "test84 case 17 failed\n"); - FAILED(buf[10] != WCONST(0x34567890abcdef12, 0x34567812), "test84 case 18 failed\n"); - FAILED(buf[11] != WCONST(0xefba9876fedcba98, 0x78fedcba), "test84 case 19 failed\n"); - FAILED(buf[12] != WCONST(0x1234567890abcdef, 0x12345678), "test84 case 20 failed\n"); - FAILED(buf[13] != -4986, "test84 case 21 failed\n"); - FAILED(buf[14] != WCONST(0x2468acf1fdb97413, 0x24690ecb), "test84 case 22 failed\n"); - FAILED(buf[15] != WCONST(0x12345678fedcba09, 0x12348765), "test84 case 23 failed\n"); - FAILED(buf[16] != 0x30, "test84 case 24 failed\n"); - FAILED(buf[17] != WCONST(0x8d159e248d159e27, 0x8d159e27), "test84 case 25 failed\n"); - FAILED(ibuf[7] != (sljit_s32)0xbc23456e, "test84 case 26 failed\n"); - FAILED(ibuf[8] != (sljit_s32)0xeabc2345, "test84 case 27 failed\n"); -#if (defined SLJIT_MASKED_SHIFT && SLJIT_MASKED_SHIFT) - FAILED(buf[18] != 24688643, "test84 case 28 failed\n"); -#endif /* SLJIT_MASKED_SHIFT */ -#if (defined SLJIT_MASKED_SHIFT32 && SLJIT_MASKED_SHIFT32) - FAILED(ibuf[9] != (sljit_s32)-2135139327, "test84 case 29 failed\n"); -#endif /* SLJIT_MASKED_SHIFT32 */ - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test85(void) -{ - /* Test count trailing zeroes. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[5]; - sljit_s32 ibuf[7]; - sljit_s32 i; - - if (verbose) - printf("Run test85\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - for (i = 0; i < 5; i++) - buf[i] = -1; - for (i = 0; i < 7; i++) - ibuf[i] = -1; - - buf[2] = 0; - ibuf[3] = 1; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W, W), 5, 5, 0, 0, 2 * sizeof(sljit_sw)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 0x80); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_CTZ, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, 0x654321); - sljit_emit_op1(compiler, SLJIT_CTZ, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_SP), 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, 2); - sljit_emit_op1(compiler, SLJIT_CTZ, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_MEM2(SLJIT_S0, SLJIT_S2), SLJIT_WORD_SHIFT); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw)); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, (sljit_sw)1 << (8 * sizeof(sljit_sw) - 3)); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 0x100000); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_CTZ, SLJIT_MEM1(SLJIT_R1), 0x100000 + 3 * sizeof(sljit_sw), SLJIT_R4, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_IMM, WCONST(0xabcdef800, 0xcdef800)); - sljit_emit_op1(compiler, SLJIT_CTZ, SLJIT_S4, 0, SLJIT_MEM0(), (sljit_sw)(buf + 4)); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 4 * sizeof(sljit_sw), SLJIT_S4, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_IMM, 0xa400); - sljit_emit_op2(compiler, SLJIT_ASHR32, SLJIT_R0, 0, SLJIT_R1, 0, SLJIT_IMM, 4); - sljit_emit_op1(compiler, SLJIT_CTZ32, SLJIT_R1, 0, SLJIT_R0, 0); - /* ibuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R1, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, 0); - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R1, 0, SLJIT_R0, 0); - /* ibuf[1] */ - sljit_emit_op1(compiler, SLJIT_CTZ32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), SLJIT_IMM, 0xbcdefe0); - sljit_emit_op1(compiler, SLJIT_CTZ32, SLJIT_S4, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32)); - /* ibuf[2] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 2 * sizeof(sljit_s32), SLJIT_S4, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3); - sljit_emit_op1(compiler, SLJIT_CTZ32, SLJIT_R0, 0, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 2); - /* ibuf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_R0, 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func2((sljit_sw)buf, (sljit_sw)ibuf); - - FAILED(buf[0] != 7, "test85 case 1 failed\n"); - FAILED(buf[1] != 0, "test85 case 2 failed\n"); - FAILED(buf[2] != WCONST(64, 32), "test85 case 3 failed\n"); - FAILED(buf[3] != WCONST(61, 29), "test85 case 4 failed\n"); - FAILED(buf[4] != 11, "test85 case 5 failed\n"); - FAILED(ibuf[0] != 6, "test85 case 6 failed\n"); - FAILED(ibuf[1] != 32, "test85 case 7 failed\n"); - FAILED(ibuf[2] != 5, "test85 case 8 failed\n"); - FAILED(ibuf[3] != 0, "test85 case 9 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test86(void) -{ - /* Test get return address. */ - executable_code code; - struct sljit_compiler* compiler; - struct sljit_jump *jump; - struct sljit_label *label; - sljit_uw return_addr = 0; - sljit_uw buf[1]; - - if (verbose) - printf("Run test86\n"); - - /* Next test. */ - - buf[0] = 0; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, W), 1, 1, 0, 0, 0); - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0(W)); - label = sljit_emit_label(compiler); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_RETURN_REG, 0); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 1, 0, 0, 0, 0); - sljit_emit_op_dst(compiler, SLJIT_GET_RETURN_ADDRESS, SLJIT_RETURN_REG, 0); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - return_addr = sljit_get_label_addr(label); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)buf); - - FAILED(buf[0] != return_addr, "test86 case 1 failed\n"); - sljit_free_code(code.code, NULL); - - /* Next test. */ - - buf[0] = 0; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(VOID), 2, 0, 0, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, -1); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, -1); - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS2(VOID, W, W)); - label = sljit_emit_label(compiler); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W, W), 1, SLJIT_NUMBER_OF_SAVED_REGISTERS - 2, 0, 0, SLJIT_MAX_LOCAL_SIZE); - sljit_emit_op_dst(compiler, SLJIT_GET_RETURN_ADDRESS, SLJIT_MEM0(), (sljit_sw)buf); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - return_addr = sljit_get_label_addr(label); - sljit_free_compiler(compiler); - - code.func0(); - - FAILED(buf[0] != return_addr, "test86 case 2 failed\n"); - sljit_free_code(code.code, NULL); - - /* Next test. */ - - buf[0] = 0; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, W), 1, 3, 0, 0, 0); - sljit_emit_op2(compiler, SLJIT_SUB, SLJIT_S2, 0, SLJIT_S0, 0, SLJIT_IMM, 16); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 8); - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS1(VOID, W)); - label = sljit_emit_label(compiler); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG | SLJIT_ENTER_KEEP(3), SLJIT_ARGS1(VOID, W_R), 1, SLJIT_NUMBER_OF_SAVED_REGISTERS, 0, 0, SLJIT_MAX_LOCAL_SIZE >> 1); - sljit_emit_op_dst(compiler, SLJIT_GET_RETURN_ADDRESS, SLJIT_MEM2(SLJIT_S2, SLJIT_R0), 1); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - return_addr = sljit_get_label_addr(label); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)buf); - - FAILED(buf[0] != return_addr, "test86 case 3 failed\n"); - sljit_free_code(code.code, NULL); - - /* Next test. */ - - buf[0] = 0; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, W_R), 1, 0, 0, 0, 0); - jump = sljit_emit_call(compiler, SLJIT_CALL_REG_ARG, SLJIT_ARGS1(VOID, W)); - label = sljit_emit_label(compiler); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, SLJIT_ENTER_REG_ARG, SLJIT_ARGS1(VOID, W_R), 1, SLJIT_NUMBER_OF_SAVED_REGISTERS >> 1, 0, 0, 64); - sljit_emit_op_dst(compiler, SLJIT_GET_RETURN_ADDRESS, SLJIT_MEM1(SLJIT_SP), 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), 0, SLJIT_MEM1(SLJIT_SP), 0); - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - return_addr = sljit_get_label_addr(label); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)buf); - - FAILED(buf[0] != return_addr, "test86 case 4 failed\n"); - sljit_free_code(code.code, NULL); - - if (sljit_has_cpu_feature(SLJIT_HAS_FPU) && SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS > 0) { - /* Next test. */ - - buf[0] = 0; - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, W), 1, 1, 0, 0, 0); - jump = sljit_emit_call(compiler, SLJIT_CALL, SLJIT_ARGS0(W)); - label = sljit_emit_label(compiler); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_RETURN_REG, 0); - sljit_emit_return_void(compiler); - - sljit_set_label(jump, sljit_emit_label(compiler)); - sljit_emit_enter(compiler, 0, SLJIT_ARGS0(W), 1, 3, 0, SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS, 64); - sljit_emit_op_dst(compiler, SLJIT_GET_RETURN_ADDRESS, SLJIT_RETURN_REG, 0); - sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - return_addr = sljit_get_label_addr(label); - sljit_free_compiler(compiler); - - code.func1((sljit_sw)buf); - - FAILED(buf[0] != return_addr, "test86 case 5 failed\n"); - sljit_free_code(code.code, NULL); - } - - successful_tests++; -} - -static void test87(void) -{ - /* Test reverse bytes. */ - executable_code code; - struct sljit_compiler* compiler = sljit_create_compiler(NULL, NULL); - sljit_sw buf[5]; - sljit_s32 ibuf[5]; - sljit_s32 i; - - if (verbose) - printf("Run test87\n"); - - FAILED(!compiler, "cannot create compiler\n"); - - for (i = 0; i < 5; i++) - buf[i] = -1; - for (i = 0; i < 5; i++) - ibuf[i] = -1; - - buf[3] = WCONST(0x8070605040302010, 0x40302010); - ibuf[1] = (sljit_s32)0xffeeddcc; - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W, W), 5, 5, 0, 0, 2 * sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, WCONST(0xf1e2d3c4b5a69788, 0xf1e2d3c4)); - sljit_emit_op1(compiler, SLJIT_REV, SLJIT_R0, 0, SLJIT_R0, 0); - /* buf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, WCONST(0xffeeddccbbaa9988, 0xffeeddcc)); - sljit_emit_op1(compiler, SLJIT_REV, SLJIT_R2, 0, SLJIT_R4, 0); - /* buf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw), SLJIT_R2, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, WCONST(0x0102030405060708, 0x01020304)); - /* buf[2] */ - sljit_emit_op1(compiler, SLJIT_REV, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_sw), SLJIT_S2, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 3); - sljit_emit_op1(compiler, SLJIT_REV, SLJIT_R4, 0, SLJIT_MEM2(SLJIT_S0, SLJIT_R0), SLJIT_WORD_SHIFT); - /* buf[3] */ - sljit_emit_op1(compiler, SLJIT_REV, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_sw), SLJIT_R4, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_S2, 0, SLJIT_IMM, WCONST(0x1122334455667788, 0x11223344)); - /* buf[4] */ - sljit_emit_op1(compiler, SLJIT_REV, SLJIT_MEM0(), (sljit_sw)&buf[4], SLJIT_S2, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_IMM, (sljit_s32)0xf1e2d3c4); - sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_R1, 0, SLJIT_R0, 0); - /* ibuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 0, SLJIT_R1, 0); - - sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R2, 0, SLJIT_S1, 0, SLJIT_IMM, 0x12340 + sizeof(sljit_s32)); - sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R2), -0x12340); - /* ibuf[1] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_s32), SLJIT_R2, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_IMM, 2); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, (sljit_s32)0x01020304); - /* ibuf[2] */ - sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_MEM2(SLJIT_S1, SLJIT_R0), 2, SLJIT_R4, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R4, 0, SLJIT_IMM, (sljit_s32)0x11223344); - sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_R4, 0, SLJIT_R4, 0); - /* ibuf[3] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_S1), 3 * sizeof(sljit_s32), SLJIT_R4, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, (sljit_s32)0xfeeddccb); - /* ibuf[4] */ - sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_MEM1(SLJIT_S1), 4 * sizeof(sljit_s32), SLJIT_MEM1(SLJIT_SP), 0); - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func2((sljit_sw)buf, (sljit_sw)ibuf); - - FAILED(buf[0] != WCONST(0x8897a6b5c4d3e2f1, 0xc4d3e2f1), "test87 case 1 failed\n"); - FAILED(buf[1] != WCONST(0x8899aabbccddeeff, 0xccddeeff), "test87 case 2 failed\n"); - FAILED(buf[2] != WCONST(0x0807060504030201, 0x04030201), "test87 case 3 failed\n"); - FAILED(buf[3] != WCONST(0x8070605040302010, 0x40302010), "test87 case 4 failed\n"); - FAILED(buf[4] != WCONST(0x8877665544332211, 0x44332211), "test87 case 5 failed\n"); - FAILED(ibuf[0] != (sljit_s32)0xc4d3e2f1, "test87 case 6 failed\n"); - FAILED(ibuf[1] != (sljit_s32)0xccddeeff, "test87 case 7 failed\n"); - FAILED(ibuf[2] != (sljit_s32)0x04030201, "test87 case 8 failed\n"); - FAILED(ibuf[3] != (sljit_s32)0x44332211, "test87 case 9 failed\n"); - FAILED(ibuf[4] != (sljit_s32)0xcbdcedfe, "test87 case 10 failed\n"); - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -static void test88(void) -{ - /* Test sljit_emit_fcopy. */ - executable_code code; - struct sljit_compiler* compiler; - sljit_f64 dbuf[4]; - sljit_f32 sbuf[2]; -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_sw wbuf[2]; - sljit_s32 ibuf[2]; -#else /* !SLJIT_64BIT_ARCHITECTURE */ - sljit_s32 ibuf[7]; -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - if (verbose) - printf("Run test88\n"); - - if (!sljit_has_cpu_feature(SLJIT_HAS_FPU)) { - if (verbose) - printf("no fpu available, test88 skipped\n"); - successful_tests++; - return; - } - - compiler = sljit_create_compiler(NULL, NULL); - FAILED(!compiler, "cannot create compiler\n"); - - sbuf[0] = 12345.0; - sbuf[1] = -1.0; - ibuf[0] = -1; - ibuf[1] = (sljit_s32)0xc7543100; - dbuf[0] = 123456789012345.0; - dbuf[1] = -1.0; -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - wbuf[0] = -1; - wbuf[1] = (sljit_sw)0xc2fee0c29f50cb10; -#else /* !SLJIT_64BIT_ARCHITECTURE */ - ibuf[2] = -1; - ibuf[3] = -1; - ibuf[4] = -1; - ibuf[5] = (sljit_sw)0x9f50cb10; - ibuf[6] = (sljit_sw)0xc2fee0c2; -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - sljit_emit_enter(compiler, 0, SLJIT_ARGS2(VOID, W, W), 5, 5, 5, 0, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)ibuf); - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_FR2, 0, SLJIT_MEM1(SLJIT_S1), 0); - sljit_emit_fcopy(compiler, SLJIT_COPY32_FROM_F32, SLJIT_FR2, SLJIT_R0); - /* ibuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R3, 0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_s32)); - sljit_emit_fcopy(compiler, SLJIT_COPY32_TO_F32, SLJIT_FR4, SLJIT_R3); - /* sbuf[1] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F32, SLJIT_MEM1(SLJIT_S1), sizeof(sljit_f32), SLJIT_FR4, 0); - -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)wbuf); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_fcopy(compiler, SLJIT_COPY_FROM_F64, SLJIT_FR1, SLJIT_S2); - /* wbuf[0] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_S2, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)); - sljit_emit_fcopy(compiler, SLJIT_COPY_TO_F64, SLJIT_FR0, SLJIT_R3); - /* dbuf[1] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64), SLJIT_FR0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0); - sljit_emit_fcopy(compiler, SLJIT_COPY_TO_F64, SLJIT_FR3, SLJIT_R2); - /* dbuf[2] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR3, 0); -#else /* !SLJIT_64BIT_ARCHITECTURE */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_FR1, 0, SLJIT_MEM1(SLJIT_S0), 0); - sljit_emit_fcopy(compiler, SLJIT_COPY_FROM_F64, SLJIT_FR1, SLJIT_REG_PAIR(SLJIT_S3, SLJIT_S2)); - /* ibuf[2-3] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(sljit_sw), SLJIT_S2, 0); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 3 * sizeof(sljit_sw), SLJIT_S3, 0); - - sljit_emit_fcopy(compiler, SLJIT_COPY_FROM_F64, SLJIT_FR1, SLJIT_R2); - /* ibuf[4] */ - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 4 * sizeof(sljit_sw), SLJIT_R2, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R3, 0, SLJIT_MEM1(SLJIT_R1), 5 * sizeof(sljit_sw)); - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), 6 * sizeof(sljit_sw)); - sljit_emit_fcopy(compiler, SLJIT_COPY_TO_F64, SLJIT_FR0, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R3)); - /* dbuf[1] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_f64), SLJIT_FR0, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 0); - sljit_emit_fcopy(compiler, SLJIT_COPY_TO_F64, SLJIT_FR3, SLJIT_REG_PAIR(SLJIT_R2, SLJIT_R2)); - /* dbuf[2] */ - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 2 * sizeof(sljit_f64), SLJIT_FR3, 0); - - sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, (sljit_sw)0xc00c0000); - sljit_emit_fcopy(compiler, SLJIT_COPY_TO_F64, SLJIT_FR3, SLJIT_R2); - sljit_emit_fop1(compiler, SLJIT_MOV_F64, SLJIT_MEM1(SLJIT_S0), 3 * sizeof(sljit_f64), SLJIT_FR3, 0); -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - sljit_emit_return_void(compiler); - - code.code = sljit_generate_code(compiler); - CHECK(compiler); - sljit_free_compiler(compiler); - - code.func2((sljit_sw)dbuf, (sljit_sw)sbuf); - - FAILED(ibuf[0] != (sljit_s32)0x4640e400, "test88 case 1 failed\n"); - FAILED(sbuf[1] != -54321.0, "test88 case 2 failed\n"); -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) - FAILED(wbuf[0] != (sljit_sw)0x42dc12218377de40, "test88 case 3 failed\n"); - FAILED(dbuf[1] != -543210987654321.0, "test88 case 4 failed\n"); - FAILED(dbuf[2] != 0.0, "test88 case 5 failed\n"); -#else /* !SLJIT_64BIT_ARCHITECTURE */ - FAILED(ibuf[2] != (sljit_sw)0x8377de40, "test88 case 3 failed\n"); - FAILED(ibuf[3] != (sljit_sw)0x42dc1221, "test88 case 4 failed\n"); - FAILED(ibuf[4] != (sljit_sw)0x42dc1221, "test88 case 5 failed\n"); - FAILED(dbuf[1] != -543210987654321.0, "test88 case 6 failed\n"); - FAILED(dbuf[2] != 0.0, "test88 case 7 failed\n"); - FAILED(dbuf[3] != -3.5, "test88 case 8 failed\n"); -#endif /* SLJIT_64BIT_ARCHITECTURE */ - - sljit_free_code(code.code, NULL); - successful_tests++; -} - -int sljit_test(int argc, char* argv[]) -{ - sljit_s32 has_arg = (argc >= 2 && argv[1][0] == '-' && argv[1][2] == '\0'); - verbose = has_arg && argv[1][1] == 'v'; - silent = has_arg && argv[1][1] == 's'; - - if (!verbose && !silent) - printf("Pass -v to enable verbose, -s to disable this hint.\n\n"); - -#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) - test_exec_allocator(); -#endif - test1(); - test2(); - test3(); - test4(); - test5(); - test6(); - test7(); - test8(); - test9(); - test10(); - test11(); - test12(); - test13(); - test14(); - test15(); - test16(); - test17(); - test18(); - test19(); - test20(); - test21(); - test22(); - test23(); - test24(); - test25(); - test26(); - test27(); - test28(); - test29(); - test30(); - test31(); - test32(); - test33(); - test34(); - test35(); - test36(); - test37(); - test38(); - test39(); - test40(); - test41(); - test42(); - test43(); - test44(); - test45(); - test46(); - test47(); - test48(); - test49(); - test50(); - test51(); - test52(); - test53(); - test54(); - test55(); - test56(); - test57(); - test58(); - test59(); - test60(); - test61(); - test62(); - test63(); - test64(); - test65(); - test66(); - test67(); - test68(); - test69(); - test70(); - test71(); - test72(); - test73(); - test74(); - test75(); - test76(); - test77(); - test78(); - test79(); - test80(); - test81(); - test82(); - test83(); - test84(); - test85(); - test86(); - test87(); - test88(); - -#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) - sljit_free_unused_memory_exec(); -#endif - -# define TEST_COUNT 88 - - printf("SLJIT tests: "); - if (successful_tests == TEST_COUNT) - printf("all tests are " COLOR_GREEN "PASSED" COLOR_DEFAULT " "); - else - printf(COLOR_RED "%d" COLOR_DEFAULT " (" COLOR_RED "%d%%" COLOR_DEFAULT ") tests are " COLOR_RED "FAILED" COLOR_DEFAULT " ", TEST_COUNT - successful_tests, (TEST_COUNT - successful_tests) * 100 / TEST_COUNT); - printf("on " COLOR_ARCH "%s" COLOR_DEFAULT "%s\n", sljit_get_platform_name(), sljit_has_cpu_feature(SLJIT_HAS_FPU) ? " (with fpu)" : " (without fpu)"); - - return TEST_COUNT - successful_tests; - -# undef TEST_COUNT -} - -#ifdef _MSC_VER -#pragma warning(pop) -#endif diff --git a/waterbox/ares64/ares/thirdparty/sljitAllocator.cpp b/waterbox/ares64/ares/thirdparty/sljitAllocator.cpp index 3e5b7e338cc..0d8146d6f98 100644 --- a/waterbox/ares64/ares/thirdparty/sljitAllocator.cpp +++ b/waterbox/ares64/ares/thirdparty/sljitAllocator.cpp @@ -5,5 +5,5 @@ auto sljit_nall_malloc_exec(sljit_uw size, void* exec_allocator_data) -> void* { auto allocator = (nall::bump_allocator*)exec_allocator_data; - return allocator->acquire(size); + return allocator->tryAcquire(size, false); } diff --git a/waterbox/common.mak b/waterbox/common.mak index 5595b793b29..53d0448d5e1 100644 --- a/waterbox/common.mak +++ b/waterbox/common.mak @@ -124,7 +124,8 @@ install: $(TARGET_RELEASE) install-debug: $(TARGET_DEBUG) @cp -f $< $(OUTPUTDLL_DIR) - @cp $(OUTPUTDLL_DIR)/$(TARGET) $(OUTPUTDLLCOPY_DIR)/$(TARGET) 2> /dev/null || true + @zstd --stdout -1 --threads=0 $< > $(OUTPUTDLL_DIR)/$(TARGET).zst + @cp $(OUTPUTDLL_DIR)/$(TARGET).zst $(OUTPUTDLLCOPY_DIR)/$(TARGET).zst 2> /dev/null || true @echo Debug build of $(TARGET) installed. else diff --git a/waterbox/gpgx/cinterface/cinterface.c b/waterbox/gpgx/cinterface/cinterface.c index 15aff3376c6..52b6aa55f80 100644 --- a/waterbox/gpgx/cinterface/cinterface.c +++ b/waterbox/gpgx/cinterface/cinterface.c @@ -715,6 +715,7 @@ struct InitSettings { uint32_t BackdropColor; int32_t Region; + int32_t ForceVDP; uint16_t LowPassRange; int16_t LowFreq; int16_t HighFreq; @@ -917,8 +918,8 @@ GPGX_EX int gpgx_init(const char* feromextension, /* system options */ config.system = 0; /* = AUTO (or SYSTEM_SG, SYSTEM_SGII, SYSTEM_SGII_RAM_EXT, SYSTEM_MARKIII, SYSTEM_SMS, SYSTEM_SMS2, SYSTEM_GG, SYSTEM_MD) */ - config.region_detect = settings->Region; /* = AUTO (1 = USA, 2 = EUROPE, 3 = JAPAN/NTSC, 4 = JAPAN/PAL) */ - config.vdp_mode = 0; /* = AUTO (1 = NTSC, 2 = PAL) */ + config.region_detect = settings->Region; /* 0 = AUTO, 1 = USA, 2 = EUROPE, 3 = JAPAN/NTSC, 4 = JAPAN/PAL */ + config.vdp_mode = settings->ForceVDP; /* 0 = AUTO, 1 = NTSC, 2 = PAL */ config.master_clock = 0; /* = AUTO (1 = NTSC, 2 = PAL) */ config.force_dtack = 0; config.addr_error = 1; diff --git a/waterbox/gpgx/util/osd.h b/waterbox/gpgx/util/osd.h index 665b101ae6d..152f28f0113 100644 --- a/waterbox/gpgx/util/osd.h +++ b/waterbox/gpgx/util/osd.h @@ -23,6 +23,13 @@ #define M_PI 3.1415926535897932385 #endif +#define HAVE_NO_SPRITE_LIMIT +#define MAX_SPRITES_PER_LINE 80 +#define TMS_MAX_SPRITES_PER_LINE (config.no_sprite_limit ? MAX_SPRITES_PER_LINE : 4) +#define MODE4_MAX_SPRITES_PER_LINE (config.no_sprite_limit ? MAX_SPRITES_PER_LINE : 8) +#define MODE5_MAX_SPRITES_PER_LINE (config.no_sprite_limit ? MAX_SPRITES_PER_LINE : (bitmap.viewport.w >> 4)) +#define MODE5_MAX_SPRITE_PIXELS (config.no_sprite_limit ? MAX_SPRITES_PER_LINE * 32 : max_sprite_pixels) + typedef struct { int8_t device; diff --git a/waterbox/libcxx/readme.txt b/waterbox/libcxx/readme.txt index a1e72ab9154..87a982e867b 100644 --- a/waterbox/libcxx/readme.txt +++ b/waterbox/libcxx/readme.txt @@ -1,6 +1,6 @@ Building and installing libcxx: 1. Run ./do-everything.sh - * This will initialize and update the llvm-project submodule if you haven't already done that + * This will initialize and/or update the llvm-project build dependency (see setup-llvm.sh) * This isn't resumable at all, so if it crashes or you're curious about the process, read its source and execute the commands individually. diff --git a/waterbox/libcxx/setup-llvm.sh b/waterbox/libcxx/setup-llvm.sh index e8b1cc6ab9f..d107f3d37af 100755 --- a/waterbox/libcxx/setup-llvm.sh +++ b/waterbox/libcxx/setup-llvm.sh @@ -3,19 +3,13 @@ set -e LLVM_TAG=llvmorg-18.1.3 LLVM_DIRS="cmake compiler-rt libunwind libcxx libcxxabi runtimes" LLVM_PATH=../llvm-project -LLVM_GIT_DIR=$(git rev-parse --git-path modules/waterbox/llvm-project) if [ ! -e "$LLVM_PATH/.git" ] || ! git -C "$LLVM_PATH" rev-parse $LLVM_TAG > /dev/null 2>&1; then rm -rf "$LLVM_PATH" - git submodule deinit -f "$LLVM_PATH" - rm -rf "$LLVM_GIT_DIR" fi if [ ! -e "$LLVM_PATH/.git" ]; then - git submodule init "$LLVM_PATH" - git clone --separate-git-dir="$LLVM_GIT_DIR" --filter=tree:0 --sparse https://github.com/llvm/llvm-project.git "$LLVM_PATH" - rm "$LLVM_PATH/.git" - printf "%s\n" "gitdir: $LLVM_GIT_DIR" > "$LLVM_PATH/.git" + git clone --filter=tree:0 --sparse https://github.com/llvm/llvm-project.git "$LLVM_PATH" fi cd "$LLVM_PATH" diff --git a/waterbox/linkscript.T b/waterbox/linkscript.T index ec147f144e0..b9f33eec6b9 100644 --- a/waterbox/linkscript.T +++ b/waterbox/linkscript.T @@ -204,7 +204,7 @@ SECTIONS *(.lbss .lbss.* .gnu.linkonce.lb.*) *(LARGE_COMMON) } - . = ALIGN(64 / 4); + . = ALIGN(64); . = SEGMENT_START("ldata-segment", .); .lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : { diff --git a/waterbox/llvm-project b/waterbox/llvm-project deleted file mode 160000 index c13b7485b87..00000000000 --- a/waterbox/llvm-project +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c13b7485b87909fcf739f62cfa382b55407433c0 diff --git a/waterbox/make-all-cores.sh b/waterbox/make-all-cores.sh index ac94da3e21a..d98001f416a 100755 --- a/waterbox/make-all-cores.sh +++ b/waterbox/make-all-cores.sh @@ -11,6 +11,7 @@ cd melon && make -f Makefile $1 -j && cd - cd picodrive && make -f Makefile $1 -j && cd - cd snes9x && make -f Makefile $1 -j && cd - cd tic80 && make -f Makefile $1 -j && cd - +cd uae && make -f Makefile $1 -j && cd - cd uzem && make -f Makefile $1 -j && cd - cd virtualjaguar && make -f Makefile $1 -j && cd - cd nyma && ./make-all-released-cores.sh $1 && cd - diff --git a/waterbox/melon/BizConsoleCreator.cpp b/waterbox/melon/BizConsoleCreator.cpp new file mode 100644 index 00000000000..28b3eec5555 --- /dev/null +++ b/waterbox/melon/BizConsoleCreator.cpp @@ -0,0 +1,789 @@ +#include "NDS.h" +#include "NDSCart.h" +#include "DSi.h" +#include "DSi_NAND.h" +#include "DSi_TMD.h" +#include "GPU3D_OpenGL.h" +#include "GPU3D_Compute.h" +#include "CRC32.h" +#include "FreeBIOS.h" +#include "SPI.h" + +#include "BizPlatform/BizFile.h" +#include "BizTypes.h" + +extern melonDS::NDS* CurrentNDS; + +namespace ConsoleCreator +{ + +struct FirmwareSettings +{ + bool OverrideSettings; + int UsernameLength; + char16_t Username[10]; + int Language; + int BirthdayMonth; + int BirthdayDay; + int Color; + int MessageLength; + char16_t Message[26]; + u8 MacAddress[6]; +}; + +template +static std::unique_ptr CreateBiosImage(u8* biosData, u32 biosLength, std::optional biosFallback = std::nullopt) +{ + auto bios = std::make_unique(); + if (biosData) + { + if (biosLength != bios->size()) + { + throw std::runtime_error("Invalid BIOS size"); + } + + memcpy(bios->data(), biosData, bios->size()); + } + else + { + if (!biosFallback) + { + throw std::runtime_error("Failed to load BIOS"); + } + + memcpy(bios->data(), biosFallback->data(), bios->size()); + } + + return std::move(bios); +} + +static void SanitizeExternalFirmware(melonDS::Firmware& firmware) +{ + auto& header = firmware.GetHeader(); + + const bool isDSiFw = header.ConsoleType == melonDS::Firmware::FirmwareConsoleType::DSi; + const auto defaultHeader = melonDS::Firmware::FirmwareHeader{isDSiFw}; + + // the user data offset won't necessarily be 0x7FE00 & Mask, DSi/iQue use 0x7FC00 & Mask instead + // but we don't want to crash due to an invalid offset + const auto maxUserDataOffset = 0x7FE00 & firmware.Mask(); + if (firmware.GetUserDataOffset() > maxUserDataOffset) + { + header.UserSettingsOffset = maxUserDataOffset >> 3; + } + + if (isDSiFw) + { + memset(&header.Bytes[0x22], 0x00, 6); + memset(&header.Bytes[0x28], 0xFF, 2); + } + + memcpy(&header.Bytes[0x2C], &defaultHeader.Bytes[0x2C], 0x136); + memset(&header.Bytes[0x162], 0xFF, 0x9E); + + if (isDSiFw) + { + header.WifiBoard = defaultHeader.WifiBoard; + header.WifiFlash = defaultHeader.WifiFlash; + } + + header.UpdateChecksum(); + + auto& aps = firmware.GetAccessPoints(); + aps[0] = melonDS::Firmware::WifiAccessPoint{isDSiFw}; + aps[1] = melonDS::Firmware::WifiAccessPoint{}; + aps[2] = melonDS::Firmware::WifiAccessPoint{}; + + if (isDSiFw) + { + auto& exAps = firmware.GetExtendedAccessPoints(); + exAps[0] = melonDS::Firmware::ExtendedWifiAccessPoint{}; + exAps[1] = melonDS::Firmware::ExtendedWifiAccessPoint{}; + exAps[2] = melonDS::Firmware::ExtendedWifiAccessPoint{}; + } +} + +static void FixFirmwareTouchscreenCalibration(melonDS::Firmware::UserData& userData) +{ + userData.TouchCalibrationADC1[0] = 0; + userData.TouchCalibrationADC1[1] = 0; + userData.TouchCalibrationPixel1[0] = 0; + userData.TouchCalibrationPixel1[1] = 0; + userData.TouchCalibrationADC2[0] = 255 << 4; + userData.TouchCalibrationADC2[1] = 191 << 4; + userData.TouchCalibrationPixel2[0] = 255; + userData.TouchCalibrationPixel2[1] = 191; +} + +static void SetFirmwareSettings(melonDS::Firmware::UserData& userData, FirmwareSettings& fwSettings) +{ + memset(userData.Bytes, 0, 0x74); + + userData.Version = 5; + FixFirmwareTouchscreenCalibration(userData); + + userData.NameLength = fwSettings.UsernameLength; + memcpy(userData.Nickname, fwSettings.Username, sizeof(fwSettings.Username)); + userData.Settings = fwSettings.Language | melonDS::Firmware::BacklightLevel::Max | 0xEC00; + userData.BirthdayMonth = fwSettings.BirthdayMonth; + userData.BirthdayDay = fwSettings.BirthdayDay; + userData.FavoriteColor = fwSettings.Color; + userData.MessageLength = fwSettings.MessageLength; + memcpy(userData.Message, fwSettings.Message, sizeof(fwSettings.Message)); + + if (userData.ExtendedSettings.Unknown0 == 1) + { + userData.ExtendedSettings.ExtendedLanguage = static_cast(fwSettings.Language & melonDS::Firmware::Language::Reserved); + memset(userData.ExtendedSettings.Unused0, 0, sizeof(userData.ExtendedSettings.Unused0)); + + if (!((1 << static_cast(userData.ExtendedSettings.ExtendedLanguage)) & userData.ExtendedSettings.SupportedLanguageMask)) + { + // Use the first supported language + for (int i = 0; i <= melonDS::Firmware::Language::Reserved; i++) + { + if ((1 << i) & userData.ExtendedSettings.SupportedLanguageMask) + { + userData.ExtendedSettings.ExtendedLanguage = static_cast(i); + break; + } + } + + userData.Settings &= ~melonDS::Firmware::Language::Reserved; + userData.Settings |= userData.ExtendedSettings.ExtendedLanguage; + } + } + else + { + memset(userData.Unused3, 0xFF, sizeof(userData.Unused3)); + } + + // only extended settings should have Chinese / Korean + // note that melonDS::Firmware::Language::Reserved is Korean, so it's valid to have language set to that + if ((userData.Settings & melonDS::Firmware::Language::Reserved) >= melonDS::Firmware::Language::Chinese) + { + userData.Settings &= ~melonDS::Firmware::Language::Reserved; + userData.Settings |= melonDS::Firmware::Language::English; + } +} + +static melonDS::Firmware CreateFirmware(u8* fwData, u32 fwLength, bool dsi, FirmwareSettings& fwSettings) +{ + melonDS::Firmware firmware{dsi}; + + if (fwData) + { + firmware = melonDS::Firmware{fwData, fwLength}; + + if (firmware.Buffer()) + { + // sanitize header, wifi calibration, and AP points + SanitizeExternalFirmware(firmware); + } + } + else + { + fwSettings.OverrideSettings = true; + } + + if (!firmware.Buffer()) + { + throw std::runtime_error("Failed to load firmware!"); + } + + for (auto& userData : firmware.GetUserData()) + { + FixFirmwareTouchscreenCalibration(userData); + userData.UpdateChecksum(); + } + + if (fwSettings.OverrideSettings) + { + for (auto& userData : firmware.GetUserData()) + { + SetFirmwareSettings(userData, fwSettings); + userData.UpdateChecksum(); + } + + melonDS::MacAddress mac; + static_assert(mac.size() == sizeof(fwSettings.MacAddress)); + memcpy(mac.data(), fwSettings.MacAddress, mac.size()); + auto& header = firmware.GetHeader(); + header.MacAddr = mac; + header.UpdateChecksum(); + } + + return firmware; +} + +static u8 GetDefaultCountryCode(melonDS::DSi_NAND::ConsoleRegion region) +{ + // TODO: CountryCode probably should be configurable + // these defaults are also completely arbitrary + switch (region) + { + case melonDS::DSi_NAND::ConsoleRegion::Japan: return 0x01; // Japan + case melonDS::DSi_NAND::ConsoleRegion::USA: return 0x31; // United States + case melonDS::DSi_NAND::ConsoleRegion::Europe: return 0x6E; // United Kingdom + case melonDS::DSi_NAND::ConsoleRegion::Australia: return 0x41; // Australia + case melonDS::DSi_NAND::ConsoleRegion::China: return 0xA0; // China + case melonDS::DSi_NAND::ConsoleRegion::Korea: return 0x88; // Korea + default: return 0x31; // ??? + } +} + +static void SanitizeNandSettings(melonDS::DSi_NAND::DSiFirmwareSystemSettings& settings, melonDS::DSi_NAND::ConsoleRegion region) +{ + memset(settings.Zero00, 0, sizeof(settings.Zero00)); + settings.Version = 1; + settings.UpdateCounter = 0; + memset(settings.Zero01, 0, sizeof(settings.Zero01)); + settings.BelowRAMAreaSize = 0x128; + // bit 0-1 are unknown (but usually 1) + // bit 2 indicates language set (?) + // bit 3 is wifi enable (really wifi LED enable; usually set) + // bit 24 set will indicate EULA is "agreed" to + settings.ConfigFlags = 0x0100000F; + settings.Zero02 = 0; + settings.CountryCode = GetDefaultCountryCode(region); + settings.RTCYear = 0; + settings.RTCOffset = 0; + memset(settings.Zero3, 0, sizeof(settings.Zero3)); + settings.EULAVersion = 1; + memset(settings.Zero04, 0, sizeof(settings.Zero04)); + settings.AlarmHour = 0; + settings.AlarmMinute = 0; + memset(settings.Zero05, 0, sizeof(settings.Zero05)); + settings.AlarmEnable = false; + memset(settings.Zero06, 0, sizeof(settings.Zero06)); + settings.Unknown0 = 0; + settings.Unknown1 = 3; // apparently 2 or 3 + memset(settings.Zero07, 0, sizeof(settings.Zero07)); + settings.SystemMenuMostRecentTitleID.fill(0); + settings.Unknown2[0] = 0x9C; + settings.Unknown2[1] = 0x20; + settings.Unknown2[2] = 0x01; + settings.Unknown2[3] = 0x02; + memset(settings.Zero08, 0, sizeof(settings.Zero08)); + settings.Zero09 = 0; + settings.ParentalControlsFlags = 0; + memset(settings.Zero10, 0, sizeof(settings.Zero10)); + settings.ParentalControlsRegion = 0; + settings.ParentalControlsYearsOfAgeRating = 0; + settings.ParentalControlsSecretQuestion = 0; + settings.Unknown3 = 0; // apparently 0 or 6 or 7 + memset(settings.Zero11, 0, sizeof(settings.Zero11)); + memset(settings.ParentalControlsPIN, 0, sizeof(settings.ParentalControlsPIN)); + memset(settings.ParentalControlsSecretAnswer, 0, sizeof(settings.ParentalControlsSecretAnswer)); +} + +static void ClearNandSavs(melonDS::DSi_NAND::NANDMount& mount, u32 category) +{ + std::vector titlelist; + mount.ListTitles(category, titlelist); + + char fname[128]; + for (auto& title : titlelist) + { + snprintf(fname, sizeof(fname), "0:/title/%08x/%08x/data/public.sav", category, title); + mount.RemoveFile(fname); + snprintf(fname, sizeof(fname), "0:/title/%08x/%08x/data/private.sav", category, title); + mount.RemoveFile(fname); + snprintf(fname, sizeof(fname), "0:/title/%08x/%08x/data/banner.sav", category, title); + mount.RemoveFile(fname); + } +} + + +static melonDS::DSi_NAND::NANDImage CreateNandImage( + u8* nandData, u32 nandLength, std::unique_ptr& arm7Bios, + FirmwareSettings& fwSettings, bool clearNand, + u8* dsiWareData, u32 dsiWareLength, u8* tmdData, u32 tmdLength) +{ + auto nand = melonDS::DSi_NAND::NANDImage{melonDS::Platform::CreateMemoryFile(nandData, nandLength), &arm7Bios->data()[0x8308]}; + if (!nand) + { + throw std::runtime_error("Failed to parse DSi NAND!"); + } + + { + auto mount = melonDS::DSi_NAND::NANDMount(nand); + if (!mount) + { + throw std::runtime_error("Failed to mount DSi NAND!"); + } + + melonDS::DSi_NAND::DSiFirmwareSystemSettings settings{}; + if (!mount.ReadUserData(settings)) + { + throw std::runtime_error("Failed to read DSi NAND user data"); + } + + // serial data will contain the NAND's region + melonDS::DSi_NAND::DSiSerialData serialData; + if (!mount.ReadSerialData(serialData)) + { + throw std::runtime_error("Failed to obtain serial data!"); + } + + if (fwSettings.OverrideSettings) + { + SanitizeNandSettings(settings, serialData.Region); + memset(settings.Nickname, 0, sizeof(settings.Nickname)); + memcpy(settings.Nickname, fwSettings.Username, fwSettings.UsernameLength * 2); + settings.Language = static_cast(fwSettings.Language & melonDS::Firmware::Language::Reserved); + settings.FavoriteColor = fwSettings.Color; + settings.BirthdayMonth = fwSettings.BirthdayMonth; + settings.BirthdayDay = fwSettings.BirthdayDay; + memset(settings.Message, 0, sizeof(settings.Message)); + memcpy(settings.Message, fwSettings.Message, fwSettings.MessageLength * 2); + + if (!((1 << static_cast(settings.Language)) & serialData.SupportedLanguages)) + { + // Use the first supported language + for (int i = 0; i <= melonDS::Firmware::Language::Reserved; i++) + { + if ((1 << i) & serialData.SupportedLanguages) + { + settings.Language = static_cast(i); + break; + } + } + } + } + + settings.TouchCalibrationADC1[0] = 0; + settings.TouchCalibrationADC1[1] = 0; + settings.TouchCalibrationPixel1[0] = 0; + settings.TouchCalibrationPixel1[1] = 0; + settings.TouchCalibrationADC2[0] = 255 << 4; + settings.TouchCalibrationADC2[1] = 191 << 4; + settings.TouchCalibrationPixel2[0] = 255; + settings.TouchCalibrationPixel2[1] = 191; + + settings.UpdateHash(); + + if (!mount.ApplyUserData(settings)) + { + throw std::runtime_error("Failed to write DSi NAND user data"); + } + + if (clearNand) + { + // clear out DSiWare + constexpr u32 DSIWARE_CATEGORY = 0x00030004; + + std::vector titlelist; + mount.ListTitles(DSIWARE_CATEGORY, titlelist); + + for (auto& title : titlelist) + { + mount.DeleteTitle(DSIWARE_CATEGORY, title); + } + + // clear out .sav files of builtin apps / title management / system menu + constexpr u32 BUILTIN_APP_CATEGORY = 0x00030005; + constexpr u32 TITLE_MANAGEMENT_CATEGORY = 0x00030015; + constexpr u32 SYSTEM_MENU_CATEGORY = 0x00030017; + + ClearNandSavs(mount, BUILTIN_APP_CATEGORY); + ClearNandSavs(mount, TITLE_MANAGEMENT_CATEGORY); + ClearNandSavs(mount, SYSTEM_MENU_CATEGORY); + + // clear out some other misc files + mount.RemoveFile("0:/shared2/launcher/wrap.bin"); + mount.RemoveFile("0:/shared2/0000"); + mount.RemoveFile("0:/sys/log/product.log"); + mount.RemoveFile("0:/sys/log/sysmenu.log"); + } + + if (dsiWareData) + { + if (tmdLength != sizeof(melonDS::DSi_TMD::TitleMetadata)) + { + throw std::runtime_error("TMD is the wrong size!"); + } + + melonDS::DSi_TMD::TitleMetadata tmd; + memcpy(&tmd, tmdData, sizeof(melonDS::DSi_TMD::TitleMetadata)); + + if (!mount.ImportTitle(dsiWareData, dsiWareLength, tmd, false)) + { + throw std::runtime_error("Loading DSiWare failed!"); + } + + // verify that the imported title is supported by this NAND + // it will not actually appear otherwise + auto regionFlags = dsiWareLength > 0x1B0 ? dsiWareData[0x1B0] : 0; + if (!(regionFlags & (1 << static_cast(serialData.Region)))) + { + throw std::runtime_error("Loaded NAND region does not support this DSiWare title!"); + } + } + } + + return nand; +} + +enum class GBASaveType +{ + NONE, + SRAM, + EEPROM512, + EEPROM, + FLASH512, + FLASH1M, +}; + +#include "GBASaveOverrides.h" + +static GBASaveType FindGbaSaveType(const u8* gbaRomData, size_t gbaRomSize) +{ + u32 crc = melonDS::CRC32(gbaRomData, gbaRomSize); + if (auto saveOverride = GbaCrcSaveTypeOverrides.find(crc); saveOverride != GbaCrcSaveTypeOverrides.end()) + { + return saveOverride->second; + } + + if (gbaRomSize >= 0xB0) + { + char gameId[4]; + std::memcpy(gameId, &gbaRomData[0xAC], 4); + if (auto saveOverride = GbaGameIdSaveTypeOverrides.find(std::string(gameId, 4)); saveOverride != GbaGameIdSaveTypeOverrides.end()) + { + return saveOverride->second; + } + } + + if (memmem(gbaRomData, gbaRomSize, "EEPROM_V", strlen("EEPROM_V"))) + { + return GBASaveType::EEPROM512; + } + + if (memmem(gbaRomData, gbaRomSize, "SRAM_V", strlen("SRAM_V"))) + { + return GBASaveType::SRAM; + } + + if (memmem(gbaRomData, gbaRomSize, "FLASH_V", strlen("FLASH_V")) + || memmem(gbaRomData, gbaRomSize, "FLASH512_V", strlen("FLASH512_V"))) + { + return GBASaveType::FLASH512; + } + + if (memmem(gbaRomData, gbaRomSize, "FLASH1M_V", strlen("FLASH1M_V"))) + { + return GBASaveType::FLASH1M; + } + + return GBASaveType::NONE; +} + +static std::pair, size_t> CreateBlankGbaSram(const u8* gbaRomData, size_t gbaRomSize) +{ + auto saveType = FindGbaSaveType(gbaRomData, gbaRomSize); + + if (saveType == GBASaveType::NONE) + { + return std::make_pair(nullptr, 0); + } + + size_t size; + switch (saveType) + { + case GBASaveType::SRAM: + size = 0x8000; + break; + case GBASaveType::EEPROM512: + size = 0x200; + break; + case GBASaveType::EEPROM: + size = 0x2000; + break; + case GBASaveType::FLASH512: + size = 0x10000; + break; + case GBASaveType::FLASH1M: + size = 0x20000; + break; + default: + __builtin_unreachable(); + } + + auto data = std::make_unique(size); + memset(data.get(), 0xFF, size); + return std::make_pair(std::move(data), size); +} + +#pragma pack(push, 1) + +struct DSiAutoLoad +{ + u8 ID[4]; // "TLNC" + u8 Unknown1; // "usually 01h" + u8 Length; // starting from PrevTitleId + u16 CRC16; // covering Length bytes ("18h=norm") + u8 PrevTitleID[8]; // can be 0 ("anonymous") + u8 NewTitleID[8]; + u32 Flags; // bit 0: is valid, bit 1-3: boot type ("01h=Cartridge, 02h=Landing, 03h=DSiware"), other bits unknown/unused + u32 Unused1; // this part is typically still checksummed + u8 Unused2[0xE0]; // this part isn't checksummed, but is 0 filled on erasing autoload data +}; + +#pragma pack(pop) + +static_assert(sizeof(DSiAutoLoad) == 0x100, "DSiAutoLoad wrong size"); + +ECL_EXPORT void ResetConsole(melonDS::NDS* nds, bool skipFw, u64 dsiTitleId) +{ + nds->Reset(); + + if (skipFw || nds->NeedsDirectBoot()) + { + if (nds->GetNDSCart()) + { + nds->SetupDirectBoot("nds.rom"); + } + else + { + auto* dsi = static_cast(nds); + + // set warm boot flag + dsi->I2C.GetBPTWL()->SetBootFlag(true); + + // setup "auto-load" feature + DSiAutoLoad dsiAutoLoad; + memset(&dsiAutoLoad, 0, sizeof(dsiAutoLoad)); + memcpy(dsiAutoLoad.ID, "TLNC", sizeof(dsiAutoLoad.ID)); + dsiAutoLoad.Unknown1 = 0x01; + dsiAutoLoad.Length = 0x18; + + for (int i = 0; i < 8; i++) + { + dsiAutoLoad.NewTitleID[i] = dsiTitleId & 0xFF; + dsiTitleId >>= 8; + } + + dsiAutoLoad.Flags |= (0x03 << 1) | 0x01; + dsiAutoLoad.Flags |= (1 << 4); // unknown bit, seems to be required to boot into games (errors otherwise?) + dsiAutoLoad.CRC16 = melonDS::CRC16((u8*)&dsiAutoLoad.PrevTitleID, dsiAutoLoad.Length, 0xFFFF); + memcpy(&nds->MainRAM[0x300], &dsiAutoLoad, sizeof(dsiAutoLoad)); + } + } + + nds->Start(); +} + +struct ConsoleCreationArgs +{ + u8* NdsRomData; + u32 NdsRomLength; + + u8* GbaRomData; + u32 GbaRomLength; + + u8* Arm9BiosData; + u32 Arm9BiosLength; + + u8* Arm7BiosData; + u32 Arm7BiosLength; + + u8* FirmwareData; + u32 FirmwareLength; + + u8* Arm9iBiosData; + u32 Arm9iBiosLength; + + u8* Arm7iBiosData; + u32 Arm7iBiosLength; + + u8* NandData; + u32 NandLength; + + u8* DsiWareData; + u32 DsiWareLength; + + u8* TmdData; + u32 TmdLength; + + bool DSi; + bool ClearNAND; + bool SkipFW; + + int BitDepth; + int Interpolation; + + int ThreeDeeRenderer; + bool Threaded3D; + int ScaleFactor; + bool BetterPolygons; + bool HiResCoordinates; + + int StartYear; // 0-99 + int StartMonth; // 1-12 + int StartDay; // 1-(28/29/30/31 depending on month/year) + int StartHour; // 0-23 + int StartMinute; // 0-59 + int StartSecond; // 0-59 + + FirmwareSettings FwSettings; +}; + +ECL_EXPORT melonDS::NDS* CreateConsole(ConsoleCreationArgs* args, char* error) +{ + try + { + std::unique_ptr ndsRom = nullptr; + if (args->NdsRomData) + { + ndsRom = melonDS::NDSCart::ParseROM(args->NdsRomData, args->NdsRomLength, std::nullopt); + + if (!ndsRom) + { + throw std::runtime_error("Failed to parse NDS ROM"); + } + } + + std::unique_ptr gbaRom = nullptr; + if (args->GbaRomData) + { + auto gbaSram = CreateBlankGbaSram(args->GbaRomData, args->GbaRomLength); + gbaRom = melonDS::GBACart::ParseROM(args->GbaRomData, args->GbaRomLength, gbaSram.first.get(), gbaSram.second); + + if (!gbaRom) + { + throw std::runtime_error("Failed to parse GBA ROM"); + } + } + + auto arm9Bios = CreateBiosImage(args->Arm9BiosData, args->Arm9BiosLength, melonDS::bios_arm9_bin); + auto arm7Bios = CreateBiosImage(args->Arm7BiosData, args->Arm7BiosLength, melonDS::bios_arm7_bin); + auto firmware = CreateFirmware(args->FirmwareData, args->FirmwareLength, args->DSi, args->FwSettings); + + auto bitDepth = static_cast(args->BitDepth); + auto interpolation = static_cast(args->Interpolation); + + std::unique_ptr renderer3d; + switch (args->ThreeDeeRenderer) + { + case 0: + { + auto softRenderer = std::make_unique(); + // SetThreaded needs the nds GPU field, so can't do this now + // softRenderer->SetThreaded(args->Threaded3D, nds->GPU); + renderer3d = std::move(softRenderer); + break; + } + case 1: + { + auto glRenderer = melonDS::GLRenderer::New(); + glRenderer->SetRenderSettings(args->BetterPolygons, args->ScaleFactor); + renderer3d = std::move(glRenderer); + break; + } + case 2: + { + auto computeRenderer = melonDS::ComputeRenderer::New(); + computeRenderer->SetRenderSettings(args->ScaleFactor, args->HiResCoordinates); + renderer3d = std::move(computeRenderer); + break; + } + default: + throw std::runtime_error("Unknown 3DRenderer!"); + } + + int currentShader, shadersCount; + while (renderer3d->NeedsShaderCompile()) + { + renderer3d->ShaderCompileStep(currentShader, shadersCount); + } + + std::unique_ptr nds; + + if (args->DSi) + { + auto arm9iBios = CreateBiosImage(args->Arm9iBiosData, args->Arm9iBiosLength); + auto arm7iBios = CreateBiosImage(args->Arm7iBiosData, args->Arm7iBiosLength); + + // upstream applies this patch to overwrite the reset vector for non-full boots + static const u8 dsiBiosPatch[] = { 0xFE, 0xFF, 0xFF, 0xEA }; + memcpy(arm9iBios->data(), dsiBiosPatch, sizeof(dsiBiosPatch)); + memcpy(arm7iBios->data(), dsiBiosPatch, sizeof(dsiBiosPatch)); + + auto nandImage = CreateNandImage( + args->NandData, args->NandLength, arm7iBios, + args->FwSettings, args->ClearNAND, + args->DsiWareData, args->DsiWareLength, args->TmdData, args->TmdLength); + + melonDS::DSiArgs dsiArgs + { + std::move(ndsRom), + std::move(gbaRom), + std::move(arm9Bios), + std::move(arm7Bios), + std::move(firmware), + std::nullopt, + bitDepth, + interpolation, + std::nullopt, + std::move(renderer3d), + // dsi specific args + std::move(arm9iBios), + std::move(arm7iBios), + std::move(nandImage), + std::nullopt, + false, + }; + + nds = std::make_unique(std::move(dsiArgs)); + } + else + { + melonDS::NDSArgs ndsArgs + { + std::move(ndsRom), + std::move(gbaRom), + std::move(arm9Bios), + std::move(arm7Bios), + std::move(firmware), + std::nullopt, + bitDepth, + interpolation, + std::nullopt, + std::move(renderer3d) + }; + + nds = std::make_unique(std::move(ndsArgs)); + } + + if (args->ThreeDeeRenderer == 0) + { + auto& softRenderer = static_cast(nds->GetRenderer3D()); + softRenderer.SetThreaded(args->Threaded3D, nds->GPU); + } + + nds->RTC.SetDateTime(args->StartYear, args->StartMonth, args->StartDay, + args->StartHour, args->StartMinute, args->StartSecond); + + u64 dsiWareId = 0; + if (args->DsiWareLength >= 0x238) + { + for (int i = 0; i < 8; i++) + { + dsiWareId <<= 8; + dsiWareId |= args->DsiWareData[0x237 - i]; + } + } + + ResetConsole(nds.get(), args->SkipFW, dsiWareId); + + CurrentNDS = nds.release(); + return CurrentNDS; + } + catch (const std::exception& e) + { + strncpy(error, e.what(), 1024); + return nullptr; + } +} + +} diff --git a/waterbox/melon/BizDebugging.cpp b/waterbox/melon/BizDebugging.cpp index 4efe39fce56..9c7ad0ee903 100644 --- a/waterbox/melon/BizDebugging.cpp +++ b/waterbox/melon/BizDebugging.cpp @@ -5,10 +5,13 @@ #include "ARM.h" #include "SPI.h" +#include "BizTypes.h" #include "dthumb.h" #include +melonDS::NDS* CurrentNDS; + void (*InputCallback)() = nullptr; ECL_EXPORT void SetInputCallback(void (*callback)()) @@ -56,7 +59,7 @@ ECL_EXPORT void GetDisassembly(TraceMask_t type, u32 opcode, char* ret) memcpy(ret, disasm, DTHUMB_STRING_LENGTH); } -void TraceTrampoline(TraceMask_t type, u32* regs, u32 opcode) +void TraceTrampoline(TraceMask_t type, u32* regs, u32 opcode, u32 cycleOffset) { static char disasm[DTHUMB_STRING_LENGTH]; @@ -70,31 +73,31 @@ void TraceTrampoline(TraceMask_t type, u32* regs, u32 opcode) default: __builtin_unreachable(); } - TraceCallback(type, opcode, regs, disasm, NDS::GetSysClockCycles(2)); + TraceCallback(type, opcode, regs, disasm, cycleOffset); } -ECL_EXPORT void GetRegs(u32* regs) +ECL_EXPORT void GetRegs(melonDS::NDS* nds, u32* regs) { for (int i = 0; i < 16; i++) { - *regs++ = NDS::ARM9->R[i]; + *regs++ = nds->ARM9.R[i]; } for (int i = 0; i < 16; i++) { - *regs++ = NDS::ARM7->R[i]; + *regs++ = nds->ARM7.R[i]; } } -ECL_EXPORT void SetReg(s32 ncpu, s32 index, s32 val) +ECL_EXPORT void SetReg(melonDS::NDS* nds, s32 ncpu, s32 index, s32 val) { if (ncpu) { - NDS::ARM7->R[index] = val; + nds->ARM7.R[index] = val; } else { - NDS::ARM9->R[index] = val; + nds->ARM9.R[index] = val; } } @@ -142,11 +145,17 @@ Further Memory (not mapped to ARM9/ARM7 bus) */ -template +template static bool SafeToPeek(u32 addr) { if (arm9) { + // dsp io reads are not safe + if ((addr & 0xFFFFFF00) == 0x04004200) + { + return false; + } + switch (addr) { case 0x04000130: @@ -176,42 +185,44 @@ static void ARM9Access(u8* buffer, s64 address, s64 count, bool write) { if (write) { - void (*Write)(u32, u8) = NDS::ConsoleType == 1 ? DSi::ARM9Write8 : NDS::ARM9Write8; while (count--) { - if (address < NDS::ARM9->ITCMSize) + if (address < CurrentNDS->ARM9.ITCMSize) { - NDS::ARM9->ITCM[address++ & (ITCMPhysicalSize - 1)] = *buffer++; + CurrentNDS->ARM9.ITCM[address & (melonDS::ITCMPhysicalSize - 1)] = *buffer; } - else if ((address & NDS::ARM9->DTCMMask) == NDS::ARM9->DTCMBase) + else if ((address & CurrentNDS->ARM9.DTCMMask) == CurrentNDS->ARM9.DTCMBase) { - NDS::ARM9->DTCM[address++ & (DTCMPhysicalSize - 1)] = *buffer++; + CurrentNDS->ARM9.DTCM[address & (melonDS::DTCMPhysicalSize - 1)] = *buffer; } else { - Write(address++, *buffer++); + CurrentNDS->ARM9Write8(address, *buffer); } + + address++; + buffer++; } } else { - u8 (*Read)(u32) = NDS::ConsoleType == 1 ? DSi::ARM9Read8 : NDS::ARM9Read8; while (count--) { - if (address < NDS::ARM9->ITCMSize) + if (address < CurrentNDS->ARM9.ITCMSize) { - *buffer++ = NDS::ARM9->ITCM[address & (ITCMPhysicalSize - 1)]; + *buffer = CurrentNDS->ARM9.ITCM[address & (melonDS::ITCMPhysicalSize - 1)]; } - else if ((address & NDS::ARM9->DTCMMask) == NDS::ARM9->DTCMBase) + else if ((address & CurrentNDS->ARM9.DTCMMask) == CurrentNDS->ARM9.DTCMBase) { - *buffer++ = NDS::ARM9->DTCM[address & (DTCMPhysicalSize - 1)]; + *buffer = CurrentNDS->ARM9.DTCM[address & (melonDS::DTCMPhysicalSize - 1)]; } else { - *buffer++ = SafeToPeek(address) ? Read(address) : 0; + *buffer = SafeToPeek(address) ? CurrentNDS->ARM9Read8(address) : 0; } address++; + buffer++; } } } @@ -220,15 +231,23 @@ static void ARM7Access(u8* buffer, s64 address, s64 count, bool write) { if (write) { - void (*Write)(u32, u8) = NDS::ConsoleType == 1 ? DSi::ARM7Write8 : NDS::ARM7Write8; while (count--) - Write(address++, *buffer++); + { + CurrentNDS->ARM7Write8(address, *buffer); + + address++; + buffer++; + } } else { - u8 (*Read)(u32) = NDS::ConsoleType == 1 ? DSi::ARM7Read8 : NDS::ARM7Read8; while (count--) - *buffer++ = SafeToPeek(address) ? Read(address) : 0, address++; + { + *buffer = SafeToPeek(address) ? CurrentNDS->ARM7Read8(address) : 0; + + address++; + buffer++; + } } } @@ -237,41 +256,43 @@ ECL_EXPORT void GetMemoryAreas(MemoryArea *m) int i = 0; #define ADD_MEMORY_DOMAIN(name, data, size, flags) do \ { \ - m[i].Data = (void*)data; \ + m[i].Data = reinterpret_cast(data); \ m[i].Name = name; \ m[i].Size = size; \ m[i].Flags = flags; \ i++; \ } while (0) - ADD_MEMORY_DOMAIN("Main RAM", NDS::MainRAM, NDS::ConsoleType == 1 ? NDS::MainRAMMaxSize : NDS::MainRAMMaxSize / 4, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_PRIMARY); - ADD_MEMORY_DOMAIN("Shared WRAM", NDS::SharedWRAM, NDS::SharedWRAMSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); - ADD_MEMORY_DOMAIN("ARM7 WRAM", NDS::ARM7WRAM, NDS::ARM7WRAMSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); + const auto mainRamSize = CurrentNDS->ConsoleType == 1 ? melonDS::MainRAMMaxSize : melonDS::MainRAMMaxSize / 4; + ADD_MEMORY_DOMAIN("Main RAM", CurrentNDS->MainRAM, mainRamSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_PRIMARY); + ADD_MEMORY_DOMAIN("Shared WRAM", CurrentNDS->SharedWRAM, melonDS::SharedWRAMSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); + ADD_MEMORY_DOMAIN("ARM7 WRAM", CurrentNDS->ARM7WRAM, melonDS::ARM7WRAMSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); - if (NDSCart::Cart) + if (auto* ndsCart = CurrentNDS->GetNDSCart()) { - ADD_MEMORY_DOMAIN("SRAM", NDSCart::GetSaveMemory(), NDSCart::GetSaveMemoryLength(), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); - ADD_MEMORY_DOMAIN("ROM", NDSCart::Cart->GetROM(), NDSCart::Cart->GetROMLength(), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); + ADD_MEMORY_DOMAIN("SRAM", CurrentNDS->GetNDSSave(), CurrentNDS->GetNDSSaveLength(), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); + ADD_MEMORY_DOMAIN("ROM", const_cast(ndsCart->GetROM()), ndsCart->GetROMLength(), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); } - if (GBACart::Cart) + if (auto* gbaCart = CurrentNDS->GetGBACart()) { - ADD_MEMORY_DOMAIN("GBA SRAM", GBACart::GetSaveMemory(), GBACart::GetSaveMemoryLength(), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); - ADD_MEMORY_DOMAIN("GBA ROM", GBACart::Cart->GetROM(), GBACart::Cart->GetROMLength(), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); + ADD_MEMORY_DOMAIN("GBA SRAM", CurrentNDS->GetGBASave(), CurrentNDS->GetGBASaveLength(), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); + ADD_MEMORY_DOMAIN("GBA ROM", const_cast(gbaCart->GetROM()), gbaCart->GetROMLength(), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); } - ADD_MEMORY_DOMAIN("Instruction TCM", NDS::ARM9->ITCM, ITCMPhysicalSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); - ADD_MEMORY_DOMAIN("Data TCM", NDS::ARM9->DTCM, DTCMPhysicalSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); + ADD_MEMORY_DOMAIN("Instruction TCM", CurrentNDS->ARM9.ITCM, melonDS::ITCMPhysicalSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); + ADD_MEMORY_DOMAIN("Data TCM", CurrentNDS->ARM9.DTCM, melonDS::DTCMPhysicalSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); - ADD_MEMORY_DOMAIN("ARM9 BIOS", NDS::ARM9BIOS, sizeof(NDS::ARM9BIOS), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); - ADD_MEMORY_DOMAIN("ARM7 BIOS", NDS::ARM7BIOS, sizeof(NDS::ARM7BIOS), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); + ADD_MEMORY_DOMAIN("ARM9 BIOS", const_cast(CurrentNDS->GetARM9BIOS().data()), melonDS::ARM9BIOSSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); + ADD_MEMORY_DOMAIN("ARM7 BIOS", const_cast(CurrentNDS->GetARM7BIOS().data()), melonDS::ARM7BIOSSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); - ADD_MEMORY_DOMAIN("Firmware", SPI_Firmware::GetFirmware()->Buffer(), SPI_Firmware::GetFirmware()->Length(), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); + ADD_MEMORY_DOMAIN("Firmware", CurrentNDS->GetFirmware().Buffer(), CurrentNDS->GetFirmware().Length(), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); - if (NDS::ConsoleType == 1) + if (CurrentNDS->ConsoleType == 1) { - ADD_MEMORY_DOMAIN("ARM9i BIOS", DSi::ARM9iBIOS, sizeof(DSi::ARM9iBIOS), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); - ADD_MEMORY_DOMAIN("ARM7i BIOS", DSi::ARM7iBIOS, sizeof(DSi::ARM7iBIOS), MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); + auto* dsi = static_cast(CurrentNDS); + ADD_MEMORY_DOMAIN("ARM9i BIOS", dsi->ARM9iBIOS.data(), melonDS::DSiBIOSSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); + ADD_MEMORY_DOMAIN("ARM7i BIOS", dsi->ARM7iBIOS.data(), melonDS::DSiBIOSSize, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE); } ADD_MEMORY_DOMAIN("ARM9 System Bus", ARM9Access, 1ull << 32, MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_FUNCTIONHOOK); diff --git a/waterbox/melon/BizFileManager.cpp b/waterbox/melon/BizFileManager.cpp deleted file mode 100644 index 18c754bc746..00000000000 --- a/waterbox/melon/BizFileManager.cpp +++ /dev/null @@ -1,628 +0,0 @@ -#include "NDS.h" -#include "NDSCart.h" -#include "DSi.h" -#include "DSi_NAND.h" -#include "DSi_TMD.h" -#include "CRC32.h" -#include "FreeBIOS.h" -#include "SPI.h" - -#include "BizFileManager.h" - -// need to peek at these internals -namespace DSi_BPTWL -{ - extern u8 Registers[0x100]; -} - -namespace FileManager -{ - -constexpr u32 DSIWARE_CATEGORY = 0x00030004; -static u8 DSiWareID[8]; - -static std::optional, size_t>> GetFileData(std::string path) -{ - auto file = Platform::OpenFile(path, Platform::FileMode::Read); - if (!file) - { - return std::nullopt; - } - - size_t size = Platform::FileLength(file); - auto data = std::make_unique(size); - - Platform::FileRewind(file); - Platform::FileRead(data.get(), size, 1, file); - Platform::CloseFile(file); - - return std::make_pair(std::move(data), size); -} - -static bool LoadBIOS(const char* path, u8* buffer, size_t len) -{ - auto bios = Platform::OpenFile(path, Platform::FileMode::Read); - if (!bios) - { - return false; - } - - if (Platform::FileLength(bios) != len) - { - Platform::CloseFile(bios); - return false; - } - - Platform::FileRewind(bios); - auto read = Platform::FileRead(buffer, len, 1, bios); - Platform::CloseFile(bios); - return read == len; -} - -// Inits NDS BIOS7 and BIOS9 -const char* InitNDSBIOS() -{ - if (NDS::ConsoleType == 1 || Platform::GetConfigBool(Platform::ExternalBIOSEnable)) - { - if (!LoadBIOS("bios7.bin", NDS::ARM7BIOS, sizeof(NDS::ARM7BIOS))) - { - return "Failed to load BIOS7!"; - } - - if (!LoadBIOS("bios9.bin", NDS::ARM9BIOS, sizeof(NDS::ARM9BIOS))) - { - return "Failed to load BIOS9!"; - } - } - else - { - memcpy(NDS::ARM7BIOS, bios_arm7_bin, sizeof(bios_arm7_bin)); - memcpy(NDS::ARM9BIOS, bios_arm9_bin, sizeof(bios_arm9_bin)); - } - - return nullptr; -} - -static void SanitizeExternalFirmware(SPI_Firmware::Firmware& firmware) -{ - auto& header = firmware.Header(); - - const bool isDSiFw = header.ConsoleType == SPI_Firmware::FirmwareConsoleType::DSi; - const auto defaultHeader = SPI_Firmware::FirmwareHeader(isDSiFw); - - // the user data offset won't necessarily be 0x7FE00 & Mask, DSi/iQue use 0x7FC00 & Mask instead - // but we don't want to crash due to an invalid offset - const auto maxUserDataOffset = 0x7FE00 & firmware.Mask(); - if (firmware.UserDataOffset() > maxUserDataOffset) - { - header.UserSettingsOffset = maxUserDataOffset >> 3; - } - - if (isDSiFw) - { - memset(&header.Bytes[0x22], 0x00, 6); - memset(&header.Bytes[0x28], 0xFF, 2); - } - - memcpy(&header.Bytes[0x2C], &defaultHeader.Bytes[0x2C], 0x136); - memset(&header.Bytes[0x162], 0xFF, 0x9E); - - if (isDSiFw) - { - header.WifiBoard = defaultHeader.WifiBoard; - header.WifiFlash = defaultHeader.WifiFlash; - } - - header.UpdateChecksum(); - - auto& aps = firmware.AccessPoints(); - aps[0] = SPI_Firmware::WifiAccessPoint(isDSiFw); - aps[1] = SPI_Firmware::WifiAccessPoint(); - aps[2] = SPI_Firmware::WifiAccessPoint(); - - if (isDSiFw) - { - auto& exAps = firmware.ExtendedAccessPoints(); - exAps[0] = SPI_Firmware::ExtendedWifiAccessPoint(); - exAps[1] = SPI_Firmware::ExtendedWifiAccessPoint(); - exAps[2] = SPI_Firmware::ExtendedWifiAccessPoint(); - } -} - -static void FixFirmwareTouchscreenCalibration(SPI_Firmware::UserData& userData) -{ - userData.TouchCalibrationADC1[0] = 0; - userData.TouchCalibrationADC1[1] = 0; - userData.TouchCalibrationPixel1[0] = 0; - userData.TouchCalibrationPixel1[1] = 0; - userData.TouchCalibrationADC2[0] = 255 << 4; - userData.TouchCalibrationADC2[1] = 191 << 4; - userData.TouchCalibrationPixel2[0] = 255; - userData.TouchCalibrationPixel2[1] = 191; -} - -static void SetFirmwareSettings(SPI_Firmware::UserData& userData, FirmwareSettings& fwSettings) -{ - memset(userData.Bytes, 0, 0x74); - - userData.Version = 5; - FixFirmwareTouchscreenCalibration(userData); - - userData.NameLength = fwSettings.UsernameLength; - memcpy(userData.Nickname, fwSettings.Username, sizeof(fwSettings.Username)); - userData.Settings = fwSettings.Language | SPI_Firmware::BacklightLevel::Max | 0xEC00; - userData.BirthdayMonth = fwSettings.BirthdayMonth; - userData.BirthdayDay = fwSettings.BirthdayDay; - userData.FavoriteColor = fwSettings.Color; - userData.MessageLength = fwSettings.MessageLength; - memcpy(userData.Message, fwSettings.Message, sizeof(fwSettings.Message)); - - if (userData.ExtendedSettings.Unknown0 == 1) - { - userData.ExtendedSettings.ExtendedLanguage = static_cast(fwSettings.Language & SPI_Firmware::Language::Reserved); - memset(userData.ExtendedSettings.Unused0, 0, sizeof(userData.ExtendedSettings.Unused0)); - - if (!((1 << static_cast(userData.ExtendedSettings.ExtendedLanguage)) & userData.ExtendedSettings.SupportedLanguageMask)) - { - userData.ExtendedSettings.ExtendedLanguage = SPI_Firmware::Language::English; - userData.Settings &= ~SPI_Firmware::Language::Reserved; - userData.Settings |= SPI_Firmware::Language::English; - } - } - else - { - memset(userData.Unused3, 0xFF, sizeof(userData.Unused3)); - } - - // only extended settings should have Chinese / Korean - // note that SPI_Firmware::Language::Reserved is Korean, so it's valid to have language set to that - if ((userData.Settings & SPI_Firmware::Language::Reserved) >= SPI_Firmware::Language::Chinese) - { - userData.Settings &= ~SPI_Firmware::Language::Reserved; - userData.Settings |= SPI_Firmware::Language::English; - } -} - -// Inits NDS firmware -const char* InitFirmware(FirmwareSettings& fwSettings) -{ - auto firmware = SPI_Firmware::Firmware(NDS::ConsoleType); - - if (Platform::GetConfigBool(Platform::ExternalBIOSEnable)) - { - auto fw = Platform::OpenFile("firmware.bin", Platform::FileMode::Read); - if (!fw) - { - return "Failed to obtain firmware!"; - } - - firmware = SPI_Firmware::Firmware(fw); - - if (firmware.Buffer()) - { - // sanitize header, wifi calibration, and AP points - SanitizeExternalFirmware(firmware); - } - } - else - { - fwSettings.OverrideSettings = true; - } - - if (!firmware.Buffer()) - { - return "Failed to load firmware!"; - } - - for (SPI_Firmware::UserData& userData : firmware.UserData()) - { - FixFirmwareTouchscreenCalibration(userData); - userData.UpdateChecksum(); - } - - if (fwSettings.OverrideSettings) - { - for (SPI_Firmware::UserData& userData : firmware.UserData()) - { - SetFirmwareSettings(userData, fwSettings); - userData.UpdateChecksum(); - } - - SPI_Firmware::MacAddress mac; - Platform::GetConfigArray(Platform::Firm_MAC, &mac); - auto& header = firmware.Header(); - header.MacAddress = mac; - header.UpdateChecksum(); - } - - if (!SPI_Firmware::InstallFirmware(std::move(firmware))) - { - return "Failed to install firmware!"; - } - - return nullptr; -} - -// Inits DSi BIOS7i and BIOS9i -const char* InitDSiBIOS() -{ - if (NDS::ConsoleType == 0) - { - return "Tried to init DSi BIOSes in NDS mode"; - } - - if (!LoadBIOS("bios7i.bin", DSi::ARM7iBIOS, sizeof(DSi::ARM7iBIOS))) - { - return "Failed to load BIOS7i!"; - } - - if (!LoadBIOS("bios9i.bin", DSi::ARM9iBIOS, sizeof(DSi::ARM9iBIOS))) - { - return "Failed to load BIOS9i!"; - } - - if (!Platform::GetConfigBool(Platform::DSi_FullBIOSBoot)) - { - // upstream applies this patch, for whatever reason - static const u8 patch[] = { 0xFE, 0xFF, 0xFF, 0xEA }; - memcpy(DSi::ARM7iBIOS, patch, sizeof(patch)); - memcpy(DSi::ARM9iBIOS, patch, sizeof(patch)); - } - - return nullptr; -} - -static u8 GetDefaultCountryCode(DSi_NAND::ConsoleRegion region) -{ - // TODO: CountryCode probably should be configurable - // these defaults are also completely arbitrary - switch (region) - { - case DSi_NAND::ConsoleRegion::Japan: return 0x01; // Japan - case DSi_NAND::ConsoleRegion::USA: return 0x31; // United States - case DSi_NAND::ConsoleRegion::Europe: return 0x6E; // United Kingdom - case DSi_NAND::ConsoleRegion::Australia: return 0x41; // Australia - case DSi_NAND::ConsoleRegion::China: return 0xA0; // China - case DSi_NAND::ConsoleRegion::Korea: return 0x88; // Korea - default: return 0x31; // ??? - } -} - -static void SanitizeNANDSettings(DSi_NAND::DSiFirmwareSystemSettings& settings, DSi_NAND::ConsoleRegion region) -{ - memset(settings.Zero00, 0, sizeof(settings.Zero00)); - settings.Version = 1; - settings.UpdateCounter = 0; - memset(settings.Zero01, 0, sizeof(settings.Zero01)); - settings.BelowRAMAreaSize = 0x128; - // bit 0-1 are unknown (but usually 1) - // bit 2 indicates language set (?) - // bit 3 is wifi enable (really wifi LED enable; usually set) - // bit 24 set will indicate EULA is "agreed" to - settings.ConfigFlags = 0x0100000F; - settings.Zero02 = 0; - settings.CountryCode = GetDefaultCountryCode(region); - settings.RTCYear = 0; - settings.RTCOffset = 0; - memset(settings.Zero3, 0, sizeof(settings.Zero3)); - settings.EULAVersion = 1; - memset(settings.Zero04, 0, sizeof(settings.Zero04)); - settings.AlarmHour = 0; - settings.AlarmMinute = 0; - memset(settings.Zero05, 0, sizeof(settings.Zero05)); - settings.AlarmEnable = false; - memset(settings.Zero06, 0, sizeof(settings.Zero06)); - settings.Unknown0 = 0; - settings.Unknown1 = 3; // apparently 2 or 3 - memset(settings.Zero07, 0, sizeof(settings.Zero07)); - settings.SystemMenuMostRecentTitleID.fill(0); - settings.Unknown2[0] = 0x9C; - settings.Unknown2[1] = 0x20; - settings.Unknown2[2] = 0x01; - settings.Unknown2[3] = 0x02; - memset(settings.Zero08, 0, sizeof(settings.Zero08)); - settings.Zero09 = 0; - settings.ParentalControlsFlags = 0; - memset(settings.Zero10, 0, sizeof(settings.Zero10)); - settings.ParentalControlsRegion = 0; - settings.ParentalControlsYearsOfAgeRating = 0; - settings.ParentalControlsSecretQuestion = 0; - settings.Unknown3 = 0; // apparently 0 or 6 or 7 - memset(settings.Zero11, 0, sizeof(settings.Zero11)); - memset(settings.ParentalControlsPIN, 0, sizeof(settings.ParentalControlsPIN)); - memset(settings.ParentalControlsSecretAnswer, 0, sizeof(settings.ParentalControlsSecretAnswer)); -} - -const char* InitNAND(FirmwareSettings& fwSettings, bool clearNand, bool dsiWare) -{ - auto nand = DSi_NAND::NANDImage(Platform::OpenFile("nand.bin", Platform::FileMode::ReadWrite), &DSi::ARM7iBIOS[0x8308]); - if (!nand) - { - return "Failed to parse DSi NAND!"; - } - - { - auto mount = DSi_NAND::NANDMount(nand); - if (!mount) - { - return "Failed to mount DSi NAND!"; - } - - DSi_NAND::DSiFirmwareSystemSettings settings{}; - if (!mount.ReadUserData(settings)) - { - return "Failed to read DSi NAND user data"; - } - - // serial data will contain the NAND's region - DSi_NAND::DSiSerialData serialData; - if (!mount.ReadSerialData(serialData)) - { - return "Failed to obtain serial data!"; - } - - if (fwSettings.OverrideSettings) - { - SanitizeNANDSettings(settings, serialData.Region); - memset(settings.Nickname, 0, sizeof(settings.Nickname)); - memcpy(settings.Nickname, fwSettings.Username, fwSettings.UsernameLength * 2); - settings.Language = static_cast(fwSettings.Language & SPI_Firmware::Language::Reserved); - settings.FavoriteColor = fwSettings.Color; - settings.BirthdayMonth = fwSettings.BirthdayMonth; - settings.BirthdayDay = fwSettings.BirthdayDay; - memset(settings.Message, 0, sizeof(settings.Message)); - memcpy(settings.Message, fwSettings.Message, fwSettings.MessageLength * 2); - - if (!((1 << static_cast(settings.Language)) & serialData.SupportedLanguages)) - { - // English is valid among all NANDs - settings.Language = SPI_Firmware::Language::English; - } - } - - settings.TouchCalibrationADC1[0] = 0; - settings.TouchCalibrationADC1[1] = 0; - settings.TouchCalibrationPixel1[0] = 0; - settings.TouchCalibrationPixel1[1] = 0; - settings.TouchCalibrationADC2[0] = 255 << 4; - settings.TouchCalibrationADC2[1] = 191 << 4; - settings.TouchCalibrationPixel2[0] = 255; - settings.TouchCalibrationPixel2[1] = 191; - - settings.UpdateHash(); - - if (!mount.ApplyUserData(settings)) - { - return "Failed to write DSi NAND user data"; - } - - if (clearNand) - { - std::vector titlelist; - mount.ListTitles(DSIWARE_CATEGORY, titlelist); - - for (auto& title : titlelist) - { - mount.DeleteTitle(DSIWARE_CATEGORY, title); - } - } - - if (dsiWare) - { - auto rom = GetFileData("dsiware.rom"); - if (!rom) - { - return "Failed to obtain DSiWare ROM!"; - } - - auto tmdData = GetFileData("tmd.rom"); - if (!tmdData) - { - return "Failed to obtain TMD!"; - } - - if (tmdData->second != sizeof(DSi_TMD::TitleMetadata)) - { - return "TMD is the wrong size!"; - } - - DSi_TMD::TitleMetadata tmd; - memcpy(&tmd, tmdData->first.get(), sizeof(DSi_TMD::TitleMetadata)); - - if (!mount.ImportTitle(rom->first.get(), rom->second, tmd, false)) - { - return "Loading DSiWare failed!"; - } - - // verify that the imported title is supported by this NAND - // it will not actually appear otherwise - auto regionFlags = rom->second > 0x1B0 ? rom->first[0x1B0] : 0; - if (!(regionFlags & (1 << static_cast(serialData.Region)))) - { - return "Loaded NAND region does not support this DSiWare title!"; - } - - if (rom->second >= 0x238) - { - memcpy(&DSiWareID, &rom->first[0x230], sizeof(DSiWareID)); - } - } - } - - DSi::NANDImage = std::make_unique(std::move(nand)); - return nullptr; -} - -enum class GBASaveType -{ - NONE, - SRAM, - EEPROM512, - EEPROM, - FLASH512, - FLASH1M, -}; - -#include "GBASaveOverrides.h" - -static GBASaveType FindGbaSaveType(const u8* gbaRomData, size_t gbaRomSize) -{ - u32 crc = CRC32(gbaRomData, gbaRomSize); - if (auto saveOverride = GbaCrcSaveTypeOverrides.find(crc); saveOverride != GbaCrcSaveTypeOverrides.end()) - { - return saveOverride->second; - } - - if (gbaRomSize >= 0xB0) - { - char gameId[4]; - std::memcpy(gameId, &gbaRomData[0xAC], 4); - if (auto saveOverride = GbaGameIdSaveTypeOverrides.find(std::string(gameId, 4)); saveOverride != GbaGameIdSaveTypeOverrides.end()) - { - return saveOverride->second; - } - } - - if (memmem(gbaRomData, gbaRomSize, "EEPROM_V", strlen("EEPROM_V"))) - { - return GBASaveType::EEPROM512; - } - - if (memmem(gbaRomData, gbaRomSize, "SRAM_V", strlen("SRAM_V"))) - { - return GBASaveType::SRAM; - } - - if (memmem(gbaRomData, gbaRomSize, "FLASH_V", strlen("FLASH_V")) - || memmem(gbaRomData, gbaRomSize, "FLASH512_V", strlen("FLASH512_V"))) - { - return GBASaveType::FLASH512; - } - - if (memmem(gbaRomData, gbaRomSize, "FLASH1M_V", strlen("FLASH1M_V"))) - { - return GBASaveType::FLASH1M; - } - - return GBASaveType::NONE; -} - -static std::pair, size_t> CreateBlankGbaSram(const u8* gbaRomData, size_t gbaRomSize) -{ - auto saveType = FindGbaSaveType(gbaRomData, gbaRomSize); - - if (saveType == GBASaveType::NONE) - { - return std::make_pair(nullptr, 0); - } - - size_t size; - switch (saveType) - { - case GBASaveType::SRAM: - size = 0x8000; - break; - case GBASaveType::EEPROM512: - size = 0x200; - break; - case GBASaveType::EEPROM: - size = 0x2000; - break; - case GBASaveType::FLASH512: - size = 0x10000; - break; - case GBASaveType::FLASH1M: - size = 0x20000; - break; - default: - __builtin_unreachable(); - } - - auto data = std::make_unique(size); - memset(data.get(), 0xFF, size); - return std::make_pair(std::move(data), size); -} - -const char* InitCarts(bool gba) -{ - auto ndsRom = GetFileData("nds.rom"); - if (!ndsRom) - { - return "Failed to obtain NDS ROM!"; - } - - if (!NDS::LoadCart(ndsRom->first.get(), ndsRom->second, nullptr, 0)) - { - return "Failed to load NDS ROM!"; - } - - if (ndsRom->second >= 0x15C && NDS::IsLoadedARM9BIOSBuiltIn()) - { - // copy logo to the ARM9 bios - // this is only needed for the builtin bios, which omits the logo - memcpy(&NDS::ARM9BIOS[0x20], &ndsRom->first[0xC0], 0x9C); - } - - if (gba) - { - auto gbaRom = GetFileData("gba.rom"); - if (!gbaRom) - { - return "Failed to obtain GBA ROM!"; - } - - auto gbaSram = CreateBlankGbaSram(gbaRom->first.get(), gbaRom->second); - if (!NDS::LoadGBACart(gbaRom->first.get(), gbaRom->second, gbaSram.first.get(), gbaSram.second)) - { - return "Failed to load GBA ROM!"; - } - } - - return nullptr; -} - -#pragma pack(push, 1) - -struct DSiAutoLoad -{ - u8 ID[4]; // "TLNC" - u8 Unknown1; // "usually 01h" - u8 Length; // starting from PrevTitleId - u16 CRC16; // covering Length bytes ("18h=norm") - u8 PrevTitleID[8]; // can be 0 ("anonymous") - u8 NewTitleID[8]; - u32 Flags; // bit 0: is valid, bit 1-3: boot type ("01h=Cartridge, 02h=Landing, 03h=DSiware"), other bits unknown/unused - u32 Unused1; // this part is typically still checksummed - u8 Unused2[0xE0]; // this part isn't checksummed, but is 0 filled on erasing autoload data -}; - -#pragma pack(pop) - -static_assert(sizeof(DSiAutoLoad) == 0x100, "DSiAutoLoad wrong size"); - -void SetupDirectBoot() -{ - if (NDSCart::Cart) - { - NDS::SetupDirectBoot("nds.rom"); - } - else - { - // set warm boot flag - DSi_BPTWL::Registers[0x70] |= 1; - - // setup "auto-load" feature - DSiAutoLoad dsiAutoLoad; - memset(&dsiAutoLoad, 0, sizeof(dsiAutoLoad)); - memcpy(dsiAutoLoad.ID, "TLNC", sizeof(dsiAutoLoad.ID)); - dsiAutoLoad.Unknown1 = 0x01; - dsiAutoLoad.Length = 0x18; - memcpy(dsiAutoLoad.NewTitleID, DSiWareID, sizeof(DSiWareID)); - dsiAutoLoad.Flags |= (0x03 << 1) | 0x01; - dsiAutoLoad.Flags |= (1 << 4); // unknown bit, seems to be required to boot into games (errors otherwise?) - dsiAutoLoad.CRC16 = SPI_Firmware::CRC16((u8*)&dsiAutoLoad.PrevTitleID, dsiAutoLoad.Length, 0xFFFF); - memcpy(&NDS::MainRAM[0x300], &dsiAutoLoad, sizeof(dsiAutoLoad)); - } -} - -} diff --git a/waterbox/melon/BizFileManager.h b/waterbox/melon/BizFileManager.h deleted file mode 100644 index fe17220a1b3..00000000000 --- a/waterbox/melon/BizFileManager.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef BIZFILEMANAGER_H -#define BIZFILEMANAGER_H - -namespace FileManager -{ - -struct FirmwareSettings -{ - bool OverrideSettings; - int UsernameLength; - char16_t Username[10]; - int Language; - int BirthdayMonth; - int BirthdayDay; - int Color; - int MessageLength; - char16_t Message[26]; -}; - -const char* InitNDSBIOS(); -const char* InitFirmware(FirmwareSettings& fwSettings); -const char* InitDSiBIOS(); -const char* InitNAND(FirmwareSettings& fwSettings, bool clearNand, bool dsiWare); -const char* InitCarts(bool gba); -void SetupDirectBoot(); - -} - -#endif diff --git a/waterbox/melon/BizGLPresenter.cpp b/waterbox/melon/BizGLPresenter.cpp index 52643e8757b..488176bbadb 100644 --- a/waterbox/melon/BizGLPresenter.cpp +++ b/waterbox/melon/BizGLPresenter.cpp @@ -1,3 +1,4 @@ +#include "NDS.h" #include "GPU.h" #include "OpenGLSupport.h" #include "frontend/FrontendUtil.h" @@ -10,6 +11,11 @@ namespace Frontend { + extern float TouchMtx[6]; + extern float HybTouchMtx[6]; + extern bool BotEnable; + extern bool HybEnable; + extern int HybScreen; extern void M23_Transform(float* m, float& x, float& y); } @@ -61,13 +67,13 @@ void main() } )"; -ECL_INVISIBLE static GLuint ScreenShaderProgram[3]; +ECL_INVISIBLE static GLuint ScreenShaderProgram; ECL_INVISIBLE static GLuint ScreenShaderTransformULoc, ScreenShaderSizeULoc; ECL_INVISIBLE static GLuint VertexBuffer, VertexArray; -ECL_INVISIBLE static float ScreenMatrix[2 * 6]; -ECL_INVISIBLE static int ScreenKinds[2]; +ECL_INVISIBLE static float ScreenMatrix[3 * 6]; +ECL_INVISIBLE static int ScreenKinds[3]; ECL_INVISIBLE static int NumScreens; ECL_INVISIBLE static u32 Width, Height; @@ -80,20 +86,18 @@ ECL_INVISIBLE static GLuint OutputPboID; void Init(u32 scale) { - OpenGL::BuildShaderProgram(ScreenVS, ScreenFS, ScreenShaderProgram, "GLPresenterShader"); + Frontend::OpenGL::CompileVertexFragmentProgram( + ScreenShaderProgram, + ScreenVS, ScreenFS, + "GLPresenterShader", + {{"vPosition", 0}, {"vTexcoord", 1}}, + {{"oColor", 0}}); - GLuint pid = ScreenShaderProgram[2]; - glBindAttribLocation(pid, 0, "vPosition"); - glBindAttribLocation(pid, 1, "vTexcoord"); - glBindFragDataLocation(pid, 0, "oColor"); + glUseProgram(ScreenShaderProgram); + glUniform1i(glGetUniformLocation(ScreenShaderProgram, "ScreenTex"), 0); - OpenGL::LinkShaderProgram(ScreenShaderProgram); - - glUseProgram(pid); - glUniform1i(glGetUniformLocation(pid, "ScreenTex"), 0); - - ScreenShaderSizeULoc = glGetUniformLocation(pid, "uScreenSize"); - ScreenShaderTransformULoc = glGetUniformLocation(pid, "uScreenTransform"); + ScreenShaderSizeULoc = glGetUniformLocation(ScreenShaderProgram, "uScreenSize"); + ScreenShaderTransformULoc = glGetUniformLocation(ScreenShaderProgram, "uScreenTransform"); constexpr int paddedHeight = NDS_HEIGHT + 2; constexpr float padPixels = 1.f / paddedHeight; @@ -133,16 +137,16 @@ void Init(u32 scale) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, NDS_WIDTH, paddedHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr); - static u8 zeroData[NDS_WIDTH * 4 * 4]{}; - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, NDS_HEIGHT / 2, NDS_WIDTH, 2, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, zeroData); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, NDS_WIDTH, paddedHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr); + static u32 zeroData[NDS_WIDTH * 2]{}; + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, NDS_HEIGHT / 2, NDS_WIDTH, 2, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, zeroData); glGenBuffers(1, &OutputPboID); GLScale = scale; } -std::pair Present() +std::pair Present(melonDS::GPU& gpu) { glBindFramebuffer(GL_FRAMEBUFFER, OutputFboID); glDisable(GL_DEPTH_TEST); @@ -154,20 +158,21 @@ std::pair Present() glViewport(0, 0, Width, Height); - glUseProgram(ScreenShaderProgram[2]); + glUseProgram(ScreenShaderProgram); glUniform2f(ScreenShaderSizeULoc, Width, Height); glActiveTexture(GL_TEXTURE0); - if (GPU3D::CurrentRenderer->Accelerated) + auto& renderer3d = gpu.GetRenderer3D(); + if (renderer3d.Accelerated) { - GPU::CurGLCompositor->BindOutputTexture(GPU::FrontBuffer); + renderer3d.BindOutputTexture(gpu.FrontBuffer); } else { glBindTexture(GL_TEXTURE_2D, InputTextureID); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, NDS_WIDTH, NDS_HEIGHT / 2, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, GPU::Framebuffer[GPU::FrontBuffer][0]); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, NDS_HEIGHT / 2 + 2, NDS_WIDTH, NDS_HEIGHT / 2, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, GPU::Framebuffer[GPU::FrontBuffer][1]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, NDS_WIDTH, NDS_HEIGHT / 2, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, gpu.Framebuffer[gpu.FrontBuffer][0].get()); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, NDS_HEIGHT / 2 + 2, NDS_WIDTH, NDS_HEIGHT / 2, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, gpu.Framebuffer[gpu.FrontBuffer][1].get()); } glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer); @@ -181,15 +186,10 @@ std::pair Present() glFlush(); - GLint oldPbo; - glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &oldPbo); - glBindBuffer(GL_PIXEL_PACK_BUFFER, OutputPboID); glBufferData(GL_PIXEL_PACK_BUFFER, Width * Height * sizeof(u32), nullptr, GL_STREAM_READ); glReadPixels(0, 0, Width, Height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, (void*)(0)); - glBindBuffer(GL_PIXEL_PACK_BUFFER, oldPbo); - return std::make_pair(Width, Height); } @@ -200,9 +200,6 @@ ECL_EXPORT u32 GetGLTexture() ECL_EXPORT void ReadFrameBuffer(u32* buffer) { - GLint oldPbo; - glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &oldPbo); - glBindBuffer(GL_PIXEL_PACK_BUFFER, OutputPboID); const auto p = static_cast(glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY)); if (p) @@ -218,8 +215,6 @@ ECL_EXPORT void ReadFrameBuffer(u32* buffer) glUnmapBuffer(GL_PIXEL_PACK_BUFFER); } - - glBindBuffer(GL_PIXEL_PACK_BUFFER, oldPbo); } struct ScreenSettings @@ -262,12 +257,16 @@ static std::pair GetScreenSize(const ScreenSettings* screenSettings, u return isHori ? std::make_pair(h * 2 + gap, w) : std::make_pair(w * 2 + gap, h); + case Frontend::screenLayout_Hybrid: + return isHori + ? std::make_pair(h * 2 + gap, w * 3 + (int)ceil(gap * 4 / 3.0)) + : std::make_pair(w * 3 + (int)ceil(gap * 4 / 3.0), h * 2 + gap); default: __builtin_unreachable(); } } -ECL_EXPORT void SetScreenSettings(const ScreenSettings* screenSettings, u32* width, u32* height, u32* vwidth, u32* vheight) +ECL_EXPORT void SetScreenSettings(melonDS::NDS* nds, const ScreenSettings* screenSettings, u32* width, u32* height, u32* vwidth, u32* vheight) { auto [w, h] = GetScreenSize(screenSettings, GLScale); if (w != Width || h != Height) @@ -283,7 +282,7 @@ ECL_EXPORT void SetScreenSettings(const ScreenSettings* screenSettings, u32* wid glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Width, Height, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr); glDeleteFramebuffers(1, &OutputFboID); glGenFramebuffers(1, &OutputFboID); @@ -303,7 +302,7 @@ ECL_EXPORT void SetScreenSettings(const ScreenSettings* screenSettings, u32* wid NumScreens = Frontend::GetScreenTransforms(ScreenMatrix, ScreenKinds); - Present(); + Present(nds->GPU); *width = w; *height = h; @@ -323,16 +322,31 @@ ECL_EXPORT void SetScreenSettings(const ScreenSettings* screenSettings, u32* wid ECL_EXPORT void GetTouchCoords(int* x, int* y) { - if (!Frontend::GetTouchCoords(*x, *y, true)) + float vx = *x; + float vy = *y; + + if (Frontend::HybEnable && Frontend::HybScreen == 1) + { + Frontend::M23_Transform(Frontend::HybTouchMtx, vx, vy); + } + else + { + Frontend::M23_Transform(Frontend::TouchMtx, vx, vy); + } + + *x = vx; + *y = vy; + + if (!Frontend::BotEnable) { - *x = 0; - *y = 0; + // top screen only, offset y to account for that + *y -= 192; } } ECL_EXPORT void GetScreenCoords(float* x, float* y) { - for (int i = 0; i < NumScreens; i++) + for (int i = NumScreens - 1; i >= 0; i--) { // bottom screen if (ScreenKinds[i] == 1) @@ -342,9 +356,18 @@ ECL_EXPORT void GetScreenCoords(float* x, float* y) } } - // bottom screen not visible - *x = 0; - *y = 0; + // top screen only, offset y to account for that + *y += 192; + + for (int i = 0; i < NumScreens; i++) + { + // top screen + if (ScreenKinds[i] == 0) + { + Frontend::M23_Transform(&ScreenMatrix[i * 6], *x, *y); + return; + } + } } } diff --git a/waterbox/melon/BizGLPresenter.h b/waterbox/melon/BizGLPresenter.h index e31d5bc3c40..92a376484d7 100644 --- a/waterbox/melon/BizGLPresenter.h +++ b/waterbox/melon/BizGLPresenter.h @@ -1,13 +1,14 @@ #ifndef BIZGLPRESENTER_H #define BIZGLPRESENTER_H -#include "types.h" +#include "GPU.h" +#include "BizTypes.h" namespace GLPresenter { void Init(u32 scale); -std::pair Present(); +std::pair Present(melonDS::GPU& gpu); } diff --git a/waterbox/melon/BizInterface.cpp b/waterbox/melon/BizInterface.cpp index 8a63826c86d..dff002c75de 100644 --- a/waterbox/melon/BizInterface.cpp +++ b/waterbox/melon/BizInterface.cpp @@ -5,158 +5,52 @@ #include "GBACart.h" #include "frontend/mic_blow.h" -#include "BizPlatform/BizConfig.h" -#include "BizPlatform/BizFile.h" -#include "BizPlatform/BizLog.h" #include "BizPlatform/BizOGL.h" - -#include "BizFileManager.h" #include "BizGLPresenter.h" #include #include -static bool SkipFW; static bool GLPresentation; -struct NDSTime -{ - int Year; // 0-99 - int Month; // 1-12 - int Day; // 1-(28/29/30/31 depending on month/year) - int Hour; // 0-23 - int Minute; // 0-59 - int Second; // 0-59 -}; - -struct InitConfig +ECL_EXPORT const char* InitGL(BizOGL::LoadGLProc loadGLProc, int threeDeeRenderer, int scaleFactor, bool isWinApi) { - bool SkipFW; - bool HasGBACart; - bool DSi; - bool ClearNAND; - bool LoadDSiWare; - bool IsWinApi; - int ThreeDeeRenderer; - GPU::RenderSettings RenderSettings; - NDSTime StartTime; - FileManager::FirmwareSettings FirmwareSettings; -}; - -ECL_EXPORT const char* Init(InitConfig* initConfig, - Platform::ConfigCallbackInterface* configCallbackInterface, - Platform::FileCallbackInterface* fileCallbackInterface, - Platform::LogCallback_t logCallback, - BizOGL::LoadGLProc loadGLProc) -{ - Platform::SetConfigCallbacks(*configCallbackInterface); - Platform::SetFileCallbacks(*fileCallbackInterface); - Platform::SetLogCallback(logCallback); - - SkipFW = initConfig->SkipFW; - NDS::SetConsoleType(initConfig->DSi); - - if (const char* error = FileManager::InitNDSBIOS()) - { - return error; - } - - if (const char* error = FileManager::InitFirmware(initConfig->FirmwareSettings)) - { - return error; - } - - if (initConfig->DSi) - { - if (const char* error = FileManager::InitDSiBIOS()) - { - return error; - } - - if (const char* error = FileManager::InitNAND(initConfig->FirmwareSettings, initConfig->ClearNAND, initConfig->LoadDSiWare)) - { - return error; - } - } - - if (!NDS::Init()) - { - return "Failed to init core!"; - } - - RTC::SetDateTime(initConfig->StartTime.Year, initConfig->StartTime.Month, initConfig->StartTime.Day, - initConfig->StartTime.Hour, initConfig->StartTime.Minute, initConfig->StartTime.Second); - - if (loadGLProc) - { - switch (initConfig->ThreeDeeRenderer) - { - case 0: - BizOGL::LoadGL(loadGLProc, BizOGL::LoadGLVersion::V3_1, initConfig->IsWinApi); - break; - case 1: - BizOGL::LoadGL(loadGLProc, BizOGL::LoadGLVersion::V3_2, initConfig->IsWinApi); - break; -#if false // OpenGL Compute Renderer isn't released yet - case 2: - BizOGL::LoadGL(loadGLProc, BizOGL::LoadGLVersion::V4_3, initConfig->IsWinApi); - break; -#endif - default: - return "Unknown 3DRenderer!"; - } - - GLPresenter::Init(initConfig->ThreeDeeRenderer ? initConfig->RenderSettings.GL_ScaleFactor : 1); - GLPresentation = true; - } - else - { - GLPresentation = false; - } - - GPU::InitRenderer(initConfig->ThreeDeeRenderer); - GPU::SetRenderSettings(initConfig->ThreeDeeRenderer, initConfig->RenderSettings); - - NDS::Reset(); - - if (!initConfig->LoadDSiWare) - { - if (const char* error = FileManager::InitCarts(initConfig->HasGBACart)) - { - return error; - } - } - - if (SkipFW || NDS::NeedsDirectBoot()) - { - FileManager::SetupDirectBoot(); - } - - NDS::Start(); - + switch (threeDeeRenderer) + { + case 0: + BizOGL::LoadGL(loadGLProc, BizOGL::LoadGLVersion::V3_1, isWinApi); + break; + case 1: + BizOGL::LoadGL(loadGLProc, BizOGL::LoadGLVersion::V3_2, isWinApi); + break; + case 2: + BizOGL::LoadGL(loadGLProc, BizOGL::LoadGLVersion::V4_3, isWinApi); + break; + default: + return "Unknown 3DRenderer!"; + } + + GLPresenter::Init(threeDeeRenderer ? scaleFactor : 1); + GLPresentation = true; return nullptr; } struct MyFrameInfo : public FrameInfo { + melonDS::NDS* NDS; u32 Keys; u8 TouchX; u8 TouchY; - s8 MicVolume; - s8 GBALightSensor; + u8 MicVolume; + u8 GBALightSensor; bool ConsiderAltLag; }; static s16 biz_mic_input[735]; -static bool ValidRange(s8 sensor) -{ - return sensor >= 0 && sensor <= 10; -} - static int sampPos = 0; -static void MicFeedNoise(s8 vol) +static void MicFeedNoise(u8 vol) { int sampLen = sizeof(mic_blow) / sizeof(*mic_blow); @@ -173,105 +67,108 @@ ECL_EXPORT void FrameAdvance(MyFrameInfo* f) { RunningFrame = true; - if (f->Keys & 0x8000) - { - NDS::Reset(); - if (SkipFW || NDS::NeedsDirectBoot()) - { - FileManager::SetupDirectBoot(); - } - - NDS::Start(); - } - - NDS::SetKeyMask(~f->Keys & 0xFFF); + f->NDS->SetKeyMask(~f->Keys & 0xFFF); if (f->Keys & 0x1000) { // move touch coords incrementally to our new touch point - NDS::MoveTouch(f->TouchX, f->TouchY); + f->NDS->MoveTouch(f->TouchX, f->TouchY); } else { - NDS::ReleaseScreen(); + f->NDS->ReleaseScreen(); } if (f->Keys & 0x2000) { - NDS::SetLidClosed(false); + f->NDS->SetLidClosed(false); } else if (f->Keys & 0x4000) { - NDS::SetLidClosed(true); + f->NDS->SetLidClosed(true); } MicFeedNoise(f->MicVolume); - NDS::MicInputFrame(biz_mic_input, 735); + f->NDS->MicInputFrame(biz_mic_input, 735); - int sensor = GBACart::SetInput(0, 1); - if (sensor != -1 && ValidRange(f->GBALightSensor)) + if (auto* gbaCart = f->NDS->GetGBACart()) { - if (sensor > f->GBALightSensor) - { - while (GBACart::SetInput(0, 1) != f->GBALightSensor); - } - else if (sensor < f->GBALightSensor) + int sensor = gbaCart->SetInput(melonDS::GBACart::Input_SolarSensorDown, 1); + if (sensor != -1) { - while (GBACart::SetInput(1, 1) != f->GBALightSensor); + if (f->GBALightSensor > 10) f->GBALightSensor = 10; + + if (sensor > f->GBALightSensor) + { + while (gbaCart->SetInput(melonDS::GBACart::Input_SolarSensorDown, 1) != f->GBALightSensor); + } + else if (sensor < f->GBALightSensor) + { + while (gbaCart->SetInput(melonDS::GBACart::Input_SolarSensorUp, 1) != f->GBALightSensor); + } } } - NDS::RunFrame(); + f->NDS->RunFrame(); if (f->Keys & 0x1000) { // finalize touch after emulation finishes - NDS::TouchScreen(f->TouchX, f->TouchY); + f->NDS->TouchScreen(f->TouchX, f->TouchY); } - if (!GPU3D::CurrentRenderer->Accelerated) + auto& renderer3d = f->NDS->GetRenderer3D(); + if (!renderer3d.Accelerated) { - auto softRenderer = reinterpret_cast(GPU3D::CurrentRenderer.get()); - softRenderer->StopRenderThread(); + auto& softRenderer = static_cast(renderer3d); + softRenderer.StopRenderThread(); } if (GLPresentation) { - std::tie(f->Width, f->Height) = GLPresenter::Present(); + std::tie(f->Width, f->Height) = GLPresenter::Present(f->NDS->GPU); } else { constexpr u32 SingleScreenSize = 256 * 192; - memcpy(f->VideoBuffer, GPU::Framebuffer[GPU::FrontBuffer][0], SingleScreenSize * sizeof(u32)); - memcpy(f->VideoBuffer + SingleScreenSize, GPU::Framebuffer[GPU::FrontBuffer][1], SingleScreenSize * sizeof(u32)); + + auto& gpu = f->NDS->GPU; + memcpy(f->VideoBuffer, gpu.Framebuffer[gpu.FrontBuffer][0].get(), SingleScreenSize * sizeof(u32)); + memcpy(f->VideoBuffer + SingleScreenSize, gpu.Framebuffer[gpu.FrontBuffer][1].get(), SingleScreenSize * sizeof(u32)); f->Width = 256; f->Height = 384; } - f->Samples = SPU::ReadOutput(f->SoundBuffer); + f->Samples = f->NDS->SPU.ReadOutput(f->SoundBuffer, 4096); if (f->Samples == 0) // hack when core decides to stop outputting audio altogether (lid closed or power off) { memset(f->SoundBuffer, 0, 737 * 2 * sizeof(u16)); f->Samples = 737; } - f->Cycles = NDS::GetSysClockCycles(2); + f->Cycles = f->NDS->GetSysClockCycles(2); // if we want to consider other lag sources, use that lag flag if we haven't unlagged already - if (f->ConsiderAltLag && NDS::LagFrameFlag) + if (f->ConsiderAltLag && f->NDS->LagFrameFlag) { - f->Lagged = NDS::AltLagFrameFlag; + f->Lagged = f->NDS->AltLagFrameFlag; } else { - f->Lagged = NDS::LagFrameFlag; + f->Lagged = f->NDS->LagFrameFlag; } RunningFrame = false; } -ECL_EXPORT u32 GetCallbackCycleOffset() +ECL_EXPORT u32 GetCallbackCycleOffset(melonDS::NDS* nds) +{ + return RunningFrame ? nds->GetSysClockCycles(2) : 0; +} + +ECL_EXPORT void SetSoundConfig(melonDS::NDS* nds, int bitDepth, int interpolation) { - return RunningFrame ? NDS::GetSysClockCycles(2) : 0; + nds->SPU.SetDegrade10Bit(static_cast(bitDepth)); + nds->SPU.SetInterpolation(static_cast(interpolation)); } diff --git a/waterbox/melon/BizPlatform/BizConfig.cpp b/waterbox/melon/BizPlatform/BizConfig.cpp deleted file mode 100644 index 1a5faecc094..00000000000 --- a/waterbox/melon/BizPlatform/BizConfig.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "BizConfig.h" - -#include - -namespace Platform -{ - -struct ConfigCallbackInterface -{ - bool (*GetBoolean)(ConfigEntry entry); - int (*GetInteger)(ConfigEntry entry); - void (*GetString)(ConfigEntry entry, char* buffer, int bufferSize); - bool (*GetArray)(ConfigEntry entry, void* buffer); -}; - -ECL_INVISIBLE static ConfigCallbackInterface ConfigCallbacks; - -void SetConfigCallbacks(ConfigCallbackInterface& configCallbackInterface) -{ - ConfigCallbacks = configCallbackInterface; -} - -bool GetConfigBool(ConfigEntry entry) -{ - return ConfigCallbacks.GetBoolean(entry); -} - -int GetConfigInt(ConfigEntry entry) -{ - return ConfigCallbacks.GetInteger(entry); -} - -std::string GetConfigString(ConfigEntry entry) -{ - char buffer[4096]{}; - ConfigCallbacks.GetString(entry, buffer, sizeof(buffer)); - return buffer; -} - -bool GetConfigArray(ConfigEntry entry, void* data) -{ - return ConfigCallbacks.GetArray(entry, data); -} - -} diff --git a/waterbox/melon/BizPlatform/BizConfig.h b/waterbox/melon/BizPlatform/BizConfig.h deleted file mode 100644 index b8add522dd4..00000000000 --- a/waterbox/melon/BizPlatform/BizConfig.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef BIZCONFIG_H -#define BIZCONFIG_H - -#include "Platform.h" - -namespace Platform -{ - -struct ConfigCallbackInterface; -void SetConfigCallbacks(ConfigCallbackInterface& configCallbackInterface); - -} - -#endif diff --git a/waterbox/melon/BizPlatform/BizFile.cpp b/waterbox/melon/BizPlatform/BizFile.cpp index af50458aa6f..b31a998b933 100644 --- a/waterbox/melon/BizPlatform/BizFile.cpp +++ b/waterbox/melon/BizPlatform/BizFile.cpp @@ -4,33 +4,35 @@ #include -namespace Platform +namespace melonDS::Platform { -struct FileCallbackInterface +struct FileHandle { - int (*GetLength)(const char* path); - void (*GetData)(const char* path, u8* buffer); +public: + virtual ~FileHandle() = default; + virtual bool IsEndOfFile() = 0; + virtual bool ReadLine(char* str, int count) = 0; + virtual bool Seek(s64 offset, FileSeekOrigin origin) = 0; + virtual void Rewind() = 0; + virtual size_t Read(void* data, u64 count) = 0; + virtual bool Flush() = 0; + virtual size_t Write(const void* data, u64 count) = 0; + virtual size_t Length() = 0; }; -ECL_INVISIBLE static FileCallbackInterface FileCallbacks; - -void SetFileCallbacks(FileCallbackInterface& fileCallbackInterface) -{ - FileCallbacks = fileCallbackInterface; -} - -struct FileHandle +struct MemoryFile final : FileHandle { public: - FileHandle(std::shared_ptr data_, size_t size_, FileMode mode_) - : data(data_) + MemoryFile(std::unique_ptr data_, size_t size_) + : data(std::move(data_)) , pos(0) , size(size_) - , mode(mode_) { } + ~MemoryFile() = default; + bool IsEndOfFile() { return pos == size; @@ -38,11 +40,6 @@ struct FileHandle bool ReadLine(char* str, int count) { - if (!Readable()) - { - return false; - } - if (count < 1) { return false; @@ -91,24 +88,19 @@ struct FileHandle size_t Read(void* data_, u64 count) { - if (!Readable()) - { - return 0; - } - count = std::min(count, (u64)(size - pos)); memcpy(data_, &data[pos], count); pos += count; return count; } - size_t Write(const void* data_, u64 count) + bool Flush() { - if (!Writable()) - { - return 0; - } + return true; + } + size_t Write(const void* data_, u64 count) + { count = std::min(count, (u64)(size - pos)); memcpy(&data[pos], data_, count); pos += count; @@ -121,46 +113,115 @@ struct FileHandle } private: - std::shared_ptr data; + std::unique_ptr data; size_t pos, size; - FileMode mode; +}; + +// private memory file creation API +FileHandle* CreateMemoryFile(u8* fileData, u32 fileLength) +{ + std::unique_ptr data(new u8[fileLength]); + memcpy(data.get(), fileData, fileLength); + return new MemoryFile(std::move(data), fileLength); +} - bool Readable() +struct CFile final : FileHandle +{ +public: + CFile(FILE* file_) + : file(file_) { - return (mode & FileMode::Read) == FileMode::Read; } - bool Writable() + ~CFile() { - return (mode & FileMode::Write) == FileMode::Write; + fclose(file); + } + + bool IsEndOfFile() + { + return feof(file) != 0; + } + + bool ReadLine(char* str, int count) + { + return fgets(str, count, file) != nullptr; + } + + bool Seek(s64 offset, FileSeekOrigin origin) + { + int forigin; + switch (origin) + { + case FileSeekOrigin::Start: + forigin = SEEK_SET; + break; + case FileSeekOrigin::Current: + forigin = SEEK_CUR; + break; + case FileSeekOrigin::End: + forigin = SEEK_END; + break; + default: + return false; + } + + return fseek(file, offset, forigin) == 0; + } + + void Rewind() + { + rewind(file); + } + + size_t Read(void* data, u64 count) + { + return fread(data, 1, count, file); } -}; -static std::unordered_map, size_t>> FileBufferCache; + bool Flush() + { + return fflush(file) == 0; + } + + size_t Write(const void* data, u64 count) + { + return fwrite(data, 1, count, file); + } + size_t Length() + { + long pos = ftell(file); + fseek(file, 0, SEEK_END); + long len = ftell(file); + fseek(file, pos, SEEK_SET); + return len; + } + +private: + FILE* file; +}; + +// public APIs open C files FileHandle* OpenFile(const std::string& path, FileMode mode) { - if ((mode & FileMode::ReadWrite) == FileMode::None) + const char* fmode; + if (mode & FileMode::Write) { - // something went wrong here - return nullptr; + fmode = "rb+"; } - - if (auto cache = FileBufferCache.find(path); cache != FileBufferCache.end()) + else { - return new FileHandle(cache->second.first, cache->second.second, mode); + fmode = "rb"; } - size_t size = FileCallbacks.GetLength(path.c_str()); - if (size == 0) + FILE* f = fopen(path.c_str(), fmode); + if (!f) { return nullptr; } - std::shared_ptr data(new u8[size]); - FileCallbacks.GetData(path.c_str(), data.get()); - FileBufferCache.emplace(path, std::make_pair(data, size)); - return new FileHandle(data, size, mode); + return new CFile(f); } FileHandle* OpenLocalFile(const std::string& path, FileMode mode) @@ -170,12 +231,10 @@ FileHandle* OpenLocalFile(const std::string& path, FileMode mode) bool FileExists(const std::string& name) { - if (auto cache = FileBufferCache.find(name); cache != FileBufferCache.end()) - { - return true; - } - - return FileCallbacks.GetLength(name.c_str()) > 0; + FILE* f = fopen(name.c_str(), "rb"); + bool exists = f != nullptr; + fclose(f); + return exists; } bool LocalFileExists(const std::string& name) @@ -216,7 +275,7 @@ u64 FileRead(void* data, u64 size, u64 count, FileHandle* file) bool FileFlush(FileHandle* file) { - return true; + return file->Flush(); } u64 FileWrite(const void* data, u64 size, u64 count, FileHandle* file) @@ -224,26 +283,10 @@ u64 FileWrite(const void* data, u64 size, u64 count, FileHandle* file) return file->Write(data, size * count); } +// only used for FATStorage (i.e. SD cards), not supported u64 FileWriteFormatted(FileHandle* file, const char* fmt, ...) { - va_list args; - - va_start(args, fmt); - size_t bufferSize = vsnprintf(nullptr, 0, fmt, args); - va_end(args); - - if ((int)bufferSize < 0) - { - return 0; - } - - auto buffer = std::make_unique(bufferSize + 1); - - va_start(args, fmt); - vsnprintf(buffer.get(), bufferSize + 1, fmt, args); - va_end(args); - - return file->Write(buffer.get(), bufferSize); + return 0; } u64 FileLength(FileHandle* file) diff --git a/waterbox/melon/BizPlatform/BizFile.h b/waterbox/melon/BizPlatform/BizFile.h index 871ada58f4f..268219dc454 100644 --- a/waterbox/melon/BizPlatform/BizFile.h +++ b/waterbox/melon/BizPlatform/BizFile.h @@ -3,11 +3,10 @@ #include "Platform.h" -namespace Platform +namespace melonDS::Platform { -struct FileCallbackInterface; -void SetFileCallbacks(FileCallbackInterface& fileCallbackInterface); +FileHandle* CreateMemoryFile(u8* fileData, u32 fileLength); } diff --git a/waterbox/melon/BizPlatform/BizLog.cpp b/waterbox/melon/BizPlatform/BizLog.cpp index 6d5bddea37c..f09aabb9c0f 100644 --- a/waterbox/melon/BizPlatform/BizLog.cpp +++ b/waterbox/melon/BizPlatform/BizLog.cpp @@ -1,15 +1,18 @@ -#include "BizLog.h" +#include "Platform.h" #include #include -namespace Platform +namespace melonDS::Platform { +using LogCallback_t = void (*)(LogLevel level, const char* message); + ECL_INVISIBLE static LogCallback_t LogCallback; +ECL_INVISIBLE static char LogBuffer[1 << 16]; -void SetLogCallback(LogCallback_t logCallback) +ECL_EXPORT void SetLogCallback(LogCallback_t logCallback) { LogCallback = logCallback; } @@ -17,23 +20,16 @@ void SetLogCallback(LogCallback_t logCallback) void Log(LogLevel level, const char* fmt, ...) { va_list args; - va_start(args, fmt); - size_t bufferSize = vsnprintf(nullptr, 0, fmt, args); + int bufferSize = vsnprintf(LogBuffer, sizeof(LogBuffer), fmt, args); va_end(args); - if ((int)bufferSize < 0) + if (bufferSize < 0) { return; } - auto buffer = std::make_unique(bufferSize + 1); - - va_start(args, fmt); - vsnprintf(buffer.get(), bufferSize + 1, fmt, args); - va_end(args); - - LogCallback(level, buffer.get()); + LogCallback(level, LogBuffer); } } diff --git a/waterbox/melon/BizPlatform/BizLog.h b/waterbox/melon/BizPlatform/BizLog.h deleted file mode 100644 index 0853bbd036f..00000000000 --- a/waterbox/melon/BizPlatform/BizLog.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef BIZLOG_H -#define BIZLOG_H - -#include "Platform.h" - -namespace Platform -{ - -using LogCallback_t = void (*)(LogLevel level, const char* message); -void SetLogCallback(LogCallback_t logCallback); - -} - -#endif diff --git a/waterbox/melon/BizPlatform/BizOGL.h b/waterbox/melon/BizPlatform/BizOGL.h index c88ff5f96e3..f20e59a19b4 100644 --- a/waterbox/melon/BizPlatform/BizOGL.h +++ b/waterbox/melon/BizPlatform/BizOGL.h @@ -64,6 +64,11 @@ class GLFunctor return glProc == proc; } + bool operator!=(const std::nullptr_t& nullptr_) const + { + return glProc != nullptr_; + } + private: GLFunc glProc = nullptr; }; diff --git a/waterbox/melon/BizPlatform/BizPlatformStubs.cpp b/waterbox/melon/BizPlatform/BizPlatformStubs.cpp index 603fa4bdfa6..c6bbdcd1f9f 100644 --- a/waterbox/melon/BizPlatform/BizPlatformStubs.cpp +++ b/waterbox/melon/BizPlatform/BizPlatformStubs.cpp @@ -1,6 +1,6 @@ #include "Platform.h" -namespace Platform +namespace melonDS::Platform { void Init(int argc, char** argv) diff --git a/waterbox/melon/BizPlatform/BizSaveManager.cpp b/waterbox/melon/BizPlatform/BizSaveManager.cpp index 288a5abc7cd..2425d69751a 100644 --- a/waterbox/melon/BizPlatform/BizSaveManager.cpp +++ b/waterbox/melon/BizPlatform/BizSaveManager.cpp @@ -5,7 +5,7 @@ #include "DSi_NAND.h" #include "Platform.h" -namespace Platform +namespace melonDS::Platform { constexpr u32 DSIWARE_CATEGORY = 0x00030004; @@ -13,47 +13,47 @@ constexpr u32 DSIWARE_CATEGORY = 0x00030004; static bool NdsSaveRamIsDirty = false; static bool GbaSaveRamIsDirty = false; -ECL_EXPORT void PutSaveRam(u8* data, u32 len) +ECL_EXPORT void PutSaveRam(melonDS::NDS* nds, u8* data, u32 len) { - const u32 ndsSaveLen = NDSCart::GetSaveMemoryLength(); - const u32 gbaSaveLen = GBACart::GetSaveMemoryLength(); + const u32 ndsSaveLen = nds->GetNDSSaveLength(); + const u32 gbaSaveLen = nds->GetGBASaveLength(); if (len >= ndsSaveLen) { - NDS::LoadSave(data, len); + nds->SetNDSSave(data, len); NdsSaveRamIsDirty = false; if (gbaSaveLen && len >= (ndsSaveLen + gbaSaveLen)) { - // don't use GBACart::LoadSave! it will re-allocate the save buffer (bad!) - // NDS::LoadSave is fine (and should be used) - memcpy(GBACart::GetSaveMemory(), data + ndsSaveLen, gbaSaveLen); + // don't use SetGBASave! it will re-allocate the save buffer (bad!) + // SetNDSSave is fine (and should be used) + memcpy(nds->GetGBASave(), data + ndsSaveLen, gbaSaveLen); GbaSaveRamIsDirty = false; } } } -ECL_EXPORT void GetSaveRam(u8* data) +ECL_EXPORT void GetSaveRam(melonDS::NDS* nds, u8* data) { - const u32 ndsSaveLen = NDSCart::GetSaveMemoryLength(); - const u32 gbaSaveLen = GBACart::GetSaveMemoryLength(); + const u32 ndsSaveLen = nds->GetNDSSaveLength(); + const u32 gbaSaveLen = nds->GetGBASaveLength(); if (ndsSaveLen) { - memcpy(data, NDSCart::GetSaveMemory(), ndsSaveLen); + memcpy(data, nds->GetNDSSave(), ndsSaveLen); NdsSaveRamIsDirty = false; } if (gbaSaveLen) { - memcpy(data + ndsSaveLen, GBACart::GetSaveMemory(), gbaSaveLen); + memcpy(data + ndsSaveLen, nds->GetGBASave(), gbaSaveLen); GbaSaveRamIsDirty = false; } } -ECL_EXPORT u32 GetSaveRamLength() +ECL_EXPORT u32 GetSaveRamLength(melonDS::NDS* nds) { - return NDSCart::GetSaveMemoryLength() + GBACart::GetSaveMemoryLength(); + return nds->GetNDSSaveLength() + nds->GetGBASaveLength(); } ECL_EXPORT bool SaveRamIsDirty() @@ -61,73 +61,42 @@ ECL_EXPORT bool SaveRamIsDirty() return NdsSaveRamIsDirty || GbaSaveRamIsDirty; } -static void ImportTitleData(DSi_NAND::NANDMount& mount, u32 titleId, int which, const char* path, u8** in) +ECL_EXPORT void ImportDSiWareSavs(melonDS::DSi* dsi, u32 titleId) { - if (auto file = Platform::OpenFile(path, Platform::FileMode::Write)) + if (auto& nand = dsi->GetNAND()) { - auto len = Platform::FileLength(file); - Platform::FileRewind(file); - Platform::FileWrite(*in, len, 1, file); - Platform::CloseFile(file); - *in += len; - } - - mount.ImportTitleData(DSIWARE_CATEGORY, titleId, which, path); -} - -ECL_EXPORT void ImportDSiWareSavs(u32 titleId, u8* data) -{ - auto& nand = DSi::NANDImage; - if (nand && *nand) - { - if (auto mount = DSi_NAND::NANDMount(*nand)) + if (auto mount = melonDS::DSi_NAND::NANDMount(nand)) { - ImportTitleData(mount, titleId, DSi_NAND::TitleData_PublicSav, "public.sav", &data); - ImportTitleData(mount, titleId, DSi_NAND::TitleData_PrivateSav, "private.sav", &data); - ImportTitleData(mount, titleId, DSi_NAND::TitleData_BannerSav, "banner.sav", &data); + mount.ImportTitleData(DSIWARE_CATEGORY, titleId, melonDS::DSi_NAND::TitleData_PublicSav, "public.sav"); + mount.ImportTitleData(DSIWARE_CATEGORY, titleId, melonDS::DSi_NAND::TitleData_PrivateSav, "private.sav"); + mount.ImportTitleData(DSIWARE_CATEGORY, titleId, melonDS::DSi_NAND::TitleData_BannerSav, "banner.sav"); } } } -static void ExportTitleData(DSi_NAND::NANDMount& mount, u32 titleId, int which, const char* path, u8** out) +ECL_EXPORT void ExportDSiWareSavs(melonDS::DSi* dsi, u32 titleId) { - mount.ExportTitleData(DSIWARE_CATEGORY, titleId, which, path); - - if (auto file = Platform::OpenFile(path, Platform::FileMode::Read)) + if (auto& nand = dsi->GetNAND()) { - auto len = Platform::FileLength(file); - Platform::FileRewind(file); - Platform::FileRead(*out, len, 1, file); - Platform::CloseFile(file); - *out += len; - } -} - -ECL_EXPORT void ExportDSiWareSavs(u32 titleId, u8* data) -{ - auto& nand = DSi::NANDImage; - if (nand && *nand) - { - if (auto mount = DSi_NAND::NANDMount(*nand)) + if (auto mount = melonDS::DSi_NAND::NANDMount(nand)) { - ExportTitleData(mount, titleId, DSi_NAND::TitleData_PublicSav, "public.sav", &data); - ExportTitleData(mount, titleId, DSi_NAND::TitleData_PrivateSav, "private.sav", &data); - ExportTitleData(mount, titleId, DSi_NAND::TitleData_BannerSav, "banner.sav", &data); + mount.ExportTitleData(DSIWARE_CATEGORY, titleId, melonDS::DSi_NAND::TitleData_PublicSav, "public.sav"); + mount.ExportTitleData(DSIWARE_CATEGORY, titleId, melonDS::DSi_NAND::TitleData_PrivateSav, "private.sav"); + mount.ExportTitleData(DSIWARE_CATEGORY, titleId, melonDS::DSi_NAND::TitleData_BannerSav, "banner.sav"); } } } -ECL_EXPORT void DSiWareSavsLength(u32 titleId, u32* publicSavSize, u32* privateSavSize, u32* bannerSavSize) +ECL_EXPORT void DSiWareSavsLength(melonDS::DSi* dsi, u32 titleId, u32* publicSavSize, u32* privateSavSize, u32* bannerSavSize) { *publicSavSize = *privateSavSize = *bannerSavSize = 0; - auto& nand = DSi::NANDImage; - if (nand && *nand) + if (auto& nand = dsi->GetNAND()) { - if (auto mount = DSi_NAND::NANDMount(*nand)) + if (auto mount = melonDS::DSi_NAND::NANDMount(nand)) { u32 version; - NDSHeader header{}; + melonDS::NDSHeader header{}; mount.GetTitleInfo(DSIWARE_CATEGORY, titleId, version, &header, nullptr); *publicSavSize = header.DSiPublicSavSize; @@ -141,26 +110,24 @@ ECL_EXPORT void DSiWareSavsLength(u32 titleId, u32* publicSavSize, u32* privateS // Perhaps instead it would be better to use FileFlush to write to disk // (guarded by frontend determinism switch, of course) -ECL_EXPORT u32 GetNANDSize() +ECL_EXPORT u32 GetNANDSize(melonDS::DSi* dsi) { - auto& nand = DSi::NANDImage; - if (nand && *nand) + if (auto& nand = dsi->GetNAND()) { - return nand->GetLength(); + return nand.GetLength(); } return 0; } -ECL_EXPORT void GetNANDData(u8* buf) +ECL_EXPORT void GetNANDData(melonDS::DSi* dsi, u8* buf) { - auto& nand = DSi::NANDImage; - if (nand && *nand) + if (auto& nand = dsi->GetNAND()) { - auto len = nand->GetLength(); - auto file = nand->GetFile(); - Platform::FileRewind(file); - Platform::FileRead(buf, 1, len, file); + auto len = nand.GetLength(); + auto file = nand.GetFile(); + melonDS::Platform::FileRewind(file); + melonDS::Platform::FileRead(buf, 1, len, file); } } @@ -174,8 +141,8 @@ void WriteGBASave(const u8* savedata, u32 savelen, u32 writeoffset, u32 writelen GbaSaveRamIsDirty = true; } -void WriteFirmware(const SPI_Firmware::Firmware& firmware, u32 writeoffset, u32 writelen) -{ +void WriteFirmware(const melonDS::Firmware& firmware, u32 writeoffset, u32 writelen) +{ } void WriteDateTime(int year, int month, int day, int hour, int minute, int second) diff --git a/waterbox/melon/BizPlatform/BizThread.cpp b/waterbox/melon/BizPlatform/BizThread.cpp index 741bb5d2c27..8d27fb7d6e6 100644 --- a/waterbox/melon/BizPlatform/BizThread.cpp +++ b/waterbox/melon/BizPlatform/BizThread.cpp @@ -2,7 +2,7 @@ #include -namespace Platform +namespace melonDS::Platform { static uintptr_t FrameThreadProc = 0; diff --git a/waterbox/melon/BizTypes.h b/waterbox/melon/BizTypes.h new file mode 100644 index 00000000000..59efe1550c3 --- /dev/null +++ b/waterbox/melon/BizTypes.h @@ -0,0 +1,15 @@ +#ifndef BIZTYPES_H +#define BIZTYPES_H + +#include "types.h" + +using melonDS::u8; +using melonDS::u16; +using melonDS::u32; +using melonDS::u64; +using melonDS::s8; +using melonDS::s16; +using melonDS::s32; +using melonDS::s64; + +#endif diff --git a/waterbox/melon/Makefile b/waterbox/melon/Makefile index d05ca4705f4..6fb6acb7375 100644 --- a/waterbox/melon/Makefile +++ b/waterbox/melon/Makefile @@ -1,6 +1,6 @@ CCFLAGS := -Wno-incompatible-pointer-types-discards-qualifiers -Wno-pointer-sign -CXXFLAGS := -DMELONDS_VERSION="" -DOGLRENDERER_ENABLED \ +CXXFLAGS := -DOGLRENDERER_ENABLED \ -I. -I./melonDS/src -I./melonDS/src/teakra/include \ -Wall -Wextra -Werror=int-to-pointer-cast \ -Wfatal-errors -Wno-unused-parameter -Wno-unused-variable \ @@ -8,11 +8,13 @@ CXXFLAGS := -DMELONDS_VERSION="" -DOGLRENDERER_ENABLED \ -Wno-sign-compare -Wno-deprecated-declarations \ -Wno-missing-braces -Wno-bitwise-instead-of-logical \ -Wno-unused-private-field -Wno-logical-op-parentheses \ - -fno-strict-aliasing -std=c++17 + -Wno-mismatched-tags -Wno-reorder-ctor \ + -fno-strict-aliasing -fwrapv -std=c++17 TARGET = melonDS.wbx CORE_SRCS = \ + ARCodeFile.cpp \ AREngine.cpp \ ARM.cpp \ ARMInterpreter.cpp \ @@ -42,20 +44,25 @@ CORE_SRCS = \ GPU2D_Soft.cpp \ GPU3D.cpp \ GPU3D_Soft.cpp \ + GPU3D_Texcache.cpp \ NDS.cpp \ NDSCart.cpp \ + NDSCartR4.cpp \ ROMList.cpp \ RTC.cpp \ Savestate.cpp \ SPI.cpp \ SPI_Firmware.cpp \ SPU.cpp \ + Utils.cpp \ Wifi.cpp \ WifiAP.cpp CORE_GL_SRCS = \ GPU_OpenGL.cpp \ GPU3D_OpenGL.cpp \ + GPU3D_Compute.cpp \ + GPU3D_TexcacheOpenGL.cpp \ OpenGLSupport.cpp \ frontend/Util_Video.cpp @@ -82,7 +89,6 @@ MISC_SRCS = \ blip_buf/blip_buf.c \ BIZPLATFORM_SRCS = \ - BizPlatform/BizConfig.cpp \ BizPlatform/BizFile.cpp \ BizPlatform/BizLog.cpp \ BizPlatform/BizOGL.cpp \ @@ -97,8 +103,8 @@ SRCS = \ $(addprefix melonDS/src/fatfs/,$(FATFS_SRCS)) \ $(addprefix melonDS/src/,$(MISC_SRCS)) \ $(BIZPLATFORM_SRCS) \ + BizConsoleCreator.cpp \ BizDebugging.cpp \ - BizFileManager.cpp \ BizGLPresenter.cpp \ BizInterface.cpp \ dthumb.c diff --git a/waterbox/melon/melonDS b/waterbox/melon/melonDS index d4899fe9b96..4e02967468c 160000 --- a/waterbox/melon/melonDS +++ b/waterbox/melon/melonDS @@ -1 +1 @@ -Subproject commit d4899fe9b9669edf009b52b2d432280c597cbdfd +Subproject commit 4e02967468c3b5ea853f5fdb0ca0b25a02fd601c diff --git a/waterbox/melon/version.h b/waterbox/melon/version.h new file mode 100644 index 00000000000..5aae135a963 --- /dev/null +++ b/waterbox/melon/version.h @@ -0,0 +1,6 @@ +#ifndef VERSION_H +#define VERSION_H + +#define MELONDS_VERSION_BASE "BizHawk" + +#endif diff --git a/waterbox/readme.txt b/waterbox/readme.txt index 141e669321d..be2471bbc63 100644 --- a/waterbox/readme.txt +++ b/waterbox/readme.txt @@ -25,8 +25,8 @@ It consists of a modified musl libc, and build scripts to tie it all together. 2. For older Debian/Ubuntu based distros, the package manager might not provide a recent enough compiler for the waterbox toolchain. In these cases, it is recommended to obtain clang and other llvm tools from llvm's apt repository: https://apt.llvm.org/ 2. Clone bizhawk sources - * Make sure git's core.autocrlf is set to false, as the alternatives cause git to modify the line endings in .sh-looking files which WILL break the build process, from the very first step. - * This is NOT git's default. You will need to change it!! Go ahead and set it false globally permanently, since do you really want git modifying files? + * Make sure git's core.autocrlf is not set to true, as otherwise git will modify the line endings in all text files, including .sh files, which WILL break the build process, from the very first step. + * This is NOT git's default. You will need to change it! We recommend changing this setting to false globally to prevent git from unexpectedly modifying files. * Make sure you have initialized and updated the needed submodules in the waterbox directory, a listing of these is here: * waterbox/musl (required for the entire waterbox toolchain) * waterbox/ares64/ares/thirdparty/angrylion-rdp (required for ares64) @@ -35,7 +35,9 @@ It consists of a modified musl libc, and build scripts to tie it all together. * waterbox/melon/melonDS (required for melonDS) * waterbox/nyma/mednafen (required for all Nyma cores) * waterbox/snes9x (required for Snes9x) - * waterbox/llvm-project is needed for the entire waterbox toolchain, but initializing and updating this is handled automatically by later scripts, so you do not need to do anything about this + * waterbox/gpgx/Genesis-Plus-GX (required for gpgx) + * waterbox/uae/libretro-uae (required for puae) + * none of these submodules need to be cloned recursively 3. Consider whether it is time to update your build environment (i.e. sudo apt-get upgrade). Build environment tools are generally best kept at the latest version, to ensure top performance for our users. @@ -51,7 +53,7 @@ It consists of a modified musl libc, and build scripts to tie it all together. ./do-everything.sh cd .. -4a. At ./wbox_configure, you may need to specify the compiler used. By default, it will try to use clang without a version suffix. If this is not present, it falls on the user to specify a CC variable (e.g. `CC=gcc-12 ./wbox_configure`). This is the only stage which the build tool may need to be manually specified, all future steps will remember this specification and thus need no manual input. +4a. At ./wbox_configure, you may need to specify the compiler used. By default, it will try to use clang without a version suffix. If this is not present, it falls on the user to specify a CC variable (e.g. `CC=gcc-13 ./wbox_configure`). This is the only stage which the build tool may need to be manually specified, all future steps will remember this specification and thus need no manual input. 4b. If errors happen in the libcxx part, it can be due to musl mismatching your current build environment. This happens when your build environment is updated; musl does not track its build dependencies correctly. do `make clean` on musl (and delete the non-checkedin directories just to be safe) and try again from the musl step. @@ -76,6 +78,7 @@ It consists of a modified musl libc, and build scripts to tie it all together. cd picodrive && make install cd snes9x && make install cd tic80 && make install + cd uae && make install cd uzem && make install cd virtualjaguar && make install diff --git a/waterbox/tic80/BizInterface.c b/waterbox/tic80/BizInterface.c index 1fed52c1124..f2c0dbd97e5 100644 --- a/waterbox/tic80/BizInterface.c +++ b/waterbox/tic80/BizInterface.c @@ -90,6 +90,12 @@ ECL_EXPORT void SetInputs(tic80_input* inputs) memcpy(&biz_inputs, inputs, sizeof(tic80_input)); } +ECL_EXPORT bool IsMouseRelative() +{ + tic_mem* mem = (tic_mem*)tic; + return mem->ram->input.mouse.relative; +} + typedef struct { FrameInfo b; diff --git a/waterbox/uae/Makefile b/waterbox/uae/Makefile new file mode 100644 index 00000000000..1641ba2f628 --- /dev/null +++ b/waterbox/uae/Makefile @@ -0,0 +1,270 @@ +CORE_DIR = libretro-uae +TARGET = puae.wbx +EMU = $(CORE_DIR)/sources/src +LIBRETRO = $(CORE_DIR)/libretro +DEPS_DIR = $(CORE_DIR)/deps +RETRODEP = $(CORE_DIR)/retrodep +LIBRETRO_COMM_DIR = $(CORE_DIR)/libretro-common + +SOURCES_C += bizhawk.c + +INCFLAGS = \ + -I$(EMU) \ + -I$(EMU)/include \ + -I$(CORE_DIR) \ + -I$(RETRODEP) \ + -I$(DEPS_DIR)/7zip \ + -I$(DEPS_DIR)/libmpeg2/include \ + -I$(LIBRETRO) \ + -I$(LIBRETRO_COMM_DIR)/include \ + -I$(LIBRETRO_COMM_DIR)/include/compat/zlib + +LDFLAGS += + +CCFLAGS += \ + -std=gnu99 \ + -w -ferror-limit=0 + +CCFLAGS += $(INCFLAGS) \ + -D__LIBRETRO__ \ + -DINLINE="inline" \ + -MMD \ + -DHAVE_ZLIB \ + -DHAVE_7ZIP \ + -D_7ZIP_ST \ + -DWATERBOX \ + -DWITH_MPEG2 + +#CCFLAGS += \ + -DPICASSO96_SUPPORTED \ + +CXXFLAGS += $(INCFLAGS) -DUAE -MMD + +SOURCES_C += \ + $(LIBRETRO)/libretro-core.c \ + $(LIBRETRO)/libretro-mapper.c \ + $(LIBRETRO)/libretro-dc.c \ + $(LIBRETRO)/libretro-glue.c \ + $(LIBRETRO)/libretro-vkbd.c \ + $(LIBRETRO)/libretro-graph.c \ + $(DEPS_DIR)/libz/unzip.c \ + $(DEPS_DIR)/libz/ioapi.c + +SOURCES_C += \ + $(EMU)/a2065.c \ + $(EMU)/a2091.c \ + $(EMU)/akiko.c \ + $(EMU)/amax.c \ + $(EMU)/ar.c \ + $(EMU)/arcadia.c \ + $(EMU)/aros.rom.c \ + $(EMU)/audio.c \ + $(EMU)/autoconf.c \ + $(EMU)/blitfunc.c \ + $(EMU)/blittable.c \ + $(EMU)/blitter.c \ + $(EMU)/blkdev.c \ + $(EMU)/blkdev_cdimage.c \ + $(EMU)/bsdsocket.c \ + $(EMU)/calc.c \ + $(EMU)/caps/caps.c \ + $(EMU)/caps/uae_dlopen.c \ + $(EMU)/casablanca.c \ + $(EMU)/cd32_fmv.c \ + $(EMU)/cd32_fmv_genlock.c \ + $(EMU)/cda_play.c \ + $(EMU)/cdrom.c \ + $(EMU)/cdtv.c \ + $(EMU)/cdtvcr.c \ + $(EMU)/cfgfile.c \ + $(EMU)/cia.c \ + $(EMU)/cpuboard.c \ + $(EMU)/cpudefs.c \ + $(EMU)/cpuemu_0.c \ + $(EMU)/cpuemu_11.c \ + $(EMU)/cpuemu_13.c \ + $(EMU)/cpuemu_20.c \ + $(EMU)/cpuemu_21.c \ + $(EMU)/cpuemu_22.c \ + $(EMU)/cpuemu_23.c \ + $(EMU)/cpuemu_24.c \ + $(EMU)/cpuemu_31.c \ + $(EMU)/cpuemu_32.c \ + $(EMU)/cpuemu_33.c \ + $(EMU)/cpuemu_34.c \ + $(EMU)/cpuemu_35.c \ + $(EMU)/cpuemu_40.c \ + $(EMU)/cpuemu_50.c \ + $(EMU)/cpummu.c \ + $(EMU)/cpummu30.c \ + $(EMU)/cpustbl.c \ + $(EMU)/crc32.c \ + $(EMU)/custom.c \ + $(EMU)/debug.c \ + $(EMU)/debugmem.c \ + $(EMU)/devices.c \ + $(EMU)/disasm.c \ + $(EMU)/disk.c \ + $(EMU)/diskutil.c \ + $(EMU)/dongle.c \ + $(EMU)/drawing.c \ + $(EMU)/driveclick.c \ + $(EMU)/ethernet.c \ + $(EMU)/events.c \ + $(EMU)/expansion.c \ + $(EMU)/fdi2raw.c\ + $(EMU)/filesys.c \ + $(EMU)/filesys_unix.c \ + $(EMU)/flashrom.c \ + $(EMU)/fpp.c \ + $(EMU)/fpp_native.c \ + $(EMU)/fpp_softfloat.c \ + $(EMU)/fsdb.c \ + $(EMU)/fsdb_unix.c \ + $(EMU)/fsusage.c \ + $(EMU)/gayle.c \ + $(EMU)/gfxboard.c \ + $(EMU)/gfxlib.c \ + $(EMU)/gfxutil.c \ + $(EMU)/hardfile.c \ + $(EMU)/hardfile_unix.c \ + $(EMU)/hrtmon.rom.c \ + $(EMU)/ide.c \ + $(EMU)/idecontrollers.c \ + $(EMU)/identify.c \ + $(EMU)/ini.c \ + $(EMU)/inputdevice.c \ + $(EMU)/isofs.c \ + $(EMU)/keybuf.c \ + $(EMU)/main.c \ + $(EMU)/memory.c \ + $(EMU)/misc.c \ + $(EMU)/missing.c \ + $(EMU)/native2amiga.c \ + $(EMU)/ncr_scsi.c \ + $(EMU)/ncr9x_scsi.c \ + $(EMU)/newcpu.c \ + $(EMU)/newcpu_common.c \ + $(EMU)/pci.c \ + $(EMU)/picasso96.c \ + $(EMU)/readcpu.c \ + $(EMU)/rommgr.c \ + $(EMU)/rtc.c \ + $(EMU)/sampler.c \ + $(EMU)/sana2.c \ + $(EMU)/savestate.c \ + $(EMU)/scsi.c \ + $(EMU)/scsiemul.c \ + $(EMU)/scsitape.c \ + $(EMU)/sndboard.c \ + $(EMU)/specialmonitors.c \ + $(EMU)/statusline.c \ + $(EMU)/test_card.c\ + $(EMU)/traps.c\ + $(EMU)/uaelib.c \ + $(EMU)/uaenet.c \ + $(EMU)/uaeresource.c \ + $(EMU)/uaeserial.c \ + $(EMU)/writelog.c \ + $(EMU)/x86.c \ + $(EMU)/zfile.c \ + $(EMU)/zfile_archive.c \ + $(EMU)/softfloat/softfloat.c \ + $(EMU)/softfloat/softfloat_decimal.c \ + $(EMU)/softfloat/softfloat_fpsp.c + +SOURCES_C += \ + $(RETRODEP)/gui.c \ + $(RETRODEP)/main.c \ + $(RETRODEP)/mman.c \ + $(RETRODEP)/parser.c \ + $(RETRODEP)/serial_host.c \ + $(RETRODEP)/machdep/support.c \ + $(RETRODEP)/sounddep/sound.c \ + $(RETRODEP)/stubs/inputrecord.c \ + $(RETRODEP)/threaddep/thread.c + +SOURCES_C += \ + $(EMU)/archivers/dms/crc_csum.c \ + $(EMU)/archivers/dms/getbits.c \ + $(EMU)/archivers/dms/maketbl.c \ + $(EMU)/archivers/dms/pfile.c \ + $(EMU)/archivers/dms/tables.c \ + $(EMU)/archivers/dms/u_deep.c \ + $(EMU)/archivers/dms/u_heavy.c \ + $(EMU)/archivers/dms/u_init.c \ + $(EMU)/archivers/dms/u_medium.c \ + $(EMU)/archivers/dms/u_quick.c \ + $(EMU)/archivers/dms/u_rle.c \ + $(EMU)/archivers/lha/crcio.c \ + $(EMU)/archivers/lha/dhuf.c \ + $(EMU)/archivers/lha/header.c \ + $(EMU)/archivers/lha/huf.c \ + $(EMU)/archivers/lha/larc.c \ + $(EMU)/archivers/lha/lhamaketbl.c \ + $(EMU)/archivers/lha/lharc.c \ + $(EMU)/archivers/lha/shuf.c \ + $(EMU)/archivers/lha/slide.c \ + $(EMU)/archivers/lha/uae_lha.c \ + $(EMU)/archivers/lha/util.c \ + $(EMU)/archivers/mp2/kjmp2.c + +SOURCES_C += \ + $(DEPS_DIR)/libmpeg2/src/convert/rgb.c \ + $(DEPS_DIR)/libmpeg2/src/cpu_accel.c \ + $(DEPS_DIR)/libmpeg2/src/cpu_state.c \ + $(DEPS_DIR)/libmpeg2/src/alloc.c \ + $(DEPS_DIR)/libmpeg2/src/decode.c \ + $(DEPS_DIR)/libmpeg2/src/header.c \ + $(DEPS_DIR)/libmpeg2/src/idct.c \ + $(DEPS_DIR)/libmpeg2/src/motion_comp.c \ + $(DEPS_DIR)/libmpeg2/src/slice.c + +SOURCES_C += \ + $(DEPS_DIR)/libz/adler32.c \ + $(DEPS_DIR)/libz/crc32.c \ + $(DEPS_DIR)/libz/deflate.c \ + $(DEPS_DIR)/libz/gzclose.c \ + $(DEPS_DIR)/libz/gzlib.c \ + $(DEPS_DIR)/libz/gzread.c \ + $(DEPS_DIR)/libz/gzwrite.c \ + $(DEPS_DIR)/libz/inffast.c \ + $(DEPS_DIR)/libz/inflate.c \ + $(DEPS_DIR)/libz/inftrees.c \ + $(DEPS_DIR)/libz/trees.c \ + $(DEPS_DIR)/libz/zutil.c + +SOURCES_C += \ + $(DEPS_DIR)/7zip/7zArcIn.c \ + $(DEPS_DIR)/7zip/7zBuf.c \ + $(DEPS_DIR)/7zip/7zCrc.c \ + $(DEPS_DIR)/7zip/7zCrcOpt.c \ + $(DEPS_DIR)/7zip/7zDec.c \ + $(DEPS_DIR)/7zip/7zFile.c \ + $(DEPS_DIR)/7zip/7zStream.c \ + $(DEPS_DIR)/7zip/Bcj2.c \ + $(DEPS_DIR)/7zip/Bra.c \ + $(DEPS_DIR)/7zip/Bra86.c \ + $(DEPS_DIR)/7zip/BraIA64.c \ + $(DEPS_DIR)/7zip/CpuArch.c \ + $(DEPS_DIR)/7zip/Delta.c \ + $(DEPS_DIR)/7zip/Lzma2Dec.c \ + $(DEPS_DIR)/7zip/LzmaDec.c + +SOURCES_C += \ + $(LIBRETRO_COMM_DIR)/compat/compat_strl.c \ + $(LIBRETRO_COMM_DIR)/compat/compat_strcasestr.c \ + $(LIBRETRO_COMM_DIR)/compat/fopen_utf8.c \ + $(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \ + $(LIBRETRO_COMM_DIR)/file/file_path.c \ + $(LIBRETRO_COMM_DIR)/file/file_path_io.c \ + $(LIBRETRO_COMM_DIR)/file/retro_dirent.c \ + $(LIBRETRO_COMM_DIR)/streams/file_stream.c \ + $(LIBRETRO_COMM_DIR)/streams/file_stream_transforms.c \ + $(LIBRETRO_COMM_DIR)/string/stdstring.c \ + $(LIBRETRO_COMM_DIR)/time/rtime.c \ + $(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c + +SRCS = $(SOURCES_C) + +include ../common.mak \ No newline at end of file diff --git a/waterbox/uae/bizhawk.c b/waterbox/uae/bizhawk.c new file mode 100644 index 00000000000..6a7b9271559 --- /dev/null +++ b/waterbox/uae/bizhawk.c @@ -0,0 +1,99 @@ +#include "bizhawk.h" + +ECL_EXPORT bool Init(int argc, char **argv) +{ + last_mouse_x = 0; + last_mouse_y = 0; + libretro_runloop_active = 0; + pix_bytes = 4; + defaultw = PUAE_VIDEO_WIDTH; + defaulth = PUAE_VIDEO_HEIGHT_PAL; + retrow = PUAE_VIDEO_WIDTH; + retrow_crop = retrow; + retroh_crop = retroh; + log_cb = biz_log_cb; + + retro_set_audio_sample_batch(biz_audio_cb); + init_output_audio_buffer(2048); + umain(argc, argv); + m68k_go(1, 0); + + libretro_runloop_active = 1; + + return true; +} + +ECL_EXPORT void FrameAdvance(MyFrameInfo* f) +{ + f->base.Width = 720; + f->base.Height = 576; + sound_buffer = f->base.SoundBuffer; + thisframe_y_adjust = minfirstline; + visible_left_border = retro_max_diwlastword - retrow; + + setjoystickstate(PORT_0, AXIS_VERTICAL, + f->JoystickState.up ? JOY_MIN : + f->JoystickState.down ? JOY_MAX : JOY_MID, 1); + setjoystickstate(PORT_0, AXIS_HORIZONTAL, + f->JoystickState.left ? JOY_MIN : + f->JoystickState.right ? JOY_MAX : JOY_MID, 1); + setjoybuttonstate(PORT_0, 0, f->JoystickState.b1); + setjoybuttonstate(PORT_0, 1, f->JoystickState.b2); + setjoybuttonstate(PORT_0, 2, f->JoystickState.b3); + + setmousebuttonstate(PORT_0, MOUSE_LEFT, f->MouseButtons & 1); + setmousebuttonstate(PORT_0, MOUSE_RIGHT, f->MouseButtons & 2); + setmousebuttonstate(PORT_0, MOUSE_MIDDLE, f->MouseButtons & 4); + setmousestate( PORT_0, AXIS_HORIZONTAL, f->MouseX - last_mouse_x, MOUSE_RELATIVE); + setmousestate( PORT_0, AXIS_VERTICAL, f->MouseY - last_mouse_y, MOUSE_RELATIVE); + + for (int i = 0; i < KEY_COUNT; i++) + if (f->Keys[i] != last_key_state[i]) + inputdevice_do_keyboard(i, f->Keys[i]); + memcpy(last_key_state, f->Keys, KEY_COUNT); + + if (f->Action == ACTION_EJECT) + { + disk_eject(f->CurrentDrive); + log_cb(RETRO_LOG_INFO, "EJECTED FD%d\n", f->CurrentDrive); + } + else if (f->Action == ACTION_INSERT) + { + disk_eject(f->CurrentDrive); + disk_insert_force(f->CurrentDrive, f->FileName, true); + log_cb(RETRO_LOG_INFO, "INSERTED FD%d: \"%s\"\n", f->CurrentDrive, f->FileName); + } + + m68k_go(1, 1); + upload_output_audio_buffer(); + f->base.Samples = sound_sample_count; + memcpy(f->base.VideoBuffer, retro_bmp, sizeof(retro_bmp) / sizeof(retro_bmp[0])); + last_mouse_x = f->MouseX; + last_mouse_y = f->MouseY; + sound_buffer = NULL; +} + +ECL_EXPORT void GetMemoryAreas(MemoryArea *m) +{ + m[0].Data = chipmem_bank.baseaddr; + m[0].Name = "Chip RAM"; + m[0].Size = chipmem_bank.allocated_size; + m[0].Flags = MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_PRIMARY; + + m[1].Data = bogomem_bank.baseaddr; + m[1].Name = "Slow RAM"; + m[1].Size = bogomem_bank.allocated_size; + m[1].Flags = MEMORYAREA_FLAGS_WORDSIZE1; + + m[2].Data = fastmem_bank[0].baseaddr; + m[2].Name = "Fast RAM"; + m[2].Size = fastmem_bank[0].allocated_size; + m[2].Flags = MEMORYAREA_FLAGS_WORDSIZE1; +} + +void (*InputCallback)(); + +ECL_EXPORT void SetInputCallback(void (*callback)()) +{ + InputCallback = callback; +} diff --git a/waterbox/uae/bizhawk.h b/waterbox/uae/bizhawk.h new file mode 100644 index 00000000000..45a88f70348 --- /dev/null +++ b/waterbox/uae/bizhawk.h @@ -0,0 +1,146 @@ +#pragma once + +// system +#include +#include +#include +#include + +// waterbox +#include "emulibc.h" +#include "waterboxcore.h" + +// core +#include "include/sysdeps.h" +#include "include/options.h" +#include "include/uae.h" +#include "include/memory.h" +#include "include/custom.h" +#include "include/drawing.h" +#include "include/inputdevice.h" + +#include "libretro/libretro-core.h" + +static const int FILENAME_MAXLENGTH = 4; +static const int KEY_COUNT = 0x68; + +int16_t* sound_buffer = NULL; +int sound_sample_count = 0; +static char last_key_state[KEY_COUNT]; +static int last_mouse_x; +static int last_mouse_y; + +extern int thisframe_y_adjust; +extern unsigned short int defaultw; +extern unsigned short int defaulth; +extern int retro_max_diwlastword; + +extern int umain(int argc, char **argv); +extern int m68k_go(int may_quit, int resume); +extern void init_output_audio_buffer(int32_t capacity); +extern void upload_output_audio_buffer(); +extern void disk_eject(int num); +extern void disk_insert_force (int num, const TCHAR *name, bool forcedwriteprotect); + +enum Axis +{ + AXIS_HORIZONTAL, + AXIS_VERTICAL +}; + +enum JoystickRange +{ + JOY_MIN = -1, + JOY_MID, + JOY_MAX +}; + +enum ControllerPort +{ + PORT_0, + PORT_1 +}; + +enum MouseButtons +{ + MOUSE_LEFT, + MOUSE_RIGHT, + MOUSE_MIDDLE +}; + +enum MousePosition +{ + MOUSE_RELATIVE, + MOUSE_ABSOLUTE +}; + +enum AudioChannels +{ + AUDIO_MONO = 1, + AUDIO_STEREO +}; + +enum DriveAction +{ + ACTION_NONE, + ACTION_EJECT, + ACTION_INSERT +}; + +typedef union +{ + struct + { + bool up:1; + bool down:1; + bool left:1; + bool right:1; + bool b1:1; + bool b2:1; + bool b3:1; + }; + uint8_t data; +} PUAEJoystick; + +typedef struct +{ + FrameInfo base; + PUAEJoystick JoystickState; + uint8_t MouseButtons; + int MouseX; + int MouseY; + char Keys[KEY_COUNT]; + int CurrentDrive; + int Action; + char FileName[FILENAME_MAXLENGTH]; +} MyFrameInfo; + +size_t biz_audio_cb(const int16_t *data, size_t frames) +{ + sound_sample_count = frames; + memcpy(sound_buffer, data, frames * sizeof(int16_t) * AUDIO_STEREO); +} + +void biz_log_cb(enum retro_log_level level, const char *fmt, ...) +{ + fprintf(stderr, "[PUAE "); + switch (level) + { + case RETRO_LOG_DEBUG: + fprintf(stderr, "DEBUG]: "); + break; + case RETRO_LOG_INFO: + fprintf(stderr, "INFO]: "); + break; + case RETRO_LOG_WARN: + fprintf(stderr, "WARN]: "); + break; + case RETRO_LOG_ERROR: + fprintf(stderr, "ERROR]: "); + break; + } + va_list va; + va_start(va, fmt); + vfprintf(stderr, fmt, va); + va_end(va); +} \ No newline at end of file diff --git a/waterbox/uae/libretro-uae b/waterbox/uae/libretro-uae new file mode 160000 index 00000000000..5de7a00350b --- /dev/null +++ b/waterbox/uae/libretro-uae @@ -0,0 +1 @@ +Subproject commit 5de7a00350b21f79805881cf36af8234aa7c3fd6 diff --git a/waterbox/uzem/uzem.cpp b/waterbox/uzem/uzem.cpp index 875c22f2dd6..af345adae93 100644 --- a/waterbox/uzem/uzem.cpp +++ b/waterbox/uzem/uzem.cpp @@ -96,7 +96,7 @@ ECL_EXPORT bool Init() srand(uzebox.randomSeed); //used for the watchdog timer entropy blip = blip_new(2048); - blip_set_rates(blip, 28618182, 44100); + blip_set_rates(blip, 315000000.0 / 11.0, 44100); return true; } diff --git a/waterbox/waterboxhost/Cargo.lock b/waterbox/waterboxhost/Cargo.lock index 973efbb2aec..460af3e08de 100644 --- a/waterbox/waterboxhost/Cargo.lock +++ b/waterbox/waterboxhost/Cargo.lock @@ -1,16 +1,18 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "anyhow" -version = "1.0.31" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "block-buffer" @@ -23,25 +25,19 @@ dependencies = [ [[package]] name = "cfg-if" -version = "0.1.10" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cloudabi" -version = "0.0.3" +name = "cpufeatures" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ - "bitflags", + "libc", ] -[[package]] -name = "cpuid-bool" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d375c433320f6c5057ae04a04376eef4d04ce2801448cf8863a78da99107be4" - [[package]] name = "digest" version = "0.9.0" @@ -53,15 +49,15 @@ dependencies = [ [[package]] name = "either" -version = "1.5.3" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "generic-array" -version = "0.14.2" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac746a5f3bbfdadd6106868134545e684693d54d9d44f6e9588a7d54af0bf980" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -95,33 +91,21 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" - -[[package]] -name = "lock_api" -version = "0.3.4" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" -dependencies = [ - "scopeguard", -] +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "log" -version = "0.4.8" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -dependencies = [ - "cfg-if", -] +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "page_size" @@ -133,30 +117,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "parking_lot" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" -dependencies = [ - "cfg-if", - "cloudabi", - "libc", - "redox_syscall", - "smallvec", - "winapi", -] - [[package]] name = "plain" version = "0.2.3" @@ -165,48 +125,36 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "proc-macro2" -version = "1.0.18" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.7" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.1.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - [[package]] name = "scroll" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb2332cb595d33f7edd5700f4cbf94892e680c7f0ae56adab58a35190b66cb1" +checksum = "fda28d4b4830b807a8b43f7b0e6b5df875311b3e7621d84577188c175b6ec1ec" dependencies = [ "scroll_derive", ] [[package]] name = "scroll_derive" -version = "0.10.2" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e367622f934864ffa1c704ba2b82280aab856e3d8213c84c5720257eb34b15b9" +checksum = "aaaae8f38bb311444cfb7f1979af0bc9240d95795f75f9ceddf6a59b79ceffa0" dependencies = [ "proc-macro2", "quote", @@ -215,51 +163,45 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.1" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer", "cfg-if", - "cpuid-bool", + "cpufeatures", "digest", "opaque-debug", ] -[[package]] -name = "smallvec" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" - [[package]] name = "syn" -version = "1.0.32" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a994520748611c17d163e81b6c4a4b13d11b7f63884362ab2efac3aa9cf16d00" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] name = "typenum" -version = "1.12.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] -name = "unicode-xid" -version = "0.2.0" +name = "unicode-ident" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "version_check" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "waterboxhost" @@ -272,16 +214,15 @@ dependencies = [ "lazy_static", "libc", "page_size", - "parking_lot", "sha2", "winapi", ] [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", diff --git a/waterbox/waterboxhost/Cargo.toml b/waterbox/waterboxhost/Cargo.toml index 7f1fbeb99bb..6b21055d39e 100644 --- a/waterbox/waterboxhost/Cargo.toml +++ b/waterbox/waterboxhost/Cargo.toml @@ -13,21 +13,19 @@ no-dirty-detection = [] lto = true [dependencies] -bitflags = "1.2.1" +bitflags = "1.3.2" page_size = "0.4.2" lazy_static = "1.4.0" -#getset = "0.1.1" -parking_lot = "0.10.2" itertools = "0.9.0" goblin = { version = "0.2.3", features = ["elf64", "std"] } anyhow = "1.0" -sha2 = "0.9.1" +sha2 = "0.9.9" [target.'cfg(windows)'.dependencies] -winapi = { version = "0.3.8", features = ["memoryapi", "handleapi", "errhandlingapi", "winnt"] } +winapi = { version = "0.3.9", features = ["memoryapi", "handleapi", "errhandlingapi", "winnt"] } [target.'cfg(unix)'.dependencies] -libc = "0.2.71" +libc = "0.2.155" [lib] doctest = false diff --git a/waterbox/waterboxhost/README.md b/waterbox/waterboxhost/README.md index 0d4edbdef96..e904e6be0cf 100644 --- a/waterbox/waterboxhost/README.md +++ b/waterbox/waterboxhost/README.md @@ -35,7 +35,7 @@ Some more advanced features: ## Building -Standard rust build infrastructure is used and can be installed with `rustup`. At the moment, we're using the `nightly-x86_64-pc-windows-gnu` +Standard rust build infrastructure is used and can be installed with `rustup`. At the moment, we're using the `nightly-x86_64-pc-windows-msvc` chain on Windows, and the `nightly-x86_64-unknown-linux-gnu` chain on linux. I don't know much about crosspiling, but presumably that will work. The linux chain works fine in WSL, anyway. When used in a Windows environment with the right default chain, `build-release.bat` will build waterboxhost.dll and copy it to the right place. When used in a Linux (or WSL) environment with the right default chain, `build-release.sh` diff --git a/waterbox/waterboxhost/build-debug-no-dirty-detection.bat b/waterbox/waterboxhost/build-debug-no-dirty-detection.bat index f385b0af1d6..d0ee8c89606 100644 --- a/waterbox/waterboxhost/build-debug-no-dirty-detection.bat +++ b/waterbox/waterboxhost/build-debug-no-dirty-detection.bat @@ -1,3 +1,3 @@ -@cargo b --features "no-dirty-detection" +@cargo +nightly b --features "no-dirty-detection" @copy target\debug\waterboxhost.dll ..\..\Assets\dll @copy target\debug\waterboxhost.dll ..\..\output\dll diff --git a/waterbox/waterboxhost/build-debug-no-dirty-detection.sh b/waterbox/waterboxhost/build-debug-no-dirty-detection.sh old mode 100644 new mode 100755 index a88ce44d7e4..cb187a383f5 --- a/waterbox/waterboxhost/build-debug-no-dirty-detection.sh +++ b/waterbox/waterboxhost/build-debug-no-dirty-detection.sh @@ -1,7 +1,7 @@ #!/bin/sh if [ -z "$BIZHAWKBUILD_HOME" ]; then export BIZHAWKBUILD_HOME="$(realpath "$(dirname "$0")/../..")"; fi -cargo b --features "no-dirty-detection" +cargo +nightly b --features "no-dirty-detection" cp target/debug/libwaterboxhost.so "$BIZHAWKBUILD_HOME/Assets/dll" if [ -e "$BIZHAWKBUILD_HOME/output" ]; then diff --git a/waterbox/waterboxhost/build-debug.bat b/waterbox/waterboxhost/build-debug.bat index 02e2fc82f38..13d1c52f743 100644 --- a/waterbox/waterboxhost/build-debug.bat +++ b/waterbox/waterboxhost/build-debug.bat @@ -1,3 +1,3 @@ -@cargo b +@cargo +nightly b @copy target\debug\waterboxhost.dll ..\..\Assets\dll @copy target\debug\waterboxhost.dll ..\..\output\dll diff --git a/waterbox/waterboxhost/build-debug.sh b/waterbox/waterboxhost/build-debug.sh old mode 100644 new mode 100755 index 4db6d725ab3..44ac1b13ff7 --- a/waterbox/waterboxhost/build-debug.sh +++ b/waterbox/waterboxhost/build-debug.sh @@ -1,7 +1,7 @@ #!/bin/sh if [ -z "$BIZHAWKBUILD_HOME" ]; then export BIZHAWKBUILD_HOME="$(realpath "$(dirname "$0")/../..")"; fi -cargo b +cargo +nightly b cp target/debug/libwaterboxhost.so "$BIZHAWKBUILD_HOME/Assets/dll" if [ -e "$BIZHAWKBUILD_HOME/output" ]; then diff --git a/waterbox/waterboxhost/build-release.bat b/waterbox/waterboxhost/build-release.bat index fa1e00f0b96..87dc8ddf5fe 100644 --- a/waterbox/waterboxhost/build-release.bat +++ b/waterbox/waterboxhost/build-release.bat @@ -1,3 +1,10 @@ -@cargo b --release -@copy target\release\waterboxhost.dll ..\..\Assets\dll -@copy target\release\waterboxhost.dll ..\..\output\dll +:: To maintain Win7/8/8.1 compat for release builds, we must compile using the *-win7-windows-msvc target +:: This is a "Tier 3" target, which does not have prebuilt binaries (e.g. for standard library) available in rustup +:: The simplest way to use this target is to use the build-std argument, which builds the standard library +:: This requires the user to install the nightly toolchain (build-std is not in stable), then add the rust-src component +:: rustup toolchain install nightly-x86_64-pc-windows-msvc +:: rustup component add rust-src --toolchain nightly-x86_64-pc-windows-msvc +:: These don't need to be done for developer only builds (e.g. debug and/or no-dirty-detection), only release builds need this +@cargo +nightly-x86_64-pc-windows-msvc b --release -Z build-std --target x86_64-win7-windows-msvc +@copy target\x86_64-win7-windows-msvc\release\waterboxhost.dll ..\..\Assets\dll +@copy target\x86_64-win7-windows-msvc\release\waterboxhost.dll ..\..\output\dll diff --git a/waterbox/waterboxhost/build-release.sh b/waterbox/waterboxhost/build-release.sh old mode 100644 new mode 100755 index 7940facc97b..9a83d8b2183 --- a/waterbox/waterboxhost/build-release.sh +++ b/waterbox/waterboxhost/build-release.sh @@ -1,7 +1,7 @@ #!/bin/sh if [ -z "$BIZHAWKBUILD_HOME" ]; then export BIZHAWKBUILD_HOME="$(realpath "$(dirname "$0")/../..")"; fi -cargo b --release +cargo +nightly b --release cp target/release/libwaterboxhost.so "$BIZHAWKBUILD_HOME/Assets/dll" if [ -e "$BIZHAWKBUILD_HOME/output" ]; then