From b92914761261cbcee2ca6d253f28bc4d42dfd8ec Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 23 Nov 2018 01:59:20 +0800 Subject: [PATCH 01/34] Update input settings, allow multi-player without matching CRC --- src/drivers/libretro/libretro.c | 280 +++++++++++++++++++++----------- 1 file changed, 182 insertions(+), 98 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 95e72de..1f6b46e 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -30,12 +30,16 @@ #define MAX_PORTS 2 /* max controller ports, * port 0 for player 1/3, port 1 for player 2/4 */ -#define RETRO_DEVICE_GAMEPAD RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 0) +#define RETRO_DEVICE_AUTO RETRO_DEVICE_JOYPAD +#define RETRO_DEVICE_GAMEPAD RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 1) #define RETRO_DEVICE_ZAPPER RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_MOUSE, 0) #define RETRO_DEVICE_ARKANOID RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_MOUSE, 1) + #define RETRO_DEVICE_FC_ARKANOID RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_MOUSE, 2) #define RETRO_DEVICE_FC_OEKAKIDS RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_MOUSE, 3) #define RETRO_DEVICE_FC_SHADOW RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_MOUSE, 4) +#define RETRO_DEVICE_FC_4PLAYERS RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 2) +#define RETRO_DEVICE_FC_AUTO RETRO_DEVICE_JOYPAD #define NES_8_7_PAR ((width * (8.0 / 7.0)) / height) #define NES_4_3 ((width / (height * (256.0 / 240.0))) * 4.0 / 3.0) @@ -99,6 +103,7 @@ unsigned swapDuty = 0; static int32_t *sound = 0; static uint32_t JSReturn = 0; +static uint32_t Dummy = 0; static uint32_t MouseData[MAX_PORTS][3] = { {0} }; static uint32_t fc_MouseData[3] = {0}; static uint32_t current_palette = 0; @@ -546,31 +551,150 @@ void retro_set_input_state(retro_input_state_t cb) input_cb = cb; } -void set_input_nes_controller(unsigned port, int x); -void set_input_famicom_controller(int x); +static void update_nes_controllers(unsigned port, unsigned device) +{ + input_type[port] = device; + + if (port < 4) + { + switch (device) + { + case RETRO_DEVICE_NONE: + FCEUI_SetInput(port, SI_NONE, &Dummy, 0); + FCEU_printf(" Player %u: None Connected\n", port + 1); + break; + case RETRO_DEVICE_ZAPPER: + FCEUI_SetInput(port, SI_ZAPPER, MouseData[port], 1); + FCEU_printf(" Player %u: Zapper\n", port + 1); + break; + case RETRO_DEVICE_ARKANOID: + FCEUI_SetInput(port, SI_ARKANOID, MouseData[port], 0); + FCEU_printf(" Player %u: Arkanoid\n", port + 1); + break; + case RETRO_DEVICE_GAMEPAD: + default: + input_type[port] = RETRO_DEVICE_GAMEPAD; + FCEUI_SetInput(port, SI_GAMEPAD, &JSReturn, 0); + FCEU_printf(" Player %u: Gamepad\n", port + 1); + break; + } + } + + if (port == 4) + { + switch (device) + { + case RETRO_DEVICE_FC_ARKANOID: + FCEUI_SetInputFC(SIFC_ARKANOID, fc_MouseData, 0); + FCEU_printf(" Famicom Expansion: Arkanoid\n"); + break; + case RETRO_DEVICE_FC_SHADOW: + FCEUI_SetInputFC(SIFC_SHADOW, fc_MouseData, 1); + FCEU_printf(" Famicom Expansion: (Bandai) Hyper Shot\n"); + break; + case RETRO_DEVICE_FC_OEKAKIDS: + FCEUI_SetInputFC(SIFC_OEKAKIDS, fc_MouseData, 1); + FCEU_printf(" Famicom Expansion: Oeka Kids Tablet\n"); + break; + case RETRO_DEVICE_FC_4PLAYERS: + FCEUI_SetInputFC(SIFC_4PLAYER, &JSReturn, 0); + FCEU_printf(" Famicom Expansion: Famicom 4-Player Adapter\n"); + break; + case RETRO_DEVICE_NONE: + default: + FCEUI_SetInputFC(SIFC_NONE, &Dummy, 0); + FCEU_printf(" Famicom Expansion: None Connected\n"); + break; + } + } +} + +static unsigned nes_to_libretro(int d) +{ + switch(d) + { + case SI_UNSET: + case SI_GAMEPAD: + return RETRO_DEVICE_GAMEPAD; + case SI_NONE: + return RETRO_DEVICE_NONE; + case SI_ZAPPER: + return RETRO_DEVICE_ZAPPER; + case SI_ARKANOID: + return RETRO_DEVICE_ARKANOID; + } +} + +static unsigned fc_to_libretro(int d) +{ + switch(d) + { + case SIFC_UNSET: + case SIFC_NONE: + return RETRO_DEVICE_NONE; + case SIFC_ARKANOID: + return RETRO_DEVICE_FC_ARKANOID; + case SIFC_SHADOW: + return RETRO_DEVICE_FC_SHADOW; + case SIFC_OEKAKIDS: + return RETRO_DEVICE_FC_OEKAKIDS; + case SIFC_4PLAYER: + return RETRO_DEVICE_FC_4PLAYERS; + } +} void retro_set_controller_port_device(unsigned port, unsigned device) { - if (port < MAX_PORTS) /* port #0 = player1/player3, port #1 = player2/player4 */ + if ((port < 5) && (input_type[port] != device)) { - switch(device) + if (port < 2) /* player 1-2 */ { - case RETRO_DEVICE_NONE: - set_input_nes_controller(port, SI_NONE); - break; - case RETRO_DEVICE_GAMEPAD: - set_input_nes_controller(port, SI_GAMEPAD); - break; - case RETRO_DEVICE_ZAPPER: - set_input_nes_controller(port, SI_ZAPPER); - break; - case RETRO_DEVICE_ARKANOID: - set_input_nes_controller(port, SI_ARKANOID); - break; - case RETRO_DEVICE_JOYPAD: /* Assigned to auto configure devices */ - default: /* based on database */ - set_input_nes_controller(port, GameInfo->input[port]); - break; + if (device != RETRO_DEVICE_AUTO) { + printf("Non-auto mode\n"); + update_nes_controllers(port, device); + } + else { + printf("automatic mode\n"); + update_nes_controllers(port, nes_to_libretro(GameInfo->input[port])); + } + } + else + { + if (port < 4) /* player 3-4 */ + { + /* This section automatically enables 4players support + * when player 3 or 4 used */ + + input_type[port] = RETRO_DEVICE_NONE; + + if (device == RETRO_DEVICE_AUTO) + { + if (enable_4player) + input_type[port] = RETRO_DEVICE_GAMEPAD; + } + else if (device == RETRO_DEVICE_GAMEPAD) + input_type[port] = RETRO_DEVICE_GAMEPAD; + + FCEU_printf(" Player %u: %s\n", port + 1, + (input_type[port] == RETRO_DEVICE_NONE) ? "None Connected" : "Gamepad"); + } + else /* do famicom controllers here */ + { + if (device != RETRO_DEVICE_FC_AUTO) + update_nes_controllers(4, device); + else + update_nes_controllers(4, fc_to_libretro(GameInfo->inputfc)); + } + + if (input_type[2] == RETRO_DEVICE_GAMEPAD + || input_type[3] == RETRO_DEVICE_GAMEPAD) + FCEUI_DisableFourScore(0); + else + FCEUI_DisableFourScore(1); + + /* check if famicom 4player adapter is used */ + if (input_type[4] == RETRO_DEVICE_FC_4PLAYERS) + FCEUI_DisableFourScore(1); } } } @@ -601,24 +725,48 @@ void retro_set_environment(retro_environment_t cb) }; static const struct retro_controller_description pads1[] = { - { "Auto", RETRO_DEVICE_JOYPAD }, + { "Auto", RETRO_DEVICE_AUTO }, { "Gamepad", RETRO_DEVICE_GAMEPAD }, { "Zapper", RETRO_DEVICE_ZAPPER }, - { NULL, 0 }, + { 0, 0 }, }; static const struct retro_controller_description pads2[] = { - { "Auto", RETRO_DEVICE_JOYPAD }, + { "Auto", RETRO_DEVICE_AUTO }, { "Gamepad", RETRO_DEVICE_GAMEPAD }, { "Arkanoid", RETRO_DEVICE_ARKANOID }, { "Zapper", RETRO_DEVICE_ZAPPER }, - { NULL, 0 }, + { 0, 0 }, + }; + + static const struct retro_controller_description pads3[] = { + { "Auto", RETRO_DEVICE_AUTO }, + { "Gamepad", RETRO_DEVICE_GAMEPAD }, + { 0, 0 }, + }; + + static const struct retro_controller_description pads4[] = { + { "Auto", RETRO_DEVICE_AUTO }, + { "Gamepad", RETRO_DEVICE_GAMEPAD }, + { 0, 0 }, + }; + + static const struct retro_controller_description pads5[] = { + { "Auto", RETRO_DEVICE_FC_AUTO }, + { "Arkanoid", RETRO_DEVICE_FC_ARKANOID }, + { "(Bandai) Hyper Shot", RETRO_DEVICE_FC_SHADOW }, + { "Oeka Kids Tablet", RETRO_DEVICE_FC_OEKAKIDS }, + { "4-Player Adapter", RETRO_DEVICE_FC_4PLAYERS }, + { 0, 0 }, }; static const struct retro_controller_info ports[] = { { pads1, 3 }, { pads2, 4 }, - { 0 }, + { pads3, 2 }, + { pads4, 2 }, + { pads5, 5 }, + { 0, 0 }, }; environ_cb = cb; @@ -813,69 +961,6 @@ static const keymap bindmap[] = { { RETRO_DEVICE_ID_JOYPAD_Y, JOY_B }, }; -/* Set NES controllers */ -void set_input_nes_controller(unsigned port, int x) -{ - switch (x) - { - case SI_NONE: - input_type[port] = RETRO_DEVICE_NONE; - FCEUI_SetInput(port, SI_NONE, NULL, 0); - FCEU_printf(" Player %u: None\n", port + 1); - break; - case SI_ZAPPER: - input_type[port] = RETRO_DEVICE_ZAPPER; - FCEUI_SetInput(port, SI_ZAPPER, MouseData[port], 1); - FCEU_printf(" Player %u: Zapper\n", port + 1); - break; - case SI_ARKANOID: - input_type[port] = RETRO_DEVICE_ARKANOID; - FCEUI_SetInput(port, SI_ARKANOID, MouseData[port], 0); - FCEU_printf(" Player %u: Arkanoid\n", port + 1); - break; - case SI_GAMEPAD: /* Set gamepad as default when an unsupported device */ - default: /* is used */ - input_type[port] = RETRO_DEVICE_GAMEPAD; - FCEUI_SetInput(port, SI_GAMEPAD, &JSReturn, 0); - FCEU_printf(" Player %u: Gamepad\n", port + 1); - break; - } - - if (enable_4player) // check if 4-player mode is enabled - input_type[2] = input_type[3] = RETRO_DEVICE_GAMEPAD; -} - -/* Set Famicom controllers */ -void set_input_famicom_controller(int x) -{ - switch (x) - { - case SIFC_ARKANOID: - input_type[4] = RETRO_DEVICE_FC_ARKANOID; - FCEUI_SetInputFC(SIFC_ARKANOID, fc_MouseData, 0); - FCEU_printf("Famicom Expansion: Arkanoid\n"); - break; - case SIFC_SHADOW: - input_type[4] = RETRO_DEVICE_FC_SHADOW; - FCEUI_SetInputFC(SIFC_SHADOW, fc_MouseData, 1); - FCEU_printf("Famicom Expansion: (Bandai) Hyper Shot\n"); - break; - case SIFC_OEKAKIDS: - input_type[4] = RETRO_DEVICE_FC_OEKAKIDS; - FCEUI_SetInputFC(SIFC_OEKAKIDS, fc_MouseData, 1); - FCEU_printf("Famicom Expansion: Oeka Kids Tablet\n"); - break; - default: - /* Do not disable port if a 4-player adaptor is used */ - if (!enable_4player) - { - input_type[4] = 0; - FCEUI_SetInputFC(SIFC_NONE, NULL, 0); - break; - } - } -} - static void check_variables(bool startup) { struct retro_variable var = {0}; @@ -1408,8 +1493,6 @@ static void retro_run_blit(uint8_t *gfx) #endif } -static bool firstrun = true; - void retro_run(void) { unsigned i; @@ -1417,13 +1500,6 @@ void retro_run(void) int32_t ssize = 0; bool updated = false; - if (firstrun) - { - /* setup famicom expansion devices */ - set_input_famicom_controller(GameInfo->inputfc); - firstrun = false; - } - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) check_variables(false); @@ -1865,7 +1941,14 @@ bool retro_load_game(const struct retro_game_info *game) } for (i = 0; i < MAX_PORTS; i++) + { + // init default controller + GameInfo->input[i] = SI_GAMEPAD; FCEUI_SetInput(i, SI_GAMEPAD, &JSReturn, 0); + } + + // + FCEU_printf("Setting default controllers...\n"); external_palette_exist = ipalette; if (external_palette_exist) @@ -1899,6 +1982,7 @@ bool retro_load_game(const struct retro_game_info *game) { if (famicom_4p_db_list[i].crc == iNESGameCRC32) { + GameInfo->inputfc = SIFC_4PLAYER; FCEUI_SetInputFC(SIFC_4PLAYER, &JSReturn, 0); enable_4player = true; break; From 53b7fc4ae7caaf6112f7fef62791abb0ec13b24d Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 23 Nov 2018 02:18:16 +0800 Subject: [PATCH 02/34] Remove leftover lines --- src/drivers/libretro/libretro.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 1f6b46e..316828d 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -649,14 +649,10 @@ void retro_set_controller_port_device(unsigned port, unsigned device) { if (port < 2) /* player 1-2 */ { - if (device != RETRO_DEVICE_AUTO) { - printf("Non-auto mode\n"); + if (device != RETRO_DEVICE_AUTO) update_nes_controllers(port, device); - } - else { - printf("automatic mode\n"); + else update_nes_controllers(port, nes_to_libretro(GameInfo->input[port])); - } } else { From 3de40d912675b82bf58823331f217f60b6b5ef15 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 23 Nov 2018 07:25:17 +0800 Subject: [PATCH 03/34] Fix autodetection of NES controllers Closes https://github.com/libretro/libretro-fceumm/issues/230 --- src/drivers/libretro/libretro.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 316828d..f34a19a 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -1937,11 +1937,7 @@ bool retro_load_game(const struct retro_game_info *game) } for (i = 0; i < MAX_PORTS; i++) - { - // init default controller - GameInfo->input[i] = SI_GAMEPAD; FCEUI_SetInput(i, SI_GAMEPAD, &JSReturn, 0); - } // FCEU_printf("Setting default controllers...\n"); From 3cd1ea0060c595b7a42961d51ee4d055d7ca5ef6 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 25 Nov 2018 09:01:21 +0800 Subject: [PATCH 04/34] palette:Labeling and index changes --- src/drivers/libretro/libretro.c | 131 ++++++++++++++++---------------- 1 file changed, 64 insertions(+), 67 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index f34a19a..9942f44 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -160,7 +160,7 @@ int FCEUD_SendData(void *data, uint32 len) #define BLUE_EXPAND 3 #endif -void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g, unsigned char b) +void FCEUD_SetPalette(uint8_t index, uint8_t r, uint8_t g, uint8_t b) { #ifdef FRONTEND_SUPPORTS_RGB565 retro_palette[index] = BUILD_PIXEL_RGB565(r >> RED_EXPAND, g >> GREEN_EXPAND, b >> BLUE_EXPAND); @@ -219,10 +219,11 @@ FILE *FCEUD_UTF8fopen(const char *n, const char *m) return NULL; } -#define MAX_PATH 1024 - /*palette for FCEU*/ -#define MAXPAL 17 /* raw palette # */ +#define PAL_TOTAL 16 /* total no. of palettes in palettes[] */ +#define PAL_DEFAULT (PAL_TOTAL + 1) +#define PAL_RAW (PAL_TOTAL + 2) +#define PAL_CUSTOM (PAL_TOTAL + 3) static int external_palette_exist = 0; extern int ipalette; @@ -834,27 +835,24 @@ static void retro_set_custom_palette(void) ipalette = 0; use_raw_palette = false; - if (!current_palette || current_palette > MAXPAL || (GameInfo->type == GIT_VSUNI)) + if (current_palette == PAL_DEFAULT || current_palette == PAL_CUSTOM + || (GameInfo->type == GIT_VSUNI)) { - if (current_palette > MAXPAL && GameInfo->type != GIT_VSUNI) + if (current_palette == PAL_CUSTOM) { - if (external_palette_exist) - { - ipalette = 1; - } + if (external_palette_exist && (GameInfo->type != GIT_VSUNI)) + ipalette = 1; } - FCEU_ResetPalette(); /* Do palette reset. Priority will be: - * -ipalette : sets external palette - * -ntsccol : sets ntsc to default palette. - * If none of the above are true, then - * default palette will be used. - * VS Uniystem should always use default palette. + FCEU_ResetPalette(); /* if ipalette is set to 1, external palette + * is loaded when FCEU_ResetPalette is called, + * else it will load default NES palette. + * VS Unisystem should always use default palette. */ return; } - if (current_palette == MAXPAL) /* raw palette */ + if (current_palette == PAL_RAW) /* raw palette */ { use_raw_palette = true; for (i = 0; i < 64; i++) @@ -870,13 +868,14 @@ static void retro_set_custom_palette(void) for ( i = 0; i < 64; i++ ) { - r = palettes[current_palette-1].data[i] >> 16; - g = ( palettes[current_palette-1].data[i] & 0xff00 ) >> 8; - b = ( palettes[current_palette-1].data[i] & 0xff ); + unsigned palette_data = palettes[current_palette].data[i]; + r = ( palette_data >> 16 ) & 0xff; + g = ( ( palette_data & 0xff00 ) >> 8 ) & 0xff; + b = ( palette_data & 0xff ); FCEUD_SetPalette( i, r, g, b); - FCEUD_SetPalette( i+64, r, g, b); - FCEUD_SetPalette( i+128, r, g, b); - FCEUD_SetPalette( i+192, r, g, b); + FCEUD_SetPalette( i + 64, r, g, b); + FCEUD_SetPalette( i + 128, r, g, b); + FCEUD_SetPalette( i + 192, r, g, b); } } @@ -970,43 +969,43 @@ static void check_variables(bool startup) unsigned orig_value = current_palette; if (!strcmp(var.value, "default")) - current_palette = 0; - else if (!strcmp(var.value, "asqrealc")) - current_palette = 1; - else if (!strcmp(var.value, "nintendo-vc")) - current_palette = 2; - else if (!strcmp(var.value, "rgb")) - current_palette = 3; - else if (!strcmp(var.value, "yuv-v3")) - current_palette = 4; - else if (!strcmp(var.value, "unsaturated-final")) - current_palette = 5; - else if (!strcmp(var.value, "sony-cxa2025as-us")) - current_palette = 6; - else if (!strcmp(var.value, "pal")) - current_palette = 7; - else if (!strcmp(var.value, "bmf-final2")) - current_palette = 8; - else if (!strcmp(var.value, "bmf-final3")) - current_palette = 9; - else if (!strcmp(var.value, "smooth-fbx")) - current_palette = 10; - else if (!strcmp(var.value, "composite-direct-fbx")) - current_palette = 11; - else if (!strcmp(var.value, "pvm-style-d93-fbx")) - current_palette = 12; - else if (!strcmp(var.value, "ntsc-hardware-fbx")) - current_palette = 13; - else if (!strcmp(var.value, "nes-classic-fbx-fs")) - current_palette = 14; - else if (!strcmp(var.value, "nescap")) - current_palette = 15; - else if (!strcmp(var.value, "wavebeam")) - current_palette = 16; + current_palette = PAL_DEFAULT; else if (!strcmp(var.value, "raw")) - current_palette = MAXPAL; + current_palette = PAL_RAW; else if (!strcmp(var.value, "custom")) - current_palette = MAXPAL+1; + current_palette = PAL_CUSTOM; + else if (!strcmp(var.value, "asqrealc")) + current_palette = 0; + else if (!strcmp(var.value, "nintendo-vc")) + current_palette = 1; + else if (!strcmp(var.value, "rgb")) + current_palette = 2; + else if (!strcmp(var.value, "yuv-v3")) + current_palette = 3; + else if (!strcmp(var.value, "unsaturated-final")) + current_palette = 4; + else if (!strcmp(var.value, "sony-cxa2025as-us")) + current_palette = 5; + else if (!strcmp(var.value, "pal")) + current_palette = 6; + else if (!strcmp(var.value, "bmf-final2")) + current_palette = 7; + else if (!strcmp(var.value, "bmf-final3")) + current_palette = 8; + else if (!strcmp(var.value, "smooth-fbx")) + current_palette = 9; + else if (!strcmp(var.value, "composite-direct-fbx")) + current_palette = 10; + else if (!strcmp(var.value, "pvm-style-d93-fbx")) + current_palette = 11; + else if (!strcmp(var.value, "ntsc-hardware-fbx")) + current_palette = 12; + else if (!strcmp(var.value, "nes-classic-fbx-fs")) + current_palette = 13; + else if (!strcmp(var.value, "nescap")) + current_palette = 14; + else if (!strcmp(var.value, "wavebeam")) + current_palette = 15; if (current_palette != orig_value) retro_set_custom_palette(); @@ -1835,6 +1834,12 @@ static const struct cartridge_db famicom_4p_db_list[] = } }; +#ifdef _WIN32 +static char slash = '\\'; +#else +static char slash = '/'; +#endif + extern uint32_t iNESGameCRC32; bool retro_load_game(const struct retro_game_info *game) @@ -1939,17 +1944,9 @@ bool retro_load_game(const struct retro_game_info *game) for (i = 0; i < MAX_PORTS; i++) FCEUI_SetInput(i, SI_GAMEPAD, &JSReturn, 0); - // - FCEU_printf("Setting default controllers...\n"); - external_palette_exist = ipalette; if (external_palette_exist) - FCEU_printf("nes.pal loaded from system directory.\n"); - else - FCEU_PrintError("Cannot find nes.pal from system directory.\n"); - - if (GameInfo->type == GIT_VSUNI) - FCEU_PrintError("VS Unisystem rom loaded, will use default palette.\n"); + FCEU_printf("Loading custom palette: %s%cnes.pal\n", dir, slash); is_PAL = retro_get_region(); /* Save current loaded region info */ From 9d9c48007d7a45a2cc7ae8175e9aa502a092ce35 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 25 Nov 2018 21:45:52 +0800 Subject: [PATCH 05/34] Add core option: RAM power up state --- src/drivers/libretro/libretro.c | 17 +++++++++++++++++ src/fceu.c | 11 ++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 9942f44..2abb4cd 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -718,6 +718,7 @@ void retro_set_environment(retro_environment_t cb) { "fceumm_zapper_mode", "Zapper Mode; lightgun|mouse" }, { "fceumm_show_crosshair", "Show Crosshair; enabled|disabled" }, { "fceumm_overclocking", "Overclocking; disabled|2x-Postrender|2x-VBlank" }, + { "fceumm_ramstate", "RAM power up state (Restart); fill $ff|fill $00|random" }, { NULL, NULL }, }; @@ -1841,6 +1842,7 @@ static char slash = '/'; #endif extern uint32_t iNESGameCRC32; +extern int option_ramstate; bool retro_load_game(const struct retro_game_info *game) { @@ -1903,10 +1905,25 @@ bool retro_load_game(const struct retro_game_info *game) struct retro_memory_descriptor descs[64]; struct retro_memory_map mmaps; + struct retro_variable var = {0}; if (!game) return false; + var.value = 0; + var.key = "fceumm_ramstate"; + + /* set this variable before calling PowerNES() */ + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "random")) + option_ramstate = 2; + else if (!strcmp(var.value, "fill $00")) + option_ramstate = 1; + else + option_ramstate = 0; + } + PowerNES(); check_system_specs(); #if defined(_3DS) diff --git a/src/fceu.c b/src/fceu.c index 6ede5fc..4f87771 100644 --- a/src/fceu.c +++ b/src/fceu.c @@ -381,6 +381,8 @@ void ResetNES(void) X6502_Reset(); } +int option_ramstate = 0; + void FCEU_MemoryRand(uint8 *ptr, uint32 size) { int x = 0; @@ -394,7 +396,14 @@ void FCEU_MemoryRand(uint8 *ptr, uint32 size) *ptr = (x & 1) ? 0x55 : 0xAA; /* F-15 Sity War HISCORE is screwed... */ /* 1942 SCORE/HISCORE is screwed... */ #endif - *ptr = 0xFF; + uint8_t v; + switch (option_ramstate) + { + case 0: v = 0xff; break; + case 1: v = 0x00; break; + case 2: v = (uint8_t)rand(); break; + } + *ptr = v; x++; size--; ptr++; From e07255c87c21460c5a7c3ee602a0837d216ec5bf Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Mon, 26 Nov 2018 10:43:06 +0800 Subject: [PATCH 06/34] Remove redundant memset() calls --- src/boards/famicombox.c | 1 - src/fds.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/boards/famicombox.c b/src/boards/famicombox.c index 67d9be1..8be1a60 100644 --- a/src/boards/famicombox.c +++ b/src/boards/famicombox.c @@ -75,7 +75,6 @@ static void SSSNROMPower(void) { regs[0] = regs[1] = regs[2] = regs[3] = regs[4] = regs[5] = regs[6] = 0; regs[7] = 0xff; Sync(); - memset(WRAM, 0x00, WRAMSIZE); /* SetWriteHandler(0x0000,0x1FFF,SSSNROMRamWrite); */ SetReadHandler(0x0800, 0x1FFF, CartBR); SetWriteHandler(0x0800, 0x1FFF, CartBW); diff --git a/src/fds.c b/src/fds.c index 775118a..0cfc215 100644 --- a/src/fds.c +++ b/src/fds.c @@ -715,13 +715,11 @@ int FDSLoad(const char *name, FCEUFILE *fp) { CHRRAMSize = 8192; CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize); - memset(CHRRAM, 0, CHRRAMSize); SetupCartCHRMapping(0, CHRRAM, CHRRAMSize, 1); AddExState(CHRRAM, CHRRAMSize, 0, "CHRR"); FDSRAMSize = 32768; FDSRAM = (uint8*)FCEU_gmalloc(FDSRAMSize); - memset(FDSRAM, 0, FDSRAMSize); SetupCartPRGMapping(1, FDSRAM, FDSRAMSize, 1); AddExState(FDSRAM, FDSRAMSize, 0, "FDSR"); From 60d6f17ceab89d7c526144318d9cb963c83a9b84 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Sun, 25 Nov 2018 21:27:21 +0100 Subject: [PATCH 07/34] Build rules for Genode platform --- .gitignore | 1 + Makefile.libretro | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e0292b1..d3399f6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.o *.a +*.so diff --git a/Makefile.libretro b/Makefile.libretro index c37b154..aff8c61 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -366,7 +366,17 @@ else ifeq ($(platform), gcw0) SHARED := -shared -Wl,--version-script=src/drivers/libretro/link.T -Wl,-no-undefined PLATFORM_DEFINES += -ffast-math -march=mips32 -mtune=mips32r2 -mhard-float EXTERNAL_ZLIB = 1 - + +# Genode +else ifeq ($(platform), genode) + TARGET := $(TARGET_NAME)_libretro.lib.so + CC := $(shell pkg-config genode-base --variable=cc) + LD := $(shell pkg-config genode-base --variable=ld) + CFLAGS += $(shell pkg-config --cflags genode-libc) + LDFLAGS += -shared --version-script=src/drivers/libretro/link.T + LDFLAGS += $(shell pkg-config --libs genode-lib genode-libc) + LIBM = + # Windows MSVC 2017 all architectures else ifneq (,$(findstring windows_msvc2017,$(platform))) @@ -660,6 +670,9 @@ else ifeq ($(platform), switch) OBJOUT = -o LINKOUT = -o # libtransistor.mk sets LD for us +else ifeq ($(platform), genode) + OBJOUT = -o + LINKOUT = -o else OBJOUT = -o LINKOUT = -o From 829a7552f199110880de9f26e170302f039973e9 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 30 Nov 2018 09:22:36 +0800 Subject: [PATCH 08/34] Audiostuff (#236) * Add option to enable/disable audio channels Audio options are backports from FCEUX. Options are set as on/off toggle for each apu channel. Compile with DEBUG=1 to see options. * Add missing audio state vars, fix for hq audio when using runahead * Additional checks for save ram (battery) * Cleanup * Update libretro header --- src/boards/69.c | 99 +++-- src/boards/n106.c | 23 ++ src/boards/vrc6.c | 51 ++- .../libretro-common/include/libretro.h | 365 +++++++++++------- src/drivers/libretro/libretro.c | 49 ++- src/fceu.h | 4 + src/file.c | 3 +- src/filter.c | 5 +- src/sound.c | 95 +++-- 9 files changed, 477 insertions(+), 217 deletions(-) diff --git a/src/boards/69.c b/src/boards/69.c index 3907b57..e29d4f0 100644 --- a/src/boards/69.c +++ b/src/boards/69.c @@ -27,6 +27,8 @@ static int32 IRQCount; static uint8 *WRAM = NULL; static uint32 WRAMSIZE; +static void(*sfun[3]) (void); + static SFORMAT StateRegs[] = { { &cmdreg, 1, "CMDR" }, @@ -41,7 +43,7 @@ static SFORMAT StateRegs[] = static void Sync(void) { uint8 i; if ((preg[3] & 0xC0) == 0xC0) - setprg8r(0x10, 0x6000, 0); + setprg8r(0x10, 0x6000, preg[3] & 0x3F); else setprg8(0x6000, preg[3] & 0x3F); setprg8(0x8000, preg[0]); @@ -89,16 +91,13 @@ static DECLFW(M69Write1) { case 0xA: preg[1] = V; Sync(); break; case 0xB: preg[2] = V; Sync(); break; case 0xC: mirr = V & 3; Sync();break; - /* 17/10/17- reg $0D should awknowledge IRQ and no other - * http://forums.nesdev.com/viewtopic.php?f=2&t=12436&start=15 - */ case 0xD: IRQa = V; X6502_IRQEnd(FCEU_IQEXT); break; case 0xE: IRQCount &= 0xFF00; IRQCount |= V; break; case 0xF: IRQCount &= 0x00FF; IRQCount |= V << 8; break; } } -/* SUNSOFT-5/FME-7 Sound */ +// SUNSOFT-5/FME-7 Sound static void AYSound(int Count); static void AYSoundHQ(void); @@ -114,6 +113,15 @@ static SFORMAT SStateRegs[] = { { &sndcmd, 1, "SCMD" }, { sreg, 14, "SREG" }, + { &dcount[0], 4 | FCEUSTATE_RLSB, "DCT0" }, + { &dcount[1], 4 | FCEUSTATE_RLSB, "DCT1" }, + { &dcount[2], 4 | FCEUSTATE_RLSB, "DCT2" }, + { &vcount[0], 4 | FCEUSTATE_RLSB, "VCT0" }, + { &vcount[1], 4 | FCEUSTATE_RLSB, "VCT1" }, + { &vcount[2], 4 | FCEUSTATE_RLSB, "VCT2" }, + { &CAYBC[0], 4 | FCEUSTATE_RLSB, "BC00" }, + { &CAYBC[1], 4 | FCEUSTATE_RLSB, "BC01" }, + { &CAYBC[2], 4 | FCEUSTATE_RLSB, "BC02" }, { 0 } }; @@ -125,22 +133,21 @@ static DECLFW(M69SWrite1) { int x; GameExpSound.Fill = AYSound; GameExpSound.HiFill = AYSoundHQ; - if (FSettings.SndRate) - switch (sndcmd) { - case 0: - case 1: - case 8: if (FSettings.soundq >= 1) DoAYSQHQ(0); else DoAYSQ(0); break; - case 2: - case 3: - case 9: if (FSettings.soundq >= 1) DoAYSQHQ(1); else DoAYSQ(1); break; - case 4: - case 5: - case 10: if (FSettings.soundq >= 1) DoAYSQHQ(2); else DoAYSQ(2); break; - case 7: - for (x = 0; x < 2; x++) - if (FSettings.soundq >= 1) DoAYSQHQ(x); else DoAYSQ(x); - break; - } + switch (sndcmd) { + case 0: + case 1: + case 8: if (sfun[0]) sfun[0](); break; + case 2: + case 3: + case 9: if (sfun[1]) sfun[1](); break; + case 4: + case 5: + case 10: if (sfun[2]) sfun[2](); break; + case 7: + if (sfun[0]) sfun[0](); + if (sfun[1]) sfun[1](); + break; + } sreg[sndcmd] = V; } @@ -190,19 +197,43 @@ static void DoAYSQHQ(int x) { CAYBC[x] = SOUNDTS; } +static void DoAYSQ1(void) { + DoAYSQ(0); +} + +static void DoAYSQ2(void) { + DoAYSQ(1); +} + +static void DoAYSQ3(void) { + DoAYSQ(2); +} + +static void DoAYSQ1HQ(void) { + DoAYSQHQ(0); +} + +static void DoAYSQ2HQ(void) { + DoAYSQHQ(1); +} + +static void DoAYSQ3HQ(void) { + DoAYSQHQ(2); +} + static void AYSound(int Count) { int x; - DoAYSQ(0); - DoAYSQ(1); - DoAYSQ(2); + DoAYSQ1(); + DoAYSQ2(); + DoAYSQ3(); for (x = 0; x < 3; x++) CAYBC[x] = Count; } static void AYSoundHQ(void) { - DoAYSQHQ(0); - DoAYSQHQ(1); - DoAYSQHQ(2); + DoAYSQ1HQ(); + DoAYSQ2HQ(); + DoAYSQ3HQ(); } static void AYHiSync(int32 ts) { @@ -218,6 +249,18 @@ void Mapper69_ESI(void) { memset(dcount, 0, sizeof(dcount)); memset(vcount, 0, sizeof(vcount)); memset(CAYBC, 0, sizeof(CAYBC)); + if (FSettings.SndRate) { + if (FSettings.soundq >= 1) { + sfun[0] = DoAYSQ1HQ; + sfun[1] = DoAYSQ2HQ; + sfun[2] = DoAYSQ3HQ; + } else { + sfun[0] = DoAYSQ1; + sfun[1] = DoAYSQ2; + sfun[2] = DoAYSQ3; + } + } else + memset(sfun, 0, sizeof(sfun)); } /* SUNSOFT-5/FME-7 Sound */ @@ -270,8 +313,8 @@ void Mapper69_Init(CartInfo *info) { } GameStateRestore = StateRestore; Mapper69_ESI(); - AddExState(&SStateRegs, ~0, 0, 0); AddExState(&StateRegs, ~0, 0, 0); + AddExState(&SStateRegs, ~0, 0, 0); } void NSFAY_Init(void) { diff --git a/src/boards/n106.c b/src/boards/n106.c index f786a57..e5e8473 100644 --- a/src/boards/n106.c +++ b/src/boards/n106.c @@ -224,6 +224,28 @@ static int32 CVBC; #define TOINDEX (16 + 1) +static SFORMAT N106_SStateRegs[] = +{ + { &PlayIndex[0], 4 | FCEUSTATE_RLSB, "IDX0" }, + { &PlayIndex[1], 4 | FCEUSTATE_RLSB, "IDX1" }, + { &PlayIndex[2], 4 | FCEUSTATE_RLSB, "IDX2" }, + { &PlayIndex[3], 4 | FCEUSTATE_RLSB, "IDX3" }, + { &PlayIndex[4], 4 | FCEUSTATE_RLSB, "IDX4" }, + { &PlayIndex[5], 4 | FCEUSTATE_RLSB, "IDX5" }, + { &PlayIndex[6], 4 | FCEUSTATE_RLSB, "IDX6" }, + { &PlayIndex[7], 4 | FCEUSTATE_RLSB, "IDX7" }, + { &vcount[0], 4 | FCEUSTATE_RLSB, "VCT0" }, + { &vcount[1], 4 | FCEUSTATE_RLSB, "VCT1" }, + { &vcount[2], 4 | FCEUSTATE_RLSB, "VCT2" }, + { &vcount[3], 4 | FCEUSTATE_RLSB, "VCT3" }, + { &vcount[4], 4 | FCEUSTATE_RLSB, "VCT4" }, + { &vcount[5], 4 | FCEUSTATE_RLSB, "VCT5" }, + { &vcount[6], 4 | FCEUSTATE_RLSB, "VCT6" }, + { &vcount[7], 4 | FCEUSTATE_RLSB, "VCT7" }, + { &CVBC, 4 | FCEUSTATE_RLSB, "BC00" }, + { 0 } +}; + /* 16:15 */ static void SyncHQ(int32 ts) { CVBC = ts; @@ -404,6 +426,7 @@ void Mapper19_Init(CartInfo *info) { AddExState(WRAM, 8192, 0, "WRAM"); AddExState(IRAM, 128, 0, "IRAM"); AddExState(N106_StateRegs, ~0, 0, 0); + AddExState(N106_SStateRegs, ~0, 0, 0); if (info->battery) { info->SaveGame[0] = WRAM; diff --git a/src/boards/vrc6.c b/src/boards/vrc6.c index c8772c7..e133e36 100644 --- a/src/boards/vrc6.c +++ b/src/boards/vrc6.c @@ -44,16 +44,32 @@ static SFORMAT StateRegs[] = }; static void(*sfun[3]) (void); + static uint8 vpsg1[8]; static uint8 vpsg2[4]; static int32 cvbc[3]; static int32 vcount[3]; static int32 dcount[2]; +static int32 saw1phaseacc; +static int32 phaseacc; +static uint8 b3; /* clock counter, resets phaseacc on the 7th clock */ static SFORMAT SStateRegs[] = { { vpsg1, 8, "PSG1" }, { vpsg2, 4, "PSG2" }, + /* rw - 2018-11-28 Added */ + { &cvbc[0], 4 | FCEUSTATE_RLSB, "BC01" }, + { &cvbc[1], 4 | FCEUSTATE_RLSB, "BC02" }, + { &cvbc[2], 4 | FCEUSTATE_RLSB, "BC03" }, + { &dcount[0], 4 | FCEUSTATE_RLSB, "DCT0" }, + { &dcount[1], 4 | FCEUSTATE_RLSB, "DCT1" }, + { &vcount[0], 4 | FCEUSTATE_RLSB, "VCT0" }, + { &vcount[1], 4 | FCEUSTATE_RLSB, "VCT1" }, + { &vcount[2], 4 | FCEUSTATE_RLSB, "VCT1" }, + { &saw1phaseacc, 4| FCEUSTATE_RLSB, "SAW1" }, + { &phaseacc, 4 | FCEUSTATE_RLSB, "PACC" }, + { &b3, 1, "CLKC" }, { 0 } }; @@ -177,15 +193,20 @@ static INLINE void DoSQV(int x) { } else { int32 thresh = (vpsg1[x << 2] >> 4) & 7; int32 freq = ((vpsg1[(x << 2) | 0x1] | ((vpsg1[(x << 2) | 0x2] & 15) << 8)) + 1) << 17; + int32 dc = dcount[x]; + int32 vc = vcount[x]; + for (V = start; V < end; V++) { - if (dcount[x] > thresh) + if (dc > thresh) Wave[V >> 4] += amp; - vcount[x] -= nesincsize; - while (vcount[x] <= 0) { - vcount[x] += freq; - dcount[x] = (dcount[x] + 1) & 15; + vc -= nesincsize; + while (vc <= 0) { + vc += freq; + dc = (dc + 1) & 15; } } + vcount[x] = vc; + dcount[x] = dc; } } } @@ -208,10 +229,7 @@ static void DoSawV(void) { cvbc[2] = end; if (vpsg2[2] & 0x80) { - static int32 saw1phaseacc = 0; uint32 freq3; - static uint8 b3 = 0; - static int32 phaseacc = 0; static uint32 duff = 0; freq3 = (vpsg2[1] + ((vpsg2[2] & 15) << 8) + 1); @@ -249,15 +267,20 @@ static INLINE void DoSQVHQ(int x) { WaveHi[V] += amp; } else { int32 thresh = (vpsg1[x << 2] >> 4) & 7; + int32 dc = dcount[x]; + int32 vc = vcount[x]; + for (V = cvbc[x]; V < (int)SOUNDTS; V++) { - if (dcount[x] > thresh) + if (dc > thresh) WaveHi[V] += amp; - vcount[x]--; - if (vcount[x] <= 0) { - vcount[x] = (vpsg1[(x << 2) | 0x1] | ((vpsg1[(x << 2) | 0x2] & 15) << 8)) + 1; - dcount[x] = (dcount[x] + 1) & 15; + vc--; + if (vc <= 0) { + vc = (vpsg1[(x << 2) | 0x1] | ((vpsg1[(x << 2) | 0x2] & 15) << 8)) + 1; + dc = (dc + 1) & 15; } } + dcount[x] = dc; + vcount[x] = vc; } } cvbc[x] = SOUNDTS; @@ -272,8 +295,6 @@ static void DoSQV2HQ(void) { } static void DoSawVHQ(void) { - static uint8 b3 = 0; - static int32 phaseacc = 0; int32 V; if (vpsg2[2] & 0x80) { diff --git a/src/drivers/libretro/libretro-common/include/libretro.h b/src/drivers/libretro/libretro-common/include/libretro.h index 7d01185..4e1a978 100644 --- a/src/drivers/libretro/libretro-common/include/libretro.h +++ b/src/drivers/libretro/libretro-common/include/libretro.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro API header (libretro.h). @@ -128,7 +128,8 @@ extern "C" { /* LIGHTGUN device is similar to Guncon-2 for PlayStation 2. * It reports X/Y coordinates in screen space (similar to the pointer) - * in the range [-0x8000, 0x7fff] in both axes, with zero being center. + * in the range [-0x8000, 0x7fff] in both axes, with zero being center and + * -0x8000 being out of bounds. * As well as reporting on/off screen state. It features a trigger, * start/select buttons, auxiliary action buttons and a * directional pad. A forced off-screen shot can be requested for @@ -139,7 +140,8 @@ extern "C" { /* The ANALOG device is an extension to JOYPAD (RetroPad). * Similar to DualShock2 it adds two analog sticks and all buttons can * be analog. This is treated as a separate device type as it returns - * axis values in the full analog range of [-0x8000, 0x7fff]. + * axis values in the full analog range of [-0x7fff, 0x7fff], + * although some devices may return -0x8000. * Positive X axis is right. Positive Y axis is down. * Buttons are returned in the range [0, 0x7fff]. * Only use ANALOG type when polling for analog values. @@ -271,6 +273,7 @@ enum retro_language RETRO_LANGUAGE_POLISH = 14, RETRO_LANGUAGE_VIETNAMESE = 15, RETRO_LANGUAGE_ARABIC = 16, + RETRO_LANGUAGE_GREEK = 17, RETRO_LANGUAGE_LAST, /* Ensure sizeof(enum) == sizeof(int) */ @@ -450,6 +453,7 @@ enum retro_key RETROK_POWER = 320, RETROK_EURO = 321, RETROK_UNDO = 322, + RETROK_OEM_102 = 323, RETROK_LAST, @@ -599,9 +603,12 @@ enum retro_mod * GET_VARIABLE. * This allows the frontend to present these variables to * a user dynamically. - * This should be called as early as possible (ideally in - * retro_set_environment). - * + * This should be called the first time as early as + * possible (ideally in retro_set_environment). + * Afterward it may be called again for the core to communicate + * updated options to the frontend, but the number of core + * options must not change from the number in the initial call. + * * 'data' points to an array of retro_variable structs * terminated by a { NULL, NULL } element. * retro_variable::key should be namespaced to not collide @@ -654,6 +661,15 @@ enum retro_mod /* Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. * It was not used by any known core at the time, * and was removed from the API. */ +#define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21 + /* const struct retro_frame_time_callback * -- + * Lets the core know how much time has passed since last + * invocation of retro_run(). + * The frontend can tamper with the timing to fake fast-forward, + * slow-motion, frame stepping, etc. + * In this case the delta time will use the reference value + * in frame_time_callback.. + */ #define RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK 22 /* const struct retro_audio_callback * -- * Sets an interface which is used to notify a libretro core about audio @@ -680,15 +696,6 @@ enum retro_mod * A libretro core using SET_AUDIO_CALLBACK should also make use of * SET_FRAME_TIME_CALLBACK. */ -#define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21 - /* const struct retro_frame_time_callback * -- - * Lets the core know how much time has passed since last - * invocation of retro_run(). - * The frontend can tamper with the timing to fake fast-forward, - * slow-motion, frame stepping, etc. - * In this case the delta time will use the reference value - * in frame_time_callback.. - */ #define RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE 23 /* struct retro_rumble_interface * -- * Gets an interface which is used by a libretro core to set @@ -775,17 +782,18 @@ enum retro_mod */ #define RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY 31 /* const char ** -- - * Returns the "save" directory of the frontend. - * This directory can be used to store SRAM, memory cards, - * high scores, etc, if the libretro core + * Returns the "save" directory of the frontend, unless there is no + * save directory available. The save directory should be used to + * store SRAM, memory cards, high scores, etc, if the libretro core * cannot use the regular memory interface (retro_get_memory_data()). * - * NOTE: libretro cores used to check GET_SYSTEM_DIRECTORY for - * similar things before. - * They should still check GET_SYSTEM_DIRECTORY if they want to - * be backwards compatible. - * The path here can be NULL. It should only be non-NULL if the - * frontend user has set a specific save path. + * If the frontend cannot designate a save directory, it will return + * NULL to indicate that the core should attempt to operate without a + * save directory set. + * + * NOTE: early libretro cores used the system directory for save + * files. Cores that need to be backwards-compatible can still check + * GET_SYSTEM_DIRECTORY. */ #define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32 /* const struct retro_system_av_info * -- @@ -853,26 +861,39 @@ enum retro_mod #define RETRO_ENVIRONMENT_SET_CONTROLLER_INFO 35 /* const struct retro_controller_info * -- * This environment call lets a libretro core tell the frontend - * which controller types are recognized in calls to + * which controller subclasses are recognized in calls to * retro_set_controller_port_device(). * - * Some emulators such as Super Nintendo - * support multiple lightgun types which must be specifically - * selected from. - * It is therefore sometimes necessary for a frontend to be able - * to tell the core about a special kind of input device which is - * not covered by the libretro input API. + * Some emulators such as Super Nintendo support multiple lightgun + * types which must be specifically selected from. It is therefore + * sometimes necessary for a frontend to be able to tell the core + * about a special kind of input device which is not specifcally + * provided by the Libretro API. * - * In order for a frontend to understand the workings of an input device, - * it must be a specialized type - * of the generic device types already defined in the libretro API. + * In order for a frontend to understand the workings of those devices, + * they must be defined as a specialized subclass of the generic device + * types already defined in the libretro API. * - * Which devices are supported can vary per input port. * The core must pass an array of const struct retro_controller_info which - * is terminated with a blanked out struct. Each element of the struct - * corresponds to an ascending port index to - * retro_set_controller_port_device(). - * Even if special device types are set in the libretro core, + * is terminated with a blanked out struct. Each element of the + * retro_controller_info struct corresponds to the ascending port index + * that is passed to retro_set_controller_port_device() when that function + * is called to indicate to the core that the frontend has changed the + * active device subclass. SEE ALSO: retro_set_controller_port_device() + * + * The ascending input port indexes provided by the core in the struct + * are generally presented by frontends as ascending User # or Player #, + * such as Player 1, Player 2, Player 3, etc. Which device subclasses are + * supported can vary per input port. + * + * The first inner element of each entry in the retro_controller_info array + * is a retro_controller_description struct that specifies the names and + * codes of all device subclasses that are available for the corresponding + * User or Player, beginning with the generic Libretro device that the + * subclasses are derived from. The second inner element of each entry is the + * total number of subclasses that are listed in the retro_controller_description. + * + * NOTE: Even if special device types are set in the libretro core, * libretro should only poll input based on the base input device types. */ #define RETRO_ENVIRONMENT_SET_MEMORY_MAPS (36 | RETRO_ENVIRONMENT_EXPERIMENTAL) @@ -951,7 +972,37 @@ enum retro_mod * A frontend must make sure that the pointer obtained from this function is * writeable (and readable). */ - +#define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* const struct retro_hw_render_interface ** -- + * Returns an API specific rendering interface for accessing API specific data. + * Not all HW rendering APIs support or need this. + * The contents of the returned pointer is specific to the rendering API + * being used. See the various headers like libretro_vulkan.h, etc. + * + * GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called. + * Similarly, after context_destroyed callback returns, + * the contents of the HW_RENDER_INTERFACE are invalidated. + */ +#define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* const bool * -- + * If true, the libretro implementation supports achievements + * either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS + * or via retro_get_memory_data/retro_get_memory_size. + * + * This must be called before the first call to retro_run. + */ +#define RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE (43 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* const struct retro_hw_render_context_negotiation_interface * -- + * Sets an interface which lets the libretro core negotiate with frontend how a context is created. + * The semantics of this interface depends on which API is used in SET_HW_RENDER earlier. + * This interface will be used when the frontend is trying to create a HW rendering context, + * so it will be used after SET_HW_RENDER, but before the context_reset callback. + */ +#define RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS 44 + /* uint64_t * -- + * Sets quirk flags associated with serialization. The frontend will zero any flags it doesn't + * recognize or support. Should be set in either retro_init or retro_load_game, but not both. + */ #define RETRO_ENVIRONMENT_SET_HW_SHARED_CONTEXT (44 | RETRO_ENVIRONMENT_EXPERIMENTAL) /* N/A (null) * -- * The frontend will try to use a 'shared' hardware context (mostly applicable @@ -963,14 +1014,70 @@ enum retro_mod * This will do nothing on its own until SET_HW_RENDER env callbacks are * being used. */ - #define RETRO_ENVIRONMENT_GET_VFS_INTERFACE (45 | RETRO_ENVIRONMENT_EXPERIMENTAL) /* struct retro_vfs_interface_info * -- * Gets access to the VFS interface. * VFS presence needs to be queried prior to load_game or any * get_system/save/other_directory being called to let front end know * core supports VFS before it starts handing out paths. - * It is recomended to do so in retro_set_environment */ + * It is recomended to do so in retro_set_environment + */ +#define RETRO_ENVIRONMENT_GET_LED_INTERFACE (46 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* struct retro_led_interface * -- + * Gets an interface which is used by a libretro core to set + * state of LEDs. + */ +#define RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE (47 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* int * -- + * Tells the core if the frontend wants audio or video. + * If disabled, the frontend will discard the audio or video, + * so the core may decide to skip generating a frame or generating audio. + * This is mainly used for increasing performance. + * Bit 0 (value 1): Enable Video + * Bit 1 (value 2): Enable Audio + * Bit 2 (value 4): Use Fast Savestates. + * Bit 3 (value 8): Hard Disable Audio + * Other bits are reserved for future use and will default to zero. + * If video is disabled: + * * The frontend wants the core to not generate any video, + * including presenting frames via hardware acceleration. + * * The frontend's video frame callback will do nothing. + * * After running the frame, the video output of the next frame should be + * no different than if video was enabled, and saving and loading state + * should have no issues. + * If audio is disabled: + * * The frontend wants the core to not generate any audio. + * * The frontend's audio callbacks will do nothing. + * * After running the frame, the audio output of the next frame should be + * no different than if audio was enabled, and saving and loading state + * should have no issues. + * Fast Savestates: + * * Guaranteed to be created by the same binary that will load them. + * * Will not be written to or read from the disk. + * * Suggest that the core assumes loading state will succeed. + * * Suggest that the core updates its memory buffers in-place if possible. + * * Suggest that the core skips clearing memory. + * * Suggest that the core skips resetting the system. + * * Suggest that the core may skip validation steps. + * Hard Disable Audio: + * * Used for a secondary core when running ahead. + * * Indicates that the frontend will never need audio from the core. + * * Suggests that the core may stop synthesizing audio, but this should not + * compromise emulation accuracy. + * * Audio output for the next frame does not matter, and the frontend will + * never need an accurate audio state in the future. + * * State will never be saved when using Hard Disable Audio. + */ +#define RETRO_ENVIRONMENT_GET_MIDI_INTERFACE (48 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* struct retro_midi_interface ** -- + * Returns a MIDI interface that can be used for raw data I/O. + */ + +#define RETRO_ENVIRONMENT_GET_FASTFORWARDING (49 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* bool * -- + * Boolean value that indicates whether or not the frontend is in + * fastforwarding mode. + */ /* VFS functionality */ @@ -1030,6 +1137,10 @@ typedef int (RETRO_CALLCONV *retro_vfs_close_t)(struct retro_vfs_file_handle *st * Introduced in VFS API v1 */ typedef int64_t (RETRO_CALLCONV *retro_vfs_size_t)(struct retro_vfs_file_handle *stream); +/* Truncate file to specified size. Returns 0 on success or -1 on error + * Introduced in VFS API v2 */ +typedef int64_t (RETRO_CALLCONV *retro_vfs_truncate_t)(struct retro_vfs_file_handle *stream, int64_t length); + /* Get the current read / write position for the file. Returns - 1 for error. * Introduced in VFS API v1 */ typedef int64_t (RETRO_CALLCONV *retro_vfs_tell_t)(struct retro_vfs_file_handle *stream); @@ -1060,6 +1171,7 @@ typedef int (RETRO_CALLCONV *retro_vfs_rename_t)(const char *old_path, const cha struct retro_vfs_interface { + /* VFS API v1 */ retro_vfs_get_path_t get_path; retro_vfs_open_t open; retro_vfs_close_t close; @@ -1071,6 +1183,8 @@ struct retro_vfs_interface retro_vfs_flush_t flush; retro_vfs_remove_t remove; retro_vfs_rename_t rename; + /* VFS API v2 */ + retro_vfs_truncate_t truncate; }; struct retro_vfs_interface_info @@ -1104,81 +1218,41 @@ struct retro_hw_render_interface unsigned interface_version; }; - -#define RETRO_ENVIRONMENT_GET_LED_INTERFACE (46 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_led_interface * -- - * Gets an interface which is used by a libretro core to set - * state of LEDs. - */ - typedef void (RETRO_CALLCONV *retro_set_led_state_t)(int led, int state); struct retro_led_interface { retro_set_led_state_t set_led_state; }; -#define RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE (47 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* int * -- - * Tells the core if the frontend wants audio or video. - * If disabled, the frontend will discard the audio or video, - * so the core may decide to skip generating a frame or generating audio. - * This is mainly used for increasing performance. - * Bit 0 (value 1): Enable Video - * Bit 1 (value 2): Enable Audio - * Bit 2 (value 4): Use Fast Savestates. - * Bit 3 (value 8): Hard Disable Audio - * Other bits are reserved for future use and will default to zero. - * If video is disabled: - * * The frontend wants the core to not generate any video, - * including presenting frames via hardware acceleration. - * * The frontend's video frame callback will do nothing. - * * After running the frame, the video output of the next frame should be - * no different than if video was enabled, and saving and loading state - * should have no issues. - * If audio is disabled: - * * The frontend wants the core to not generate any audio. - * * The frontend's audio callbacks will do nothing. - * * After running the frame, the audio output of the next frame should be - * no different than if audio was enabled, and saving and loading state - * should have no issues. - * Fast Savestates: - * * Guaranteed to be created by the same binary that will load them. - * * Will not be written to or read from the disk. - * * Suggest that the core assumes loading state will succeed. - * * Suggest that the core updates its memory buffers in-place if possible. - * * Suggest that the core skips clearing memory. - * * Suggest that the core skips resetting the system. - * * Suggest that the core may skip validation steps. - * Hard Disable Audio: - * * Used for a secondary core when running ahead. - * * Indicates that the frontend will never need audio from the core. - * * Suggests that the core may stop synthesizing audio, but this should not - * compromise emulation accuracy. - * * Audio output for the next frame does not matter, and the frontend will - * never need an accurate audio state in the future. - * * State will never be saved when using Hard Disable Audio. - */ +/* Retrieves the current state of the MIDI input. + * Returns true if it's enabled, false otherwise. */ +typedef bool (RETRO_CALLCONV *retro_midi_input_enabled_t)(void); -#define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const struct retro_hw_render_interface ** -- - * Returns an API specific rendering interface for accessing API specific data. - * Not all HW rendering APIs support or need this. - * The contents of the returned pointer is specific to the rendering API - * being used. See the various headers like libretro_vulkan.h, etc. - * - * GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called. - * Similarly, after context_destroyed callback returns, - * the contents of the HW_RENDER_INTERFACE are invalidated. - */ +/* Retrieves the current state of the MIDI output. + * Returns true if it's enabled, false otherwise */ +typedef bool (RETRO_CALLCONV *retro_midi_output_enabled_t)(void); -#define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const bool * -- - * If true, the libretro implementation supports achievements - * either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS - * or via retro_get_memory_data/retro_get_memory_size. - * - * This must be called before the first call to retro_run. - */ +/* Reads next byte from the input stream. + * Returns true if byte is read, false otherwise. */ +typedef bool (RETRO_CALLCONV *retro_midi_read_t)(uint8_t *byte); + +/* Writes byte to the output stream. + * 'delta_time' is in microseconds and represent time elapsed since previous write. + * Returns true if byte is written, false otherwise. */ +typedef bool (RETRO_CALLCONV *retro_midi_write_t)(uint8_t byte, uint32_t delta_time); + +/* Flushes previously written data. + * Returns true if successful, false otherwise. */ +typedef bool (RETRO_CALLCONV *retro_midi_flush_t)(void); + +struct retro_midi_interface +{ + retro_midi_input_enabled_t input_enabled; + retro_midi_output_enabled_t output_enabled; + retro_midi_read_t read; + retro_midi_write_t write; + retro_midi_flush_t flush; +}; enum retro_hw_render_context_negotiation_interface_type { @@ -1193,13 +1267,6 @@ struct retro_hw_render_context_negotiation_interface enum retro_hw_render_context_negotiation_interface_type interface_type; unsigned interface_version; }; -#define RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE (43 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const struct retro_hw_render_context_negotiation_interface * -- - * Sets an interface which lets the libretro core negotiate with frontend how a context is created. - * The semantics of this interface depends on which API is used in SET_HW_RENDER earlier. - * This interface will be used when the frontend is trying to create a HW rendering context, - * so it will be used after SET_HW_RENDER, but before the context_reset callback. - */ /* Serialized state is incomplete in some way. Set if serialization is * usable in typical end-user cases but should not be relied upon to @@ -1225,20 +1292,17 @@ struct retro_hw_render_context_negotiation_interface * dependence */ #define RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT (1 << 6) -#define RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS 44 - /* uint64_t * -- - * Sets quirk flags associated with serialization. The frontend will zero any flags it doesn't - * recognize or support. Should be set in either retro_init or retro_load_game, but not both. - */ - -#define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */ -#define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */ -#define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */ -#define RETRO_MEMDESC_ALIGN_4 (2 << 16) -#define RETRO_MEMDESC_ALIGN_8 (3 << 16) -#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) /* All memory in this region is accessed at least 2 bytes at the time. */ -#define RETRO_MEMDESC_MINSIZE_4 (2 << 24) -#define RETRO_MEMDESC_MINSIZE_8 (3 << 24) +#define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */ +#define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */ +#define RETRO_MEMDESC_SYSTEM_RAM (1 << 2) /* The memory area is system RAM. This is main RAM of the gaming system. */ +#define RETRO_MEMDESC_SAVE_RAM (1 << 3) /* The memory area is save RAM. This RAM is usually found on a game cartridge, backed up by a battery. */ +#define RETRO_MEMDESC_VIDEO_RAM (1 << 4) /* The memory area is video RAM (VRAM) */ +#define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */ +#define RETRO_MEMDESC_ALIGN_4 (2 << 16) +#define RETRO_MEMDESC_ALIGN_8 (3 << 16) +#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) /* All memory in this region is accessed at least 2 bytes at the time. */ +#define RETRO_MEMDESC_MINSIZE_4 (2 << 24) +#define RETRO_MEMDESC_MINSIZE_8 (3 << 24) struct retro_memory_descriptor { uint64_t flags; @@ -2138,17 +2202,26 @@ struct retro_system_info * Typically used for a GUI to filter * out extensions. */ - /* If true, retro_load_game() is guaranteed to provide a valid pathname - * in retro_game_info::path. - * ::data and ::size are both invalid. + /* Libretro cores that need to have direct access to their content + * files, including cores which use the path of the content files to + * determine the paths of other files, should set need_fullpath to true. * - * If false, ::data and ::size are guaranteed to be valid, but ::path - * might not be valid. + * Cores should strive for setting need_fullpath to false, + * as it allows the frontend to perform patching, etc. * - * This is typically set to true for libretro implementations that must - * load from file. - * Implementations should strive for setting this to false, as it allows - * the frontend to perform patching, etc. */ + * If need_fullpath is true and retro_load_game() is called: + * - retro_game_info::path is guaranteed to have a valid path + * - retro_game_info::data and retro_game_info::size are invalid + * + * If need_fullpath is false and retro_load_game() is called: + * - retro_game_info::path may be NULL + * - retro_game_info::data and retro_game_info::size are guaranteed + * to be valid + * + * See also: + * - RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY + * - RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY + */ bool need_fullpath; /* If true, the frontend is not allowed to extract any archives before @@ -2333,7 +2406,13 @@ RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info); * will only poll input based on that particular device type. It is only a * hint to the libretro core when a core cannot automatically detect the * appropriate input device type on its own. It is also relevant when a - * core can change its behavior depending on device type. */ + * core can change its behavior depending on device type. + * + * As part of the core's implementation of retro_set_controller_port_device, + * the core should call RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS to notify the + * frontend if the descriptions for any controls have changed as a + * result of changing the device type. + */ RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device); /* Resets the current game. */ @@ -2365,7 +2444,9 @@ RETRO_API bool retro_unserialize(const void *data, size_t size); RETRO_API void retro_cheat_reset(void); RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code); -/* Loads a game. */ +/* Loads a game. + * Return true to indicate successful loading and false to indicate load failure. + */ RETRO_API bool retro_load_game(const struct retro_game_info *game); /* Loads a "special" kind of game. Should not be used, @@ -2375,7 +2456,7 @@ RETRO_API bool retro_load_game_special( const struct retro_game_info *info, size_t num_info ); -/* Unloads a currently loaded game. */ +/* Unloads the currently loaded game. Called before retro_deinit(void). */ RETRO_API void retro_unload_game(void); /* Gets region of game. */ diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 2abb4cd..f62ed8e 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -719,6 +719,13 @@ void retro_set_environment(retro_environment_t cb) { "fceumm_show_crosshair", "Show Crosshair; enabled|disabled" }, { "fceumm_overclocking", "Overclocking; disabled|2x-Postrender|2x-VBlank" }, { "fceumm_ramstate", "RAM power up state (Restart); fill $ff|fill $00|random" }, +#ifdef DEBUG + { "fceumm_apu_1", "Enable Sound Channel 1 (Square 1); enabled|disabled" }, + { "fceumm_apu_2", "Enable Sound Channel 2 (Square 2); enabled|disabled" }, + { "fceumm_apu_3", "Enable Sound Channel 3 (Triangle); enabled|disabled" }, + { "fceumm_apu_4", "Enable Sound Channel 4 (Noise) ; enabled|disabled" }, + { "fceumm_apu_5", "Enable Sound Channel 5 (PCM); enabled|disabled" }, +#endif { NULL, NULL }, }; @@ -957,11 +964,22 @@ static const keymap bindmap[] = { { RETRO_DEVICE_ID_JOYPAD_Y, JOY_B }, }; +static void set_apu_channels(int chan) +{ + FSettings.SquareVolume[1] = 255 * ((chan >> 0) & 1); + FSettings.SquareVolume[0] = 255 * ((chan >> 1) & 1); + FSettings.TriangleVolume = 255 * ((chan >> 2) & 1); + FSettings.NoiseVolume = 255 * ((chan >> 3) & 1); + FSettings.PCMVolume = 255 * ((chan >> 4) & 1); +} + static void check_variables(bool startup) { struct retro_variable var = {0}; struct retro_system_av_info av_info; bool geometry_update = false; + char key[256]; + int i, enable_apu; var.key = "fceumm_palette"; @@ -1169,7 +1187,6 @@ static void check_variables(bool startup) FCEUD_RegionOverride(setregion); } - var.key = "fceumm_aspect"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) @@ -1221,6 +1238,27 @@ static void check_variables(bool startup) swapDuty = newval; } } + +#ifdef DEBUG + var.key = key; + + enable_apu = 0; + + strcpy(key, "fceumm_apu_x"); + for (i = 0; i < 5; i++) + { + key[strlen("fceumm_apu_")] = '1' + i; + var.value = NULL; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && !strcmp(var.value, "disabled")) + { + enable_apu |= (1 << i); + } + } + set_apu_channels(enable_apu ^ 0xff); +#else + set_apu_channels(0xff); +#endif + } static int mzx = 0, mzy = 0; @@ -2043,7 +2081,6 @@ unsigned retro_get_region(void) return FSettings.PAL ? RETRO_REGION_PAL : RETRO_REGION_NTSC; } - void *retro_get_memory_data(unsigned type) { uint8_t* data; @@ -2051,9 +2088,9 @@ void *retro_get_memory_data(unsigned type) switch(type) { case RETRO_MEMORY_SAVE_RAM: - if (iNESCart.battery) + if (iNESCart.battery && iNESCart.SaveGame[0] && iNESCart.SaveGameLen[0]) return iNESCart.SaveGame[0]; - else if (UNIFCart.battery) + else if (UNIFCart.battery && UNIFCart.SaveGame[0] && UNIFCart.SaveGameLen[0]) return UNIFCart.SaveGame[0]; else data = NULL; @@ -2076,9 +2113,9 @@ size_t retro_get_memory_size(unsigned type) switch(type) { case RETRO_MEMORY_SAVE_RAM: - if (iNESCart.battery) + if (iNESCart.battery && iNESCart.SaveGame[0] && iNESCart.SaveGameLen[0]) size = iNESCart.SaveGameLen[0]; - else if (UNIFCart.battery) + else if (UNIFCart.battery && UNIFCart.SaveGame[0] && UNIFCart.SaveGameLen[0]) size = UNIFCart.SaveGameLen[0]; else size = 0; diff --git a/src/fceu.h b/src/fceu.h index b15d374..f50c5c0 100644 --- a/src/fceu.h +++ b/src/fceu.h @@ -83,6 +83,10 @@ typedef struct { int PAL; int NetworkPlay; int SoundVolume; + int TriangleVolume; + int SquareVolume[2]; + int NoiseVolume; + int PCMVolume; int GameGenie; /* Current first and last rendered scanlines. */ diff --git a/src/file.c b/src/file.c index 02a074c..2ceb96f 100644 --- a/src/file.c +++ b/src/file.c @@ -58,8 +58,6 @@ static MEMWRAP *MakeMemWrap(void *tz, int type) fread(tmp->data, 1, tmp->size, (FILE*)tz); doret: - if (type == 0) - fclose((FILE*)tz); return tmp; } @@ -97,6 +95,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, fseek((FILE*)t, 0, SEEK_SET); fceufp->fp = MakeMemWrap(t, 0); + fclose((FILE*)t); } return fceufp; } diff --git a/src/filter.c b/src/filter.c index 0627058..33fa188 100644 --- a/src/filter.c +++ b/src/filter.c @@ -100,7 +100,7 @@ int32 NeoFilterSound(int32 *in, int32 *out, uint32 inlen, int32 *leftover) { #endif max = (inlen - 1) << 16; - if (FSettings.soundq == 2) + if (FSettings.soundq == 2) { for (x = mrindex; x < max; x += mrratio) { int32 acc = 0, acc2 = 0; uint32 c; @@ -116,7 +116,7 @@ int32 NeoFilterSound(int32 *in, int32 *out, uint32 inlen, int32 *leftover) { out++; count++; } - else + } else { for (x = mrindex; x < max; x += mrratio) { int32 acc = 0, acc2 = 0; uint32 c; @@ -132,6 +132,7 @@ int32 NeoFilterSound(int32 *in, int32 *out, uint32 inlen, int32 *leftover) { out++; count++; } + } mrindex = x - max; diff --git a/src/sound.c b/src/sound.c index df4b878..69b333a 100644 --- a/src/sound.c +++ b/src/sound.c @@ -520,7 +520,8 @@ void RDoPCM(void) { uint32 V; for (V = ChannelBC[4]; V < SOUNDTS; V++) - WaveHi[V] += RawDALatch << 16; + /* TODO: get rid of floating calculations to binary. set log volume scaling. */ + WaveHi[V] += (((RawDALatch << 16) / 256) * FSettings.PCMVolume ) & (~0xFFFF); ChannelBC[4] = SOUNDTS; } @@ -546,7 +547,16 @@ static INLINE void RDoSQ(int x) { amp = EnvUnits[x].Speed; else amp = EnvUnits[x].decvolume; -/* printf("%d\n",amp); */ + /* printf("%d\n",amp); */ + + /* Modify Square wave volume based on channel volume modifiers + * Note: the formulat x = x * y /100 does not yield exact results, + * but is "close enough" and avoids the need for using double values + * or implicit cohersion which are slower (we need speed here) */ + /* TODO: Optimize this. */ + if (FSettings.SquareVolume[x] != 256) + amp = (amp * FSettings.SquareVolume[x]) / 256; + amp <<= 24; rthresh = RectDuties[(PSG[(x << 2)] & 0xC0) >> 6]; @@ -618,6 +628,15 @@ static void RDoSQLQ(void) { else amp[x] = EnvUnits[x].decvolume; + /* Modify Square wave volume based on channel volume modifiers + * Note: the formulat x = x * y /100 does not yield exact results, + * but is "close enough" and avoids the need for using double vales + * or implicit cohersion which are slower (we need speed here) + * fixed - setting up maximum volume for square2 caused complete mute square2 channel. + * TODO: Optimize this. */ + if (FSettings.SquareVolume[x] != 256) + amp[x] = (amp[x] * FSettings.SquareVolume[x]) / 256; + if (!inie[x]) amp[x] = 0; /* Correct? Buzzing in MM2, others otherwise... */ rthresh[x] = RectDuties[(PSG[x * 4] & 0xC0) >> 6]; @@ -637,7 +656,7 @@ static void RDoSQLQ(void) { if (!inie[0] && !inie[1]) { for (V = start; V < end; V++) Wave[V >> 4] += totalout; - } else + } else { for (V = start; V < end; V++) { /* int tmpamp=0; if(RectDutyCount[0]> 0xe) & 1]; } } - else + } else { for (V = ChannelBC[3]; V < SOUNDTS; V++) { WaveHi[V] += outo; wlcount[3]--; @@ -885,6 +923,7 @@ static void RDoNoise(void) { outo = amptab[(nreg >> 0xe) & 1]; } } + } ChannelBC[3] = SOUNDTS; } @@ -938,6 +977,7 @@ int FlushEmulateSound(void) { *tmpo = (b & 65535) + wlookup2[(b >> 16) & 255] + wlookup1[b >> 24]; tmpo++; } + end = NeoFilterSound(WaveHi, WaveFinal, SOUNDTS, &left); memmove(WaveHi, WaveHi + SOUNDTS - left, left * sizeof(uint32)); @@ -953,10 +993,9 @@ int FlushEmulateSound(void) { SexyFilter(Wave, WaveFinal, end >> 4); -#if 0 - if (FSettings.lowpass) - SexyFilter2(WaveFinal, end >> 4); -#endif + /* if (FSettings.lowpass) + SexyFilter2(WaveFinal, end >> 4); */ + if (end & 0xF) Wave[0] = Wave[(end >> 4)]; Wave[end >> 4] = 0; @@ -1023,6 +1062,8 @@ void FCEUSND_Reset(void) { DMCAddress = 0; DMCSize = 0; DMCShift = 0; + DMCacc=1; + DMCBitCount=0; } void FCEUSND_Power(void) { @@ -1162,7 +1203,7 @@ SFORMAT FCEUSND_STATEINFO[] = { { &DMCAddressLatch, 1, "5ADL" }, { &DMCFormat, 1, "5FMT" }, { &RawDALatch, 1, "RWDA" }, - + //these are important for smooth sound after loading state { &sqacc[0], sizeof(sqacc[0]) | FCEUSTATE_RLSB, "SAC1" }, { &sqacc[1], sizeof(sqacc[1]) | FCEUSTATE_RLSB, "SAC2" }, @@ -1171,7 +1212,7 @@ SFORMAT FCEUSND_STATEINFO[] = { { &tristep, sizeof(tristep) | FCEUSTATE_RLSB, "TRIS"}, { &lq_triacc, sizeof(lq_triacc) | FCEUSTATE_RLSB, "TACC" }, { &lq_noiseacc, sizeof(lq_noiseacc) | FCEUSTATE_RLSB, "NACC" }, - + //less important but still necessary { &ChannelBC[0], sizeof(ChannelBC[0]) | FCEUSTATE_RLSB, "CBC1" }, { &ChannelBC[1], sizeof(ChannelBC[1]) | FCEUSTATE_RLSB, "CBC2" }, @@ -1187,10 +1228,10 @@ SFORMAT FCEUSND_STATEINFO[] = { { &sexyfilter_acc1, sizeof(sexyfilter_acc1) | FCEUSTATE_RLSB, "FAC1" }, { &sexyfilter_acc2, sizeof(sexyfilter_acc2) | FCEUSTATE_RLSB, "FAC2" }, { &lq_tcout, sizeof(lq_tcout) | FCEUSTATE_RLSB, "TCOU"}, - + //wave buffer is used for filtering, only need first 17 values from it { &Wave, 32 * sizeof(int32), "WAVE"}, -{ 0 } + { 0 } }; void FCEUSND_SaveState(void) { @@ -1205,7 +1246,17 @@ void FCEUSND_LoadState(int version) { //minimal validation for (i = 0; i < 5; i++) { - if (ChannelBC[i] < 0 || ChannelBC[i] > 15) + int BC_max = 15; + + if (FSettings.soundq == 2) + { + BC_max = 1025; + } + else if (FSettings.soundq == 1) + { + BC_max = 485; + } + if (ChannelBC[i] < 0 || ChannelBC[i] > BC_max) { ChannelBC[i] = 0; } From b5803e0e1d56d534e5ace80598e188d30bc7d6cb Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Tue, 4 Dec 2018 10:25:17 +0800 Subject: [PATCH 09/34] c89 compliant? (#237) * Replace C++ comments into C comments * Move INLINE out of Makefile.common, move to fceu-types.h An INLINE define is still existing in Makefile.common for msvc (dont have a way to to test that). Moved the rest into fceu-types.h using the one already existing from emu2413.h. * Increase maximum volume for apu channels --- Makefile.common | 2 -- src/boards/69.c | 2 +- src/boards/emu2413.h | 14 -------------- src/boards/unrom512.c | 8 ++++---- src/drivers/libretro/libretro.c | 24 ++++++++++++------------ src/fceu-types.h | 13 +++++++++++++ src/sound.c | 8 ++++---- 7 files changed, 34 insertions(+), 37 deletions(-) diff --git a/Makefile.common b/Makefile.common index f493168..36127ad 100644 --- a/Makefile.common +++ b/Makefile.common @@ -17,8 +17,6 @@ endif ifneq (,$(findstring msvc,$(platform))) COREDEFINES += -DINLINE=_inline -else -COREDEFINES += -DINLINE=inline endif ifeq ($(PSS_STYLE),2) diff --git a/src/boards/69.c b/src/boards/69.c index e29d4f0..672f924 100644 --- a/src/boards/69.c +++ b/src/boards/69.c @@ -97,7 +97,7 @@ static DECLFW(M69Write1) { } } -// SUNSOFT-5/FME-7 Sound +/* SUNSOFT-5/FME-7 Sound */ static void AYSound(int Count); static void AYSoundHQ(void); diff --git a/src/boards/emu2413.h b/src/boards/emu2413.h index 06eccd8..a0c173c 100644 --- a/src/boards/emu2413.h +++ b/src/boards/emu2413.h @@ -7,20 +7,6 @@ #include #include "../fceu-types.h" -#ifndef INLINE - -#if defined(_MSC_VER) -#define INLINE __forceinline -#elif defined(__GNUC__) -#define INLINE __inline__ -#elif defined(_MWERKS_) -#define INLINE inline -#else -#define INLINE -#endif -#endif - - #ifdef __cplusplus extern "C" { #endif diff --git a/src/boards/unrom512.c b/src/boards/unrom512.c index 9bc4736..59ac51d 100644 --- a/src/boards/unrom512.c +++ b/src/boards/unrom512.c @@ -226,16 +226,16 @@ void UNROM512_Init(CartInfo *info) { mirror = (head.ROM_type & 1) | ((head.ROM_type & 8) >> 2); switch (mirror) { - case 0: // hard horizontal, internal + case 0: /* hard horizontal, internal */ SetupCartMirroring(MI_H, 1, NULL); break; - case 1: // hard vertical, internal + case 1: /* hard vertical, internal */ SetupCartMirroring(MI_V, 1, NULL); break; - case 2: // switchable 1-screen, internal (flags: 4-screen + horizontal) + case 2: /* switchable 1-screen, internal (flags: 4-screen + horizontal) */ SetupCartMirroring(MI_0, 0, NULL); break; - case 3: // hard four screen, last 8k of 32k RAM (flags: 4-screen + vertical) + case 3: /* hard four screen, last 8k of 32k RAM (flags: 4-screen + vertical) */ SetupCartMirroring(4, 1, VROM + (info->vram_size - 8192)); break; } diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index f62ed8e..bd44830 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -713,12 +713,6 @@ void retro_set_environment(retro_environment_t cb) { "fceumm_sndvolume", "Sound Volume; 150|160|170|180|190|200|210|220|230|240|250|0|10|20|30|40|50|60|70|80|90|100|110|120|130|140" }, { "fceumm_sndquality", "Sound Quality; Low|High|Very High" }, { "fceumm_swapduty", "Swap Duty Cycles; disabled|enabled" }, - { "fceumm_turbo_enable", "Turbo Enable; None|Player 1|Player 2|Both" }, - { "fceumm_turbo_delay", "Turbo Delay (in frames); 3|5|10|15|30|60|1|2" }, - { "fceumm_zapper_mode", "Zapper Mode; lightgun|mouse" }, - { "fceumm_show_crosshair", "Show Crosshair; enabled|disabled" }, - { "fceumm_overclocking", "Overclocking; disabled|2x-Postrender|2x-VBlank" }, - { "fceumm_ramstate", "RAM power up state (Restart); fill $ff|fill $00|random" }, #ifdef DEBUG { "fceumm_apu_1", "Enable Sound Channel 1 (Square 1); enabled|disabled" }, { "fceumm_apu_2", "Enable Sound Channel 2 (Square 2); enabled|disabled" }, @@ -726,6 +720,12 @@ void retro_set_environment(retro_environment_t cb) { "fceumm_apu_4", "Enable Sound Channel 4 (Noise) ; enabled|disabled" }, { "fceumm_apu_5", "Enable Sound Channel 5 (PCM); enabled|disabled" }, #endif + { "fceumm_turbo_enable", "Turbo Enable; None|Player 1|Player 2|Both" }, + { "fceumm_turbo_delay", "Turbo Delay (in frames); 3|5|10|15|30|60|1|2" }, + { "fceumm_zapper_mode", "Zapper Mode; lightgun|mouse" }, + { "fceumm_show_crosshair", "Show Crosshair; enabled|disabled" }, + { "fceumm_overclocking", "Overclocking; disabled|2x-Postrender|2x-VBlank" }, + { "fceumm_ramstate", "RAM power up state (Restart); fill $ff|fill $00|random" }, { NULL, NULL }, }; @@ -966,11 +966,11 @@ static const keymap bindmap[] = { static void set_apu_channels(int chan) { - FSettings.SquareVolume[1] = 255 * ((chan >> 0) & 1); - FSettings.SquareVolume[0] = 255 * ((chan >> 1) & 1); - FSettings.TriangleVolume = 255 * ((chan >> 2) & 1); - FSettings.NoiseVolume = 255 * ((chan >> 3) & 1); - FSettings.PCMVolume = 255 * ((chan >> 4) & 1); + FSettings.SquareVolume[1] = 256 * ((chan >> 0) & 1); + FSettings.SquareVolume[0] = 256 * ((chan >> 1) & 1); + FSettings.TriangleVolume = 256 * ((chan >> 2) & 1); + FSettings.NoiseVolume = 256 * ((chan >> 3) & 1); + FSettings.PCMVolume = 256 * ((chan >> 4) & 1); } static void check_variables(bool startup) @@ -1356,7 +1356,7 @@ static void FCEUD_UpdateInput(void) JSReturn = 0; - // nes gamepad + /* nes gamepad */ for (player = 0; player < MAX_PLAYERS; player++) { uint8_t input_buf = 0; diff --git a/src/fceu-types.h b/src/fceu-types.h index dda3a8e..53c5ec5 100644 --- a/src/fceu-types.h +++ b/src/fceu-types.h @@ -53,6 +53,19 @@ typedef unsigned long long uint64; typedef long long int64; #endif +#ifndef INLINE + +#if defined(_MSC_VER) +#define INLINE __forceinline +#elif defined(__GNUC__) +#define INLINE __inline__ +#elif defined(_MWERKS_) +#define INLINE inline +#else +#define INLINE +#endif +#endif + #if PSS_STYLE == 2 #define PSS "\\" diff --git a/src/sound.c b/src/sound.c index 69b333a..0891eb7 100644 --- a/src/sound.c +++ b/src/sound.c @@ -1204,7 +1204,7 @@ SFORMAT FCEUSND_STATEINFO[] = { { &DMCFormat, 1, "5FMT" }, { &RawDALatch, 1, "RWDA" }, - //these are important for smooth sound after loading state + /* these are important for smooth sound after loading state */ { &sqacc[0], sizeof(sqacc[0]) | FCEUSTATE_RLSB, "SAC1" }, { &sqacc[1], sizeof(sqacc[1]) | FCEUSTATE_RLSB, "SAC2" }, { &RectDutyCount[0], sizeof(RectDutyCount[0]) | FCEUSTATE_RLSB, "RCD1"}, @@ -1213,7 +1213,7 @@ SFORMAT FCEUSND_STATEINFO[] = { { &lq_triacc, sizeof(lq_triacc) | FCEUSTATE_RLSB, "TACC" }, { &lq_noiseacc, sizeof(lq_noiseacc) | FCEUSTATE_RLSB, "NACC" }, - //less important but still necessary + /* less important but still necessary */ { &ChannelBC[0], sizeof(ChannelBC[0]) | FCEUSTATE_RLSB, "CBC1" }, { &ChannelBC[1], sizeof(ChannelBC[1]) | FCEUSTATE_RLSB, "CBC2" }, { &ChannelBC[2], sizeof(ChannelBC[2]) | FCEUSTATE_RLSB, "CBC3" }, @@ -1229,7 +1229,7 @@ SFORMAT FCEUSND_STATEINFO[] = { { &sexyfilter_acc2, sizeof(sexyfilter_acc2) | FCEUSTATE_RLSB, "FAC2" }, { &lq_tcout, sizeof(lq_tcout) | FCEUSTATE_RLSB, "TCOU"}, - //wave buffer is used for filtering, only need first 17 values from it + /* wave buffer is used for filtering, only need first 17 values from it */ { &Wave, 32 * sizeof(int32), "WAVE"}, { 0 } }; @@ -1243,7 +1243,7 @@ void FCEUSND_LoadState(int version) { RawDALatch &= 0x7F; DMCAddress &= 0x7FFF; - //minimal validation + /* minimal validation */ for (i = 0; i < 5; i++) { int BC_max = 15; From b238ca5d6234dec31690533efcec09b6b8b8a4c9 Mon Sep 17 00:00:00 2001 From: Tatsuya79 Date: Tue, 4 Dec 2018 11:27:54 +0100 Subject: [PATCH 10/34] Update libretro.c --- src/drivers/libretro/libretro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index bd44830..50abb6d 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -717,7 +717,7 @@ void retro_set_environment(retro_environment_t cb) { "fceumm_apu_1", "Enable Sound Channel 1 (Square 1); enabled|disabled" }, { "fceumm_apu_2", "Enable Sound Channel 2 (Square 2); enabled|disabled" }, { "fceumm_apu_3", "Enable Sound Channel 3 (Triangle); enabled|disabled" }, - { "fceumm_apu_4", "Enable Sound Channel 4 (Noise) ; enabled|disabled" }, + { "fceumm_apu_4", "Enable Sound Channel 4 (Noise); enabled|disabled" }, { "fceumm_apu_5", "Enable Sound Channel 5 (PCM); enabled|disabled" }, #endif { "fceumm_turbo_enable", "Turbo Enable; None|Player 1|Player 2|Both" }, From 1993f3135205b54f6a9a08b902c9f7b7449c0b66 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Wed, 5 Dec 2018 15:09:13 +0800 Subject: [PATCH 11/34] Fix wrong info in some comments --- src/sound.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sound.c b/src/sound.c index 0891eb7..1c4d633 100644 --- a/src/sound.c +++ b/src/sound.c @@ -761,7 +761,7 @@ static void RDoTriangleNoisePCMLQ(void) { else amptab[0] = EnvUnits[2].decvolume; - /* Modify Square wave volume based on channel volume modifiers + /* Modify Triangle wave volume based on channel volume modifiers * Note: the formulat x = x * y /100 does not yield exact results, * but is "close enough" and avoids the need for using double vales * or implicit cohersion which are slower (we need speed here) @@ -872,7 +872,7 @@ static void RDoNoise(void) { else amptab[0] = EnvUnits[2].decvolume; - /* Modify Square wave volume based on channel volume modifiers + /* Modify Noise wave volume based on channel volume modifiers * Note: the formulat x = x * y /100 does not yield exact results, * but is "close enough" and avoids the need for using double vales * or implicit cohersion which are slower (we need speed here) From 095fd57117b7885dbd76a47d05c5da3864859856 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Wed, 5 Dec 2018 15:52:20 +0800 Subject: [PATCH 12/34] Fix audio states in VRC6 --- src/boards/vrc6.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/boards/vrc6.c b/src/boards/vrc6.c index e133e36..b40261c 100644 --- a/src/boards/vrc6.c +++ b/src/boards/vrc6.c @@ -49,10 +49,8 @@ static uint8 vpsg1[8]; static uint8 vpsg2[4]; static int32 cvbc[3]; static int32 vcount[3]; -static int32 dcount[2]; -static int32 saw1phaseacc; +static int32 dcount[3]; static int32 phaseacc; -static uint8 b3; /* clock counter, resets phaseacc on the 7th clock */ static SFORMAT SStateRegs[] = { @@ -64,12 +62,11 @@ static SFORMAT SStateRegs[] = { &cvbc[2], 4 | FCEUSTATE_RLSB, "BC03" }, { &dcount[0], 4 | FCEUSTATE_RLSB, "DCT0" }, { &dcount[1], 4 | FCEUSTATE_RLSB, "DCT1" }, + { &dcount[2], 4 | FCEUSTATE_RLSB, "DCT2" }, { &vcount[0], 4 | FCEUSTATE_RLSB, "VCT0" }, { &vcount[1], 4 | FCEUSTATE_RLSB, "VCT1" }, - { &vcount[2], 4 | FCEUSTATE_RLSB, "VCT1" }, - { &saw1phaseacc, 4| FCEUSTATE_RLSB, "SAW1" }, - { &phaseacc, 4 | FCEUSTATE_RLSB, "PACC" }, - { &b3, 1, "CLKC" }, + { &vcount[2], 4 | FCEUSTATE_RLSB, "VCT2" }, + { &phaseacc, 4 | FCEUSTATE_RLSB, "ACCU" }, { 0 } }; @@ -235,20 +232,20 @@ static void DoSawV(void) { freq3 = (vpsg2[1] + ((vpsg2[2] & 15) << 8) + 1); for (V = start; V < end; V++) { - saw1phaseacc -= nesincsize; - if (saw1phaseacc <= 0) { + vcount[2] -= nesincsize; + if (vcount[2] <= 0) { int32 t; rea: t = freq3; t <<= 18; - saw1phaseacc += t; + vcount[2] += t; phaseacc += vpsg2[0] & 0x3f; - b3++; - if (b3 == 7) { - b3 = 0; + dcount[2]++; + if (dcount[2] == 7) { + dcount[2] = 0; phaseacc = 0; } - if (saw1phaseacc <= 0) + if (vcount[2] <= 0) goto rea; duff = (((phaseacc >> 3) & 0x1f) << 4) * 6 / 8; } @@ -304,9 +301,9 @@ static void DoSawVHQ(void) { if (vcount[2] <= 0) { vcount[2] = (vpsg2[1] + ((vpsg2[2] & 15) << 8) + 1) << 1; phaseacc += vpsg2[0] & 0x3f; - b3++; - if (b3 == 7) { - b3 = 0; + dcount[2]++; + if (dcount[2] == 7) { + dcount[2] = 0; phaseacc = 0; } } @@ -315,7 +312,6 @@ static void DoSawVHQ(void) { cvbc[2] = SOUNDTS; } - void VRC6Sound(int Count) { int x; @@ -343,6 +339,7 @@ static void VRC6_ESI(void) { GameExpSound.HiFill = VRC6SoundHQ; GameExpSound.HiSync = VRC6SyncHQ; + phaseacc = 0; memset(cvbc, 0, sizeof(cvbc)); memset(vcount, 0, sizeof(vcount)); memset(dcount, 0, sizeof(dcount)); @@ -368,8 +365,8 @@ void Mapper24_Init(CartInfo *info) { MapIRQHook = VRC6IRQHook; VRC6_ESI(); GameStateRestore = StateRestore; - AddExState(&SStateRegs, ~0, 0, 0); AddExState(&StateRegs, ~0, 0, 0); + AddExState(&SStateRegs, ~0, 0, 0); } void Mapper26_Init(CartInfo *info) { @@ -388,8 +385,8 @@ void Mapper26_Init(CartInfo *info) { info->SaveGame[0] = WRAM; info->SaveGameLen[0] = WRAMSIZE; } - AddExState(&SStateRegs, ~0, 0, 0); AddExState(&StateRegs, ~0, 0, 0); + AddExState(&SStateRegs, ~0, 0, 0); } void NSFVRC6_Init(void) { From 34985a9d6e3296c620dfa51bc95d1022952c1c82 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Wed, 5 Dec 2018 16:05:55 +0800 Subject: [PATCH 13/34] Set max_width and max_height to its actual NES values Fix crash while using video filters and video dimensions is changed for example when using the overscan options. --- src/drivers/libretro/libretro.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 50abb6d..33d57b1 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -41,6 +41,8 @@ #define RETRO_DEVICE_FC_4PLAYERS RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 2) #define RETRO_DEVICE_FC_AUTO RETRO_DEVICE_JOYPAD +#define NES_WIDTH 256 +#define NES_HEIGHT 240 #define NES_8_7_PAR ((width * (8.0 / 7.0)) / height) #define NES_4_3 ((width / (height * (256.0 / 240.0))) * 4.0 / 3.0) @@ -795,16 +797,16 @@ void retro_get_system_info(struct retro_system_info *info) void retro_get_system_av_info(struct retro_system_av_info *info) { #ifdef PSP - unsigned width = use_overscan ? 256 : (256 - 16); - unsigned height = use_overscan ? 240 : (240 - 16); + unsigned width = NES_WIDTH - (use_overscan ? 16 : 0); + unsigned height = NES_HEIGHT - (use_overscan ? 16 : 0); #else - unsigned width = 256 - (overscan_h ? 16 : 0); - unsigned height = 240 - (overscan_v ? 16 : 0); + unsigned width = NES_WIDTH - (overscan_h ? 16 : 0); + unsigned height = NES_HEIGHT - (overscan_v ? 16 : 0); #endif info->geometry.base_width = width; info->geometry.base_height = height; - info->geometry.max_width = width; - info->geometry.max_height = height; + info->geometry.max_width = NES_WIDTH; + info->geometry.max_height = NES_HEIGHT; info->geometry.aspect_ratio = (float)(use_par ? NES_8_7_PAR : NES_4_3); info->timing.sample_rate = (float)sndsamplerate; if (FSettings.PAL || dendy) From 5bc56f786bec2cde3938425c69128f5da67dc68d Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Thu, 6 Dec 2018 00:45:24 +0800 Subject: [PATCH 14/34] Fix RC Pro Am II intro music and pulse phase reset behavior (#241) References: - RC Pro Am II, intro music square channels are wrong. - apu_phase_reset.nes - http://forums.nesdev.com/viewtopic.php?f=2&t=15346 --- src/sound.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/sound.c b/src/sound.c index 1c4d633..69750e1 100644 --- a/src/sound.c +++ b/src/sound.c @@ -386,7 +386,8 @@ static void FASTAPASS(1) FrameSoundStuff(int V) { mod = curfreq[P] >> (PSG[(P << 2) + 0x1] & 7); if ((mod + curfreq[P]) & 0x800) { sweepon[P] = 0; - curfreq[P] = 0; + /* https://github.com/TASVideos/fceux/issues/11 */ + /* curfreq[P] = 0; */ } else { if (curfreq[P] && (PSG[(P << 2) + 0x1] & 7) /* && sweepon[P]&0x80*/) { curfreq[P] += mod; @@ -536,12 +537,13 @@ static INLINE void RDoSQ(int x) { int32 cf; int32 rc; - if (curfreq[x] < 8 || curfreq[x] > 0x7ff) + /* This has been updated in a section further down: */ + /* if (curfreq[x] < 8 || curfreq[x] > 0x7ff) goto endit; if (!CheckFreq(curfreq[x], PSG[(x << 2) | 0x1])) goto endit; if (!lengthcount[x]) - goto endit; + goto endit; */ if (EnvUnits[x].Mode & 0x1) amp = EnvUnits[x].Speed; @@ -568,6 +570,20 @@ static INLINE void RDoSQ(int x) { cf = (curfreq[x] + 1) * 2; rc = wlcount[x]; + /* Testrom: apu_phase_reset.nes + * http://forums.nesdev.com/viewtopic.php?f=2&t=15346 */ + if (curfreq[x] < 8 || !CheckFreq(curfreq[x], PSG[(x << 2) | 0x1]) + || !lengthcount[x]) { + rc -= V; + if (rc <= 0) { + rc = cf - (-rc % cf); + } + V = 0; + } + + if (rthresh == 6) /* Reversed below */ + currdc = (currdc - 2) & 0x7; + while (V > 0) { if (currdc < rthresh) *D += amp; @@ -580,6 +596,9 @@ static INLINE void RDoSQ(int x) { D++; } + if (rthresh == 6) /* Reverse above */ + currdc = (currdc + 2) & 0x7; + RectDutyCount[x] = currdc; wlcount[x] = rc; From 64bccb470a58b35546a7a56b4ad8edcd7944e63f Mon Sep 17 00:00:00 2001 From: hizzlekizzle Date: Wed, 5 Dec 2018 13:25:25 -0600 Subject: [PATCH 15/34] Revert "Fix RC Pro Am II intro music and pulse phase reset behavior (#241)" (#242) This reverts commit 5bc56f786bec2cde3938425c69128f5da67dc68d. --- src/sound.c | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/src/sound.c b/src/sound.c index 69750e1..1c4d633 100644 --- a/src/sound.c +++ b/src/sound.c @@ -386,8 +386,7 @@ static void FASTAPASS(1) FrameSoundStuff(int V) { mod = curfreq[P] >> (PSG[(P << 2) + 0x1] & 7); if ((mod + curfreq[P]) & 0x800) { sweepon[P] = 0; - /* https://github.com/TASVideos/fceux/issues/11 */ - /* curfreq[P] = 0; */ + curfreq[P] = 0; } else { if (curfreq[P] && (PSG[(P << 2) + 0x1] & 7) /* && sweepon[P]&0x80*/) { curfreq[P] += mod; @@ -537,13 +536,12 @@ static INLINE void RDoSQ(int x) { int32 cf; int32 rc; - /* This has been updated in a section further down: */ - /* if (curfreq[x] < 8 || curfreq[x] > 0x7ff) + if (curfreq[x] < 8 || curfreq[x] > 0x7ff) goto endit; if (!CheckFreq(curfreq[x], PSG[(x << 2) | 0x1])) goto endit; if (!lengthcount[x]) - goto endit; */ + goto endit; if (EnvUnits[x].Mode & 0x1) amp = EnvUnits[x].Speed; @@ -570,20 +568,6 @@ static INLINE void RDoSQ(int x) { cf = (curfreq[x] + 1) * 2; rc = wlcount[x]; - /* Testrom: apu_phase_reset.nes - * http://forums.nesdev.com/viewtopic.php?f=2&t=15346 */ - if (curfreq[x] < 8 || !CheckFreq(curfreq[x], PSG[(x << 2) | 0x1]) - || !lengthcount[x]) { - rc -= V; - if (rc <= 0) { - rc = cf - (-rc % cf); - } - V = 0; - } - - if (rthresh == 6) /* Reversed below */ - currdc = (currdc - 2) & 0x7; - while (V > 0) { if (currdc < rthresh) *D += amp; @@ -596,9 +580,6 @@ static INLINE void RDoSQ(int x) { D++; } - if (rthresh == 6) /* Reverse above */ - currdc = (currdc + 2) & 0x7; - RectDutyCount[x] = currdc; wlcount[x] = rc; From 68c5289726379b9b88112f74d81b502595918bba Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sat, 8 Dec 2018 08:42:33 +0800 Subject: [PATCH 16/34] Update apu sweep unit - http://wiki.nesdev.com/w/index.php/APU_Sweep - APU sweep test roms: https://forums.nesdev.com/viewtopic.php?t=219&p=1403 - Fixes R.C. Pro AM II intro music --- src/sound.c | 56 +++++++++++++++++++++++------------------------------ 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/src/sound.c b/src/sound.c index 1c4d633..af3f5ee 100644 --- a/src/sound.c +++ b/src/sound.c @@ -70,6 +70,7 @@ static int32 RectDutyCount[2]; static uint8 sweepon[2]; static int32 curfreq[2]; static uint8 SweepCount[2]; +static uint8 sweepReload[2]; static uint16 nreg = 0; @@ -183,13 +184,9 @@ static void SQReload(int x, uint8 V) { lengthcount[x] = lengthtable[(V >> 3) & 0x1f]; } - sweepon[x] = PSG[(x << 2) | 1] & 0x80; - curfreq[x] = PSG[(x << 2) | 0x2] | ((V & 7) << 8); - SweepCount[x] = ((PSG[(x << 2) | 0x1] >> 4) & 7) + 1; - + curfreq[x] = curfreq[x] & 0xff | ((V & 7) << 8); RectDutyCount[x] = 7; EnvUnits[x].reloaddec = 1; - /* reloadfreq[x]=1; */ } static DECLFW(Write_PSG) { @@ -204,7 +201,9 @@ static DECLFW(Write_PSG) { V = (V & 0x3F) | ((V & 0x80) >> 1) | ((V & 0x40) << 1); break; case 0x1: - sweepon[0] = V & 0x80; + DoSQ1(); + sweepReload[0] = 1; + sweepon[0] = (V & 0x80); break; case 0x2: DoSQ1(); @@ -222,7 +221,9 @@ static DECLFW(Write_PSG) { V = (V & 0x3F) | ((V & 0x80) >> 1) | ((V & 0x40) << 1); break; case 0x5: - sweepon[1] = V & 0x80; + DoSQ2(); + sweepReload[1] = 1; + sweepon[1] = (V & 0x80); break; case 0x6: DoSQ2(); @@ -371,34 +372,25 @@ static void FASTAPASS(1) FrameSoundStuff(int V) { /* Frequency Sweep Code Here */ /* xxxx 0000 */ /* xxxx = hz. 120/(x+1)*/ - if (sweepon[P]) { - int32 mod = 0; - - if (SweepCount[P] > 0) SweepCount[P]--; - if (SweepCount[P] <= 0) { - SweepCount[P] = ((PSG[(P << 2) + 0x1] >> 4) & 7) + 1; /* +1; */ + /* http://wiki.nesdev.com/w/index.php/APU_Sweep */ + if (SweepCount[P] > 0) SweepCount[P]--; + if (SweepCount[P] <= 0) { + uint32 sweepShift = (PSG[(P << 2) + 0x1] & 7); + if (sweepon[P] && sweepShift && curfreq[P] >= 8) { + int32 mod = (curfreq[P] >> sweepShift); if (PSG[(P << 2) + 0x1] & 0x8) { - mod -= (P ^ 1) + ((curfreq[P]) >> (PSG[(P << 2) + 0x1] & 7)); - if (curfreq[P] && (PSG[(P << 2) + 0x1] & 7) /* && sweepon[P]&0x80*/) { - curfreq[P] += mod; - } - } else { - mod = curfreq[P] >> (PSG[(P << 2) + 0x1] & 7); - if ((mod + curfreq[P]) & 0x800) { - sweepon[P] = 0; - curfreq[P] = 0; - } else { - if (curfreq[P] && (PSG[(P << 2) + 0x1] & 7) /* && sweepon[P]&0x80*/) { - curfreq[P] += mod; - } - } + curfreq[P] -= (mod + (P ^ 1)); + } else if ((mod + curfreq[P]) < 0x800) { + curfreq[P] += mod; } } - } else {/* Sweeping is disabled: */ -#if 0 - curfreq[P]&=0xFF00; - curfreq[P]|=PSG[(P<<2)|0x2]; /* |((PSG[(P<<2)|3]&7)<<8); */ -#endif + + SweepCount[P] = (((PSG[(P << 2) + 0x1] >> 4) & 7) + 1); + } + + if (sweepReload[P]) { + SweepCount[P] = (((PSG[(P << 2) + 0x1] >> 4) & 7) + 1); + sweepReload[P] = 0; } } } From 3b2511a8fea8e7502e30c1b8e33b8a981b54344b Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sat, 8 Dec 2018 11:35:04 +0800 Subject: [PATCH 17/34] Fix APU IRQ inhibit flag $4017 and dmc --- src/sound.c | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/sound.c b/src/sound.c index af3f5ee..e4280a1 100644 --- a/src/sound.c +++ b/src/sound.c @@ -289,17 +289,17 @@ static DECLFW(Write_DMCRegs) { break; case 0x01: DoPCM(); RawDALatch = V & 0x7F; - if (RawDALatch) - DMC_7bit = 1; + if (RawDALatch) + DMC_7bit = 1; break; case 0x02: - DMCAddressLatch = V; - if (V) + DMCAddressLatch = V; + if (V) DMC_7bit = 0; - break; + break; case 0x03: - DMCSizeLatch = V; - if (V) + DMCSizeLatch = V; + if (V) DMC_7bit = 0; break; } @@ -314,6 +314,7 @@ static DECLFW(StatusWrite) { DoTriangle(); DoNoise(); DoPCM(); + for (x = 0; x < 4; x++) if (!(V & (1 << x))) lengthcount[x] = 0; /* Force length counters to 0. */ @@ -337,9 +338,9 @@ static DECLFR(StatusRead) { for (x = 0; x < 4; x++) ret |= lengthcount[x] ? (1 << x) : 0; if (DMCSize) ret |= 0x10; - #ifdef FCEUDEF_DEBUGGER + #ifdef FCEUDEF_DEBUGGER if (!fceuindbg) - #endif + #endif { SIRQStat &= ~0x40; X6502_IRQEnd(FCEU_IQFCOUNT); @@ -429,19 +430,21 @@ void FrameSoundUpdate(void) { * Length counter: Bit 4-7 of $4003, $4007, $400b, $400f */ - if (!fcnt && !(IRQFrameMode & 0x3)) { - SIRQStat |= 0x40; - X6502_IRQBegin(FCEU_IQFCOUNT); - } - if (fcnt == 3) { if (IRQFrameMode & 0x2) fhcnt += fhinc; } + FrameSoundStuff(fcnt); fcnt = (fcnt + 1) & 3; -} + /* has to be moved here to fix Dragon Warrior 4 + * after irq inhibit fix for $4017 */ + if (!fcnt && !(IRQFrameMode & 0x3)) { + SIRQStat |= 0x40; + X6502_IRQBegin(FCEU_IQFCOUNT); + } +} static INLINE void tester(void) { if (DMCBitCount == 0) { @@ -468,9 +471,10 @@ static INLINE void DMCDMA(void) { if (DMCFormat & 0x40) PrepDPCM(); else { - SIRQStat |= 0x80; - if (DMCFormat & 0x80) + if (DMCFormat & 0x80) { + SIRQStat |= 0x80; X6502_IRQBegin(FCEU_IQDPCM); + } } } } @@ -853,7 +857,6 @@ static void RDoTriangleNoisePCMLQ(void) { } } - static void RDoNoise(void) { uint32 V; int32 outo; @@ -924,10 +927,12 @@ DECLFW(Write_IRQFM) { fcnt = 0; if (V & 2) FrameSoundUpdate(); - fcnt = 1; + /* fcnt = 1; */ fhcnt = fhinc; - X6502_IRQEnd(FCEU_IQFCOUNT); - SIRQStat &= ~0x40; + if (V & 1) { + X6502_IRQEnd(FCEU_IQFCOUNT); + SIRQStat &= ~0x40; + } IRQFrameMode = V; } From fd5c95e60c64785e869fe7556f3434adfd0b0988 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sat, 8 Dec 2018 19:56:31 +0800 Subject: [PATCH 18/34] Fix pulse channel fails to clock lenght counter when silenced - Backported implementation from Mednafen-NES - Reference test roms: https://forums.nesdev.com/viewtopic.php?t=15346 https://github.com/christopherpow/nes-test-roms/tree/master/apu_mixer --- src/sound.c | 102 ++++++++++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 52 deletions(-) diff --git a/src/sound.c b/src/sound.c index e4280a1..4eed69f 100644 --- a/src/sound.c +++ b/src/sound.c @@ -85,6 +85,9 @@ int32 nesincsize = 0; uint32 soundtsinc = 0; uint32 soundtsi = 0; static int32 sqacc[2]; +static uint32 lq_tcout; +static int32 lq_triacc; +static int32 lq_noiseacc; /* LQ variables segment ends. */ static int32 lengthcount[4]; @@ -126,9 +129,9 @@ static const uint32 PALDMCTable[0x10] = * $4013 - Size register: Size in bytes = (V+1)*64 */ -/*static*/ int32 DMCacc = 1; +static int32 DMCacc = 1; static int32 DMCPeriod = 0; -/*static*/ uint8 DMCBitCount = 0; +static uint8 DMCBitCount = 0; static uint8 DMCAddressLatch = 0, DMCSizeLatch = 0; /* writes to 4012 and 4013 */ static uint8 DMCFormat = 0; /* Write to $4010 */ @@ -176,13 +179,8 @@ static int FASTAPASS(2) CheckFreq(uint32 cf, uint8 sr) { } static void SQReload(int x, uint8 V) { - if (EnabledChannels & (1 << x)) { - if (x) - DoSQ2(); - else - DoSQ1(); + if (EnabledChannels & (1 << x)) lengthcount[x] = lengthtable[(V >> 3) & 0x1f]; - } curfreq[x] = curfreq[x] & 0xff | ((V & 7) << 8); RectDutyCount[x] = 7; @@ -211,6 +209,7 @@ static DECLFW(Write_PSG) { curfreq[0] |= V; break; case 0x3: + DoSQ1(); SQReload(0, V); break; case 0x4: @@ -231,6 +230,7 @@ static DECLFW(Write_PSG) { curfreq[1] |= V; break; case 0x7: + DoSQ2(); SQReload(1, V); break; case 0xa: @@ -532,54 +532,56 @@ static INLINE void RDoSQ(int x) { int32 cf; int32 rc; - if (curfreq[x] < 8 || curfreq[x] > 0x7ff) - goto endit; - if (!CheckFreq(curfreq[x], PSG[(x << 2) | 0x1])) - goto endit; - if (!lengthcount[x]) - goto endit; - - if (EnvUnits[x].Mode & 0x1) - amp = EnvUnits[x].Speed; - else - amp = EnvUnits[x].decvolume; - /* printf("%d\n",amp); */ - - /* Modify Square wave volume based on channel volume modifiers - * Note: the formulat x = x * y /100 does not yield exact results, - * but is "close enough" and avoids the need for using double values - * or implicit cohersion which are slower (we need speed here) */ - /* TODO: Optimize this. */ - if (FSettings.SquareVolume[x] != 256) - amp = (amp * FSettings.SquareVolume[x]) / 256; - - amp <<= 24; - - rthresh = RectDuties[(PSG[(x << 2)] & 0xC0) >> 6]; - - D = &WaveHi[ChannelBC[x]]; V = SOUNDTS - ChannelBC[x]; - - currdc = RectDutyCount[x]; cf = (curfreq[x] + 1) * 2; rc = wlcount[x]; - while (V > 0) { - if (currdc < rthresh) - *D += amp; - rc--; - if (!rc) { - rc = cf; - currdc = (currdc + 1) & 7; + /* added 2018/12/08 */ + /* when pulse channel is silenced, resets length counters but not + * duty cycle, instead of resetting both */ + if ((curfreq[x] < 8 || curfreq[x] > 0x7ff) || + !CheckFreq(curfreq[x], PSG[(x << 2) | 0x1]) || + !lengthcount[x]) { + rc -= V; + if (rc <= 0) { + rc = cf - (-rc % cf); } - V--; - D++; + } else { + if (EnvUnits[x].Mode & 0x1) + amp = EnvUnits[x].Speed; + else + amp = EnvUnits[x].decvolume; + /* printf("%d\n",amp); */ + + /* Modify Square wave volume based on channel volume modifiers + * Note: the formulat x = x * y /100 does not yield exact results, + * but is "close enough" and avoids the need for using double values + * or implicit cohersion which are slower (we need speed here) */ + /* TODO: Optimize this. */ + if (FSettings.SquareVolume[x] != 256) + amp = (amp * FSettings.SquareVolume[x]) / 256; + + amp <<= 24; + rthresh = RectDuties[(PSG[(x << 2)] & 0xC0) >> 6]; + currdc = RectDutyCount[x]; + D = &WaveHi[ChannelBC[x]]; + + while (V > 0) { + if (currdc < rthresh) + *D += amp; + rc--; + if (!rc) { + rc = cf; + currdc = (currdc + 1) & 7; + } + V--; + D++; + } + + RectDutyCount[x] = currdc; } - RectDutyCount[x] = currdc; wlcount[x] = rc; - - endit: ChannelBC[x] = SOUNDTS; } @@ -724,10 +726,6 @@ static void RDoTriangle(void) { ChannelBC[2] = SOUNDTS; } -uint32 lq_tcout = 0; -int32 lq_triacc = 0; -int32 lq_noiseacc = 0; - static void RDoTriangleNoisePCMLQ(void) { int32 V; int32 start, end; From 049007f33b0787843f217b66a873a77dff319497 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 9 Dec 2018 20:23:53 +0800 Subject: [PATCH 19/34] Use -fsigned-char on some builds --- Makefile.libretro | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index aff8c61..9fb893b 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -1,9 +1,10 @@ -DEBUG=0 +DEBUG=1 PSS_STYLE=1 EXTERNAL_ZLIB=0 -HAVE_GRIFFIN=1 +HAVE_GRIFFIN=0 STATIC_LINKING=0 ENDIANNESS_DEFINES= +SIGNED_CHAR=0 SPACE := SPACE := $(SPACE) $(SPACE) @@ -255,6 +256,7 @@ else ifeq ($(platform), wii) ENDIANNESS_DEFINES += -DMSB_FIRST STATIC_LINKING=1 EXTERNAL_ZLIB=1 + SIGNED_CHAR=1 # Nintendo WiiU else ifeq ($(platform), wiiu) @@ -266,6 +268,7 @@ else ifeq ($(platform), wiiu) ENDIANNESS_DEFINES += -DMSB_FIRST STATIC_LINKING=1 EXTERNAL_ZLIB=1 + SIGNED_CHAR=1 # Nintendo Switch (libtransistor) else ifeq ($(platform), switch) @@ -626,6 +629,10 @@ ifeq ($(EXTERNAL_ZLIB), 1) CFLAGS += -DHAVE_EXTERNAL_ZLIB endif +ifeq ($(SIGNED_CHAR), 1) + CFLAGS += -fsigned-char +endif + CORE_DIR := src include Makefile.common From c352ddd9da024cac05a4247bf1d97df88a13acc0 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 9 Dec 2018 20:29:49 +0800 Subject: [PATCH 20/34] Update Makefile.libretro accidentally left debugging options enabled... --- Makefile.libretro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 9fb893b..3a27cb9 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -1,7 +1,7 @@ -DEBUG=1 +DEBUG=0 PSS_STYLE=1 EXTERNAL_ZLIB=0 -HAVE_GRIFFIN=0 +HAVE_GRIFFIN=1 STATIC_LINKING=0 ENDIANNESS_DEFINES= SIGNED_CHAR=0 From e3cf3efc69d19b002157a5883d372e599a4c60ca Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Wed, 12 Dec 2018 06:16:02 +0800 Subject: [PATCH 21/34] fix vrc7 issue #235, update state.c (#245) * vrc7: Add sound save states * Try to fix some save state issues try to fix big-endian related save problems * vrc7: fix crash in some cases when loading states --- src/boards/vrc7.c | 23 +++++++++++++++++++++++ src/fceu-endian.c | 5 ++++- src/state.c | 9 +++++---- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/boards/vrc7.c b/src/boards/vrc7.c index 7166f8c..9a30f1f 100644 --- a/src/boards/vrc7.c +++ b/src/boards/vrc7.c @@ -174,6 +174,7 @@ static void VRC7IRQHook(int a) { static void StateRestore(int version) { Sync(); + OPLL_forceRefresh(VRC7Sound); } void Mapper85_Init(CartInfo *info) { @@ -191,6 +192,28 @@ void Mapper85_Init(CartInfo *info) { GameStateRestore = StateRestore; VRC7_ESI(); AddExState(&StateRegs, ~0, 0, 0); + + /* Sound states */ + AddExState(&VRC7Sound->adr, sizeof(VRC7Sound->adr), 0, "ADDR"); + AddExState(&VRC7Sound->out, sizeof(VRC7Sound->out), 0, "OUT0"); + AddExState(&VRC7Sound->realstep, sizeof(VRC7Sound->realstep), 0, "RTIM"); + AddExState(&VRC7Sound->oplltime, sizeof(VRC7Sound->oplltime), 0, "TIME"); + AddExState(&VRC7Sound->opllstep, sizeof(VRC7Sound->opllstep), 0, "STEP"); + AddExState(&VRC7Sound->prev, sizeof(VRC7Sound->prev), 0, "PREV"); + AddExState(&VRC7Sound->next, sizeof(VRC7Sound->next), 0, "NEXT"); + AddExState(&VRC7Sound->LowFreq, sizeof(VRC7Sound->LowFreq), 0, "LFQ0"); + AddExState(&VRC7Sound->HiFreq, sizeof(VRC7Sound->HiFreq), 0, "HFQ0"); + AddExState(&VRC7Sound->InstVol, sizeof(VRC7Sound->InstVol), 0, "VOLI"); + AddExState(&VRC7Sound->CustInst, sizeof(VRC7Sound->CustInst), 0, "CUSI"); + AddExState(&VRC7Sound->slot_on_flag, sizeof(VRC7Sound->slot_on_flag), 0, "FLAG"); + AddExState(&VRC7Sound->pm_phase, sizeof(VRC7Sound->pm_phase), 0, "PMPH"); + AddExState(&VRC7Sound->lfo_pm, sizeof(VRC7Sound->lfo_pm), 0, "PLFO"); + AddExState(&VRC7Sound->am_phase, sizeof(VRC7Sound->am_phase), 0, "AMPH"); + AddExState(&VRC7Sound->lfo_am, sizeof(VRC7Sound->lfo_am), 0, "ALFO"); + AddExState(&VRC7Sound->patch_number, sizeof(VRC7Sound->patch_number), 0, "PNUM"); + AddExState(&VRC7Sound->key_status, sizeof(VRC7Sound->key_status), 0, "KET"); + AddExState(&VRC7Sound->mask, sizeof(VRC7Sound->mask), 0, "MASK"); + AddExState((uint8 *)VRC7Sound->slot, sizeof(VRC7Sound->slot), 0, "SLOT"); } void NSFVRC7_Init(void) { diff --git a/src/fceu-endian.c b/src/fceu-endian.c index 754489f..cfe35d9 100644 --- a/src/fceu-endian.c +++ b/src/fceu-endian.c @@ -31,7 +31,10 @@ void FlipByteOrder(uint8 *src, uint32 count) uint8 *start = src; uint8 *end = src + count - 1; - while(start < end) + if ((count & 1) || !count) + return; /* This shouldn't happen. */ + + while (count--) { uint8 tmp; diff --git a/src/state.c b/src/state.c index 35f7d6a..baeab1c 100644 --- a/src/state.c +++ b/src/state.c @@ -108,7 +108,7 @@ static int SubWrite(memstream_t *mem, SFORMAT *sf) if(sf->s & RLSB) FlipByteOrder((uint8 *)sf->v, sf->s & (~RLSB)); #endif - memstream_write(mem, (uint8 *)sf->v, sf->s & (~RLSB)); + memstream_write(mem, (char *)sf->v, sf->s & (~RLSB)); /* Now restore the original byte order. */ #ifdef MSB_FIRST @@ -176,7 +176,7 @@ static int ReadStateChunk(memstream_t *mem, SFORMAT *sf, int size) if((tmp = CheckS(sf, tsize, toa))) { - memstream_read(mem, (uint8 *)tmp->v, tmp->s & (~RLSB)); + memstream_read(mem, (char *)tmp->v, tmp->s & (~RLSB)); #ifdef MSB_FIRST if(tmp->s & RLSB) @@ -213,8 +213,8 @@ static int ReadStateChunks(memstream_t *st, int32 totalsize) case 2: if (!ReadStateChunk(st, SFCPUC, size)) ret = 0; - else - X.mooPI = X.P; /* Quick and dirty hack. */ + /* else + X.mooPI = X.P; */ /* Quick and dirty hack. */ break; case 3: if (!ReadStateChunk(st, FCEUPPU_STATEINFO, size)) @@ -320,6 +320,7 @@ void ResetExState(void (*PreSave)(void), void (*PostSave)(void)) SPreSave = PreSave; SPostSave = PostSave; SFEXINDEX = 0; + SFMDATA[0].s = 0; } void AddExState(void *v, uint32 s, int type, char *desc) From b09a060ae6ec695a1dba0cbea3b91c63428ca9af Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sat, 15 Dec 2018 10:23:43 +0800 Subject: [PATCH 22/34] Wii related updates for save state fixes/workarounds (#246) * Wii: Fix uninitialized save state size causing load state problems - Issue origially from Wii and possibly affects similar devices where retroarch and the core are one program. The problem was that the serialize size was not reset when you change game, causing the last serialized size to be carried over to the next game loaded causing save state issues due to change in size. Initializing this variable during retro_init() seems enough for most of the games. - In this same observation, also initialized some variables in a similar way. - also exluded a variable used for sound state that was added for smooth sound after load state which causes similar loading issues as well. - default sample rate has been lowered to 32K as well as to minimize some stuttering for these devices, while maintaining 48K sample rate for others. - Some comments are added to modified section as necessary. * Add workaround for save state issue in Wii with expansion audio - Some mappers are not loading states as well. Seems to affect those that are using expansion audio. some of these mappers(bandai, mmc5, namco106), the state variables has to be expanded so that it will load states fine with big endian while others (vrc6, vrc7 sunsoft), some variables that were added for smoother audio during load state has been removed. - This does not guarantee though that other mappers might not have similar incompatibilities after loading a state but so far, some of the most common roms in each mapper has been tested to load fine. * FDS: Expand state variables for big endian compatibility * FDS: Change OSD label from Disk 0 to Disk 1... when switching disks - Minor osd label change that now shows Disk 1 of (# of disks) instead of just Disk 0 Side nth. --- src/boards/69.c | 5 ++++ src/boards/bandai.c | 23 +++++++++++++--- src/boards/mmc5.c | 48 +++++++++++++++++++++++++++------ src/boards/n106.c | 30 ++++++++++++++++++--- src/boards/vrc6.c | 4 +++ src/boards/vrc7.c | 6 +++++ src/drivers/libretro/libretro.c | 26 +++++++++++++----- src/fds.c | 16 ++++++++--- src/sound.c | 7 +++++ 9 files changed, 141 insertions(+), 24 deletions(-) diff --git a/src/boards/69.c b/src/boards/69.c index 672f924..2a7093b 100644 --- a/src/boards/69.c +++ b/src/boards/69.c @@ -113,6 +113,9 @@ static SFORMAT SStateRegs[] = { { &sndcmd, 1, "SCMD" }, { sreg, 14, "SREG" }, + +/* Ignoring these sound state files for Wii since it causes states unable to load */ +#ifndef GEKKO { &dcount[0], 4 | FCEUSTATE_RLSB, "DCT0" }, { &dcount[1], 4 | FCEUSTATE_RLSB, "DCT1" }, { &dcount[2], 4 | FCEUSTATE_RLSB, "DCT2" }, @@ -122,6 +125,8 @@ static SFORMAT SStateRegs[] = { &CAYBC[0], 4 | FCEUSTATE_RLSB, "BC00" }, { &CAYBC[1], 4 | FCEUSTATE_RLSB, "BC01" }, { &CAYBC[2], 4 | FCEUSTATE_RLSB, "BC02" }, +#endif + { 0 } }; diff --git a/src/boards/bandai.c b/src/boards/bandai.c index 9d3ca99..375d2b0 100644 --- a/src/boards/bandai.c +++ b/src/boards/bandai.c @@ -31,12 +31,29 @@ static int16 IRQCount, IRQLatch; static uint8 *WRAM = NULL; static uint32 WRAMSIZE; +/* TODO: Clean this up. State variables are expanded for + * big-endian compatibility when saving and loading states */ static SFORMAT StateRegs[] = { - { reg, 16, "REGS" }, + { ®[0], 1, "REG0" }, + { ®[1], 1, "REG1" }, + { ®[2], 1, "REG2" }, + { ®[3], 1, "REG3" }, + { ®[4], 1, "REG4" }, + { ®[5], 1, "REG5" }, + { ®[6], 1, "REG6" }, + { ®[7], 1, "REG7" }, + { ®[8], 1, "REG8" }, + { ®[9], 1, "REG9" }, + { ®[10], 1, "REGA" }, + { ®[11], 1, "REGB" }, + { ®[12], 1, "REGC" }, + { ®[13], 1, "REGD" }, + { ®[14], 1, "REGE" }, + { ®[15], 1, "REGF" }, { &IRQa, 1, "IRQA" }, - { &IRQCount, 2, "IRQC" }, - { &IRQLatch, 2, "IRQL" }, /* need for Famicom Jump II - Saikyou no 7 Nin (J) [!] */ + { &IRQCount, 2 | FCEUSTATE_RLSB, "IRQC" }, + { &IRQLatch, 2 | FCEUSTATE_RLSB, "IRQL" }, /* need for Famicom Jump II - Saikyou no 7 Nin (J) [!] */ { 0 } }; diff --git a/src/boards/mmc5.c b/src/boards/mmc5.c index 27952c6..0ef1681 100644 --- a/src/boards/mmc5.c +++ b/src/boards/mmc5.c @@ -751,12 +751,31 @@ static void GenMMC5Reset(void) { FCEU_CheatAddRAM(1, 0x5c00, ExRAM); } +/* TODO: Clean this up. State variables are expanded for + * big-endian compatibility when saving and loading states */ static SFORMAT MMC5_StateRegs[] = { - { PRGBanks, 4, "PRGB" }, - { CHRBanksA, 16, "CHRA" }, - { CHRBanksB, 8, "CHRB" }, + { &PRGBanks[0], 1, "PRG1" }, + { &PRGBanks[1], 1, "PRG2" }, + { &PRGBanks[2], 1, "PRG3" }, + { &PRGBanks[3], 1, "PRG4" }, + + { &CHRBanksA[0], 2 | FCEUSTATE_RLSB, "CRA1" }, + { &CHRBanksA[1], 2 | FCEUSTATE_RLSB, "CRA2" }, + { &CHRBanksA[2], 2 | FCEUSTATE_RLSB, "CRA3" }, + { &CHRBanksA[3], 2 | FCEUSTATE_RLSB, "CRA4" }, + { &CHRBanksA[4], 2 | FCEUSTATE_RLSB, "CRA5" }, + { &CHRBanksA[5], 2 | FCEUSTATE_RLSB, "CRA6" }, + { &CHRBanksA[6], 2 | FCEUSTATE_RLSB, "CRA7" }, + { &CHRBanksA[7], 2 | FCEUSTATE_RLSB, "CRA8" }, + + { &CHRBanksB[0], 2 | FCEUSTATE_RLSB, "CRB1" }, + { &CHRBanksB[1], 2 | FCEUSTATE_RLSB, "CRB2" }, + { &CHRBanksB[2], 2 | FCEUSTATE_RLSB, "CRB3" }, + { &CHRBanksB[3], 2 | FCEUSTATE_RLSB, "CRB4" }, + { &WRAMPage, 1, "WRMP" }, - { WRAMMaskEnable, 2, "WRME" }, + { &WRAMMaskEnable[0], 1, "WRM1" }, + { &WRAMMaskEnable[1], 1, "WRM2" }, { &mmc5ABMode, 1, "ABMD" }, { &IRQScanline, 1, "IRQS" }, { &IRQEnable, 1, "IRQE" }, @@ -770,13 +789,25 @@ static SFORMAT MMC5_StateRegs[] = { { &MMC5LineCounter, 1, "LCTR" }, { &mmc5psize, 1, "PSIZ" }, { &mmc5vsize, 1, "VSIZ" }, - { mul, 2, "MUL2" }, - { MMC5ROMWrProtect, 4, "WRPR" }, - { MMC5MemIn, 5, "MEMI" }, + + { &mul[0], 1, "MUL1" }, + { &mul[1], 1, "MUL2" }, + + { &MMC5ROMWrProtect[0], 1, "WRP1" }, + { &MMC5ROMWrProtect[1], 1, "WRP2" }, + { &MMC5ROMWrProtect[2], 1, "WRP3" }, + { &MMC5ROMWrProtect[3], 1, "WRP4" }, + + { &MMC5MemIn[0], 1, "MMI1" }, + { &MMC5MemIn[1], 1, "MMI2" }, + { &MMC5MemIn[2], 1, "MMI3" }, + { &MMC5MemIn[3], 1, "MMI4" }, + { &MMC5MemIn[4], 1, "MMI5" }, { &MMC5Sound.wl[0], 2 | FCEUSTATE_RLSB, "SDW0" }, { &MMC5Sound.wl[1], 2 | FCEUSTATE_RLSB, "SDW1" }, - { MMC5Sound.env, 2, "SDEV" }, + { &MMC5Sound.env[0], 1, "SEV1" }, + { &MMC5Sound.env[1], 1, "SEV2" }, { &MMC5Sound.enable, 1, "SDEN" }, { &MMC5Sound.running, 1, "SDRU" }, { &MMC5Sound.raw, 1, "SDRW" }, @@ -790,6 +821,7 @@ static SFORMAT MMC5_StateRegs[] = { { &MMC5Sound.BC[2], 4 | FCEUSTATE_RLSB, "BC02" }, { &MMC5Sound.vcount[0], 4 | FCEUSTATE_RLSB, "VCT0" }, { &MMC5Sound.vcount[1], 4 | FCEUSTATE_RLSB, "VCT1" }, + { 0 } }; diff --git a/src/boards/n106.c b/src/boards/n106.c index e5e8473..b1d6618 100644 --- a/src/boards/n106.c +++ b/src/boards/n106.c @@ -53,10 +53,34 @@ static int is210; /* Lesser mapper. */ static uint8 PRG[3]; static uint8 CHR[8]; +/* TODO: Clean this up. State variables are expanded for + * big-endian compatibility when saving and loading states */ static SFORMAT N106_StateRegs[] = { - { PRG, 3, "PRG" }, - { CHR, 8, "CHR" }, - { NTAPage, 4, "NTA" }, + { &PRG[0], 1, "PRG1" }, + { &PRG[1], 1, "PRG2" }, + { &PRG[2], 1, "PRG3" }, + + { &CHR[0], 1, "CHR1" }, + { &CHR[1], 1, "CHR2" }, + { &CHR[2], 1, "CHR3" }, + { &CHR[3], 1, "CHR4" }, + { &CHR[4], 1, "CHR5" }, + { &CHR[5], 1, "CHR6" }, + { &CHR[6], 1, "CHR7" }, + { &CHR[7], 1, "CHR8" }, + + { &NTAPage[0], 1, "NTA1" }, + { &NTAPage[1], 1, "NTA2" }, + { &NTAPage[2], 1, "NTA3" }, + { &NTAPage[3], 1, "NTA4" }, + + { &IRQCount, 2 | FCEUSTATE_RLSB, "IRQC" }, + { &IRQa, 1, "IRQA" }, + + { &dopol, 1, "GORF" }, + { &gorfus, 1, "DOPO" }, + { &gorko, 1, "GORK" }, + { 0 } }; diff --git a/src/boards/vrc6.c b/src/boards/vrc6.c index b40261c..0574cef 100644 --- a/src/boards/vrc6.c +++ b/src/boards/vrc6.c @@ -56,6 +56,9 @@ static SFORMAT SStateRegs[] = { { vpsg1, 8, "PSG1" }, { vpsg2, 4, "PSG2" }, + +/* Ignoring these sound state files for Wii since it causes states unable to load */ +#ifndef GEKKO /* rw - 2018-11-28 Added */ { &cvbc[0], 4 | FCEUSTATE_RLSB, "BC01" }, { &cvbc[1], 4 | FCEUSTATE_RLSB, "BC02" }, @@ -67,6 +70,7 @@ static SFORMAT SStateRegs[] = { &vcount[1], 4 | FCEUSTATE_RLSB, "VCT1" }, { &vcount[2], 4 | FCEUSTATE_RLSB, "VCT2" }, { &phaseacc, 4 | FCEUSTATE_RLSB, "ACCU" }, +#endif { 0 } }; diff --git a/src/boards/vrc7.c b/src/boards/vrc7.c index 9a30f1f..2d77fa2 100644 --- a/src/boards/vrc7.c +++ b/src/boards/vrc7.c @@ -174,7 +174,10 @@ static void VRC7IRQHook(int a) { static void StateRestore(int version) { Sync(); + +#ifndef GEKKO OPLL_forceRefresh(VRC7Sound); +#endif } void Mapper85_Init(CartInfo *info) { @@ -193,6 +196,8 @@ void Mapper85_Init(CartInfo *info) { VRC7_ESI(); AddExState(&StateRegs, ~0, 0, 0); +/* Ignoring these sound state files for Wii since it causes states unable to load */ +#ifndef GEKKO /* Sound states */ AddExState(&VRC7Sound->adr, sizeof(VRC7Sound->adr), 0, "ADDR"); AddExState(&VRC7Sound->out, sizeof(VRC7Sound->out), 0, "OUT0"); @@ -214,6 +219,7 @@ void Mapper85_Init(CartInfo *info) { AddExState(&VRC7Sound->key_status, sizeof(VRC7Sound->key_status), 0, "KET"); AddExState(&VRC7Sound->mask, sizeof(VRC7Sound->mask), 0, "MASK"); AddExState((uint8 *)VRC7Sound->slot, sizeof(VRC7Sound->slot), 0, "SLOT"); +#endif } void NSFVRC7_Init(void) { diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 33d57b1..4862585 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -98,10 +98,10 @@ static uint16_t retro_palette[256]; static uint16_t* fceu_video_out; /* Some timing-related variables. */ -unsigned sndsamplerate = 48000; -unsigned sndquality = 0; -unsigned sndvolume = 150; -unsigned swapDuty = 0; +static unsigned sndsamplerate; +static unsigned sndquality; +static unsigned sndvolume; +unsigned swapDuty; static int32_t *sound = 0; static uint32_t JSReturn = 0; @@ -110,6 +110,8 @@ static uint32_t MouseData[MAX_PORTS][3] = { {0} }; static uint32_t fc_MouseData[3] = {0}; static uint32_t current_palette = 0; +static unsigned serialize_size; + int PPUViewScanline=0; int PPUViewer=0; @@ -836,6 +838,20 @@ void retro_init(void) if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565)) log_cb.log(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n"); #endif + + /* initialize some of the default variables */ +#ifdef GEKKO + sndsamplerate = 32000; +#else + sndsamplerate = 48000; +#endif + sndquality = 0; + sndvolume = 150; + swapDuty = 0; + + /* Wii: initialize this or else last variable is passed through + * when loading another rom causing save state size change. */ + serialize_size = 0; } static void retro_set_custom_palette(void) @@ -1550,8 +1566,6 @@ void retro_run(void) retro_run_blit(gfx); } -static unsigned serialize_size = 0; - size_t retro_serialize_size(void) { if (serialize_size == 0) diff --git a/src/fds.c b/src/fds.c index 0cfc215..c783009 100644 --- a/src/fds.c +++ b/src/fds.c @@ -142,10 +142,12 @@ static void FDSInit(void) { void FCEU_FDSInsert(int oride) { if (InDisk == 255) { - FCEU_DispMessage("Disk %d Side %s Inserted", SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A"); + FCEU_DispMessage("Disk %d of %d Side %s Inserted", + 1 + (SelectDisk >> 1), (TotalSides + 1) >> 1, (SelectDisk & 1) ? "B" : "A"); InDisk = SelectDisk; } else { - FCEU_DispMessage("Disk %d Side %s Ejected", SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A"); + FCEU_DispMessage("Disk %d of %d Side %s Ejected", + 1 + (SelectDisk >> 1), (TotalSides + 1) >> 1, (SelectDisk & 1) ? "B" : "A"); InDisk = 255; } } @@ -160,7 +162,8 @@ void FCEU_FDSSelect(void) { return; } SelectDisk = ((SelectDisk + 1) % TotalSides) & 3; - FCEU_DispMessage("Disk %d Side %s Selected", SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A"); + FCEU_DispMessage("Disk %d of %d Side %s Selected", + 1 + (SelectDisk >> 1), (TotalSides + 1) >> 1, (SelectDisk & 1) ? "B" : "A"); } static void FP_FASTAPASS(1) FDSFix(int a) { @@ -702,7 +705,12 @@ int FDSLoad(const char *name, FCEUFILE *fp) { AddExState(diskdata[x], 65500, 0, temp); } - AddExState(FDSRegs, sizeof(FDSRegs), 0, "FREG"); + AddExState(&FDSRegs[0], 1, 0, "REG1"); + AddExState(&FDSRegs[1], 1, 0, "REG2"); + AddExState(&FDSRegs[2], 1, 0, "REG3"); + AddExState(&FDSRegs[3], 1, 0, "REG4"); + AddExState(&FDSRegs[4], 1, 0, "REG5"); + AddExState(&FDSRegs[5], 1, 0, "REG6"); AddExState(&IRQCount, 4, 1, "IRQC"); AddExState(&IRQLatch, 4, 1, "IQL1"); AddExState(&IRQa, 1, 0, "IRQA"); diff --git a/src/sound.c b/src/sound.c index 4eed69f..6454f13 100644 --- a/src/sound.c +++ b/src/sound.c @@ -1224,8 +1224,15 @@ SFORMAT FCEUSND_STATEINFO[] = { { &sexyfilter_acc2, sizeof(sexyfilter_acc2) | FCEUSTATE_RLSB, "FAC2" }, { &lq_tcout, sizeof(lq_tcout) | FCEUSTATE_RLSB, "TCOU"}, +/* 2018-12-14 - Wii and possibly other big-endian platforms are having + * issues loading states with this. Increasing it only helps a few games. + * Disabling this state variable for Wii/WiiU/GC for now. */ +/* TODO: fix this for better runahead feature for big-endian */ +#ifndef GEKKO /* wave buffer is used for filtering, only need first 17 values from it */ { &Wave, 32 * sizeof(int32), "WAVE"}, +#endif + { 0 } }; From a44a9b5be16e8648564f4c3e2fa97fd36da9fc3e Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 16 Dec 2018 08:50:08 +0800 Subject: [PATCH 23/34] FDS: Fix IRQ timing (#247) - Fixes Druid flickering status window --- src/fds.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/fds.c b/src/fds.c index c783009..baf52d0 100644 --- a/src/fds.c +++ b/src/fds.c @@ -166,18 +166,19 @@ void FCEU_FDSSelect(void) { 1 + (SelectDisk >> 1), (TotalSides + 1) >> 1, (SelectDisk & 1) ? "B" : "A"); } +/* 2018/12/15 - update irq timings */ static void FP_FASTAPASS(1) FDSFix(int a) { - if ((IRQa & 2) && IRQCount) { - IRQCount -= a; + if ((IRQa & 2) && (FDSRegs[3] & 0x1)) { if (IRQCount <= 0) { - if (!(IRQa & 1)) { - IRQa &= ~2; - IRQCount = IRQLatch = 0; - } else - IRQCount = IRQLatch; + if (!(IRQa & 1)) + IRQa &= ~2; /* does not clear latch, fix Druid */ + IRQCount = IRQLatch; X6502_IRQBegin(FCEU_IQEXT); + } else { + IRQCount -= a; } } + if (DiskSeekIRQ > 0) { DiskSeekIRQ -= a; if (DiskSeekIRQ <= 0) { @@ -495,20 +496,29 @@ void FDSSoundReset(void) { static DECLFW(FDSWrite) { switch (A) { case 0x4020: - X6502_IRQEnd(FCEU_IQEXT); IRQLatch &= 0xFF00; IRQLatch |= V; break; case 0x4021: - X6502_IRQEnd(FCEU_IQEXT); IRQLatch &= 0xFF; IRQLatch |= V << 8; break; case 0x4022: - X6502_IRQEnd(FCEU_IQEXT); - IRQCount = IRQLatch; - IRQa = V & 3; + if (FDSRegs[3] & 0x1) { + IRQa = (V & 0x3); + if (IRQa & 2) { + IRQCount = IRQLatch; + } else { + X6502_IRQEnd(FCEU_IQEXT); + X6502_IRQEnd(FCEU_IQEXT2); + } + } break; + case 0x4023: + if (!(V & 1)) { + X6502_IRQEnd(FCEU_IQEXT); + X6502_IRQEnd(FCEU_IQEXT2); + } case 0x4024: if ((InDisk != 255) && !(FDSRegs[5] & 0x4) && (FDSRegs[3] & 0x1)) { if (DiskPtr >= 0 && DiskPtr < 65500) { From b6c251b7b2be18d10f819ffec291995fc62c54e7 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 23 Dec 2018 22:46:17 +0800 Subject: [PATCH 24/34] Cleanup (#248) * Silence some clang warnings * Cleanup input and turbo functions * Update apu pulse' swap duty cycle --- src/drivers/libretro/libretro.c | 85 +++++++++++++++++++-------------- src/fceu-memory.c | 1 + src/sound.c | 19 +++++--- 3 files changed, 63 insertions(+), 42 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 4862585..67b80e4 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -628,6 +628,8 @@ static unsigned nes_to_libretro(int d) case SI_ARKANOID: return RETRO_DEVICE_ARKANOID; } + + return (RETRO_DEVICE_GAMEPAD); } static unsigned fc_to_libretro(int d) @@ -646,6 +648,8 @@ static unsigned fc_to_libretro(int d) case SIFC_4PLAYER: return RETRO_DEVICE_FC_4PLAYERS; } + + return (RETRO_DEVICE_NONE); } void retro_set_controller_port_device(unsigned port, unsigned device) @@ -978,6 +982,9 @@ static const keymap bindmap[] = { { RETRO_DEVICE_ID_JOYPAD_DOWN, JOY_DOWN }, { RETRO_DEVICE_ID_JOYPAD_LEFT, JOY_LEFT }, { RETRO_DEVICE_ID_JOYPAD_RIGHT, JOY_RIGHT }, +}; + +static const keymap turbomap[] = { { RETRO_DEVICE_ID_JOYPAD_X, JOY_A }, { RETRO_DEVICE_ID_JOYPAD_Y, JOY_B }, }; @@ -1168,13 +1175,19 @@ static void check_variables(bool startup) { unsigned i; - for (i = 0; i < MAX_PLAYERS; i++) - turbo_enabler[i] = 0; + turbo_enabler[0] = 0; + turbo_enabler[1] = 0; if (!strcmp(var.value, "Player 1")) + { turbo_enabler[0] = 1; + turbo_enabler[1] = 0; + } else if (!strcmp(var.value, "Player 2")) + { + turbo_enabler[0] = 0; turbo_enabler[1] = 1; + } else if (!strcmp(var.value, "Both")) { turbo_enabler[0] = 1; @@ -1363,12 +1376,13 @@ void get_mouse_input(unsigned port, uint32_t *zapdata) * each player */ +#define MAX_BUTTONS 8 #define TURBO_BUTTONS 2 unsigned char turbo_button_toggle[MAX_PLAYERS][TURBO_BUTTONS] = { {0} }; static void FCEUD_UpdateInput(void) { - unsigned player, port, i; + unsigned player, port; poll_cb(); @@ -1377,41 +1391,43 @@ static void FCEUD_UpdateInput(void) /* nes gamepad */ for (player = 0; player < MAX_PLAYERS; player++) { - uint8_t input_buf = 0; - bool player_enabled = (input_type[player] == RETRO_DEVICE_GAMEPAD); + int i = 0; + uint8_t input_buf = 0; + int player_enabled = (input_type[player] == RETRO_DEVICE_GAMEPAD); - for (i = 0; i < 8; i++) - input_buf |= (player_enabled && input_cb(player, RETRO_DEVICE_JOYPAD, 0, - bindmap[i].retro)) ? bindmap[i].nes : 0; - - /* Turbo A and Turbo B buttons are - * mapped to Joypad X and Joypad Y - * in RetroArch joypad. - * - * We achieve this by keeping track of - * the number of times it increments - * the toggle counter and fire or not fire - * depending on whether the delay value has - * been reached. - */ - - if (turbo_enabler[player] == 1 && player_enabled) + if (player_enabled) { - /* Handle Turbo A & B buttons */ - for (i = 8; i < 10; i++) + for (i = 0; i < MAX_BUTTONS; i++) + input_buf |= input_cb(player, RETRO_DEVICE_JOYPAD, 0, + bindmap[i].retro) ? bindmap[i].nes : 0; + + /* Turbo A and Turbo B buttons are + * mapped to Joypad X and Joypad Y + * in RetroArch joypad. + * + * We achieve this by keeping track of + * the number of times it increments + * the toggle counter and fire or not fire + * depending on whether the delay value has + * been reached. + */ + + if (turbo_enabler[player]) { - if (input_cb(player, RETRO_DEVICE_JOYPAD, 0, bindmap[i].retro)) + /* Handle Turbo A & B buttons */ + for (i = 0; i < TURBO_BUTTONS; i++) { - if (turbo_button_toggle[player][i-8] == 0) - input_buf |= bindmap[i].nes; - turbo_button_toggle[player][i-8]++; - if (turbo_button_toggle[player][i-8] > turbo_delay) - /* Reset the toggle if delay value is reached */ - turbo_button_toggle[player][i-8] = 0; + if (input_cb(player, RETRO_DEVICE_JOYPAD, 0, turbomap[i].retro)) + { + if (!turbo_button_toggle[player][i]) + input_buf |= turbomap[i].nes; + turbo_button_toggle[player][i]++; + turbo_button_toggle[player][i] %= turbo_delay + 1; + } + else + /* If the button is not pressed, just reset the toggle */ + turbo_button_toggle[player][i] = 0; } - else - /* If the button is not pressed, just reset the toggle */ - turbo_button_toggle[player][i-8] = 0; } } @@ -1426,7 +1442,6 @@ static void FCEUD_UpdateInput(void) } JSReturn |= (input_buf & 0xff) << (player << 3); - } /* other inputs*/ @@ -2017,7 +2032,7 @@ bool retro_load_game(const struct retro_game_info *game) external_palette_exist = ipalette; if (external_palette_exist) - FCEU_printf("Loading custom palette: %s%cnes.pal\n", dir, slash); + FCEU_printf(" Loading custom palette: %s%cnes.pal\n", dir, slash); is_PAL = retro_get_region(); /* Save current loaded region info */ diff --git a/src/fceu-memory.c b/src/fceu-memory.c index 0e38cc8..6dfecfe 100644 --- a/src/fceu-memory.c +++ b/src/fceu-memory.c @@ -19,6 +19,7 @@ */ #include +#include #include "fceu-types.h" #include "fceu.h" diff --git a/src/sound.c b/src/sound.c index 6454f13..03646af 100644 --- a/src/sound.c +++ b/src/sound.c @@ -182,7 +182,7 @@ static void SQReload(int x, uint8 V) { if (EnabledChannels & (1 << x)) lengthcount[x] = lengthtable[(V >> 3) & 0x1f]; - curfreq[x] = curfreq[x] & 0xff | ((V & 7) << 8); + curfreq[x] = (curfreq[x] & 0xff) | ((V & 7) << 8); RectDutyCount[x] = 7; EnvUnits[x].reloaddec = 1; } @@ -195,8 +195,6 @@ static DECLFW(Write_PSG) { DoSQ1(); EnvUnits[0].Mode = (V & 0x30) >> 4; EnvUnits[0].Speed = (V & 0xF); - if (swapDuty) - V = (V & 0x3F) | ((V & 0x80) >> 1) | ((V & 0x40) << 1); break; case 0x1: DoSQ1(); @@ -216,8 +214,6 @@ static DECLFW(Write_PSG) { DoSQ2(); EnvUnits[1].Mode = (V & 0x30) >> 4; EnvUnits[1].Speed = (V & 0xF); - if (swapDuty) - V = (V & 0x3F) | ((V & 0x80) >> 1) | ((V & 0x40) << 1); break; case 0x5: DoSQ2(); @@ -547,6 +543,8 @@ static INLINE void RDoSQ(int x) { rc = cf - (-rc % cf); } } else { + int dutyCycle; + if (EnvUnits[x].Mode & 0x1) amp = EnvUnits[x].Speed; else @@ -562,7 +560,10 @@ static INLINE void RDoSQ(int x) { amp = (amp * FSettings.SquareVolume[x]) / 256; amp <<= 24; - rthresh = RectDuties[(PSG[(x << 2)] & 0xC0) >> 6]; + dutyCycle = (PSG[(x << 2)] & 0xC0) >> 6; + if (swapDuty) + dutyCycle = ((dutyCycle & 2) >> 1) | ((dutyCycle & 1) << 1); + rthresh = RectDuties[dutyCycle]; currdc = RectDutyCount[x]; D = &WaveHi[ChannelBC[x]]; @@ -612,6 +613,7 @@ static void RDoSQLQ(void) { for (x = 0; x < 2; x++) { int y; + int dutyCycle; inie[x] = nesincsize; if (curfreq[x] < 8 || curfreq[x] > 0x7ff) @@ -637,7 +639,10 @@ static void RDoSQLQ(void) { if (!inie[x]) amp[x] = 0; /* Correct? Buzzing in MM2, others otherwise... */ - rthresh[x] = RectDuties[(PSG[x * 4] & 0xC0) >> 6]; + dutyCycle = (PSG[(x << 2)] & 0xC0) >> 6; + if (swapDuty) + dutyCycle = ((dutyCycle & 2) >> 1) | ((dutyCycle & 1) << 1); + rthresh[x] = RectDuties[dutyCycle]; for (y = 0; y < 8; y++) { if (y < rthresh[x]) From 290b1f92ce9840770de0d312ea62c6fea9430305 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Thu, 27 Dec 2018 19:52:31 +0100 Subject: [PATCH 25/34] Add MSVC2008 target --- Makefile.common | 6 +----- Makefile.libretro | 25 ++++++++++++++++++++++--- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/Makefile.common b/Makefile.common index 36127ad..9ee013b 100644 --- a/Makefile.common +++ b/Makefile.common @@ -3,11 +3,7 @@ INCFLAGS := -I$(CORE_DIR)/drivers/libretro -I$(LIBRETRO_COMM_DIR)/include - COREDEFINES = -D__LIBRETRO__ -DSOUND_QUALITY=0 -DPATH_MAX=1024 -DFCEU_VERSION_NUMERIC=9813 -DFRONTEND_SUPPORTS_RGB565 INCLUDE_STDINT = 0 -ifneq (,$(findstring msvc2003,$(platform))) -INCLUDE_STDINT = 1 -endif - -ifneq (,$(findstring msvc2005,$(platform))) +ifneq (,$(findstring msvc200,$(platform))) INCLUDE_STDINT = 1 endif diff --git a/Makefile.libretro b/Makefile.libretro index 3a27cb9..ab3908c 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -543,6 +543,26 @@ CXXFLAGS += -D_XBOX -D_XBOX360 ENDIANNESS_DEFINES += -DMSB_FIRST STATIC_LINKING=1 +# Windows MSVC 2008 x86 +else ifeq ($(platform), windows_msvc2008_x86) + CC = cl.exe + CXX = cl.exe + +PATH := $(shell IFS=$$'\n'; cygpath "$(VS90COMNTOOLS)../../VC/bin"):$(PATH) +PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS90COMNTOOLS)../IDE") +INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS90COMNTOOLS)../../VC/include") +LIB := $(shell IFS=$$'\n'; cygpath -w "$(VS90COMNTOOLS)../../VC/lib") +BIN := $(shell IFS=$$'\n'; cygpath "$(VS90COMNTOOLS)../../VC/bin") + +WindowsSdkDir := $(INETSDK) + +export INCLUDE := $(INCLUDE);$(INETSDK)/Include +export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib +TARGET := $(TARGET_NAME)_libretro.dll +PSS_STYLE :=2 +LDFLAGS += -DLL +CFLAGS += -D_CRT_SECURE_NO_DEPRECATE + # Windows MSVC 2005 x86 else ifeq ($(platform), windows_msvc2005_x86) CC = cl.exe @@ -556,7 +576,7 @@ BIN := $(shell IFS=$$'\n'; cygpath "$(VS80COMNTOOLS)../../VC/bin") WindowsSdkDir := $(INETSDK) -export INCLUDE := $(INCLUDE);$(INETSDK)/Include;src/drivers/libretro/msvc/msvc-2005 +export INCLUDE := $(INCLUDE);$(INETSDK)/Include export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib TARGET := $(TARGET_NAME)_libretro.dll PSS_STYLE :=2 @@ -576,7 +596,7 @@ BIN := $(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../../Vc7/bin") WindowsSdkDir := $(INETSDK) -export INCLUDE := $(INCLUDE);$(INETSDK)/Include;src/drivers/libretro/msvc/msvc-2005 +export INCLUDE := $(INCLUDE);$(INETSDK)/Include export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib TARGET := $(TARGET_NAME)_libretro.dll PSS_STYLE :=2 @@ -704,7 +724,6 @@ endif else $(LD) $(LINKOUT)$@ $(SHARED) $(OBJECTS) $(LDFLAGS) $(LIBS) endif - @echo "** BUILD SUCCESSFUL! GG NO RE **" %.o: %.c $(CC) -c $(OBJOUT)$@ $< $(CFLAGS) $(INCFLAGS) From 919468f74cbce8b132029a191a4a2adddcdee624 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Thu, 3 Jan 2019 14:05:53 +0100 Subject: [PATCH 26/34] Update Makefile --- Makefile.libretro | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index ab3908c..2222307 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -382,6 +382,8 @@ else ifeq ($(platform), genode) # Windows MSVC 2017 all architectures else ifneq (,$(findstring windows_msvc2017,$(platform))) + CC = cl.exe + CXX = cl.exe PlatformSuffix = $(subst windows_msvc2017_,,$(platform)) ifneq (,$(findstring desktop,$(PlatformSuffix))) @@ -401,8 +403,6 @@ else ifneq (,$(findstring windows_msvc2017,$(platform))) TargetArchMoniker = $(subst $(WinPartition)_,,$(PlatformSuffix)) - CC = cl.exe - CXX = cl.exe LD = link.exe reg_query = $(call filter_out2,$(subst $2,,$(shell reg query "$2" -v "$1" 2>nul))) @@ -714,7 +714,6 @@ include $(THEOS_MAKE_PATH)/library.mk else all: $(TARGET) $(TARGET): $(OBJECTS) - @echo "** BUILDING $(TARGET) FOR PLATFORM $(platform) **" ifeq ($(STATIC_LINKING),1) ifneq (,$(findstring msvc,$(platform))) $(LD) $(LINKOUT)$@ $(OBJECTS) From b53fb9123957182ef14ec728a2ae8dc73195c9ee Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 4 Jan 2019 17:13:09 +0800 Subject: [PATCH 27/34] FDS: Use retro_get_memory_data/size for disk saving --- src/drivers/libretro/libretro.c | 4 ++ src/fds.c | 115 +++++++++++++++----------------- src/fds.h | 3 + 3 files changed, 60 insertions(+), 62 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 67b80e4..89ed88a 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -2123,6 +2123,8 @@ void *retro_get_memory_data(unsigned type) return iNESCart.SaveGame[0]; else if (UNIFCart.battery && UNIFCart.SaveGame[0] && UNIFCart.SaveGameLen[0]) return UNIFCart.SaveGame[0]; + else if (GameInfo->type == GIT_FDS) + return FDSROM_ptr(); else data = NULL; break; @@ -2148,6 +2150,8 @@ size_t retro_get_memory_size(unsigned type) size = iNESCart.SaveGameLen[0]; else if (UNIFCart.battery && UNIFCart.SaveGame[0] && UNIFCart.SaveGameLen[0]) size = UNIFCart.SaveGameLen[0]; + else if (GameInfo->type == GIT_FDS) + size = FDSROM_size(); else size = 0; break; diff --git a/src/fds.c b/src/fds.c index baf52d0..2836560 100644 --- a/src/fds.c +++ b/src/fds.c @@ -62,6 +62,8 @@ static uint8 FDSRegs[6]; static int32 IRQLatch, IRQCount; static uint8 IRQa; +static uint8 *FDSROM = NULL; +static uint32 FDSROMSize = 0; static uint8 *FDSRAM = NULL; static uint32 FDSRAMSize; static uint8 *FDSBIOS = NULL; @@ -71,7 +73,6 @@ static uint32 CHRRAMSize; /* Original disk data backup, to help in creating save states. */ static uint8 *diskdatao[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - static uint8 *diskdata[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; static uint32 TotalSides; @@ -84,6 +85,15 @@ static uint8 SelectDisk, InDisk; uint32 lastDiskPtrRead, lastDiskPtrWrite; #define DC_INC 1 +#define BYTES_PER_SIDE 65500 + +uint8 *FDSROM_ptr(void) { + return (FDSROM); +} + +uint32 FDSROM_size(void) { + return (FDSROMSize); +} void FDSGI(int h) { switch (h) { @@ -555,13 +565,18 @@ static DECLFW(FDSWrite) { } static void FreeFDSMemory(void) { - int x; - - for (x = 0; x < TotalSides; x++) - if (diskdata[x]) { - free(diskdata[x]); - diskdata[x] = 0; - } + if (FDSROM) + free(FDSROM); + FDSROM = NULL; + if (FDSBIOS) + free(FDSBIOS); + FDSBIOS = NULL; + if (FDSRAM) + free(FDSRAM); + FDSRAM = NULL; + if (CHRRAM) + free(CHRRAM); + CHRRAM = NULL; } static int SubLoad(FCEUFILE *fp) { @@ -584,19 +599,21 @@ static int SubLoad(FCEUFILE *fp) { } else TotalSides = header[4]; - md5_starts(&md5); - if (TotalSides > 8) TotalSides = 8; if (TotalSides < 1) TotalSides = 1; + FDSROMSize = TotalSides * BYTES_PER_SIDE; + FDSROM = (uint8*)FCEU_malloc(FDSROMSize); + + if (!FDSROM) + return (0); + + for (x = 0; x < TotalSides; x++) + diskdata[x] = &FDSROM[x * BYTES_PER_SIDE]; + + md5_starts(&md5); + for (x = 0; x < TotalSides; x++) { - diskdata[x] = (uint8*)FCEU_malloc(65500); - if (!diskdata[x]) { - int zol; - for (zol = 0; zol < x; zol++) - free(diskdata[zol]); - return 0; - } FCEU_fread(diskdata[x], 1, 65500, fp); md5_update(&md5, diskdata[x], 65500); } @@ -636,17 +653,9 @@ int FDSLoad(const char *name, FCEUFILE *fp) { free(fn); - ResetCartMapping(); + FreeFDSMemory(); - if (FDSBIOS) - free(FDSBIOS); - FDSBIOS = NULL; - if (FDSRAM) - free(FDSRAM); - FDSRAM = NULL; - if (CHRRAM) - free(CHRRAM); - CHRRAM = NULL; + ResetCartMapping(); FDSBIOSsize = 8192; FDSBIOS = (uint8*)FCEU_gmalloc(FDSBIOSsize); @@ -665,7 +674,6 @@ int FDSLoad(const char *name, FCEUFILE *fp) { FCEU_fseek(fp, 0, SEEK_SET); - FreeFDSMemory(); if (!SubLoad(fp)) { if (FDSBIOS) free(FDSBIOS); @@ -673,6 +681,14 @@ int FDSLoad(const char *name, FCEUFILE *fp) { return(0); } + for (x = 0; x < TotalSides; x++) { + diskdatao[x] = (uint8*)FCEU_malloc(65500); + memcpy(diskdatao[x], diskdata[x], 65500); + } + +#if 0 + /* auxillary rom loading for save file is now handled + * using retro_get_memory_size/data */ { FCEUFILE *tp; char *fn = FCEU_MakeFName(FCEUMKF_FDS, 0, 0); @@ -699,6 +715,7 @@ int FDSLoad(const char *name, FCEUFILE *fp) { } free(fn); } +#endif GameInfo->type = GIT_FDS; GameInterface = FDSGI; @@ -715,12 +732,12 @@ int FDSLoad(const char *name, FCEUFILE *fp) { AddExState(diskdata[x], 65500, 0, temp); } - AddExState(&FDSRegs[0], 1, 0, "REG1"); - AddExState(&FDSRegs[1], 1, 0, "REG2"); - AddExState(&FDSRegs[2], 1, 0, "REG3"); - AddExState(&FDSRegs[3], 1, 0, "REG4"); - AddExState(&FDSRegs[4], 1, 0, "REG5"); - AddExState(&FDSRegs[5], 1, 0, "REG6"); + AddExState(&FDSRegs[0], 1, 0, "REG1"); + AddExState(&FDSRegs[1], 1, 0, "REG2"); + AddExState(&FDSRegs[2], 1, 0, "REG3"); + AddExState(&FDSRegs[3], 1, 0, "REG4"); + AddExState(&FDSRegs[4], 1, 0, "REG5"); + AddExState(&FDSRegs[5], 1, 0, "REG6"); AddExState(&IRQCount, 4, 1, "IRQC"); AddExState(&IRQLatch, 4, 1, "IQL1"); AddExState(&IRQa, 1, 0, "IRQA"); @@ -743,7 +760,8 @@ int FDSLoad(const char *name, FCEUFILE *fp) { SetupCartMirroring(0, 0, 0); - FCEU_printf(" Sides: %d\n\n", TotalSides); + FCEU_printf(" # of Sides : %d\n\n", TotalSides); + FCEU_printf(" ROM MD5 : 0x%s\n", md5_asciistr(GameInfo->MD5)); FCEUI_SetVidSystem(0); @@ -751,27 +769,10 @@ int FDSLoad(const char *name, FCEUFILE *fp) { } void FDSClose(void) { - FILE *fp; int x; - char *fn = FCEU_MakeFName(FCEUMKF_FDS, 0, 0); if (!DiskWritten) return; - if (!(fp = fopen(fn, "wb"))) { - free(fn); - return; - } - FCEU_printf("FDS Save \"%s\"\n", fn); - free(fn); - - for (x = 0; x < TotalSides; x++) { - if (fwrite(diskdata[x], 1, 65500, fp) != 65500) { - FCEU_PrintError("Error saving FDS image!\n"); - fclose(fp); - return; - } - } - for (x = 0; x < TotalSides; x++) if (diskdatao[x]) { free(diskdatao[x]); @@ -779,14 +780,4 @@ void FDSClose(void) { } FreeFDSMemory(); - if (FDSBIOS) - free(FDSBIOS); - FDSBIOS = NULL; - if (FDSRAM) - free(FDSRAM); - FDSRAM = NULL; - if (CHRRAM) - free(CHRRAM); - CHRRAM = NULL; - fclose(fp); } diff --git a/src/fds.h b/src/fds.h index a07dbba..236d936 100644 --- a/src/fds.h +++ b/src/fds.h @@ -1,6 +1,9 @@ #ifndef _FCEU_FDS_H #define _FCEU_FDS_H +uint8 *FDSROM_ptr(void); +uint32 FDSROM_size(void); + void FDSSoundReset(void); void FCEU_FDSInsert(int oride); From 00bf47ebf83d12b810c236a8344e77230c247839 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 4 Jan 2019 19:33:26 +0800 Subject: [PATCH 28/34] Fix memory leak --- src/fds.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fds.c b/src/fds.c index 2836560..56ee503 100644 --- a/src/fds.c +++ b/src/fds.c @@ -665,11 +665,13 @@ int FDSLoad(const char *name, FCEUFILE *fp) { if (FDSBIOS) free(FDSBIOS); FDSBIOS = NULL; + free(zp->fp->data); FCEU_fclose(zp); FCEU_PrintError("Error reading FDS BIOS ROM image.\n"); return 0; } + free(zp->fp->data); FCEU_fclose(zp); FCEU_fseek(fp, 0, SEEK_SET); From 1b47b366c572ccd39f357336844bd20990edd8bc Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Fri, 4 Jan 2019 22:33:26 +0800 Subject: [PATCH 29/34] FDS: Print manufacturer label when loading rom --- src/fds.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 165 insertions(+), 2 deletions(-) diff --git a/src/fds.c b/src/fds.c index 56ee503..5f2b56b 100644 --- a/src/fds.c +++ b/src/fds.c @@ -564,6 +564,167 @@ static DECLFW(FDSWrite) { FDSRegs[A & 7] = V; } +struct codes_t { + uint8 code; + char *name; +}; + +static const struct codes_t list[] = { + { 0x01, "Nintendo" }, + { 0x02, "Rocket Games" }, + { 0x08, "Capcom" }, + { 0x09, "Hot B Co." }, + { 0x0A, "Jaleco" }, + { 0x0B, "Coconuts Japan" }, + { 0x0C, "Coconuts Japan/G.X.Media" }, + { 0x13, "Electronic Arts Japan" }, + { 0x18, "Hudson Soft Japan" }, + { 0x19, "S.C.P." }, + { 0x1A, "Yonoman" }, + { 0x20, "Destination Software" }, + { 0x22, "VR 1 Japan" }, + { 0x25, "San-X" }, + { 0x28, "Kemco Japan" }, + { 0x29, "Seta" }, + { 0x36, "Codemasters" }, + { 0x37, "GAGA Communications" }, + { 0x38, "Laguna" }, + { 0x39, "Telstar Fun and Games" }, + { 0x41, "Ubi Soft Entertainment" }, + { 0x42, "Sunsoft" }, + { 0x47, "Spectrum Holobyte" }, + { 0x49, "Irem" }, + { 0x4A, "Gakken" }, + { 0x4D, "Malibu Games" }, + { 0x4F, "Eidos/U.S. Gold" }, + { 0x50, "Absolute Entertainment" }, + { 0x51, "Acclaim" }, + { 0x52, "Activision" }, + { 0x53, "American Sammy Corp." }, + { 0x54, "Take 2 Interactive" }, + { 0x55, "Hi Tech" }, + { 0x56, "LJN LTD." }, + { 0x58, "Mattel" }, + { 0x5A, "Mindscape/Red Orb Ent." }, + { 0x5C, "Taxan" }, + { 0x5D, "Midway" }, + { 0x5F, "American Softworks" }, + { 0x60, "Titus Interactive Studios" }, + { 0x61, "Virgin Interactive" }, + { 0x62, "Maxis" }, + { 0x64, "LucasArts Entertainment" }, + { 0x67, "Ocean" }, + { 0x69, "Electronic Arts" }, + { 0x6E, "Elite Systems Ltd." }, + { 0x6F, "Electro Brain" }, + { 0x70, "Infogrames" }, + { 0x71, "Interplay" }, + { 0x72, "JVC Musical Industries Inc" }, + { 0x73, "Parker Brothers" }, + { 0x75, "SCI" }, + { 0x78, "THQ" }, + { 0x79, "Accolade" }, + { 0x7A, "Triffix Ent. Inc." }, + { 0x7C, "Microprose Software" }, + { 0x7D, "Universal Interactive Studios" }, + { 0x7F, "Kemco" }, + { 0x80, "Misawa" }, + { 0x83, "LOZC" }, + { 0x8B, "Bulletproof Software" }, + { 0x8C, "Vic Tokai Inc." }, + { 0x91, "Chun Soft" }, + { 0x92, "Video System" }, + { 0x93, "BEC" }, + { 0x96, "Yonezawa/S'pal" }, + { 0x97, "Kaneko" }, + { 0x99, "Victor Interactive Software" }, + { 0x9A, "Nichibutsu/Nihon Bussan" }, + { 0x9B, "Tecmo" }, + { 0x9C, "Imagineer" }, + { 0x9F, "Nova" }, + { 0xA0, "Telenet" }, + { 0xA1, "Hori" }, + { 0xA2, "Scorpion Soft " }, + { 0xA4, "Konami" }, + { 0xA6, "Kawada" }, + { 0xA7, "Takara" }, + { 0xA8, "Royal Industries" }, + { 0xA9, "Technos Japan Corp." }, + { 0xAA, "JVC" }, + { 0xAC, "Toei Animation" }, + { 0xAD, "Toho" }, + { 0xAF, "Namco" }, + { 0xB0, "Acclaim Japan" }, + { 0xB1, "ASCII" }, + { 0xB2, "Bandai" }, + { 0xB3, "Soft Pro Inc." }, + { 0xB4, "Enix" }, + { 0xB6, "HAL Laboratory" }, + { 0xB7, "SNK" }, + { 0xB9, "Pony Canyon Hanbai" }, + { 0xBA, "Culture Brain" }, + { 0xBB, "Sunsoft" }, + { 0xBC, "Toshiba EMI" }, + { 0xBD, "Sony Imagesoft" }, + { 0xBF, "Sammy" }, + { 0xC0, "Taito" }, + { 0xC1, "Sunsoft / Ask Co., Ltd." }, + { 0xC2, "Kemco" }, + { 0xC3, "Square Soft" }, + { 0xC4, "Tokuma Shoten " }, + { 0xC5, "Data East" }, + { 0xC6, "Tonkin House" }, + { 0xC7, "East Cube" }, + { 0xC8, "Koei" }, + { 0xCA, "Konami/Palcom/Ultra" }, + { 0xCB, "Vapinc/NTVIC" }, + { 0xCC, "Use Co.,Ltd." }, + { 0xCD, "Meldac" }, + { 0xCE, "FCI/Pony Canyon" }, + { 0xCF, "Angel" }, + { 0xD1, "Sofel" }, + /*{ 0xD2, "Quest" },*/ + { 0xD2, "Bothtec, Inc." }, + { 0xD3, "Sigma Enterprises" }, + { 0xD4, "Ask Kodansa" }, + { 0xD6, "Naxat" }, + { 0xD7, "Copya System" }, + { 0xD9, "Banpresto" }, + { 0xDA, "TOMY" }, + /*{ 0xDB, "LJN Japan" },*/ + { 0xDB, "Hiro Co., Ltd." }, + { 0xDD, "NCS" }, + { 0xDF, "Altron Corporation" }, + { 0xE2, "Yutaka" }, + { 0xE3, "Varie" }, + { 0xE5, "Epoch" }, + { 0xE7, "Athena" }, + { 0xE8, "Asmik Ace Entertainment Inc." }, + { 0xE9, "Natsume" }, + { 0xEA, "King Records" }, + { 0xEB, "Atlus" }, + { 0xEC, "Epic/Sony Records" }, + { 0xEE, "IGS" }, + { 0xF0, "A Wave" }, + { 0 } + }; + +static const char *getManufacturer(uint8 code) +{ + int x = 0; + char *ret = "unlicensed"; + + while (list[x].code != 0) { + if (list[x].code == code) { + ret = list[x].name; + break; + } + x++; + } + + return ret; +} + static void FreeFDSMemory(void) { if (FDSROM) free(FDSROM); @@ -762,8 +923,10 @@ int FDSLoad(const char *name, FCEUFILE *fp) { SetupCartMirroring(0, 0, 0); - FCEU_printf(" # of Sides : %d\n\n", TotalSides); - FCEU_printf(" ROM MD5 : 0x%s\n", md5_asciistr(GameInfo->MD5)); + FCEU_printf(" Code : %02x\n", diskdata[0][0xf]); + FCEU_printf(" Manufacturer : %s\n", getManufacturer(diskdata[0][0xf])); + FCEU_printf(" # of Sides : %d\n", TotalSides); + FCEU_printf(" ROM MD5 : 0x%s\n", md5_asciistr(GameInfo->MD5)); FCEUI_SetVidSystem(0); From 55b3d8a5bc95e62c1a6c405afb7cae72d377475c Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 6 Jan 2019 10:42:12 +0800 Subject: [PATCH 30/34] FDS: Fix pointers are not freed when closing rom --- src/fds.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fds.c b/src/fds.c index 5f2b56b..2dc76a6 100644 --- a/src/fds.c +++ b/src/fds.c @@ -848,6 +848,8 @@ int FDSLoad(const char *name, FCEUFILE *fp) { diskdatao[x] = (uint8*)FCEU_malloc(65500); memcpy(diskdatao[x], diskdata[x], 65500); } + + DiskWritten = 1; #if 0 /* auxillary rom loading for save file is now handled From d7f7709a37419d5b626aeec119a985bda162f2d8 Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Mon, 21 Jan 2019 22:19:46 +0100 Subject: [PATCH 31/34] Add palette into FCEumm for PS2 --- Makefile.libretro | 12 ++++ ps2/inttypes.h | 8 +++ ps2/stdint.h | 33 +++++++++ .../include/libretro_gskit_ps2.h | 56 +++++++++++++++ src/drivers/libretro/libretro.c | 72 ++++++++++++++++++- 5 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 ps2/inttypes.h create mode 100644 ps2/stdint.h create mode 100644 src/drivers/libretro/libretro-common/include/libretro_gskit_ps2.h diff --git a/Makefile.libretro b/Makefile.libretro index 2222307..ba86af4 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -155,6 +155,18 @@ else ifeq ($(platform), sncps3) STATIC_LINKING=1 EXTERNAL_ZLIB=1 +# PS2 +else ifeq ($(platform), ps2) + TARGET := $(TARGET_NAME)_libretro_$(platform).a + CC = ee-gcc$(EXE_EXT) + AR = ee-ar$(EXE_EXT) + FCEU_DEFINES := -DPATH_MAX=1024 -DINLINE=inline -DPSS_STYLE=1 -DFCEU_VERSION_NUMERIC=9813 -DHAVE_ASPRINTF + ENDIANNESS_DEFINES := -DLSB_FIRST -DLOCAL_LE=1 + PLATFORM_DEFINES := -DPS2 -G0 -DFRONTEND_SUPPORTS_ABGR1555 -DRENDER_GSKIT_PS2 + PLATFORM_DEFINES += -I$(PS2SDK)/ee/include -I$(PS2SDK)/common/include -Ips2/ -I$(PS2DEV)/gsKit/include + STATIC_LINKING=1 + EXTERNAL_ZLIB=1 + # PSP else ifeq ($(platform), psp1) TARGET := $(TARGET_NAME)_libretro_$(platform).a diff --git a/ps2/inttypes.h b/ps2/inttypes.h new file mode 100644 index 0000000..3049fbd --- /dev/null +++ b/ps2/inttypes.h @@ -0,0 +1,8 @@ +#ifndef INTTYPES_H +#define INTTYPES_H + +#define PRId64 "ld" +#define PRIu64 "lu" +#define PRIuPTR "lu" + +#endif //INTTYPES_H diff --git a/ps2/stdint.h b/ps2/stdint.h new file mode 100644 index 0000000..ae9a75b --- /dev/null +++ b/ps2/stdint.h @@ -0,0 +1,33 @@ +#ifndef STDINT_H +#define STDINT_H + +typedef unsigned long uintptr_t; +typedef signed long intptr_t; + +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed int int32_t; +typedef signed long int64_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long uint64_t; + +typedef unsigned long uint_least32_t; +typedef unsigned short uint_least16_t; + +#define STDIN_FILENO 0 /* standard input file descriptor */ +#define STDOUT_FILENO 1 /* standard output file descriptor */ +#define STDERR_FILENO 2 /* standard error file descriptor */ + +#define INT8_C(val) val##c +#define INT16_C(val) val##h +#define INT32_C(val) val##i +#define INT64_C(val) val##l + +#define UINT8_C(val) val##uc +#define UINT16_C(val) val##uh +#define UINT32_C(val) val##ui +#define UINT64_C(val) val##ul + +#endif //STDINT_H diff --git a/src/drivers/libretro/libretro-common/include/libretro_gskit_ps2.h b/src/drivers/libretro/libretro-common/include/libretro_gskit_ps2.h new file mode 100644 index 0000000..e1e978d --- /dev/null +++ b/src/drivers/libretro/libretro-common/include/libretro_gskit_ps2.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2010-2018 The RetroArch team + * + * --------------------------------------------------------------------------------------------- + * The following license statement only applies to this libretro API header (libretro_d3d.h) + * --------------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the + * "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef LIBRETRO_GSKIT_PS2_H_ +#define LIBRETRO_GSKIT_PS2_H_ + +#include "libretro.h" + +#if defined(PS2) + +#include + +#define RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION 1 + +struct retro_hw_render_interface_gskit_ps2 +{ + /* Must be set to RETRO_HW_RENDER_INTERFACE_GSKIT_PS2. */ + enum retro_hw_render_interface_type interface_type; + /* Must be set to RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION. */ + unsigned interface_version; + + /* Opaque handle to the GSKit_PS2 backend in the frontend + * which must be passed along to all function pointers + * in this interface. + */ + GSTEXTURE *coreTexture; + bool clearTexture; +}; +typedef struct retro_hw_render_interface_gskit_ps2 RETRO_HW_RENDER_INTEFACE_GSKIT_PS2; + +#endif + +#endif /* LIBRETRO_GSKIT_PS2_H_ */ diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 89ed88a..cc6cfb0 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -24,6 +24,10 @@ #include "../../vsuni.h" #include "../../video.h" +#if defined(RENDER_GSKIT_PS2) +#include "libretro-common/include/libretro_gskit_ps2.h" +#endif + #include "libretro-common/include/streams/memory_stream.h" #define MAX_PLAYERS 4 /* max supported players */ @@ -95,7 +99,11 @@ static __attribute__((aligned(16))) uint16_t retro_palette[256]; #else static uint16_t retro_palette[256]; #endif +#if defined(RENDER_GSKIT_PS2) +static uint8_t* fceu_video_out; +#else static uint16_t* fceu_video_out; +#endif /* Some timing-related variables. */ static unsigned sndsamplerate; @@ -145,6 +153,16 @@ int FCEUD_SendData(void *data, uint32 len) #define RED_EXPAND 3 #define GREEN_EXPAND 2 #define BLUE_EXPAND 3 +#elif defined (FRONTEND_SUPPORTS_ABGR1555) +#define RED_SHIFT 0 +#define GREEN_SHIFT 5 +#define BLUE_SHIFT 10 +#define RED_EXPAND 3 +#define GREEN_EXPAND 3 +#define BLUE_EXPAND 3 +#define RED_MASK 0x1F +#define GREEN_MASK 0x3E0 +#define BLUE_MASK 0x7C00 #elif defined (FRONTEND_SUPPORTS_RGB565) #define RED_SHIFT 11 #define GREEN_SHIFT 5 @@ -166,10 +184,21 @@ int FCEUD_SendData(void *data, uint32 len) void FCEUD_SetPalette(uint8_t index, uint8_t r, uint8_t g, uint8_t b) { + unsigned char index_to_write = index; +#if defined(RENDER_GSKIT_PS2) + /* Index correction for PS2 GS */ + int modi = index & 63; + if ((modi >= 8 && modi < 16) || (modi >= 40 && modi < 48)) { + index_to_write += 8; + } else if ((modi >= 16 && modi < 24) || (modi >= 48 && modi < 56)) { + index_to_write -= 8; + } +#endif + #ifdef FRONTEND_SUPPORTS_RGB565 - retro_palette[index] = BUILD_PIXEL_RGB565(r >> RED_EXPAND, g >> GREEN_EXPAND, b >> BLUE_EXPAND); + retro_palette[index_to_write] = BUILD_PIXEL_RGB565(r >> RED_EXPAND, g >> GREEN_EXPAND, b >> BLUE_EXPAND); #else - retro_palette[index] = + retro_palette[index_to_write] = ((r >> RED_EXPAND) << RED_SHIFT) | ((g >> GREEN_EXPAND) << GREEN_SHIFT) | ((b >> BLUE_EXPAND) << BLUE_SHIFT); #endif } @@ -1534,6 +1563,45 @@ static void retro_run_blit(uint8_t *gfx) sceGuFinish(); video_cb(texture_vram_p, width, height, 256); +#elif defined(RENDER_GSKIT_PS2) + + RETRO_HW_RENDER_INTEFACE_GSKIT_PS2 *ps2 = NULL; + uint32_t *buf = (uint32_t *)RETRO_HW_FRAME_BUFFER_VALID; + + incr += (overscan_h ? 16 : 0); + width -= (overscan_h ? 16 : 0); + height -= (overscan_v ? 16 : 0); + pitch -= (overscan_h ? 32 : 0); + gfx += (overscan_v ? ((overscan_h ? 8 : 0) + 256 * 8) : (overscan_h ? 8 : 0)); + + if (!environ_cb(RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE, (void **)&ps2) || !ps2) { + printf("Failed to get HW rendering interface!\n"); + return; + } + + if (ps2->interface_version != RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION) { + printf("HW render interface mismatch, expected %u, got %u!\n", + RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION, ps2->interface_version); + return; + } + + if (ps2->clearTexture || !ps2->coreTexture->Clut || !ps2->coreTexture->Mem ) { + /* If it is empty we need to create it */ + ps2->coreTexture->Width = width; + ps2->coreTexture->Height = height; + ps2->coreTexture->PSM = GS_PSM_T8; + ps2->coreTexture->ClutPSM = GS_PSM_CT16; + ps2->coreTexture->Filter = GS_FILTER_LINEAR; + } + + for (y = 0; y < height; y++, gfx += incr) + for ( x = 0; x < width; x++, gfx++) + fceu_video_out[y * width + x] = *gfx; + + ps2->coreTexture->Clut = (u32*)retro_palette; + ps2->coreTexture->Mem = (u32*)fceu_video_out; + + video_cb(buf, width, height, pitch); #else incr += (overscan_h ? 16 : 0); width -= (overscan_h ? 16 : 0); From 9715f13bc77ed78b62d45456d0df0227ed7ae48a Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Sat, 16 Feb 2019 18:41:46 +0100 Subject: [PATCH 32/34] Improvement paddings Improvement palette --- Makefile.libretro | 10 + ps2/SMS_Utils.s | 202 ++++++++++++++++++ .../include/libretro_gskit_ps2.h | 12 ++ src/drivers/libretro/libretro.c | 43 ++-- 4 files changed, 242 insertions(+), 25 deletions(-) create mode 100644 ps2/SMS_Utils.s diff --git a/Makefile.libretro b/Makefile.libretro index ba86af4..140b874 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -14,6 +14,7 @@ filter_out1 = $(filter-out $(firstword $1),$1) filter_out2 = $(call filter_out1,$(call filter_out1,$1)) unixpath = $(subst \,/,$1) unixcygpath = /$(subst :,,$(call unixpath,$1)) +RETROARCH_OBJECTS := ifeq ($(platform),) platform = unix @@ -163,10 +164,13 @@ else ifeq ($(platform), ps2) FCEU_DEFINES := -DPATH_MAX=1024 -DINLINE=inline -DPSS_STYLE=1 -DFCEU_VERSION_NUMERIC=9813 -DHAVE_ASPRINTF ENDIANNESS_DEFINES := -DLSB_FIRST -DLOCAL_LE=1 PLATFORM_DEFINES := -DPS2 -G0 -DFRONTEND_SUPPORTS_ABGR1555 -DRENDER_GSKIT_PS2 + PLATFORM_DEFINES += -Dmemcpy=mips_memcpy -Dmemset=mips_memset PLATFORM_DEFINES += -I$(PS2SDK)/ee/include -I$(PS2SDK)/common/include -Ips2/ -I$(PS2DEV)/gsKit/include STATIC_LINKING=1 EXTERNAL_ZLIB=1 + RETROARCH_OBJECTS += ps2/SMS_Utils.o + # PSP else ifeq ($(platform), psp1) TARGET := $(TARGET_NAME)_libretro_$(platform).a @@ -672,6 +676,7 @@ include Makefile.common CFLAGS += -DWANT_GRIFFIN OBJECTS := $(SOURCES_C:.c=.o) +OBJECTS += $(RETROARCH_OBJECTS) DEFINES := $(COREDEFINES) $(PLATFORM_DEFINES) @@ -739,6 +744,11 @@ endif %.o: %.c $(CC) -c $(OBJOUT)$@ $< $(CFLAGS) $(INCFLAGS) +ifeq ($(platform), ps2) +%.o: %.s + ee-as -G0 $< -o $@ +endif + clean-objs: rm -f $(OBJECTS) diff --git a/ps2/SMS_Utils.s b/ps2/SMS_Utils.s new file mode 100644 index 0000000..e437356 --- /dev/null +++ b/ps2/SMS_Utils.s @@ -0,0 +1,202 @@ +/* +# ___ _ _ ___ +# | | | | | +# ___| | | ___| PS2DEV Open Source Project. +#---------------------------------------------------------- +# MUL64 is pulled from some binary library (I don't remember which one). +# mips_memcpy routine is pulled from 'sde' library from MIPS. +# +*/ +.set noat +.set noreorder +.set nomacro + +.globl MUL64 +.globl mips_memcpy +.globl mips_memset + +.text + +MUL64: + pmultuw $v0, $a0, $a1 + dsra32 $a2, $a0, 0 + dsra32 $v1, $a1, 0 + mult $v1, $a0, $v1 + mult1 $a2, $a2, $a1 + addu $v1, $v1, $a2 + dsll32 $v1, $v1, 0 + jr $ra + daddu $v0, $v0, $v1 + +mips_memcpy: + addu $v0, $a0, $zero + beqz $a2, 1f + sltiu $t2, $a2, 12 + bnez $t2, 2f + xor $v1, $a1, $a0 + andi $v1, $v1, 7 + negu $a3, $a0 + beqz $v1, 3f + andi $a3, $a3, 7 + beqz $a3, 4f + subu $a2, $a2, $a3 + ldr $v1, 0($a1) + ldl $v1, 7($a1) + addu $a1, $a1, $a3 + sdr $v1, 0($a0) + addu $a0, $a0, $a3 +4: + andi $v1, $a2, 31 + subu $a3, $a2, $v1 + beqz $a3, 5f + addu $a2, $v1, $zero + addu $a3, $a3, $a1 +6: + ldr $v1, 0($a1) + ldl $v1, 7($a1) + ldr $t0, 8($a1) + ldl $t0, 15($a1) + ldr $t1, 16($a1) + ldl $t1, 23($a1) + ldr $t2, 24($a1) + ldl $t2, 31($a1) + sd $v1, 0($a0) + sd $t0, 8($a0) + sd $t1, 16($a0) + addiu $a1, $a1, 32 + addiu $a0, $a0, 32 + bne $a1, $a3, 6b + sd $t2, -8($a0) +5: + andi $v1, $a2, 7 + subu $a3, $a2, $v1 + beqz $a3, 2f + addu $a2, $v1, $zero + addu $a3, $a3, $a1 +7: + ldr $v1, 0($a1) + ldl $v1, 7($a1) + addiu $a1, $a1, 8 + addiu $a0, $a0, 8 + nop + bne $a1, $a3, 7b + sd $v1, -8($a0) + beq $zero, $zero, 2f + nop +3: + beqz $a3, 8f + subu $a2, $a2, $a3 + ldr $v1, 0($a1) + addu $a1, $a1, $a3 + sdr $v1, 0($a0) + addu $a0, $a0, $a3 +8: + andi $v1, $a2, 31 + subu $a3, $a2, $v1 + beqz $a3, 9f + addu $a2, $v1, $zero + addu $a3, $a3, $a1 +10: + ld $v1, 0($a1) + ld $t0, 8($a1) + ld $t1, 16($a1) + ld $t2, 24($a1) + sd $v1, 0($a0) + sd $t0, 8($a0) + sd $t1, 16($a0) + addiu $a1, $a1, 32 + addiu $a0, $a0, 32 + bne $a1, $a3, 10b + sd $t2, -8($a0) +9: + andi $v1, $a2, 7 + subu $a3, $a2, $v1 + beqz $a3, 2f + addu $a2, $v1, $zero + addu $a3, $a3, $a1 +11: + ld $v1, 0($a1) + addiu $a1, $a1, 8 + addiu $a0, $a0, 8 + nop + nop + bne $a1, $a3, 11b + sd $v1, -8($a0) +2: + beqz $a2, 1f + addu $a3, $a2, $a1 +12: + lbu $v1, 0($a1) + addiu $a1, $a1, 1 + addiu $a0, $a0, 1 + nop + nop + bne $a1, $a3, 12b + sb $v1, -1($a0) +1: + jr $ra + nop + +mips_memset: + beqz $a2, 1f + sltiu $at, $a2, 16 + bnez $at, 2f + andi $a1, $a1, 0xFF + dsll $at, $a1, 0x8 + or $a1, $a1, $at + dsll $at, $a1, 0x10 + or $a1, $a1, $at + dsll32 $at, $a1, 0x0 + or $a1, $a1, $at + andi $v1, $a0, 0x7 + beqz $v1, 3f + li $a3, 8 + subu $a3, $a3, $v1 + subu $a2, $a2, $a3 + sdr $a1, 0($a0) + addu $a0, $a0, $a3 +3: + andi $v1, $a2, 0x1f + subu $a3, $a2, $v1 + beqz $a3, 4f + move $a2, $v1 + addu $a3, $a3, $a0 +5: + sd $a1, 0($a0) + sd $a1, 8($a0) + sd $a1, 16($a0) + addiu $a0, $a0, 32 + sd $a1, -8($a0) + bne $a0, $a3, 5b +4: + andi $v1, $a2, 0x7 + subu $a3, $a2, $v1 + beqz $a3, 2f + move $a2, $v1 + addu $a3, $a3, $a0 +6: + addiu $a0, $a0, 8 + beq $a0, $a3, 2f + sd $a1, -8($a0) + addiu $a0, $a0, 8 + beq $a0, $a3, 2f + sd $a1, -8($a0) + addiu $a0, $a0, 8 + bne $a0, $a3, 6b + sd $a1, -8($a0) +2: + beqz $a2, 1f + addu $a3, $a2, $a0 +7: + addiu $a0, $a0, 1 + beq $a0, $a3, 1f + sb $a1, -1($a0) + addiu $a0, $a0, 1 + beq $a0, $a3, 1f + sb $a1, -1($a0) + addiu $a0, $a0, 1 + bne $a0, $a3, 7b + sb $a1, -1($a0) +1: + jr $ra + nop diff --git a/src/drivers/libretro/libretro-common/include/libretro_gskit_ps2.h b/src/drivers/libretro/libretro-common/include/libretro_gskit_ps2.h index e1e978d..f7b61dc 100644 --- a/src/drivers/libretro/libretro-common/include/libretro_gskit_ps2.h +++ b/src/drivers/libretro/libretro-common/include/libretro_gskit_ps2.h @@ -35,6 +35,16 @@ #define RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION 1 +struct retro_hw_ps2_insets +{ + float top; + float left; + float bottom; + float right; +}; + +#define empty_ps2_insets (struct retro_hw_ps2_insets){0.f, 0.f, 0.f, 0.f} + struct retro_hw_render_interface_gskit_ps2 { /* Must be set to RETRO_HW_RENDER_INTERFACE_GSKIT_PS2. */ @@ -48,6 +58,8 @@ struct retro_hw_render_interface_gskit_ps2 */ GSTEXTURE *coreTexture; bool clearTexture; + bool updatedPalette; + struct retro_hw_ps2_insets padding; }; typedef struct retro_hw_render_interface_gskit_ps2 RETRO_HW_RENDER_INTEFACE_GSKIT_PS2; diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index cc6cfb0..aad2752 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -55,6 +55,10 @@ void* linearMemAlign(size_t size, size_t alignment); void linearFree(void* mem); #endif +#if defined(RENDER_GSKIT_PS2) +RETRO_HW_RENDER_INTEFACE_GSKIT_PS2 *ps2 = NULL; +#endif + static retro_video_refresh_t video_cb = NULL; static retro_input_poll_t poll_cb = NULL; static retro_input_state_t input_cb = NULL; @@ -1564,42 +1568,31 @@ static void retro_run_blit(uint8_t *gfx) video_cb(texture_vram_p, width, height, 256); #elif defined(RENDER_GSKIT_PS2) - - RETRO_HW_RENDER_INTEFACE_GSKIT_PS2 *ps2 = NULL; uint32_t *buf = (uint32_t *)RETRO_HW_FRAME_BUFFER_VALID; - incr += (overscan_h ? 16 : 0); - width -= (overscan_h ? 16 : 0); - height -= (overscan_v ? 16 : 0); - pitch -= (overscan_h ? 32 : 0); - gfx += (overscan_v ? ((overscan_h ? 8 : 0) + 256 * 8) : (overscan_h ? 8 : 0)); + if (!ps2) { + if (!environ_cb(RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE, (void **)&ps2) || !ps2) { + printf("Failed to get HW rendering interface!\n"); + return; + } - if (!environ_cb(RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE, (void **)&ps2) || !ps2) { - printf("Failed to get HW rendering interface!\n"); - return; - } + if (ps2->interface_version != RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION) { + printf("HW render interface mismatch, expected %u, got %u!\n", + RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION, ps2->interface_version); + return; + } - if (ps2->interface_version != RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION) { - printf("HW render interface mismatch, expected %u, got %u!\n", - RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION, ps2->interface_version); - return; - } - - if (ps2->clearTexture || !ps2->coreTexture->Clut || !ps2->coreTexture->Mem ) { - /* If it is empty we need to create it */ ps2->coreTexture->Width = width; ps2->coreTexture->Height = height; ps2->coreTexture->PSM = GS_PSM_T8; ps2->coreTexture->ClutPSM = GS_PSM_CT16; ps2->coreTexture->Filter = GS_FILTER_LINEAR; + ps2->coreTexture->Clut = (u32*)retro_palette; + ps2->updatedPalette = true; + ps2->padding = (struct retro_hw_ps2_insets){8.0f, 8.0f, 8.0f, 8.0f}; } - for (y = 0; y < height; y++, gfx += incr) - for ( x = 0; x < width; x++, gfx++) - fceu_video_out[y * width + x] = *gfx; - - ps2->coreTexture->Clut = (u32*)retro_palette; - ps2->coreTexture->Mem = (u32*)fceu_video_out; + ps2->coreTexture->Mem = (u32*)gfx; video_cb(buf, width, height, pitch); #else From e962d1f19ca52c453ced2fe68e287c1c8b01d724 Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Fri, 22 Feb 2019 00:05:24 +0100 Subject: [PATCH 33/34] [PS2] Fix wrong palette in FCEUmm --- src/drivers/libretro/libretro.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index aad2752..ad31bd3 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -940,6 +940,12 @@ static void retro_set_custom_palette(void) FCEUD_SetPalette( i + 128, r, g, b); FCEUD_SetPalette( i + 192, r, g, b); } + +#if defined(RENDER_GSKIT_PS2) + if (ps2) { + ps2->updatedPalette = true; + } +#endif } /* Set variables for NTSC(1) / PAL(2) / Dendy(3) @@ -993,6 +999,10 @@ void retro_deinit (void) free(fceu_video_out); fceu_video_out = NULL; #endif +#if defined(RENDER_GSKIT_PS2) + ps2 = NULL; +#endif + } void retro_reset(void) @@ -1587,11 +1597,14 @@ static void retro_run_blit(uint8_t *gfx) ps2->coreTexture->PSM = GS_PSM_T8; ps2->coreTexture->ClutPSM = GS_PSM_CT16; ps2->coreTexture->Filter = GS_FILTER_LINEAR; - ps2->coreTexture->Clut = (u32*)retro_palette; - ps2->updatedPalette = true; - ps2->padding = (struct retro_hw_ps2_insets){8.0f, 8.0f, 8.0f, 8.0f}; + ps2->padding = (struct retro_hw_ps2_insets){ overscan_v ? 8.0f : 0.0f, + overscan_h ? 8.0f : 0.0f, + overscan_v ? 8.0f : 0.0f, + overscan_h ? 8.0f : 0.0f}; } + ps2->updatedPalette = true; + ps2->coreTexture->Clut = (u32*)retro_palette; ps2->coreTexture->Mem = (u32*)gfx; video_cb(buf, width, height, pitch); @@ -2166,6 +2179,9 @@ void retro_unload_game(void) free(fceu_video_out); fceu_video_out = NULL; #endif +#if defined(RENDER_GSKIT_PS2) + ps2 = NULL; +#endif } unsigned retro_get_region(void) From 75e837f34aa0aeefd513a4847415baa425ad5759 Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sun, 24 Feb 2019 01:51:44 +0800 Subject: [PATCH 34/34] Update libretro.c --- src/drivers/libretro/libretro.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index ad31bd3..28e1796 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -1436,7 +1436,7 @@ static void FCEUD_UpdateInput(void) { int i = 0; uint8_t input_buf = 0; - int player_enabled = (input_type[player] == RETRO_DEVICE_GAMEPAD); + int player_enabled = (input_type[player] == RETRO_DEVICE_GAMEPAD) || (input_type[player] == RETRO_DEVICE_JOYPAD); if (player_enabled) { @@ -2101,8 +2101,10 @@ bool retro_load_game(const struct retro_game_info *game) return false; } - for (i = 0; i < MAX_PORTS; i++) + for (i = 0; i < MAX_PORTS; i++) { FCEUI_SetInput(i, SI_GAMEPAD, &JSReturn, 0); + input_type[i] == RETRO_DEVICE_JOYPAD; + } external_palette_exist = ipalette; if (external_palette_exist)