Skip to content

Commit

Permalink
Add the rest of the AR instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
OFFTKP committed Jul 19, 2023
1 parent b0ec7c6 commit 45a38ce
Showing 1 changed file with 270 additions and 6 deletions.
276 changes: 270 additions & 6 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
///////////////////////////////
Expand Down Expand Up @@ -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<size;i+=2){
current_code = buffer[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:{
Expand All @@ -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:{
Expand All @@ -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:{
Expand All @@ -4842,18 +4862,262 @@ 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:{
// BXXXXXXX ????????
// 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<count;j+=4){
uint32_t current = buffer[i+2+j/4];
se_write_word(address+j,0,current);
}
i+=count/4;
if (i % 2 == 1) i++;
break;
}
case 0xF:{
// FXXXXXXX NNNNNNNN Memory copy
// Copies NNNNNNNN bytes from addresses starting at the ‘offset’ register to
// addresses starting at XXXXXXXX
uint32_t address = buffer[i] & 0x0fffffff;
uint32_t count = buffer[i+1];
for(uint32_t j=0; j<count; j++){
uint8_t value = se_read_byte(offset_register+j,0);
se_write_byte(address+j,0,value);
}
break;
}
}

}

return true;
Expand Down

0 comments on commit 45a38ce

Please sign in to comment.