diff --git a/mupen64plus-core/doc/emuwiki-api-doc/Mupen64Plus-Core-Parameters.mediawiki b/mupen64plus-core/doc/emuwiki-api-doc/Mupen64Plus-Core-Parameters.mediawiki
index 34e70ea..06b0b4b 100644
--- a/mupen64plus-core/doc/emuwiki-api-doc/Mupen64Plus-Core-Parameters.mediawiki
+++ b/mupen64plus-core/doc/emuwiki-api-doc/Mupen64Plus-Core-Parameters.mediawiki
@@ -59,6 +59,10 @@ These are standard parameters which are used by the Mupen64Plus Core library. T
|M64TYPE_INT
|Force number of cycles per emulated instruction when set greater than 0.
|-
+|CountPerOpDenomPot
+|M64TYPE_INT
+|Reduce number of cycles per update by power of two when set greater than 0 (overclock).
+|-
|}
These configuration parameters are used in the Core's event loop to detect keyboard and joystick commands. They are stored in a configuration section called "CoreEvents" and may be altered by the front-end in order to adjust the behaviour of the emulator. These may be adjusted at any time and the effect of the change should occur immediately. The Keysym value stored is actually (SDLMod << 16) || SDLKey, so that keypresses with modifiers like shift, control, or alt may be used.
diff --git a/mupen64plus-core/doc/emuwiki-api-doc/Mupen64Plus-v2.0-Netplay-API.mediawiki b/mupen64plus-core/doc/emuwiki-api-doc/Mupen64Plus-v2.0-Netplay-API.mediawiki
index 6f085a0..85272a9 100644
--- a/mupen64plus-core/doc/emuwiki-api-doc/Mupen64Plus-v2.0-Netplay-API.mediawiki
+++ b/mupen64plus-core/doc/emuwiki-api-doc/Mupen64Plus-v2.0-Netplay-API.mediawiki
@@ -82,13 +82,14 @@ The server is responsible for maintaining healthy buffers and also for detecting
** byte[file size] = save file data
* Send settings (sent by client):
-** 21 bytes
+** 25 bytes
** byte[0] = 3
** byte[1-4] = count_per_op
-** byte[5-8] = disable_extra_mem
-** byte[9-12] = si_dma_duration
-** byte[13-16] = emumode
-** byte[17-20] = no_compiled_jump
+** byte[5-8] = count_per_op_denom_pot
+** byte[9-12] = disable_extra_mem
+** byte[13-16] = si_dma_duration
+** byte[17-20] = emumode
+** byte[21-24] = no_compiled_jump
* Request settings (sent by client):
** 1 byte
@@ -96,12 +97,13 @@ The server is responsible for maintaining healthy buffers and also for detecting
* Send settings (sent by server):
** Server responds with this data right after the above request
-** 20 bytes
+** 24 bytes
** byte[0-3] = count_per_op
-** byte[4-7] = disable_extra_mem
-** byte[8-11] = si_dma_duration
-** byte[12-15] = emumode
-** byte[16-19] = no_compiled_jump
+** byte[4-7] = count_per_op_denom_pot
+** byte[8-11] = disable_extra_mem
+** byte[12-15] = si_dma_duration
+** byte[16-19] = emumode
+** byte[20-23] = no_compiled_jump
* Request player registration data (sent by client):
** 1 byte
diff --git a/mupen64plus-core/src/device/device.c b/mupen64plus-core/src/device/device.c
index cae2cdc..cad4381 100644
--- a/mupen64plus-core/src/device/device.c
+++ b/mupen64plus-core/src/device/device.c
@@ -83,6 +83,7 @@ void init_device(struct device* dev,
/* r4300 */
unsigned int emumode,
unsigned int count_per_op,
+ unsigned int count_per_op_denom_pot,
int no_compiled_jump,
int randomize_interrupt,
uint32_t start_address,
@@ -178,7 +179,7 @@ void init_device(struct device* dev,
init_rdram(&dev->rdram, mem_base_u32(base, MM_RDRAM_DRAM), dram_size, &dev->r4300);
init_r4300(&dev->r4300, &dev->mem, &dev->mi, &dev->rdram, interrupt_handlers,
- emumode, count_per_op, no_compiled_jump, randomize_interrupt, start_address);
+ emumode, count_per_op, count_per_op_denom_pot, no_compiled_jump, randomize_interrupt, start_address);
init_rdp(&dev->dp, &dev->sp, &dev->mi, &dev->mem, &dev->rdram, &dev->r4300);
init_rsp(&dev->sp, mem_base_u32(base, MM_RSP_MEM), &dev->mi, &dev->dp, &dev->ri);
init_ai(&dev->ai, &dev->mi, &dev->ri, &dev->vi, aout, iaout, dma_modifier);
diff --git a/mupen64plus-core/src/device/device.h b/mupen64plus-core/src/device/device.h
index de174c1..cb000a7 100644
--- a/mupen64plus-core/src/device/device.h
+++ b/mupen64plus-core/src/device/device.h
@@ -121,6 +121,7 @@ void init_device(struct device* dev,
/* r4300 */
unsigned int emumode,
unsigned int count_per_op,
+ unsigned int count_per_op_denom_pot,
int no_compiled_jump,
int randomize_interrupt,
uint32_t start_address,
diff --git a/mupen64plus-core/src/device/r4300/cp0.c b/mupen64plus-core/src/device/r4300/cp0.c
index 2241ef6..ecf4818 100644
--- a/mupen64plus-core/src/device/r4300/cp0.c
+++ b/mupen64plus-core/src/device/r4300/cp0.c
@@ -36,9 +36,10 @@
#endif
/* global functions */
-void init_cp0(struct cp0* cp0, unsigned int count_per_op, struct new_dynarec_hot_state* new_dynarec_hot_state, const struct interrupt_handler* interrupt_handlers)
+void init_cp0(struct cp0* cp0, unsigned int count_per_op, unsigned int count_per_op_denom_pot, struct new_dynarec_hot_state* new_dynarec_hot_state, const struct interrupt_handler* interrupt_handlers)
{
cp0->count_per_op = count_per_op;
+ cp0->count_per_op_denom_pot = count_per_op_denom_pot;
#ifdef NEW_DYNAREC
cp0->new_dynarec_hot_state = new_dynarec_hot_state;
#endif
@@ -134,6 +135,10 @@ void cp0_update_count(struct r4300_core* r4300)
{
#endif
uint32_t count = ((*r4300_pc(r4300) - cp0->last_addr) >> 2) * cp0->count_per_op;
+ if (r4300->cp0.count_per_op_denom_pot) {
+ count += (1 << r4300->cp0.count_per_op_denom_pot) - 1;
+ count >>= r4300->cp0.count_per_op_denom_pot;
+ }
cp0_regs[CP0_COUNT_REG] += count;
*r4300_cp0_cycle_count(cp0) += count;
cp0->last_addr = *r4300_pc(r4300);
diff --git a/mupen64plus-core/src/device/r4300/cp0.h b/mupen64plus-core/src/device/r4300/cp0.h
index beab717..78aa4c4 100644
--- a/mupen64plus-core/src/device/r4300/cp0.h
+++ b/mupen64plus-core/src/device/r4300/cp0.h
@@ -201,6 +201,7 @@ struct cp0
uint32_t last_addr;
unsigned int count_per_op;
+ unsigned int count_per_op_denom_pot;
struct tlb tlb;
};
@@ -215,7 +216,7 @@ struct cp0
offsetof(struct new_dynarec_hot_state, cp0_regs))
#endif
-void init_cp0(struct cp0* cp0, unsigned int count_per_op, struct new_dynarec_hot_state* new_dynarec_hot_state, const struct interrupt_handler* interrupt_handlers);
+void init_cp0(struct cp0* cp0, unsigned int count_per_op, unsigned int count_per_op_denom_pot, struct new_dynarec_hot_state* new_dynarec_hot_state, const struct interrupt_handler* interrupt_handlers);
void poweron_cp0(struct cp0* cp0);
uint32_t* r4300_cp0_regs(struct cp0* cp0);
diff --git a/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c b/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c
index 17b2707..b371631 100644
--- a/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c
+++ b/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c
@@ -4485,6 +4485,10 @@ static void do_cc(int i,signed char i_regmap[],int *adj,int addr,int taken,int i
emit_jmp(0);
}
else if(*adj==0||invert) {
+ if(g_dev.r4300.cp0.count_per_op_denom_pot) {
+ count += (1 << g_dev.r4300.cp0.count_per_op_denom_pot) - 1;
+ count >>= g_dev.r4300.cp0.count_per_op_denom_pot;
+ }
emit_addimm_and_set_flags(CLOCK_DIVIDER*(count+2),HOST_CCREG);
jaddr=(intptr_t)out;
emit_jns(0);
diff --git a/mupen64plus-core/src/device/r4300/r4300_core.c b/mupen64plus-core/src/device/r4300/r4300_core.c
index dee5156..e87a3d8 100644
--- a/mupen64plus-core/src/device/r4300/r4300_core.c
+++ b/mupen64plus-core/src/device/r4300/r4300_core.c
@@ -41,7 +41,7 @@
#include
void init_r4300(struct r4300_core* r4300, struct memory* mem, struct mi_controller* mi, struct rdram* rdram, const struct interrupt_handler* interrupt_handlers,
- unsigned int emumode, unsigned int count_per_op, int no_compiled_jump, int randomize_interrupt, uint32_t start_address)
+ unsigned int emumode, unsigned int count_per_op, unsigned int count_per_op_denom_pot, int no_compiled_jump, int randomize_interrupt, uint32_t start_address)
{
struct new_dynarec_hot_state* new_dynarec_hot_state =
#ifdef NEW_DYNAREC
@@ -51,7 +51,7 @@ void init_r4300(struct r4300_core* r4300, struct memory* mem, struct mi_controll
#endif
r4300->emumode = emumode;
- init_cp0(&r4300->cp0, count_per_op, new_dynarec_hot_state, interrupt_handlers);
+ init_cp0(&r4300->cp0, count_per_op, count_per_op_denom_pot, new_dynarec_hot_state, interrupt_handlers);
init_cp1(&r4300->cp1, new_dynarec_hot_state);
#ifndef NEW_DYNAREC
diff --git a/mupen64plus-core/src/device/r4300/r4300_core.h b/mupen64plus-core/src/device/r4300/r4300_core.h
index d79100e..335b10e 100644
--- a/mupen64plus-core/src/device/r4300/r4300_core.h
+++ b/mupen64plus-core/src/device/r4300/r4300_core.h
@@ -211,7 +211,7 @@ struct r4300_core
offsetof(struct new_dynarec_hot_state, regs))
#endif
-void init_r4300(struct r4300_core* r4300, struct memory* mem, struct mi_controller* mi, struct rdram* rdram, const struct interrupt_handler* interrupt_handlers, unsigned int emumode, unsigned int count_per_op, int no_compiled_jump, int randomize_interrupt, uint32_t start_address);
+void init_r4300(struct r4300_core* r4300, struct memory* mem, struct mi_controller* mi, struct rdram* rdram, const struct interrupt_handler* interrupt_handlers, unsigned int emumode, unsigned int count_per_op, unsigned int count_per_op_denom_pot, int no_compiled_jump, int randomize_interrupt, uint32_t start_address);
void poweron_r4300(struct r4300_core* r4300);
void run_r4300(struct r4300_core* r4300);
diff --git a/mupen64plus-core/src/device/r4300/x86/dynarec.c b/mupen64plus-core/src/device/r4300/x86/dynarec.c
index d14f763..8ab4ad8 100644
--- a/mupen64plus-core/src/device/r4300/x86/dynarec.c
+++ b/mupen64plus-core/src/device/r4300/x86/dynarec.c
@@ -128,6 +128,11 @@ static void gencp0_update_count(struct r4300_core* r4300, unsigned int addr)
shr_reg32_imm8(EAX, 2);
mov_reg32_m32(EDX, &r4300->cp0.count_per_op);
mul_reg32(EDX);
+ if (r4300->cp0.count_per_op_denom_pot)
+ {
+ add_reg32_imm32(EAX, (1 << g_dev.r4300.cp0.count_per_op_denom_pot) - 1);
+ shr_reg32_imm8(EAX, g_dev.r4300.cp0.count_per_op_denom_pot);
+ }
add_m32_reg32((unsigned int*)(&r4300_cp0_regs(&r4300->cp0)[CP0_COUNT_REG]), EAX);
add_m32_reg32((unsigned int*)r4300_cp0_cycle_count(&r4300->cp0), EAX);
#else
diff --git a/mupen64plus-core/src/device/r4300/x86_64/dynarec.c b/mupen64plus-core/src/device/r4300/x86_64/dynarec.c
index 1d445d9..751032d 100644
--- a/mupen64plus-core/src/device/r4300/x86_64/dynarec.c
+++ b/mupen64plus-core/src/device/r4300/x86_64/dynarec.c
@@ -139,6 +139,11 @@ static void gencp0_update_count(struct r4300_core* r4300, unsigned int addr)
shr_reg32_imm8(EAX, 2);
mov_xreg32_m32rel(EDX, (void*)&r4300->cp0.count_per_op);
mul_reg32(EDX);
+ if (r4300->cp0.count_per_op_denom_pot)
+ {
+ add_reg32_imm32(EAX, (1 << g_dev.r4300.cp0.count_per_op_denom_pot) - 1);
+ shr_reg32_imm8(EAX, g_dev.r4300.cp0.count_per_op_denom_pot);
+ }
add_m32rel_xreg32((unsigned int*)(&r4300_cp0_regs(&r4300->cp0)[CP0_COUNT_REG]), EAX);
add_m32rel_xreg32((unsigned int*)(r4300_cp0_cycle_count(&r4300->cp0)), EAX);
#else
diff --git a/mupen64plus-core/src/main/main.c b/mupen64plus-core/src/main/main.c
index 6b091d8..0cf4f11 100644
--- a/mupen64plus-core/src/main/main.c
+++ b/mupen64plus-core/src/main/main.c
@@ -345,6 +345,7 @@ int main_set_core_defaults(void)
ConfigSetDefaultBool(g_CoreConfig, "NoCompiledJump", 0, "Disable compiled jump commands in dynamic recompiler (should be set to False) ");
ConfigSetDefaultBool(g_CoreConfig, "DisableExtraMem", 0, "Disable 4MB expansion RAM pack. May be necessary for some games");
ConfigSetDefaultInt(g_CoreConfig, "CountPerOp", 0, "Force number of cycles per emulated instruction");
+ ConfigSetDefaultInt(g_CoreConfig, "CountPerOpDenomPot", 0, "Reduce number of cycles per update by power of two when set greater than 0 (overclock)");
ConfigSetDefaultBool(g_CoreConfig, "AutoStateSlotIncrement", 0, "Increment the save state slot after each save operation");
ConfigSetDefaultInt(g_CoreConfig, "CurrentStateSlot", 0, "Save state slot (0-9) to use when saving/loading the emulator state");
ConfigSetDefaultBool(g_CoreConfig, "EnableDebugger", 0, "Activate the R4300 debugger when ROM execution begins, if core was built with Debugger support");
@@ -1436,6 +1437,7 @@ m64p_error main_run(void)
size_t i, k;
size_t rdram_size;
uint32_t count_per_op;
+ uint32_t count_per_op_denom_pot;
uint32_t emumode;
uint32_t disable_extra_mem;
int32_t si_dma_duration;
@@ -1479,6 +1481,7 @@ m64p_error main_run(void)
//We disable any randomness for netplay
randomize_interrupt = !netplay_is_init() ? ConfigGetParamBool(g_CoreConfig, "RandomizeInterrupt") : 0;
count_per_op = ConfigGetParamInt(g_CoreConfig, "CountPerOp");
+ count_per_op_denom_pot = ConfigGetParamInt(g_CoreConfig, "CountPerOpDenomPot");
if (ROM_SETTINGS.disableextramem)
disable_extra_mem = ROM_SETTINGS.disableextramem;
@@ -1491,12 +1494,15 @@ m64p_error main_run(void)
if (count_per_op <= 0)
count_per_op = ROM_SETTINGS.countperop;
+ if (count_per_op_denom_pot > 11)
+ count_per_op_denom_pot = 11;
+
si_dma_duration = ConfigGetParamInt(g_CoreConfig, "SiDmaDuration");
if (si_dma_duration < 0)
si_dma_duration = ROM_SETTINGS.sidmaduration;
//During netplay, player 1 is the source of truth for these settings
- netplay_sync_settings(&count_per_op, &disable_extra_mem, &si_dma_duration, &emumode, &no_compiled_jump);
+ netplay_sync_settings(&count_per_op, &count_per_op_denom_pot, &disable_extra_mem, &si_dma_duration, &emumode, &no_compiled_jump);
cheat_add_hacks(&g_cheat_ctx, ROM_PARAMS.cheats);
@@ -1734,6 +1740,7 @@ m64p_error main_run(void)
g_mem_base,
emumode,
count_per_op,
+ count_per_op_denom_pot,
no_compiled_jump,
randomize_interrupt,
g_start_address,
diff --git a/mupen64plus-core/src/main/netplay.c b/mupen64plus-core/src/main/netplay.c
index e5143e1..7a853b5 100644
--- a/mupen64plus-core/src/main/netplay.c
+++ b/mupen64plus-core/src/main/netplay.c
@@ -498,23 +498,24 @@ file_status_t netplay_read_storage(const char *filename, void *data, size_t size
return ret;
}
-void netplay_sync_settings(uint32_t *count_per_op, uint32_t *disable_extra_mem, int32_t *si_dma_duration, uint32_t *emumode, int32_t *no_compiled_jump)
+void netplay_sync_settings(uint32_t *count_per_op, uint32_t *count_per_op_denom_pot, uint32_t *disable_extra_mem, int32_t *si_dma_duration, uint32_t *emumode, int32_t *no_compiled_jump)
{
if (!netplay_is_init())
return;
- char output_data[21];
+ char output_data[25];
uint8_t request;
if (l_netplay_control[0] != -1) //player 1 is the source of truth for settings
{
request = TCP_SEND_SETTINGS;
memcpy(&output_data[0], &request, 1);
SDLNet_Write32(*count_per_op, &output_data[1]);
- SDLNet_Write32(*disable_extra_mem, &output_data[5]);
- SDLNet_Write32(*si_dma_duration, &output_data[9]);
- SDLNet_Write32(*emumode, &output_data[13]);
- SDLNet_Write32(*no_compiled_jump, &output_data[17]);
- SDLNet_TCP_Send(l_tcpSocket, &output_data[0], 21);
+ SDLNet_Write32(*count_per_op_denom_pot, &output_data[5]);
+ SDLNet_Write32(*disable_extra_mem, &output_data[9]);
+ SDLNet_Write32(*si_dma_duration, &output_data[13]);
+ SDLNet_Write32(*emumode, &output_data[17]);
+ SDLNet_Write32(*no_compiled_jump, &output_data[21]);
+ SDLNet_TCP_Send(l_tcpSocket, &output_data[0], 25);
}
else
{
@@ -522,13 +523,14 @@ void netplay_sync_settings(uint32_t *count_per_op, uint32_t *disable_extra_mem,
memcpy(&output_data[0], &request, 1);
SDLNet_TCP_Send(l_tcpSocket, &output_data[0], 1);
int32_t recv = 0;
- while (recv < 20)
- recv += SDLNet_TCP_Recv(l_tcpSocket, &output_data[recv], 20 - recv);
+ while (recv < 24)
+ recv += SDLNet_TCP_Recv(l_tcpSocket, &output_data[recv], 24 - recv);
*count_per_op = SDLNet_Read32(&output_data[0]);
- *disable_extra_mem = SDLNet_Read32(&output_data[4]);
- *si_dma_duration = SDLNet_Read32(&output_data[8]);
- *emumode = SDLNet_Read32(&output_data[12]);
- *no_compiled_jump = SDLNet_Read32(&output_data[16]);
+ *count_per_op_denom_pot = SDLNet_Read32(&output_data[4]);
+ *disable_extra_mem = SDLNet_Read32(&output_data[8]);
+ *si_dma_duration = SDLNet_Read32(&output_data[12]);
+ *emumode = SDLNet_Read32(&output_data[16]);
+ *no_compiled_jump = SDLNet_Read32(&output_data[20]);
}
}
diff --git a/mupen64plus-core/src/main/netplay.h b/mupen64plus-core/src/main/netplay.h
index ed83cc1..a5b8f31 100644
--- a/mupen64plus-core/src/main/netplay.h
+++ b/mupen64plus-core/src/main/netplay.h
@@ -47,7 +47,7 @@ void netplay_set_controller(uint8_t player);
int netplay_is_init();
int netplay_get_controller(uint8_t player);
file_status_t netplay_read_storage(const char *filename, void *data, size_t size);
-void netplay_sync_settings(uint32_t *count_per_op, uint32_t *disable_extra_mem, int32_t *si_dma_duration, uint32_t *emumode, int32_t *no_compiled_jump);
+void netplay_sync_settings(uint32_t *count_per_op, uint32_t *count_per_op_denom_pot, uint32_t *disable_extra_mem, int32_t *si_dma_duration, uint32_t *emumode, int32_t *no_compiled_jump);
void netplay_check_sync(struct cp0* cp0);
int netplay_next_controller();
void netplay_read_registration(struct controller_input_compat* cin_compats);
@@ -97,7 +97,7 @@ static osal_inline file_status_t netplay_read_storage(const char *filename, void
return 0;
}
-static osal_inline void netplay_sync_settings(uint32_t *count_per_op, uint32_t *disable_extra_mem, int32_t *si_dma_duration, uint32_t *emumode, int32_t *no_compiled_jump)
+static osal_inline void netplay_sync_settings(uint32_t *count_per_op, uint32_t *count_per_op_denom_pot, uint32_t *disable_extra_mem, int32_t *si_dma_duration, uint32_t *emumode, int32_t *no_compiled_jump)
{
}
diff --git a/mupen64plus-core/src/main/version.h b/mupen64plus-core/src/main/version.h
index a08b49e..c047866 100644
--- a/mupen64plus-core/src/main/version.h
+++ b/mupen64plus-core/src/main/version.h
@@ -31,7 +31,7 @@
#define CONFIG_API_VERSION 0x020302
#define DEBUG_API_VERSION 0x020001
#define VIDEXT_API_VERSION 0x030200
-#define NETPLAY_API_VERSION 0x010000
+#define NETPLAY_API_VERSION 0x010001
#define VERSION_PRINTF_SPLIT(x) (((x) >> 16) & 0xffff), (((x) >> 8) & 0xff), ((x) & 0xff)