Last active
November 21, 2024 23:27
-
-
Save gabteles/10000006 to your computer and use it in GitHub Desktop.
Emulador do RGSS Player do RPG Maker (XP, VX e VXA) escrito em Ruby. A versão do Ruby deve ter arquitetura x86, já que a WinAPI falha ao carregar DLLs x86 (as do RM, no caso) em programas x64.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: utf-8 | |
# @file : Main.rb | |
# @desc : Omni RGSSx Player | |
# @author : Gab! | |
# @history : 2014/04/04 | |
# Requires | |
require 'fiddle' | |
require 'fiddle/struct' | |
require 'fiddle/types' | |
# DLL Wrapper | |
module DLLWrapper | |
def target(lib) | |
self.const_set("Library", Fiddle.dlopen(lib)) | |
self.const_set("Functions", {}) | |
end | |
def getFiddleEquiv(type) | |
return case type | |
when :pointer then Fiddle::TYPE_VOIDP | |
when :int then Fiddle::TYPE_INT | |
when :uint then -Fiddle::TYPE_INT | |
when :long then Fiddle::TYPE_LONG | |
when :ulong then -Fiddle::TYPE_LONG | |
when :dword then -Fiddle::TYPE_LONG | |
when :long_long then Fiddle::TYPE_LONG_LONG | |
when :void then Fiddle::TYPE_VOID | |
else Fiddle::TYPE_VOID | |
end | |
end | |
module_function :getFiddleEquiv | |
def define(function, name, inTypes, outType) | |
functions = self.const_get("Functions") | |
library = self.const_get("Library") | |
functions[function] = Fiddle::Function.new( | |
library[name.to_s], | |
inTypes.map{|type| getFiddleEquiv(type) }, | |
getFiddleEquiv(outType) | |
) | |
define_method(function){|*args| | |
functions[function].call(*args) | |
} | |
module_function(function) | |
end | |
def getAddress(function) | |
return self.const_get("Library")[function.to_s] | |
end | |
module_function :getAddress | |
public :getAddress | |
#============================== | |
module Struct | |
module_function | |
def create(members) | |
return Fiddle::CStructBuilder.create( | |
Fiddle::CStruct, | |
members.values.map{|type| DLLWrapper.getFiddleEquiv(type) }, | |
members.keys.map{|name| name.to_s } | |
) | |
end | |
end | |
end | |
# Base Module | |
module Omni | |
#============================== | |
# Defaults Section | |
Version = 2 | |
BaseName = "Game." | |
WndClassName = "Omni RGSS Player" | |
case Version | |
when 1 | |
UTF8 = false | |
ScreenWidth = 640 | |
ScreenHeight = 480 | |
CryptoExtension = "rgssad" | |
DefaultData = { | |
Library: "RGSS102E.dll", | |
Title: "Untitled", | |
Scripts: "Data\\Scripts.rxdata" | |
} | |
when 2 | |
UTF8 = true | |
ScreenWidth = 544 | |
ScreenHeight = 416 | |
CryptoExtension = "rgss2a" | |
DefaultData = { | |
Library: "RGSS202E.dll", | |
Title: "Untitled", | |
Scripts: "Data\\Scripts.rvdata" | |
} | |
when 3 | |
UTF8 = true | |
ScreenWidth = 544 | |
ScreenHeight = 416 | |
CryptoExtension = "rgss3a" | |
DefaultData = { | |
Library: "System\\RGSS300E.dll", | |
Title: "Untitled", | |
Scripts: "Data\\Scripts.rvdata2" | |
} | |
end | |
IniName = BaseName + "ini" | |
CryptoName = BaseName + CryptoExtension | |
#============================== | |
# Libraries Section | |
module WinAPI | |
#=== Macros | |
module_function | |
def MakeIntResource(i) | |
return Fiddle::Pointer.new(i & 0xFFFF) | |
end | |
#=== Constants | |
NULL = 0 | |
MAX_PATH = 260 | |
CS_DBLCLKS = 0x0008 | |
CS_HREDRAW = 0x0002 | |
CS_OWNDC = 0x0020 | |
CS_VREDRAW = 0x0001 | |
IDI_APPLICATION = MakeIntResource(32512) | |
IDC_ARROW = MakeIntResource(32512) | |
#=== Structs | |
WNDCLASS = DLLWrapper::Struct.create( | |
style: :long, | |
lpfnWndProc: :pointer, | |
cbClsExtra: :int, | |
cbWndExtra: :int, | |
hInstance: :pointer, | |
hIcon: :pointer, | |
hCursor: :pointer, | |
hbrBackground: :pointer, | |
lpszMenuName: :pointer, | |
lpszClassName: :pointer | |
) | |
end | |
module GDI32 | |
extend DLLWrapper | |
target('gdi32') | |
#=== Functions | |
# HGDIOBJ GetStockObject(int fnObject); | |
define(:GetStockObject, :GetStockObject, [:int], :pointer) | |
#=== Constants | |
BLACK_BRUSH = 4 | |
end | |
module User32 | |
extend DLLWrapper | |
target('user32') | |
#=== Constants | |
MB_ICONERROR = 0x00000010 | |
SM_CXSCREEN = 0x00000000 | |
SM_CYSCREEN = 0x00000001 | |
SM_CYCAPTION = 0x00000004 | |
SM_CXFIXEDFRAME = 0x00000007 | |
SM_CYFIXEDFRAME = 0x00000008 | |
WS_EX_WINDOWEDGE = 0x00000100 | |
WS_POPUP = 0x80000000 | |
WS_CAPTION = 0x00C00000 | |
WS_SYSMENU = 0x00080000 | |
WS_MINIMIZEBOX = 0x00020000 | |
WS_VISIBLE = 0x10000000 | |
SW_SHOW = 0x00000005 | |
#=== Functions | |
# int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType); | |
define(:MessageBox, Omni::UTF8 ? :MessageBoxW : :MessageBoxA, [:pointer, :pointer, :pointer, :int], :int) | |
# HICON LoadIcon(HINSTANCE hInstance, LPCTSTR lpIconName); | |
define(:LoadIcon, :LoadIcon, [:pointer, :pointer], :pointer) | |
# HCURSOR LoadCursor(HINSTANCE hInstance, LPCTSTR lpCursorName); | |
define(:LoadCursor, :LoadCursor, [:pointer, :pointer], :pointer) | |
# ATOM RegisterClass(WNDCLASS *lpWndClass); | |
define(:_RegisterClass, Omni::UTF8 ? :RegisterClassW : :RegisterClassA, [:pointer], :pointer) | |
# int GetSystemMetrics(int nIndex); | |
define(:GetSystemMetrics, :GetSystemMetrics, [:int], :int) | |
# HWND CreateWindowEx(DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam); | |
define(:_CreateWindowEx, Omni::UTF8 ? :CreateWindowExW : :CreateWindowExA, [:dword, :pointer, :pointer, :dword, :int, :int, :int, :int, :pointer, :pointer, :pointer, :pointer], :pointer) | |
# BOOL ShowWindow(HWND hWnd, int nCmdShow); | |
define(:ShowWindow, :ShowWindow, [:pointer, :int], :int) | |
# BOOL DestroyWindow(HWND hWnd); | |
define(:DestroyWindow, :DestroyWindow, [:pointer], :int) | |
# BOOL UnregisterClass(LPCTSTR lpClassName, HINSTANCE hInstance); | |
define(:_UnregisterClass, Omni::UTF8 ? :UnregisterClassW : :UnregisterClassA, [:pointer, :pointer], :int) | |
# int LookupIconIdFromDirectoryEx(PBYTE presbits, BOOL fIcon, int cxDesired, int cyDesired, UINT Flags); | |
define(:LookupIconIdFromDirectoryEx, :LookupIconIdFromDirectoryEx, [:pointer, :int, :int, :int, :uint], :int) | |
#=== Functions+ | |
module_function | |
def RegisterClass(lpWndClass) | |
klass = Omni::WinAPI::WNDCLASS.new(lpWndClass) | |
klass.lpszClassName = Omni.encode(klass.lpszClassName) | |
_RegisterClass(lpWndClass) | |
end | |
def CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) | |
_CreateWindowEx( | |
dwExStyle, | |
Omni.encode(lpClassName), | |
Omni.encode(lpWindowName), | |
dwStyle, | |
x, y, nWidth, nHeight, | |
hWndParent, hMenu, hInstance, lpParam | |
) | |
end | |
def UnregisterClass(lpClassName, hInstance) | |
_UnregisterClass(Omni.encode(lpClassName), hInstance) | |
end | |
end | |
module Kernel32 | |
extend DLLWrapper | |
target('kernel32') | |
#=== Functions | |
# HMODULE GetModuleHandle(LPCTSTR lpModuleName); | |
define(:GetModuleHandle, Omni::UTF8 ? :GetModuleHandleW : :GetModuleHandleA, [:pointer], :pointer) | |
# DWORD GetModuleFileName(HMODULE hModule, LPTSTR lpFilename, DWORD nSize); | |
define(:GetModuleFileName, Omni::UTF8 ? :GetModuleFileNameW : :GetModuleFileNameA, [:pointer, :pointer, :dword], :dword) | |
# int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar); | |
define(:_MultiByteToWideChar, :MultiByteToWideChar, [:uint, :dword, :pointer, :int, :pointer, :int], :int) | |
# int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar); | |
define(:_WideCharToMultiByte, :WideCharToMultiByte, [:uint, :dword, :pointer, :int, :pointer, :int, :pointer, :long], :int) | |
# DWORD GetPrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault, LPTSTR lpReturnedString, DWORD nSize, LPCTSTR lpFileName); | |
define(:_GetPrivateProfileString, Omni::UTF8 ? :GetPrivateProfileStringW : :GetPrivateProfileStringA, [:pointer, :pointer, :pointer, :pointer, :dword, :pointer], :dword) | |
# DWORD GetLastError(void); | |
define(:GetLastError, :GetLastError, [], :dword) | |
# HMODULE LoadLibrary(LPCTSTR lpFileName); | |
define(:_LoadLibrary, Omni::UTF8 ? :LoadLibraryW : :LoadLibraryA, [:pointer], :pointer) | |
# BOOL FreeLibrary(HMODULE hModule); | |
define(:FreeLibrary, :FreeLibrary, [:pointer], :int) | |
# BOOL AllocConsole(void); | |
define(:AllocConsole, :AllocConsole, [], :int) | |
# BOOL SetConsoleTitle(LPCTSTR lpConsoleTitle); | |
define(:_SetConsoleTitle, Omni::UTF8 ? :SetConsoleTitleW : :SetConsoleTitleA, [:pointer], :int) | |
#=== Functions+ | |
module_function | |
def MultiByteToWideChar(lpMultiByteStr) | |
lpWideCharStr = "" | |
cchWideChar = 0 | |
cchWideChar = _MultiByteToWideChar(65001, 0, lpMultiByteStr, -1, lpWideCharStr, cchWideChar) | |
lpWideCharStr = 0.chr * (2 * cchWideChar) | |
_MultiByteToWideChar(65001, 0, lpMultiByteStr, -1, lpWideCharStr, cchWideChar) | |
return lpWideCharStr | |
end | |
def WideCharToMultiByte(lpWideCharStr) | |
cchWideChar = -1 | |
lpMultiByteStr = "" | |
cbMultiByte = 0 | |
cbMultiByte = _WideCharToMultiByte(65001, 0, lpWideCharStr, cchWideChar, lpMultiByteStr, cbMultiByte, nil, 0) | |
lpMultiByteStr = 0.chr * cbMultiByte | |
size = _WideCharToMultiByte(65001, 0, lpWideCharStr, cchWideChar, lpMultiByteStr, cbMultiByte, nil, 0) | |
return lpMultiByteStr[0, size - 1] | |
end | |
def GetPrivateProfileString(lpAppName, lpKeyName, lpDefault, lpReturnedString, nSize, lpFilename) | |
_GetPrivateProfileString(Omni.encode(lpAppName), Omni.encode(lpKeyName), Omni.encode(lpDefault), lpReturnedString, nSize, Omni.encode(lpFilename)) | |
return lpReturnedString | |
end | |
def LoadLibrary(lpFileName) | |
k = Omni.encode(lpFileName).to_s | |
_LoadLibrary(k) | |
end | |
def SetConsoleTitle(lpConsoleTitle) | |
_SetConsoleTitle(Omni.encode(lpConsoleTitle)) | |
end | |
end | |
#============================== | |
# Functions Section | |
module_function | |
def createBuffer(size) | |
return Fiddle::Pointer.malloc(size) | |
end | |
def encode(str) | |
Omni::UTF8 ? Kernel32.MultiByteToWideChar(str) : str | |
end | |
def decode(str) | |
Omni::UTF8 ? Kernel32.WideCharToMultiByte(str) : str | |
end | |
def showError(hWnd, title, format, *args) | |
msg = sprintf(format, *args) | |
User32.MessageBox(hWnd, encode(msg), encode(title), User32::MB_ICONERROR) | |
end | |
def exit(wndClass = nil, hWnd = nil, core = nil) | |
User32.UnregisterClass(wndClass, HInstance) if wndClass | |
User32.DestroyWindow(hWnd) if hWnd | |
Kernel32.FreeLibrary(core) if core | |
Kernel.exit | |
end | |
#============================== | |
# Initialize Section | |
HInstance = Kernel32.GetModuleHandle(WinAPI::NULL) | |
end | |
#============================== | |
# Omni RGSS Player Start | |
# AppPath | |
buffer = Omni.createBuffer(Omni::WinAPI::MAX_PATH) | |
Omni::Kernel32.GetModuleFileName(Omni::HInstance, buffer, buffer.size) | |
AppPath = Dir.pwd # File.dirname(Omni.decode(buffer)) | |
# IniPath | |
IniPath = File.join(AppPath, Omni::IniName) | |
# RGSSAD / RGSS2A / RGSS3A Path | |
CryptoPath = File.join(AppPath, Omni::CryptoName) | |
# Ini data | |
IniData = Omni::DefaultData.clone | |
if File.exist?(IniPath) | |
IniData.each_pair{|key, default| | |
tmpBuffer = Omni.createBuffer(Omni::WinAPI::MAX_PATH) | |
size = Omni::Kernel32.GetPrivateProfileString("Game", key.to_s, default, tmpBuffer, tmpBuffer.size, IniPath) | |
IniData[key] = Omni.decode(tmpBuffer) | |
} | |
end | |
# CryptoPath | |
if File.exist?(CryptoPath) | |
CryptoPointer = Fiddle::Pointer[CryptoPath] | |
else | |
CryptoPointer = Fiddle::Pointer.new(0) | |
end | |
# Window Class Creation/Register | |
winclass = Omni::WinAPI::WNDCLASS.malloc | |
winclass.style = Omni::WinAPI::CS_DBLCLKS | Omni::WinAPI::CS_OWNDC | Omni::WinAPI::CS_HREDRAW | Omni::WinAPI::CS_VREDRAW | |
winclass.lpfnWndProc = Omni::User32.getAddress(:DefWindowProc) | |
winclass.cbClsExtra = 0 | |
winclass.cbWndExtra = 0 | |
winclass.hInstance = Omni::HInstance | |
winclass.hIcon = Omni::User32.LoadIcon(Omni::HInstance, Omni::WinAPI::IDI_APPLICATION) | |
winclass.hCursor = Omni::User32.LoadCursor(Omni::WinAPI::NULL, Omni::WinAPI::IDC_ARROW) | |
winclass.hbrBackground = Omni::GDI32.GetStockObject(Omni::GDI32::BLACK_BRUSH) | |
winclass.lpszMenuName = Omni::WinAPI::NULL | |
winclass.lpszClassName = Omni::WndClassName | |
if Omni::User32.RegisterClass(winclass.to_ptr).null? | |
Omni.showError(0, IniData[:Title], "Erro ao criar classe de janela: %s", Omni::WndClassName) | |
Omni.exit | |
end | |
# Create & Show Window | |
width = Omni::ScreenWidth + Omni::User32.GetSystemMetrics(Omni::User32::SM_CXFIXEDFRAME) * 2 | |
height = Omni::ScreenHeight + Omni::User32.GetSystemMetrics(Omni::User32::SM_CYFIXEDFRAME) * 2 + Omni::User32.GetSystemMetrics(Omni::User32::SM_CYCAPTION) | |
left = (Omni::User32.GetSystemMetrics(Omni::User32::SM_CXSCREEN) - width) / 2 | |
top = (Omni::User32.GetSystemMetrics(Omni::User32::SM_CYSCREEN) - height) / 2 | |
dwStyle = (Omni::User32::WS_POPUP | Omni::User32::WS_CAPTION | Omni::User32::WS_SYSMENU | Omni::User32::WS_MINIMIZEBOX | Omni::User32::WS_VISIBLE) | |
hWnd = Omni::User32.CreateWindowEx( | |
Omni::User32::WS_EX_WINDOWEDGE, | |
Omni::WndClassName, | |
IniData[:Title], | |
dwStyle, | |
left, top, width, height, | |
0, 0, Omni::HInstance, 0 | |
) | |
if hWnd.null? | |
Omni.showError(0, IniData[:Title], "Erro ao criar janela do Omni RGSS Player"); | |
Omni.exit(Omni::WndClassName) | |
end | |
if ARGV.include?("console") | |
unless Omni::Kernel32.AllocConsole.zero? | |
Omni::Kernel32.SetConsoleTitle("RGSS Console") | |
$stdout.reopen("conout$") | |
end | |
end | |
Omni::User32.ShowWindow(hWnd, Omni::User32::SW_SHOW); | |
# Load RGSS Core | |
RGSSCore = Omni::Kernel32.LoadLibrary(IniData[:Library]) | |
if RGSSCore.null? | |
Omni.showError(hWnd, IniData[:Title], "Erro ao carregar %s", IniData[:Library]) | |
Omni.exit(Omni::WndClassName, hWnd) | |
end | |
module Omni::RGSS | |
extend DLLWrapper | |
target(IniData[:Library]) | |
#=== Constants | |
EvalErrorCode = 6 | |
#=== Functions | |
# BOOL (*RGSSSetupRTP)(const wchar_t* pIniPath, wchar_t* pErrorMsgBuffer, int iBufferLength); | |
define(:_SetupRTP, :RGSSSetupRTP, [:pointer, :pointer, :int], :int) | |
# void (*RGSSInitializeX)(HMODULE hRgssDll); | |
define(:Initialize, Omni::Version == 1 ? :RGSSInitialize : Omni::Version == 2 ? :RGSSInitialize2 : :RGSSInitialize3, [:pointer], :void) | |
# int (*RGSSEval)(const char* pScripts); | |
define(:_Eval, :RGSSEval, [:pointer], :int) | |
# void (*RGSSGameMain)(HWND hWnd, const wchar_t* pScriptNames, wchar_t** pRgssadName); | |
define(:_GameMain, :RGSSGameMain, [:pointer, :pointer, :pointer], :void) | |
if (Omni::Version > 1) | |
# void (*RGSSSetupFonts)(); | |
define(:SetupFonts, :RGSSSetupFonts, [], :void) | |
end | |
#=== Functions+ | |
module_function | |
def SetupRTP(pIniPath, pErrorMsgBuffer, iBufferLength) | |
_SetupRTP(Omni.encode(pIniPath), pErrorMsgBuffer, iBufferLength) | |
end | |
def Eval(str) | |
result = _Eval(str) | |
raise(Exception, "RGSSEval falhou.", caller) if (result == EvalErrorCode) | |
return result | |
end | |
def GameMain(hWnd, pScriptNames, pRgssadName) | |
_GameMain(hWnd, Omni.encode(pScriptNames), pRgssadName) | |
end | |
end | |
# 1 - RTP | |
RTPName = Omni.createBuffer(1024) | |
if Omni::RGSS.SetupRTP(IniPath, RTPName, RTPName.size).zero? | |
Omni.showError(hWnd, IniData[:Title], "Erro ao carregar RTP: %s", RTPName) | |
Omni.exit(Omni::WndClassName, hWnd, RGSSCore) | |
end | |
# 2 - Initialize RGSS | |
Omni::RGSS.Initialize(RGSSCore) | |
# 3 - Setup Fonts | |
Omni::RGSS.SetupFonts if (Omni::Version > 1) | |
# 4 - Process command lines | |
if ARGV.include?("btest") | |
CryptoPointer = Fiddle::Pointer.new(0) | |
Omni::RGSS.Eval("$TEST = true") | |
Omni::RGSS.Eval("$BTEST = true") | |
else | |
if ARGV.include?("test") | |
CryptoPointer = Fiddle::Pointer.new(0) | |
Omni::RGSS.Eval("$TEST = true") | |
else | |
Omni::RGSS.Eval("$TEST = false") | |
end | |
Omni::RGSS.Eval("$BTEST = false") | |
end | |
# 5 - Run, Forest, Run | |
Omni::RGSS.GameMain(hWnd, IniData[:Scripts], CryptoPointer.null? ? CryptoPointer.ref : Fiddle::Pointer[Omni.encode(CryptoPointer)]) | |
# 6 - End | |
Omni.exit(Omni::WndClassName, hWnd, RGSSCore) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Tem como usar o Socket.so nesse Emulador?? usar mais ruby nele?