mirror of
https://github.com/ares-emulator/ares.git
synced 2026-11-09 17:03:16 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
625df94505 | ||
|
|
0dc80ee4a2 | ||
|
|
f373fdc165 | ||
|
|
68f2c94658 | ||
|
|
11750b9600 | ||
|
|
135cadd32f | ||
|
|
f015fffd69 | ||
|
|
aa7260a58d | ||
|
|
cdd551f122 | ||
|
|
f3ce7952f6 | ||
|
|
9b1eb2e2f9 | ||
|
|
c337ba258f | ||
|
|
6f16c5c17e | ||
|
|
b494705ad7 | ||
|
|
371ba7b136 | ||
|
|
fb685afa70 | ||
|
|
f3ff75feb1 | ||
|
|
5211e6c56d | ||
|
|
e3c5cfb44d | ||
|
|
c95b48d95f | ||
|
|
136afead52 | ||
|
|
0865680da1 | ||
|
|
08811ee3cb | ||
|
|
b79ed895ff | ||
|
|
ece74e44e4 | ||
|
|
b1c69c9f3f | ||
|
|
4c42273a07 | ||
|
|
ac58451996 | ||
|
|
325c0ed876 | ||
|
|
f89777d8cc | ||
|
|
f0fd4c0bd2 | ||
|
|
a3d8db1c2a | ||
|
|
073d7a5375 | ||
|
|
264a1baafa | ||
|
|
645be6ab9b | ||
|
|
67fc2b1073 | ||
|
|
46b1991f8f | ||
|
|
c9dfe8a1b9 | ||
|
|
af07e1f863 | ||
|
|
b624fadd75 | ||
|
|
46209710d7 | ||
|
|
90eb0df7d7 | ||
|
|
64c9751dc5 | ||
|
|
54e3479708 | ||
|
|
9186ec0201 | ||
|
|
64196caef8 | ||
|
|
1d0d6177a5 | ||
|
|
421b7abf96 | ||
|
|
7e9df5858d | ||
|
|
69381f7c54 | ||
|
|
8f55894d65 | ||
|
|
4e1435be8a | ||
|
|
cf0c21e15a | ||
|
|
e10ce79153 | ||
|
|
ad7b83b604 | ||
|
|
53f3b6a2a2 | ||
|
|
b630377ddc | ||
|
|
24a9c00ae7 | ||
|
|
b5488aad82 | ||
|
|
5f782419ae | ||
|
|
7d5c6d2561 | ||
|
|
585e43a94c | ||
|
|
28ab75242f | ||
|
|
4dd7a1f5fe | ||
|
|
756ea5b704 | ||
|
|
7c051bae0b | ||
|
|
edfc6b5fb0 | ||
|
|
cdc0633fdd | ||
|
|
71facd2e14 | ||
|
|
af95d2b760 | ||
|
|
f4f48eb4b9 | ||
|
|
667827ab00 | ||
|
|
70480452a8 | ||
|
|
a70acad605 | ||
|
|
dca8745f83 | ||
|
|
fabbdc8d8f | ||
|
|
1a79a0aae0 | ||
|
|
de066b1ea2 | ||
|
|
c185fbd66e | ||
|
|
dae8db9883 | ||
|
|
4c4b2a5e5a | ||
|
|
510ccf01d7 | ||
|
|
aab2fdf9b2 | ||
|
|
e2d7106a6c | ||
|
|
1598f67506 | ||
|
|
5d3f614c63 | ||
|
|
8ef16dfbd9 | ||
|
|
701cfb7b13 | ||
|
|
ae121d7377 | ||
|
|
ed1e34c74e | ||
|
|
728105b28e | ||
|
|
3d88e24559 | ||
|
|
a61ce6449f | ||
|
|
63aa9ec5e4 | ||
|
|
50e42627e2 | ||
|
|
3a46652b15 | ||
|
|
7528feabe8 | ||
|
|
e57a80ea1b | ||
|
|
4c0a03b35a | ||
|
|
a247271e35 | ||
|
|
d61cfa905a | ||
|
|
9987bf18b2 | ||
|
|
8a80d32519 | ||
|
|
5d0de5fbb3 | ||
|
|
f06168e3f5 | ||
|
|
828f847efe | ||
|
|
d8c997ca8a | ||
|
|
93137b76b4 | ||
|
|
b889aff3d4 | ||
|
|
70f3bfa00c | ||
|
|
d942746f74 | ||
|
|
1c05456bec | ||
|
|
240363d31a | ||
|
|
ebb3bcb37b | ||
|
|
ab14fb1d10 | ||
|
|
7ba94fe7e4 | ||
|
|
69ea086d95 | ||
|
|
a510ac7e55 | ||
|
|
ac98fd8d9c | ||
|
|
122820753e | ||
|
|
e355fbe88c | ||
|
|
c1efa05d65 | ||
|
|
da071246fe | ||
|
|
cca0ecf202 | ||
|
|
17aee9071d | ||
|
|
b92ae8a14c | ||
|
|
4ae42b2d44 | ||
|
|
2a11da200d | ||
|
|
cbf4a939aa | ||
|
|
d10a8498e2 | ||
|
|
2eb6bf6df8 | ||
|
|
35ede44b80 | ||
|
|
0c011fb2d4 | ||
|
|
a006ef97e7 | ||
|
|
14a4f32997 | ||
|
|
25c1e281cc | ||
|
|
3ee7556bb7 | ||
|
|
a5b11b13d0 | ||
|
|
01e6cc1443 | ||
|
|
f5dace0a0f | ||
|
|
6b5ebb2882 | ||
|
|
140782662b | ||
|
|
3daec1184a | ||
|
|
7e4386c1bf | ||
|
|
8eba8ad784 | ||
|
|
08377d02e2 | ||
|
|
ea4ad6890a | ||
|
|
50be2e4e63 | ||
|
|
effc5614bc | ||
|
|
5f81464857 | ||
|
|
bd8442605e | ||
|
|
da312032de | ||
|
|
c509dd3964 | ||
|
|
10a4d480de | ||
|
|
8c3ead7cb0 | ||
|
|
1b36d47554 | ||
|
|
2c940b03a1 | ||
|
|
7a5174a712 | ||
|
|
274d6eb9a5 | ||
|
|
de0cb099cb | ||
|
|
32fd70f7c7 | ||
|
|
b2251305c0 | ||
|
|
25a2602300 | ||
|
|
4480f7adec | ||
|
|
4197502402 | ||
|
|
fb96de3eef | ||
|
|
54c898f199 | ||
|
|
e48b208de2 | ||
|
|
a9f9fd90e7 | ||
|
|
deb8830c82 | ||
|
|
58af8cb64b | ||
|
|
c9285b5289 | ||
|
|
4fc09438d2 | ||
|
|
a0a7a53b32 | ||
|
|
90f1425b8e | ||
|
|
9f4446061d | ||
|
|
32e58943f0 | ||
|
|
bc116e70e1 | ||
|
|
992e1c08cb | ||
|
|
9dcc1a39d3 | ||
|
|
9bbcf638dd | ||
|
|
d6c8d36770 | ||
|
|
c19cf47803 | ||
|
|
1d5a5aef83 | ||
|
|
64ec01bd57 | ||
|
|
82b1e88ec1 | ||
|
|
a592dc24d2 | ||
|
|
976b9828b6 | ||
|
|
7f625b6348 | ||
|
|
23a9d66924 | ||
|
|
e4e9044097 | ||
|
|
04a51df859 | ||
|
|
0c80c1e56b | ||
|
|
6f7618dc81 | ||
|
|
fdd7acb76b | ||
|
|
7ce2ffd010 | ||
|
|
bb22386f5f | ||
|
|
b372f65691 | ||
|
|
048d0e331d | ||
|
|
1323a627b3 | ||
|
|
b4ef96e4d6 | ||
|
|
8d2f88b745 | ||
|
|
ca7eee17a9 | ||
|
|
9ef81df3cf | ||
|
|
68af829f8e | ||
|
|
56862e0026 | ||
|
|
09d8af1c18 | ||
|
|
d20bc3c1b0 | ||
|
|
97c82119b5 | ||
|
|
b78228c5c0 | ||
|
|
5107ed00cb | ||
|
|
aeff8ec8f9 | ||
|
|
7640e1598c | ||
|
|
04c608a21e | ||
|
|
8a75015d7e | ||
|
|
330a329abc | ||
|
|
a21f8c074c | ||
|
|
c899461cf1 | ||
|
|
512b53f808 | ||
|
|
2fb2da047c | ||
|
|
cdbd9e0d2c | ||
|
|
745e41a6ee | ||
|
|
ab40ecbb9b | ||
|
|
72ead4d2a6 | ||
|
|
aef110f35d | ||
|
|
e99c9c57b0 | ||
|
|
9c273abec3 | ||
|
|
6cc9f5a416 | ||
|
|
69c20711fc | ||
|
|
539aa9b7d6 | ||
|
|
5d7dbb7eed | ||
|
|
6176287392 | ||
|
|
ce2e6f8c19 | ||
|
|
76ab41c69c | ||
|
|
928d76b0b5 | ||
|
|
c1949d8eb5 | ||
|
|
6946437115 | ||
|
|
76a5f8e1da | ||
|
|
bf9aae53d0 | ||
|
|
1a5559a24b | ||
|
|
af5fa1a1c8 | ||
|
|
4c367fd32f | ||
|
|
2d714d1a9c | ||
|
|
8dbd2135b7 | ||
|
|
c62e2a254c | ||
|
|
dfcd7d4fce | ||
|
|
fa1c21ba3d | ||
|
|
a584782a86 | ||
|
|
6185edc43b | ||
|
|
7772fdbf0a | ||
|
|
fd8bcad5a1 | ||
|
|
da7a79b21e | ||
|
|
639ebe6285 | ||
|
|
9be2f9bb92 | ||
|
|
ce71fff00c | ||
|
|
a91b24acf1 | ||
|
|
c5d316274a | ||
|
|
8444f52843 | ||
|
|
d775c0968b | ||
|
|
c76b87cdb2 | ||
|
|
2197df8cca | ||
|
|
324a192109 | ||
|
|
4a9b77a5e1 | ||
|
|
a27c2a2b3a | ||
|
|
34124fd1cc | ||
|
|
f6b58b076b | ||
|
|
b4b026db28 | ||
|
|
05898a6a04 | ||
|
|
331c4956b0 | ||
|
|
d6c42e59e4 | ||
|
|
58661451ed | ||
|
|
e808d2c5ab | ||
|
|
445acba894 | ||
|
|
07fa6bc265 | ||
|
|
3e5ed40801 | ||
|
|
10b747c305 | ||
|
|
2ed2ed34bc | ||
|
|
41b61ee6d5 | ||
|
|
a960aeef52 | ||
|
|
1eb0a1659a | ||
|
|
c19a2ac1b2 | ||
|
|
8642d35e5f | ||
|
|
80db392140 | ||
|
|
a2400ad43a | ||
|
|
e8cd9b3e04 | ||
|
|
e04922c4d5 | ||
|
|
69795d578a | ||
|
|
8433666dc2 | ||
|
|
ecdce5e92b | ||
|
|
0b4fea8ce5 | ||
|
|
5bcef4741a | ||
|
|
3b18a3f808 | ||
|
|
7d327a2c8a | ||
|
|
07bafb6a51 | ||
|
|
1bb1669b03 | ||
|
|
a752b85d6f | ||
|
|
a02c0f80de | ||
|
|
50ceb088ef | ||
|
|
65618ce1e2 | ||
|
|
4691971416 | ||
|
|
98d9eb7786 | ||
|
|
431aba5a1a | ||
|
|
78e5332361 | ||
|
|
687bfe8efc | ||
|
|
7cc6d517a2 | ||
|
|
3bd385e4a8 | ||
|
|
de2d7d86c9 | ||
|
|
a0d8ce25c5 | ||
|
|
557ecb5319 | ||
|
|
8cc98f94ae | ||
|
|
7e5d749adc | ||
|
|
675d57b6fa | ||
|
|
28cfa89970 | ||
|
|
8668f98fa5 | ||
|
|
8f772cdb01 | ||
|
|
229e16df98 | ||
|
|
36290b9705 | ||
|
|
014d0130f5 | ||
|
|
d6465d0daa | ||
|
|
802a902cd3 | ||
|
|
2bf4e28db5 | ||
|
|
1469299363 |
No files matched your search
+11
@@ -0,0 +1,11 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/BlankSpruce/gersemi/master/gersemi/configuration.schema.json
|
||||
|
||||
color: false
|
||||
definitions: [ares/CMakeLists.txt]
|
||||
line_length: 120
|
||||
indent: 2
|
||||
list_expansion: favour-inlining
|
||||
quiet: false
|
||||
unsafe: false
|
||||
warn_about_unknown_commands: false
|
||||
workers: 10
|
||||
@@ -0,0 +1,2 @@
|
||||
# When archiving, export a version file containing tag/commit information
|
||||
cmake/common/.archive-version.json export-subst
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env sh
|
||||
set -euo pipefail
|
||||
|
||||
# configure
|
||||
cmake --preset $TARGET_PRESET
|
||||
|
||||
# change into the build directory
|
||||
pushd build
|
||||
|
||||
# build; pipe output to render warnings neatly
|
||||
xcodebuild -configuration RelWithDebInfo \
|
||||
DEBUG_INFORMATION_FORMAT="dwarf-with-dsym" \
|
||||
-parallelizeTargets \
|
||||
2>&1 | xcbeautify --renderer github-actions
|
||||
|
||||
popd
|
||||
|
||||
# package debug symbols
|
||||
|
||||
# move dependency dSYMs to build output directory
|
||||
ditto .deps/ares-deps-macos-universal/lib/*.dSYM build/desktop-ui/RelWithDebInfo
|
||||
|
||||
mkdir build/dsyms
|
||||
|
||||
# ares.app.dSYM already exists alongside ares.app; package it with the rest
|
||||
mv build/desktop-ui/RelWithDebInfo/*.dSYM build/dSYMs/
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# configure
|
||||
cmake --preset $TARGET_PRESET
|
||||
|
||||
# change into the build directory
|
||||
pushd build
|
||||
|
||||
ninja
|
||||
|
||||
popd
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env sh
|
||||
set -euo pipefail
|
||||
|
||||
if [ "$CROSS_COMPILE" = true ]; then
|
||||
cmake --preset $NATIVE_PRESET -B build_native
|
||||
pushd build_native
|
||||
# build sourcery natively so it may be invoked during cross-compilation
|
||||
cmake --build . --target sourcery --config RelWithDebInfo
|
||||
popd
|
||||
fi
|
||||
|
||||
cmake --preset $TARGET_PRESET
|
||||
pushd build
|
||||
cmake --build . --config RelWithDebInfo
|
||||
|
||||
if [ "$CROSS_COMPILE" = true ] || [ "$ARES_PLATFORM_NAME" = "windows-arm64" ]; then
|
||||
cp ../.deps/ares-deps-windows-arm64/lib/*.pdb desktop-ui/rundir/
|
||||
else
|
||||
cp ../.deps/ares-deps-windows-x64/lib/*.pdb desktop-ui/rundir/
|
||||
fi
|
||||
|
||||
mkdir PDBs
|
||||
mv desktop-ui/rundir/*.pdb PDBs/
|
||||
popd
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
set -eu
|
||||
case ${GITHUB_REF} in
|
||||
refs/tags/*) suffix="-${GITHUB_REF#refs/tags/}" ;;
|
||||
refs/heads/master) suffix="-nightly" ;;
|
||||
*) suffix="" ;;
|
||||
esac
|
||||
|
||||
bindir="${GITHUB_WORKSPACE}/bin"
|
||||
|
||||
# Hack: Workaround for GitHub artifacts losing attributes.
|
||||
chmod +x ${bindir}/ares-macos-universal/ares.app/Contents/MacOS/ares
|
||||
|
||||
for package in macos-universal
|
||||
do
|
||||
mkdir "${package}"
|
||||
cd "${package}"
|
||||
|
||||
# Package ares.
|
||||
outdir=ares${suffix}
|
||||
mkdir ${outdir}
|
||||
mkdir ${outdir}-dSYMs
|
||||
cp -a ${bindir}/ares-${package}-dSYMs/*.dSYM ${outdir}-dSYMs
|
||||
cp -a ${bindir}/ares-${package}/*.app ${outdir}
|
||||
zip -r -y ../ares-${package}.zip ${outdir}
|
||||
zip -r -y ../ares-${package}-dSYMs.zip ${outdir}-dSYMs
|
||||
cd -
|
||||
done
|
||||
|
||||
for package in windows-x64 windows-clang-cl-arm64
|
||||
do
|
||||
mkdir "${package}"
|
||||
cd "${package}"
|
||||
|
||||
# Package ares.
|
||||
outdir=ares${suffix}
|
||||
mkdir ${outdir}
|
||||
mkdir ${outdir}-PDBs
|
||||
cp -a ${bindir}/ares-${package}-PDBs/*.pdb ${outdir}-PDBs
|
||||
zip -r ../ares-${package}-PDBs.zip ${outdir}-PDBs
|
||||
rm -rf ${bindir}/ares-${package}/PDBs
|
||||
cp -a ${bindir}/ares-${package}/* ${outdir}
|
||||
zip -r ../ares-${package}.zip ${outdir}
|
||||
cd -
|
||||
done
|
||||
@@ -0,0 +1,112 @@
|
||||
name: Build (Auxiliary)
|
||||
on:
|
||||
workflow_call
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
program:
|
||||
- ares
|
||||
config:
|
||||
- RelWithDebInfo
|
||||
platform:
|
||||
- name: windows-x64-gcc
|
||||
os: windows-latest
|
||||
shell: 'msys2 {0}'
|
||||
msystem: mingw64
|
||||
install: make git cmake ccache ninja mingw-w64-x86_64-toolchain
|
||||
target-cmake-preset: windows-ci-mingw-native
|
||||
- name: windows-clang-cl-x64
|
||||
os: windows-latest
|
||||
windres: rc
|
||||
shell: bash
|
||||
target-cmake-preset: windows-ci-cl-native
|
||||
- name: windows-arm64
|
||||
os: windows-11-arm
|
||||
compiler: clang++
|
||||
shell: 'msys2 {0}'
|
||||
msystem: clangarm64
|
||||
install: mingw-w64-clang-aarch64-make git mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-ccache mingw-w64-clang-aarch64-ninja mingw-w64-clang-aarch64-clang
|
||||
target-cmake-preset: windows-ci-mingw-native
|
||||
- name: windows-msvc-x64
|
||||
os: windows-latest
|
||||
windres: rc
|
||||
shell: bash
|
||||
target-cmake-preset: windows-ci-msvc-native
|
||||
- name: windows-msvc-arm64
|
||||
os: windows-latest
|
||||
windres: rc
|
||||
shell: bash
|
||||
target-cmake-preset: windows-ci-msvc-cross
|
||||
native-cmake-preset: windows-ci-msvc-native
|
||||
- name: ubuntu-gcc-x64
|
||||
os: ubuntu-24.04
|
||||
shell: bash
|
||||
target-cmake-preset: ubuntu-ci
|
||||
- name: ubuntu-gcc-arm64
|
||||
os: ubuntu-24.04-arm
|
||||
shell: bash
|
||||
target-cmake-preset: ubuntu-ci
|
||||
- name: ubuntu-clang-x64
|
||||
os: ubuntu-24.04
|
||||
shell: bash
|
||||
target-cmake-preset: ubuntu-ci-clang
|
||||
- name: ubuntu-clang-arm64
|
||||
os: ubuntu-24.04-arm
|
||||
shell: bash
|
||||
target-cmake-preset: ubuntu-ci-clang
|
||||
name: ${{ matrix.program }}-${{ matrix.platform.name }}
|
||||
runs-on: ${{ matrix.platform.os }}
|
||||
defaults:
|
||||
run:
|
||||
shell: ${{ matrix.platform.shell }}
|
||||
steps:
|
||||
- name: Install MSYS2 Dependencies
|
||||
if: matrix.platform.shell == 'msys2 {0}'
|
||||
uses: msys2/setup-msys2@40677d36a502eb2cf0fb808cc9dec31bf6152638
|
||||
with:
|
||||
msystem: ${{ matrix.platform.msystem }}
|
||||
install: ${{ matrix.platform.install }}
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
with:
|
||||
fetch-tags: true
|
||||
fetch-depth: 0
|
||||
- name: Setup MSYS2 Git Environment
|
||||
if: matrix.platform.shell == 'msys2 {0}'
|
||||
run: |
|
||||
git config core.autocrlf true
|
||||
- name: Install Linux Dependencies
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get update -y -qq
|
||||
sudo apt-get install cmake ccache ninja-build libsdl2-dev libgtk-3-dev libao-dev libopenal-dev
|
||||
- name: "Build: Linux"
|
||||
if: runner.os == 'Linux'
|
||||
run: .github/scripts/build_ubuntu.sh
|
||||
env:
|
||||
TARGET_PRESET: ${{ matrix.platform.target-cmake-preset }}
|
||||
- name: "Build: Windows"
|
||||
if: runner.os != 'macOS' && runner.os != 'Linux'
|
||||
run: .github/scripts/build_windows.sh
|
||||
env:
|
||||
ARES_PLATFORM_NAME: ${{ matrix.platform.name }}
|
||||
CROSS_COMPILE: ${{ matrix.platform.native-cmake-preset != '' }}
|
||||
NATIVE_PRESET: ${{ matrix.platform.native-cmake-preset }}
|
||||
TARGET_PRESET: ${{ matrix.platform.target-cmake-preset }}
|
||||
- name: "Compress Build Artifacts (Windows)"
|
||||
if: runner.os != 'macOS' && runner.os != 'Linux'
|
||||
run: |
|
||||
tar -cvJf ares-${{ matrix.platform.name }}.tar.xz -C build/desktop-ui/rundir/ .
|
||||
- name: Upload Build
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
|
||||
with:
|
||||
name: ${{ matrix.program }}-${{ matrix.platform.name }}
|
||||
path: ares-${{ matrix.platform.name }}.tar.xz
|
||||
- name: Upload Debug Symbols (Windows)
|
||||
if: runner.os != 'macOS' && runner.os != 'Linux'
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
|
||||
with:
|
||||
name: ${{ matrix.program }}-${{ matrix.platform.name }}-PDBs
|
||||
path: build/PDBs/*
|
||||
+83
-285
@@ -1,10 +1,17 @@
|
||||
name: Build
|
||||
name: Build (Primary)
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
tags: [ 'v*' ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
workflow_call:
|
||||
inputs:
|
||||
codesign:
|
||||
description: Enable codesigning
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
official:
|
||||
description: Use official version strings
|
||||
required: true
|
||||
default: true
|
||||
type: boolean
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
@@ -12,57 +19,28 @@ jobs:
|
||||
matrix:
|
||||
program:
|
||||
- ares
|
||||
config:
|
||||
- RelWithDebInfo
|
||||
platform:
|
||||
- name: windows
|
||||
- name: windows-x64
|
||||
os: windows-latest
|
||||
compiler: clang++
|
||||
windres: windres
|
||||
shell: 'msys2 {0}'
|
||||
msystem: clang64
|
||||
install: mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-pkgconf mingw-w64-clang-x86_64-SDL2
|
||||
- name: windows-arm64
|
||||
install: make git cmake ccache ninja mingw-w64-clang-x86_64-clang
|
||||
target-cmake-preset: windows-ci-mingw-native
|
||||
- name: windows-clang-cl-arm64
|
||||
os: windows-latest
|
||||
compiler: clang++ --target=aarch64-w64-windows-gnu --sysroot=/clangarm64 -resource-dir=/clangarm64/lib/clang/$(basename "$(clang++ -print-resource-dir)")
|
||||
windres: windres --target=aarch64-w64-windows-gnu
|
||||
shell: 'msys2 {0}'
|
||||
msystem: clang64
|
||||
install: mingw-w64-clang-x86_64-clang mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-pkgconf mingw-w64-clang-aarch64-SDL2
|
||||
- name: windows-msvc-x64
|
||||
os: windows-latest
|
||||
compiler: clang++
|
||||
windres: llvm-rc
|
||||
shell: bash
|
||||
msvc-arch: x64
|
||||
- name: windows-msvc-arm64
|
||||
os: windows-latest
|
||||
compiler: clang++ --target=aarch64-w64-windows-msvc
|
||||
windres: llvm-rc
|
||||
shell: bash
|
||||
msvc-arch: x64_arm64
|
||||
- name: windows-cl-x64
|
||||
os: windows-latest
|
||||
compiler: cl
|
||||
windres: rc
|
||||
shell: bash
|
||||
msvc-arch: x64
|
||||
- name: windows-cl-arm64
|
||||
os: windows-latest
|
||||
compiler: cl
|
||||
windres: rc
|
||||
shell: bash
|
||||
msvc-arch: x64_arm64
|
||||
- name: macos-compat
|
||||
os: macos-12
|
||||
target-cmake-preset: windows-ci-cl-cross
|
||||
native-cmake-preset: windows-ci-cl-native
|
||||
- name: macos-universal
|
||||
os: macos-15
|
||||
compiler: clang++
|
||||
shell: sh
|
||||
- name: macos-latest
|
||||
os: macos-latest
|
||||
compiler: clang++
|
||||
shell: sh
|
||||
- name: ubuntu
|
||||
os: ubuntu-latest
|
||||
compiler: g++
|
||||
shell: sh
|
||||
install: cmake ccache xcbeautify
|
||||
target-cmake-preset: macos-ci-universal
|
||||
name: ${{ matrix.program }}-${{ matrix.platform.name }}
|
||||
runs-on: ${{ matrix.platform.os }}
|
||||
defaults:
|
||||
@@ -71,264 +49,84 @@ jobs:
|
||||
steps:
|
||||
- name: Install MSYS2 Dependencies
|
||||
if: matrix.platform.shell == 'msys2 {0}'
|
||||
uses: msys2/setup-msys2@v2
|
||||
uses: msys2/setup-msys2@40677d36a502eb2cf0fb808cc9dec31bf6152638
|
||||
with:
|
||||
msystem: ${{ matrix.platform.msystem }}
|
||||
install: make ${{ matrix.platform.install }}
|
||||
install: ${{ matrix.platform.install }}
|
||||
- name: "macOS: Import Certificate"
|
||||
if: runner.os == 'macOS' && inputs.codesign
|
||||
uses: apple-actions/import-codesign-certs@65cfbc37e1464d733524cb555b724878f278b8c3
|
||||
continue-on-error: ${{ secrets.MACOS_CERTIFICATE_NAME == '' }}
|
||||
with:
|
||||
p12-file-base64: ${{ secrets.MACOS_CERTIFICATE_DATA }}
|
||||
p12-password: ${{ secrets.MACOS_CERTIFICATE_PASSPHRASE }}
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
with:
|
||||
fetch-tags: true
|
||||
fetch-depth: 0
|
||||
- name: Setup MSYS2 Git Environment
|
||||
if: matrix.platform.shell == 'msys2 {0}'
|
||||
run: |
|
||||
git config core.autocrlf true
|
||||
- name: Install Linux Dependencies
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get update -y -qq
|
||||
sudo apt-get install libsdl2-dev libgtk-3-dev libao-dev libopenal-dev
|
||||
- name: "macOS: Import Certificate"
|
||||
if: runner.os == 'macOS' && github.event_name != 'pull_request'
|
||||
continue-on-error: ${{ github.repository != 'ares-emulator/ares' }}
|
||||
uses: wpilibsuite/import-signing-certificate@2ac4f44d28045073d23153256efbb4c4b2d8aa22 # Don't use rolling branch for security reasons
|
||||
with:
|
||||
certificate-data: ${{ secrets.MACOS_CERTIFICATE_DATA }}
|
||||
certificate-passphrase: ${{ secrets.MACOS_CERTIFICATE_PASSPHRASE }}
|
||||
keychain-name: ares-macos-keychain
|
||||
keychain-password: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }}
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Windows Dependencies
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
export PATH="/c/Users/runneradmin/.cargo/bin:$PATH" # correct on windows-latest as of 2024-02-19
|
||||
if [[ ${{ matrix.platform.name }} == *-arm64 ]]; then
|
||||
rustup toolchain install nightly
|
||||
rustup default nightly
|
||||
rustup target add aarch64-pc-windows-msvc
|
||||
pushd thirdparty/librashader
|
||||
./build-librashader.sh aarch64-pc-windows-msvc
|
||||
popd
|
||||
else
|
||||
rustup toolchain install nightly
|
||||
rustup default nightly
|
||||
pushd thirdparty/librashader
|
||||
./build-librashader.sh
|
||||
popd
|
||||
fi
|
||||
- name: "macOS: recover MoltenVK cache"
|
||||
if: runner.os == 'macOS'
|
||||
uses: actions/cache@v4
|
||||
env:
|
||||
cache-name: moltenvk
|
||||
with:
|
||||
path: thirdparty/MoltenVK/MoltenVK
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('thirdparty/MoltenVK/HEAD') }}
|
||||
sudo apt-get install ${{ matrix.platform.install }}
|
||||
- name: Install macOS Dependencies
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
if [ $ImageOS == "macos14" ]; then
|
||||
sudo xcode-select -s /Applications/Xcode_15.2.app/Contents/Developer
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.13
|
||||
echo "Set Xcode version to 15.2 for macos-latest build."
|
||||
elif [ $ImageOS == "macos12" ]; then
|
||||
sudo xcode-select -s /Applications/Xcode_13.4.app/Contents/Developer
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.9
|
||||
echo "Set Xcode version to 13.4 for macos-compat build."
|
||||
fi
|
||||
brew install make ninja cmake
|
||||
pip install --no-input setuptools
|
||||
rustup toolchain install nightly
|
||||
rustup default nightly
|
||||
rustup target add x86_64-apple-darwin
|
||||
rustup target add aarch64-apple-darwin
|
||||
echo "MAKE=gmake" >> $GITHUB_ENV
|
||||
pushd thirdparty/SDL
|
||||
./build-SDL.sh
|
||||
popd
|
||||
pushd thirdparty/MoltenVK
|
||||
./build-moltenvk.sh
|
||||
popd
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.15
|
||||
pushd thirdparty/librashader
|
||||
./build-librashader.sh
|
||||
popd
|
||||
- name: Set up MSVC environment
|
||||
if: matrix.platform.msvc-arch != ''
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: ${{ matrix.platform.msvc-arch }}
|
||||
- name: Make
|
||||
if: runner.os != 'macOS'
|
||||
run: ${MAKE:-make} -j4 -C desktop-ui build=optimized local=false compiler="${{ matrix.platform.compiler }}" windres="${{ matrix.platform.windres }}"
|
||||
- name: "macOS: Make universal app"
|
||||
if: runner.os == 'macOS'
|
||||
run: scripts/macos-make-universal.sh build=optimized local=false
|
||||
brew install ${{ matrix.platform.install }}
|
||||
- name: "Build: Windows"
|
||||
if: runner.os != 'macOS' && runner.os != 'Linux'
|
||||
run: .github/scripts/build_windows.sh
|
||||
env:
|
||||
MAKEFLAGS: -j3
|
||||
MACOS_CERTIFICATE_NAME: ${{ secrets.MACOS_CERTIFICATE_NAME }}
|
||||
MACOS_KEYCHAIN_NAME: ares-macos-keychain
|
||||
MACOS_KEYCHAIN_PASSWORD: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }}
|
||||
ARES_BUILD_OFFICIAL: ${{ inputs.official }}
|
||||
ARES_PLATFORM_NAME: ${{ matrix.platform.name }}
|
||||
CROSS_COMPILE: ${{ matrix.platform.native-cmake-preset != '' }}
|
||||
NATIVE_PRESET: ${{ matrix.platform.native-cmake-preset }}
|
||||
TARGET_PRESET: ${{ matrix.platform.target-cmake-preset }}
|
||||
- name: "Windows: sign"
|
||||
if: runner.os == 'Windows' && github.event_name != 'pull_request'
|
||||
if: runner.os == 'Windows' && inputs.codesign
|
||||
uses: DanaBear/code-sign-action@98c79121b376beab8d6a9484f445089db4461bca
|
||||
with:
|
||||
certificate: '${{ secrets.WIN_CERTIFICATE }}'
|
||||
password: '${{ secrets.WIN_PASSWORD }}'
|
||||
certificatesha1: '${{ secrets.WIN_CERTHASH }}'
|
||||
certificatename: '${{ secrets.WIN_CERTNAME }}'
|
||||
folder: 'desktop-ui/out'
|
||||
timestampUrl: 'http://timestamp.digicert.com'
|
||||
- name: "macOS: notarize"
|
||||
if: runner.os == 'macOS' && github.event_name != 'pull_request'
|
||||
continue-on-error: ${{ github.repository != 'ares-emulator/ares' }}
|
||||
run: |
|
||||
ditto -c -k --keepParent desktop-ui/out/ares.app /tmp/ares.zip
|
||||
xcrun notarytool submit /tmp/ares.zip --apple-id "$MACOS_NOTARIZATION_USERNAME" --password "$MACOS_NOTARIZATION_PASSWORD" --team-id "$MACOS_NOTARIZATION_TEAMID" --wait
|
||||
xcrun stapler staple desktop-ui/out/ares.app
|
||||
folder: 'build/desktop-ui/rundir/'
|
||||
timestampUrl: 'http://timestamp.digicert.com'
|
||||
- name: "Build: macOS"
|
||||
if: runner.os == 'macOS'
|
||||
run: .github/scripts/build_macos.sh
|
||||
env:
|
||||
MACOS_NOTARIZATION_USERNAME: ${{ secrets.MACOS_NOTARIZATION_USERNAME }}
|
||||
MACOS_NOTARIZATION_PASSWORD: ${{ secrets.MACOS_NOTARIZATION_PASSWORD }}
|
||||
ARES_BUILD_OFFICIAL: ${{ inputs.official }}
|
||||
TARGET_PRESET: ${{ matrix.platform.target-cmake-preset }}
|
||||
MACOS_CERTIFICATE_NAME: ${{ secrets.MACOS_CERTIFICATE_NAME }}
|
||||
MACOS_NOTARIZATION_TEAMID: ${{ secrets.MACOS_NOTARIZATION_TEAMID }}
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v4
|
||||
- name: "Compress Build Artifact (macOS)"
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
tar -cvJf ares-${{ matrix.platform.name }}.tar.xz -C build/desktop-ui/RelWithDebInfo/ .
|
||||
- name: "Compress Build Artifacts (Windows)"
|
||||
if: runner.os != 'macOS' && runner.os != 'Linux'
|
||||
run: |
|
||||
tar -cvJf ares-${{ matrix.platform.name }}.tar.xz -C build/desktop-ui/rundir/ .
|
||||
- name: Upload Build
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
|
||||
with:
|
||||
name: ${{ matrix.program }}-${{ matrix.platform.name }}
|
||||
path: desktop-ui/out/*
|
||||
|
||||
|
||||
release:
|
||||
if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- build
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
path: ares-${{ matrix.platform.name }}.tar.xz
|
||||
- name: Upload Debug Symbols (Windows)
|
||||
if: runner.os != 'macOS' && runner.os != 'Linux'
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
|
||||
with:
|
||||
path: 'src'
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
name: ${{ matrix.program }}-${{ matrix.platform.name }}-PDBs
|
||||
path: build/PDBs/*
|
||||
- name: Upload Debug Symbols (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
|
||||
with:
|
||||
path: 'bin'
|
||||
- name: Package Artifacts
|
||||
run: |
|
||||
set -eu
|
||||
case ${GITHUB_REF} in
|
||||
refs/tags/*) suffix="-${GITHUB_REF#refs/tags/}" ;;
|
||||
refs/heads/master) suffix="-nightly" ;;
|
||||
*) suffix="" ;;
|
||||
esac
|
||||
|
||||
srcdir="${GITHUB_WORKSPACE}/src"
|
||||
bindir="${GITHUB_WORKSPACE}/bin"
|
||||
|
||||
# Hack: Workaround for GitHub artifacts losing attributes.
|
||||
chmod +x ${bindir}/ares-macos-latest/ares.app/Contents/MacOS/ares
|
||||
chmod +x ${bindir}/ares-macos-compat/ares.app/Contents/MacOS/ares
|
||||
|
||||
for package in windows windows-msvc-arm64 macos-latest macos-compat
|
||||
do
|
||||
mkdir "${package}"
|
||||
cd "${package}"
|
||||
|
||||
# Package ares.
|
||||
outdir=ares${suffix}
|
||||
mkdir ${outdir}
|
||||
cp -ar ${bindir}/ares-${package}/* ${outdir}
|
||||
zip -r ../ares-${package}.zip ${outdir}
|
||||
|
||||
cd -
|
||||
done
|
||||
- name: Create Release
|
||||
id: release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
set -eu
|
||||
github_rest()
|
||||
{
|
||||
local method="${1}"
|
||||
local url="https://api.github.com${2}"
|
||||
shift 2
|
||||
>&2 echo "${method} ${url}"
|
||||
curl \
|
||||
--fail \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
-H "Authorization: token ${GITHUB_TOKEN}" \
|
||||
-X "${method}" \
|
||||
"${url}" \
|
||||
"$@"
|
||||
}
|
||||
github_get_release_id_for_tag()
|
||||
{
|
||||
payload=$(github_rest GET "/repos/${GITHUB_REPOSITORY}/releases/tags/${1}") || return
|
||||
echo "${payload}" | jq .id
|
||||
}
|
||||
github_delete_release_by_id()
|
||||
{
|
||||
github_rest DELETE "/repos/${GITHUB_REPOSITORY}/releases/${1}"
|
||||
}
|
||||
github_create_release()
|
||||
{
|
||||
local payload="{
|
||||
\"tag_name\": \"${1}\",
|
||||
\"target_commitish\": \"${2}\",
|
||||
\"name\": \"${3}\",
|
||||
\"body\": \"${4}\",
|
||||
\"draft\": ${5},
|
||||
\"prerelease\": ${6}
|
||||
}"
|
||||
github_rest POST "/repos/${GITHUB_REPOSITORY}/releases" -d "${payload}"
|
||||
}
|
||||
make_nightly_release()
|
||||
{
|
||||
github_create_release \
|
||||
nightly \
|
||||
"${GITHUB_SHA}" \
|
||||
"ares nightly $(date +"%Y-%m-%d")" \
|
||||
"Auto-generated nightly release on $(date -u +"%Y-%m-%d %T %Z")" \
|
||||
false \
|
||||
true
|
||||
}
|
||||
make_version_release()
|
||||
{
|
||||
github_create_release \
|
||||
"${1}" \
|
||||
"${GITHUB_SHA}" \
|
||||
"ares ${1}" \
|
||||
"This is ares ${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}" ;;
|
||||
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 ares-windows
|
||||
uses: actions/upload-release-asset@v1
|
||||
env: { GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' }
|
||||
with: { upload_url: '${{ env.UPLOAD_URL }}', asset_path: 'ares-windows.zip', asset_name: 'ares-windows.zip', asset_content_type: 'application/zip' }
|
||||
- name: Upload ares-windows-msvc-arm64
|
||||
uses: actions/upload-release-asset@v1
|
||||
env: { GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' }
|
||||
with: { upload_url: '${{ env.UPLOAD_URL }}', asset_path: 'ares-windows-msvc-arm64.zip', asset_name: 'ares-windows-msvc-arm64.zip', asset_content_type: 'application/zip' }
|
||||
- name: Upload ares-macos-latest
|
||||
uses: actions/upload-release-asset@v1
|
||||
env: { GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' }
|
||||
with: { upload_url: '${{ env.UPLOAD_URL }}', asset_path: 'ares-macos-latest.zip', asset_name: 'ares-macos-latest.zip', asset_content_type: 'application/zip' }
|
||||
- name: Upload ares-macos-compat
|
||||
uses: actions/upload-release-asset@v1
|
||||
env: { GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' }
|
||||
with: { upload_url: '${{ env.UPLOAD_URL }}', asset_path: 'ares-macos-compat.zip', asset_name: 'ares-macos-compat.zip', asset_content_type: 'application/zip' }
|
||||
# - name: Upload ares-ubuntu
|
||||
# uses: actions/upload-release-asset@v1
|
||||
# env: { GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' }
|
||||
# with: { upload_url: '${{ env.UPLOAD_URL }}', asset_path: 'ares-ubuntu.zip', asset_name: 'ares-ubuntu.zip', asset_content_type: 'application/zip' }
|
||||
|
||||
name: ${{ matrix.program }}-${{ matrix.platform.name }}-dSYMs
|
||||
path: build/dSYMs/*
|
||||
@@ -0,0 +1,23 @@
|
||||
name: Pull Request
|
||||
run-name: ${{ github.event.pull_request.title }} PR run
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ '*' ]
|
||||
types: [ opened, synchronize, reopened ]
|
||||
permissions:
|
||||
contents: read
|
||||
concurrency:
|
||||
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
build-project:
|
||||
name: Build ares (primary)
|
||||
uses: ./.github/workflows/build.yml
|
||||
permissions:
|
||||
contents: read
|
||||
with:
|
||||
official: false
|
||||
build-aux:
|
||||
name: Build ares (auxiliary)
|
||||
uses: ./.github/workflows/build-aux.yml
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,27 @@
|
||||
name: Push
|
||||
on:
|
||||
push
|
||||
concurrency:
|
||||
group: '${{ github.workflow }} @ ${{ github.head_ref || github.ref }}'
|
||||
cancel-in-progress: true
|
||||
permissions:
|
||||
contents: write
|
||||
jobs:
|
||||
build:
|
||||
name: Build ares (primary)
|
||||
uses: ./.github/workflows/build.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
codesign: true
|
||||
official: ${{ github.ref_name == 'master' || github.ref_type == 'tag' }}
|
||||
build-aux:
|
||||
name: Build ares (auxiliary)
|
||||
uses: ./.github/workflows/build-aux.yml
|
||||
secrets: inherit
|
||||
release:
|
||||
name: Release
|
||||
needs: build
|
||||
secrets: inherit
|
||||
uses: ./.github/workflows/release.yml
|
||||
with:
|
||||
notarize: true
|
||||
@@ -0,0 +1,81 @@
|
||||
name: Release
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
notarize:
|
||||
description: Notarize build (macOS only)
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
jobs:
|
||||
release:
|
||||
if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
with:
|
||||
path: 'src'
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
|
||||
with:
|
||||
path: 'bin'
|
||||
- name: "Decompress Build Artifacts"
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
for package in macos-universal windows-x64 windows-clang-cl-arm64; do
|
||||
pushd bin/ares-${package}
|
||||
tar -xJf ares-${package}.tar.xz
|
||||
rm -f ares-${package}.tar.xz
|
||||
popd
|
||||
done
|
||||
- name: "macOS: notarize"
|
||||
if: inputs.notarize
|
||||
run: |
|
||||
ditto -c -k --keepParent ${{ github.workspace }}/bin/ares-macos-universal/ares.app /tmp/ares.zip
|
||||
xcrun notarytool submit /tmp/ares.zip --apple-id "$MACOS_NOTARIZATION_USERNAME" --password "$MACOS_NOTARIZATION_PASSWORD" --team-id "$MACOS_NOTARIZATION_TEAMID" --wait
|
||||
xcrun stapler staple ${{ github.workspace }}/bin/ares-macos-universal/ares.app
|
||||
env:
|
||||
MACOS_NOTARIZATION_USERNAME: ${{ secrets.MACOS_NOTARIZATION_USERNAME }}
|
||||
MACOS_NOTARIZATION_PASSWORD: ${{ secrets.MACOS_NOTARIZATION_PASSWORD }}
|
||||
MACOS_NOTARIZATION_TEAMID: ${{ secrets.MACOS_NOTARIZATION_TEAMID }}
|
||||
- name: Package Artifacts
|
||||
run: src/.github/scripts/package_artifacts.sh
|
||||
- name: Check Release Tag ☑️
|
||||
id: check
|
||||
run: |
|
||||
now=$(date +'%Y-%m-%d')
|
||||
subject=$(git -C src log -1 --pretty=%s)
|
||||
if [[ ${GITHUB_REF_NAME} == master ]];
|
||||
then
|
||||
echo "tag=nightly" >> $GITHUB_OUTPUT
|
||||
versionName="nightly ${now}"
|
||||
echo "versionName=${versionName}" >> $GITHUB_OUTPUT
|
||||
echo "description=${subject}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "tag=${GITHUB_REF_NAME}" >> $GITHUB_OUTPUT
|
||||
echo "versionName=${GITHUB_REF_NAME}" >> $GITHUB_OUTPUT
|
||||
description="This is ares ${GITHUB_REF_NAME}, released on ${now}."
|
||||
echo "description=${description}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Update Git Tag
|
||||
if: steps.check.outputs.tag == 'nightly'
|
||||
id: update-tag
|
||||
run: |
|
||||
git -C src tag -f ${{ steps.check.outputs.tag }}
|
||||
git -C src push -f origin ${{ steps.check.outputs.tag }}
|
||||
|
||||
- name: Create Release 🛫
|
||||
id: create_release
|
||||
uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191
|
||||
with:
|
||||
prerelease: ${{ steps.check.outputs.tag == 'nightly' }}
|
||||
tag_name: ${{ steps.check.outputs.tag }}
|
||||
name: ares ${{ steps.check.outputs.versionName }}
|
||||
body: ${{ steps.check.outputs.description }}
|
||||
files: |
|
||||
${{ github.workspace }}/ares-macos-universal.zip
|
||||
${{ github.workspace }}/ares-macos-universal-dSYMs.zip
|
||||
${{ github.workspace }}/ares-windows-x64.zip
|
||||
${{ github.workspace }}/ares-windows-x64-PDBs.zip
|
||||
${{ github.workspace }}/ares-windows-clang-cl-arm64.zip
|
||||
${{ github.workspace }}/ares-windows-clang-cl-arm64-PDBs.zip
|
||||
+50
-18
@@ -1,18 +1,50 @@
|
||||
*.moc
|
||||
*.user
|
||||
*.xcuserdata
|
||||
.vs/
|
||||
.vscode/
|
||||
.idea/
|
||||
cmake-*/
|
||||
obj/
|
||||
out/
|
||||
obj-amd64/
|
||||
obj-arm64/
|
||||
out-amd64/
|
||||
out-arm64/
|
||||
thirdparty/SDL/SDL
|
||||
thirdparty/SDL/libSDL2-2.0.0.dylib
|
||||
macos-xcode/
|
||||
.swiftpm
|
||||
*.xcodeproj
|
||||
# Exclude everything
|
||||
/*
|
||||
|
||||
# Except for default project files
|
||||
!/.github
|
||||
!/ares
|
||||
!/desktop-ui
|
||||
!/hiro
|
||||
!/cmake
|
||||
!/libco
|
||||
!/mia
|
||||
!/nall
|
||||
!/ruby
|
||||
!/scripts
|
||||
!/tests
|
||||
!/thirdparty
|
||||
!/tools
|
||||
!/GNUMakefile
|
||||
!/LICENSE
|
||||
!/README.md
|
||||
!.editorconfig
|
||||
!.gitignore
|
||||
!.gitattributes
|
||||
!.gersemirc
|
||||
!deps.json
|
||||
!CMakeLists.txt
|
||||
!CMakePresets.json
|
||||
|
||||
# Exclude old macOS Finder metadata
|
||||
.DS_Store
|
||||
|
||||
# Exclude generated sources that still reside in-tree
|
||||
ruby/video/metal/shaders.metallib
|
||||
ruby/video/metal/shaders.ir
|
||||
ares/ares/resource/resource.cpp
|
||||
ares/ares/resource/resource.hpp
|
||||
hiro/resource/resource.cpp
|
||||
hiro/resource/resource.hpp
|
||||
desktop-ui/resource/resource.cpp
|
||||
desktop-ui/resource/resource.hpp
|
||||
mia/resource/resource.cpp
|
||||
mia/resource/resource.hpp
|
||||
|
||||
# Exclude fetched third-party processor test binaries
|
||||
tests/arm7tdmi/tests
|
||||
tests/m68000/tests
|
||||
|
||||
# Exclude unused legacy zlib header that is renamed by CMake
|
||||
thirdparty/libchdr/deps/zlib-*/zconf.h
|
||||
thirdparty/libchdr/deps/zlib-*/zconf.h.included
|
||||
@@ -0,0 +1,55 @@
|
||||
cmake_minimum_required(VERSION 3.28...4.0)
|
||||
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/common/bootstrap.cmake" NO_POLICY_SCOPE)
|
||||
|
||||
project(ares VERSION ${ARES_VERSION_CANONICAL})
|
||||
|
||||
include(compilerconfig)
|
||||
include(defaults)
|
||||
include(helpers)
|
||||
|
||||
add_subdirectory(cmake)
|
||||
|
||||
add_subdirectory(thirdparty)
|
||||
|
||||
add_subdirectory(nall/nall)
|
||||
add_subdirectory(libco)
|
||||
add_subdirectory(ruby)
|
||||
add_subdirectory(hiro)
|
||||
|
||||
# gersemi: off
|
||||
set(
|
||||
ARES_CORES
|
||||
a26 fc sfc sg ms md ps1 pce ng msx cv myvision gb gba ws ngp spec n64
|
||||
CACHE STRING LIST
|
||||
)
|
||||
# gersemi: on
|
||||
|
||||
add_subdirectory(ares)
|
||||
add_subdirectory(mia)
|
||||
add_subdirectory(desktop-ui)
|
||||
|
||||
option(ARES_BUILD_OPTIONAL_TARGETS "Include supplemental tools and tests" OFF)
|
||||
|
||||
if(ARES_BUILD_OPTIONAL_TARGETS)
|
||||
add_subdirectory(tests/arm7tdmi)
|
||||
add_subdirectory(tests/i8080)
|
||||
add_subdirectory(tests/m68000)
|
||||
if(NOT OS_WINDOWS AND NOT OS_MACOS)
|
||||
add_subdirectory(tools/genius)
|
||||
else()
|
||||
target_disable_subproject(genius "genius (database editor)")
|
||||
endif()
|
||||
add_subdirectory(tools/mame2bml)
|
||||
else()
|
||||
target_disable_subproject(arm7tdmi "arm7tdmi processor test harness")
|
||||
target_disable_subproject(i8080 "i8080 processor test harness")
|
||||
target_disable_subproject(m68000 "m68000 processor test harness")
|
||||
target_disable_subproject(mame2bml "mame2bml (MAME manifest converter)")
|
||||
target_disable_subproject(genius "genius (database editor)")
|
||||
endif()
|
||||
|
||||
add_subdirectory(tools/sourcery)
|
||||
|
||||
message_configuration()
|
||||
return()
|
||||
@@ -0,0 +1,187 @@
|
||||
{
|
||||
"version": 3,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 28,
|
||||
"patch": 0
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "baseCacheVars",
|
||||
"hidden": true,
|
||||
"cacheVariables": {
|
||||
"ARES_PROFILE_ACCURACY": false,
|
||||
"ARES_BUILD_LOCAL": true,
|
||||
"ENABLE_CCACHE": true,
|
||||
"ARES_BUILD_OFFICIAL": {"type": "BOOL", "value": "$penv{ARES_BUILD_OFFICIAL}"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos",
|
||||
"displayName": "macOS",
|
||||
"description": "Xcode project (host architecture by default)",
|
||||
"inherits": ["baseCacheVars"],
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
},
|
||||
"generator": "Xcode",
|
||||
"binaryDir": "${sourceDir}/build_macos",
|
||||
"cacheVariables": {
|
||||
"ARES_CODESIGN_IDENTITY": {"type": "STRING", "value": "$penv{CODESIGN_IDENT}"},
|
||||
"ARES_CODESIGN_TEAM": {"type": "STRING", "value": "$penv{CODESIGN_TEAM}"},
|
||||
"ARES_BUILD_OPTIONAL_TARGETS": true,
|
||||
"ENABLE_CCACHE": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows",
|
||||
"displayName": "Windows (Visual Studio, ClangCL)",
|
||||
"description": "Visual Studio project using ClangCL (host architecture)",
|
||||
"inherits": ["baseCacheVars"],
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"binaryDir": "${sourceDir}/build_vsclang",
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"toolset": "ClangCL",
|
||||
"cacheVariables": {
|
||||
"ENABLE_CCACHE": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-msvc",
|
||||
"displayName": "Windows (Visual Studio, MSVC)",
|
||||
"description": "Visual Studio project using MSVC (host architecture)",
|
||||
"inherits": ["baseCacheVars"],
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"binaryDir": "${sourceDir}/build_msvc",
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"cacheVariables": {
|
||||
"ENABLE_CCACHE": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos-ci-universal",
|
||||
"displayName": "macOS for CI",
|
||||
"description": "Universal binary for building on Github Actions",
|
||||
"inherits": ["baseCacheVars"],
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
},
|
||||
"generator": "Xcode",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"cacheVariables": {
|
||||
"CMAKE_OSX_ARCHITECTURES": {"type": "STRING", "value": "x86_64;arm64"},
|
||||
"CMAKE_OSX_DEPLOYMENT_TARGET": {"type": "STRING", "value": "10.15"},
|
||||
"ARES_CODESIGN_IDENTITY": {"type": "STRING", "value": "$penv{MACOS_CERTIFICATE_NAME}"},
|
||||
"ARES_CODESIGN_TEAM": {"type": "STRING", "value": "$penv{MACOS_NOTARIZATION_TEAMID}"},
|
||||
"ENABLE_CCACHE": true,
|
||||
"ARES_BUILD_LOCAL": false,
|
||||
"ARES_UNITY_CORES": true,
|
||||
"ARES_BUILD_OPTIONAL_TARGETS": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-ci-base",
|
||||
"hidden": true,
|
||||
"inherits": ["baseCacheVars"],
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": {"type": "STRING", "value": "RelWithDebInfo"},
|
||||
"ENABLE_CCACHE": true,
|
||||
"ARES_BUILD_LOCAL": false,
|
||||
"ARES_BUILD_OPTIONAL_TARGETS": true,
|
||||
"ARES_UNITY_CORES": true,
|
||||
"ARES_PRECOMPILE_HEADERS": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-ci-mingw-native",
|
||||
"displayName": "Windows for CI (x64 MSYS2/MinGW Clang)",
|
||||
"description": "Single-arch binary for building on Github Actions",
|
||||
"inherits": ["windows-ci-base"],
|
||||
"generator": "Ninja"
|
||||
},
|
||||
{
|
||||
"name": "windows-ci-cl-native",
|
||||
"displayName": "Windows for CI (x64 ClangCL)",
|
||||
"description": "Single-arch binary for building on Github Actions",
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"inherits": ["windows-ci-base"],
|
||||
"toolset": "ClangCL"
|
||||
},
|
||||
{
|
||||
"name": "windows-ci-cl-cross",
|
||||
"displayName": "Windows for CI (arm64 ClangCL)",
|
||||
"description": "Single-arch binary for building on Github Actions",
|
||||
"inherits": ["windows-ci-base"],
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"architecture": "arm64",
|
||||
"toolset": "ClangCL",
|
||||
"cacheVariables": {
|
||||
"ARES_CROSSCOMPILING": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-ci-msvc-native",
|
||||
"displayName": "Windows for CI (x64 MSVC)",
|
||||
"description": "Single-arch binary for building on Github Actions",
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"inherits": ["windows-ci-base"]
|
||||
},
|
||||
{
|
||||
"name": "windows-ci-msvc-cross",
|
||||
"displayName": "Windows for CI (arm64 MSVC)",
|
||||
"description": "Single-arch binary for building on Github Actions",
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"architecture": "arm64",
|
||||
"inherits": ["windows-ci-base"],
|
||||
"cacheVariables": {
|
||||
"ARES_CROSSCOMPILING": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ubuntu-ci",
|
||||
"displayName": "Ubuntu CI (x64 gcc)",
|
||||
"description": "Single-arch binary for building on Github Actions",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": {"type": "STRING", "value": "RelWithDebInfo"},
|
||||
"ENABLE_CCACHE": true,
|
||||
"ARES_BUILD_LOCAL": false,
|
||||
"ARES_BUILD_OPTIONAL_TARGETS": true,
|
||||
"ARES_PRECOMPILE_HEADERS": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ubuntu-ci-clang",
|
||||
"displayName": "Ubuntu CI (clang)",
|
||||
"description": "Single-arch binary for building on Github Actions",
|
||||
"inherits": ["ubuntu-ci"],
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "clang",
|
||||
"CMAKE_CXX_COMPILER": "clang++"
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "windows",
|
||||
"configurePreset": "windows",
|
||||
"displayName": "Windows build (host architecture)",
|
||||
"description": "Windows build (host architecture)",
|
||||
"configuration": "RelWithDebInfo"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
targets = all clean install uninstall verbose
|
||||
|
||||
$(targets):
|
||||
@$(MAKE) -C desktop-ui $@
|
||||
|
||||
.PHONY: $(targets)
|
||||
@@ -1,7 +1,7 @@
|
||||
----------------------------------------------------------------------
|
||||
ares
|
||||
|
||||
Copyright (c) 2004-2021 ares team, Near et al
|
||||
Copyright (c) 2004-2025 ares team, Near et al
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||

|
||||
<img src="https://github.com/ares-emulator/ares/blob/master/ares/ares/resource/logo@2x.png" width="350"/>
|
||||
|
||||
[](https://github.com/higan-emu/ares/blob/master/LICENSE)
|
||||
|
||||
**ares** is a multi-system emulator that began development on October 14th, 2004.
|
||||
It is a descendant of [higan](https://github.com/higan-emu/higan) and [bsnes](https://github.com/bsnes-emu/bsnes/), and focuses on accuracy and preservation.
|
||||
|
||||
It's worth noting that ares takes some uncommon design approaches that essentially trade speed for code clarity. We avoid state machines and bitmasks (when possible). Most cores end up being half the amount of code, but slower. The code is clearer and less spaghettified, especially for systems with lots of processors. C bitfields being non-portable incurs a speedhit. Windows also has a speedhit over Linux due to its ABI needing more instructions to switch contexts.
|
||||
|
||||
Official Releases
|
||||
-----------------
|
||||
|
||||
@@ -14,130 +16,18 @@ Official releases are available from
|
||||
Nightly Builds
|
||||
--------------
|
||||
|
||||
Automated, untested builds of ares are available for Windows and macOS as a [pre-release](https://github.com/higan-emu/ares/releases/tag/nightly).
|
||||
Automated, untested builds of ares are available for Windows and macOS as a [pre-release](https://github.com/ares-emulator/ares/releases/tag/nightly).
|
||||
Only the latest nightly build is kept.
|
||||
|
||||
Prerequisites
|
||||
Building ares
|
||||
-------------
|
||||
|
||||
### *nix building
|
||||
|
||||
###### Minimum required packages:
|
||||
```
|
||||
g++ make pkg-config libgtk-3-dev libcanberra-gtk-module libgl-dev libasound2-dev
|
||||
```
|
||||
###### Additional Audio Drivers
|
||||
ares supports additional audio drivers besides the ALSA drivers included above. Installing these additional packages will allow them to be selected in Settings > Drivers:
|
||||
`libao-dev libopenal-dev`
|
||||
|
||||
###### GTK2 & GTK3
|
||||
By default, GTK3 is used, but support for GTK2 is available. You will need to install the additional package `libgtk2.0-dev` as well as specifying the command line option `hiro=gtk2` at compile time.
|
||||
|
||||
###### SDL2 for input
|
||||
If you would like to use SDL for input (e.g. for using a controller), you will need to install the `libsdl2-dev` and `libsdl2-2.0-0` packages and perform a clean build of ares.
|
||||
You should then be able to select SDL for input in the Settings > Drivers menu.
|
||||
|
||||
##### Building with clang
|
||||
|
||||
clang++ is now the preferred compiler for ares. If clang is detected on Windows/macOS/BSD, it will be selected by default. On Linux and other platforms, g++ remains the default if present. To build with clang, it is necessary to install both the `clang` and `lld` packages. If you would like to manually specify a compiler, you can use the following option: `compiler=[g++|clang++]`
|
||||
|
||||
##### Librashader Support
|
||||
If you do not want to include librashader support, you can pass the following option to the `make` command to skip these requirements using: `librashader=false`
|
||||
|
||||
Librashader requires rust in order to build. You can install it with the following command:
|
||||
```
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
source ~/.cargo/env
|
||||
rustup toolchain install nightly
|
||||
```
|
||||
|
||||
In order to build librashader, change into the `ares/thirdparty/librashader` directory and run the script `build-librashader.sh`
|
||||
Note that once the build completes, it will instruct you to run three copy commands to install the library on your system. These paths may be different depending on Linux distribution.
|
||||
|
||||
--------------
|
||||
|
||||
### Windows building
|
||||
|
||||
To build on Windows, using MSYS2 is recommended which can be download [here](https://www.msys2.org/). Follow the instructions
|
||||
on this page to install and setup an appropriate MINGW64 environment. Running the command:
|
||||
```
|
||||
pacman -S --needed base-devel mingw-w64-x86_64-toolchain mingw-w64-x86_64-SDL2
|
||||
```
|
||||
from the MSYS2 MSYS terminal should setup everything you need to compile ares. Note that in order to compile, you will want to be in a MINGW64 terminal window after install and setup is complete.
|
||||
|
||||
##### Building with clang
|
||||
|
||||
clang is available through Visual Studio (or Build Tools for Visual Studio) through its installer and can be used to build ares. You will still need to supply GNU make in this instance. MSYS2 also offers a clang environment. You will want to make sure you select the clangw64 option during installation of MSYS2 which should provide and additional CLANG64 pre-configured environment. Install the clang toolchain package from the MSYS2 terminal:
|
||||
```
|
||||
pacman -S mingw-w64-clang-x86_64-toolchain mingw-w64-clang-x86_64-SDL2
|
||||
```
|
||||
Once complete, open a CLANG64 terminal window and proceed with building ares.
|
||||
|
||||
###### Debug Symbols
|
||||
When building with clang, by default symbols will be generated for debug builds using an MSVC compatible format (CodeView) for use with Windows debugging tools. In order to generate GDB compatible symbols, specify the following option: `symformat=gdb`
|
||||
|
||||
###### Librashader Support
|
||||
ares has introduced support for the [librashader](https://github.com/SnowflakePowered/librashader) library, which is a preprocessor, compiler, and runtime for RetroArch 'slang' shaders. If you are not interested in working with librashaders, you can pass the following option to the `make` command to skip these requirements using: `librashader=false`
|
||||
|
||||
Building the librashader library on Windows requires Rust. Follow these steps to prepare your system and build the librashader library:
|
||||
|
||||
1. Download and execute the rustup-init.exe installer from: https://rustup.rs/
|
||||
2. Open a new Windows terminal and run the following commands:
|
||||
```
|
||||
rustup toolchain install nightly
|
||||
rustup default nightly
|
||||
```
|
||||
3. With Rust successfully installed, you will need to update your PATH environment variable within your MSYS2 environment. In an MSYS2 shell, open $HOME/.bash_profile and append something like the following (note you will need to replace both instances of %USER_NAME% with the real user name you used to install Rust):
|
||||
```
|
||||
if [ -d "/C/Users/%USER_NAME%/.cargo/bin" ] ; then
|
||||
PATH="/C/Users/%USER_NAME%/.cargo/bin:${PATH}"
|
||||
fi
|
||||
```
|
||||
4. Open a new MSYS2 based shell for the compiler you are using (MinGW64|CLANG64|UCRT64), execute `rustup` to validate the path is set properly within your MSYS2 environment.
|
||||
5. In your MSYS2 compiler shell, `cd` into the `ares/thirdparty/librashader` directory
|
||||
6. Execute the build script, build should complete successfully:
|
||||
```
|
||||
./build-librashader.sh
|
||||
```
|
||||
|
||||
This only needs to be done once, or anytime the librashader library is updated. Once built, ares will build with librashader support by default requiring no additional flags.
|
||||
|
||||
Compilation
|
||||
-----------
|
||||
|
||||
Check out the source code by running this command:
|
||||
|
||||
```
|
||||
git clone https://github.com/ares-emulator/ares.git
|
||||
```
|
||||
|
||||
From the root of the project directory run:
|
||||
|
||||
```
|
||||
make -j4
|
||||
```
|
||||
|
||||
`-j#` indicates number of parallel build processes, and shouldn't be set higher than N-1 cores on your processor. Specifying this option can significantly decrease the time to build this project. There are multiple build types available and it defaults to an 'optimized' build. Build types can be specified using: `build=[debug|stable|release|minified|optimized]`
|
||||
|
||||
Build options can be found in the following two make files: nall/GNUmakefile desktop-ui/GNUmakefile
|
||||
|
||||
To start compilation from the beginning, run the following prior to compiling:
|
||||
|
||||
```
|
||||
make clean
|
||||
```
|
||||
|
||||
#### Building specific cores
|
||||
If you would like to build a subset of cores, you can specify the `cores="core1 core2"` option. Currently available cores:
|
||||
```
|
||||
a26 fc sfc n64 sg ms md ps1 pce ng msx cv myvision gb gba ws ngp spec
|
||||
```
|
||||
|
||||
Build Output
|
||||
------------
|
||||
|
||||
There is a single binary produced at the end of compilation which can be found in `desktop-ui/out`. On OS's besides Linux, the `Database` & `Shader` directories are copied over here as well. On Linux, running `make install` after compilation will copy these directories and binary into suitable locations (see desktop-ui/GNUmakefile for details). Alternatively, these directories can be copied from `thirdparty/slang-shaders/*` into a `Shader` directory, and by copying `mia/Database/*`
|
||||
ares supports building on Windows, macOS, and various Linux/BSD distributions. See build instructions for:
|
||||
|
||||
* [Windows](https://github.com/ares-emulator/ares/wiki/Build-Instructions-For-Windows)
|
||||
* [macOS](https://github.com/ares-emulator/ares/wiki/Build-Instructions-For-macOS)
|
||||
* [Linux](https://github.com/ares-emulator/ares/wiki/Build-Instructions-For-Linux)
|
||||
* [BSD](https://github.com/ares-emulator/ares/wiki/Build-Instructions-For-BSD)
|
||||
|
||||
Command-line options
|
||||
--------------------
|
||||
@@ -150,7 +40,7 @@ Usage: ./ares [options] game(s)
|
||||
--help Displays available options and exit
|
||||
--fullscreen Start in full screen mode
|
||||
--system system Specify the system name
|
||||
--shader shader Specify GLSL shader name to load (requires OpenGL driver)
|
||||
--shader shader Specify a slang shader to load (requires OpenGL or Metal)
|
||||
--setting name=value Specify a value for a setting
|
||||
--dump-all-settings Show a list of all existing settings and exit
|
||||
--no-file-prompt Do not prompt to load (optional) additional roms (eg: 64DD)
|
||||
|
||||
@@ -0,0 +1,314 @@
|
||||
add_library(ares STATIC ares/ares.cpp ares/memory/fixed-allocator.cpp)
|
||||
|
||||
configure_file(ares/ares.cpp.in ares/ares.cpp @ONLY)
|
||||
|
||||
add_library(ares::ares ALIAS ares)
|
||||
|
||||
option(ARES_PROFILE_ACCURACY "Build to prefer emulation accuracy over performance in certain specific areas" OFF)
|
||||
option(ARES_PRECOMPILE_HEADERS "Precompile ares/ares.hpp header for performance" OFF)
|
||||
option(
|
||||
ARES_UNITY_CORES
|
||||
"\
|
||||
Build each core as one translation unit. Decreases cold build times but increases incremental build times. Slightly \
|
||||
increases performance.
|
||||
"
|
||||
OFF
|
||||
)
|
||||
|
||||
add_sourcery_command(ares ares/resource)
|
||||
|
||||
if(ARES_PRECOMPILE_HEADERS)
|
||||
target_precompile_headers(ares PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:ares/ares.hpp>")
|
||||
endif()
|
||||
|
||||
target_link_libraries(ares PUBLIC libco sljit nall)
|
||||
|
||||
if(ARES_PROFILE_ACCURACY)
|
||||
target_compile_definitions(ares PUBLIC PROFILE_ACCURACY)
|
||||
else()
|
||||
target_compile_definitions(ares PUBLIC PROFILE_PERFORMANCE)
|
||||
endif()
|
||||
|
||||
target_sources(
|
||||
ares
|
||||
PRIVATE ares/ares.cpp ares/ares.cpp.in ares/ares.hpp ares/inline.hpp ares/platform.hpp ares/random.hpp ares/types.hpp
|
||||
)
|
||||
|
||||
target_sources(
|
||||
ares
|
||||
PRIVATE
|
||||
ares/debug/debug.cpp
|
||||
ares/debug/debug.hpp
|
||||
ares/memory/fixed-allocator.cpp
|
||||
ares/memory/fixed-allocator.hpp
|
||||
ares/memory/memory.hpp
|
||||
ares/memory/readable.hpp
|
||||
ares/memory/writable.hpp
|
||||
)
|
||||
|
||||
target_sources(
|
||||
ares
|
||||
PRIVATE ares/scheduler/scheduler.cpp ares/scheduler/scheduler.hpp ares/scheduler/thread.cpp ares/scheduler/thread.hpp
|
||||
)
|
||||
|
||||
target_sources(
|
||||
ares
|
||||
PRIVATE
|
||||
ares/node/attribute.hpp
|
||||
ares/node/class.hpp
|
||||
ares/node/node.cpp
|
||||
ares/node/node.hpp
|
||||
ares/node/object.hpp
|
||||
ares/node/peripheral.hpp
|
||||
ares/node/port.hpp
|
||||
ares/node/system.hpp
|
||||
)
|
||||
|
||||
target_sources(ares PRIVATE ares/node/audio/audio.hpp ares/node/audio/stream.cpp ares/node/audio/stream.hpp)
|
||||
|
||||
target_sources(ares PRIVATE ares/node/component/component.hpp ares/node/component/real-time-clock.hpp)
|
||||
|
||||
target_sources(
|
||||
ares
|
||||
PRIVATE
|
||||
ares/node/input/axis.hpp
|
||||
ares/node/input/button.hpp
|
||||
ares/node/input/input.hpp
|
||||
ares/node/input/rumble.hpp
|
||||
ares/node/input/trigger.hpp
|
||||
)
|
||||
|
||||
target_sources(
|
||||
ares
|
||||
PRIVATE
|
||||
ares/node/setting/boolean.hpp
|
||||
ares/node/setting/integer.hpp
|
||||
ares/node/setting/natural.hpp
|
||||
ares/node/setting/real.hpp
|
||||
ares/node/setting/setting.hpp
|
||||
ares/node/setting/string.hpp
|
||||
)
|
||||
|
||||
target_sources(
|
||||
ares
|
||||
PRIVATE
|
||||
ares/node/video/screen.cpp
|
||||
ares/node/video/screen.hpp
|
||||
ares/node/video/sprite.cpp
|
||||
ares/node/video/sprite.hpp
|
||||
ares/node/video/video.hpp
|
||||
)
|
||||
|
||||
if(OS_WINDOWS)
|
||||
include(cmake/os-windows.cmake)
|
||||
elseif(OS_MACOS)
|
||||
include(cmake/os-macos.cmake)
|
||||
elseif(OS_LINUX OR OS_FREEBSD OR OS_OPENBSD)
|
||||
include(cmake/os-linux.cmake)
|
||||
endif()
|
||||
|
||||
macro(ares_components)
|
||||
list(APPEND ares.components ${ARGV})
|
||||
set(ares.components ${ares.components} PARENT_SCOPE)
|
||||
endmacro()
|
||||
|
||||
macro(ares_add_sources)
|
||||
set(options "")
|
||||
set(oneValueArgs CORE)
|
||||
set(multiValueArgs PRIMARY INCLUDED UNITY)
|
||||
cmake_parse_arguments(AAS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
target_sources(ares PRIVATE ${AAS_INCLUDED} ${AAS_PRIMARY})
|
||||
|
||||
if(ARES_UNITY_CORES)
|
||||
list(APPEND AAS_INCLUDED ${AAS_PRIMARY})
|
||||
target_sources(ares PRIVATE ${AAS_UNITY})
|
||||
endif()
|
||||
|
||||
foreach(arg IN ITEMS ${AAS_INCLUDED})
|
||||
list(APPEND ARES_HEADER_SOURCES "${AAS_CORE}/${arg}")
|
||||
endforeach()
|
||||
set(ARES_HEADER_SOURCES ${ARES_HEADER_SOURCES} PARENT_SCOPE)
|
||||
endmacro()
|
||||
|
||||
list(TRANSFORM ARES_CORES STRIP)
|
||||
|
||||
if(a26 IN_LIST ARES_CORES)
|
||||
enable_core("Atari 2600")
|
||||
add_subdirectory(a26)
|
||||
else()
|
||||
disable_core("Atari 2600")
|
||||
endif()
|
||||
|
||||
if(fc IN_LIST ARES_CORES)
|
||||
enable_core("NES / Famicom")
|
||||
add_subdirectory(fc)
|
||||
else()
|
||||
disable_core("NES / Famicom")
|
||||
endif()
|
||||
|
||||
if(sfc IN_LIST ARES_CORES)
|
||||
enable_core("SNES / Super Famicom")
|
||||
add_subdirectory(sfc)
|
||||
else()
|
||||
disable_core("SNES / Super Famicom")
|
||||
endif()
|
||||
|
||||
if(n64 IN_LIST ARES_CORES)
|
||||
enable_core("Nintendo 64")
|
||||
add_subdirectory(n64)
|
||||
else()
|
||||
disable_core("Nintendo 64")
|
||||
endif()
|
||||
|
||||
if(sg IN_LIST ARES_CORES)
|
||||
enable_core("Sega SG-1000")
|
||||
add_subdirectory(sg)
|
||||
else()
|
||||
disable_core("Sega SG-1000")
|
||||
endif()
|
||||
|
||||
if(ms IN_LIST ARES_CORES)
|
||||
enable_core("Sega Master System / Mark III")
|
||||
add_subdirectory(ms)
|
||||
else()
|
||||
disable_core("Sega Master System / Mark III")
|
||||
endif()
|
||||
|
||||
if(md IN_LIST ARES_CORES)
|
||||
enable_core("Sega Mega Drive / Genesis")
|
||||
add_subdirectory(md)
|
||||
else()
|
||||
disable_core("Sega Mega Drive / Genesis")
|
||||
endif()
|
||||
|
||||
if(saturn IN_LIST ARES_CORES)
|
||||
enable_core("Sega Saturn")
|
||||
add_subdirectory(saturn)
|
||||
else()
|
||||
disable_core("Sega Saturn")
|
||||
endif()
|
||||
|
||||
if(ps1 IN_LIST ARES_CORES)
|
||||
enable_core("PlayStation")
|
||||
add_subdirectory(ps1)
|
||||
else()
|
||||
disable_core("Playstation")
|
||||
endif()
|
||||
|
||||
if(pce IN_LIST ARES_CORES)
|
||||
enable_core("PC-Engine / TurboGrafx")
|
||||
add_subdirectory(pce)
|
||||
else()
|
||||
disable_core("PC-Engine / TurboGrafx")
|
||||
endif()
|
||||
|
||||
if(msx IN_LIST ARES_CORES)
|
||||
enable_core("Microsoft MSX")
|
||||
add_subdirectory(msx)
|
||||
else()
|
||||
disable_core("Microsoft MSX")
|
||||
endif()
|
||||
|
||||
if(cv IN_LIST ARES_CORES)
|
||||
enable_core("ColecoVision")
|
||||
add_subdirectory(cv)
|
||||
else()
|
||||
disable_core("ColecoVision")
|
||||
endif()
|
||||
|
||||
if(myvision IN_LIST ARES_CORES)
|
||||
enable_core("My Vision")
|
||||
add_subdirectory(myvision)
|
||||
else()
|
||||
disable_core("My Vision")
|
||||
endif()
|
||||
|
||||
if(gb IN_LIST ARES_CORES)
|
||||
enable_core("Game Boy / Game Boy Color")
|
||||
add_subdirectory(gb)
|
||||
else()
|
||||
disable_core("Game Boy / Game Boy Color")
|
||||
endif()
|
||||
|
||||
if(gba IN_LIST ARES_CORES)
|
||||
enable_core("Game Boy Advance")
|
||||
add_subdirectory(gba)
|
||||
else()
|
||||
disable_core("Game Boy Advance")
|
||||
endif()
|
||||
|
||||
if(ws IN_LIST ARES_CORES)
|
||||
enable_core("WonderSwan / WonderSwan Color")
|
||||
add_subdirectory(ws)
|
||||
else()
|
||||
disable_core("WonderSwan / WonderSwan Color")
|
||||
endif()
|
||||
|
||||
if(ng IN_LIST ARES_CORES)
|
||||
enable_core("Neo Geo (AES/MVS)")
|
||||
add_subdirectory(ng)
|
||||
else()
|
||||
disable_core("Neo Geo (AES/MVS)")
|
||||
endif()
|
||||
|
||||
if(ngp IN_LIST ARES_CORES)
|
||||
enable_core("Neo Geo Pocket / Neo Geo Pocket Color")
|
||||
add_subdirectory(ngp)
|
||||
else()
|
||||
disable_core("Neo Geo Pocket / Neo Geo Pocket Color")
|
||||
endif()
|
||||
|
||||
if(spec IN_LIST ARES_CORES)
|
||||
enable_core("ZX Spectrum")
|
||||
add_subdirectory(spec)
|
||||
else()
|
||||
disable_core("ZX Spectrum")
|
||||
endif()
|
||||
|
||||
add_subdirectory(component)
|
||||
|
||||
foreach(c IN LISTS ARES_CORES)
|
||||
# target_enable_feature(ares "${c} core" CORE_$<UPPER_CASE:${c}>)
|
||||
target_compile_definitions(ares PUBLIC CORE_$<UPPER_CASE:${c}>)
|
||||
endforeach()
|
||||
|
||||
get_target_property(ares_SOURCES ares SOURCES)
|
||||
|
||||
set_source_files_properties(
|
||||
ares
|
||||
ares/debug/debug.cpp
|
||||
ares/node/audio/stream.cpp
|
||||
ares/node/node.cpp
|
||||
ares/node/video/screen.cpp
|
||||
ares/node/video/sprite.cpp
|
||||
ares/scheduler/thread.cpp
|
||||
ares/scheduler/scheduler.cpp
|
||||
PROPERTIES HEADER_FILE_ONLY TRUE
|
||||
)
|
||||
|
||||
set_source_files_properties(
|
||||
n64/vulkan/parallel-rdp/vulkan/shader.cpp
|
||||
n64/vulkan/parallel-rdp/vulkan/descriptor_set.cpp
|
||||
n64/vulkan/parallel-rdp/vulkan/device.cpp
|
||||
n64/vulkan/parallel-rdp/vulkan/command_buffer.cpp
|
||||
n64/vulkan/parallel-rdp/vulkan/render_pass.cpp
|
||||
n64/vulkan/parallel-rdp/vulkan/context.cpp
|
||||
n64/vulkan/parallel-rdp/vulkan/memory_allocator.cpp
|
||||
n64/vulkan/parallel-rdp/vulkan/semaphore.cpp
|
||||
n64/vulkan/parallel-rdp/util/logging.cpp
|
||||
n64/vulkan/parallel-rdp/util/environment.cpp
|
||||
n64/vulkan/parallel-rdp/util/thread_name.cpp
|
||||
n64/vulkan/parallel-rdp/util/timer.cpp
|
||||
PROPERTIES SKIP_PRECOMPILE_HEADERS ON
|
||||
)
|
||||
|
||||
target_sources(ares PRIVATE cmake/os-macos.cmake cmake/os-windows.cmake cmake/os-linux.cmake)
|
||||
|
||||
set_source_files_properties(ares ${ARES_HEADER_SOURCES} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
set_source_files_properties(ares ares/ares.cpp ares/memory/fixed-allocator.cpp PROPERTIES HEADER_FILE_ONLY FALSE)
|
||||
|
||||
target_include_directories(ares INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${ares_SOURCES})
|
||||
@@ -1,108 +0,0 @@
|
||||
ifeq ($(platform),windows)
|
||||
options += $(call lib,uuid kernel32 user32 gdi32 comctl32 comdlg32 shell32)
|
||||
else ifeq ($(platform),macos)
|
||||
else ifneq ($(filter $(platform),linux bsd),)
|
||||
options += -Wl,-export-dynamic
|
||||
options += -lX11 -lXext
|
||||
else
|
||||
$(error "ares is a library and cannot be built directly.")
|
||||
endif
|
||||
|
||||
ares.objects := ares ares-fixed-allocator
|
||||
|
||||
$(object.path)/ares.o: $(ares.path)/ares/ares.cpp
|
||||
$(object.path)/ares-fixed-allocator.o: $(ares.path)/ares/memory/fixed-allocator.cpp
|
||||
|
||||
ifeq ($(vulkan),true)
|
||||
flags += -DVULKAN
|
||||
endif
|
||||
|
||||
ifeq ($(profile),accuracy)
|
||||
flags += -DPROFILE_ACCURACY
|
||||
endif
|
||||
|
||||
ifeq ($(profile),performance)
|
||||
flags += -DPROFILE_PERFORMANCE
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),a26),)
|
||||
include $(ares.path)/a26/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),fc),)
|
||||
include $(ares.path)/fc/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),sfc),)
|
||||
include $(ares.path)/sfc/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),n64),)
|
||||
include $(ares.path)/n64/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),sg),)
|
||||
include $(ares.path)/sg/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),ms),)
|
||||
include $(ares.path)/ms/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),md),)
|
||||
include $(ares.path)/md/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),saturn),)
|
||||
include $(ares.path)/saturn/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),ps1),)
|
||||
include $(ares.path)/ps1/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),pce),)
|
||||
include $(ares.path)/pce/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),msx),)
|
||||
include $(ares.path)/msx/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),cv),)
|
||||
include $(ares.path)/cv/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),myvision),)
|
||||
include $(ares.path)/myvision/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),gb),)
|
||||
include $(ares.path)/gb/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),gba),)
|
||||
include $(ares.path)/gba/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),ws),)
|
||||
include $(ares.path)/ws/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),ng),)
|
||||
include $(ares.path)/ng/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),ngp),)
|
||||
include $(ares.path)/ngp/GNUmakefile
|
||||
endif
|
||||
|
||||
ifneq ($(filter $(cores),spec),)
|
||||
include $(ares.path)/spec/GNUmakefile
|
||||
endif
|
||||
|
||||
include $(ares.path)/component/GNUmakefile
|
||||
|
||||
flags += $(foreach c,$(call strupper,$(cores)),-DCORE_$c)
|
||||
|
||||
ares.objects := $(ares.objects:%=$(object.path)/%.o)
|
||||
@@ -0,0 +1,98 @@
|
||||
ares_components(mos6502)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
a26
|
||||
UNITY #
|
||||
a26.cpp
|
||||
PRIMARY #
|
||||
system/system.cpp
|
||||
controller/controller.cpp
|
||||
cartridge/cartridge.cpp
|
||||
cpu/cpu.cpp
|
||||
tia/tia.cpp
|
||||
riot/riot.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
a26
|
||||
INCLUDED #
|
||||
a26.hpp
|
||||
CMakeLists.txt
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
a26
|
||||
INCLUDED #
|
||||
cartridge/cartridge.hpp
|
||||
cartridge/serialization.cpp
|
||||
cartridge/slot.cpp
|
||||
cartridge/slot.hpp
|
||||
cartridge/board/atari16k.cpp
|
||||
cartridge/board/atari32k.cpp
|
||||
cartridge/board/atari8k.cpp
|
||||
cartridge/board/board.cpp
|
||||
cartridge/board/board.hpp
|
||||
cartridge/board/commavid.cpp
|
||||
cartridge/board/linear.cpp
|
||||
cartridge/board/parker-bros.cpp
|
||||
cartridge/board/tigervision.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
a26
|
||||
INCLUDED #
|
||||
controller/controller.hpp
|
||||
controller/port.cpp
|
||||
controller/port.hpp
|
||||
controller/gamepad/gamepad.cpp
|
||||
controller/gamepad/gamepad.hpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
a26
|
||||
INCLUDED #
|
||||
cpu/cpu.hpp
|
||||
cpu/debugger.cpp
|
||||
cpu/memory.cpp
|
||||
cpu/serialization.cpp
|
||||
cpu/timing.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
a26
|
||||
INCLUDED #
|
||||
riot/io.cpp
|
||||
riot/riot.hpp
|
||||
riot/serialization.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
a26
|
||||
INCLUDED #
|
||||
system/controls.cpp
|
||||
system/serialization.cpp
|
||||
system/system.hpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
a26
|
||||
INCLUDED #
|
||||
tia/audio.cpp
|
||||
tia/ball.cpp
|
||||
tia/color.cpp
|
||||
tia/io.cpp
|
||||
tia/missile.cpp
|
||||
tia/player.cpp
|
||||
tia/playfield.cpp
|
||||
tia/serialization.cpp
|
||||
tia/tia.hpp
|
||||
tia/write-queue.cpp
|
||||
)
|
||||
@@ -1,15 +0,0 @@
|
||||
ares.components += mos6502
|
||||
|
||||
ares.objects += ares-a26-system
|
||||
ares.objects += ares-a26-controller
|
||||
ares.objects += ares-a26-cartridge
|
||||
ares.objects += ares-a26-cpu
|
||||
ares.objects += ares-a26-tia
|
||||
ares.objects += ares-a26-riot
|
||||
|
||||
$(object.path)/ares-a26-system.o: $(ares.path)/a26/system/system.cpp
|
||||
$(object.path)/ares-a26-controller.o: $(ares.path)/a26/controller/controller.cpp
|
||||
$(object.path)/ares-a26-cartridge.o: $(ares.path)/a26/cartridge/cartridge.cpp
|
||||
$(object.path)/ares-a26-cpu.o: $(ares.path)/a26/cpu/cpu.cpp
|
||||
$(object.path)/ares-a26-tia.o: $(ares.path)/a26/tia/tia.cpp
|
||||
$(object.path)/ares-a26-riot.o: $(ares.path)/a26/riot/riot.cpp
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
#include <a26/cartridge/cartridge.cpp>
|
||||
#include <a26/controller/controller.cpp>
|
||||
#include <a26/cpu/cpu.cpp>
|
||||
#include <a26/riot/riot.cpp>
|
||||
#include <a26/system/system.cpp>
|
||||
#include <a26/tia/tia.cpp>
|
||||
@@ -54,6 +54,7 @@ auto System::load(Node::System& root, string name) -> bool {
|
||||
}
|
||||
|
||||
node = Node::System::create(information.name);
|
||||
node->setAttribute("configuration", name);
|
||||
node->setGame({&System::game, this});
|
||||
node->setRun({&System::run, this});
|
||||
node->setPower({&System::power, this});
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
namespace ares {
|
||||
|
||||
Platform* platform = nullptr;
|
||||
bool _runAhead = false;
|
||||
atomic<bool> _runAhead = false;
|
||||
|
||||
const string Name = "ares";
|
||||
const string Version = "141";
|
||||
const string Copyright = "ares team, Near";
|
||||
const string Name = "@ARES_NAME@";
|
||||
const string Version = "@ARES_VERSION@";
|
||||
const string Copyright = "@ARES_LEGAL_COPYRIGHT_SHORT@";
|
||||
const string License = "ISC";
|
||||
const string LicenseURI = "https://opensource.org/licenses/ISC";
|
||||
const string Website = "ares-emu.net";
|
||||
const string WebsiteURI = "https://ares-emu.net/";
|
||||
const string Website = "@ARES_WEBSITE@";
|
||||
const string WebsiteURI = "https://@ARES_WEBSITE@/";
|
||||
const u32 SerializerSignature = 0x31545342; //"BST1" (little-endian)
|
||||
|
||||
}
|
||||
+14
-2
@@ -15,6 +15,7 @@
|
||||
#include <nall/endian.hpp>
|
||||
#include <nall/hashset.hpp>
|
||||
#include <nall/image.hpp>
|
||||
#include <nall/instruction-set.hpp>
|
||||
#include <nall/literals.hpp>
|
||||
#include <nall/priority-queue.hpp>
|
||||
#include <nall/queue.hpp>
|
||||
@@ -65,11 +66,23 @@ namespace ares {
|
||||
}
|
||||
}
|
||||
|
||||
extern bool _runAhead;
|
||||
extern atomic<bool> _runAhead;
|
||||
inline auto runAhead() -> bool { return _runAhead; }
|
||||
inline auto setRunAhead(bool runAhead) -> void { _runAhead = runAhead; }
|
||||
}
|
||||
|
||||
/// ares elects to use the reserved C++ `register` identifier liberally in a few different areas so that it can more
|
||||
/// freely describe hardware registers within emulated system components. This macro exists to prevent compilers
|
||||
/// exploding at the sight of the reserved identifier.
|
||||
///
|
||||
/// Perhaps unsurprisingly, this macro will conflict with certain system headers. MSVC headers will emit an error
|
||||
/// forbidding macroizing `register` if the identifier is defined, while the `clangarm64` system headers in MSYS2
|
||||
/// appear to try to make use of the obsolete keyword meaning of the identifier.
|
||||
///
|
||||
/// Defining this macro after all platform headers are included avoids these conflicts... for now. Removing this
|
||||
/// macro along with all uses of this identifier may inevitably become necessary in the future.
|
||||
#define register $register
|
||||
|
||||
#include <ares/types.hpp>
|
||||
#include <ares/random.hpp>
|
||||
#include <ares/debug/debug.hpp>
|
||||
@@ -78,4 +91,3 @@ namespace ares {
|
||||
#include <ares/memory/fixed-allocator.hpp>
|
||||
#include <ares/memory/readable.hpp>
|
||||
#include <ares/memory/writable.hpp>
|
||||
#include <ares/resource/resource.hpp>
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
namespace ares::Memory {
|
||||
|
||||
constexpr u32 fixedBufferSize = 128_MiB;
|
||||
constexpr u32 fixedBufferSize = 64_MiB;
|
||||
|
||||
#if defined(STATIC_ALLOCATION)
|
||||
u8 fixedBuffer[fixedBufferSize + 64_KiB];
|
||||
|
||||
@@ -24,6 +24,7 @@ Screen::~Screen() {
|
||||
}
|
||||
|
||||
auto Screen::main(uintptr_t) -> void {
|
||||
thread::setName("dev.ares.screen");
|
||||
while(!_kill) {
|
||||
unique_lock<mutex> lock(_frameMutex);
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ protected:
|
||||
f64 _luminance = 1.0;
|
||||
u32 _fillColor = 0;
|
||||
bool _colorBleed = false;
|
||||
bool _colorBleedWidth = 1;
|
||||
u32 _colorBleedWidth = 1;
|
||||
bool _interframeBlending = false;
|
||||
bool _overscan = true;
|
||||
u32 _rotation = 0; //counter-clockwise (90 = left, 270 = right)
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
build := stable
|
||||
nall.path := ../../../nall
|
||||
include $(nall.path)/GNUmakefile
|
||||
|
||||
all:
|
||||
sourcery resource.bml resource.cpp resource.hpp
|
||||
|
||||
clean:
|
||||
$(call delete,resource.cpp)
|
||||
$(call delete,resource.hpp)
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,34 +0,0 @@
|
||||
namespace Resource {
|
||||
namespace Ares {
|
||||
extern const unsigned char Icon1x[6562];
|
||||
extern const unsigned char Icon2x[9662];
|
||||
extern const unsigned char Logo1x[11533];
|
||||
extern const unsigned char Logo2x[18991];
|
||||
}
|
||||
namespace Sprite {
|
||||
namespace SuperFamicom {
|
||||
extern const unsigned char CrosshairBlue[332];
|
||||
extern const unsigned char CrosshairGreen[329];
|
||||
extern const unsigned char CrosshairRed[342];
|
||||
}
|
||||
namespace WonderSwan {
|
||||
extern const unsigned char Auxiliary0[117];
|
||||
extern const unsigned char Auxiliary1[134];
|
||||
extern const unsigned char Auxiliary2[136];
|
||||
extern const unsigned char Headphones[167];
|
||||
extern const unsigned char Initialized[136];
|
||||
extern const unsigned char LowBattery[144];
|
||||
extern const unsigned char Orientation0[148];
|
||||
extern const unsigned char Orientation1[150];
|
||||
extern const unsigned char PoweredOn[155];
|
||||
extern const unsigned char Sleeping[154];
|
||||
extern const unsigned char VolumeA0[129];
|
||||
extern const unsigned char VolumeA1[142];
|
||||
extern const unsigned char VolumeA2[146];
|
||||
extern const unsigned char VolumeB0[125];
|
||||
extern const unsigned char VolumeB1[137];
|
||||
extern const unsigned char VolumeB2[148];
|
||||
extern const unsigned char VolumeB3[153];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
target_link_options(ares PRIVATE LINKER:-export-dynamic)
|
||||
|
||||
target_sources(ares PRIVATE cmake/os-linux.cmake)
|
||||
@@ -0,0 +1 @@
|
||||
target_sources(ares PRIVATE cmake/os-macos.cmake)
|
||||
@@ -0,0 +1,5 @@
|
||||
target_link_libraries(
|
||||
ares
|
||||
PRIVATE uuid kernel32 user32 gdi32 comctl32 comdlg32 shell32
|
||||
)
|
||||
target_sources(ares PRIVATE cmake/os-windows.cmake)
|
||||
@@ -0,0 +1,481 @@
|
||||
list(REMOVE_DUPLICATES ares.components)
|
||||
|
||||
ares_add_sources(INCLUDED CMakeLists.txt)
|
||||
|
||||
macro(component_sources)
|
||||
set(options "")
|
||||
set(oneValueArgs COMPONENT PRIMARY)
|
||||
set(multiValueArgs INCLUDED)
|
||||
|
||||
cmake_parse_arguments(CPS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(${CPS_COMPONENT} IN_LIST ares.components)
|
||||
target_sources(ares PRIVATE ${CPS_PRIMARY})
|
||||
foreach(arg IN ITEMS ${CPS_INCLUDED})
|
||||
list(APPEND ARES_HEADER_SOURCES "component/${arg}")
|
||||
target_sources(ares PRIVATE ${arg})
|
||||
endforeach()
|
||||
endif()
|
||||
set(ARES_HEADER_SOURCES ${ARES_HEADER_SOURCES} PARENT_SCOPE)
|
||||
endmacro()
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
ay38910
|
||||
PRIMARY
|
||||
audio/ay38910/ay38910.cpp
|
||||
INCLUDED
|
||||
audio/ay38910/ay38910.hpp
|
||||
audio/ay38910/serialization.cpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
msm5205
|
||||
PRIMARY
|
||||
audio/msm5205/msm5205.cpp
|
||||
INCLUDED
|
||||
audio/msm5205/msm5205.hpp
|
||||
audio/msm5205/serialization.cpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
sn76489
|
||||
PRIMARY
|
||||
audio/sn76489/sn76489.cpp
|
||||
INCLUDED
|
||||
audio/sn76489/sn76489.hpp
|
||||
audio/sn76489/serialization.cpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
t6w28
|
||||
PRIMARY
|
||||
audio/t6w28/t6w28.cpp
|
||||
INCLUDED
|
||||
audio/t6w28/t6w28.hpp
|
||||
audio/t6w28/serialization.cpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
ym2149
|
||||
PRIMARY
|
||||
audio/ym2149/ym2149.cpp
|
||||
INCLUDED
|
||||
audio/ym2149/ym2149.hpp
|
||||
audio/ym2149/serialization.cpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
ym2413
|
||||
PRIMARY
|
||||
audio/ym2413/ym2413.cpp
|
||||
INCLUDED
|
||||
audio/ym2413/constants.cpp
|
||||
audio/ym2413/io.cpp
|
||||
audio/ym2413/operator.cpp
|
||||
audio/ym2413/serialization.cpp
|
||||
audio/ym2413/voice.cpp
|
||||
audio/ym2413/ym2413.hpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
ym2612
|
||||
PRIMARY
|
||||
audio/ym2612/ym2612.cpp
|
||||
INCLUDED
|
||||
audio/ym2612/channel.cpp
|
||||
audio/ym2612/constants.cpp
|
||||
audio/ym2612/io.cpp
|
||||
audio/ym2612/serialization.cpp
|
||||
audio/ym2612/timer.cpp
|
||||
audio/ym2612/ym2612.hpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
m24c
|
||||
PRIMARY
|
||||
eeprom/m24c/m24c.cpp
|
||||
INCLUDED
|
||||
eeprom/m24c/m24c.hpp
|
||||
eeprom/m24c/serialization.cpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
m93lcx6
|
||||
PRIMARY
|
||||
eeprom/m93lcx6/m93lcx6.cpp
|
||||
INCLUDED
|
||||
eeprom/m93lcx6/m93lcx6.hpp
|
||||
eeprom/m93lcx6/serialization.cpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
i8255
|
||||
PRIMARY
|
||||
io/i8255/i8255.cpp
|
||||
INCLUDED
|
||||
io/i8255/i8255.hpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
arm7tdmi
|
||||
PRIMARY
|
||||
processor/arm7tdmi/arm7tdmi.cpp
|
||||
INCLUDED
|
||||
processor/arm7tdmi/algorithms.cpp
|
||||
processor/arm7tdmi/arm7tdmi.hpp
|
||||
processor/arm7tdmi/disassembler.cpp
|
||||
processor/arm7tdmi/instruction.cpp
|
||||
processor/arm7tdmi/instructions-arm.cpp
|
||||
processor/arm7tdmi/instructions-thumb.cpp
|
||||
processor/arm7tdmi/memory.cpp
|
||||
processor/arm7tdmi/registers.cpp
|
||||
processor/arm7tdmi/serialization.cpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
gsu
|
||||
PRIMARY
|
||||
processor/gsu/gsu.cpp
|
||||
INCLUDED
|
||||
processor/gsu/disassembler.cpp
|
||||
processor/gsu/gsu.hpp
|
||||
processor/gsu/instruction.cpp
|
||||
processor/gsu/instructions.cpp
|
||||
processor/gsu/registers.hpp
|
||||
processor/gsu/serialization.cpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
hg51b
|
||||
PRIMARY
|
||||
processor/hg51b/hg51b.cpp
|
||||
INCLUDED
|
||||
processor/hg51b/disassembler.cpp
|
||||
processor/hg51b/hg51b.hpp
|
||||
processor/hg51b/instruction.cpp
|
||||
processor/hg51b/instructions.cpp
|
||||
processor/hg51b/registers.cpp
|
||||
processor/hg51b/serialization.cpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
huc6280
|
||||
PRIMARY
|
||||
processor/huc6280/huc6280.cpp
|
||||
INCLUDED
|
||||
processor/huc6280/algorithms.cpp
|
||||
processor/huc6280/disassembler.cpp
|
||||
processor/huc6280/huc6280.hpp
|
||||
processor/huc6280/instruction.cpp
|
||||
processor/huc6280/instructions.cpp
|
||||
processor/huc6280/memory.cpp
|
||||
processor/huc6280/serialization.cpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
i8080
|
||||
PRIMARY
|
||||
processor/i8080/i8080.cpp
|
||||
INCLUDED
|
||||
processor/i8080/algorithms.cpp
|
||||
processor/i8080/disassembler.cpp
|
||||
processor/i8080/i8080.hpp
|
||||
processor/i8080/instruction.cpp
|
||||
processor/i8080/instructions.cpp
|
||||
processor/i8080/memory.cpp
|
||||
processor/i8080/registers.hpp
|
||||
processor/i8080/serialization.cpp
|
||||
)
|
||||
component_sources(
|
||||
COMPONENT
|
||||
m68hc05
|
||||
PRIMARY
|
||||
processor/m68hc05/m68hc05.cpp
|
||||
INCLUDED
|
||||
processor/m68hc05/algorithms.cpp
|
||||
processor/m68hc05/disassembler.cpp
|
||||
processor/m68hc05/instruction.cpp
|
||||
processor/m68hc05/instructions.cpp
|
||||
processor/m68hc05/m68hc05.hpp
|
||||
processor/m68hc05/memory.cpp
|
||||
processor/m68hc05/serialization.cpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
m68000
|
||||
PRIMARY
|
||||
processor/m68000/m68000.cpp
|
||||
INCLUDED
|
||||
processor/m68000/algorithms.cpp
|
||||
processor/m68000/conditions.cpp
|
||||
processor/m68000/disassembler.cpp
|
||||
processor/m68000/effective-address.cpp
|
||||
processor/m68000/instruction.cpp
|
||||
processor/m68000/instructions.cpp
|
||||
processor/m68000/m68000.hpp
|
||||
processor/m68000/memory.cpp
|
||||
processor/m68000/registers.cpp
|
||||
processor/m68000/serialization.cpp
|
||||
processor/m68000/traits.cpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
mos6502
|
||||
PRIMARY
|
||||
processor/mos6502/mos6502.cpp
|
||||
INCLUDED
|
||||
processor/mos6502/addresses.cpp
|
||||
processor/mos6502/algorithms.cpp
|
||||
processor/mos6502/disassembler.cpp
|
||||
processor/mos6502/instruction.cpp
|
||||
processor/mos6502/instructions.cpp
|
||||
processor/mos6502/memory.cpp
|
||||
processor/mos6502/mos6502.hpp
|
||||
processor/mos6502/serialization.cpp
|
||||
)
|
||||
component_sources(
|
||||
COMPONENT
|
||||
sh2
|
||||
PRIMARY
|
||||
processor/sh2/sh2.cpp
|
||||
INCLUDED
|
||||
processor/sh2/accuracy.hpp
|
||||
processor/sh2/decoder.hpp
|
||||
processor/sh2/disassembler.cpp
|
||||
processor/sh2/exceptions.cpp
|
||||
processor/sh2/instruction.cpp
|
||||
processor/sh2/instructions.cpp
|
||||
processor/sh2/recompiler.cpp
|
||||
processor/sh2/serialization.cpp
|
||||
processor/sh2/sh2.hpp
|
||||
processor/sh2/sh7604/bus.cpp
|
||||
processor/sh2/sh7604/cache.cpp
|
||||
processor/sh2/sh7604/dma.cpp
|
||||
processor/sh2/sh7604/interrupts.cpp
|
||||
processor/sh2/sh7604/io.cpp
|
||||
processor/sh2/sh7604/serial.cpp
|
||||
processor/sh2/sh7604/sh7604.cpp
|
||||
processor/sh2/sh7604/sh7604.hpp
|
||||
processor/sh2/sh7604/timer.cpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
sm5k
|
||||
PRIMARY
|
||||
processor/sm5k/sm5k.cpp
|
||||
INCLUDED
|
||||
processor/sm5k/disassembler.cpp
|
||||
processor/sm5k/instruction.cpp
|
||||
processor/sm5k/instructions.cpp
|
||||
processor/sm5k/memory.cpp
|
||||
processor/sm5k/serialization.cpp
|
||||
processor/sm5k/sm5k.hpp
|
||||
processor/sm5k/timer.cpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
sm83
|
||||
PRIMARY
|
||||
processor/sm83/sm83.cpp
|
||||
INCLUDED
|
||||
processor/sm83/algorithms.cpp
|
||||
processor/sm83/disassembler.cpp
|
||||
processor/sm83/instruction.cpp
|
||||
processor/sm83/instructions.cpp
|
||||
processor/sm83/memory.cpp
|
||||
processor/sm83/registers.hpp
|
||||
processor/sm83/serialization.cpp
|
||||
processor/sm83/sm83.hpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
spc700
|
||||
PRIMARY
|
||||
processor/spc700/spc700.cpp
|
||||
INCLUDED
|
||||
processor/spc700/algorithms.cpp
|
||||
processor/spc700/disassembler.cpp
|
||||
processor/spc700/instruction.cpp
|
||||
processor/spc700/instructions.cpp
|
||||
processor/spc700/memory.cpp
|
||||
processor/spc700/serialization.cpp
|
||||
processor/spc700/spc700.hpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
ssp1601
|
||||
PRIMARY
|
||||
processor/ssp1601/ssp1601.cpp
|
||||
INCLUDED
|
||||
processor/ssp1601/algorithms.cpp
|
||||
processor/ssp1601/disassembler.cpp
|
||||
processor/ssp1601/instructions.cpp
|
||||
processor/ssp1601/memory.cpp
|
||||
processor/ssp1601/registers.cpp
|
||||
processor/ssp1601/serialization.cpp
|
||||
processor/ssp1601/ssp1601.hpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
tlcs900h
|
||||
PRIMARY
|
||||
processor/tlcs900h/tlcs900h.cpp
|
||||
INCLUDED
|
||||
processor/tlcs900h/algorithms.cpp
|
||||
processor/tlcs900h/conditions.cpp
|
||||
processor/tlcs900h/control-registers.cpp
|
||||
processor/tlcs900h/disassembler.cpp
|
||||
processor/tlcs900h/dma.cpp
|
||||
processor/tlcs900h/instruction.cpp
|
||||
processor/tlcs900h/instructions.cpp
|
||||
processor/tlcs900h/memory.cpp
|
||||
processor/tlcs900h/prefetch.cpp
|
||||
processor/tlcs900h/registers.cpp
|
||||
processor/tlcs900h/serialization.cpp
|
||||
processor/tlcs900h/tlcs900h.hpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
upd96050
|
||||
PRIMARY
|
||||
processor/upd96050/upd96050.cpp
|
||||
INCLUDED
|
||||
processor/upd96050/disassembler.cpp
|
||||
processor/upd96050/instructions.cpp
|
||||
processor/upd96050/memory.cpp
|
||||
processor/upd96050/serialization.cpp
|
||||
processor/upd96050/upd96050.hpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
v30mz
|
||||
PRIMARY
|
||||
processor/v30mz/v30mz.cpp
|
||||
INCLUDED
|
||||
processor/v30mz/algorithms.cpp
|
||||
processor/v30mz/disassembler.cpp
|
||||
processor/v30mz/instruction.cpp
|
||||
processor/v30mz/instructions-adjust.cpp
|
||||
processor/v30mz/instructions-alu.cpp
|
||||
processor/v30mz/instructions-exec.cpp
|
||||
processor/v30mz/instructions-flag.cpp
|
||||
processor/v30mz/instructions-group.cpp
|
||||
processor/v30mz/instructions-misc.cpp
|
||||
processor/v30mz/instructions-move.cpp
|
||||
processor/v30mz/instructions-string.cpp
|
||||
processor/v30mz/memory.cpp
|
||||
processor/v30mz/modrm.cpp
|
||||
processor/v30mz/prefetch.cpp
|
||||
processor/v30mz/registers.cpp
|
||||
processor/v30mz/serialization.cpp
|
||||
processor/v30mz/v30mz.hpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
wdc65816
|
||||
PRIMARY
|
||||
processor/wdc65816/wdc65816.cpp
|
||||
INCLUDED
|
||||
processor/wdc65816/algorithms.cpp
|
||||
processor/wdc65816/disassembler.cpp
|
||||
processor/wdc65816/instruction.cpp
|
||||
processor/wdc65816/instruction.hpp
|
||||
processor/wdc65816/instructions-modify.cpp
|
||||
processor/wdc65816/instructions-other.cpp
|
||||
processor/wdc65816/instructions-pc.cpp
|
||||
processor/wdc65816/instructions-read.cpp
|
||||
processor/wdc65816/instructions-write.cpp
|
||||
processor/wdc65816/memory.cpp
|
||||
processor/wdc65816/registers.hpp
|
||||
processor/wdc65816/serialization.cpp
|
||||
processor/wdc65816/wdc65816.hpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
z80
|
||||
PRIMARY
|
||||
processor/z80/z80.cpp
|
||||
INCLUDED
|
||||
processor/z80/algorithms.cpp
|
||||
processor/z80/disassembler.cpp
|
||||
processor/z80/instruction.cpp
|
||||
processor/z80/instructions.cpp
|
||||
processor/z80/memory.cpp
|
||||
processor/z80/registers.hpp
|
||||
processor/z80/serialization.cpp
|
||||
processor/z80/z80.hpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
s3511a
|
||||
PRIMARY
|
||||
rtc/s3511a/s3511a.cpp
|
||||
INCLUDED
|
||||
rtc/s3511a/s3511a.hpp
|
||||
rtc/s3511a/serialization.cpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
sst39sf0x0
|
||||
PRIMARY
|
||||
flash/sst39sf0x0/sst39sf0x0.cpp
|
||||
INCLUDED
|
||||
flash/sst39sf0x0/sst39sf0x0.hpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
tms9918
|
||||
PRIMARY
|
||||
video/tms9918/tms9918.cpp
|
||||
INCLUDED
|
||||
video/tms9918/background.cpp
|
||||
video/tms9918/dac.cpp
|
||||
video/tms9918/io.cpp
|
||||
video/tms9918/serialization.cpp
|
||||
video/tms9918/sprite.cpp
|
||||
video/tms9918/tms9918.hpp
|
||||
)
|
||||
|
||||
component_sources(
|
||||
COMPONENT
|
||||
v9938
|
||||
PRIMARY
|
||||
video/v9938/v9938.cpp
|
||||
INCLUDED
|
||||
video/v9938/background.cpp
|
||||
video/v9938/commands.cpp
|
||||
video/v9938/dac.cpp
|
||||
video/v9938/io.cpp
|
||||
video/v9938/serialization.cpp
|
||||
video/v9938/sprite.cpp
|
||||
video/v9938/v9938.hpp
|
||||
)
|
||||
@@ -1,76 +0,0 @@
|
||||
ares.components := $(call unique,$(ares.components))
|
||||
|
||||
ares.objects += $(if $(findstring ay38910,$(ares.components)),ares-audio-ay38910)
|
||||
ares.objects += $(if $(findstring msm5205,$(ares.components)),ares-audio-msm5205)
|
||||
ares.objects += $(if $(findstring sn76489,$(ares.components)),ares-audio-sn76489)
|
||||
ares.objects += $(if $(findstring t6w28,$(ares.components)),ares-audio-t6w28)
|
||||
ares.objects += $(if $(findstring ym2149,$(ares.components)),ares-audio-ym2149)
|
||||
ares.objects += $(if $(findstring ym2413,$(ares.components)),ares-audio-ym2413)
|
||||
ares.objects += $(if $(findstring ym2610,$(ares.components)),ares-audio-ym2610)
|
||||
ares.objects += $(if $(findstring ym2612,$(ares.components)),ares-audio-ym2612)
|
||||
|
||||
ares.objects += $(if $(findstring m24c,$(ares.components)),ares-eeprom-m24c)
|
||||
ares.objects += $(if $(findstring m93lcx6,$(ares.components)),ares-eeprom-m93lcx6)
|
||||
|
||||
ares.objects += $(if $(findstring i8255,$(ares.components)),ares-io-i8255)
|
||||
|
||||
ares.objects += $(if $(findstring arm7tdmi,$(ares.components)),ares-processor-arm7tdmi)
|
||||
ares.objects += $(if $(findstring gsu,$(ares.components)),ares-processor-gsu)
|
||||
ares.objects += $(if $(findstring hg51b,$(ares.components)),ares-processor-hg51b)
|
||||
ares.objects += $(if $(findstring huc6280,$(ares.components)),ares-processor-huc6280)
|
||||
ares.objects += $(if $(findstring i8080,$(ares.components)),ares-processor-i8080)
|
||||
ares.objects += $(if $(findstring m68hc05,$(ares.components)),ares-processor-m68hc05)
|
||||
ares.objects += $(if $(findstring m68000,$(ares.components)),ares-processor-m68000)
|
||||
ares.objects += $(if $(findstring mos6502,$(ares.components)),ares-processor-mos6502)
|
||||
ares.objects += $(if $(findstring sh2,$(ares.components)),ares-processor-sh2)
|
||||
ares.objects += $(if $(findstring sm5k,$(ares.components)),ares-processor-sm5k)
|
||||
ares.objects += $(if $(findstring sm83,$(ares.components)),ares-processor-sm83)
|
||||
ares.objects += $(if $(findstring spc700,$(ares.components)),ares-processor-spc700)
|
||||
ares.objects += $(if $(findstring ssp1601,$(ares.components)),ares-processor-ssp1601)
|
||||
ares.objects += $(if $(findstring tlcs900h,$(ares.components)),ares-processor-tlcs900h)
|
||||
ares.objects += $(if $(findstring upd96050,$(ares.components)),ares-processor-upd96050)
|
||||
ares.objects += $(if $(findstring v30mz,$(ares.components)),ares-processor-v30mz)
|
||||
ares.objects += $(if $(findstring wdc65816,$(ares.components)),ares-processor-wdc65816)
|
||||
ares.objects += $(if $(findstring z80,$(ares.components)),ares-processor-z80)
|
||||
|
||||
ares.objects += $(if $(findstring sst39sf0x0,$(ares.components)),ares-flash-sst39sf0x0)
|
||||
|
||||
ares.objects += $(if $(findstring tms9918,$(ares.components)),ares-video-tms9918)
|
||||
ares.objects += $(if $(findstring v9938,$(ares.components)),ares-video-v9938)
|
||||
|
||||
$(object.path)/ares-audio-ay38910.o: $(ares.path)/component/audio/ay38910/ay38910.cpp
|
||||
$(object.path)/ares-audio-msm5205.o: $(ares.path)/component/audio/msm5205/msm5205.cpp
|
||||
$(object.path)/ares-audio-sn76489.o: $(ares.path)/component/audio/sn76489/sn76489.cpp
|
||||
$(object.path)/ares-audio-t6w28.o: $(ares.path)/component/audio/t6w28/t6w28.cpp
|
||||
$(object.path)/ares-audio-ym2149.o: $(ares.path)/component/audio/ym2149/ym2149.cpp
|
||||
$(object.path)/ares-audio-ym2413.o: $(ares.path)/component/audio/ym2413/ym2413.cpp
|
||||
$(object.path)/ares-audio-ym2612.o: $(ares.path)/component/audio/ym2612/ym2612.cpp
|
||||
|
||||
$(object.path)/ares-eeprom-m24c.o: $(ares.path)/component/eeprom/m24c/m24c.cpp
|
||||
$(object.path)/ares-eeprom-m93lcx6.o: $(ares.path)/component/eeprom/m93lcx6/m93lcx6.cpp
|
||||
|
||||
$(object.path)/ares-io-i8255.o: $(ares.path)/component/io/i8255/i8255.cpp
|
||||
|
||||
$(object.path)/ares-processor-arm7tdmi.o: $(ares.path)/component/processor/arm7tdmi/arm7tdmi.cpp
|
||||
$(object.path)/ares-processor-gsu.o: $(ares.path)/component/processor/gsu/gsu.cpp
|
||||
$(object.path)/ares-processor-hg51b.o: $(ares.path)/component/processor/hg51b/hg51b.cpp
|
||||
$(object.path)/ares-processor-huc6280.o: $(ares.path)/component/processor/huc6280/huc6280.cpp
|
||||
$(object.path)/ares-processor-i8080.o: $(ares.path)/component/processor/i8080/i8080.cpp
|
||||
$(object.path)/ares-processor-m68hc05.o: $(ares.path)/component/processor/m68hc05/m68hc05.cpp
|
||||
$(object.path)/ares-processor-m68000.o: $(ares.path)/component/processor/m68000/m68000.cpp
|
||||
$(object.path)/ares-processor-mos6502.o: $(ares.path)/component/processor/mos6502/mos6502.cpp
|
||||
$(object.path)/ares-processor-sh2.o: $(ares.path)/component/processor/sh2/sh2.cpp
|
||||
$(object.path)/ares-processor-sm5k.o: $(ares.path)/component/processor/sm5k/sm5k.cpp
|
||||
$(object.path)/ares-processor-sm83.o: $(ares.path)/component/processor/sm83/sm83.cpp
|
||||
$(object.path)/ares-processor-spc700.o: $(ares.path)/component/processor/spc700/spc700.cpp
|
||||
$(object.path)/ares-processor-ssp1601.o: $(ares.path)/component/processor/ssp1601/ssp1601.cpp
|
||||
$(object.path)/ares-processor-tlcs900h.o: $(ares.path)/component/processor/tlcs900h/tlcs900h.cpp
|
||||
$(object.path)/ares-processor-upd96050.o: $(ares.path)/component/processor/upd96050/upd96050.cpp
|
||||
$(object.path)/ares-processor-v30mz.o: $(ares.path)/component/processor/v30mz/v30mz.cpp
|
||||
$(object.path)/ares-processor-wdc65816.o: $(ares.path)/component/processor/wdc65816/wdc65816.cpp
|
||||
$(object.path)/ares-processor-z80.o: $(ares.path)/component/processor/z80/z80.cpp
|
||||
|
||||
$(object.path)/ares-flash-sst39sf0x0.o: $(ares.path)/component/flash/sst39sf0x0/sst39sf0x0.cpp
|
||||
|
||||
$(object.path)/ares-video-tms9918.o: $(ares.path)/component/video/tms9918/tms9918.cpp
|
||||
$(object.path)/ares-video-v9938.o: $(ares.path)/component/video/v9938/v9938.cpp
|
||||
@@ -29,24 +29,25 @@ auto YM2612::Channel::Operator::updateKeyState() -> void {
|
||||
auto YM2612::Channel::Operator::runEnvelope() -> void {
|
||||
if(ym2612.envelope.clock & (1 << envelope.divider) - 1) return;
|
||||
|
||||
if(envelope.state == Attack && envelope.value == 0) {
|
||||
envelope.state = Decay;
|
||||
updateEnvelope();
|
||||
}
|
||||
|
||||
u32 sustain = envelope.sustainLevel < 15 ? envelope.sustainLevel << 5 : 0x1f << 5;
|
||||
if(envelope.state == Decay && envelope.value >= sustain) {
|
||||
envelope.state = Sustain;
|
||||
updateEnvelope();
|
||||
}
|
||||
|
||||
u32 value = ym2612.envelope.clock >> envelope.divider;
|
||||
u32 step = envelope.steps >> ((~value & 7) << 2) & 0xf;
|
||||
u32 sustain = envelope.sustainLevel < 15 ? envelope.sustainLevel << 5 : 0x1f << 5;
|
||||
|
||||
if(envelope.state == Attack) {
|
||||
if(envelope.value == 0) {
|
||||
envelope.state = Decay;
|
||||
updateEnvelope();
|
||||
} else if(envelope.rate < 62) {
|
||||
// will stop updating if attack rate is increased to upper threshold during attack phase (confirmed behavior)
|
||||
envelope.value += ~u16(envelope.value) * step >> 4;
|
||||
}
|
||||
// will stop updating if attack rate is increased to upper threshold during attack phase (confirmed behavior)
|
||||
if(envelope.rate < 62) envelope.value += ~u16(envelope.value) * step >> 4;
|
||||
}
|
||||
if(envelope.state != Attack) {
|
||||
if(envelope.state == Decay && envelope.value >= sustain) {
|
||||
envelope.state = Sustain;
|
||||
updateEnvelope();
|
||||
}
|
||||
if(ssg.enable) step = envelope.value < 0x200 ? step << 2 : 0; //SSG results in a 4x faster envelope
|
||||
envelope.value = min(envelope.value + step, 0x3ff);
|
||||
}
|
||||
@@ -82,8 +83,6 @@ auto YM2612::Channel::Operator::runPhase() -> void {
|
||||
}
|
||||
|
||||
auto YM2612::Channel::Operator::updateEnvelope() -> void {
|
||||
u32 key = min(max((u32)pitch.value, 0x300), 0x4ff);
|
||||
u32 ksr = (octave.value << 2) + ((key - 0x300) >> 7);
|
||||
u32 rate = 0;
|
||||
|
||||
if(envelope.state == Attack) rate += (envelope.attackRate << 1);
|
||||
@@ -91,7 +90,7 @@ auto YM2612::Channel::Operator::updateEnvelope() -> void {
|
||||
if(envelope.state == Sustain) rate += (envelope.sustainRate << 1);
|
||||
if(envelope.state == Release) rate += (envelope.releaseRate << 1);
|
||||
|
||||
rate += (ksr >> 3 - envelope.keyScale) * (rate > 0);
|
||||
rate += (keyScale >> 3 - envelope.rateScaling) * (rate > 0);
|
||||
rate = min(rate, 63);
|
||||
|
||||
auto& entry = envelopeRates[rate >> 2];
|
||||
@@ -107,15 +106,15 @@ auto YM2612::Channel::Operator::updatePitch() -> void {
|
||||
pitch.value = channel.mode ? pitch.reload : channel[3].pitch.reload;
|
||||
octave.value = channel.mode ? octave.reload : channel[3].octave.reload;
|
||||
|
||||
u32 key = min(max((u32)pitch.value, 0x300), 0x4ff);
|
||||
keyScale = (octave.value << 2) + ((key - 0x300) >> 7);
|
||||
|
||||
updatePhase();
|
||||
updateEnvelope(); //due to key scaling
|
||||
}
|
||||
|
||||
auto YM2612::Channel::Operator::updatePhase() -> void {
|
||||
u32 key = min(max((u32)pitch.value, 0x300), 0x4ff);
|
||||
u32 ksr = (octave.value << 2) + ((key - 0x300) >> 7);
|
||||
u32 tuning = detune & 3 ? detunes[(detune & 3) - 1][ksr & 7] >> (3 - (ksr >> 3)) : 0;
|
||||
|
||||
u32 tuning = detune & 3 ? detunes[(detune & 3) - 1][keyScale & 7] >> (3 - (keyScale >> 3)) : 0;
|
||||
u32 lfo = ym2612.lfo.clock >> 2 & 0x1f;
|
||||
s32 pm = (pitch.value * vibratos[channel.vibrato][lfo & 15] >> 9) * (lfo > 15 ? -1 : 1);
|
||||
|
||||
@@ -126,12 +125,12 @@ auto YM2612::Channel::Operator::updatePhase() -> void {
|
||||
|
||||
auto YM2612::Channel::Operator::updateLevel() -> void {
|
||||
u32 lfo = ym2612.lfo.clock & 0x40 ? ym2612.lfo.clock & 0x3f : ~ym2612.lfo.clock & 0x3f;
|
||||
u32 depth = tremolos[channel.tremolo];
|
||||
u32 depth = tremolos[tremoloEnable * channel.tremolo];
|
||||
|
||||
bool invert = ssg.attack != ssg.invert && envelope.state != Release;
|
||||
n10 value = ssg.enable && invert ? 0x200 - envelope.value : 0 + envelope.value;
|
||||
|
||||
outputLevel = ((totalLevel << 3) + value + (lfoEnable ? lfo << 1 >> depth : 0)) << 3;
|
||||
outputLevel = (totalLevel << 3) + value + (lfo << 1 >> depth) << 3;
|
||||
}
|
||||
|
||||
auto YM2612::Channel::power() -> void {
|
||||
@@ -148,7 +147,8 @@ auto YM2612::Channel::power() -> void {
|
||||
for(auto& op : operators) {
|
||||
op.keyOn = 0;
|
||||
op.keyLine = 0;
|
||||
op.lfoEnable = 0;
|
||||
op.tremoloEnable = 0;
|
||||
op.keyScale = 0;
|
||||
op.detune = 0;
|
||||
op.multiple = 0;
|
||||
op.totalLevel = 0;
|
||||
@@ -175,7 +175,7 @@ auto YM2612::Channel::power() -> void {
|
||||
op.envelope.steps = 0;
|
||||
op.envelope.value = 0x3ff;
|
||||
|
||||
op.envelope.keyScale = 0;
|
||||
op.envelope.rateScaling = 0;
|
||||
op.envelope.attackRate = 0;
|
||||
op.envelope.decayRate = 0;
|
||||
op.envelope.sustainRate = 0;
|
||||
|
||||
@@ -14,8 +14,10 @@ auto YM2612::writeData(n8 data) -> void {
|
||||
case 0x022: {
|
||||
lfo.rate = data.bit(0,2);
|
||||
lfo.enable = data.bit(3);
|
||||
lfo.clock = 0;
|
||||
lfo.divider = 0;
|
||||
if(!lfo.enable) {
|
||||
lfo.clock = 0;
|
||||
lfo.divider = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -34,18 +36,14 @@ auto YM2612::writeData(n8 data) -> void {
|
||||
//timer B period
|
||||
case 0x026: {
|
||||
timerB.period.bit(0,7) = data.bit(0,7);
|
||||
// Not sure if this is the right place for it, but...
|
||||
// handle a specific use case to reset the subticks on timer B
|
||||
if(!timerB.enable) timerB.divider = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
//timer control
|
||||
case 0x027: {
|
||||
//reload period on 0->1 transition
|
||||
if(!timerA.enable && data.bit(0)) timerA.counter = timerA.period;
|
||||
if(!timerB.enable && data.bit(1)) {
|
||||
timerB.counter = timerB.period;
|
||||
timerB.divider = 0;
|
||||
}
|
||||
|
||||
timerA.enable = data.bit(0);
|
||||
timerB.enable = data.bit(1);
|
||||
timerA.irq = data.bit(2);
|
||||
@@ -114,19 +112,19 @@ auto YM2612::writeData(n8 data) -> void {
|
||||
break;
|
||||
}
|
||||
|
||||
//key scaling, attack rate
|
||||
//rate scaling, attack rate
|
||||
case 0x050: {
|
||||
op.envelope.attackRate = data.bit(0,4);
|
||||
op.envelope.keyScale = data.bit(6,7);
|
||||
op.envelope.rateScaling = data.bit(6,7);
|
||||
channel[index].updateEnvelope();
|
||||
channel[index].updatePhase();
|
||||
break;
|
||||
}
|
||||
|
||||
//LFO enable, decay rate
|
||||
//LFO AM enable, decay rate
|
||||
case 0x060: {
|
||||
op.envelope.decayRate = data.bit(0,4);
|
||||
op.lfoEnable = data.bit(7);
|
||||
op.tremoloEnable = data.bit(7);
|
||||
channel[index].updateEnvelope();
|
||||
channel[index].updateLevel();
|
||||
break;
|
||||
|
||||
@@ -13,12 +13,14 @@ auto YM2612::serialize(serializer& s) -> void {
|
||||
s(envelope.divider);
|
||||
|
||||
s(timerA.enable);
|
||||
s(timerA.enableLatch);
|
||||
s(timerA.irq);
|
||||
s(timerA.line);
|
||||
s(timerA.period);
|
||||
s(timerA.counter);
|
||||
|
||||
s(timerB.enable);
|
||||
s(timerB.enableLatch);
|
||||
s(timerB.irq);
|
||||
s(timerB.line);
|
||||
s(timerB.period);
|
||||
@@ -43,7 +45,8 @@ auto YM2612::Channel::serialize(serializer& s) -> void {
|
||||
auto YM2612::Channel::Operator::serialize(serializer& s) -> void {
|
||||
s(keyOn);
|
||||
s(keyLine);
|
||||
s(lfoEnable);
|
||||
s(tremoloEnable);
|
||||
s(keyScale);
|
||||
s(detune);
|
||||
s(multiple);
|
||||
s(totalLevel);
|
||||
@@ -68,7 +71,7 @@ auto YM2612::Channel::Operator::serialize(serializer& s) -> void {
|
||||
s(envelope.divider);
|
||||
s(envelope.steps);
|
||||
s(envelope.value);
|
||||
s(envelope.keyScale);
|
||||
s(envelope.rateScaling);
|
||||
s(envelope.attackRate);
|
||||
s(envelope.decayRate);
|
||||
s(envelope.sustainRate);
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
auto YM2612::TimerA::run() -> void {
|
||||
if(!enable) return;
|
||||
if(++counter) return;
|
||||
|
||||
counter = period;
|
||||
line |= irq;
|
||||
if(!++counter)
|
||||
line |= irq & enableLatch;
|
||||
if(enableLatch < enable || !counter)
|
||||
counter = period;
|
||||
enableLatch = enable;
|
||||
}
|
||||
|
||||
auto YM2612::TimerB::run() -> void {
|
||||
if(!enable) return;
|
||||
if(++divider) return;
|
||||
if(++counter) return;
|
||||
|
||||
counter = period;
|
||||
line |= irq;
|
||||
if(!++divider && !++counter)
|
||||
line |= irq & enableLatch;
|
||||
if(enableLatch < enable || !counter && !divider)
|
||||
counter = period; // do not reset divider on reenable
|
||||
enableLatch = enable;
|
||||
}
|
||||
@@ -13,6 +13,25 @@ auto YM2612::clock() -> array<i16[2]> {
|
||||
s32 left = 0;
|
||||
s32 right = 0;
|
||||
|
||||
timerA.run();
|
||||
timerB.run();
|
||||
|
||||
if(++envelope.divider == 3) {
|
||||
envelope.divider = 0;
|
||||
if(!++envelope.clock) ++envelope.clock; // 12-bit counter: 1..4095 - zero-value is skipped (confirmed behavior)
|
||||
}
|
||||
|
||||
if(lfo.enable && ++lfo.divider >= lfoDividers[lfo.rate]) {
|
||||
lfo.divider = 0;
|
||||
lfo.clock++;
|
||||
for(auto& channel : channels) {
|
||||
for(auto& op : channel.operators) {
|
||||
op.updatePhase(); //due to vibrato
|
||||
op.updateLevel(); //due to tremolo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(auto& channel : channels) {
|
||||
auto& op = channel.operators;
|
||||
|
||||
@@ -30,12 +49,18 @@ auto YM2612::clock() -> array<i16[2]> {
|
||||
return y < 0x1a00 ? pow2[y & 0x1ff] << 2 >> (y >> 9) : 0; // -78 dB floor
|
||||
};
|
||||
|
||||
s32 feedback = modMask & op[0].prior + op[0].priorBuffer >> 9 - channel.feedback;
|
||||
s32 accumulator = 0;
|
||||
|
||||
op[0].priorBuffer = op[0].prior; // only need to buffer the output for feedback
|
||||
for(auto n : range(4)) op[n].prior = op[n].output;
|
||||
|
||||
for(auto& op : channel.operators) {
|
||||
op.runPhase();
|
||||
if(envelope.divider) continue;
|
||||
op.runEnvelope();
|
||||
}
|
||||
|
||||
s32 feedback = modMask & op[0].prior + op[0].priorBuffer >> 9 - channel.feedback;
|
||||
s32 accumulator = 0;
|
||||
|
||||
op[0].output = wave(0, feedback * (channel.feedback > 0));
|
||||
|
||||
// Note: Despite not emulating per cycle, operator pipelining has been accounted for.
|
||||
@@ -122,33 +147,6 @@ auto YM2612::clock() -> array<i16[2]> {
|
||||
//if(channel.rightEnable) right += voiceData;
|
||||
}
|
||||
|
||||
timerA.run();
|
||||
timerB.run();
|
||||
|
||||
if(lfo.enable && ++lfo.divider == lfoDividers[lfo.rate]) {
|
||||
lfo.divider = 0;
|
||||
lfo.clock++;
|
||||
for(auto& channel : channels) {
|
||||
for(auto& op : channel.operators) {
|
||||
op.updatePhase(); //due to vibrato
|
||||
op.updateLevel(); //due to tremolo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(++envelope.divider == 3) {
|
||||
envelope.divider = 0;
|
||||
if(!++envelope.clock) ++envelope.clock; // 12-bit counter: 1..4095 - zero-value is skipped (confirmed behavior)
|
||||
}
|
||||
|
||||
for(auto& channel : channels) {
|
||||
for(auto& op : channel.operators) {
|
||||
op.runPhase();
|
||||
if(envelope.divider) continue;
|
||||
op.runEnvelope();
|
||||
}
|
||||
}
|
||||
|
||||
return {sclamp<16>(left), sclamp<16>(right)};
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ protected:
|
||||
auto run() -> void;
|
||||
|
||||
n1 enable = 0;
|
||||
n1 enableLatch = 0;
|
||||
n1 irq = 0;
|
||||
n1 line = 0;
|
||||
n10 period = 0;
|
||||
@@ -56,6 +57,7 @@ protected:
|
||||
auto run() -> void;
|
||||
|
||||
n1 enable = 0;
|
||||
n1 enableLatch = 0;
|
||||
n1 irq = 0;
|
||||
n1 line = 0;
|
||||
n8 period = 0;
|
||||
@@ -106,7 +108,8 @@ protected:
|
||||
|
||||
n1 keyOn = 0;
|
||||
n1 keyLine = 0;
|
||||
n1 lfoEnable = 0;
|
||||
n1 tremoloEnable = 0;
|
||||
n5 keyScale = 0;
|
||||
n3 detune = 0;
|
||||
n4 multiple = 0;
|
||||
n7 totalLevel = 0;
|
||||
@@ -140,7 +143,7 @@ protected:
|
||||
n32 steps = 0;
|
||||
n10 value = 0x3ff;
|
||||
|
||||
n2 keyScale = 0;
|
||||
n2 rateScaling = 0;
|
||||
n5 attackRate = 0;
|
||||
n5 decayRate = 0;
|
||||
n5 sustainRate = 0;
|
||||
|
||||
@@ -9,7 +9,6 @@ namespace ares {
|
||||
io.portCHigherInput = 1;
|
||||
io.portAInput = 1;
|
||||
io.groupAMode = 0;
|
||||
io.ioMode = 0;
|
||||
state.portA = 0xff;
|
||||
state.portB = 0xff;
|
||||
state.portC = 0xff;
|
||||
@@ -43,15 +42,20 @@ namespace ares {
|
||||
}
|
||||
|
||||
auto I8255::writeControl(n8 data) -> void {
|
||||
if(data.bit(7) == 0) {
|
||||
n3 bitSelect = data.bit(1, 3);
|
||||
state.portC.bit(bitSelect) = data.bit(0);
|
||||
writePortC(state.portC);
|
||||
return;
|
||||
}
|
||||
|
||||
io.portCLowerInput = data.bit(0);
|
||||
io.portBInput = data.bit(1);
|
||||
io.groupBMode = data.bit(2);
|
||||
io.portCHigherInput = data.bit(3);
|
||||
io.portAInput = data.bit(4);
|
||||
io.groupAMode = data.bit(5,6);
|
||||
io.ioMode = data.bit(7);
|
||||
|
||||
if(!io.ioMode) debug(unimplemented, "[I8255] BSR Mode");
|
||||
if(io.groupAMode != 0) debug(unimplemented, "[I8255] Group A Mode != 0");
|
||||
if(io.groupBMode != 0) debug(unimplemented, "[I8255] Group B Mode != 0");
|
||||
}
|
||||
@@ -63,7 +67,6 @@ namespace ares {
|
||||
s(io.portCHigherInput);
|
||||
s(io.portAInput);
|
||||
s(io.groupAMode);
|
||||
s(io.ioMode);
|
||||
|
||||
s(state.portA);
|
||||
s(state.portB);
|
||||
|
||||
@@ -23,7 +23,6 @@ namespace ares {
|
||||
n1 portCHigherInput;
|
||||
n1 portAInput;
|
||||
n2 groupAMode;
|
||||
n1 ioMode;
|
||||
} io;
|
||||
|
||||
struct State {
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace ares {
|
||||
#include "instruction.cpp"
|
||||
#include "instructions-arm.cpp"
|
||||
#include "instructions-thumb.cpp"
|
||||
#include "coprocessor.cpp"
|
||||
#include "serialization.cpp"
|
||||
#include "disassembler.cpp"
|
||||
|
||||
@@ -19,7 +20,9 @@ ARM7TDMI::ARM7TDMI() {
|
||||
|
||||
auto ARM7TDMI::power() -> void {
|
||||
processor = {};
|
||||
processor.r15.modify = [&] { pipeline.reload = true; };
|
||||
processor.r15.modify = [&] { processor.r15.data &= ~1; pipeline.reload = true; };
|
||||
processor.rNULL.modify = [&] { processor.rNULL.data = 0; };
|
||||
processor.spsrNULL.readonly = true;
|
||||
pipeline = {};
|
||||
carry = 0;
|
||||
irq = 0;
|
||||
|
||||
@@ -6,15 +6,13 @@ namespace ares {
|
||||
|
||||
struct ARM7TDMI {
|
||||
enum : u32 {
|
||||
Nonsequential = 1 << 0, //N cycle
|
||||
Sequential = 1 << 1, //S cycle
|
||||
Load = 1 << 0, //load operation
|
||||
Store = 1 << 1, //store operation
|
||||
Prefetch = 1 << 2, //instruction fetch
|
||||
Byte = 1 << 3, // 8-bit access
|
||||
Half = 1 << 4, //16-bit access
|
||||
Word = 1 << 5, //32-bit access
|
||||
Load = 1 << 6, //load operation
|
||||
Store = 1 << 7, //store operation
|
||||
Signed = 1 << 8, //sign-extend
|
||||
Signed = 1 << 6, //sign-extend
|
||||
};
|
||||
|
||||
virtual auto step(u32 clocks) -> void = 0;
|
||||
@@ -22,6 +20,8 @@ struct ARM7TDMI {
|
||||
virtual auto get(u32 mode, n32 address) -> n32 = 0;
|
||||
virtual auto getDebugger(u32 mode, n32 address) -> n32 { return get(mode, address); }
|
||||
virtual auto set(u32 mode, n32 address, n32 word) -> void = 0;
|
||||
virtual auto lock() -> void { return; }
|
||||
virtual auto unlock() -> void { return; }
|
||||
|
||||
//arm7tdmi.cpp
|
||||
ARM7TDMI();
|
||||
@@ -42,6 +42,7 @@ struct ARM7TDMI {
|
||||
auto load(u32 mode, n32 address) -> n32;
|
||||
auto write(u32 mode, n32 address, n32 word) -> void;
|
||||
auto store(u32 mode, n32 address, n32 word) -> void;
|
||||
auto endBurst() -> void { nonsequential = true; return; }
|
||||
|
||||
//algorithms.cpp
|
||||
auto ADD(n32, n32, bool) -> n32;
|
||||
@@ -56,6 +57,7 @@ struct ARM7TDMI {
|
||||
auto TST(n4) -> bool;
|
||||
|
||||
//instruction.cpp
|
||||
auto reload() -> void;
|
||||
auto fetch() -> void;
|
||||
auto instruction() -> void;
|
||||
auto exception(u32 mode, n32 address) -> void;
|
||||
@@ -67,21 +69,25 @@ struct ARM7TDMI {
|
||||
auto armMoveToStatus(n4 field, n1 source, n32 data) -> void;
|
||||
|
||||
auto armInstructionBranch(i24, n1) -> void;
|
||||
auto armInstructionBranchExchangeRegister(n4) -> void;
|
||||
auto armInstructionBranchExchangeRegister(n4, n4, n4, n1) -> void;
|
||||
auto armInstructionCoprocessorDataProcessing(n4, n3, n4, n4, n4, n4) -> void;
|
||||
auto armInstructionDataImmediate(n8, n4, n4, n4, n1, n4) -> void;
|
||||
auto armInstructionDataImmediateShift(n4, n2, n5, n4, n4, n1, n4) -> void;
|
||||
auto armInstructionDataRegisterShift(n4, n2, n4, n4, n4, n1, n4) -> void;
|
||||
auto armInstructionLoadImmediate(n8, n1, n4, n4, n1, n1, n1) -> void;
|
||||
auto armInstructionLoadRegister(n4, n1, n4, n4, n1, n1, n1) -> void;
|
||||
auto armInstructionMemorySwap(n4, n4, n4, n1) -> void;
|
||||
auto armInstructionMoveHalfImmediate(n8, n4, n4, n1, n1, n1, n1) -> void;
|
||||
auto armInstructionMoveHalfRegister(n4, n4, n4, n1, n1, n1, n1) -> void;
|
||||
auto armInstructionMoveImmediateOffset(n12, n4, n4, n1, n1, n1, n1, n1) -> void;
|
||||
auto armInstructionMoveMultiple(n16, n4, n1, n1, n1, n1, n1) -> void;
|
||||
auto armInstructionMoveRegisterOffset(n4, n2, n5, n4, n4, n1, n1, n1, n1, n1) -> void;
|
||||
auto armInstructionMoveSignedImmediate(n8, n1, n4, n4, n1, n1, n1, n1) -> void;
|
||||
auto armInstructionMoveSignedRegister(n4, n1, n4, n4, n1, n1, n1, n1) -> void;
|
||||
auto armInstructionMoveToCoprocessorFromRegister(n4, n3, n4, n4, n4, n3) -> void;
|
||||
auto armInstructionMoveToRegisterFromCoprocessor(n4, n3, n4, n4, n4, n3) -> void;
|
||||
auto armInstructionMoveToRegisterFromRegister(n4, n4) -> void;
|
||||
auto armInstructionMoveToRegisterFromStatus(n4, n1) -> void;
|
||||
auto armInstructionMoveToStatusFromImmediate(n8, n4, n4, n1) -> void;
|
||||
auto armInstructionMoveToStatusFromRegister(n4, n4, n1) -> void;
|
||||
auto armInstructionMoveToStatusFromRegister(n4, n2, n5, n4, n1) -> void;
|
||||
auto armInstructionMultiply(n4, n4, n4, n4, n1, n1) -> void;
|
||||
auto armInstructionMultiplyLong(n4, n4, n4, n4, n1, n1, n1) -> void;
|
||||
auto armInstructionSoftwareInterrupt(n24 immediate) -> void;
|
||||
@@ -145,21 +151,31 @@ struct ARM7TDMI {
|
||||
};
|
||||
|
||||
operator u32() const {
|
||||
return m << 0 | t << 5 | f << 6 | i << 7 | v << 28 | c << 29 | z << 30 | n << 31;
|
||||
return m << 0 | 1 << 4 | t << 5 | f << 6 | i << 7 | v << 28 | c << 29 | z << 30 | n << 31;
|
||||
}
|
||||
|
||||
auto operator=(n32 data) -> PSR& {
|
||||
m = data.bit(0,4);
|
||||
t = data.bit(5);
|
||||
f = data.bit(6);
|
||||
i = data.bit(7);
|
||||
v = data.bit(28);
|
||||
c = data.bit(29);
|
||||
z = data.bit(30);
|
||||
n = data.bit(31);
|
||||
set(0b1111, data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto set(n4 field, n32 data) -> void {
|
||||
if(readonly) return;
|
||||
if(field.bit(0)) {
|
||||
m = data.bit(0,4) | 0x10;
|
||||
t = data.bit(5);
|
||||
f = data.bit(6);
|
||||
i = data.bit(7);
|
||||
}
|
||||
|
||||
if(field.bit(3)) {
|
||||
v = data.bit(28);
|
||||
c = data.bit(29);
|
||||
z = data.bit(30);
|
||||
n = data.bit(31);
|
||||
}
|
||||
}
|
||||
|
||||
//serialization.cpp
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
@@ -171,6 +187,8 @@ struct ARM7TDMI {
|
||||
b1 c; //carry
|
||||
b1 z; //zero
|
||||
b1 n; //negative
|
||||
|
||||
b1 readonly;
|
||||
};
|
||||
|
||||
struct Processor {
|
||||
@@ -179,6 +197,8 @@ struct ARM7TDMI {
|
||||
|
||||
GPR r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15;
|
||||
PSR cpsr;
|
||||
GPR rNULL; //read-only, used when no register is mapped to r(13) or r(14)
|
||||
PSR spsrNULL; //read-only, used when no SPSR is mapped
|
||||
|
||||
struct FIQ {
|
||||
GPR r8, r9, r10, r11, r12, r13, r14;
|
||||
@@ -214,10 +234,10 @@ struct ARM7TDMI {
|
||||
n32 address;
|
||||
n32 instruction;
|
||||
b1 thumb; //not used by fetch stage
|
||||
b1 irq; //not used by fetch stage
|
||||
};
|
||||
|
||||
n1 reload = 1;
|
||||
n1 nonsequential = 1;
|
||||
Instruction fetch;
|
||||
Instruction decode;
|
||||
Instruction execute;
|
||||
@@ -226,27 +246,41 @@ struct ARM7TDMI {
|
||||
n32 opcode;
|
||||
b1 carry;
|
||||
b1 irq;
|
||||
b1 nonsequential;
|
||||
|
||||
function<void (n32 opcode)> armInstruction[4096];
|
||||
function<void ()> thumbInstruction[65536];
|
||||
|
||||
//coprocessor.cpp
|
||||
auto bindCDP(n4 id, function<void (n4 cm, n3 op2, n4 cd, n4 cn, n4 op1)> handler) -> void;
|
||||
auto bindMCR(n4 id, function<void (n32 data, n4 cm, n3 op2, n4 cn, n3 op1)> handler) -> void;
|
||||
auto bindMRC(n4 id, function<n32 (n4 cm, n3 op2, n4 cn, n3 op1)> handler) -> void;
|
||||
|
||||
function<void (n4 cm, n3 op2, n4 cd, n4 cn, n4 op1)> CDP[16];
|
||||
function<void (n32 data, n4 cm, n3 op2, n4 cn, n3 op1)> MCR[16];
|
||||
function<n32 (n4 cm, n3 op2, n4 cn, n3 op1)> MRC[16];
|
||||
|
||||
//disassembler.cpp
|
||||
auto armDisassembleBranch(i24, n1) -> string;
|
||||
auto armDisassembleBranchExchangeRegister(n4) -> string;
|
||||
auto armDisassembleBranchExchangeRegister(n4, n4, n4, n1) -> string;
|
||||
auto armDisassembleCoprocessorDataProcessing(n4, n3, n4, n4, n4, n4) -> string;
|
||||
auto armDisassembleDataImmediate(n8, n4, n4, n4, n1, n4) -> string;
|
||||
auto armDisassembleDataImmediateShift(n4, n2, n5, n4, n4, n1, n4) -> string;
|
||||
auto armDisassembleDataRegisterShift(n4, n2, n4, n4, n4, n1, n4) -> string;
|
||||
auto armDisassembleLoadImmediate(n8, n1, n4, n4, n1, n1, n1) -> string;
|
||||
auto armDisassembleLoadRegister(n4, n1, n4, n4, n1, n1, n1) -> string;
|
||||
auto armDisassembleMemorySwap(n4, n4, n4, n1) -> string;
|
||||
auto armDisassembleMoveHalfImmediate(n8, n4, n4, n1, n1, n1, n1) -> string;
|
||||
auto armDisassembleMoveHalfRegister(n4, n4, n4, n1, n1, n1, n1) -> string;
|
||||
auto armDisassembleMoveImmediateOffset(n12, n4, n4, n1, n1, n1, n1, n1) -> string;
|
||||
auto armDisassembleMoveMultiple(n16, n4, n1, n1, n1, n1, n1) -> string;
|
||||
auto armDisassembleMoveRegisterOffset(n4, n2, n5, n4, n4, n1, n1, n1, n1, n1) -> string;
|
||||
auto armDisassembleMoveSignedImmediate(n8, n1, n4, n4, n1, n1, n1, n1) -> string;
|
||||
auto armDisassembleMoveSignedRegister(n4, n1, n4, n4, n1, n1, n1, n1) -> string;
|
||||
auto armDisassembleMoveToCoprocessorFromRegister(n4, n3, n4, n4, n4, n3) -> string;
|
||||
auto armDisassembleMoveToRegisterFromCoprocessor(n4, n3, n4, n4, n4, n3) -> string;
|
||||
auto armDisassembleMoveToRegisterFromRegister(n4, n4) -> string;
|
||||
auto armDisassembleMoveToRegisterFromStatus(n4, n1) -> string;
|
||||
auto armDisassembleMoveToStatusFromImmediate(n8, n4, n4, n1) -> string;
|
||||
auto armDisassembleMoveToStatusFromRegister(n4, n4, n1) -> string;
|
||||
auto armDisassembleMoveToStatusFromRegister(n4, n2, n5, n4, n1) -> string;
|
||||
auto armDisassembleMultiply(n4, n4, n4, n4, n1, n1) -> string;
|
||||
auto armDisassembleMultiplyLong(n4, n4, n4, n4, n1, n1, n1) -> string;
|
||||
auto armDisassembleSoftwareInterrupt(n24) -> string;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
auto ARM7TDMI::bindCDP(n4 id, function<void (n4 cm, n3 op2, n4 cd, n4 cn, n4 op1)> handler) -> void {
|
||||
CDP[id] = handler;
|
||||
}
|
||||
|
||||
auto ARM7TDMI::bindMCR(n4 id, function<void (n32 data, n4 cm, n3 op2, n4 cn, n3 op1)> handler) -> void {
|
||||
MCR[id] = handler;
|
||||
}
|
||||
|
||||
auto ARM7TDMI::bindMRC(n4 id, function<n32 (n4 cm, n3 op2, n4 cn, n3 op1)> handler) -> void {
|
||||
MRC[id] = handler;
|
||||
}
|
||||
@@ -17,12 +17,12 @@ auto ARM7TDMI::disassembleInstruction(maybe<n32> pc, maybe<boolean> thumb) -> st
|
||||
|
||||
_pc = pc();
|
||||
if(!thumb()) {
|
||||
n32 opcode = getDebugger(Word | Nonsequential, _pc & ~3);
|
||||
n32 opcode = getDebugger(Word, _pc & ~3);
|
||||
n12 index = (opcode & 0x0ff00000) >> 16 | (opcode & 0x000000f0) >> 4;
|
||||
_c = _conditions[opcode >> 28];
|
||||
return pad(armDisassemble[index](opcode), -40);
|
||||
} else {
|
||||
n16 opcode = getDebugger(Half | Nonsequential, _pc & ~1);
|
||||
n16 opcode = getDebugger(Half, _pc & ~1);
|
||||
return pad(thumbDisassemble[opcode](), -40);
|
||||
}
|
||||
}
|
||||
@@ -64,10 +64,16 @@ auto ARM7TDMI::armDisassembleBranch
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armDisassembleBranchExchangeRegister
|
||||
(n4 m) -> string {
|
||||
(n4 m, n4 d, n4 field, n1 mode) -> string {
|
||||
return {"bx", _c, " ", _r[m]};
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armDisassembleCoprocessorDataProcessing
|
||||
(n4 cm, n3 op2, n4 cpid, n4 cd, n4 cn, n4 op1) -> string {
|
||||
return {"cdp", _c, " p", cpid, ", ", op1, ", cr", cd,
|
||||
", cr", cn, ", cr", cm, ", ", op2};
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armDisassembleDataImmediate
|
||||
(n8 immediate, n4 shift, n4 d, n4 n, n1 save, n4 mode) -> string {
|
||||
static const string opcode[] = {
|
||||
@@ -118,30 +124,6 @@ auto ARM7TDMI::armDisassembleDataRegisterShift
|
||||
" ", _r[s]};
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armDisassembleLoadImmediate
|
||||
(n8 immediate, n1 half, n4 d, n4 n, n1 writeback, n1 up, n1 pre) -> string {
|
||||
string data;
|
||||
if(n == 15) data = {" =0x", hex(getDebugger((half ? Half : Byte) | Nonsequential,
|
||||
_pc + 8 + (up ? +immediate : -immediate)), half ? 4L : 2L)};
|
||||
|
||||
return {"ldr", _c, half ? "sh" : "sb", " ",
|
||||
_r[d], ",[", _r[n],
|
||||
pre == 0 ? "]" : "",
|
||||
immediate ? string{",", up ? "+" : "-", "0x", hex(immediate, 2L)} : string{},
|
||||
pre == 1 ? "]" : "",
|
||||
pre == 0 || writeback ? "!" : "", data};
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armDisassembleLoadRegister
|
||||
(n4 m, n1 half, n4 d, n4 n, n1 writeback, n1 up, n1 pre) -> string {
|
||||
return {"ldr", _c, half ? "sh" : "sb", " ",
|
||||
_r[d], ",[", _r[n],
|
||||
pre == 0 ? "]" : "",
|
||||
",", up ? "+" : "-", _r[m],
|
||||
pre == 1 ? "]" : "",
|
||||
pre == 0 || writeback ? "!" : ""};
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armDisassembleMemorySwap
|
||||
(n4 m, n4 d, n4 n, n1 byte) -> string {
|
||||
return {"swp", _c, byte ? "b" : "", " ", _r[d], ",", _r[m], ",[", _r[n], "]"};
|
||||
@@ -150,7 +132,7 @@ auto ARM7TDMI::armDisassembleMemorySwap
|
||||
auto ARM7TDMI::armDisassembleMoveHalfImmediate
|
||||
(n8 immediate, n4 d, n4 n, n1 mode, n1 writeback, n1 up, n1 pre) -> string {
|
||||
string data;
|
||||
if(n == 15) data = {" =0x", hex(getDebugger(Half | Nonsequential, _pc + (up ? +immediate : -immediate)), 4L)};
|
||||
if(n == 15) data = {" =0x", hex(getDebugger(Half, _pc + (up ? +immediate : -immediate)), 4L)};
|
||||
|
||||
return {mode ? "ldr" : "str", _c, "h ",
|
||||
_r[d], ",[", _r[n],
|
||||
@@ -173,7 +155,7 @@ auto ARM7TDMI::armDisassembleMoveHalfRegister
|
||||
auto ARM7TDMI::armDisassembleMoveImmediateOffset
|
||||
(n12 immediate, n4 d, n4 n, n1 mode, n1 writeback, n1 byte, n1 up, n1 pre) -> string {
|
||||
string data;
|
||||
if(n == 15) data = {" =0x", hex(getDebugger((byte ? Byte : Word) | Nonsequential,
|
||||
if(n == 15) data = {" =0x", hex(getDebugger((byte ? Byte : Word),
|
||||
_pc + 8 + (up ? +immediate : -immediate)), byte ? 2L : 4L)};
|
||||
return {mode ? "ldr" : "str", _c, byte ? "b" : "", " ", _r[d], ",[", _r[n],
|
||||
pre == 0 ? "]" : "",
|
||||
@@ -212,6 +194,47 @@ auto ARM7TDMI::armDisassembleMoveRegisterOffset
|
||||
pre == 0 || writeback ? "!" : ""};
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armDisassembleMoveSignedImmediate
|
||||
(n8 immediate, n1 half, n4 d, n4 n, n1 mode, n1 writeback, n1 up, n1 pre) -> string {
|
||||
string data;
|
||||
if(n == 15) data = {" =0x", hex(getDebugger((half ? Half : Byte),
|
||||
_pc + 8 + (up ? +immediate : -immediate)), half ? 4L : 2L)};
|
||||
|
||||
return {mode ? "ldr" : "str", _c, half ? "sh" : "sb", " ",
|
||||
_r[d], ",[", _r[n],
|
||||
pre == 0 ? "]" : "",
|
||||
immediate ? string{",", up ? "+" : "-", "0x", hex(immediate, 2L)} : string{},
|
||||
pre == 1 ? "]" : "",
|
||||
pre == 0 || writeback ? "!" : "", data};
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armDisassembleMoveSignedRegister
|
||||
(n4 m, n1 half, n4 d, n4 n, n1 mode, n1 writeback, n1 up, n1 pre) -> string {
|
||||
return {mode ? "ldr" : "str", _c, half ? "sh" : "sb", " ",
|
||||
_r[d], ",[", _r[n],
|
||||
pre == 0 ? "]" : "",
|
||||
",", up ? "+" : "-", _r[m],
|
||||
pre == 1 ? "]" : "",
|
||||
pre == 0 || writeback ? "!" : ""};
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armDisassembleMoveToCoprocessorFromRegister
|
||||
(n4 cm, n3 op2, n4 cpid, n4 d, n4 cn, n3 op1) -> string {
|
||||
return {"mcr", _c, " p", cpid, ", ", op1, ", ", _r[d],
|
||||
", cr", cn, ", cr", cm, ", ", op2};
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armDisassembleMoveToRegisterFromCoprocessor
|
||||
(n4 cm, n3 op2, n4 cpid, n4 d, n4 cn, n3 op1) -> string {
|
||||
return {"mrc", _c, " p", cpid, ", ", op1, ", ", _r[d],
|
||||
", cr", cn, ", cr", cm, ", ", op2};
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armDisassembleMoveToRegisterFromRegister
|
||||
(n4 d, n4 n) -> string {
|
||||
return {"mov", _c, " ", _r[d], ",", _r[n]};
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armDisassembleMoveToRegisterFromStatus
|
||||
(n4 d, n1 mode) -> string {
|
||||
return {"mrs", _c, " ", _r[d], ",", mode ? "spsr" : "cpsr"};
|
||||
@@ -229,13 +252,18 @@ auto ARM7TDMI::armDisassembleMoveToStatusFromImmediate
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armDisassembleMoveToStatusFromRegister
|
||||
(n4 m, n4 field, n1 mode) -> string {
|
||||
(n4 m, n2 type, n5 shift, n4 field, n1 mode) -> string {
|
||||
return {"msr", _c, " ", mode ? "spsr:" : "cpsr:",
|
||||
field.bit(0) ? "c" : "",
|
||||
field.bit(1) ? "x" : "",
|
||||
field.bit(2) ? "s" : "",
|
||||
field.bit(3) ? "f" : "",
|
||||
",", _r[m]};
|
||||
",", _r[m],
|
||||
type == 0 && shift ? string{" lsl #", shift} : string{},
|
||||
type == 1 ? string{" lsr #", shift ? (u32)shift : 32} : string{},
|
||||
type == 2 ? string{" asr #", shift ? (u32)shift : 32} : string{},
|
||||
type == 3 && shift ? string{" ror #", shift} : string{},
|
||||
type == 3 && !shift ? " rrx" : ""};
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armDisassembleMultiply
|
||||
@@ -276,7 +304,7 @@ auto ARM7TDMI::thumbDisassembleALU
|
||||
|
||||
auto ARM7TDMI::thumbDisassembleALUExtended
|
||||
(n4 d, n4 m, n2 mode) -> string {
|
||||
static const string opcode[] = {"add", "sub", "mov"};
|
||||
static const string opcode[] = {"add", "cmp", "mov"};
|
||||
if(d == 8 && m == 8 && mode == 2) return {"nop"};
|
||||
return {opcode[mode], " ", _r[d], ",", _r[m]};
|
||||
}
|
||||
@@ -308,7 +336,7 @@ auto ARM7TDMI::thumbDisassembleBranchExchange
|
||||
|
||||
auto ARM7TDMI::thumbDisassembleBranchFarPrefix
|
||||
(i11 displacementHi) -> string {
|
||||
n11 displacementLo = getDebugger(Half | Nonsequential, (_pc & ~1) + 2);
|
||||
n11 displacementLo = getDebugger(Half, (_pc & ~1) + 2);
|
||||
i22 displacement = displacementHi << 11 | displacementLo << 0;
|
||||
n32 address = _pc + 4 + displacement * 2;
|
||||
return {"bl 0x", hex(address, 8L)};
|
||||
@@ -340,7 +368,7 @@ auto ARM7TDMI::thumbDisassembleImmediate
|
||||
auto ARM7TDMI::thumbDisassembleLoadLiteral
|
||||
(n8 displacement, n3 d) -> string {
|
||||
n32 address = ((_pc + 4) & ~3) + (displacement << 2);
|
||||
n32 data = getDebugger(Word | Nonsequential, address);
|
||||
n32 data = getDebugger(Word, address);
|
||||
return {"ldr ", _r[d], ",[pc,#0x", hex(address, 8L), "] =0x", hex(data, 8L)};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,36 +1,30 @@
|
||||
auto ARM7TDMI::reload() -> void {
|
||||
u32 size = !cpsr().t ? Word : Half;
|
||||
pipeline.reload = false;
|
||||
endBurst();
|
||||
pipeline.fetch.address = r(15);
|
||||
pipeline.fetch.instruction = read(Prefetch | size, pipeline.fetch.address);
|
||||
fetch();
|
||||
}
|
||||
|
||||
auto ARM7TDMI::fetch() -> void {
|
||||
pipeline.execute = pipeline.decode;
|
||||
pipeline.execute.irq = pipeline.execute.irq & irq;
|
||||
pipeline.decode = pipeline.fetch;
|
||||
pipeline.decode.thumb = cpsr().t;
|
||||
pipeline.decode.irq = !cpsr().i;
|
||||
|
||||
u32 sequential = Sequential;
|
||||
if(pipeline.nonsequential) {
|
||||
pipeline.nonsequential = false;
|
||||
sequential = Nonsequential;
|
||||
}
|
||||
|
||||
u32 mask = !cpsr().t ? 3 : 1;
|
||||
u32 size = !cpsr().t ? Word : Half;
|
||||
|
||||
r(15).data += size >> 3;
|
||||
pipeline.fetch.address = r(15) & ~mask;
|
||||
pipeline.fetch.instruction = read(Prefetch | size | sequential, pipeline.fetch.address);
|
||||
pipeline.fetch.address = r(15);
|
||||
pipeline.fetch.instruction = read(Prefetch | size, pipeline.fetch.address);
|
||||
}
|
||||
|
||||
auto ARM7TDMI::instruction() -> void {
|
||||
u32 mask = !cpsr().t ? 3 : 1;
|
||||
u32 size = !cpsr().t ? Word : Half;
|
||||
|
||||
if(pipeline.reload) {
|
||||
pipeline.reload = false;
|
||||
r(15).data &= ~mask;
|
||||
pipeline.fetch.address = r(15) & ~mask;
|
||||
pipeline.fetch.instruction = read(Prefetch | size | Nonsequential, pipeline.fetch.address);
|
||||
fetch();
|
||||
}
|
||||
if(pipeline.reload) reload();
|
||||
fetch();
|
||||
|
||||
if(irq && !cpsr().i) {
|
||||
if(pipeline.execute.irq) {
|
||||
exception(PSR::IRQ, 0x18);
|
||||
if(pipeline.execute.thumb) r(14).data += 2;
|
||||
return;
|
||||
@@ -81,13 +75,31 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||
#undef arguments
|
||||
|
||||
#define arguments \
|
||||
opcode.bit( 0, 3) /* m */
|
||||
{
|
||||
auto opcode = pattern(".... 0001 0010 ---- ---- ---- 0001 ????");
|
||||
opcode.bit( 0, 3), /* m */ \
|
||||
opcode.bit(12,15), /* d */ \
|
||||
opcode.bit(16,19), /* field */ \
|
||||
opcode.bit(22) /* mode */
|
||||
for(n3 _ : range(8))
|
||||
for(n1 mode : range(2)) {
|
||||
auto opcode = pattern(".... 0001 0??0 ???? ???? ---- 0??1 ????") | _.bit(0,1) << 5 | _.bit(2) << 21 | mode << 22;
|
||||
bind(opcode, BranchExchangeRegister);
|
||||
}
|
||||
#undef arguments
|
||||
|
||||
#define arguments \
|
||||
opcode.bit( 0, 3), /* cm */ \
|
||||
opcode.bit( 5, 7), /* op2 */ \
|
||||
opcode.bit( 8,11), /* cpid */ \
|
||||
opcode.bit(12,15), /* cd */ \
|
||||
opcode.bit(16,19), /* cn */ \
|
||||
opcode.bit(20,23) /* op1 */
|
||||
for(n3 op2 : range(8))
|
||||
for(n4 op1 : range(16)) {
|
||||
auto opcode = pattern(".... 1110 ???? ???? ???? ???? ???0 ????") | op2 << 5 | op1 << 20;
|
||||
bind(opcode, CoprocessorDataProcessing);
|
||||
}
|
||||
#undef arguments
|
||||
|
||||
#define arguments \
|
||||
opcode.bit( 0, 7), /* immediate */ \
|
||||
opcode.bit( 8,11), /* shift */ \
|
||||
@@ -139,47 +151,14 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||
}
|
||||
#undef arguments
|
||||
|
||||
#define arguments \
|
||||
opcode.bit( 0, 3) << 0 | opcode.bit( 8,11) << 4, /* immediate */ \
|
||||
opcode.bit( 5), /* half */ \
|
||||
opcode.bit(12,15), /* d */ \
|
||||
opcode.bit(16,19), /* n */ \
|
||||
opcode.bit(21), /* writeback */ \
|
||||
opcode.bit(23), /* up */ \
|
||||
opcode.bit(24) /* pre */
|
||||
for(n1 half : range(2))
|
||||
for(n1 writeback : range(2))
|
||||
for(n1 up : range(2))
|
||||
for(n1 pre : range(2)) {
|
||||
auto opcode = pattern(".... 000? ?1?1 ???? ???? ???? 11?1 ????") | half << 5 | writeback << 21 | up << 23 | pre << 24;
|
||||
bind(opcode, LoadImmediate);
|
||||
}
|
||||
#undef arguments
|
||||
|
||||
#define arguments \
|
||||
opcode.bit( 0, 3), /* m */ \
|
||||
opcode.bit( 5), /* half */ \
|
||||
opcode.bit(12,15), /* d */ \
|
||||
opcode.bit(16,19), /* n */ \
|
||||
opcode.bit(21), /* writeback */ \
|
||||
opcode.bit(23), /* up */ \
|
||||
opcode.bit(24) /* pre */
|
||||
for(n1 half : range(2))
|
||||
for(n1 writeback : range(2))
|
||||
for(n1 up : range(2))
|
||||
for(n1 pre : range(2)) {
|
||||
auto opcode = pattern(".... 000? ?0?1 ???? ???? ---- 11?1 ????") | half << 5 | writeback << 21 | up << 23 | pre << 24;
|
||||
bind(opcode, LoadRegister);
|
||||
}
|
||||
#undef arguments
|
||||
|
||||
#define arguments \
|
||||
opcode.bit( 0, 3), /* m */ \
|
||||
opcode.bit(12,15), /* d */ \
|
||||
opcode.bit(16,19), /* n */ \
|
||||
opcode.bit(22) /* byte */
|
||||
for(n3 _ : range(8))
|
||||
for(n1 byte : range(2)) {
|
||||
auto opcode = pattern(".... 0001 0?00 ???? ???? ---- 1001 ????") | byte << 22;
|
||||
auto opcode = pattern(".... 0001 ???? ???? ???? ---- 1001 ????") | _.bit(0,1) << 20 | byte << 22 | _.bit(2) << 23;
|
||||
bind(opcode, MemorySwap);
|
||||
}
|
||||
#undef arguments
|
||||
@@ -283,11 +262,88 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||
}
|
||||
#undef arguments
|
||||
|
||||
#define arguments \
|
||||
opcode.bit( 0, 3) << 0 | opcode.bit( 8,11) << 4, /* immediate */ \
|
||||
opcode.bit( 5), /* half */ \
|
||||
opcode.bit(12,15), /* d */ \
|
||||
opcode.bit(16,19), /* n */ \
|
||||
opcode.bit(20), /* mode */ \
|
||||
opcode.bit(21), /* writeback */ \
|
||||
opcode.bit(23), /* up */ \
|
||||
opcode.bit(24) /* pre */
|
||||
for(n1 half : range(2))
|
||||
for(n1 mode : range(2))
|
||||
for(n1 writeback : range(2))
|
||||
for(n1 up : range(2))
|
||||
for(n1 pre : range(2)) {
|
||||
auto opcode = pattern(".... 000? ?1?? ???? ???? ???? 11?1 ????") | half << 5 | mode << 20 | writeback << 21 | up << 23 | pre << 24;
|
||||
bind(opcode, MoveSignedImmediate);
|
||||
}
|
||||
#undef arguments
|
||||
|
||||
#define arguments \
|
||||
opcode.bit( 0, 3), /* m */ \
|
||||
opcode.bit( 5), /* half */ \
|
||||
opcode.bit(12,15), /* d */ \
|
||||
opcode.bit(16,19), /* n */ \
|
||||
opcode.bit(20), /* mode */ \
|
||||
opcode.bit(21), /* writeback */ \
|
||||
opcode.bit(23), /* up */ \
|
||||
opcode.bit(24) /* pre */
|
||||
for(n1 half : range(2))
|
||||
for(n1 mode : range(2))
|
||||
for(n1 writeback : range(2))
|
||||
for(n1 up : range(2))
|
||||
for(n1 pre : range(2)) {
|
||||
auto opcode = pattern(".... 000? ?0?? ???? ???? ---- 11?1 ????") | half << 5 | mode << 20 | writeback << 21 | up << 23 | pre << 24;
|
||||
bind(opcode, MoveSignedRegister);
|
||||
}
|
||||
#undef arguments
|
||||
|
||||
#define arguments \
|
||||
opcode.bit( 0, 3), /* cm */ \
|
||||
opcode.bit( 5, 7), /* op2 */ \
|
||||
opcode.bit( 8,11), /* cpid */ \
|
||||
opcode.bit(12,15), /* d */ \
|
||||
opcode.bit(16,19), /* cn */ \
|
||||
opcode.bit(21,23) /* op1 */
|
||||
for(n3 op2 : range(8))
|
||||
for(n3 op1 : range(8)) {
|
||||
auto opcode = pattern(".... 1110 ???0 ???? ???? ???? ???1 ????") | op2 << 5 | op1 << 21;
|
||||
bind(opcode, MoveToCoprocessorFromRegister);
|
||||
}
|
||||
#undef arguments
|
||||
|
||||
#define arguments \
|
||||
opcode.bit( 0, 3), /* cm */ \
|
||||
opcode.bit( 5, 7), /* op2 */ \
|
||||
opcode.bit( 8,11), /* cpid */ \
|
||||
opcode.bit(12,15), /* d */ \
|
||||
opcode.bit(16,19), /* cn */ \
|
||||
opcode.bit(21,23) /* op1 */
|
||||
for(n3 op2 : range(8))
|
||||
for(n3 op1 : range(8)) {
|
||||
auto opcode = pattern(".... 1110 ???1 ???? ???? ???? ???1 ????") | op2 << 5 | op1 << 21;
|
||||
bind(opcode, MoveToRegisterFromCoprocessor);
|
||||
}
|
||||
#undef arguments
|
||||
|
||||
#define arguments \
|
||||
opcode.bit(12,15), /* d */ \
|
||||
opcode.bit(16,19) /* n */
|
||||
for(n5 _ : range(32)) {
|
||||
//undocumented instruction, equivalent to "mov rd, rn"
|
||||
auto opcode = pattern(".... 0011 0?00 ???? ???? ---- ???? ----") | _.bit(0,3) << 4 | _.bit(4) << 22;
|
||||
bind(opcode, MoveToRegisterFromRegister);
|
||||
}
|
||||
#undef arguments
|
||||
|
||||
#define arguments \
|
||||
opcode.bit(12,15), /* d */ \
|
||||
opcode.bit(22) /* mode */
|
||||
for(n3 _ : range(8))
|
||||
for(n1 mode : range(2)) {
|
||||
auto opcode = pattern(".... 0001 0?00 ---- ???? ---- 0000 ----") | mode << 22;
|
||||
auto opcode = pattern(".... 0001 0?00 ---- ???? ---- ???0 ----") | _ << 5 | mode << 22;
|
||||
bind(opcode, MoveToRegisterFromStatus);
|
||||
}
|
||||
#undef arguments
|
||||
@@ -306,10 +362,14 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||
|
||||
#define arguments \
|
||||
opcode.bit( 0, 3), /* m */ \
|
||||
opcode.bit( 5, 6), /* type */ \
|
||||
opcode.bit( 7,11), /* shift */ \
|
||||
opcode.bit(16,19), /* field */ \
|
||||
opcode.bit(22) /* mode */
|
||||
for(n2 type : range(4))
|
||||
for(n1 shiftLo : range(2))
|
||||
for(n1 mode : range(2)) {
|
||||
auto opcode = pattern(".... 0001 0?10 ???? ---- ---- 0000 ????") | mode << 22;
|
||||
auto opcode = pattern(".... 0001 0?10 ???? ---- ???? ???0 ????") | type << 5 | shiftLo << 7 | mode << 22;
|
||||
bind(opcode, MoveToStatusFromRegister);
|
||||
}
|
||||
#undef arguments
|
||||
@@ -322,8 +382,9 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||
opcode.bit(20), /* save */ \
|
||||
opcode.bit(21) /* accumulate */
|
||||
for(n1 save : range(2))
|
||||
for(n1 accumulate : range(2)) {
|
||||
auto opcode = pattern(".... 0000 00?? ???? ???? ???? 1001 ????") | save << 20 | accumulate << 21;
|
||||
for(n1 accumulate : range(2))
|
||||
for(n1 _ : range(2)) {
|
||||
auto opcode = pattern(".... 0000 0??? ???? ???? ???? 1001 ????") | save << 20 | accumulate << 21 | _ << 22;
|
||||
bind(opcode, Multiply);
|
||||
}
|
||||
#undef arguments
|
||||
@@ -354,15 +415,28 @@ auto ARM7TDMI::armInitialize() -> void {
|
||||
#undef arguments
|
||||
|
||||
#define arguments
|
||||
for(n12 id : range(4096)) {
|
||||
if(armInstruction[id]) continue;
|
||||
auto opcode = pattern(".... ???? ???? ---- ---- ---- ???? ----") | id.bit(0,3) << 4 | id.bit(4,11) << 20;
|
||||
for(n8 _ : range(256)) {
|
||||
//architecturally undefined
|
||||
auto opcode = pattern(".... 011? ???? ---- ---- ---- ???1 ----") | _.bit(0,2) << 5 | _.bit(3,7) << 20;
|
||||
bind(opcode, Undefined);
|
||||
}
|
||||
for(n8 _ : range(256)) {
|
||||
//load to coprocessor
|
||||
auto opcode = pattern(".... 110? ???1 ---- ---- ---- ???? ----") | _.bit(0,3) << 4 | _.bit(4,7) << 21;
|
||||
bind(opcode, Undefined);
|
||||
}
|
||||
for(n8 _ : range(256)) {
|
||||
//store from coprocessor
|
||||
auto opcode = pattern(".... 110? ???0 ---- ---- ---- ???? ----") | _.bit(0,3) << 4 | _.bit(4,7) << 21;
|
||||
bind(opcode, Undefined);
|
||||
}
|
||||
#undef arguments
|
||||
|
||||
#undef bind
|
||||
#undef pattern
|
||||
|
||||
//check that all encodings are bound
|
||||
for(n12 index : range(4096)) assert(armInstruction[index]);
|
||||
}
|
||||
|
||||
auto ARM7TDMI::thumbInitialize() -> void {
|
||||
@@ -419,9 +493,9 @@ auto ARM7TDMI::thumbInitialize() -> void {
|
||||
bind(opcode, AdjustStack, immediate, mode);
|
||||
}
|
||||
|
||||
for(n3 _ : range(8))
|
||||
for(n4 _ : range(16))
|
||||
for(n4 m : range(16)) {
|
||||
auto opcode = pattern("0100 0111 0??? ?---") | _ << 0 | m << 3;
|
||||
auto opcode = pattern("0100 0111 ???? ?---") | _.bit(0,2) << 0 | m << 3 | _.bit(3) << 7;
|
||||
bind(opcode, BranchExchange, m);
|
||||
}
|
||||
|
||||
@@ -442,6 +516,7 @@ auto ARM7TDMI::thumbInitialize() -> void {
|
||||
|
||||
for(n8 displacement : range(256))
|
||||
for(n4 condition : range(16)) {
|
||||
if(condition == 14) continue; //BAL
|
||||
if(condition == 15) continue; //BNV
|
||||
auto opcode = pattern("1101 ???? ???? ????") | displacement << 0 | condition << 8;
|
||||
bind(opcode, BranchTest, displacement, condition);
|
||||
|
||||
@@ -24,24 +24,12 @@ auto ARM7TDMI::armALU(n4 mode, n4 d, n32 rn, n32 rm) -> void {
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armMoveToStatus(n4 field, n1 mode, n32 data) -> void {
|
||||
if(mode && (cpsr().m == PSR::USR || cpsr().m == PSR::SYS)) return;
|
||||
PSR& psr = mode ? spsr() : cpsr();
|
||||
|
||||
if(field.bit(0)) {
|
||||
if(mode || privileged()) {
|
||||
psr.m = data.bit(0,4);
|
||||
psr.t = data.bit(5);
|
||||
psr.f = data.bit(6);
|
||||
psr.i = data.bit(7);
|
||||
if(!mode && psr.t) r(15).data += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if(field.bit(3)) {
|
||||
psr.v = data.bit(28);
|
||||
psr.c = data.bit(29);
|
||||
psr.z = data.bit(30);
|
||||
psr.n = data.bit(31);
|
||||
if(mode) {
|
||||
spsr().set(field, data);
|
||||
} else {
|
||||
if(!privileged()) field.bit(0) = 0;
|
||||
cpsr().set(field, data);
|
||||
if(cpsr().t) r(15).data += 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,10 +42,21 @@ auto ARM7TDMI::armInstructionBranch
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionBranchExchangeRegister
|
||||
(n4 m) -> void {
|
||||
(n4 m, n4 d, n4 field, n1 mode) -> void {
|
||||
n32 address = r(m);
|
||||
cpsr().t = address.bit(0);
|
||||
r(15) = address;
|
||||
if((field & 0b1001) == 0b1001) {
|
||||
PSR& psr = mode ? spsr() : cpsr();
|
||||
psr.t = address.bit(0);
|
||||
} else {
|
||||
armMoveToStatus(field, mode, address);
|
||||
}
|
||||
r(d) = address;
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionCoprocessorDataProcessing
|
||||
(n4 cm, n3 op2, n4 cpid, n4 cd, n4 cn, n4 op1) -> void {
|
||||
if(!CDP[cpid]) return armInstructionUndefined();
|
||||
CDP[cpid](cm, op2, cd, cn, op1);
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionDataImmediate
|
||||
@@ -87,66 +86,43 @@ auto ARM7TDMI::armInstructionDataImmediateShift
|
||||
|
||||
auto ARM7TDMI::armInstructionDataRegisterShift
|
||||
(n4 m, n2 type, n4 s, n4 d, n4 n, n1 save, n4 mode) -> void {
|
||||
n8 rs = r(s) + (s == 15 ? 4 : 0);
|
||||
n8 rs = r(s);
|
||||
n32 rn = r(n) + (n == 15 ? 4 : 0);
|
||||
n32 rm = r(m) + (m == 15 ? 4 : 0);
|
||||
carry = cpsr().c;
|
||||
|
||||
idle();
|
||||
switch(type) {
|
||||
case 0: rm = LSL(rm, rs < 33 ? rs : (n8)33); break;
|
||||
case 1: rm = LSR(rm, rs < 33 ? rs : (n8)33); break;
|
||||
case 2: rm = ASR(rm, rs < 32 ? rs : (n8)32); break;
|
||||
case 3: if(rs) rm = ROR(rm, rs & 31 ? u32(rs & 31) : 32); break;
|
||||
case 0: rm = LSL(rm, rs); break;
|
||||
case 1: rm = LSR(rm, rs); break;
|
||||
case 2: rm = ASR(rm, rs); break;
|
||||
case 3: rm = ROR(rm, rs); break;
|
||||
}
|
||||
|
||||
armALU(mode, d, rn, rm);
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionLoadImmediate
|
||||
(n8 immediate, n1 half, n4 d, n4 n, n1 writeback, n1 up, n1 pre) -> void {
|
||||
n32 rn = r(n);
|
||||
n32 rd = r(d);
|
||||
|
||||
if(pre == 1) rn = up ? rn + immediate : rn - immediate;
|
||||
rd = load((half ? Half : Byte) | Nonsequential | Signed, rn);
|
||||
if(pre == 0) rn = up ? rn + immediate : rn - immediate;
|
||||
|
||||
if(pre == 0 || writeback) r(n) = rn;
|
||||
r(d) = rd;
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionLoadRegister
|
||||
(n4 m, n1 half, n4 d, n4 n, n1 writeback, n1 up, n1 pre) -> void {
|
||||
n32 rn = r(n);
|
||||
n32 rm = r(m);
|
||||
n32 rd = r(d);
|
||||
|
||||
if(pre == 1) rn = up ? rn + rm : rn - rm;
|
||||
rd = load((half ? Half : Byte) | Nonsequential | Signed, rn);
|
||||
if(pre == 0) rn = up ? rn + rm : rn - rm;
|
||||
|
||||
if(pre == 0 || writeback) r(n) = rn;
|
||||
r(d) = rd;
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionMemorySwap
|
||||
(n4 m, n4 d, n4 n, n1 byte) -> void {
|
||||
n32 word = load((byte ? Byte : Word) | Nonsequential, r(n));
|
||||
store((byte ? Byte : Word) | Nonsequential, r(n), r(m));
|
||||
n32 rm = r(m) + (m == 15 ? 4 : 0);
|
||||
lock();
|
||||
n32 word = load((byte ? Byte : Word), r(n));
|
||||
store((byte ? Byte : Word), r(n), rm);
|
||||
r(d) = word;
|
||||
unlock();
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionMoveHalfImmediate
|
||||
(n8 immediate, n4 d, n4 n, n1 mode, n1 writeback, n1 up, n1 pre) -> void {
|
||||
n32 rn = r(n);
|
||||
n32 rd = r(d);
|
||||
n32 rd = r(d) + (d == 15 ? 4 : 0);
|
||||
|
||||
if(pre == 1) rn = up ? rn + immediate : rn - immediate;
|
||||
if(mode == 1) rd = load(Half | Nonsequential, rn);
|
||||
if(mode == 0) store(Half | Nonsequential, rn, rd);
|
||||
if(mode == 1) rd = load(Half, rn);
|
||||
if(mode == 0) store(Half, rn, rd);
|
||||
if(pre == 0) rn = up ? rn + immediate : rn - immediate;
|
||||
|
||||
if(pre == 0 || writeback) r(n) = rn;
|
||||
if(pre == 0 || writeback) r(n) = rn + (n == 15 ? 4 : 0);
|
||||
if(mode == 1) r(d) = rd;
|
||||
}
|
||||
|
||||
@@ -154,14 +130,14 @@ auto ARM7TDMI::armInstructionMoveHalfRegister
|
||||
(n4 m, n4 d, n4 n, n1 mode, n1 writeback, n1 up, n1 pre) -> void {
|
||||
n32 rn = r(n);
|
||||
n32 rm = r(m);
|
||||
n32 rd = r(d);
|
||||
n32 rd = r(d) + (d == 15 ? 4 : 0);
|
||||
|
||||
if(pre == 1) rn = up ? rn + rm : rn - rm;
|
||||
if(mode == 1) rd = load(Half | Nonsequential, rn);
|
||||
if(mode == 0) store(Half | Nonsequential, rn, rd);
|
||||
if(mode == 1) rd = load(Half, rn);
|
||||
if(mode == 0) store(Half, rn, rd);
|
||||
if(pre == 0) rn = up ? rn + rm : rn - rm;
|
||||
|
||||
if(pre == 0 || writeback) r(n) = rn;
|
||||
if(pre == 0 || writeback) r(n) = rn + (n == 15 ? 4 : 0);
|
||||
if(mode == 1) r(d) = rd;
|
||||
}
|
||||
|
||||
@@ -171,8 +147,8 @@ auto ARM7TDMI::armInstructionMoveImmediateOffset
|
||||
n32 rd = r(d) + (d == 15 ? 4 : 0);
|
||||
|
||||
if(pre == 1) rn = up ? rn + immediate : rn - immediate;
|
||||
if(mode == 1) rd = load((byte ? Byte : Word) | Nonsequential, rn);
|
||||
if(mode == 0) store((byte ? Byte : Word) | Nonsequential, rn, rd);
|
||||
if(mode == 1) rd = load((byte ? Byte : Word), rn);
|
||||
if(mode == 0) store((byte ? Byte : Word), rn, rd);
|
||||
if(pre == 0) rn = up ? rn + immediate : rn - immediate;
|
||||
|
||||
if(pre == 0 || writeback) r(n) = rn;
|
||||
@@ -183,34 +159,32 @@ auto ARM7TDMI::armInstructionMoveMultiple
|
||||
(n16 list, n4 n, n1 mode, n1 writeback, n1 type, n1 up, n1 pre) -> void {
|
||||
n32 rn = r(n);
|
||||
n32 bitCount = list ? bit::count(list) : 16;
|
||||
n32 rnEnd;
|
||||
if(up == 1) rnEnd = r(n) + bitCount * 4; //IA,IB
|
||||
if(up == 0) rnEnd = r(n) - bitCount * 4; //DA,DB
|
||||
if(pre == 0 && up == 1) rn = rn + 0; //IA
|
||||
if(pre == 1 && up == 1) rn = rn + 4; //IB
|
||||
if(pre == 1 && up == 0) rn = rn - bitCount * 4 + 0; //DB
|
||||
if(pre == 0 && up == 0) rn = rn - bitCount * 4 + 4; //DA
|
||||
|
||||
if(writeback && mode == 1 && !list.bit(n)) {
|
||||
if(up == 1) r(n) = r(n) + bitCount * 4; //IA,IB
|
||||
if(up == 0) r(n) = r(n) - bitCount * 4; //DA,DB
|
||||
}
|
||||
|
||||
auto cpsrMode = cpsr().m;
|
||||
bool usr = false;
|
||||
if(type && mode == 1 && !list.bit(15)) usr = true;
|
||||
if(type && mode == 0) usr = true;
|
||||
if(usr) cpsr().m = PSR::USR;
|
||||
|
||||
u32 sequential = Nonsequential;
|
||||
if(!list) {
|
||||
if(mode == 1) r(15) = read(Word | sequential, rn);
|
||||
if(mode == 0) write(Word | sequential, rn, r(15) + 4);
|
||||
} else {
|
||||
for(u32 m : range(16)) {
|
||||
if(!list.bit(m)) continue;
|
||||
if(mode == 1) r(m) = read(Word | sequential, rn);
|
||||
if(mode == 0) write(Word | sequential, rn, r(m) + (m == 15 ? 4 : 0));
|
||||
rn += 4;
|
||||
sequential = Sequential;
|
||||
if(writeback && mode == 1 && !list.bit(n)) r(n) = rnEnd;
|
||||
|
||||
endBurst();
|
||||
if(!list) list.bit(15) = 1;
|
||||
for(u32 m : range(16)) {
|
||||
if(!list.bit(m)) continue;
|
||||
if(mode == 1) r(m) = read(Word, rn);
|
||||
if(mode == 0) {
|
||||
write(Word, rn, r(m) + (!(n == 15 && writeback) && m == 15 ? 4 : 0));
|
||||
if(writeback) r(n) = rnEnd; //writeback occurs after first access
|
||||
}
|
||||
rn += 4;
|
||||
}
|
||||
|
||||
if(usr) cpsr().m = cpsrMode;
|
||||
@@ -221,19 +195,14 @@ auto ARM7TDMI::armInstructionMoveMultiple
|
||||
cpsr() = spsr();
|
||||
}
|
||||
} else {
|
||||
pipeline.nonsequential = true;
|
||||
}
|
||||
|
||||
if(writeback && mode == 0) {
|
||||
if(up == 1) r(n) = r(n) + bitCount * 4; //IA,IB
|
||||
if(up == 0) r(n) = r(n) - bitCount * 4; //DA,DB
|
||||
endBurst();
|
||||
}
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionMoveRegisterOffset
|
||||
(n4 m, n2 type, n5 shift, n4 d, n4 n, n1 mode, n1 writeback, n1 byte, n1 up, n1 pre) -> void {
|
||||
n32 rm = r(m);
|
||||
n32 rd = r(d);
|
||||
n32 rd = r(d) + (d == 15 ? 4 : 0);
|
||||
n32 rn = r(n);
|
||||
carry = cpsr().c;
|
||||
|
||||
@@ -245,14 +214,60 @@ auto ARM7TDMI::armInstructionMoveRegisterOffset
|
||||
}
|
||||
|
||||
if(pre == 1) rn = up ? rn + rm : rn - rm;
|
||||
if(mode == 1) rd = load((byte ? Byte : Word) | Nonsequential, rn);
|
||||
if(mode == 0) store((byte ? Byte : Word) | Nonsequential, rn, rd);
|
||||
if(mode == 1) rd = load((byte ? Byte : Word), rn);
|
||||
if(mode == 0) store((byte ? Byte : Word), rn, rd);
|
||||
if(pre == 0) rn = up ? rn + rm : rn - rm;
|
||||
|
||||
if(pre == 0 || writeback) r(n) = rn;
|
||||
if(mode == 1) r(d) = rd;
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionMoveSignedImmediate
|
||||
(n8 immediate, n1 half, n4 d, n4 n, n1 mode, n1 writeback, n1 up, n1 pre) -> void {
|
||||
n32 rn = r(n);
|
||||
n32 rd = r(d) + (d == 15 ? 4 : 0);
|
||||
|
||||
if(pre == 1) rn = up ? rn + immediate : rn - immediate;
|
||||
if(mode == 1) rd = load((half ? Half : Byte) | Signed, rn);
|
||||
if(mode == 0) store((half ? Half : Byte) | Signed, rn, rd);
|
||||
if(pre == 0) rn = up ? rn + immediate : rn - immediate;
|
||||
|
||||
if(pre == 0 || writeback) r(n) = rn + (n == 15 ? 4 : 0);
|
||||
if(mode == 1) r(d) = rd;
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionMoveSignedRegister
|
||||
(n4 m, n1 half, n4 d, n4 n, n1 mode, n1 writeback, n1 up, n1 pre) -> void {
|
||||
n32 rn = r(n);
|
||||
n32 rm = r(m);
|
||||
n32 rd = r(d) + (d == 15 ? 4 : 0);
|
||||
|
||||
if(pre == 1) rn = up ? rn + rm : rn - rm;
|
||||
if(mode == 1) rd = load((half ? Half : Byte) | Signed, rn);
|
||||
if(mode == 0) store((half ? Half : Byte) | Signed, rn, rd);
|
||||
if(pre == 0) rn = up ? rn + rm : rn - rm;
|
||||
|
||||
if(pre == 0 || writeback) r(n) = rn + (n == 15 ? 4 : 0);
|
||||
if(mode == 1) r(d) = rd;
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionMoveToCoprocessorFromRegister
|
||||
(n4 cm, n3 op2, n4 cpid, n4 d, n4 cn, n3 op1) -> void {
|
||||
if(!MCR[cpid]) return armInstructionUndefined();
|
||||
MCR[cpid](r(d), cm, op2, cn, op1);
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionMoveToRegisterFromCoprocessor
|
||||
(n4 cm, n3 op2, n4 cpid, n4 d, n4 cn, n3 op1) -> void {
|
||||
if(!MRC[cpid]) return armInstructionUndefined();
|
||||
r(d) = MRC[cpid](cm, op2, cn, op1);
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionMoveToRegisterFromRegister
|
||||
(n4 d, n4 n) -> void {
|
||||
r(d) = r(n);
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionMoveToRegisterFromStatus
|
||||
(n4 d, n1 mode) -> void {
|
||||
r(d) = (mode && cpsr().m != PSR::USR && cpsr().m != PSR::SYS) ? spsr() : cpsr();
|
||||
@@ -266,14 +281,25 @@ auto ARM7TDMI::armInstructionMoveToStatusFromImmediate
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionMoveToStatusFromRegister
|
||||
(n4 m, n4 field, n1 mode) -> void {
|
||||
armMoveToStatus(field, mode, r(m));
|
||||
(n4 m, n2 type, n5 shift, n4 field, n1 mode) -> void {
|
||||
n32 rm = r(m);
|
||||
carry = cpsr().c;
|
||||
|
||||
switch(type) {
|
||||
case 0: rm = LSL(rm, shift); break;
|
||||
case 1: rm = LSR(rm, shift ? (u32)shift : 32); break;
|
||||
case 2: rm = ASR(rm, shift ? (u32)shift : 32); break;
|
||||
case 3: rm = shift ? ROR(rm, shift) : RRX(rm); break;
|
||||
}
|
||||
|
||||
armMoveToStatus(field, mode, rm);
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionMultiply
|
||||
(n4 m, n4 s, n4 n, n4 d, n1 save, n1 accumulate) -> void {
|
||||
if(accumulate) idle();
|
||||
r(d) = MUL(accumulate ? r(n) : 0, r(m), r(s));
|
||||
n32 product = MUL(accumulate ? r(n) : 0, r(m), r(s));
|
||||
if(d != 15) r(d) = product;
|
||||
}
|
||||
|
||||
auto ARM7TDMI::armInstructionMultiplyLong
|
||||
@@ -300,8 +326,8 @@ auto ARM7TDMI::armInstructionMultiplyLong
|
||||
n64 rd = rm * rs;
|
||||
if(accumulate) rd += (n64)r(h) << 32 | (n64)r(l) << 0;
|
||||
|
||||
r(h) = rd >> 32;
|
||||
r(l) = rd >> 0;
|
||||
if(l != 15) r(l) = rd >> 0;
|
||||
if(h != 15) r(h) = rd >> 32;
|
||||
|
||||
if(save) {
|
||||
cpsr().z = rd == 0;
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
auto ARM7TDMI::thumbInstructionALU
|
||||
(n3 d, n3 m, n4 mode) -> void {
|
||||
carry = cpsr().c;
|
||||
switch(mode) {
|
||||
case 0: r(d) = BIT(r(d) & r(m)); break; //AND
|
||||
case 1: r(d) = BIT(r(d) ^ r(m)); break; //EOR
|
||||
case 2: r(d) = BIT(LSL(r(d), r(m))); break; //LSL
|
||||
case 3: r(d) = BIT(LSR(r(d), r(m))); break; //LSR
|
||||
case 4: r(d) = BIT(ASR(r(d), r(m))); break; //ASR
|
||||
case 2: r(d) = BIT(LSL(r(d), r(m))); idle(); break; //LSL
|
||||
case 3: r(d) = BIT(LSR(r(d), r(m))); idle(); break; //LSR
|
||||
case 4: r(d) = BIT(ASR(r(d), r(m))); idle(); break; //ASR
|
||||
case 5: r(d) = ADD(r(d), r(m), cpsr().c); break; //ADC
|
||||
case 6: r(d) = SUB(r(d), r(m), cpsr().c); break; //SBC
|
||||
case 7: r(d) = BIT(ROR(r(d), r(m))); break; //ROR
|
||||
case 7: r(d) = BIT(ROR(r(d), r(m))); idle(); break; //ROR
|
||||
case 8: BIT(r(d) & r(m)); break; //TST
|
||||
case 9: r(d) = SUB(0, r(m), 1); break; //NEG
|
||||
case 10: SUB(r(d), r(m), 1); break; //CMP
|
||||
@@ -24,7 +25,7 @@ auto ARM7TDMI::thumbInstructionALUExtended
|
||||
(n4 d, n4 m, n2 mode) -> void {
|
||||
switch(mode) {
|
||||
case 0: r(d) = r(d) + r(m); break; //ADD
|
||||
case 1: SUB(r(d), r(m), 1); break; //SUBS
|
||||
case 1: SUB(r(d), r(m), 1); break; //CMP
|
||||
case 2: r(d) = r(m); break; //MOV
|
||||
}
|
||||
}
|
||||
@@ -92,6 +93,7 @@ auto ARM7TDMI::thumbInstructionBranchTest
|
||||
|
||||
auto ARM7TDMI::thumbInstructionImmediate
|
||||
(n8 immediate, n3 d, n2 mode) -> void {
|
||||
carry = cpsr().c;
|
||||
switch(mode) {
|
||||
case 0: r(d) = BIT(immediate); break; //MOV
|
||||
case 1: SUB(r(d), immediate, 1); break; //CMP
|
||||
@@ -103,81 +105,80 @@ auto ARM7TDMI::thumbInstructionImmediate
|
||||
auto ARM7TDMI::thumbInstructionLoadLiteral
|
||||
(n8 displacement, n3 d) -> void {
|
||||
n32 address = (r(15) & ~3) + (displacement << 2);
|
||||
r(d) = load(Word | Nonsequential, address);
|
||||
r(d) = load(Word, address);
|
||||
}
|
||||
|
||||
auto ARM7TDMI::thumbInstructionMoveByteImmediate
|
||||
(n3 d, n3 n, n5 offset, n1 mode) -> void {
|
||||
switch(mode) {
|
||||
case 0: store(Byte | Nonsequential, r(n) + offset, r(d)); break; //STRB
|
||||
case 1: r(d) = load(Byte | Nonsequential, r(n) + offset); break; //LDRB
|
||||
case 0: store(Byte, r(n) + offset, r(d)); break; //STRB
|
||||
case 1: r(d) = load(Byte, r(n) + offset); break; //LDRB
|
||||
}
|
||||
}
|
||||
|
||||
auto ARM7TDMI::thumbInstructionMoveHalfImmediate
|
||||
(n3 d, n3 n, n5 offset, n1 mode) -> void {
|
||||
switch(mode) {
|
||||
case 0: store(Half | Nonsequential, r(n) + offset * 2, r(d)); break; //STRH
|
||||
case 1: r(d) = load(Half | Nonsequential, r(n) + offset * 2); break; //LDRH
|
||||
case 0: store(Half, r(n) + offset * 2, r(d)); break; //STRH
|
||||
case 1: r(d) = load(Half, r(n) + offset * 2); break; //LDRH
|
||||
}
|
||||
}
|
||||
|
||||
auto ARM7TDMI::thumbInstructionMoveMultiple
|
||||
(n8 list, n3 n, n1 mode) -> void {
|
||||
n32 rn = r(n);
|
||||
n32 bitCount = list ? bit::count(list) : 16;
|
||||
n16 rlist = list;
|
||||
n32 bitCount = rlist ? bit::count(rlist) : 16;
|
||||
n32 rnEnd = r(n) + bitCount * 4;
|
||||
|
||||
if(mode == 1 && !list.bit(n)) r(n) = r(n) + bitCount * 4;
|
||||
if(mode == 1 && !rlist.bit(n)) r(n) = rnEnd;
|
||||
|
||||
u32 sequential = Nonsequential;
|
||||
if(!list) {
|
||||
if(mode == 1) r(15) = read(Word | sequential, rn);
|
||||
if(mode == 0) write(Word | sequential, rn, r(15) + 2);
|
||||
} else {
|
||||
for(u32 m : range(8)) {
|
||||
if(!list.bit(m)) continue;
|
||||
if(mode == 1) r(m) = read(Word | sequential, rn); //LDMIA
|
||||
if(mode == 0) write(Word | sequential, rn, r(m)); //STMIA
|
||||
rn += 4;
|
||||
sequential = Sequential;
|
||||
endBurst();
|
||||
if(!rlist) rlist.bit(15) = 1;
|
||||
for(u32 m : range(16)) {
|
||||
if(!rlist.bit(m)) continue;
|
||||
if(mode == 1) r(m) = read(Word, rn); //LDMIA
|
||||
if(mode == 0) {
|
||||
write(Word, rn, r(m) + (m == 15 ? 2 : 0)); //STMIA
|
||||
r(n) = rnEnd; //writeback occurs after first access
|
||||
}
|
||||
rn += 4;
|
||||
}
|
||||
|
||||
if(mode) {
|
||||
idle();
|
||||
} else {
|
||||
pipeline.nonsequential = true;
|
||||
r(n) = r(n) + bitCount * 4;
|
||||
endBurst();
|
||||
}
|
||||
}
|
||||
|
||||
auto ARM7TDMI::thumbInstructionMoveRegisterOffset
|
||||
(n3 d, n3 n, n3 m, n3 mode) -> void {
|
||||
switch(mode) {
|
||||
case 0: store(Word | Nonsequential, r(n) + r(m), r(d)); break; //STR
|
||||
case 1: store(Half | Nonsequential, r(n) + r(m), r(d)); break; //STRH
|
||||
case 2: store(Byte | Nonsequential, r(n) + r(m), r(d)); break; //STRB
|
||||
case 3: r(d) = load(Byte | Nonsequential | Signed, r(n) + r(m)); break; //LDSB
|
||||
case 4: r(d) = load(Word | Nonsequential, r(n) + r(m)); break; //LDR
|
||||
case 5: r(d) = load(Half | Nonsequential, r(n) + r(m)); break; //LDRH
|
||||
case 6: r(d) = load(Byte | Nonsequential, r(n) + r(m)); break; //LDRB
|
||||
case 7: r(d) = load(Half | Nonsequential | Signed, r(n) + r(m)); break; //LDSH
|
||||
case 0: store(Word, r(n) + r(m), r(d)); break; //STR
|
||||
case 1: store(Half, r(n) + r(m), r(d)); break; //STRH
|
||||
case 2: store(Byte, r(n) + r(m), r(d)); break; //STRB
|
||||
case 3: r(d) = load(Byte | Signed, r(n) + r(m)); break; //LDSB
|
||||
case 4: r(d) = load(Word, r(n) + r(m)); break; //LDR
|
||||
case 5: r(d) = load(Half, r(n) + r(m)); break; //LDRH
|
||||
case 6: r(d) = load(Byte, r(n) + r(m)); break; //LDRB
|
||||
case 7: r(d) = load(Half | Signed, r(n) + r(m)); break; //LDSH
|
||||
}
|
||||
}
|
||||
|
||||
auto ARM7TDMI::thumbInstructionMoveStack
|
||||
(n8 immediate, n3 d, n1 mode) -> void {
|
||||
switch(mode) {
|
||||
case 0: store(Word | Nonsequential, r(13) + immediate * 4, r(d)); break; //STR
|
||||
case 1: r(d) = load(Word | Nonsequential, r(13) + immediate * 4); break; //LDR
|
||||
case 0: store(Word, r(13) + immediate * 4, r(d)); break; //STR
|
||||
case 1: r(d) = load(Word, r(13) + immediate * 4); break; //LDR
|
||||
}
|
||||
}
|
||||
|
||||
auto ARM7TDMI::thumbInstructionMoveWordImmediate
|
||||
(n3 d, n3 n, n5 offset, n1 mode) -> void {
|
||||
switch(mode) {
|
||||
case 0: store(Word | Nonsequential, r(n) + offset * 4, r(d)); break; //STR
|
||||
case 1: r(d) = load(Word | Nonsequential, r(n) + offset * 4); break; //LDR
|
||||
case 0: store(Word, r(n) + offset * 4, r(d)); break; //STR
|
||||
case 1: r(d) = load(Word, r(n) + offset * 4); break; //LDR
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,33 +199,28 @@ auto ARM7TDMI::thumbInstructionSoftwareInterrupt
|
||||
auto ARM7TDMI::thumbInstructionStackMultiple
|
||||
(n8 list, n1 lrpc, n1 mode) -> void {
|
||||
n32 sp = r(13);
|
||||
n32 bitCount = (list | lrpc) ? (bit::count(list) + lrpc) : 16;
|
||||
n16 rlist = list;
|
||||
if(lrpc) {
|
||||
if(mode == 1) rlist.bit(15) = 1; //POP
|
||||
if(mode == 0) rlist.bit(14) = 1; //PUSH
|
||||
}
|
||||
n32 bitCount = rlist ? bit::count(rlist) : 16;
|
||||
if(mode == 1) r(13) = r(13) + bitCount * 4; //POP
|
||||
if(mode == 0) sp = sp - bitCount * 4 + 0; //PUSH
|
||||
|
||||
u32 sequential = Nonsequential;
|
||||
if(bitCount == 16) {
|
||||
if(mode == 1) r(15) = read(Word | sequential, sp); //POP
|
||||
if(mode == 0) write(Word | sequential, sp, r(15) + 2); //PUSH
|
||||
} else {
|
||||
for(u32 m : range(8)) {
|
||||
if(!list.bit(m)) continue;
|
||||
if(mode == 1) r(m) = read(Word | sequential, sp); //POP
|
||||
if(mode == 0) write(Word | sequential, sp, r(m)); //PUSH
|
||||
sp += 4;
|
||||
sequential = Sequential;
|
||||
}
|
||||
}
|
||||
if(lrpc) {
|
||||
if(mode == 1) r(15) = read(Word | sequential, sp); //POP
|
||||
if(mode == 0) write(Word | sequential, sp, r(14)); //PUSH
|
||||
endBurst();
|
||||
if(!rlist) rlist.bit(15) = 1;
|
||||
for(u32 m : range(16)) {
|
||||
if(!rlist.bit(m)) continue;
|
||||
if(mode == 1) r(m) = read(Word, sp); //POP
|
||||
if(mode == 0) write(Word, sp, r(m) + (m == 15 ? 2 : 0)); //PUSH
|
||||
sp += 4;
|
||||
}
|
||||
|
||||
if(mode) {
|
||||
idle();
|
||||
} else {
|
||||
pipeline.nonsequential = true;
|
||||
endBurst();
|
||||
r(13) = r(13) - bitCount * 4; //PUSH
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
auto ARM7TDMI::idle() -> void {
|
||||
pipeline.nonsequential = true;
|
||||
endBurst();
|
||||
sleep();
|
||||
}
|
||||
|
||||
auto ARM7TDMI::read(u32 mode, n32 address) -> n32 {
|
||||
return get(mode, address);
|
||||
n32 word = get(mode, address);
|
||||
nonsequential = false; //allows burst transfer to continue
|
||||
return word;
|
||||
}
|
||||
|
||||
auto ARM7TDMI::load(u32 mode, n32 address) -> n32 {
|
||||
pipeline.nonsequential = true;
|
||||
endBurst();
|
||||
auto word = get(Load | mode, address);
|
||||
if(mode & Half) {
|
||||
address &= 1;
|
||||
@@ -28,12 +30,13 @@ auto ARM7TDMI::load(u32 mode, n32 address) -> n32 {
|
||||
}
|
||||
|
||||
auto ARM7TDMI::write(u32 mode, n32 address, n32 word) -> void {
|
||||
pipeline.nonsequential = true;
|
||||
return set(mode, address, word);
|
||||
set(mode, address, word);
|
||||
nonsequential = false; //allows burst transfer to continue
|
||||
return;
|
||||
}
|
||||
|
||||
auto ARM7TDMI::store(u32 mode, n32 address, n32 word) -> void {
|
||||
pipeline.nonsequential = true;
|
||||
endBurst();
|
||||
if(mode & Half) { word &= 0xffff; word |= word << 16; }
|
||||
if(mode & Byte) { word &= 0xff; word |= word << 8; word |= word << 16; }
|
||||
return set(Store | mode, address, word);
|
||||
|
||||
@@ -14,20 +14,24 @@ inline auto ARM7TDMI::r(n4 index) -> GPR& {
|
||||
case 11: return processor.cpsr.m == PSR::FIQ ? processor.fiq.r11 : processor.r11;
|
||||
case 12: return processor.cpsr.m == PSR::FIQ ? processor.fiq.r12 : processor.r12;
|
||||
case 13: switch(processor.cpsr.m) {
|
||||
case PSR::USR: return processor.r13;
|
||||
case PSR::FIQ: return processor.fiq.r13;
|
||||
case PSR::IRQ: return processor.irq.r13;
|
||||
case PSR::SVC: return processor.svc.r13;
|
||||
case PSR::ABT: return processor.abt.r13;
|
||||
case PSR::UND: return processor.und.r13;
|
||||
default: return processor.r13;
|
||||
case PSR::SYS: return processor.r13;
|
||||
default: return processor.rNULL;
|
||||
}
|
||||
case 14: switch(processor.cpsr.m) {
|
||||
case PSR::USR: return processor.r14;
|
||||
case PSR::FIQ: return processor.fiq.r14;
|
||||
case PSR::IRQ: return processor.irq.r14;
|
||||
case PSR::SVC: return processor.svc.r14;
|
||||
case PSR::ABT: return processor.abt.r14;
|
||||
case PSR::UND: return processor.und.r14;
|
||||
default: return processor.r14;
|
||||
case PSR::SYS: return processor.r14;
|
||||
default: return processor.rNULL;
|
||||
}
|
||||
case 15: return processor.r15;
|
||||
}
|
||||
@@ -46,7 +50,7 @@ inline auto ARM7TDMI::spsr() -> PSR& {
|
||||
case PSR::ABT: return processor.abt.spsr;
|
||||
case PSR::UND: return processor.und.spsr;
|
||||
}
|
||||
throw;
|
||||
return processor.spsrNULL;
|
||||
}
|
||||
|
||||
inline auto ARM7TDMI::privileged() const -> bool {
|
||||
|
||||
@@ -3,6 +3,7 @@ auto ARM7TDMI::serialize(serializer& s) -> void {
|
||||
s(pipeline);
|
||||
s(carry);
|
||||
s(irq);
|
||||
s(nonsequential);
|
||||
}
|
||||
|
||||
auto ARM7TDMI::Processor::serialize(serializer& s) -> void {
|
||||
@@ -23,6 +24,8 @@ auto ARM7TDMI::Processor::serialize(serializer& s) -> void {
|
||||
s(r14.data);
|
||||
s(r15.data);
|
||||
s(cpsr);
|
||||
s(rNULL.data);
|
||||
s(spsrNULL);
|
||||
s(fiq.r8.data);
|
||||
s(fiq.r9.data);
|
||||
s(fiq.r10.data);
|
||||
@@ -54,18 +57,21 @@ auto ARM7TDMI::PSR::serialize(serializer& s) -> void {
|
||||
s(c);
|
||||
s(z);
|
||||
s(n);
|
||||
s(readonly);
|
||||
}
|
||||
|
||||
auto ARM7TDMI::Pipeline::serialize(serializer& s) -> void {
|
||||
s(reload);
|
||||
s(nonsequential);
|
||||
s(fetch.address);
|
||||
s(fetch.instruction);
|
||||
s(fetch.thumb);
|
||||
s(fetch.irq);
|
||||
s(decode.address);
|
||||
s(decode.instruction);
|
||||
s(decode.thumb);
|
||||
s(decode.irq);
|
||||
s(execute.address);
|
||||
s(execute.instruction);
|
||||
s(execute.thumb);
|
||||
s(execute.irq);
|
||||
}
|
||||
@@ -37,56 +37,56 @@ auto GSU::disassembleOpcode(char* output) -> void {
|
||||
auto GSU::disassembleALT0(char* output) -> void {
|
||||
char t[256] = "";
|
||||
switch(op0) {
|
||||
case (0x00): sprintf(t, "stop"); break;
|
||||
case (0x01): sprintf(t, "nop"); break;
|
||||
case (0x02): sprintf(t, "cache"); break;
|
||||
case (0x03): sprintf(t, "lsr"); break;
|
||||
case (0x04): sprintf(t, "rol"); break;
|
||||
case (0x05): sprintf(t, "bra %+d", (s8)op1); break;
|
||||
case (0x06): sprintf(t, "blt %+d", (s8)op1); break;
|
||||
case (0x07): sprintf(t, "bge %+d", (s8)op1); break;
|
||||
case (0x08): sprintf(t, "bne %+d", (s8)op1); break;
|
||||
case (0x09): sprintf(t, "beq %+d", (s8)op1); break;
|
||||
case (0x0a): sprintf(t, "bpl %+d", (s8)op1); break;
|
||||
case (0x0b): sprintf(t, "bmi %+d", (s8)op1); break;
|
||||
case (0x0c): sprintf(t, "bcc %+d", (s8)op1); break;
|
||||
case (0x0d): sprintf(t, "bcs %+d", (s8)op1); break;
|
||||
case (0x0e): sprintf(t, "bvc %+d", (s8)op1); break;
|
||||
case (0x0f): sprintf(t, "bvs %+d", (s8)op1); break;
|
||||
case16(0x10): sprintf(t, "to r%u", op0 & 15); break;
|
||||
case16(0x20): sprintf(t, "with r%u", op0 & 15); break;
|
||||
case12(0x30): sprintf(t, "stw (r%u)", op0 & 15); break;
|
||||
case (0x3c): sprintf(t, "loop"); break;
|
||||
case (0x3d): sprintf(t, "alt1"); break;
|
||||
case (0x3e): sprintf(t, "alt2"); break;
|
||||
case (0x3f): sprintf(t, "alt3"); break;
|
||||
case12(0x40): sprintf(t, "ldw (r%u)", op0 & 15); break;
|
||||
case (0x4c): sprintf(t, "plot"); break;
|
||||
case (0x4d): sprintf(t, "swap"); break;
|
||||
case (0x4e): sprintf(t, "color"); break;
|
||||
case (0x4f): sprintf(t, "not"); break;
|
||||
case16(0x50): sprintf(t, "add r%u", op0 & 15); break;
|
||||
case16(0x60): sprintf(t, "sub r%u", op0 & 15); break;
|
||||
case (0x70): sprintf(t, "merge"); break;
|
||||
case15(0x71): sprintf(t, "and r%u", op0 & 15); break;
|
||||
case16(0x80): sprintf(t, "mult r%u", op0 & 15); break;
|
||||
case (0x90): sprintf(t, "sbk"); break;
|
||||
case4 (0x91): sprintf(t, "link #%u", op0 & 15); break;
|
||||
case (0x95): sprintf(t, "sex"); break;
|
||||
case (0x96): sprintf(t, "asr"); break;
|
||||
case (0x97): sprintf(t, "ror"); break;
|
||||
case6 (0x98): sprintf(t, "jmp r%u", op0 & 15); break;
|
||||
case (0x9e): sprintf(t, "lob"); break;
|
||||
case (0x9f): sprintf(t, "fmult"); break;
|
||||
case16(0xa0): sprintf(t, "ibt r%u,#$%.2x", op0 & 15, op1 & 255); break;
|
||||
case16(0xb0): sprintf(t, "from r%u", op0 & 15); break;
|
||||
case (0xc0): sprintf(t, "hib"); break;
|
||||
case15(0xc1): sprintf(t, "or r%u", op0 & 15); break;
|
||||
case15(0xd0): sprintf(t, "inc r%u", op0 & 15); break;
|
||||
case (0xdf): sprintf(t, "getc"); break;
|
||||
case15(0xe0): sprintf(t, "dec r%u", op0 & 15); break;
|
||||
case (0xef): sprintf(t, "getb"); break;
|
||||
case16(0xf0): sprintf(t, "iwt r%u,#$%.2x%.2x", op0 & 15, op2 & 255, op1 & 255); break;
|
||||
case (0x00):snprintf(t, sizeof(t), "stop"); break;
|
||||
case (0x01):snprintf(t, sizeof(t), "nop"); break;
|
||||
case (0x02):snprintf(t, sizeof(t), "cache"); break;
|
||||
case (0x03):snprintf(t, sizeof(t), "lsr"); break;
|
||||
case (0x04):snprintf(t, sizeof(t), "rol"); break;
|
||||
case (0x05):snprintf(t, sizeof(t), "bra %+d", (s8)op1); break;
|
||||
case (0x06):snprintf(t, sizeof(t), "blt %+d", (s8)op1); break;
|
||||
case (0x07):snprintf(t, sizeof(t), "bge %+d", (s8)op1); break;
|
||||
case (0x08):snprintf(t, sizeof(t), "bne %+d", (s8)op1); break;
|
||||
case (0x09):snprintf(t, sizeof(t), "beq %+d", (s8)op1); break;
|
||||
case (0x0a):snprintf(t, sizeof(t), "bpl %+d", (s8)op1); break;
|
||||
case (0x0b):snprintf(t, sizeof(t), "bmi %+d", (s8)op1); break;
|
||||
case (0x0c):snprintf(t, sizeof(t), "bcc %+d", (s8)op1); break;
|
||||
case (0x0d):snprintf(t, sizeof(t), "bcs %+d", (s8)op1); break;
|
||||
case (0x0e):snprintf(t, sizeof(t), "bvc %+d", (s8)op1); break;
|
||||
case (0x0f):snprintf(t, sizeof(t), "bvs %+d", (s8)op1); break;
|
||||
case16(0x10):snprintf(t, sizeof(t), "to r%u", op0 & 15); break;
|
||||
case16(0x20):snprintf(t, sizeof(t), "with r%u", op0 & 15); break;
|
||||
case12(0x30):snprintf(t, sizeof(t), "stw (r%u)", op0 & 15); break;
|
||||
case (0x3c):snprintf(t, sizeof(t), "loop"); break;
|
||||
case (0x3d):snprintf(t, sizeof(t), "alt1"); break;
|
||||
case (0x3e):snprintf(t, sizeof(t), "alt2"); break;
|
||||
case (0x3f):snprintf(t, sizeof(t), "alt3"); break;
|
||||
case12(0x40):snprintf(t, sizeof(t), "ldw (r%u)", op0 & 15); break;
|
||||
case (0x4c):snprintf(t, sizeof(t), "plot"); break;
|
||||
case (0x4d):snprintf(t, sizeof(t), "swap"); break;
|
||||
case (0x4e):snprintf(t, sizeof(t), "color"); break;
|
||||
case (0x4f):snprintf(t, sizeof(t), "not"); break;
|
||||
case16(0x50):snprintf(t, sizeof(t), "add r%u", op0 & 15); break;
|
||||
case16(0x60):snprintf(t, sizeof(t), "sub r%u", op0 & 15); break;
|
||||
case (0x70):snprintf(t, sizeof(t), "merge"); break;
|
||||
case15(0x71):snprintf(t, sizeof(t), "and r%u", op0 & 15); break;
|
||||
case16(0x80):snprintf(t, sizeof(t), "mult r%u", op0 & 15); break;
|
||||
case (0x90):snprintf(t, sizeof(t), "sbk"); break;
|
||||
case4 (0x91):snprintf(t, sizeof(t), "link #%u", op0 & 15); break;
|
||||
case (0x95):snprintf(t, sizeof(t), "sex"); break;
|
||||
case (0x96):snprintf(t, sizeof(t), "asr"); break;
|
||||
case (0x97):snprintf(t, sizeof(t), "ror"); break;
|
||||
case6 (0x98):snprintf(t, sizeof(t), "jmp r%u", op0 & 15); break;
|
||||
case (0x9e):snprintf(t, sizeof(t), "lob"); break;
|
||||
case (0x9f):snprintf(t, sizeof(t), "fmult"); break;
|
||||
case16(0xa0):snprintf(t, sizeof(t), "ibt r%u,#$%.2x", op0 & 15, op1 & 255); break;
|
||||
case16(0xb0):snprintf(t, sizeof(t), "from r%u", op0 & 15); break;
|
||||
case (0xc0):snprintf(t, sizeof(t), "hib"); break;
|
||||
case15(0xc1):snprintf(t, sizeof(t), "or r%u", op0 & 15); break;
|
||||
case15(0xd0):snprintf(t, sizeof(t), "inc r%u", op0 & 15); break;
|
||||
case (0xdf):snprintf(t, sizeof(t), "getc"); break;
|
||||
case15(0xe0):snprintf(t, sizeof(t), "dec r%u", op0 & 15); break;
|
||||
case (0xef):snprintf(t, sizeof(t), "getb"); break;
|
||||
case16(0xf0):snprintf(t, sizeof(t), "iwt r%u,#$%.2x%.2x", op0 & 15, op2 & 255, op1 & 255); break;
|
||||
}
|
||||
strcat(output, t);
|
||||
}
|
||||
@@ -94,56 +94,56 @@ auto GSU::disassembleALT0(char* output) -> void {
|
||||
auto GSU::disassembleALT1(char* output) -> void {
|
||||
char t[256] = "";
|
||||
switch(op0) {
|
||||
case (0x00): sprintf(t, "stop"); break;
|
||||
case (0x01): sprintf(t, "nop"); break;
|
||||
case (0x02): sprintf(t, "cache"); break;
|
||||
case (0x03): sprintf(t, "lsr"); break;
|
||||
case (0x04): sprintf(t, "rol"); break;
|
||||
case (0x05): sprintf(t, "bra %+d", (s8)op1); break;
|
||||
case (0x06): sprintf(t, "blt %+d", (s8)op1); break;
|
||||
case (0x07): sprintf(t, "bge %+d", (s8)op1); break;
|
||||
case (0x08): sprintf(t, "bne %+d", (s8)op1); break;
|
||||
case (0x09): sprintf(t, "beq %+d", (s8)op1); break;
|
||||
case (0x0a): sprintf(t, "bpl %+d", (s8)op1); break;
|
||||
case (0x0b): sprintf(t, "bmi %+d", (s8)op1); break;
|
||||
case (0x0c): sprintf(t, "bcc %+d", (s8)op1); break;
|
||||
case (0x0d): sprintf(t, "bcs %+d", (s8)op1); break;
|
||||
case (0x0e): sprintf(t, "bvc %+d", (s8)op1); break;
|
||||
case (0x0f): sprintf(t, "bvs %+d", (s8)op1); break;
|
||||
case16(0x10): sprintf(t, "to r%u", op0 & 15); break;
|
||||
case16(0x20): sprintf(t, "with r%u", op0 & 15); break;
|
||||
case12(0x30): sprintf(t, "stb (r%u)", op0 & 15); break;
|
||||
case (0x3c): sprintf(t, "loop"); break;
|
||||
case (0x3d): sprintf(t, "alt1"); break;
|
||||
case (0x3e): sprintf(t, "alt2"); break;
|
||||
case (0x3f): sprintf(t, "alt3"); break;
|
||||
case12(0x40): sprintf(t, "ldb (r%u)", op0 & 15); break;
|
||||
case (0x4c): sprintf(t, "rpix"); break;
|
||||
case (0x4d): sprintf(t, "swap"); break;
|
||||
case (0x4e): sprintf(t, "cmode"); break;
|
||||
case (0x4f): sprintf(t, "not"); break;
|
||||
case16(0x50): sprintf(t, "adc r%u", op0 & 15); break;
|
||||
case16(0x60): sprintf(t, "sbc r%u", op0 & 15); break;
|
||||
case (0x70): sprintf(t, "merge"); break;
|
||||
case15(0x71): sprintf(t, "bic r%u", op0 & 15); break;
|
||||
case16(0x80): sprintf(t, "umult r%u", op0 & 15); break;
|
||||
case (0x90): sprintf(t, "sbk"); break;
|
||||
case4 (0x91): sprintf(t, "link #%u", op0 & 15); break;
|
||||
case (0x95): sprintf(t, "sex"); break;
|
||||
case (0x96): sprintf(t, "div2"); break;
|
||||
case (0x97): sprintf(t, "ror"); break;
|
||||
case6 (0x98): sprintf(t, "ljmp r%u", op0 & 15); break;
|
||||
case (0x9e): sprintf(t, "lob"); break;
|
||||
case (0x9f): sprintf(t, "lmult"); break;
|
||||
case16(0xa0): sprintf(t, "lms r%u,(#$%.4x)", op0 & 15, op1 << 1); break;
|
||||
case16(0xb0): sprintf(t, "from r%u", op0 & 15); break;
|
||||
case (0xc0): sprintf(t, "hib"); break;
|
||||
case15(0xc1): sprintf(t, "xor r%u", op0 & 15); break;
|
||||
case15(0xd0): sprintf(t, "inc r%u", op0 & 15); break;
|
||||
case (0xdf): sprintf(t, "getc"); break;
|
||||
case15(0xe0): sprintf(t, "dec r%u", op0 & 15); break;
|
||||
case (0xef): sprintf(t, "getbh"); break;
|
||||
case16(0xf0): sprintf(t, "lm r%u", op0 & 15); break;
|
||||
case (0x00):snprintf(t, sizeof(t), "stop"); break;
|
||||
case (0x01):snprintf(t, sizeof(t), "nop"); break;
|
||||
case (0x02):snprintf(t, sizeof(t), "cache"); break;
|
||||
case (0x03):snprintf(t, sizeof(t), "lsr"); break;
|
||||
case (0x04):snprintf(t, sizeof(t), "rol"); break;
|
||||
case (0x05):snprintf(t, sizeof(t), "bra %+d", (s8)op1); break;
|
||||
case (0x06):snprintf(t, sizeof(t), "blt %+d", (s8)op1); break;
|
||||
case (0x07):snprintf(t, sizeof(t), "bge %+d", (s8)op1); break;
|
||||
case (0x08):snprintf(t, sizeof(t), "bne %+d", (s8)op1); break;
|
||||
case (0x09):snprintf(t, sizeof(t), "beq %+d", (s8)op1); break;
|
||||
case (0x0a):snprintf(t, sizeof(t), "bpl %+d", (s8)op1); break;
|
||||
case (0x0b):snprintf(t, sizeof(t), "bmi %+d", (s8)op1); break;
|
||||
case (0x0c):snprintf(t, sizeof(t), "bcc %+d", (s8)op1); break;
|
||||
case (0x0d):snprintf(t, sizeof(t), "bcs %+d", (s8)op1); break;
|
||||
case (0x0e):snprintf(t, sizeof(t), "bvc %+d", (s8)op1); break;
|
||||
case (0x0f):snprintf(t, sizeof(t), "bvs %+d", (s8)op1); break;
|
||||
case16(0x10):snprintf(t, sizeof(t), "to r%u", op0 & 15); break;
|
||||
case16(0x20):snprintf(t, sizeof(t), "with r%u", op0 & 15); break;
|
||||
case12(0x30):snprintf(t, sizeof(t), "stb (r%u)", op0 & 15); break;
|
||||
case (0x3c):snprintf(t, sizeof(t), "loop"); break;
|
||||
case (0x3d):snprintf(t, sizeof(t), "alt1"); break;
|
||||
case (0x3e):snprintf(t, sizeof(t), "alt2"); break;
|
||||
case (0x3f):snprintf(t, sizeof(t), "alt3"); break;
|
||||
case12(0x40):snprintf(t, sizeof(t), "ldb (r%u)", op0 & 15); break;
|
||||
case (0x4c):snprintf(t, sizeof(t), "rpix"); break;
|
||||
case (0x4d):snprintf(t, sizeof(t), "swap"); break;
|
||||
case (0x4e):snprintf(t, sizeof(t), "cmode"); break;
|
||||
case (0x4f):snprintf(t, sizeof(t), "not"); break;
|
||||
case16(0x50):snprintf(t, sizeof(t), "adc r%u", op0 & 15); break;
|
||||
case16(0x60):snprintf(t, sizeof(t), "sbc r%u", op0 & 15); break;
|
||||
case (0x70):snprintf(t, sizeof(t), "merge"); break;
|
||||
case15(0x71):snprintf(t, sizeof(t), "bic r%u", op0 & 15); break;
|
||||
case16(0x80):snprintf(t, sizeof(t), "umult r%u", op0 & 15); break;
|
||||
case (0x90):snprintf(t, sizeof(t), "sbk"); break;
|
||||
case4 (0x91):snprintf(t, sizeof(t), "link #%u", op0 & 15); break;
|
||||
case (0x95):snprintf(t, sizeof(t), "sex"); break;
|
||||
case (0x96):snprintf(t, sizeof(t), "div2"); break;
|
||||
case (0x97):snprintf(t, sizeof(t), "ror"); break;
|
||||
case6 (0x98):snprintf(t, sizeof(t), "ljmp r%u", op0 & 15); break;
|
||||
case (0x9e):snprintf(t, sizeof(t), "lob"); break;
|
||||
case (0x9f):snprintf(t, sizeof(t), "lmult"); break;
|
||||
case16(0xa0):snprintf(t, sizeof(t), "lms r%u,(#$%.4x)", op0 & 15, op1 << 1); break;
|
||||
case16(0xb0):snprintf(t, sizeof(t), "from r%u", op0 & 15); break;
|
||||
case (0xc0):snprintf(t, sizeof(t), "hib"); break;
|
||||
case15(0xc1):snprintf(t, sizeof(t), "xor r%u", op0 & 15); break;
|
||||
case15(0xd0):snprintf(t, sizeof(t), "inc r%u", op0 & 15); break;
|
||||
case (0xdf):snprintf(t, sizeof(t), "getc"); break;
|
||||
case15(0xe0):snprintf(t, sizeof(t), "dec r%u", op0 & 15); break;
|
||||
case (0xef):snprintf(t, sizeof(t), "getbh"); break;
|
||||
case16(0xf0):snprintf(t, sizeof(t), "lm r%u", op0 & 15); break;
|
||||
}
|
||||
strcat(output, t);
|
||||
}
|
||||
@@ -151,56 +151,56 @@ auto GSU::disassembleALT1(char* output) -> void {
|
||||
auto GSU::disassembleALT2(char* output) -> void {
|
||||
char t[256] = "";
|
||||
switch(op0) {
|
||||
case (0x00): sprintf(t, "stop"); break;
|
||||
case (0x01): sprintf(t, "nop"); break;
|
||||
case (0x02): sprintf(t, "cache"); break;
|
||||
case (0x03): sprintf(t, "lsr"); break;
|
||||
case (0x04): sprintf(t, "rol"); break;
|
||||
case (0x05): sprintf(t, "bra %+d", (s8)op1); break;
|
||||
case (0x06): sprintf(t, "blt %+d", (s8)op1); break;
|
||||
case (0x07): sprintf(t, "bge %+d", (s8)op1); break;
|
||||
case (0x08): sprintf(t, "bne %+d", (s8)op1); break;
|
||||
case (0x09): sprintf(t, "beq %+d", (s8)op1); break;
|
||||
case (0x0a): sprintf(t, "bpl %+d", (s8)op1); break;
|
||||
case (0x0b): sprintf(t, "bmi %+d", (s8)op1); break;
|
||||
case (0x0c): sprintf(t, "bcc %+d", (s8)op1); break;
|
||||
case (0x0d): sprintf(t, "bcs %+d", (s8)op1); break;
|
||||
case (0x0e): sprintf(t, "bvc %+d", (s8)op1); break;
|
||||
case (0x0f): sprintf(t, "bvs %+d", (s8)op1); break;
|
||||
case16(0x10): sprintf(t, "to r%u", op0 & 15); break;
|
||||
case16(0x20): sprintf(t, "with r%u", op0 & 15); break;
|
||||
case12(0x30): sprintf(t, "stw (r%u)", op0 & 15); break;
|
||||
case (0x3c): sprintf(t, "loop"); break;
|
||||
case (0x3d): sprintf(t, "alt1"); break;
|
||||
case (0x3e): sprintf(t, "alt2"); break;
|
||||
case (0x3f): sprintf(t, "alt3"); break;
|
||||
case12(0x40): sprintf(t, "ldw (r%u)", op0 & 15); break;
|
||||
case (0x4c): sprintf(t, "plot"); break;
|
||||
case (0x4d): sprintf(t, "swap"); break;
|
||||
case (0x4e): sprintf(t, "color"); break;
|
||||
case (0x4f): sprintf(t, "not"); break;
|
||||
case16(0x50): sprintf(t, "add #%u", op0 & 15); break;
|
||||
case16(0x60): sprintf(t, "sub #%u", op0 & 15); break;
|
||||
case (0x70): sprintf(t, "merge"); break;
|
||||
case15(0x71): sprintf(t, "and #%u", op0 & 15); break;
|
||||
case16(0x80): sprintf(t, "mult #%u", op0 & 15); break;
|
||||
case (0x90): sprintf(t, "sbk"); break;
|
||||
case4 (0x91): sprintf(t, "link #%u", op0 & 15); break;
|
||||
case (0x95): sprintf(t, "sex"); break;
|
||||
case (0x96): sprintf(t, "asr"); break;
|
||||
case (0x97): sprintf(t, "ror"); break;
|
||||
case6 (0x98): sprintf(t, "jmp r%u", op0 & 15); break;
|
||||
case (0x9e): sprintf(t, "lob"); break;
|
||||
case (0x9f): sprintf(t, "fmult"); break;
|
||||
case16(0xa0): sprintf(t, "sms r%u,(#$%.4x)", op0 & 15, op1 << 1); break;
|
||||
case16(0xb0): sprintf(t, "from r%u", op0 & 15); break;
|
||||
case (0xc0): sprintf(t, "hib"); break;
|
||||
case15(0xc1): sprintf(t, "or #%u", op0 & 15); break;
|
||||
case15(0xd0): sprintf(t, "inc r%u", op0 & 15); break;
|
||||
case (0xdf): sprintf(t, "ramb"); break;
|
||||
case15(0xe0): sprintf(t, "dec r%u", op0 & 15); break;
|
||||
case (0xef): sprintf(t, "getbl"); break;
|
||||
case16(0xf0): sprintf(t, "sm r%u", op0 & 15); break;
|
||||
case (0x00):snprintf(t, sizeof(t), "stop"); break;
|
||||
case (0x01):snprintf(t, sizeof(t), "nop"); break;
|
||||
case (0x02):snprintf(t, sizeof(t), "cache"); break;
|
||||
case (0x03):snprintf(t, sizeof(t), "lsr"); break;
|
||||
case (0x04):snprintf(t, sizeof(t), "rol"); break;
|
||||
case (0x05):snprintf(t, sizeof(t), "bra %+d", (s8)op1); break;
|
||||
case (0x06):snprintf(t, sizeof(t), "blt %+d", (s8)op1); break;
|
||||
case (0x07):snprintf(t, sizeof(t), "bge %+d", (s8)op1); break;
|
||||
case (0x08):snprintf(t, sizeof(t), "bne %+d", (s8)op1); break;
|
||||
case (0x09):snprintf(t, sizeof(t), "beq %+d", (s8)op1); break;
|
||||
case (0x0a):snprintf(t, sizeof(t), "bpl %+d", (s8)op1); break;
|
||||
case (0x0b):snprintf(t, sizeof(t), "bmi %+d", (s8)op1); break;
|
||||
case (0x0c):snprintf(t, sizeof(t), "bcc %+d", (s8)op1); break;
|
||||
case (0x0d):snprintf(t, sizeof(t), "bcs %+d", (s8)op1); break;
|
||||
case (0x0e):snprintf(t, sizeof(t), "bvc %+d", (s8)op1); break;
|
||||
case (0x0f):snprintf(t, sizeof(t), "bvs %+d", (s8)op1); break;
|
||||
case16(0x10):snprintf(t, sizeof(t), "to r%u", op0 & 15); break;
|
||||
case16(0x20):snprintf(t, sizeof(t), "with r%u", op0 & 15); break;
|
||||
case12(0x30):snprintf(t, sizeof(t), "stw (r%u)", op0 & 15); break;
|
||||
case (0x3c):snprintf(t, sizeof(t), "loop"); break;
|
||||
case (0x3d):snprintf(t, sizeof(t), "alt1"); break;
|
||||
case (0x3e):snprintf(t, sizeof(t), "alt2"); break;
|
||||
case (0x3f):snprintf(t, sizeof(t), "alt3"); break;
|
||||
case12(0x40):snprintf(t, sizeof(t), "ldw (r%u)", op0 & 15); break;
|
||||
case (0x4c):snprintf(t, sizeof(t), "plot"); break;
|
||||
case (0x4d):snprintf(t, sizeof(t), "swap"); break;
|
||||
case (0x4e):snprintf(t, sizeof(t), "color"); break;
|
||||
case (0x4f):snprintf(t, sizeof(t), "not"); break;
|
||||
case16(0x50):snprintf(t, sizeof(t), "add #%u", op0 & 15); break;
|
||||
case16(0x60):snprintf(t, sizeof(t), "sub #%u", op0 & 15); break;
|
||||
case (0x70):snprintf(t, sizeof(t), "merge"); break;
|
||||
case15(0x71):snprintf(t, sizeof(t), "and #%u", op0 & 15); break;
|
||||
case16(0x80):snprintf(t, sizeof(t), "mult #%u", op0 & 15); break;
|
||||
case (0x90):snprintf(t, sizeof(t), "sbk"); break;
|
||||
case4 (0x91):snprintf(t, sizeof(t), "link #%u", op0 & 15); break;
|
||||
case (0x95):snprintf(t, sizeof(t), "sex"); break;
|
||||
case (0x96):snprintf(t, sizeof(t), "asr"); break;
|
||||
case (0x97):snprintf(t, sizeof(t), "ror"); break;
|
||||
case6 (0x98):snprintf(t, sizeof(t), "jmp r%u", op0 & 15); break;
|
||||
case (0x9e):snprintf(t, sizeof(t), "lob"); break;
|
||||
case (0x9f):snprintf(t, sizeof(t), "fmult"); break;
|
||||
case16(0xa0):snprintf(t, sizeof(t), "sms r%u,(#$%.4x)", op0 & 15, op1 << 1); break;
|
||||
case16(0xb0):snprintf(t, sizeof(t), "from r%u", op0 & 15); break;
|
||||
case (0xc0):snprintf(t, sizeof(t), "hib"); break;
|
||||
case15(0xc1):snprintf(t, sizeof(t), "or #%u", op0 & 15); break;
|
||||
case15(0xd0):snprintf(t, sizeof(t), "inc r%u", op0 & 15); break;
|
||||
case (0xdf):snprintf(t, sizeof(t), "ramb"); break;
|
||||
case15(0xe0):snprintf(t, sizeof(t), "dec r%u", op0 & 15); break;
|
||||
case (0xef):snprintf(t, sizeof(t), "getbl"); break;
|
||||
case16(0xf0):snprintf(t, sizeof(t), "sm r%u", op0 & 15); break;
|
||||
}
|
||||
strcat(output, t);
|
||||
}
|
||||
@@ -208,56 +208,56 @@ auto GSU::disassembleALT2(char* output) -> void {
|
||||
auto GSU::disassembleALT3(char* output) -> void {
|
||||
char t[256] = "";
|
||||
switch(op0) {
|
||||
case (0x00): sprintf(t, "stop"); break;
|
||||
case (0x01): sprintf(t, "nop"); break;
|
||||
case (0x02): sprintf(t, "cache"); break;
|
||||
case (0x03): sprintf(t, "lsr"); break;
|
||||
case (0x04): sprintf(t, "rol"); break;
|
||||
case (0x05): sprintf(t, "bra %+d", (s8)op1); break;
|
||||
case (0x06): sprintf(t, "blt %+d", (s8)op1); break;
|
||||
case (0x07): sprintf(t, "bge %+d", (s8)op1); break;
|
||||
case (0x08): sprintf(t, "bne %+d", (s8)op1); break;
|
||||
case (0x09): sprintf(t, "beq %+d", (s8)op1); break;
|
||||
case (0x0a): sprintf(t, "bpl %+d", (s8)op1); break;
|
||||
case (0x0b): sprintf(t, "bmi %+d", (s8)op1); break;
|
||||
case (0x0c): sprintf(t, "bcc %+d", (s8)op1); break;
|
||||
case (0x0d): sprintf(t, "bcs %+d", (s8)op1); break;
|
||||
case (0x0e): sprintf(t, "bvc %+d", (s8)op1); break;
|
||||
case (0x0f): sprintf(t, "bvs %+d", (s8)op1); break;
|
||||
case16(0x10): sprintf(t, "to r%u", op0 & 15); break;
|
||||
case16(0x20): sprintf(t, "with r%u", op0 & 15); break;
|
||||
case12(0x30): sprintf(t, "stb (r%u)", op0 & 15); break;
|
||||
case (0x3c): sprintf(t, "loop"); break;
|
||||
case (0x3d): sprintf(t, "alt1"); break;
|
||||
case (0x3e): sprintf(t, "alt2"); break;
|
||||
case (0x3f): sprintf(t, "alt3"); break;
|
||||
case12(0x40): sprintf(t, "ldb (r%u)", op0 & 15); break;
|
||||
case (0x4c): sprintf(t, "rpix"); break;
|
||||
case (0x4d): sprintf(t, "swap"); break;
|
||||
case (0x4e): sprintf(t, "cmode"); break;
|
||||
case (0x4f): sprintf(t, "not"); break;
|
||||
case16(0x50): sprintf(t, "adc #%u", op0 & 15); break;
|
||||
case16(0x60): sprintf(t, "cmp r%u", op0 & 15); break;
|
||||
case (0x70): sprintf(t, "merge"); break;
|
||||
case15(0x71): sprintf(t, "bic #%u", op0 & 15); break;
|
||||
case16(0x80): sprintf(t, "umult #%u", op0 & 15); break;
|
||||
case (0x90): sprintf(t, "sbk"); break;
|
||||
case4 (0x91): sprintf(t, "link #%u", op0 & 15); break;
|
||||
case (0x95): sprintf(t, "sex"); break;
|
||||
case (0x96): sprintf(t, "div2"); break;
|
||||
case (0x97): sprintf(t, "ror"); break;
|
||||
case6 (0x98): sprintf(t, "ljmp r%u", op0 & 15); break;
|
||||
case (0x9e): sprintf(t, "lob"); break;
|
||||
case (0x9f): sprintf(t, "lmult"); break;
|
||||
case16(0xa0): sprintf(t, "lms r%u", op0 & 15); break;
|
||||
case16(0xb0): sprintf(t, "from r%u", op0 & 15); break;
|
||||
case (0xc0): sprintf(t, "hib"); break;
|
||||
case15(0xc1): sprintf(t, "xor #%u", op0 & 15); break;
|
||||
case15(0xd0): sprintf(t, "inc r%u", op0 & 15); break;
|
||||
case (0xdf): sprintf(t, "romb"); break;
|
||||
case15(0xe0): sprintf(t, "dec r%u", op0 & 15); break;
|
||||
case (0xef): sprintf(t, "getbs"); break;
|
||||
case16(0xf0): sprintf(t, "lm r%u", op0 & 15); break;
|
||||
case (0x00):snprintf(t, sizeof(t), "stop"); break;
|
||||
case (0x01):snprintf(t, sizeof(t), "nop"); break;
|
||||
case (0x02):snprintf(t, sizeof(t), "cache"); break;
|
||||
case (0x03):snprintf(t, sizeof(t), "lsr"); break;
|
||||
case (0x04):snprintf(t, sizeof(t), "rol"); break;
|
||||
case (0x05):snprintf(t, sizeof(t), "bra %+d", (s8)op1); break;
|
||||
case (0x06):snprintf(t, sizeof(t), "blt %+d", (s8)op1); break;
|
||||
case (0x07):snprintf(t, sizeof(t), "bge %+d", (s8)op1); break;
|
||||
case (0x08):snprintf(t, sizeof(t), "bne %+d", (s8)op1); break;
|
||||
case (0x09):snprintf(t, sizeof(t), "beq %+d", (s8)op1); break;
|
||||
case (0x0a):snprintf(t, sizeof(t), "bpl %+d", (s8)op1); break;
|
||||
case (0x0b):snprintf(t, sizeof(t), "bmi %+d", (s8)op1); break;
|
||||
case (0x0c):snprintf(t, sizeof(t), "bcc %+d", (s8)op1); break;
|
||||
case (0x0d):snprintf(t, sizeof(t), "bcs %+d", (s8)op1); break;
|
||||
case (0x0e):snprintf(t, sizeof(t), "bvc %+d", (s8)op1); break;
|
||||
case (0x0f):snprintf(t, sizeof(t), "bvs %+d", (s8)op1); break;
|
||||
case16(0x10):snprintf(t, sizeof(t), "to r%u", op0 & 15); break;
|
||||
case16(0x20):snprintf(t, sizeof(t), "with r%u", op0 & 15); break;
|
||||
case12(0x30):snprintf(t, sizeof(t), "stb (r%u)", op0 & 15); break;
|
||||
case (0x3c):snprintf(t, sizeof(t), "loop"); break;
|
||||
case (0x3d):snprintf(t, sizeof(t), "alt1"); break;
|
||||
case (0x3e):snprintf(t, sizeof(t), "alt2"); break;
|
||||
case (0x3f):snprintf(t, sizeof(t), "alt3"); break;
|
||||
case12(0x40):snprintf(t, sizeof(t), "ldb (r%u)", op0 & 15); break;
|
||||
case (0x4c):snprintf(t, sizeof(t), "rpix"); break;
|
||||
case (0x4d):snprintf(t, sizeof(t), "swap"); break;
|
||||
case (0x4e):snprintf(t, sizeof(t), "cmode"); break;
|
||||
case (0x4f):snprintf(t, sizeof(t), "not"); break;
|
||||
case16(0x50):snprintf(t, sizeof(t), "adc #%u", op0 & 15); break;
|
||||
case16(0x60):snprintf(t, sizeof(t), "cmp r%u", op0 & 15); break;
|
||||
case (0x70):snprintf(t, sizeof(t), "merge"); break;
|
||||
case15(0x71):snprintf(t, sizeof(t), "bic #%u", op0 & 15); break;
|
||||
case16(0x80):snprintf(t, sizeof(t), "umult #%u", op0 & 15); break;
|
||||
case (0x90):snprintf(t, sizeof(t), "sbk"); break;
|
||||
case4 (0x91):snprintf(t, sizeof(t), "link #%u", op0 & 15); break;
|
||||
case (0x95):snprintf(t, sizeof(t), "sex"); break;
|
||||
case (0x96):snprintf(t, sizeof(t), "div2"); break;
|
||||
case (0x97):snprintf(t, sizeof(t), "ror"); break;
|
||||
case6 (0x98):snprintf(t, sizeof(t), "ljmp r%u", op0 & 15); break;
|
||||
case (0x9e):snprintf(t, sizeof(t), "lob"); break;
|
||||
case (0x9f):snprintf(t, sizeof(t), "lmult"); break;
|
||||
case16(0xa0):snprintf(t, sizeof(t), "lms r%u", op0 & 15); break;
|
||||
case16(0xb0):snprintf(t, sizeof(t), "from r%u", op0 & 15); break;
|
||||
case (0xc0):snprintf(t, sizeof(t), "hib"); break;
|
||||
case15(0xc1):snprintf(t, sizeof(t), "xor #%u", op0 & 15); break;
|
||||
case15(0xd0):snprintf(t, sizeof(t), "inc r%u", op0 & 15); break;
|
||||
case (0xdf):snprintf(t, sizeof(t), "romb"); break;
|
||||
case15(0xe0):snprintf(t, sizeof(t), "dec r%u", op0 & 15); break;
|
||||
case (0xef):snprintf(t, sizeof(t), "getbs"); break;
|
||||
case16(0xf0):snprintf(t, sizeof(t), "lm r%u", op0 & 15); break;
|
||||
}
|
||||
strcat(output, t);
|
||||
}
|
||||
|
||||
@@ -338,28 +338,27 @@ template<u32 Size> auto M68000::instructionBTST(EffectiveAddress with) -> void {
|
||||
}
|
||||
|
||||
auto M68000::instructionCHK(DataRegister compare, EffectiveAddress maximum) -> void {
|
||||
auto source = read<Word>(maximum);
|
||||
auto target = read<Word>(compare);
|
||||
auto result = (n64)target - source;
|
||||
r.c = sign<Word>(result >> 1) < 0;
|
||||
r.v = sign<Word>((target ^ source) & (target ^ result)) < 0;
|
||||
r.z = clip<Word>(result) == 0;
|
||||
r.n = sign<Word>(result) < 0;
|
||||
r.n ^= r.v;
|
||||
prefetch();
|
||||
auto source = read<Word>(compare);
|
||||
auto target = read<Word>(maximum);
|
||||
CMP<Word>(source, target);
|
||||
idle(2);
|
||||
bool bound = r.n || r.v;
|
||||
CMP<Word>(0, source);
|
||||
idle(2);
|
||||
|
||||
if(!r.n && !r.z) {
|
||||
if(bound) {
|
||||
prefetched();
|
||||
return exception(Exception::BoundsCheck, Vector::BoundsCheck);
|
||||
}
|
||||
|
||||
r.z = clip<Word>(target) == 0;
|
||||
r.n = sign<Word>(target) < 0;
|
||||
idle(2);
|
||||
|
||||
if(r.n) {
|
||||
idle(2);
|
||||
prefetched();
|
||||
return exception(Exception::BoundsCheck, Vector::BoundsCheck);
|
||||
}
|
||||
|
||||
idle(6);
|
||||
prefetch();
|
||||
}
|
||||
|
||||
template<u32 Size> auto M68000::instructionCLR(EffectiveAddress with) -> void {
|
||||
|
||||
@@ -43,7 +43,6 @@ auto M68000::power() -> void {
|
||||
auto M68000::supervisor() -> bool {
|
||||
if(r.s) return true;
|
||||
|
||||
r.pc -= 4;
|
||||
exception(Exception::Unprivileged, Vector::Unprivileged);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -513,19 +513,19 @@ auto SH2::MOVI(u32 i, u32 n) -> void {
|
||||
}
|
||||
|
||||
//MOV.W @(disp,PC),Rn
|
||||
NALL_NOINLINE auto SH2::MOVWI(u32 d, u32 n) -> void {
|
||||
auto SH2::MOVWI(u32 d, u32 n) -> void {
|
||||
u32 pc = inDelaySlot() ? PPC - 2 : PC;
|
||||
R[n] = (s16)readWord(pc + d * 2);
|
||||
}
|
||||
|
||||
//MOV.L @(disp,PC),Rn
|
||||
NALL_NOINLINE auto SH2::MOVLI(u32 d, u32 n) -> void {
|
||||
auto SH2::MOVLI(u32 d, u32 n) -> void {
|
||||
u32 pc = inDelaySlot() ? PPC - 2 : PC;
|
||||
R[n] = readLong((pc & ~3) + d * 4);
|
||||
}
|
||||
|
||||
//MOVA @(disp,PC),R0
|
||||
NALL_NOINLINE auto SH2::MOVA(u32 d) -> void {
|
||||
auto SH2::MOVA(u32 d) -> void {
|
||||
u32 pc = inDelaySlot() ? PPC - 2 : PC;
|
||||
R[0] = (pc & ~3) + d * 4;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ auto SH2::Recompiler::emit(u32 address) -> Block* {
|
||||
u16 instruction = instructions[index++];
|
||||
if(callInstructionPrologue) {
|
||||
mov32(reg(1), imm(instruction));
|
||||
call(&SH2::instructionPrologue);
|
||||
call(&SH2::instructionPrologueTrampoline);
|
||||
}
|
||||
auto branch = emitInstruction(instruction);
|
||||
inDelaySlot = branch == Branch::Slot;
|
||||
|
||||
@@ -65,8 +65,8 @@ auto SH2::power(bool reset) -> void {
|
||||
|
||||
if constexpr(Accuracy::Recompiler) {
|
||||
if(!reset) {
|
||||
auto buffer = ares::Memory::FixedAllocator::get().tryAcquire(64_MiB);
|
||||
recompiler.allocator.resize(64_MiB, bump_allocator::executable, buffer);
|
||||
auto buffer = ares::Memory::FixedAllocator::get().tryAcquire(32_MiB);
|
||||
recompiler.allocator.resize(32_MiB, bump_allocator::executable, buffer);
|
||||
}
|
||||
recompiler.reset();
|
||||
}
|
||||
|
||||
@@ -249,6 +249,10 @@ struct SH2 {
|
||||
s32 cyclesUntilRecompilerExit = 0;
|
||||
s32 recompilerStepCycles = 0;
|
||||
|
||||
auto instructionPrologueTrampoline(u16 instruction) -> void {
|
||||
return instructionPrologue(instruction); //virtual function call
|
||||
}
|
||||
|
||||
struct Recompiler : recompiler::generic {
|
||||
SH2& self;
|
||||
Recompiler(SH2& self) : self(self), generic(allocator) {}
|
||||
@@ -279,7 +283,8 @@ struct SH2 {
|
||||
auto reset() -> void {
|
||||
generation = 0;
|
||||
blocks.reset();
|
||||
for(u32 index : range(1 << 24)) pools[index] = nullptr;
|
||||
pools.reallocate(1 << 24);
|
||||
pools.fill();
|
||||
}
|
||||
|
||||
auto invalidateCached() -> void {
|
||||
@@ -307,7 +312,7 @@ struct SH2 {
|
||||
bump_allocator allocator;
|
||||
hashset<BlockHashPair> blocks;
|
||||
u16 instructions[1 << 7];
|
||||
Pool* pools[1 << 24];
|
||||
vector<Pool*> pools;
|
||||
} recompiler{*this};
|
||||
|
||||
#include "sh7604/sh7604.hpp"
|
||||
|
||||
@@ -105,8 +105,6 @@ auto SH2::Cache::purge() -> void {
|
||||
}
|
||||
|
||||
auto SH2::Cache::power() -> void {
|
||||
purge(4 * 256);
|
||||
|
||||
for(n6 n : range(64)) {
|
||||
if(n.bit(5) == 1 && n.bit(4) == 1 && n.bit(3) == 1) { lruSelect[n] = 0; continue; }
|
||||
if(n.bit(5) == 0 && n.bit(2) == 1 && n.bit(1) == 1) { lruSelect[n] = 1; continue; }
|
||||
|
||||
@@ -150,6 +150,7 @@ auto SH2::internalReadByte(u32 address, n8 data) -> n8 {
|
||||
data.bit(5) = wdt.wtcsr.tme;
|
||||
data.bit(6) = wdt.wtcsr.wtit;
|
||||
data.bit(7) = wdt.wtcsr.ovf;
|
||||
if(wdt.wtcsr.wtit) debug(unimplemented, "SH2: wdt.wtit = 1");
|
||||
return data;
|
||||
|
||||
//WTCNT: watchdog timer counter
|
||||
|
||||
@@ -216,7 +216,7 @@
|
||||
//watchdog timer
|
||||
struct WDT {
|
||||
//timer.cpp
|
||||
auto run() -> void;
|
||||
auto run(int cycles) -> void;
|
||||
|
||||
//serialization.cpp
|
||||
auto serialize(serializer&) -> void;
|
||||
@@ -282,7 +282,7 @@
|
||||
maybe<SH2&> self;
|
||||
|
||||
//timer.cpp
|
||||
auto run() -> void;
|
||||
auto run(int cycles) -> void;
|
||||
|
||||
//serialization.cpp
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
@@ -1,43 +1,45 @@
|
||||
auto SH2::FRT::run() -> void {
|
||||
auto SH2::FRT::run(int cycles) -> void {
|
||||
static constexpr u32 frequencies[4] = {8, 32, 128, 1};
|
||||
auto frequency = frequencies[tcr.cks];
|
||||
|
||||
if(++counter >= frequencies[tcr.cks]) {
|
||||
counter -= frequencies[tcr.cks];
|
||||
if(++frc == 0) {
|
||||
ftcsr.ovf = 1;
|
||||
if(tier.ovie) {
|
||||
pendingOutputIRQ = 1;
|
||||
}
|
||||
}
|
||||
if(frc == ocra) {
|
||||
ftcsr.ocfa = 1;
|
||||
if(tier.ociae) {
|
||||
pendingOutputIRQ = 1;
|
||||
}
|
||||
if(ftcsr.cclra) {
|
||||
frc = 0;
|
||||
}
|
||||
}
|
||||
if(frc == ocrb) {
|
||||
ftcsr.ocfb = 1;
|
||||
if(tier.ocibe) {
|
||||
pendingOutputIRQ = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
counter += cycles;
|
||||
auto increments = counter / frequency;
|
||||
counter -= increments * frequency;
|
||||
|
||||
if (!increments) return;
|
||||
|
||||
auto prevFrc = frc;
|
||||
frc += increments;
|
||||
|
||||
ftcsr.ovf |= (frc < prevFrc);
|
||||
ftcsr.ocfa |= (u32(ocra - 1 - prevFrc) < increments);
|
||||
ftcsr.ocfb |= (u32(ocrb - 1 - prevFrc) < increments);
|
||||
|
||||
pendingOutputIRQ |= (tier.ovie & ftcsr.ovf) |
|
||||
(tier.ociae & ftcsr.ocfa) |
|
||||
(tier.ocibe & ftcsr.ocfb);
|
||||
|
||||
if (ftcsr.cclra && ftcsr.ocfa) frc = 0;
|
||||
}
|
||||
auto SH2::WDT::run() -> void {
|
||||
|
||||
auto SH2::WDT::run(int cycles) -> void {
|
||||
static constexpr u32 frequencies[8] = {2, 64, 128, 256, 512, 1024, 4096, 8192};
|
||||
|
||||
if(!wtcsr.tme) return;
|
||||
if(wtcsr.wtit) return; // Watchdog mode currently unsupported
|
||||
if(!wtcsr.tme || wtcsr.wtit) return; //watchdog mode (wtit) currently unsupported
|
||||
|
||||
if(++counter >= frequencies[wtcsr.cks]) {
|
||||
counter -= frequencies[wtcsr.cks];
|
||||
auto frequency = frequencies[wtcsr.cks];
|
||||
|
||||
if(++wtcnt == 0) {
|
||||
wtcsr.ovf = 1;
|
||||
pendingIRQ = 1;
|
||||
}
|
||||
counter += cycles;
|
||||
auto increments = counter / frequency;
|
||||
counter %= frequency;
|
||||
|
||||
if(!increments) return;
|
||||
|
||||
auto prevWtcnt = wtcnt;
|
||||
wtcnt += increments;
|
||||
|
||||
if (wtcnt < prevWtcnt) {
|
||||
wtcsr.ovf = 1;
|
||||
pendingIRQ = 1;
|
||||
}
|
||||
}
|
||||
@@ -42,17 +42,20 @@ auto V30MZ::interrupt(u8 vector, InterruptSource source) -> bool {
|
||||
|
||||
auto V30MZ::interrupt(u8 vector) -> bool {
|
||||
state.halt = false;
|
||||
if(!PSW.IE) return false;
|
||||
if(!state.interrupt || !PSW.IE) return false;
|
||||
return interrupt(vector, InterruptSource::INT);
|
||||
}
|
||||
|
||||
auto V30MZ::nonMaskableInterrupt() -> bool {
|
||||
return interrupt(2, InterruptSource::NMI);
|
||||
auto V30MZ::nonMaskableInterrupt(bool value) -> bool {
|
||||
state.nmi = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define op(id, name, ...) case id: instruction##name(__VA_ARGS__); break;
|
||||
|
||||
auto V30MZ::instruction() -> void {
|
||||
state.brk = PSW.BRK;
|
||||
state.interrupt = PSW.IE;
|
||||
state.poll = 1;
|
||||
state.prefix = 0;
|
||||
if(state.halt) return wait(1);
|
||||
@@ -317,7 +320,8 @@ auto V30MZ::instruction() -> void {
|
||||
}
|
||||
|
||||
if(!state.prefix) prefixFlush();
|
||||
if(PSW.BRK) interrupt(1, InterruptSource::SingleStep);
|
||||
if(state.poll && state.nmi) interrupt(2, InterruptSource::NMI);
|
||||
if(state.poll && state.brk) interrupt(1, InterruptSource::SingleStep);
|
||||
}
|
||||
|
||||
#undef op
|
||||
@@ -105,7 +105,6 @@ auto V30MZ::instructionReturnInt() -> void {
|
||||
PS = pop();
|
||||
PSW = pop();
|
||||
flush();
|
||||
state.poll = 0;
|
||||
}
|
||||
|
||||
auto V30MZ::instructionInt3() -> void {
|
||||
@@ -182,7 +181,6 @@ auto V30MZ::instructionPushFlags() -> void {
|
||||
auto V30MZ::instructionPopFlags() -> void {
|
||||
wait(2);
|
||||
PSW = pop();
|
||||
state.poll = 0;
|
||||
}
|
||||
|
||||
auto V30MZ::instructionPushAll() -> void {
|
||||
|
||||
@@ -21,5 +21,4 @@ auto V30MZ::instructionClearFlag(u32 bit) -> void {
|
||||
auto V30MZ::instructionSetFlag(u32 bit) -> void {
|
||||
wait(4);
|
||||
PSW |= 1 << bit;
|
||||
if(bit == PSW.IE.bit()) state.poll = 0;
|
||||
}
|
||||
@@ -43,21 +43,27 @@ auto V30MZ::instructionUndefined1() -> void {
|
||||
}
|
||||
|
||||
template<u32 size> auto V30MZ::instructionIn() -> void {
|
||||
wait(6);
|
||||
// TODO: The exact cycle on which I/O access is performed remains unknown.
|
||||
wait(5);
|
||||
setAccumulator<size>(in<size>(fetch<Byte>()));
|
||||
wait(1);
|
||||
}
|
||||
|
||||
template<u32 size> auto V30MZ::instructionOut() -> void {
|
||||
// TODO: The exact cycle on which I/O access is performed remains unknown.
|
||||
wait(6);
|
||||
out<size>(fetch<Byte>(), getAccumulator<size>());
|
||||
}
|
||||
|
||||
template<u32 size> auto V30MZ::instructionInDW() -> void {
|
||||
wait(5);
|
||||
// TODO: The exact cycle on which I/O access is performed remains unknown.
|
||||
wait(4);
|
||||
setAccumulator<size>(in<size>(DW));
|
||||
wait(1);
|
||||
}
|
||||
|
||||
template<u32 size> auto V30MZ::instructionOutDW() -> void {
|
||||
// TODO: The exact cycle on which I/O access is performed remains unknown.
|
||||
wait(5);
|
||||
out<size>(DW, getAccumulator<size>());
|
||||
}
|
||||
|
||||
@@ -14,14 +14,14 @@ auto V30MZ::instructionMoveMemSeg() -> void {
|
||||
wait(1);
|
||||
modRM();
|
||||
setMemory<Word>(getSegment());
|
||||
state.poll = 0;
|
||||
}
|
||||
|
||||
auto V30MZ::instructionMoveSegMem() -> void {
|
||||
wait(2);
|
||||
modRM();
|
||||
setSegment(getMemory<Word>());
|
||||
if((modrm.reg & 3) == 3) state.poll = 0;
|
||||
// delay interrupt polling if stack segment changed
|
||||
if((modrm.reg & 3) == 2) state.poll = 0;
|
||||
}
|
||||
|
||||
template<u32 size> auto V30MZ::instructionMoveAccMem() -> void {
|
||||
|
||||
@@ -2,6 +2,9 @@ auto V30MZ::serialize(serializer& s) -> void {
|
||||
s(state.halt);
|
||||
s(state.poll);
|
||||
s(state.prefix);
|
||||
s(state.interrupt);
|
||||
s(state.brk);
|
||||
s(state.nmi);
|
||||
|
||||
s(opcode);
|
||||
|
||||
|
||||
@@ -26,6 +26,9 @@ auto V30MZ::power() -> void {
|
||||
state.halt = 0;
|
||||
state.poll = 1;
|
||||
state.prefix = 0;
|
||||
state.interrupt = 0;
|
||||
state.brk = 0;
|
||||
state.nmi = 0;
|
||||
|
||||
opcode = 0;
|
||||
prefixFlush();
|
||||
|
||||
@@ -41,7 +41,7 @@ struct V30MZ {
|
||||
//instruction.cpp
|
||||
auto prefixFlush() -> void;
|
||||
auto interrupt(u8 vector) -> bool;
|
||||
auto nonMaskableInterrupt() -> bool;
|
||||
auto nonMaskableInterrupt(bool value) -> bool;
|
||||
auto instruction() -> void;
|
||||
|
||||
//registers.cpp
|
||||
@@ -237,9 +237,12 @@ struct V30MZ {
|
||||
auto disassembleContext() -> string;
|
||||
|
||||
struct State {
|
||||
bool halt; //set to true for hlt instruction; blocks execution until next interrupt
|
||||
bool poll; //set to false to suppress interrupt polling between CPU instructions
|
||||
bool prefix; //set to true for prefix instructions; prevents flushing of Prefix struct
|
||||
bool halt; //set to true for hlt instruction; blocks execution until next interrupt
|
||||
bool poll; //set to false to suppress interrupt polling between CPU instructions
|
||||
bool prefix; //set to true for prefix instructions; prevents flushing of Prefix struct
|
||||
bool interrupt; //interrupt enable processor status before CPU instruction execution
|
||||
bool brk; //breakpoint enable processor status before CPU instruction execution
|
||||
bool nmi; //non-maskable interrupt requested
|
||||
} state;
|
||||
|
||||
u8 opcode;
|
||||
|
||||
@@ -0,0 +1,286 @@
|
||||
#include <ares/ares.hpp>
|
||||
#include "s3511a.hpp"
|
||||
|
||||
namespace ares {
|
||||
|
||||
#include "serialization.cpp"
|
||||
|
||||
//calculate time between last play of game and current time;
|
||||
//increment RTC by said amount of seconds
|
||||
auto S3511A::load() -> void {
|
||||
n64 timestamp = 0;
|
||||
for(auto n : range(8)) timestamp.byte(n) = data[8 + n];
|
||||
if(!timestamp || !(timestamp + 1)) return initRegs(false); //new save file
|
||||
|
||||
if(status() & 0x15) {
|
||||
//these status bits are always 0; reset state on invalid status.
|
||||
initRegs(false);
|
||||
return;
|
||||
}
|
||||
|
||||
timestamp = time(0) - timestamp;
|
||||
//prevent insurmountable slowdown by limiting skips to 5 years
|
||||
if(timestamp < 60*60*24*365*5) {
|
||||
while(timestamp--) tickSecond();
|
||||
}
|
||||
}
|
||||
|
||||
//save time when game is unloaded
|
||||
auto S3511A::save() -> void {
|
||||
n64 timestamp = time(0);
|
||||
for(auto n : range(8)) data[8 + n] = timestamp.byte(n);
|
||||
}
|
||||
|
||||
auto S3511A::power() -> void {
|
||||
cs = 0;
|
||||
sio = 0;
|
||||
sck = 0;
|
||||
inBuffer = 0;
|
||||
outBuffer = 0;
|
||||
shift = 0;
|
||||
index = 0;
|
||||
rwSelect = 0;
|
||||
regSelect = 0;
|
||||
cmdLatched = 0;
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
auto S3511A::tickSecond() -> void {
|
||||
static auto bcdIncrement = [](n8& data) -> n8 {
|
||||
if ((data & 0x0F) >= 0x09) {
|
||||
data = (data & 0xF0) + 0x10;
|
||||
} else {
|
||||
data++;
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
if(bcdIncrement(second()) < 0x60) return;
|
||||
second() = 0;
|
||||
|
||||
if(bcdIncrement(minute()) < 0x60) return;
|
||||
minute() = 0;
|
||||
|
||||
if(status() & 0x40) {
|
||||
//24-hour clock
|
||||
if((bcdIncrement(hour()) & 0x7F) < 0x24) return;
|
||||
hour().bit(0,5) = 0;
|
||||
} else {
|
||||
//12-hour clock
|
||||
if((bcdIncrement(hour()) & 0x7F) < 0x12) return;
|
||||
hour().bit(0,5) = 0;
|
||||
hour().bit(7) ^= 1;
|
||||
}
|
||||
|
||||
weekday() += 1;
|
||||
weekday() %= 7;
|
||||
|
||||
u32 bcdDaysInMonth[12] = {0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31};
|
||||
if(year() && !(year() & 3)) bcdDaysInMonth[1]++;
|
||||
|
||||
if(bcdIncrement(day()) <= bcdDaysInMonth[month()]) return;
|
||||
day() = 1;
|
||||
|
||||
if(bcdIncrement(month()) <= 0x12) return;
|
||||
month() = 1;
|
||||
|
||||
bcdIncrement(year());
|
||||
}
|
||||
|
||||
auto S3511A::checkAlarm() -> void {
|
||||
//todo: a lot of this is vaguely informed guesswork.
|
||||
if(status() & 0x08) {
|
||||
//per-minute edge/steady
|
||||
if(counter < 256) irqLevel(1);
|
||||
if(status() & 0x02 && second() == 0x30 && counter == 0) irqLevel(0);
|
||||
} else if(status() & 0x02) {
|
||||
//selected frequency steady
|
||||
n16 duty = (counter << 1) ^ 0xFFFF;
|
||||
n16 mask = (alarmHour() | (alarmMinute() << 8));
|
||||
irqLevel((duty & mask) != 0);
|
||||
} else if(status() & 0x20) {
|
||||
//alarm
|
||||
if(status() & 0x40) {
|
||||
//24-hour clock
|
||||
irqLevel((hour() & 0x3F) == (alarmHour() & 0x3F) && (minute() & 0x7F) == (alarmMinute() & 0x7F));
|
||||
} else {
|
||||
//12-hour clock
|
||||
irqLevel((hour() & 0xBF) == (alarmHour() & 0xBF) && (minute() & 0x7F) == (alarmMinute() & 0x7F));
|
||||
}
|
||||
} else {
|
||||
irqLevel(0);
|
||||
}
|
||||
}
|
||||
|
||||
auto S3511A::readSIO() -> n1 {
|
||||
return sio | ~rwSelect | ~cs;
|
||||
}
|
||||
|
||||
auto S3511A::writeCS(n1 data) -> void {
|
||||
n1 csPrev = cs;
|
||||
cs = data;
|
||||
|
||||
//clear command status on falling edge
|
||||
if(csPrev == 1 && cs == 0) {
|
||||
inBuffer = 0x00;
|
||||
shift = 0;
|
||||
index = 0;
|
||||
rwSelect = 0;
|
||||
cmdLatched = 0;
|
||||
}
|
||||
}
|
||||
|
||||
auto S3511A::writeSIO(n1 data) -> void {
|
||||
sio = data;
|
||||
}
|
||||
|
||||
auto S3511A::writeSCK(n1 data) -> void {
|
||||
n1 sckPrev = sck | ~cs;
|
||||
sck = data;
|
||||
|
||||
//only read SIO data if CS is raised
|
||||
if(!cs) return;
|
||||
|
||||
//process command and output data on falling edge of SCK
|
||||
if(sckPrev == 1 && sck == 0) {
|
||||
if(!cmdLatched && shift == 0) writeCommand();
|
||||
if(cmdLatched && rwSelect == 1 && shift == 0) readRegister();
|
||||
sio = outBuffer.bit(shift);
|
||||
}
|
||||
|
||||
//sample RTC command data on rising edge of SCK
|
||||
if(sckPrev == 0 && sck == 1) {
|
||||
//add bit into input buffer
|
||||
inBuffer.bit(shift) = sio;
|
||||
shift++;
|
||||
if(cmdLatched && rwSelect == 0 && shift == 0) writeRegister();
|
||||
}
|
||||
}
|
||||
|
||||
auto S3511A::writeCommand() -> void {
|
||||
n4 magic = inBuffer >> 4;
|
||||
n4 cmd = inBuffer;
|
||||
if(magic != 0b0110) {
|
||||
//flip bit order of command
|
||||
magic = cmd;
|
||||
cmd.bit(0) = inBuffer.bit(7);
|
||||
cmd.bit(1) = inBuffer.bit(6);
|
||||
cmd.bit(2) = inBuffer.bit(5);
|
||||
cmd.bit(3) = inBuffer.bit(4);
|
||||
}
|
||||
if(magic != 0b0110) return; //invalid command
|
||||
rwSelect = cmd;
|
||||
regSelect = cmd >> 1;
|
||||
cmdLatched = 1;
|
||||
|
||||
//process any registers that have an effect on write without a payload
|
||||
if(rwSelect == 1) return;
|
||||
switch(regSelect) {
|
||||
case 0:
|
||||
//RESET
|
||||
initRegs(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto S3511A::readRegister() -> void {
|
||||
switch(regSelect) {
|
||||
case 1:
|
||||
//STATUS
|
||||
outBuffer = status();
|
||||
break;
|
||||
case 2: {
|
||||
//DATETIME
|
||||
switch(index) {
|
||||
case 0: outBuffer = year(); index++; break;
|
||||
case 1: outBuffer = month(); index++; break;
|
||||
case 2: outBuffer = day(); index++; break;
|
||||
case 3: outBuffer = weekday(); index++; break;
|
||||
case 4: outBuffer = hour(); index++; break;
|
||||
case 5: outBuffer = minute(); index++; break;
|
||||
default: outBuffer = second(); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
//TIME
|
||||
switch(index) {
|
||||
case 0: outBuffer = hour(); index++; break;
|
||||
case 1: outBuffer = minute(); index++; break;
|
||||
default: outBuffer = second(); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
//ALARM
|
||||
switch(index) {
|
||||
case 0: outBuffer = alarmHour(); index++; break;
|
||||
default: outBuffer = alarmMinute(); break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
outBuffer = 0xff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto S3511A::writeRegister() -> void {
|
||||
switch(regSelect) {
|
||||
case 1:
|
||||
//STATUS
|
||||
status().bit(1) = inBuffer.bit(1);
|
||||
status().bit(3) = inBuffer.bit(3);
|
||||
status().bit(5) = inBuffer.bit(5);
|
||||
status().bit(6) = inBuffer.bit(6);
|
||||
status().bit(7) &= inBuffer.bit(7);
|
||||
break;
|
||||
case 2: {
|
||||
//DATETIME
|
||||
switch(index) {
|
||||
case 0: year() = inBuffer; index++; break;
|
||||
case 1: month() = inBuffer; index++; break;
|
||||
case 2: day() = inBuffer; index++; break;
|
||||
case 3: weekday() = inBuffer; index++; break;
|
||||
case 4: hour() = inBuffer; index++; break;
|
||||
case 5: minute() = inBuffer; index++; break;
|
||||
default: second().bit(0,6) = inBuffer.bit(0,6); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
//TIME
|
||||
switch(index) {
|
||||
case 0: hour() = inBuffer; index++; break;
|
||||
case 1: minute() = inBuffer; index++; break;
|
||||
default: second().bit(0,6) = inBuffer.bit(0,6); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
//ALARM
|
||||
switch(index) {
|
||||
case 0: alarmHour() = inBuffer; index++; break;
|
||||
default: alarmMinute() = inBuffer; break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto S3511A::initRegs(bool reset) -> void {
|
||||
year() = 0;
|
||||
month() = 1;
|
||||
day() = 1;
|
||||
weekday() = 0;
|
||||
hour() = 0;
|
||||
minute() = 0;
|
||||
second() = 0;
|
||||
status() = reset ? 0x00 : 0x82;
|
||||
alarmHour() = 0x00;
|
||||
alarmMinute() = reset ? 0x00 : 0x80;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
namespace ares {
|
||||
|
||||
//Seiko S-3511A Real-Time Clock
|
||||
|
||||
struct S3511A {
|
||||
// bytes 0- 6: date/time data, BCD
|
||||
// bytes 7- 7: status register
|
||||
// bytes 8-15: last timestamp
|
||||
// bytes 16-17: alarm register
|
||||
static constexpr u32 size = 18;
|
||||
n8 data[size];
|
||||
|
||||
virtual auto irqLevel(bool value) -> void = 0;
|
||||
|
||||
//s3511a.cpp
|
||||
auto load() -> void;
|
||||
auto save() -> void;
|
||||
auto power() -> void;
|
||||
auto tickSecond() -> void;
|
||||
auto checkAlarm() -> void;
|
||||
auto readSIO() -> n1;
|
||||
auto writeCS(n1 data) -> void;
|
||||
auto writeSIO(n1 data) -> void;
|
||||
auto writeSCK(n1 data) -> void;
|
||||
auto writeCommand() -> void;
|
||||
auto readRegister() -> void;
|
||||
auto writeRegister() -> void;
|
||||
auto initRegs(bool reset) -> void;
|
||||
|
||||
//serialization.cpp
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
//pin states
|
||||
n1 cs;
|
||||
n1 sio;
|
||||
n1 sck;
|
||||
|
||||
//buffered command data
|
||||
n8 inBuffer;
|
||||
n8 outBuffer;
|
||||
n3 shift;
|
||||
n3 index;
|
||||
|
||||
//internal state
|
||||
n1 rwSelect;
|
||||
n3 regSelect;
|
||||
n1 cmdLatched;
|
||||
n15 counter;
|
||||
|
||||
auto year() -> n8& { return data[ 0]; }
|
||||
auto month() -> n8& { return data[ 1]; }
|
||||
auto day() -> n8& { return data[ 2]; }
|
||||
auto weekday() -> n8& { return data[ 3]; }
|
||||
auto hour() -> n8& { return data[ 4]; }
|
||||
auto minute() -> n8& { return data[ 5]; }
|
||||
auto second() -> n8& { return data[ 6]; }
|
||||
auto status() -> n8& { return data[ 7]; }
|
||||
auto alarmHour() -> n8& { return data[16]; }
|
||||
auto alarmMinute() -> n8& { return data[17]; }
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
auto S3511A::serialize(serializer& s) -> void {
|
||||
s(array_span<u8>{data, size});
|
||||
|
||||
s(cs);
|
||||
s(sio);
|
||||
s(sck);
|
||||
s(inBuffer);
|
||||
s(outBuffer);
|
||||
s(shift);
|
||||
s(index);
|
||||
s(rwSelect);
|
||||
s(regSelect);
|
||||
s(cmdLatched);
|
||||
s(counter);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
ares_components(z80 tms9918 sn76489)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
cv
|
||||
UNITY #
|
||||
cv.cpp
|
||||
PRIMARY #
|
||||
cpu/cpu.cpp
|
||||
vdp/vdp.cpp
|
||||
psg/psg.cpp
|
||||
system/system.cpp
|
||||
cartridge/cartridge.cpp
|
||||
controller/controller.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
cv
|
||||
INCLUDED #
|
||||
cv.hpp
|
||||
CMakeLists.txt
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
cv
|
||||
INCLUDED #
|
||||
cartridge/cartridge.hpp
|
||||
cartridge/serialization.cpp
|
||||
cartridge/slot.cpp
|
||||
cartridge/slot.hpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
cv
|
||||
INCLUDED #
|
||||
cartridge/board/board.cpp
|
||||
cartridge/board/board.hpp
|
||||
cartridge/board/coleco.cpp
|
||||
cartridge/board/megacart.cpp
|
||||
cartridge/board/xin1.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
cv
|
||||
INCLUDED #
|
||||
controller/controller.hpp
|
||||
controller/port.cpp
|
||||
controller/port.hpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
cv
|
||||
INCLUDED #
|
||||
controller/gamepad/gamepad.cpp
|
||||
controller/gamepad/gamepad.hpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
cv
|
||||
INCLUDED #
|
||||
cpu/cpu.hpp
|
||||
cpu/debugger.cpp
|
||||
cpu/memory.cpp
|
||||
cpu/serialization.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
cv
|
||||
INCLUDED #
|
||||
psg/psg.hpp
|
||||
psg/serialization.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
cv
|
||||
INCLUDED #
|
||||
system/controls.cpp
|
||||
system/serialization.cpp
|
||||
system/system.hpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
cv
|
||||
INCLUDED #
|
||||
vdp/color.cpp
|
||||
vdp/serialization.cpp
|
||||
vdp/vdp.hpp
|
||||
)
|
||||
@@ -1,17 +0,0 @@
|
||||
ares.components += z80
|
||||
ares.components += tms9918
|
||||
ares.components += sn76489
|
||||
|
||||
ares.objects += ares-cv-cpu
|
||||
ares.objects += ares-cv-vdp
|
||||
ares.objects += ares-cv-psg
|
||||
ares.objects += ares-cv-system
|
||||
ares.objects += ares-cv-cartridge
|
||||
ares.objects += ares-cv-controller
|
||||
|
||||
$(object.path)/ares-cv-cpu.o: $(ares.path)/cv/cpu/cpu.cpp
|
||||
$(object.path)/ares-cv-vdp.o: $(ares.path)/cv/vdp/vdp.cpp
|
||||
$(object.path)/ares-cv-psg.o: $(ares.path)/cv/psg/psg.cpp
|
||||
$(object.path)/ares-cv-system.o: $(ares.path)/cv/system/system.cpp
|
||||
$(object.path)/ares-cv-cartridge.o: $(ares.path)/cv/cartridge/cartridge.cpp
|
||||
$(object.path)/ares-cv-controller.o: $(ares.path)/cv/controller/controller.cpp
|
||||
@@ -0,0 +1,8 @@
|
||||
//started: 2019-02-19
|
||||
|
||||
#include <cv/cpu/cpu.cpp>
|
||||
#include <cv/vdp/vdp.cpp>
|
||||
#include <cv/psg/psg.cpp>
|
||||
#include <cv/system/system.cpp>
|
||||
#include <cv/cartridge/cartridge.cpp>
|
||||
#include <cv/controller/controller.cpp>
|
||||
@@ -56,6 +56,7 @@ auto System::load(Node::System& root, string name) -> bool {
|
||||
}
|
||||
|
||||
node = Node::System::create(information.name);
|
||||
node->setAttribute("configuration", name);
|
||||
node->setGame({&System::game, this});
|
||||
node->setRun({&System::run, this});
|
||||
node->setPower({&System::power, this});
|
||||
|
||||
+4
-4
@@ -44,10 +44,10 @@ auto VDP::frame() -> void {
|
||||
screen->setSize(284, 243);
|
||||
screen->setViewport(0, 0, 284, 243);
|
||||
} else {
|
||||
int x = 16;
|
||||
int y = 16;
|
||||
int width = 284 - 32;
|
||||
int height = 243 - 32;
|
||||
int x = 13;
|
||||
int y = 27;
|
||||
int width = 284 - 28;
|
||||
int height = 243 - 51;
|
||||
|
||||
screen->setSize(width, height);
|
||||
screen->setViewport(x, y, width, height);
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
ares_components(
|
||||
mos6502
|
||||
ym2149
|
||||
ym2413
|
||||
m24c
|
||||
sst39sf0x0
|
||||
)
|
||||
|
||||
target_link_libraries(ares PRIVATE ymfm)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
fc
|
||||
UNITY #
|
||||
fc.cpp
|
||||
PRIMARY #
|
||||
system/system.cpp
|
||||
controller/controller.cpp
|
||||
expansion/expansion.cpp
|
||||
cartridge/cartridge.cpp
|
||||
cpu/cpu.cpp
|
||||
apu/apu.cpp
|
||||
ppu/ppu.cpp
|
||||
fds/fds.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(CORE fc INCLUDED fc.hpp CMakeLists.txt)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
fc
|
||||
INCLUDED #
|
||||
apu/apu.hpp
|
||||
apu/dmc.cpp
|
||||
apu/envelope.cpp
|
||||
apu/framecounter.cpp
|
||||
apu/length.cpp
|
||||
apu/noise.cpp
|
||||
apu/pulse.cpp
|
||||
apu/serialization.cpp
|
||||
apu/sweep.cpp
|
||||
apu/triangle.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
fc
|
||||
INCLUDED #
|
||||
cartridge/cartridge.hpp
|
||||
cartridge/serialization.cpp
|
||||
cartridge/slot.cpp
|
||||
cartridge/slot.hpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
fc
|
||||
INCLUDED #
|
||||
cartridge/board/action53.cpp
|
||||
cartridge/board/ave-nina-001.cpp
|
||||
cartridge/board/ave-nina-06.cpp
|
||||
cartridge/board/bandai-74161.cpp
|
||||
cartridge/board/bandai-fcg.cpp
|
||||
cartridge/board/bandai-karaoke.cpp
|
||||
cartridge/board/bandai-lz93d50.cpp
|
||||
cartridge/board/bandai-oeka.cpp
|
||||
cartridge/board/board.cpp
|
||||
cartridge/board/board.hpp
|
||||
cartridge/board/camerica-bf909x.cpp
|
||||
cartridge/board/colordreams-74x377.cpp
|
||||
cartridge/board/gtrom.cpp
|
||||
cartridge/board/hvc-axrom.cpp
|
||||
cartridge/board/hvc-bnrom.cpp
|
||||
cartridge/board/hvc-cnrom.cpp
|
||||
cartridge/board/hvc-exrom.cpp
|
||||
cartridge/board/hvc-fmr.cpp
|
||||
cartridge/board/hvc-fxrom.cpp
|
||||
cartridge/board/hvc-gxrom.cpp
|
||||
cartridge/board/hvc-hkrom.cpp
|
||||
cartridge/board/hvc-nrom.cpp
|
||||
cartridge/board/hvc-pxrom.cpp
|
||||
cartridge/board/hvc-sxrom.cpp
|
||||
cartridge/board/hvc-txrom.cpp
|
||||
cartridge/board/hvc-uxrom.cpp
|
||||
cartridge/board/inl-nsf.cpp
|
||||
cartridge/board/irem-g101.cpp
|
||||
cartridge/board/irem-h3001.cpp
|
||||
cartridge/board/irem-lrog017.cpp
|
||||
cartridge/board/irem-tam-s1.cpp
|
||||
cartridge/board/jaleco-jf05.cpp
|
||||
cartridge/board/jaleco-jf11.cpp
|
||||
cartridge/board/jaleco-jf16.cpp
|
||||
cartridge/board/jaleco-jf17.cpp
|
||||
cartridge/board/jaleco-jf23.cpp
|
||||
cartridge/board/konami-vrc1.cpp
|
||||
cartridge/board/konami-vrc2.cpp
|
||||
cartridge/board/konami-vrc3.cpp
|
||||
cartridge/board/konami-vrc4.cpp
|
||||
cartridge/board/konami-vrc5.cpp
|
||||
cartridge/board/konami-vrc6.cpp
|
||||
cartridge/board/konami-vrc7.cpp
|
||||
cartridge/board/magicfloor.cpp
|
||||
cartridge/board/mlt-action52.cpp
|
||||
cartridge/board/namco-118.cpp
|
||||
cartridge/board/namco-163.cpp
|
||||
cartridge/board/namco-340.cpp
|
||||
cartridge/board/sunsoft-1.cpp
|
||||
cartridge/board/sunsoft-2.cpp
|
||||
cartridge/board/sunsoft-3.cpp
|
||||
cartridge/board/sunsoft-4.cpp
|
||||
cartridge/board/sunsoft-5b.cpp
|
||||
cartridge/board/taito-tc0190.cpp
|
||||
cartridge/board/taito-tc0690.cpp
|
||||
cartridge/board/taito-x1-005.cpp
|
||||
cartridge/board/taito-x1-017.cpp
|
||||
cartridge/board/tengen-80003x.cpp
|
||||
cartridge/board/unl-bmc.cpp
|
||||
cartridge/board/unl-sachen-74ls374n.cpp
|
||||
cartridge/board/unl-sachen-sa0037.cpp
|
||||
cartridge/board/unl-txc.cpp
|
||||
cartridge/board/unrom-512.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
fc
|
||||
INCLUDED #
|
||||
cartridge/board/ic/jv001.hpp
|
||||
cartridge/board/ic/txc05-00002-010.hpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
fc
|
||||
INCLUDED #
|
||||
controller/controller.hpp
|
||||
controller/port.cpp
|
||||
controller/port.hpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
fc
|
||||
INCLUDED #
|
||||
controller/gamepad/gamepad.cpp
|
||||
controller/gamepad/gamepad.hpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
fc
|
||||
INCLUDED #
|
||||
cpu/cpu.hpp
|
||||
cpu/debugger.cpp
|
||||
cpu/memory.cpp
|
||||
cpu/serialization.cpp
|
||||
cpu/timing.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
fc
|
||||
INCLUDED #
|
||||
expansion/expansion.hpp
|
||||
expansion/port.cpp
|
||||
expansion/port.hpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
fc
|
||||
INCLUDED #
|
||||
expansion/epsm/epsm.cpp
|
||||
expansion/epsm/epsm.hpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
fc
|
||||
INCLUDED #
|
||||
expansion/family-keyboard/family-keyboard.cpp
|
||||
expansion/family-keyboard/family-keyboard.hpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
fc
|
||||
INCLUDED #
|
||||
fds/audio.cpp
|
||||
fds/audio.hpp
|
||||
fds/drive.cpp
|
||||
fds/drive.hpp
|
||||
fds/fds.hpp
|
||||
fds/serialization.cpp
|
||||
fds/timer.cpp
|
||||
fds/timer.hpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
fc
|
||||
INCLUDED #
|
||||
ppu/color.cpp
|
||||
ppu/debugger.cpp
|
||||
ppu/memory.cpp
|
||||
ppu/ppu.hpp
|
||||
ppu/render.cpp
|
||||
ppu/scroll.cpp
|
||||
ppu/serialization.cpp
|
||||
ppu/sprite.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
fc
|
||||
INCLUDED #
|
||||
system/controls.cpp
|
||||
system/serialization.cpp
|
||||
system/system.hpp
|
||||
)
|
||||
@@ -1,23 +0,0 @@
|
||||
ares.components += mos6502
|
||||
ares.components += ym2149
|
||||
ares.components += ym2413
|
||||
ares.components += m24c
|
||||
ares.components += sst39sf0x0
|
||||
|
||||
ares.objects += ares-fc-system
|
||||
ares.objects += ares-fc-controller
|
||||
ares.objects += ares-fc-expansion
|
||||
ares.objects += ares-fc-cartridge
|
||||
ares.objects += ares-fc-cpu
|
||||
ares.objects += ares-fc-apu
|
||||
ares.objects += ares-fc-ppu
|
||||
ares.objects += ares-fc-fds
|
||||
|
||||
$(object.path)/ares-fc-system.o: $(ares.path)/fc/system/system.cpp
|
||||
$(object.path)/ares-fc-controller.o: $(ares.path)/fc/controller/controller.cpp
|
||||
$(object.path)/ares-fc-expansion.o: $(ares.path)/fc/expansion/expansion.cpp
|
||||
$(object.path)/ares-fc-cartridge.o: $(ares.path)/fc/cartridge/cartridge.cpp
|
||||
$(object.path)/ares-fc-cpu.o: $(ares.path)/fc/cpu/cpu.cpp
|
||||
$(object.path)/ares-fc-apu.o: $(ares.path)/fc/apu/apu.cpp
|
||||
$(object.path)/ares-fc-ppu.o: $(ares.path)/fc/ppu/ppu.cpp
|
||||
$(object.path)/ares-fc-fds.o: $(ares.path)/fc/fds/fds.cpp
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <fc/fc.hpp>
|
||||
#include <ares/resource/resource.hpp>
|
||||
|
||||
namespace ares::Famicom {
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ auto CPU::read(n16 address) -> n8 {
|
||||
}
|
||||
|
||||
auto CPU::write(n16 address, n8 data) -> void {
|
||||
writeBus(address, io.openBus = data);
|
||||
writeBus(address, data);
|
||||
io.openBus = data;
|
||||
step(rate());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
//started: 2011-09-05
|
||||
|
||||
#include <fc/system/system.cpp>
|
||||
#include <fc/controller/controller.cpp>
|
||||
#include <fc/expansion/expansion.cpp>
|
||||
#include <fc/cartridge/cartridge.cpp>
|
||||
#include <fc/cpu/cpu.cpp>
|
||||
#include <fc/apu/apu.cpp>
|
||||
#include <fc/ppu/ppu.cpp>
|
||||
#include <fc/fds/fds.cpp>
|
||||
+6
-3
@@ -81,6 +81,12 @@ auto FDS::connect() -> void {
|
||||
auto FDS::disconnect() -> void {
|
||||
if(!node) return;
|
||||
|
||||
save();
|
||||
pak.reset();
|
||||
node.reset();
|
||||
}
|
||||
|
||||
auto FDS::save() -> void {
|
||||
if(disk1.sideA)
|
||||
if(auto fp = pak->write("disk1.sideA")) {
|
||||
disk1.sideA.save(fp);
|
||||
@@ -100,9 +106,6 @@ auto FDS::disconnect() -> void {
|
||||
if(auto fp = pak->write("disk2.sideB")) {
|
||||
disk2.sideB.save(fp);
|
||||
}
|
||||
|
||||
pak.reset();
|
||||
node.reset();
|
||||
}
|
||||
|
||||
auto FDS::change(string value) -> void {
|
||||
|
||||
@@ -34,6 +34,7 @@ struct FDS {
|
||||
auto change(string value) -> void;
|
||||
auto change() -> void;
|
||||
|
||||
auto save() -> void;
|
||||
auto poll() -> void;
|
||||
auto main() -> void;
|
||||
auto power() -> void;
|
||||
|
||||
@@ -81,7 +81,10 @@ auto PPU::writeIO(n16 address, n8 data) -> void {
|
||||
|
||||
//PPUCTRL
|
||||
case 0:
|
||||
scroll.nametable = data.bit(0,1);
|
||||
scroll.nametable = data.bit(0,1);
|
||||
if (io.lx == 257 && rendering())
|
||||
var.nametableX = cpu.io.openBus.bit(0);
|
||||
|
||||
io.vramIncrement = data.bit(2) ? 32 : 1;
|
||||
io.spriteAddress = data.bit(3) ? 0x1000 : 0x0000;
|
||||
io.bgAddress = data.bit(4) ? 0x1000 : 0x0000;
|
||||
@@ -141,6 +144,9 @@ auto PPU::writeIO(n16 address, n8 data) -> void {
|
||||
if(scroll.latch++ == 0) {
|
||||
scroll.fineX = data.bit(0,2);
|
||||
scroll.tileX = data.bit(3,7);
|
||||
|
||||
if (io.lx == 257 && rendering())
|
||||
var.tileX = cpu.io.openBus.bit(3,7);
|
||||
} else {
|
||||
scroll.fineY = data.bit(0,2);
|
||||
scroll.tileY = data.bit(3,7);
|
||||
@@ -151,6 +157,8 @@ auto PPU::writeIO(n16 address, n8 data) -> void {
|
||||
case 6:
|
||||
if(scroll.latch++ == 0) {
|
||||
scroll.addressHi = data.bit(0,5);
|
||||
if (io.lx == 257 && rendering())
|
||||
var.nametable = cpu.io.openBus.bit(2,3);
|
||||
} else {
|
||||
scroll.addressLo = data.bit(0,7);
|
||||
scroll.transferDelay = 3;
|
||||
|
||||
+7
-4
@@ -97,11 +97,14 @@ auto PPU::frame() -> void {
|
||||
screen->setViewport(0, 0, 283, displayHeight());
|
||||
} else {
|
||||
int x = 16;
|
||||
int y = 8;
|
||||
int width = 283 - 33;
|
||||
int height = displayHeight() - 16;
|
||||
int y = 0;
|
||||
int width = 283 - 27;
|
||||
int height = displayHeight() - 2;
|
||||
|
||||
if(Region::PAL()) height -= 48;
|
||||
if(Region::PAL()) {
|
||||
x += 2;
|
||||
height -= 46;
|
||||
}
|
||||
|
||||
screen->setSize(width, height);
|
||||
screen->setViewport(x, y, width, height);
|
||||
|
||||
@@ -25,8 +25,8 @@ auto PPU::renderPixel() -> void {
|
||||
u32 objectPalette = 0;
|
||||
bool objectPriority = 0;
|
||||
|
||||
//PAL systems blank the topmost scanline and the first and last 2px of active display
|
||||
if(Region::PAL()) if(io.ly == 0 || x < 2 || x > 254) return;
|
||||
//PAL systems technically blank the topmost scanline and a 2px column on each side of active display.
|
||||
if(Region::PAL()) if(io.ly == 0 || x < 2 || x > 253) return;
|
||||
|
||||
palette |= latch.tiledataLo & mask ? 1 : 0;
|
||||
palette |= latch.tiledataHi & mask ? 2 : 0;
|
||||
|
||||
@@ -61,6 +61,7 @@ auto System::load(Node::System& root, string name) -> bool {
|
||||
}
|
||||
|
||||
node = Node::System::create(information.name);
|
||||
node->setAttribute("configuration", name);
|
||||
node->setGame({&System::game, this});
|
||||
node->setRun({&System::run, this});
|
||||
node->setPower({&System::power, this});
|
||||
@@ -85,6 +86,7 @@ auto System::load(Node::System& root, string name) -> bool {
|
||||
auto System::save() -> void {
|
||||
if(!node) return;
|
||||
cartridge.save();
|
||||
if(fds.present) fds.save();
|
||||
}
|
||||
|
||||
auto System::unload() -> void {
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
ares_components(sm83 m93lcx6)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
gb
|
||||
UNITY #
|
||||
gb.cpp
|
||||
PRIMARY #
|
||||
system/system.cpp
|
||||
cartridge/cartridge.cpp
|
||||
bus/bus.cpp
|
||||
cpu/cpu.cpp
|
||||
ppu/ppu.cpp
|
||||
apu/apu.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
gb
|
||||
INCLUDED #
|
||||
gb.hpp
|
||||
CMakeLists.txt
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
gb
|
||||
INCLUDED #
|
||||
apu/apu.hpp
|
||||
apu/io.cpp
|
||||
apu/noise.cpp
|
||||
apu/sequencer.cpp
|
||||
apu/serialization.cpp
|
||||
apu/square1.cpp
|
||||
apu/square2.cpp
|
||||
apu/wave.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
gb
|
||||
INCLUDED #
|
||||
bus/bus.hpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
gb
|
||||
INCLUDED #
|
||||
cartridge/cartridge.hpp
|
||||
cartridge/memory.cpp
|
||||
cartridge/serialization.cpp
|
||||
cartridge/slot.cpp
|
||||
cartridge/slot.hpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
gb
|
||||
INCLUDED #
|
||||
cartridge/board/board.cpp
|
||||
cartridge/board/board.hpp
|
||||
cartridge/board/huc1.cpp
|
||||
cartridge/board/huc3.cpp
|
||||
cartridge/board/linear.cpp
|
||||
cartridge/board/mbc1.cpp
|
||||
cartridge/board/mbc1m.cpp
|
||||
cartridge/board/mbc2.cpp
|
||||
cartridge/board/mbc3.cpp
|
||||
cartridge/board/mbc5.cpp
|
||||
cartridge/board/mbc6.cpp
|
||||
cartridge/board/mbc7.cpp
|
||||
cartridge/board/mmm01.cpp
|
||||
cartridge/board/none.cpp
|
||||
cartridge/board/tama.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
gb
|
||||
INCLUDED #
|
||||
cpu/cpu.hpp
|
||||
cpu/debugger.cpp
|
||||
cpu/io.cpp
|
||||
cpu/memory.cpp
|
||||
cpu/serialization.cpp
|
||||
cpu/timing.cpp
|
||||
)
|
||||
|
||||
ares_add_sources(
|
||||
CORE #
|
||||
gb
|
||||
INCLUDED #
|
||||
system/controls.cpp
|
||||
system/serialization.cpp
|
||||
system/system.hpp
|
||||
)
|
||||
@@ -1,16 +0,0 @@
|
||||
ares.components += sm83
|
||||
ares.components += m93lcx6
|
||||
|
||||
ares.objects += ares-gb-system
|
||||
ares.objects += ares-gb-bus
|
||||
ares.objects += ares-gb-cartridge
|
||||
ares.objects += ares-gb-cpu
|
||||
ares.objects += ares-gb-ppu
|
||||
ares.objects += ares-gb-apu
|
||||
|
||||
$(object.path)/ares-gb-system.o: $(ares.path)/gb/system/system.cpp
|
||||
$(object.path)/ares-gb-cartridge.o: $(ares.path)/gb/cartridge/cartridge.cpp
|
||||
$(object.path)/ares-gb-bus.o: $(ares.path)/gb/bus/bus.cpp
|
||||
$(object.path)/ares-gb-cpu.o: $(ares.path)/gb/cpu/cpu.cpp
|
||||
$(object.path)/ares-gb-ppu.o: $(ares.path)/gb/ppu/ppu.cpp
|
||||
$(object.path)/ares-gb-apu.o: $(ares.path)/gb/apu/apu.cpp
|
||||
@@ -44,6 +44,7 @@ struct APU : Thread {
|
||||
n11 frequency;
|
||||
bool counter;
|
||||
|
||||
n4 sample;
|
||||
i16 output;
|
||||
bool dutyOutput;
|
||||
n3 phase;
|
||||
@@ -77,6 +78,7 @@ struct APU : Thread {
|
||||
n11 frequency;
|
||||
bool counter;
|
||||
|
||||
n4 sample;
|
||||
i16 output;
|
||||
bool dutyOutput;
|
||||
n3 phase;
|
||||
@@ -105,6 +107,7 @@ struct APU : Thread {
|
||||
bool counter;
|
||||
n8 pattern[16];
|
||||
|
||||
n4 sample;
|
||||
i16 output;
|
||||
u32 length;
|
||||
u32 period;
|
||||
@@ -135,6 +138,7 @@ struct APU : Thread {
|
||||
n3 divisor;
|
||||
bool counter;
|
||||
|
||||
n4 sample;
|
||||
i16 output;
|
||||
u32 length;
|
||||
n3 envelopePeriod;
|
||||
|
||||
@@ -1,4 +1,20 @@
|
||||
auto APU::readIO(u32 cycle, n16 address, n8 data) -> n8 {
|
||||
if(Model::GameBoyColor()) {
|
||||
//PCM12
|
||||
if(address == 0xff76 && cycle == 2) {
|
||||
data.bit(0,3) = square1.sample;
|
||||
data.bit(4,7) = square2.sample;
|
||||
return data;
|
||||
}
|
||||
|
||||
//PCM34
|
||||
if(address == 0xff77 && cycle == 2) {
|
||||
data.bit(0,3) = wave.sample;
|
||||
data.bit(4,7) = noise.sample;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
if(address < 0xff10 || address > 0xff3f) return data;
|
||||
|
||||
//NR10
|
||||
|
||||
@@ -16,7 +16,7 @@ auto APU::Noise::run() -> void {
|
||||
}
|
||||
}
|
||||
|
||||
n4 sample = lfsr & 1 ? 0 : (u32)volume;
|
||||
sample = lfsr & 1 ? 0 : (u32)volume;
|
||||
if(!enable) sample = 0;
|
||||
|
||||
output = sample;
|
||||
@@ -79,6 +79,7 @@ auto APU::Noise::serialize(serializer& s) -> void {
|
||||
s(divisor);
|
||||
s(counter);
|
||||
|
||||
s(sample);
|
||||
s(output);
|
||||
s(length);
|
||||
s(envelopePeriod);
|
||||
|
||||
@@ -14,7 +14,7 @@ auto APU::Square1::run() -> void {
|
||||
}
|
||||
}
|
||||
|
||||
n4 sample = dutyOutput ? (u32)volume : 0;
|
||||
sample = dutyOutput ? (u32)volume : 0;
|
||||
if(!enable) sample = 0;
|
||||
|
||||
output = sample;
|
||||
@@ -120,6 +120,7 @@ auto APU::Square1::serialize(serializer& s) -> void {
|
||||
s(frequency);
|
||||
s(counter);
|
||||
|
||||
s(sample);
|
||||
s(output);
|
||||
s(dutyOutput);
|
||||
s(phase);
|
||||
|
||||
@@ -14,7 +14,7 @@ auto APU::Square2::run() -> void {
|
||||
}
|
||||
}
|
||||
|
||||
n4 sample = dutyOutput ? (u32)volume : 0;
|
||||
sample = dutyOutput ? (u32)volume : 0;
|
||||
if(!enable) sample = 0;
|
||||
|
||||
output = sample;
|
||||
@@ -77,6 +77,7 @@ auto APU::Square2::serialize(serializer& s) -> void {
|
||||
s(frequency);
|
||||
s(counter);
|
||||
|
||||
s(sample);
|
||||
s(output);
|
||||
s(dutyOutput);
|
||||
s(phase);
|
||||
|
||||
@@ -12,7 +12,7 @@ auto APU::Wave::run() -> void {
|
||||
}
|
||||
|
||||
static const u32 shift[] = {4, 0, 1, 2}; //0%, 100%, 50%, 25%
|
||||
n4 sample = patternSample >> shift[volume];
|
||||
sample = patternSample >> shift[volume];
|
||||
if(!enable) sample = 0;
|
||||
|
||||
output = sample;
|
||||
@@ -95,6 +95,7 @@ auto APU::Wave::serialize(serializer& s) -> void {
|
||||
s(counter);
|
||||
s(pattern);
|
||||
|
||||
s(sample);
|
||||
s(output);
|
||||
s(length);
|
||||
s(period);
|
||||
|
||||
Loaded 100 of 4883 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user