Compare commits
No commits in common. "master" and "1.0rc" have entirely different histories.
|
@ -4,17 +4,16 @@ on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
- ci/*
|
- ci/vcpkg-update
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
env:
|
env:
|
||||||
VCPKG_COMMIT: 2ad004460f5db4d3b66f62f5799ff66c265c4b5d
|
|
||||||
MELONDS_GIT_BRANCH: ${{ github.ref }}
|
MELONDS_GIT_BRANCH: ${{ github.ref }}
|
||||||
MELONDS_GIT_HASH: ${{ github.sha }}
|
MELONDS_GIT_HASH: ${{ github.sha }}
|
||||||
MELONDS_BUILD_PROVIDER: GitHub Actions
|
MELONDS_BUILD_PROVIDER: GitHub Actions
|
||||||
# MELONDS_VERSION_SUFFIX: " RC"
|
MELONDS_VERSION_SUFFIX: " RC"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-macos:
|
build-macos:
|
||||||
|
@ -35,7 +34,7 @@ jobs:
|
||||||
- name: Set up vcpkg
|
- name: Set up vcpkg
|
||||||
uses: lukka/run-vcpkg@v11
|
uses: lukka/run-vcpkg@v11
|
||||||
with:
|
with:
|
||||||
vcpkgGitCommitId: ${{ env.VCPKG_COMMIT }}
|
vcpkgGitCommitId: 10b7a178346f3f0abef60cecd5130e295afd8da4
|
||||||
- name: Build
|
- name: Build
|
||||||
uses: lukka/run-cmake@v10
|
uses: lukka/run-cmake@v10
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -4,7 +4,6 @@ on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
- ci/*
|
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
@ -13,27 +12,19 @@ env:
|
||||||
MELONDS_GIT_BRANCH: ${{ github.ref }}
|
MELONDS_GIT_BRANCH: ${{ github.ref }}
|
||||||
MELONDS_GIT_HASH: ${{ github.sha }}
|
MELONDS_GIT_HASH: ${{ github.sha }}
|
||||||
MELONDS_BUILD_PROVIDER: GitHub Actions
|
MELONDS_BUILD_PROVIDER: GitHub Actions
|
||||||
# MELONDS_VERSION_SUFFIX: " RC"
|
MELONDS_VERSION_SUFFIX: " RC"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build-x86_64:
|
||||||
continue-on-error: true
|
name: x86_64
|
||||||
strategy:
|
runs-on: ubuntu-22.04
|
||||||
matrix:
|
|
||||||
arch:
|
|
||||||
- runner: ubuntu-22.04
|
|
||||||
name: x86_64
|
|
||||||
- runner: ubuntu-22.04-arm
|
|
||||||
name: aarch64
|
|
||||||
|
|
||||||
name: ${{ matrix.arch.name }}
|
|
||||||
runs-on: ${{ matrix.arch.runner }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
name: Check out sources
|
name: Check out sources
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
|
sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install --allow-downgrades cmake ninja-build extra-cmake-modules libpcap0.8-dev libsdl2-dev libenet-dev \
|
sudo apt install --allow-downgrades cmake ninja-build extra-cmake-modules libpcap0.8-dev libsdl2-dev libenet-dev \
|
||||||
qt6-{base,base-private,multimedia}-dev libqt6svg6-dev libarchive-dev libzstd-dev libfuse2
|
qt6-{base,base-private,multimedia}-dev libqt6svg6-dev libarchive-dev libzstd-dev libfuse2
|
||||||
|
@ -45,19 +36,56 @@ jobs:
|
||||||
DESTDIR=AppDir cmake --install build
|
DESTDIR=AppDir cmake --install build
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: melonDS-ubuntu-${{ matrix.arch.name }}
|
name: melonDS-ubuntu-x86_64
|
||||||
path: AppDir/usr/bin/melonDS
|
path: AppDir/usr/bin/melonDS
|
||||||
- name: Fetch AppImage tools
|
- name: Fetch AppImage tools
|
||||||
run: |
|
run: |
|
||||||
wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${{ matrix.arch.name }}.AppImage
|
wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
|
||||||
wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-${{ matrix.arch.name }}.AppImage
|
wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
|
||||||
chmod a+x linuxdeploy-*.AppImage
|
chmod a+x linuxdeploy-*.AppImage
|
||||||
- name: Build the AppImage
|
- name: Build the AppImage
|
||||||
env:
|
env:
|
||||||
QMAKE: /usr/lib/qt6/bin/qmake
|
QMAKE: /usr/lib/qt6/bin/qmake
|
||||||
run: |
|
run: |
|
||||||
./linuxdeploy-${{ matrix.arch.name }}.AppImage --appdir AppDir --plugin qt --output appimage
|
./linuxdeploy-x86_64.AppImage --appdir AppDir --plugin qt --output appimage
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: melonDS-appimage-${{ matrix.arch.name }}
|
name: melonDS-appimage-x86_64
|
||||||
path: melonDS*.AppImage
|
path: melonDS*.AppImage
|
||||||
|
|
||||||
|
build-aarch64:
|
||||||
|
name: aarch64
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: ubuntu:22.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Prepare system
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
dpkg --add-architecture arm64
|
||||||
|
sh -c "sed \"s|^deb \([a-z\.:/]*\) \([a-z\-]*\) \(.*\)$|deb [arch=amd64] \1 \2 \3\ndeb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports \2 \3|\" /etc/apt/sources.list > /etc/apt/sources.list.new"
|
||||||
|
rm /etc/apt/sources.list
|
||||||
|
mv /etc/apt/sources.list{.new,}
|
||||||
|
apt update
|
||||||
|
apt -y full-upgrade
|
||||||
|
apt -y install git {gcc-12,g++-12}-aarch64-linux-gnu cmake ninja-build extra-cmake-modules \
|
||||||
|
{libsdl2,qt6-{base,base-private,multimedia},libqt6svg6,libarchive,libzstd,libenet}-dev:arm64 \
|
||||||
|
pkg-config dpkg-dev
|
||||||
|
- name: Check out source
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Configure
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cmake -B build -G Ninja \
|
||||||
|
-DPKG_CONFIG_EXECUTABLE=/usr/bin/aarch64-linux-gnu-pkg-config \
|
||||||
|
-DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc-12 \
|
||||||
|
-DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++-12 \
|
||||||
|
-DMELONDS_EMBED_BUILD_INFO=ON
|
||||||
|
- name: Build
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cmake --build build
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: melonDS-ubuntu-aarch64
|
||||||
|
path: build/melonDS
|
||||||
|
|
|
@ -10,11 +10,10 @@ on:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
env:
|
env:
|
||||||
VCPKG_COMMIT: 2ad004460f5db4d3b66f62f5799ff66c265c4b5d
|
|
||||||
MELONDS_GIT_BRANCH: ${{ github.ref }}
|
MELONDS_GIT_BRANCH: ${{ github.ref }}
|
||||||
MELONDS_GIT_HASH: ${{ github.sha }}
|
MELONDS_GIT_HASH: ${{ github.sha }}
|
||||||
MELONDS_BUILD_PROVIDER: GitHub Actions
|
MELONDS_BUILD_PROVIDER: GitHub Actions
|
||||||
# MELONDS_VERSION_SUFFIX: " RC"
|
MELONDS_VERSION_SUFFIX: " RC"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
@ -34,7 +33,7 @@ jobs:
|
||||||
- name: Set up vcpkg
|
- name: Set up vcpkg
|
||||||
uses: lukka/run-vcpkg@v11
|
uses: lukka/run-vcpkg@v11
|
||||||
with:
|
with:
|
||||||
vcpkgGitCommitId: ${{ env.VCPKG_COMMIT }}
|
vcpkgGitCommitId: 10b7a178346f3f0abef60cecd5130e295afd8da4
|
||||||
- name: Configure
|
- name: Configure
|
||||||
run: cmake --preset=release-mingw-x86_64 -DMELONDS_EMBED_BUILD_INFO=ON
|
run: cmake --preset=release-mingw-x86_64 -DMELONDS_EMBED_BUILD_INFO=ON
|
||||||
- name: Build
|
- name: Build
|
||||||
|
|
|
@ -9,7 +9,6 @@ set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/DefaultBuildFlags.cmake")
|
set(CMAKE_USER_MAKE_RULES_OVERRIDE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/DefaultBuildFlags.cmake")
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
|
|
||||||
|
|
||||||
option(USE_VCPKG "Use vcpkg for dependency packages" OFF)
|
option(USE_VCPKG "Use vcpkg for dependency packages" OFF)
|
||||||
if (USE_VCPKG)
|
if (USE_VCPKG)
|
||||||
|
@ -30,6 +29,8 @@ include(CheckIPOSupported)
|
||||||
include(SetupCCache)
|
include(SetupCCache)
|
||||||
include(Sanitizers)
|
include(Sanitizers)
|
||||||
|
|
||||||
|
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<h2 align="center"><b>melonDS</b></h2>
|
<h2 align="center"><b>melonDS</b></h2>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="http://melonds.kuribo64.net/" alt="melonDS website"><img src="https://img.shields.io/badge/website-melonds.kuribo64.net-%2331352e.svg"></a>
|
<a href="http://melonds.kuribo64.net/" alt="melonDS website"><img src="https://img.shields.io/badge/website-melonds.kuribo64.net-%2331352e.svg"></a>
|
||||||
<a href="http://melonds.kuribo64.net/downloads.php" alt="Release: 1.0"><img src="https://img.shields.io/badge/release-1.0-%235c913b.svg"></a>
|
<a href="http://melonds.kuribo64.net/downloads.php" alt="Release: 0.9.5"><img src="https://img.shields.io/badge/release-0.9.5-%235c913b.svg"></a>
|
||||||
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPLv3"><img src="https://img.shields.io/badge/License-GPL%20v3-%23ff554d.svg"></a>
|
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPLv3"><img src="https://img.shields.io/badge/License-GPL%20v3-%23ff554d.svg"></a>
|
||||||
<a href="https://kiwiirc.com/client/irc.badnik.net/?nick=IRC-Source_?#melonds" alt="IRC channel: #melonds"><img src="https://img.shields.io/badge/IRC%20chat-%23melonds-%23dd2e44.svg"></a>
|
<a href="https://kiwiirc.com/client/irc.badnik.net/?nick=IRC-Source_?#melonds" alt="IRC channel: #melonds"><img src="https://img.shields.io/badge/IRC%20chat-%23melonds-%23dd2e44.svg"></a>
|
||||||
<a href="https://discord.gg/pAMAtExcqV" alt="Discord"><img src="https://img.shields.io/badge/Discord-Kuribo64-7289da?logo=discord&logoColor=white"></a>
|
<a href="https://discord.gg/pAMAtExcqV" alt="Discord"><img src="https://img.shields.io/badge/Discord-Kuribo64-7289da?logo=discord&logoColor=white"></a>
|
||||||
|
|
|
@ -9,8 +9,7 @@ if (VCPKG_ROOT STREQUAL "${_DEFAULT_VCPKG_ROOT}")
|
||||||
endif()
|
endif()
|
||||||
FetchContent_Declare(vcpkg
|
FetchContent_Declare(vcpkg
|
||||||
GIT_REPOSITORY "https://github.com/Microsoft/vcpkg.git"
|
GIT_REPOSITORY "https://github.com/Microsoft/vcpkg.git"
|
||||||
GIT_TAG 2ad004460f5db4d3b66f62f5799ff66c265c4b5d
|
GIT_TAG 2024.10.21
|
||||||
EXCLUDE_FROM_ALL
|
|
||||||
SOURCE_DIR "${CMAKE_SOURCE_DIR}/vcpkg")
|
SOURCE_DIR "${CMAKE_SOURCE_DIR}/vcpkg")
|
||||||
FetchContent_MakeAvailable(vcpkg)
|
FetchContent_MakeAvailable(vcpkg)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -7,9 +7,3 @@ endif()
|
||||||
|
|
||||||
string(REPLACE "-O2" "-O3" CMAKE_C_FLAGS_RELEASE_INIT "${CMAKE_C_FLAGS_RELEASE_INIT}")
|
string(REPLACE "-O2" "-O3" CMAKE_C_FLAGS_RELEASE_INIT "${CMAKE_C_FLAGS_RELEASE_INIT}")
|
||||||
string(REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS_RELEASE_INIT "${CMAKE_CXX_FLAGS_RELEASE_INIT}")
|
string(REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS_RELEASE_INIT "${CMAKE_CXX_FLAGS_RELEASE_INIT}")
|
||||||
|
|
||||||
# Building with LTO causes an internal compiler error in GCC 15.1.0
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15.0 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15.1.1)
|
|
||||||
set(ENABLE_LTO_RELEASE OFF CACHE BOOL "Enable LTO for release builds" FORCE)
|
|
||||||
set(ENABLE_LTO OFF CACHE BOOL "Enable LTO" FORCE)
|
|
||||||
endif()
|
|
||||||
|
|
12
flake.lock
12
flake.lock
|
@ -5,11 +5,11 @@
|
||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1731533236,
|
"lastModified": 1726560853,
|
||||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -20,11 +20,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1739020877,
|
"lastModified": 1730531603,
|
||||||
"narHash": "sha256-mIvECo/NNdJJ/bXjNqIh8yeoSjVLAuDuTUzAo7dzs8Y=",
|
"narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "a79cfe0ebd24952b580b1cf08cd906354996d547",
|
"rev": "7ffd9ae656aec493492b44d0ddfb28e79a1ea25d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -95,13 +95,7 @@
|
||||||
libtool
|
libtool
|
||||||
ninja
|
ninja
|
||||||
pkg-config
|
pkg-config
|
||||||
python3
|
|
||||||
];
|
];
|
||||||
|
|
||||||
# Undo the SDK setup done by nixpkgs so we can use AppleClang
|
|
||||||
shellHook = ''
|
|
||||||
unset DEVELOPER_DIR SDKROOT MACOSX_DEPLOYMENT_TARGET
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
AS = arm-none-eabi-as
|
|
||||||
LD = arm-none-eabi-ld
|
|
||||||
OBJCOPY = arm-none-eabi-objcopy
|
|
||||||
|
|
||||||
BIN = melonDLDI
|
|
||||||
|
|
||||||
all:
|
|
||||||
$(AS) $(BIN).s -o $(BIN).o
|
|
||||||
$(LD) $(BIN).o -Ttext 0xBF800000 -e 0xBF800000 -o $(BIN).elf
|
|
||||||
$(OBJCOPY) -O binary $(BIN).elf $(BIN).bin
|
|
||||||
xxd -i -n $(BIN) -c 16 $(BIN).bin $(BIN).h
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(BIN).h $(BIN).bin $(BIN).elf $(BIN).o
|
|
||||||
|
|
|
@ -1,172 +0,0 @@
|
||||||
.arm
|
|
||||||
.text
|
|
||||||
|
|
||||||
.align 2
|
|
||||||
|
|
||||||
_start:
|
|
||||||
.word 0xBF8DA5ED
|
|
||||||
.string " Chishm"
|
|
||||||
.byte 1
|
|
||||||
.byte 9 @ size
|
|
||||||
.byte 0
|
|
||||||
.byte 0
|
|
||||||
.string "melonDS DLDI driver"
|
|
||||||
.align 6, 0
|
|
||||||
.word _start, melon_end
|
|
||||||
.word 0, 0
|
|
||||||
.word 0, 0
|
|
||||||
.word 0, 0
|
|
||||||
.ascii "MELN"
|
|
||||||
.word 0x23
|
|
||||||
.word melon_startup
|
|
||||||
.word melon_isInserted
|
|
||||||
.word melon_readSectors
|
|
||||||
.word melon_writeSectors
|
|
||||||
.word melon_clearStatus
|
|
||||||
.word melon_shutdown
|
|
||||||
|
|
||||||
|
|
||||||
.align 2
|
|
||||||
|
|
||||||
melon_startup:
|
|
||||||
mov r0, #1
|
|
||||||
bx lr
|
|
||||||
|
|
||||||
|
|
||||||
melon_isInserted:
|
|
||||||
mov r0, #1
|
|
||||||
bx lr
|
|
||||||
|
|
||||||
|
|
||||||
@ r0=cmd r1=sector r2=out (0=none)
|
|
||||||
_sendcmd:
|
|
||||||
mov r12, #0x04000000
|
|
||||||
add r12, r12, #0x1A0
|
|
||||||
@ init
|
|
||||||
mov r3, #0x8000
|
|
||||||
strh r3, [r12]
|
|
||||||
@ set cmd
|
|
||||||
strb r0, [r12, #0x8]
|
|
||||||
strb r1, [r12, #0xC]
|
|
||||||
mov r1, r1, lsr #8
|
|
||||||
strb r1, [r12, #0xB]
|
|
||||||
mov r1, r1, lsr #8
|
|
||||||
strb r1, [r12, #0xA]
|
|
||||||
mov r1, r1, lsr #8
|
|
||||||
strb r1, [r12, #0x9]
|
|
||||||
mov r1, r1, lsr #8
|
|
||||||
strb r1, [r12, #0xD]
|
|
||||||
strh r1, [r12, #0xE]
|
|
||||||
@ send
|
|
||||||
mov r3, #0xA0000000
|
|
||||||
orr r3, r3, r0, lsl #30
|
|
||||||
cmp r2, #0
|
|
||||||
orrne r3, r3, #0x01000000 @ block size
|
|
||||||
orr r3, r3, #0x00400000 @ KEY2
|
|
||||||
str r3, [r12, #0x4]
|
|
||||||
mov r3, #0x04100000
|
|
||||||
tst r0, #0x01
|
|
||||||
bne __send_write
|
|
||||||
@ receive data
|
|
||||||
tst r2, #0x3
|
|
||||||
bne __read_unal_loop
|
|
||||||
__read_busyloop:
|
|
||||||
ldr r0, [r12, #0x4]
|
|
||||||
tst r0, #0x80000000
|
|
||||||
bxeq lr
|
|
||||||
tst r0, #0x00800000
|
|
||||||
ldrne r1, [r3, #0x10] @ load data
|
|
||||||
strne r1, [r2], #4
|
|
||||||
b __read_busyloop
|
|
||||||
__read_unal_loop:
|
|
||||||
ldr r0, [r12, #0x4]
|
|
||||||
tst r0, #0x80000000
|
|
||||||
bxeq lr
|
|
||||||
tst r0, #0x00800000
|
|
||||||
beq __read_unal_loop
|
|
||||||
ldr r1, [r3, #0x10] @ load data
|
|
||||||
strb r1, [r2], #1
|
|
||||||
mov r1, r1, lsr #8
|
|
||||||
strb r1, [r2], #1
|
|
||||||
mov r1, r1, lsr #8
|
|
||||||
strb r1, [r2], #1
|
|
||||||
mov r1, r1, lsr #8
|
|
||||||
strb r1, [r2], #1
|
|
||||||
b __read_unal_loop
|
|
||||||
@ send data
|
|
||||||
__send_write:
|
|
||||||
mov r1, #0
|
|
||||||
tst r2, #0x3
|
|
||||||
bne __write_unal_loop
|
|
||||||
__write_busyloop:
|
|
||||||
ldr r0, [r12, #0x4]
|
|
||||||
tst r0, #0x80000000
|
|
||||||
bxeq lr
|
|
||||||
tst r0, #0x00800000
|
|
||||||
ldrne r1, [r2], #4
|
|
||||||
strne r1, [r3, #0x10] @ store data
|
|
||||||
b __write_busyloop
|
|
||||||
__write_unal_loop:
|
|
||||||
ldr r0, [r12, #0x4]
|
|
||||||
tst r0, #0x80000000
|
|
||||||
bxeq lr
|
|
||||||
tst r0, #0x00800000
|
|
||||||
beq __write_unal_loop
|
|
||||||
ldrb r1, [r2], #1
|
|
||||||
ldrb r0, [r2], #1
|
|
||||||
orr r1, r1, r0, lsl #8
|
|
||||||
ldrb r0, [r2], #1
|
|
||||||
orr r1, r1, r0, lsl #16
|
|
||||||
ldrb r0, [r2], #1
|
|
||||||
orr r1, r1, r0, lsl #24
|
|
||||||
str r1, [r3, #0x10] @ store data
|
|
||||||
b __write_unal_loop
|
|
||||||
|
|
||||||
|
|
||||||
@ r0=sector r1=numsectors r2=out
|
|
||||||
melon_readSectors:
|
|
||||||
stmdb sp!, {r3-r6, lr}
|
|
||||||
mov r4, r0
|
|
||||||
mov r5, r1
|
|
||||||
mov r6, #0
|
|
||||||
_readloop:
|
|
||||||
mov r0, #0xC0
|
|
||||||
add r1, r4, r6
|
|
||||||
bl _sendcmd
|
|
||||||
add r6, r6, #1
|
|
||||||
cmp r6, r5
|
|
||||||
bcc _readloop
|
|
||||||
ldmia sp!, {r3-r6, lr}
|
|
||||||
mov r0, #1
|
|
||||||
bx lr
|
|
||||||
|
|
||||||
|
|
||||||
@ r0=sector r1=numsectors r2=out
|
|
||||||
melon_writeSectors:
|
|
||||||
stmdb sp!, {r3-r6, lr}
|
|
||||||
mov r4, r0
|
|
||||||
mov r5, r1
|
|
||||||
mov r6, #0
|
|
||||||
_writeloop:
|
|
||||||
mov r0, #0xC1
|
|
||||||
add r1, r4, r6
|
|
||||||
bl _sendcmd
|
|
||||||
add r6, r6, #1
|
|
||||||
cmp r6, r5
|
|
||||||
bcc _writeloop
|
|
||||||
ldmia sp!, {r3-r6, lr}
|
|
||||||
mov r0, #1
|
|
||||||
bx lr
|
|
||||||
|
|
||||||
|
|
||||||
melon_clearStatus:
|
|
||||||
mov r0, #1
|
|
||||||
bx lr
|
|
||||||
|
|
||||||
|
|
||||||
melon_shutdown:
|
|
||||||
mov r0, #1
|
|
||||||
bx lr
|
|
||||||
|
|
||||||
|
|
||||||
melon_end:
|
|
|
@ -18,7 +18,7 @@ FILETYPE VFT_APP
|
||||||
VALUE "FileVersion", "${melonDS_VERSION}"
|
VALUE "FileVersion", "${melonDS_VERSION}"
|
||||||
VALUE "FileDescription", "melonDS emulator"
|
VALUE "FileDescription", "melonDS emulator"
|
||||||
VALUE "InternalName", "SDnolem"
|
VALUE "InternalName", "SDnolem"
|
||||||
VALUE "LegalCopyright", "2016-2025 melonDS team"
|
VALUE "LegalCopyright", "2016-2023 melonDS team"
|
||||||
VALUE "LegalTrademarks", ""
|
VALUE "LegalTrademarks", ""
|
||||||
VALUE "OriginalFilename", "melonDS.exe"
|
VALUE "OriginalFilename", "melonDS.exe"
|
||||||
VALUE "ProductName", "melonDS"
|
VALUE "ProductName", "melonDS"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
@ -58,8 +58,7 @@ void AREngine::RunCheat(const ARCode& arcode)
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (code > &arcode.Code[arcode.Code.size() - 1])
|
if (code >= &arcode.Code[arcode.Code.size()])
|
||||||
// If the instruction pointer is past the end of the cheat code...
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
u32 a = *code++;
|
u32 a = *code++;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ ARM::ARM(u32 num, bool jit, std::optional<GDBArgs> gdb, melonDS::NDS& nds) :
|
||||||
Num(num), // well uh
|
Num(num), // well uh
|
||||||
NDS(nds)
|
NDS(nds)
|
||||||
{
|
{
|
||||||
SetGdbArgs(jit ? std::nullopt : gdb);
|
SetGdbArgs(jit ? gdb : std::nullopt);
|
||||||
}
|
}
|
||||||
|
|
||||||
ARM::~ARM()
|
ARM::~ARM()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team, RSDuck
|
Copyright 2016-2024 melonDS team, RSDuck
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team, RSDuck
|
Copyright 2016-2024 melonDS team, RSDuck
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ void Compiler::Comp_JumpTo(u32 addr, bool forceNonConstantCycles)
|
||||||
// doesn't matter if we put garbage in the MSbs there
|
// doesn't matter if we put garbage in the MSbs there
|
||||||
if (addr & 0x2)
|
if (addr & 0x2)
|
||||||
{
|
{
|
||||||
cpu9->CodeRead32(addr-2, true);
|
cpu9->CodeRead32(addr-2, true) >> 16;
|
||||||
cycles += cpu9->CodeCycles;
|
cycles += cpu9->CodeCycles;
|
||||||
cpu9->CodeRead32(addr+2, false);
|
cpu9->CodeRead32(addr+2, false);
|
||||||
cycles += CurCPU->CodeCycles;
|
cycles += CurCPU->CodeCycles;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team, RSDuck
|
Copyright 2016-2024 melonDS team, RSDuck
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team, RSDuck
|
Copyright 2016-2024 melonDS team, RSDuck
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team, RSDuck
|
Copyright 2016-2024 melonDS team, RSDuck
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team, RSDuck
|
Copyright 2016-2024 melonDS team, RSDuck
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team, RSDuck
|
Copyright 2016-2024 melonDS team, RSDuck
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team, RSDuck
|
Copyright 2016-2024 melonDS team, RSDuck
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
@ -753,7 +753,7 @@ bool ARMJIT_Memory::IsFastMemSupported()
|
||||||
|
|
||||||
PageSize = RegularPageSize;
|
PageSize = RegularPageSize;
|
||||||
#else
|
#else
|
||||||
PageSize = sysconf(_SC_PAGESIZE);
|
PageSize = __sysconf(_SC_PAGESIZE);
|
||||||
isSupported = PageSize == RegularPageSize || PageSize == LargePageSize;
|
isSupported = PageSize == RegularPageSize || PageSize == LargePageSize;
|
||||||
#endif
|
#endif
|
||||||
PageShift = __builtin_ctz(PageSize);
|
PageShift = __builtin_ctz(PageSize);
|
||||||
|
@ -900,7 +900,7 @@ ARMJIT_Memory::ARMJIT_Memory(melonDS::NDS& nds) : NDS(nds)
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
char fastmemPidName[snprintf(NULL, 0, "/melondsfastmem%d", getpid()) + 1];
|
char fastmemPidName[snprintf(NULL, 0, "/melondsfastmem%d", getpid()) + 1];
|
||||||
snprintf(fastmemPidName, sizeof(fastmemPidName), "/melondsfastmem%d", getpid());
|
sprintf(fastmemPidName, "/melondsfastmem%d", getpid());
|
||||||
MemoryFile = shm_open(fastmemPidName, O_RDWR | O_CREAT | O_EXCL, 0600);
|
MemoryFile = shm_open(fastmemPidName, O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||||
if (MemoryFile == -1)
|
if (MemoryFile == -1)
|
||||||
{
|
{
|
||||||
|
@ -951,6 +951,7 @@ ARMJIT_Memory::~ARMJIT_Memory() noexcept
|
||||||
MemoryBase = nullptr;
|
MemoryBase = nullptr;
|
||||||
FastMem9Start = nullptr;
|
FastMem9Start = nullptr;
|
||||||
FastMem7Start = nullptr;
|
FastMem7Start = nullptr;
|
||||||
|
printf("unmappinged everything\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MemoryFile)
|
if (MemoryFile)
|
||||||
|
@ -978,8 +979,6 @@ ARMJIT_Memory::~ARMJIT_Memory() noexcept
|
||||||
MemoryFile = -1;
|
MemoryFile = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(LogLevel::Info, "unmappinged everything\n");
|
|
||||||
|
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
if (Libandroid)
|
if (Libandroid)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
@ -29,8 +29,7 @@
|
||||||
# if defined(__SWITCH__)
|
# if defined(__SWITCH__)
|
||||||
# include <switch.h>
|
# include <switch.h>
|
||||||
# elif defined(_WIN32)
|
# elif defined(_WIN32)
|
||||||
# include <vector>
|
#include <windows.h>
|
||||||
# include <windows.h>
|
|
||||||
# else
|
# else
|
||||||
# include <sys/mman.h>
|
# include <sys/mman.h>
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team, RSDuck
|
Copyright 2016-2024 melonDS team, RSDuck
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team, RSDuck
|
Copyright 2016-2024 melonDS team, RSDuck
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team, RSDuck
|
Copyright 2016-2024 melonDS team, RSDuck
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ add_library(core STATIC
|
||||||
FATStorage.cpp
|
FATStorage.cpp
|
||||||
FIFO.h
|
FIFO.h
|
||||||
GBACart.cpp
|
GBACart.cpp
|
||||||
GBACartMotionPak.cpp
|
|
||||||
GPU.cpp
|
GPU.cpp
|
||||||
GPU2D.cpp
|
GPU2D.cpp
|
||||||
GPU2D_Soft.cpp
|
GPU2D_Soft.cpp
|
||||||
|
@ -103,8 +102,6 @@ if (ENABLE_JIT)
|
||||||
dolphin/CommonFuncs.cpp)
|
dolphin/CommonFuncs.cpp)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
# Required for memory mapping-related functions introduced in Windows 8
|
|
||||||
target_compile_definitions(core PRIVATE -D_WIN32_WINNT=_WIN32_WINNT_WIN8)
|
|
||||||
target_link_libraries(core PRIVATE onecore)
|
target_link_libraries(core PRIVATE onecore)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
31
src/DSi.cpp
31
src/DSi.cpp
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
@ -113,8 +113,6 @@ DSi::DSi(DSiArgs&& args, void* userdata) noexcept :
|
||||||
NWRAM_A = JIT.Memory.GetNWRAM_A();
|
NWRAM_A = JIT.Memory.GetNWRAM_A();
|
||||||
NWRAM_B = JIT.Memory.GetNWRAM_B();
|
NWRAM_B = JIT.Memory.GetNWRAM_B();
|
||||||
NWRAM_C = JIT.Memory.GetNWRAM_C();
|
NWRAM_C = JIT.Memory.GetNWRAM_C();
|
||||||
|
|
||||||
SetFullBIOSBoot(args.FullBIOSBoot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DSi::~DSi() noexcept
|
DSi::~DSi() noexcept
|
||||||
|
@ -177,8 +175,6 @@ void DSi::Reset()
|
||||||
// LCD init flag
|
// LCD init flag
|
||||||
GPU.DispStat[0] |= (1<<6);
|
GPU.DispStat[0] |= (1<<6);
|
||||||
GPU.DispStat[1] |= (1<<6);
|
GPU.DispStat[1] |= (1<<6);
|
||||||
|
|
||||||
UpdateVRAMTimings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSi::Stop(Platform::StopReason reason)
|
void DSi::Stop(Platform::StopReason reason)
|
||||||
|
@ -284,13 +280,11 @@ void DSi::DoSavestateExtra(Savestate* file)
|
||||||
NDMAs[i].DoSavestate(file);
|
NDMAs[i].DoSavestate(file);
|
||||||
|
|
||||||
AES.DoSavestate(file);
|
AES.DoSavestate(file);
|
||||||
|
CamModule.DoSavestate(file);
|
||||||
DSP.DoSavestate(file);
|
DSP.DoSavestate(file);
|
||||||
I2C.DoSavestate(file);
|
I2C.DoSavestate(file);
|
||||||
CamModule.DoSavestate(file);
|
|
||||||
SDMMC.DoSavestate(file);
|
SDMMC.DoSavestate(file);
|
||||||
SDIO.DoSavestate(file);
|
SDIO.DoSavestate(file);
|
||||||
|
|
||||||
UpdateVRAMTimings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSi::SetCartInserted(bool inserted)
|
void DSi::SetCartInserted(bool inserted)
|
||||||
|
@ -672,8 +666,6 @@ void DSi::SetupDirectBoot()
|
||||||
ARM9.CP15Write(0x671, 0x02FFC01B);
|
ARM9.CP15Write(0x671, 0x02FFC01B);
|
||||||
ARM9.CP15Write(0x910, 0x0E00000A);
|
ARM9.CP15Write(0x910, 0x0E00000A);
|
||||||
ARM9.CP15Write(0x911, 0x00000020);
|
ARM9.CP15Write(0x911, 0x00000020);
|
||||||
|
|
||||||
UpdateVRAMTimings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSi::SoftReset()
|
void DSi::SoftReset()
|
||||||
|
@ -725,11 +717,10 @@ void DSi::SoftReset()
|
||||||
SCFG_RST = 0;
|
SCFG_RST = 0;
|
||||||
DSP.SetRstLine(false);
|
DSP.SetRstLine(false);
|
||||||
|
|
||||||
|
|
||||||
// LCD init flag
|
// LCD init flag
|
||||||
GPU.DispStat[0] |= (1<<6);
|
GPU.DispStat[0] |= (1<<6);
|
||||||
GPU.DispStat[1] |= (1<<6);
|
GPU.DispStat[1] |= (1<<6);
|
||||||
|
|
||||||
UpdateVRAMTimings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSi::LoadNAND()
|
bool DSi::LoadNAND()
|
||||||
|
@ -1261,20 +1252,6 @@ void DSi::MapNWRAMRange(u32 cpu, u32 num, u32 val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSi::UpdateVRAMTimings()
|
|
||||||
{
|
|
||||||
if (SCFG_EXT[0] & (1<<13))
|
|
||||||
{
|
|
||||||
SetARM9RegionTimings(0x06000, 0x07000, Mem9_VRAM, 32, 1, 1);
|
|
||||||
SetARM7RegionTimings(0x06000, 0x07000, Mem7_VRAM, 32, 1, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetARM9RegionTimings(0x06000, 0x07000, Mem9_VRAM, 16, 1, 1);
|
|
||||||
SetARM7RegionTimings(0x06000, 0x07000, Mem7_VRAM, 16, 1, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DSi::ApplyNewRAMSize(u32 size)
|
void DSi::ApplyNewRAMSize(u32 size)
|
||||||
{
|
{
|
||||||
switch (size)
|
switch (size)
|
||||||
|
@ -2588,8 +2565,6 @@ void DSi::ARM9IOWrite32(u32 addr, u32 val)
|
||||||
//if (newram != oldram)
|
//if (newram != oldram)
|
||||||
// NDS::ScheduleEvent(NDS::Event_DSi_RAMSizeChange, false, 512*512*512, ApplyNewRAMSize, newram);
|
// NDS::ScheduleEvent(NDS::Event_DSi_RAMSizeChange, false, 512*512*512, ApplyNewRAMSize, newram);
|
||||||
Log(LogLevel::Debug, "from %08X, ARM7 %08X, %08X\n", NDS::GetPC(0), NDS::GetPC(1), ARM7.R[1]);
|
Log(LogLevel::Debug, "from %08X, ARM7 %08X, %08X\n", NDS::GetPC(0), NDS::GetPC(1), ARM7.R[1]);
|
||||||
|
|
||||||
UpdateVRAMTimings();
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
@ -97,8 +97,6 @@ public:
|
||||||
void MapNWRAM_C(u32 num, u8 val);
|
void MapNWRAM_C(u32 num, u8 val);
|
||||||
void MapNWRAMRange(u32 cpu, u32 num, u32 val);
|
void MapNWRAMRange(u32 cpu, u32 num, u32 val);
|
||||||
|
|
||||||
void UpdateVRAMTimings();
|
|
||||||
|
|
||||||
u8 ARM9Read8(u32 addr) override;
|
u8 ARM9Read8(u32 addr) override;
|
||||||
u16 ARM9Read16(u32 addr) override;
|
u16 ARM9Read16(u32 addr) override;
|
||||||
u32 ARM9Read32(u32 addr) override;
|
u32 ARM9Read32(u32 addr) override;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
@ -90,9 +90,6 @@ void DSi_AES::Reset()
|
||||||
*(u32*)&KeyX[1][8] = (u32)(consoleid >> 32) ^ 0xC80C4B72;
|
*(u32*)&KeyX[1][8] = (u32)(consoleid >> 32) ^ 0xC80C4B72;
|
||||||
*(u32*)&KeyX[1][12] = (u32)consoleid;
|
*(u32*)&KeyX[1][12] = (u32)consoleid;
|
||||||
|
|
||||||
// slot 2: For 'Tad'
|
|
||||||
std::memcpy(KeyX[2], &DSi.ARM9iBIOS[0x8B8C], 0x10);
|
|
||||||
|
|
||||||
// slot 3: console-unique eMMC crypto
|
// slot 3: console-unique eMMC crypto
|
||||||
*(u32*)&KeyX[3][0] = (u32)consoleid;
|
*(u32*)&KeyX[3][0] = (u32)consoleid;
|
||||||
*(u32*)&KeyX[3][4] = (u32)consoleid ^ 0x24EE6906;
|
*(u32*)&KeyX[3][4] = (u32)consoleid ^ 0x24EE6906;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
@ -34,11 +34,8 @@ using Platform::LogLevel;
|
||||||
// namely, how long cameras take to process frames
|
// namely, how long cameras take to process frames
|
||||||
// camera IRQ is fired at roughly 15FPS with default config
|
// camera IRQ is fired at roughly 15FPS with default config
|
||||||
|
|
||||||
// camera IRQ marks camera VBlank
|
const u32 DSi_CamModule::kIRQInterval = 1120000; // ~30 FPS
|
||||||
// each scanline takes roughly 3173 cycles
|
const u32 DSi_CamModule::kTransferStart = 60000;
|
||||||
const u32 DSi_CamModule::kIRQInterval = 2234248; // ~15 FPS
|
|
||||||
const u32 DSi_CamModule::kScanlineTime = 3173;
|
|
||||||
const u32 DSi_CamModule::kTransferStart = DSi_CamModule::kIRQInterval - (DSi_CamModule::kScanlineTime * 480);
|
|
||||||
|
|
||||||
|
|
||||||
DSi_CamModule::DSi_CamModule(melonDS::DSi& dsi) : DSi(dsi)
|
DSi_CamModule::DSi_CamModule(melonDS::DSi& dsi) : DSi(dsi)
|
||||||
|
@ -67,15 +64,12 @@ void DSi_CamModule::Reset()
|
||||||
CropStart = 0;
|
CropStart = 0;
|
||||||
CropEnd = 0;
|
CropEnd = 0;
|
||||||
|
|
||||||
Transferring = false;
|
memset(DataBuffer, 0, 512*sizeof(u32));
|
||||||
|
BufferReadPos = 0;
|
||||||
memset(PixelBuffer, 0, sizeof(PixelBuffer));
|
BufferWritePos = 0;
|
||||||
CurPixelBuffer = 0;
|
|
||||||
BufferNumLines = 0;
|
BufferNumLines = 0;
|
||||||
CurCamera = nullptr;
|
CurCamera = nullptr;
|
||||||
|
|
||||||
// TODO: ideally this should be started when a camera is active
|
|
||||||
// instead of just being a constant thing
|
|
||||||
DSi.ScheduleEvent(Event_DSi_CamIRQ, false, kIRQInterval, 0, 0);
|
DSi.ScheduleEvent(Event_DSi_CamIRQ, false, kIRQInterval, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,30 +86,9 @@ void DSi_CamModule::DoSavestate(Savestate* file)
|
||||||
file->Var16(&ModuleCnt);
|
file->Var16(&ModuleCnt);
|
||||||
file->Var16(&Cnt);
|
file->Var16(&Cnt);
|
||||||
|
|
||||||
file->Var32(&CropStart);
|
/*file->VarArray(FrameBuffer, sizeof(FrameBuffer));
|
||||||
file->Var32(&CropEnd);
|
file->Var32(&TransferPos);
|
||||||
|
file->Var32(&FrameLength);*/
|
||||||
file->Bool32(&Transferring);
|
|
||||||
|
|
||||||
file->VarArray(&PixelBuffer[0].Data, 512);
|
|
||||||
file->Var32(&PixelBuffer[0].ReadPos);
|
|
||||||
file->Var32(&PixelBuffer[0].WritePos);
|
|
||||||
file->VarArray(&PixelBuffer[1].Data, 512);
|
|
||||||
file->Var32(&PixelBuffer[1].ReadPos);
|
|
||||||
file->Var32(&PixelBuffer[1].WritePos);
|
|
||||||
file->Var8(&CurPixelBuffer);
|
|
||||||
|
|
||||||
file->Var32(&BufferNumLines);
|
|
||||||
|
|
||||||
if (!file->Saving)
|
|
||||||
{
|
|
||||||
DSi_Camera* activecam = nullptr;
|
|
||||||
|
|
||||||
if (Camera0->IsActivated()) activecam = Camera0;
|
|
||||||
else if (Camera1->IsActivated()) activecam = Camera1;
|
|
||||||
|
|
||||||
CurCamera = activecam;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -135,8 +108,14 @@ void DSi_CamModule::IRQ(u32 param)
|
||||||
if (Cnt & (1<<11))
|
if (Cnt & (1<<11))
|
||||||
DSi.SetIRQ(0, IRQ_DSi_Camera);
|
DSi.SetIRQ(0, IRQ_DSi_Camera);
|
||||||
|
|
||||||
CurCamera = activecam;
|
if (Cnt & (1<<15))
|
||||||
DSi.ScheduleEvent(Event_DSi_CamTransfer, false, kTransferStart, 0, 0);
|
{
|
||||||
|
BufferReadPos = 0;
|
||||||
|
BufferWritePos = 0;
|
||||||
|
BufferNumLines = 0;
|
||||||
|
CurCamera = activecam;
|
||||||
|
DSi.ScheduleEvent(Event_DSi_CamTransfer, false, kTransferStart, 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DSi.ScheduleEvent(Event_DSi_CamIRQ, true, kIRQInterval, 0, 0);
|
DSi.ScheduleEvent(Event_DSi_CamIRQ, true, kIRQInterval, 0, 0);
|
||||||
|
@ -144,35 +123,17 @@ void DSi_CamModule::IRQ(u32 param)
|
||||||
|
|
||||||
void DSi_CamModule::TransferScanline(u32 line)
|
void DSi_CamModule::TransferScanline(u32 line)
|
||||||
{
|
{
|
||||||
if (Cnt & (1<<4))
|
u32* dstbuf = &DataBuffer[BufferWritePos];
|
||||||
{
|
int maxlen = 512 - BufferWritePos;
|
||||||
Transferring = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line == 0)
|
|
||||||
{
|
|
||||||
if (!(Cnt & (1<<15)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
BufferNumLines = 0;
|
|
||||||
Transferring = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
sPixelBuffer* buffer = &PixelBuffer[CurPixelBuffer];
|
|
||||||
u32* dstbuf = &buffer->Data[buffer->WritePos];
|
|
||||||
int maxlen = 512 - buffer->WritePos;
|
|
||||||
|
|
||||||
u32 tmpbuf[512];
|
u32 tmpbuf[512];
|
||||||
int lines_next;
|
int datalen = CurCamera->TransferScanline(tmpbuf, 512);
|
||||||
int datalen = CurCamera->TransferScanline(tmpbuf, 512, lines_next);
|
|
||||||
u32 numscan;
|
|
||||||
|
|
||||||
u32 delay = lines_next * kScanlineTime;
|
// TODO: must be tweaked such that each block has enough time to transfer
|
||||||
|
u32 delay = datalen*4 + 16;
|
||||||
|
|
||||||
int copystart = 0;
|
int copystart = 0;
|
||||||
int copylen = datalen;
|
int copylen = datalen;
|
||||||
bool line_last = false;
|
|
||||||
|
|
||||||
if (Cnt & (1<<14))
|
if (Cnt & (1<<14))
|
||||||
{
|
{
|
||||||
|
@ -182,8 +143,10 @@ void DSi_CamModule::TransferScanline(u32 line)
|
||||||
int yend = (CropEnd >> 16) & 0x1FF;
|
int yend = (CropEnd >> 16) & 0x1FF;
|
||||||
if (line < ystart || line > yend)
|
if (line < ystart || line > yend)
|
||||||
{
|
{
|
||||||
if (line == yend+1) line_last = true;
|
if (!CurCamera->TransferDone())
|
||||||
goto skip_line;
|
DSi.ScheduleEvent(Event_DSi_CamTransfer, false, delay, 0, line+1);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int xstart = (CropStart >> 1) & 0x1FF;
|
int xstart = (CropStart >> 1) & 0x1FF;
|
||||||
|
@ -201,6 +164,7 @@ void DSi_CamModule::TransferScanline(u32 line)
|
||||||
if (copylen > maxlen)
|
if (copylen > maxlen)
|
||||||
{
|
{
|
||||||
copylen = maxlen;
|
copylen = maxlen;
|
||||||
|
Cnt |= (1<<4);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Cnt & (1<<13))
|
if (Cnt & (1<<13))
|
||||||
|
@ -242,70 +206,27 @@ void DSi_CamModule::TransferScanline(u32 line)
|
||||||
memcpy(dstbuf, &tmpbuf[copystart], copylen*sizeof(u32));
|
memcpy(dstbuf, &tmpbuf[copystart], copylen*sizeof(u32));
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer->WritePos += copylen;
|
u32 numscan = Cnt & 0x000F;
|
||||||
if (buffer->WritePos > 512) buffer->WritePos = 512;
|
|
||||||
|
|
||||||
numscan = Cnt & 0x000F;
|
|
||||||
if (BufferNumLines >= numscan)
|
if (BufferNumLines >= numscan)
|
||||||
{
|
{
|
||||||
|
BufferReadPos = 0; // checkme
|
||||||
|
BufferWritePos = 0;
|
||||||
BufferNumLines = 0;
|
BufferNumLines = 0;
|
||||||
SwapPixelBuffers();
|
DSi.CheckNDMAs(0, 0x0B);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
BufferWritePos += copylen;
|
||||||
|
if (BufferWritePos > 512) BufferWritePos = 512;
|
||||||
BufferNumLines++;
|
BufferNumLines++;
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_line:
|
if (CurCamera->TransferDone())
|
||||||
bool done = CurCamera->TransferDone();
|
|
||||||
if (done || line_last)
|
|
||||||
{
|
|
||||||
// when the frame is finished, transfer any remaining data if needed
|
|
||||||
// (if the frame height isn't a multiple of the DMA interval)
|
|
||||||
if (BufferNumLines > 0)
|
|
||||||
{
|
|
||||||
BufferNumLines = 0;
|
|
||||||
SwapPixelBuffers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (done)
|
|
||||||
{
|
|
||||||
Transferring = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
DSi.ScheduleEvent(Event_DSi_CamTransfer, false, delay, 0, line+1);
|
DSi.ScheduleEvent(Event_DSi_CamTransfer, false, delay, 0, line+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSi_CamModule::SwapPixelBuffers()
|
|
||||||
{
|
|
||||||
// pixel buffers are swapped every time a buffer is filled (ie. when the DMA interval is reached)
|
|
||||||
// the swap fails if the other buffer isn't empty
|
|
||||||
|
|
||||||
sPixelBuffer* otherbuf = &PixelBuffer[CurPixelBuffer ^ 1];
|
|
||||||
if (otherbuf->ReadPos < otherbuf->WritePos)
|
|
||||||
{
|
|
||||||
// overrun
|
|
||||||
Cnt |= (1<<4);
|
|
||||||
Transferring = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PixelBuffer[CurPixelBuffer].ReadPos = 0;
|
|
||||||
otherbuf->WritePos = 0;
|
|
||||||
CurPixelBuffer ^= 1;
|
|
||||||
DSi.CheckNDMAs(0, 0x0B);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DSi_CamModule::IsTransferring()
|
|
||||||
{
|
|
||||||
if (Cnt & (1<<15)) return true;
|
|
||||||
if (Transferring) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
u8 DSi_CamModule::Read8(u32 addr)
|
u8 DSi_CamModule::Read8(u32 addr)
|
||||||
{
|
{
|
||||||
|
@ -320,7 +241,7 @@ u16 DSi_CamModule::Read16(u32 addr)
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case 0x04004200: return ModuleCnt;
|
case 0x04004200: return ModuleCnt;
|
||||||
case 0x04004202: return Cnt | (Transferring ? (1<<15) : 0);
|
case 0x04004202: return Cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(LogLevel::Debug, "unknown DSi cam read16 %08X\n", addr);
|
Log(LogLevel::Debug, "unknown DSi cam read16 %08X\n", addr);
|
||||||
|
@ -333,14 +254,14 @@ u32 DSi_CamModule::Read32(u32 addr)
|
||||||
{
|
{
|
||||||
case 0x04004204:
|
case 0x04004204:
|
||||||
{
|
{
|
||||||
sPixelBuffer* buffer = &PixelBuffer[CurPixelBuffer ^ 1];
|
u32 ret = DataBuffer[BufferReadPos];
|
||||||
u32 ret;
|
if (Cnt & (1<<15))
|
||||||
if (buffer->ReadPos < buffer->WritePos)
|
{
|
||||||
ret = buffer->Data[buffer->ReadPos++];
|
if (BufferReadPos < 511)
|
||||||
else if (buffer->ReadPos > 0)
|
BufferReadPos++;
|
||||||
ret = buffer->Data[buffer->ReadPos - 1];
|
// CHECKME!!!!
|
||||||
else
|
// also presumably we should set bit4 in Cnt if there's no new data to be read
|
||||||
ret = buffer->Data[0];
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -375,7 +296,6 @@ void DSi_CamModule::Write16(u32 addr, u16 val)
|
||||||
// CHECKME
|
// CHECKME
|
||||||
|
|
||||||
Cnt = 0;
|
Cnt = 0;
|
||||||
Transferring = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ModuleCnt & (1<<5)) && !(oldcnt & (1<<5)))
|
if ((ModuleCnt & (1<<5)) && !(oldcnt & (1<<5)))
|
||||||
|
@ -387,9 +307,12 @@ void DSi_CamModule::Write16(u32 addr, u16 val)
|
||||||
|
|
||||||
case 0x04004202:
|
case 0x04004202:
|
||||||
{
|
{
|
||||||
|
// TODO: during a transfer, clearing bit15 does not reflect immediately
|
||||||
|
// maybe it needs to finish the trasnfer or atleast the current block
|
||||||
|
|
||||||
// checkme
|
// checkme
|
||||||
u16 oldmask;
|
u16 oldmask;
|
||||||
if (IsTransferring())
|
if (Cnt & 0x8000)
|
||||||
{
|
{
|
||||||
val &= 0x8F20;
|
val &= 0x8F20;
|
||||||
oldmask = 0x601F;
|
oldmask = 0x601F;
|
||||||
|
@ -404,26 +327,32 @@ void DSi_CamModule::Write16(u32 addr, u16 val)
|
||||||
if (val & (1<<5))
|
if (val & (1<<5))
|
||||||
{
|
{
|
||||||
Cnt &= ~(1<<4);
|
Cnt &= ~(1<<4);
|
||||||
memset(PixelBuffer, 0, sizeof(PixelBuffer));
|
BufferReadPos = 0;
|
||||||
CurPixelBuffer = 0;
|
BufferWritePos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((val & (1<<15)) && !(Cnt & (1<<15)))
|
||||||
|
{
|
||||||
|
// start transfer
|
||||||
|
//DSi::CheckNDMAs(0, 0x0B);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x04004210:
|
case 0x04004210:
|
||||||
if (IsTransferring()) return;
|
if (Cnt & (1<<15)) return;
|
||||||
CropStart = (CropStart & 0x01FF0000) | (val & 0x03FE);
|
CropStart = (CropStart & 0x01FF0000) | (val & 0x03FE);
|
||||||
return;
|
return;
|
||||||
case 0x04004212:
|
case 0x04004212:
|
||||||
if (IsTransferring()) return;
|
if (Cnt & (1<<15)) return;
|
||||||
CropStart = (CropStart & 0x03FE) | ((val & 0x01FF) << 16);
|
CropStart = (CropStart & 0x03FE) | ((val & 0x01FF) << 16);
|
||||||
return;
|
return;
|
||||||
case 0x04004214:
|
case 0x04004214:
|
||||||
if (IsTransferring()) return;
|
if (Cnt & (1<<15)) return;
|
||||||
CropEnd = (CropEnd & 0x01FF0000) | (val & 0x03FE);
|
CropEnd = (CropEnd & 0x01FF0000) | (val & 0x03FE);
|
||||||
return;
|
return;
|
||||||
case 0x04004216:
|
case 0x04004216:
|
||||||
if (IsTransferring()) return;
|
if (Cnt & (1<<15)) return;
|
||||||
CropEnd = (CropEnd & 0x03FE) | ((val & 0x01FF) << 16);
|
CropEnd = (CropEnd & 0x03FE) | ((val & 0x01FF) << 16);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -436,11 +365,11 @@ void DSi_CamModule::Write32(u32 addr, u32 val)
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case 0x04004210:
|
case 0x04004210:
|
||||||
if (IsTransferring()) return;
|
if (Cnt & (1<<15)) return;
|
||||||
CropStart = val & 0x01FF03FE;
|
CropStart = val & 0x01FF03FE;
|
||||||
return;
|
return;
|
||||||
case 0x04004214:
|
case 0x04004214:
|
||||||
if (IsTransferring()) return;
|
if (Cnt & (1<<15)) return;
|
||||||
CropEnd = val & 0x01FF03FE;
|
CropEnd = val & 0x01FF03FE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -500,7 +429,6 @@ void DSi_Camera::Reset()
|
||||||
// default state is preview mode (checkme)
|
// default state is preview mode (checkme)
|
||||||
MCURegs[0x2104] = 3;
|
MCURegs[0x2104] = 3;
|
||||||
|
|
||||||
InternalY = 0;
|
|
||||||
TransferY = 0;
|
TransferY = 0;
|
||||||
memset(FrameBuffer, 0, (640*480/2)*sizeof(u32));
|
memset(FrameBuffer, 0, (640*480/2)*sizeof(u32));
|
||||||
}
|
}
|
||||||
|
@ -521,7 +449,6 @@ bool DSi_Camera::IsActivated() const
|
||||||
|
|
||||||
void DSi_Camera::StartTransfer()
|
void DSi_Camera::StartTransfer()
|
||||||
{
|
{
|
||||||
InternalY = 0;
|
|
||||||
TransferY = 0;
|
TransferY = 0;
|
||||||
|
|
||||||
u8 state = MCURegs[0x2104];
|
u8 state = MCURegs[0x2104];
|
||||||
|
@ -555,11 +482,9 @@ bool DSi_Camera::TransferDone() const
|
||||||
return TransferY >= FrameHeight;
|
return TransferY >= FrameHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSi_Camera::TransferScanline(u32* buffer, int maxlen, int& nlines)
|
int DSi_Camera::TransferScanline(u32* buffer, int maxlen)
|
||||||
{
|
{
|
||||||
nlines = 0;
|
if (TransferY >= FrameHeight)
|
||||||
|
|
||||||
if ((TransferY >= FrameHeight) || (InternalY >= 480))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (FrameWidth > 640 || FrameHeight > 480 ||
|
if (FrameWidth > 640 || FrameHeight > 480 ||
|
||||||
|
@ -575,7 +500,7 @@ int DSi_Camera::TransferScanline(u32* buffer, int maxlen, int& nlines)
|
||||||
// TODO: non-YUV pixel formats and all
|
// TODO: non-YUV pixel formats and all
|
||||||
|
|
||||||
int retlen = FrameWidth >> 1;
|
int retlen = FrameWidth >> 1;
|
||||||
int sy = InternalY;
|
int sy = (TransferY * 480) / FrameHeight;
|
||||||
if (FrameReadMode & (1<<1))
|
if (FrameReadMode & (1<<1))
|
||||||
sy = 479 - sy;
|
sy = 479 - sy;
|
||||||
|
|
||||||
|
@ -604,15 +529,7 @@ int DSi_Camera::TransferScanline(u32* buffer, int maxlen, int& nlines)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine how many scanlines we're skipping until the next scanline
|
TransferY++;
|
||||||
int oldy = TransferY;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
InternalY++;
|
|
||||||
TransferY = (InternalY * FrameHeight) / 480;
|
|
||||||
nlines++;
|
|
||||||
}
|
|
||||||
while ((TransferY == oldy) && (InternalY < 480));
|
|
||||||
|
|
||||||
return retlen;
|
return retlen;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ public:
|
||||||
bool TransferDone() const;
|
bool TransferDone() const;
|
||||||
|
|
||||||
// lengths in words
|
// lengths in words
|
||||||
int TransferScanline(u32* buffer, int maxlen, int& nlines);
|
int TransferScanline(u32* buffer, int maxlen);
|
||||||
|
|
||||||
void Acquire() override;
|
void Acquire() override;
|
||||||
u8 Read(bool last) override;
|
u8 Read(bool last) override;
|
||||||
|
@ -77,7 +77,6 @@ private:
|
||||||
|
|
||||||
u16 FrameWidth, FrameHeight;
|
u16 FrameWidth, FrameHeight;
|
||||||
u16 FrameReadMode, FrameFormat;
|
u16 FrameReadMode, FrameFormat;
|
||||||
int InternalY;
|
|
||||||
int TransferY;
|
int TransferY;
|
||||||
u32 FrameBuffer[640*480/2]; // YUYV framebuffer, two pixels per word
|
u32 FrameBuffer[640*480/2]; // YUYV framebuffer, two pixels per word
|
||||||
};
|
};
|
||||||
|
@ -118,26 +117,14 @@ private:
|
||||||
|
|
||||||
u32 CropStart, CropEnd;
|
u32 CropStart, CropEnd;
|
||||||
|
|
||||||
bool Transferring;
|
// pixel data buffer holds a maximum of 512 words, regardless of how long scanlines are
|
||||||
|
u32 DataBuffer[512];
|
||||||
// pixel data buffers hold a maximum of 512 words, regardless of how long scanlines are
|
u32 BufferReadPos, BufferWritePos;
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
u32 Data[512];
|
|
||||||
u32 ReadPos, WritePos;
|
|
||||||
|
|
||||||
} sPixelBuffer;
|
|
||||||
sPixelBuffer PixelBuffer[2];
|
|
||||||
u8 CurPixelBuffer;
|
|
||||||
u32 BufferNumLines;
|
u32 BufferNumLines;
|
||||||
DSi_Camera* CurCamera;
|
DSi_Camera* CurCamera;
|
||||||
|
|
||||||
static const u32 kIRQInterval;
|
static const u32 kIRQInterval;
|
||||||
static const u32 kScanlineTime;
|
|
||||||
static const u32 kTransferStart;
|
static const u32 kTransferStart;
|
||||||
|
|
||||||
void SwapPixelBuffers();
|
|
||||||
bool IsTransferring();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -323,7 +323,7 @@ void DSi_DSP::PDataDMAFetch()
|
||||||
}
|
}
|
||||||
void DSi_DSP::PDataDMAStart()
|
void DSi_DSP::PDataDMAStart()
|
||||||
{
|
{
|
||||||
switch ((DSP_PCFG & (3<<2)) >> 2)
|
switch ((DSP_PSTS & (3<<2)) >> 2)
|
||||||
{
|
{
|
||||||
case 0: PDataDMALen = 1; break;
|
case 0: PDataDMALen = 1; break;
|
||||||
case 1: PDataDMALen = 8; break;
|
case 1: PDataDMALen = 8; break;
|
||||||
|
@ -348,7 +348,7 @@ void DSi_DSP::PDataDMACancel()
|
||||||
}
|
}
|
||||||
u16 DSi_DSP::PDataDMAReadMMIO()
|
u16 DSi_DSP::PDataDMAReadMMIO()
|
||||||
{
|
{
|
||||||
u16 ret = 0; // TODO: is this actually 0, or just open bus?
|
u16 ret;
|
||||||
|
|
||||||
if (!PDATAReadFifo.IsEmpty())
|
if (!PDATAReadFifo.IsEmpty())
|
||||||
ret = PDATAReadFifo.Read();
|
ret = PDATAReadFifo.Read();
|
||||||
|
@ -362,9 +362,15 @@ u16 DSi_DSP::PDataDMAReadMMIO()
|
||||||
|
|
||||||
for (int i = 0; i < left; ++i)
|
for (int i = 0; i < left; ++i)
|
||||||
PDataDMAFetch();
|
PDataDMAFetch();
|
||||||
|
|
||||||
|
ret = PDATAReadFifo.Read();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ah, crap
|
||||||
|
ret = 0; // TODO: is this actually 0, or just open bus?
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO only trigger IRQ if enabled!!
|
|
||||||
if (!PDATAReadFifo.IsEmpty() || PDATAReadFifo.IsFull())
|
if (!PDATAReadFifo.IsEmpty() || PDATAReadFifo.IsFull())
|
||||||
DSi.SetIRQ(0, IRQ_DSi_DSP);
|
DSi.SetIRQ(0, IRQ_DSi_DSP);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
@ -132,6 +132,7 @@ void DSi_NDMA::WriteCnt(u32 val)
|
||||||
|
|
||||||
// TODO: unsupported start modes:
|
// TODO: unsupported start modes:
|
||||||
// * timers (00-03)
|
// * timers (00-03)
|
||||||
|
// * camera (ARM9 0B)
|
||||||
// * microphone (ARM7 0C)
|
// * microphone (ARM7 0C)
|
||||||
// * NDS-wifi?? (ARM7 07, likely not working)
|
// * NDS-wifi?? (ARM7 07, likely not working)
|
||||||
|
|
||||||
|
@ -269,18 +270,11 @@ void DSi_NDMA::Run9()
|
||||||
|
|
||||||
if ((StartMode & 0x1F) == 0x10) // CHECKME
|
if ((StartMode & 0x1F) == 0x10) // CHECKME
|
||||||
{
|
{
|
||||||
// no repeat
|
|
||||||
Cnt &= ~(1<<31);
|
Cnt &= ~(1<<31);
|
||||||
if (Cnt & (1<<30)) DSi.SetIRQ(0, IRQ_DSi_NDMA0 + Num);
|
if (Cnt & (1<<30)) DSi.SetIRQ(0, IRQ_DSi_NDMA0 + Num);
|
||||||
}
|
}
|
||||||
else if (Cnt & (1<<29))
|
else if (!(Cnt & (1<<29)))
|
||||||
{
|
{
|
||||||
// repeat infinitely
|
|
||||||
if (Cnt & (1<<30)) DSi.SetIRQ(0, IRQ_DSi_NDMA0 + Num);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// repeat until total count is reached
|
|
||||||
if (TotalRemCount == 0)
|
if (TotalRemCount == 0)
|
||||||
{
|
{
|
||||||
Cnt &= ~(1<<31);
|
Cnt &= ~(1<<31);
|
||||||
|
@ -365,18 +359,11 @@ void DSi_NDMA::Run7()
|
||||||
|
|
||||||
if ((StartMode & 0x1F) == 0x10) // CHECKME
|
if ((StartMode & 0x1F) == 0x10) // CHECKME
|
||||||
{
|
{
|
||||||
// no repeat
|
|
||||||
Cnt &= ~(1<<31);
|
Cnt &= ~(1<<31);
|
||||||
if (Cnt & (1<<30)) DSi.SetIRQ(1, IRQ_DSi_NDMA0 + Num);
|
if (Cnt & (1<<30)) DSi.SetIRQ(1, IRQ_DSi_NDMA0 + Num);
|
||||||
}
|
}
|
||||||
else if (Cnt & (1<<29))
|
else if (!(Cnt & (1<<29)))
|
||||||
{
|
{
|
||||||
// repeat infinitely
|
|
||||||
if (Cnt & (1<<30)) DSi.SetIRQ(1, IRQ_DSi_NDMA0 + Num);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// repeat until total count is reached
|
|
||||||
if (TotalRemCount == 0)
|
if (TotalRemCount == 0)
|
||||||
{
|
{
|
||||||
Cnt &= ~(1<<31);
|
Cnt &= ~(1<<31);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
@ -242,6 +242,8 @@ u16 CartGame::ROMRead(u32 addr) const
|
||||||
case 0xC8: return GPIO.control;
|
case 0xC8: return GPIO.control;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECKME: does ROM mirror?
|
// CHECKME: does ROM mirror?
|
||||||
|
@ -537,57 +539,6 @@ CartGameSolarSensor::CartGameSolarSensor(std::unique_ptr<u8[]>&& rom, u32 len, s
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CartGameSolarSensor> CreateFakeSolarSensorROM(const char* gamecode, const NDSCart::CartCommon& cart, void* userdata) noexcept
|
|
||||||
{
|
|
||||||
return CreateFakeSolarSensorROM(gamecode, cart.GetHeader().NintendoLogo, userdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<CartGameSolarSensor> CreateFakeSolarSensorROM(const char* gamecode, const GBACart::CartGame& cart, void* userdata) noexcept
|
|
||||||
{
|
|
||||||
return CreateFakeSolarSensorROM(gamecode, cart.GetHeader().NintendoLogo, userdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<CartGameSolarSensor> CreateFakeSolarSensorROM(const char* gamecode, const u8* logo, void* userdata) noexcept
|
|
||||||
{
|
|
||||||
if (!gamecode)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (strnlen(gamecode, sizeof(GBAHeader::GameCode)) > sizeof(GBAHeader::GameCode))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
bool solarsensor = false;
|
|
||||||
for (const char* i : SOLAR_SENSOR_GAMECODES)
|
|
||||||
{
|
|
||||||
if (strcmp(gamecode, i) == 0) {
|
|
||||||
solarsensor = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!solarsensor)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// just 256 bytes; we don't need a whole ROM!
|
|
||||||
constexpr size_t FAKE_BOKTAI_ROM_LENGTH = 0x100;
|
|
||||||
std::unique_ptr<u8[]> rom = std::make_unique<u8[]>(FAKE_BOKTAI_ROM_LENGTH);
|
|
||||||
|
|
||||||
// create a fake ROM
|
|
||||||
GBAHeader& header = *reinterpret_cast<GBAHeader*>(rom.get());
|
|
||||||
memcpy(header.Title, BOKTAI_STUB_TITLE, strnlen(BOKTAI_STUB_TITLE, sizeof(header.Title)));
|
|
||||||
memcpy(header.GameCode, gamecode, strnlen(gamecode, sizeof(header.GameCode)));
|
|
||||||
header.FixedValue = 0x96;
|
|
||||||
if (logo)
|
|
||||||
{
|
|
||||||
memcpy(header.NintendoLogo, logo, sizeof(header.NintendoLogo));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memset(header.NintendoLogo, 0xFF, sizeof(header.NintendoLogo));
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_unique<CartGameSolarSensor>(std::move(rom), FAKE_BOKTAI_ROM_LENGTH, nullptr, 0, userdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
const int CartGameSolarSensor::kLuxLevels[11] = {0, 5, 11, 18, 27, 42, 62, 84, 109, 139, 183};
|
const int CartGameSolarSensor::kLuxLevels[11] = {0, 5, 11, 18, 27, 42, 62, 84, 109, 139, 183};
|
||||||
|
|
||||||
void CartGameSolarSensor::Reset()
|
void CartGameSolarSensor::Reset()
|
||||||
|
@ -773,27 +724,6 @@ void CartRumblePak::ROMWrite(u32 addr, u16 val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CartGuitarGrip::CartGuitarGrip(void* userdata) :
|
|
||||||
CartCommon(GuitarGrip),
|
|
||||||
UserData(userdata)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CartGuitarGrip::~CartGuitarGrip() = default;
|
|
||||||
|
|
||||||
u16 CartGuitarGrip::ROMRead(u32 addr) const
|
|
||||||
{
|
|
||||||
return 0xF9FF;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CartGuitarGrip::SRAMRead(u32 addr)
|
|
||||||
{
|
|
||||||
return ~((Platform::Addon_KeyDown(Platform::KeyGuitarGripGreen, UserData) ? 0x40 : 0)
|
|
||||||
| (Platform::Addon_KeyDown(Platform::KeyGuitarGripRed, UserData) ? 0x20 : 0)
|
|
||||||
| (Platform::Addon_KeyDown(Platform::KeyGuitarGripYellow, UserData) ? 0x10 : 0)
|
|
||||||
| (Platform::Addon_KeyDown(Platform::KeyGuitarGripBlue, UserData) ? 0x08 : 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
GBACartSlot::GBACartSlot(melonDS::NDS& nds, std::unique_ptr<CartCommon>&& cart) noexcept : NDS(nds), Cart(std::move(cart))
|
GBACartSlot::GBACartSlot(melonDS::NDS& nds, std::unique_ptr<CartCommon>&& cart) noexcept : NDS(nds), Cart(std::move(cart))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -913,27 +843,7 @@ std::unique_ptr<CartCommon> LoadAddon(int type, void* userdata)
|
||||||
case GBAAddon_RumblePak:
|
case GBAAddon_RumblePak:
|
||||||
cart = std::make_unique<CartRumblePak>(userdata);
|
cart = std::make_unique<CartRumblePak>(userdata);
|
||||||
break;
|
break;
|
||||||
case GBAAddon_SolarSensorBoktai1:
|
|
||||||
// US Boktai 1
|
|
||||||
cart = CreateFakeSolarSensorROM("U3IE", nullptr, userdata);
|
|
||||||
break;
|
|
||||||
case GBAAddon_SolarSensorBoktai2:
|
|
||||||
// US Boktai 2
|
|
||||||
cart = CreateFakeSolarSensorROM("U32E", nullptr, userdata);
|
|
||||||
break;
|
|
||||||
case GBAAddon_SolarSensorBoktai3:
|
|
||||||
// JP Boktai 3
|
|
||||||
cart = CreateFakeSolarSensorROM("U33J", nullptr, userdata);
|
|
||||||
break;
|
|
||||||
case GBAAddon_MotionPakHomebrew:
|
|
||||||
cart = std::make_unique<CartMotionPakHomebrew>(userdata);
|
|
||||||
break;
|
|
||||||
case GBAAddon_MotionPakRetail:
|
|
||||||
cart = std::make_unique<CartMotionPakRetail>(userdata);
|
|
||||||
break;
|
|
||||||
case GBAAddon_GuitarGrip:
|
|
||||||
cart = std::make_unique<CartGuitarGrip>(userdata);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
Log(LogLevel::Warn, "GBACart: !! invalid addon type %d\n", type);
|
Log(LogLevel::Warn, "GBACart: !! invalid addon type %d\n", type);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
100
src/GBACart.h
100
src/GBACart.h
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
@ -33,30 +33,8 @@ enum CartType
|
||||||
GameSolarSensor = 0x102,
|
GameSolarSensor = 0x102,
|
||||||
RAMExpansion = 0x201,
|
RAMExpansion = 0x201,
|
||||||
RumblePak = 0x202,
|
RumblePak = 0x202,
|
||||||
MotionPakHomebrew = 0x203,
|
|
||||||
MotionPakRetail = 0x204,
|
|
||||||
GuitarGrip = 0x205,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// See https://problemkaputt.de/gbatek.htm#gbacartridgeheader for details
|
|
||||||
struct GBAHeader
|
|
||||||
{
|
|
||||||
u32 EntryPoint;
|
|
||||||
u8 NintendoLogo[156]; // must be valid
|
|
||||||
char Title[12];
|
|
||||||
char GameCode[4];
|
|
||||||
char MakerCode[2];
|
|
||||||
u8 FixedValue; // must be 0x96
|
|
||||||
u8 MainUnitCode;
|
|
||||||
u8 DeviceType;
|
|
||||||
u8 Reserved0[7];
|
|
||||||
u8 SoftwareVersion;
|
|
||||||
u8 ComplementCheck;
|
|
||||||
u8 Reserved1[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(sizeof(GBAHeader) == 192, "GBAHeader should be 192 bytes");
|
|
||||||
|
|
||||||
// CartCommon -- base code shared by all cart types
|
// CartCommon -- base code shared by all cart types
|
||||||
class CartCommon
|
class CartCommon
|
||||||
{
|
{
|
||||||
|
@ -113,8 +91,6 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] const u8* GetROM() const override { return ROM.get(); }
|
[[nodiscard]] const u8* GetROM() const override { return ROM.get(); }
|
||||||
[[nodiscard]] u32 GetROMLength() const override { return ROMLength; }
|
[[nodiscard]] u32 GetROMLength() const override { return ROMLength; }
|
||||||
[[nodiscard]] const GBAHeader& GetHeader() const noexcept { return *reinterpret_cast<const GBAHeader*>(ROM.get()); }
|
|
||||||
[[nodiscard]] GBAHeader& GetHeader() noexcept { return *reinterpret_cast<GBAHeader*>(ROM.get()); }
|
|
||||||
|
|
||||||
u8* GetSaveMemory() const override;
|
u8* GetSaveMemory() const override;
|
||||||
u32 GetSaveMemoryLength() const override;
|
u32 GetSaveMemoryLength() const override;
|
||||||
|
@ -235,68 +211,11 @@ private:
|
||||||
u16 RumbleState = 0;
|
u16 RumbleState = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// CartGuitarGrip -- DS Guitar Grip (used in various NDS games)
|
|
||||||
class CartGuitarGrip : public CartCommon
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CartGuitarGrip(void* userdata);
|
|
||||||
~CartGuitarGrip() override;
|
|
||||||
|
|
||||||
u16 ROMRead(u32 addr) const override;
|
|
||||||
u8 SRAMRead(u32 addr) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void* UserData;
|
|
||||||
};
|
|
||||||
|
|
||||||
// CartMotionPakHomebrew -- DS Motion Pak (Homebrew)
|
|
||||||
class CartMotionPakHomebrew : public CartCommon
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CartMotionPakHomebrew(void* userdata);
|
|
||||||
~CartMotionPakHomebrew() override;
|
|
||||||
|
|
||||||
void Reset() override;
|
|
||||||
|
|
||||||
void DoSavestate(Savestate* file) override;
|
|
||||||
|
|
||||||
u16 ROMRead(u32 addr) const override;
|
|
||||||
u8 SRAMRead(u32 addr) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void* UserData;
|
|
||||||
u16 ShiftVal = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// CartMotionPakRetail -- DS Motion Pack (Retail)
|
|
||||||
class CartMotionPakRetail : public CartCommon
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CartMotionPakRetail(void* userdata);
|
|
||||||
~CartMotionPakRetail() override;
|
|
||||||
|
|
||||||
void Reset() override;
|
|
||||||
|
|
||||||
void DoSavestate(Savestate* file) override;
|
|
||||||
|
|
||||||
u16 ROMRead(u32 addr) const override;
|
|
||||||
u8 SRAMRead(u32 addr) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void* UserData;
|
|
||||||
u8 Value;
|
|
||||||
u8 Step = 16;
|
|
||||||
};
|
|
||||||
|
|
||||||
// possible inputs for GBA carts that might accept user input
|
// possible inputs for GBA carts that might accept user input
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
Input_SolarSensorDown = 0,
|
Input_SolarSensorDown = 0,
|
||||||
Input_SolarSensorUp,
|
Input_SolarSensorUp,
|
||||||
Input_GuitarGripGreen,
|
|
||||||
Input_GuitarGripRed,
|
|
||||||
Input_GuitarGripYellow,
|
|
||||||
Input_GuitarGripBlue,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GBACartSlot
|
class GBACartSlot
|
||||||
|
@ -390,23 +309,6 @@ std::unique_ptr<CartCommon> ParseROM(std::unique_ptr<u8[]>&& romdata, u32 romlen
|
||||||
|
|
||||||
std::unique_ptr<CartCommon> LoadAddon(int type, void* userdata);
|
std::unique_ptr<CartCommon> LoadAddon(int type, void* userdata);
|
||||||
|
|
||||||
/// Creates a solar sensor-enabled GBA cart without needing a real Boktai ROM.
|
|
||||||
/// This enables the solar sensor to be used in supported games.
|
|
||||||
/// Will not contain any SRAM.
|
|
||||||
/// @param gamecode
|
|
||||||
/// @param logo The Nintendo logo data embedded in the headers for GBA ROMs and NDS ROMs.
|
|
||||||
/// Required for the cart to be recognized as a valid GBA cart.
|
|
||||||
/// Overloads that accept cart objects directly exist as well.
|
|
||||||
/// If not provided, then it will have to be patched with equivalent data
|
|
||||||
/// from a real ROM (NDS or GBA) before booting the emulator.
|
|
||||||
/// @param userdata Optional user data to associate with the cart.
|
|
||||||
/// @return A CartGameSolarSensor if the ROM was created successfully,
|
|
||||||
/// or nullptr if any argument is wrong (e.g. an incorrect game code).
|
|
||||||
std::unique_ptr<CartGameSolarSensor> CreateFakeSolarSensorROM(const char* gamecode, const u8* logo, void* userdata = nullptr) noexcept;
|
|
||||||
std::unique_ptr<CartGameSolarSensor> CreateFakeSolarSensorROM(const char* gamecode, const NDSCart::CartCommon& cart, void* userdata = nullptr) noexcept;
|
|
||||||
std::unique_ptr<CartGameSolarSensor> CreateFakeSolarSensorROM(const char* gamecode, const GBACart::CartGame& cart, void* userdata = nullptr) noexcept;
|
|
||||||
|
|
||||||
constexpr const char* BOKTAI_STUB_TITLE = "BOKTAI STUB";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GBACART_H
|
#endif // GBACART_H
|
||||||
|
|
|
@ -1,196 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2016-2024 melonDS team
|
|
||||||
|
|
||||||
This file is part of melonDS.
|
|
||||||
|
|
||||||
melonDS is free software: you can redistribute it and/or modify it under
|
|
||||||
the terms of the GNU General Public License as published by the Free
|
|
||||||
Software Foundation, either version 3 of the License, or (at your option)
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with melonDS. If not, see http://www.gnu.org/licenses/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include "NDS.h"
|
|
||||||
#include "GBACart.h"
|
|
||||||
#include "Platform.h"
|
|
||||||
#include <algorithm>
|
|
||||||
#include "math.h"
|
|
||||||
|
|
||||||
namespace melonDS
|
|
||||||
{
|
|
||||||
using Platform::Log;
|
|
||||||
using Platform::LogLevel;
|
|
||||||
|
|
||||||
namespace GBACart
|
|
||||||
{
|
|
||||||
|
|
||||||
CartMotionPakHomebrew::CartMotionPakHomebrew(void* userdata) :
|
|
||||||
CartCommon(MotionPakHomebrew),
|
|
||||||
UserData(userdata)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CartMotionPakHomebrew::~CartMotionPakHomebrew() = default;
|
|
||||||
|
|
||||||
void CartMotionPakHomebrew::Reset()
|
|
||||||
{
|
|
||||||
ShiftVal = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CartMotionPakHomebrew::DoSavestate(Savestate* file)
|
|
||||||
{
|
|
||||||
CartCommon::DoSavestate(file);
|
|
||||||
file->Var16(&ShiftVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 CartMotionPakHomebrew::ROMRead(u32 addr) const
|
|
||||||
{
|
|
||||||
// CHECKME: Does this apply to the homebrew cart as well?
|
|
||||||
return 0xFCFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int AccelerationToMotionPak(float accel)
|
|
||||||
{
|
|
||||||
const float GRAVITY_M_S2 = 9.80665f;
|
|
||||||
|
|
||||||
return std::clamp(
|
|
||||||
(int) ((accel / (5 * GRAVITY_M_S2) + 0.5) * 4096),
|
|
||||||
0, 4095
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int AccelerationToMotionPakRetail(float accel)
|
|
||||||
{
|
|
||||||
const float GRAVITY_M_S2 = 9.80665f;
|
|
||||||
|
|
||||||
return std::clamp(
|
|
||||||
(int) ((accel / (5 * GRAVITY_M_S2) + 0.5) * 256),
|
|
||||||
0, 254
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int RotationToMotionPak(float rot)
|
|
||||||
{
|
|
||||||
const float DEGREES_PER_RAD = 180 / M_PI;
|
|
||||||
const float COUNTS_PER_DEG_PER_SEC = 0.825;
|
|
||||||
const int CENTER = 1680;
|
|
||||||
|
|
||||||
return std::clamp(
|
|
||||||
(int) ((rot * DEGREES_PER_RAD * COUNTS_PER_DEG_PER_SEC) + CENTER + 0.5),
|
|
||||||
0, 4095
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CartMotionPakHomebrew::SRAMRead(u32 addr)
|
|
||||||
{
|
|
||||||
// CHECKME: SRAM address mask
|
|
||||||
addr &= 0xFFFF;
|
|
||||||
|
|
||||||
switch (addr)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
// Read next byte
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
// Read X acceleration
|
|
||||||
ShiftVal = AccelerationToMotionPak(Platform::Addon_MotionQuery(Platform::MotionAccelerationX, UserData)) << 4;
|
|
||||||
// CHECKME: First byte returned when reading acceleration/rotation
|
|
||||||
return 0;
|
|
||||||
case 4:
|
|
||||||
// Read Y acceleration
|
|
||||||
ShiftVal = AccelerationToMotionPak(Platform::Addon_MotionQuery(Platform::MotionAccelerationY, UserData)) << 4;
|
|
||||||
return 0;
|
|
||||||
case 6:
|
|
||||||
// Read Z acceleration
|
|
||||||
ShiftVal = AccelerationToMotionPak(Platform::Addon_MotionQuery(Platform::MotionAccelerationZ, UserData)) << 4;
|
|
||||||
return 0;
|
|
||||||
case 8:
|
|
||||||
// Read Z rotation
|
|
||||||
// CHECKME: This is a guess, compare with real hardware
|
|
||||||
ShiftVal = RotationToMotionPak(-Platform::Addon_MotionQuery(Platform::MotionRotationZ, UserData)) << 4;
|
|
||||||
return 0;
|
|
||||||
case 10:
|
|
||||||
// Identify cart
|
|
||||||
ShiftVal = 0xF00F;
|
|
||||||
return 0;
|
|
||||||
case 12:
|
|
||||||
case 14:
|
|
||||||
case 16:
|
|
||||||
case 18:
|
|
||||||
// Read/enable analog inputs
|
|
||||||
//
|
|
||||||
// These are not connected by defualt and require do-it-yourself cart
|
|
||||||
// modification, so there is no reason to emulate them.
|
|
||||||
ShiftVal = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read high byte from the emulated shift register
|
|
||||||
u8 val = ShiftVal >> 8;
|
|
||||||
ShiftVal <<= 8;
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
CartMotionPakRetail::CartMotionPakRetail(void* userdata) :
|
|
||||||
CartCommon(MotionPakRetail),
|
|
||||||
UserData(userdata)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CartMotionPakRetail::~CartMotionPakRetail() = default;
|
|
||||||
|
|
||||||
void CartMotionPakRetail::Reset()
|
|
||||||
{
|
|
||||||
Value = 0;
|
|
||||||
Step = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CartMotionPakRetail::DoSavestate(Savestate* file)
|
|
||||||
{
|
|
||||||
CartCommon::DoSavestate(file);
|
|
||||||
file->Var8(&Value);
|
|
||||||
file->Var8(&Step);
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 CartMotionPakRetail::ROMRead(u32 addr) const
|
|
||||||
{
|
|
||||||
// A9-A8 is pulled low on a real Motion Pack.
|
|
||||||
return 0xFCFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CartMotionPakRetail::SRAMRead(u32 addr)
|
|
||||||
{
|
|
||||||
switch (Step)
|
|
||||||
{
|
|
||||||
case 0: // Synchronization - read 0xFF
|
|
||||||
Value = 0xFF;
|
|
||||||
break;
|
|
||||||
case 4: // X acceleration
|
|
||||||
Value = AccelerationToMotionPakRetail(Platform::Addon_MotionQuery(Platform::MotionAccelerationX, UserData));
|
|
||||||
break;
|
|
||||||
case 8: // Y acceleration
|
|
||||||
Value = AccelerationToMotionPakRetail(Platform::Addon_MotionQuery(Platform::MotionAccelerationY, UserData));
|
|
||||||
break;
|
|
||||||
case 12: // Z acceleration
|
|
||||||
Value = AccelerationToMotionPakRetail(Platform::Addon_MotionQuery(Platform::MotionAccelerationZ, UserData));
|
|
||||||
break;
|
|
||||||
case 16: // Synchronization - read 0b00
|
|
||||||
Step = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int shift = 6 - ((Step & 3) * 2);
|
|
||||||
Step++;
|
|
||||||
return (Value >> shift) & 0x03;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
@ -1219,7 +1219,7 @@ void GPU3D::SubmitPolygon() noexcept
|
||||||
|
|
||||||
u32 texfmt = (TexParam >> 26) & 0x7;
|
u32 texfmt = (TexParam >> 26) & 0x7;
|
||||||
u32 polyalpha = (CurPolygonAttr >> 16) & 0x1F;
|
u32 polyalpha = (CurPolygonAttr >> 16) & 0x1F;
|
||||||
poly->Translucent = (texfmt == 1 || texfmt == 6) || (polyalpha > 0 && polyalpha < 31);
|
poly->Translucent = ((texfmt == 1 || texfmt == 6) && !(CurPolygonAttr & 0x10)) || (polyalpha > 0 && polyalpha < 31);
|
||||||
|
|
||||||
poly->IsShadowMask = ((CurPolygonAttr & 0x3F000030) == 0x00000030);
|
poly->IsShadowMask = ((CurPolygonAttr & 0x3F000030) == 0x00000030);
|
||||||
poly->IsShadow = ((CurPolygonAttr & 0x30) == 0x30) && !poly->IsShadowMask;
|
poly->IsShadow = ((CurPolygonAttr & 0x30) == 0x30) && !poly->IsShadowMask;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016-2025 melonDS team
|
Copyright 2016-2024 melonDS team
|
||||||
|
|
||||||
This file is part of melonDS.
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue