自制虚拟机(C/C++)(三、做成标准GUI Windows软件,扩展指令集,直接支持img软盘)

开源地址:VMwork

要使终端不弹出,

#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")

还要实现jmp near 0x01类似的

本次的main.cpp

#include <graphics.h>
#include <conio.h>
#include <windows.h>
#include <commdlg.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <thread>
#include <mutex>
#include <functional>
#include <vector>
#include <string>
#include <map>
#include <shlwapi.h>

using namespace std;

#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")

void VM(const string& file);

void ShowErrorDialog(const string& message) {
    MessageBox(GetHWnd(), message.c_str(), "VMwork 错误", MB_ICONERROR | MB_OK);
}


string GetCurrentDirectoryPath() {
    char buffer[MAX_PATH] = {0};
    GetModuleFileNameA(NULL, buffer, MAX_PATH);
    string::size_type pos = string(buffer).find_last_of("\\/");
    return string(buffer).substr(0, pos);
}


// 虚拟机配置结构体
struct VMConfig {
    string name;
    string filePath;  // 统一文件路径字段
    string fileType;  // "ASM" 或 "IMG"
};

// 全局配置存储
map<string, VMConfig> vmConfigs;
const char* CONFIG_FILE = "vm.dll";

// 图形界面尺寸参数
const int WIDTH = 800;
const int HEIGHT = 600;
const int BTN_WIDTH = 200;
const int BTN_HEIGHT = 40;

// 当前操作状态
enum class AppState {
    MAIN_MENU,
    CREATE_VM,
    OPEN_VM,
    SETTINGS
};
AppState currentState = AppState::MAIN_MENU;

char vmNameInput[64] = {0};
char asmPathInput[256] = {0};

void InitGUI() {
    initgraph(WIDTH, HEIGHT);
    HWND hWnd = GetHWnd();
    SetWindowText(hWnd, "VMwork 虚拟机");
    ShowWindow(hWnd, SW_SHOWNORMAL);
    setbkcolor(WHITE);
    cleardevice();
    settextcolor(BLACK);
    settextstyle(30, 0, "宋体");
}

void SaveConfig() {
    ofstream fout(CONFIG_FILE);
    for (auto& entry : vmConfigs) {
        auto& name = entry.first;
        auto& config = entry.second;
        fout << name << endl;
        fout << config.filePath << endl;
        fout << config.fileType << endl;
    }
    fout.close();
}

void LoadConfig() {
    vmConfigs.clear();
    ifstream fin(CONFIG_FILE);
    string name, path, type;
    while (getline(fin, name) && 
           getline(fin, path) && 
           getline(fin, type)) {
        vmConfigs[name] = {name, path, type};
    }
    fin.close();
}

void DrawMainMenu() {
    cleardevice();
    setbkcolor(WHITE);
    settextcolor(BLUE);
    settextstyle(30, 0, "宋体");
    outtextxy(100, 50, "VMwork 虚拟机");

    setfillcolor(LIGHTGRAY);
    fillroundrect(300, 150, 300 + BTN_WIDTH, 150 + BTN_HEIGHT, 5, 5);
    outtextxy(330, 155, "新建虚拟机");

    fillroundrect(300, 250, 300 + BTN_WIDTH, 250 + BTN_HEIGHT, 5, 5);
    outtextxy(330, 255, "打开虚拟机");

    fillroundrect(300, 350, 300 + BTN_WIDTH, 350 + BTN_HEIGHT, 5, 5);
    outtextxy(350, 355, "设置");
}

string SelectFile() {
    OPENFILENAMEA ofn;
    char szFile[260] = {0};

    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = sizeof(szFile);
    ofn.lpstrFilter = "IMG Files (*.img)\0*.img\0All Files (*.*)\0*.*\0";
    ofn.nFilterIndex = 1;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

    if (GetOpenFileNameA(&ofn)) {
        return szFile;
    }
    return "";
}


bool InputBox(const char* title, char* buffer, int bufferSize) {
    char prompt[10] = "";
    return InputBox(buffer, bufferSize, prompt, title); 
}

