Results 1 to 6 of 6

Thread: DOS Game Emulator

  1. #1

    Thread Starter
    Member
    Join Date
    Nov 2011
    Location
    Finland
    Posts
    36

    Question DOS Game Emulator

    I was thinking about making a DOS game emulator in VB 2008. Is that even possible, and if it is would someone give help making it. I have used Dosbox lot. But I want to make simpler emulator.

    Thanks
    Hece

  2. #2
    Elite Hacker Jacob Roman's Avatar
    Join Date
    Aug 2004
    Location
    Miami Beach, FL
    Posts
    5,349

    Re: DOS Game Emulator

    Personally I think your only good language to pull this off would be in C++ cause DOS games to be emulated would require a good knowledge of Assembly, and C++ is best for it. Rom files are in binary format and have numerical instructions. Those instructions get processed either by a console system or through an emulator. Then the emulator emulates the instructions and processes it through a graphical API such as DirectX or OpenGL.

    READ THIS ABOUT HOW TO WRITE A COMPUTER EMULATOR

    You can download Visual C++ 2010 express edition for free if you don't have it:
    Visual C++ 2010 Express Edition

    Also there's Visual C++ 2008 you can download as well Visual C++ 2008 Express Edition

    Next you are gonna wanna install the DirectX 9.0c SDK


    Start a new project. Goto Source Files, right click it and Add New Item. Create a new cpp file and call it whatever you want such as Main.

    A simple window created as an example:
    c++ Code:
    1. #include <windows.h>
    2.  
    3. HWND hWnd;
    4. MSG msg;
    5.  
    6. bool Running;
    7.  
    8. LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
    9.  
    10. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
    11. {
    12.     WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_VREDRAW|CS_HREDRAW|CS_OWNDC, WindowProcedure, 0, 0, hInstance, NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, "FORM", NULL};
    13.     RegisterClassEx(&wc);
    14.     hWnd = CreateWindowEx (0, "FORM", "Form1", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 330, 250, HWND_DESKTOP, NULL, hInstance, NULL);
    15.     ShowWindow (hWnd, nCmdShow);
    16.     Running = true;
    17.     while (Running == true)
    18.     {
    19.         if (PeekMessage(&msg,NULL,0,0,PM_REMOVE) > 0)
    20.         {
    21.             if (WM_QUIT == msg.message) break;
    22.             TranslateMessage (&msg);
    23.             DispatchMessage (&msg);
    24.         }
    25.         //Render code here
    26.     }
    27.     return msg.wParam;
    28. }
    29.  
    30. LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    31. {
    32.     switch (msg)
    33.     {
    34.         case WM_DESTROY:
    35.             Running = false;
    36.             PostQuitMessage (0);
    37.             HANDLE Process;
    38.             Process = OpenProcess(PROCESS_ALL_ACCESS , true , GetCurrentProcessId());
    39.             TerminateProcess(Process , 0);
    40.             break;
    41.         case WM_KEYDOWN:
    42.             if(wParam == VK_ESCAPE)
    43.             {
    44.                 DestroyWindow(hWnd);
    45.                 return(0);
    46.             }
    47.         default:
    48.             return DefWindowProc (hWnd, msg, wParam, lParam);
    49.     }
    50.     return 0;
    51. }

    For the first time of working with DirectX9, you'll only need to do this part once ever. On the left where your project name is within Solution Explorer, right click it and goto Properties. Then goto Configuration Properties > VC++ Directories and goto Include Directories and click it to reveal a [v]. Click it and goto <Edit...>. If you do not see $(DXSDK_DIR)Include, manually put it in and click Ok. Next goto Library Directories and click it to reveal a [v]. Click it and goto <Edit...>. If you do not see $(DXSDK_DIR)Lib\x86, manually put it in and click OK. You no longer need to do that with Include and Library.

    Now with every new project you will need to do this: On the left where your project name is within Solution Explorer, right click it and goto Properties. Goto Configuration Properties and goto > Linker > Input. Towards the right where it says Additional Dependencies, click it to reveal a [v] and goto <Edit...>. On top in the listbox add d3d9.lib. You are welcome to adding more dx librarys for what ever you need to do such as d3dx9.lib, dsound.lib, dplay.lib, etc. Now you are ready to code DirectX9.

    Note: VC++ 2010 seems to have issues with long project path's and you will probably receive errors such as Source File Not Found even on the simplest projects. To fix this, just put your project in a new location where the file path won't be huge.

    Then try this as a sample project
    c++ Code:
    1. #include <windows.h>
    2. #include <d3d9.h>
    3.  
    4. struct CUSTOM_VERTEX
    5. {
    6.     float X, Y, Z, RHW;
    7.     DWORD Color;
    8. };
    9.  
    10. #define CUSTOM_VERTEX_FORMAT (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
    11.  
    12. const D3DFORMAT COLOR_DEPTH_16_BIT = D3DFMT_R5G6B5;
    13. const D3DFORMAT COLOR_DEPTH_24_BIT = D3DFMT_A8R8G8B8;
    14. const D3DFORMAT COLOR_DEPTH_32_BIT = D3DFMT_X8R8G8B8;
    15.  
    16. LPDIRECT3D9 Direct3D = NULL;
    17. LPDIRECT3DDEVICE9 Direct3D_Device = NULL;
    18. D3DDISPLAYMODE Display_Mode;
    19. D3DPRESENT_PARAMETERS Direct3D_Window;
    20. HWND hWnd;
    21. MSG msg;
    22. bool Fullscreen_Enabled;
    23. bool Running;
    24. CUSTOM_VERTEX Vertex_List[3];
    25.  
    26. CUSTOM_VERTEX Create_TLVertex();
    27. void Create_Polygon();
    28. void Draw_Polygon();
    29. void Render();
    30. void Game_Loop();
    31. void Main();
    32. void Shutdown();
    33. void DirectX9_Initialize();
    34. LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
    35.  
    36. CUSTOM_VERTEX Create_Custom_Vertex(float X, float Y, float Z, float RHW, DWORD Color)
    37. {
    38.     CUSTOM_VERTEX Vertex;
    39.  
    40.     Vertex.X = X;
    41.     Vertex.Y = Y;
    42.     Vertex.Z = Z;
    43.     Vertex.RHW = RHW;
    44.     Vertex.Color = Color;
    45.  
    46.     return Vertex;
    47. }
    48.  
    49. void DirectX9_Initialize()
    50. {
    51.     Direct3D = Direct3DCreate9(D3D_SDK_VERSION);
    52.     memset(&Direct3D_Window, 0, sizeof(D3DPRESENT_PARAMETERS));
    53.  
    54.     if (Fullscreen_Enabled == true)
    55.     {
    56.        Display_Mode.Width = 800;
    57.        Display_Mode.Height = 600;
    58.        Display_Mode.Format = COLOR_DEPTH_16_BIT;
    59.        Direct3D_Window.Windowed = FALSE;
    60.        Direct3D_Window.BackBufferCount = 1;
    61.        Direct3D_Window.BackBufferWidth = Display_Mode.Width;
    62.        Direct3D_Window.BackBufferHeight = Display_Mode.Height;
    63.        Direct3D_Window.hDeviceWindow = hWnd;
    64.     }
    65.     else
    66.     {
    67.        Direct3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &Display_Mode);
    68.        Direct3D_Window.Windowed = TRUE;
    69.     }
    70.     Direct3D_Window.SwapEffect = D3DSWAPEFFECT_COPY;
    71.     Direct3D_Window.BackBufferFormat = Display_Mode.Format;
    72.     Direct3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &Direct3D_Window, &Direct3D_Device);
    73. }
    74.  
    75. void Create_Polygon()
    76. {
    77.     Vertex_List[0] = Create_Custom_Vertex(0, 0, 0, 1, D3DCOLOR_RGBA(255, 255, 255, 255));
    78.     Vertex_List[1] = Create_Custom_Vertex(100, 0, 0, 1, D3DCOLOR_RGBA(255, 255, 255, 255));
    79.     Vertex_List[2] = Create_Custom_Vertex(0, 100, 0, 1, D3DCOLOR_RGBA(255, 255, 255, 255));
    80.     Vertex_List[3] = Create_Custom_Vertex(100, 100, 0, 1, D3DCOLOR_RGBA(255, 255, 255, 255));
    81. }
    82.  
    83. void Draw_Polygon()
    84. {
    85.     Direct3D_Device->SetFVF(CUSTOM_VERTEX_FORMAT);
    86.     Direct3D_Device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, Vertex_List, sizeof(CUSTOM_VERTEX));
    87. }
    88.  
    89. void Render()
    90. {    
    91.     Direct3D_Device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 1.0f, 0); // clear frame
    92.     Direct3D_Device->BeginScene();
    93.     Create_Polygon();
    94.     Draw_Polygon();
    95.     Direct3D_Device->EndScene();
    96.     Direct3D_Device->Present(NULL, NULL, NULL, NULL);
    97. }
    98.  
    99. void Game_Loop()
    100. {
    101.     while (Running == true)
    102.     {
    103.         if (PeekMessage(&msg,NULL,0,0,PM_REMOVE) > 0)
    104.         {
    105.             if (WM_QUIT == msg.message) break;
    106.             TranslateMessage (&msg);
    107.             DispatchMessage (&msg);
    108.         }
    109.         else
    110.             Render();
    111.     }
    112. }
    113.  
    114. void Main()
    115. {
    116.     DirectX9_Initialize();
    117.     Running = true;
    118. }
    119.  
    120. void Shutdown()
    121. {
    122.     Running = false;
    123.     Direct3D_Device->Release();
    124.     Direct3D->Release();
    125.     PostQuitMessage (0);
    126.     HANDLE Process;
    127.     Process = OpenProcess(PROCESS_ALL_ACCESS , true , GetCurrentProcessId());
    128.     TerminateProcess(Process , 0);
    129. }
    130.  
    131. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
    132. {
    133.    
    134.     WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_VREDRAW|CS_HREDRAW|CS_OWNDC, WindowProcedure, 0, 0, hInstance, NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, "DX_TUT", NULL};
    135.     RegisterClassEx(&wc);
    136.  
    137.     if (MessageBox(hWnd, "Click Yes to go to fullscreen (Recommended)", "", MB_ICONQUESTION | MB_YESNO) == IDYES)
    138.        Fullscreen_Enabled = true;
    139.  
    140.     if (Fullscreen_Enabled == true)
    141.         hWnd = CreateWindowEx (0, "DX_TUT", "DirectX Tutorial", WS_VISIBLE | WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, 330, 250, HWND_DESKTOP, NULL, hInstance, NULL);
    142.     else
    143.         hWnd = CreateWindowEx (0, "DX_TUT", "DirectX Tutorial", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 330, 250, HWND_DESKTOP, NULL, hInstance, NULL);
    144.     ShowWindow (hWnd, nCmdShow);
    145.     Main();
    146.     Game_Loop();
    147.     return msg.wParam;
    148. }
    149.  
    150. LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    151. {
    152.     switch (msg)
    153.     {
    154.         case WM_DESTROY:
    155.             Shutdown();
    156.             break;
    157.         case WM_KEYDOWN:
    158.             if(wParam == VK_ESCAPE)
    159.             {
    160.                 DestroyWindow(hWnd);
    161.                 return(0);
    162.             }
    163.         default:
    164.             return DefWindowProc (hWnd, msg, wParam, lParam);
    165.     }
    166.     return 0;
    167. }

    Once you have a good understanding of C++, Win32, and the ins and outs of DOS programs, you should be able to emulate it using assembly commands. As for assembly, you are gonna wanna learn that as well over at
    The Art of Assembly. A simple assembly instruction can be like so:

    Code:
    int add(int a, int b)
    {
       __asm
        {
            mov eax, a
            mov ebx, b
            add eax, ebx
        }
    }
    This takes 2 values and adds em together. It puts a in the 32 bit register called eax. Then b in the 2nd 32 bit register called ebx. And add adds them together and sticks it back into eax. eax automatically returns the value into the function add();

    Another cool thing you can do with assembly:
    Code:
    #include <stdio.h>
    
    inline void Mem_Set_QUAD(void *dest, unsigned int data, int count)
    
    {
    
        _asm
            {
    
             mov edi, dest     ;edi points to destination memory
             mov ecx, count  ;number of 32-bit words to move
             mov eax, data   ;32-bit data
             rep stosd          ;move data   
    
            }
    
    }
    
    int main(void)
    {
    
         int a[5] = {0};
         
         Mem_Set_QUAD(a, 100, sizeof(int) * 5);
    
         for (int i = 0; i<5; i++)
              printf("&#37;d\n", a[i]);
    
         return 0;
    
    }
    This takes a 32 bit array and fills the entire array with a value instantly! No for loops required. Inline assembly is a little faster cause it acts as if the function wasn't called but hardcoded instead. Function calls take a microbite of speed for every call.

  3. #3
    Elite Hacker Jacob Roman's Avatar
    Join Date
    Aug 2004
    Location
    Miami Beach, FL
    Posts
    5,349

    Re: DOS Game Emulator

    Had to make a new post:

    A Visual Basic comparison can be done with a simple exponent function. Here's the C++ method:

    c++ Code:
    1. inline int Exponent(int n, int exp)
    2. {
    3.     __asm {
    4.         mov eax, n      ; num
    5.         mov ebx, n      ; exp
    6.         mov ecx, exp ; counter
    7.  
    8.         cmp ecx, 0
    9.         je retOne
    10.  
    11.         cmp ecx, 1
    12.         je retVal
    13.  
    14.         loopstart:
    15.             imul eax, ebx
    16.             dec ecx
    17.             cmp ecx, 1
    18.             jg loopstart
    19.             jmp retVal
    20.  
    21.         retOne:
    22.             mov eax, 1
    23.  
    24.         retVal:
    25.     }
    26. }

    Ok before I explain what the code does, I'll talk about the registers.

    eax - accumulator register (commonly used for arithmetic and is the fastest)
    ebx - base address register
    ecx - counter register
    edx - data register

    And as you may already know, these are 32 bit registers. You can actually store the data in any register you want pretty much.

    Here is a VB 2008 example:

    vb.net Code:
    1. Private eax As Integer, ebx As Integer, ecx As Integer
    2.  
    3. Private Function Exponent(n As Integer, exp As Integer) As Integer
    4.     eax = n
    5.     ebx = n
    6.     ecx = exp
    7.     If ecx = 0 Then Goto retOne
    8.     If ecx = 1 Then Goto retVal
    9. loopstart:
    10.     eax = eax * ebx
    11.     ecx = ecx - 1
    12.    
    13.     If ecx > 1 Then Goto loopstart
    14.     Goto retVal
    15. retOne:
    16.     eax = 1
    17. retVal:
    18.     Return = eax
    19. End Function

  4. #4

    Thread Starter
    Member
    Join Date
    Nov 2011
    Location
    Finland
    Posts
    36

    Re: DOS Game Emulator

    WOW! Thanks Dudes!

  5. #5
    Elite Hacker Jacob Roman's Avatar
    Join Date
    Aug 2004
    Location
    Miami Beach, FL
    Posts
    5,349

    Re: DOS Game Emulator

    Dude actually. It was all me

    You'll also need a way of making the DOS games an ISO or bin file and use a disassembler or something to understand what makes them tick.

  6. #6

    Thread Starter
    Member
    Join Date
    Nov 2011
    Location
    Finland
    Posts
    36

    Re: DOS Game Emulator

    Oh sorry, my bad. Btw you have helped me in probably every question : )

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width