diff --git a/src/main.c b/src/main.c index 8c0663441..51e4d6216 100644 --- a/src/main.c +++ b/src/main.c @@ -4878,328 +4878,9 @@ static void event(const sapp_event* ev) { } } bool se_run_ar_cheat(const uint32_t* buffer, uint32_t size){ - if(!buffer){ - printf("Invalid Action Replay cheat buffer\n"); - return false; - } - if(size%2!=0){ - printf("Invalid Action Replay cheat size:%d\n",size); - return false; - } - - 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; - - emu_byte_read_t byte_read = se_read_byte_func(0); - emu_byte_write_t byte_write = se_write_byte_func(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:{ - // 0XXXXXXX YYYYYYYY - // 32bit write of YYYYYYYY to location: (xxxxxxx + ‘offset’) - uint32_t address = buffer[i] & 0x0fffffff; - uint32_t data = buffer[i+1]; - address += offset_register; - se_write32(byte_write,address,data); - break; - } - case 0x1:{ - // 1XXXXXXX ????YYYY - // 16bit write of YYYY to location: (xxxxxxx + ‘offset’) - uint32_t address = buffer[i] & 0x0fffffff; - uint16_t data = buffer[i+1] & 0x0000ffff; - address += offset_register; - se_write16(byte_write,address,data); - break; - } - case 0x2:{ - // 2XXXXXXX ??????YY - // 8bit write of YY to location: (xxxxxxx + ‘offset’) - uint32_t address = buffer[i] & 0x0fffffff; - uint8_t data = buffer[i+1] & 0x000000ff; - address += offset_register; - byte_write(address,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_read32(byte_read,address); - 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_read32(byte_read,address); - 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_read32(byte_read,address); - 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_read32(byte_read,address); - 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_read16(byte_read,address); - 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_read16(byte_read,address); - 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_read16(byte_read,address); - 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_read16(byte_read, address); - bool condition = (value & mask) != data; - if_stack_index++; - if_stack[if_stack_index] = condition; - break; - } - case 0xB:{ - // BXXXXXXX ???????? - // Loads the offset register with the data at address (XXXXXXX + ‘offset’) - uint32_t address = buffer[i] & 0x0fffffff; - address += offset_register; - offset_register = se_read32(byte_read, address); - 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_write32(byte_write,address,stored_register); - offset_register += 4; - break; - } - case 0xD7:{ - // 16 bit store and increment - uint32_t address = buffer[i+1]; - address += offset_register; - se_write16(byte_write,address,stored_register); - offset_register += 2; - break; - } - case 0xD8:{ - // 8 bit store and increment - uint32_t address = buffer[i+1]; - address += offset_register; - byte_write(address,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_read32(byte_read,address); - break; - } - case 0xDA:{ - // 16 bit load into stored register - uint32_t address = buffer[i+1]; - address += offset_register; - stored_register = se_read16(byte_read,address); - break; - } - case 0xDB:{ - // 8 bit load into stored register - uint32_t address = buffer[i+1]; - address += offset_register; - stored_register = byte_read(address); - 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> 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:{ + // 0XXXXXXX YYYYYYYY + // 32bit write of YYYYYYYY to location: (xxxxxxx + ‘offset’) + uint32_t address = buffer[i] & 0x0fffffff; + uint32_t data = buffer[i+1]; + address += offset_register; + nds9_debug_write32(nds,address,data); + break; + } + case 0x1:{ + // 1XXXXXXX ????YYYY + // 16bit write of YYYY to location: (xxxxxxx + ‘offset’) + uint32_t address = buffer[i] & 0x0fffffff; + uint16_t data = buffer[i+1] & 0x0000ffff; + address += offset_register; + nds9_debug_write16(nds,address,data); + break; + } + case 0x2:{ + // 2XXXXXXX ??????YY + // 8bit write of YY to location: (xxxxxxx + ‘offset’) + uint32_t address = buffer[i] & 0x0fffffff; + uint8_t data = buffer[i+1] & 0x000000ff; + address += offset_register; + nds9_debug_write8(nds,address,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 = nds9_debug_read32(nds,address); + 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 = nds9_debug_read32(nds,address); + 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 = nds9_debug_read32(nds,address); + 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 = nds9_debug_read32(nds,address); + 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 = nds9_debug_read16(nds,address); + 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 = nds9_debug_read16(nds,address); + 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 = nds9_debug_read16(nds,address); + 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 = nds9_debug_read16(nds,address); + bool condition = (value & mask) != data; + if_stack_index++; + if_stack[if_stack_index] = condition; + break; + } + case 0xB:{ + // BXXXXXXX ???????? + // Loads the offset register with the data at address (XXXXXXX + ‘offset’) + uint32_t address = buffer[i] & 0x0fffffff; + address += offset_register; + offset_register = nds9_debug_read32(nds,address); + 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; + nds9_debug_write32(nds,address,stored_register); + offset_register += 4; + break; + } + case 0xD7:{ + // 16 bit store and increment + uint32_t address = buffer[i+1]; + address += offset_register; + nds9_debug_write16(nds,address,stored_register); + offset_register += 2; + break; + } + case 0xD8:{ + // 8 bit store and increment + uint32_t address = buffer[i+1]; + address += offset_register; + nds9_debug_write8(nds,address,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 = nds9_debug_read32(nds,address); + break; + } + case 0xDA:{ + // 16 bit load into stored register + uint32_t address = buffer[i+1]; + address += offset_register; + stored_register = nds9_debug_read16(nds,address); + break; + } + case 0xDB:{ + // 8 bit load into stored register + uint32_t address = buffer[i+1]; + address += offset_register; + stored_register = nds9_debug_read8(nds,address); + 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