From 13c9a48c26ba05678f34ead0f93e2873e00f93e8 Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 5 Jul 2024 21:44:34 +0200 Subject: [PATCH 01/16] ui, minor menu fix --- platform/common/menu_pico.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index a4abd7a6..53e52b87 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -577,7 +577,7 @@ static int menu_loop_32x_options(int id, int keys) static const char *sms_hardwares[] = { "auto", "Game Gear", "Master System", "SG-1000", "SC-3000", NULL }; static const char *gg_ghosting_opts[] = { "OFF", "weak", "normal", NULL }; static const char *sms_mappers[] = { "auto", "Sega", "Codemasters", "Korea", "Korea MSX", "Korea X-in-1", "Korea 4-Pak", "Korea Janggun", "Korea Nemesis", "Taiwan 8K RAM", "Korea XOR", "Sega 32K RAM", NULL }; -static const char *sms_tmspalette[] = { "SMS", "SG-1000" }; +static const char *sms_tmspalette[] = { "SMS", "SG-1000", NULL }; static const char h_smsfm[] = "FM sound is only supported by few games,\n" "some games may crash with FM enabled"; -- 2.39.2 From 4af69a1df0d4e5e16bb4648934e30441835fab93 Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 5 Jul 2024 21:47:33 +0200 Subject: [PATCH 02/16] sms, improve pad handling (TR as output) --- pico/sms.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/pico/sms.c b/pico/sms.c index 919b6ea6..0c2ee634 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -189,9 +189,11 @@ static unsigned char z80_sms_in(unsigned short a) break; case 0xc0: /* I/O port A and B */ - if (! (PicoIn.AHW & PAHW_SC) || (Pico.ms.io_sg & 7) == 7) + if (! (PicoIn.AHW & PAHW_SC) || (Pico.ms.io_sg & 7) == 7) { d = ~((PicoIn.pad[0] & 0x3f) | (PicoIn.pad[1] << 6)); - else + if (!(Pico.ms.io_ctl & 0x01)) // TR as output + d = (d & ~0x20) | ((Pico.ms.io_ctl << 1) & 0x20); + } else ; // read kbd 8 bits break; @@ -199,6 +201,8 @@ static unsigned char z80_sms_in(unsigned short a) if (! (PicoIn.AHW & PAHW_SC) || (Pico.ms.io_sg & 7) == 7) { d = (Pico.ms.io_ctl & 0x80) | ((Pico.ms.io_ctl << 1) & 0x40) | 0x30; d |= ~(PicoIn.pad[1] >> 2) & 0x0f; + if (!(Pico.ms.io_ctl & 0x04)) // TR as output + d = (d & ~0x08) | ((Pico.ms.io_ctl >> 3) & 0x08); if (Pico.ms.io_ctl & 0x08) d |= 0x80; // TH as input is unconnected if (Pico.ms.io_ctl & 0x02) d |= 0x40; } else @@ -309,6 +313,7 @@ static void write_bank_sega(unsigned short a, unsigned char d) elprintf(EL_Z80BNK, "bank sega %04x %02x @ %04x", a, d, z80_pc()); Pico.ms.mapper = PMS_MAP_SEGA; + if (d == Pico.ms.carthw[a & 0x0f]) return; Pico.ms.carthw[a & 0x0f] = d; switch (a & 0x0f) @@ -348,6 +353,7 @@ static void write_bank_codem(unsigned short a, unsigned char d) if (Pico.ms.mapper != PMS_MAP_CODEM && (Pico.ms.mapper || (a>>14) == d)) return; elprintf(EL_Z80BNK, "bank codem %04x %02x @ %04x", a, d, z80_pc()); Pico.ms.mapper = PMS_MAP_CODEM; + if (Pico.ms.carthw[a>>14] == d) return; Pico.ms.carthw[a>>14] = d; d &= bank_mask; @@ -690,8 +696,9 @@ void PicoResetMS(void) z80_reset(); PsndReset(); // pal must be known here + + Pico.ms.io_ctl = (PicoIn.AHW & (PAHW_SG|PAHW_SC)) ? 0xf5 : 0xff; Pico.ms.fm_ctl = 0xff; - Pico.m.dirtyPal = 1; // reset memory mapping PicoMemSetupMS(); @@ -708,6 +715,7 @@ void PicoResetMS(void) Pico.video.reg[8] = 0x00; Pico.video.reg[9] = 0x00; Pico.video.reg[10] = 0xff; + Pico.m.dirtyPal = 1; // BIOS, clear zram (unitialized on Mark-III, cf src/mame/drivers/sms.cpp) i = !(PicoIn.AHW & PAHW_GG) && (Pico.m.hardware & PMS_HW_JAP) ? 0xf0 : 0x00; -- 2.39.2 From 73411ac44791153f79f1f03d82103954619ad140 Mon Sep 17 00:00:00 2001 From: kub Date: Mon, 8 Jul 2024 22:41:01 +0200 Subject: [PATCH 03/16] sound, add panning for ym2612 dac --- pico/sound/sound.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/pico/sound/sound.c b/pico/sound/sound.c index 650f7aca..74f9967b 100644 --- a/pico/sound/sound.c +++ b/pico/sound/sound.c @@ -16,6 +16,8 @@ #include "resampler.h" #include "mix.h" +#define YM2612_CH6PAN 0x1b6 // panning register for channel 6 (used for DAC) + void (*PsndMix_32_to_16)(s16 *dest, s32 *src, int count) = mix_32_to_16_stereo; // master int buffer to mix to @@ -282,9 +284,12 @@ PICO_INTERNAL void PsndDoDAC(int cyc_to) // 1 sample delay for correct IIR filtering over audio frame boundaries if (PicoIn.opt & POPT_EN_STEREO) { s16 *d = PicoIn.sndOut + pos*2; - // left channel only, mixed ro right channel in mixing phase - *d++ += Pico.snd.dac_val2, *d++ += Pico.snd.dac_val2; - while (--len) *d++ += Pico.snd.dac_val, *d++ += Pico.snd.dac_val; + int pan = ym2612.REGS[YM2612_CH6PAN]; + int l = pan & 0x80 ? Pico.snd.dac_val : 0; + int r = pan & 0x40 ? Pico.snd.dac_val : 0; + *d++ += pan & 0x80 ? Pico.snd.dac_val2 : 0; + *d++ += pan & 0x40 ? Pico.snd.dac_val2 : 0; + while (--len) *d++ += l, *d++ += r; } else { s16 *d = PicoIn.sndOut + pos; *d++ += Pico.snd.dac_val2; @@ -516,13 +521,21 @@ static int PsndRender(int offset, int length) // Fill up DAC output in case of missing samples (Q rounding errors) if (length-daclen > 0 && PicoIn.sndOut) { - s16 *dacbuf = PicoIn.sndOut + (daclen << stereo); Pico.snd.dac_pos += (length-daclen) << 20; - *dacbuf++ += Pico.snd.dac_val2; - if (stereo) *dacbuf++ += Pico.snd.dac_val2; - for (daclen++; length-daclen > 0; daclen++) { - *dacbuf++ += Pico.snd.dac_val; - if (stereo) *dacbuf++ += Pico.snd.dac_val; + if (PicoIn.opt & POPT_EN_STEREO) { + s16 *d = PicoIn.sndOut + daclen*2; + int pan = ym2612.REGS[YM2612_CH6PAN]; + int l = pan & 0x80 ? Pico.snd.dac_val : 0; + int r = pan & 0x40 ? Pico.snd.dac_val : 0; + *d++ += pan & 0x80 ? Pico.snd.dac_val2 : 0; + *d++ += pan & 0x40 ? Pico.snd.dac_val2 : 0; + if (l|r) for (daclen++; length-daclen > 0; daclen++) + *d++ += l, *d++ += r; + } else { + s16 *d = PicoIn.sndOut + daclen; + *d++ += Pico.snd.dac_val2; + if (Pico.snd.dac_val) for (daclen++; length-daclen > 0; daclen++) + *d++ += Pico.snd.dac_val; } Pico.snd.dac_val2 = Pico.snd.dac_val; } -- 2.39.2 From 977e5db898cd5c1980db66953dbcbce8a1e1c7d0 Mon Sep 17 00:00:00 2001 From: kub Date: Mon, 8 Jul 2024 22:46:06 +0200 Subject: [PATCH 04/16] core, fix typo --- pico/pico_int.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico/pico_int.h b/pico/pico_int.h index 3d495739..4caa800d 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -203,7 +203,7 @@ extern struct DrZ80 drZ80; #define z80_resetCycles() { \ Pico.t.z80c_cnt -= Pico.t.z80c_aim, Pico.t.z80c_aim = Pico.t.z80_scanline = 0; \ - if (!Pico.m.z80Run | Pico.m.z80_reset) Pico.t.z80c_cnt = 0; \ + if (!Pico.m.z80Run || Pico.m.z80_reset) Pico.t.z80c_cnt = 0; \ } #define z80_cyclesDone() \ -- 2.39.2 From 538982b062eaad7c1ec4eca046e5e7749dbe321a Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 9 Jul 2024 22:30:17 +0300 Subject: [PATCH 05/16] mcd: unbreak cue search --- pico/cd/cd_parse.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pico/cd/cd_parse.c b/pico/cd/cd_parse.c index aebd7d12..eeb3e880 100644 --- a/pico/cd/cd_parse.c +++ b/pico/cd/cd_parse.c @@ -71,23 +71,23 @@ static int get_token(const char *buff, char *dest, int len) static int get_ext(const char *fname, char ext[4], char *base, size_t base_size) { - int len, pos = 0; + size_t pos = 0; + char *p; - len = strrchr(fname, '.') - fname; - if (len > 0) - pos = len; + ext[0] = 0; + if (!(p = strrchr(fname, '.'))) + return -1; + pos = p - fname; strncpy(ext, fname + pos + 1, 4/*sizeof(ext)*/-1); ext[4/*sizeof(ext)*/-1] = '\0'; if (base != NULL && base_size > 0) { - if (pos + 1 < base_size) + if (pos >= base_size) pos = base_size - 1; - len = (pos < len) ? pos : len; - - memcpy(base, fname, len); - base[len] = 0; + memcpy(base, fname, pos); + base[pos] = 0; } return pos; } @@ -219,17 +219,17 @@ cd_data_t *cue_parse(const char *fname) if (fname == NULL || (fname_len = strlen(fname)) == 0) return NULL; - ret = get_ext(fname, ext, cue_base, sizeof(cue_base)); + ret = get_ext(fname, ext, cue_base, sizeof(cue_base) - 4); if (strcasecmp(ext, "cue") == 0) { f = fopen(fname, "r"); } - else { + else if (strcasecmp(ext, "chd") != 0) { // not a .cue, try one with the same base name - if (ret + 3 < sizeof(cue_base)) { - strcpy(cue_base + ret, "cue"); + if (0 < ret && ret < sizeof(cue_base)) { + strcpy(cue_base + ret, ".cue"); f = fopen(cue_base, "r"); if (f == NULL) { - strcpy(cue_base + ret, "CUE"); + strcpy(cue_base + ret, ".CUE"); f = fopen(cue_base, "r"); } } -- 2.39.2 From 34070ccc345572d73a59c1a27579dc7602272577 Mon Sep 17 00:00:00 2001 From: irixxxx <31696370+irixxxx@users.noreply.github.com> Date: Wed, 10 Jul 2024 19:17:04 +0200 Subject: [PATCH 06/16] add some images to readme --- README.md | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dd5e3604..9e506c95 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ This is yet another SEGA 8 bit and 16 bit console emulator for emulating most of the hardware SEGA has published up to and including the 32X. -Emulated 16 bit systems: Mega Drive/Genesis, Sega/Mega CD, 32X, Pico. -Emulated 8 bit systems: SG-1000, SC-3000, Master System/Mark III, Game Gear. PicoDrive was originally written having ARM-based handheld devices in mind, but later had got various improvements for other architectures @@ -16,6 +14,33 @@ Currently the main development happens in the [irixxxx's fork](https://github.com/irixxxx/picodrive), [notaz's repo](https://github.com/notaz/picodrive) isn't updated as much. +### gallery + +Some images of demos and homebrew software: + +**16/32 bit systems**: Mega Drive/Genesis, Sega/Mega CD, 32X, Pico. + +![Titan Overdrive 2](https://github.com/irixxxx/picodrive/assets/31696370/02a4295b-ac9d-4114-bcd1-b5dd6e5930d0) +![Raycast Demo](https://github.com/irixxxx/picodrive/assets/31696370/6e9c0bfe-49a9-45aa-bad7-544de065e388) +![OpenLara](https://github.com/irixxxx/picodrive/assets/31696370/8a00002a-5c10-4d1d-a948-739bf978282a) + +![Titan Overdrive 2](https://github.com/irixxxx/picodrive/assets/31696370/2e263e81-51c8-4daa-ab16-0b2cd5554f84) +![DMA David](https://github.com/irixxxx/picodrive/assets/31696370/fbbeac15-8665-4d3e-9729-d1f8c35e417a) +![Doom Resurrection](https://github.com/irixxxx/picodrive/assets/31696370/db7b7153-b917-4850-8442-a748c2fbb968) + +$~$ + +**8 bit systems**: SG-1000, SC-3000, Master System/Mark III, Game Gear. + +![Cheril Perils Classics](https://github.com/irixxxx/picodrive/assets/31696370/653914a4-9f90-45f8-bd91-56e784df7550) +![Stygian Quest](https://github.com/irixxxx/picodrive/assets/31696370/8196801b-85c8-4d84-97e1-ae57ab3d577f) +![Wing Warriors](https://github.com/irixxxx/picodrive/assets/31696370/3c4a8f40-dad6-4fa4-b188-46b428a4b8c6) + +![Nyan Cat](https://github.com/irixxxx/picodrive/assets/31696370/6fe0d38b-549d-4faa-9351-b260a89dc745) +![Anguna the Prison Dungeon](https://github.com/irixxxx/picodrive/assets/31696370/3264b962-7da2-4257-9ff7-1b509bd50cdf) +![Turrican](https://github.com/irixxxx/picodrive/assets/31696370/c4eb2f2c-806e-4f4b-ac94-5c2cda82e962) + + ### compiling For platforms for which release builds are supplied the most easy way is to -- 2.39.2 From 29dcbc52b2f279970fd3b76cc320389356a9042a Mon Sep 17 00:00:00 2001 From: irixxxx <31696370+irixxxx@users.noreply.github.com> Date: Thu, 11 Jul 2024 22:56:04 +0200 Subject: [PATCH 07/16] add links to images --- README.md | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 9e506c95..8da8c717 100644 --- a/README.md +++ b/README.md @@ -14,31 +14,26 @@ Currently the main development happens in the [irixxxx's fork](https://github.com/irixxxx/picodrive), [notaz's repo](https://github.com/notaz/picodrive) isn't updated as much. + ### gallery Some images of demos and homebrew software: -**16/32 bit systems**: Mega Drive/Genesis, Sega/Mega CD, 32X, Pico. - -![Titan Overdrive 2](https://github.com/irixxxx/picodrive/assets/31696370/02a4295b-ac9d-4114-bcd1-b5dd6e5930d0) -![Raycast Demo](https://github.com/irixxxx/picodrive/assets/31696370/6e9c0bfe-49a9-45aa-bad7-544de065e388) -![OpenLara](https://github.com/irixxxx/picodrive/assets/31696370/8a00002a-5c10-4d1d-a948-739bf978282a) +**16 bit systems**: Mega Drive/Genesis, Sega/Mega CD, 32X, Pico. -![Titan Overdrive 2](https://github.com/irixxxx/picodrive/assets/31696370/2e263e81-51c8-4daa-ab16-0b2cd5554f84) -![DMA David](https://github.com/irixxxx/picodrive/assets/31696370/fbbeac15-8665-4d3e-9729-d1f8c35e417a) -![Doom Resurrection](https://github.com/irixxxx/picodrive/assets/31696370/db7b7153-b917-4850-8442-a748c2fbb968) - -$~$ +| ![Titan Overdrive 2](https://github.com/irixxxx/picodrive/assets/31696370/02a4295b-ac9d-4114-bcd1-b5dd6e5930d0) | ![Raycast Demo](https://github.com/irixxxx/picodrive/assets/31696370/6e9c0bfe-49a9-45aa-bad7-544de065e388) | ![OpenLara](https://github.com/irixxxx/picodrive/assets/31696370/8a00002a-5c10-4d1d-a948-739bf978282a) | +| --- | --- | --- | +| [_MegaDrive: Titan Overdrive 2_](https://demozoo.org/productions/170767/) | [_MegaCD: RaycastDemo_](https://github.com/matteusbeus/RaycastDemo) | [_32X: OpenLara_](https://github.com/XProger/OpenLara/releases) | +|![Titan Overdrive 2](https://github.com/irixxxx/picodrive/assets/31696370/2e263e81-51c8-4daa-ab16-0b2cd5554f84)|![DMA David](https://github.com/irixxxx/picodrive/assets/31696370/fbbeac15-8665-4d3e-9729-d1f8c35e417a)|![Doom Resurrection](https://github.com/irixxxx/picodrive/assets/31696370/db7b7153-b917-4850-8442-a748c2fbb968)| +| | [_MegaDrive: DMA David_](http://www.mode5.net/DMA_David.html) | [_32X: Doom Resurrection_](https://archive.org/details/doom-32x-all-versions) | **8 bit systems**: SG-1000, SC-3000, Master System/Mark III, Game Gear. -![Cheril Perils Classics](https://github.com/irixxxx/picodrive/assets/31696370/653914a4-9f90-45f8-bd91-56e784df7550) -![Stygian Quest](https://github.com/irixxxx/picodrive/assets/31696370/8196801b-85c8-4d84-97e1-ae57ab3d577f) -![Wing Warriors](https://github.com/irixxxx/picodrive/assets/31696370/3c4a8f40-dad6-4fa4-b188-46b428a4b8c6) - -![Nyan Cat](https://github.com/irixxxx/picodrive/assets/31696370/6fe0d38b-549d-4faa-9351-b260a89dc745) -![Anguna the Prison Dungeon](https://github.com/irixxxx/picodrive/assets/31696370/3264b962-7da2-4257-9ff7-1b509bd50cdf) -![Turrican](https://github.com/irixxxx/picodrive/assets/31696370/c4eb2f2c-806e-4f4b-ac94-5c2cda82e962) +| ![Cheril Perils Classics](https://github.com/irixxxx/picodrive/assets/31696370/653914a4-9f90-45f8-bd91-56e784df7550) | ![Stygian Quest](https://github.com/irixxxx/picodrive/assets/31696370/8196801b-85c8-4d84-97e1-ae57ab3d577f) | ![Sword of Stone](https://github.com/irixxxx/picodrive/assets/31696370/3c4a8f40-dad6-4fa4-b188-46b428a4b8c6) | +| --- | --- | --- | +| [_SG-1000: Cheril Perils Classic_](https://www.smspower.org/Homebrew/CherilPerilsClassic-SG) | [_MasterSystem: Stygian Quest_](https://www.smspower.org/Homebrew/StygianQuest-SMS) | [_GameGear: The Sword of Stone_](https://www.smspower.org/Homebrew/SwordOfStone-GG) | +| ![Nyan Cat](https://github.com/irixxxx/picodrive/assets/31696370/6fe0d38b-549d-4faa-9351-b260a89dc745) | ![Anguna the Prison Dungeon](https://github.com/irixxxx/picodrive/assets/31696370/3264b962-7da2-4257-9ff7-1b509bd50cdf) | ![Turrican](https://github.com/irixxxx/picodrive/assets/31696370/c4eb2f2c-806e-4f4b-ac94-5c2cda82e962) | +| [_SG-1000: Nyan Cat_](https://www.smspower.org/Homebrew/NyanCat-SG) | [_MS: Anguna the Prison Dungeon_](https://www.smspower.org/Homebrew/AngunaThePrisonDungeon-SMS) | [_GameGear: Turrican_](https://www.smspower.org/Homebrew/GGTurrican-GG) | ### compiling -- 2.39.2 From e3fa3ee270fc5905943719e966277b8ae10e1cd4 Mon Sep 17 00:00:00 2001 From: Apaczer <94932128+Apaczer@users.noreply.github.com> Date: Thu, 11 Jul 2024 22:49:13 +0200 Subject: [PATCH 08/16] platform-miyoo: change to IPK release output create `platform/miyoo/pkg.cfg` --- .github/workflows/ci.yml | 4 ++-- .gitignore | 1 + Makefile | 8 ++++--- platform/miyoo/pkg.cfg | 45 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 platform/miyoo/pkg.cfg diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 50847c34..40b77daf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -196,12 +196,12 @@ jobs: ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=miyoo make -j$(getconf _NPROCESSORS_ONLN) - mv PicoDrive-miyoo.zip PicoDrive-miyoo-$ver.zip + mv PicoDrive-miyoo.ipk PicoDrive-miyoo-$ver.ipk - name: artifacts uses: actions/upload-artifact@v4 with: name: Miyoo - path: PicoDrive-miyoo*.zip + path: PicoDrive-miyoo*.ipk build-retrofw: runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index 79cc126b..742cba8e 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ PicoDrive picodrive picodrive_libretro* PicoDrive*.opk +PicoDrive*.ipk PicoDrive*.zip pico_int_offs.h amalgamate diff --git a/Makefile b/Makefile index f6ae8a5a..48fa6a4d 100644 --- a/Makefile +++ b/Makefile @@ -141,10 +141,12 @@ all: PicoDrive-dge.zip CFLAGS += -DSDL_SURFACE_SW # some legacy dinguces had bugs in HWSURFACE else ifneq (,$(filter %__MIYOO__, $(CFLAGS))) -PicoDrive-miyoo.zip: .od_data +PicoDrive-miyoo.ipk: .od_data rm -f .od_data/default.*.desktop .od_data/PicoDrive.dge - cd .od_data && zip -9 -r ../$@ * -all: PicoDrive-miyoo.zip + gm2xpkg -i platform/miyoo/pkg.cfg + mv picodrive.ipk $@ + @gm2xpkg -c platform/miyoo/pkg.cfg >/dev/null 2>&1 +all: PicoDrive-miyoo.ipk else PicoDrive.opk: .od_data rm -f .od_data/PicoDrive.dge diff --git a/platform/miyoo/pkg.cfg b/platform/miyoo/pkg.cfg new file mode 100644 index 00000000..dd5fa0d8 --- /dev/null +++ b/platform/miyoo/pkg.cfg @@ -0,0 +1,45 @@ +# NOTES: +## All variable values should enclosed within double quotes: "" +## CONFIGURATION FILE for `gm2xpkg` script version: +PKGVER="0.4" + +# EXEC commands (set to "1" anyone for desired outcome), you can instead use [OPTIONS] of `gm2xpkg`: +PACKAGE="" +ZIP="" +IPK="" +CLEAN="" + +# ENV VAR. +## Specific (mandatory to provide!) +TARGET="picodrive" # replace with binary name +VERSION="v2.00" # replace with correct release version if exist + +## Generic - common to all apps (better to not modify) +HOMEPATH="/mnt" +RELEASEDIR="" +ASSETSDIR=".od_data" +OPKG_ASSETSDIR="" +LINK="" # full name of gm2x link, modify if exec binary name may be different from target name - place in CWD (warning: it may be removed with CLEAN=1) +ALIASES="" # full name (with ext) of *.txt file with new names for selector e.g. old_title=new_title - place in CWD +MANUAL="" # full name (with ext) of *.man.txt file with usage description of target app - place in CWD + +## Link entries (better modify if no .lnk file provided) +TITLE="PicoDrive" +DESCRI="MegaDrive/MegaCD/32X emulator" +SELDIR="/mnt/roms/SMD" +DESTDIR="emus" # default=apps +SECTION="emulators" # default=applications + +## Custom entries (if needed then modify) +TARGET_DIR="" # the directory /$HOMEPATH/$DESTDIR/TARGET_DIR of executable binary if not provided the TARGET_DIR=$TARGET +DOCS=("COPYING" "AUTHORS") # array of extra text files e.g. =("LICENSE" "CHANGELOG" "CONTRIBUTORS") which will be copied & converted to *.txt files for ease of use by frontend + +## IPK control entries (if needed then modify) +PRIORITY="" +MAINTAINER="irixxxx" +CONFFILES="" +ARCH="" # default=arm - do not modify for ARM chips +# CONTROL= # automated output of *.ipk control config file +DEPENDS="" # list of dependency packages e.g. ="sdl, libpng" or ="sdl (>= 2.9.2), sdl_mixer (= ed76d39cda0735d26c14a3e4f4da996e420f6478)" provide only for shared libs build, otherwise ignored +SOURCE="https://github.com/irixxxx/picodrive" +LICENSE="Custom" -- 2.39.2 From a9d1e99533de1fd378892c0da5caa564f2bb639b Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 12 Jul 2024 22:11:51 +0200 Subject: [PATCH 09/16] core, adjustment for background color DMA --- pico/videoport.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pico/videoport.c b/pico/videoport.c index 9663e2bf..9c35162d 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -626,7 +626,8 @@ static void DmaSlow(int len, u32 source) if (sl > VdpFIFO.fifo_hcounts[0]-5) // hint delay is 5 slots sl = (s8)sl; // TODO this is needed to cover timing inaccuracies - if (sl <= 12) sl = -2; + if (sl <= 12) sl = -3; + else if (sl <= 40) sl = 30; PicoDrawBgcDMA(base, source, mask, len, sl); // do last DMA cycle since it's all going to the same cram location source = source+len-1; -- 2.39.2 From c12b126f06818948dd89e7fd8524158582773e2a Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 12 Jul 2024 22:57:25 +0200 Subject: [PATCH 10/16] platform miyoo, switch menu key to RESET --- platform/common/inputmap_kbd.c | 3 ++- platform/common/plat_sdl.c | 5 ++--- platform/common/plat_sdl.h | 2 +- platform/opendingux/inputmap.c | 13 ++++++++++++- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/platform/common/inputmap_kbd.c b/platform/common/inputmap_kbd.c index c41abbb3..8fbb29f8 100644 --- a/platform/common/inputmap_kbd.c +++ b/platform/common/inputmap_kbd.c @@ -7,7 +7,7 @@ #include "../common/input_pico.h" #include "../common/plat_sdl.h" -const struct in_default_bind in_sdl_defbinds[] = { +const struct in_default_bind _in_sdl_defbinds[] = { { SDLK_UP, IN_BINDTYPE_PLAYER12, GBTN_UP }, { SDLK_DOWN, IN_BINDTYPE_PLAYER12, GBTN_DOWN }, { SDLK_LEFT, IN_BINDTYPE_PLAYER12, GBTN_LEFT }, @@ -35,6 +35,7 @@ const struct in_default_bind in_sdl_defbinds[] = { { SDLK_BACKSPACE, IN_BINDTYPE_EMU, PEVB_FF }, { 0, 0, 0 } }; +const struct in_default_bind *in_sdl_defbinds = _in_sdl_defbinds; const struct menu_keymap _in_sdl_key_map[] = { { SDLK_UP, PBTN_UP }, diff --git a/platform/common/plat_sdl.c b/platform/common/plat_sdl.c index 140480e8..d1e833f3 100644 --- a/platform/common/plat_sdl.c +++ b/platform/common/plat_sdl.c @@ -26,9 +26,7 @@ static void *shadow_fb; static int shadow_size; static struct area { int w, h; } area; -static struct in_pdata in_sdl_platform_data = { - .defbinds = in_sdl_defbinds, -}; +static struct in_pdata in_sdl_platform_data; static int sound_rates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 53000, -1 }; struct plat_target plat_target = { .sound_rates = sound_rates }; @@ -438,6 +436,7 @@ void plat_init(void) g_screen_ptr = shadow_fb; plat_target_setup_input(); + in_sdl_platform_data.defbinds = in_sdl_defbinds, in_sdl_platform_data.kmap_size = in_sdl_key_map_sz, in_sdl_platform_data.key_map = in_sdl_key_map, in_sdl_platform_data.jmap_size = in_sdl_joy_map_sz, diff --git a/platform/common/plat_sdl.h b/platform/common/plat_sdl.h index aefa8076..cecdb2b3 100644 --- a/platform/common/plat_sdl.h +++ b/platform/common/plat_sdl.h @@ -1,5 +1,5 @@ -extern const struct in_default_bind in_sdl_defbinds[]; +extern const struct in_default_bind *in_sdl_defbinds; extern const struct menu_keymap *in_sdl_key_map; extern const int in_sdl_key_map_sz; extern const struct menu_keymap *in_sdl_joy_map; diff --git a/platform/opendingux/inputmap.c b/platform/opendingux/inputmap.c index e8eace45..30c4639a 100644 --- a/platform/opendingux/inputmap.c +++ b/platform/opendingux/inputmap.c @@ -10,7 +10,7 @@ #include "../common/plat_sdl.h" #include "../common/emu.h" -const struct in_default_bind in_sdl_defbinds[] = { +struct in_default_bind _in_sdl_defbinds[] = { { SDLK_UP, IN_BINDTYPE_PLAYER12, GBTN_UP }, { SDLK_DOWN, IN_BINDTYPE_PLAYER12, GBTN_DOWN }, { SDLK_LEFT, IN_BINDTYPE_PLAYER12, GBTN_LEFT }, @@ -27,6 +27,7 @@ const struct in_default_bind in_sdl_defbinds[] = { { SDLK_SPACE, IN_BINDTYPE_EMU, PEVB_FF }, { 0, 0, 0 } }; +const struct in_default_bind *in_sdl_defbinds = _in_sdl_defbinds; struct menu_keymap _in_sdl_key_map[] = { { SDLK_UP, PBTN_UP }, @@ -122,6 +123,15 @@ static void keyswap(int k1, int k2) } } +static void bindswap(int k1, int k2) +{ + int i; + + for (i = 0; _in_sdl_defbinds[i].code; i++) + if (_in_sdl_defbinds[i].code == k1) + _in_sdl_defbinds[i].code = k2; +} + void plat_target_setup_input(void) { if (strcmp(plat_device, "miyoo") == 0) { @@ -129,6 +139,7 @@ void plat_target_setup_input(void) keyswap(SDLK_LALT, SDLK_LCTRL); nameswap(SDLK_LALT, SDLK_LCTRL); nameswap(SDLK_SPACE, SDLK_LSHIFT); + bindswap(SDLK_ESCAPE, SDLK_RCTRL); } else if (strcmp(plat_device, "gcw0") == 0) { /* swapped X/Y keys, single L/R keys */ nameswap(SDLK_SPACE, SDLK_LSHIFT); -- 2.39.2 From b4244cbb6dfe5607911fbe78c16ad1b1f7cc11fc Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 12 Jul 2024 22:15:21 +0200 Subject: [PATCH 11/16] update README --- README.md | 130 +++++++++++++++++++++++++++++------------------------- 1 file changed, 71 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 8da8c717..527aa29b 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,39 @@ -This is yet another SEGA 8 bit and 16 bit console emulator for emulating most -of the hardware SEGA has published up to and including the 32X. +This is yet another SEGA 8 bit and 16 bit console emulator. +It can run games developed for most consumer hardware released +by SEGA, up to and including the 32X: +- **16 bit systems:** Mega Drive/Genesis, Sega/Mega CD, 32X, Pico +- **8 bit systems**: SG-1000, SC-3000, Master System/Mark III, Game Gear -PicoDrive was originally written having ARM-based handheld devices -in mind, but later had got various improvements for other architectures -too, like SH2 recompilers for MIPS (mips32r2), ARM64 (armv8), RISC-V (RV64IM) +PicoDrive was originally created with ARM-based handheld devices +in mind, but later received various cross-platform improvements +such as SH2 recompilers for MIPS (mips32r2), ARM64 (armv8), RISC-V (RV64IM) and PowerPC (G4/2.03). -PicoDrive was the first emulator ever to properly emulate Virtua Racing and +PicoDrive was the first software to properly emulate Virtua Racing and its SVP chip. -Currently the main development happens in the -[irixxxx's fork](https://github.com/irixxxx/picodrive), -[notaz's repo](https://github.com/notaz/picodrive) isn't updated as much. +At present, most development activity occurs in +[irixxxx's fork](https://github.com/irixxxx/picodrive); +[notaz's repo](https://github.com/notaz/picodrive) is updated less frequently. +### Sega Pico and Storyware Pages -### gallery +PicoDrive can use Storyware pages and pad overlays in png format in the same +directory as the cartridge image. The selected page is displayed automatically +if the pen is used on the storyware or pad. Details about how to correctly name +the pages can be found in the *How to run Sega Pico games* section in +`platform/base_readme.txt`. -Some images of demos and homebrew software: +### Gallery -**16 bit systems**: Mega Drive/Genesis, Sega/Mega CD, 32X, Pico. +Some images of demos and homebrew software: | ![Titan Overdrive 2](https://github.com/irixxxx/picodrive/assets/31696370/02a4295b-ac9d-4114-bcd1-b5dd6e5930d0) | ![Raycast Demo](https://github.com/irixxxx/picodrive/assets/31696370/6e9c0bfe-49a9-45aa-bad7-544de065e388) | ![OpenLara](https://github.com/irixxxx/picodrive/assets/31696370/8a00002a-5c10-4d1d-a948-739bf978282a) | | --- | --- | --- | | [_MegaDrive: Titan Overdrive 2_](https://demozoo.org/productions/170767/) | [_MegaCD: RaycastDemo_](https://github.com/matteusbeus/RaycastDemo) | [_32X: OpenLara_](https://github.com/XProger/OpenLara/releases) | |![Titan Overdrive 2](https://github.com/irixxxx/picodrive/assets/31696370/2e263e81-51c8-4daa-ab16-0b2cd5554f84)|![DMA David](https://github.com/irixxxx/picodrive/assets/31696370/fbbeac15-8665-4d3e-9729-d1f8c35e417a)|![Doom Resurrection](https://github.com/irixxxx/picodrive/assets/31696370/db7b7153-b917-4850-8442-a748c2fbb968)| -| | [_MegaDrive: DMA David_](http://www.mode5.net/DMA_David.html) | [_32X: Doom Resurrection_](https://archive.org/details/doom-32x-all-versions) | - -**8 bit systems**: SG-1000, SC-3000, Master System/Mark III, Game Gear. +| [_MegaDrive: Titan Overdrive 2_](https://www.pouet.net/prod.php?which=69648) | [_MegaDrive: DMA David_](http://www.mode5.net/DMA_David.html) | [_32X: Doom Resurrection_](https://archive.org/details/doom-32x-all-versions) | | ![Cheril Perils Classics](https://github.com/irixxxx/picodrive/assets/31696370/653914a4-9f90-45f8-bd91-56e784df7550) | ![Stygian Quest](https://github.com/irixxxx/picodrive/assets/31696370/8196801b-85c8-4d84-97e1-ae57ab3d577f) | ![Sword of Stone](https://github.com/irixxxx/picodrive/assets/31696370/3c4a8f40-dad6-4fa4-b188-46b428a4b8c6) | | --- | --- | --- | @@ -35,62 +41,68 @@ Some images of demos and homebrew software: | ![Nyan Cat](https://github.com/irixxxx/picodrive/assets/31696370/6fe0d38b-549d-4faa-9351-b260a89dc745) | ![Anguna the Prison Dungeon](https://github.com/irixxxx/picodrive/assets/31696370/3264b962-7da2-4257-9ff7-1b509bd50cdf) | ![Turrican](https://github.com/irixxxx/picodrive/assets/31696370/c4eb2f2c-806e-4f4b-ac94-5c2cda82e962) | | [_SG-1000: Nyan Cat_](https://www.smspower.org/Homebrew/NyanCat-SG) | [_MS: Anguna the Prison Dungeon_](https://www.smspower.org/Homebrew/AngunaThePrisonDungeon-SMS) | [_GameGear: Turrican_](https://www.smspower.org/Homebrew/GGTurrican-GG) | +### Compiling -### compiling - -For platforms for which release builds are supplied the most easy way is to -use the release script in tools/release.sh. See the release script for details. -To make a platform build use +For platforms where release builds are provided, the simplest method is to +use the release script `tools/release.sh`. See the script itself for details. +To create platform builds run the command: -> tools/release.sh [version] [platforms...] +``` +tools/release.sh [version] [platforms...] +``` -This will deliver a file for each platform in a the release-[version] directory. -A list of platforms is in the release script. +This will generate a file for each platform in the `release-[version]` directory. +A list of supported platforms can be found in the release script. -If you want to build an executable for a unixoid platform not listed in the -platform list, try using +These commands should create an executable for a unixoid platform not included in the list: -> configure --platform=generic +``` +configure --platform=generic +make +``` -If DRC is available for the platform, it should be enabled automatically. -For gp2x, wiz, and caanoo you may need to compile libpng first. +To compile PicoDrive as a libretro core, use this command: -After configure, compile with +``` +make -f Makefile.libretro +``` -> make - - -### helix MP3 decoder for ARM +### Helix MP3 decoder for ARM For 32 bit ARM platforms, the optimized helix MP3 decoder can be used to play -MP3 audio files with CD games. The helix source files are however not supplied -due to licensing issues. If you have legally obtained the sources, put them in -the platform/common/helix directory. - -To compile the helix sources, set CROSS_COMPILE to your cross compiler prefix -(e.g. arm-linux-gnueabi-) and LIBGCC to your cross compiler's libgcc.a -(e.g. /usr/lib/gcc-cross/arm-linux-gnueabi/4.7/libgcc.a), and compile with - -> make -C platform/common/helix CROSS_COMPILE=$CROSS_COMPILE LIBGCC=$LIBGCC - -This will result in a shared library named ${CROSS_COMPILE}helix_mp3.so. Copy -this as libhelix.so to where the PicoDrive binary is on the target device. - - -Also, the support for helix must be enabled in PicoDrive by compiling with - -> make PLATFORM_MP3=1 - -This switch is automatically enabled for Gamepark Holdings devices (gp2x, -caanoo and wiz). Without installing libhelix.so those devices will not play +MP3 audio files with CD games. Due to licensing issues, the helix source files +cannot be provided here; if you have obtained the sources legally, place them in +the `platform/common/helix` directory. + +To compile the helix sources: + +- Set the environment variable `CROSS_COMPILE` to your cross compiler prefix +(e.g. `arm-linux-gnueabi-`) +- Set the environment variable `LIBGCC` to your cross compiler's `libgcc.a` +(e.g. `/usr/lib/gcc-cross/arm-linux-gnueabi/4.7/libgcc.a`) +- Run the command: +``` +make -C platform/common/helix CROSS_COMPILE=$CROSS_COMPILE LIBGCC=$LIBGCC +``` +- Copy the resulting shared library named `${CROSS_COMPILE}helix_mp3.so` as +`libhelix.so` to the directory containing the PicoDrive binary on the target device. + +In addition, helix support must be enabled in PicoDrive itself by compiling with: + +``` +make PLATFORM_MP3=1 +``` + +This switch is enabled automatically for Gamepark Holdings devices (`gp2x`, +`caanoo` and `wiz`). Without installing `libhelix.so`, these devices will not play MP3 audio. +### Installing -### installing +The release script produces packages or zip archives which have to be installed +manually on the target device. Usually this involves unpacking the archive or +copying the package to a directory on either the internal device storage or an +SD card. Device-specific instructions can be found on the internet. -The release scripts produces zip files which need to be installed on the -target device manually. Usually that means unpacking the file to some -directory on the device storage or on an SD card. See device specific -descriptions on the net. -Send bug reports, fixes etc to +Send bug reports, fixes etc. to -- 2.39.2 From 4a347fbe946e4ee4ae0687f4139a8f6f0aa179cd Mon Sep 17 00:00:00 2001 From: Apaczer <94932128+Apaczer@users.noreply.github.com> Date: Mon, 15 Jul 2024 23:13:09 +0200 Subject: [PATCH 12/16] platform/miyoo: scripted versioning update pkg.cfg --- platform/miyoo/pkg.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/miyoo/pkg.cfg b/platform/miyoo/pkg.cfg index dd5fa0d8..940cf277 100644 --- a/platform/miyoo/pkg.cfg +++ b/platform/miyoo/pkg.cfg @@ -12,8 +12,8 @@ CLEAN="" # ENV VAR. ## Specific (mandatory to provide!) TARGET="picodrive" # replace with binary name -VERSION="v2.00" # replace with correct release version if exist - +VERSION="$(cut -d'"' -f2 platform/common/version.h)" # replace with correct release version if exist +test "$(git describe --tags --exact-match HEAD 2>/dev/null)" == "" && VERSION="${VERSION}-$(git rev-parse --short HEAD || echo unknown)" ## Generic - common to all apps (better to not modify) HOMEPATH="/mnt" RELEASEDIR="" -- 2.39.2 From 1fad746a1f0fa19c874be4130e328141bcefb974 Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 17 Jul 2024 22:47:02 +0200 Subject: [PATCH 13/16] core vdp, fix layer/window borders for vertical window --- pico/draw.c | 235 +++++++++++++++++++++++++++--------------------- pico/draw_arm.S | 83 ++++++++++++++--- 2 files changed, 205 insertions(+), 113 deletions(-) diff --git a/pico/draw.c b/pico/draw.c index 5868268b..0f9b137a 100644 --- a/pico/draw.c +++ b/pico/draw.c @@ -304,13 +304,43 @@ TileFlipMakerAS(TileFlipSH_AS_and, pix_sh_as_and) // -------------------------------------------- #ifndef _ASM_DRAW_C +#define DrawTile(mask) { \ + if (code!=oldcode) { \ + oldcode = code; \ + \ + pack = 0; \ + if (code != blank) { \ + /* Get tile address/2: */\ + u32 addr = ((code&0x7ff)<<4) + ty; \ + if (code & 0x1000) addr ^= 0xe; /* Y-flip */ \ + \ + pal = ((code>>9)&0x30) | sh; /* shadow */ \ + \ + pack = CPU_LE2(*(u32 *)(PicoMem.vram + addr)); \ + if (!pack) \ + blank = code; \ + } \ + } \ + \ + if (code & 0x8000) { /* (un-forced) high priority tile */ \ + if (sh | (pack&mask)) { \ + code |= (dx<<16) | (ty<<25); \ + if (code & 0x1000) code ^= 0xe<<25; \ + *hc++ = code, *hc++ = pack&mask; /* cache it */ \ + } \ + } else if (pack&mask) { \ + if (code & 0x0800) TileFlip(pd + dx, pack&mask, pal); \ + else TileNorm(pd + dx, pack&mask, pal); \ + } \ +} + static void DrawStrip(struct TileStrip *ts, int lflags, int cellskip) { unsigned char *pd = Pico.est.HighCol; u32 *hc = ts->hc; int tilex, dx, ty, cells; - u32 pack = 0, oldcode = -1, blank = -1; // The tile we know is blank - unsigned int pal = 0, sh; + u32 code, oldcode = -1, blank = -1; // The tile we know is blank + unsigned int pal = 0, pack = 0, sh, mask = ~0; // Draw tiles across screen: sh = (lflags & LF_SH) << 6; // shadow @@ -318,42 +348,39 @@ static void DrawStrip(struct TileStrip *ts, int lflags, int cellskip) ty=(ts->line&7)<<1; // Y-Offset into tile dx=((ts->hscroll-1)&7)+1; cells = ts->cells - cellskip; - if(dx != 8) cells++; // have hscroll, need to draw 1 cell more dx+=cellskip<<3; + if (dx & 7) { + code = PicoMem.vram[ts->nametab + (tilex & ts->xmask)]; + mask = 0xffffffff<<((dx&7)*4); + if (code & 0x0800) mask = 0xffffffff>>((dx&7)*4); + mask = (~mask << 16) | (~mask >> 16); + + DrawTile(mask); + dx += 8, tilex++, cells--; + } + // int force = (lflags&LF_FORCE) << 13; for (; cells > 0; dx+=8, tilex++, cells--) { - u32 code = PicoMem.vram[ts->nametab + (tilex & ts->xmask)]; + code = PicoMem.vram[ts->nametab + (tilex & ts->xmask)]; // code &= ~force; // forced always draw everything if (code == blank && !((code & 0x8000) && sh)) continue; - if (code!=oldcode) { - oldcode = code; - - pack = 0; - if (code != blank) { - // Get tile address/2: - u32 addr = ((code&0x7ff)<<4) + ty; - if (code & 0x1000) addr ^= 0xe; // Y-flip - - pal = ((code>>9)&0x30) | sh; // shadow + DrawTile(~0); + } - pack = CPU_LE2(*(u32 *)(PicoMem.vram + addr)); - if (!pack) - blank = code; - } - } + if (dx & 7) { + code = PicoMem.vram[ts->nametab + (tilex & ts->xmask)]; +// code &= ~force; // forced always draw everything + if (!(code == blank && !((code & 0x8000) && sh))) { + mask = 0xffffffff<<((dx&7)*4); + if (code & 0x0800) mask = 0xffffffff>>((dx&7)*4); + mask = (mask << 16) | (mask >> 16); - if (code & 0x8000) { // (un-forced) high priority tile - code |= (dx<<16) | (ty<<25); - if (code & 0x1000) code ^= 0xe<<25; - *hc++ = code, *hc++ = pack; // cache it - } else if (code != blank) { - if (code & 0x0800) TileFlip(pd + dx, pack, pal); - else TileNorm(pd + dx, pack, pal); + DrawTile(mask); } } @@ -451,6 +478,36 @@ static void DrawStripVSRam(struct TileStrip *ts, int plane_sh, int cellskip) } #endif +#define DrawTileInterlace(mask) { \ + if (code!=oldcode) { \ + oldcode = code; \ + \ + pack = 0; \ + if (code != blank) { \ + /* Get tile address/2: */ \ + u32 addr = ((code&0x3ff)<<5) + ty; \ + if (code & 0x1000) addr ^= 0x1e; /* Y-flip */ \ + \ + pal = ((code>>9)&0x30) | sh; /* shadow */ \ + \ + pack = CPU_LE2(*(u32 *)(PicoMem.vram + addr)); \ + if (!pack) \ + blank = code; \ + } \ + } \ + \ + if (code & 0x8000) { /* high priority tile */ \ + if (sh | (pack&mask)) { \ + code = (code&0xfc00) | ((code&0x3ff)<<1) | (dx<<16) | (ty<<25); \ + if (code & 0x1000) code ^= 0x1e<<25; \ + *hc++ = code, *hc++ = pack&mask; /* cache it */ \ + } \ + } else if (pack&mask) { \ + if (code & 0x0800) TileFlip(pd + dx, pack&mask, pal); \ + else TileNorm(pd + dx, pack&mask, pal); \ + } \ +} + #ifndef _ASM_DRAW_C static #endif @@ -459,8 +516,8 @@ void DrawStripInterlace(struct TileStrip *ts, int plane_sh) unsigned char *pd = Pico.est.HighCol; u32 *hc = ts->hc; int tilex = 0, dx = 0, ty = 0, cells; - u32 oldcode = -1, blank = -1; // The tile we know is blank - unsigned int pal = 0, pack = 0, sh; + u32 code, oldcode = -1, blank = -1; // The tile we know is blank + unsigned int pal = 0, pack = 0, sh, mask = ~0; // Draw tiles across screen: sh = (plane_sh & LF_SH) << 6; // shadow @@ -468,7 +525,16 @@ void DrawStripInterlace(struct TileStrip *ts, int plane_sh) ty=(ts->line&15)<<1; // Y-Offset into tile dx=((ts->hscroll-1)&7)+1; cells = ts->cells; - if(dx != 8) cells++; // have hscroll, need to draw 1 cell more + + if (dx & 7) { + code = PicoMem.vram[ts->nametab + (tilex & ts->xmask)]; + mask = 0xffffffff<<(dx*4); + if (code & 0x0800) mask = 0xffffffff>>(dx*4); + mask = (~mask << 16) | (~mask >> 16); + + DrawTileInterlace(mask); + dx += 8, tilex++, cells--; + } // int force = (plane_sh&LF_FORCE) << 13; for (; cells; dx+=8,tilex++,cells--) @@ -479,33 +545,18 @@ void DrawStripInterlace(struct TileStrip *ts, int plane_sh) if (code == blank && !(code & 0x8000)) continue; - if (code!=oldcode) { - oldcode = code; - - pack = 0; - if (code != blank) { - // Get tile address/2: - u32 addr = ((code&0x3ff)<<5) + ty; - if (code & 0x1000) addr ^= 0x1e; // Y-flip - - pal = ((code>>9)&0x30) | sh; // shadow + DrawTileInterlace(~0); + } - pack = CPU_LE2(*(u32 *)(PicoMem.vram + addr)); - if (!pack) - blank = code; - } - } + if (dx & 7) { + code = PicoMem.vram[ts->nametab + (tilex & ts->xmask)]; +// code &= ~force; // forced always draw everything + if (!(code == blank && !((code & 0x8000) && sh))) { + mask = 0xffffffff<<((dx&7)*4); + if (code & 0x0800) mask = 0xffffffff>>((dx&7)*4); + mask = (mask << 16) | (mask >> 16); - if (code & 0x8000) { // high priority tile - if ((plane_sh&LF_SH) | (code!=blank)) { - code = (code&0xfc00) | ((code&0x3ff)<<1) | (dx<<16) | (ty<<25); - if (code & 0x1000) code ^= 0x1e<<25; - *hc++ = code, *hc++ = pack; // cache it - } - continue; - } else if (code != blank) { - if (code & 0x0800) TileFlip(pd + dx, pack, pal); - else TileNorm(pd + dx, pack, pal); + DrawTileInterlace(mask); } } @@ -698,19 +749,6 @@ static void DrawWindow(int tstart, int tend, int prio, int sh, // -------------------------------------------- -static void DrawTilesFromCacheShPrep(void) -{ - // as some layer has covered whole line with hi priority tiles, - // we can process whole line and then act as if sh/hi mode was off, - // but leave lo pri op sprite markers alone - int c = 320/4, *zb = (int *)(Pico.est.HighCol+8); - Pico.est.rendstatus |= PDRAW_SHHI_DONE; - while (c--) - { - *zb++ &= 0x7f7f7f7f; - } -} - static void DrawTilesFromCache(u32 *hc, int sh, int rlim, struct PicoEState *est) { unsigned char *pd = est->HighCol; @@ -722,8 +760,18 @@ static void DrawTilesFromCache(u32 *hc, int sh, int rlim, struct PicoEState *est if (sh && (est->rendstatus & (PDRAW_SHHI_DONE|PDRAW_PLANE_HI_PRIO))) { - if (!(est->rendstatus & PDRAW_SHHI_DONE)) - DrawTilesFromCacheShPrep(); + if (!(est->rendstatus & PDRAW_SHHI_DONE)) { + // as some layer has covered whole line with hi priority tiles, + // we can process whole line and then act as if sh/hi mode was off, + // but leave lo pri op sprite markers alone + int *zb = (int *)(Pico.est.HighCol+8); + int c = rlim / 4; + while (c--) + { + *zb++ &= 0x7f7f7f7f; + } + Pico.est.rendstatus |= PDRAW_SHHI_DONE; + } sh = 0; } @@ -731,13 +779,13 @@ static void DrawTilesFromCache(u32 *hc, int sh, int rlim, struct PicoEState *est { while ((code=*hc++)) { pack = *hc++; + if (rlim-dx < 0) + goto last_cut_tile; if (!pack) continue; dx = (code >> 16) & 0x1ff; pal = ((code >> 9) & 0x30); - if (rlim-dx < 0) - goto last_cut_tile; if (code & 0x0800) TileFlip(pd + dx, pack, pal); else TileNorm(pd + dx, pack, pal); @@ -754,12 +802,12 @@ static void DrawTilesFromCache(u32 *hc, int sh, int rlim, struct PicoEState *est *zb++ &= 0x7f; *zb++ &= 0x7f; *zb++ &= 0x7f; *zb++ &= 0x7f; pack = *hc++; + if (rlim - dx < 0) + goto last_cut_tile; if (!pack) continue; pal = ((code >> 9) & 0x30); - if (rlim - dx < 0) - goto last_cut_tile; if (code & 0x0800) TileFlip(pd + dx, pack, pal); else TileNorm(pd + dx, pack, pal); @@ -770,35 +818,18 @@ static void DrawTilesFromCache(u32 *hc, int sh, int rlim, struct PicoEState *est last_cut_tile: // for vertical window cutoff { - unsigned int t; - - pd += dx; - if (code&0x0800) - { - switch (rlim-dx+8) - { - case 7: t=pack&0x00000f00; if (t) pd[6]=(unsigned char)(pal|(t>> 8)); // "break" is left out intentionally - case 6: t=pack&0x000000f0; if (t) pd[5]=(unsigned char)(pal|(t>> 4)); - case 5: t=pack&0x0000000f; if (t) pd[4]=(unsigned char)(pal|(t )); - case 4: t=pack&0xf0000000; if (t) pd[3]=(unsigned char)(pal|(t>>28)); - case 3: t=pack&0x0f000000; if (t) pd[2]=(unsigned char)(pal|(t>>24)); - case 2: t=pack&0x00f00000; if (t) pd[1]=(unsigned char)(pal|(t>>20)); - case 1: t=pack&0x000f0000; if (t) pd[0]=(unsigned char)(pal|(t>>16)); - default: break; - } - } - else - { - switch (rlim-dx+8) - { - case 7: t=pack&0x00f00000; if (t) pd[6]=(unsigned char)(pal|(t>>20)); - case 6: t=pack&0x0f000000; if (t) pd[5]=(unsigned char)(pal|(t>>24)); - case 5: t=pack&0xf0000000; if (t) pd[4]=(unsigned char)(pal|(t>>28)); - case 4: t=pack&0x0000000f; if (t) pd[3]=(unsigned char)(pal|(t )); - case 3: t=pack&0x000000f0; if (t) pd[2]=(unsigned char)(pal|(t>> 4)); - case 2: t=pack&0x00000f00; if (t) pd[1]=(unsigned char)(pal|(t>> 8)); - case 1: t=pack&0x0000f000; if (t) pd[0]=(unsigned char)(pal|(t>>12)); - default: break; + unsigned int t, mask; + + // rlim-dx + 8 px to draw -> mask shift 8-(rlim-dx + 8) + t = -(rlim - dx); + if (t < 8) { + mask = 0xffffffff<<(t*4); + if (code & 0x0800) mask = 0xffffffff>>(t*4); + mask = (mask << 16) | (mask >> 16); + + if (pack&mask) { + if (code & 0x0800) TileFlip(pd + dx, pack&mask, pal); + else TileNorm(pd + dx, pack&mask, pal); } } } diff --git a/pico/draw_arm.S b/pico/draw_arm.S index e3f6ce83..7a2e6f1d 100644 --- a/pico/draw_arm.S +++ b/pico/draw_arm.S @@ -433,11 +433,11 @@ DrawLayer: movs r3, r9, lsl #1 @ (force[31]|sh[30]) << 1 mov r3, #0 orrmi r10,r10, #1<<23 @ r10=cells[31:24]|sh[23]|hi_not_empty[22] -@ orrcc r10,r10, #1<<20 @ |had_output[21]|!force[20]|ty[15:0] +@ orrcc r10,r10, #1<<20 @ |had_output[21]|!force[20]|hscroll[19:17]|ty[15:0] movmi r3, #0x80 @ default to shadowed pal on sh mode - cmp r7, #8 - addne r10,r10, #0x01000000 @ we will loop cells+1 times if there is scroll + and r4, r7, #7 + orr r10,r10, r4, lsl #16 @ we will process cells+1 if there is scroll and r9, r9, #0xff00 add r8, r8, r9, lsr #8 @ tilex+=cellskip @@ -452,9 +452,40 @@ DrawLayer: mvn r9, #0 @ r9=prevcode=-1 add r1, r11, r7 @ r1=pdest - @ r10=cells[31:24]|sh[23]|hi_not_empty[22]|had_output[21]|!force[20]|ty[15:0] + @ r10=cells[31:24]|sh[23]|hi_not_empty[22]|had_output[21]|!force[20]|hscroll[19:17]|ty[15:0] @ r1=pd+dx r2=pack r3=pal r5=xmask r6=hc r8=tilex r9=prevcode r11=HighCol r12=nametab lr=vram @ r4 & r7 are scratch in this loop + + ands r4, r10, #7<<16 @ hscroll? + beq .dsloop_subr1 + subs r10,r10, #0x01000000 + bmi .dsloop_exit + + and r7, r5, r8 @ do first cut tile + add r7, lr, r7, lsl #1 @ Pico.vram+((tilex&ts->xmask) as halfwords) + ldrh r9, [r7, r12] @ r7=code (int, but from unsigned, no sign extend) + + add r8, r8, #1 + + movs r2, r9, lsl #20 @ if (code&0x1000) + mov r2, r2, lsl #1 + add r2, r2, r10, lsl #17 + mov r2, r2, lsr #17 + eorcs r2, r2, #0x0e @ if (code&0x1000) addr^=0xe; + + ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + + mvn r7, #0 + mov r4, r4, lsr #16-2 @ (dx&7)*4 + tst r9, #0x0800 + moveq r7, r7, lsl r4 @ mask = ~0 [shift] (dx&7)*4 + movne r7, r7, lsr r4 + mvn r7, r7, ror #16 + and r2, r2, r7 @ pack&mask + + orr r9, r9, #0x80000000 @ invalidate oldcode since pack is masked + b .DrawStrip_samecode + .dsloop_subr1: sub r1, r1, #8 .dsloop: @ 40-41 times @@ -480,7 +511,6 @@ DrawLayer: eorcs r2, r2, #0x0e @ if (code&0x1000) addr^=0xe; ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels - .DrawStrip_samecode: tst r9, #0x8000 @ tstne r10, #1<<20 @ !force[20] @@ -538,6 +568,35 @@ DrawLayer: b .dsloop .dsloop_exit: + ands r4,r10, #7<<16 @ hscroll? + beq .DrawStrip_noscroll + + and r7, r5, r8 @ do one more cut tile + add r7, lr, r7, lsl #1 @ Pico.vram+((tilex&ts->xmask) as halfwords) + ldrh r9, [r7, r12] @ r7=code (int, but from unsigned, no sign extend) + + add r1, r1, #8 + + movs r2, r9, lsl #20 @ if (code&0x1000) + mov r2, r2, lsl #1 + add r2, r2, r10, lsl #17 + mov r2, r2, lsr #17 + eorcs r2, r2, #0x0e @ if (code&0x1000) addr^=0xe; + + ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + + mvn r7, #0 + mov r4, r4, lsr #16-2 @ (dx&7)*4 + tst r9, #0x0800 + moveq r7, r7, lsl r4 @ mask = ~0 [shift] (dx&7)*4 + movne r7, r7, lsr r4 + mov r7, r7, ror #16 + and r2, r2, r7 @ pack&mask + + bic r10,r10, #7<<16 + b .DrawStrip_samecode @ one last time, with last tile now masked + +.DrawStrip_noscroll: tst r10, #1<<21 @ seen non hi-prio tile ldr r1, [sp, #9*4] @ est mov r0, #0 @@ -939,15 +998,17 @@ DrawTilesFromCache: b .dtfc_loop .dtfc_cut_tile: - add r4, r4, #7 @ 0-6 + cmn r4, #8 + ble .dtfc_loop @ off limits + + rsb r4, r4, #0 @ 1-7 mov r4, r4, lsl #2 - mov r12,#0xf<<28 - mov r12,r12,asr r4 - mov r2, r2, ror #16 + mvn r12,#0 tst r6, #0x0800 @ flipped? - mvnne r12,r12 + moveq r12,r12, lsl r4 + movne r12,r12, lsr r4 + mov r12,r12, ror #16 and r2, r2, r12 - mov r2, r2, ror #16 mov r12,#0xf tst r8, #1 bne .dtfc_shadow -- 2.39.2 From 11a1966bf349ab74035df4673293bdeab41b1a96 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 18 Jul 2024 21:36:43 +0200 Subject: [PATCH 14/16] core vdp, arm rendering speed optimisation --- pico/draw.c | 112 ++++++++++++++++++++++++------------------------ pico/draw_arm.S | 69 +++++++++++++---------------- 2 files changed, 85 insertions(+), 96 deletions(-) diff --git a/pico/draw.c b/pico/draw.c index 0f9b137a..387f3a42 100644 --- a/pico/draw.c +++ b/pico/draw.c @@ -304,34 +304,34 @@ TileFlipMakerAS(TileFlipSH_AS_and, pix_sh_as_and) // -------------------------------------------- #ifndef _ASM_DRAW_C -#define DrawTile(mask) { \ - if (code!=oldcode) { \ - oldcode = code; \ - \ - pack = 0; \ - if (code != blank) { \ - /* Get tile address/2: */\ - u32 addr = ((code&0x7ff)<<4) + ty; \ - if (code & 0x1000) addr ^= 0xe; /* Y-flip */ \ - \ - pal = ((code>>9)&0x30) | sh; /* shadow */ \ - \ - pack = CPU_LE2(*(u32 *)(PicoMem.vram + addr)); \ - if (!pack) \ - blank = code; \ - } \ - } \ - \ - if (code & 0x8000) { /* (un-forced) high priority tile */ \ - if (sh | (pack&mask)) { \ - code |= (dx<<16) | (ty<<25); \ - if (code & 0x1000) code ^= 0xe<<25; \ - *hc++ = code, *hc++ = pack&mask; /* cache it */ \ - } \ - } else if (pack&mask) { \ - if (code & 0x0800) TileFlip(pd + dx, pack&mask, pal); \ - else TileNorm(pd + dx, pack&mask, pal); \ - } \ +#define DrawTile(mask) { \ + if (code!=oldcode) { \ + oldcode = code; \ + \ + pack = 0; \ + if (code != blank) { \ + /* Get tile address/2: */ \ + u32 addr = ((code&0x7ff)<<4) + ty; \ + if (code & 0x1000) addr ^= 0xe; /* Y-flip */ \ + \ + pal = ((code>>9)&0x30) | sh; /* shadow */ \ + \ + pack = CPU_LE2(*(u32 *)(PicoMem.vram + addr)); \ + if (!pack) \ + blank = code; \ + } \ + } \ + \ + if (code & 0x8000) { /* (un-forced) high priority tile */ \ + if (sh | (pack&mask)) { \ + code |= (dx<<16) | (ty<<25); \ + if (code & 0x1000) code ^= 0xe<<25; \ + *hc++ = code, *hc++ = pack&mask; /* cache it */ \ + } \ + } else if (pack&mask) { \ + if (code & 0x0800) TileFlip(pd + dx, pack&mask, pal); \ + else TileNorm(pd + dx, pack&mask, pal); \ + } \ } static void DrawStrip(struct TileStrip *ts, int lflags, int cellskip) @@ -478,34 +478,34 @@ static void DrawStripVSRam(struct TileStrip *ts, int plane_sh, int cellskip) } #endif -#define DrawTileInterlace(mask) { \ - if (code!=oldcode) { \ - oldcode = code; \ - \ - pack = 0; \ - if (code != blank) { \ - /* Get tile address/2: */ \ - u32 addr = ((code&0x3ff)<<5) + ty; \ - if (code & 0x1000) addr ^= 0x1e; /* Y-flip */ \ - \ - pal = ((code>>9)&0x30) | sh; /* shadow */ \ - \ - pack = CPU_LE2(*(u32 *)(PicoMem.vram + addr)); \ - if (!pack) \ - blank = code; \ - } \ - } \ - \ - if (code & 0x8000) { /* high priority tile */ \ - if (sh | (pack&mask)) { \ - code = (code&0xfc00) | ((code&0x3ff)<<1) | (dx<<16) | (ty<<25); \ - if (code & 0x1000) code ^= 0x1e<<25; \ - *hc++ = code, *hc++ = pack&mask; /* cache it */ \ - } \ - } else if (pack&mask) { \ - if (code & 0x0800) TileFlip(pd + dx, pack&mask, pal); \ - else TileNorm(pd + dx, pack&mask, pal); \ - } \ +#define DrawTileInterlace(mask) { \ + if (code!=oldcode) { \ + oldcode = code; \ + \ + pack = 0; \ + if (code != blank) { \ + /* Get tile address/2: */ \ + u32 addr = ((code&0x3ff)<<5) + ty; \ + if (code & 0x1000) addr ^= 0x1e; /* Y-flip */ \ + \ + pal = ((code>>9)&0x30) | sh; /* shadow */ \ + \ + pack = CPU_LE2(*(u32 *)(PicoMem.vram + addr)); \ + if (!pack) \ + blank = code; \ + } \ + } \ + \ + if (code & 0x8000) { /* high priority tile */ \ + if (sh | (pack&mask)) { \ + code = (code&0xfc00) | ((code&0x3ff)<<1) | (dx<<16) | (ty<<25); \ + if (code & 0x1000) code ^= 0x1e<<25; \ + *hc++ = code, *hc++ = pack&mask; /* cache it */ \ + } \ + } else if (pack&mask) { \ + if (code & 0x0800) TileFlip(pd + dx, pack&mask, pal); \ + else TileNorm(pd + dx, pack&mask, pal); \ + } \ } #ifndef _ASM_DRAW_C diff --git a/pico/draw_arm.S b/pico/draw_arm.S index 7a2e6f1d..40d5c443 100644 --- a/pico/draw_arm.S +++ b/pico/draw_arm.S @@ -433,7 +433,7 @@ DrawLayer: movs r3, r9, lsl #1 @ (force[31]|sh[30]) << 1 mov r3, #0 orrmi r10,r10, #1<<23 @ r10=cells[31:24]|sh[23]|hi_not_empty[22] -@ orrcc r10,r10, #1<<20 @ |had_output[21]|!force[20]|hscroll[19:17]|ty[15:0] +@ orrcc r10,r10, #1<<20 @ |had_output[21]|!force[20]|hscroll[18:16]|ty[15:0] movmi r3, #0x80 @ default to shadowed pal on sh mode and r4, r7, #7 @@ -452,7 +452,7 @@ DrawLayer: mvn r9, #0 @ r9=prevcode=-1 add r1, r11, r7 @ r1=pdest - @ r10=cells[31:24]|sh[23]|hi_not_empty[22]|had_output[21]|!force[20]|hscroll[19:17]|ty[15:0] + @ r10=cells[31:24]|sh[23]|hi_not_empty[22]|had_output[21]|!force[20]|hscroll[18:16]|ty[15:0] @ r1=pd+dx r2=pack r3=pal r5=xmask r6=hc r8=tilex r9=prevcode r11=HighCol r12=nametab lr=vram @ r4 & r7 are scratch in this loop @@ -467,21 +467,19 @@ DrawLayer: add r8, r8, #1 - movs r2, r9, lsl #20 @ if (code&0x1000) - mov r2, r2, lsl #1 + tst r9, #0x1000 @ if (code&0x1000) + mov r2, r9, lsl #21 add r2, r2, r10, lsl #17 - mov r2, r2, lsr #17 - eorcs r2, r2, #0x0e @ if (code&0x1000) addr^=0xe; + eorne r2, r2, #0xe<<17 @ if (code&0x1000) addr^=0xe; - ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + ldr r2, [lr, r2, lsr #16] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels mvn r7, #0 mov r4, r4, lsr #16-2 @ (dx&7)*4 tst r9, #0x0800 moveq r7, r7, lsl r4 @ mask = ~0 [shift] (dx&7)*4 movne r7, r7, lsr r4 - mvn r7, r7, ror #16 - and r2, r2, r7 @ pack&mask + bic r2, r2, r7, ror #16 @ pack&~mask orr r9, r9, #0x80000000 @ invalidate oldcode since pack is masked b .DrawStrip_samecode @@ -504,13 +502,12 @@ DrawLayer: mov r9, r7 @ remember code - movs r2, r9, lsl #20 @ if (code&0x1000) - mov r2, r2, lsl #1 + tst r9, #0x1000 @ if (code&0x1000) + mov r2, r9, lsl #21 add r2, r2, r10, lsl #17 - mov r2, r2, lsr #17 - eorcs r2, r2, #0x0e @ if (code&0x1000) addr^=0xe; + eorne r2, r2, #0x0e<<17 @ if (code&0x1000) addr^=0xe; - ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + ldr r2, [lr, r2, lsr #16] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels .DrawStrip_samecode: tst r9, #0x8000 @ tstne r10, #1<<20 @ !force[20] @@ -577,21 +574,19 @@ DrawLayer: add r1, r1, #8 - movs r2, r9, lsl #20 @ if (code&0x1000) - mov r2, r2, lsl #1 + tst r9, #0x1000 @ if (code&0x1000) + mov r2, r9, lsl #21 add r2, r2, r10, lsl #17 - mov r2, r2, lsr #17 - eorcs r2, r2, #0x0e @ if (code&0x1000) addr^=0xe; + eorne r2, r2, #0x0e<<17 @ if (code&0x1000) addr^=0xe; - ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + ldr r2, [lr, r2, lsr #16] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels mvn r7, #0 mov r4, r4, lsr #16-2 @ (dx&7)*4 tst r9, #0x0800 moveq r7, r7, lsl r4 @ mask = ~0 [shift] (dx&7)*4 movne r7, r7, lsr r4 - mov r7, r7, ror #16 - and r2, r2, r7 @ pack&mask + and r2, r2, r7, ror #16 @ pack&mask bic r10,r10, #7<<16 b .DrawStrip_samecode @ one last time, with last tile now masked @@ -743,13 +738,12 @@ DrawLayer: mov r9, r7 @ remember code - movs r2, r9, lsl #20 @ if (code&0x1000) - mov r2, r2, lsl #1 + tst r9, #0x1000 @ if (code&0x1000) + mov r2, r9, lsl #21 add r2, r2, r10, lsl #17 - mov r2, r2, lsr #17 - eorcs r2, r2, #0x0e @ if (code&0x1000) addr^=0xe; + eorne r2, r2, #0x0e<<17 @ if (code&0x1000) addr^=0xe; - ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(PicoMem.vram+addr); // Get 8 pixels + ldr r2, [lr, r2, lsr #16] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels .DrawStrip_vs_samecode: tst r9, #0x8000 @@ -1007,8 +1001,7 @@ DrawTilesFromCache: tst r6, #0x0800 @ flipped? moveq r12,r12, lsl r4 movne r12,r12, lsr r4 - mov r12,r12, ror #16 - and r2, r2, r12 + and r2, r2, r12, ror #16 mov r12,#0xf tst r8, #1 bne .dtfc_shadow @@ -1152,9 +1145,7 @@ DrawSpriteSHi: cmp r0, #328 bge DrawSpriteSHi - mov r8, r8, lsl #17 - mov r8, r8, lsr #17 @ tile&=0x7fff; // Clip tile address - + bic r8, r8, #0xf8000 @ tile&=0x7fff; // Clip tile address ldr r2, [lr, r8, lsl #1] @ pack=*(unsigned int *)(PicoMem.vram+addr); // Get 8 pixels add r1, r11, r0 @ r1=pdest tst r2, r2 @@ -1346,9 +1337,7 @@ DrawSprite: cmp r0, #328 bge DrawSprite - mov r8, r8, lsl #17 - mov r8, r8, lsr #17 @ tile&=0x7fff; // Clip tile address - + bic r8, r8, #0xf8000 @ tile&=0x7fff; // Clip tile address ldr r2, [lr, r8, lsl #1] @ pack=*(unsigned int *)(PicoMem.vram+addr); // Get 8 pixels add r1, r11, r0 @ r1=pdest tst r2, r2 @@ -1492,16 +1481,16 @@ DrawWindow: mov r9, r7 @ remember code - movs r2, r9, lsl #20 @ if (code&0x1000) - mov r2, r2, lsl #1 - add r2, r10, r2, lsr #17 @ r2=addr=(code&0x7ff)<<4; addr+=ty - eorcs r2, r2, #0x0e @ if (code&0x1000) addr^=0xe; + tst r9, #0x1000 @ if (code&0x1000) + mov r2, r9, lsl #21 + add r2, r2, r10, lsl #17 + eorne r2, r2, #0xe<<17 @ if (code&0x1000) addr^=0xe; + + ldr r2, [lr, r2, lsr #16] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels and r3, r9, #0x6000 mov r3, r3, lsr #9 @ r3=pal=((code&0x6000)>>9); - ldr r2, [lr, r2, lsl #1] @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels - .dw_samecode: tst r6, #0x100 bne .dw_shadow -- 2.39.2 From ecc3f2ecc052238d66d020839845c0e5c52e7fd2 Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 19 Jul 2024 19:21:26 +0200 Subject: [PATCH 15/16] release 2.00 --- platform/common/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/common/version.h b/platform/common/version.h index 1ab6c650..230f315a 100644 --- a/platform/common/version.h +++ b/platform/common/version.h @@ -1 +1 @@ -#define VERSION "pre-2.00-beta3" REVISION +#define VERSION "2.00" REVISION -- 2.39.2 From 75db61b756baeb95547bb80775e07796de204810 Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 21 Jul 2024 16:33:07 +0200 Subject: [PATCH 16/16] platform ps2, handle audio similar to psp --- platform/ps2/emu.c | 109 ++++++++++++++++++++++++++++++++++----------- platform/psp/emu.c | 2 +- 2 files changed, 85 insertions(+), 26 deletions(-) diff --git a/platform/ps2/emu.c b/platform/ps2/emu.c index 32c3d6c4..09e13d25 100644 --- a/platform/ps2/emu.c +++ b/platform/ps2/emu.c @@ -87,9 +87,10 @@ static uint8_t vsync; /* 0 (Disabled), 1 (Enabled), 2 (Dynamic) */ #define SOUND_BLOCK_COUNT 7 #define SOUND_BUFFER_CHUNK (2*54000/50) // max.rate/min.frames in stereo +static short sndBuffer_emu[SOUND_BUFFER_CHUNK+4]; // 4 for sample rounding overhang static short __attribute__((aligned(4))) sndBuffer[SOUND_BUFFER_CHUNK*SOUND_BLOCK_COUNT]; static short __attribute__((aligned(4))) nulBuffer[SOUND_BUFFER_CHUNK]; -static short *snd_playptr, *sndBuffer_endptr; +static short *snd_playptr, *sndBuffer_ptr, *sndBuffer_endptr; static int samples_made, samples_done, samples_block; static int sound_thread_exit = 0, sound_stopped = 1; @@ -122,24 +123,78 @@ static void writeSound(int len) if (samples_made - samples_done < samples_block * (SOUND_BLOCK_COUNT-2) - 4) { samples_made += len / 2; - PicoIn.sndOut += len / 2; + sndBuffer_ptr += len / 2; + l = sndBuffer_ptr - sndBuffer; + + if (sndBuffer_ptr > sndBuffer_endptr) + sndBuffer_endptr = sndBuffer_ptr; + if (l > sizeof(sndBuffer)/2) + lprintf("snd ovrn %d %d\n", len, sndBuffer_ptr - sndBuffer); + if (l > samples_block * (SOUND_BLOCK_COUNT-2)) { + sndBuffer_endptr = sndBuffer_ptr; + sndBuffer_ptr = sndBuffer; + } } else lprintf("ovfl %d\n", samples_made - samples_done); - if (sndBuffer_endptr < PicoIn.sndOut) - sndBuffer_endptr = PicoIn.sndOut; - - l = PicoIn.sndOut - sndBuffer; - if (l > sizeof(sndBuffer)/2) - lprintf("ovrn %d %d\n", len, PicoIn.sndOut - sndBuffer); - if (l > samples_block * (SOUND_BLOCK_COUNT-2)) { - sndBuffer_endptr = PicoIn.sndOut; - PicoIn.sndOut = sndBuffer; - } // signal the snd thread SignalSema(sound_sem); } +static void writeSound_44100(int len) +{ + writeSound(len); + PicoIn.sndOut = sndBuffer_ptr; +} + +static void writeSound_22050_stereo(int len) +{ + short *p = sndBuffer_ptr; + int i; + + for (i = 0; i < len / 2; i+=2, p+=4) { + p[0] = p[2] = PicoIn.sndOut[i]; + p[1] = p[3] = PicoIn.sndOut[i+1]; + } + writeSound(2*len); +} + +static void writeSound_22050_mono(int len) +{ + short *p = sndBuffer_ptr; + int i; + + for (i = 0; i < len / 2; i++, p+=2) { + p[0] = p[1] = PicoIn.sndOut[i]; + } + writeSound(2*len); +} + +static void writeSound_11025_stereo(int len) +{ + short *p = sndBuffer_ptr; + int i; + + for (i = 0; i < len / 2; i+=2, p+=8) { + p[0] = p[2] = p[4] = p[6] = PicoIn.sndOut[i]; + p[1] = p[3] = p[5] = p[7] = PicoIn.sndOut[i+1]; + } + writeSound(4*len); +} + +static void writeSound_11025_mono(int len) +{ + short *p = sndBuffer_ptr; + int i; + + for (i = 0; i < len / 2; i++, p+=4) { + p[0] = p[1] = p[2] = p[3] = PicoIn.sndOut[i]; + } + writeSound(4*len); +} + +#define PS2_RATE 44100 // PicoIn.sndRate + static void resetSound() { struct audsrv_fmt_t format; @@ -147,7 +202,7 @@ static void resetSound() int ret; format.bits = 16; - format.freq = PicoIn.sndRate; + format.freq = PS2_RATE; format.channels = stereo ? 2 : 1; ret = audsrv_set_format(&format); if (ret < 0) { @@ -170,14 +225,10 @@ static int sound_thread(void *argp) // if there aren't enough samples, queue silence int queued = audsrv_queued()/2; while (queued < 2*samples_block) { - short *sndOut = PicoIn.sndOut, *sndEnd = sndBuffer_endptr; - // compute sample chunk size - int buflen = sndEnd - snd_playptr; - if (sndOut >= snd_playptr) - buflen = sndOut - snd_playptr; - if (buflen > samples_made - samples_done) - buflen = samples_made - samples_done; + int buflen = samples_made - samples_done; + if (buflen > sndBuffer_endptr - snd_playptr) + buflen = sndBuffer_endptr - snd_playptr; if (buflen > 3*samples_block - queued) buflen = 3*samples_block - queued; @@ -241,7 +292,7 @@ static void sound_init(void) thread.initial_priority = 40; thid = CreateThread(&thread); - samples_block = 22050/50; // needs to be initialized before thread start + samples_block = PS2_RATE/60; // needs to be initialized before thread start if (thid >= 0) { ret = StartThread(thid, NULL); if (ret < 0) lprintf("sound_init: StartThread returned %08x\n", ret); @@ -255,7 +306,7 @@ static void sound_init(void) void pemu_sound_start(void) { static int PsndRate_old = 0, PicoOpt_old = 0, pal_old = 0; static int mp3_init_done; - int ret, stereo; + int ret, stereo, factor; samples_made = samples_done = 0; @@ -279,14 +330,22 @@ void pemu_sound_start(void) { PsndRerate(Pico.m.frame_count ? 1 : 0); } stereo = (PicoIn.opt&8)>>3; - samples_block = (PicoIn.sndRate / (Pico.m.pal ? 50 : 60)) * (stereo ? 2 : 1); + + factor = PS2_RATE / PicoIn.sndRate; + samples_block = (PS2_RATE / (Pico.m.pal ? 50 : 60)) * (stereo ? 2 : 1); lprintf("starting audio: %i, len: %i, stereo: %i, pal: %i, block samples: %i\n", PicoIn.sndRate, Pico.snd.len, stereo, Pico.m.pal, samples_block); resetSound(); - PicoIn.writeSound = writeSound; - snd_playptr = PicoIn.sndOut = sndBuffer_endptr = sndBuffer; + switch (factor) { + case 1: PicoIn.writeSound = stereo ? writeSound_44100 :writeSound_44100 ; break; + case 2: PicoIn.writeSound = stereo ? writeSound_22050_stereo:writeSound_22050_mono; break; + case 4: PicoIn.writeSound = stereo ? writeSound_11025_stereo:writeSound_11025_mono; break; + } + sndBuffer_endptr = sndBuffer; + snd_playptr = sndBuffer_ptr = sndBuffer; + PicoIn.sndOut = (factor == 1 ? sndBuffer_ptr : sndBuffer_emu); PsndRate_old = PicoIn.sndRate; PicoOpt_old = PicoIn.opt; diff --git a/platform/psp/emu.c b/platform/psp/emu.c index a3e22571..41deba8d 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -450,7 +450,7 @@ static void writeSound(int len) if (samples_made - samples_done < samples_block * (SOUND_BLOCK_COUNT-2) - 4) { sndBuffer_ptr += len / 2; if (sndBuffer_ptr - sndBuffer > sizeof(sndBuffer)/2) - lprintf("snd ovrn %d %d\n", len, PicoIn.sndOut - sndBuffer); + lprintf("snd ovrn %d %d\n", len, sndBuffer_ptr - sndBuffer); if (sndBuffer_ptr >= sndBuffer_endptr) { int wrap = sndBuffer_ptr - sndBuffer_endptr; if (wrap > 0) -- 2.39.2