Merge branch 'bsnes-emu:master' into master

This commit is contained in:
ds22x 2024-03-09 03:19:31 +01:00 committed by GitHub
commit 9c688ea5cb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 105 additions and 189 deletions

View File

@ -1,33 +1,9 @@
linux-x86_64-binaries_task:
container:
image: ubuntu:latest
setup_script:
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install build-essential libgtk2.0-dev libpulse-dev mesa-common-dev libcairo2-dev libsdl2-dev libxv-dev libao-dev libopenal-dev libudev-dev zip
compile_script:
- make -C bsnes local=false
package_script:
- mkdir bsnes-nightly
- mkdir bsnes-nightly/Database
- mkdir bsnes-nightly/Firmware
- cp -a bsnes/out/bsnes bsnes-nightly/bsnes
- cp -a bsnes/Database/* bsnes-nightly/Database
- cp -a shaders bsnes-nightly/Shaders
- cp -a GPLv3.txt bsnes-nightly
- cp -a extras/* bsnes-nightly
- zip -r bsnes-nightly.zip bsnes-nightly
bsnes-nightly_artifacts:
path: "bsnes-nightly.zip"
freebsd-x86_64-binaries_task: freebsd-x86_64-binaries_task:
freebsd_instance: freebsd_instance:
image_family: freebsd-12-2 image_family: freebsd-12-2
setup_script: setup_script:
- pkg install --yes gmake gdb gcc8 pkgconf sdl2 openal-soft gtk2 libXv zip - pkg install --yes gmake gdb gcc8 pkgconf sdl2 openal-soft gtk3 gtksourceview3 libXv zip
compile_script: compile_script:
- gmake -C bsnes local=false - gmake -C bsnes local=false
@ -45,43 +21,3 @@ freebsd-x86_64-binaries_task:
bsnes-nightly_artifacts: bsnes-nightly_artifacts:
path: "bsnes-nightly.zip" path: "bsnes-nightly.zip"
windows-x86_64-binaries_task:
container:
image: ubuntu:latest
setup_script:
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install build-essential mingw-w64 zip
compile_script:
- make -C bsnes local=false platform=windows compiler="x86_64-w64-mingw32-g++" windres="x86_64-w64-mingw32-windres"
package_script:
- mkdir bsnes-nightly
- mkdir bsnes-nightly/Database
- mkdir bsnes-nightly/Firmware
- cp -a bsnes/out/bsnes.exe bsnes-nightly/bsnes.exe
- cp -a bsnes/Database/* bsnes-nightly/Database
- cp -a shaders bsnes-nightly/Shaders
- cp -a GPLv3.txt bsnes-nightly
- cp -a extras/* bsnes-nightly
- zip -r bsnes-nightly.zip bsnes-nightly
bsnes-nightly_artifacts:
path: "bsnes-nightly.zip"
macOS-aarch64-binaries_task:
macos_instance:
image: ghcr.io/cirruslabs/macos-ventura-base:latest
compile_script:
- make -C bsnes local=false
package_script:
- mkdir bsnes-nightly
- cp -a bsnes/out/bsnes.app bsnes-nightly
- cp -a GPLv3.txt bsnes-nightly
- cp -a extras/* bsnes-nightly
- zip -r bsnes-nightly.zip bsnes-nightly
bsnes-nightly_artifacts:
path: "bsnes-nightly.zip"

View File

@ -5,6 +5,8 @@ on:
tags: [ 'v*' ] tags: [ 'v*' ]
pull_request: pull_request:
branches: [ master ] branches: [ master ]
permissions:
contents: write
jobs: jobs:
build: build:
strategy: strategy:
@ -18,33 +20,33 @@ jobs:
version: latest version: latest
runs-on: ${{ matrix.os.name }}-${{ matrix.os.version }} runs-on: ${{ matrix.os.name }}-${{ matrix.os.version }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: Install Dependencies - name: Install Dependencies
if: matrix.os.name == 'ubuntu' if: matrix.os.name == 'ubuntu'
run: | run: |
sudo apt-get update -y -qq sudo apt-get update -y -qq
sudo apt-get install \ sudo apt-get install libsdl2-dev libgtk-3-dev gtksourceview-3.0 libao-dev libopenal-dev
libgtk2.0-dev libpulse-dev mesa-common-dev libcairo2-dev \
libsdl2-dev libxv-dev libao-dev libopenal-dev libudev-dev
- name: Make - name: Make
run: make -j4 -C bsnes local=false run: make -j4 -C bsnes local=false
- name: Upload - name: Upload
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: bsnes-${{ matrix.os.name }} name: bsnes-${{ matrix.os.name }}
path: bsnes/out/bsnes* path: bsnes/out/bsnes*
release: release:
if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/') if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')
# Prevent multiple conflicting release jobs from running at once.
concurrency: release-${{ github.ref == 'refs/heads/master' && 'nightly' || github.ref }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
- build - build
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
with: with:
path: 'src' path: 'src'
- name: Download Artifacts - name: Download Artifacts
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
path: 'bin' path: 'bin'
- name: Package Artifacts - name: Package Artifacts
@ -85,103 +87,53 @@ jobs:
cd - cd -
done done
- name: Create Release - name: Calculate release info
id: release id: relinfo
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: | run: |
set -eu echo "datetime=$(date -u +"%Y-%m-%d %T %Z")" >> $GITHUB_OUTPUT
github_rest() echo "date=$(date +"%Y-%m-%d")" >> $GITHUB_OUTPUT
{ - name: Delete old nightly release
local method="${1}" uses: actions/github-script@v7
local url="https://api.github.com${2}" id: release
shift 2 if: ${{!startsWith(github.ref, 'refs/tags/')}}
>&2 echo "${method} ${url}" with:
curl \ retries: 3
--fail \ script: |
-H "Accept: application/vnd.github.v3+json" \ const {owner, repo} = context.repo;
-H "Authorization: token ${GITHUB_TOKEN}" \ try {
-X "${method}" \ const release = await github.rest.repos.getReleaseByTag({owner, repo, tag: "nightly"});
"${url}" \ if (release && release.status === 200) {
"$@" await github.rest.repos.deleteRelease({owner, repo, release_id: release.data.id});
} }
github_get_release_id_for_tag() } catch (e) {
{ console.log(`error deleting old release: ${e}`);
payload=$(github_rest GET "/repos/${GITHUB_REPOSITORY}/releases/tags/${1}") || return }
echo "${payload}" | jq .id try {
} await github.rest.git.deleteRef({owner, repo, ref: "tags/nightly"});
github_delete_release_by_id() } catch (e) {
{ console.log(`error trying to delete ref: ${e}`);
github_rest DELETE "/repos/${GITHUB_REPOSITORY}/releases/${1}" }
} await github.rest.git.createTag({
github_delete_tag() owner,
{ repo,
github_rest DELETE "/repos/${GITHUB_REPOSITORY}/git/refs/tags/${1}" tag: "nightly",
} message: "nightly release",
github_create_release() object: context.sha,
{ type: "commit",
local payload="{ })
\"tag_name\": \"${1}\", - name: Create nightly release
\"target_commitish\": \"${2}\", uses: softprops/action-gh-release@v1
\"name\": \"${3}\", if: ${{!startsWith(github.ref, 'refs/tags/')}}
\"body\": \"${4}\", with:
\"draft\": ${5}, tag_name: nightly
\"prerelease\": ${6} name: bsnes nightly ${{steps.relinfo.outputs.date}}
}" body: Auto-generated nightly release on ${{steps.relinfo.outputs.datetime}}
github_rest POST "/repos/${GITHUB_REPOSITORY}/releases" -d "${payload}" files: bsnes*.zip
} prerelease: true
make_nightly_release() - name: Create version release
{ uses: softprops/action-gh-release@v1
github_create_release \ if: ${{startsWith(github.ref, 'refs/tags/')}}
nightly \ with:
"${GITHUB_SHA}" \ name: bsnes ${{github.ref_name}}
"bsnes nightly $(date +"%Y-%m-%d")" \ body: This is bsnes ${{github.ref_name}}, released on ${{steps.relinfo.outputs.date}}.
"Auto-generated nightly release on $(date -u +"%Y-%m-%d %T %Z")" \ files: bsnes*.zip
false \
true
}
make_version_release()
{
github_create_release \
"${1}" \
"${GITHUB_SHA}" \
"bsnes ${1}" \
"This is bsnes ${1}, released on $(date +"%Y-%m-%d")." \
false \
false
}
case ${GITHUB_REF} in
refs/tags/*)
# Create a new version release using the current revision.
echo "UPLOAD_URL=$(make_version_release ${GITHUB_REF#refs/tags/} | jq -r .upload_url)" >> $GITHUB_ENV
;;
refs/heads/master)
# Check for an existing nightly release.
{ release_id=$(github_get_release_id_for_tag nightly); status=$?; } || true
# Delete existing nightly release if it exists.
case ${status} in
0)
github_delete_release_by_id "${release_id}"
# Deleting the 'nightly' release doesn't delete
# the 'nightly' tag, so let's do it manually.
github_delete_tag nightly
;;
22) >&2 echo "No current nightly release; skipping tag deletion." ;;
*) >&2 echo "API call failed unexpectedly." && exit 1 ;;
esac
# Create a new nightly release using the current revision.
echo "UPLOAD_URL=$(make_nightly_release | jq -r .upload_url)" >> $GITHUB_ENV
;;
esac
- name: Upload bsnes-ubuntu
uses: actions/upload-release-asset@v1
env: { GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' }
with: { upload_url: '${{ env.UPLOAD_URL }}', asset_path: 'bsnes-ubuntu.zip', asset_name: 'bsnes-ubuntu.zip', asset_content_type: 'application/zip' }
- name: Upload bsnes-windows
uses: actions/upload-release-asset@v1
env: { GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' }
with: { upload_url: '${{ env.UPLOAD_URL }}', asset_path: 'bsnes-windows.zip', asset_name: 'bsnes-windows.zip', asset_content_type: 'application/zip' }
- name: Upload bsnes-macos
uses: actions/upload-release-asset@v1
env: { GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' }
with: { upload_url: '${{ env.UPLOAD_URL }}', asset_path: 'bsnes-macos.zip', asset_name: 'bsnes-macos.zip', asset_content_type: 'application/zip' }

View File

@ -4,7 +4,7 @@ bsnes
![bsnes logo](bsnes/target-bsnes/resource/logo.png) ![bsnes logo](bsnes/target-bsnes/resource/logo.png)
bsnes is a multi-platform Super Nintendo (Super Famicom) emulator, originally bsnes is a multi-platform Super Nintendo (Super Famicom) emulator, originally
developed by [Near](https://near.sh), which focuses on performance, developed by Near, which focuses on performance,
features, and ease of use. features, and ease of use.
Unique Features Unique Features
@ -62,11 +62,10 @@ Links
Nightly Builds Nightly Builds
-------------- --------------
- [Download](https://github.com/bsnes-emu/bsnes/releases/tag/nightly) - [Windows](https://github.com/bsnes-emu/bsnes/releases/download/nightly/bsnes-windows.zip)
- ![Build status](https://api.cirrus-ci.com/github/bsnes-emu/bsnes.svg?task=windows-x86_64-binaries) - [macOS](https://github.com/bsnes-emu/bsnes/releases/download/nightly/bsnes-macos.zip)
- ![Build status](https://api.cirrus-ci.com/github/bsnes-emu/bsnes.svg?task=macOS-x86_64-binaries) - [Linux](https://github.com/bsnes-emu/bsnes/releases/download/nightly/bsnes-ubuntu.zip)
- ![Build status](https://api.cirrus-ci.com/github/bsnes-emu/bsnes.svg?task=linux-x86_64-binaries) - [FreeBSD](https://api.cirrus-ci.com/v1/artifact/github/bsnes-emu/bsnes/freebsd-x86_64-binaries/bsnes-nightly/bsnes-nightly.zip)
- ![Build status](https://api.cirrus-ci.com/github/bsnes-emu/bsnes.svg?task=freebsd-x86_64-binaries)
Preview Preview
------- -------

View File

@ -113,8 +113,8 @@ auto WDC65816::instructionIndexedIndirectRead8(alu8 op) -> void {
U.l = fetch(); U.l = fetch();
idle2(); idle2();
idle(); idle();
V.l = readDirect(U.l + X.w + 0); V.l = readDirectX(U.l + X.w, 0);
V.h = readDirect(U.l + X.w + 1); V.h = readDirectX(U.l + X.w, 1);
L W.l = readBank(V.w + 0); L W.l = readBank(V.w + 0);
alu(W.l); alu(W.l);
} }
@ -123,8 +123,8 @@ auto WDC65816::instructionIndexedIndirectRead16(alu16 op) -> void {
U.l = fetch(); U.l = fetch();
idle2(); idle2();
idle(); idle();
V.l = readDirect(U.l + X.w + 0); V.l = readDirectX(U.l + X.w, 0);
V.h = readDirect(U.l + X.w + 1); V.h = readDirectX(U.l + X.w, 1);
W.l = readBank(V.w + 0); W.l = readBank(V.w + 0);
L W.h = readBank(V.w + 1); L W.h = readBank(V.w + 1);
alu(W.w); alu(W.w);

View File

@ -90,8 +90,8 @@ auto WDC65816::instructionIndexedIndirectWrite8() -> void {
U.l = fetch(); U.l = fetch();
idle2(); idle2();
idle(); idle();
V.l = readDirect(U.l + X.w + 0); V.l = readDirectX(U.l + X.w, 0);
V.h = readDirect(U.l + X.w + 1); V.h = readDirectX(U.l + X.w, 1);
L writeBank(V.w + 0, A.l); L writeBank(V.w + 0, A.l);
} }
@ -99,8 +99,8 @@ auto WDC65816::instructionIndexedIndirectWrite16() -> void {
U.l = fetch(); U.l = fetch();
idle2(); idle2();
idle(); idle();
V.l = readDirect(U.l + X.w + 0); V.l = readDirectX(U.l + X.w, 0);
V.h = readDirect(U.l + X.w + 1); V.h = readDirectX(U.l + X.w, 1);
writeBank(V.w + 0, A.l); writeBank(V.w + 0, A.l);
L writeBank(V.w + 1, A.h); L writeBank(V.w + 1, A.h);
} }

View File

@ -59,6 +59,13 @@ auto WDC65816::writeDirect(uint address, uint8 data) -> void {
write(D.w + address & 0xffff, data); write(D.w + address & 0xffff, data);
} }
auto WDC65816::readDirectX(uint address, uint offset) -> uint8 {
// The (direct,X) addressing mode has a bug in which the high byte is
// wrapped within the page if E = 1 and D&0xFF != 0.
if(EF && D.l) return read(((D.w + address) & 0xffff00) | ((D.w + address + offset) & 0xff));
else return readDirect(address + offset);
}
auto WDC65816::readDirectN(uint address) -> uint8 { auto WDC65816::readDirectN(uint address) -> uint8 {
return read(D.w + address & 0xffff); return read(D.w + address & 0xffff);
} }

View File

@ -58,6 +58,7 @@ struct WDC65816 {
alwaysinline auto pushN(uint8 data) -> void; alwaysinline auto pushN(uint8 data) -> void;
alwaysinline auto readDirect(uint address) -> uint8; alwaysinline auto readDirect(uint address) -> uint8;
alwaysinline auto writeDirect(uint address, uint8 data) -> void; alwaysinline auto writeDirect(uint address, uint8 data) -> void;
alwaysinline auto readDirectX(uint address, uint offset) -> uint8;
alwaysinline auto readDirectN(uint address) -> uint8; alwaysinline auto readDirectN(uint address) -> uint8;
alwaysinline auto readBank(uint address) -> uint8; alwaysinline auto readBank(uint address) -> uint8;
alwaysinline auto writeBank(uint address, uint8 data) -> void; alwaysinline auto writeBank(uint address, uint8 data) -> void;

View File

@ -39,6 +39,8 @@ auto SA1::BWRAM::writeCPU(uint address, uint8 data) -> void {
address = sa1.mmio.sbm * 0x2000 + (address & 0x1fff); address = sa1.mmio.sbm * 0x2000 + (address & 0x1fff);
} }
//note: BW-RAM protection works only when both SWEN and CWEN are disabled.
if(!sa1.mmio.swen && !sa1.mmio.cwen && (address & 0x3ffff) < 0x100 << sa1.mmio.bwp) return;
return write(address, data); return write(address, data);
} }
@ -71,6 +73,15 @@ auto SA1::BWRAM::readLinear(uint address, uint8 data) -> uint8 {
} }
auto SA1::BWRAM::writeLinear(uint address, uint8 data) -> void { auto SA1::BWRAM::writeLinear(uint address, uint8 data) -> void {
//note: BW-RAM protection works only when both SWEN and CWEN are disabled.
//this is required for Kirby's Dream Land 3 to work:
//* BWPA = 02 (protect 400000-4003ff)
//* SWEN = 80 (writes enabled)
//* CWEN = 00 (writes disabled)
//KDL3 proceeds to write to 4001ax and 40032x which must succeed.
//note: BWPA also affects SA-1 protection
if(!sa1.mmio.swen && !sa1.mmio.cwen && (address & 0x3ffff) < 0x100 << sa1.mmio.bwp) return;
return write(address, data); return write(address, data);
} }

View File

@ -108,8 +108,16 @@ auto SA1::writeIOCPU(uint address, uint8 data) -> void {
//(CCNT) SA-1 control //(CCNT) SA-1 control
case 0x2200: { case 0x2200: {
if(mmio.sa1_resb && !(data & 0x20)) { if(mmio.sa1_resb && !(data & 0x20)) {
//reset SA-1 CPU (PC bank set to 0x00) //reset SA-1 CPU (PC bank and data bank set to 0x00, clear STP status)
r.pc.d = mmio.crv; r.pc.d = mmio.crv;
r.b = 0x00;
r.stp = false;
//todo: probably needs a SA-1 CPU reset
//reset r.s, r.e, r.wai ...
//reset io status
//todo: reset timing is unknown, CIWP is set to 0 at reset
mmio.ciwp = 0x00;
} }
mmio.sa1_irq = (data & 0x80); mmio.sa1_irq = (data & 0x80);

View File

@ -37,7 +37,7 @@ auto SA1::read(uint address) -> uint8 {
} }
if((address & 0x40e000) == 0x006000 //00-3f,80-bf:6000-7fff if((address & 0x40e000) == 0x006000 //00-3f,80-bf:6000-7fff
|| (address & 0xf00000) == 0x400000 //40-4f:0000-ffff || (address & 0xe00000) == 0x400000 //40-5f:0000-ffff
|| (address & 0xf00000) == 0x600000 //60-6f:0000-ffff || (address & 0xf00000) == 0x600000 //60-6f:0000-ffff
) { ) {
step(); step();
@ -81,7 +81,7 @@ auto SA1::write(uint address, uint8 data) -> void {
} }
if((address & 0x40e000) == 0x006000 //00-3f,80-bf:6000-7fff if((address & 0x40e000) == 0x006000 //00-3f,80-bf:6000-7fff
|| (address & 0xf00000) == 0x400000 //40-4f:0000-ffff || (address & 0xe00000) == 0x400000 //40-5f:0000-ffff
|| (address & 0xf00000) == 0x600000 //60-6f:0000-ffff || (address & 0xf00000) == 0x600000 //60-6f:0000-ffff
) { ) {
step(); step();

View File

@ -32,7 +32,7 @@ endif
ifneq ($(filter $(platform),linux bsd),) ifneq ($(filter $(platform),linux bsd),)
ifeq ($(hiro),) ifeq ($(hiro),)
hiro := gtk2 hiro := gtk3
endif endif
ifeq ($(hiro),gtk2) ifeq ($(hiro),gtk2)

View File

@ -82,6 +82,8 @@ auto pApplication::state() -> State& {
auto pApplication::initialize() -> void { auto pApplication::initialize() -> void {
#if defined(DISPLAY_XORG) #if defined(DISPLAY_XORG)
// If running on Wayland, force usage of XWayland
setenv("GDK_BACKEND", "x11", 1);
state().display = XOpenDisplay(nullptr); state().display = XOpenDisplay(nullptr);
state().screenSaverXDG = (bool)execute("xdg-screensaver", "--version").output.find("xdg-screensaver"); state().screenSaverXDG = (bool)execute("xdg-screensaver", "--version").output.find("xdg-screensaver");