Skip to content

Instantly share code, notes, and snippets.

@gabteles
Last active January 21, 2024 22:32
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gabteles/10000006 to your computer and use it in GitHub Desktop.
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.
# 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)
@klebersonromero
Copy link

Tem como usar o Socket.so nesse Emulador?? usar mais ruby nele?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment