diff --git a/src/main.c b/src/main.c index 1c63a559a..0704d89eb 100644 --- a/src/main.c +++ b/src/main.c @@ -1911,13 +1911,13 @@ void se_write_halfword(uint64_t address, int addr_map, uint16_t halfword){ } uint32_t se_read_word(uint64_t address, int addr_map){ if(emu_state.system ==SYSTEM_GBA)return gba_word_read(address); - if(emu_state.system ==SYSTEM_GB)return printf("se_read_word not implemented for gb\n"); + if(emu_state.system ==SYSTEM_GB)printf("se_read_word not implemented for gb\n"); if(emu_state.system ==SYSTEM_NDS)return addr_map==7? nds7_word_read(address):nds9_word_read(address); return 0; } void se_write_word(uint64_t address, int addr_map, uint32_t word){ if(emu_state.system ==SYSTEM_GBA)return gba_word_write(address,word); - if(emu_state.system ==SYSTEM_GB)return printf("se_write_word not implemented for gb\n"); + if(emu_state.system ==SYSTEM_GB)printf("se_write_word not implemented for gb\n"); if(emu_state.system ==SYSTEM_NDS)return addr_map==7? nds7_word_write(address,word):nds9_word_write(address,word); } /////////////////////////////// @@ -4813,9 +4813,29 @@ bool se_run_ar_cheat(const uint32_t* buffer, uint32_t size){ uint32_t offset_register = 0, stored_register = 0; + // stack for if statements + // the first element is always true + bool if_stack[32] = {true}; + size_t if_stack_index = 0; + + // repeat blocks can't be nested + uint32_t repeat_count = 0; + size_t repeat_block_index = 0; + size_t repeat_if_stack_index = 0; + uint8_t current_code = 0; + uint16_t current_byte = 0; + for(int i=0;i> 28; + current_byte = buffer[i] >> 24; + + // check if we're in an if that has evaluated to false, and the current instruction + // isn't an "End-if" or an "End-code" + if (!if_stack[if_stack_index] && current_byte != 0xD0 && current_byte != 0xD2) { + // skip this instruction + continue; + } switch(current_code){ case 0x0:{ @@ -4824,7 +4844,7 @@ bool se_run_ar_cheat(const uint32_t* buffer, uint32_t size){ uint32_t address = buffer[i] & 0x0fffffff; uint32_t data = buffer[i+1]; address += offset_register; - se_write_word(address,data); + se_write_word(address,0,data); break; } case 0x1:{ @@ -4833,7 +4853,7 @@ bool se_run_ar_cheat(const uint32_t* buffer, uint32_t size){ uint32_t address = buffer[i] & 0x0fffffff; uint16_t data = buffer[i+1] & 0x0000ffff; address += offset_register; - se_write_halfword(address,data); + se_write_halfword(address,0,data); break; } case 0x2:{ @@ -4842,7 +4862,116 @@ bool se_run_ar_cheat(const uint32_t* buffer, uint32_t size){ uint32_t address = buffer[i] & 0x0fffffff; uint8_t data = buffer[i+1] & 0x000000ff; address += offset_register; - se_write_byte(address,data); + se_write_byte(address,0,data); + break; + } + case 0x3:{ + // 3XXXXXXX YYYYYYYY 32bit ‘If less-than’ instruction + // If the value at (XXXXXXX or ‘offset’ when address is 0) < YYYYYYYY then + // execute the following block of instructions + uint32_t address = buffer[i] & 0x0fffffff; + uint32_t data = buffer[i+1]; + if (address == 0) address = offset_register; + uint32_t value = se_read_word(address,0); + bool condition = value < data; + if_stack_index++; + if_stack[if_stack_index] = condition; + break; + } + case 0x4:{ + // 4XXXXXXX YYYYYYYY 32bit ‘If greater-than’ instruction + // If the value at (XXXXXXX or ‘offset’ when address is 0) > YYYYYYYY then + // execute the following block of instructions + uint32_t address = buffer[i] & 0x0fffffff; + uint32_t data = buffer[i+1]; + if (address == 0) address = offset_register; + uint32_t value = se_read_word(address,0); + bool condition = value > data; + if_stack_index++; + if_stack[if_stack_index] = condition; + break; + } + case 0x5:{ + // 5XXXXXXX YYYYYYYY 32bit ‘If equal’ instruction + // If the value at (XXXXXXX or ‘offset’ when address is 0) == YYYYYYYY then + // execute the following block of instructions + uint32_t address = buffer[i] & 0x0fffffff; + uint32_t data = buffer[i+1]; + if (address == 0) address = offset_register; + uint32_t value = se_read_word(address,0); + bool condition = value == data; + if_stack_index++; + if_stack[if_stack_index] = condition; + printf("%08x %08x %d\n",value,data,condition); + break; + } + case 0x6:{ + // 6XXXXXXX YYYYYYYY 32bit ‘If not equal’ instruction + // If the value at (XXXXXXX or ‘offset’ when address is 0) != YYYYYYYY then + // execute the following block of instructions + uint32_t address = buffer[i] & 0x0fffffff; + uint32_t data = buffer[i+1]; + if (address == 0) address = offset_register; + uint32_t value = se_read_word(address,0); + bool condition = value != data; + if_stack_index++; + if_stack[if_stack_index] = condition; + break; + } + case 0x7:{ + // 7XXXXXXX ZZZZYYYY 16bit ‘If less-than’ instruction + // If the value at (XXXXXXX or ‘offset’ when address is 0) masked by ZZZZ < + // YYYY then execute the following block of instructions + uint32_t address = buffer[i] & 0x0fffffff; + uint16_t data = buffer[i+1] & 0x0000ffff; + uint16_t mask = ~(buffer[i+1] >> 16); + if (address == 0) address = offset_register; + uint16_t value = se_read_halfword(address,0); + bool condition = (value & mask) < data; + if_stack_index++; + if_stack[if_stack_index] = condition; + break; + } + case 0x8:{ + // 8XXXXXXX ZZZZYYYY 16bit ‘If greater-than’ instruction + // If the value at (XXXXXXX or ‘offset’ when address is 0) masked by ZZZZ > + // YYYY then execute the following block of instructions + uint32_t address = buffer[i] & 0x0fffffff; + uint16_t data = buffer[i+1] & 0x0000ffff; + uint16_t mask = ~(buffer[i+1] >> 16); + if (address == 0) address = offset_register; + uint16_t value = se_read_halfword(address,0); + bool condition = (value & mask) > data; + if_stack_index++; + if_stack[if_stack_index] = condition; + break; + } + case 0x9:{ + // 9XXXXXXX ZZZZYYYY 16bit ‘If equal’ instruction + // If the value at (XXXXXXX or ‘offset’ when address is 0) masked by ZZZZ == + // YYYY then execute the following block of instructions + uint32_t address = buffer[i] & 0x0fffffff; + uint16_t data = buffer[i+1] & 0x0000ffff; + uint16_t mask = ~(buffer[i+1] >> 16); + if (address == 0) address = offset_register; + uint16_t value = se_read_halfword(address,0); + bool condition = (value & mask) == data; + if_stack_index++; + if_stack[if_stack_index] = condition; + break; + } + case 0xA:{ + // AXXXXXXX ZZZZYYYY 16bit ‘If not equal’ instruction + // If the value at (XXXXXXX or ‘offset’ when address is 0) masked by ZZZZ != + // YYYY then execute the following block of instructions + uint32_t address = buffer[i] & 0x0fffffff; + uint16_t data = buffer[i+1] & 0x0000ffff; + uint16_t mask = ~(buffer[i+1] >> 16); + if (address == 0) address = offset_register; + uint16_t value = se_read_halfword(address,0); + bool condition = (value & mask) != data; + if_stack_index++; + if_stack[if_stack_index] = condition; break; } case 0xB:{ @@ -4850,10 +4979,145 @@ bool se_run_ar_cheat(const uint32_t* buffer, uint32_t size){ // Loads the offset register with the data at address (XXXXXXX + ‘offset’) uint32_t address = buffer[i] & 0x0fffffff; address += offset_register; - offset_register = se_read_word(address); + offset_register = se_read_word(address,0); + break; + } + case 0xC:{ + // C??????? NNNNNNNN + // Repeat operation, repeats a block of codes for NNNNNNNN times + // Repeats blocks cannot contain further repeats + uint32_t count = buffer[i+1]; + repeat_count = buffer[i+1]; + repeat_block_index = i; + repeat_if_stack_index = if_stack_index; + break; + } + case 0xD:{ + switch(current_byte){ + case 0xD0:{ + // End-if instruction + if_stack_index--; + break; + } + case 0xD1:{ + // End-repeat instruction + // Also implicitly ends any conditional instructions inside the repeat block + if (repeat_count > 0){ + repeat_count--; + i = repeat_block_index; + if_stack_index = repeat_if_stack_index; + } + break; + } + case 0xD2:{ + // End-code instruction + if (repeat_count > 0){ + repeat_count--; + i = repeat_block_index; + } else { + if_stack_index=0; + } + break; + } + case 0xD3:{ + // Set offset register + offset_register = buffer[i+1]; + break; + } + case 0xD4:{ + // Add to stored register + stored_register += buffer[i+1]; + break; + } + case 0xD5:{ + // Set stored register + stored_register = buffer[i+1]; + break; + } + case 0xD6:{ + // 32 bit store and increment + uint32_t address = buffer[i+1]; + address += offset_register; + se_write_word(address,0,stored_register); + offset_register += 4; + break; + } + case 0xD7:{ + // 16 bit store and increment + uint32_t address = buffer[i+1]; + address += offset_register; + se_write_halfword(address,0,stored_register); + offset_register += 2; + break; + } + case 0xD8:{ + // 8 bit store and increment + uint32_t address = buffer[i+1]; + address += offset_register; + se_write_byte(address,0,stored_register); + offset_register += 1; + break; + } + case 0xD9:{ + // 32 bit load into stored register + uint32_t address = buffer[i+1]; + address += offset_register; + stored_register = se_read_word(address,0); + break; + } + case 0xDA:{ + // 16 bit load into stored register + uint32_t address = buffer[i+1]; + address += offset_register; + stored_register = se_read_halfword(address,0); + break; + } + case 0xDB:{ + // 8 bit load into stored register + uint32_t address = buffer[i+1]; + address += offset_register; + stored_register = se_read_byte(address,0); + break; + } + default:{ + // Unknown instruction + printf("Unknown instruction: %08X %08X\n", buffer[i], buffer[i+1]); + return false; + } + } + break; + } + case 0xE:{ + // EXXXXXXX NNNNNNNN Direct memory write + // VVVVVVVV VVVVVVVV + // ... (NNNNNNNN times) + // Writes NNNNNNNN bytes from the list of values VVVVVVVV to the addresses + // starting at (XXXXXXX + ‘offset’) + uint32_t address = buffer[i] & 0x0fffffff; + address += offset_register; + uint32_t count = buffer[i+1]; + for (uint32_t j=0;j