Просмотр исходного кода

The whole bombing mission is now playable without editing the original data!

- Bit operations implemented in Lua scripts.
- Fixed opcodes BITON, BITOFF, GOLDU, GOLDD, CHGLD, CKITM.
- Music doesn't reset on map change.
- 15th data bank is now saved too.
- Deleted original music from the repo.
Iñigo Valentin 3 лет назад
Родитель
Сommit
026c97614a
28 измененных файлов с 153 добавлено и 36 удалено
  1. 1 1
      CMakeLists.txt
  2. 4 1
      README.md
  3. 25 7
      V-Gears-Installer/src/FieldDataInstaller.cpp
  4. 2 2
      V-Gears-Installer/src/decompiler/field/FieldDisassembler.cpp
  5. 1 0
      V-Gears-Installer/src/decompiler/field/instruction/FieldBackgroundInstruction.cpp
  6. 1 0
      V-Gears-Installer/src/decompiler/field/instruction/FieldCameraInstruction.cpp
  7. 2 2
      V-Gears-Installer/src/decompiler/field/instruction/FieldCondJumpInstruction.cpp
  8. 3 2
      V-Gears-Installer/src/decompiler/field/instruction/FieldMathInstruction.cpp
  9. 1 0
      V-Gears-Installer/src/decompiler/field/instruction/FieldMediaInstruction.cpp
  10. 1 0
      V-Gears-Installer/src/decompiler/field/instruction/FieldModelInstruction.cpp
  11. 1 0
      V-Gears-Installer/src/decompiler/field/instruction/FieldModuleInstruction.cpp
  12. 3 2
      V-Gears-Installer/src/decompiler/field/instruction/FieldPartyInstruction.cpp
  13. 1 0
      V-Gears-Installer/src/decompiler/field/instruction/FieldWalkmeshInstruction.cpp
  14. 1 3
      V-Gears-Installer/src/decompiler/field/instruction/FieldWindowInstruction.cpp
  15. 3 3
      V-Gears/include/Version.h
  16. 5 0
      V-Gears/include/core/AudioManager.h
  17. 2 2
      V-Gears/include/core/Savemap.h
  18. 8 0
      V-Gears/src/core/AudioManager.cpp
  19. BIN
      data/data/musics/ffvii_main_theme.mp3
  20. BIN
      data/data/musics/ffvii_main_theme.ogg
  21. BIN
      data/data/musics/loop1.ogg
  22. BIN
      data/data/musics/loop2.ogg
  23. BIN
      data/data/musics/loop3.ogg
  24. 1 1
      data/data/screens/main_menu/prototypes.xml
  25. 9 4
      data/data/scripts/data.lua
  26. 2 0
      data/data/scripts/menu/name_menu.lua
  27. 4 4
      data/data/scripts/save.lua
  28. 72 2
      data/data/scripts/system.lua

+ 1 - 1
CMakeLists.txt

@@ -14,7 +14,7 @@ project(V-Gears)
 set(CMAKE_PACKAGE_ICON v-gears.png)
 set(CMAKE_PACKAGE_ICON v-gears.png)
 set(VGears_VERSION__MAJOR 0)
 set(VGears_VERSION__MAJOR 0)
 set(VGears_VERSION__MINOR 1)
 set(VGears_VERSION__MINOR 1)
-set(VGears_VERSION__PATCH 0)
+set(VGears_VERSION__PATCH 1)
 set(VGears_VERSION ${VGears_VERSION__MAJOR}.${VGears_VERSION__MINOR}.${VGears_VERSION__PATCH})
 set(VGears_VERSION ${VGears_VERSION__MAJOR}.${VGears_VERSION__MINOR}.${VGears_VERSION__PATCH})
 
 
 # Generate version header.
 # Generate version header.

+ 4 - 1
README.md

@@ -59,7 +59,10 @@ Well, let's call it a work in progress... of a work in progress.
 
 
 
 
 If the question was "How deep into the game can I play?", then the answer is
 If the question was "How deep into the game can I play?", then the answer is
