diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..4c39a334be --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + commit-message: + prefix: "ci" diff --git a/.github/workflows/build-xemu-win64-toolchain.yml b/.github/workflows/build-xemu-win64-toolchain.yml index deefd9c070..7a521389a5 100644 --- a/.github/workflows/build-xemu-win64-toolchain.yml +++ b/.github/workflows/build-xemu-win64-toolchain.yml @@ -21,10 +21,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Clone tree - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - name: Extract image metadata (tags, labels) id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} labels: | @@ -35,16 +35,16 @@ jobs: type=ref,event=branch type=sha - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3 - name: Login to GitHub Container Registry - uses: docker/login-action@v3 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3 if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v5 with: context: ubuntu-win64-cross push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0ef3537790..fb2a6cc123 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Clone tree - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: fetch-depth: 0 - name: Install dependencies @@ -50,7 +50,7 @@ jobs: ./scripts/archive-source.sh src.tar gzip -1 src.tar - name: Upload source package artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: src.tar.gz path: src.tar.gz @@ -79,18 +79,18 @@ jobs: artifact_name: xemu-win-aarch64-release arch: aarch64 env: - DOCKER_IMAGE_NAME: ghcr.io/xemu-project/xemu-win64-toolchain:sha-3bdb9e7 + DOCKER_IMAGE_NAME: ghcr.io/xemu-project/xemu-win64-toolchain:sha-0d06ce8 steps: - name: Download source package - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: src.tar.gz - name: Extract source package run: tar xf src.tar.gz - name: Initialize compiler cache id: cache - uses: actions/cache@v4 + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4 with: path: /tmp/xemu-ccache key: cache-wincross-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.configuration }}-${{ github.sha }} @@ -111,7 +111,7 @@ jobs: $DOCKER_IMAGE_NAME \ bash -c "ccache -z; ./build.sh -p win64-cross ${{ matrix.build_param }} && ccache -s" - name: Upload build artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: ${{ matrix.artifact_name }} path: dist @@ -140,7 +140,7 @@ jobs: arch: aarch64 steps: - name: Download artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: ${{ matrix.artifact_name }} path: ${{ matrix.artifact_name }} @@ -157,7 +157,7 @@ jobs: 7z a -tzip ../dist/${{ matrix.artifact_name }}.zip * "-xr!*.pdb" 7z a -tzip ../dist/${{ matrix.artifact_name }}-pdb.zip "-ir!*.pdb" - name: Upload build artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: ${{ matrix.artifact_name }}-pdb path: dist @@ -196,13 +196,13 @@ jobs: steps: - name: Initialize compiler cache id: cache - uses: actions/cache@v4 + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4 with: path: /tmp/xemu-ccache key: cache-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.configuration }}-${{ github.sha }} restore-keys: cache-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.configuration }}- - name: Download source package - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: src.tar.gz - name: Extract source package @@ -245,6 +245,11 @@ jobs: echo -e "\n\nCompiler Cache Stats:" ccache -s + - name: Test + run: | + pushd src/build + ./pyvenv/bin/meson test --suite xbox + popd - name: Generate AppImage run: | wget --no-verbose https://github.com/linuxdeploy/linuxdeploy/releases/latest/download/linuxdeploy-${{ matrix.arch }}.AppImage @@ -266,7 +271,7 @@ jobs: run: | tar -czvf ${{ matrix.artifact_filename }} --transform "s#^dist#xemu#" dist - name: Upload build artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: ${{ matrix.artifact_name }} path: ${{ matrix.artifact_filename }} @@ -300,12 +305,12 @@ jobs: artifact_filename: xemu-macos-arm64-release.zip steps: - name: Download source package - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: src.tar.gz - name: Extract source package run: tar xf src.tar.gz - - uses: actions/setup-python@v5.1.0 + - uses: actions/setup-python@v5.5.0 with: python-version: '3.12' - name: Install dependencies @@ -319,7 +324,7 @@ jobs: pip install pyyaml requests - name: Initialize compiler, library cache id: cache - uses: actions/cache@v4 + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4 with: path: | xemu-ccache @@ -339,7 +344,7 @@ jobs: zip -r ../${{ matrix.artifact_filename }} * popd - name: Upload build artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: ${{ matrix.artifact_name }} path: ${{ matrix.artifact_filename }} @@ -353,12 +358,12 @@ jobs: configuration: ["debug", "release"] steps: - name: Download x86_64 build - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: xemu-macos-x86_64-${{ matrix.configuration }} path: xemu-macos-x86_64-${{ matrix.configuration }} - name: Download arm64 build - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: xemu-macos-arm64-${{ matrix.configuration }} path: xemu-macos-arm64-${{ matrix.configuration }} @@ -382,7 +387,7 @@ jobs: zip -r ../xemu-macos-universal-${{ matrix.configuration }}.zip * popd - name: Upload build artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: xemu-macos-universal-${{ matrix.configuration }} path: xemu-macos-universal-${{ matrix.configuration }}.zip @@ -393,7 +398,7 @@ jobs: needs: [Ubuntu, macOSUniversal, Windows, WindowsPdb] steps: - name: Download artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: path: dist - name: Extract source package @@ -415,7 +420,7 @@ jobs: run: | cp dist/xemu-win-x86_64-release-pdb/xemu-win-x86_64-release.zip dist/xemu-win-x86_64-release-pdb/xemu-win-release.zip - name: Publish release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2.2.1 with: tag_name: v${{ env.XEMU_VERSION }} name: v${{ env.XEMU_VERSION }} @@ -439,7 +444,7 @@ jobs: dist/xemu-ubuntu-aarch64-debug/xemu/xemu-v${{ env.XEMU_VERSION }}-dbg-aarch64.AppImage dist/xemu-ubuntu-aarch64-release/xemu/xemu-v${{ env.XEMU_VERSION }}-aarch64.AppImage - name: Trigger website update - uses: benc-uk/workflow-dispatch@v1.2.2 + uses: benc-uk/workflow-dispatch@e2e5e9a103e331dad343f381a29e654aea3cf8fc # v1.2.4 with: workflow: build.yml repo: xemu-project/xemu-website @@ -457,7 +462,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Download source package - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 with: name: src.tar.gz - name: Extract source package @@ -476,7 +481,7 @@ jobs: -- Matt Borgerson $(date -R)" > debian/changelog popd - name: Deploy source archive to branch - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./src diff --git a/.gitignore b/.gitignore index bfac196fad..e1927ae154 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,6 @@ .sdk .stgit-* .git-submodule-status -.clang-format .gdb_history cscope.* tags diff --git a/debian/control b/debian/control index eb495ec081..7f5871bbd7 100644 --- a/debian/control +++ b/debian/control @@ -6,6 +6,8 @@ Build-Depends: debhelper (>= 11), cmake, git, python3:any, + python3-pip, + python3-tomli, python3-yaml, python3-venv, ninja-build, diff --git a/hw/xbox/mcpx/apu.c b/hw/xbox/mcpx/apu.c index ecace96ce3..338e132956 100644 --- a/hw/xbox/mcpx/apu.c +++ b/hw/xbox/mcpx/apu.c @@ -154,6 +154,14 @@ typedef struct MCPXAPUState { int16_t apu_fifo_output[256][2]; // 1 EP frame (0x400 bytes), 8 buffered } MCPXAPUState; +static const struct { + hwaddr top, current, next; +} voice_list_regs[] = { + { NV_PAPU_TVL2D, NV_PAPU_CVL2D, NV_PAPU_NVL2D }, // 2D + { NV_PAPU_TVL3D, NV_PAPU_CVL3D, NV_PAPU_NVL3D }, // 3D + { NV_PAPU_TVLMP, NV_PAPU_CVLMP, NV_PAPU_NVLMP }, // MP +}; + static MCPXAPUState *g_state; // Used via debug handlers static struct McpxApuDebug g_dbg, g_dbg_cache; static int g_dbg_voice_monitor = -1; @@ -2571,7 +2579,7 @@ const VMStateDescription vmstate_vp_dsp_core_state = { VMSTATE_UINT32(num_inst, dsp_core_t), VMSTATE_UINT32(cur_inst_len, dsp_core_t), VMSTATE_UINT32(cur_inst, dsp_core_t), - VMSTATE_BOOL(executing_for_disasm, dsp_core_t), + VMSTATE_UNUSED(1), VMSTATE_UINT32(disasm_memory_ptr, dsp_core_t), VMSTATE_BOOL(exception_debugging, dsp_core_t), VMSTATE_UINT32(disasm_prev_inst_pc, dsp_core_t), diff --git a/hw/xbox/mcpx/apu_regs.h b/hw/xbox/mcpx/apu_regs.h index 7488c2e267..d745a69354 100644 --- a/hw/xbox/mcpx/apu_regs.h +++ b/hw/xbox/mcpx/apu_regs.h @@ -22,6 +22,8 @@ #ifndef MCPX_APU_REGS_H #define MCPX_APU_REGS_H +// clang-format off + #define NV_PAPU_ISTS 0x00001000 # define NV_PAPU_ISTS_GINTSTS (1 << 0) # define NV_PAPU_ISTS_FETINTSTS (1 << 4) @@ -122,15 +124,6 @@ #define NV_PAPU_EPPMEM 0x0000A000 #define NV_PAPU_EPRST 0x0000FFFC -static const struct { - hwaddr top, current, next; -} voice_list_regs[] = { - {NV_PAPU_TVL2D, NV_PAPU_CVL2D, NV_PAPU_NVL2D}, //2D - {NV_PAPU_TVL3D, NV_PAPU_CVL3D, NV_PAPU_NVL3D}, //3D - {NV_PAPU_TVLMP, NV_PAPU_CVLMP, NV_PAPU_NVLMP}, //MP -}; - - /* audio processor object / front-end messages */ #define NV1BA0_PIO_FREE 0x00000010 #define NV1BA0_PIO_SET_ANTECEDENT_VOICE 0x00000120 @@ -343,4 +336,6 @@ enum MCPX_HW_NOTIFIER { #define NV1BA0_NOTIFICATION_STATUS_DONE_SUCCESS 0x01 #define NV1BA0_NOTIFICATION_STATUS_IN_PROGRESS 0x80 +// clang-format on + #endif diff --git a/hw/xbox/mcpx/dsp/debug.c b/hw/xbox/mcpx/dsp/debug.c new file mode 100644 index 0000000000..e41a222bf9 --- /dev/null +++ b/hw/xbox/mcpx/dsp/debug.c @@ -0,0 +1,299 @@ +/* + * MCPX DSP emulator + * + * Copyright (c) 2015 espes + * Copyright (c) 2020-2025 Matt Borgerson + * + * Adapted from Hatari DSP M56001 emulation + * (C) 2001-2008 ARAnyM developer team + * Adaption to Hatari (C) 2008 by Thomas Huth + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "qemu/osdep.h" + +#include +#include +#include +#include + +#include "dsp_cpu.h" +#include "dsp_dma.h" +#include "dsp_state.h" + +#include "dsp.h" +#include "debug.h" + +#if DEBUG_DSP +#define BITMASK(x) ((1<<(x))-1) + +/** + * Output memory values between given addresses in given DSP address space. + * Return next DSP address value. + */ +uint32_t dsp_disasm_memory(DSPState* dsp, uint32_t dsp_memdump_addr, uint32_t dsp_memdump_upper, char space) +{ + uint32_t mem, value; + + for (mem = dsp_memdump_addr; mem <= dsp_memdump_upper; mem++) { + value = dsp_read_memory(dsp, space, mem); + printf("%04x %06x\n", mem, value); + } + return dsp_memdump_upper+1; +} + +/** + * Show information on DSP core state which isn't + * shown by any of the other commands (dd, dm, dr). + */ +void dsp_info(DSPState* dsp) +{ + int i, j; + const char *stackname[] = { "SSH", "SSL" }; + + printf("DSP core information:\n"); + + for (i = 0; i < ARRAY_SIZE(stackname); i++) { + printf("- %s stack:", stackname[i]); + for (j = 0; j < ARRAY_SIZE(dsp->core.stack[0]); j++) { + printf(" %04x", dsp->core.stack[i][j]); + } + printf("\n"); + } + + printf("- Interrupt IPL:"); + for (i = 0; i < ARRAY_SIZE(dsp->core.interrupt_ipl); i++) { + printf(" %04x", dsp->core.interrupt_ipl[i]); + } + printf("\n"); + + printf("- Pending ints: "); + for (i = 0; i < ARRAY_SIZE(dsp->core.interrupt_is_pending); i++) { + printf(" %04hx", dsp->core.interrupt_is_pending[i]); + } + printf("\n"); +} + +/** + * Show DSP register contents + */ +void dsp_print_registers(DSPState* dsp) +{ + uint32_t i; + + printf("A: A2: %02x A1: %06x A0: %06x\n", + dsp->core.registers[DSP_REG_A2], dsp->core.registers[DSP_REG_A1], dsp->core.registers[DSP_REG_A0]); + printf("B: B2: %02x B1: %06x B0: %06x\n", + dsp->core.registers[DSP_REG_B2], dsp->core.registers[DSP_REG_B1], dsp->core.registers[DSP_REG_B0]); + + printf("X: X1: %06x X0: %06x\n", dsp->core.registers[DSP_REG_X1], dsp->core.registers[DSP_REG_X0]); + printf("Y: Y1: %06x Y0: %06x\n", dsp->core.registers[DSP_REG_Y1], dsp->core.registers[DSP_REG_Y0]); + + for (i=0; i<8; i++) { + printf("R%01x: %04x N%01x: %04x M%01x: %04x\n", + i, dsp->core.registers[DSP_REG_R0+i], + i, dsp->core.registers[DSP_REG_N0+i], + i, dsp->core.registers[DSP_REG_M0+i]); + } + + printf("LA: %04x LC: %04x PC: %04x\n", dsp->core.registers[DSP_REG_LA], dsp->core.registers[DSP_REG_LC], dsp->core.pc); + printf("SR: %04x OMR: %02x\n", dsp->core.registers[DSP_REG_SR], dsp->core.registers[DSP_REG_OMR]); + printf("SP: %02x SSH: %04x SSL: %04x\n", + dsp->core.registers[DSP_REG_SP], dsp->core.registers[DSP_REG_SSH], dsp->core.registers[DSP_REG_SSL]); +} + + +/** + * Get given DSP register address and required bit mask. + * Works for A0-2, B0-2, LA, LC, M0-7, N0-7, R0-7, X0-1, Y0-1, PC, SR, SP, + * OMR, SSH & SSL registers, but note that the SP, SSH & SSL registers + * need special handling (in DSP*SetRegister()) when they are set. + * Return the register width in bits or zero for an error. + */ +int dsp_get_register_address(DSPState* dsp, const char *regname, uint32_t **addr, uint32_t *mask) +{ +#define MAX_REGNAME_LEN 4 + typedef struct { + const char name[MAX_REGNAME_LEN]; + uint32_t *addr; + size_t bits; + uint32_t mask; + } reg_addr_t; + + /* sorted by name so that this can be bisected */ + const reg_addr_t registers[] = { + + /* 56-bit A register */ + { "A0", &dsp->core.registers[DSP_REG_A0], 32, BITMASK(24) }, + { "A1", &dsp->core.registers[DSP_REG_A1], 32, BITMASK(24) }, + { "A2", &dsp->core.registers[DSP_REG_A2], 32, BITMASK(8) }, + + /* 56-bit B register */ + { "B0", &dsp->core.registers[DSP_REG_B0], 32, BITMASK(24) }, + { "B1", &dsp->core.registers[DSP_REG_B1], 32, BITMASK(24) }, + { "B2", &dsp->core.registers[DSP_REG_B2], 32, BITMASK(8) }, + + /* 16-bit LA & LC registers */ + { "LA", &dsp->core.registers[DSP_REG_LA], 32, BITMASK(16) }, + { "LC", &dsp->core.registers[DSP_REG_LC], 32, BITMASK(16) }, + + /* 16-bit M registers */ + { "M0", &dsp->core.registers[DSP_REG_M0], 32, BITMASK(16) }, + { "M1", &dsp->core.registers[DSP_REG_M1], 32, BITMASK(16) }, + { "M2", &dsp->core.registers[DSP_REG_M2], 32, BITMASK(16) }, + { "M3", &dsp->core.registers[DSP_REG_M3], 32, BITMASK(16) }, + { "M4", &dsp->core.registers[DSP_REG_M4], 32, BITMASK(16) }, + { "M5", &dsp->core.registers[DSP_REG_M5], 32, BITMASK(16) }, + { "M6", &dsp->core.registers[DSP_REG_M6], 32, BITMASK(16) }, + { "M7", &dsp->core.registers[DSP_REG_M7], 32, BITMASK(16) }, + + /* 16-bit N registers */ + { "N0", &dsp->core.registers[DSP_REG_N0], 32, BITMASK(16) }, + { "N1", &dsp->core.registers[DSP_REG_N1], 32, BITMASK(16) }, + { "N2", &dsp->core.registers[DSP_REG_N2], 32, BITMASK(16) }, + { "N3", &dsp->core.registers[DSP_REG_N3], 32, BITMASK(16) }, + { "N4", &dsp->core.registers[DSP_REG_N4], 32, BITMASK(16) }, + { "N5", &dsp->core.registers[DSP_REG_N5], 32, BITMASK(16) }, + { "N6", &dsp->core.registers[DSP_REG_N6], 32, BITMASK(16) }, + { "N7", &dsp->core.registers[DSP_REG_N7], 32, BITMASK(16) }, + + { "OMR", &dsp->core.registers[DSP_REG_OMR], 32, 0x5f }, + + /* 16-bit program counter */ + { "PC", (uint32_t*)(&dsp->core.pc), 24, BITMASK(24) }, + + /* 16-bit DSP R (address) registers */ + { "R0", &dsp->core.registers[DSP_REG_R0], 32, BITMASK(16) }, + { "R1", &dsp->core.registers[DSP_REG_R1], 32, BITMASK(16) }, + { "R2", &dsp->core.registers[DSP_REG_R2], 32, BITMASK(16) }, + { "R3", &dsp->core.registers[DSP_REG_R3], 32, BITMASK(16) }, + { "R4", &dsp->core.registers[DSP_REG_R4], 32, BITMASK(16) }, + { "R5", &dsp->core.registers[DSP_REG_R5], 32, BITMASK(16) }, + { "R6", &dsp->core.registers[DSP_REG_R6], 32, BITMASK(16) }, + { "R7", &dsp->core.registers[DSP_REG_R7], 32, BITMASK(16) }, + + { "SSH", &dsp->core.registers[DSP_REG_SSH], 32, BITMASK(16) }, + { "SSL", &dsp->core.registers[DSP_REG_SSL], 32, BITMASK(16) }, + { "SP", &dsp->core.registers[DSP_REG_SP], 32, BITMASK(6) }, + + /* 16-bit status register */ + { "SR", &dsp->core.registers[DSP_REG_SR], 32, 0xefff }, + + /* 48-bit X register */ + { "X0", &dsp->core.registers[DSP_REG_X0], 32, BITMASK(24) }, + { "X1", &dsp->core.registers[DSP_REG_X1], 32, BITMASK(24) }, + + /* 48-bit Y register */ + { "Y0", &dsp->core.registers[DSP_REG_Y0], 32, BITMASK(24) }, + { "Y1", &dsp->core.registers[DSP_REG_Y1], 32, BITMASK(24) } + }; + /* left, right, middle, direction */ + int l, r, m, dir = 0; + unsigned int i, len; + char reg[MAX_REGNAME_LEN]; + + for (i = 0; i < sizeof(reg) && regname[i]; i++) { + reg[i] = toupper(regname[i]); + } + if (i < 2 || regname[i]) { + /* too short or longer than any of the names */ + return 0; + } + len = i; + + /* bisect */ + l = 0; + r = ARRAY_SIZE(registers) - 1; + do { + m = (l+r) >> 1; + for (i = 0; i < len; i++) { + dir = (int)reg[i] - registers[m].name[i]; + if (dir) { + break; + } + } + if (dir == 0) { + *addr = registers[m].addr; + *mask = registers[m].mask; + return registers[m].bits; + } + if (dir < 0) { + r = m-1; + } else { + l = m+1; + } + } while (l <= r); +#undef MAX_REGNAME_LEN + return 0; +} + + +/** + * Set given DSP register value, return false if unknown register given + */ +bool dsp_disasm_set_register(DSPState* dsp, const char *arg, uint32_t value) +{ + uint32_t *addr, mask, sp_value; + int bits; + + /* first check registers needing special handling... */ + if (arg[0]=='S' || arg[0]=='s') { + if (arg[1]=='P' || arg[1]=='p') { + dsp->core.registers[DSP_REG_SP] = value & BITMASK(6); + value &= BITMASK(4); + dsp->core.registers[DSP_REG_SSH] = dsp->core.stack[0][value]; + dsp->core.registers[DSP_REG_SSL] = dsp->core.stack[1][value]; + return true; + } + if (arg[1]=='S' || arg[1]=='s') { + sp_value = dsp->core.registers[DSP_REG_SP] & BITMASK(4); + if (arg[2]=='H' || arg[2]=='h') { + if (sp_value == 0) { + dsp->core.registers[DSP_REG_SSH] = 0; + dsp->core.stack[0][sp_value] = 0; + } else { + dsp->core.registers[DSP_REG_SSH] = value & BITMASK(16); + dsp->core.stack[0][sp_value] = value & BITMASK(16); + } + return true; + } + if (arg[2]=='L' || arg[2]=='l') { + if (sp_value == 0) { + dsp->core.registers[DSP_REG_SSL] = 0; + dsp->core.stack[1][sp_value] = 0; + } else { + dsp->core.registers[DSP_REG_SSL] = value & BITMASK(16); + dsp->core.stack[1][sp_value] = value & BITMASK(16); + } + return true; + } + } + } + + /* ...then registers where address & mask are enough */ + bits = dsp_get_register_address(dsp, arg, &addr, &mask); + switch (bits) { + case 32: + *addr = value & mask; + return true; + case 16: + *(uint16_t*)addr = value & mask; + return true; + } + return false; +} + +#endif diff --git a/hw/xbox/mcpx/dsp/debug.h b/hw/xbox/mcpx/dsp/debug.h new file mode 100644 index 0000000000..befef229b1 --- /dev/null +++ b/hw/xbox/mcpx/dsp/debug.h @@ -0,0 +1,37 @@ +/* + * MCPX DSP emulator + + * Copyright (c) 2025 Matt Borgerson + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef HW_XBOX_MCPX_DSP_DEBUG_H +#define HW_XBOX_MCPX_DSP_DEBUG_H + +#ifndef DEBUG_DSP +#define DEBUG_DSP 0 +#endif + +#define TRACE_DSP_DISASM 0 +#define TRACE_DSP_DISASM_REG 0 +#define TRACE_DSP_DISASM_MEM 0 + +#define DPRINTF(fmt, ...) \ + do { \ + if (DEBUG_DSP) fprintf(stderr, fmt, ## __VA_ARGS__); \ + } while (0) + +#endif diff --git a/hw/xbox/mcpx/dsp/dsp.c b/hw/xbox/mcpx/dsp/dsp.c index d1e3b2a9b3..32b9c12d40 100644 --- a/hw/xbox/mcpx/dsp/dsp.c +++ b/hw/xbox/mcpx/dsp/dsp.c @@ -2,6 +2,7 @@ * MCPX DSP emulator * * Copyright (c) 2015 espes + * Copyright (c) 2020-2025 Matt Borgerson * * Adapted from Hatari DSP M56001 emulation * (C) 2001-2008 ARAnyM developer team @@ -23,17 +24,12 @@ */ #include "qemu/osdep.h" - -#include -#include -#include -#include - #include "dsp_cpu.h" #include "dsp_dma.h" #include "dsp_state.h" - #include "dsp.h" +#include "debug.h" +#include "trace.h" /* Defines */ #define BITMASK(x) ((1<<(x))-1) @@ -42,16 +38,6 @@ #define INTERRUPT_START_FRAME (1 << 1) #define INTERRUPT_DMA_EOL (1 << 7) -// #define DEBUG_DSP - -#ifdef DEBUG_DSP -#define DPRINTF(fmt, ...) \ - do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) \ - do { } while (0) -#endif - static uint32_t read_peripheral(dsp_core_t* core, uint32_t address); static void write_peripheral(dsp_core_t* core, uint32_t address, uint32_t value); @@ -91,8 +77,6 @@ void dsp_destroy(DSPState* dsp) static uint32_t read_peripheral(dsp_core_t* core, uint32_t address) { DSPState* dsp = container_of(core, DSPState, core); - DPRINTF("read_peripheral 0x%06x", address); - uint32_t v = 0xababa; switch(address) { case 0xFFFFB3: @@ -118,15 +102,13 @@ static uint32_t read_peripheral(dsp_core_t* core, uint32_t address) { break; } - DPRINTF(" -> 0x%06x\n", v); + trace_dsp_read_peripheral(address, v); return v; } static void write_peripheral(dsp_core_t* core, uint32_t address, uint32_t value) { DSPState* dsp = container_of(core, DSPState, core); - DPRINTF("write_peripheral [0x%06x] = 0x%06x\n", address, value); - switch(address) { case 0xFFFFC4: if (value & 1) { @@ -152,6 +134,8 @@ static void write_peripheral(dsp_core_t* core, uint32_t address, uint32_t value) dsp_dma_write(&dsp->dma, DMA_CONFIGURATION, value); break; } + + trace_dsp_write_peripheral(address, value); } @@ -201,7 +185,7 @@ void dsp_bootstrap(DSPState* dsp) (uint8_t*)dsp->core.pram, 0, 0x800*4, false); for (int i = 0; i < 0x800; i++) { if (dsp->core.pram[i] & 0xff000000) { - DPRINTF(stderr, "Bootstrap %04x: %08x\n", i, dsp->core.pram[i]); + DPRINTF("Bootstrap %04x: %08x\n", i, dsp->core.pram[i]); dsp->core.pram[i] &= 0x00ffffff; } } @@ -213,19 +197,6 @@ void dsp_start_frame(DSPState* dsp) dsp->interrupts |= INTERRUPT_START_FRAME; } -/** - * Disassemble DSP code between given addresses, return next PC address - */ -uint32_t dsp_disasm_address(DSPState* dsp, FILE *out, uint32_t lowerAdr, uint32_t UpperAdr) -{ - uint32_t dsp_pc; - - for (dsp_pc=lowerAdr; dsp_pc<=UpperAdr; dsp_pc++) { - dsp_pc += dsp56k_execute_one_disasm_instruction(&dsp->core, out, dsp_pc); - } - return dsp_pc; -} - uint32_t dsp_read_memory(DSPState* dsp, char space, uint32_t address) { int space_id; @@ -269,259 +240,3 @@ void dsp_write_memory(DSPState* dsp, char space, uint32_t address, uint32_t valu dsp56k_write_memory(&dsp->core, space_id, address, value); } - -/** - * Output memory values between given addresses in given DSP address space. - * Return next DSP address value. - */ -uint32_t dsp_disasm_memory(DSPState* dsp, uint32_t dsp_memdump_addr, uint32_t dsp_memdump_upper, char space) -{ - uint32_t mem, value; - - for (mem = dsp_memdump_addr; mem <= dsp_memdump_upper; mem++) { - value = dsp_read_memory(dsp, space, mem); - printf("%04x %06x\n", mem, value); - } - return dsp_memdump_upper+1; -} - -/** - * Show information on DSP core state which isn't - * shown by any of the other commands (dd, dm, dr). - */ -void dsp_info(DSPState* dsp) -{ - int i, j; - const char *stackname[] = { "SSH", "SSL" }; - - printf("DSP core information:\n"); - - for (i = 0; i < ARRAY_SIZE(stackname); i++) { - printf("- %s stack:", stackname[i]); - for (j = 0; j < ARRAY_SIZE(dsp->core.stack[0]); j++) { - printf(" %04x", dsp->core.stack[i][j]); - } - printf("\n"); - } - - printf("- Interrupt IPL:"); - for (i = 0; i < ARRAY_SIZE(dsp->core.interrupt_ipl); i++) { - printf(" %04x", dsp->core.interrupt_ipl[i]); - } - printf("\n"); - - printf("- Pending ints: "); - for (i = 0; i < ARRAY_SIZE(dsp->core.interrupt_is_pending); i++) { - printf(" %04hx", dsp->core.interrupt_is_pending[i]); - } - printf("\n"); -} - -/** - * Show DSP register contents - */ -void dsp_print_registers(DSPState* dsp) -{ - uint32_t i; - - printf("A: A2: %02x A1: %06x A0: %06x\n", - dsp->core.registers[DSP_REG_A2], dsp->core.registers[DSP_REG_A1], dsp->core.registers[DSP_REG_A0]); - printf("B: B2: %02x B1: %06x B0: %06x\n", - dsp->core.registers[DSP_REG_B2], dsp->core.registers[DSP_REG_B1], dsp->core.registers[DSP_REG_B0]); - - printf("X: X1: %06x X0: %06x\n", dsp->core.registers[DSP_REG_X1], dsp->core.registers[DSP_REG_X0]); - printf("Y: Y1: %06x Y0: %06x\n", dsp->core.registers[DSP_REG_Y1], dsp->core.registers[DSP_REG_Y0]); - - for (i=0; i<8; i++) { - printf("R%01x: %04x N%01x: %04x M%01x: %04x\n", - i, dsp->core.registers[DSP_REG_R0+i], - i, dsp->core.registers[DSP_REG_N0+i], - i, dsp->core.registers[DSP_REG_M0+i]); - } - - printf("LA: %04x LC: %04x PC: %04x\n", dsp->core.registers[DSP_REG_LA], dsp->core.registers[DSP_REG_LC], dsp->core.pc); - printf("SR: %04x OMR: %02x\n", dsp->core.registers[DSP_REG_SR], dsp->core.registers[DSP_REG_OMR]); - printf("SP: %02x SSH: %04x SSL: %04x\n", - dsp->core.registers[DSP_REG_SP], dsp->core.registers[DSP_REG_SSH], dsp->core.registers[DSP_REG_SSL]); -} - - -/** - * Get given DSP register address and required bit mask. - * Works for A0-2, B0-2, LA, LC, M0-7, N0-7, R0-7, X0-1, Y0-1, PC, SR, SP, - * OMR, SSH & SSL registers, but note that the SP, SSH & SSL registers - * need special handling (in DSP*SetRegister()) when they are set. - * Return the register width in bits or zero for an error. - */ -int dsp_get_register_address(DSPState* dsp, const char *regname, uint32_t **addr, uint32_t *mask) -{ -#define MAX_REGNAME_LEN 4 - typedef struct { - const char name[MAX_REGNAME_LEN]; - uint32_t *addr; - size_t bits; - uint32_t mask; - } reg_addr_t; - - /* sorted by name so that this can be bisected */ - const reg_addr_t registers[] = { - - /* 56-bit A register */ - { "A0", &dsp->core.registers[DSP_REG_A0], 32, BITMASK(24) }, - { "A1", &dsp->core.registers[DSP_REG_A1], 32, BITMASK(24) }, - { "A2", &dsp->core.registers[DSP_REG_A2], 32, BITMASK(8) }, - - /* 56-bit B register */ - { "B0", &dsp->core.registers[DSP_REG_B0], 32, BITMASK(24) }, - { "B1", &dsp->core.registers[DSP_REG_B1], 32, BITMASK(24) }, - { "B2", &dsp->core.registers[DSP_REG_B2], 32, BITMASK(8) }, - - /* 16-bit LA & LC registers */ - { "LA", &dsp->core.registers[DSP_REG_LA], 32, BITMASK(16) }, - { "LC", &dsp->core.registers[DSP_REG_LC], 32, BITMASK(16) }, - - /* 16-bit M registers */ - { "M0", &dsp->core.registers[DSP_REG_M0], 32, BITMASK(16) }, - { "M1", &dsp->core.registers[DSP_REG_M1], 32, BITMASK(16) }, - { "M2", &dsp->core.registers[DSP_REG_M2], 32, BITMASK(16) }, - { "M3", &dsp->core.registers[DSP_REG_M3], 32, BITMASK(16) }, - { "M4", &dsp->core.registers[DSP_REG_M4], 32, BITMASK(16) }, - { "M5", &dsp->core.registers[DSP_REG_M5], 32, BITMASK(16) }, - { "M6", &dsp->core.registers[DSP_REG_M6], 32, BITMASK(16) }, - { "M7", &dsp->core.registers[DSP_REG_M7], 32, BITMASK(16) }, - - /* 16-bit N registers */ - { "N0", &dsp->core.registers[DSP_REG_N0], 32, BITMASK(16) }, - { "N1", &dsp->core.registers[DSP_REG_N1], 32, BITMASK(16) }, - { "N2", &dsp->core.registers[DSP_REG_N2], 32, BITMASK(16) }, - { "N3", &dsp->core.registers[DSP_REG_N3], 32, BITMASK(16) }, - { "N4", &dsp->core.registers[DSP_REG_N4], 32, BITMASK(16) }, - { "N5", &dsp->core.registers[DSP_REG_N5], 32, BITMASK(16) }, - { "N6", &dsp->core.registers[DSP_REG_N6], 32, BITMASK(16) }, - { "N7", &dsp->core.registers[DSP_REG_N7], 32, BITMASK(16) }, - - { "OMR", &dsp->core.registers[DSP_REG_OMR], 32, 0x5f }, - - /* 16-bit program counter */ - { "PC", (uint32_t*)(&dsp->core.pc), 24, BITMASK(24) }, - - /* 16-bit DSP R (address) registers */ - { "R0", &dsp->core.registers[DSP_REG_R0], 32, BITMASK(16) }, - { "R1", &dsp->core.registers[DSP_REG_R1], 32, BITMASK(16) }, - { "R2", &dsp->core.registers[DSP_REG_R2], 32, BITMASK(16) }, - { "R3", &dsp->core.registers[DSP_REG_R3], 32, BITMASK(16) }, - { "R4", &dsp->core.registers[DSP_REG_R4], 32, BITMASK(16) }, - { "R5", &dsp->core.registers[DSP_REG_R5], 32, BITMASK(16) }, - { "R6", &dsp->core.registers[DSP_REG_R6], 32, BITMASK(16) }, - { "R7", &dsp->core.registers[DSP_REG_R7], 32, BITMASK(16) }, - - { "SSH", &dsp->core.registers[DSP_REG_SSH], 32, BITMASK(16) }, - { "SSL", &dsp->core.registers[DSP_REG_SSL], 32, BITMASK(16) }, - { "SP", &dsp->core.registers[DSP_REG_SP], 32, BITMASK(6) }, - - /* 16-bit status register */ - { "SR", &dsp->core.registers[DSP_REG_SR], 32, 0xefff }, - - /* 48-bit X register */ - { "X0", &dsp->core.registers[DSP_REG_X0], 32, BITMASK(24) }, - { "X1", &dsp->core.registers[DSP_REG_X1], 32, BITMASK(24) }, - - /* 48-bit Y register */ - { "Y0", &dsp->core.registers[DSP_REG_Y0], 32, BITMASK(24) }, - { "Y1", &dsp->core.registers[DSP_REG_Y1], 32, BITMASK(24) } - }; - /* left, right, middle, direction */ - int l, r, m, dir = 0; - unsigned int i, len; - char reg[MAX_REGNAME_LEN]; - - for (i = 0; i < sizeof(reg) && regname[i]; i++) { - reg[i] = toupper(regname[i]); - } - if (i < 2 || regname[i]) { - /* too short or longer than any of the names */ - return 0; - } - len = i; - - /* bisect */ - l = 0; - r = ARRAY_SIZE(registers) - 1; - do { - m = (l+r) >> 1; - for (i = 0; i < len; i++) { - dir = (int)reg[i] - registers[m].name[i]; - if (dir) { - break; - } - } - if (dir == 0) { - *addr = registers[m].addr; - *mask = registers[m].mask; - return registers[m].bits; - } - if (dir < 0) { - r = m-1; - } else { - l = m+1; - } - } while (l <= r); -#undef MAX_REGNAME_LEN - return 0; -} - - -/** - * Set given DSP register value, return false if unknown register given - */ -bool dsp_disasm_set_register(DSPState* dsp, const char *arg, uint32_t value) -{ - uint32_t *addr, mask, sp_value; - int bits; - - /* first check registers needing special handling... */ - if (arg[0]=='S' || arg[0]=='s') { - if (arg[1]=='P' || arg[1]=='p') { - dsp->core.registers[DSP_REG_SP] = value & BITMASK(6); - value &= BITMASK(4); - dsp->core.registers[DSP_REG_SSH] = dsp->core.stack[0][value]; - dsp->core.registers[DSP_REG_SSL] = dsp->core.stack[1][value]; - return true; - } - if (arg[1]=='S' || arg[1]=='s') { - sp_value = dsp->core.registers[DSP_REG_SP] & BITMASK(4); - if (arg[2]=='H' || arg[2]=='h') { - if (sp_value == 0) { - dsp->core.registers[DSP_REG_SSH] = 0; - dsp->core.stack[0][sp_value] = 0; - } else { - dsp->core.registers[DSP_REG_SSH] = value & BITMASK(16); - dsp->core.stack[0][sp_value] = value & BITMASK(16); - } - return true; - } - if (arg[2]=='L' || arg[2]=='l') { - if (sp_value == 0) { - dsp->core.registers[DSP_REG_SSL] = 0; - dsp->core.stack[1][sp_value] = 0; - } else { - dsp->core.registers[DSP_REG_SSL] = value & BITMASK(16); - dsp->core.stack[1][sp_value] = value & BITMASK(16); - } - return true; - } - } - } - - /* ...then registers where address & mask are enough */ - bits = dsp_get_register_address(dsp, arg, &addr, &mask); - switch (bits) { - case 32: - *addr = value & mask; - return true; - case 16: - *(uint16_t*)addr = value & mask; - return true; - } - return false; -} diff --git a/hw/xbox/mcpx/dsp/dsp.h b/hw/xbox/mcpx/dsp/dsp.h index 0b18fa0c45..d85e03d55e 100644 --- a/hw/xbox/mcpx/dsp/dsp.h +++ b/hw/xbox/mcpx/dsp/dsp.h @@ -36,7 +36,6 @@ typedef void (*dsp_scratch_rw_func)( typedef void (*dsp_fifo_rw_func)( void *opaque, uint8_t *ptr, unsigned int index, size_t len, bool dir); -/* Dsp commands */ DSPState *dsp_init(void *rw_opaque, dsp_scratch_rw_func scratch_rw, dsp_fifo_rw_func fifo_rw); @@ -49,16 +48,14 @@ void dsp_run(DSPState* dsp, int cycles); void dsp_bootstrap(DSPState* dsp); void dsp_start_frame(DSPState* dsp); - -/* Dsp Debugger commands */ uint32_t dsp_read_memory(DSPState* dsp, char space, uint32_t addr); void dsp_write_memory(DSPState* dsp, char space, uint32_t address, uint32_t value); -uint32_t dsp_disasm_memory(DSPState* dsp, uint32_t dsp_memdump_addr, uint32_t dsp_memdump_upper, char space); -uint32_t dsp_disasm_address(DSPState* dsp, FILE *out, uint32_t lowerAdr, uint32_t UpperAdr); + void dsp_info(DSPState* dsp); void dsp_print_registers(DSPState* dsp); int dsp_get_register_address(DSPState* dsp, const char *arg, uint32_t **addr, uint32_t *mask); +uint32_t dsp_disasm_memory(DSPState* dsp, uint32_t dsp_memdump_addr, uint32_t dsp_memdump_upper, char space); +uint32_t dsp_disasm_address(DSPState* dsp, FILE *out, uint32_t lowerAdr, uint32_t UpperAdr); bool dsp_disasm_set_register(DSPState* dsp, const char *arg, uint32_t value); - #endif /* DSP_H */ diff --git a/hw/xbox/mcpx/dsp/dsp_cpu.c b/hw/xbox/mcpx/dsp/dsp_cpu.c index 874dd494ce..380c07e1bb 100644 --- a/hw/xbox/mcpx/dsp/dsp_cpu.c +++ b/hw/xbox/mcpx/dsp/dsp_cpu.c @@ -2,6 +2,7 @@ * DSP56300 emulator * * Copyright (c) 2015 espes + * Copyright (c) 2020-2025 Matt Borgerson * * Adapted from Hatari DSP M56001 emulation * (C) 2003-2008 ARAnyM developer team @@ -23,20 +24,10 @@ */ #include "qemu/osdep.h" - -#include -#include -#include - #include "qemu/bswap.h" - #include "dsp_cpu.h" - -#define TRACE_DSP_DISASM 0 -#define TRACE_DSP_DISASM_REG 0 -#define TRACE_DSP_DISASM_MEM 0 - -#define DPRINTF(s, ...) printf(s, ## __VA_ARGS__) +#include "debug.h" +#include "trace.h" #define BITMASK(x) ((1<<(x))-1) @@ -80,18 +71,18 @@ static void dsp_rnd56(dsp_core_t* dsp, uint32_t *dest); static uint32_t dsp_signextend(int bits, uint32_t v); static const dsp_interrupt_t dsp_interrupt[12] = { - {DSP_INTER_RESET , 0x00, 0, "Reset"}, - {DSP_INTER_ILLEGAL , 0x3e, 0, "Illegal"}, - {DSP_INTER_STACK_ERROR , 0x02, 0, "Stack Error"}, - {DSP_INTER_TRACE , 0x04, 0, "Trace"}, - {DSP_INTER_SWI , 0x06, 0, "Swi"}, - {DSP_INTER_HOST_COMMAND , 0xff, 1, "Host Command"}, - {DSP_INTER_HOST_RCV_DATA, 0x20, 1, "Host receive"}, - {DSP_INTER_HOST_TRX_DATA, 0x22, 1, "Host transmit"}, - {DSP_INTER_SSI_RCV_DATA_E, 0x0e, 2, "SSI receive with exception"}, - {DSP_INTER_SSI_RCV_DATA , 0x0c, 2, "SSI receive"}, - {DSP_INTER_SSI_TRX_DATA_E, 0x12, 2, "SSI transmit with exception"}, - {DSP_INTER_SSI_TRX_DATA , 0x10, 2, "SSI tramsmit"} + { DSP_INTER_RESET, 0x00, 0, "Reset" }, + { DSP_INTER_ILLEGAL, 0x3e, 0, "Illegal" }, + { DSP_INTER_STACK_ERROR, 0x02, 0, "Stack Error" }, + { DSP_INTER_TRACE, 0x04, 0, "Trace" }, + { DSP_INTER_SWI, 0x06, 0, "Swi" }, + { DSP_INTER_HOST_COMMAND, 0xff, 1, "Host Command" }, + { DSP_INTER_HOST_RCV_DATA, 0x20, 1, "Host receive" }, + { DSP_INTER_HOST_TRX_DATA, 0x22, 1, "Host transmit" }, + { DSP_INTER_SSI_RCV_DATA_E, 0x0e, 2, "SSI receive with exception" }, + { DSP_INTER_SSI_RCV_DATA, 0x0c, 2, "SSI receive" }, + { DSP_INTER_SSI_TRX_DATA_E, 0x12, 2, "SSI transmit with exception" }, + { DSP_INTER_SSI_TRX_DATA, 0x10, 2, "SSI transmit" } }; static const int registers_tcc[16][2] = { @@ -138,9 +129,8 @@ static const int registers_mask[64] = { 16, 16, 16, 16 }; -#include "dsp_emu.inl" - -#include "dsp_dis.inl" +#include "dsp_emu.c.inc" +#include "dsp_dis.c.inc" typedef bool (*match_func_t)(uint32_t op); @@ -415,7 +405,6 @@ void dsp56k_reset_cpu(dsp_core_t* dsp) /* runtime shit */ - dsp->executing_for_disasm = false; // start_time = SDL_GetTicks(); dsp->num_inst = 0; @@ -462,7 +451,7 @@ static uint16_t disasm_instruction(dsp_core_t* dsp, dsp_trace_disasm_t mode) if (mode == DSP_TRACE_MODE) { if (dsp->disasm_prev_inst_pc == dsp->pc) { if (!dsp->disasm_is_looping) { - printf( "Looping on DSP instruction at PC = $%04x\n", dsp->disasm_prev_inst_pc); + DPRINTF("Looping on DSP instruction at PC = $%04x\n", dsp->disasm_prev_inst_pc); dsp->disasm_is_looping = true; } return 0; @@ -520,7 +509,7 @@ static void disasm_reg_compare(dsp_core_t* dsp) case DSP_REG_X1: case DSP_REG_Y0: case DSP_REG_Y1: - printf("\tReg: %s $%06x -> $%06x\n", + DPRINTF("\tReg: %s $%06x -> $%06x\n", registers_name[i], dsp->disasm_registers_save[i], dsp->registers[i]); break; case DSP_REG_R0: @@ -550,21 +539,21 @@ static void disasm_reg_compare(dsp_core_t* dsp) case DSP_REG_SR: case DSP_REG_LA: case DSP_REG_LC: - printf("\tReg: %s $%04x -> $%04x\n", + DPRINTF("\tReg: %s $%04x -> $%04x\n", registers_name[i], dsp->disasm_registers_save[i], dsp->registers[i]); break; case DSP_REG_OMR: case DSP_REG_SP: case DSP_REG_SSH: case DSP_REG_SSL: - printf("\tReg: %s $%02x -> $%02x\n", + DPRINTF("\tReg: %s $%02x -> $%02x\n", registers_name[i], dsp->disasm_registers_save[i], dsp->registers[i]); break; case DSP_REG_A0: case DSP_REG_A1: case DSP_REG_A2: if (bRegA == false) { - printf("\tReg: a $%02x:%06x:%06x -> $%02x:%06x:%06x\n", + DPRINTF("\tReg: a $%02x:%06x:%06x -> $%02x:%06x:%06x\n", dsp->disasm_registers_save[DSP_REG_A2], dsp->disasm_registers_save[DSP_REG_A1], dsp->disasm_registers_save[DSP_REG_A0], dsp->registers[DSP_REG_A2], dsp->registers[DSP_REG_A1], dsp->registers[DSP_REG_A0] ); @@ -575,7 +564,7 @@ static void disasm_reg_compare(dsp_core_t* dsp) case DSP_REG_B1: case DSP_REG_B2: if (bRegB == false) { - printf("\tReg: b $%02x:%06x:%06x -> $%02x:%06x:%06x\n", + DPRINTF("\tReg: b $%02x:%06x:%06x -> $%02x:%06x:%06x\n", dsp->disasm_registers_save[DSP_REG_B2], dsp->disasm_registers_save[DSP_REG_B1], dsp->disasm_registers_save[DSP_REG_B0], dsp->registers[DSP_REG_B2], dsp->registers[DSP_REG_B1], dsp->registers[DSP_REG_B0] ); @@ -587,70 +576,28 @@ static void disasm_reg_compare(dsp_core_t* dsp) #ifdef DSP_DISASM_REG_PC if (pc_save != dsp->pc) { - printf("\tReg: pc $%04x -> $%04x\n", pc_save, dsp->pc); + DPRINTF("\tReg: pc $%04x -> $%04x\n", pc_save, dsp->pc); } #endif } static const char* disasm_get_instruction_text(dsp_core_t* dsp) { - // const int len = sizeof(dsp->disasm_str_instr); - // uint64_t count, cycles; - // uint16_t cycle_diff; - // float percentage; - // int offset; - if (dsp->disasm_is_looping) { dsp->disasm_str_instr2[0] = 0; } - // if (dsp->disasm_cur_inst_len == 1) { - // offset = sprintf(dsp->disasm_str_instr2, "p:%04x %06x (%02d cyc) %-*s\n", dsp->disasm_prev_inst_pc, dsp->disasm_cur_inst, dsp->instr_cycle, len, dsp->disasm_str_instr); - // } else { - // offset = sprintf(dsp->disasm_str_instr2, "p:%04x %06x %06x (%02d cyc) %-*s\n", dsp->disasm_prev_inst_pc, dsp->disasm_cur_inst, read_memory_p(dsp, dsp->disasm_prev_inst_pc + 1), dsp->instr_cycle, len, dsp->disasm_str_instr); - // } - // if (offset > 2 && Profile_DspAddressData(dsp->disasm_prev_inst_pc, &percentage, &count, &cycles, &cycle_diff)) { - // offset -= 2; - // sprintf(str_instr2+offset, "%5.2f%% (%"PRId64", %"PRId64", %d)\n", - // percentage, count, cycles, cycle_diff); - // } + if (dsp->disasm_cur_inst_len == 1) { + snprintf(dsp->disasm_str_instr2, sizeof(dsp->disasm_str_instr2), "p:%04x %06x (%02d cyc) %s", dsp->disasm_prev_inst_pc, dsp->disasm_cur_inst, dsp->instr_cycle, dsp->disasm_str_instr); + } else { + snprintf(dsp->disasm_str_instr2, sizeof(dsp->disasm_str_instr2), "p:%04x %06x %06x (%02d cyc) %s", dsp->disasm_prev_inst_pc, dsp->disasm_cur_inst, read_memory_p(dsp, dsp->disasm_prev_inst_pc + 1), dsp->instr_cycle, dsp->disasm_str_instr); + } return dsp->disasm_str_instr2; } -/** - * Execute one instruction in trace mode at a given PC address. - * */ -uint16_t dsp56k_execute_one_disasm_instruction(dsp_core_t* dsp, FILE *out, uint32_t pc) -{ - dsp_core_t dsp_core_save; - - /* Set DSP in disasm mode */ - dsp->executing_for_disasm = true; - - /* Save DSP context before executing instruction */ - memcpy(&dsp_core_save, dsp, sizeof(dsp_core_t)); - - /* execute and disasm instruction */ - dsp->pc = pc; - - /* Disasm instruction */ - uint16_t instruction_length = disasm_instruction(dsp, DSP_DISASM_MODE) - 1; - - /* Execute instruction at address given in parameter to get the number of cycles it takes */ - dsp56k_execute_instruction(dsp); - - fprintf(out, "%s", disasm_get_instruction_text(dsp)); - - /* Restore DSP context after executing instruction */ - memcpy(dsp, &dsp_core_save, sizeof(dsp_core_t)); - - /* Unset DSP in disasm mode */ - dsp->executing_for_disasm = false; - - return instruction_length; -} - void dsp56k_execute_instruction(dsp_core_t* dsp) { + trace_dsp56k_execute_instruction(dsp->is_gp, dsp->pc); + uint32_t disasm_return = 0; dsp->disasm_memory_ptr = 0; @@ -661,17 +608,18 @@ void dsp56k_execute_instruction(dsp_core_t* dsp) dsp->cur_inst_len = 1; dsp->instr_cycle = 2; - /* Disasm current instruction ? (trace mode only) */ - if (TRACE_DSP_DISASM) { - /* Call disasm_instruction only when DSP is called in trace mode */ - if (!dsp->executing_for_disasm) { - disasm_return = disasm_instruction(dsp, DSP_TRACE_MODE); + bool tracing = TRACE_DSP_DISASM || trace_event_get_state(TRACE_DSP56K_EXECUTE_INSTRUCTION_DISASM); - if (disasm_return) { - printf( "%s", disasm_get_instruction_text(dsp)); + /* Disasm current instruction ? (trace mode only) */ + if (tracing) { + disasm_return = disasm_instruction(dsp, DSP_TRACE_MODE); + if (disasm_return) { + const char *text = disasm_get_instruction_text(dsp); + trace_dsp56k_execute_instruction_disasm(text); + if (TRACE_DSP_DISASM) { + DPRINTF("%s\n", text); } - if (disasm_return != 0 && TRACE_DSP_DISASM_REG) { - /* DSP regs trace enabled only if DSP DISASM is enabled */ + if (TRACE_DSP_DISASM_REG) { disasm_reg_save(dsp); } } @@ -686,7 +634,7 @@ void dsp56k_execute_instruction(dsp_core_t* dsp) if (op->emu_func) { op->emu_func(dsp); } else { - printf("%x - %s\n", dsp->cur_inst, op->name); + DPRINTF("%x - %s\n", dsp->cur_inst, op->name); emu_undefined(dsp); } } else { @@ -695,26 +643,18 @@ void dsp56k_execute_instruction(dsp_core_t* dsp) } /* Disasm current instruction ? (trace mode only) */ - if (TRACE_DSP_DISASM) { - /* Display only when DSP is called in trace mode */ - if (!dsp->executing_for_disasm) { - if (disasm_return != 0) { - // printf( "%s", disasm_get_instruction_text(dsp)); - - /* DSP regs trace enabled only if DSP DISASM is enabled */ - if (TRACE_DSP_DISASM_REG) - disasm_reg_compare(dsp); - - if (TRACE_DSP_DISASM_MEM) { - /* 1 memory change to display ? */ - if (dsp->disasm_memory_ptr == 1) - printf( "\t%s\n", dsp->str_disasm_memory[0]); - /* 2 memory changes to display ? */ - else if (dsp->disasm_memory_ptr == 2) { - printf( "\t%s\n", dsp->str_disasm_memory[0]); - printf( "\t%s\n", dsp->str_disasm_memory[1]); - } - } + if (tracing && disasm_return) { + if (TRACE_DSP_DISASM_REG) { + disasm_reg_compare(dsp); + } + if (TRACE_DSP_DISASM_MEM) { + /* 1 memory change to display ? */ + if (dsp->disasm_memory_ptr == 1) + DPRINTF("\t%s\n", dsp->str_disasm_memory[0]); + /* 2 memory changes to display ? */ + else if (dsp->disasm_memory_ptr == 2) { + DPRINTF("\t%s\n", dsp->str_disasm_memory[0]); + DPRINTF("\t%s\n", dsp->str_disasm_memory[1]); } } } @@ -734,7 +674,7 @@ void dsp56k_execute_instruction(dsp_core_t* dsp) /* Evaluate time after instructions have been executed to avoid asking too frequently */ uint32_t cur_time = SDL_GetTicks(); if (cur_time-start_time>1000) { - printf( "Dsp: %d i/s\n", (dsp->num_inst*1000)/(cur_time-start_time)); + DPRINTF("Dsp: %d i/s\n", (dsp->num_inst*1000)/(cur_time-start_time)); start_time=cur_time; dsp->num_inst=0; } @@ -1021,9 +961,6 @@ uint32_t dsp56k_read_memory(dsp_core_t* dsp, int space, uint32_t address) void dsp56k_write_memory(dsp_core_t* dsp, int space, uint32_t address, uint32_t value) { - assert((value & 0xFF000000) == 0); - assert((address & 0xFF000000) == 0); - if (TRACE_DSP_DISASM_MEM) write_memory_disasm(dsp, space, address, value); else @@ -1122,9 +1059,7 @@ static void dsp_write_reg(dsp_core_t* dsp, uint32_t numreg, uint32_t value) /* Stack underflow or overflow detected, raise interrupt */ dsp56k_add_interrupt(dsp, DSP_INTER_STACK_ERROR); dsp->registers[DSP_REG_SP] = value & (3<executing_for_disasm) { - printf( "Dsp: Stack Overflow or Underflow\n"); - } + DPRINTF("Dsp: Stack Overflow or Underflow\n"); if (dsp->exception_debugging) { assert(false); } @@ -1167,8 +1102,7 @@ static void dsp_stack_push(dsp_core_t* dsp, uint32_t curpc, uint32_t cursr, uint if ((stack_error==0) && (stack & (1<executing_for_disasm) - printf("Dsp: Stack Overflow\n"); + DPRINTF("Dsp: Stack Overflow\n"); if (dsp->exception_debugging) assert(false); } @@ -1204,8 +1138,7 @@ static void dsp_stack_pop(dsp_core_t* dsp, uint32_t *newpc, uint32_t *newsr) if ((stack_error==0) && (stack & (1<executing_for_disasm) - printf("Dsp: Stack underflow\n"); + DPRINTF("Dsp: Stack underflow\n"); if (dsp->exception_debugging) assert(false); } @@ -1458,5 +1391,3 @@ static uint32_t dsp_signextend(int bits, uint32_t v) { assert(shift > 0); return (uint32_t)(((int32_t)v << shift) >> shift); } - - diff --git a/hw/xbox/mcpx/dsp/dsp_cpu.h b/hw/xbox/mcpx/dsp/dsp_cpu.h index 6876b4d20a..4cffd2631d 100644 --- a/hw/xbox/mcpx/dsp/dsp_cpu.h +++ b/hw/xbox/mcpx/dsp/dsp_cpu.h @@ -29,115 +29,7 @@ #include #include -#define DSP_OMR_MA 0x00 -#define DSP_OMR_MB 0x01 -#define DSP_OMR_DE 0x02 -#define DSP_OMR_SD 0x06 -#define DSP_OMR_EA 0x07 - -#define DSP_SR_C 0x00 -#define DSP_SR_V 0x01 -#define DSP_SR_Z 0x02 -#define DSP_SR_N 0x03 -#define DSP_SR_U 0x04 -#define DSP_SR_E 0x05 -#define DSP_SR_L 0x06 - -#define DSP_SR_I0 0x08 -#define DSP_SR_I1 0x09 -#define DSP_SR_S0 0x0a -#define DSP_SR_S1 0x0b -#define DSP_SR_T 0x0d -#define DSP_SR_LF 0x0f - -#define DSP_SP_SE 0x04 -#define DSP_SP_UF 0x05 - -/* Registers numbers in dsp.registers[] */ -#define DSP_REG_X0 0x04 -#define DSP_REG_X1 0x05 -#define DSP_REG_Y0 0x06 -#define DSP_REG_Y1 0x07 -#define DSP_REG_A0 0x08 -#define DSP_REG_B0 0x09 -#define DSP_REG_A2 0x0a -#define DSP_REG_B2 0x0b -#define DSP_REG_A1 0x0c -#define DSP_REG_B1 0x0d -#define DSP_REG_A 0x0e -#define DSP_REG_B 0x0f - -#define DSP_REG_R0 0x10 -#define DSP_REG_R1 0x11 -#define DSP_REG_R2 0x12 -#define DSP_REG_R3 0x13 -#define DSP_REG_R4 0x14 -#define DSP_REG_R5 0x15 -#define DSP_REG_R6 0x16 -#define DSP_REG_R7 0x17 - -#define DSP_REG_N0 0x18 -#define DSP_REG_N1 0x19 -#define DSP_REG_N2 0x1a -#define DSP_REG_N3 0x1b -#define DSP_REG_N4 0x1c -#define DSP_REG_N5 0x1d -#define DSP_REG_N6 0x1e -#define DSP_REG_N7 0x1f - -#define DSP_REG_M0 0x20 -#define DSP_REG_M1 0x21 -#define DSP_REG_M2 0x22 -#define DSP_REG_M3 0x23 -#define DSP_REG_M4 0x24 -#define DSP_REG_M5 0x25 -#define DSP_REG_M6 0x26 -#define DSP_REG_M7 0x27 - -#define DSP_REG_SR 0x39 -#define DSP_REG_OMR 0x3a -#define DSP_REG_SP 0x3b -#define DSP_REG_SSH 0x3c -#define DSP_REG_SSL 0x3d -#define DSP_REG_LA 0x3e -#define DSP_REG_LC 0x3f - -#define DSP_REG_NULL 0x00 -#define DSP_REG_LCSAVE 0x30 - -#define DSP_REG_MAX 0x40 - -/* Memory spaces for dsp.ram[], dsp.rom[] */ -#define DSP_SPACE_X 0x00 -#define DSP_SPACE_Y 0x01 -#define DSP_SPACE_P 0x02 - -#define DSP_XRAM_SIZE 4096 -#define DSP_YRAM_SIZE 2048 -#define DSP_PRAM_SIZE 4096 - -#define DSP_MIXBUFFER_BASE 0x001400 -#define DSP_MIXBUFFER_SIZE 1024 - -#define DSP_PERIPH_BASE 0xFFFF80 -#define DSP_PERIPH_SIZE 128 - -#define DSP_INTERRUPT_NONE 0x0 -#define DSP_INTERRUPT_DISABLED 0x1 -#define DSP_INTERRUPT_LONG 0x2 - -#define DSP_INTER_RESET 0x0 -#define DSP_INTER_ILLEGAL 0x1 -#define DSP_INTER_STACK_ERROR 0x2 -#define DSP_INTER_TRACE 0x3 -#define DSP_INTER_SWI 0x4 -#define DSP_INTER_HOST_COMMAND 0x5 -#define DSP_INTER_HOST_RCV_DATA 0x6 -#define DSP_INTER_HOST_TRX_DATA 0x7 -#define DSP_INTER_SSI_RCV_DATA_E 0x8 -#define DSP_INTER_SSI_RCV_DATA 0x9 -#define DSP_INTER_SSI_TRX_DATA_E 0xa -#define DSP_INTER_SSI_TRX_DATA 0xb +#include "dsp_cpu_regs.h" typedef enum { DSP_TRACE_MODE, @@ -209,10 +101,6 @@ struct dsp_core_s { /* Current instruction */ uint32_t cur_inst; - /* DSP is in disasm mode ? */ - /* If yes, stack overflow, underflow and illegal instructions messages are not displayed */ - bool executing_for_disasm; - char str_disasm_memory[2][50]; /* Buffer for memory change text in disasm mode */ uint32_t disasm_memory_ptr; /* Pointer for memory change in disasm mode */ @@ -250,7 +138,6 @@ struct dsp_core_s { /* Functions */ void dsp56k_reset_cpu(dsp_core_t* dsp); /* Set dsp_core to use */ void dsp56k_execute_instruction(dsp_core_t* dsp); /* Execute 1 instruction */ -uint16_t dsp56k_execute_one_disasm_instruction(dsp_core_t* dsp, FILE *out, uint32_t pc); /* Execute 1 instruction in disasm mode */ uint32_t dsp56k_read_memory(dsp_core_t* dsp, int space, uint32_t address); void dsp56k_write_memory(dsp_core_t* dsp, int space, uint32_t address, uint32_t value); diff --git a/hw/xbox/mcpx/dsp/dsp_cpu_regs.h b/hw/xbox/mcpx/dsp/dsp_cpu_regs.h new file mode 100644 index 0000000000..75b2009b2f --- /dev/null +++ b/hw/xbox/mcpx/dsp/dsp_cpu_regs.h @@ -0,0 +1,138 @@ +/* + * DSP56300 emulator + * + * Copyright (c) 2015 espes + * + * Adapted from Hatari DSP M56001 emulation + * (C) 2003-2008 ARAnyM developer team + * Adaption to Hatari (C) 2008 by Thomas Huth + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef HW_XBOX_MCPX_DSP_DSP_CPU_REGS_H +#define HW_XBOX_MCPX_DSP_DSP_CPU_REGS_H + +#define DSP_OMR_MA 0x00 +#define DSP_OMR_MB 0x01 +#define DSP_OMR_DE 0x02 +#define DSP_OMR_SD 0x06 +#define DSP_OMR_EA 0x07 + +#define DSP_SR_C 0x00 +#define DSP_SR_V 0x01 +#define DSP_SR_Z 0x02 +#define DSP_SR_N 0x03 +#define DSP_SR_U 0x04 +#define DSP_SR_E 0x05 +#define DSP_SR_L 0x06 + +#define DSP_SR_I0 0x08 +#define DSP_SR_I1 0x09 +#define DSP_SR_S0 0x0a +#define DSP_SR_S1 0x0b +#define DSP_SR_T 0x0d +#define DSP_SR_LF 0x0f + +#define DSP_SP_SE 0x04 +#define DSP_SP_UF 0x05 + +/* Registers numbers in dsp.registers[] */ +#define DSP_REG_X0 0x04 +#define DSP_REG_X1 0x05 +#define DSP_REG_Y0 0x06 +#define DSP_REG_Y1 0x07 +#define DSP_REG_A0 0x08 +#define DSP_REG_B0 0x09 +#define DSP_REG_A2 0x0a +#define DSP_REG_B2 0x0b +#define DSP_REG_A1 0x0c +#define DSP_REG_B1 0x0d +#define DSP_REG_A 0x0e +#define DSP_REG_B 0x0f + +#define DSP_REG_R0 0x10 +#define DSP_REG_R1 0x11 +#define DSP_REG_R2 0x12 +#define DSP_REG_R3 0x13 +#define DSP_REG_R4 0x14 +#define DSP_REG_R5 0x15 +#define DSP_REG_R6 0x16 +#define DSP_REG_R7 0x17 + +#define DSP_REG_N0 0x18 +#define DSP_REG_N1 0x19 +#define DSP_REG_N2 0x1a +#define DSP_REG_N3 0x1b +#define DSP_REG_N4 0x1c +#define DSP_REG_N5 0x1d +#define DSP_REG_N6 0x1e +#define DSP_REG_N7 0x1f + +#define DSP_REG_M0 0x20 +#define DSP_REG_M1 0x21 +#define DSP_REG_M2 0x22 +#define DSP_REG_M3 0x23 +#define DSP_REG_M4 0x24 +#define DSP_REG_M5 0x25 +#define DSP_REG_M6 0x26 +#define DSP_REG_M7 0x27 + +#define DSP_REG_SR 0x39 +#define DSP_REG_OMR 0x3a +#define DSP_REG_SP 0x3b +#define DSP_REG_SSH 0x3c +#define DSP_REG_SSL 0x3d +#define DSP_REG_LA 0x3e +#define DSP_REG_LC 0x3f + +#define DSP_REG_NULL 0x00 +#define DSP_REG_LCSAVE 0x30 + +#define DSP_REG_MAX 0x40 + +/* Memory spaces for dsp.ram[], dsp.rom[] */ +#define DSP_SPACE_X 0x00 +#define DSP_SPACE_Y 0x01 +#define DSP_SPACE_P 0x02 + +#define DSP_XRAM_SIZE 4096 +#define DSP_YRAM_SIZE 2048 +#define DSP_PRAM_SIZE 4096 + +#define DSP_MIXBUFFER_BASE 0x001400 +#define DSP_MIXBUFFER_SIZE 1024 + +#define DSP_PERIPH_BASE 0xFFFF80 +#define DSP_PERIPH_SIZE 128 + +#define DSP_INTERRUPT_NONE 0x0 +#define DSP_INTERRUPT_DISABLED 0x1 +#define DSP_INTERRUPT_LONG 0x2 + +#define DSP_INTER_RESET 0x0 +#define DSP_INTER_ILLEGAL 0x1 +#define DSP_INTER_STACK_ERROR 0x2 +#define DSP_INTER_TRACE 0x3 +#define DSP_INTER_SWI 0x4 +#define DSP_INTER_HOST_COMMAND 0x5 +#define DSP_INTER_HOST_RCV_DATA 0x6 +#define DSP_INTER_HOST_TRX_DATA 0x7 +#define DSP_INTER_SSI_RCV_DATA_E 0x8 +#define DSP_INTER_SSI_RCV_DATA 0x9 +#define DSP_INTER_SSI_TRX_DATA_E 0xa +#define DSP_INTER_SSI_TRX_DATA 0xb + +#endif diff --git a/hw/xbox/mcpx/dsp/dsp_dis.inl b/hw/xbox/mcpx/dsp/dsp_dis.c.inc similarity index 100% rename from hw/xbox/mcpx/dsp/dsp_dis.inl rename to hw/xbox/mcpx/dsp/dsp_dis.c.inc diff --git a/hw/xbox/mcpx/dsp/dsp_dma.c b/hw/xbox/mcpx/dsp/dsp_dma.c index 377475fb76..98f7bc3cb7 100644 --- a/hw/xbox/mcpx/dsp/dsp_dma.c +++ b/hw/xbox/mcpx/dsp/dsp_dma.c @@ -18,48 +18,14 @@ * License along with this library; if not, see . */ -#include -#include -#include -#include - -#include +#include "qemu/osdep.h" #include "qemu/compiler.h" #include "dsp_dma.h" +#include "dsp_dma_regs.h" #include "dsp_state.h" - -#define DMA_CONFIGURATION_AUTOSTART (1 << 0) -#define DMA_CONFIGURATION_AUTOREADY (1 << 1) -#define DMA_CONFIGURATION_IOC_CLEAR (1 << 2) -#define DMA_CONFIGURATION_EOL_CLEAR (1 << 3) -#define DMA_CONFIGURATION_ERR_CLEAR (1 << 4) - -#define DMA_CONTROL_ACTION 0x7 -#define DMA_CONTROL_ACTION_NOP 0 -#define DMA_CONTROL_ACTION_START 1 -#define DMA_CONTROL_ACTION_STOP 2 -#define DMA_CONTROL_ACTION_FREEZE 3 -#define DMA_CONTROL_ACTION_UNFREEZE 4 -#define DMA_CONTROL_ACTION_ABORT 5 -#define DMA_CONTROL_FROZEN (1 << 3) -#define DMA_CONTROL_RUNNING (1 << 4) -#define DMA_CONTROL_STOPPED (1 << 5) - -#define NODE_POINTER_VAL 0x3fff -#define NODE_POINTER_EOL (1 << 14) - -#define NODE_CONTROL_DIRECTION (1 << 1) - - -// #define DEBUG #ifdef DEBUG -# define DPRINTF(s, ...) printf(s, ## __VA_ARGS__) -#else -# define DPRINTF(s, ...) do { } while (0) -#endif -#ifdef DEBUG const char *buffer_names[] = { "fifo0", /* 0x0 */ "fifo1", /* 0x1 */ @@ -98,8 +64,6 @@ const char *space_names[] = { #endif -#define MIN(a,b) (((a)<(b))?(a):(b)) - static void scratch_circular_copy( DSPDMAState *s, uint32_t scratch_base, @@ -142,8 +106,6 @@ static void dsp_dma_run(DSPDMAState *s) return; } - // DSPState *dsp = container_of(s, DSPState, dma); - while (!(s->next_block & NODE_POINTER_EOL)) { uint32_t addr = s->next_block & NODE_POINTER_VAL; uint32_t block_addr = 0; diff --git a/hw/xbox/mcpx/dsp/dsp_dma_regs.h b/hw/xbox/mcpx/dsp/dsp_dma_regs.h new file mode 100644 index 0000000000..a373cb7c14 --- /dev/null +++ b/hw/xbox/mcpx/dsp/dsp_dma_regs.h @@ -0,0 +1,46 @@ +/* + * MCPX DSP DMA + * + * Copyright (c) 2015 espes + * Copyright (c) 2020-2025 Matt Borgerson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef HW_XBOX_MCPX_DSP_DSP_DMA_REGS_H +#define HW_XBOX_MCPX_DSP_DSP_DMA_REGS_H + +#define DMA_CONFIGURATION_AUTOSTART (1 << 0) +#define DMA_CONFIGURATION_AUTOREADY (1 << 1) +#define DMA_CONFIGURATION_IOC_CLEAR (1 << 2) +#define DMA_CONFIGURATION_EOL_CLEAR (1 << 3) +#define DMA_CONFIGURATION_ERR_CLEAR (1 << 4) + +#define DMA_CONTROL_ACTION 0x7 +#define DMA_CONTROL_ACTION_NOP 0 +#define DMA_CONTROL_ACTION_START 1 +#define DMA_CONTROL_ACTION_STOP 2 +#define DMA_CONTROL_ACTION_FREEZE 3 +#define DMA_CONTROL_ACTION_UNFREEZE 4 +#define DMA_CONTROL_ACTION_ABORT 5 +#define DMA_CONTROL_FROZEN (1 << 3) +#define DMA_CONTROL_RUNNING (1 << 4) +#define DMA_CONTROL_STOPPED (1 << 5) + +#define NODE_POINTER_VAL 0x3fff +#define NODE_POINTER_EOL (1 << 14) + +#define NODE_CONTROL_DIRECTION (1 << 1) + +#endif diff --git a/hw/xbox/mcpx/dsp/dsp_emu.inl b/hw/xbox/mcpx/dsp/dsp_emu.c.inc similarity index 99% rename from hw/xbox/mcpx/dsp/dsp_emu.inl rename to hw/xbox/mcpx/dsp/dsp_emu.c.inc index e509baa2d7..b67ea13398 100644 --- a/hw/xbox/mcpx/dsp/dsp_emu.inl +++ b/hw/xbox/mcpx/dsp/dsp_emu.c.inc @@ -27,15 +27,10 @@ typedef void (*emu_func_t)(dsp_core_t* dsp); static void emu_undefined(dsp_core_t* dsp) { - if (!dsp->executing_for_disasm) { - dsp->cur_inst_len = 0; - printf("Dsp: 0x%04x: 0x%06x Illegal instruction\n",dsp->pc, dsp->cur_inst); - /* Add some artificial CPU cycles to avoid being stuck in an infinite loop */ - dsp->instr_cycle += 100; - } else { - dsp->cur_inst_len = 1; - dsp->instr_cycle = 0; - } + dsp->cur_inst_len = 0; + printf("Dsp: 0x%04x: 0x%06x Illegal instruction\n",dsp->pc, dsp->cur_inst); + /* Add some artificial CPU cycles to avoid being stuck in an infinite loop */ + dsp->instr_cycle += 100; if (dsp->exception_debugging) { assert(false); } diff --git a/hw/xbox/mcpx/dsp/meson.build b/hw/xbox/mcpx/dsp/meson.build new file mode 100644 index 0000000000..4e06c59496 --- /dev/null +++ b/hw/xbox/mcpx/dsp/meson.build @@ -0,0 +1,2 @@ +libdsp = static_library('dsp', files(['debug.c', 'dsp.c', 'dsp_cpu.c', 'dsp_dma.c']) + genh) +dsp = declare_dependency(objects: libdsp.extract_all_objects(recursive: false)) diff --git a/hw/xbox/mcpx/dsp/trace-events b/hw/xbox/mcpx/dsp/trace-events new file mode 100644 index 0000000000..82f10a3f92 --- /dev/null +++ b/hw/xbox/mcpx/dsp/trace-events @@ -0,0 +1,9 @@ +# See docs/devel/tracing.rst for syntax documentation. + +# dsp.c +dsp_read_peripheral(uint32_t addr, uint32_t val) "addr 0x%"PRIx32" val 0x%"PRIx32 +dsp_write_peripheral(uint32_t addr, uint32_t val) "addr 0x%"PRIx32" val 0x%"PRIx32 + +# dsp_cpu.c +dsp56k_execute_instruction(uint32_t id, uint32_t pc) "[gp=%d]: pc=0x%"PRIx32 +dsp56k_execute_instruction_disasm(const char *disasm) "%s" diff --git a/hw/xbox/mcpx/dsp/trace.h b/hw/xbox/mcpx/dsp/trace.h new file mode 100644 index 0000000000..6ab110fe5b --- /dev/null +++ b/hw/xbox/mcpx/dsp/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_xbox_mcpx_dsp.h" diff --git a/hw/xbox/mcpx/meson.build b/hw/xbox/mcpx/meson.build index fd87ef118e..5f6807337d 100644 --- a/hw/xbox/mcpx/meson.build +++ b/hw/xbox/mcpx/meson.build @@ -1,10 +1,9 @@ +subdir('dsp') + mcpx_ss = ss.source_set() -mcpx_ss.add(sdl, libsamplerate, files( +mcpx_ss.add(sdl, libsamplerate, dsp, files( 'apu.c', 'aci.c', - 'dsp/dsp.c', - 'dsp/dsp_cpu.c', - 'dsp/dsp_dma.c', )) specific_ss.add_all(mcpx_ss) \ No newline at end of file diff --git a/hw/xbox/nv2a/nv2a_regs.h b/hw/xbox/nv2a/nv2a_regs.h index 78a9091eb5..fa62536181 100644 --- a/hw/xbox/nv2a/nv2a_regs.h +++ b/hw/xbox/nv2a/nv2a_regs.h @@ -32,6 +32,8 @@ (v) |= ((__val) << ctz32(__mask)) & (__mask); \ }) +// clang-format off + #define NV_NUM_BLOCKS 21 #define NV_PMC 0 /* card master control */ #define NV_PBUS 1 /* bus control */ @@ -312,6 +314,7 @@ # define NV_PGRAPH_CSV0_D_SKIN_4 6 #define NV_PGRAPH_CSV0_C 0x00000FB8 # define NV_PGRAPH_CSV0_C_CHEOPS_PROGRAM_START 0x0000FF00 +# define NV_PGRAPH_CSV0_C_SPECULAR_ENABLE (1 << 16) # define NV_PGRAPH_CSV0_C_SPECULAR (3 << 19) # define NV_PGRAPH_CSV0_C_DIFFUSE (3 << 21) # define NV_PGRAPH_CSV0_C_AMBIENT (3 << 23) @@ -1013,6 +1016,7 @@ # define NV097_SET_NORMALIZATION_ENABLE 0x000003A4 # define NV097_SET_MATERIAL_EMISSION 0x000003A8 # define NV097_SET_MATERIAL_ALPHA 0x000003B4 +# define NV097_SET_SPECULAR_ENABLE 0x000003B8 # define NV097_SET_LIGHT_ENABLE_MASK 0x000003BC # define NV097_SET_LIGHT_ENABLE_MASK_LIGHT0_OFF 0 # define NV097_SET_LIGHT_ENABLE_MASK_LIGHT0_INFINITE 1 @@ -1463,4 +1467,6 @@ #define NV2A_CUBEMAP_FACE_ALIGNMENT 128 +// clang-format on + #endif diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c index 2412826647..445ce73066 100644 --- a/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c +++ b/hw/xbox/nv2a/pgraph/glsl/vsh-ff.c @@ -383,6 +383,11 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz mstring_append(body, " oD0 = diffuse;\n"); mstring_append(body, " oD1 = specular;\n"); } + + if (!state->specular_enable) { + mstring_append(body, " oD1 = vec4(0.0, 0.0, 0.0, 1.0);\n"); + } + mstring_append(body, " oB0 = backDiffuse;\n"); mstring_append(body, " oB1 = backSpecular;\n"); diff --git a/hw/xbox/nv2a/pgraph/glsl/vsh.c b/hw/xbox/nv2a/pgraph/glsl/vsh.c index d92c8b2fb3..5fff5cf410 100644 --- a/hw/xbox/nv2a/pgraph/glsl/vsh.c +++ b/hw/xbox/nv2a/pgraph/glsl/vsh.c @@ -34,7 +34,6 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs) mstring_append_fmt(output, "#version %d\n\n", state->vulkan ? 450 : 400); MString *header = mstring_from_str(""); - MString *uniforms = mstring_from_str(""); const char *u = state->vulkan ? "" : "uniform "; // FIXME: Remove @@ -243,9 +242,7 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs) /* Set outputs */ mstring_append(body, "\n" " vtxD0 = clamp(oD0, 0.0, 1.0);\n" - " vtxD1 = clamp(oD1, 0.0, 1.0);\n" " vtxB0 = clamp(oB0, 0.0, 1.0);\n" - " vtxB1 = clamp(oB1, 0.0, 1.0);\n" " vtxFog = oFog.x;\n" " vtxT0 = oT0;\n" " vtxT1 = oT1;\n" @@ -254,6 +251,18 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs) " gl_PointSize = oPts.x;\n" ); + if (state->specular_enable) { + mstring_append(body, + " vtxD1 = clamp(oD1, 0.0, 1.0);\n" + " vtxB1 = clamp(oB1, 0.0, 1.0);\n" + ); + } else { + mstring_append(body, + " vtxD1 = vec4(0.0, 0.0, 0.0, 1.0);\n" + " vtxB1 = vec4(0.0, 0.0, 0.0, 1.0);\n" + ); + } + if (state->vulkan) { mstring_append(body, " gl_Position = oPos;\n" diff --git a/hw/xbox/nv2a/pgraph/methods.h b/hw/xbox/nv2a/pgraph/methods.h.inc similarity index 99% rename from hw/xbox/nv2a/pgraph/methods.h rename to hw/xbox/nv2a/pgraph/methods.h.inc index 380df07ea5..fd6184426e 100644 --- a/hw/xbox/nv2a/pgraph/methods.h +++ b/hw/xbox/nv2a/pgraph/methods.h.inc @@ -78,6 +78,7 @@ DEF_METHOD(NV097, SET_FRONT_FACE) DEF_METHOD(NV097, SET_NORMALIZATION_ENABLE) DEF_METHOD_RANGE(NV097, SET_MATERIAL_EMISSION, 3) DEF_METHOD(NV097, SET_MATERIAL_ALPHA) +DEF_METHOD(NV097, SET_SPECULAR_ENABLE) DEF_METHOD(NV097, SET_LIGHT_ENABLE_MASK) DEF_METHOD_CASE_4(NV097, SET_TEXGEN_S, 16) DEF_METHOD_CASE_4(NV097, SET_TEXGEN_T, 16) diff --git a/hw/xbox/nv2a/pgraph/pgraph.c b/hw/xbox/nv2a/pgraph/pgraph.c index 9db475796e..0f17fde184 100644 --- a/hw/xbox/nv2a/pgraph/pgraph.c +++ b/hw/xbox/nv2a/pgraph/pgraph.c @@ -19,7 +19,7 @@ * License along with this library; if not, see . */ -#include "../nv2a_int.h" +#include "hw/xbox/nv2a/nv2a_int.h" #include "ui/xemu-notifications.h" #include "ui/xemu-settings.h" #include "util.h" @@ -431,7 +431,7 @@ unsigned int nv2a_get_surface_scale_factor(void) #define DEF_METHOD_CASE_4_OFFSET(gclass, name, offset, stride) /* Drop */ #define DEF_METHOD_CASE_4(gclass, name, stride) \ DEF_METHOD_PROTO(gclass, name); -#include "methods.h" +#include "methods.h.inc" #undef DEF_METHOD #undef DEF_METHOD_RANGE #undef DEF_METHOD_CASE_4_OFFSET @@ -485,7 +485,7 @@ static const struct { }, #define DEF_METHOD_CASE_4(gclass, name, stride) \ DEF_METHOD_CASE_4_OFFSET(gclass, name, 0, stride) -#include "methods.h" +#include "methods.h.inc" #undef DEF_METHOD #undef DEF_METHOD_RANGE #undef DEF_METHOD_CASE_4_OFFSET @@ -504,7 +504,7 @@ static const struct { #define DEF_METHOD_CASE_4(gclass, name, stride) \ static const size_t METHOD_RANGE_END_NAME(gclass, name) = \ METHOD_ADDR(gclass, name) + 4*stride; -#include "methods.h" +#include "methods.h.inc" #undef DEF_METHOD #undef DEF_METHOD_RANGE #undef DEF_METHOD_CASE_4_OFFSET @@ -1619,6 +1619,11 @@ DEF_METHOD(NV097, SET_MATERIAL_ALPHA) pg->material_alpha = *(float*)¶meter; } +DEF_METHOD(NV097, SET_SPECULAR_ENABLE) +{ + PG_SET_MASK(NV_PGRAPH_CSV0_C, NV_PGRAPH_CSV0_C_SPECULAR_ENABLE, parameter); +} + DEF_METHOD(NV097, SET_LIGHT_ENABLE_MASK) { PG_SET_MASK(NV_PGRAPH_CSV0_D, NV_PGRAPH_CSV0_D_LIGHTS, parameter); @@ -3022,4 +3027,3 @@ void pgraph_pre_shutdown_wait(NV2AState *d) PGRAPHState *pg = &d->pgraph; pg->renderer->ops.pre_shutdown_wait(d); } - diff --git a/hw/xbox/nv2a/pgraph/profile.c b/hw/xbox/nv2a/pgraph/profile.c index 69a1b5bfbd..295042010d 100644 --- a/hw/xbox/nv2a/pgraph/profile.c +++ b/hw/xbox/nv2a/pgraph/profile.c @@ -17,7 +17,7 @@ * License along with this library; if not, see . */ -#include "../nv2a_int.h" +#include "hw/xbox/nv2a/nv2a_int.h" NV2AStats g_nv2a_stats; diff --git a/hw/xbox/nv2a/pgraph/rdi.c b/hw/xbox/nv2a/pgraph/rdi.c index 297c7a67c0..f540b240c6 100644 --- a/hw/xbox/nv2a/pgraph/rdi.c +++ b/hw/xbox/nv2a/pgraph/rdi.c @@ -19,7 +19,7 @@ * License along with this library; if not, see . */ -#include "../nv2a_int.h" +#include "hw/xbox/nv2a/nv2a_int.h" uint32_t pgraph_rdi_read(PGRAPHState *pg, unsigned int select, unsigned int address) diff --git a/hw/xbox/nv2a/pgraph/shaders.c b/hw/xbox/nv2a/pgraph/shaders.c index 6e13f2084c..dce6d05bb3 100644 --- a/hw/xbox/nv2a/pgraph/shaders.c +++ b/hw/xbox/nv2a/pgraph/shaders.c @@ -69,6 +69,8 @@ ShaderState pgraph_get_shader_state(PGRAPHState *pg) pgraph_reg_r(pg, NV_PGRAPH_SHADOWCTL), NV_PGRAPH_SHADOWCTL_SHADOW_ZFUNC); state.fixed_function = fixed_function; + state.specular_enable = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), + NV_PGRAPH_CSV0_C_SPECULAR_ENABLE); /* fixed function stuff */ if (fixed_function) { diff --git a/hw/xbox/nv2a/pgraph/shaders.h b/hw/xbox/nv2a/pgraph/shaders.h index 71febe2e2f..7ff93a6302 100644 --- a/hw/xbox/nv2a/pgraph/shaders.h +++ b/hw/xbox/nv2a/pgraph/shaders.h @@ -83,6 +83,7 @@ typedef struct ShaderState { enum VshLight light[NV2A_MAX_LIGHTS]; bool fixed_function; + bool specular_enable; /* vertex program */ bool vertex_program; diff --git a/hw/xbox/nvnet_regs.h b/hw/xbox/nvnet_regs.h index 992f609937..7a1744f7bc 100644 --- a/hw/xbox/nvnet_regs.h +++ b/hw/xbox/nvnet_regs.h @@ -68,6 +68,8 @@ #ifndef HW_NVNET_REGS_H #define HW_NVNET_REGS_H +// clang-format on + #define DEV_NEED_LASTPACKET1 0x0001 #define DEV_IRQMASK_1 0x0002 #define DEV_IRQMASK_2 0x0004 @@ -291,4 +293,6 @@ enum { #define LPA_LPACK 0x4000 /* Link partner acked us */ #define LPA_NPAGE 0x8000 /* Next page bit */ +// clang-format off + #endif /* HW_NVNET_REGS_H */ diff --git a/meson.build b/meson.build index 72e7049e02..c1e9612bbf 100644 --- a/meson.build +++ b/meson.build @@ -3772,6 +3772,7 @@ if have_system 'hw/remote', 'hw/xbox/nv2a', 'hw/xbox/mcpx', + 'hw/xbox/mcpx/dsp', 'hw/xbox', ] endif diff --git a/subprojects/SPIRV-Reflect.wrap b/subprojects/SPIRV-Reflect.wrap index dded924d1d..bdc1486c5c 100644 --- a/subprojects/SPIRV-Reflect.wrap +++ b/subprojects/SPIRV-Reflect.wrap @@ -1,4 +1,4 @@ [wrap-git] url=https://github.com/KhronosGroup/SPIRV-Reflect -revision=vulkan-sdk-1.4.304.0 +revision=vulkan-sdk-1.4.309.0 depth=1 diff --git a/subprojects/glslang.wrap b/subprojects/glslang.wrap index 29b74d8249..9aa182135a 100644 --- a/subprojects/glslang.wrap +++ b/subprojects/glslang.wrap @@ -1,4 +1,4 @@ [wrap-git] url=https://github.com/KhronosGroup/glslang -revision=vulkan-sdk-1.4.304.0 +revision=vulkan-sdk-1.4.309.0 depth=1 diff --git a/tests/meson.build b/tests/meson.build index 907a4c1c98..febbe02806 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -86,3 +86,4 @@ subdir('qapi-schema') subdir('qtest') subdir('migration') subdir('functional') +subdir('xbox') diff --git a/tests/xbox/dsp/data/Makefile b/tests/xbox/dsp/data/Makefile new file mode 100644 index 0000000000..8bd271a422 --- /dev/null +++ b/tests/xbox/dsp/data/Makefile @@ -0,0 +1,4 @@ +all: basic + +%: %.a56 + a56 -o $@ $< diff --git a/tests/xbox/dsp/data/basic b/tests/xbox/dsp/data/basic new file mode 100644 index 0000000000..7b11e507ea --- /dev/null +++ b/tests/xbox/dsp/data/basic @@ -0,0 +1,12 @@ +P 0000 0C0040 +P 0040 0AF080 +P 0041 000042 +P 0042 56F400 +P 0043 123456 +P 0044 567000 +P 0045 000003 +P 0046 08F484 +P 0047 000001 +P 0048 0C0042 +I 000040 start +I 000042 mainloop diff --git a/tests/xbox/dsp/data/basic.a56 b/tests/xbox/dsp/data/basic.a56 new file mode 100644 index 0000000000..0be7483dba --- /dev/null +++ b/tests/xbox/dsp/data/basic.a56 @@ -0,0 +1,12 @@ + org p:$0000 + jmp . + */ + +#include "qemu/osdep.h" +#include "hw/xbox/mcpx/dsp/dsp.h" + +static void scratch_rw(void *opaque, uint8_t *ptr, uint32_t addr, size_t len, bool dir) +{ + assert(!"Not implemented"); +} + +static void fifo_rw(void *opaque, uint8_t *ptr, unsigned int index, size_t len, bool dir) +{ + assert(!"Not implemented"); +} + +static void load_prog(DSPState *s, const char *path) +{ + FILE *file = fopen(path, "r"); + assert(file && "Error opening file"); + + char type, line[100], arg1[20], arg2[20]; + int addr, value; + + while (fgets(line, sizeof(line), file)) { + if (sscanf(line, "%c %s %s", &type, arg1, arg2) >= 2) { + switch (type) { + case 'P': + case 'X': + case 'Y': { + assert(sscanf(arg1, "%x", &addr) == 1); + assert(sscanf(arg2, "%x", &value) == 1); + dsp_write_memory(s, type, addr, value); + break; + } + } + } else { + printf("Invalid line: %s\n", line); + assert(0); + } + } + + fclose(file); +} + +static void test_dsp_basic(void) +{ + g_autofree gchar *path = g_test_build_filename(G_TEST_DIST, "data", "basic", NULL); + + DSPState *s = dsp_init(NULL, scratch_rw, fifo_rw); + + load_prog(s, path); + dsp_run(s, 1000); + + uint32_t v = dsp_read_memory(s, 'X', 3); + g_assert_cmphex(v, ==, 0x123456); + + dsp_destroy(s); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/basic", test_dsp_basic); + + return g_test_run(); +} diff --git a/tests/xbox/meson.build b/tests/xbox/meson.build new file mode 100644 index 0000000000..e836218210 --- /dev/null +++ b/tests/xbox/meson.build @@ -0,0 +1 @@ +subdir('dsp') diff --git a/ubuntu-win64-cross/Dockerfile b/ubuntu-win64-cross/Dockerfile index 8741b629de..a3aeb78329 100644 --- a/ubuntu-win64-cross/Dockerfile +++ b/ubuntu-win64-cross/Dockerfile @@ -6,10 +6,10 @@ FROM ubuntu:24.04 ENV MXE_PATH=/opt/mxe ENV MXE_REPO=https://github.com/mxe/mxe.git -ENV MXE_VERSION=866492387740cc6580ef516c8a746402be645453 +ENV MXE_VERSION=db7f5247eaab700f28bb9b9433d279e5958f5f01 ENV MXE_LLVM_MINGW_REPO=https://github.com/libvips/build-win64-mxe -ENV MXE_LLVM_MINGW_VERSION=32a2d0ecdfd3ea16bb4a99e333a8d5a3d63be491 +ENV MXE_LLVM_MINGW_VERSION=51fc5884d0c4a3be43a2f09fa36a464885918d3d ENV MXE_LLVM_MINGW_PATH=/opt/build-win64-mxe ARG PLUGIN_DIRS="${MXE_LLVM_MINGW_PATH} ${MXE_LLVM_MINGW_PATH}/build/plugins/llvm-mingw" diff --git a/ubuntu-win64-cross/vulkan-headers.mk b/ubuntu-win64-cross/vulkan-headers.mk index 01594d6c3a..3ea0f9d679 100644 --- a/ubuntu-win64-cross/vulkan-headers.mk +++ b/ubuntu-win64-cross/vulkan-headers.mk @@ -2,10 +2,10 @@ PKG := vulkan-headers $(PKG)_WEBSITE := https://github.com/KhronosGroup/Vulkan-Headers $(PKG)_DESCR := Vulkan-Headers $(PKG)_IGNORE := -$(PKG)_VERSION := vulkan-sdk-1.4.304.0 +$(PKG)_VERSION := vulkan-sdk-1.4.309.0 $(PKG)_SUBDIR := Vulkan-Headers-$($(PKG)_VERSION) $(PKG)_FILE := vulkan-headers-$($(PKG)_VERSION).tar.gz -$(PKG)_CHECKSUM := 46f8f5b6384a36c688e0c40d28d534df41d22de406493dfb5c9b7bcc29672613 +$(PKG)_CHECKSUM := 2bc1b4127950badc80212abf1edfa5c3b5032f3425edf37255863ba7592c1969 $(PKG)_URL := https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/$($(PKG)_VERSION).tar.gz $(PKG)_DEPS := cc