Skip to content

Instantly share code, notes, and snippets.

@gabteles gabteles/Game.rb
Last active Sep 24, 2017

Embed
What would you like to do?
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

This comment has been minimized.

Copy link

klebersonromero commented Sep 24, 2017

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
You can’t perform that action at this time.