void CreateVMProcess() {
    int fileType = MessageBox(GetHWnd(), "是否启用读取nasm语法?\n[否]则以img软盘读取", "VMwork", MB_YESNO | MB_ICONQUESTION);
    bool isASM = (fileType == IDYES);

    OPENFILENAMEA ofn;
    char szFile[260] = {0};
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = sizeof(szFile);
    ofn.lpstrFilter = isASM ? 
        "ASM Files (*.asm)\0*.asm\0All Files (*.*)\0*.*\0" :
        "IMG Files (*.img)\0*.img\0All Files (*.*)\0*.*\0";
    ofn.nFilterIndex = 1;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

    if (!GetOpenFileNameA(&ofn)) return;

    if (!InputBox("输入虚拟机名称", vmNameInput, sizeof(vmNameInput))) return;

    vmConfigs[vmNameInput] = {
        vmNameInput, 
        szFile, 
        isASM ? "ASM" : "IMG"
    };
    SaveConfig();
}

void DisassembleImg(const string& imgPath, const string& asmPath) {
    string cmd = "cmd /c \"\"" + GetCurrentDirectoryPath() + "\\ndisasm.exe\" \"" 
               + imgPath + "\" > \"" + asmPath + "\"\"";
    WinExec(cmd.c_str(), SW_HIDE);
}

void ProcessAsm(const string& asmPath, const string& finalAsmPath) {
    string cmd = "cmd /c \"\"" + GetCurrentDirectoryPath() + "\\toasm.exe\" \"" 
               + asmPath + "\" \"" + finalAsmPath + "\"\"";
    WinExec(cmd.c_str(), SW_HIDE);
}

void OpenVMProcess() {
    LoadConfig();
    cleardevice();
    settextcolor(BLACK);
    outtextxy(50, 50, "选择虚拟机:");

    int y = 100;
    for (auto& entry : vmConfigs) {
        std::string text = entry.first + " (" + entry.second.filePath + ")";
        outtextxy(100, y, const_cast<char*>(text.c_str()));
        y += 50;
    }

    int choice = 0;
    while (true) {
        if (MouseHit()) {
            MOUSEMSG msg = GetMouseMsg();
            if (msg.uMsg == WM_LBUTTONDOWN) {
                int clickY = msg.y;
                int index = 0;
                for (auto& entry : vmConfigs) {
                    int itemTop = 100 + index * 40;
                    if (clickY > itemTop && clickY < itemTop + 50) {
                        choice = index + 1;
                        break;
                    }
                    index++;
                }
            }
        }
        if (choice!= 0) break;
    }

    if (choice > 0 && choice <= vmConfigs.size()) {
        auto it = vmConfigs.begin();
        advance(it, choice - 1);
        string selectedPath = it->second.filePath;

        string tempAsmPath = "temp.asm";
        string finalAsmPath = "final.asm";
        if (it->second.fileType == "IMG") {
            DisassembleImg(selectedPath, tempAsmPath);
            ProcessAsm(tempAsmPath, finalAsmPath);
        }
        else {
            finalAsmPath = selectedPath;
        }

        VM(finalAsmPath);
    }
}

void SetVMProcess() {
    LoadConfig();
    cleardevice();
    settextcolor(BLACK);
    outtextxy(30, 50, "虚拟机");
    outtextxy(50, 90, "处理器  : 1");
    outtextxy(50, 130, "内存    : 64KB");
    outtextxy(50, 170, "启动方式: 软盘(引导扇区)");
    outtextxy(50, 210, "光盘    : 无");
    outtextxy(50, 250, "BIOS    : VMwork");
    outtextxy(50, 290, "方式    : .IMG/.ASM");
    while (1) {}
}


void MainLoop() {
	AppState prevState = AppState::MAIN_MENU; 
    while (true) {
        if (MouseHit()) {
            MOUSEMSG msg = GetMouseMsg();
            if (msg.uMsg == WM_LBUTTONDOWN) {
                // 主界面按钮处理
                if (currentState == AppState::MAIN_MENU) {
                    if (msg.x > 300 && msg.x < 300 + BTN_WIDTH) {
                        if (msg.y > 150 && msg.y < 150 + BTN_HEIGHT) {
                            CreateVMProcess();
                        } else if (msg.y > 250 && msg.y < 250 + BTN_HEIGHT) {
                            OpenVMProcess();
                        } else if (msg.y > 350 && msg.y < 350 + BTN_HEIGHT) {
                            SetVMProcess(); 
                        }
                    }
                }
            }
        }
 
        switch (currentState) {
            case AppState::MAIN_MENU:
                if (prevState!= AppState::MAIN_MENU) {
                    //cleardevice();
                }
                DrawMainMenu();
                break;
            case AppState::CREATE_VM:
                if (prevState!= AppState::CREATE_VM) {
                    //cleardevice();
                }
                DrawMainMenu();
                break;
            cas
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值