From a149dc9e3b84922a7e52d31e9a56f255a5597dff Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Mon, 8 Jan 2024 19:15:28 +0100 Subject: [PATCH] Fix examples, update submodules and CI script --- .github/workflows/build.yml | 31 ++++++++++++++++--------------- examples/cdrom/cdxa/main.c | 2 +- examples/mdec/strvideo/main.c | 22 ++++++++++++++++------ examples/sound/cdstream/main.c | 11 ++--------- examples/sound/cdstream/stream.c | 18 ++++++++++-------- examples/sound/spustream/main.c | 11 ++--------- examples/sound/vagsample/main.c | 31 ++++++++++++------------------- tools/mkpsxiso | 2 +- tools/tinyxml2 | 2 +- 9 files changed, 61 insertions(+), 69 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 00926ef..09147ab 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,17 +10,14 @@ name: Build PSn00bSDK on: [ push, pull_request ] env: - BINUTILS_VERSION: '2.40' + BINUTILS_VERSION: '2.41' BINUTILS_OPTIONS: '--disable-docs --disable-nls --disable-werror --with-float=soft' - GCC_VERSION: '12.3.0' + GCC_VERSION: '13.2.0' GCC_OPTIONS: '--disable-docs --disable-nls --disable-werror --disable-libada --disable-libssp --disable-libquadmath --disable-threads --disable-libgomp --disable-libstdcxx-pch --disable-hosted-libstdcxx --enable-languages=c,c++ --without-isl --without-headers --with-float=soft --with-gnu-as --with-gnu-ld' GCC_TARGET: 'mipsel-none-elf' jobs: # This is based on doc/toolchain.md, no surprises here other than the cache. - # Since actions/cache@v2 has bugs when restoring on Windows caches created on - # Linux, v1 is used instead. - # https://github.com/actions/cache/issues/576 build-gcc: name: Build GCC toolchain runs-on: ubuntu-latest @@ -28,8 +25,9 @@ jobs: steps: - name: Initialize toolchain cache id: _cache - uses: actions/cache@v1 + uses: actions/cache@v3.3.2 with: + enableCrossOsArchive: true key: gcc-${{ env.GCC_TARGET }}-${{ env.GCC_VERSION }} path: gcc @@ -100,8 +98,9 @@ jobs: echo "C:\msys64\usr\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - name: Initialize toolchain cache - uses: actions/cache@v1 + uses: actions/cache@v3.3.2 with: + enableCrossOsArchive: true key: gcc-${{ env.GCC_TARGET }}-${{ env.GCC_VERSION }} path: gcc @@ -110,7 +109,7 @@ jobs: pacman -S --noconfirm mingw-w64-x86_64-ninja - name: Fetch repo contents - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: path: sdk submodules: recursive @@ -125,7 +124,7 @@ jobs: # an artifact, so it's best to upload each package type as a separate # artifact. - name: Upload build artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: psn00bsdk-windows path: build/packages/*.zip @@ -137,8 +136,9 @@ jobs: steps: - name: Initialize toolchain cache - uses: actions/cache@v1 + uses: actions/cache@v3.3.2 with: + enableCrossOsArchive: true key: gcc-${{ env.GCC_TARGET }}-${{ env.GCC_VERSION }} path: gcc @@ -148,7 +148,7 @@ jobs: sudo apt-get install -y --no-install-recommends ninja-build - name: Fetch repo contents - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: path: sdk submodules: recursive @@ -160,7 +160,7 @@ jobs: cmake --build build -t package - name: Upload build artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: psn00bsdk-linux path: build/packages/*.zip @@ -175,8 +175,9 @@ jobs: steps: - name: Initialize toolchain cache if: ${{ github.ref_type == 'tag' }} - uses: actions/cache@v1 + uses: actions/cache@v3.3.2 with: + enableCrossOsArchive: true key: gcc-${{ env.GCC_TARGET }}-${{ env.GCC_VERSION }} path: gcc @@ -190,7 +191,7 @@ jobs: - name: Fetch repo contents if: ${{ github.ref_type == 'tag' }} - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: path: sdk @@ -201,7 +202,7 @@ jobs: - name: Fetch build artifacts if: ${{ github.ref_type == 'tag' }} - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: path: . diff --git a/examples/cdrom/cdxa/main.c b/examples/cdrom/cdxa/main.c index 253f540..d49ff1b 100644 --- a/examples/cdrom/cdxa/main.c +++ b/examples/cdrom/cdxa/main.c @@ -214,7 +214,7 @@ void cd_event_handler(CdlIntrResult event, uint8_t *payload) { if ( !(sector.xa_header[0].submode & XA_TYPE_AUDIO) && - !(sector.xa_header[0].submode & XA_TYPE_AUDIO) + !(sector.xa_header[1].submode & XA_TYPE_AUDIO) ) { // Seek back to the beginning of the file. CdControlF(CdlReadS, &xa_loc); diff --git a/examples/mdec/strvideo/main.c b/examples/mdec/strvideo/main.c index 853e0c2..038ba7a 100644 --- a/examples/mdec/strvideo/main.c +++ b/examples/mdec/strvideo/main.c @@ -17,13 +17,13 @@ * CD drive handles XA-ADPCM sectors automatically, so no CPU intervention is * necessary to play the audio track interleaved with the video. * - Once a full frame has been demuxed, the bitstream data is parsed and - * decompressed by the CPU (using DecDCTvlc()) to an array of run-length - * codes to be fed to the MDEC. This is done in the main loop. + * decompressed by the CPU (using DecDCTvlc()) to an array of run-length codes + * to be fed to the MDEC. This is done in the main loop. * - At the same time the last frame decompressed is read from RAM by the MDEC, * which decodes it and outputs one 16-pixel-wide vertical slice at a time. * - When a slice is ready, it is uploaded by mdec_dma_handler() to the current * framebuffer in VRAM while the MDEC is decoding the next slice. - * A text overlay is drawn on top of the framebuffer using the GPU after the + * - A text overlay is drawn on top of the framebuffer using the GPU after the * entire frame has been decoded. * * Since pretty much all buffers used are going to be read and written at the @@ -56,6 +56,12 @@ // support 24bpp rendering, so the text overlay is only enabled in 16bpp mode. //#define DISP_24BPP +// Uncomment to enable waiting for vertical sync after each frame is decoded. +// This will get rid of screen tearing, but may result in the player failing to +// play .STR files with higher frame rates (see main() for more details and +// possible workarounds). +//#define ENABLE_VSYNC + /* Display/GPU context utilities */ #define SCREEN_XRES 320 @@ -163,12 +169,14 @@ typedef struct { volatile int8_t cur_frame, cur_slice; } StreamContext; +// This structure contains all buffers required for playback as well as the +// current state of the player. Note that it takes up a significant amount of +// RAM, so allocating it on the heap when needed and keeping a pointer to it +// may be a better option. static StreamContext str_ctx; // This buffer is used by cd_sector_handler() as a temporary area for sectors -// read from the CD. Due to DMA limitations it can't be allocated on the stack -// (especially not in the interrupt callbacks' stack, whose size is very -// limited). +// read from the CD. Due to DMA limitations it can't be allocated on the stack. static STR_Header sector_header; void cd_sector_handler(void) { @@ -394,7 +402,9 @@ int main(int argc, const char* argv[]) { // implement triple buffering (i.e. always keep 2 fully decoded frames // in VRAM and use VSyncCallback() to register a function that displays // the next decoded frame if available whenever vblank occurs). +#ifdef ENABLE_VSYNC VSync(0); +#endif DecDCTinSync(0); DecDCToutSync(0); diff --git a/examples/sound/cdstream/main.c b/examples/sound/cdstream/main.c index 2bd2142..2a9bbab 100644 --- a/examples/sound/cdstream/main.c +++ b/examples/sound/cdstream/main.c @@ -152,13 +152,6 @@ typedef struct { char name[16]; } VAG_Header; -#define SWAP_ENDIAN(x) ( \ - (((uint32_t) (x) & 0x000000ff) << 24) | \ - (((uint32_t) (x) & 0x0000ff00) << 8) | \ - (((uint32_t) (x) & 0x00ff0000) >> 8) | \ - (((uint32_t) (x) & 0xff000000) >> 24) \ -) - /* Helper functions */ #define DUMMY_BLOCK_ADDR 0x1000 @@ -250,14 +243,14 @@ void setup_stream(const CdlLOC *pos) { int num_channels = vag->channels ? vag->channels : 2; int num_chunks = - (SWAP_ENDIAN(vag->size) + vag->interleave - 1) / vag->interleave; + (__builtin_bswap32(vag->size) + vag->interleave - 1) / vag->interleave; __builtin_memset(&config, 0, sizeof(Stream_Config)); config.spu_address = STREAM_BUFFER_ADDR; config.interleave = vag->interleave; config.buffer_size = RAM_BUFFER_SIZE; - config.sample_rate = SWAP_ENDIAN(vag->sample_rate); + config.sample_rate = __builtin_bswap32(vag->sample_rate); // Use the first N channels of the SPU and pan them left/right in pairs // (this assumes the stream contains one or more stereo tracks). diff --git a/examples/sound/cdstream/stream.c b/examples/sound/cdstream/stream.c index 624b6e1..9dfc9ba 100644 --- a/examples/sound/cdstream/stream.c +++ b/examples/sound/cdstream/stream.c @@ -29,7 +29,7 @@ /* Private utilities */ -static volatile Stream_Context *_active_ctx = (void *) 0; +static volatile Stream_Context *volatile _active_ctx = (void *) 0; static Stream_Time _default_timer_function(void) { return VSync(-1); @@ -42,7 +42,7 @@ static int _get_default_timer_rate(void) { /* Interrupt handlers */ static void _spu_irq_handler(void) { - Stream_Context *ctx = _active_ctx; + volatile Stream_Context *ctx = _active_ctx; // Acknowledge the interrupt to ensure it can be triggered again. The only // way to do this is actually to disable the interrupt entirely; we'll @@ -90,13 +90,13 @@ static void _spu_irq_handler(void) { // both channels' loop addresses to make them "jump" to the new buffers, // rather than actually looping when they encounter the loop flag at the end // of the currently playing buffers. - uint32_t offset = 0; uint32_t address = ctx->config.spu_address + (ctx->db_active ? ctx->chunk_size : 0); int sample_rate = ctx->new_sample_rate; ctx->config.sample_rate = sample_rate; + SpuSetTransferStartAddr(address); SPU_IRQ_ADDR = getSPUAddr(address); for (uint32_t ch = 0, mask = ctx->config.channel_mask; mask; ch++, mask >>= 1) { @@ -104,15 +104,14 @@ static void _spu_irq_handler(void) { continue; SPU_CH_FREQ (ch) = getSPUSampleRate(sample_rate); - SPU_CH_LOOP_ADDR(ch) = getSPUAddr(address + offset); - offset += ctx->config.interleave; + SPU_CH_LOOP_ADDR(ch) = getSPUAddr(address); + address += ctx->config.interleave; // Make sure this channel's data ends with an appropriate loop flag. //ptr[offset - 15] |= 0x03; } // Start uploading the next chunk to the SPU. - SpuSetTransferStartAddr(address); SpuWrite((const uint32_t *) ptr, ctx->chunk_size); } @@ -186,6 +185,9 @@ bool Stream_Start(Stream_Context *ctx, bool resume) { int sample_rate = ctx->new_sample_rate; ctx->config.sample_rate = sample_rate; + // Disable the IRQ as we're going to call spu_irq_handler() manually (due to + // finicky SPU timings). + SPU_CTRL &= ~(1 << 6); SpuSetKey(0, ctx->config.channel_mask); for (uint32_t ch = 0, mask = ctx->config.channel_mask; mask; ch++, mask >>= 1) { @@ -200,14 +202,14 @@ bool Stream_Start(Stream_Context *ctx, bool resume) { address += ctx->config.interleave; } - _spu_irq_handler(); SpuSetKey(1, ctx->config.channel_mask); + _spu_irq_handler(); return true; } bool Stream_Stop(void) { - Stream_Context *ctx = _active_ctx; + volatile Stream_Context *ctx = _active_ctx; if (!ctx) return false; diff --git a/examples/sound/spustream/main.c b/examples/sound/spustream/main.c index 28a0ce5..cf91c26 100644 --- a/examples/sound/spustream/main.c +++ b/examples/sound/spustream/main.c @@ -127,13 +127,6 @@ typedef struct { char name[16]; } VAG_Header; -#define SWAP_ENDIAN(x) ( \ - (((uint32_t) (x) & 0x000000ff) << 24) | \ - (((uint32_t) (x) & 0x0000ff00) << 8) | \ - (((uint32_t) (x) & 0x00ff0000) >> 8) | \ - (((uint32_t) (x) & 0xff000000) >> 24) \ -) - /* Interrupt callbacks */ // The first 4 KB of SPU RAM are reserved for capture buffers and psxspu @@ -220,8 +213,8 @@ void init_stream(const VAG_Header *vag) { stream_ctx.data = &((const uint8_t *) vag)[2048]; stream_ctx.buffer_size = buf_size; - stream_ctx.num_chunks = (SWAP_ENDIAN(vag->size) + buf_size - 1) / buf_size; - stream_ctx.sample_rate = SWAP_ENDIAN(vag->sample_rate); + stream_ctx.num_chunks = (__builtin_bswap32(vag->size) + buf_size - 1) / buf_size; + stream_ctx.sample_rate = __builtin_bswap32(vag->sample_rate); stream_ctx.channels = vag->channels ? vag->channels : 1; stream_ctx.db_active = 1; diff --git a/examples/sound/vagsample/main.c b/examples/sound/vagsample/main.c index 701bfb5..4af92e9 100644 --- a/examples/sound/vagsample/main.c +++ b/examples/sound/vagsample/main.c @@ -99,13 +99,6 @@ typedef struct { char name[16]; } VAG_Header; -#define SWAP_ENDIAN(x) ( \ - (((uint32_t) (x) & 0x000000ff) << 24) | \ - (((uint32_t) (x) & 0x0000ff00) << 8) | \ - (((uint32_t) (x) & 0x00ff0000) >> 8) | \ - (((uint32_t) (x) & 0xff000000) >> 24) \ -) - /* Helper functions */ // The first 4 KB of SPU RAM are reserved for capture buffers and psxspu @@ -119,17 +112,17 @@ static int next_sample_addr = ALLOC_START_ADDR; int upload_sample(const void *data, int size) { // Round the size up to the nearest multiple of 64, as SPU DMA transfers // are done in 64-byte blocks. - int _addr = next_sample_addr; - int _size = (size + 63) & 0xffffffc0; + int addr = next_sample_addr; + size = (size + 63) & ~63; SpuSetTransferMode(SPU_TRANSFER_BY_DMA); - SpuSetTransferStartAddr(_addr); + SpuSetTransferStartAddr(addr); - SpuWrite((const uint32_t *) data, _size); + SpuWrite((const uint32_t *) data, size); SpuIsTransferCompleted(SPU_TRANSFER_WAIT); - next_sample_addr = _addr + _size; - return _addr; + next_sample_addr = addr + size; + return addr; } void play_sample(int addr, int sample_rate) { @@ -168,13 +161,13 @@ int main(int argc, const char* argv[]) { SpuInit(); // Upload the samples to the SPU and parse their headers. - VAG_Header *proyt_vag = (VAG_Header *) proyt; - VAG_Header *tdfx_vag = (VAG_Header *) tdfx; + const VAG_Header *proyt_vag = (const VAG_Header *) proyt; + const VAG_Header *tdfx_vag = (const VAG_Header *) tdfx; - int proyt_addr = upload_sample(&proyt_vag[1], SWAP_ENDIAN(proyt_vag->size)); - int tdfx_addr = upload_sample(&tdfx_vag[1], SWAP_ENDIAN(tdfx_vag->size)); - int proyt_sr = SWAP_ENDIAN(proyt_vag->sample_rate); - int tdfx_sr = SWAP_ENDIAN(tdfx_vag->sample_rate); + int proyt_addr = upload_sample(proyt_vag + 1, __builtin_bswap32(proyt_vag->size)); + int tdfx_addr = upload_sample(tdfx_vag + 1, __builtin_bswap32(tdfx_vag->size)); + int proyt_sr = __builtin_bswap32(proyt_vag->sample_rate); + int tdfx_sr = __builtin_bswap32(tdfx_vag->sample_rate); // Set up controller polling. uint8_t pad_buff[2][34]; diff --git a/tools/mkpsxiso b/tools/mkpsxiso index 9f6275f..08fa69f 160000 --- a/tools/mkpsxiso +++ b/tools/mkpsxiso @@ -1 +1 @@ -Subproject commit 9f6275f08829ea9de8122c8232a019e8724acbbd +Subproject commit 08fa69f61365a3314b98076bfe7b2f37ed9db5d3 diff --git a/tools/tinyxml2 b/tools/tinyxml2 index e059560..321ea88 160000 --- a/tools/tinyxml2 +++ b/tools/tinyxml2 @@ -1 +1 @@ -Subproject commit e05956094c27117f989d22f25b75633123d72a83 +Subproject commit 321ea883b7190d4e85cae5512a12e5eaa8f8731f