From 6e8a71eda0dd8ea6234b33c02b2652addebb078b Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 9 Nov 2023 22:56:00 +0000 Subject: [PATCH 01/40] prerelease 2.00-alpha1 --- 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 98ec231a1..8b2db2738 100644 --- a/platform/common/version.h +++ b/platform/common/version.h @@ -1 +1 @@ -#define VERSION "2.00-alpha1" REVISION +#define VERSION "pre-2.00-alpha1" REVISION From 7f09f5c477d5834b2dbef96d341852ee563360a5 Mon Sep 17 00:00:00 2001 From: kub Date: Tue, 14 Nov 2023 23:34:50 +0100 Subject: [PATCH 02/40] build, switch to static miyoo toolchain --- .github/workflows/ci.yml | 5 ++--- tools/release.sh | 11 +++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 58a35a8fe..27f9edc8c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -161,15 +161,14 @@ jobs: runs-on: ubuntu-latest permissions: packages: read - container: miyoocfw/toolchain + container: ghcr.io/irixxxx/toolchain-miyoo steps: - uses: actions/checkout@v3 with: submodules: true - name: build run: | - export CROSS_COMPILE=arm-buildroot-linux-musleabi- - git config --global --add safe.directory /home/picodrive + git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=miyoo make -j2 diff --git a/tools/release.sh b/tools/release.sh index b4e043025..9c9cbcd22 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -12,7 +12,7 @@ # dingux: ghcr.io/irixxxx/toolchain-dingux # retrofw: ghcr.io/irixxxx/toolchain-retrofw # gcw0, rg350: ghcr.io/irixxxx/toolchain-opendingux -# miyoo: miyoocfw/toolchain +# miyoo: ghcr.io/irixxxx/toolchain-miyoo # psp: ghcr.io/pspdev/pspdev # odbeta-gcw0: ghcr.io/irixxxx/toolchain-odbeta-gcw0 # odbeta-lepus: ghcr.io/irixxxx/toolchain-odbeta-lepus @@ -23,7 +23,7 @@ rel=$1 mkdir -p release-$rel shift; plat=" $* " -[ -z "$(echo $plat|tr -d ' ')" ] && plat=" gph dingux retrofw gcw0 rg350 miyoo psp " +[ -z "$(echo $plat|tr -d ' ')" ] && plat=" gph dingux retrofw gcw0 rg350 miyoo psp pandora odbeta-gcw0 odbeta-lepus " [ -z "${plat##* gph *}" ] && { @@ -80,12 +80,11 @@ mv PicoDrive.opk release-$rel/PicoDrive-opendingux_$rel.opk [ -z "${plat##* miyoo *}" ] && { # miyoo: BittBoy >=v1, PocketGo, Powkiddy [QV]90/Q20 (Allwinner F1C100s, ARM926) -docker pull miyoocfw/toolchain -echo " export CROSS_COMPILE=arm-buildroot-linux-musleabi- &&\ - git config --global --add safe.directory /home/picodrive &&\ +docker pull ghcr.io/irixxxx/toolchain-miyoo +echo " git config --global --add safe.directory /home/picodrive &&\ ./configure --platform=miyoo &&\ make clean && make -j2 all "\ - | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm miyoocfw/toolchain sh && + | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-miyoo sh && mv PicoDrive.zip release-$rel/PicoDrive-miyoo_$rel.zip } From f2554438f8bd2e0bc11b05302010338becaa33c0 Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 15 Nov 2023 22:38:10 +0000 Subject: [PATCH 03/40] build, revisions and fixes for opendingux based platforms --- .github/workflows/ci.yml | 4 ++-- Makefile | 1 + configure | 19 +++++++++++-------- platform/common/plat_sdl.c | 2 +- platform/libpicofe | 2 +- platform/opendingux/inputmap.c | 2 +- tools/release.sh | 4 ++-- 7 files changed, 19 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 27f9edc8c..d0beb46b3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -210,7 +210,7 @@ jobs: run: | git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) - ./configure --platform=opendingux + ./configure --platform=gcw0 --platform=odbeta make -j2 mv PicoDrive.opk PicoDrive-odbeta-gcw0-$ver.opk - name: artifacts @@ -230,7 +230,7 @@ jobs: run: | git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) - ./configure --platform=opendingux + ./configure --platform=opendingux --platform=odbeta make -j2 mv PicoDrive.opk PicoDrive-odbeta-lepus-$ver.opk - name: artifacts diff --git a/Makefile b/Makefile index 152e01819..2405a51f1 100644 --- a/Makefile +++ b/Makefile @@ -458,3 +458,4 @@ pico/memory.o pico/cd/memory.o pico/32x/memory.o : pico/memory.h $(shell grep -rl pico_int.h pico) : pico/pico_int.h # pico/cart.o : pico/carthw_cfg.c cpu/fame/famec.o: cpu/fame/famec.c cpu/fame/famec_opcodes.h +platform/common/menu_pico.o: platform/libpicofe/menu.c diff --git a/configure b/configure index 7bbf52a33..12b5a46e3 100755 --- a/configure +++ b/configure @@ -39,7 +39,7 @@ check_define() # "" means "autodetect". # TODO this is annoyingly messy. should have platform and device -platform_list="generic pandora gp2x wiz caanoo dingux retrofw gcw0 rg350 opendingux miyoo rpi1 rpi2 psp rg99" +platform_list="generic pandora gp2x wiz caanoo dingux retrofw gcw0 rg350 opendingux miyoo rpi1 rpi2 psp rg99 odbeta" platform="generic" sound_driver_list="oss alsa sdl" sound_drivers="" @@ -73,6 +73,7 @@ fail() set_platform() { platform=$1 + CFLAGS="$CFLAGS -D__`echo $platform | tr '[a-z]' '[A-Z]'`__" case "$platform" in rpi1) MFLAGS="-mcpu=arm1176jzf-s -mfpu=vfp" @@ -83,6 +84,7 @@ set_platform() have_gles="yes" ;; generic) + MFLAGS="" ;; dingux) # dingoo a320, ritmix rzx-50, the like. all have Ingenic MIPS cpu <= JZ4755 @@ -90,7 +92,6 @@ set_platform() # use static linking since the lib situation is ... let's say vague #LDFLAGS="$LDFLAGS -static" # uses a pre-gcw0 version of opendingux - CFLAGS="$CFLAGS -D__DINGUX__" MFLAGS="-march=mips32 -msoft-float" platform="opendingux" ;; @@ -98,7 +99,6 @@ set_platform() # devices using retrofw. AFAIK all have Ingenic MIPS JZ4760 with fpu sound_drivers="sdl" # uses it's own modified version of opendingux - CFLAGS="$CFLAGS -D__RETROFW__" MFLAGS="-march=mips32" platform="opendingux" ;; @@ -106,22 +106,26 @@ set_platform() # more modern devices using opendingux, with Ingenic MIPS JZ4770 or newer sound_drivers="sdl" # mostly based on opendingux for gcw0, save device type as C define. - CFLAGS="$CFLAGS -D__`echo $platform | tr '[a-z]' '[A-Z]'`__" + CFLAGS="$CFLAGS -D__OPENDINGUX__" MFLAGS="-march=mips32r2" platform="opendingux" ;; + odbeta) + # various devices with opendingux beta, arch flags from toolchain default + MFLAGS="" + platform="opendingux" + ;; rg99) # RG99 using opendingux, with Ingenic MIPS JZ4725B sound_drivers="sdl" # mostly based on opendingux for gcw0, save device type as C define. - CFLAGS="$CFLAGS -D__`echo $platform | tr '[a-z]' '[A-Z]'`__" MFLAGS="-march=mips32" + CFLAGS="$CFLAGS -D__OPENDINGUX__" platform="opendingux" ;; miyoo) # Miyoo BittBoy, PocketGO 1, PowKiddy V90/Q90 with Allwinner F1C100s sound_drivers="sdl" - CFLAGS="$CFLAGS -D__MIYOO__" MFLAGS="-mcpu=arm926ej-s -marm" platform="miyoo" ;; @@ -146,7 +150,6 @@ set_platform() psp) # use newlib SYSLIBS="-lc -lpspuser -lpspkernel" - CFLAGS="$CFLAGS -D__PSP__" MFLAGS="-march=allegrex" ARCH=mipsel ;; @@ -276,7 +279,7 @@ arm*) esac case "$platform" in -rpi1 | rpi2 | generic | opendingux | miyoo) +rpi1 | rpi2 | generic | opendingux | odbeta | miyoo) need_sdl="yes" ;; esac diff --git a/platform/common/plat_sdl.c b/platform/common/plat_sdl.c index 705d4769f..b6b42610c 100644 --- a/platform/common/plat_sdl.c +++ b/platform/common/plat_sdl.c @@ -351,7 +351,7 @@ void plat_init(void) ret = plat_sdl_init(); if (ret != 0) exit(1); -#if defined(__RG350__) || defined(__GCW0__) || defined(__OPENDINGUX__) || defined(__RG99__) +#if defined(__OPENDINGUX__) // opendingux on JZ47x0 may falsely report a HW overlay, fix to window plat_target.vout_method = 0; #endif diff --git a/platform/libpicofe b/platform/libpicofe index 7b58e1563..d5a43fbd9 160000 --- a/platform/libpicofe +++ b/platform/libpicofe @@ -1 +1 @@ -Subproject commit 7b58e15633b54621f9508cb673da61a6b0844955 +Subproject commit d5a43fbd972854cf6f02a47a8ca4ccc1bdadfca8 diff --git a/platform/opendingux/inputmap.c b/platform/opendingux/inputmap.c index 15f1b200b..c6382f30d 100644 --- a/platform/opendingux/inputmap.c +++ b/platform/opendingux/inputmap.c @@ -78,7 +78,7 @@ const char * const _in_sdl_key_names[SDLK_LAST] = { [SDLK_RETURN] = "START", [SDLK_ESCAPE] = "SELECT", -#if defined(__RG350__) || defined(__OPENDINGUX__) || defined(__RG99__) +#if defined(__OPENDINGUX__) [SDLK_HOME] = "POWER", [SDLK_TAB] = "L1", diff --git a/tools/release.sh b/tools/release.sh index 9c9cbcd22..97814a827 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -115,7 +115,7 @@ mv PicoDrive-pandora-$rel release-$rel/ # gcw0 (untested): JZ4770 (mips32r2 with fpu), swapped X/Y buttons docker pull ghcr.io/irixxxx/toolchain-odbeta-gcw0 echo " git config --global --add safe.directory /home/picodrive &&\ - ./configure --platform=gcw0 &&\ + ./configure --platform=gcw0 --platform=odbeta &&\ make clean && make -j2 all "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-odbeta-gcw0 sh && mv PicoDrive.opk release-$rel/PicoDrive-odbeta-gcw0_$rel.opk @@ -125,7 +125,7 @@ mv PicoDrive.opk release-$rel/PicoDrive-odbeta-gcw0_$rel.opk # lepus (untested): JZ4760 (mips32r1 with fpu) docker pull ghcr.io/irixxxx/toolchain-odbeta-lepus echo " git config --global --add safe.directory /home/picodrive &&\ - ./configure --platform=opendingux &&\ + ./configure --platform=opendingux --platform=odbeta &&\ make clean && make -j2 all "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-odbeta-lepus sh && mv PicoDrive.opk release-$rel/PicoDrive-odbeta-lepus_$rel.opk From 4b2223986c32856d0affe27c386ec87e7a906e18 Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Wed, 15 Nov 2023 19:36:26 +0100 Subject: [PATCH 04/40] Use posix functions for PSP --- platform/psp/plat.c | 155 ++++++++++++-------------------------------- platform/psp/psp.c | 1 - 2 files changed, 42 insertions(+), 114 deletions(-) diff --git a/platform/psp/plat.c b/platform/psp/plat.c index cd4df5a60..d15b1b5e3 100644 --- a/platform/psp/plat.c +++ b/platform/psp/plat.c @@ -7,6 +7,9 @@ #include #include #include +#include +#include +#include #include "../common/emu.h" #include "../libpicofe/menu.h" @@ -137,42 +140,61 @@ int plat_get_data_dir(char *dst, int len) /* check if path is a directory */ int plat_is_dir(const char *path) { - SceIoStat st; - int ret = sceIoGetstat(path, &st); - return (ret >= 0 && (st.st_mode & FIO_S_IFDIR)); + DIR *dir; + if ((dir = opendir(path))) { + closedir(dir); + return 1; + } + return 0; } /* current time in ms */ unsigned int plat_get_ticks_ms(void) { + struct timeval tv; + unsigned int ret; + + gettimeofday(&tv, NULL); + + ret = (unsigned)tv.tv_sec * 1000; /* approximate /= 1000 */ - unsigned long long v64; - v64 = (unsigned long long)plat_get_ticks_us() * 4294968; - return v64 >> 32; + ret += ((unsigned)tv.tv_usec * 4195) >> 22; + + return ret; } /* current time in us */ unsigned int plat_get_ticks_us(void) { - return sceKernelGetSystemTimeLow(); + struct timeval tv; + unsigned int ret; + + gettimeofday(&tv, NULL); + + ret = (unsigned)tv.tv_sec * 1000000; + ret += (unsigned)tv.tv_usec; + + return ret; } /* sleep for some time in ms */ void plat_sleep_ms(int ms) { - psp_msleep(ms); + usleep(ms * 1000); } /* sleep for some time in us */ void plat_wait_till_us(unsigned int us_to) { - unsigned int tval; - int diff; + unsigned int now; + + now = plat_get_ticks_us(); - tval = sceKernelGetSystemTimeLow(); - diff = (int)us_to - (int)tval; - if (diff >= 512 && diff < 100*1024) - sceKernelDelayThread(diff); + while ((signed int)(us_to - now) > 512) + { + usleep(1024); + now = plat_get_ticks_us(); + } } /* wait until some event occurs, or timeout */ @@ -237,110 +259,17 @@ struct plat_target plat_target = { // .hwfilters = plat_hwfilters, }; -#ifndef DT_DIR -/* replacement libc stuff */ - -int alphasort(const struct dirent **a, const struct dirent **b) -{ - return strcoll ((*a)->d_name, (*b)->d_name); -} - -int scandir(const char *dir, struct dirent ***namelist_out, - int(*filter)(const struct dirent *), - int(*compar)(const struct dirent **, const struct dirent **)) +int _flush_cache (char *addr, const int size, const int op) { - int ret = -1, dir_uid = -1, name_alloc = 4, name_count = 0; - struct dirent **namelist = NULL, *ent; - SceIoDirent sce_ent; - - namelist = malloc(sizeof(*namelist) * name_alloc); - if (namelist == NULL) { lprintf("%s:%i: OOM\n", __FILE__, __LINE__); goto fail; } - - // try to read first.. - dir_uid = sceIoDopen(dir); - if (dir_uid >= 0) - { - /* it is very important to clear SceIoDirent to be passed to sceIoDread(), */ - /* or else it may crash, probably misinterpreting something in it. */ - memset(&sce_ent, 0, sizeof(sce_ent)); - ret = sceIoDread(dir_uid, &sce_ent); - if (ret < 0) - { - lprintf("sceIoDread(\"%s\") failed with %i\n", dir, ret); - goto fail; - } - } - else - lprintf("sceIoDopen(\"%s\") failed with %i\n", dir, dir_uid); - - while (ret > 0) - { - ent = malloc(sizeof(*ent)); - if (ent == NULL) { lprintf("%s:%i: OOM\n", __FILE__, __LINE__); goto fail; } - ent->d_stat = sce_ent.d_stat; - ent->d_stat.st_attr &= FIO_SO_IFMT; // serves as d_type - strncpy(ent->d_name, sce_ent.d_name, sizeof(ent->d_name)); - ent->d_name[sizeof(ent->d_name)-1] = 0; - if (filter == NULL || filter(ent)) - namelist[name_count++] = ent; - else free(ent); - - if (name_count >= name_alloc) - { - void *tmp; - name_alloc *= 2; - tmp = realloc(namelist, sizeof(*namelist) * name_alloc); - if (tmp == NULL) { lprintf("%s:%i: OOM\n", __FILE__, __LINE__); goto fail; } - namelist = tmp; - } - - memset(&sce_ent, 0, sizeof(sce_ent)); - ret = sceIoDread(dir_uid, &sce_ent); - } - - // sort - if (compar != NULL && name_count > 3) - qsort(&namelist[2], name_count - 2, sizeof(namelist[0]), (int (*)()) compar); - - // all done. - ret = name_count; - *namelist_out = namelist; - goto end; - -fail: - if (namelist != NULL) - { - while (name_count--) - free(namelist[name_count]); - free(namelist); - } -end: - if (dir_uid >= 0) sceIoDclose(dir_uid); - return ret; + //sceKernelDcacheWritebackAll(); + sceKernelDcacheWritebackRange(addr, size); + sceKernelIcacheInvalidateRange(addr, size); + return 0; } -/* stubs for libflac (embedded in libchdr) */ -#include - -int chown(const char *pathname, uid_t owner, gid_t group) { return -1; } -int chmod(const char *pathname, mode_t mode) { return -1; } -int utime(const char *filename, const struct utimbuf *times) { return -1; } -#endif - -#include -#include - int posix_memalign(void **p, size_t align, size_t size) { if (p) *p = memalign(align, size); return (p ? *p ? 0 : ENOMEM : EINVAL); -} - -int _flush_cache (char *addr, const int size, const int op) -{ - //sceKernelDcacheWritebackAll(); - sceKernelDcacheWritebackRange(addr, size); - sceKernelIcacheInvalidateRange(addr, size); - return 0; -} +} \ No newline at end of file diff --git a/platform/psp/psp.c b/platform/psp/psp.c index 4e884879d..e719e4695 100644 --- a/platform/psp/psp.c +++ b/platform/psp/psp.c @@ -31,7 +31,6 @@ extern int pico_main(int argc, char *argv[]); #ifndef FW15 PSP_MODULE_INFO("PicoDrive", 0, 1, 97); -PSP_HEAP_SIZE_MAX(); int main(int argc, char *argv[]) { return pico_main(argc, argv); } /* just a wrapper */ From a20af2f935d0c63a182caa99075e0bfc02d103bb Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Wed, 15 Nov 2023 20:05:05 +0100 Subject: [PATCH 05/40] Clean-up makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2405a51f1..e39cd8e7d 100644 --- a/Makefile +++ b/Makefile @@ -236,7 +236,7 @@ endif ifeq "$(PLATFORM)" "psp" CFLAGS += -DUSE_BGR565 -G8 # -DLPRINTF_STDIO -DFW15 LDLIBS += -lpspgu -lpspge -lpsppower -lpspaudio -lpspdisplay -lpspaudiocodec -LDLIBS += -lpsprtc -lpspctrl -lpspsdk -lc -lpspnet_inet -lpspuser -lpspkernel +LDLIBS += -lpspctrl platform/common/main.o: CFLAGS += -Dmain=pico_main OBJS += platform/psp/plat.o OBJS += platform/psp/emu.o From 250c8ffbc0d8796ecaa0aeb6a43b15ec58ca9b97 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 16 Nov 2023 22:53:05 +0200 Subject: [PATCH 06/40] build, revisions and fixes for opendingux based platforms --- .github/workflows/ci.yml | 2 +- Makefile | 25 ++++++------------- configure | 21 ++++++++-------- .../opendingux/data/default.lepus.desktop | 9 +++++++ platform/opendingux/inputmap.c | 23 ++++++++--------- platform/psp/plat.c | 2 +- tools/release.sh | 6 ++--- 7 files changed, 44 insertions(+), 44 deletions(-) create mode 100644 platform/opendingux/data/default.lepus.desktop diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0beb46b3..61fc10ae7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -172,7 +172,7 @@ jobs: ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=miyoo make -j2 - mv PicoDrive.zip PicoDrive-miyoo-$ver.zip + mv PicoDrive-miyoo.zip PicoDrive-miyoo-$ver.zip - name: artifacts uses: actions/upload-artifact@v3 with: diff --git a/Makefile b/Makefile index e39cd8e7d..1120f8bb4 100644 --- a/Makefile +++ b/Makefile @@ -59,7 +59,7 @@ endif chkCCflag = $(shell n=/dev/null; echo $(1) | tr " " "\n" | while read f; do \ $(CC) $$f -x c -c $$n -o $$n 2>$$n && echo "_$$f" | tr -d _; done) -ifeq ("$(PLATFORM)",$(filter "$(PLATFORM)","gp2x" "opendingux" "miyoo" "rpi1")) +ifeq ("$(PLATFORM)",$(filter "$(PLATFORM)","gp2x" "opendingux" "rpi1")) # very small caches, avoid optimization options making the binary much bigger CFLAGS += -fno-common -finline-limit=42 -fno-unroll-loops -ffast-math CFLAGS += $(call chkCCflag, -fno-stack-protector) @@ -136,11 +136,18 @@ $(TARGET)-dge.zip: .od_data all: $(TARGET)-dge.zip CFLAGS += -DSDL_SURFACE_SW # some legacy dinguces had bugs in HWSURFACE else +ifneq (,$(filter %__MIYOO__, $(CFLAGS))) +$(TARGET)-miyoo.zip: .od_data + rm -f .od_data/default.*.desktop .od_data/PicoDrive.dge + cd .od_data && zip -9 -r ../$@ * +all: $(TARGET)-miyoo.zip +else $(TARGET).opk: .od_data rm -f .od_data/PicoDrive.dge mksquashfs .od_data $@ -all-root -noappend -no-exports -no-xattrs all: $(TARGET).opk endif +endif ifneq (,$(filter %mips32r2, $(CFLAGS))) CFLAGS += -DMIPS_USE_SYNCI # mips32r2 clear_cache uses SYNCI instead of a syscall @@ -152,22 +159,6 @@ use_inputmap ?= 1 # OpenDingux is a generic platform, really. PLATFORM := generic endif -ifeq "$(PLATFORM)" "miyoo" -$(TARGET).zip: $(TARGET) - $(RM) -rf .od_data - mkdir .od_data - cp -r platform/opendingux/data/. .od_data - cp platform/game_def.cfg .od_data - cp $< .od_data/PicoDrive - $(STRIP) .od_data/PicoDrive - rm -f .od_data/default.*.desktop .od_data/PicoDrive.dge - cd .od_data && zip -9 -r ../$@ * -all: $(TARGET).zip - -OBJS += platform/opendingux/inputmap.o -use_inputmap ?= 1 -PLATFORM := generic -endif ifeq ("$(PLATFORM)",$(filter "$(PLATFORM)","rpi1" "rpi2")) CFLAGS += -DHAVE_GLES -DRASPBERRY CFLAGS += -I/opt/vc/include/ -I/opt/vc/include/interface/vcos/pthreads/ -I/opt/vc/include/interface/vmcs_host/linux/ diff --git a/configure b/configure index 12b5a46e3..aede72159 100755 --- a/configure +++ b/configure @@ -105,29 +105,29 @@ set_platform() opendingux | gcw0 | rg350) # more modern devices using opendingux, with Ingenic MIPS JZ4770 or newer sound_drivers="sdl" - # mostly based on opendingux for gcw0, save device type as C define. + # mostly based on opendingux for gcw0 CFLAGS="$CFLAGS -D__OPENDINGUX__" MFLAGS="-march=mips32r2" platform="opendingux" ;; - odbeta) - # various devices with opendingux beta, arch flags from toolchain default - MFLAGS="" - platform="opendingux" - ;; rg99) # RG99 using opendingux, with Ingenic MIPS JZ4725B sound_drivers="sdl" - # mostly based on opendingux for gcw0, save device type as C define. - MFLAGS="-march=mips32" CFLAGS="$CFLAGS -D__OPENDINGUX__" + MFLAGS="-march=mips32" platform="opendingux" ;; miyoo) # Miyoo BittBoy, PocketGO 1, PowKiddy V90/Q90 with Allwinner F1C100s sound_drivers="sdl" + CFLAGS="$CFLAGS -D__OPENDINGUX__" MFLAGS="-mcpu=arm926ej-s -marm" - platform="miyoo" + platform="opendingux" + ;; + odbeta) + # various devices with opendingux beta, arch flags from toolchain default + MFLAGS="" + platform="opendingux" ;; pandora) sound_drivers="oss alsa" @@ -279,7 +279,7 @@ arm*) esac case "$platform" in -rpi1 | rpi2 | generic | opendingux | odbeta | miyoo) +rpi1 | rpi2 | generic | opendingux) need_sdl="yes" ;; esac @@ -363,6 +363,7 @@ test -n "$SDL_CONFIG" || SDL_CONFIG="$(ls $SYSROOT/*/*bin*/sdl-config 2>/dev/nul #test -n "$SDL_CONFIG" || SDL_CONFIG="$(ls $SYSROOT/*bin*/sdl2-config 2>/dev/null | grep /bin/sdl2-config | head -n 1)" #test -n "$SDL_CONFIG" || SDL_CONFIG="$(ls $SYSROOT/*/*bin*/sdl2-config 2>/dev/null | grep /bin/sdl2-config | head -n 1)" SDLVERSION=sdl && echo $SDL_CONFIG | grep -q sdl2 && SDLVERSION=sdl2 +test -n "$SDL_CONFIG" || SDL_CONFIG=false MAIN_LDLIBS="$LDLIBS -lm" diff --git a/platform/opendingux/data/default.lepus.desktop b/platform/opendingux/data/default.lepus.desktop new file mode 100644 index 000000000..857f932f8 --- /dev/null +++ b/platform/opendingux/data/default.lepus.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Type=Application +Name=Picodrive +Comment=A mega drive/genesis emulator +Exec=PicoDrive %f +Icon=megadrive +Terminal=false +Categories=emulators; +MimeType=.md;.smd;.gen;.bin;.sms;.gg;.sg;.cue;.chd;.cso;.iso;.32x;.pco;.zip diff --git a/platform/opendingux/inputmap.c b/platform/opendingux/inputmap.c index c6382f30d..a8af36b2f 100644 --- a/platform/opendingux/inputmap.c +++ b/platform/opendingux/inputmap.c @@ -78,26 +78,25 @@ const char * const _in_sdl_key_names[SDLK_LAST] = { [SDLK_RETURN] = "START", [SDLK_ESCAPE] = "SELECT", -#if defined(__OPENDINGUX__) - [SDLK_HOME] = "POWER", - - [SDLK_TAB] = "L1", - [SDLK_BACKSPACE] = "R1", - [SDLK_PAGEUP] = "L2", - [SDLK_PAGEDOWN] = "R2", - [SDLK_KP_DIVIDE] = "L3", - [SDLK_KP_PERIOD] = "R3", -#elif defined(__MIYOO__) +#if defined(__MIYOO__) [SDLK_TAB] = "L1", [SDLK_BACKSPACE] = "R1", [SDLK_RALT] = "L2", [SDLK_RSHIFT] = "R2", - [SDLK_RCTRL] = "R", -#else + [SDLK_RCTRL] = "RESET", +#elif defined(__GCW0__) || defined(__DINGUX__) || defined(__RETROFW__) [SDLK_TAB] = "L", [SDLK_BACKSPACE] = "R", [SDLK_POWER] = "POWER", [SDLK_PAUSE] = "LOCK", +#else + [SDLK_TAB] = "L1", + [SDLK_BACKSPACE] = "R1", + [SDLK_PAGEUP] = "L2", + [SDLK_PAGEDOWN] = "R2", + [SDLK_KP_DIVIDE] = "L3", + [SDLK_KP_PERIOD] = "R3", + [SDLK_HOME] = "POWER", #endif }; const char * const (*in_sdl_key_names)[SDLK_LAST] = &_in_sdl_key_names; diff --git a/platform/psp/plat.c b/platform/psp/plat.c index d15b1b5e3..0232b1d0d 100644 --- a/platform/psp/plat.c +++ b/platform/psp/plat.c @@ -272,4 +272,4 @@ int posix_memalign(void **p, size_t align, size_t size) if (p) *p = memalign(align, size); return (p ? *p ? 0 : ENOMEM : EINVAL); -} \ No newline at end of file +} diff --git a/tools/release.sh b/tools/release.sh index 97814a827..eb0930961 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -72,7 +72,7 @@ mv PicoDrive.opk release-$rel/PicoDrive-gcw0_$rel.opk # rg350, gkd350h etc: JZ4770 or newer docker pull ghcr.io/irixxxx/toolchain-opendingux echo " git config --global --add safe.directory /home/picodrive &&\ - ./configure --platform=opendingux &&\ + ./configure --platform=rg350 &&\ make clean && make -j2 all "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-opendingux sh && mv PicoDrive.opk release-$rel/PicoDrive-opendingux_$rel.opk @@ -85,7 +85,7 @@ echo " git config --global --add safe.directory /home/picodrive &&\ ./configure --platform=miyoo &&\ make clean && make -j2 all "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-miyoo sh && -mv PicoDrive.zip release-$rel/PicoDrive-miyoo_$rel.zip +mv PicoDrive-miyoo.zip release-$rel/PicoDrive-miyoo_$rel.zip } [ -z "${plat##* psp *}" ] && { @@ -122,7 +122,7 @@ mv PicoDrive.opk release-$rel/PicoDrive-odbeta-gcw0_$rel.opk } [ -z "${plat##* odbeta-lepus *}" ] && { -# lepus (untested): JZ4760 (mips32r1 with fpu) +# rg300 and other ingenic lepus based (untested): JZ4760 (mips32r1 with fpu) docker pull ghcr.io/irixxxx/toolchain-odbeta-lepus echo " git config --global --add safe.directory /home/picodrive &&\ ./configure --platform=opendingux --platform=odbeta &&\ From 43ef4071dac81b19cdb8fbfa5866806ccedf882c Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 23 Nov 2023 20:50:25 +0100 Subject: [PATCH 07/40] sound, faster resampler for SMS FM --- pico/pico_int.h | 1 + pico/sms.c | 1 + pico/sound/sound.c | 103 ++++++++++++++++++++++++++++----------------- 3 files changed, 67 insertions(+), 38 deletions(-) diff --git a/pico/pico_int.h b/pico/pico_int.h index b8e788e4c..e74a4ac21 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -346,6 +346,7 @@ struct PicoMisc #define PMS_HW_LCD 0x2 // GG LCD #define PMS_HW_JAP 0x4 // japanese system #define PMS_HW_FM 0x8 // FM sound +#define PMS_HW_FMUSED 0x10 // FM sound accessed #define PMS_MAP_AUTO 0 #define PMS_MAP_SEGA 1 diff --git a/pico/sms.c b/pico/sms.c index 52a36b3d7..398a4da3c 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -221,6 +221,7 @@ static void z80_sms_out(unsigned short a, unsigned char d) { case 0xf0: // FM reg port + Pico.m.hardware |= PMS_HW_FMUSED; YM2413_regWrite(d); break; case 0xf1: diff --git a/pico/sound/sound.c b/pico/sound/sound.c index 9c7a92891..c31c2cf4c 100644 --- a/pico/sound/sound.c +++ b/pico/sound/sound.c @@ -27,8 +27,11 @@ s16 cdda_out_buffer[2*1152]; // sn76496 extern int *sn76496_regs; +// FM resampling polyphase FIR +static resampler_t *fmresampler; +static int (*PsndFMUpdate)(s32 *buffer, int length, int stereo, int is_buf_empty); + // ym2413 -#define YM2413_CLK 3579545 static OPLL *opll = NULL; static OPLL old_opll; static struct { @@ -36,6 +39,14 @@ static struct { uint8_t reg[sizeof(opll->reg)]; } opll_buf; + +void YM2413_regWrite(unsigned data){ + OPLL_writeIO(opll,0,data); +} +void YM2413_dataWrite(unsigned data){ + OPLL_writeIO(opll,1,data); +} + PICO_INTERNAL void *YM2413GetRegs(void) { memcpy(opll_buf.reg, opll->reg, sizeof(opll->reg)); @@ -54,12 +65,9 @@ PICO_INTERNAL void YM2413UnpackState(void) opll->adr = opll_buf.adr; } -static resampler_t *fmresampler; -static int (*PsndFMUpdate)(s32 *buffer, int length, int stereo, int is_buf_empty); - PICO_INTERNAL void PsndInit(void) { - opll = OPLL_new(YM2413_CLK, PicoIn.sndRate); + opll = OPLL_new(OSC_NTSC/15, OSC_NTSC/15/72); OPLL_setChipType(opll,0); OPLL_reset(opll); } @@ -95,7 +103,25 @@ static int YM2612UpdateFIR(s32 *buffer, int length, int stereo, int is_buf_empty return ymchans; } -static void YM2612_setup_FIR(int inrate, int outrate, int stereo) +// resample SMS FM from its native 49716Hz/49262Hz with polyphase FIR filter +static void YM2413Update(s32 *buffer, int length, int stereo) +{ + while (length-- > 0) { + int16_t getdata = OPLL_calc(opll) * 3; + *buffer++ = getdata; + buffer += stereo; // only left for stereo, to be mixed to right later + } +} + +static int YM2413UpdateFIR(s32 *buffer, int length, int stereo, int is_buf_empty) +{ + if (!is_buf_empty) memset(buffer, 0, (length << stereo) * sizeof(*buffer)); + resampler_update(fmresampler, buffer, length, YM2413Update); + return 0; +} + +// FIR setup, looks for a close enough rational number matching the ratio +static void YMFM_setup_FIR(int inrate, int outrate, int stereo) { int mindiff = 999; int diff, mul, div; @@ -132,21 +158,31 @@ void PsndRerate(int preserve_state) void *state = NULL; int target_fps = Pico.m.pal ? 50 : 60; int target_lines = Pico.m.pal ? 313 : 262; + int sms_clock = Pico.m.pal ? OSC_PAL/15 : OSC_NTSC/15; int ym2612_clock = Pico.m.pal ? OSC_PAL/7 : OSC_NTSC/7; int ym2612_rate = YM2612_NATIVE_RATE(); + int ym2413_rate = (sms_clock + 36) / 72; if (preserve_state) { state = malloc(0x204); if (state == NULL) return; ym2612_pack_state(); memcpy(state, YM2612GetRegs(), 0x204); + + if (opll != NULL) + memcpy(&old_opll, opll, sizeof(OPLL)); // remember old state } - if ((PicoIn.opt & POPT_EN_FM_FILTER) && ym2612_rate != PicoIn.sndRate) { + if (PicoIn.AHW & PAHW_SMS) { + OPLL_setRate(opll, ym2413_rate); + OPLL_reset(opll); + YMFM_setup_FIR(ym2413_rate, PicoIn.sndRate, 0); + PsndFMUpdate = YM2413UpdateFIR; + } else if ((PicoIn.opt & POPT_EN_FM_FILTER) && ym2612_rate != PicoIn.sndRate) { // polyphase FIR resampler, resampling directly from native to output rate YM2612Init(ym2612_clock, ym2612_rate, ((PicoIn.opt&POPT_DIS_FM_SSGEG) ? 0 : ST_SSG) | ((PicoIn.opt&POPT_EN_FM_DAC) ? ST_DAC : 0)); - YM2612_setup_FIR(ym2612_rate, PicoIn.sndRate, PicoIn.opt & POPT_EN_STEREO); + YMFM_setup_FIR(ym2612_rate, PicoIn.sndRate, PicoIn.opt & POPT_EN_STEREO); PsndFMUpdate = YM2612UpdateFIR; } else { YM2612Init(ym2612_clock, PicoIn.sndRate, @@ -158,20 +194,17 @@ void PsndRerate(int preserve_state) // feed it back it's own registers, just like after loading state memcpy(YM2612GetRegs(), state, 0x204); ym2612_unpack_state(); + + if (opll != NULL) { + memcpy(&opll->adr, &old_opll.adr, sizeof(OPLL)-20); // restore old state + OPLL_forceRefresh(opll); + } } if (preserve_state) memcpy(state, sn76496_regs, 28*4); // remember old state SN76496_init(Pico.m.pal ? OSC_PAL/15 : OSC_NTSC/15, PicoIn.sndRate); if (preserve_state) memcpy(sn76496_regs, state, 28*4); // restore old state - if(opll != NULL){ - if (preserve_state) memcpy(&old_opll, opll, sizeof(OPLL)); // remember old state - OPLL_setRate(opll, PicoIn.sndRate); - OPLL_reset(opll); - if (preserve_state) memcpy(&opll->adr, &old_opll.adr, sizeof(OPLL)-20); // restore old state - OPLL_forceRefresh(opll); - } - if (state) free(state); @@ -284,12 +317,12 @@ PICO_INTERNAL void PsndDoPSG(int cyc_to) SN76496Update(PicoIn.sndOut + pos, len, stereo); } -#if 0 -PICO_INTERNAL void PsndDoYM2413(int cyc_to) +PICO_INTERNAL void PsndDoSMSFM(int cyc_to) { int pos, len; int stereo = 0; - s16 *buf; + s32 *buf32 = PsndBuffer; + s16 *buf = PicoIn.sndOut; // nothing to do if sound is off if (!PicoIn.sndOut) return; @@ -312,22 +345,15 @@ PICO_INTERNAL void PsndDoYM2413(int cyc_to) pos <<= 1; } - buf = PicoIn.sndOut + pos; - while (len-- > 0) { - int16_t getdata = OPLL_calc(opll) * 3; - *buf++ += getdata; - buf += stereo; // only left for stereo, to be mixed to right later + if (Pico.m.hardware & PMS_HW_FMUSED) { + buf += pos; + PsndFMUpdate(buf32, len, 0, 0); + while (len--) { + *buf++ += *buf32++; + buf += stereo; + } } } -#endif - -void YM2413_regWrite(unsigned data){ - OPLL_writeIO(opll,0,data); -} -void YM2413_dataWrite(unsigned data){ - OPLL_writeIO(opll,1,data); -} - PICO_INTERNAL void PsndDoFM(int cyc_to) { @@ -515,6 +541,7 @@ PICO_INTERNAL void PsndGetSamples(int y) static int PsndRenderMS(int offset, int length) { + s32 *buf32 = PsndBuffer; int stereo = (PicoIn.opt & 8) >> 3; int psglen = ((Pico.snd.psg_pos+0x80000) >> 20); int ym2413len = ((Pico.snd.ym2413_pos+0x80000) >> 20); @@ -536,11 +563,11 @@ static int PsndRenderMS(int offset, int length) s16 *ym2413buf = PicoIn.sndOut + (ym2413len << stereo); Pico.snd.ym2413_pos += (length-ym2413len) << 20; int len = (length-ym2413len); - if (PicoIn.opt & POPT_EN_YM2413){ - while (len-- > 0) { - int16_t getdata = OPLL_calc(opll) * 3; - *ym2413buf += getdata; - ym2413buf += 1< Date: Thu, 23 Nov 2023 20:55:14 +0100 Subject: [PATCH 08/40] build, update psp toolchain container --- .github/workflows/ci.yml | 2 +- tools/release.sh | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 61fc10ae7..b8192a5c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,7 +72,7 @@ jobs: build-psp: runs-on: ubuntu-latest - container: ghcr.io/pspdev/pspdev + container: pspdev/pspdev steps: - name: build environment run: | diff --git a/tools/release.sh b/tools/release.sh index eb0930961..83f807fae 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -13,7 +13,7 @@ # retrofw: ghcr.io/irixxxx/toolchain-retrofw # gcw0, rg350: ghcr.io/irixxxx/toolchain-opendingux # miyoo: ghcr.io/irixxxx/toolchain-miyoo -# psp: ghcr.io/pspdev/pspdev +# psp: docker.io/pspdev/pspdev # odbeta-gcw0: ghcr.io/irixxxx/toolchain-odbeta-gcw0 # odbeta-lepus: ghcr.io/irixxxx/toolchain-odbeta-lepus @@ -90,13 +90,13 @@ mv PicoDrive-miyoo.zip release-$rel/PicoDrive-miyoo_$rel.zip [ -z "${plat##* psp *}" ] && { # psp (experimental), pspdev SDK toolchain -docker pull --platform=linux/amd64 ghcr.io/pspdev/pspdev +docker pull --platform=linux/amd64 pspdev/pspdev echo " apk add git gcc g++ zip && export CROSS_COMPILE=psp- &&\ git config --global --add safe.directory /home/picodrive &&\ ./configure --platform=psp &&\ make clean && make -j2 all &&\ make -C platform/psp rel VER=$rel "\ - | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/pspdev/pspdev sh && + | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm pspdev/pspdev sh && mv PicoDrive_psp_$rel.zip release-$rel/PicoDrive-psp_$rel.zip } From 96a972dcecac663fafb40564a75d209e261afa72 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 23 Nov 2023 20:56:47 +0100 Subject: [PATCH 09/40] core, fix H32 mode in fast renderer --- pico/draw2.c | 14 +++++++------- pico/draw2_arm.S | 4 ++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/pico/draw2.c b/pico/draw2.c index 952c13ed8..4882af146 100644 --- a/pico/draw2.c +++ b/pico/draw2.c @@ -168,7 +168,7 @@ static void DrawWindowFull(int start, int end, int prio, struct PicoEState *est) end = end<<16>>16; // Find name table line: - if (pvid->reg[12]&1) + if (!(est->rendstatus & PDRAW_32_COLS)) { nametab=(pvid->reg[3]&0x3c)<<9; // 40-cell mode nametab_step = 1<<6; @@ -268,7 +268,7 @@ static void DrawLayerFull(int plane, u32 *hcache, int planestart, int planeend, else nametab=(pvid->reg[4]&0x07)<<12; // B scrpos = est->Draw2FB; - if (est->rendstatus & PDRAW_BORDER_32) + if ((~est->rendstatus & (PDRAW_BORDER_32|PDRAW_32_COLS)) == 0) scrpos += 32; scrpos+=8*est->Draw2Width*(planestart-scrstart); @@ -280,7 +280,7 @@ static void DrawLayerFull(int plane, u32 *hcache, int planestart, int planeend, // Get vertical scroll value: vscroll=PicoMem.vsram[plane];//&0x1ff; #if VSRAM - if (!(pvid->reg[12]&1) && (pvid->reg[11]&4)) // H32 + 2-cell mode + if ((est->rendstatus & PDRAW_32_COLS) && (pvid->reg[11]&4)) // H32 + 2-cell mode vscroll=PicoMem.vsram[plane+0x20];//&0x1ff; #endif #if INTERLACE @@ -371,7 +371,7 @@ static void DrawTilesFromCacheF(u32 *hc, struct PicoEState *est) unsigned char *scrpos = est->Draw2FB, *pd = 0; int scrstart = est->Draw2Start; - if (est->rendstatus & PDRAW_BORDER_32) + if ((~est->rendstatus & (PDRAW_BORDER_32|PDRAW_32_COLS)) == 0) scrpos += 32; while((code=*hc++)) { @@ -446,7 +446,7 @@ static void DrawSpriteFull(u32 *sprite, struct PicoEState *est) while(sy <= 0) { sy+=8; tile+=tdeltay; height--; } scrpos = est->Draw2FB; - if (est->rendstatus&PDRAW_BORDER_32) + if ((~est->rendstatus & (PDRAW_BORDER_32|PDRAW_32_COLS)) == 0) scrpos += 32; scrpos+=sy*est->Draw2Width; @@ -489,13 +489,13 @@ static void DrawAllSpritesFull(int prio, int maxwidth, struct PicoEState *est) int i,u,link=0; u32 *sprites[80]; // Sprites int y_min=START_ROW*8, y_max=END_ROW*8; // for a simple sprite masking - int max_sprites = pvid->reg[12]&1 ? 80 : 64; + int max_sprites = !(est->rendstatus & PDRAW_32_COLS) ? 80 : 64; if (est->rendstatus & PDRAW_30_ROWS) y_min += 8, y_max += 8; table=pvid->reg[5]&0x7f; - if (pvid->reg[12]&1) table&=0x7e; // Lowest bit 0 in 40-cell mode + if (!(est->rendstatus & PDRAW_32_COLS)) table&=0x7e; // Lowest bit 0 in 40-cell mode table<<=8; // Get sprite table address/2 for (i = u = 0; u < max_sprites && link < max_sprites; u++) diff --git a/pico/draw2_arm.S b/pico/draw2_arm.S index 3101a8235..c926ce6a2 100644 --- a/pico/draw2_arm.S +++ b/pico/draw2_arm.S @@ -428,6 +428,7 @@ DrawLayerFull: ldr r11, [r11, #OFS_EST_Draw2FB] sub r4, r9, r4, lsl #24 tst r7, #PDRAW_BORDER_32 @ H32 border mode? + tstne r7, #PDRAW_32_COLS addne r11, r11, #32 mov r4, r4, asr #24 mov r7, #328*8 @@ -609,6 +610,7 @@ DrawTilesFromCacheF: ldr r11,[r1, #OFS_EST_Draw2Start] ldr r2, [r0], #4 @ read y offset tst r7, #PDRAW_BORDER_32 @ H32 border mode? + tstne r7, #PDRAW_32_COLS addne r4, r4, #32 mov r7, #328 mla r2, r7, r2, r4 @@ -717,6 +719,7 @@ DrawWindowFull: and r12, r12, #0xf800 mov r5, r5, lsl #6 @ nametab_step tst r7, #PDRAW_BORDER_32 + tstne r7, #PDRAW_32_COLS addne r11, r11, #32 @ center screen in H32 mode 0: and r4, r0, #0xff @@ -945,6 +948,7 @@ DrawSpriteFull: ldr r2, [r1, #OFS_EST_Draw2Start] ldr r10, [r1, #OFS_EST_PicoMem_vram] tst r0, #PDRAW_BORDER_32 @ H32 border mode? + tstne r0, #PDRAW_32_COLS addne r11, r11, #32 sub r12, r12, r2, lsl #3 mov r0, #328 From 48fc9762de700ffce656edcf9883147f66a51916 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 23 Nov 2023 21:00:56 +0100 Subject: [PATCH 10/40] psp, fix GU hardware rendering --- platform/psp/emu.c | 168 ++++++++++++++++++++++---------------------- platform/psp/emu.h | 2 + platform/psp/plat.c | 23 +++++- platform/psp/psp.c | 6 +- 4 files changed, 111 insertions(+), 88 deletions(-) diff --git a/platform/psp/emu.c b/platform/psp/emu.c index 18eb388b7..a1c44cae6 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "psp.h" #include "emu.h" @@ -48,7 +49,9 @@ static struct Vertex __attribute__((aligned(4))) g_vertices[2]; static u16 __attribute__((aligned(16))) localPal[0x100]; static int need_pal_upload = 0; -static u16 __attribute__((aligned(16))) osd_buf[512*8]; // buffer for osd text +u16 __attribute__((aligned(16))) osd_buf[512*8]; // buffer for osd text +int osd_buf_x[4], osd_buf_l[4]; // store for x and length for blitting +int osd_buf_cnt, osd_cdleds; static int out_x, out_y; static int out_w, out_h; @@ -105,6 +108,7 @@ static void change_renderer(int diff) static void apply_renderer(void) { PicoIn.opt &= ~(POPT_ALT_RENDERER|POPT_EN_SOFTSCALE); + PicoIn.opt |= POPT_DIS_32C_BORDER; switch (get_renderer()) { case RT_16BIT: @@ -120,32 +124,6 @@ static void apply_renderer(void) } } -static void osd_text(int x, const char *text) -{ - struct Vertex* vx; - int len = strlen(text) * 8 / 2; - int *p, h; - void *tmp = g_screen_ptr; - - g_screen_ptr = osd_buf; - for (h = 0; h < 8; h++) { - p = (int *) (osd_buf+x+512*h); - p = (int *) ((int)p & ~3); // align - memset32_uncached(p, 0, len); - } - emu_text_out16(x, 0, text); - g_screen_ptr = tmp; - - vx = (struct Vertex*)sceGuGetMemory(2 * sizeof(struct Vertex)); - vx[0].u = x, vx[0].v = 0; - vx[1].u = x + len*2, vx[1].v = 8; - vx[0].x = x, vx[0].y = 264; - vx[1].x = x + len*2, vx[1].y = 272; - sceGuTexMode(GU_PSM_5650,0,0,0); - sceGuTexImage(0,512,8,512,osd_buf); - sceGuDrawArray(GU_SPRITES,GU_TEXTURE_16BIT|GU_VERTEX_16BIT|GU_TRANSFORM_2D,2,0,vx); -} - static void set_scaling_params(void) { @@ -276,7 +254,79 @@ static void do_pal_update(void) need_pal_upload = 1; } -static void blitscreen_clut(void) +static void osd_text(int x, const char *text) +{ + int len = strlen(text) * 8; + int *p, h; + void *tmp = g_screen_ptr; + + g_screen_ptr = osd_buf; + for (h = 0; h < 8; h++) { + p = (int *) (osd_buf+x+512*h); + p = (int *) ((int)p & ~3); // align + memset32_uncached(p, 0, len/2); + } + emu_text_out16(x, 0, text); + g_screen_ptr = tmp; + + osd_buf_x[osd_buf_cnt] = x; + osd_buf_l[osd_buf_cnt] = len; + osd_buf_cnt ++; +} + +static void blit_osd(void) +{ + struct Vertex* vx; + int x, len; + + while (osd_buf_cnt > 0) { + osd_buf_cnt --; + x = osd_buf_x[osd_buf_cnt]; + len = osd_buf_l[osd_buf_cnt]; + vx = (struct Vertex*)sceGuGetMemory(2 * sizeof(struct Vertex)); + vx[0].u = x, vx[0].v = 0; + vx[1].u = x + len, vx[1].v = 8; + vx[0].x = x, vx[0].y = 264; + vx[1].x = x + len, vx[1].y = 272; + sceGuTexMode(GU_PSM_5650,0,0,0); + sceGuTexImage(0,512,8,512,osd_buf); + sceGuDrawArray(GU_SPRITES,GU_TEXTURE_16BIT|GU_VERTEX_16BIT|GU_TRANSFORM_2D,2,0,vx); + } +} + +static void cd_leds(void) +{ + unsigned int reg, col_g, col_r, *p; + + reg = Pico_mcd->s68k_regs[0]; + + p = (unsigned int *)((short *)osd_buf + 512*2+498); + col_g = (reg & 2) ? 0x06000600 : 0; + col_r = (reg & 1) ? 0x00180018 : 0; + *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 512/2 - 12/2; + *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 512/2 - 12/2; + *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; + + osd_cdleds = 1; +} + +static void blit_cdleds(void) +{ + struct Vertex* vx; + + if (!osd_cdleds) return; + + vx = (struct Vertex*)sceGuGetMemory(2 * sizeof(struct Vertex)); + vx[0].u = 497, vx[0].v = 1; + vx[1].u = 497+14, vx[1].v = 6; + vx[0].x = 4, vx[0].y = 1; + vx[1].x = 4+14, vx[1].y = 6; + sceGuTexMode(GU_PSM_5650,0,0,0); + sceGuTexImage(0,512,8,512,osd_buf); + sceGuDrawArray(GU_SPRITES,GU_TEXTURE_16BIT|GU_VERTEX_16BIT|GU_TRANSFORM_2D,2,0,vx); +} + +void blitscreen_clut(void) { sceGuTexMode(is_16bit_mode() ? GU_PSM_5650:GU_PSM_T8,0,0,0); sceGuTexImage(0,512,512,512,g_screen_ptr); @@ -314,33 +364,12 @@ static void blitscreen_clut(void) else #endif sceGuDrawArray(GU_SPRITES,GU_TEXTURE_16BIT|GU_VERTEX_16BIT|GU_TRANSFORM_2D,2,0,g_vertices); -} - - -static void cd_leds(void) -{ - struct Vertex* vx; - unsigned int reg, col_g, col_r, *p; - - reg = Pico_mcd->s68k_regs[0]; - - p = (unsigned int *)((short *)osd_buf + 512*2+498); - col_g = (reg & 2) ? 0x06000600 : 0; - col_r = (reg & 1) ? 0x00180018 : 0; - *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 512/2 - 12/2; - *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += 512/2 - 12/2; - *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; - vx = (struct Vertex*)sceGuGetMemory(2 * sizeof(struct Vertex)); - vx[0].u = 497, vx[0].v = 1; - vx[1].u = 497+14, vx[1].v = 6; - vx[0].x = 4, vx[0].y = 1; - vx[1].x = 4+14, vx[1].y = 6; - sceGuTexMode(GU_PSM_5650,0,0,0); - sceGuTexImage(0,512,8,512,osd_buf); - sceGuDrawArray(GU_SPRITES,GU_TEXTURE_16BIT|GU_VERTEX_16BIT|GU_TRANSFORM_2D,2,0,vx); + blit_osd(); + blit_cdleds(); } + static void draw_pico_ptr(void) { unsigned char *p = (unsigned char *)g_screen_ptr + 8; @@ -359,23 +388,6 @@ static void draw_pico_ptr(void) } -// clears whole screen or just the notice area (in all buffers) -static void clearArea(int full) -{ - void *fb = psp_video_get_active_fb(); - - if (full) { - u32 val = (is_16bit_mode() ? 0x00000000 : 0xe0e0e0e0); - long sz = 512*272*2; - memset32_uncached(psp_screen, 0, 512*272*2/4); // frame buffer - memset32_uncached(fb, 0, 512*272*2/4); // frame buff on display - memset32(VRAM_CACHED_STUFF, val, 2*sz/4); // 2 draw buffers - } else { - memset32_uncached((int *)((char *)psp_screen + 512*264*2), 0, 512*8*2/4); - memset32_uncached((int *)((char *)fb + 512*264*2), 0, 512*8*2/4); - } -} - static void vidResetMode(void) { // setup GU @@ -614,25 +626,19 @@ void pemu_validate_config(void) void pemu_finalize_frame(const char *fps, const char *notice) { int emu_opt = currentConfig.EmuOpt; - int offs = (psp_screen == VRAM_FB0) ? VRAMOFFS_FB0 : VRAMOFFS_FB1; if (PicoIn.AHW & PAHW_PICO) draw_pico_ptr(); - sceGuSync(0,0); // sync with prev - sceGuStart(GU_DIRECT, guCmdList); - sceGuDrawBuffer(GU_PSM_5650, (void *)offs, 512); // point to back buffer - - blitscreen_clut(); - + osd_buf_cnt = 0; if (notice) osd_text(4, notice); if (emu_opt & 2) osd_text(OSD_FPS_X, fps); + osd_cdleds = 0; if ((emu_opt & 0x400) && (PicoIn.AHW & PAHW_MCD)) cd_leds(); sceKernelDcacheWritebackAll(); - sceGuFinish(); } /* FIXME: move plat_* to plat? */ @@ -676,7 +682,7 @@ void plat_status_msg_busy_next(const char *msg) /* clear status message area */ void plat_status_msg_clear(void) { - clearArea(0); + // not needed since the screen buf is cleared through the GU } /* change the audio volume setting */ @@ -690,7 +696,7 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co out_y = start_line; out_x = start_col; out_h = line_count; out_w = col_count; - if (col_count == 248) // mind aspect ration when blanking 1st column + if (col_count == 248) // mind aspect ratio when blanking 1st column col_count = 256; switch (currentConfig.vscaling) { @@ -723,8 +729,6 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co } vidResetMode(); - if (col_count < 320) // clear borders from h40 remnants - clearArea(1); } /* render one frame in RGB */ @@ -741,7 +745,6 @@ void pemu_forced_frame(int no_scale, int do_emu) void plat_video_toggle_renderer(int change, int is_menu_call) { change_renderer(change); - clearArea(1); if (is_menu_call) return; @@ -770,7 +773,6 @@ void plat_video_loop_prepare(void) { apply_renderer(); vidResetMode(); - clearArea(1); } /* prepare for entering the emulator loop */ diff --git a/platform/psp/emu.h b/platform/psp/emu.h index e9202745a..7eed9f9cc 100644 --- a/platform/psp/emu.h +++ b/platform/psp/emu.h @@ -3,6 +3,8 @@ extern int engineStateSuspend; void emu_handle_resume(void); +void blitscreen_clut(void); + // actually comes from Pico/Misc_amips.s void memset32_uncached(int *dest, int c, int count); diff --git a/platform/psp/plat.c b/platform/psp/plat.c index 0232b1d0d..9832bd10e 100644 --- a/platform/psp/plat.c +++ b/platform/psp/plat.c @@ -70,8 +70,23 @@ void plat_target_finish(void) /* display a completed frame buffer and prepare a new render buffer */ void plat_video_flip(void) { + int offs = (psp_screen == VRAM_FB0) ? VRAMOFFS_FB0 : VRAMOFFS_FB1; + g_menubg_src_ptr = psp_screen; - psp_video_flip(currentConfig.EmuOpt & EOPT_VSYNC, 1); + + sceGuSync(0, 0); // sync with prev + psp_video_flip(currentConfig.EmuOpt & EOPT_VSYNC, 0); + + sceGuStart(GU_DIRECT, guCmdList); + sceGuDrawBuffer(GU_PSM_5650, (void *)offs, 512); // point to back buffer + sceGuClearColor(0); + sceGuClearDepth(0); + sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT); + + blitscreen_clut(); + + sceGuFinish(); + g_screen_ptr = VRAM_CACHED_STUFF + (psp_screen - VRAM_FB0); plat_video_set_buffer(g_screen_ptr); } @@ -96,13 +111,15 @@ void plat_video_menu_begin(void) /* display a completed menu screen */ void plat_video_menu_end(void) { - plat_video_wait_vsync(); - psp_video_flip(0, 0); + g_menuscreen_ptr = NULL; + psp_video_flip(1, 0); } /* terminate menu display */ void plat_video_menu_leave(void) { + g_screen_ptr = VRAM_CACHED_STUFF + (psp_screen - VRAM_FB0); + plat_video_set_buffer(g_screen_ptr); } /* Preliminary initialization needed at program start */ diff --git a/platform/psp/psp.c b/platform/psp/psp.c index e719e4695..081723afc 100644 --- a/platform/psp/psp.c +++ b/platform/psp/psp.c @@ -155,6 +155,8 @@ void psp_init(void) sceGuDrawBuffer(GU_PSM_5650, (void *)VRAMOFFS_FB0, 512); sceGuDispBuffer(480, 272, (void *)VRAMOFFS_FB1, 512); // don't care sceGuDepthBuffer((void *)VRAMOFFS_DEPTH, 512); + sceGuClearColor(0); + sceGuClearDepth(0); sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT); sceGuOffset(2048 - (480 / 2), 2048 - (272 / 2)); sceGuViewport(2048, 2048, 480, 272); @@ -195,9 +197,9 @@ void psp_video_flip(int wait_vsync, int other) { unsigned long fb = (unsigned long)psp_screen & ~0x40000000; if (other) fb ^= 0x44000; - //if (wait_vsync) sceDisplayWaitVblankStart(); + if (wait_vsync) sceDisplayWaitVblankStart(); sceDisplaySetFrameBuf((void *)fb, 512, PSP_DISPLAY_PIXEL_FORMAT_565, - wait_vsync ? PSP_DISPLAY_SETBUF_NEXTFRAME : PSP_DISPLAY_SETBUF_IMMEDIATE); + PSP_DISPLAY_SETBUF_IMMEDIATE); current_screen ^= 1; psp_screen = current_screen ? VRAM_FB0 : VRAM_FB1; } From 8a553c6b3d8083f8ca0afc49c8ae3c6155037148 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 23 Nov 2023 23:53:57 +0100 Subject: [PATCH 11/40] update libpicofe (file selector) --- platform/libpicofe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/libpicofe b/platform/libpicofe index d5a43fbd9..bf1b3e327 160000 --- a/platform/libpicofe +++ b/platform/libpicofe @@ -1 +1 @@ -Subproject commit d5a43fbd972854cf6f02a47a8ca4ccc1bdadfca8 +Subproject commit bf1b3e327f29c7f0872e028ba34d865b54cb9036 From 575d2247807e81eebcaec57ee5092246c89d9fa1 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 23 Nov 2023 23:01:17 +0100 Subject: [PATCH 12/40] psp, fix enable sound option --- platform/psp/emu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/psp/emu.c b/platform/psp/emu.c index a1c44cae6..b8800642f 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -494,6 +494,9 @@ void pemu_sound_start(void) samples_made = samples_done = 0; + if (!(currentConfig.EmuOpt & EOPT_EN_SOUND)) + return; + if (PicoIn.AHW & PAHW_MCD) { // mp3... if (!mp3_init_done) { From 4b24b6b74c2e5c7fb09ff2c2a89e2c0a37a123a5 Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 24 Nov 2023 18:50:12 +0100 Subject: [PATCH 13/40] build, fix cross compiling under osx --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1120f8bb4..2ab08f592 100644 --- a/Makefile +++ b/Makefile @@ -350,7 +350,7 @@ endif ifneq ($(findstring gcc,$(CC)),) ifneq ($(findstring SunOS,$(shell uname -a)),SunOS) -ifeq ($(findstring Darwin,$(shell uname -a)),Darwin) +ifneq ($(findstring clang,$(shell $(CC) -v 2>&1)),) LDFLAGS += -Wl,-map,$(TARGET).map else LDFLAGS += -Wl,-Map=$(TARGET).map From fc07fe2b4eb1eadf565ff0e64777a8be3c97c300 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 30 Nov 2023 20:35:49 +0100 Subject: [PATCH 14/40] psp, revisit scaling --- platform/common/emu.h | 10 +++++----- platform/psp/emu.c | 24 +++++++++++++----------- platform/psp/menu.c | 6 +++--- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/platform/common/emu.h b/platform/common/emu.h index 1b2fa0cd0..db0840223 100644 --- a/platform/common/emu.h +++ b/platform/common/emu.h @@ -41,12 +41,12 @@ enum { EOPT_SCALE_SW = 1, EOPT_SCALE_HW, // PSP horiz: - EOPT_SCALE_43 = 1, // DAR 4:3 (12:9) - EOPT_SCALE_WIDE, // DAR 14:9 - EOPT_SCALE_FULL, // DAR 16:9 + EOPT_SCALE_43 = 1, // 4:3 screen + EOPT_SCALE_STRETCH, // stretched to between _43 and _WIDE + EOPT_SCALE_WIDE, // stretched to match display width // PSP vert: - EOPT_VSCALE_43 = 1, // DAR 4:3 - EOPT_VSCALE_FULL, // zoomed to full height + EOPT_VSCALE_FULL = 1, // TV height scaled to screen height + EOPT_VSCALE_NOBORDER, // VDP area scaled to screen height }; enum { diff --git a/platform/psp/emu.c b/platform/psp/emu.c index b8800642f..dbfa0eca2 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -608,7 +608,7 @@ void pemu_prep_defconfig(void) defaultConfig.CPUclock = 333; defaultConfig.filter = EOPT_FILTER_BILINEAR; // bilinear filtering defaultConfig.scaling = EOPT_SCALE_43; - defaultConfig.vscaling = EOPT_VSCALE_43; + defaultConfig.vscaling = EOPT_VSCALE_FULL; defaultConfig.renderer = RT_8BIT_ACC; defaultConfig.renderer32x = RT_8BIT_ACC; defaultConfig.EmuOpt |= EOPT_SHOW_RTC; @@ -696,6 +696,9 @@ void plat_update_volume(int has_changed, int is_up) /* prepare for MD screen mode change */ void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count) { + int h43 = (col_count >= 192 ? 320 : col_count); // ugh, mind GG... + int v43 = (line_count >= 192 ? Pico.m.pal ? 240 : 224 : line_count); + out_y = start_line; out_x = start_col; out_h = line_count; out_w = col_count; @@ -703,31 +706,30 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co col_count = 256; switch (currentConfig.vscaling) { - case EOPT_VSCALE_43: - // ugh, mind GG... - if (line_count >= 160) - line_count = (Pico.m.pal ? 240 : 224); + case EOPT_VSCALE_FULL: + line_count = v43; vscale = (float)270/line_count; break; - case EOPT_VSCALE_FULL: + case EOPT_VSCALE_NOBORDER: vscale = (float)270/line_count; break; default: vscale = 1; break; } + switch (currentConfig.scaling) { case EOPT_SCALE_43: - hscale = (float)360/col_count; + hscale = (vscale*h43)/col_count; break; - case EOPT_SCALE_WIDE: - hscale = (float)420/col_count; + case EOPT_SCALE_STRETCH: + hscale = (vscale*h43/2 + 480/2)/col_count; break; - case EOPT_SCALE_FULL: + case EOPT_SCALE_WIDE: hscale = (float)480/col_count; break; default: - hscale = 1; + hscale = vscale; break; } diff --git a/platform/psp/menu.c b/platform/psp/menu.c index 034ef3ee1..95698a84f 100644 --- a/platform/psp/menu.c +++ b/platform/psp/menu.c @@ -1,11 +1,11 @@ -static const char *men_hscaling_opts[] = { "OFF", "4:3", "wide", "fullscreen", NULL }; -static const char *men_vscaling_opts[] = { "OFF", "4:3", "fullscreen", NULL }; +static const char *men_vscaling_opts[] = { "OFF", "fullscreen", "borderless", NULL }; +static const char *men_hscaling_opts[] = { "1:1", "4:3", "extended", "fullwidth", NULL }; static const char *men_filter_opts[] = { "nearest", "bilinear", NULL }; #define MENU_OPTIONS_GFX \ - mee_enum ("Horizontal scaling", MA_OPT_SCALING, currentConfig.scaling, men_hscaling_opts), \ mee_enum ("Vertical scaling", MA_OPT_VSCALING, currentConfig.vscaling, men_vscaling_opts), \ + mee_enum ("Aspect ratio", MA_OPT_SCALING, currentConfig.scaling, men_hscaling_opts), \ mee_enum ("Scaler type", MA_OPT3_FILTERING, currentConfig.filter, men_filter_opts), \ mee_range ("Gamma adjustment", MA_OPT3_GAMMAA, currentConfig.gamma, -4, 16), \ mee_range ("Black level", MA_OPT3_BLACKLVL, currentConfig.gamma2, 0, 2), \ From a0ecb299796e232b67183f1c673b0eb00ca2b609 Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 1 Dec 2023 00:59:43 +0100 Subject: [PATCH 15/40] core, fix no ym2612 timers if z80 in reset --- pico/pico_cmn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index 3e5a038eb..5a7354493 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -334,7 +334,7 @@ static int PicoFrameHints(void) // get samples from sound chips PsndGetSamples(y); - timers_cycle(Pico.t.z80c_aim); + timers_cycle(cycles_68k_to_z80(Pico.t.m68c_aim - Pico.t.m68c_frame_start)); pv->hint_cnt = hint; From 0f1b9bccc0427d789159da911b3becb0c3711215 Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 3 Dec 2023 14:42:32 +0100 Subject: [PATCH 16/40] sdl, improve redraw in file selector --- platform/common/menu_pico.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index a8e5e3b6b..25d8756d6 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -1249,10 +1249,8 @@ static int main_menu_handler(int id, int keys) break; case MA_MAIN_LOAD_ROM: rom_fname_reload = NULL; - ret_name = menu_loop_romsel(rom_fname_loaded, - sizeof(rom_fname_loaded), rom_exts, NULL); -// ret_name = menu_loop_romsel_d(rom_fname_loaded, -// sizeof(rom_fname_loaded), rom_exts, NULL, menu_draw_prep); + ret_name = menu_loop_romsel_d(rom_fname_loaded, + sizeof(rom_fname_loaded), rom_exts, NULL, menu_draw_prep); if (ret_name != NULL) { lprintf("selected file: %s\n", ret_name); rom_fname_reload = ret_name; @@ -1383,10 +1381,8 @@ static int mh_tray_load_cd(int id, int keys) const char *ret_name; rom_fname_reload = NULL; - ret_name = menu_loop_romsel(rom_fname_loaded, - sizeof(rom_fname_loaded), rom_exts, NULL); -// ret_name = menu_loop_romsel_d(rom_fname_loaded, -// sizeof(rom_fname_loaded), rom_exts, NULL, menu_draw_prep); + ret_name = menu_loop_romsel_d(rom_fname_loaded, + sizeof(rom_fname_loaded), rom_exts, NULL, menu_draw_prep); if (ret_name == NULL) return 0; From 6396f46107ad156f967709bd7dd626d70d8d33cc Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 3 Dec 2023 14:56:24 +0100 Subject: [PATCH 17/40] sound, fix ffw crash in PSG --- pico/sound/sn76496.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pico/sound/sn76496.c b/pico/sound/sn76496.c index 27764a93c..cb3831181 100644 --- a/pico/sound/sn76496.c +++ b/pico/sound/sn76496.c @@ -60,7 +60,7 @@ struct SN76496 }; static struct SN76496 ono_sn; // one and only SN76496 -int *sn76496_regs; +int *sn76496_regs = ono_sn.Register; //static void SN76496Write(int data) @@ -264,7 +264,6 @@ int SN76496_init(int clock,int sample_rate) int i; //R->Channel = stream_create(0,1, sample_rate,R,SN76496Update); - sn76496_regs = R->Register; R->SampleRate = sample_rate; SN76496_set_clock(R,clock); From c180662e07d428ca4c2c9a39fdb152d4fcacc6dd Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 3 Dec 2023 17:46:59 +0100 Subject: [PATCH 18/40] sms, improve changing of video mode --- pico/draw.c | 2 +- pico/mode4.c | 27 +++++++++++++++------------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/pico/draw.c b/pico/draw.c index f6a710c5c..66b4fca5a 100644 --- a/pico/draw.c +++ b/pico/draw.c @@ -1943,7 +1943,7 @@ PICO_INTERNAL void PicoFrameStart(void) if (est->rendstatus != rendstatus_old || lines != rendlines) { rendlines = lines; - // mode_change() might reset rendstatus_old by calling SetColorFormat + // mode_change() might reset rendstatus_old by calling SetOutFormat int rendstatus = est->rendstatus; emu_video_mode_change(loffs, lines, coffs, columns); rendstatus_old = rendstatus; diff --git a/pico/mode4.c b/pico/mode4.c index b56cf4429..78108ec0d 100644 --- a/pico/mode4.c +++ b/pico/mode4.c @@ -728,11 +728,12 @@ static void FinalizeLine8bitSMS(int line); void PicoFrameStartSMS(void) { + struct PicoEState *est = &Pico.est; int lines = 192, columns = 256, loffs, coffs; skip_next_line = 0; loffs = screen_offset = 24; // 192 lines is really 224 with top/bottom bars - Pico.est.rendstatus = PDRAW_32_COLS; + est->rendstatus = PDRAW_32_COLS; // if mode changes make palette dirty since some modes switch to a fixed one if (mode != ((Pico.video.reg[0]&0x06) | (Pico.video.reg[1]&0x18))) { @@ -753,14 +754,14 @@ void PicoFrameStartSMS(void) } else { if ((mode & 4) && (Pico.video.reg[0] & 0x20)) { // SMS mode 4 with 1st column blanked - Pico.est.rendstatus |= PDRAW_SMS_BLANK_1; + est->rendstatus |= PDRAW_SMS_BLANK_1; columns = 248; } switch (mode) { // SMS2 only 224/240 line modes, e.g. Micro Machines case 0x06|0x08: - Pico.est.rendstatus |= PDRAW_30_ROWS; + est->rendstatus |= PDRAW_30_ROWS; loffs = screen_offset = 0; lines = 240; break; @@ -776,32 +777,34 @@ void PicoFrameStartSMS(void) coffs = (FinalizeLineSMS == NULL && columns == 248 ? 8 : 0); if (FinalizeLineSMS != NULL && (PicoIn.opt & POPT_EN_SOFTSCALE)) { // softscaling always generates 320px, but no scaling in 8bit fast - Pico.est.rendstatus |= PDRAW_SOFTSCALE; + est->rendstatus |= PDRAW_SOFTSCALE; coffs = 0; columns = 320; } else if (!(PicoIn.opt & POPT_DIS_32C_BORDER)) { - Pico.est.rendstatus |= PDRAW_BORDER_32; + est->rendstatus |= PDRAW_BORDER_32; line_offset -= coffs; coffs = (320-columns) / 2; if (FinalizeLineSMS == NULL) line_offset += coffs; // ... else centering done in FinalizeLine } - if (Pico.est.rendstatus != rendstatus_old || lines != rendlines) { + if (est->rendstatus != rendstatus_old || lines != rendlines) { + // mode_change() might reset rendstatus_old by calling SetOutFormat + int rendstatus = est->rendstatus; emu_video_mode_change(loffs, lines, coffs, columns); - rendstatus_old = Pico.est.rendstatus; + rendstatus_old = rendstatus; rendlines = lines; sprites = 0; } - Pico.est.HighCol = HighColBase + screen_offset * HighColIncrement; - Pico.est.DrawLineDest = (char *)DrawLineDestBase + screen_offset * DrawLineDestIncrement; + est->HighCol = HighColBase + screen_offset * HighColIncrement; + est->DrawLineDest = (char *)DrawLineDestBase + screen_offset * DrawLineDestIncrement; if (FinalizeLineSMS == FinalizeLine8bitSMS) { - Pico.m.dirtyPal = (Pico.m.dirtyPal || Pico.est.SonicPalCount ? 2 : 0); - memcpy(Pico.est.SonicPal, PicoMem.cram, 0x40*2); + Pico.m.dirtyPal = (Pico.m.dirtyPal || est->SonicPalCount ? 2 : 0); + memcpy(est->SonicPal, PicoMem.cram, 0x40*2); } - Pico.est.SonicPalCount = 0; + est->SonicPalCount = 0; } void PicoParseSATSMS(int line) From 0e7c5311690aa81ca40ba02083a4d107ff1ed109 Mon Sep 17 00:00:00 2001 From: sydarn Date: Tue, 21 Nov 2023 22:00:40 +0100 Subject: [PATCH 19/40] ODBETA: use 320x240 sdl surface when not hw scaling on 320x480 LCDs --- configure | 1 + platform/common/plat_sdl.c | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/configure b/configure index aede72159..3c88c6a2d 100755 --- a/configure +++ b/configure @@ -127,6 +127,7 @@ set_platform() odbeta) # various devices with opendingux beta, arch flags from toolchain default MFLAGS="" + CFLAGS="$CFLAGS -D__ODBETA__" platform="opendingux" ;; pandora) diff --git a/platform/common/plat_sdl.c b/platform/common/plat_sdl.c index b6b42610c..219b2c34e 100644 --- a/platform/common/plat_sdl.c +++ b/platform/common/plat_sdl.c @@ -331,9 +331,20 @@ static void plat_sdl_resize(int w, int h) { // take over new settings if (plat_sdl_screen->w != area.w || plat_sdl_screen->h != area.h) { - g_menuscreen_h = plat_sdl_screen->h; - g_menuscreen_w = plat_sdl_screen->w; - resize_buffers(); +#if defined(__ODBETA__) + if (currentConfig.vscaling != EOPT_SCALE_HW && + plat_sdl_screen->w == 320 && + plat_sdl_screen->h == 480) { + g_menuscreen_h = 240; + g_menuscreen_w = 320; + + } else +#endif + { + g_menuscreen_h = plat_sdl_screen->h; + g_menuscreen_w = plat_sdl_screen->w; + } + resize_buffers(); rendstatus_old = -1; } } From 830935963d85a84061bb22f41a5e2373024b6247 Mon Sep 17 00:00:00 2001 From: sydarn Date: Fri, 1 Dec 2023 18:42:21 +0100 Subject: [PATCH 20/40] cleanup rg99 specifics and remove odbetaflag --- configure | 9 +-------- platform/common/plat_sdl.c | 7 +------ 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/configure b/configure index 3c88c6a2d..8449010b6 100755 --- a/configure +++ b/configure @@ -110,13 +110,6 @@ set_platform() MFLAGS="-march=mips32r2" platform="opendingux" ;; - rg99) - # RG99 using opendingux, with Ingenic MIPS JZ4725B - sound_drivers="sdl" - CFLAGS="$CFLAGS -D__OPENDINGUX__" - MFLAGS="-march=mips32" - platform="opendingux" - ;; miyoo) # Miyoo BittBoy, PocketGO 1, PowKiddy V90/Q90 with Allwinner F1C100s sound_drivers="sdl" @@ -127,7 +120,7 @@ set_platform() odbeta) # various devices with opendingux beta, arch flags from toolchain default MFLAGS="" - CFLAGS="$CFLAGS -D__ODBETA__" + CFLAGS="$CFLAGS -D__OPENDINGUX__" platform="opendingux" ;; pandora) diff --git a/platform/common/plat_sdl.c b/platform/common/plat_sdl.c index 219b2c34e..f9f892d12 100644 --- a/platform/common/plat_sdl.c +++ b/platform/common/plat_sdl.c @@ -331,7 +331,7 @@ static void plat_sdl_resize(int w, int h) { // take over new settings if (plat_sdl_screen->w != area.w || plat_sdl_screen->h != area.h) { -#if defined(__ODBETA__) +#if defined(__OPENDINGUX__) if (currentConfig.vscaling != EOPT_SCALE_HW && plat_sdl_screen->w == 320 && plat_sdl_screen->h == 480) { @@ -398,11 +398,6 @@ void plat_init(void) in_sdl_init(&in_sdl_platform_data, plat_sdl_event_handler); in_probe(); -#if defined(__RG99__) - // do not use the default resolution - plat_sdl_change_video_mode(320, 240, 1); -#endif - bgr_to_uyvy_init(); } From 8a40739892cff72f8a81d10b8e5031f0df2901da Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 2 Dec 2023 23:52:55 +0200 Subject: [PATCH 21/40] cosmetic fixes for pandora port --- platform/pandora/menu.c | 11 ++++++----- platform/pandora/plat.c | 13 +++++++------ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/platform/pandora/menu.c b/platform/pandora/menu.c index 867b5c0d9..476af311a 100644 --- a/platform/pandora/menu.c +++ b/platform/pandora/menu.c @@ -24,11 +24,12 @@ static int menu_loop_cscaler(int id, int keys) inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT |PBTN_R|PBTN_MOK|PBTN_MBACK, NULL, 40); - if (inp & PBTN_UP) g_layer_cy--; - if (inp & PBTN_DOWN) g_layer_cy++; - if (inp & PBTN_LEFT) g_layer_cx--; - if (inp & PBTN_RIGHT) g_layer_cx++; - if (!(inp & PBTN_R)) { + if (inp & PBTN_R) { + if (inp & PBTN_UP) g_layer_cy--; + if (inp & PBTN_DOWN) g_layer_cy++; + if (inp & PBTN_LEFT) g_layer_cx--; + if (inp & PBTN_RIGHT) g_layer_cx++; + } else { if (inp & PBTN_UP) g_layer_ch += 2; if (inp & PBTN_DOWN) g_layer_ch -= 2; if (inp & PBTN_LEFT) g_layer_cw += 2; diff --git a/platform/pandora/plat.c b/platform/pandora/plat.c index 9b71d87aa..88a965292 100644 --- a/platform/pandora/plat.c +++ b/platform/pandora/plat.c @@ -37,10 +37,10 @@ static struct vout_fbdev *main_fb, *layer_fb; // g_layer_* - in use, g_layer_c* - configured custom -int g_layer_cx, g_layer_cy, g_layer_cw, g_layer_ch; +int g_layer_cx = 80, g_layer_cy, g_layer_cw = 640, g_layer_ch = 480; static int g_layer_x, g_layer_y; static int g_layer_w = 320, g_layer_h = 240; -static int g_osd_fps_x, g_osd_y, doing_bg_frame; +static int g_osd_start_x, g_osd_fps_x, g_osd_y, doing_bg_frame; static unsigned char __attribute__((aligned(4))) fb_copy[320 * 240 * 2]; static void *temp_frame; @@ -48,7 +48,6 @@ const char *renderer_names[] = { NULL }; const char *renderer_names32x[] = { NULL }; static const char * const pandora_gpio_keys[KEY_MAX + 1] = { - [0 ... KEY_MAX] = NULL, [KEY_UP] = "Up", [KEY_LEFT] = "Left", [KEY_RIGHT] = "Right", @@ -165,7 +164,7 @@ static void draw_cd_leds(void) void pemu_finalize_frame(const char *fps, const char *notice) { if (notice && notice[0]) - emu_osd_text16(2, g_osd_y, notice); + emu_osd_text16(2 + g_osd_start_x, g_osd_y, notice); if (fps && fps[0] && (currentConfig.EmuOpt & EOPT_SHOW_FPS)) emu_osd_text16(g_osd_fps_x, g_osd_y, fps); if ((PicoIn.AHW & PAHW_MCD) && (currentConfig.EmuOpt & EOPT_EN_CD_LEDS)) @@ -340,7 +339,7 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co fb_w = col_count; fb_left = start_col; - fb_right = 320 - (fb_w+fb_left);; + fb_right = 320 - (fb_w + fb_left); switch (currentConfig.scaling) { case SCALE_1x1: @@ -380,7 +379,8 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co fb_h = line_count; break; } - g_osd_fps_x = col_count < 320 ? 232 : 264; + g_osd_start_x = start_col; + g_osd_fps_x = start_col + col_count - 5*8 - 2; g_osd_y = fb_top + fb_h - 8; pnd_setup_layer(1, g_layer_x, g_layer_y, g_layer_w, g_layer_h); @@ -411,6 +411,7 @@ void pemu_loop_prep(void) void pemu_loop_end(void) { + memset(fb_copy, 0, sizeof(fb_copy)); /* do one more frame for menu bg */ pemu_forced_frame(0, 1); From 92efe29e6af614cbcec03504065bff76e38cfa80 Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 3 Dec 2023 21:13:04 +0200 Subject: [PATCH 22/40] pandora: move PicoDrawSetOutFormat --- platform/pandora/plat.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/pandora/plat.c b/platform/pandora/plat.c index 88a965292..3b2af5447 100644 --- a/platform/pandora/plat.c +++ b/platform/pandora/plat.c @@ -387,8 +387,6 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co vout_fbdev_resize(layer_fb, fb_w, fb_h, 16, fb_left, fb_right, fb_top, fb_bottom, 4, 0); vout_fbdev_clear(layer_fb); plat_video_flip(); - - PicoDrawSetOutFormat(PDF_RGB555, 0); } void plat_video_loop_prepare(void) @@ -397,6 +395,7 @@ void plat_video_loop_prepare(void) memset(g_menuscreen_ptr, 0, g_menuscreen_w * g_menuscreen_h * 2); g_menuscreen_ptr = vout_fbdev_flip(main_fb); + PicoDrawSetOutFormat(PDF_RGB555, 0); // emu_video_mode_change will call pnd_setup_layer() } From 2a5ca3d5f0b01fd09b08d10e195c1ad68b596e2e Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 3 Dec 2023 21:57:44 +0100 Subject: [PATCH 23/40] update libpicofe (parallel menu keys) --- platform/libpicofe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/libpicofe b/platform/libpicofe index bf1b3e327..7b3f69a4a 160000 --- a/platform/libpicofe +++ b/platform/libpicofe @@ -1 +1 @@ -Subproject commit bf1b3e327f29c7f0872e028ba34d865b54cb9036 +Subproject commit 7b3f69a4aa53eaf0fb51065c86e71748066e09ed From 85174a6d8daf05918233c8371887ac5085e06eeb Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 3 Dec 2023 22:10:48 +0100 Subject: [PATCH 24/40] build, cleanup - remove/rename some platforms from configure - new rg99 odbeta build, courtesy of sydarn - pandora support, courtesy of notaz --- .github/workflows/ci.yml | 28 ++++++++++++++++++++++++---- configure | 8 ++++---- platform/common/main.c | 3 +++ platform/common/plat_sdl.c | 1 + platform/common/plat_sdl.h | 2 ++ platform/linux/menu.c | 3 +++ platform/pandora/Makefile | 6 +++--- platform/pandora/make_pxml.sh | 4 ++-- platform/psp/menu.c | 2 ++ tools/release.sh | 28 ++++++++++++++++++++-------- 10 files changed, 64 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b8192a5c4..f9965cf9b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,7 +39,7 @@ jobs: run: | git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) - ./configure --platform=gp2x + ./configure --platform=gph make -j2 PLATFORM_MP3=0 make -C platform/gp2x rel VER=$ver mv PicoDrive_$ver.zip PicoDrive-gph_$ver.zip @@ -62,13 +62,13 @@ jobs: ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) ./configure --platform=pandora make -j2 - mv PicoDrive PicoDrive-pandora - ${CROSS_COMPILE}strip PicoDrive-pandora + make -C platform/pandora rel VER=$ver + mv platform/pandora/PicoDrive_*.pnd . - name: artifacts uses: actions/upload-artifact@v3 with: name: Pandora - path: PicoDrive-pandora + path: PicoDrive_*.pnd build-psp: runs-on: ubuntu-latest @@ -238,3 +238,23 @@ jobs: with: name: ODbeta lepus path: PicoDrive-odbeta-*.opk + + build-odbeta-rg99: + runs-on: ubuntu-latest + container: ghcr.io/irixxxx/toolchain-odbeta-rs90 + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - name: build + run: | + git config --global --add safe.directory $PWD + ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) + ./configure --platform=opendingux --platform=odbeta + make -j2 + mv PicoDrive.opk PicoDrive-odbeta-rg99-$ver.opk + - name: artifacts + uses: actions/upload-artifact@v3 + with: + name: ODbeta rg99 + path: PicoDrive-odbeta-*.opk diff --git a/configure b/configure index 8449010b6..4209784fc 100755 --- a/configure +++ b/configure @@ -39,7 +39,7 @@ check_define() # "" means "autodetect". # TODO this is annoyingly messy. should have platform and device -platform_list="generic pandora gp2x wiz caanoo dingux retrofw gcw0 rg350 opendingux miyoo rpi1 rpi2 psp rg99 odbeta" +platform_list="generic pandora gph dingux retrofw gcw0 opendingux odbeta miyoo rpi1 rpi2 psp" platform="generic" sound_driver_list="oss alsa sdl" sound_drivers="" @@ -102,7 +102,7 @@ set_platform() MFLAGS="-march=mips32" platform="opendingux" ;; - opendingux | gcw0 | rg350) + opendingux | gcw0) # more modern devices using opendingux, with Ingenic MIPS JZ4770 or newer sound_drivers="sdl" # mostly based on opendingux for gcw0 @@ -119,8 +119,8 @@ set_platform() ;; odbeta) # various devices with opendingux beta, arch flags from toolchain default - MFLAGS="" CFLAGS="$CFLAGS -D__OPENDINGUX__" + MFLAGS="" # toolchains are arch specific platform="opendingux" ;; pandora) @@ -128,7 +128,7 @@ set_platform() have_libavcodec="yes" MFLAGS="-mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp" ;; - gp2x | wiz | caanoo) + gph) sound_drivers="oss" # compile for OABI if toolchain provides it (faster code on caanoo) have_arm_oabi="yes" diff --git a/platform/common/main.c b/platform/common/main.c index 6fce5d58a..e503edc12 100644 --- a/platform/common/main.c +++ b/platform/common/main.c @@ -84,6 +84,9 @@ int main(int argc, char *argv[]) //in_probe(); plat_target_init(); + if (argc > 1) + parse_cmd_line(argc, argv); + plat_init(); menu_init(); diff --git a/platform/common/plat_sdl.c b/platform/common/plat_sdl.c index f9f892d12..552806146 100644 --- a/platform/common/plat_sdl.c +++ b/platform/common/plat_sdl.c @@ -399,6 +399,7 @@ void plat_init(void) in_probe(); bgr_to_uyvy_init(); + linux_menu_init(); } void plat_finish(void) diff --git a/platform/common/plat_sdl.h b/platform/common/plat_sdl.h index ea8680fec..0bbe2bd3a 100644 --- a/platform/common/plat_sdl.h +++ b/platform/common/plat_sdl.h @@ -5,3 +5,5 @@ extern const int in_sdl_key_map_sz; extern const struct menu_keymap in_sdl_joy_map[]; extern const int in_sdl_joy_map_sz; extern const char * const (*in_sdl_key_names)[SDLK_LAST]; + +void linux_menu_init(void); diff --git a/platform/linux/menu.c b/platform/linux/menu.c index 6eb2e459b..b37f3a53f 100644 --- a/platform/linux/menu.c +++ b/platform/linux/menu.c @@ -13,7 +13,10 @@ static const char h_stype[] = "Scaler algorithm for software scaling"; #define MENU_OPTIONS_ADV +static menu_entry e_menu_keyconfig[]; + void linux_menu_init(void) { + me_enable(e_menu_keyconfig, MA_CTRL_DEADZONE, 0); } diff --git a/platform/pandora/Makefile b/platform/pandora/Makefile index 31c104084..fd362696e 100644 --- a/platform/pandora/Makefile +++ b/platform/pandora/Makefile @@ -1,14 +1,14 @@ # release packaging makefile VER := $(shell head -n 1 ../common/version.h | \ - sed 's/.*"\(.*\)\.\(.*\)".*/\1\2/g') + sed 's/[^0-9]*\([0-9]*\)\.\([0-9]*\).*/\1\2/g') BUILD := $(shell git describe HEAD | grep -- - | \ sed -e 's/.*\-\(.*\)\-.*/\1/') ifneq "$(BUILD)" "" VER := $(VER)_$(BUILD) endif -PND_MAKE ?= $(HOME)/dev/pnd/src/pandora-libraries/testdata/scripts/pnd_make.sh +PND_MAKE ?= pnd_make all: rel @@ -24,7 +24,7 @@ all: rel rel: ../../PicoDrive PicoDrive.sh picorestore \ PicoDrive.png PicoDrive_p.png \ ../../pico/carthw.cfg skin \ - ../../README /tmp/PicoDrive.pxml + ../../README.md /tmp/PicoDrive.pxml rm -rf out mkdir out cp -r $^ out/ diff --git a/platform/pandora/make_pxml.sh b/platform/pandora/make_pxml.sh index 2fcf8334b..35d537a44 100755 --- a/platform/pandora/make_pxml.sh +++ b/platform/pandora/make_pxml.sh @@ -4,8 +4,8 @@ set -e verfile=../common/version.h test -f $verfile -major=`head -n 1 $verfile | sed 's/.*"\([0-9]*\)\.\([0-9]*\).*/\1/g'` -minor=`head -n 1 $verfile | sed 's/.*"\([0-9]*\)\.\([0-9]*\).*/\2/g'` +major=`head -n 1 $verfile | sed 's/[^0-9]*\([0-9]*\)\.\([0-9]*\).*/\1/g'` +minor=`head -n 1 $verfile | sed 's/[^0-9]*\([0-9]*\)\.\([0-9]*\).*/\2/g'` # lame, I know.. build=`git describe HEAD | grep -- - | sed -e 's/.*\-\(.*\)\-.*/\1/'` test -n "$build" && build_post="-$build" diff --git a/platform/psp/menu.c b/platform/psp/menu.c index 95698a84f..25ca98939 100644 --- a/platform/psp/menu.c +++ b/platform/psp/menu.c @@ -14,8 +14,10 @@ static const char *men_filter_opts[] = { "nearest", "bilinear", NULL }; #define MENU_OPTIONS_ADV static menu_entry e_menu_sms_options[]; +static menu_entry e_menu_keyconfig[]; void psp_menu_init(void) { me_enable(e_menu_sms_options, MA_SMSOPT_GHOSTING, 0); + me_enable(e_menu_keyconfig, MA_CTRL_DEADZONE, 0); } diff --git a/tools/release.sh b/tools/release.sh index 83f807fae..f431c5351 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -5,7 +5,7 @@ # creates builds for the supported platforms in the release directory # # usage: release.sh [platform...] -# platforms: gph dingux retrofw gcw0 rg350 miyoo psp pandora odbeta-gcw0 odbeta-lepus +# platforms: gph dingux retrofw gcw0 opendingux miyoo psp pandora odbeta-gcw0 odbeta-lepus odbeta-rg99 # # expects toolchains to be installed in these docker containers: # gph: ghcr.io/irixxxx/toolchain-gp2x @@ -14,8 +14,10 @@ # gcw0, rg350: ghcr.io/irixxxx/toolchain-opendingux # miyoo: ghcr.io/irixxxx/toolchain-miyoo # psp: docker.io/pspdev/pspdev +# pandora: ghcr.io/irixxxx/toolchain-pandora # odbeta-gcw0: ghcr.io/irixxxx/toolchain-odbeta-gcw0 # odbeta-lepus: ghcr.io/irixxxx/toolchain-odbeta-lepus +# odbeta-rg99: ghcr.io/irixxxx/toolchain-odbeta-rg99 trap "exit" ERR @@ -23,14 +25,14 @@ rel=$1 mkdir -p release-$rel shift; plat=" $* " -[ -z "$(echo $plat|tr -d ' ')" ] && plat=" gph dingux retrofw gcw0 rg350 miyoo psp pandora odbeta-gcw0 odbeta-lepus " +[ -z "$(echo $plat|tr -d ' ')" ] && plat=" gph dingux retrofw gcw0 opendingux miyoo psp pandora odbeta-gcw0 odbeta-lepus odbeta-rg99 " [ -z "${plat##* gph *}" ] && { # GPH devices: gp2x, wiz, caanoo, with ubuntu arm gcc 4.7 docker pull ghcr.io/irixxxx/toolchain-gp2x echo " git config --global --add safe.directory /home/picodrive &&\ - ./configure --platform=gp2x &&\ + ./configure --platform=gph &&\ make clean && make -j2 all &&\ make -C platform/gp2x rel VER=$rel "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-gp2x sh && @@ -68,11 +70,11 @@ echo " git config --global --add safe.directory /home/picodrive &&\ mv PicoDrive.opk release-$rel/PicoDrive-gcw0_$rel.opk } -[ -z "${plat##* rg350 *}" ] && { +[ -z "${plat##* opendingux *}" ] && { # rg350, gkd350h etc: JZ4770 or newer docker pull ghcr.io/irixxxx/toolchain-opendingux echo " git config --global --add safe.directory /home/picodrive &&\ - ./configure --platform=rg350 &&\ + ./configure --platform=opendingux &&\ make clean && make -j2 all "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-opendingux sh && mv PicoDrive.opk release-$rel/PicoDrive-opendingux_$rel.opk @@ -106,9 +108,9 @@ docker pull ghcr.io/irixxxx/toolchain-pandora echo " git config --global --add safe.directory /home/picodrive &&\ ./configure --platform=pandora &&\ make clean && make -j2 all &&\ - \${CROSS_COMPILE}strip -o PicoDrive-pandora-$rel PicoDrive"\ + make -C platform/pandora rel VER=$rel "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-pandora sh && -mv PicoDrive-pandora-$rel release-$rel/ +mv platform/pandora/PicoDrive_*.pnd release-$rel/ } [ -z "${plat##* odbeta-gcw0 *}" ] && { @@ -122,7 +124,7 @@ mv PicoDrive.opk release-$rel/PicoDrive-odbeta-gcw0_$rel.opk } [ -z "${plat##* odbeta-lepus *}" ] && { -# rg300 and other ingenic lepus based (untested): JZ4760 (mips32r1 with fpu) +# rg300 and other Ingenic lepus based (untested): JZ4760 (mips32r1 with fpu) docker pull ghcr.io/irixxxx/toolchain-odbeta-lepus echo " git config --global --add safe.directory /home/picodrive &&\ ./configure --platform=opendingux --platform=odbeta &&\ @@ -130,3 +132,13 @@ echo " git config --global --add safe.directory /home/picodrive &&\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-odbeta-lepus sh && mv PicoDrive.opk release-$rel/PicoDrive-odbeta-lepus_$rel.opk } + +[ -z "${plat##* odbeta-rg99 *}" ] && { +# rg99 and other JZ4725B based (untested): JZ4760 (mips32r1 w/o fpu) +docker pull ghcr.io/irixxxx/toolchain-odbeta-rs90 +echo " git config --global --add safe.directory /home/picodrive &&\ + ./configure --platform=opendingux --platform=odbeta &&\ + make clean && make -j2 all "\ + | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-odbeta-rs90 sh && +mv PicoDrive.opk release-$rel/PicoDrive-odbeta-rg99_$rel.opk +} From 58fc34b1d67b5622e9f9140456398ac046c0c1d8 Mon Sep 17 00:00:00 2001 From: kub Date: Tue, 5 Dec 2023 22:13:00 +0100 Subject: [PATCH 25/40] build, odbeta and opendingux cleanup --- .github/workflows/ci.yml | 8 +-- Makefile | 6 +- configure | 11 ++-- platform/common/emu.h | 1 + platform/common/inputmap_kbd.c | 17 ++++-- platform/common/main.c | 11 +--- platform/common/plat_sdl.c | 61 +++++++++++++++++--- platform/common/plat_sdl.h | 7 ++- platform/gp2x/plat.c | 5 ++ platform/opendingux/inputmap.c | 102 ++++++++++++++++++++++----------- platform/pandora/plat.c | 5 ++ platform/psp/plat.c | 6 ++ platform/win32/plat.c | 5 ++ tools/release.sh | 16 +++--- 14 files changed, 184 insertions(+), 77 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f9965cf9b..af1f43920 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -128,7 +128,7 @@ jobs: run: | git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) - ./configure --platform=gcw0 + ./configure --platform=opendingux-gcw0 make -j2 mv PicoDrive.opk PicoDrive-gcw0-$ver.opk - name: artifacts @@ -210,7 +210,7 @@ jobs: run: | git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) - ./configure --platform=gcw0 --platform=odbeta + ./configure --platform=odbeta make -j2 mv PicoDrive.opk PicoDrive-odbeta-gcw0-$ver.opk - name: artifacts @@ -230,7 +230,7 @@ jobs: run: | git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) - ./configure --platform=opendingux --platform=odbeta + ./configure --platform=odbeta make -j2 mv PicoDrive.opk PicoDrive-odbeta-lepus-$ver.opk - name: artifacts @@ -250,7 +250,7 @@ jobs: run: | git config --global --add safe.directory $PWD ver=$(cut -d'"' -f2 platform/common/version.h)-$(git rev-parse --short HEAD) - ./configure --platform=opendingux --platform=odbeta + ./configure --platform=odbeta make -j2 mv PicoDrive.opk PicoDrive-odbeta-rg99-$ver.opk - name: artifacts diff --git a/Makefile b/Makefile index 2ab08f592..bd8a5b5c5 100644 --- a/Makefile +++ b/Makefile @@ -67,7 +67,7 @@ ifneq ($(call chkCCflag, -fipa-ra),) # gcc >= 5 CFLAGS += $(call chkCCflag, -flto -fipa-pta -fipa-ra) else # these improve execution speed on 32bit arm/mips with gcc pre-5 toolchains -CFLAGS += -fno-caller-saves -fno-guess-branch-probability -fno-regmove +CFLAGS += $(call chkCCflag, -fno-caller-saves -fno-guess-branch-probability -fno-regmove) # very old gcc toolchains may not have these options CFLAGS += $(call chkCCflag, -fno-tree-loop-if-convert -fipa-pta -fno-ipa-cp) endif @@ -172,7 +172,7 @@ endif OBJS += platform/linux/emu.o platform/linux/blit.o # FIXME OBJS += platform/common/plat_sdl.o platform/common/input_sdlkbd.o OBJS += platform/libpicofe/plat_sdl.o platform/libpicofe/in_sdl.o -OBJS += platform/libpicofe/plat_dummy.o platform/libpicofe/linux/plat.o +OBJS += platform/libpicofe/linux/plat.o USE_FRONTEND = 1 endif ifeq "$(PLATFORM)" "generic" @@ -189,7 +189,7 @@ else OBJS += platform/common/plat_sdl.o platform/common/inputmap_kbd.o endif OBJS += platform/libpicofe/plat_sdl.o platform/libpicofe/in_sdl.o -OBJS += platform/libpicofe/plat_dummy.o platform/libpicofe/linux/plat.o +OBJS += platform/libpicofe/linux/plat.o USE_FRONTEND = 1 endif ifeq "$(PLATFORM)" "pandora" diff --git a/configure b/configure index 4209784fc..fd2d9a7e3 100755 --- a/configure +++ b/configure @@ -39,7 +39,7 @@ check_define() # "" means "autodetect". # TODO this is annoyingly messy. should have platform and device -platform_list="generic pandora gph dingux retrofw gcw0 opendingux odbeta miyoo rpi1 rpi2 psp" +platform_list="generic pandora gph dingux retrofw opendingux[-gcw0] odbeta[-gcw0] miyoo rpi1 rpi2 psp" platform="generic" sound_driver_list="oss alsa sdl" sound_drivers="" @@ -73,7 +73,7 @@ fail() set_platform() { platform=$1 - CFLAGS="$CFLAGS -D__`echo $platform | tr '[a-z]' '[A-Z]'`__" + CFLAGS="$CFLAGS -D__`echo ${platform%-*} | tr '[a-z]' '[A-Z]'`__" case "$platform" in rpi1) MFLAGS="-mcpu=arm1176jzf-s -mfpu=vfp" @@ -102,11 +102,12 @@ set_platform() MFLAGS="-march=mips32" platform="opendingux" ;; - opendingux | gcw0) + opendingux | opendingux-gcw0) # more modern devices using opendingux, with Ingenic MIPS JZ4770 or newer sound_drivers="sdl" # mostly based on opendingux for gcw0 CFLAGS="$CFLAGS -D__OPENDINGUX__" + [ "${platform#*gcw0}" = "" ] && CFLAGS="$CFLAGS -D__GCW0__" MFLAGS="-march=mips32r2" platform="opendingux" ;; @@ -117,9 +118,11 @@ set_platform() MFLAGS="-mcpu=arm926ej-s -marm" platform="opendingux" ;; - odbeta) + odbeta | odbeta-gcw0) # various devices with opendingux beta, arch flags from toolchain default + sound_drivers="sdl" CFLAGS="$CFLAGS -D__OPENDINGUX__" + [ "${platform#*gcw0}" = "" ] && CFLAGS="$CFLAGS -D__GCW0__" MFLAGS="" # toolchains are arch specific platform="opendingux" ;; diff --git a/platform/common/emu.h b/platform/common/emu.h index db0840223..287b43d55 100644 --- a/platform/common/emu.h +++ b/platform/common/emu.h @@ -180,6 +180,7 @@ void pemu_finalize_frame(const char *fps, const char *notice_msg); void pemu_sound_start(void); +int plat_parse_arg(int argc, char *argv[], int *x); void plat_early_init(void); void plat_init(void); void plat_finish(void); diff --git a/platform/common/inputmap_kbd.c b/platform/common/inputmap_kbd.c index e34fd9db2..b6b32be95 100644 --- a/platform/common/inputmap_kbd.c +++ b/platform/common/inputmap_kbd.c @@ -3,6 +3,7 @@ #include "../libpicofe/input.h" #include "../libpicofe/in_sdl.h" +#include "../libpicofe/plat.h" #include "../common/input_pico.h" #include "../common/plat_sdl.h" @@ -33,7 +34,7 @@ const struct in_default_bind in_sdl_defbinds[] = { { 0, 0, 0 } }; -const struct menu_keymap in_sdl_key_map[] = { +const struct menu_keymap _in_sdl_key_map[] = { { SDLK_UP, PBTN_UP }, { SDLK_DOWN, PBTN_DOWN }, { SDLK_LEFT, PBTN_LEFT }, @@ -45,9 +46,10 @@ const struct menu_keymap in_sdl_key_map[] = { { SDLK_TAB, PBTN_R }, { SDLK_BACKSPACE, PBTN_L }, }; -const int in_sdl_key_map_sz = sizeof(in_sdl_key_map) / sizeof(in_sdl_key_map[0]); +const int in_sdl_key_map_sz = sizeof(_in_sdl_key_map) / sizeof(_in_sdl_key_map[0]); +const struct menu_keymap *in_sdl_key_map = _in_sdl_key_map; -const struct menu_keymap in_sdl_joy_map[] = { +const struct menu_keymap _in_sdl_joy_map[] = { { SDLK_UP, PBTN_UP }, { SDLK_DOWN, PBTN_DOWN }, { SDLK_LEFT, PBTN_LEFT }, @@ -58,6 +60,11 @@ const struct menu_keymap in_sdl_joy_map[] = { { SDLK_WORLD_2, PBTN_MA2 }, { SDLK_WORLD_3, PBTN_MA3 }, }; -const int in_sdl_joy_map_sz = sizeof(in_sdl_joy_map) / sizeof(in_sdl_joy_map[0]); +const int in_sdl_joy_map_sz = sizeof(_in_sdl_joy_map) / sizeof(_in_sdl_joy_map[0]); +const struct menu_keymap *in_sdl_joy_map = _in_sdl_joy_map; -const char * const (*in_sdl_key_names)[SDLK_LAST] = NULL; +const char * const *in_sdl_key_names = NULL; + +void plat_target_setup_input(void) +{ +} diff --git a/platform/common/main.c b/platform/common/main.c index e503edc12..8e6987e49 100644 --- a/platform/common/main.c +++ b/platform/common/main.c @@ -28,7 +28,7 @@ void parse_cmd_line(int argc, char *argv[]) { int x, unrecognized = 0; - for (x = 1; x < argc; x++) + for (x = 1; x < argc && !unrecognized; x++) { if (argv[x][0] == '-') { @@ -47,15 +47,13 @@ void parse_cmd_line(int argc, char *argv[]) if (x+2 < argc) { pdb_net_connect(argv[x+1], argv[x+2]); x += 2; } } else { - unrecognized = 1; - break; + unrecognized = plat_parse_arg(argc, argv, &x); } } else { FILE *f = fopen(argv[x], "rb"); if (f) { fclose(f); rom_fname_reload = argv[x]; - engineState = PGS_ReloadRom; } else unrecognized = 1; @@ -95,12 +93,9 @@ int main(int argc, char *argv[]) emu_init(); - engineState = PGS_Menu; + engineState = rom_fname_reload ? PGS_ReloadRom : PGS_Menu; plat_video_menu_enter(0); - if (argc > 1) - parse_cmd_line(argc, argv); - if (engineState == PGS_ReloadRom) { plat_video_menu_begin(); diff --git a/platform/common/plat_sdl.c b/platform/common/plat_sdl.c index 552806146..c47ef1b7f 100644 --- a/platform/common/plat_sdl.c +++ b/platform/common/plat_sdl.c @@ -28,10 +28,58 @@ static struct area { int w, h; } area; static struct in_pdata in_sdl_platform_data = { .defbinds = in_sdl_defbinds, - .key_map = in_sdl_key_map, - .joy_map = in_sdl_joy_map, }; +struct plat_target plat_target; + +#if defined __MIYOO__ +const char *plat_device = "miyoo"; +#elif defined __GCW0__ +const char *plat_device = "gcw0"; +#elif defined __RETROFW__ +const char *plat_device = "retrofw"; +#elif defined __DINGUX__ +const char *plat_device = "dingux"; +#else +const char *plat_device = ""; +#endif + +int plat_parse_arg(int argc, char *argv[], int *x) +{ +#if defined __OPENDINGUX__ + if (*plat_device == '\0' && strcasecmp(argv[*x], "-device") == 0) { + plat_device = argv[++(*x)]; + return 0; + } +#endif + return 1; +} + +void plat_early_init(void) +{ +} + +int plat_target_init(void) +{ +#if defined __ODBETA__ + if (*plat_device == '\0') { + /* ODbeta should always have a device tree, get the model info from there */ + FILE *f = fopen("/proc/device-tree/compatible", "r"); + if (f) { + char buf[10]; + int c = fread(buf, 1, sizeof(buf), f); + if (strncmp(buf, "gcw,", 4) == 0) + plat_device = "gcw0"; + } + } +#endif + return 0; +} + +void plat_target_finish(void) +{ +} + /* YUV stuff */ static int yuv_ry[32], yuv_gy[32], yuv_by[32]; static unsigned char yuv_u[32 * 2], yuv_v[32 * 2]; @@ -323,10 +371,6 @@ void plat_video_loop_prepare(void) plat_video_set_buffer(g_screen_ptr); } -void plat_early_init(void) -{ -} - static void plat_sdl_resize(int w, int h) { // take over new settings @@ -392,9 +436,12 @@ void plat_init(void) g_screen_ppitch = 320; g_screen_ptr = shadow_fb; + plat_target_setup_input(); 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, - in_sdl_platform_data.key_names = *in_sdl_key_names, + in_sdl_platform_data.joy_map = in_sdl_joy_map, + in_sdl_platform_data.key_names = in_sdl_key_names, in_sdl_init(&in_sdl_platform_data, plat_sdl_event_handler); in_probe(); diff --git a/platform/common/plat_sdl.h b/platform/common/plat_sdl.h index 0bbe2bd3a..aefa80766 100644 --- a/platform/common/plat_sdl.h +++ b/platform/common/plat_sdl.h @@ -1,9 +1,10 @@ extern const struct in_default_bind in_sdl_defbinds[]; -extern const struct menu_keymap in_sdl_key_map[]; +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[]; +extern const struct menu_keymap *in_sdl_joy_map; extern const int in_sdl_joy_map_sz; -extern const char * const (*in_sdl_key_names)[SDLK_LAST]; +extern const char * const *in_sdl_key_names; +extern const char *plat_device; void linux_menu_init(void); diff --git a/platform/gp2x/plat.c b/platform/gp2x/plat.c index b25ce8502..96e9be091 100644 --- a/platform/gp2x/plat.c +++ b/platform/gp2x/plat.c @@ -184,6 +184,11 @@ void *plat_mem_get_for_drc(size_t size) return NULL; } +int plat_parse_arg(int argc, char *argv[], int *x) +{ + return 1; +} + void plat_early_init(void) { // just use gettimeofday until plat_init() diff --git a/platform/opendingux/inputmap.c b/platform/opendingux/inputmap.c index a8af36b2f..8df598d65 100644 --- a/platform/opendingux/inputmap.c +++ b/platform/opendingux/inputmap.c @@ -1,10 +1,14 @@ +#include #include +#include #include #include "../libpicofe/input.h" #include "../libpicofe/in_sdl.h" +#include "../libpicofe/plat.h" #include "../common/input_pico.h" #include "../common/plat_sdl.h" +#include "../common/emu.h" const struct in_default_bind in_sdl_defbinds[] = { { SDLK_UP, IN_BINDTYPE_PLAYER12, GBTN_UP }, @@ -24,26 +28,22 @@ const struct in_default_bind in_sdl_defbinds[] = { { 0, 0, 0 } }; -const struct menu_keymap in_sdl_key_map[] = { +struct menu_keymap _in_sdl_key_map[] = { { SDLK_UP, PBTN_UP }, { SDLK_DOWN, PBTN_DOWN }, { SDLK_LEFT, PBTN_LEFT }, { SDLK_RIGHT, PBTN_RIGHT }, -#if defined(__MIYOO__) - { SDLK_LALT, PBTN_MOK }, - { SDLK_LCTRL, PBTN_MBACK }, -#else { SDLK_LCTRL, PBTN_MOK }, { SDLK_LALT, PBTN_MBACK }, -#endif { SDLK_SPACE, PBTN_MA2 }, { SDLK_LSHIFT, PBTN_MA3 }, { SDLK_TAB, PBTN_L }, { SDLK_BACKSPACE, PBTN_R }, }; -const int in_sdl_key_map_sz = sizeof(in_sdl_key_map) / sizeof(in_sdl_key_map[0]); +const int in_sdl_key_map_sz = sizeof(_in_sdl_key_map) / sizeof(_in_sdl_key_map[0]); +const struct menu_keymap *in_sdl_key_map = _in_sdl_key_map; -const struct menu_keymap in_sdl_joy_map[] = { +const struct menu_keymap _in_sdl_joy_map[] = { { SDLK_UP, PBTN_UP }, { SDLK_DOWN, PBTN_DOWN }, { SDLK_LEFT, PBTN_LEFT }, @@ -54,49 +54,81 @@ const struct menu_keymap in_sdl_joy_map[] = { { SDLK_WORLD_2, PBTN_MA2 }, { SDLK_WORLD_3, PBTN_MA3 }, }; -const int in_sdl_joy_map_sz = sizeof(in_sdl_joy_map) / sizeof(in_sdl_joy_map[0]); +const int in_sdl_joy_map_sz = sizeof(_in_sdl_joy_map) / sizeof(_in_sdl_joy_map[0]); +const struct menu_keymap *in_sdl_joy_map = _in_sdl_joy_map; -const char * const _in_sdl_key_names[SDLK_LAST] = { +const char * _in_sdl_key_names[SDLK_LAST] = { + /* common */ [SDLK_UP] = "UP", [SDLK_DOWN] = "DOWN", [SDLK_LEFT] = "LEFT", [SDLK_RIGHT] = "RIGHT", -#if defined(__MIYOO__) - [SDLK_LALT] = "A", - [SDLK_LCTRL] = "B", -#else [SDLK_LCTRL] = "A", [SDLK_LALT] = "B", -#endif -#if defined(__GCW0__) || defined(__MIYOO__) - [SDLK_LSHIFT] = "X", - [SDLK_SPACE] = "Y", -#else [SDLK_LSHIFT] = "Y", [SDLK_SPACE] = "X", -#endif [SDLK_RETURN] = "START", [SDLK_ESCAPE] = "SELECT", - -#if defined(__MIYOO__) - [SDLK_TAB] = "L1", - [SDLK_BACKSPACE] = "R1", - [SDLK_RALT] = "L2", - [SDLK_RSHIFT] = "R2", - [SDLK_RCTRL] = "RESET", -#elif defined(__GCW0__) || defined(__DINGUX__) || defined(__RETROFW__) - [SDLK_TAB] = "L", - [SDLK_BACKSPACE] = "R", - [SDLK_POWER] = "POWER", - [SDLK_PAUSE] = "LOCK", -#else [SDLK_TAB] = "L1", [SDLK_BACKSPACE] = "R1", + + /* opendingux rg, gkd etc */ [SDLK_PAGEUP] = "L2", [SDLK_PAGEDOWN] = "R2", [SDLK_KP_DIVIDE] = "L3", [SDLK_KP_PERIOD] = "R3", [SDLK_HOME] = "POWER", -#endif + /* gcw0 */ + [SDLK_POWER] = "POWER", + [SDLK_PAUSE] = "LOCK", + /* miyoo */ + [SDLK_RALT] = "L2", + [SDLK_RSHIFT] = "R2", + [SDLK_RCTRL] = "RESET", }; -const char * const (*in_sdl_key_names)[SDLK_LAST] = &_in_sdl_key_names; +const char * const *in_sdl_key_names = _in_sdl_key_names; + + +static void nameset(int x1, const char *name) +{ + _in_sdl_key_names[x1] = name; +} + +static void nameswap(int x1, int x2) +{ + const char **p = &_in_sdl_key_names[x1]; + const char **q = &_in_sdl_key_names[x2]; + const char *t = *p; *p = *q; *q = t; +} + +static void keyswap(int k1, int k2) +{ + int x1, x2, t; + + for (x1 = in_sdl_key_map_sz-1; x1 >= 0; x1--) + if (_in_sdl_key_map[x1].key == k1) break; + for (x2 = in_sdl_key_map_sz-1; x2 >= 0; x2--) + if (_in_sdl_key_map[x2].key == k2) break; + if (x1 >= 0 && x2 >= 0) { + struct menu_keymap *p = &_in_sdl_key_map[x1]; + struct menu_keymap *q = &_in_sdl_key_map[x2]; + t = p->pbtn; p->pbtn = q->pbtn; q->pbtn = t; + } +} + +void plat_target_setup_input(void) +{ + if (strcmp(plat_device, "miyoo") == 0) { + /* swapped A/B and X/Y keys */ + keyswap(SDLK_LALT, SDLK_LCTRL); + nameswap(SDLK_LALT, SDLK_LCTRL); + nameswap(SDLK_SPACE, SDLK_LSHIFT); + } else if (strcmp(plat_device, "gcw0") == 0) { + /* swapped X/Y keys, single L/R keys */ + nameswap(SDLK_SPACE, SDLK_LSHIFT); + nameset(SDLK_TAB, "L"); nameset(SDLK_BACKSPACE, "R"); + } else if (strcmp(plat_device, "retrofw") == 0 || strcmp(plat_device, "dingux") == 0) { + /* single L/R keys */ + nameset(SDLK_TAB, "L"); nameset(SDLK_BACKSPACE, "R"); + } +} diff --git a/platform/pandora/plat.c b/platform/pandora/plat.c index 3b2af5447..be1f5781d 100644 --- a/platform/pandora/plat.c +++ b/platform/pandora/plat.c @@ -445,6 +445,11 @@ void *plat_mem_get_for_drc(size_t size) return NULL; } +int plat_parse_arg(int argc, char *argv[], int *x) +{ + return 1; +} + void plat_early_init(void) { } diff --git a/platform/psp/plat.c b/platform/psp/plat.c index 9832bd10e..271d35dd1 100644 --- a/platform/psp/plat.c +++ b/platform/psp/plat.c @@ -122,6 +122,12 @@ void plat_video_menu_leave(void) plat_video_set_buffer(g_screen_ptr); } +/* check arg at index x */ +int plat_parse_arg(int argc, char *argv[], int *x) +{ + return 1; +} + /* Preliminary initialization needed at program start */ void plat_early_init(void) { diff --git a/platform/win32/plat.c b/platform/win32/plat.c index 2c82ef7e5..f275010da 100644 --- a/platform/win32/plat.c +++ b/platform/win32/plat.c @@ -20,6 +20,11 @@ static unsigned short screen_buff[320 * 240]; const char *renderer_names[] = { NULL }; const char *renderer_names32x[] = { NULL }; +int plat_parse_arg(int argc, char *argv[], int *x) +{ + return 1; +} + void plat_init(void) { g_screen_ptr = (void *)screen_buff; diff --git a/tools/release.sh b/tools/release.sh index f431c5351..d5d134ea9 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -11,7 +11,7 @@ # gph: ghcr.io/irixxxx/toolchain-gp2x # dingux: ghcr.io/irixxxx/toolchain-dingux # retrofw: ghcr.io/irixxxx/toolchain-retrofw -# gcw0, rg350: ghcr.io/irixxxx/toolchain-opendingux +# gcw0,opendingux:ghcr.io/irixxxx/toolchain-opendingux # miyoo: ghcr.io/irixxxx/toolchain-miyoo # psp: docker.io/pspdev/pspdev # pandora: ghcr.io/irixxxx/toolchain-pandora @@ -64,7 +64,7 @@ mv PicoDrive.opk release-$rel/PicoDrive-retrofw_$rel.opk # gcw0: JZ4770 (mips32r2 with fpu), swapped X/Y buttons docker pull ghcr.io/irixxxx/toolchain-opendingux echo " git config --global --add safe.directory /home/picodrive &&\ - ./configure --platform=gcw0 &&\ + ./configure --platform=opendingux-gcw0 &&\ make clean && make -j2 all "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-opendingux sh && mv PicoDrive.opk release-$rel/PicoDrive-gcw0_$rel.opk @@ -114,30 +114,30 @@ mv platform/pandora/PicoDrive_*.pnd release-$rel/ } [ -z "${plat##* odbeta-gcw0 *}" ] && { -# gcw0 (untested): JZ4770 (mips32r2 with fpu), swapped X/Y buttons +# gcw0, rg350 and similar devices: JZ4770 (mips32r2 with fpu) docker pull ghcr.io/irixxxx/toolchain-odbeta-gcw0 echo " git config --global --add safe.directory /home/picodrive &&\ - ./configure --platform=gcw0 --platform=odbeta &&\ + ./configure --platform=odbeta &&\ make clean && make -j2 all "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-odbeta-gcw0 sh && mv PicoDrive.opk release-$rel/PicoDrive-odbeta-gcw0_$rel.opk } [ -z "${plat##* odbeta-lepus *}" ] && { -# rg300 and other Ingenic lepus based (untested): JZ4760 (mips32r1 with fpu) +# rg300 and other Ingenic lepus based: JZ4760 (mips32r1 with fpu) docker pull ghcr.io/irixxxx/toolchain-odbeta-lepus echo " git config --global --add safe.directory /home/picodrive &&\ - ./configure --platform=opendingux --platform=odbeta &&\ + ./configure --platform=odbeta &&\ make clean && make -j2 all "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-odbeta-lepus sh && mv PicoDrive.opk release-$rel/PicoDrive-odbeta-lepus_$rel.opk } [ -z "${plat##* odbeta-rg99 *}" ] && { -# rg99 and other JZ4725B based (untested): JZ4760 (mips32r1 w/o fpu) +# rg99 and similar devices: JZ4725B (mips32r1 w/o fpu) docker pull ghcr.io/irixxxx/toolchain-odbeta-rs90 echo " git config --global --add safe.directory /home/picodrive &&\ - ./configure --platform=opendingux --platform=odbeta &&\ + ./configure --platform=odbeta &&\ make clean && make -j2 all "\ | docker run -i -v$PWD:/home/picodrive -w/home/picodrive --rm ghcr.io/irixxxx/toolchain-odbeta-rs90 sh && mv PicoDrive.opk release-$rel/PicoDrive-odbeta-rg99_$rel.opk From 82f97f10a11339cdc7a13621a634d30647e262d5 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 14 Dec 2023 22:30:00 +0100 Subject: [PATCH 26/40] prerelease 2.00-alpha2 --- 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 8b2db2738..cc4da6634 100644 --- a/platform/common/version.h +++ b/platform/common/version.h @@ -1 +1 @@ -#define VERSION "pre-2.00-alpha1" REVISION +#define VERSION "pre-2.00-alpha2" REVISION From 70db485b44b711818fa07fb94fa62ec30b8d92ec Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 7 Jan 2024 00:39:44 +0200 Subject: [PATCH 27/40] config: save disabled options also Pandora uses disabled menu options to store the layer position (mee_range_hide() menu entries) and actually modifies them using a special menu handler. --- platform/common/config_file.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/platform/common/config_file.c b/platform/common/config_file.c index 260fd79c3..d5f583d94 100644 --- a/platform/common/config_file.c +++ b/platform/common/config_file.c @@ -118,7 +118,7 @@ int config_write(const char *fname) for (me = me_list_get_first(); me != NULL; me = me_list_get_next()) { int dummy; - if (!me->need_to_save || !me->enabled) + if (!me->need_to_save) continue; if (me->name == NULL || me->name[0] == 0) continue; @@ -129,8 +129,10 @@ int config_write(const char *fname) else if (me->beh == MB_OPT_RANGE || me->beh == MB_OPT_CUSTRANGE) { fprintf(fn, "%s = %i" NL, me->name, *(int *)me->var); } - else if (me->beh == MB_OPT_ENUM && me->data != NULL) { + else if (me->beh == MB_OPT_ENUM) { const char **names = (const char **)me->data; + if (names == NULL) + continue; for (t = 0; names[t] != NULL; t++) { if (*(int *)me->var == t) { strncpy(line, names[t], sizeof(line)-1); @@ -145,7 +147,8 @@ int config_write(const char *fname) goto write_line; } else - lprintf("config: unhandled write: %i\n", me->id); + lprintf("config: unhandled write: '%s' id %d behavior %d\n", + me->name, me->id, me->beh); continue; write_line: From ca980e1b0a60cc459f96fbf36e6ee837d25d2c9e Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 7 Jan 2024 00:46:36 +0200 Subject: [PATCH 28/40] pandora: allow to move the overlay partially offscreen to allow to cut off black bars, if the user chooses to do so --- platform/pandora/menu.c | 69 +++++++++++++++++++++++++++-------------- platform/pandora/plat.c | 66 ++++++++++++++++++++++----------------- platform/pandora/plat.h | 2 ++ 3 files changed, 86 insertions(+), 51 deletions(-) diff --git a/platform/pandora/menu.c b/platform/pandora/menu.c index 476af311a..45936d978 100644 --- a/platform/pandora/menu.c +++ b/platform/pandora/menu.c @@ -1,5 +1,8 @@ #include "plat.h" +static int min(int x, int y) { return x < y ? x : y; } +static int max(int x, int y) { return x > y ? x : y; } + static const char *men_scaler[] = { "1x1, 1x1", "2x2, 3x2", "2x2, 2x2", "fullscreen", "custom", NULL }; static const char h_scaler[] = "Scalers for 40 and 32 column modes\n" "(320 and 256 pixel wide horizontal)"; @@ -8,6 +11,7 @@ static const char h_cscaler[] = "Displays the scaler layer, you can resize it\ static int menu_loop_cscaler(int id, int keys) { + int was_layer_clipped = 0; unsigned int inp; currentConfig.scaling = SCALE_CUSTOM; @@ -15,21 +19,32 @@ static int menu_loop_cscaler(int id, int keys) pnd_setup_layer(1, g_layer_cx, g_layer_cy, g_layer_cw, g_layer_ch); pnd_restore_layer_data(); + menu_draw_begin(0, 1); + menuscreen_memset_lines(g_menuscreen_ptr, 0, g_menuscreen_h); + menu_draw_end(); + for (;;) { - menu_draw_begin(0, 1); - menuscreen_memset_lines(g_menuscreen_ptr, 0, g_menuscreen_h); - text_out16(2, 480 - 18, "%dx%d | d-pad to resize, R+d-pad to move", g_layer_cw, g_layer_ch); - menu_draw_end(); + int top_x = max(0, -g_layer_cx * g_screen_ppitch / 800) + 1; + int top_y = max(0, -g_layer_cy * g_screen_height / 480) + 1; + char text[128]; + memcpy(g_screen_ptr, g_menubg_src_ptr, + g_screen_ppitch * g_screen_height * 2); + snprintf(text, sizeof(text), "%d,%d %dx%d", + g_layer_cx, g_layer_cy, g_layer_cw, g_layer_ch); + basic_text_out16_nf(g_screen_ptr, g_screen_ppitch, + saved_start_col + top_x, saved_start_line + top_y, text); + basic_text_out16_nf(g_screen_ptr, g_screen_ppitch, 2, + g_screen_height - 20, "d-pad: resize, R+d-pad: move"); + plat_video_flip(); inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT |PBTN_R|PBTN_MOK|PBTN_MBACK, NULL, 40); - if (inp & PBTN_R) { - if (inp & PBTN_UP) g_layer_cy--; - if (inp & PBTN_DOWN) g_layer_cy++; - if (inp & PBTN_LEFT) g_layer_cx--; - if (inp & PBTN_RIGHT) g_layer_cx++; - } else { + if (inp & PBTN_UP) g_layer_cy--; + if (inp & PBTN_DOWN) g_layer_cy++; + if (inp & PBTN_LEFT) g_layer_cx--; + if (inp & PBTN_RIGHT) g_layer_cx++; + if (!(inp & PBTN_R)) { if (inp & PBTN_UP) g_layer_ch += 2; if (inp & PBTN_DOWN) g_layer_ch -= 2; if (inp & PBTN_LEFT) g_layer_cw += 2; @@ -39,17 +54,25 @@ static int menu_loop_cscaler(int id, int keys) break; if (inp & (PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT)) { - if (g_layer_cx < 0) g_layer_cx = 0; - if (g_layer_cx > 640) g_layer_cx = 640; - if (g_layer_cy < 0) g_layer_cy = 0; - if (g_layer_cy > 420) g_layer_cy = 420; - if (g_layer_cw < 160) g_layer_cw = 160; - if (g_layer_ch < 60) g_layer_ch = 60; - if (g_layer_cx + g_layer_cw > 800) - g_layer_cw = 800 - g_layer_cx; - if (g_layer_cy + g_layer_ch > 480) - g_layer_ch = 480 - g_layer_cy; + int layer_clipped = 0; + g_layer_cx = max(-320, min(g_layer_cx, 640)); + g_layer_cy = max(-240, min(g_layer_cy, 420)); + g_layer_cw = max(160, g_layer_cw); + g_layer_ch = max( 60, g_layer_ch); + if (g_layer_cx < 0 || g_layer_cx + g_layer_cw > 800) + layer_clipped = 1; + if (g_layer_cw > 800+400) + g_layer_cw = 800+400; + if (g_layer_cy < 0 || g_layer_cy + g_layer_ch > 480) + layer_clipped = 1; + if (g_layer_ch > 480+360) + g_layer_ch = 480+360; + // resize the layer pnd_setup_layer(1, g_layer_cx, g_layer_cy, g_layer_cw, g_layer_ch); + if (layer_clipped || was_layer_clipped) + emu_video_mode_change(saved_start_line, saved_line_count, + saved_start_col, saved_col_count); + was_layer_clipped = layer_clipped; } } @@ -62,9 +85,9 @@ static int menu_loop_cscaler(int id, int keys) mee_enum_h ("Scaler", MA_OPT_SCALING, currentConfig.scaling, \ men_scaler, h_scaler), \ mee_onoff ("Vsync", MA_OPT2_VSYNC, currentConfig.EmuOpt, EOPT_VSYNC), \ - mee_cust_h ("Setup custom scaler", MA_NONE, menu_loop_cscaler, NULL, h_cscaler), \ - mee_range_hide("layer_x", MA_OPT3_LAYER_X, g_layer_cx, 0, 640), \ - mee_range_hide("layer_y", MA_OPT3_LAYER_Y, g_layer_cy, 0, 420), \ + mee_cust_s_h ("Setup custom scaler", MA_NONE, 0, menu_loop_cscaler, NULL, h_cscaler), \ + mee_range_hide("layer_x", MA_OPT3_LAYER_X, g_layer_cx, -320, 640), \ + mee_range_hide("layer_y", MA_OPT3_LAYER_Y, g_layer_cy, -240, 420), \ mee_range_hide("layer_w", MA_OPT3_LAYER_W, g_layer_cw, 160, 800), \ mee_range_hide("layer_h", MA_OPT3_LAYER_H, g_layer_ch, 60, 480), \ diff --git a/platform/pandora/plat.c b/platform/pandora/plat.c index be1f5781d..e072a266a 100644 --- a/platform/pandora/plat.c +++ b/platform/pandora/plat.c @@ -38,6 +38,8 @@ static struct vout_fbdev *main_fb, *layer_fb; // g_layer_* - in use, g_layer_c* - configured custom int g_layer_cx = 80, g_layer_cy, g_layer_cw = 640, g_layer_ch = 480; +int saved_start_line = 0, saved_line_count = 240; +int saved_start_col = 0, saved_col_count = 320; static int g_layer_x, g_layer_y; static int g_layer_w = 320, g_layer_h = 240; static int g_osd_start_x, g_osd_fps_x, g_osd_y, doing_bg_frame; @@ -47,22 +49,6 @@ static void *temp_frame; const char *renderer_names[] = { NULL }; const char *renderer_names32x[] = { NULL }; -static const char * const pandora_gpio_keys[KEY_MAX + 1] = { - [KEY_UP] = "Up", - [KEY_LEFT] = "Left", - [KEY_RIGHT] = "Right", - [KEY_DOWN] = "Down", - [KEY_HOME] = "A", - [KEY_PAGEDOWN] = "X", - [KEY_END] = "B", - [KEY_PAGEUP] = "Y", - [KEY_RIGHTSHIFT]= "L", - [KEY_RIGHTCTRL] = "R", - [KEY_LEFTALT] = "Start", - [KEY_LEFTCTRL] = "Select", - [KEY_MENU] = "Pandora", -}; - static struct in_default_bind in_evdev_defbinds[] = { { KEY_UP, IN_BINDTYPE_PLAYER12, GBTN_UP }, @@ -314,6 +300,13 @@ static int pnd_setup_layer_(int fd, int enabled, int x, int y, int w, int h) int pnd_setup_layer(int enabled, int x, int y, int w, int h) { + // it's not allowed for the layer to be partially offscreen, + // instead it is faked by emu_video_mode_change() + if (x < 0) { w += x; x = 0; } + if (y < 0) { h += y; y = 0; } + if (x + w > 800) w = 800 - x; + if (y + h > 480) h = 480 - y; + return pnd_setup_layer_(vout_fbdev_get_fd(layer_fb), enabled, x, y, w, h); } @@ -332,26 +325,22 @@ void pnd_restore_layer_data(void) void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count) { - int fb_w = 320, fb_h = 240, fb_left = 0, fb_right = 0, fb_top = 0, fb_bottom = 0; + int fb_w, fb_h = 240, fb_left = 0, fb_right = 0, fb_top = 0, fb_bottom = 0; if (doing_bg_frame) return; - fb_w = col_count; - fb_left = start_col; - fb_right = 320 - (fb_w + fb_left); - switch (currentConfig.scaling) { case SCALE_1x1: - g_layer_w = fb_w; + g_layer_w = col_count; g_layer_h = fb_h; break; case SCALE_2x2_3x2: - g_layer_w = fb_w * (col_count < 320 ? 3 : 2); + g_layer_w = col_count * (col_count < 320 ? 3 : 2); g_layer_h = fb_h * 2; break; case SCALE_2x2_2x2: - g_layer_w = fb_w * 2; + g_layer_w = col_count * 2; g_layer_h = fb_h * 2; break; case SCALE_FULLSCREEN: @@ -376,17 +365,38 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co case SCALE_FULLSCREEN: case SCALE_CUSTOM: fb_top = start_line; - fb_h = line_count; + fb_h = start_line + line_count; break; } - g_osd_start_x = start_col; - g_osd_fps_x = start_col + col_count - 5*8 - 2; - g_osd_y = fb_top + fb_h - 8; + fb_w = 320; + fb_left = start_col; + fb_right = 320 - (start_col + col_count); + if (currentConfig.scaling == SCALE_CUSTOM) { + int right = g_layer_x + g_layer_w; + int bottom = g_layer_y + g_layer_h; + if (g_layer_x < 0) + fb_left += -g_layer_x * col_count / g_menuscreen_w; + if (g_layer_y < 0) + fb_top += -g_layer_y * line_count / g_menuscreen_h; + if (right > g_menuscreen_w) + fb_right += (right - g_menuscreen_w) * col_count / g_menuscreen_w; + if (bottom > g_menuscreen_h) + fb_bottom += (bottom - g_menuscreen_h) * line_count / g_menuscreen_h; + } + fb_w -= fb_left + fb_right; + fb_h -= fb_top + fb_bottom; pnd_setup_layer(1, g_layer_x, g_layer_y, g_layer_w, g_layer_h); vout_fbdev_resize(layer_fb, fb_w, fb_h, 16, fb_left, fb_right, fb_top, fb_bottom, 4, 0); vout_fbdev_clear(layer_fb); plat_video_flip(); + + g_osd_start_x = start_col; + g_osd_fps_x = start_col + col_count - 5*8 - 2; + g_osd_y = fb_top + fb_h - 8; + + saved_start_line = start_line, saved_line_count = line_count; + saved_start_col = start_col, saved_col_count = col_count; } void plat_video_loop_prepare(void) diff --git a/platform/pandora/plat.h b/platform/pandora/plat.h index 8e6816adc..2ac1b09c9 100644 --- a/platform/pandora/plat.h +++ b/platform/pandora/plat.h @@ -1,6 +1,8 @@ extern int g_layer_cx, g_layer_cy; extern int g_layer_cw, g_layer_ch; +extern int saved_start_line, saved_line_count; +extern int saved_start_col, saved_col_count; void pnd_menu_init(void); int pnd_setup_layer(int enabled, int x, int y, int w, int h); From 68e06234e3beb9c252efbb7af8aae76cff313271 Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 12 Jan 2024 02:23:31 +0200 Subject: [PATCH 29/40] sound: fix ym2612 freq latch there is only a single register, as described in: http://www.mjsstuf.x10host.com/pages/vgmPlay/vgmPlay.htm --- pico/sound/ym2612.c | 6 +++--- pico/sound/ym2612.h | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pico/sound/ym2612.c b/pico/sound/ym2612.c index 86dbda251..f8a18625d 100644 --- a/pico/sound/ym2612.c +++ b/pico/sound/ym2612.c @@ -1671,8 +1671,8 @@ static int OPNWriteReg(int r, int v) switch( OPN_SLOT(r) ){ case 0: /* 0xa0-0xa2 : FNUM1 | depends on fn_h (below) */ { - UINT32 fn = (((UINT32)( (CH->fn_h)&7))<<8) + v; - UINT8 blk = CH->fn_h>>3; + UINT32 fn = ((UINT32)(ym2612.OPN.ST.fn_h & 7) << 8) | v; + UINT8 blk = ym2612.OPN.ST.fn_h >> 3; /* keyscale code */ CH->kcode = (blk<<2) | opn_fktable[fn >> 7]; /* phase increment counter */ @@ -1685,7 +1685,7 @@ static int OPNWriteReg(int r, int v) } break; case 1: /* 0xa4-0xa6 : FNUM2,BLK */ - CH->fn_h = v&0x3f; + ym2612.OPN.ST.fn_h = v & 0x3f; ret = 0; break; case 2: /* 0xa8-0xaa : 3CH FNUM1 */ diff --git a/pico/sound/ym2612.h b/pico/sound/ym2612.h index 84263b2bd..b981a428b 100644 --- a/pico/sound/ym2612.h +++ b/pico/sound/ym2612.h @@ -78,7 +78,7 @@ typedef struct UINT8 ams; /* channel AMS */ UINT8 kcode; /* +11 key code: */ - UINT8 fn_h; /* freq latch */ + UINT8 pad2; UINT8 upd_cnt; /* eg update counter */ UINT32 fc; /* fnum,blk:adjusted to sample rate */ UINT32 block_fnum; /* current blk/fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */ @@ -101,7 +101,8 @@ typedef struct int TAC; /* timer a maxval */ int TAT; /* timer a ticker | need_save */ UINT8 TB; /* timer b */ - UINT8 pad2[3]; + UINT8 fn_h; /* freq latch */ + UINT8 pad2[2]; int TBC; /* timer b maxval */ int TBT; /* timer b ticker | need_save */ /* local time tables */ From 724db457da104aa9298bdeb861e540e0e2ab42fd Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 13 Jan 2024 12:07:13 +0100 Subject: [PATCH 30/40] core, handle background color DMA (aka fantom bitmap) --- pico/draw.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++- pico/pico.c | 1 + pico/pico_int.h | 1 + pico/videoport.c | 10 ++++++ 4 files changed, 97 insertions(+), 1 deletion(-) diff --git a/pico/draw.c b/pico/draw.c index 66b4fca5a..40903e74f 100644 --- a/pico/draw.c +++ b/pico/draw.c @@ -1599,7 +1599,59 @@ void BackFill(int bgc, int sh, struct PicoEState *est) // -------------------------------------------- -void PicoDoHighPal555_8bit(int sh, int line, struct PicoEState *est) +static u16 *BgcDMAbase; +static u32 BgcDMAsrc, BgcDMAmask; +static int BgcDMAlen, BgcDMAoffs; + +#ifndef _ASM_DRAW_C +static +#endif +// handle DMA to background color +int BgcDMA(u16 *pd, int len, struct PicoEState *est) +{ + int xl = (len == 320 ? 38 : 33); // DMA slots during HSYNC + int upscale = (est->rendstatus & PDRAW_SOFTSCALE) && len < 320; + + if (BgcDMAlen > 0) { + // BG color DMA under way. TODO for now handles the line as all background. + int i, l = len; + u16 *q = upscale ? DefOutBuff : pd; + u16 t; + + if ((est->rendstatus & PDRAW_BORDER_32) && !upscale) + q += (320-len) / 2; + + BgcDMAlen -= (l>>1)+xl; + if (BgcDMAlen < 0) + // partial line + l += 2*BgcDMAlen; + + for (i = 0; i < l; i += 2) { + // TODO use ps to overwrite only real bg pixels + t = BgcDMAbase[BgcDMAsrc++ & BgcDMAmask]; + q[i] = q[i+1] = PXCONV(t); + } + BgcDMAsrc += xl; // HSYNC DMA + + t = est->HighPal[Pico.video.reg[7] & 0x3f]; + while (i < len) q[i++] = t; // fill partial line with BG + + if (upscale) { + switch (PicoIn.filter) { + case 3: h_upscale_bl4_4_5(pd, 320, q, 256, len, f_nop); break; + case 2: h_upscale_bl2_4_5(pd, 320, q, 256, len, f_nop); break; + case 1: h_upscale_snn_4_5(pd, 320, q, 256, len, f_nop); break; + default: h_upscale_nn_4_5(pd, 320, q, 256, len, f_nop); break; + } + } + return 1; + } + return 0; +} + +// -------------------------------------------- + +static void PicoDoHighPal555_8bit(int sh, int line, struct PicoEState *est) { unsigned int *spal, *dpal; unsigned int cnt = (sh ? 1 : est->SonicPalCount+1); @@ -1695,6 +1747,9 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est) else if ((PicoIn.AHW & PAHW_SMS) && (est->Pico->video.reg[0] & 0x20)) len -= 8, ps += 8; + if (BgcDMA(pd, len, est)) + return; + if ((est->rendstatus & PDRAW_SOFTSCALE) && len < 320) { if (len >= 240 && len <= 256) { pd += (256-len)>>1; @@ -2111,6 +2166,35 @@ void PicoDrawRefreshSprites(void) } } +void PicoDrawBgcDMA(u16 *base, u32 source, u32 mask, int dlen, int sl) +{ + struct PicoEState *est = &Pico.est; + int len = (est->Pico->video.reg[12]&1) ? 320 : 256; + int xl = (est->Pico->video.reg[12]&1) ? 38 : 33; // DMA slots during HSYNC + + BgcDMAbase = base; + BgcDMAsrc = source; + BgcDMAmask = mask; + BgcDMAlen = dlen; + BgcDMAoffs = 0; + + // handle slot offset in 1st line + if (sl-12 > 0) // active display output only starts at slot 12 + BgcDMAoffs = 2*(sl-12); + else if (sl < 0) { // DMA starts before active display + BgcDMAsrc += 2*-sl; + BgcDMAlen -= 2*-sl; + } + + // skip 1st line if it had been drawn already + if (Pico.est.DrawScanline > Pico.m.scanline) { + len -= BgcDMAoffs; + BgcDMAsrc += (len>>1)+xl; + BgcDMAlen -= (len>>1)+xl; + BgcDMAoffs = 0; + } +} + // also works for fast renderer void PicoDrawUpdateHighPal(void) { diff --git a/pico/pico.c b/pico/pico.c index ced4091e7..ad57b6ec8 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -190,6 +190,7 @@ int PicoReset(void) // create an empty "dma" to cause 68k exec start at random frame location Pico.t.m68c_line_start = Pico.t.m68c_aim; + PicoDrawBgcDMA(NULL, 0, 0, 0, 0); PicoVideoFIFOWrite(rand() & 0x1fff, 0, 0, PVS_CPURD); SekFinishIdleDet(); diff --git a/pico/pico_int.h b/pico/pico_int.h index e74a4ac21..0d336822c 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -704,6 +704,7 @@ int CM_compareRun(int cyc, int is_sub); void PicoDrawInit(void); PICO_INTERNAL void PicoFrameStart(void); void PicoDrawRefreshSprites(void); +void PicoDrawBgcDMA(u16 *base, u32 source, u32 mask, int len, int sl); void PicoDrawSync(int to, int blank_last_line, int limit_sprites); void BackFill(int reg7, int sh, struct PicoEState *est); void FinalizeLine555(int sh, int line, struct PicoEState *est); diff --git a/pico/videoport.c b/pico/videoport.c index bd744a3b2..fe8e5ebde 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -522,6 +522,7 @@ static void DmaSlow(int len, u32 source) u32 a = Pico.video.addr | (Pico.video.addr_u << 16), e; u16 *r, *base = NULL; u32 mask = 0x1ffff; + int lc = SekCyclesDone()-Pico.t.m68c_line_start; elprintf(EL_VDPDMA, "DmaSlow[%i] %06x->%04x len %i inc=%i blank %i [%u] @ %06x", Pico.video.type, source, a, len, inc, (Pico.video.status&SR_VB)||!(Pico.video.reg[1]&0x40), @@ -603,6 +604,15 @@ static void DmaSlow(int len, u32 source) case 3: // cram Pico.m.dirtyPal = 1; r = PicoMem.cram; + if (inc == 0 && (Pico.video.reg[7] & 0x3f) == ((a/2) & 0x3f)) { // bg color DMA + PicoVideoSync(1); + int sl = VdpFIFO.fifo_hcounts[lc/clkdiv]; + 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; + PicoDrawBgcDMA(base, source, mask, len, sl); + } for (; len; len--) { r[(a / 2) & 0x3f] = base[source++ & mask] & 0xeee; From dca20effa2dc8d249cb83f86a8880231aaecae11 Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 7 Jan 2024 10:59:24 +0100 Subject: [PATCH 31/40] platforms, revisit Pico ptr handling --- platform/common/emu.c | 26 +++++++++---------- platform/common/emu.h | 3 ++- platform/common/input_pico.h | 6 +++-- platform/common/inputmap_kbd.c | 1 + platform/common/menu_pico.c | 44 +++++++++++++++++++++++-------- platform/common/menu_pico.h | 2 ++ platform/gp2x/emu.c | 47 +++++++++++++++++----------------- platform/libretro/libretro.c | 8 +++--- platform/linux/emu.c | 17 ++++++++++++ platform/pandora/plat.c | 43 +++++++++++++++++-------------- platform/psp/emu.c | 42 +++++++++++++++++------------- 11 files changed, 148 insertions(+), 91 deletions(-) diff --git a/platform/common/emu.c b/platform/common/emu.c index 43c7d0af7..309178c5a 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -1043,8 +1043,6 @@ void emu_reset_game(void) void run_events_pico(unsigned int events) { - int lim_x; - if (events & PEV_PICO_SWINP) { pico_inp_mode++; if (pico_inp_mode > 2) @@ -1069,6 +1067,10 @@ void run_events_pico(unsigned int events) PicoPicohw.page = 6; emu_status_msg("Page %i", PicoPicohw.page); } + if (events & PEV_PICO_PEN) { + currentConfig.EmuOpt ^= EOPT_PICO_PEN; + emu_status_msg("%s Pen", currentConfig.EmuOpt & EOPT_PICO_PEN ? "Show" : "Hide"); + } if (pico_inp_mode == 0) return; @@ -1080,20 +1082,16 @@ void run_events_pico(unsigned int events) if (PicoIn.pad[0] & 8) pico_pen_x++; PicoIn.pad[0] &= ~0x0f; // release UDLR - lim_x = (Pico.video.reg[12]&1) ? 319 : 255; - if (pico_pen_y < 8) - pico_pen_y = 8; + if (pico_pen_y < PICO_PEN_ADJUST_Y) + pico_pen_y = PICO_PEN_ADJUST_Y; if (pico_pen_y > 224 - PICO_PEN_ADJUST_Y) pico_pen_y = 224 - PICO_PEN_ADJUST_Y; - if (pico_pen_x < 0) - pico_pen_x = 0; - if (pico_pen_x > lim_x - PICO_PEN_ADJUST_X) - pico_pen_x = lim_x - PICO_PEN_ADJUST_X; - - PicoPicohw.pen_pos[0] = pico_pen_x; - if (!(Pico.video.reg[12] & 1)) - PicoPicohw.pen_pos[0] += pico_pen_x / 4; - PicoPicohw.pen_pos[0] += 0x3c; + if (pico_pen_x < PICO_PEN_ADJUST_X) + pico_pen_x = PICO_PEN_ADJUST_X; + if (pico_pen_x > 320 - PICO_PEN_ADJUST_X) + pico_pen_x = 320 - PICO_PEN_ADJUST_X; + + PicoPicohw.pen_pos[0] = 0x03c + pico_pen_x; PicoPicohw.pen_pos[1] = pico_inp_mode == 1 ? (0x2f8 + pico_pen_y) : (0x1fc + pico_pen_y); } diff --git a/platform/common/emu.h b/platform/common/emu.h index 287b43d55..d32cf7058 100644 --- a/platform/common/emu.h +++ b/platform/common/emu.h @@ -34,6 +34,7 @@ extern int g_screen_ppitch; // pitch in pixels #define EOPT_NO_FRMLIMIT (1<<18) #define EOPT_WIZ_TEAR_FIX (1<<19) #define EOPT_EXT_FRMLIMIT (1<<20) // no internal frame limiter (limited by snd, etc) +#define EOPT_PICO_PEN (1<<21) enum { EOPT_SCALE_NONE = 0, @@ -106,7 +107,7 @@ extern unsigned char *movie_data; extern int reset_timing; extern int flip_after_sync; -#define PICO_PEN_ADJUST_X 4 +#define PICO_PEN_ADJUST_X 2 #define PICO_PEN_ADJUST_Y 2 extern int pico_pen_x, pico_pen_y; extern int pico_inp_mode; diff --git a/platform/common/input_pico.h b/platform/common/input_pico.h index c0501d33f..b3138d0b3 100644 --- a/platform/common/input_pico.h +++ b/platform/common/input_pico.h @@ -28,7 +28,8 @@ #define PEVB_PICO_PNEXT 21 #define PEVB_PICO_PPREV 20 #define PEVB_PICO_SWINP 19 -#define PEVB_RESET 18 +#define PEVB_PICO_PEN 18 +#define PEVB_RESET 17 #define PEV_VOL_DOWN (1 << PEVB_VOL_DOWN) #define PEV_VOL_UP (1 << PEVB_VOL_UP) @@ -42,8 +43,9 @@ #define PEV_PICO_PNEXT (1 << PEVB_PICO_PNEXT) #define PEV_PICO_PPREV (1 << PEVB_PICO_PPREV) #define PEV_PICO_SWINP (1 << PEVB_PICO_SWINP) +#define PEV_PICO_PEN (1 << PEVB_PICO_PEN) #define PEV_RESET (1 << PEVB_RESET) -#define PEV_MASK 0x7ffc0000 +#define PEV_MASK 0x7ffe0000 #endif /* INCLUDE_c48097f3ff2a6a9af1cce8fd7a9b3f0c */ diff --git a/platform/common/inputmap_kbd.c b/platform/common/inputmap_kbd.c index b6b32be95..038651122 100644 --- a/platform/common/inputmap_kbd.c +++ b/platform/common/inputmap_kbd.c @@ -30,6 +30,7 @@ const struct in_default_bind in_sdl_defbinds[] = { { SDLK_F6, IN_BINDTYPE_EMU, PEVB_PICO_PPREV }, { SDLK_F7, IN_BINDTYPE_EMU, PEVB_PICO_PNEXT }, { SDLK_F8, IN_BINDTYPE_EMU, PEVB_PICO_SWINP }, + { SDLK_F9, IN_BINDTYPE_EMU, PEVB_PICO_PEN }, { SDLK_BACKSPACE, IN_BINDTYPE_EMU, PEVB_FF }, { 0, 0, 0 } }; diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 25d8756d6..4312bf87d 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -366,6 +366,7 @@ me_bind_action emuctrl_actions[] = { "Pico Next page ", PEV_PICO_PNEXT }, { "Pico Prev page ", PEV_PICO_PPREV }, { "Pico Switch input", PEV_PICO_SWINP }, + { "Pico Display pen ", PEV_PICO_PEN }, { NULL, 0 } }; @@ -473,6 +474,7 @@ static menu_entry e_menu_md_options[] = mee_onoff_h ("FM audio", MA_OPT2_ENABLE_YM2612, PicoIn.opt, POPT_EN_FM, h_fmsound), mee_onoff_h ("FM filter", MA_OPT_FM_FILTER, PicoIn.opt, POPT_EN_FM_FILTER, h_fmfilter), mee_onoff_h ("FM DAC noise", MA_OPT2_ENABLE_YM_DAC, PicoIn.opt, POPT_EN_FM_DAC, h_dacnoise), + mee_onoff ("Show Pico pen", MA_OPT_PICO_PEN, currentConfig.EmuOpt, EOPT_PICO_PEN), mee_end, }; @@ -928,14 +930,6 @@ static const char *mgn_opt_region(int id, int *offs) } } -static const char *mgn_saveloadcfg(int id, int *offs) -{ - strcpy(static_buff, " "); - if (config_slot != 0) - sprintf(static_buff, "[%i]", config_slot); - return static_buff; -} - static const char h_hotkeysvld[] = "Slot used for save/load by emulator hotkey"; static menu_entry e_menu_options[] = @@ -1289,6 +1283,34 @@ static int main_menu_handler(int id, int keys) return 0; } +static const char *mgn_picopage(int id, int *offs) +{ + strcpy(static_buff, " "); + sprintf(static_buff, "%i", PicoPicohw.page); + return static_buff; +} + +static int mh_picopage(int id, int keys) +{ + int ret; + + if (keys & (PBTN_LEFT|PBTN_RIGHT)) { // multi choice + PicoPicohw.page += (keys & PBTN_LEFT) ? -1 : 1; + if (PicoPicohw.page < 0) PicoPicohw.page = 6; + else if (PicoPicohw.page > 6) PicoPicohw.page = 0; + return 0; + } + return 1; +} + +static const char *mgn_saveloadcfg(int id, int *offs) +{ + strcpy(static_buff, " "); + if (config_slot != 0) + sprintf(static_buff, "[%i]", config_slot); + return static_buff; +} + static int mh_saveloadcfg(int id, int keys) { int ret; @@ -1330,10 +1352,11 @@ static menu_entry e_menu_main[] = mee_label (""), mee_label (""), mee_handler_id("Resume game", MA_MAIN_RESUME_GAME, main_menu_handler), - mee_handler_id("Save State", MA_MAIN_SAVE_STATE, main_menu_handler), - mee_handler_id("Load State", MA_MAIN_LOAD_STATE, main_menu_handler), + mee_handler_id("Save state", MA_MAIN_SAVE_STATE, main_menu_handler), + mee_handler_id("Load state", MA_MAIN_LOAD_STATE, main_menu_handler), mee_handler_id("Reset game", MA_MAIN_RESET_GAME, main_menu_handler), mee_handler_id("Change CD", MA_MAIN_CHANGE_CD, main_menu_handler), + mee_cust_s_h ("Storyware page", MA_MAIN_PICO_PAGE, 0,mh_picopage, mgn_picopage, NULL), mee_handler_id("Patches / GameGenie",MA_MAIN_PATCHES, main_menu_handler), mee_handler_id("Load new game", MA_MAIN_LOAD_ROM, main_menu_handler), mee_handler ("Change options", menu_loop_options), @@ -1354,6 +1377,7 @@ void menu_loop(void) me_enable(e_menu_main, MA_MAIN_LOAD_STATE, PicoGameLoaded); me_enable(e_menu_main, MA_MAIN_RESET_GAME, PicoGameLoaded); me_enable(e_menu_main, MA_MAIN_CHANGE_CD, PicoIn.AHW & PAHW_MCD); + me_enable(e_menu_main, MA_MAIN_PICO_PAGE, PicoIn.AHW & PAHW_PICO); me_enable(e_menu_main, MA_MAIN_PATCHES, PicoPatches != NULL); me_enable(e_menu_main, MA_OPT_SAVECFG_GAME, PicoGameLoaded); me_enable(e_menu_main, MA_OPT_LOADCFG, PicoGameLoaded && config_slot != config_slot_current); diff --git a/platform/common/menu_pico.h b/platform/common/menu_pico.h index d8c1855c5..1cfae2f18 100644 --- a/platform/common/menu_pico.h +++ b/platform/common/menu_pico.h @@ -12,6 +12,7 @@ typedef enum MA_MAIN_RESET_GAME, MA_MAIN_LOAD_ROM, MA_MAIN_CHANGE_CD, + MA_MAIN_PICO_PAGE, MA_MAIN_CONTROLS, MA_MAIN_CREDITS, MA_MAIN_PATCHES, @@ -49,6 +50,7 @@ typedef enum MA_OPT_SOUND_FILTER, MA_OPT_SOUND_ALPHA, MA_OPT_FM_FILTER, + MA_OPT_PICO_PEN, MA_OPT2_GAMMA, MA_OPT2_A_SN_GAMMA, MA_OPT2_DBLBUFF, /* giz */ diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index 42b30437e..6bc96df78 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -46,6 +46,10 @@ const char *renderer_names[] = { "16bit accurate", " 8bit accurate", " 8bit fast const char *renderer_names32x[] = { "accurate", "faster", "fastest", NULL }; enum renderer_types { RT_16BIT, RT_8BIT_ACC, RT_8BIT_FAST, RT_COUNT }; +static int is_1stblanked; +static int firstline, linecount; +static int firstcol, colcount; + static int (*emu_scan_begin)(unsigned int num) = NULL; static int (*emu_scan_end)(unsigned int num) = NULL; @@ -190,29 +194,30 @@ static void draw_cd_leds(void) static void draw_pico_ptr(void) { - unsigned short *p = (unsigned short *)g_screen_ptr; - int x, y, pitch = 320; + int x, y, pitch = 320, offs; - // only if pen enabled and for 16bit modes - if (pico_inp_mode == 0 || !is_16bit_mode()) - return; - - x = pico_pen_x + PICO_PEN_ADJUST_X; - y = pico_pen_y + PICO_PEN_ADJUST_Y; - if (!(Pico.video.reg[12]&1) && !(PicoIn.opt & POPT_DIS_32C_BORDER)) - x += 32; + x = ((pico_pen_x * colcount * ((1ULL<<32) / 320)) >> 32) + firstcol; + y = ((pico_pen_y * linecount * ((1ULL<<32) / 224)) >> 32) + firstline; if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) { pitch = 240; - p += (319 - x) * pitch + y; + offs = (319 - x) * pitch + y; } else - p += x + y * pitch; + offs = x + y * pitch; + + if (is_16bit_mode()) { + unsigned short *p = (unsigned short *)g_screen_ptr + offs; - p[0] ^= 0xffff; - p[pitch-1] ^= 0xffff; - p[pitch] ^= 0xffff; - p[pitch+1] ^= 0xffff; - p[pitch*2] ^= 0xffff; + p[0] ^= 0xffff; + p[pitch-1] ^= 0xffff; p[pitch] ^= 0xffff; p[pitch+1] ^= 0xffff; + p[pitch*2] ^= 0xffff; + } else { + unsigned char *p = (unsigned char *)g_screen_ptr + offs; + + p[-1] = 0xe0; p[0] = 0xf0; p[1] = 0xe0; + p[pitch-1] = 0xf0; p[pitch] = 0xf0; p[pitch+1] = 0xf0; + p[2*pitch-1] = 0xe0; p[2*pitch] = 0xf0; p[2*pitch+1] = 0xe0; + } } static void clear_1st_column(int firstcol, int firstline, int linecount) @@ -389,10 +394,6 @@ static int make_local_pal_sms(int fast_mode) return (Pico.est.SonicPalCount+1)*0x40; } -static int is_1stblanked; -static int firstline, linecount; -static int firstcol, colcount; - void pemu_finalize_frame(const char *fps, const char *notice) { int emu_opt = currentConfig.EmuOpt; @@ -430,8 +431,8 @@ void pemu_finalize_frame(const char *fps, const char *notice) osd_text(osd_fps_x, osd_y, fps); if ((PicoIn.AHW & PAHW_MCD) && (emu_opt & EOPT_EN_CD_LEDS)) draw_cd_leds(); - if (PicoIn.AHW & PAHW_PICO) - draw_pico_ptr(); + if ((PicoIn.AHW & PAHW_PICO) && (currentConfig.EmuOpt & EOPT_PICO_PEN)) + if (pico_inp_mode) draw_pico_ptr(); } void plat_video_flip(void) diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index 6aae0a34e..adb43993f 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -2086,12 +2086,12 @@ void run_events_pico(unsigned int events) PicoIn.pad[0] &= ~0x0f; // release UDLR lim_x = (Pico.video.reg[12]&1) ? 319 : 255; - if (pico_pen_y < 8) - pico_pen_y = 8; + if (pico_pen_y < PICO_PEN_ADJUST_Y) + pico_pen_y = PICO_PEN_ADJUST_Y; if (pico_pen_y > 224 - PICO_PEN_ADJUST_Y) pico_pen_y = 224 - PICO_PEN_ADJUST_Y; - if (pico_pen_x < 0) - pico_pen_x = 0; + if (pico_pen_x < PICO_PEN_ADJUST_X) + pico_pen_x = PICO_PEN_ADJUST_X; if (pico_pen_x > lim_x - PICO_PEN_ADJUST_X) pico_pen_x = lim_x - PICO_PEN_ADJUST_X; diff --git a/platform/linux/emu.c b/platform/linux/emu.c index f4a1c51ba..9519a6bf7 100644 --- a/platform/linux/emu.c +++ b/platform/linux/emu.c @@ -85,6 +85,21 @@ static void draw_cd_leds(void) #undef p } +static void draw_pico_ptr(void) +{ + int pitch = g_screen_ppitch; + u16 *p = g_screen_ptr; + int x = pico_pen_x, y = pico_pen_y; + + x = (x * out_w * ((1ULL<<32) / 320)) >> 32; + y = (y * out_h * ((1ULL<<32) / 224)) >> 32; + p += (screen_y+y)*pitch + (screen_x+x); + + p[-pitch] ^= 0xffff; + p[-1] ^= 0xffff; p[0] ^= 0xffff; p[1] ^= 0xffff; + p[pitch] ^= 0xffff; +} + /* render/screen buffer handling: * In 16 bit mode, render output is directly placed in the screen buffer. * SW scaling is handled in renderer (x) and in vscaling callbacks here (y). @@ -191,6 +206,8 @@ void pemu_finalize_frame(const char *fps, const char *notice) } } + if ((PicoIn.AHW & PAHW_PICO) && (currentConfig.EmuOpt & EOPT_PICO_PEN)) + if (pico_inp_mode) draw_pico_ptr(); if (notice) emu_osd_text16(4, g_screen_height - 8, notice); if (currentConfig.EmuOpt & EOPT_SHOW_FPS) diff --git a/platform/pandora/plat.c b/platform/pandora/plat.c index e072a266a..575f1612b 100644 --- a/platform/pandora/plat.c +++ b/platform/pandora/plat.c @@ -76,6 +76,7 @@ static struct in_default_bind in_evdev_defbinds[] = { KEY_5, IN_BINDTYPE_EMU, PEVB_PICO_PPREV }, { KEY_6, IN_BINDTYPE_EMU, PEVB_PICO_PNEXT }, { KEY_7, IN_BINDTYPE_EMU, PEVB_PICO_SWINP }, + { KEY_8, IN_BINDTYPE_EMU, PEVB_PICO_PEN }, { 0, 0, 0 } }; @@ -126,29 +127,33 @@ static void draw_cd_leds(void) int old_reg; old_reg = Pico_mcd->s68k_regs[0]; - if (0) { - // 8-bit modes - unsigned int col_g = (old_reg & 2) ? 0xc0c0c0c0 : 0xe0e0e0e0; - unsigned int col_r = (old_reg & 1) ? 0xd0d0d0d0 : 0xe0e0e0e0; - *(unsigned int *)((char *)g_screen_ptr + g_screen_width*2+ 4) = - *(unsigned int *)((char *)g_screen_ptr + g_screen_width*3+ 4) = - *(unsigned int *)((char *)g_screen_ptr + g_screen_width*4+ 4) = col_g; - *(unsigned int *)((char *)g_screen_ptr + g_screen_width*2+12) = - *(unsigned int *)((char *)g_screen_ptr + g_screen_width*3+12) = - *(unsigned int *)((char *)g_screen_ptr + g_screen_width*4+12) = col_r; - } else { - // 16-bit modes - unsigned int *p = (unsigned int *)((short *)g_screen_ptr + g_screen_width*2+4); - unsigned int col_g = (old_reg & 2) ? 0x06000600 : 0; - unsigned int col_r = (old_reg & 1) ? 0xc000c000 : 0; - *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += g_screen_width/2 - 12/2; - *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += g_screen_width/2 - 12/2; - *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; - } + // 16-bit modes + unsigned int *p = (unsigned int *)((short *)g_screen_ptr + g_screen_width*2+4); + unsigned int col_g = (old_reg & 2) ? 0x06000600 : 0; + unsigned int col_r = (old_reg & 1) ? 0xc000c000 : 0; + *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += g_screen_width/2 - 12/2; + *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += g_screen_width/2 - 12/2; + *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; +} + +static void draw_pico_ptr(void) +{ + int x = pico_pen_x, y = pico_pen_y, pitch = g_screen_ppitch; + unsigned short *p = (unsigned short *)g_screen_ptr; + + x = (x * saved_col_count * ((1ULL<<32) / 320)) >> 32; + y = (y * saved_line_count * ((1ULL<<32) / 224)) >> 32; + p += (saved_start_col+x) + (saved_start_line+y) * pitch; + + p[-pitch] ^= 0xffff; + p[-1] ^= 0xffff; p[0] ^= 0xffff; p[1] ^= 0xffff; + p[pitch] ^= 0xffff; } void pemu_finalize_frame(const char *fps, const char *notice) { + if ((PicoIn.AHW & PAHW_PICO) && (currentConfig.EmuOpt & EOPT_PICO_PEN)) + if (pico_inp_mode) draw_pico_ptr(); if (notice && notice[0]) emu_osd_text16(2 + g_osd_start_x, g_osd_y, notice); if (fps && fps[0] && (currentConfig.EmuOpt & EOPT_SHOW_FPS)) diff --git a/platform/psp/emu.c b/platform/psp/emu.c index dbfa0eca2..54773387d 100644 --- a/platform/psp/emu.c +++ b/platform/psp/emu.c @@ -36,9 +36,6 @@ int engineStateSuspend; -#define PICO_PEN_ADJUST_X 4 -#define PICO_PEN_ADJUST_Y 2 - struct Vertex { short u,v; @@ -372,19 +369,26 @@ void blitscreen_clut(void) static void draw_pico_ptr(void) { - unsigned char *p = (unsigned char *)g_screen_ptr + 8; + int x = pico_pen_x, y = pico_pen_y, offs; + + x = (x * out_w * ((1ULL<<32) / 320)) >> 32; + y = (y * out_h * ((1ULL<<32) / 224)) >> 32; - // only if pen enabled and for 8bit mode - if (pico_inp_mode == 0 || is_16bit_mode()) return; + offs = 512 * (out_y+y) + (out_x+x); - p += 512 * (pico_pen_y + PICO_PEN_ADJUST_Y); - p += pico_pen_x + PICO_PEN_ADJUST_X; - if (!(Pico.video.reg[12]&1) && !(PicoIn.opt & POPT_DIS_32C_BORDER)) - p += 32; + if (is_16bit_mode()) { + unsigned short *p = (unsigned short *)g_screen_ptr + offs; - p[ -1] = 0xe0; p[ 0] = 0xf0; p[ 1] = 0xe0; - p[ 511] = 0xf0; p[ 512] = 0xf0; p[ 513] = 0xf0; - p[1023] = 0xe0; p[1024] = 0xf0; p[1025] = 0xe0; + p[ -1] = 0x0000; p[ 0] = 0x001f; p[ 1] = 0x0000; + p[ 511] = 0x001f; p[ 512] = 0x001f; p[ 513] = 0x001f; + p[1023] = 0x0000; p[1024] = 0x001f; p[1025] = 0x0000; + } else { + unsigned char *p = (unsigned char *)g_screen_ptr + offs + 8; + + p[ -1] = 0xe0; p[ 0] = 0xf0; p[ 1] = 0xe0; + p[ 511] = 0xf0; p[ 512] = 0xf0; p[ 513] = 0xf0; + p[1023] = 0xe0; p[1024] = 0xf0; p[1025] = 0xe0; + } } @@ -630,15 +634,17 @@ void pemu_finalize_frame(const char *fps, const char *notice) { int emu_opt = currentConfig.EmuOpt; - if (PicoIn.AHW & PAHW_PICO) - draw_pico_ptr(); + if ((PicoIn.AHW & PAHW_PICO) && (currentConfig.EmuOpt & EOPT_PICO_PEN)) + if (pico_inp_mode) draw_pico_ptr(); osd_buf_cnt = 0; - if (notice) osd_text(4, notice); - if (emu_opt & 2) osd_text(OSD_FPS_X, fps); + if (notice) + osd_text(4, notice); + if (emu_opt & EOPT_SHOW_FPS) + osd_text(OSD_FPS_X, fps); osd_cdleds = 0; - if ((emu_opt & 0x400) && (PicoIn.AHW & PAHW_MCD)) + if ((emu_opt & EOPT_EN_CD_LEDS) && (PicoIn.AHW & PAHW_MCD)) cd_leds(); sceKernelDcacheWritebackAll(); From 214a6c624cd63ea582e278f0dc32ef0f00f0f5c9 Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 13 Jan 2024 16:31:43 +0100 Subject: [PATCH 32/40] core+platforms, add SMS option to select TMS palette for gfx modes 0-3 --- pico/mode4.c | 6 +++++- pico/pico.h | 1 + pico/pico_int.h | 3 ++- platform/common/menu_pico.c | 4 ++++ platform/common/menu_pico.h | 1 + platform/libretro/libretro.c | 9 +++++++++ platform/libretro/libretro_core_options.h | 14 ++++++++++++++ 7 files changed, 36 insertions(+), 2 deletions(-) diff --git a/pico/mode4.c b/pico/mode4.c index 78108ec0d..b396af66a 100644 --- a/pico/mode4.c +++ b/pico/mode4.c @@ -741,6 +741,10 @@ void PicoFrameStartSMS(void) Pico.m.dirtyPal = 1; } + Pico.m.hardware &= ~PMS_HW_TMS; + if (PicoIn.tmsPalette || (PicoIn.AHW & (PAHW_SG|PAHW_SC))) + Pico.m.hardware |= PMS_HW_TMS; + // Copy LCD enable flag for easier handling Pico.m.hardware &= ~PMS_HW_LCD; if ((PicoIn.opt & POPT_EN_GG_LCD) && (PicoIn.AHW & PAHW_GG)) { @@ -886,7 +890,7 @@ void PicoDoHighPal555SMS(void) * hence GG/SMS/TMS can all be handled the same here */ for (j = cnt; j > 0; j--) { if (!(Pico.video.reg[0] & 0x4)) // fixed palette in TMS modes - spal = (u32 *)tmspal + (PicoIn.AHW & (PAHW_SG|PAHW_SC) ? 16/2:0); + spal = (u32 *)tmspal + (Pico.m.hardware & PMS_HW_TMS ? 16/2:0); for (i = 0x20/2; i > 0; i--, spal++, dpal++) { t = *spal; #if defined(USE_BGR555) diff --git a/pico/pico.h b/pico/pico.h index f17d93ded..e45540c3d 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -116,6 +116,7 @@ typedef struct PicoInterface unsigned short autoRgnOrder; // packed priority list of regions, for example 0x148 means this detection order: EUR, USA, JAP unsigned int hwSelect; // hardware preselected via option menu unsigned int mapper; // mapper selection for SMS, 0 = auto + unsigned int tmsPalette; // palette used by SMS in TMS graphic modes unsigned short quirks; // game-specific quirks: PQUIRK_* unsigned short overclockM68k; // overclock the emulated 68k, in % diff --git a/pico/pico_int.h b/pico/pico_int.h index 0d336822c..9ccfddb7f 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -346,7 +346,8 @@ struct PicoMisc #define PMS_HW_LCD 0x2 // GG LCD #define PMS_HW_JAP 0x4 // japanese system #define PMS_HW_FM 0x8 // FM sound -#define PMS_HW_FMUSED 0x10 // FM sound accessed +#define PMS_HW_TMS 0x10 // assume TMS9918 +#define PMS_HW_FMUSED 0x80 // FM sound accessed #define PMS_MAP_AUTO 0 #define PMS_MAP_SEGA 1 diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 4312bf87d..1492738ad 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -577,10 +577,13 @@ 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 h_smsfm[] = "FM sound is only supported by few games,\n" "some games may crash with FM enabled"; static const char h_ghost[] = "Simulate the inertia of the GG LCD display"; +static const char h_smspal[] = "Selects the color palette used for SMS games\n" + "using the original TMS9918 graphics modes"; static menu_entry e_menu_sms_options[] = { @@ -588,6 +591,7 @@ static menu_entry e_menu_sms_options[] = mee_enum ("Cartridge mapping", MA_SMSOPT_MAPPER, PicoIn.mapper, sms_mappers), mee_enum_h ("Game Gear LCD ghosting", MA_SMSOPT_GHOSTING, currentConfig.ghosting, gg_ghosting_opts, h_ghost), mee_onoff_h ("FM Sound Unit", MA_OPT2_ENABLE_YM2413, PicoIn.opt, POPT_EN_YM2413, h_smsfm), + mee_enum_h ("SMS palette in TMS mode", MA_SMSOPT_TMSPALETTE, PicoIn.tmsPalette, sms_tmspalette, h_smspal), mee_end, }; diff --git a/platform/common/menu_pico.h b/platform/common/menu_pico.h index 1cfae2f18..59e6af80b 100644 --- a/platform/common/menu_pico.h +++ b/platform/common/menu_pico.h @@ -99,6 +99,7 @@ typedef enum MA_SMSOPT_HARDWARE, MA_SMSOPT_MAPPER, MA_SMSOPT_GHOSTING, + MA_SMSOPT_TMSPALETTE, MA_CTRL_PLAYER1, MA_CTRL_PLAYER2, MA_CTRL_PLAYER3, diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index adb43993f..600c01598 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -1814,6 +1814,15 @@ static void update_variables(bool first_run) PicoIn.opt &= ~POPT_EN_YM2413; } + var.value = NULL; + var.key = "picodrive_smstms"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + if (strcmp(var.value, "SG-1000") == 0) + PicoIn.tmsPalette = 1; + else + PicoIn.tmsPalette = 0; + } + var.value = NULL; var.key = "picodrive_smsmapper"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { diff --git a/platform/libretro/libretro_core_options.h b/platform/libretro/libretro_core_options.h index 1e1d4c4bf..a5f7cb8cb 100644 --- a/platform/libretro/libretro_core_options.h +++ b/platform/libretro/libretro_core_options.h @@ -145,6 +145,20 @@ struct retro_core_option_v2_definition option_defs_us[] = { }, "Auto" }, + { + "picodrive_smstms", + "Master System Palette in TMS modes", + NULL, + "Choose which colour palette should be used when an SMS game runs in one of the SG-1000 graphics modes.", + NULL, + "system", + { + { "SMS", NULL }, + { "SG-1000", NULL }, + { NULL, NULL }, + }, + "SMS" + }, { "picodrive_ramcart", "Sega CD RAM Cart", From ba2b97dc24bf1ea054da06d2e7f4fe699e6ce189 Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 20 Jan 2024 17:15:51 +0100 Subject: [PATCH 33/40] core, fix Pico horizontal irq (on irq level 5) --- pico/pico.c | 1 + pico/pico_cmn.c | 4 ++-- pico/pico_int.h | 2 +- pico/sek.c | 3 ++- pico/videoport.c | 7 ++++--- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/pico/pico.c b/pico/pico.c index ad57b6ec8..cc5ef7cc8 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -185,6 +185,7 @@ int PicoReset(void) PicoDetectRegion(); Pico.video.status = 0x3428 | Pico.m.pal; // 'always set' bits | vblank | collision | pal + Pico.video.hint_irq = (PicoIn.AHW & PAHW_PICO ? 5 : 4); PsndReset(); // pal must be known here diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index 5a7354493..d51477f1a 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -105,8 +105,8 @@ static void do_hint(struct PicoVideo *pv) pv->pending_ints |= 0x10; if (pv->reg[0] & 0x10) { elprintf(EL_INTS, "hint: @ %06x [%u]", SekPc, SekCyclesDone()); - if (SekIrqLevel < 4) - SekInterrupt(4); + if (SekIrqLevel < pv->hint_irq) + SekInterrupt(pv->hint_irq); } } diff --git a/pico/pico_int.h b/pico/pico_int.h index 9ccfddb7f..cbf61e43b 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -312,7 +312,7 @@ struct PicoVideo unsigned char debug_p; // ... parsed: PVD_* unsigned char addr_u; // bit16 of .addr unsigned char hint_cnt; - unsigned char pad2; + unsigned char hint_irq; // irq# of HINT (4 on MD, 5 on Pico) unsigned short hv_latch; // latched hvcounter value signed int fifo_cnt; // pending xfers for blocking FIFO queue entries signed int fifo_bgcnt; // pending xfers for background FIFO queue entries diff --git a/pico/sek.c b/pico/sek.c index 4dd0b4abe..236d03fe4 100644 --- a/pico/sek.c +++ b/pico/sek.c @@ -35,7 +35,8 @@ static int do_ack(int level) if (pv->pending_ints & pv->reg[1] & 0x20) { pv->pending_ints &= ~0x20; pv->status &= ~SR_F; - return (pv->reg[0] & pv->pending_ints & 0x10) >> 2; + if (pv->reg[0] & pv->pending_ints & 0x10) + return pv->hint_irq; } else if (pv->pending_ints & pv->reg[0] & 0x10) pv->pending_ints &= ~0x10; diff --git a/pico/videoport.c b/pico/videoport.c index fe8e5ebde..dcfc58c8c 100644 --- a/pico/videoport.c +++ b/pico/videoport.c @@ -979,7 +979,7 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d) } SATaddr = ((pvid->reg[5]&0x7f) << 9) | ((pvid->reg[6]&0x20) << 11); SATmask = ~0x1ff; - if (Pico.video.reg[12]&1) + if (pvid->reg[12]&1) SATaddr &= ~0x200, SATmask &= ~0x200; // H40, zero lowest SAT bit //elprintf(EL_STATUS, "spritep moved to %04x", SATaddr); return; @@ -993,8 +993,9 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d) lines = (pvid->reg[1] & 0x20) | (pvid->reg[0] & 0x10); pints = pvid->pending_ints & lines; if (pints & 0x20) irq = 6; - else if (pints & 0x10) irq = 4; - SekInterrupt(irq); // update line + else if (pints & 0x10) irq = pvid->hint_irq; + if (SekIrqLevel < irq) + SekInterrupt(irq); // update line // this is broken because cost of current insn isn't known here if (irq) SekEndRun(21); // make it delayed From e348af76ec2d0ae83c7178307425d9305ecaa258 Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 20 Jan 2024 17:23:44 +0100 Subject: [PATCH 34/40] core, revisit Pico sound handling --- pico/pico_int.h | 2 ++ pico/sound/sn76496.c | 7 +++---- pico/sound/sound.c | 40 ++++++++++++++++++++++++++++++++-------- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/pico/pico_int.h b/pico/pico_int.h index cbf61e43b..52734c621 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -475,6 +475,7 @@ struct PicoSound unsigned int fm_pos; // last FM position in Q20 unsigned int psg_pos; // last PSG position in Q16 unsigned int ym2413_pos; // last YM2413 position + unsigned int pcm_pos; // last PCM position in Q16 unsigned int fm_fir_mul, fm_fir_div; // ratio for FM resampling FIR }; @@ -975,6 +976,7 @@ PICO_INTERNAL void PsndDoDAC(int cycle_to); PICO_INTERNAL void PsndDoPSG(int cyc_to); PICO_INTERNAL void PsndDoYM2413(int cyc_to); PICO_INTERNAL void PsndDoFM(int cyc_to); +PICO_INTERNAL void PsndDoPCM(int cyc_to); PICO_INTERNAL void PsndClear(void); PICO_INTERNAL void PsndGetSamples(int y); PICO_INTERNAL void PsndGetSamplesMS(int y); diff --git a/pico/sound/sn76496.c b/pico/sound/sn76496.c index cb3831181..3bb5cf741 100644 --- a/pico/sound/sn76496.c +++ b/pico/sound/sn76496.c @@ -208,10 +208,9 @@ void SN76496Update(short *buffer, int length, int stereo) if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP; - if ((out /= STEP)) // will be optimized to shift; max 0x4800 = 18432 - *buffer += out; - if(stereo) buffer+=2; // only left for stereo, to be mixed to right later - else buffer++; + out /= STEP; // will be optimized to shift; max 0x4800 = 18432 + *buffer++ += out; + if (stereo) *buffer++ += out; length--; } diff --git a/pico/sound/sound.c b/pico/sound/sound.c index c31c2cf4c..5d7fac630 100644 --- a/pico/sound/sound.c +++ b/pico/sound/sound.c @@ -269,9 +269,6 @@ PICO_INTERNAL void PsndDoDAC(int cyc_to) if (len <= 0) return; - if (!PicoIn.sndOut) - return; - // fill buffer, applying a rather weak order 1 bessel IIR on the way // y[n] = (x[n] + x[n-1])*(1/2) (3dB cutoff at 11025 Hz, no gain) // 1 sample delay for correct IIR filtering over audio frame boundaries @@ -307,7 +304,7 @@ PICO_INTERNAL void PsndDoPSG(int cyc_to) if (len <= 0) return; - if (!PicoIn.sndOut || !(PicoIn.opt & POPT_EN_PSG)) + if (!(PicoIn.opt & POPT_EN_PSG)) return; if (PicoIn.opt & POPT_EN_STEREO) { @@ -337,7 +334,7 @@ PICO_INTERNAL void PsndDoSMSFM(int cyc_to) if (len <= 0) return; - if (!PicoIn.sndOut || !(PicoIn.opt & POPT_EN_YM2413)) + if (!(PicoIn.opt & POPT_EN_YM2413)) return; if (PicoIn.opt & POPT_EN_STEREO) { @@ -382,6 +379,32 @@ PICO_INTERNAL void PsndDoFM(int cyc_to) PsndFMUpdate(PsndBuffer + pos, len, stereo, 1); } +PICO_INTERNAL void PsndDoPCM(int cyc_to) +{ + int pos, len; + int stereo = 0; + + // nothing to do if sound is off + if (!PicoIn.sndOut) return; + + // Q20, number of samples since last call + len = (cyc_to * Pico.snd.clkl_mult) - Pico.snd.pcm_pos; + + // update position and calculate buffer offset and length + pos = (Pico.snd.pcm_pos+0x80000) >> 20; + Pico.snd.pcm_pos += len; + len = ((Pico.snd.pcm_pos+0x80000) >> 20) - pos; + if (len <= 0) + return; + + // fill buffer + if (PicoIn.opt & POPT_EN_STEREO) { + stereo = 1; + pos <<= 1; + } + PicoPicoPCMUpdate(PicoIn.sndOut + pos, len, stereo); +} + // cdda static void cdda_raw_update(s32 *buffer, int length, int stereo) { @@ -434,7 +457,7 @@ PICO_INTERNAL void PsndClear(void) if (Pico.snd.len_e_add) len++; // drop pos remainder to avoid rounding errors (not entirely correct though) - Pico.snd.dac_pos = Pico.snd.fm_pos = Pico.snd.psg_pos = Pico.snd.ym2413_pos = 0; + Pico.snd.dac_pos = Pico.snd.fm_pos = Pico.snd.psg_pos = Pico.snd.ym2413_pos = Pico.snd.pcm_pos = 0; if (!PicoIn.sndOut) return; if (PicoIn.opt & POPT_EN_STEREO) @@ -457,6 +480,7 @@ static int PsndRender(int offset, int length) int fmlen = ((Pico.snd.fm_pos+0x80000) >> 20); int daclen = ((Pico.snd.dac_pos+0x80000) >> 20); int psglen = ((Pico.snd.psg_pos+0x80000) >> 20); + int pcmlen = ((Pico.snd.pcm_pos+0x80000) >> 20); buf32 = PsndBuffer+(offset< Date: Sat, 20 Jan 2024 17:29:22 +0100 Subject: [PATCH 35/40] core, fix Pico hardware region code --- pico/pico/pico.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pico/pico/pico.c b/pico/pico/pico.c index 077b9b21f..1266ce87b 100644 --- a/pico/pico/pico.c +++ b/pico/pico/pico.c @@ -95,9 +95,9 @@ PICO_INTERNAL void PicoInitPico(void) // map version register PicoDetectRegion(); switch (Pico.m.hardware >> 6) { - case 0: PicoPicohw.r1 = 0x00; break; + case 0: PicoPicohw.r1 = 0x40; break; case 1: PicoPicohw.r1 = 0x00; break; - case 2: PicoPicohw.r1 = 0x40; break; + case 2: PicoPicohw.r1 = 0x60; break; case 3: PicoPicohw.r1 = 0x20; break; } } From f1b425e380dde381d4e7e0684b3f6a387866ccbf Mon Sep 17 00:00:00 2001 From: kub Date: Sat, 20 Jan 2024 17:48:16 +0100 Subject: [PATCH 36/40] core, complete rewrite of Pico adpcm driver --- pico/pico/memory.c | 73 ++++++----- pico/pico/pico.c | 86 ++++--------- pico/pico/xpcm.c | 303 ++++++++++++++++++++++++++++++++++----------- pico/pico_int.h | 10 +- pico/sek.c | 2 +- 5 files changed, 303 insertions(+), 171 deletions(-) diff --git a/pico/pico/memory.c b/pico/pico/memory.c index 14bf5d438..f294b037f 100644 --- a/pico/pico/memory.c +++ b/pico/pico/memory.c @@ -1,6 +1,7 @@ /* * PicoDrive * (C) notaz, 2008 + * (C) irixxxx, 2024 * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. @@ -24,49 +25,43 @@ void dump(u16 w) } */ -static u32 PicoRead8_pico(u32 a) +static u32 PicoRead16_pico(u32 a) { u32 d = 0; - if ((a & 0xffffe0) == 0x800000) // Pico I/O + switch (a & 0x1e) { - switch (a & 0x1f) - { - case 0x01: d = PicoPicohw.r1; break; - case 0x03: - d = PicoIn.pad[0]&0x1f; // d-pad - d |= (PicoIn.pad[0]&0x20) << 2; // pen push -> C - d = ~d; - break; - - case 0x05: d = (PicoPicohw.pen_pos[0] >> 8); break; // what is MS bit for? Games read it.. - case 0x07: d = PicoPicohw.pen_pos[0] & 0xff; break; - case 0x09: d = (PicoPicohw.pen_pos[1] >> 8); break; - case 0x0b: d = PicoPicohw.pen_pos[1] & 0xff; break; - case 0x0d: d = (1 << (PicoPicohw.page & 7)) - 1; break; - case 0x12: d = PicoPicohw.fifo_bytes == 0 ? 0x80 : 0; break; // guess - default: - goto unhandled; - } - return d; + case 0x00: d = PicoPicohw.r1; break; + case 0x02: d = PicoIn.pad[0]&0x1f; // d-pad + d |= (PicoIn.pad[0]&0x20) << 2; // pen push -> C + d = ~d; + break; + case 0x04: d = (PicoPicohw.pen_pos[0] >> 8); break; // what is MS bit for? Games read it.. + case 0x06: d = PicoPicohw.pen_pos[0] & 0xff; break; + case 0x08: d = (PicoPicohw.pen_pos[1] >> 8); break; + case 0x0a: d = PicoPicohw.pen_pos[1] & 0xff; break; + case 0x0c: d = (1 << (PicoPicohw.page & 7)) - 1; break; + case 0x10: d = (PicoPicohw.fifo_bytes > 0x3f) ? 0 : (0x3f - PicoPicohw.fifo_bytes); break; + case 0x12: d = (PicoPicohw.fifo_bytes | !PicoPicoPCMBusyN()) ? 0 : 0x8000; + d |= PicoPicohw.r12 & 0x7fff; + break; + default: elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc); break; } - -unhandled: - elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc); return d; } -static u32 PicoRead16_pico(u32 a) +static u32 PicoRead8_pico(u32 a) { u32 d = 0; - if (a == 0x800010) - d = (PicoPicohw.fifo_bytes > 0x3f) ? 0 : (0x3f - PicoPicohw.fifo_bytes); - else if (a == 0x800012) - d = PicoPicohw.fifo_bytes == 0 ? 0x8000 : 0; // guess - else - elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc); + if ((a & 0xffffe0) == 0x800000) // Pico I/O + { + d = PicoRead16_pico(a); + if (!(a & 1)) d >>= 8; + return d & 0xff; + } + elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc); return d; } @@ -97,10 +92,20 @@ static void PicoWrite16_pico(u32 a, u32 d) } } else if (a == 0x800012) { - int r12_old = PicoPicohw.r12; PicoPicohw.r12 = d; - if (r12_old != d) - PicoReratePico(); + + PicoPicoPCMGain(8 - (d & 0x0007)); // volume + PicoPicoPCMFilter((d & 0x00c0) >> 6); // low pass filter + PicoPicoPCMIrqEn(d & 0x4000); // PCM IRQ enable + + if (d & 0x8000) { // PCM reset if 1 is written (dalmatians)? + PsndDoPCM(cycles_68k_to_z80(SekCyclesDone() - Pico.t.m68c_frame_start)); + PicoPicoPCMResetN(0); + PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer; + PicoPicohw.fifo_bytes = 0; + PicoPicoPCMResetN(1); + } + // other bits used in software: 0x3f00. } else elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); diff --git a/pico/pico/pico.c b/pico/pico/pico.c index 1266ce87b..81d535abe 100644 --- a/pico/pico/pico.c +++ b/pico/pico/pico.c @@ -1,6 +1,7 @@ /* * PicoDrive * (C) notaz, 2008 + * (C) irixxxx, 2024 * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. @@ -12,72 +13,40 @@ // 0x2f8 - 0x3f3 picohw_state PicoPicohw; -static int prev_line_cnt_irq3 = 0, prev_line_cnt_irq5 = 0; -static int fifo_bytes_line = (16000<<16)/60/262/2; -static const int guessed_rates[] = { 8000, 14000, 12000, 14000, 16000, 18000, 16000, 16000 }; // ? - -#define PICOHW_FIFO_IRQ_THRESHOLD 12 PICO_INTERNAL void PicoReratePico(void) { - int rate = guessed_rates[PicoPicohw.r12 & 7]; - if (Pico.m.pal) - fifo_bytes_line = (rate<<16)/50/313/2; - else fifo_bytes_line = (rate<<16)/60/262/2; - PicoPicoPCMRerate(rate); + PicoPicoPCMRerate(); } static void PicoLinePico(void) { - PicoPicohw.line_counter++; - -#if 1 - if ((PicoPicohw.r12 & 0x4003) && PicoPicohw.line_counter - prev_line_cnt_irq3 > 200) { - prev_line_cnt_irq3 = PicoPicohw.line_counter; - // just a guess/hack, allows 101 Dalmantians to boot - elprintf(EL_PICOHW, "irq3"); - SekInterrupt(3); - return; - } -#endif - - if (PicoPicohw.fifo_bytes > 0) - { - PicoPicohw.fifo_line_bytes += fifo_bytes_line; - if (PicoPicohw.fifo_line_bytes >= (1<<16)) { - PicoPicohw.fifo_bytes -= PicoPicohw.fifo_line_bytes >> 16; - PicoPicohw.fifo_line_bytes &= 0xffff; - if (PicoPicohw.fifo_bytes < 0) - PicoPicohw.fifo_bytes = 0; - } - } - else - PicoPicohw.fifo_line_bytes = 0; - -#if 1 - if (PicoPicohw.fifo_bytes_prev >= PICOHW_FIFO_IRQ_THRESHOLD && - PicoPicohw.fifo_bytes < PICOHW_FIFO_IRQ_THRESHOLD) { - prev_line_cnt_irq3 = PicoPicohw.line_counter; // ? - elprintf(EL_PICOHW, "irq3, fb=%i", PicoPicohw.fifo_bytes); - SekInterrupt(3); - } - PicoPicohw.fifo_bytes_prev = PicoPicohw.fifo_bytes; -#endif - -#if 0 - if (PicoPicohw.line_counter - prev_line_cnt_irq5 > 512) { - prev_line_cnt_irq5 = PicoPicohw.line_counter; - elprintf(EL_PICOHW, "irq5"); - SekInterrupt(5); - } -#endif + // update sound so that irq for FIFO refill is generated + if ((PicoPicohw.fifo_bytes | !PicoPicoPCMBusyN()) && (Pico.m.scanline & 7) == 7) + PsndDoPCM(cycles_68k_to_z80(SekCyclesDone() - Pico.t.m68c_frame_start)); } static void PicoResetPico(void) { - PicoPicoPCMReset(); + PicoPicoPCMResetN(1); + PicoPicoPCMStartN(1); PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer; + PicoPicohw.fifo_bytes = 0; + PicoPicohw.r12 = 0; + + PicoPicoPCMIrqEn(0); + PicoPicoPCMFilter(0); + PicoPicoPCMGain(8); + + // map version register + PicoDetectRegion(); + switch (Pico.m.hardware >> 6) { + case 0: PicoPicohw.r1 = 0x40; break; // JP NTSC + case 1: PicoPicohw.r1 = 0x00; break; // JP PAL + case 2: PicoPicohw.r1 = 0x60; break; // US + case 3: PicoPicohw.r1 = 0x20; break; // EU + } } PICO_INTERNAL void PicoInitPico(void) @@ -90,15 +59,4 @@ PICO_INTERNAL void PicoInitPico(void) memset(&PicoPicohw, 0, sizeof(PicoPicohw)); PicoPicohw.pen_pos[0] = 0x03c + 320/2; PicoPicohw.pen_pos[1] = 0x200 + 240/2; - prev_line_cnt_irq3 = prev_line_cnt_irq5 = 0; - - // map version register - PicoDetectRegion(); - switch (Pico.m.hardware >> 6) { - case 0: PicoPicohw.r1 = 0x40; break; - case 1: PicoPicohw.r1 = 0x00; break; - case 2: PicoPicohw.r1 = 0x60; break; - case 3: PicoPicohw.r1 = 0x20; break; - } } - diff --git a/pico/pico/xpcm.c b/pico/pico/xpcm.c index 5d13a4b75..ef0f8701e 100644 --- a/pico/pico/xpcm.c +++ b/pico/pico/xpcm.c @@ -1,122 +1,285 @@ /* * PicoDrive * (C) notaz, 2008 + * (C) irixxxx, 2024 * * This work is licensed under the terms of MAME license. * See COPYING file in the top-level directory. * - * The following ADPCM algorithm was stolen from MAME aica driver. - * I'm quite sure it's not the right one, but it's the - * best sounding of the ones that I tried. + * The following ADPCM algorithm was derived from MAME upd7759 driver. */ +#include #include "../pico_int.h" -#define ADPCMSHIFT 8 -#define ADFIX(f) (int) ((double)f * (double)(1< max ) val = max; \ - else if ( val < min ) val = min; \ -} +#define Limit(val, max, min) \ + (val > max ? max : val < min ? min : val) + +#define ADPCM_CLOCK (1280000/4) + +#define FIFO_IRQ_THRESHOLD 16 -static const int TableQuant[8] = +static const int step_deltas[16][16] = { - ADFIX(0.8984375), - ADFIX(0.8984375), - ADFIX(0.8984375), - ADFIX(0.8984375), - ADFIX(1.19921875), - ADFIX(1.59765625), - ADFIX(2.0), - ADFIX(2.3984375) + { 0, 0, 1, 2, 3, 5, 7, 10, 0, 0, -1, -2, -3, -5, -7, -10 }, + { 0, 1, 2, 3, 4, 6, 8, 13, 0, -1, -2, -3, -4, -6, -8, -13 }, + { 0, 1, 2, 4, 5, 7, 10, 15, 0, -1, -2, -4, -5, -7, -10, -15 }, + { 0, 1, 3, 4, 6, 9, 13, 19, 0, -1, -3, -4, -6, -9, -13, -19 }, + { 0, 2, 3, 5, 8, 11, 15, 23, 0, -2, -3, -5, -8, -11, -15, -23 }, + { 0, 2, 4, 7, 10, 14, 19, 29, 0, -2, -4, -7, -10, -14, -19, -29 }, + { 0, 3, 5, 8, 12, 16, 22, 33, 0, -3, -5, -8, -12, -16, -22, -33 }, + { 1, 4, 7, 10, 15, 20, 29, 43, -1, -4, -7, -10, -15, -20, -29, -43 }, + { 1, 4, 8, 13, 18, 25, 35, 53, -1, -4, -8, -13, -18, -25, -35, -53 }, + { 1, 6, 10, 16, 22, 31, 43, 64, -1, -6, -10, -16, -22, -31, -43, -64 }, + { 2, 7, 12, 19, 27, 37, 51, 76, -2, -7, -12, -19, -27, -37, -51, -76 }, + { 2, 9, 16, 24, 34, 46, 64, 96, -2, -9, -16, -24, -34, -46, -64, -96 }, + { 3, 11, 19, 29, 41, 57, 79, 117, -3, -11, -19, -29, -41, -57, -79, -117 }, + { 4, 13, 24, 36, 50, 69, 96, 143, -4, -13, -24, -36, -50, -69, -96, -143 }, + { 4, 16, 29, 44, 62, 85, 118, 175, -4, -16, -29, -44, -62, -85, -118, -175 }, + { 6, 20, 36, 54, 76, 104, 144, 214, -6, -20, -36, -54, -76, -104, -144, -214 }, }; -// changed using trial and error.. -//static const int quant_mul[16] = { 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15 }; -static const int quant_mul[16] = { 1, 3, 5, 7, 9, 11, 13, -1, -1, -3, -5, -7, -9, -11, -13, -15 }; +static const int state_deltas[16] = { -1, -1, 0, 0, 1, 2, 2, 3, -1, -1, 0, 0, 1, 2, 2, 3 }; + +static int sample = 0, state = 0; +static s32 stepsamples = (44100LL<<16)/ADPCM_CLOCK; +static s32 samplepos; +static int samplegain; + +static int startpin, irqenable; +static enum { RESET, START, HDR, COUNT } portstate = RESET; +static int rate, silence, nibbles, highlow, cache; + + +// SEGA Pico specific filtering + +#define QB 16 // mantissa bits +#define FP(f) (int)((f)*(1<= rate/2) { + memset(iir, 0, sizeof(*iir)); + return; + } + + // compute 2nd order butterworth filter coefficients + double a = 1 / tan(M_PI * cutoff / rate); + double axa = a*a; + double gain = 1/(1 + M_SQRT2*a + axa); + iir->gain = FP(gain); + iir->a[0] = FP(2 * (axa-1) * gain); + iir->a[1] = FP(-(1 - M_SQRT2*a + axa) * gain); +} + +static int PicoPicoFilterApply(struct iir2 *iir, int sample) +{ + if (!iir) + return sample; + + iir->x[0] = iir->x[1]; iir->x[1] = iir->x[2]; + iir->x[2] = sample * iir->gain; // Qb + iir->y[0] = iir->y[1]; iir->y[1] = iir->y[2]; + iir->y[2] = (iir->x[0] + 2*iir->x[1] + iir->x[2] + + iir->y[0]*iir->a[1] + iir->y[1]*iir->a[0]) >> QB; + return iir->y[2]; +} + + +// pin functions, N designating a negated pin + +PICO_INTERNAL void PicoPicoPCMResetN(int pin) +{ + if (!pin) { + portstate = RESET; + sample = samplepos = state = 0; + portstate = nibbles = silence = 0; + } else if (portstate == RESET) + portstate = START; +} + +PICO_INTERNAL void PicoPicoPCMStartN(int pin) +{ + startpin = pin; +} + +PICO_INTERNAL int PicoPicoPCMBusyN(void) +{ + return (portstate <= START); +} + + +// configuration functions + +PICO_INTERNAL void PicoPicoPCMRerate(void) +{ + // output samples per chip clock + stepsamples = ((u64)PicoIn.sndRate<<16)/ADPCM_CLOCK; -static int sample = 0, quant = 0, sgn = 0; -static int stepsamples = (44100<<10)/16000; + // compute filter coefficients, cutoff at half the ADPCM sample rate + PicoPicoFilterCoeff(&filters[1], 5000/2, PicoIn.sndRate); // 5-6 KHz + PicoPicoFilterCoeff(&filters[2], 8000/2, PicoIn.sndRate); // 8-12 KHz + PicoPicoFilterCoeff(&filters[3], 14000/2, PicoIn.sndRate); // 14-16 KHz +} +PICO_INTERNAL void PicoPicoPCMGain(int gain) +{ + samplegain = gain*4; +} + +PICO_INTERNAL void PicoPicoPCMFilter(int index) +{ + filter = filters+index; + if (filter->a[0] == 0) + filter = NULL; +} -PICO_INTERNAL void PicoPicoPCMReset(void) +PICO_INTERNAL void PicoPicoPCMIrqEn(int enable) { - sample = sgn = 0; - quant = 0x7f; - memset(PicoPicohw.xpcm_buffer, 0, sizeof(PicoPicohw.xpcm_buffer)); + irqenable = (enable ? 3 : 0); } -PICO_INTERNAL void PicoPicoPCMRerate(int xpcm_rate) +// TODO need an interupt pending mask? +PICO_INTERNAL int PicoPicoIrqAck(int level) { - stepsamples = (PicoIn.sndRate<<10)/xpcm_rate; + return (PicoPicohw.fifo_bytes < FIFO_IRQ_THRESHOLD && level != irqenable ? irqenable : 0); } -#define XSHIFT 6 -#define do_sample() \ +// adpcm operation + +#define apply_filter(v) PicoPicoFilterApply(filter, v) + +#define do_sample(nibble) \ { \ - int delta = quant * quant_mul[srcval] >> XSHIFT; \ - sample += delta - (delta >> 2); /* 3/4 */ \ - quant = (quant * TableQuant[srcval&7]) >> ADPCMSHIFT; \ - Limit(quant, 0x6000, 0x7f); \ - Limit(sample, 32767*3/4, -32768*3/4); \ + sample += step_deltas[state][nibble]; \ + state += state_deltas[nibble]; \ + state = (state < 0 ? 0 : state > 15 ? 15 : state); \ +} + +#define write_sample(buffer, length, stereo) \ +{ \ + while (samplepos > 0 && length > 0) { \ + int val = Limit(samplegain*sample, 16383, -16384); \ + samplepos -= 1<<16; \ + length --; \ + if (buffer) { \ + int out = apply_filter(val); \ + *buffer++ += out; \ + if (stereo) *buffer++ += out; \ + } \ + } \ } PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo) { unsigned char *src = PicoPicohw.xpcm_buffer; unsigned char *lim = PicoPicohw.xpcm_ptr; - int srcval, needsamples = 0; + int srcval, irq = 0; - if (src == lim) goto end; + // leftover partial sample from last run + write_sample(buffer, length, stereo); - for (; length > 0 && src < lim; src++) + // loop over FIFO data, generating ADPCM samples + while (length > 0 && src < lim) { - srcval = *src >> 4; - do_sample(); + if (silence > 0) { + silence --; + sample = 0; + samplepos += stepsamples*256; - if (buffer) - for (needsamples += stepsamples; needsamples > (1<<10) && length > 0; needsamples -= (1<<10), length--) { - *buffer++ += sample; - if (stereo) { buffer[0] = buffer[-1]; buffer++; } - } + } else if (nibbles > 0) { + nibbles --; + + if (highlow) + cache = *src++; + else + cache <<= 4; + highlow = !highlow; - srcval = *src & 0xf; - do_sample(); + do_sample((cache & 0xf0) >> 4); + samplepos += stepsamples*rate; - if (buffer) - for (needsamples += stepsamples; needsamples > (1<<10) && length > 0; needsamples -= (1<<10), length--) { - *buffer++ += sample; - if (stereo) { buffer[0] = buffer[-1]; buffer++; } + } else switch (portstate) { + case RESET: + sample = 0; + samplepos += length<<16; + break; + case START: + if (startpin) { + if (*src) + portstate ++; + else // kill 0x00 bytes at stream start + src ++; + } else { + sample = 0; + samplepos += length<<16; + } + break; + case HDR: + srcval = *src++; + nibbles = silence = rate = 0; + highlow = 1; + if (srcval == 0) { // terminator + // HACK, kill leftover odd byte to avoid restart (Minna de Odorou) + if (lim-src == 1) src++; + portstate = START; + } else switch (srcval >> 6) { + case 0: silence = (srcval & 0x3f) + 1; break; + case 1: rate = (srcval & 0x3f) + 1; nibbles = 256; break; + case 2: rate = (srcval & 0x3f) + 1; portstate = COUNT; break; + case 3: break; + } + break; + case COUNT: + nibbles = *src++ + 1; portstate = HDR; + break; } - // lame normalization stuff, needed due to wrong adpcm algo - sgn += (sample < 0) ? -1 : 1; - if (sgn < -16 || sgn > 16) sample -= sample >> 5; + write_sample(buffer, length, stereo); } - if (src < lim) { + // buffer cleanup, generate irq if lowwater reached + if (src < lim && src != PicoPicohw.xpcm_buffer) { int di = lim - src; memmove(PicoPicohw.xpcm_buffer, src, di); PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer + di; elprintf(EL_PICOHW, "xpcm update: over %i", di); - // adjust fifo + + if (!irq && di < FIFO_IRQ_THRESHOLD) + irq = irqenable; PicoPicohw.fifo_bytes = di; - return; - } + } else if (src == lim && src != PicoPicohw.xpcm_buffer) { + PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer; + elprintf(EL_PICOHW, "xpcm update: under %i", length); - elprintf(EL_PICOHW, "xpcm update: under %i", length); - PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer; + if (!irq) + irq = irqenable; + PicoPicohw.fifo_bytes = 0; + } -end: - if (buffer && stereo) - // still must expand SN76496 to stereo - for (; length > 0; buffer+=2, length--) - buffer[1] = buffer[0]; + // TODO need an IRQ mask somewhere to avoid loosing one in cases of HINT/VINT + if (irq && SekIrqLevel != irq) { + elprintf(EL_PICOHW, "irq%d", irq); + if (SekIrqLevel < irq) + SekInterrupt(irq); + } - sample = sgn = 0; - quant = 0x7f; + if (buffer && length) { + // for underflow, use last sample to avoid clicks + int val = Limit(samplegain*sample, 16383, -16384); + while (length--) { + int out = apply_filter(val); + *buffer++ += out; + if (stereo) *buffer++ += out; + } + } } - diff --git a/pico/pico_int.h b/pico/pico_int.h index 52734c621..e9437c137 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -842,11 +842,17 @@ unsigned int pcd_pcm_read(unsigned int a); // pico/pico.c PICO_INTERNAL void PicoInitPico(void); PICO_INTERNAL void PicoReratePico(void); +PICO_INTERNAL int PicoPicoIrqAck(int level); // pico/xpcm.c PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo); -PICO_INTERNAL void PicoPicoPCMReset(void); -PICO_INTERNAL void PicoPicoPCMRerate(int xpcm_rate); +PICO_INTERNAL void PicoPicoPCMResetN(int pin); +PICO_INTERNAL void PicoPicoPCMStartN(int pin); +PICO_INTERNAL int PicoPicoPCMBusyN(void); +PICO_INTERNAL void PicoPicoPCMGain(int gain); +PICO_INTERNAL void PicoPicoPCMFilter(int index); +PICO_INTERNAL void PicoPicoPCMIrqEn(int enable); +PICO_INTERNAL void PicoPicoPCMRerate(void); // sek.c PICO_INTERNAL void SekInit(void); diff --git a/pico/sek.c b/pico/sek.c index 236d03fe4..68aeb1739 100644 --- a/pico/sek.c +++ b/pico/sek.c @@ -41,7 +41,7 @@ static int do_ack(int level) else if (pv->pending_ints & pv->reg[0] & 0x10) pv->pending_ints &= ~0x10; - return 0; + return (PicoIn.AHW & PAHW_PICO ? PicoPicoIrqAck(level) : 0); } /* callbacks */ From fa4e0531d406845caef687a91540d86c3ce6993e Mon Sep 17 00:00:00 2001 From: kub Date: Tue, 23 Jan 2024 21:57:27 +0100 Subject: [PATCH 37/40] core, improve pico save/load (ADPCM state, page, etc) --- pico/pico.h | 7 +-- pico/pico/pico.c | 1 + pico/pico/xpcm.c | 155 ++++++++++++++++++++++++++++++----------------- pico/pico_int.h | 2 + pico/state.c | 49 ++++++++++----- 5 files changed, 136 insertions(+), 78 deletions(-) diff --git a/pico/pico.h b/pico/pico.h index e45540c3d..e91cad29e 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -150,17 +150,14 @@ void PicoGetInternal(pint_t which, pint_ret_t *ret); struct PicoEState; // pico.c -#define XPCM_BUFFER_SIZE (320+160) +#define XPCM_BUFFER_SIZE 64 typedef struct { int pen_pos[2]; int page; - // internal int fifo_bytes; // bytes in FIFO - int fifo_bytes_prev; - int fifo_line_bytes; // float part, << 16 - int line_counter; unsigned short r1, r12; + unsigned int reserved[3]; unsigned char xpcm_buffer[XPCM_BUFFER_SIZE+4]; unsigned char *xpcm_ptr; } picohw_state; diff --git a/pico/pico/pico.c b/pico/pico/pico.c index 81d535abe..d190a9402 100644 --- a/pico/pico/pico.c +++ b/pico/pico/pico.c @@ -18,6 +18,7 @@ picohw_state PicoPicohw; PICO_INTERNAL void PicoReratePico(void) { PicoPicoPCMRerate(); + PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer + PicoPicohw.fifo_bytes; } static void PicoLinePico(void) diff --git a/pico/pico/xpcm.c b/pico/pico/xpcm.c index ef0f8701e..91749bacd 100644 --- a/pico/pico/xpcm.c +++ b/pico/pico/xpcm.c @@ -42,14 +42,23 @@ static const int step_deltas[16][16] = static const int state_deltas[16] = { -1, -1, 0, 0, 1, 2, 2, 3, -1, -1, 0, 0, 1, 2, 2, 3 }; -static int sample = 0, state = 0; -static s32 stepsamples = (44100LL<<16)/ADPCM_CLOCK; -static s32 samplepos; -static int samplegain; +s32 stepsamples = (44100LL<<16)/ADPCM_CLOCK; -static int startpin, irqenable; -static enum { RESET, START, HDR, COUNT } portstate = RESET; -static int rate, silence, nibbles, highlow, cache; +static struct xpcm_state { + s32 samplepos; // leftover duration for current sample wrt sndrate, Q16 + int sample; // current sample + short state; // ADPCM engine state + short samplegain; // programmable gain + + char startpin; // value on the !START pin + char irqenable; // IRQ enabled? + + char portstate; // data stream state + short silence; // silence blocks still to be played + short rate, nibbles; // ADPCM nibbles still to be played + unsigned char highlow, cache; // nibble selector and cache +} xpcm; +enum { RESET, START, HDR, COUNT }; // portstate // SEGA Pico specific filtering @@ -58,8 +67,8 @@ static int rate, silence, nibbles, highlow, cache; #define FP(f) (int)((f)*(1<x[0] = iir->x[1]; iir->x[1] = iir->x[2]; iir->x[2] = sample * iir->gain; // Qb iir->y[0] = iir->y[1]; iir->y[1] = iir->y[2]; @@ -99,21 +109,21 @@ static int PicoPicoFilterApply(struct iir2 *iir, int sample) PICO_INTERNAL void PicoPicoPCMResetN(int pin) { if (!pin) { - portstate = RESET; - sample = samplepos = state = 0; - portstate = nibbles = silence = 0; - } else if (portstate == RESET) - portstate = START; + xpcm.portstate = RESET; + xpcm.sample = xpcm.samplepos = xpcm.state = 0; + xpcm.nibbles = xpcm.silence = 0; + } else if (xpcm.portstate == RESET) + xpcm.portstate = START; } PICO_INTERNAL void PicoPicoPCMStartN(int pin) { - startpin = pin; + xpcm.startpin = pin; } PICO_INTERNAL int PicoPicoPCMBusyN(void) { - return (portstate <= START); + return (xpcm.portstate <= START); } @@ -125,14 +135,14 @@ PICO_INTERNAL void PicoPicoPCMRerate(void) stepsamples = ((u64)PicoIn.sndRate<<16)/ADPCM_CLOCK; // compute filter coefficients, cutoff at half the ADPCM sample rate - PicoPicoFilterCoeff(&filters[1], 5000/2, PicoIn.sndRate); // 5-6 KHz - PicoPicoFilterCoeff(&filters[2], 8000/2, PicoIn.sndRate); // 8-12 KHz - PicoPicoFilterCoeff(&filters[3], 14000/2, PicoIn.sndRate); // 14-16 KHz + PicoPicoFilterCoeff(&filters[1], 6000/2, PicoIn.sndRate); // 5-6 KHz + PicoPicoFilterCoeff(&filters[2], 9000/2, PicoIn.sndRate); // 8-12 KHz + PicoPicoFilterCoeff(&filters[3], 15000/2, PicoIn.sndRate); // 14-16 KHz } PICO_INTERNAL void PicoPicoPCMGain(int gain) { - samplegain = gain*4; + xpcm.samplegain = gain*4; } PICO_INTERNAL void PicoPicoPCMFilter(int index) @@ -144,13 +154,14 @@ PICO_INTERNAL void PicoPicoPCMFilter(int index) PICO_INTERNAL void PicoPicoPCMIrqEn(int enable) { - irqenable = (enable ? 3 : 0); + xpcm.irqenable = (enable ? 3 : 0); } // TODO need an interupt pending mask? PICO_INTERNAL int PicoPicoIrqAck(int level) { - return (PicoPicohw.fifo_bytes < FIFO_IRQ_THRESHOLD && level != irqenable ? irqenable : 0); + return (PicoPicohw.fifo_bytes < FIFO_IRQ_THRESHOLD && level != xpcm.irqenable + ? xpcm.irqenable : 0); } @@ -158,18 +169,20 @@ PICO_INTERNAL int PicoPicoIrqAck(int level) #define apply_filter(v) PicoPicoFilterApply(filter, v) +// compute next ADPCM sample #define do_sample(nibble) \ { \ - sample += step_deltas[state][nibble]; \ - state += state_deltas[nibble]; \ - state = (state < 0 ? 0 : state > 15 ? 15 : state); \ + xpcm.sample += step_deltas[xpcm.state][nibble]; \ + xpcm.state += state_deltas[nibble]; \ + xpcm.state = (xpcm.state < 0 ? 0 : xpcm.state > 15 ? 15 : xpcm.state); \ } +// writes samples with sndRate, nearest neighbour resampling, filtering #define write_sample(buffer, length, stereo) \ { \ - while (samplepos > 0 && length > 0) { \ - int val = Limit(samplegain*sample, 16383, -16384); \ - samplepos -= 1<<16; \ + while (xpcm.samplepos > 0 && length > 0) { \ + int val = Limit(xpcm.samplegain*xpcm.sample, 16383, -16384); \ + xpcm.samplepos -= 1<<16; \ length --; \ if (buffer) { \ int out = apply_filter(val); \ @@ -191,56 +204,56 @@ PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo) // loop over FIFO data, generating ADPCM samples while (length > 0 && src < lim) { - if (silence > 0) { - silence --; - sample = 0; - samplepos += stepsamples*256; + if (xpcm.silence > 0) { + xpcm.silence --; + xpcm.sample = 0; + xpcm.samplepos += stepsamples*256; - } else if (nibbles > 0) { - nibbles --; + } else if (xpcm.nibbles > 0) { + xpcm.nibbles --; - if (highlow) - cache = *src++; + if (xpcm.highlow) + xpcm.cache = *src++; else - cache <<= 4; - highlow = !highlow; + xpcm.cache <<= 4; + xpcm.highlow = !xpcm.highlow; - do_sample((cache & 0xf0) >> 4); - samplepos += stepsamples*rate; + do_sample((xpcm.cache & 0xf0) >> 4); + xpcm.samplepos += stepsamples*xpcm.rate; - } else switch (portstate) { + } else switch (xpcm.portstate) { case RESET: - sample = 0; - samplepos += length<<16; + xpcm.sample = 0; + xpcm.samplepos += length<<16; break; case START: - if (startpin) { + if (xpcm.startpin) { if (*src) - portstate ++; + xpcm.portstate ++; else // kill 0x00 bytes at stream start src ++; } else { - sample = 0; - samplepos += length<<16; + xpcm.sample = 0; + xpcm.samplepos += length<<16; } break; case HDR: srcval = *src++; - nibbles = silence = rate = 0; - highlow = 1; + xpcm.nibbles = xpcm.silence = xpcm.rate = 0; + xpcm.highlow = 1; if (srcval == 0) { // terminator // HACK, kill leftover odd byte to avoid restart (Minna de Odorou) if (lim-src == 1) src++; - portstate = START; + xpcm.portstate = START; } else switch (srcval >> 6) { - case 0: silence = (srcval & 0x3f) + 1; break; - case 1: rate = (srcval & 0x3f) + 1; nibbles = 256; break; - case 2: rate = (srcval & 0x3f) + 1; portstate = COUNT; break; + case 0: xpcm.silence = (srcval & 0x3f) + 1; break; + case 1: xpcm.rate = (srcval & 0x3f) + 1; xpcm.nibbles = 256; break; + case 2: xpcm.rate = (srcval & 0x3f) + 1; xpcm.portstate = COUNT; break; case 3: break; } break; case COUNT: - nibbles = *src++ + 1; portstate = HDR; + xpcm.nibbles = *src++ + 1; xpcm.portstate = HDR; break; } @@ -255,14 +268,14 @@ PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo) elprintf(EL_PICOHW, "xpcm update: over %i", di); if (!irq && di < FIFO_IRQ_THRESHOLD) - irq = irqenable; + irq = xpcm.irqenable; PicoPicohw.fifo_bytes = di; } else if (src == lim && src != PicoPicohw.xpcm_buffer) { PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer; elprintf(EL_PICOHW, "xpcm update: under %i", length); if (!irq) - irq = irqenable; + irq = xpcm.irqenable; PicoPicohw.fifo_bytes = 0; } @@ -275,7 +288,7 @@ PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo) if (buffer && length) { // for underflow, use last sample to avoid clicks - int val = Limit(samplegain*sample, 16383, -16384); + int val = Limit(xpcm.samplegain*xpcm.sample, 16383, -16384); while (length--) { int out = apply_filter(val); *buffer++ += out; @@ -283,3 +296,31 @@ PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo) } } } + +PICO_INTERNAL int PicoPicoPCMSave(void *buffer, int length) +{ + u8 *bp = buffer; + + if (length < sizeof(xpcm) + sizeof(filters)) { + elprintf(EL_ANOMALY, "save buffer too small?"); + return 0; + } + + memcpy(bp, &xpcm, sizeof(xpcm)); + bp += sizeof(xpcm); + memcpy(bp, filters, sizeof(filters)); + bp += sizeof(filters); + return (bp - (u8*)buffer); +} + +PICO_INTERNAL void PicoPicoPCMLoad(void *buffer, int length) +{ + u8 *bp = buffer; + + if (length >= sizeof(xpcm)) + memcpy(&xpcm, bp, sizeof(xpcm)); + bp += sizeof(xpcm); + if (length >= sizeof(xpcm) + sizeof(filters)) + memcpy(filters, bp, sizeof(filters)); + bp += sizeof(filters); +} diff --git a/pico/pico_int.h b/pico/pico_int.h index e9437c137..86259cd75 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -853,6 +853,8 @@ PICO_INTERNAL void PicoPicoPCMGain(int gain); PICO_INTERNAL void PicoPicoPCMFilter(int index); PICO_INTERNAL void PicoPicoPCMIrqEn(int enable); PICO_INTERNAL void PicoPicoPCMRerate(void); +PICO_INTERNAL int PicoPicoPCMSave(void *buffer, int length); +PICO_INTERNAL void PicoPicoPCMLoad(void *buffer, int length); // sek.c PICO_INTERNAL void SekInit(void); diff --git a/pico/state.c b/pico/state.c index 9f91cd154..3b93765fa 100644 --- a/pico/state.c +++ b/pico/state.c @@ -133,6 +133,8 @@ typedef enum { CHUNK_CD_CDC, CHUNK_CD_CDD, CHUNK_YM2413, + CHUNK_PICO_PCM, + CHUNK_PICO, // CHUNK_DEFAULT_COUNT, CHUNK_CARTHW_ = CHUNK_CARTHW, // 64 (defined in PicoInt) @@ -181,9 +183,8 @@ static const char * const chunk_names[CHUNK_DEFAULT_COUNT] = { "SSH2 BIOS", // 35 "SDRAM", "DRAM", - "PAL", - "events", - "YM2413", //40 + "32X palette", + "32X events", }; static int write_chunk(chunk_name_e name, int len, void *data, void *file) @@ -230,6 +231,10 @@ static int state_save(void *file) int retval = -1; int len; + buf2 = malloc(CHUNK_LIMIT_W); + if (buf2 == NULL) + return -1; + areaWrite("PicoSEXT", 1, 8, file); areaWrite(&ver, 1, 4, file); @@ -243,9 +248,15 @@ static int state_save(void *file) CHECKED_WRITE_BUFF(CHUNK_RAM, PicoMem.ram); CHECKED_WRITE_BUFF(CHUNK_VSRAM, PicoMem.vsram); CHECKED_WRITE_BUFF(CHUNK_IOPORTS, PicoMem.ioports); - ym2612_pack_state(); - ym_regs = YM2612GetRegs(); - CHECKED_WRITE(CHUNK_FM, 0x200+4, ym_regs); + if (PicoIn.AHW & PAHW_PICO) { + len = PicoPicoPCMSave(buf2, CHUNK_LIMIT_W); + CHECKED_WRITE(CHUNK_PICO_PCM, len, buf2); + CHECKED_WRITE(CHUNK_PICO, sizeof(PicoPicohw), &PicoPicohw); + } else { + ym2612_pack_state(); + ym_regs = YM2612GetRegs(); + CHECKED_WRITE(CHUNK_FM, 0x200+4, ym_regs); + } if (!(PicoIn.opt & POPT_DIS_IDLE_DET)) SekInitIdleDet(); @@ -255,25 +266,23 @@ static int state_save(void *file) ym_regs = YM2413GetRegs(); CHECKED_WRITE(CHUNK_YM2413, 0x40+4, ym_regs); } + CHECKED_WRITE(CHUNK_PSG, 28*4, sn76496_regs); + + if (!(PicoIn.AHW & PAHW_PICO)) { + z80_pack(buff_z80); + CHECKED_WRITE_BUFF(CHUNK_Z80, buff_z80); + CHECKED_WRITE_BUFF(CHUNK_ZRAM, PicoMem.zram); + } CHECKED_WRITE_BUFF(CHUNK_VRAM, PicoMem.vram); - CHECKED_WRITE_BUFF(CHUNK_ZRAM, PicoMem.zram); CHECKED_WRITE_BUFF(CHUNK_CRAM, PicoMem.cram); - CHECKED_WRITE_BUFF(CHUNK_MISC, Pico.m); + CHECKED_WRITE_BUFF(CHUNK_MISC, Pico.m); PicoVideoSave(); CHECKED_WRITE_BUFF(CHUNK_VIDEO, Pico.video); - z80_pack(buff_z80); - CHECKED_WRITE_BUFF(CHUNK_Z80, buff_z80); - CHECKED_WRITE(CHUNK_PSG, 28*4, sn76496_regs); - if (PicoIn.AHW & PAHW_MCD) { - buf2 = malloc(CHUNK_LIMIT_W); - if (buf2 == NULL) - return -1; - memset(buff, 0, sizeof(buff)); SekPackCpu(buff, 1); if (Pico_mcd->s68k_regs[3] & 4) // 1M mode? @@ -464,6 +473,14 @@ static int state_load(void *file) ym2612_unpack_state(); break; + case CHUNK_PICO_PCM: + CHECKED_READ(len, buf); + PicoPicoPCMLoad(buf, len); + break; + case CHUNK_PICO: + CHECKED_READ_BUFF(PicoPicohw); + break; + case CHUNK_SMS: CHECKED_READ_BUFF(Pico.ms); break; From 70efc52db8ca92b8d5c4e0db4d3e85fb9fc7d7c1 Mon Sep 17 00:00:00 2001 From: kub Date: Sun, 21 Jan 2024 21:41:31 +0100 Subject: [PATCH 38/40] core, implement GG stereo --- pico/pico.h | 2 +- pico/sms.c | 2 ++ pico/sound/mix.c | 21 +++++++------- pico/sound/mix.h | 6 ++-- pico/sound/mix_arm.S | 66 +++++++++++++++++++++++--------------------- pico/sound/sn76496.c | 44 ++++++++++++++++++++++------- pico/sound/sn76496.h | 1 + pico/sound/sound.c | 48 +++++++++++++++++--------------- platform/gp2x/emu.c | 6 ++-- 9 files changed, 114 insertions(+), 82 deletions(-) diff --git a/pico/pico.h b/pico/pico.h index e91cad29e..2db502d5b 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -267,7 +267,7 @@ void Pico32xSetClocks(int msh2_hz, int ssh2_hz); #define PICO_SSH2_HZ ((int)(7670442.0 * 2.4)) // sound.c -extern void (*PsndMix_32_to_16l)(s16 *dest, s32 *src, int count); +extern void (*PsndMix_32_to_16)(s16 *dest, s32 *src, int count); void PsndRerate(int preserve_state); // media.c diff --git a/pico/sms.c b/pico/sms.c index 398a4da3c..615ba36ea 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -241,6 +241,8 @@ static void z80_sms_out(unsigned short a, unsigned char d) case 0x00: if ((PicoIn.AHW & PAHW_GG) && a < 0x8) // GG I/O area Pico.ms.io_gg[a] = d; + if ((PicoIn.AHW & PAHW_GG) && a == 0x6) + SN76496Config(d); break; case 0x01: if ((PicoIn.AHW & PAHW_GG) && a < 0x8) { // GG I/O area diff --git a/pico/sound/mix.c b/pico/sound/mix.c index 8f75ef0ab..1c79b4854 100644 --- a/pico/sound/mix.c +++ b/pico/sound/mix.c @@ -18,7 +18,7 @@ val -= val >> 3; /* reduce level to avoid clipping */ \ if ((s16)val != val) val = (val < 0 ? MINOUT : MAXOUT) -int mix_32_to_16l_level; +int mix_32_to_16_level; static struct iir { int alpha; // alpha for EMA low pass @@ -63,33 +63,34 @@ static inline int filter_null(struct iir *fi2, int x) #define filter filter_band -#define mix_32_to_16l_stereo_core(dest, src, count, lv, fl) { \ +#define mix_32_to_16_stereo_core(dest, src, count, lv, fl) { \ int l, r; \ struct iir lf = lfi2, rf = rfi2; \ \ for (; count > 0; count--) \ { \ - l = r = *dest; \ + l = *dest; \ l += *src++ >> lv; \ - r += *src++ >> lv; \ l = fl(&lf, l); \ - r = fl(&rf, r); \ Limit16(l); \ - Limit16(r); \ *dest++ = l; \ + r = *dest; \ + r += *src++ >> lv; \ + r = fl(&rf, r); \ + Limit16(r); \ *dest++ = r; \ } \ lfi2 = lf, rfi2 = rf; \ } -void mix_32_to_16l_stereo_lvl(s16 *dest, s32 *src, int count) +void mix_32_to_16_stereo_lvl(s16 *dest, s32 *src, int count) { - mix_32_to_16l_stereo_core(dest, src, count, mix_32_to_16l_level, filter); + mix_32_to_16_stereo_core(dest, src, count, mix_32_to_16_level, filter); } -void mix_32_to_16l_stereo(s16 *dest, s32 *src, int count) +void mix_32_to_16_stereo(s16 *dest, s32 *src, int count) { - mix_32_to_16l_stereo_core(dest, src, count, 0, filter); + mix_32_to_16_stereo_core(dest, src, count, 0, filter); } void mix_32_to_16_mono(s16 *dest, s32 *src, int count) diff --git a/pico/sound/mix.h b/pico/sound/mix.h index 3aa3ee874..43fb52a52 100644 --- a/pico/sound/mix.h +++ b/pico/sound/mix.h @@ -6,9 +6,9 @@ void mix_16h_to_32_s2(s32 *dest, s16 *src, int count); void mix_16h_to_32_resample_stereo(s32 *dest, s16 *src, int count, int fac16); void mix_16h_to_32_resample_mono(s32 *dest, s16 *src, int count, int fac16); -void mix_32_to_16l_stereo(s16 *dest, s32 *src, int count); +void mix_32_to_16_stereo(s16 *dest, s32 *src, int count); void mix_32_to_16_mono(s16 *dest, s32 *src, int count); -extern int mix_32_to_16l_level; -void mix_32_to_16l_stereo_lvl(s16 *dest, s32 *src, int count); +extern int mix_32_to_16_level; +void mix_32_to_16_stereo_lvl(s16 *dest, s32 *src, int count); void mix_reset(int alpha_q16); diff --git a/pico/sound/mix_arm.S b/pico/sound/mix_arm.S index f051b3861..dc9e980b4 100644 --- a/pico/sound/mix_arm.S +++ b/pico/sound/mix_arm.S @@ -282,29 +282,29 @@ m16_32_rsm_end: @ mix 32bit audio (with 16bits really used, upper bits indicate overflow) with normal 16 bit audio with left channel only @ warning: this function assumes dest is word aligned -.global mix_32_to_16l_stereo @ short *dest, int *src, int count +.global mix_32_to_16_stereo @ short *dest, int *src, int count -mix_32_to_16l_stereo: +mix_32_to_16_stereo: stmfd sp!, {r4-r8,r10-r11,lr} mov r2, r2, lsl #1 subs r2, r2, #4 - bmi m32_16l_st_end + bmi m32_16_st_end ldr r12, =filter ldr r8, [r12], #4 ldmia r12, {r3,r10-r11,lr} str r8, [sp, #-4]! -m32_16l_st_loop: +m32_16_st_loop: ldmia r0, {r8,r12} ldmia r1!, {r4-r7} + add r5, r5, r8, asr #16 + add r7, r7, r12,asr #16 mov r8, r8, lsl #16 mov r12,r12,lsl #16 add r4, r4, r8, asr #16 - add r5, r5, r8, asr #16 add r6, r6, r12,asr #16 - add r7, r7, r12,asr #16 ldr r12,[sp] LPfilt r4, r3 LPfilt r5, lr @@ -323,16 +323,17 @@ m32_16l_st_loop: orr r4, r5, r4, lsr #16 orr r5, r7, r6, lsr #16 stmia r0!, {r4,r5} - bpl m32_16l_st_loop + bpl m32_16_st_loop -m32_16l_st_end: +m32_16_st_end: @ check for remaining bytes to convert tst r2, #2 - beq m32_16l_st_no_unal2 - ldrsh r6, [r0] + beq m32_16_st_no_unal2 + ldr r6, [r0] ldmia r1!,{r4,r5} - add r4, r4, r6 - add r5, r5, r6 + add r5, r5, r6, asr #16 + mov r6, r6, lsl #16 + add r4, r4, r6, asr #16 ldr r12,[sp] LPfilt r4, r3 LPfilt r5, lr @@ -344,7 +345,7 @@ m32_16l_st_end: orr r4, r5, r4, lsr #16 str r4, [r0], #4 -m32_16l_st_no_unal2: +m32_16_st_no_unal2: ldr r12, =filter add r12,r12, #4 stmia r12, {r3,r10-r11,lr} @@ -386,10 +387,10 @@ m32_16_mo_loop: ldmia r0, {r8,r12} ldmia r1!, {r4-r7} add r5, r5, r8, asr #16 - mov r8, r8, lsl #16 - add r4, r4, r8, asr #16 add r7, r7, r12,asr #16 + mov r8, r8, lsl #16 mov r12,r12,lsl #16 + add r4, r4, r8, asr #16 add r6, r6, r12,asr #16 ldr r12,[sp] LPfilt r4, r11 @@ -458,20 +459,20 @@ m32_16_mo_no_unal: .data .align 4 -.global mix_32_to_16l_level -mix_32_to_16l_level: +.global mix_32_to_16_level +mix_32_to_16_level: .word 0 .text .align 4 -@ same as mix_32_to_16l_stereo, but with additional shift -.global mix_32_to_16l_stereo_lvl @ short *dest, int *src, int count +@ same as mix_32_to_16_stereo, but with additional shift +.global mix_32_to_16_stereo_lvl @ short *dest, int *src, int count -mix_32_to_16l_stereo_lvl: +mix_32_to_16_stereo_lvl: stmfd sp!, {r4-r11,lr} - ldr r9, =mix_32_to_16l_level + ldr r9, =mix_32_to_16_level mov lr, #1 ldr r9, [r9] ldr r12, =filter @@ -481,17 +482,17 @@ mix_32_to_16l_stereo_lvl: mov r2, r2, lsl #1 subs r2, r2, #4 - bmi m32_16l_st_l_end + bmi m32_16_st_l_end -m32_16l_st_l_loop: +m32_16_st_l_loop: ldmia r0, {r8,r12} ldmia r1!, {r4-r7} + add r5, r5, r8, asr #16 + add r7, r7, r12,asr #16 mov r8, r8, lsl #16 mov r12,r12,lsl #16 add r4, r4, r8, asr #16 - add r5, r5, r8, asr #16 add r6, r6, r12,asr #16 - add r7, r7, r12,asr #16 mov r4, r4, asr r9 mov r5, r5, asr r9 mov r6, r6, asr r9 @@ -514,16 +515,17 @@ m32_16l_st_l_loop: orr r4, r5, r4, lsr #16 orr r5, r7, r6, lsr #16 stmia r0!, {r4,r5} - bpl m32_16l_st_l_loop + bpl m32_16_st_l_loop -m32_16l_st_l_end: +m32_16_st_l_end: @ check for remaining bytes to convert tst r2, #2 - beq m32_16l_st_l_no_unal2 - ldrsh r6, [r0] + beq m32_16_st_l_no_unal2 + ldr r6, [r0] ldmia r1!,{r4,r5} - add r4, r4, r6 - add r5, r5, r6 + add r5, r5, r6, asr #16 + mov r6, r6, lsl #16 + add r4, r4, r6, asr #16 mov r4, r4, asr r9 mov r5, r5, asr r9 ldr r12,[sp] @@ -537,7 +539,7 @@ m32_16l_st_l_end: orr r4, r5, r4, lsr #16 str r4, [r0], #4 -m32_16l_st_l_no_unal2: +m32_16_st_l_no_unal2: ldr r12, =filter add r12,r12, #4 stmia r12, {r3,r10-r11,lr} diff --git a/pico/sound/sn76496.c b/pico/sound/sn76496.c index 3bb5cf741..0837839c8 100644 --- a/pico/sound/sn76496.c +++ b/pico/sound/sn76496.c @@ -56,7 +56,7 @@ struct SN76496 int Period[4]; int Count[4]; int Output[4]; - int pad[1]; + int Panning; }; static struct SN76496 ono_sn; // one and only SN76496 @@ -135,7 +135,6 @@ void SN76496Update(short *buffer, int length, int stereo) while (length > 0) { int vol[4]; - unsigned int out; int left; @@ -203,19 +202,43 @@ void SN76496Update(short *buffer, int length, int stereo) } while (left > 0 && R->Volume[3]); if (R->Output[3]) vol[3] -= R->Count[3]; - out = vol[0] * R->Volume[0] + vol[1] * R->Volume[1] + + length--; + if (R->Panning == 0xff || !stereo) { + unsigned int out = + vol[0] * R->Volume[0] + vol[1] * R->Volume[1] + vol[2] * R->Volume[2] + vol[3] * R->Volume[3]; - if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP; - - out /= STEP; // will be optimized to shift; max 0x4800 = 18432 - *buffer++ += out; - if (stereo) *buffer++ += out; - - length--; + if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP; + + out /= STEP; // will be optimized to shift; max 0x4800 = 18432 + *buffer++ += out; + if (stereo) *buffer++ += out; + } else { +#define P(n) !!(R->Panning & (1<<(n))) + unsigned int outl = + vol[0] * R->Volume[0] * P(4) + vol[1] * R->Volume[1] * P(5) + + vol[2] * R->Volume[2] * P(6) + vol[3] * R->Volume[3] * P(7); + unsigned int outr = + vol[0] * R->Volume[0] * P(0) + vol[1] * R->Volume[1] * P(1) + + vol[2] * R->Volume[2] * P(2) + vol[3] * R->Volume[3] * P(3); +#undef P + if (outl > MAX_OUTPUT * STEP) outl = MAX_OUTPUT * STEP; + if (outr > MAX_OUTPUT * STEP) outr = MAX_OUTPUT * STEP; + + outl /= STEP; // will be optimized to shift; max 0x4800 = 18432 + outr /= STEP; // will be optimized to shift; max 0x4800 = 18432 + *buffer++ += outl; + *buffer++ += outr; + } } } +void SN76496Config(int panning) +{ + struct SN76496 *R = &ono_sn; + R->Panning = panning & 0xff; +} + static void SN76496_set_clock(struct SN76496 *R,int clock) { @@ -286,6 +309,7 @@ int SN76496_init(int clock,int sample_rate) // added SN76496_set_gain(R, 0); + R->Panning = 0xff; return 0; } diff --git a/pico/sound/sn76496.h b/pico/sound/sn76496.h index e0de6edaf..707bb5dd1 100644 --- a/pico/sound/sn76496.h +++ b/pico/sound/sn76496.h @@ -3,6 +3,7 @@ void SN76496Write(int data); void SN76496Update(short *buffer,int length,int stereo); +void SN76496Config(int panning); int SN76496_init(int clock,int sample_rate); #endif diff --git a/pico/sound/sound.c b/pico/sound/sound.c index 5d7fac630..edf9c8960 100644 --- a/pico/sound/sound.c +++ b/pico/sound/sound.c @@ -15,7 +15,7 @@ #include "resampler.h" #include "mix.h" -void (*PsndMix_32_to_16l)(s16 *dest, s32 *src, int count) = mix_32_to_16l_stereo; +void (*PsndMix_32_to_16)(s16 *dest, s32 *src, int count) = mix_32_to_16_stereo; // master int buffer to mix to // +1 for a fill triggered by an instruction overhanging into the next scanline @@ -228,7 +228,7 @@ void PsndRerate(int preserve_state) PsndClear(); // set mixer - PsndMix_32_to_16l = (PicoIn.opt & POPT_EN_STEREO) ? mix_32_to_16l_stereo : mix_32_to_16_mono; + PsndMix_32_to_16 = (PicoIn.opt & POPT_EN_STEREO) ? mix_32_to_16_stereo : mix_32_to_16_mono; mix_reset(PicoIn.opt & POPT_EN_SNDFILTER ? PicoIn.sndFilterAlpha : 0); if (PicoIn.AHW & PAHW_PICO) @@ -275,8 +275,8 @@ PICO_INTERNAL void PsndDoDAC(int cyc_to) 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++; - while (--len) *d++ += Pico.snd.dac_val, d++; + *d++ += Pico.snd.dac_val2, *d++ += Pico.snd.dac_val2; + while (--len) *d++ += Pico.snd.dac_val, *d++ += Pico.snd.dac_val; } else { s16 *d = PicoIn.sndOut + pos; *d++ += Pico.snd.dac_val2; @@ -345,10 +345,15 @@ PICO_INTERNAL void PsndDoSMSFM(int cyc_to) if (Pico.m.hardware & PMS_HW_FMUSED) { buf += pos; PsndFMUpdate(buf32, len, 0, 0); - while (len--) { - *buf++ += *buf32++; - buf += stereo; - } + if (stereo) + while (len--) { + *buf++ += *buf32; + *buf++ += *buf32++; + } + else + while (len--) { + *buf++ += *buf32++; + } } } @@ -506,10 +511,10 @@ static int PsndRender(int offset, int length) s16 *dacbuf = PicoIn.sndOut + (daclen << stereo); Pico.snd.dac_pos += (length-daclen) << 20; *dacbuf++ += Pico.snd.dac_val2; - if (stereo) dacbuf++; + if (stereo) *dacbuf++ += Pico.snd.dac_val2; for (daclen++; length-daclen > 0; daclen++) { *dacbuf++ += Pico.snd.dac_val; - if (stereo) dacbuf++; + if (stereo) *dacbuf++ += Pico.snd.dac_val; } Pico.snd.dac_val2 = Pico.snd.dac_val; } @@ -544,7 +549,7 @@ static int PsndRender(int offset, int length) // convert + limit to normal 16bit output if (PicoIn.sndOut) - PsndMix_32_to_16l(PicoIn.sndOut+(offset< 0; i--, p+=2) - *(p + 1) = *p; - } - pprof_end(sound); return length; diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index 6bc96df78..d59f3ecae 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -753,10 +753,10 @@ void plat_update_volume(int has_changed, int is_up) /* set the right mixer func */ if (vol >= 5) - PsndMix_32_to_16l = mix_32_to_16l_stereo; + PsndMix_32_to_16 = mix_32_to_16_stereo; else { - mix_32_to_16l_level = 5 - vol; - PsndMix_32_to_16l = mix_32_to_16l_stereo_lvl; + mix_32_to_16_level = 5 - vol; + PsndMix_32_to_16 = mix_32_to_16_stereo_lvl; } } From cbe78533332cf2a7081d0de65d0d7fa9924b2b1c Mon Sep 17 00:00:00 2001 From: kub Date: Tue, 23 Jan 2024 22:55:38 +0100 Subject: [PATCH 39/40] update libpicofe (redraw event handling) --- platform/libpicofe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/libpicofe b/platform/libpicofe index 7b3f69a4a..7cddc27ac 160000 --- a/platform/libpicofe +++ b/platform/libpicofe @@ -1 +1 @@ -Subproject commit 7b3f69a4aa53eaf0fb51065c86e71748066e09ed +Subproject commit 7cddc27accc089fdb58e99cdac0071cc904ecef1 From a914c976f8cc9487d6a06f4bed3558a1918ecc8e Mon Sep 17 00:00:00 2001 From: kub Date: Tue, 23 Jan 2024 22:56:31 +0100 Subject: [PATCH 40/40] prerelease 2.00-alpha3 --- 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 cc4da6634..db39ac35a 100644 --- a/platform/common/version.h +++ b/platform/common/version.h @@ -1 +1 @@ -#define VERSION "pre-2.00-alpha2" REVISION +#define VERSION "pre-2.00-alpha3" REVISION