|
@@ -21,6 +21,127 @@ KernelDataInstaller::KernelDataInstaller(std::string path): kernel_(path){}
|
|
|
|
|
|
|
|
KernelDataInstaller::~KernelDataInstaller(){}
|
|
KernelDataInstaller::~KernelDataInstaller(){}
|
|
|
|
|
|
|
|
|
|
+int KernelDataInstaller::ReadCommands(){
|
|
|
|
|
+
|
|
|
|
|
+ // Empty the item list
|
|
|
|
|
+ commands_.clear();
|
|
|
|
|
+
|
|
|
|
|
+ File command_file = kernel_.ExtractGZip(KERNEL_COMMAND_DATA);
|
|
|
|
|
+ File command_name_file = kernel_.ExtractGZip(KERNEL_COMMAND_NAMES);
|
|
|
|
|
+ File command_desc_file = kernel_.ExtractGZip(KERNEL_COMMAND_DESCRIPTIONS);
|
|
|
|
|
+ int name_offset = 0;
|
|
|
|
|
+ int desc_offset = 0;
|
|
|
|
|
+ int command_count = 0;
|
|
|
|
|
+
|
|
|
|
|
+ std::cout << "| ID | cur | c_s | c_m| tar |\n";
|
|
|
|
|
+
|
|
|
|
|
+ // There are exactly 32 commands. Some of them are blank, so there is not really a
|
|
|
|
|
+ // reliable exit condition.
|
|
|
|
|
+ for (int i = 0; i < 32; i ++){
|
|
|
|
|
+
|
|
|
|
|
+ CommandData data;
|
|
|
|
|
+
|
|
|
|
|
+ // From the current name file offset, read 16 bytes.
|
|
|
|
|
+ // This is the pointer to the offset for the item name.
|
|
|
|
|
+ // Start reading there until 0xFF is found.
|
|
|
|
|
+ data.name = "";
|
|
|
|
|
+ u8 ch = 1;
|
|
|
|
|
+ name_offset = command_name_file.readU16LE();
|
|
|
|
|
+ while (ch != 0xFF){
|
|
|
|
|
+ ch = command_name_file.GetU8(name_offset);
|
|
|
|
|
+ if (ch != 0xFF) data.name += ENGLISH_CHARS[ch];
|
|
|
|
|
+ name_offset ++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // For descriptions, do the same as for names.
|
|
|
|
|
+ data.description = "";
|
|
|
|
|
+ ch = 1;
|
|
|
|
|
+ desc_offset = command_desc_file.readU16LE();
|
|
|
|
|
+ while (ch != 0xFF){
|
|
|
|
|
+ ch = command_desc_file.GetU8(desc_offset);
|
|
|
|
|
+ if (ch != 0xFF){
|
|
|
|
|
+ // Warning: If the char is 0xF9, special function!
|
|
|
|
|
+ // the next byte (in bits, aaoooooo) means to read aa data at offset oooooo.
|
|
|
|
|
+ // This is to compress information in the kernel.
|
|
|
|
|
+ if (ch == 0xF9){
|
|
|
|
|
+ // Get how much to read, two upper bits of the next byte.
|
|
|
|
|
+ // Multiply by 2 and add 4. That's just how it is.
|
|
|
|
|
+ u8 comp_size = (command_desc_file.GetU8(desc_offset + 1) >> 6) * 2 + 4;
|
|
|
|
|
+ // Get new offset, lower six bits of the next byte.
|
|
|
|
|
+ // The offset goes backwards from the position of the 0xF9 byte.
|
|
|
|
|
+ u8 comp_offset = command_desc_file.GetU8(desc_offset + 1) & 63;
|
|
|
|
|
+
|
|
|
|
|
+ for (int i = 0; i < comp_size; i ++){
|
|
|
|
|
+ data.description += ENGLISH_CHARS[
|
|
|
|
|
+ command_desc_file.GetU8(desc_offset - 1 - comp_offset + i)
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+ desc_offset ++;
|
|
|
|
|
+ }
|
|
|
|
|
+ else data.description += ENGLISH_CHARS[ch];
|
|
|
|
|
+ }
|
|
|
|
|
+ desc_offset ++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Read data from the item data section.
|
|
|
|
|
+ data.cursor_action = command_file.readU8();
|
|
|
|
|
+ data.target_raw = command_file.readU8();
|
|
|
|
|
+ data.camera_single = command_file.readU16LE();
|
|
|
|
|
+ data.camera_multiple = command_file.readU16LE();
|
|
|
|
|
+
|
|
|
|
|
+ // Derive data from the read data.
|
|
|
|
|
+ data.id = i;
|
|
|
|
|
+ if (data.target_raw == (data.target_raw | 0x01)) data.target.selection_enabled = true;
|
|
|
|
|
+ else data.target.selection_enabled = false;
|
|
|
|
|
+ if (data.target_raw == (data.target_raw | 0x02)) data.target.default_enemy = true;
|
|
|
|
|
+ else data.target.default_enemy = false;
|
|
|
|
|
+ if (data.target_raw == (data.target_raw | 0x04)) data.target.default_multiple = true;
|
|
|
|
|
+ else data.target.default_multiple = false;
|
|
|
|
|
+ if (data.target_raw == (data.target_raw | 0x08)) data.target.toggle_multiple = true;
|
|
|
|
|
+ else data.target.toggle_multiple = false;
|
|
|
|
|
+ if (data.target_raw == (data.target_raw | 0x10)) data.target.fixed_row = true;
|
|
|
|
|
+ else data.target.fixed_row = false;
|
|
|
|
|
+ if (data.target_raw == (data.target_raw | 0x20)) data.target.short_range = true;
|
|
|
|
|
+ else data.target.short_range = false;
|
|
|
|
|
+ if (data.target_raw == (data.target_raw | 0x40)) data.target.default_enemy = true;
|
|
|
|
|
+ else data.target.all_rows = false;
|
|
|
|
|
+ if (data.target_raw == (data.target_raw | 0x80)) data.target.random = true;
|
|
|
|
|
+ else data.target.random = false;
|
|
|
|
|
+
|
|
|
|
|
+ // Add to the list of items.
|
|
|
|
|
+ if (data.name != ""){
|
|
|
|
|
+ commands_.push_back(data);
|
|
|
|
|
+ command_count ++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ printf(
|
|
|
|
|
+ "| %3d | %3d | %3d | %3d | ",
|
|
|
|
|
+ i, data.camera_single, data.camera_multiple, data.target_raw
|
|
|
|
|
+ );
|
|
|
|
|
+ std::cout << data.name << ": " << data.description << std::endl;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return command_count;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void KernelDataInstaller::WriteCommands(std::string file){
|
|
|
|
|
+ TiXmlDocument xml;
|
|
|
|
|
+ std::unique_ptr<TiXmlElement> container(new TiXmlElement("commands"));
|
|
|
|
|
+ for (CommandData command : commands_){
|
|
|
|
|
+ std::unique_ptr<TiXmlElement> xml_command(new TiXmlElement("item"));
|
|
|
|
|
+ xml_command->SetAttribute("id", command.id);
|
|
|
|
|
+ xml_command->SetAttribute("name", command.name);
|
|
|
|
|
+ xml_command->SetAttribute("description", command.description);
|
|
|
|
|
+ xml_command->SetAttribute("camera_1", command.camera_single);
|
|
|
|
|
+ xml_command->SetAttribute("camera_x", command.camera_single);
|
|
|
|
|
+ container->LinkEndChild(xml_command.release());
|
|
|
|
|
+ }
|
|
|
|
|
+ xml.LinkEndChild(container.release());
|
|
|
|
|
+ xml.SaveFile(file);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
int KernelDataInstaller::ReadItems(){
|
|
int KernelDataInstaller::ReadItems(){
|
|
|
|
|
|
|
|
// Empty the item list
|
|
// Empty the item list
|
|
@@ -77,9 +198,7 @@ int KernelDataInstaller::ReadItems(){
|
|
|
}
|
|
}
|
|
|
desc_offset ++;
|
|
desc_offset ++;
|
|
|
}
|
|
}
|
|
|
- else{
|
|
|
|
|
- data.description += ENGLISH_CHARS[ch];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ else data.description += ENGLISH_CHARS[ch];
|
|
|
}
|
|
}
|
|
|
desc_offset ++;
|
|
desc_offset ++;
|
|
|
}
|
|
}
|
|
@@ -111,6 +230,7 @@ int KernelDataInstaller::ReadItems(){
|
|
|
data.useable_battle = !(data.restrict_raw & (2 << 0));
|
|
data.useable_battle = !(data.restrict_raw & (2 << 0));
|
|
|
data.useable_menu = !(data.restrict_raw & (4 << 0));
|
|
data.useable_menu = !(data.restrict_raw & (4 << 0));
|
|
|
// TODO: XOR, not individual bits
|
|
// TODO: XOR, not individual bits
|
|
|
|
|
+ /*
|
|
|
data.target.selection_enabled = data.target_raw & (0 << 0); // First bit...
|
|
data.target.selection_enabled = data.target_raw & (0 << 0); // First bit...
|
|
|
data.target.default_enemy = data.target_raw & (1 << 0);
|
|
data.target.default_enemy = data.target_raw & (1 << 0);
|
|
|
data.target.default_multiple = data.target_raw & (2 << 0);
|
|
data.target.default_multiple = data.target_raw & (2 << 0);
|
|
@@ -119,19 +239,45 @@ int KernelDataInstaller::ReadItems(){
|
|
|
data.target.short_range = data.target_raw & (5 << 0);
|
|
data.target.short_range = data.target_raw & (5 << 0);
|
|
|
data.target.all_rows = data.target_raw & (6 << 0);
|
|
data.target.all_rows = data.target_raw & (6 << 0);
|
|
|
data.target.random = data.target_raw & (7 << 0); // ... last bit.
|
|
data.target.random = data.target_raw & (7 << 0); // ... last bit.
|
|
|
|
|
+ */
|
|
|
|
|
+ if (data.target_raw == (data.target_raw | 0x01)) data.target.selection_enabled = true;
|
|
|
|
|
+ else data.target.selection_enabled = false;
|
|
|
|
|
+ if (data.target_raw == (data.target_raw | 0x02)) data.target.default_enemy = true;
|
|
|
|
|
+ else data.target.default_enemy = false;
|
|
|
|
|
+ if (data.target_raw == (data.target_raw | 0x04)) data.target.default_multiple = true;
|
|
|
|
|
+ else data.target.default_multiple = false;
|
|
|
|
|
+ if (data.target_raw == (data.target_raw | 0x08)) data.target.toggle_multiple = true;
|
|
|
|
|
+ else data.target.toggle_multiple = false;
|
|
|
|
|
+ if (data.target_raw == (data.target_raw | 0x10)) data.target.fixed_row = true;
|
|
|
|
|
+ else data.target.fixed_row = false;
|
|
|
|
|
+ if (data.target_raw == (data.target_raw | 0x20)) data.target.short_range = true;
|
|
|
|
|
+ else data.target.short_range = false;
|
|
|
|
|
+ if (data.target_raw == (data.target_raw | 0x40)) data.target.default_enemy = true;
|
|
|
|
|
+ else data.target.all_rows = false;
|
|
|
|
|
+ if (data.target_raw == (data.target_raw | 0x80)) data.target.random = true;
|
|
|
|
|
+ else data.target.random = false;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
data.damage_formula = data.damage_raw >> 4; // Upper nybble.
|
|
data.damage_formula = data.damage_raw >> 4; // Upper nybble.
|
|
|
data.damage_modifier = data.damage_raw & 15; // Lower nybble.
|
|
data.damage_modifier = data.damage_raw & 15; // Lower nybble.
|
|
|
- data.condition.party_hp = data.condition_raw & (0 << 0); //First bit...
|
|
|
|
|
- data.condition.party_mp = data.condition_raw & (1 << 0);
|
|
|
|
|
- data.condition.party_status = data.condition_raw & (2 << 0); // ... last bit.
|
|
|
|
|
|
|
+ /*data.condition.party_hp = data.condition_raw & (0 << 0); //First bit...
|
|
|
|
|
+ data.condition.mp = data.condition_raw & (1 << 0);
|
|
|
|
|
+ data.condition.party_status = data.condition_raw & (2 << 0); // ... last bit.*/
|
|
|
|
|
|
|
|
- data.status.chance = 64 - (data.status_change_raw ^ 63); // Out of 63;
|
|
|
|
|
|
|
+ data.status.chance = 63 - (data.status_change_raw ^ 63); // Out of 63;
|
|
|
if (data.status_change_raw == (data.status_change_raw | 0x00000080))
|
|
if (data.status_change_raw == (data.status_change_raw | 0x00000080))
|
|
|
data.status.mode = TOGGLE;
|
|
data.status.mode = TOGGLE;
|
|
|
else if (data.status_change_raw == (data.status_change_raw | 0x00000040))
|
|
else if (data.status_change_raw == (data.status_change_raw | 0x00000040))
|
|
|
data.status.mode = CURE;
|
|
data.status.mode = CURE;
|
|
|
else data.status.mode = INFLICT;
|
|
else data.status.mode = INFLICT;
|
|
|
|
|
|
|
|
|
|
+ switch (data.condition_raw){
|
|
|
|
|
+ case 0: data.restore_type = RESTORE_HP; break;
|
|
|
|
|
+ case 1: data.restore_type = RESTORE_MP; break;
|
|
|
|
|
+ case 2: data.restore_type = RESTORE_STATUS; break;
|
|
|
|
|
+ default: data.restore_type = RESTORE_NONE;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
|
|
|
// In KERNEL.BIN, items that don't induce statuses actually have all statuses marked, and
|
|
// In KERNEL.BIN, items that don't induce statuses actually have all statuses marked, and
|
|
|
// a chance of 255. If it's the case, skip statuses altogether.
|
|
// a chance of 255. If it's the case, skip statuses altogether.
|
|
@@ -260,7 +406,16 @@ void KernelDataInstaller::WriteItems(std::string file){
|
|
|
xml_item->SetAttribute("dmg_formula", item.damage_formula);
|
|
xml_item->SetAttribute("dmg_formula", item.damage_formula);
|
|
|
xml_item->SetAttribute("dmg_modifier", item.damage_modifier);
|
|
xml_item->SetAttribute("dmg_modifier", item.damage_modifier);
|
|
|
xml_item->SetAttribute("power", item.power);
|
|
xml_item->SetAttribute("power", item.power);
|
|
|
- //if (item.status.status.size() > 0 && item.status.chance <= 64){
|
|
|
|
|
|
|
+ xml_item->SetAttribute("restore", item.restore_type);
|
|
|
|
|
+ xml_item->SetAttribute("target_select", item.target.selection_enabled);
|
|
|
|
|
+ xml_item->SetAttribute("target_default_enemy", item.target.default_enemy);
|
|
|
|
|
+ xml_item->SetAttribute("target_default_multiple", item.target.default_multiple);
|
|
|
|
|
+ xml_item->SetAttribute("target_toggle_multiple", item.target.toggle_multiple);
|
|
|
|
|
+ xml_item->SetAttribute("target_fixed", item.target.fixed_row);
|
|
|
|
|
+ xml_item->SetAttribute("target_short_range", item.target.short_range);
|
|
|
|
|
+ xml_item->SetAttribute("target_all", item.target.all_rows);
|
|
|
|
|
+ xml_item->SetAttribute("target_random", item.target.random);
|
|
|
|
|
+ // Statuses.
|
|
|
if (item.status.status.size() > 0){
|
|
if (item.status.status.size() > 0){
|
|
|
std::unique_ptr<TiXmlElement> xml_status(new TiXmlElement("statuses"));
|
|
std::unique_ptr<TiXmlElement> xml_status(new TiXmlElement("statuses"));
|
|
|
xml_status->SetAttribute("mode", item.status.mode);
|
|
xml_status->SetAttribute("mode", item.status.mode);
|
|
@@ -273,8 +428,6 @@ void KernelDataInstaller::WriteItems(std::string file){
|
|
|
xml_item->LinkEndChild(xml_status.release());
|
|
xml_item->LinkEndChild(xml_status.release());
|
|
|
}
|
|
}
|
|
|
// Add elements.
|
|
// Add elements.
|
|
|
- // In KERNEL.BIN, Non elemental item actually have all elements marked. Don't print them.
|
|
|
|
|
- //if (item.elements.size() > 0 && item.elements.size() < 16){
|
|
|
|
|
if (item.elements.size() > 0){
|
|
if (item.elements.size() > 0){
|
|
|
std::unique_ptr<TiXmlElement> xml_elements(new TiXmlElement("elements"));
|
|
std::unique_ptr<TiXmlElement> xml_elements(new TiXmlElement("elements"));
|
|
|
for (int s : item.elements){
|
|
for (int s : item.elements){
|