-> You can ALMOST play the whole Mako Reactor 1 mission. But dumbass Biggs won't show up to open the way out, so you die on fire. Or you would, if the bomb timer actually worked.
+
+[<img src="https://v-gears.inigovalentin.com/img/screenshot/max_progress.png" alt="Max progress" width="450"/>](https://v-gears.inigovalentin.com/img/screenshot/max_progress.png "Max progress")
+
+Until there. Whitout cheats, and without using the developer console, the game hangs there.
 
 
 But don't worry! The engine is not fixed sequentially, or map by map. Once a fix is implememnted, it applies to all maps at once, anb big chunck of the game are unlocked after each fix.
 But don't worry! The engine is not fixed sequentially, or map by map. Once a fix is implememnted, it applies to all maps at once, anb big chunck of the game are unlocked after each fix.
 
 

+ 25 - 7
V-Gears-Installer/src/FieldDataInstaller.cpp

@@ -104,21 +104,39 @@ bool FieldDataInstaller::IsTestField(const Ogre::String& resource_name){
       || resource_name == "md1stin"
       || resource_name == "md1stin"
       || resource_name == "md1_1"
       || resource_name == "md1_1"
       || resource_name == "md1_2"
       || resource_name == "md1_2"
-      || resource_name == "md8_1"
+      || resource_name == "nrthmk"
       || resource_name == "nmkin_1"
       || resource_name == "nmkin_1"
+      || resource_name == "elevtr1"
       || resource_name == "nmkin_2"
       || resource_name == "nmkin_2"
       || resource_name == "nmkin_3"
       || resource_name == "nmkin_3"
       || resource_name == "nmkin_4"
       || resource_name == "nmkin_4"
       || resource_name == "nmkin_5"
       || resource_name == "nmkin_5"
-      || resource_name == "nrthmk"
-      || resource_name == "elevtr1"
+      || resource_name == "southmk1"
+      || resource_name == "southmk2"
+      || resource_name == "smkin_1"
+      || resource_name == "smkin_2"
+      || resource_name == "smkin_3"
+      || resource_name == "smkin_4"
+      || resource_name == "smkin_5"
+      || resource_name == "md8_1"
+      || resource_name == "md8_2"
+      || resource_name == "md8_3"
+      || resource_name == "md8_4"
+      || resource_name == "md8brdg"
+      || resource_name == "cargoin"
       || resource_name == "tin_1"
       || resource_name == "tin_1"
       || resource_name == "tin_2"
       || resource_name == "tin_2"
+      || resource_name == "tin_3"
+      || resource_name == "tin_4"
       || resource_name == "rootmap"
       || resource_name == "rootmap"
-      || resource_name == "md8_1"
-      //|| resource_name == "md8_2"
-      //|| resource_name == "md8_3"
-      //|| resource_name == "md8_4"
+      || resource_name == "mds7st1"
+      || resource_name == "mds7st2"
+      || resource_name == "mds7st3"
+      || resource_name == "mds7st32"
+      || resource_name == "mds7_w1"
+      || resource_name == "mds7_w2"
+      || resource_name == "mds7_w3"
+      || resource_name == "mds7"
     ){return true;}
     ){return true;}
     return false;
     return false;
 }
 }

+ 2 - 2
V-Gears-Installer/src/decompiler/field/FieldDisassembler.cpp

