diff --git a/ia86.cpp b/ia86.cpp index 0c84d2b..9153294 100644 --- a/ia86.cpp +++ b/ia86.cpp @@ -153,6 +153,12 @@ std::vector> InstructionWindow::get() return content; } +void InstructionWindow::clear() +{ + listview.clear(); + listview.redraw(); +} + void InstructionWindow::set(std::vector> src) { content=src; @@ -162,7 +168,7 @@ void InstructionWindow::set(std::vector> src) const finalcut::FStringList line (place.begin(), place.end()); listview.insert (line); } - + listview.redraw(); } void InstructionWindow::initLayout() @@ -176,43 +182,7 @@ void InstructionWindow::adjustSize() { finalcut::FDialog::adjustSize(); listview.setGeometry (FPoint{1, 2}, FSize(getWidth(), getHeight() - 1)); -} - -//---------------------------------------------------------------------- -// Classe TextFixedWindow -//---------------------------------------------------------------------- - -TextFixedWindow::TextFixedWindow (finalcut::FWidget* parent) - : finalcut::FDialog{parent} -{ - - fixedtext.ignorePadding(); - fixedtext.setFocus(); -} - -std::string TextFixedWindow::get() -{ - std::stringstream out; - out << fixedtext.getText(); - return out.str(); -} - -void TextFixedWindow::set(std::string str) -{ - fixedtext.setText(str); -} - -void TextFixedWindow::initLayout() -{ - fixedtext.setGeometry (FPoint{2, 3}, FSize{getWidth()-2, getHeight() - 2}); - FDialog::initLayout(); -} - -void TextFixedWindow::adjustSize() -{ - finalcut::FDialog::adjustSize(); - fixedtext.setGeometry (FPoint{2, 3}, FSize(getWidth()-2, getHeight() - 2)); -} +} //---------------------------------------------------------------------- // Classe TextEditWindow @@ -221,32 +191,49 @@ void TextFixedWindow::adjustSize() TextEditWindow::TextEditWindow (finalcut::FWidget* parent) : finalcut::FDialog{parent} { - fixedtext.ignorePadding(); - fixedtext.setFocus(); + scrolltext.ignorePadding(); + scrolltext.setFocus(); +} + +void TextEditWindow::onClose(finalcut::FCloseEvent*) +{ + return; +} + +void TextEditWindow::append(const finalcut::FString& str) +{ + scrolltext.append(str); + scrolltext.scrollBy (0, 10); } std::string TextEditWindow::get() { - std::stringstream out; - out << fixedtext.getText(); - return out.str(); + return scrolltext.getText().toString () ; } -void TextEditWindow::set(std::string str) +void TextEditWindow::set(const finalcut::FString& str) { - fixedtext.setText(str); + scrolltext.clear(); + scrolltext.append(str); + scrolltext.redraw(); } +void TextEditWindow::clear() +{ + scrolltext.clear(); +} + + void TextEditWindow::initLayout() { - fixedtext.setGeometry (FPoint{2, 3}, FSize{getWidth()-2, getHeight() - 2}); + scrolltext.setGeometry (FPoint{1, 2}, FSize{getWidth(), getHeight() - 1}); FDialog::initLayout(); } void TextEditWindow::adjustSize() { finalcut::FDialog::adjustSize(); - fixedtext.setGeometry (FPoint{2, 3}, FSize{getWidth()-2, getHeight() - 2}); + scrolltext.setGeometry (FPoint{1, 2}, FSize(getWidth(), getHeight() - 1)); } //---------------------------------------------------------------------- @@ -271,6 +258,18 @@ void TextWindow::append(const finalcut::FString& str) scrolltext.scrollBy (0, 10); } +std::string TextWindow::get() +{ + return scrolltext.getText().toString () ; +} + +void TextWindow::set(const finalcut::FString& str) +{ + scrolltext.clear(); + scrolltext.append(str); + scrolltext.redraw(); +} + void TextWindow::clear() { scrolltext.clear(); @@ -387,14 +386,7 @@ Code *Assembler::Assemble(std::string source,uint32_t address) VMEngine::VMEngine(TextWindow *log) : log(log) { - std::stringstream out; - err = uc_open(UC_ARCH_X86, UC_MODE_16, &uc); - if (err != UC_ERR_OK) { - out << "Impossible d'initialiser la machine virtuelle: " << err; - log->append(out.str()); - } - else - log->append("Initialisation de l'ordinateur IA86"); + Init(); } // Level 1 : IP AL // Level 2 : IP AX @@ -506,8 +498,64 @@ std::string VMEngine::getRegs(int level) out << "EFLAGS:" << std::uppercase << std::setfill('0') << std::setw(8) << std::hex << vals[15] << ""; return out.str(); } - + +void VMEngine::Init() +{ + std::stringstream out; + err = uc_open(UC_ARCH_X86, UC_MODE_16, &uc); + if (err != UC_ERR_OK) { + out << "Impossible d'initialiser la machine virtuelle: " << err; + log->append(out.str()); + } + else + log->append("Initialisation de l'ordinateur IA86"); +} + +void VMEngine::Close() +{ + uc_close(uc); +} + +void VMEngine::Halt(Code *code) +{ + code->executed=false; +} + void VMEngine::Configure(State *init, Code *code) +{ + Close(); + Init(); + code->assembled=false; + code->initialized=false; + code->executed=false; + log->append("Mappage de la mémoire virtuelle"); + uc_mem_map(uc, init->dump.regs.eip, 1 * 1024 * 1024, UC_PROT_ALL); +} + +void VMEngine::Prepare(State *init, Code *code) +{ + SetMem(init, code); + SetRegs(init, code); +} + +void VMEngine::SetMem(State *init, Code *code) +{ + + err = uc_mem_write(uc, init->dump.regs.eip, code->content, code->size); + if (err) + { + code->initialized=false; + log->append("Erreur de copie mémoire dans la machine virtuelle"); + return; + } + else + { + code->initialized=true; + log->append("Chargement en mémoire de la machine virtuelle, taille: "+to_string(code->size)); + } +} + +void VMEngine::SetRegs(State *init, Code *code) { std::stringstream out; out << "Configuration initiale de l'ordinateur IA86:\n "; @@ -593,16 +641,6 @@ void VMEngine::Configure(State *init, Code *code) else out << "EAX=" << std::uppercase << std::setfill('0') << std::setw(8) << std::hex << init->dump.regs.eax << " "; log->append(out.str()); - uc_mem_map(uc, init->dump.regs.eip, 1 * 1024 * 1024, UC_PROT_ALL); - err = uc_mem_write(uc, init->dump.regs.eip, code->content, code->size); - if (err) - { - code->loaded=false; - log->append("Erreur de copie mémoire dans la machine virtuelle"); - return; - } - else - code->loaded=true; } void VMEngine::Run(Code *code,uint32_t start, uint32_t stop, uint64_t timeout) @@ -641,6 +679,7 @@ void Menu::initNow() void Menu::initCore() { + addTimer (50); loadGoal(); } @@ -663,20 +702,16 @@ void Menu::initWindows() regs.show(); flags.setText ("Drapeaux"); flags.setGeometry ( FPoint { 60, 01 }, FSize{15, 15} ); - flags.show(); stack.setText ("Pile"); stack.setGeometry ( FPoint { 43, 01 }, FSize{15, 15} ); - stack.show(); mem.setText ("Mémoire"); mem.setGeometry ( FPoint { 77, 01 }, FSize{108, 15} ); - mem.show(); tuto.setText ("Guide"); tuto.setGeometry ( FPoint { 125, 45 }, FSize{60, 11} ); tuto.setResizeable(); tuto.show(); screen.setText ("Ecran"); screen.setGeometry ( FPoint { 105, 18 }, FSize{80, 25} ); - screen.show(); debug.setText ("Instructions"); debug.setGeometry ( FPoint { 42, 17 }, FSize{60, 27} ); debug.setResizeable(); @@ -702,6 +737,17 @@ void Menu::initWindows() void Menu::AdjustWindows() { + log.setGeometry ( FPoint { 63, 45 }, FSize{60, 11} ); + edit.setGeometry ( FPoint { 01, 17 }, FSize{39, 27} ); + view.setGeometry ( FPoint { 01, 45 }, FSize{60, 11} ); + regs.setGeometry ( FPoint { 01, 01 }, FSize{40, 15} ); + flags.setGeometry ( FPoint { 60, 01 }, FSize{15, 15} ); + stack.setGeometry ( FPoint { 43, 01 }, FSize{15, 15} ); + mem.setGeometry ( FPoint { 77, 01 }, FSize{108, 15} ); + tuto.setGeometry ( FPoint { 125, 45 }, FSize{60, 11} ); + screen.setGeometry ( FPoint { 105, 18 }, FSize{80, 25} ); + debug.setGeometry ( FPoint { 42, 17 }, FSize{60, 27} ); + scenar.setGeometry ( FPoint { 187, 01 }, FSize{23, 55} ); flags.hide(); stack.hide(); mem.hide(); @@ -729,7 +775,7 @@ void Menu::initMenus() New.setStatusbarMessage ("Debuter une nouvelle partie"); Quit.addAccelerator (FKey::Meta_x); Quit.setStatusbarMessage ("Quitter IA86"); - Run.addAccelerator (FKey::Meta_f9); + Run.addAccelerator (FKey::F9); Run.setStatusbarMessage ("Exécuter le programme - seul un breakpoint arrête"); TraceInto.addAccelerator (FKey::F7); TraceInto.setStatusbarMessage ("Pas à pas détaillé - entre dans les CALL"); @@ -737,15 +783,20 @@ void Menu::initMenus() StepOver.setStatusbarMessage ("Pas à pas - ne rentre pas dans les CALL"); Assemble.addAccelerator (FKey::F2); Assemble.setStatusbarMessage ("Assemble le source vers du code machine"); - Rearange.addAccelerator (FKey::F1); + Rearange.addAccelerator (FKey::Meta_r); Rearange.setStatusbarMessage ("Reorganise les fenêtres dans leur état initial"); Breakpoint.addAccelerator (FKey::F5); Breakpoint.setStatusbarMessage ("Enlève ou met un point d'arrêt"); - End.addAccelerator (FKey::Meta_f2); + End.addAccelerator (FKey::F6); End.setStatusbarMessage ("Termine le programme et remet à zéro la machine IA86"); About.setStatusbarMessage ("A propos de IA86"); } +void Menu::onTimer (finalcut::FTimerEvent* ev) +{ + refresh(); +} + void Menu::initMenusCallBack() { Quit.addCallback @@ -785,6 +836,12 @@ void Menu::initMenusCallBack() this, &Menu::step ); + End.addCallback + ( + "clicked", + this, + &Menu::end + ); } void Menu::initMisc() @@ -825,11 +882,24 @@ void Menu::onClose (finalcut::FCloseEvent* ev) void Menu::loadGoal() { + log.append("Chargement du scénario "+goals[scenar.getselected()].title); view.setText("Objectif: "+goals[scenar.getselected()].title); view.clear(); view.append(goals[scenar.getselected()].description); + tuto.clear(); + tuto.append(goals[scenar.getselected()].help); + regs.set("En attente d'initialisation..."); edit.set(goals[scenar.getselected()].code); AdjustWindows(); + debug.clear(); + vm.Configure(&goals[scenar.getselected()].init,code); + end(); +} + +void Menu::end() +{ + regs.set("En attente d'initialisation..."); + vm.Halt(code); } void Menu::compile() @@ -838,44 +908,47 @@ void Menu::compile() debug.set(unasmer.Desassemble(code)); } -void Menu::verify() +bool Menu::verify() { + if (!code->assembled) + { + finalcut::FMessageBox::error(this, "Vous devez compiler le source d'abord !"); + return false; + } + if (!code->initialized) + vm.Prepare(&goals[scenar.getselected()].init,code); + if (!code->initialized) + return false; + return true; +} + +void Menu::refresh() +{ + if (!code->executed) + finalcut::FApplication::setDarkTheme(); + else + finalcut::FApplication::setDefaultTheme(); + auto root_widget = getRootWidget(); + root_widget->resetColors(); + root_widget->redraw(); } void Menu::exec() { - if (!code->assembled) - { - finalcut::FMessageBox::error(this, "Vous devez compiler le source d'abord !"); - return; - } - if (!code->executed) - vm.Configure(&goals[scenar.getselected()].init,code); + if (!verify()) return; vm.Run(code,code->address,code->address+code->size,0); regs.set(vm.getRegs(goals[scenar.getselected()].level)); } void Menu::trace() { - if (!code->assembled) - { - finalcut::FMessageBox::error(this, "Vous devez compiler le source d'abord !"); - return; - } - if (!code->executed) - vm.Configure(&goals[scenar.getselected()].init,code); + if (!verify()) return; } void Menu::step() { - if (!code->assembled) - { - finalcut::FMessageBox::error(this, "Vous devez compiler le source d'abord !"); - return; - } - if (!code->executed) - vm.Configure(&goals[scenar.getselected()].init,code); + if (!verify()) return; } //---------------------------------------------------------------------- @@ -890,6 +963,7 @@ int main (int argc, char* argv[]) main_dlg.setSize ({50, 14}); main_dlg.setShadow(); main_dlg.show(); + finalcut::FApplication::setDarkTheme(); finalcut::FWidget::setMainWidget (&main_dlg); //usleep(5 * 1000000); main_dlg.hide(); diff --git a/ia86.h b/ia86.h index 4e8dfbc..8833990 100644 --- a/ia86.h +++ b/ia86.h @@ -3,9 +3,12 @@ using std::cout; using std::endl; using std::vector; using std::string; using FKey = finalcut::FKey; +using finalcut::FColor; using finalcut::FPoint; +using finalcut::FRect; using finalcut::FSize; + //---------------------------------------------------------------------- // Types & classes mineures //---------------------------------------------------------------------- @@ -137,8 +140,8 @@ class Code size_t size; unsigned char *content; bool assembled; + bool initialized; bool executed; - bool loaded; }; class ScenarioWindow final : public finalcut::FDialog @@ -178,6 +181,7 @@ class InstructionWindow final : public finalcut::FDialog // Method std::vector> get(); void set(std::vector> src); + void clear(); private: // Method std::vector> content; @@ -187,29 +191,6 @@ class InstructionWindow final : public finalcut::FDialog finalcut::FListView listview{this}; }; - -class TextFixedWindow final : public finalcut::FDialog -{ - public: - // Constructor - explicit TextFixedWindow (finalcut::FWidget* = nullptr); - // Disable copy constructor - TextFixedWindow (const TextFixedWindow&) = delete; - // Destructor - ~TextFixedWindow() override = default; - // Disable copy assignment operator (=) - TextFixedWindow& operator = (const TextFixedWindow&) = delete; - // Method - std::string get(); - void set(std::string str); - private: - // Method - void initLayout() override; - void adjustSize() override; - // Data members - finalcut::FLabel fixedtext{this}; -}; - class TextEditWindow final : public finalcut::FDialog { public: @@ -222,14 +203,17 @@ class TextEditWindow final : public finalcut::FDialog // Disable copy assignment operator (=) TextEditWindow& operator = (const TextEditWindow&) = delete; // Method + void append(const finalcut::FString&); + void clear(); std::string get(); - void set(std::string str); + void set(const finalcut::FString&); private: // Method + void onClose(finalcut::FCloseEvent*) override; void initLayout() override; void adjustSize() override; // Data members - finalcut::FLabel fixedtext{this}; + finalcut::FTextView scrolltext{this}; }; class TextWindow final : public finalcut::FDialog @@ -246,6 +230,8 @@ class TextWindow final : public finalcut::FDialog // Method void append(const finalcut::FString&); void clear(); + std::string get(); + void set(const finalcut::FString&); private: // Method void onClose(finalcut::FCloseEvent*) override; @@ -291,9 +277,15 @@ class VMEngine public: VMEngine(TextWindow *log); void Configure(State *init,Code *code); + void Halt(Code *code); void Run(Code *code, uint32_t start, uint32_t stop, uint64_t timeout); std::string getRegs(int level); + void Prepare(State *init, Code *code); + void SetMem(State *init, Code *code); + void SetRegs(State *init, Code *code); private: + void Init(); + void Close(); uc_engine *uc; uc_err err; TextWindow *log; @@ -314,6 +306,8 @@ class Menu final : public finalcut::FDialog void loadGoal(); private: Code *code = new Code(); + void onTimer (finalcut::FTimerEvent*) override; + void refresh(); void configureFileMenuItems(); void initMenusCallBack (); void initMenus(); @@ -321,10 +315,11 @@ class Menu final : public finalcut::FDialog void initNow(); void initCore(); void compile(); + void end(); void exec(); void trace(); void step(); - void verify(); + bool verify(); void AdjustWindows(); void initWindows(); void splash(); @@ -358,13 +353,13 @@ class Menu final : public finalcut::FDialog finalcut::FStatusBar Statusbar{this}; TextWindow log{this}; TextWindow view{this}; - InstructionWindow debug{this}; - TextFixedWindow regs{this}; - TextFixedWindow flags{this}; - TextFixedWindow stack{this}; - TextFixedWindow mem{this}; - TextFixedWindow tuto{this}; - TextFixedWindow screen{this}; + InstructionWindow debug{this}; + TextWindow regs{this}; + TextWindow flags{this}; + TextWindow stack{this}; + TextWindow mem{this}; + TextWindow tuto{this}; + TextWindow screen{this}; TextEditWindow edit{this}; ScenarioWindow scenar{this}; VMEngine vm{&log}; @@ -372,3 +367,4 @@ class Menu final : public finalcut::FDialog Desassembler unasmer{&log}; }; +