@@ -684,10 +684,10 @@ bool FieldDisassembler::ReadOpCodesToPositionOrReturn(
             case OPCODES::GOLDU:
             case OPCODES::GOLDU:
                 // Goldu can have two argument formats: (nybble, word) or (nybble, byte, 3 bytes)
                 // Goldu can have two argument formats: (nybble, word) or (nybble, byte, 3 bytes)
                 // Read it as nybble, byte, byte, byte, byte and operate later
                 // Read it as nybble, byte, byte, byte, byte and operate later
-                ParseOpcode(full_opcode, "GOLDU", new FieldPartyInstruction(), 0, "BBBBB");
+                ParseOpcode(full_opcode, "GOLDU", new FieldPartyInstruction(), 0, "NBBBB");
                 break;
                 break;
             case OPCODES::GOLDD:
             case OPCODES::GOLDD:
-                ParseOpcode(full_opcode, "GOLDD", new FieldPartyInstruction(), 0, "Nww");
+                ParseOpcode(full_opcode, "GOLDD", new FieldPartyInstruction(), 0, "NBBBB");
                 break;
                 break;
             case OPCODES::CHGLD:
             case OPCODES::CHGLD:
                 ParseOpcode(full_opcode, "CHGLD", new FieldPartyInstruction(), 0, "NBB");
                 ParseOpcode(full_opcode, "CHGLD", new FieldPartyInstruction(), 0, "NBB");

+ 1 - 0
V-Gears-Installer/src/decompiler/field/instruction/FieldBackgroundInstruction.cpp

@@ -28,6 +28,7 @@ void FieldBackgroundInstruction::ProcessInst(
   Function& func, ValueStack&, Engine* engine, CodeGenerator *code_gen
   Function& func, ValueStack&, Engine* engine, CodeGenerator *code_gen
 ){
 ){
     FunctionMetaData md(func.metadata);
     FunctionMetaData md(func.metadata);
+    //std::cout << "Background opcode: " << opcode_ << "\n";
     switch (opcode_){
     switch (opcode_){
         case OPCODES::BGPDH: code_gen->WriteTodo(md.GetEntityName(), "BGPDH");break;
         case OPCODES::BGPDH: code_gen->WriteTodo(md.GetEntityName(), "BGPDH");break;
         case OPCODES::BGSCR: code_gen->WriteTodo(md.GetEntityName(), "BGSCR"); break;
         case OPCODES::BGSCR: code_gen->WriteTodo(md.GetEntityName(), "BGSCR"); break;

+ 1 - 0
V-Gears-Installer/src/decompiler/field/instruction/FieldCameraInstruction.cpp

@@ -28,6 +28,7 @@ void FieldCameraInstruction::ProcessInst(
   Function& func, ValueStack&, Engine* engine, CodeGenerator *code_gen
   Function& func, ValueStack&, Engine* engine, CodeGenerator *code_gen
 ){
 ){
     FunctionMetaData md(func.metadata);
     FunctionMetaData md(func.metadata);
+    //std::cout << "Camera opcode: " << opcode_ << "\n";
     switch (opcode_){
     switch (opcode_){
     case OPCODES::NFADE: ProcessNFADE(code_gen); break;
     case OPCODES::NFADE: ProcessNFADE(code_gen); break;
     case OPCODES::SHAKE: code_gen->WriteTodo(md.GetEntityName(), "SHAKE"); break;
     case OPCODES::SHAKE: code_gen->WriteTodo(md.GetEntityName(), "SHAKE"); break;

+ 2 - 2
V-Gears-Installer/src/decompiler/field/instruction/FieldCondJumpInstruction.cpp

@@ -74,7 +74,7 @@ void FieldCondJumpInstruction::ProcessInst(
         case 8: op = "|"; break;
         case 8: op = "|"; break;
         case 9:
         case 9:
             {
             {
-                op = "bit(" + params_[0]->GetString() + ", " + params_[2]->GetString()
+                op = "get_bank_bit(" + params_[0]->GetString() + ", " + params_[2]->GetString()
                   + ", " + destination + ") == 1";
                   + ", " + destination + ") == 1";
                 ValuePtr v = new UnquotedStringValue(op);
                 ValuePtr v = new UnquotedStringValue(op);
                 stack.Push(v);
                 stack.Push(v);
@@ -82,7 +82,7 @@ void FieldCondJumpInstruction::ProcessInst(
             return;
             return;
         case 0xA:
         case 0xA:
             {
             {
-                op = "bit(" + params_[0]->GetString() + ", " + params_[2]->GetString()
+                op = "get_bank_bit(" + params_[0]->GetString() + ", " + params_[2]->GetString()
                   + ", " + destination + ") == 0";
                   + ", " + destination + ") == 0";
                 ValuePtr v = new UnquotedStringValue(op);
                 ValuePtr v = new UnquotedStringValue(op);
                 stack.Push(v);
                 stack.Push(v);

+ 3 - 2
V-Gears-Installer/src/decompiler/field/instruction/FieldMathInstruction.cpp

@@ -29,6 +29,7 @@ void FieldMathInstruction::ProcessInst(
 ){
 ){
     FieldCodeGenerator* cg = static_cast<FieldCodeGenerator*>(code_gen);
     FieldCodeGenerator* cg = static_cast<FieldCodeGenerator*>(code_gen);
     FunctionMetaData md(func.metadata);
     FunctionMetaData md(func.metadata);
+    //std::cout << "Math opcode: " << opcode_ << "\n";
     switch (opcode_){
     switch (opcode_){
         case OPCODES::PLUS_: ProcessSaturatedPLUS(code_gen); break;
         case OPCODES::PLUS_: ProcessSaturatedPLUS(code_gen); break;
         case OPCODES::PLUS2_: ProcessSaturatedPLUS2(code_gen); break;
         case OPCODES::PLUS2_: ProcessSaturatedPLUS2(code_gen); break;
@@ -223,13 +224,13 @@ void FieldMathInstruction::ProcessSETBYTE_SETWORD(CodeGenerator* code_gen){
 }
 }
 
 
 void FieldMathInstruction::ProcessBITON(CodeGenerator* code_gen){
 void FieldMathInstruction::ProcessBITON(CodeGenerator* code_gen){
-    code_gen->AddOutputLine((boost::format("bit_on(%1%, %2%, %3%)")
+    code_gen->AddOutputLine((boost::format("set_bank_bit(%1%, %2%, %3%, 1)")
       % params_[0]->GetUnsigned() % params_[2]->GetUnsigned() % params_[3]->GetUnsigned()
       % params_[0]->GetUnsigned() % params_[2]->GetUnsigned() % params_[3]->GetUnsigned()
     ).str());
     ).str());
 }
 }
 
 
 void FieldMathInstruction::ProcessBITOFF(CodeGenerator* code_gen){
 void FieldMathInstruction::ProcessBITOFF(CodeGenerator* code_gen){
-    code_gen->AddOutputLine((boost::format("bit_off(%1%, %2%, %3%)")
+    code_gen->AddOutputLine((boost::format("set_bank_bit(%1%, %2%, %3%, 0)")
       % params_[0]->GetUnsigned() % params_[2]->GetUnsigned() % params_[3]->GetUnsigned()
       % params_[0]->GetUnsigned() % params_[2]->GetUnsigned() % params_[3]->GetUnsigned()
     ).str());
     ).str());
 }
 }

+ 1 - 0
V-Gears-Installer/src/decompiler/field/instruction/FieldMediaInstruction.cpp

@@ -28,6 +28,7 @@ void FieldMediaInstruction::ProcessInst(
   Function& func, ValueStack&, Engine* engine, CodeGenerator *code_gen
   Function& func, ValueStack&, Engine* engine, CodeGenerator *code_gen
 ){
 ){
     FunctionMetaData md(func.metadata);
     FunctionMetaData md(func.metadata);
+    //std::cout << "Media opcode: " << opcode_ << "\n";
     switch (opcode_){
     switch (opcode_){
         case OPCODES::BGMOVIE: code_gen->WriteTodo(md.GetEntityName(), "BGMOVIE"); break;
         case OPCODES::BGMOVIE: code_gen->WriteTodo(md.GetEntityName(), "BGMOVIE"); break;
         case OPCODES::AKAO2: ProcessAKAO(code_gen); break;
         case OPCODES::AKAO2: ProcessAKAO(code_gen); break;

+ 1 - 0
V-Gears-Installer/src/decompiler/field/instruction/FieldModelInstruction.cpp

@@ -29,6 +29,7 @@ void FieldModelInstruction::ProcessInst(
 ){
 ){
     FieldEngine& eng = static_cast<FieldEngine&>(*engine);
     FieldEngine& eng = static_cast<FieldEngine&>(*engine);
     FunctionMetaData md(func.metadata);
     FunctionMetaData md(func.metadata);
+    //std::cout << "Model opcode: " << opcode_ << "\n";
     switch (opcode_){
     switch (opcode_){
         case OPCODES::JOIN: ProcessJOIN(code_gen); break;
         case OPCODES::JOIN: ProcessJOIN(code_gen); break;
         case OPCODES::SPLIT: ProcessSPLIT(code_gen); break;
         case OPCODES::SPLIT: ProcessSPLIT(code_gen); break;

+ 1 - 0
V-Gears-Installer/src/decompiler/field/instruction/FieldModuleInstruction.cpp

@@ -28,6 +28,7 @@ void FieldModuleInstruction::ProcessInst(
   Function& func, ValueStack&, Engine* engine, CodeGenerator *code_gen
   Function& func, ValueStack&, Engine* engine, CodeGenerator *code_gen
 ){
 ){
     FunctionMetaData md(func.metadata);
     FunctionMetaData md(func.metadata);
+    //std::cout << "Module opcode: " << opcode_ << "\n";
     switch (opcode_){
     switch (opcode_){
         case OPCODES::DSKCG: code_gen->WriteTodo(md.GetEntityName(), "DSKCG"); break;
         case OPCODES::DSKCG: code_gen->WriteTodo(md.GetEntityName(), "DSKCG"); break;
         case (OPCODES::SPECIAL << 8) | OPCODES_SPECIAL::ARROW:
         case (OPCODES::SPECIAL << 8) | OPCODES_SPECIAL::ARROW:

+ 3 - 2
V-Gears-Installer/src/decompiler/field/instruction/FieldPartyInstruction.cpp

@@ -28,6 +28,7 @@ void FieldPartyInstruction::ProcessInst(
   Function& func, ValueStack&, Engine* engine, CodeGenerator *code_gen
   Function& func, ValueStack&, Engine* engine, CodeGenerator *code_gen
 ){
 ){
     FunctionMetaData md(func.metadata);
     FunctionMetaData md(func.metadata);
+    //std::cout << "Party opcode: " << opcode_ << "\n";
     switch (opcode_){
     switch (opcode_){
         case OPCODES::SPTYE: code_gen->WriteTodo(md.GetEntityName(), "SPTYE"); break;
         case OPCODES::SPTYE: code_gen->WriteTodo(md.GetEntityName(), "SPTYE"); break;
         case OPCODES::GTPYE: code_gen->WriteTodo(md.GetEntityName(), "GTPYE"); break;
         case OPCODES::GTPYE: code_gen->WriteTodo(md.GetEntityName(), "GTPYE"); break;
@@ -124,7 +125,7 @@ void FieldPartyInstruction::ProcessDLITM(CodeGenerator* code_gen){
 
 
 void FieldPartyInstruction::ProcessCKITM(CodeGenerator* code_gen){
 void FieldPartyInstruction::ProcessCKITM(CodeGenerator* code_gen){
     code_gen->AddOutputLine((
     code_gen->AddOutputLine((
-      boost::format("Banks[%1][%2] = Inventory.get_item_quantity(%3%)")
+      boost::format("Banks[%1%][%2%] = Inventory.get_item_quantity(%3%)")
       % params_[0]->GetUnsigned() % params_[2]->GetUnsigned() % params_[1]->GetUnsigned()
       % params_[0]->GetUnsigned() % params_[2]->GetUnsigned() % params_[1]->GetUnsigned()
     ).str());
     ).str());
 }
 }
@@ -142,7 +143,7 @@ void FieldPartyInstruction::ProcessPRTYE(CodeGenerator* code_gen){
 
 
 void FieldPartyInstruction::ProcessCHGLD(CodeGenerator* code_gen){
 void FieldPartyInstruction::ProcessCHGLD(CodeGenerator* code_gen){
     code_gen->AddOutputLine((
     code_gen->AddOutputLine((
-      boost::format("Inventory.money_to_banks(%1%, %2%, %3, %4)")
+      boost::format("Inventory.money_to_banks(%1%, %2%, %3%, %4%)")
         % params_[0]->GetUnsigned() % params_[1]->GetUnsigned()
         % params_[0]->GetUnsigned() % params_[1]->GetUnsigned()
         % params_[2]->GetUnsigned() % params_[3]->GetUnsigned()
         % params_[2]->GetUnsigned() % params_[3]->GetUnsigned()
     ).str());
     ).str());

+ 1 - 0
V-Gears-Installer/src/decompiler/field/instruction/FieldWalkmeshInstruction.cpp

@@ -28,6 +28,7 @@ void FieldWalkmeshInstruction::ProcessInst(
   Function& func, ValueStack&, Engine* engine, CodeGenerator *code_gen
   Function& func, ValueStack&, Engine* engine, CodeGenerator *code_gen
 ){
 ){
     FunctionMetaData md(func.metadata);
     FunctionMetaData md(func.metadata);
+    //std::cout << "WMesh opcode: " << opcode_ << "\n";
     switch (opcode_){
     switch (opcode_){
         case OPCODES::SLIP: code_gen->WriteTodo(md.GetEntityName(), "SLIP"); break;
         case OPCODES::SLIP: code_gen->WriteTodo(md.GetEntityName(), "SLIP"); break;
         case OPCODES::UC: ProcessUC(code_gen); break;
         case OPCODES::UC: ProcessUC(code_gen); break;

+ 1 - 3
V-Gears-Installer/src/decompiler/field/instruction/FieldWindowInstruction.cpp

@@ -29,6 +29,7 @@ void FieldWindowInstruction::ProcessInst(
 ){
 ){
     FieldEngine& eng = static_cast<FieldEngine&>(*engine);
     FieldEngine& eng = static_cast<FieldEngine&>(*engine);
     FunctionMetaData md(func.metadata);
     FunctionMetaData md(func.metadata);
+    //std::cout << "Window opcode: " << opcode_ << "\n";
     switch (opcode_){
     switch (opcode_){
         case OPCODES::TUTOR: code_gen->WriteTodo(md.GetEntityName(), "TUTOR"); break;
         case OPCODES::TUTOR: code_gen->WriteTodo(md.GetEntityName(), "TUTOR"); break;
         case OPCODES::WCLS: code_gen->WriteTodo(md.GetEntityName(), "WCLS"); break;
         case OPCODES::WCLS: code_gen->WriteTodo(md.GetEntityName(), "WCLS"); break;
@@ -161,9 +162,6 @@ void FieldWindowInstruction::ProcessMENU(CodeGenerator* code_gen){
 }
 }
 
 
 void FieldWindowInstruction::ProcessSTTIM(CodeGenerator* code_gen){
 void FieldWindowInstruction::ProcessSTTIM(CodeGenerator* code_gen){
-    std::cout << "STTIM params:\n";
-    for (int i = 0; i < params_.size(); i ++) std::cout << "    " << params_[i] << "\n";
-    std::cout << "STTIM params END\n";
     FieldCodeGenerator* cg = static_cast<FieldCodeGenerator*>(code_gen);
     FieldCodeGenerator* cg = static_cast<FieldCodeGenerator*>(code_gen);
     int h = std::stoi(FieldCodeGenerator::FormatValueOrVariable(
     int h = std::stoi(FieldCodeGenerator::FormatValueOrVariable(
       cg->GetFormatter(), params_[0]->GetUnsigned(), params_[4]->GetSigned(),
       cg->GetFormatter(), params_[0]->GetUnsigned(), params_[4]->GetSigned(),

+ 3 - 3
V-Gears/include/Version.h

@@ -22,8 +22,8 @@
 /**
 /**
  * Application version.
  * Application version.
  */
  */
-#define VGEARS_VERSION "0.1.0"
+#define VGEARS_VERSION "0.1.1"
 #define VGEARS_VERSION_MAJOR "0"
 #define VGEARS_VERSION_MAJOR "0"
 #define VGEARS_VERSION_MINOR "1"
 #define VGEARS_VERSION_MINOR "1"
-#define VGEARS_VERSION_PATCH "0"
-#define VGEARS_VERSION_SIGNATURE "V-Gears v0.1.0"
+#define VGEARS_VERSION_PATCH "1"
+#define VGEARS_VERSION_SIGNATURE "V-Gears v0.1.1"

+ 5 - 0
V-Gears/include/core/AudioManager.h

@@ -295,6 +295,11 @@ class AudioManager : public Ogre::Singleton<AudioManager>{
                  */
                  */
                 float loop_;
                 float loop_;
 
 
+                /**
+                 * Name of the file currently being played.
+                 */
+                Ogre::String file_;
+
                 /**
                 /**
                  * File played or to play.
                  * File played or to play.
                  */
                  */

+ 2 - 2
V-Gears/include/core/Savemap.h

@@ -931,12 +931,12 @@ class Savemap{
         /**
         /**
          * Number of data banks.
          * Number of data banks.
          */
          */
-        static const unsigned int BANK_COUNT = 15;
+        static const unsigned int BANK_COUNT = 16;
 
 
         /**
         /**
          * Number of addresses in each data bank.
          * Number of addresses in each data bank.
          */
          */
-        static const unsigned int BANK_ADDRESS_COUNT = 254;
+        static const unsigned int BANK_ADDRESS_COUNT = 256;
 
 
         /**
         /**
          * MAx colour component value.
          * MAx colour component value.

+ 8 - 0
V-Gears/src/core/AudioManager.cpp

@@ -231,11 +231,18 @@ void AudioManager::Player::Pause(){
 
 
 void AudioManager::Player::Play(const Ogre::String &file){
 void AudioManager::Player::Play(const Ogre::String &file){
     boost::recursive_mutex::scoped_lock lock(*update_mutex_);
     boost::recursive_mutex::scoped_lock lock(*update_mutex_);
+
+
+    // If the same track is already playing, don't restart.
+
+    if (file_ == file) return;
+
     // Open vorbis file.
     // Open vorbis file.
     if (ov_fopen(const_cast<char*>(file.c_str()), &vorbis_file_)){
     if (ov_fopen(const_cast<char*>(file.c_str()), &vorbis_file_)){
         LOG_ERROR("Can't play file \"" + file + "\".");
         LOG_ERROR("Can't play file \"" + file + "\".");
         return;
         return;
     }
     }
+    file_ = file;
     // Get file info.
     // Get file info.
     vorbis_info_ = ov_info(&vorbis_file_, -1.0f);
     vorbis_info_ = ov_info(&vorbis_file_, -1.0f);
     // Create sound source
     // Create sound source
@@ -284,6 +291,7 @@ void AudioManager::Player::Stop(){
     // Cleanup
     // Cleanup
     ov_clear(&vorbis_file_);
     ov_clear(&vorbis_file_);
     stream_finished_ = false;
     stream_finished_ = false;
+    file_ = "";
 }
 }
 
 
 void AudioManager::Player::SetLoop(const float loop){
 void AudioManager::Player::SetLoop(const float loop){

BIN
data/data/musics/ffvii_main_theme.mp3


BIN
data/data/musics/ffvii_main_theme.ogg


BIN
data/data/musics/loop1.ogg


BIN
data/data/musics/loop2.ogg


BIN
data/data/musics/loop3.ogg


+ 1 - 1
data/data/screens/main_menu/prototypes.xml

@@ -2,7 +2,7 @@
     <prototype name="MenuCharacterData">
     <prototype name="MenuCharacterData">
         <text_area name="Name" x="0" y="0" font="FFVIIFont" visible="true" />
         <text_area name="Name" x="0" y="0" font="FFVIIFont" visible="true" />
         <text_area name="Lv" x="0" y="5" text_name="CharacterDataLv" colour="0 0.9 0.9" font="FFVIIMenuFont" visible="true" />
         <text_area name="Lv" x="0" y="5" text_name="CharacterDataLv" colour="0 0.9 0.9" font="FFVIIMenuFont" visible="true" />
-        <text_area name="LvNumber" x="18" y="13" font="FFVIITimerFont" visible="true" />
+        <text_area name="LvNumber" x="18" y="13" font="FFVIIMenuDigits" visible="true" />
         <text_area name="Hp" x="0" y="16" text_name="CharacterDataHp" colour="0 0.9 0.9" font="FFVIIMenuFont" visible="true" />
         <text_area name="Hp" x="0" y="16" text_name="CharacterDataHp" colour="0 0.9 0.9" font="FFVIIMenuFont" visible="true" />
         <text_area name="HpCurrent" x="16" y="23" colour="0.9 0.9 0.9" font="FFVIIMenuDigits" visible="true" />
         <text_area name="HpCurrent" x="16" y="23" colour="0.9 0.9 0.9" font="FFVIIMenuDigits" visible="true" />
         <sprite name="HpSlash" image="images/icons/slash.png" x="51" y="23" width="4" height="8" visible="true" />
         <sprite name="HpSlash" image="images/icons/slash.png" x="51" y="23" width="4" height="8" visible="true" />

+ 9 - 4
data/data/scripts/data.lua

@@ -233,6 +233,7 @@ MenuSettings = {
 
 
 --- Current party.
 --- Current party.
 Party = {
 Party = {
+    MAX = 3,
     [1] = nil,
     [1] = nil,
     [2] = nil,
     [2] = nil,
     [3] = nil
     [3] = nil
@@ -244,9 +245,11 @@ Party = {
 -- 15 banks (indexes 0-14) with 255 addresses (indexes 0-254) each. Memory banks 4, 5, 7, 8 and 9
 -- 15 banks (indexes 0-14) with 255 addresses (indexes 0-254) each. Memory banks 4, 5, 7, 8 and 9
 -- are temporary and are not saved to the savemap.
 -- are temporary and are not saved to the savemap.
 Banks = {}
 Banks = {}
-for i = 0, 14 do
+Banks.COUNT = 15
+Banks.SIZE = 255
+for i = 0, Banks.COUNT do
     Banks[i] = {}
     Banks[i] = {}
-    for j = 0, 254 do
+    for j = 0, Banks.SIZE do
         Banks[i][j] = 0
         Banks[i][j] = 0
     end
     end
 end
 end
@@ -256,9 +259,11 @@ end
 --
 --
 -- @todo Delete this, and implement bit operations over Banks.
 -- @todo Delete this, and implement bit operations over Banks.
 BitBanks = {}
 BitBanks = {}
-for i = 0, 15 do
+BitBanks.COUNT = 15
+BitBanks.SIZE = 255
+for i = 0, BitBanks.COUNT do
     BitBanks[i] = {}
     BitBanks[i] = {}
-    for j = 0, 255 do
+    for j = 0, BitBanks.SIZE do
         BitBanks[i][j] = {}
         BitBanks[i][j] = {}
         for k = 0, 8 do
         for k = 0, 8 do
             BitBanks[i][j][k] = 0
             BitBanks[i][j][k] = 0

+ 2 - 0
data/data/scripts/menu/name_menu.lua

@@ -174,6 +174,8 @@ UiContainer.NameMenu = {
         UiContainer.current_submenu = ""
         UiContainer.current_submenu = ""
         self.options_position = 1
         self.options_position = 1
         self.confirm_position = 1
         self.confirm_position = 1
+        ui_manager:get_widget("NameMenu.Container.Confirm.Cursor"):set_default_animation("Position" .. self.confirm_position)
+        ui_manager:get_widget("NameMenu.Container.Options.Cursor"):set_default_animation("Position" .. self.options_position)
         ui_manager:get_widget("NameMenu.Container.Character.Portrait"):set_image("images/characters/" .. tostring(self.id) .. ".png")
         ui_manager:get_widget("NameMenu.Container.Character.Portrait"):set_image("images/characters/" .. tostring(self.id) .. ".png")
         if (string.lower(Characters[self.id].name) == "ex-soldier") then
         if (string.lower(Characters[self.id].name) == "ex-soldier") then
             -- HACK: Hack for Ex-Soldier default. Can this be extracted from menu.lgp?
             -- HACK: Hack for Ex-Soldier default. Can this be extracted from menu.lgp?

+ 4 - 4
data/data/scripts/save.lua

@@ -88,8 +88,8 @@ save_game = function(slot, force)
             -- TODO: Character statuses
             -- TODO: Character statuses
         end
         end
     end
     end
-    for b = 0, 14 do
-        for a = 0, 254 do
+    for b = 0, Banks.COUNT do
+        for a = 0, Banks.SIZE do
             if (Banks[b] ~= nil and Banks[b][a] ~= nil and Banks[b][a] ~= 0) then
             if (Banks[b] ~= nil and Banks[b][a] ~= nil and Banks[b][a] ~= 0) then
                 savemap_manager:set_data(b, a, tonumber(Banks[b][a]))
                 savemap_manager:set_data(b, a, tonumber(Banks[b][a]))
             end
             end
@@ -104,8 +104,8 @@ end
 -- @param slot The slot to load (0-15).
 -- @param slot The slot to load (0-15).
 load_game = function(slot)
 load_game = function(slot)
     -- Populate banks
     -- Populate banks
-    for b = 0, 14 do
-        for a = 0, 254 do
+    for b = 0, Banks.COUNT do
+        for a = 0, Banks.SIZE do
             Banks[b][a] = savemap_manager:get_slot_data(slot, b, a)
             Banks[b][a] = savemap_manager:get_slot_data(slot, b, a)
         end
         end
     end
     end

+ 72 - 2
data/data/scripts/system.lua

@@ -774,11 +774,33 @@ end
 -- @param bit The bit to get (0-7)
 -- @param bit The bit to get (0-7)
 -- @return The bit value (1-0)
 -- @return The bit value (1-0)
 function get_bank_bit(bank, address, bit)
 function get_bank_bit(bank, address, bit)
-    -- TODO: Validation
+    if bank < 0 or bank > Banks.COUNT or address < 0 or address > Banks.SIZE or bit < 0 or bit > 7 then
+        print("ERROR: Tried to check invalid bit " .. tostring(bit) .. " from bank " .. tostring(bank) .. " at address " .. tostring(address) .. ".")
+        return 0
+    end
     local val = Banks[bank][address]
     local val = Banks[bank][address]
     return get_byte_nth_bit(val, bit)
     return get_byte_nth_bit(val, bit)
 end
 end
 
 
+--- Sets a bit in an address in a data bank
+--
+-- @param bank The bank (0-14)
+-- @param address The bank address (0-254)
+-- @param bit The bit to set (0-7)
+-- @param value The bit value (1-0)
+function set_bank_bit(bank, address, bit, value)
+    if bank < 0 or bank > Banks.COUNT or address < 0 or address > Banks.SIZE or bit < 0 or bit > 7 then
+        print("ERROR: Tried to set invalid bit " .. tostring(bit) .. " from bank " .. tostring(bank) .. " at address " .. tostring(address) .. ".")
+        return
+    end
+    if value ~= 1 and value ~= 0  then
+        print("ERROR: Tried to set bit to invalid value " .. tostring(value) .. " from bank " .. tostring(bank) .. " at address " .. tostring(address) .. ".")
+        return
+    end
+    local val = Banks[bank][address]
+    Banks[bank][address] =  set_byte_nth_bit(val, bit, value)
+end
+
 --- Obtains a bit from an unsigned byte
 --- Obtains a bit from an unsigned byte
 --
 --
 -- @param value The value (0-254)
 -- @param value The value (0-254)
@@ -786,6 +808,15 @@ end
 -- @return The bit value (1-0)
 -- @return The bit value (1-0)
 function get_byte_nth_bit(value, n)
 function get_byte_nth_bit(value, n)
     if n < 0 or n > 7 then
     if n < 0 or n > 7 then
+        print("ERROR: Tried to get invalid bit " .. tostring(bit) .. " from value " .. tostring(value) .. ".")
+        return 0
+    end
+    if value < 0 then
+        print("ERROR: Tried to get bit " .. tostring(bit) .. " from negative value " .. tostring(value) .. ".")
+        return 0
+    end
+    if value > 254 then
+        print("ERROR: Tried to get bit " .. tostring(bit) .. " from value " .. tostring(value) .. " that exceeds byte size.")
         return 0
         return 0
     end
     end
     -- Convert to binary string
     -- Convert to binary string
@@ -795,6 +826,45 @@ function get_byte_nth_bit(value, n)
         s = s .. tostring(temp % 2)
         s = s .. tostring(temp % 2)
         temp = math.floor(temp / 2)
         temp = math.floor(temp / 2)
     end
     end
-    print("S:" .. s)
     return tonumber(string.sub(s, n + 1, n + 1))
     return tonumber(string.sub(s, n + 1, n + 1))
 end
 end
+
+--- Obtains a bit from an unsigned byte
+--
+-- @param value The value (0-254)
+-- @param bit The bit to get (0-7)
+-- @return The bit value (1-0)
+function set_byte_nth_bit(value, n, bit)
+    if bit ~= 0 and bit ~= 1 then
+        print("ERROR: Tried to set bit " .. tostring(bit) .. " to an invalid value " .. tostring(bit) .. " from value " .. tostring(value) .. ".")
+        return value
+    end
+    if n < 0 or n > 7 then
+        print("ERROR: Tried to set invalid bit " .. tostring(bit) .. " to " .. tostring(bit) .. " from value " .. tostring(value) .. ".")
+        return value
+    end
+    if value < 0 then
+        print("ERROR: Tried to set bit " .. tostring(bit) .. " to " .. tostring(bit) .. "from negative value " .. tostring(value) .. ".")
+        return value
+    end
+    if value > 254 then
+        print("ERROR: Tried to set bit " .. tostring(bit) .. " to " .. tostring(bit) .. "from value " .. tostring(value) .. " that exceeds byte size.")
+        return value
+    end
+    -- Convert to binary string.
+    local s = ""
+    local temp = value
+    for i = 1, 8 do
+        s = s .. tostring(temp % 2)
+        temp = math.floor(temp / 2)
+    end
+    -- Replace the requested bit.
+    s = string.sub(s, 1, n) .. tostring(bit) .. string.sub(s, n + 2)
+    -- Convert back to a number.
+    val = 0
+    for i = 1, 8 do
+        val = val + (tonumber(string.sub(s, i, i )) * 2 ^ (i - 1))
+    end
+    return math.floor(val)
+end
+set_byte_nth_bit(25, 2, 1)