chore: initial commit

This commit is contained in:
fallenoak 2023-01-02 13:17:18 -06:00
commit 70b00c5c38
No known key found for this signature in database
GPG Key ID: 7628F8E61AEA070D
965 changed files with 264882 additions and 0 deletions

17
.editorconfig Normal file
View File

@ -0,0 +1,17 @@
root = true
[src/**/*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[test/**/*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

35
.github/workflows/pr.yml vendored Normal file
View File

@ -0,0 +1,35 @@
name: PR
on: [pull_request]
jobs:
build:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
strategy:
fail-fast: false
matrix:
config:
- name: Ubuntu Latest (GCC)
os: ubuntu-latest
build_type: Release
cc: "gcc"
cxx: "g++"
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Prepare
run: mkdir build
- name: Configure
run: cd build && cmake .. -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }}
- name: Build
run: cd build && make install
- name: Test
run: cd build && ./dist/bin/WhoaTest

38
.github/workflows/push.yml vendored Normal file
View File

@ -0,0 +1,38 @@
name: Push
on:
push:
branches:
- master
jobs:
build:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
strategy:
fail-fast: false
matrix:
config:
- name: Ubuntu Latest (GCC)
os: ubuntu-latest
build_type: Release
cc: "gcc"
cxx: "g++"
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Prepare
run: mkdir build
- name: Configure
run: cd build && cmake .. -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }}
- name: Build
run: cd build && make install
- name: Test
run: cd build && ./dist/bin/WhoaTest

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
.DS_Store
.vscode
.idea
/build
/cmake-build-*

12
.gitmodules vendored Normal file
View File

@ -0,0 +1,12 @@
[submodule "lib/common"]
path = lib/common
url = https://github.com/whoahq/common.git
[submodule "lib/squall"]
path = lib/squall
url = https://github.com/whoahq/squall.git
[submodule "lib/typhoon"]
path = lib/typhoon
url = https://github.com/whoahq/typhoon.git
[submodule "lib/system"]
path = lib/system
url = https://github.com/whoahq/system.git

50
CMakeLists.txt Normal file
View File

@ -0,0 +1,50 @@
cmake_minimum_required(VERSION 3.1)
if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
message(FATAL_ERROR
"In-source builds not allowed.
Please make a new directory (called a build directory) and run CMake from there.
You may need to remove CMakeCache.txt."
)
endif()
# OS variables
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14" CACHE STRING "macOS Deployment Target" FORCE)
# Project
project(whoa)
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "dist" CACHE PATH "Installation prefix" FORCE)
endif()
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_BUILD_TYPE Debug)
# Some templates abuse offsetof
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-offsetof")
# OS defines
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
add_definitions(
-DGL_SILENCE_DEPRECATION
)
endif()
include(lib/system/cmake/system.cmake)
# Threads
if(WHOA_SYSTEM_LINUX OR WHOA_SYSTEM_MAC)
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Threads REQUIRED)
endif()
add_subdirectory(lib)
add_subdirectory(src)
add_subdirectory(test)
add_subdirectory(vendor)

47
README.md Normal file
View File

@ -0,0 +1,47 @@
# Whoa
Welcome to Whoa, a reimplementation of World of Warcraft 3.3.5a (build 12340) in C++11.
## Supported Platforms
Currently, macOS 10.14+ is supported, including recent versions of macOS on M1 processors. Support for Linux is in progress. Support for Windows is coming soon™.
## Building
To build, ensure you have a recent version of CMake installed, and run the following from the `whoa` directory:
```
mkdir build && cd build
cmake ..
make install
```
Assuming all went well, you should see a `dist/bin` directory appear in the `build` directory. The `bin` directory will contain a `whoa` executable.
## Running
Whoa doesn't currently support reading from MPQ archives. Instead, it assumes you are launching the Whoa executable from the root of a fully extracted MPQ archive set for World of Warcraft 3.3.5a (build 12340). You can obtain a valid set of MPQ archives to extract by installing World of Warcraft 3.3.5a from legally purchased original install media. Whoa does not provide any copy of game data.
Assuming all goes well, you should be greeted by the login screen, complete with its flying dragon animation loop.
Whoa is very much a work-in-progress: it does not fully connect to a login server, does not play back sound or music, and does not support customizing settings. These things will be supported over time.
## FAQ
**Why?**
It's fascinating to explore the development practices used to build a modern major video game.
**Why 3.3.5a?**
The game and its libraries have become significantly more complex in the intervening 10+ years. By picking 3.3.5a, it's possible to imagine this implementation will eventually be complete.
**Can I use this in my own development projects?**
It's probably a bad idea. The game is closed source, and this project is in no way official.
## Legal
This project is released into the public domain.
World of Warcraft: Wrath of the Lich King ©2008 Blizzard Entertainment, Inc. All rights reserved. Wrath of the Lich King is a trademark, and World of Warcraft, Warcraft and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries.

4
lib/CMakeLists.txt Normal file
View File

@ -0,0 +1,4 @@
add_subdirectory(common)
add_subdirectory(squall)
add_subdirectory(system)
add_subdirectory(typhoon)

1
lib/common Submodule

@ -0,0 +1 @@
Subproject commit ff3c28bbd910983147ddc1d99d83c482ae23df7d

1
lib/squall Submodule

@ -0,0 +1 @@
Subproject commit e3b0c356adc0abb4ad5c549951a5423b6edaf64d

1
lib/system Submodule

@ -0,0 +1 @@
Subproject commit f886ab5bc35b2e0d968baa8dec3faaccf385fbc3

1
lib/typhoon Submodule

@ -0,0 +1 @@
Subproject commit 36d177759d273ae599e7c99920466e4886d57a41

13
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,13 @@
add_subdirectory(app)
add_subdirectory(async)
add_subdirectory(client)
add_subdirectory(event)
add_subdirectory(glue)
add_subdirectory(gx)
add_subdirectory(math)
add_subdirectory(model)
add_subdirectory(net)
add_subdirectory(sound)
add_subdirectory(ui)
add_subdirectory(util)
add_subdirectory(world)

48
src/app/CMakeLists.txt Normal file
View File

@ -0,0 +1,48 @@
if(WHOA_SYSTEM_MAC)
file(GLOB PRIVATE_SOURCES "mac/*.cpp" "mac/*.mm")
set_source_files_properties(${PRIVATE_SOURCES}
PROPERTIES COMPILE_FLAGS "-x objective-c++"
)
add_executable(Whoa ${PRIVATE_SOURCES})
target_link_libraries(Whoa
PRIVATE
client
event
gx
net
util
"-framework AppKit"
"-framework Carbon"
"-framework IOKit"
)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mac/MainMenu.nib DESTINATION "bin")
endif()
if(WHOA_SYSTEM_LINUX)
file(GLOB PRIVATE_SOURCES "linux/*.cpp")
add_executable(Whoa ${PRIVATE_SOURCES})
target_link_libraries(Whoa
PRIVATE
client
event
gx
net
util
)
endif()
target_include_directories(Whoa
PRIVATE
${CMAKE_SOURCE_DIR}/src
)
# Windows executables yet to be done
if(WHOA_SYSTEM_MAC OR WHOA_SYSTEM_LINUX)
install(TARGETS Whoa DESTINATION "bin")
endif()

11
src/app/linux/Wowre.cpp Normal file
View File

@ -0,0 +1,11 @@
#include "client/Client.hpp"
int main(int argc, char* argv[]) {
// TODO
CommonMain();
// TODO
return 0;
}

View File

@ -0,0 +1,16 @@
#ifndef APP_MAC_ENGINE_GL_LAYER_VIEW_H
#define APP_MAC_ENGINE_GL_LAYER_VIEW_H
#include "gx/gll/GLLayerView.h"
#include <AppKit/AppKit.h>
#include <Foundation/Foundation.h>
@interface EngineGLLayerView : GLLayerView
- (void)insertText:(id)string;
- (void)keyDown:(NSEvent*)event;
@end
#endif

View File

@ -0,0 +1,41 @@
#include "app/mac/EngineGLLayerView.h"
#include "app/mac/MacClient.h"
#include "event/Input.hpp"
#include <Carbon/Carbon.h>
@implementation EngineGLLayerView
- (void)insertText:(id)string {
// TODO
}
- (void)keyDown:(NSEvent*)event {
uint32_t keyCode = event.keyCode;
MacClient::CheckKeyboardLayout();
if (keyCode <= 0x7F) {
uint32_t key = MacClient::s_keyConversion[keyCode];
if (key != KEY_NONE) {
OsQueuePut(OS_INPUT_KEY_DOWN, key, 0, 0, 0);
}
}
if (MacClient::GetTextInputEnabled()) {
auto events = [NSArray arrayWithObject:event];
[self interpretKeyEvents:events];
} else {
EventRef eventRef = static_cast<EventRef>(const_cast<void*>([event eventRef]));
uint8_t chr;
if (GetEventParameter(eventRef, 'kchr', 'TEXT', 0, 1, 0, &chr) == noErr) {
if (chr > 0x1F && chr <= 0x7E) {
OsQueuePut(OS_INPUT_CHAR, chr, 1, 0, 0);
}
}
}
}
@end

30
src/app/mac/MacClient.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef APP_MAC_MAC_CLIENT_H
#define APP_MAC_MAC_CLIENT_H
#include "event/Event.hpp"
#include <cstdint>
class MacClient {
public:
enum ClipboardAction {
ClipboardUndo = 1,
ClipboardCut = 2,
ClipboardCopy = 3,
ClipboardPaste = 4,
ClipboardSelectAll = 5
};
static void* s_currentKeyboardLayout;
static KEY s_specialKeyConversion[128];
static KEY s_keyConversion[128];
static void CheckKeyboardLayout(void);
static double GetMouseSpeed(void);
static bool GetTextInputEnabled(void);
static void InitializeKeyConversion(void);
static bool IsUsingGLLayer(void);
static void PostClipboardKeyEvents(MacClient::ClipboardAction);
static void SetMouseCoalescingEnabled(bool);
};
#endif

375
src/app/mac/MacClient.mm Normal file
View File

@ -0,0 +1,375 @@
#include "app/mac/MacClient.h"
#include "event/Input.hpp"
#include "os/Compat.hpp"
#include <AppKit/AppKit.h>
#include <Carbon/Carbon.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/hidsystem/event_status_driver.h>
#include <IOKit/hidsystem/IOHIDLib.h>
#include <IOKit/hidsystem/IOHIDParameter.h>
void* MacClient::s_currentKeyboardLayout = nullptr;
KEY MacClient::s_specialKeyConversion[128] = {
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_1, // kVK_ANSI_1 (0x12)
KEY_2, // kVK_ANSI_2 (0x13)
KEY_3, // kVK_ANSI_3 (0x14)
KEY_4, // kVK_ANSI_4 (0x15)
KEY_6, // kVK_ANSI_6 (0x16)
KEY_5, // kVK_ANSI_5 (0x17)
KEY_NONE,
KEY_9, // kVK_ANSI_9 (0x19)
KEY_7, // kVK_ANSI_7 (0x1A)
KEY_NONE,
KEY_8, // kVK_ANSI_8 (0x1C)
KEY_0, // kVK_ANSI_0 (0x1D)
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_ENTER, // kVK_Return (0x24)
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_TAB, // kVK_Tab (0x30)
KEY_SPACE, // kVK_Space (0x31)
KEY_NONE,
KEY_BACKSPACE, // kVK_Delete (0x33)
KEY_NONE,
KEY_ESCAPE, // kVK_Escape (0x35)
KEY_NONE,
KEY_NONE,
KEY_LSHIFT, // kVK_Shift (0x38)
KEY_CAPSLOCK, // kVK_CapsLock (0x39)
KEY_LALT, // kVK_Option (0x3A)
KEY_LCONTROL, // kVK_Control (0x3B)
KEY_RSHIFT, // kVK_RightShift (0x3C)
KEY_RALT, // kVK_RightOption (0x3D)
KEY_RCONTROL, // kVK_RightControl (0x3E)
KEY_NONE,
KEY_F17, // kVK_F17 (0x40)
KEY_NUMPAD_DECIMAL, // kVK_ANSI_KeypadDecimal (0x41)
KEY_NONE,
KEY_NUMPAD_MULTIPLY, // kVK_ANSI_KeypadMultiply (0x43)
KEY_NONE,
KEY_NUMPAD_PLUS, // kVK_ANSI_KeypadPlus (0x45)
KEY_NONE,
KEY_NUMLOCK, // kVK_ANSI_KeypadClear (0x47)
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_NUMPAD_DIVIDE, // kVK_ANSI_KeypadDivide (0x4B)
KEY_ENTER, // kVK_ANSI_KeypadEnter (0x4C)
KEY_NONE,
KEY_NUMPAD_MINUS, // kVK_ANSI_KeypadMinus (0x4E)
KEY_F18, // kVK_F18 (0x4F)
KEY_F19, // kVK_F19 (0x50)
KEY_NUMPAD_EQUALS, // kVK_ANSI_KeypadEquals (0x51)
KEY_NUMPAD0, // kVK_ANSI_Keypad0 (0x52)
KEY_NUMPAD1, // kVK_ANSI_Keypad1 (0x53)
KEY_NUMPAD2, // kVK_ANSI_Keypad2 (0x54)
KEY_NUMPAD3, // kVK_ANSI_Keypad3 (0x55)
KEY_NUMPAD4, // kVK_ANSI_Keypad4 (0x56)
KEY_NUMPAD5, // kVK_ANSI_Keypad5 (0x57)
KEY_NUMPAD6, // kVK_ANSI_Keypad6 (0x58)
KEY_NUMPAD7, // kVK_ANSI_Keypad7 (0x59)
KEY_NONE,
KEY_NUMPAD8, // kVK_ANSI_Keypad8 (0x5B)
KEY_NUMPAD9, // kVK_ANSI_Keypad9 (0x5C)
KEY_NONE,
KEY_NONE,
KEY_NONE,
KEY_F5, // kVK_F5 (0x60)
KEY_F6, // kVK_F6 (0x61)
KEY_F7, // kVK_F7 (0x62)
KEY_F3, // kVK_F3 (0x63)
KEY_F8, // kVK_F8 (0x64)
KEY_F9, // kVK_F9 (0x65)
KEY_NONE,
KEY_F11, // kVK_F11 (0x67)
KEY_NONE,
KEY_F13, // kVK_F13 (0x69)
KEY_F16, // kVK_F16 (0x6A)
KEY_F14, // kVK_F14 (0x6B)
KEY_NONE,
KEY_F10, // kVK_F10 (0x6D)
KEY_NONE,
KEY_F12, // kVK_F12 (0x6F)
KEY_NONE,
KEY_F15, // kVK_F15 (0x71)
KEY_INSERT, // kVK_Help (0x72)
KEY_HOME, // kVK_Home (0x73)
KEY_PAGEUP, // kVK_PageUp (0x74)
KEY_DELETE, // kVK_ForwardDelete (0x75)
KEY_F4, // kVK_F4 (0x76)
KEY_END, // kVK_End (0x77)
KEY_F2, // kVK_F2 (0x78)
KEY_PAGEDOWN, // kVK_PageDown (0x79)
KEY_F1, // kVK_F1 (0x7A)
KEY_LEFT, // kVK_LeftArrow (0x7B)
KEY_RIGHT, // kVK_RightArrow (0x7C)
KEY_DOWN, // kVK_DownArrow (0x7D)
KEY_UP, // kVK_UpArrow (0x7E)
KEY_NONE
};
KEY MacClient::s_keyConversion[128];
void MacClient::CheckKeyboardLayout() {
#if WHOA_SYSTEM_VERSION < WHOA_MACOS_10_6
void* KCHR = reinterpret_cast<void*>(GetScriptManagerVariable(smKCHRCache));
if (MacClient::s_currentKeyboardLayout != KCHR) {
MacClient::InitializeKeyConversion();
MacClient::s_currentKeyboardLayout = KCHR;
}
#endif
#if WHOA_SYSTEM_VERSION >= WHOA_MACOS_10_6
TISInputSourceRef inputSrc = TISCopyCurrentKeyboardLayoutInputSource();
CFDataRef layoutData = static_cast<CFDataRef>(TISGetInputSourceProperty(inputSrc, kTISPropertyUnicodeKeyLayoutData));
const UCKeyboardLayout* keyboardLayout = reinterpret_cast<const UCKeyboardLayout*>(CFDataGetBytePtr(layoutData));
if (MacClient::s_currentKeyboardLayout != keyboardLayout) {
MacClient::InitializeKeyConversion();
MacClient::s_currentKeyboardLayout = const_cast<UCKeyboardLayout*>(keyboardLayout);
}
#endif
}
double MacClient::GetMouseSpeed() {
#if WHOA_SYSTEM_VERSION < WHOA_MACOS_10_12
double mouseSpeed = 1.0;
NXEventHandle handle = NXOpenEventStatus();
if (handle) {
IOHIDGetAccelerationWithKey(handle, CFSTR(kIOHIDMouseAccelerationType), &mouseSpeed);
NXCloseEventStatus(handle);
}
return mouseSpeed;
#endif
#if WHOA_SYSTEM_VERSION >= WHOA_MACOS_10_12
double mouseSpeed = 1.0;
io_service_t service = IORegistryEntryFromPath(kIOMasterPortDefault, kIOServicePlane ":/IOResources/IOHIDSystem");
if (service != MACH_PORT_NULL) {
CFDictionaryRef parameters = static_cast<CFDictionaryRef>(IORegistryEntryCreateCFProperty(service, CFSTR(kIOHIDParametersKey), kCFAllocatorDefault, kNilOptions));
CFNumberRef speedParameter = static_cast<CFNumberRef>(CFDictionaryGetValue(parameters, CFSTR(kIOHIDMouseAccelerationType)));
if (speedParameter) {
int32_t number;
if (CFNumberGetValue(static_cast<CFNumberRef>(speedParameter), kCFNumberSInt32Type, &number)) {
mouseSpeed = static_cast<double>(number) / 65536.0;
}
}
CFRelease(parameters);
IOObjectRelease(service);
}
return mouseSpeed;
#endif
}
bool MacClient::GetTextInputEnabled() {
// TODO
return false;
}
void MacClient::InitializeKeyConversion() {
memcpy(MacClient::s_keyConversion, MacClient::s_specialKeyConversion, sizeof(MacClient::s_specialKeyConversion));
#if WHOA_SYSTEM_VERSION < WHOA_MACOS_10_6
void* KCHR = reinterpret_cast<void*>(GetScriptManagerVariable(smKCHRCache));
if (KCHR) {
for (uint16_t i = 0; i < 128; i++) {
if (MacClient::s_keyConversion[i] == KEY_NONE) {
uint16_t translate = i | (1 << 7);
uint32_t state = 0;
uint32_t value = KeyTranslate(KCHR, translate, &state);
if (state) {
value = KeyTranslate(KCHR, translate, &state);
}
if (value) {
value = value - 97 <= 25 ? value - 32 : value;
auto string = CFStringCreateWithBytes(
nullptr,
reinterpret_cast<uint8_t*>(&value),
1,
0,
false
);
if (string) {
CFIndex len;
CFRange range = CFRangeMake(0, 1);
CFStringGetBytes(
string,
range,
kCFStringEncodingISOLatin1,
0,
0,
reinterpret_cast<uint8_t*>(&value),
1,
&len
);
if (len && value) {
MacClient::s_keyConversion[i] = static_cast<KEY>(value);
}
}
}
}
}
}
#endif
#if WHOA_SYSTEM_VERSION >= WHOA_MACOS_10_6
TISInputSourceRef inputSrc = TISCopyCurrentKeyboardLayoutInputSource();
CFDataRef layoutData = static_cast<CFDataRef>(TISGetInputSourceProperty(inputSrc, kTISPropertyUnicodeKeyLayoutData));
const UCKeyboardLayout* keyboardLayout = reinterpret_cast<const UCKeyboardLayout*>(CFDataGetBytePtr(layoutData));
const uint32_t keyboardType = LMGetKbdType();
if (keyboardLayout) {
for (uint16_t i = 0; i < 128; i++) {
if (MacClient::s_keyConversion[i] == KEY_NONE) {
uint16_t vkey = i;
uint32_t state = 0;
UniChar buf[1];
UniCharCount len;
OSStatus res = UCKeyTranslate(
keyboardLayout,
vkey,
kUCKeyActionUp,
0,
keyboardType,
0,
&state,
1,
&len,
buf
);
if (res != noErr) {
continue;
}
if (state) {
res = UCKeyTranslate(
keyboardLayout,
vkey,
kUCKeyActionUp,
0,
keyboardType,
0,
&state,
1,
&len,
buf
);
if (res != noErr) {
continue;
}
}
uint16_t value = buf[0];
if (len && value) {
value = value >= 97 && value <= 122 ? value - 32 : value;
MacClient::s_keyConversion[i] = static_cast<KEY>(value);
}
}
}
}
#endif
}
bool MacClient::IsUsingGLLayer() {
return true;
}
void MacClient::PostClipboardKeyEvents(MacClient::ClipboardAction action) {
int32_t v1;
switch (action) {
case ClipboardUndo:
v1 = 90;
break;
case ClipboardCut:
v1 = 88;
break;
case ClipboardCopy:
v1 = 67;
break;
case ClipboardPaste:
v1 = 86;
break;
case ClipboardSelectAll:
v1 = 65;
break;
default:
return;
}
OsInputPostEvent(OS_INPUT_KEY_DOWN, 2, 0, 0, 0);
OsInputPostEvent(OS_INPUT_KEY_DOWN, v1, 0, 0, 0);
OsInputPostEvent(OS_INPUT_KEY_UP, v1, 0, 0, 0);
OsInputPostEvent(OS_INPUT_KEY_UP, 2, 0, 0, 0);
}
void MacClient::SetMouseCoalescingEnabled(bool enabled) {
#if WHOA_SYSTEM_VERSION < WHOA_MACOS_10_5
bool prevEnabled = false;
SetMouseCoalescingEnabled(true, &prevEnabled);
#endif
#if WHOA_SYSTEM_VERSION >= WHOA_MACOS_10_5
[NSEvent setMouseCoalescingEnabled: enabled];
#endif
}

8
src/app/mac/Main.nib/classes.nib generated Executable file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBVersion</key>
<string>1</string>
</dict>
</plist>

18
src/app/mac/Main.nib/info.nib generated Executable file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBFramework Version</key>
<string>677</string>
<key>IBLastKnownRelativeProjectPath</key>
<string>../../../WoW.xcodeproj</string>
<key>IBOldestOS</key>
<integer>3</integer>
<key>IBOpenObjects</key>
<array/>
<key>IBSystem Version</key>
<string>9J61</string>
<key>targetFramework</key>
<string>IBCarbonFramework</string>
</dict>
</plist>

131
src/app/mac/Main.nib/objects.xib Executable file
View File

@ -0,0 +1,131 @@
<?xml version="1.0" standalone="yes"?>
<object class="NSIBObjectData">
<object name="rootObject" class="NSCustomObject" id="1">
</object>
<array count="17" name="allObjects">
<object class="IBCarbonMenuItem" id="144">
<string name="title">Paste</string>
<string name="keyEquivalent">v</string>
<ostype name="command">past</ostype>
</object>
<object class="IBCarbonMenuItem" id="142">
<boolean name="separator">TRUE</boolean>
</object>
<object class="IBCarbonMenuItem" id="149">
<string name="title">Copy</string>
<string name="keyEquivalent">c</string>
<ostype name="command">copy</ostype>
</object>
<object class="IBCarbonMenuItem" id="183">
<string name="title">About World of Warcraft...</string>
<int name="keyEquivalentModifier">0</int>
<ostype name="command">abou</ostype>
</object>
<object class="IBCarbonMenu" id="181">
<string name="title">World of Warcraft</string>
<string name="name">_NSAppleMenu</string>
<array count="3" name="items">
<reference idRef="183"/>
<object class="IBCarbonMenuItem" id="186">
<boolean name="separator">TRUE</boolean>
</object>
<object class="IBCarbonMenuItem" id="187">
<string name="title">Switch To Full Screen Mode</string>
<string name="keyEquivalent">m</string>
<ostype name="command">Full</ostype>
</object>
</array>
</object>
<object class="IBCarbonMenuItem" id="152">
<string name="title">Edit</string>
<object name="submenu" class="IBCarbonMenu" id="147">
<string name="title">Edit</string>
<int name="menuID">128</int>
<array count="6" name="items">
<object class="IBCarbonMenuItem" id="141">
<string name="title">Undo</string>
<string name="keyEquivalent">z</string>
<ostype name="command">undo</ostype>
</object>
<reference idRef="142"/>
<object class="IBCarbonMenuItem" id="143">
<string name="title">Cut</string>
<string name="keyEquivalent">x</string>
<ostype name="command">cut </ostype>
</object>
<reference idRef="149"/>
<reference idRef="144"/>
<object class="IBCarbonMenuItem" id="148">
<string name="title">Select All</string>
<string name="keyEquivalent">a</string>
<ostype name="command">sall</ostype>
</object>
</array>
</object>
</object>
<object class="IBCarbonMenu" id="29">
<string name="title">Untitled</string>
<string name="name">_NSMainMenu</string>
<array count="2" name="items">
<object class="IBCarbonMenuItem" id="182">
<string name="title">World of Warcraft</string>
<reference name="submenu" idRef="181"/>
</object>
<reference idRef="152"/>
</array>
</object>
<reference idRef="141"/>
<reference idRef="143"/>
<object class="IBCarbonMenuItem" id="198">
<string name="title">Show BatchViewer</string>
<boolean name="notPreviousAlternate">TRUE</boolean>
<ostype name="command">BVwr</ostype>
</object>
<reference idRef="187"/>
<reference idRef="182"/>
<object class="IBCarbonMenuItem" id="199">
<string name="title">Show GL Layer Setup</string>
<boolean name="notPreviousAlternate">TRUE</boolean>
<ostype name="command">GLLs</ostype>
</object>
<object class="IBCarbonMenu" id="197">
<string name="title">Batch Viewer</string>
<array count="2" name="items">
<reference idRef="198"/>
<reference idRef="199"/>
</array>
</object>
<reference idRef="186"/>
<reference idRef="147"/>
<reference idRef="148"/>
</array>
<array count="17" name="allParents">
<reference idRef="147"/>
<reference idRef="147"/>
<reference idRef="147"/>
<reference idRef="181"/>
<reference idRef="182"/>
<reference idRef="29"/>
<reference idRef="1"/>
<reference idRef="147"/>
<reference idRef="147"/>
<reference idRef="197"/>
<reference idRef="181"/>
<reference idRef="29"/>
<reference idRef="197"/>
<reference idRef="1"/>
<reference idRef="181"/>
<reference idRef="152"/>
<reference idRef="147"/>
</array>
<dictionary count="3" name="nameTable">
<string>BatchViewerMenu</string>
<reference idRef="197"/>
<string>File&apos;s Owner</string>
<reference idRef="1"/>
<string>MenuBar</string>
<reference idRef="29"/>
</dictionary>
<string name="targetFramework">IBCarbonFramework</string>
<unsigned_int name="nextObjectID">200</unsigned_int>
</object>

597
src/app/mac/Main.xib Normal file
View File

@ -0,0 +1,597 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.Carbon.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1030</int>
<string key="IBDocument.SystemVersion">15G19009</string>
<string key="IBDocument.InterfaceBuilderVersion">11000</string>
<string key="IBDocument.AppKitVersion">1404.47</string>
<string key="IBDocument.HIToolboxVersion">807.20</string>
<dictionary class="NSMutableDictionary" key="IBDocument.PluginVersions"/>
<array class="NSMutableArray" key="IBDocument.EditedObjectIDs"/>
<array key="IBDocument.PluginDependencies" id="0"/>
<dictionary class="NSMutableDictionary" key="IBDocument.Metadata"/>
<array class="NSMutableArray" key="IBDocument.RootObjects" id="234250886">
<object class="IBHIMenu" id="783341525">
<string key="NSTitle">Untitled</string>
<array class="NSMutableArray" key="NSMenuItems">
<object class="IBHIMenuItem" id="374205419">
<reference key="NSMenu" ref="783341525"/>
<string key="NSTitle">World of Warcraft</string>
<string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<object class="NSImage" key="NSOnImage" id="678796781">
<string key="NSName">NSMenuCheckmark</string>
<int key="NSImageFlags">-1396703232</int>
</object>
<object class="NSImage" key="NSMixedImage" id="788635175">
<string key="NSName">NSMenuMixedState</string>
<int key="NSImageFlags">-1396703232</int>
</object>
<string key="NSAction">submenuAction:</string>
<reference key="NSTarget" ref="273282363"/>
<object class="IBHIMenu" key="NSSubmenu" id="273282363">
<string key="NSTitle">World of Warcraft</string>
<array class="NSMutableArray" key="NSMenuItems">
<object class="IBHIMenuItem" id="962291476">
<reference key="NSMenu" ref="273282363"/>
<string key="NSTitle">About World of Warcraft...</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="678796781"/>
<reference key="NSMixedImage" ref="788635175"/>
<string key="title">About World of Warcraft...</string>
<string key="keyEquivalent"/>
<integer value="0" key="disabled"/>
<integer value="0" key="checked"/>
<integer value="0" key="submenuParentChoosable"/>
<integer value="0" key="dynamic"/>
<integer value="0" key="notPreviousAlternate"/>
<integer value="0" key="hidden"/>
<integer value="0" key="ignoreMeta"/>
<integer value="0" key="sectionHeader"/>
<integer value="0" key="customDraw"/>
<integer value="0" key="autoRepeat"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="updateSingleItem"/>
<integer value="0" key="includeInCmdKeyMatching"/>
<integer value="0" key="keyEquivalentModifierMask"/>
<integer value="1633841013" key="command"/>
<nil key="helpTagText"/>
<nil key="helpTagExtendedText"/>
<integer value="0" key="helpTagDisplaySide"/>
</object>
<object class="IBHIMenuItem" id="28259413">
<reference key="NSMenu" ref="273282363"/>
<bool key="NSIsSeparator">YES</bool>
<string key="NSTitle"/>
<string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="678796781"/>
<reference key="NSMixedImage" ref="788635175"/>
<string key="title"/>
<string key="keyEquivalent"/>
<integer value="0" key="disabled"/>
<integer value="0" key="checked"/>
<integer value="0" key="submenuParentChoosable"/>
<integer value="0" key="dynamic"/>
<integer value="0" key="notPreviousAlternate"/>
<integer value="0" key="hidden"/>
<integer value="0" key="ignoreMeta"/>
<integer value="0" key="sectionHeader"/>
<integer value="0" key="customDraw"/>
<integer value="0" key="autoRepeat"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="updateSingleItem"/>
<integer value="0" key="includeInCmdKeyMatching"/>
<integer value="1048576" key="keyEquivalentModifierMask"/>
<integer value="0" key="command"/>
<nil key="helpTagText"/>
<nil key="helpTagExtendedText"/>
<integer value="0" key="helpTagDisplaySide"/>
</object>
<object class="IBHIMenuItem" id="716945557">
<reference key="NSMenu" ref="273282363"/>
<string key="NSTitle">Switch To Full Screen Mode</string>
<string key="NSKeyEquiv">m</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="678796781"/>
<reference key="NSMixedImage" ref="788635175"/>
<string key="title">Switch To Full Screen Mode</string>
<string key="keyEquivalent">m</string>
<integer value="0" key="disabled"/>
<integer value="0" key="checked"/>
<integer value="0" key="submenuParentChoosable"/>
<integer value="0" key="dynamic"/>
<integer value="0" key="notPreviousAlternate"/>
<integer value="0" key="hidden"/>
<integer value="0" key="ignoreMeta"/>
<integer value="0" key="sectionHeader"/>
<integer value="0" key="customDraw"/>
<integer value="0" key="autoRepeat"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="updateSingleItem"/>
<integer value="0" key="includeInCmdKeyMatching"/>
<integer value="1048576" key="keyEquivalentModifierMask"/>
<integer value="1182100588" key="command"/>
<nil key="helpTagText"/>
<nil key="helpTagExtendedText"/>
<integer value="0" key="helpTagDisplaySide"/>
</object>
</array>
<string key="name">_NSAppleMenu</string>
<string key="title">World of Warcraft</string>
<integer value="0" key="menuID"/>
<integer value="0" key="excludesMarkColumn"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="usePencilGlyph"/>
<integer value="0" key="hidden"/>
<integer value="0" key="condenseSeparators"/>
</object>
<string key="title">World of Warcraft</string>
<string key="keyEquivalent"/>
<integer value="0" key="disabled"/>
<integer value="0" key="checked"/>
<integer value="0" key="submenuParentChoosable"/>
<integer value="0" key="dynamic"/>
<integer value="0" key="notPreviousAlternate"/>
<integer value="0" key="hidden"/>
<integer value="0" key="ignoreMeta"/>
<integer value="0" key="sectionHeader"/>
<integer value="0" key="customDraw"/>
<integer value="0" key="autoRepeat"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="updateSingleItem"/>
<integer value="0" key="includeInCmdKeyMatching"/>
<integer value="1048576" key="keyEquivalentModifierMask"/>
<integer value="0" key="command"/>
<nil key="helpTagText"/>
<nil key="helpTagExtendedText"/>
<integer value="0" key="helpTagDisplaySide"/>
</object>
<object class="IBHIMenuItem" id="832277564">
<reference key="NSMenu" ref="783341525"/>
<string key="NSTitle">Edit</string>
<string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="678796781"/>
<reference key="NSMixedImage" ref="788635175"/>
<string key="NSAction">submenuAction:</string>
<reference key="NSTarget" ref="775244329"/>
<object class="IBHIMenu" key="NSSubmenu" id="775244329">
<string key="NSTitle">Edit</string>
<array class="NSMutableArray" key="NSMenuItems">
<object class="IBHIMenuItem" id="525595591">
<reference key="NSMenu" ref="775244329"/>
<string key="NSTitle">Undo</string>
<string key="NSKeyEquiv">z</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="678796781"/>
<reference key="NSMixedImage" ref="788635175"/>
<string key="title">Undo</string>
<string key="keyEquivalent">z</string>
<integer value="0" key="disabled"/>
<integer value="0" key="checked"/>
<integer value="0" key="submenuParentChoosable"/>
<integer value="0" key="dynamic"/>
<integer value="0" key="notPreviousAlternate"/>
<integer value="0" key="hidden"/>
<integer value="0" key="ignoreMeta"/>
<integer value="0" key="sectionHeader"/>
<integer value="0" key="customDraw"/>
<integer value="0" key="autoRepeat"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="updateSingleItem"/>
<integer value="0" key="includeInCmdKeyMatching"/>
<integer value="1048576" key="keyEquivalentModifierMask"/>
<integer value="1970168943" key="command"/>
<nil key="helpTagText"/>
<nil key="helpTagExtendedText"/>
<integer value="0" key="helpTagDisplaySide"/>
</object>
<object class="IBHIMenuItem" id="348288318">
<reference key="NSMenu" ref="775244329"/>
<bool key="NSIsSeparator">YES</bool>
<string key="NSTitle"/>
<string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="678796781"/>
<reference key="NSMixedImage" ref="788635175"/>
<string key="title"/>
<string key="keyEquivalent"/>
<integer value="0" key="disabled"/>
<integer value="0" key="checked"/>
<integer value="0" key="submenuParentChoosable"/>
<integer value="0" key="dynamic"/>
<integer value="0" key="notPreviousAlternate"/>
<integer value="0" key="hidden"/>
<integer value="0" key="ignoreMeta"/>
<integer value="0" key="sectionHeader"/>
<integer value="0" key="customDraw"/>
<integer value="0" key="autoRepeat"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="updateSingleItem"/>
<integer value="0" key="includeInCmdKeyMatching"/>
<integer value="1048576" key="keyEquivalentModifierMask"/>
<integer value="0" key="command"/>
<nil key="helpTagText"/>
<nil key="helpTagExtendedText"/>
<integer value="0" key="helpTagDisplaySide"/>
</object>
<object class="IBHIMenuItem" id="504943467">
<reference key="NSMenu" ref="775244329"/>
<string key="NSTitle">Cut</string>
<string key="NSKeyEquiv">x</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="678796781"/>
<reference key="NSMixedImage" ref="788635175"/>
<string key="title">Cut</string>
<string key="keyEquivalent">x</string>
<integer value="0" key="disabled"/>
<integer value="0" key="checked"/>
<integer value="0" key="submenuParentChoosable"/>
<integer value="0" key="dynamic"/>
<integer value="0" key="notPreviousAlternate"/>
<integer value="0" key="hidden"/>
<integer value="0" key="ignoreMeta"/>
<integer value="0" key="sectionHeader"/>
<integer value="0" key="customDraw"/>
<integer value="0" key="autoRepeat"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="updateSingleItem"/>
<integer value="0" key="includeInCmdKeyMatching"/>
<integer value="1048576" key="keyEquivalentModifierMask"/>
<integer value="1668641824" key="command"/>
<nil key="helpTagText"/>
<nil key="helpTagExtendedText"/>
<integer value="0" key="helpTagDisplaySide"/>
</object>
<object class="IBHIMenuItem" id="1036249919">
<reference key="NSMenu" ref="775244329"/>
<string key="NSTitle">Copy</string>
<string key="NSKeyEquiv">c</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="678796781"/>
<reference key="NSMixedImage" ref="788635175"/>
<string key="title">Copy</string>
<string key="keyEquivalent">c</string>
<integer value="0" key="disabled"/>
<integer value="0" key="checked"/>
<integer value="0" key="submenuParentChoosable"/>
<integer value="0" key="dynamic"/>
<integer value="0" key="notPreviousAlternate"/>
<integer value="0" key="hidden"/>
<integer value="0" key="ignoreMeta"/>
<integer value="0" key="sectionHeader"/>
<integer value="0" key="customDraw"/>
<integer value="0" key="autoRepeat"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="updateSingleItem"/>
<integer value="0" key="includeInCmdKeyMatching"/>
<integer value="1048576" key="keyEquivalentModifierMask"/>
<integer value="1668247673" key="command"/>
<nil key="helpTagText"/>
<nil key="helpTagExtendedText"/>
<integer value="0" key="helpTagDisplaySide"/>
</object>
<object class="IBHIMenuItem" id="780439468">
<reference key="NSMenu" ref="775244329"/>
<string key="NSTitle">Paste</string>
<string key="NSKeyEquiv">v</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="678796781"/>
<reference key="NSMixedImage" ref="788635175"/>
<string key="title">Paste</string>
<string key="keyEquivalent">v</string>
<integer value="0" key="disabled"/>
<integer value="0" key="checked"/>
<integer value="0" key="submenuParentChoosable"/>
<integer value="0" key="dynamic"/>
<integer value="0" key="notPreviousAlternate"/>
<integer value="0" key="hidden"/>
<integer value="0" key="ignoreMeta"/>
<integer value="0" key="sectionHeader"/>
<integer value="0" key="customDraw"/>
<integer value="0" key="autoRepeat"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="updateSingleItem"/>
<integer value="0" key="includeInCmdKeyMatching"/>
<integer value="1048576" key="keyEquivalentModifierMask"/>
<integer value="1885434740" key="command"/>
<nil key="helpTagText"/>
<nil key="helpTagExtendedText"/>
<integer value="0" key="helpTagDisplaySide"/>
</object>
<object class="IBHIMenuItem" id="270786867">
<reference key="NSMenu" ref="775244329"/>
<string key="NSTitle">Select All</string>
<string key="NSKeyEquiv">a</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="678796781"/>
<reference key="NSMixedImage" ref="788635175"/>
<string key="title">Select All</string>
<string key="keyEquivalent">a</string>
<integer value="0" key="disabled"/>
<integer value="0" key="checked"/>
<integer value="0" key="submenuParentChoosable"/>
<integer value="0" key="dynamic"/>
<integer value="0" key="notPreviousAlternate"/>
<integer value="0" key="hidden"/>
<integer value="0" key="ignoreMeta"/>
<integer value="0" key="sectionHeader"/>
<integer value="0" key="customDraw"/>
<integer value="0" key="autoRepeat"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="updateSingleItem"/>
<integer value="0" key="includeInCmdKeyMatching"/>
<integer value="1048576" key="keyEquivalentModifierMask"/>
<integer value="1935764588" key="command"/>
<nil key="helpTagText"/>
<nil key="helpTagExtendedText"/>
<integer value="0" key="helpTagDisplaySide"/>
</object>
</array>
<string key="title">Edit</string>
<integer value="128" key="menuID"/>
<integer value="0" key="excludesMarkColumn"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="usePencilGlyph"/>
<integer value="0" key="hidden"/>
<integer value="0" key="condenseSeparators"/>
</object>
<string key="title">Edit</string>
<string key="keyEquivalent"/>
<integer value="0" key="disabled"/>
<integer value="0" key="checked"/>
<integer value="0" key="submenuParentChoosable"/>
<integer value="0" key="dynamic"/>
<integer value="0" key="notPreviousAlternate"/>
<integer value="0" key="hidden"/>
<integer value="0" key="ignoreMeta"/>
<integer value="0" key="sectionHeader"/>
<integer value="0" key="customDraw"/>
<integer value="0" key="autoRepeat"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="updateSingleItem"/>
<integer value="0" key="includeInCmdKeyMatching"/>
<integer value="1048576" key="keyEquivalentModifierMask"/>
<integer value="0" key="command"/>
<nil key="helpTagText"/>
<nil key="helpTagExtendedText"/>
<integer value="0" key="helpTagDisplaySide"/>
</object>
</array>
<string key="name">_NSMainMenu</string>
<string key="title">Untitled</string>
<integer value="0" key="menuID"/>
<integer value="0" key="excludesMarkColumn"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="usePencilGlyph"/>
<integer value="0" key="hidden"/>
<integer value="0" key="condenseSeparators"/>
</object>
<object class="IBHIMenu" id="231014827">
<string key="NSTitle">Batch Viewer</string>
<array class="NSMutableArray" key="NSMenuItems">
<object class="IBHIMenuItem" id="177821328">
<reference key="NSMenu" ref="231014827"/>
<string key="NSTitle">Show BatchViewer</string>
<string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="678796781"/>
<reference key="NSMixedImage" ref="788635175"/>
<string key="title">Show BatchViewer</string>
<string key="keyEquivalent"/>
<integer value="0" key="disabled"/>
<integer value="0" key="checked"/>
<integer value="0" key="submenuParentChoosable"/>
<integer value="0" key="dynamic"/>
<integer value="1" key="notPreviousAlternate"/>
<integer value="0" key="hidden"/>
<integer value="0" key="ignoreMeta"/>
<integer value="0" key="sectionHeader"/>
<integer value="0" key="customDraw"/>
<integer value="0" key="autoRepeat"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="updateSingleItem"/>
<integer value="0" key="includeInCmdKeyMatching"/>
<integer value="1048576" key="keyEquivalentModifierMask"/>
<integer value="1112962930" key="command"/>
<nil key="helpTagText"/>
<nil key="helpTagExtendedText"/>
<integer value="0" key="helpTagDisplaySide"/>
</object>
<object class="IBHIMenuItem" id="443792299">
<reference key="NSMenu" ref="231014827"/>
<string key="NSTitle">Show GL Layer Setup</string>
<string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="678796781"/>
<reference key="NSMixedImage" ref="788635175"/>
<string key="title">Show GL Layer Setup</string>
<string key="keyEquivalent"/>
<integer value="0" key="disabled"/>
<integer value="0" key="checked"/>
<integer value="0" key="submenuParentChoosable"/>
<integer value="0" key="dynamic"/>
<integer value="1" key="notPreviousAlternate"/>
<integer value="0" key="hidden"/>
<integer value="0" key="ignoreMeta"/>
<integer value="0" key="sectionHeader"/>
<integer value="0" key="customDraw"/>
<integer value="0" key="autoRepeat"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="updateSingleItem"/>
<integer value="0" key="includeInCmdKeyMatching"/>
<integer value="1048576" key="keyEquivalentModifierMask"/>
<integer value="1196182643" key="command"/>
<nil key="helpTagText"/>
<nil key="helpTagExtendedText"/>
<integer value="0" key="helpTagDisplaySide"/>
</object>
</array>
<string key="title">Batch Viewer</string>
<integer value="0" key="menuID"/>
<integer value="0" key="excludesMarkColumn"/>
<integer value="0" key="autoDisable"/>
<integer value="0" key="usePencilGlyph"/>
<integer value="0" key="hidden"/>
<integer value="0" key="condenseSeparators"/>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords"/>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
<object class="IBObjectRecord">
<int key="objectID">0</int>
<reference key="object" ref="0"/>
<reference key="children" ref="234250886"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">29</int>
<reference key="object" ref="783341525"/>
<array class="NSMutableArray" key="children">
<reference ref="832277564"/>
<reference ref="374205419"/>
</array>
<reference key="parent" ref="0"/>
<string key="objectName">MenuBar</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">197</int>
<reference key="object" ref="231014827"/>
<array class="NSMutableArray" key="children">
<reference ref="177821328"/>
<reference ref="443792299"/>
</array>
<reference key="parent" ref="0"/>
<string key="objectName">BatchViewerMenu</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">152</int>
<reference key="object" ref="832277564"/>
<array class="NSMutableArray" key="children">
<reference ref="775244329"/>
</array>
<reference key="parent" ref="783341525"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">182</int>
<reference key="object" ref="374205419"/>
<array class="NSMutableArray" key="children">
<reference ref="273282363"/>
</array>
<reference key="parent" ref="783341525"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">198</int>
<reference key="object" ref="177821328"/>
<reference key="parent" ref="231014827"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">199</int>
<reference key="object" ref="443792299"/>
<reference key="parent" ref="231014827"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">147</int>
<reference key="object" ref="775244329"/>
<array class="NSMutableArray" key="children">
<reference ref="780439468"/>
<reference ref="348288318"/>
<reference ref="1036249919"/>
<reference ref="525595591"/>
<reference ref="504943467"/>
<reference ref="270786867"/>
</array>
<reference key="parent" ref="832277564"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">181</int>
<reference key="object" ref="273282363"/>
<array class="NSMutableArray" key="children">
<reference ref="962291476"/>
<reference ref="716945557"/>
<reference ref="28259413"/>
</array>
<reference key="parent" ref="374205419"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">144</int>
<reference key="object" ref="780439468"/>
<reference key="parent" ref="775244329"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">142</int>
<reference key="object" ref="348288318"/>
<reference key="parent" ref="775244329"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">149</int>
<reference key="object" ref="1036249919"/>
<reference key="parent" ref="775244329"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">141</int>
<reference key="object" ref="525595591"/>
<reference key="parent" ref="775244329"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">143</int>
<reference key="object" ref="504943467"/>
<reference key="parent" ref="775244329"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">148</int>
<reference key="object" ref="270786867"/>
<reference key="parent" ref="775244329"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">183</int>
<reference key="object" ref="962291476"/>
<reference key="parent" ref="273282363"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">187</int>
<reference key="object" ref="716945557"/>
<reference key="parent" ref="273282363"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">186</int>
<reference key="object" ref="28259413"/>
<reference key="parent" ref="273282363"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties"/>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">200</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes"/>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCarbonFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
<string key="NS.key.0">com.apple.InterfaceBuilder.CarbonPlugin.macosx</string>
<integer value="1030" key="NS.object.0"/>
</object>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<string key="IBDocument.LastKnownRelativeProjectPath">../../../WoW.xcodeproj</string>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
</data>
</archive>

19
src/app/mac/MainApp.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef APP_MAC_MAIN_APP_H
#define APP_MAC_MAIN_APP_H
#include "app/mac/MacClient.h"
#include <AppKit/AppKit.h>
#include <Foundation/Foundation.h>
@interface MainApp : NSObject
@property (retain) NSTimer* m_pollTimer;
@property bool isPolling;
@property (retain) IBOutlet NSMenuItem* captureFrameMenuItem;
@property (retain) IBOutlet NSMenuItem* showBatchViewerMenuItem;
@property (retain) IBOutlet NSMenuItem* showGLLayerSetupMenuItem;
@end
#endif

90
src/app/mac/MainApp.mm Normal file
View File

@ -0,0 +1,90 @@
#include "app/mac/MainApp.h"
#include "event/Event.hpp"
#include "event/Scheduler.hpp"
#include "os/Compat.hpp"
@implementation MainApp
+ (void)initialize {
[[NSUserDefaults standardUserDefaults]
registerDefaults: [NSDictionary
dictionaryWithObject: @"YES"
forKey: @"NSDisabledCharacterPaletteMenuItem"]];
[NSApp
setActivationPolicy: NSApplicationActivationPolicyRegular];
}
- (void)applicationDidFinishLaunching:(id)a1 {
self.m_pollTimer = [NSTimer
timerWithTimeInterval: 0.0001
target: self
selector: @selector(poll:)
userInfo: nil
repeats: true];
[[NSRunLoop currentRunLoop]
addTimer: self.m_pollTimer
forMode: NSDefaultRunLoopMode];
}
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
// TODO
// OsQueuePut(5, 0, 0, 0, 0);
return NSTerminateCancel;
}
- (void)captureFrame:(id)a1 {
}
- (void)copy:(id)a3 {
MacClient::PostClipboardKeyEvents(MacClient::ClipboardCopy);
}
- (void)cut:(id)a3 {
MacClient::PostClipboardKeyEvents(MacClient::ClipboardCut);
}
- (void)paste:(id)a3 {
MacClient::PostClipboardKeyEvents(MacClient::ClipboardPaste);
}
- (void)poll:(id)a1 {
if (!Event::s_shouldLoopTerminate) {
Event::s_shouldLoopTerminate = SchedulerMainProcess();
if (Event::s_shouldLoopTerminate) {
[self.m_pollTimer invalidate];
self.m_pollTimer = nil;
[NSApp stop:self];
[NSApp
postEvent:
[NSEvent
otherEventWithType: NSEventTypeApplicationDefined
location: NSMakePoint(0, 0)
modifierFlags: 0
timestamp: 0
windowNumber: 0
context: 0
subtype: 0
data1: 0
data2: 0]
atStart: 0];
}
}
}
- (void)showBatchViewer:(id)a1 {
}
- (void)showGLLayerSetup:(id)a1 {
}
- (void)toggleFullscreenMode:(id)a1 {
// TODO
}
@end

901
src/app/mac/MainMenu.nib/designable.nib generated Executable file
View File

@ -0,0 +1,901 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
<data>
<int key="IBDocument.SystemTarget">1030</int>
<string key="IBDocument.SystemVersion">9J61</string>
<string key="IBDocument.InterfaceBuilderVersion">677</string>
<string key="IBDocument.AppKitVersion">949.46</string>
<string key="IBDocument.HIToolboxVersion">353.00</string>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
<integer value="24"/>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
</object>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
</object>
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1048">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSCustomObject" id="1021">
<string key="NSClassName">NSApplication</string>
</object>
<object class="NSCustomObject" id="1014">
<string key="NSClassName">FirstResponder</string>
</object>
<object class="NSCustomObject" id="1050">
<string key="NSClassName">NSApplication</string>
</object>
<object class="NSMenu" id="649796088">
<string key="NSTitle">AMainMenu</string>
<object class="NSMutableArray" key="NSMenuItems">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMenuItem" id="694149608">
<reference key="NSMenu" ref="649796088"/>
<string key="NSTitle">World of Warcraft</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<object class="NSCustomResource" key="NSOnImage" id="229763992">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">NSMenuCheckmark</string>
</object>
<object class="NSCustomResource" key="NSMixedImage" id="909111550">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">NSMenuMixedState</string>
</object>
<string key="NSAction">submenuAction:</string>
<object class="NSMenu" key="NSSubmenu" id="110575045">
<string key="NSTitle">World of Warcraft</string>
<object class="NSMutableArray" key="NSMenuItems">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMenuItem" id="238522557">
<reference key="NSMenu" ref="110575045"/>
<string key="NSTitle">MENU_ABOUT</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="304266470">
<reference key="NSMenu" ref="110575045"/>
<bool key="NSIsDisabled">YES</bool>
<bool key="NSIsSeparator">YES</bool>
<string key="NSTitle"/>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="41361050">
<reference key="NSMenu" ref="110575045"/>
<string key="NSTitle">MENU_SWITCH_TO_FULLSCREEN</string>
<string key="NSKeyEquiv">m</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="294290359">
<reference key="NSMenu" ref="110575045"/>
<bool key="NSIsDisabled">YES</bool>
<bool key="NSIsSeparator">YES</bool>
<string key="NSTitle"/>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="755159360">
<reference key="NSMenu" ref="110575045"/>
<string key="NSTitle">MENU_HIDE</string>
<string key="NSKeyEquiv">h</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="342932134">
<reference key="NSMenu" ref="110575045"/>
<string key="NSTitle">MENU_HIDE_OTHERS</string>
<string key="NSKeyEquiv">h</string>
<int key="NSKeyEquivModMask">1572864</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="908899353">
<reference key="NSMenu" ref="110575045"/>
<string key="NSTitle">MENU_SHOW_ALL</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="1056857174">
<reference key="NSMenu" ref="110575045"/>
<bool key="NSIsDisabled">YES</bool>
<bool key="NSIsSeparator">YES</bool>
<string key="NSTitle"/>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="632727374">
<reference key="NSMenu" ref="110575045"/>
<string key="NSTitle">MENU_QUIT</string>
<string key="NSKeyEquiv">q</string>
<int key="NSKeyEquivModMask">1572864</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
</object>
<string key="NSName">_NSAppleMenu</string>
</object>
</object>
<object class="NSMenuItem" id="952259628">
<reference key="NSMenu" ref="649796088"/>
<string key="NSTitle">MENU_EDIT</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
<string key="NSAction">submenuAction:</string>
<object class="NSMenu" key="NSSubmenu" id="789758025">
<string key="NSTitle">MENU_EDIT</string>
<object class="NSMutableArray" key="NSMenuItems">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMenuItem" id="1058277027">
<reference key="NSMenu" ref="789758025"/>
<string key="NSTitle">MENU_UNDO</string>
<string key="NSKeyEquiv">z</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="1040322652">
<reference key="NSMenu" ref="789758025"/>
<bool key="NSIsDisabled">YES</bool>
<bool key="NSIsSeparator">YES</bool>
<string key="NSTitle"/>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="296257095">
<reference key="NSMenu" ref="789758025"/>
<string key="NSTitle">MENU_EDIT_CUT</string>
<string key="NSKeyEquiv">x</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="860595796">
<reference key="NSMenu" ref="789758025"/>
<string key="NSTitle">MENU_EDIT_COPY</string>
<string key="NSKeyEquiv">c</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="29853731">
<reference key="NSMenu" ref="789758025"/>
<string key="NSTitle">MENU_EDIT_PASTE</string>
<string key="NSKeyEquiv">v</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="583158037">
<reference key="NSMenu" ref="789758025"/>
<string key="NSTitle">MENU_EDIT_SELECT_ALL</string>
<string key="NSKeyEquiv">a</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
</object>
</object>
</object>
<object class="NSMenuItem" id="713487014">
<reference key="NSMenu" ref="649796088"/>
<string key="NSTitle">MENU_WINDOW</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
<string key="NSAction">submenuAction:</string>
<object class="NSMenu" key="NSSubmenu" id="835318025">
<string key="NSTitle">MENU_WINDOW</string>
<object class="NSMutableArray" key="NSMenuItems">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMenuItem" id="839061908">
<reference key="NSMenu" ref="835318025"/>
<string key="NSTitle">Show Batch Viewer</string>
<string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="825097611">
<reference key="NSMenu" ref="835318025"/>
<string key="NSTitle">Show GL Layer Setup</string>
<string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="891014876">
<reference key="NSMenu" ref="835318025"/>
<string key="NSTitle">Capture Frame</string>
<string key="NSKeyEquiv">r</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
</object>
<string key="NSName">_NSWindowsMenu</string>
</object>
</object>
</object>
<string key="NSName">_NSMainMenu</string>
</object>
<object class="NSCustomObject" id="106825686">
<string key="NSClassName">MainApp</string>
</object>
</object>
<object class="IBObjectContainer" key="IBDocument.Objects">
<object class="NSMutableArray" key="connectionRecords">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">orderFrontStandardAboutPanel:</string>
<reference key="source" ref="1021"/>
<reference key="destination" ref="238522557"/>
</object>
<int key="connectionID">142</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">undo:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="1058277027"/>
</object>
<int key="connectionID">223</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">copy:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="860595796"/>
</object>
<int key="connectionID">224</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">paste:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="29853731"/>
</object>
<int key="connectionID">226</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">cut:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="296257095"/>
</object>
<int key="connectionID">228</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">selectAll:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="583158037"/>
</object>
<int key="connectionID">232</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">hide:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="755159360"/>
</object>
<int key="connectionID">367</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">hideOtherApplications:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="342932134"/>
</object>
<int key="connectionID">368</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">terminate:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="632727374"/>
</object>
<int key="connectionID">369</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">unhideAllApplications:</string>
<reference key="source" ref="1014"/>
<reference key="destination" ref="908899353"/>
</object>
<int key="connectionID">370</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">delegate</string>
<reference key="source" ref="1021"/>
<reference key="destination" ref="106825686"/>
</object>
<int key="connectionID">452</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">showGLLayerSetup:</string>
<reference key="source" ref="106825686"/>
<reference key="destination" ref="825097611"/>
</object>
<int key="connectionID">454</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">showBatchViewer:</string>
<reference key="source" ref="106825686"/>
<reference key="destination" ref="839061908"/>
</object>
<int key="connectionID">455</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">showBatchViewerMenuItem</string>
<reference key="source" ref="106825686"/>
<reference key="destination" ref="839061908"/>
</object>
<int key="connectionID">456</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">showGLLayerSetupMenuItem</string>
<reference key="source" ref="106825686"/>
<reference key="destination" ref="825097611"/>
</object>
<int key="connectionID">457</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">toggleFullscreenMode:</string>
<reference key="source" ref="106825686"/>
<reference key="destination" ref="41361050"/>
</object>
<int key="connectionID">460</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">captureFrameMenuItem</string>
<reference key="source" ref="106825686"/>
<reference key="destination" ref="891014876"/>
</object>
<int key="connectionID">462</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">captureFrame:</string>
<reference key="source" ref="106825686"/>
<reference key="destination" ref="891014876"/>
</object>
<int key="connectionID">463</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBObjectRecord">
<int key="objectID">0</int>
<object class="NSArray" key="object" id="1049">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<reference key="children" ref="1048"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="1021"/>
<reference key="parent" ref="1049"/>
<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="1014"/>
<reference key="parent" ref="1049"/>
<string key="objectName">First Responder</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-3</int>
<reference key="object" ref="1050"/>
<reference key="parent" ref="1049"/>
<string key="objectName">Application</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">29</int>
<reference key="object" ref="649796088"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="713487014"/>
<reference ref="694149608"/>
<reference ref="952259628"/>
</object>
<reference key="parent" ref="1049"/>
<string key="objectName">Main Menu</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">19</int>
<reference key="object" ref="713487014"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="835318025"/>
</object>
<reference key="parent" ref="649796088"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">56</int>
<reference key="object" ref="694149608"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="110575045"/>
</object>
<reference key="parent" ref="649796088"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">217</int>
<reference key="object" ref="952259628"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="789758025"/>
</object>
<reference key="parent" ref="649796088"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">205</int>
<reference key="object" ref="789758025"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="583158037"/>
<reference ref="1058277027"/>
<reference ref="296257095"/>
<reference ref="29853731"/>
<reference ref="860595796"/>
<reference ref="1040322652"/>
</object>
<reference key="parent" ref="952259628"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">198</int>
<reference key="object" ref="583158037"/>
<reference key="parent" ref="789758025"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">207</int>
<reference key="object" ref="1058277027"/>
<reference key="parent" ref="789758025"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">199</int>
<reference key="object" ref="296257095"/>
<reference key="parent" ref="789758025"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">203</int>
<reference key="object" ref="29853731"/>
<reference key="parent" ref="789758025"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">197</int>
<reference key="object" ref="860595796"/>
<reference key="parent" ref="789758025"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">206</int>
<reference key="object" ref="1040322652"/>
<reference key="parent" ref="789758025"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">57</int>
<reference key="object" ref="110575045"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="238522557"/>
<reference ref="755159360"/>
<reference ref="908899353"/>
<reference ref="632727374"/>
<reference ref="304266470"/>
<reference ref="1056857174"/>
<reference ref="342932134"/>
<reference ref="41361050"/>
<reference ref="294290359"/>
</object>
<reference key="parent" ref="694149608"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">58</int>
<reference key="object" ref="238522557"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">134</int>
<reference key="object" ref="755159360"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">150</int>
<reference key="object" ref="908899353"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">136</int>
<reference key="object" ref="632727374"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">236</int>
<reference key="object" ref="304266470"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">149</int>
<reference key="object" ref="1056857174"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">145</int>
<reference key="object" ref="342932134"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">24</int>
<reference key="object" ref="835318025"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="839061908"/>
<reference ref="825097611"/>
<reference ref="891014876"/>
</object>
<reference key="parent" ref="713487014"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">449</int>
<reference key="object" ref="839061908"/>
<reference key="parent" ref="835318025"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">450</int>
<reference key="object" ref="825097611"/>
<reference key="parent" ref="835318025"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">451</int>
<reference key="object" ref="106825686"/>
<reference key="parent" ref="1049"/>
<string key="objectName">MainApp</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">458</int>
<reference key="object" ref="41361050"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">459</int>
<reference key="object" ref="294290359"/>
<reference key="parent" ref="110575045"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">461</int>
<reference key="object" ref="891014876"/>
<reference key="parent" ref="835318025"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMutableArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>-1.IBPluginDependency</string>
<string>-2.IBPluginDependency</string>
<string>-3.IBPluginDependency</string>
<string>134.IBPluginDependency</string>
<string>134.ImportedFromIB2</string>
<string>136.IBPluginDependency</string>
<string>136.ImportedFromIB2</string>
<string>145.IBPluginDependency</string>
<string>145.ImportedFromIB2</string>
<string>149.IBPluginDependency</string>
<string>149.ImportedFromIB2</string>
<string>150.IBPluginDependency</string>
<string>150.ImportedFromIB2</string>
<string>19.IBPluginDependency</string>
<string>19.ImportedFromIB2</string>
<string>197.IBPluginDependency</string>
<string>197.ImportedFromIB2</string>
<string>198.IBPluginDependency</string>
<string>198.ImportedFromIB2</string>
<string>199.IBPluginDependency</string>
<string>199.ImportedFromIB2</string>
<string>203.IBPluginDependency</string>
<string>203.ImportedFromIB2</string>
<string>205.IBEditorWindowLastContentRect</string>
<string>205.IBPluginDependency</string>
<string>205.ImportedFromIB2</string>
<string>205.editorWindowContentRectSynchronizationRect</string>
<string>206.IBPluginDependency</string>
<string>206.ImportedFromIB2</string>
<string>207.IBPluginDependency</string>
<string>207.ImportedFromIB2</string>
<string>217.IBPluginDependency</string>
<string>217.ImportedFromIB2</string>
<string>236.IBPluginDependency</string>
<string>236.ImportedFromIB2</string>
<string>24.IBEditorWindowLastContentRect</string>
<string>24.IBPluginDependency</string>
<string>24.ImportedFromIB2</string>
<string>24.editorWindowContentRectSynchronizationRect</string>
<string>29.IBEditorWindowLastContentRect</string>
<string>29.IBPluginDependency</string>
<string>29.ImportedFromIB2</string>
<string>29.WindowOrigin</string>
<string>29.editorWindowContentRectSynchronizationRect</string>
<string>449.IBPluginDependency</string>
<string>449.ImportedFromIB2</string>
<string>450.IBPluginDependency</string>
<string>450.ImportedFromIB2</string>
<string>451.IBPluginDependency</string>
<string>458.IBPluginDependency</string>
<string>458.ImportedFromIB2</string>
<string>459.IBPluginDependency</string>
<string>459.ImportedFromIB2</string>
<string>461.IBPluginDependency</string>
<string>56.IBPluginDependency</string>
<string>56.ImportedFromIB2</string>
<string>57.IBEditorWindowLastContentRect</string>
<string>57.IBPluginDependency</string>
<string>57.ImportedFromIB2</string>
<string>57.editorWindowContentRectSynchronizationRect</string>
<string>58.IBPluginDependency</string>
<string>58.ImportedFromIB2</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1" id="9"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>{{1422, 1180}, {243, 113}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>{{197, 734}, {243, 243}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>{{1548, 966}, {218, 63}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>{{525, 802}, {197, 73}}</string>
<string>{{1295, 1029}, {390, 20}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>{74, 862}</string>
<string>{{11, 977}, {478, 20}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="YES" id="5"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="5"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="5"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>{{49, 388}, {312, 153}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
<string>{{23, 794}, {245, 183}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<reference ref="9"/>
</object>
</object>
<object class="NSMutableDictionary" key="unlocalizedProperties">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
</object>
<nil key="activeLocalization"/>
<object class="NSMutableDictionary" key="localizations">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">463</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription">
<string key="className">MainApp</string>
<string key="superclassName">NSObject</string>
<object class="NSMutableDictionary" key="actions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMutableArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>captureFrame:</string>
<string>cut:</string>
<string>paste:</string>
<string>selectAll:</string>
<string>showBatchViewer:</string>
<string>showGLLayerSetup:</string>
<string>toggleFullscreenMode:</string>
<string>undo:</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>id</string>
<string>id</string>
<string>id</string>
<string>id</string>
<string>id</string>
<string>id</string>
<string>id</string>
<string>id</string>
</object>
</object>
<object class="NSMutableDictionary" key="outlets">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMutableArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>captureFrameMenuItem</string>
<string>showBatchViewerMenuItem</string>
<string>showGLLayerSetupMenuItem</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>NSMenuItem</string>
<string>NSMenuItem</string>
<string>NSMenuItem</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">Source/MainApp.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">MainApp</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBUserSource</string>
<string key="minorKey"/>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="NSMutableDictionary" key="actions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMutableArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>didAdjustSubviews:</string>
<string>willAdjustSubviews:</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>RBSplitView</string>
<string>RBSplitView</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier" id="35014534">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../../../Engine/Source/Gx/CGxDeviceGLL/GLLayer/RBSplitView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">RBSplitSubview</string>
<string key="superclassName">NSView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../../../Engine/Source/Gx/CGxDeviceGLL/GLLayer/RBSplitSubview.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">RBSplitSubview</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier" id="60681676">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../../../Engine/Source/Gx/CGxDeviceGLL/GLLayer/RBSplitViewPrivateDefines.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">RBSplitView</string>
<string key="superclassName">RBSplitSubview</string>
<object class="NSMutableDictionary" key="outlets">
<string key="NS.key.0">delegate</string>
<string key="NS.object.0">id</string>
</object>
<reference key="sourceIdentifier" ref="35014534"/>
</object>
<object class="IBPartialClassDescription">
<string key="className">RBSplitView</string>
<reference key="sourceIdentifier" ref="60681676"/>
</object>
<object class="IBPartialClassDescription">
<string key="className">StackTableView</string>
<string key="superclassName">NSTableView</string>
<object class="NSMutableDictionary" key="actions">
<string key="NS.key.0">copy:</string>
<string key="NS.object.0">id</string>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../../../Engine/Source/Gx/CGxDeviceGLL/GLLayer/StackCrawlViewer.h</string>
</object>
</object>
</object>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.LastKnownRelativeProjectPath">../../WoW.xcodeproj</string>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
</data>
</archive>

BIN
src/app/mac/MainMenu.nib/keyedobjects.nib generated Executable file

Binary file not shown.

126
src/app/mac/MainMenu.xib Normal file
View File

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11762" systemVersion="15G19009" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
<dependencies>
<deployment version="1030" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11762"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<outlet property="delegate" destination="451" id="452"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<menu title="AMainMenu" systemMenu="main" id="29" userLabel="Main Menu">
<items>
<menuItem title="World of Warcraft" id="56">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="World of Warcraft" systemMenu="apple" id="57">
<items>
<menuItem title="MENU_ABOUT" id="58">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="236"/>
<menuItem title="MENU_SWITCH_TO_FULLSCREEN" keyEquivalent="m" id="458">
<connections>
<action selector="toggleFullscreenMode:" target="451" id="460"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="459"/>
<menuItem title="MENU_HIDE" keyEquivalent="h" id="134">
<connections>
<action selector="hide:" target="-1" id="367"/>
</connections>
</menuItem>
<menuItem title="MENU_HIDE_OTHERS" keyEquivalent="h" id="145">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="-1" id="368"/>
</connections>
</menuItem>
<menuItem title="MENU_SHOW_ALL" id="150">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unhideAllApplications:" target="-1" id="370"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="149"/>
<menuItem title="MENU_QUIT" keyEquivalent="q" id="136">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="terminate:" target="-1" id="369"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="MENU_EDIT" id="217">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="MENU_EDIT" id="205">
<items>
<menuItem title="MENU_UNDO" keyEquivalent="z" id="207">
<connections>
<action selector="undo:" target="-1" id="223"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="206"/>
<menuItem title="MENU_EDIT_CUT" keyEquivalent="x" id="199">
<connections>
<action selector="cut:" target="-1" id="228"/>
</connections>
</menuItem>
<menuItem title="MENU_EDIT_COPY" keyEquivalent="c" id="197">
<connections>
<action selector="copy:" target="-1" id="224"/>
</connections>
</menuItem>
<menuItem title="MENU_EDIT_PASTE" keyEquivalent="v" id="203">
<connections>
<action selector="paste:" target="-1" id="226"/>
</connections>
</menuItem>
<menuItem title="MENU_EDIT_SELECT_ALL" keyEquivalent="a" id="198">
<connections>
<action selector="selectAll:" target="-1" id="232"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="MENU_WINDOW" id="19">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="MENU_WINDOW" systemMenu="window" id="24">
<items>
<menuItem title="Show Batch Viewer" id="449">
<connections>
<action selector="showBatchViewer:" target="451" id="455"/>
</connections>
</menuItem>
<menuItem title="Show GL Layer Setup" id="450">
<connections>
<action selector="showGLLayerSetup:" target="451" id="454"/>
</connections>
</menuItem>
<menuItem title="Capture Frame" keyEquivalent="r" id="461">
<connections>
<action selector="captureFrame:" target="451" id="463"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<customObject id="451" userLabel="MainApp" customClass="MainApp">
<connections>
<outlet property="captureFrameMenuItem" destination="461" id="462"/>
<outlet property="showBatchViewerMenuItem" destination="449" id="456"/>
<outlet property="showGLLayerSetupMenuItem" destination="450" id="457"/>
</connections>
</customObject>
</objects>
</document>

12
src/app/mac/View.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef APP_MAC_VIEW_H
#define APP_MAC_VIEW_H
#include <objc/objc-runtime.h>
struct GLWindowCallbacks;
void AssignEngineViewCallbacks(GLWindowCallbacks*);
Class GetEngineViewClass(void);
#endif

27
src/app/mac/View.mm Normal file
View File

@ -0,0 +1,27 @@
#include "app/mac/View.h"
#include "app/mac/EngineGLLayerView.h"
#include "app/mac/WindowCallbacks.h"
#include "gx/gll/GLWindow.h"
GLWindowCallbacks EngineViewCallbacks = {
&MacOnResized,
&MacOnMouseDown,
&MacOnMouseMoved,
&MacOnMouseUp,
&MacOnKeyDown,
&MacOnKeyUp
};
void AssignEngineViewCallbacks(GLWindowCallbacks* callbacks) {
*callbacks = EngineViewCallbacks;
// TODO
// (callbacks + 100) = 0;
// TODO
// dword_12B9F54 = sub_A15850;
}
Class GetEngineViewClass() {
return [EngineGLLayerView class];
}

41
src/app/mac/Whoa.mm Normal file
View File

@ -0,0 +1,41 @@
#include "app/mac/WoWApplication.h"
#include "app/mac/MacClient.h"
#include "client/Client.hpp"
#include <AppKit/AppKit.h>
#include <Foundation/Foundation.h>
int32_t main(int32_t argc, char* argv[]) {
// TODO
// MacClient::SetupCommandLine(argc, argv, v10);
if (MacClient::IsUsingGLLayer()) {
// TODO
// GxSetRequestedApi(3);
// TODO
// OsInputSetIsUsingCocoaEventLoop(1);
[WoWApplication sharedApplication];
#if WHOA_SYSTEM_VERSION < WHOA_MACOS_10_8
[NSBundle
loadNibNamed: @"MainMenu"
owner: NSApp];
#endif
#if WHOA_SYSTEM_VERSION >= WHOA_MACOS_10_8
[[NSBundle mainBundle]
loadNibNamed: @"MainMenu"
owner: NSApp
topLevelObjects: nil];
#endif
[NSRunLoop currentRunLoop];
[NSApp mainMenu];
CommonMain();
}
return 0;
}

View File

@ -0,0 +1,19 @@
#ifndef APP_MAC_WINDOW_CALLBACKS_H
#define APP_MAC_WINDOW_CALLBACKS_H
#include <cstdint>
#include <AppKit/AppKit.h>
void MacOnKeyDown(NSEvent*);
void MacOnKeyUp(NSEvent*);
void MacOnMouseDown(int16_t, int32_t, int32_t);
void MacOnMouseMoved(int32_t, int32_t);
void MacOnMouseUp(int16_t, int32_t, int32_t);
void MacOnResized(int32_t width, int32_t height, bool a3);
#endif

View File

@ -0,0 +1,188 @@
#include "app/mac/WindowCallbacks.h"
#include "app/mac/MacClient.h"
#include "event/Input.hpp"
#include "gx/gll/CGxDeviceGLL.hpp"
#include "gx/Device.hpp"
#include "gx/Window.hpp"
#include "util/BlizzardCore.hpp"
void MacOnKeyDown(NSEvent* event) {
BLIZZARD_ASSERT(false);
}
void MacOnKeyUp(NSEvent* event) {
uint32_t keyCode = event.keyCode;
MacClient::CheckKeyboardLayout();
if (keyCode <= 0x7F) {
uint32_t key = MacClient::s_keyConversion[keyCode];
if (key != KEY_NONE) {
OsQueuePut(OS_INPUT_KEY_UP, key, 0, 0, 0);
}
}
}
void MacOnMouseDown(int16_t button, int32_t x, int32_t y) {
NSEvent* event = [NSApp currentEvent];
uint32_t modifierFlags = event.modifierFlags;
uint32_t v8 = 0;
if (modifierFlags & NSShiftKeyMask) {
v8 |= 0x2;
}
if (modifierFlags & NSAlternateKeyMask) {
v8 |= 0x8;
}
if (modifierFlags & NSCommandKeyMask) {
v8 |= 0x1;
}
if (modifierFlags & NSControlKeyMask) {
v8 |= 0x10;
}
if (modifierFlags & NSAlphaShiftKeyMask) {
v8 |= 0x4;
}
int16_t buttonNumber = button + 1;
int16_t buttonIndex = button;
if (buttonNumber > 0xF) {
return;
}
if (Input::s_buttonDown[buttonIndex]) {
return;
}
int16_t effectiveButtonNumber = buttonNumber;
Input::s_buttonDown[buttonIndex] = 1;
if (buttonNumber == 1) {
effectiveButtonNumber = 1;
if (v8 & 0x1) {
Input::s_simulatedRightButtonClick = 1;
// TODO
// if (Input::byte_12B94E2) {
// return;
// }
effectiveButtonNumber = 2;
}
}
if (buttonNumber == 2) {
if (Input::s_simulatedRightButtonClick) {
return;
} else {
effectiveButtonNumber = 2;
}
}
MOUSEBUTTON mouseButton = ConvertButtonNumberToMOUSEBUTTON(effectiveButtonNumber);
if (mouseButton) {
if (Input::s_mouseMode == 0) {
Input::s_currentMouse = { x, y };
}
OsQueuePut(OS_INPUT_MOUSE_DOWN, mouseButton, x, y, 0);
}
}
void MacOnMouseMoved(int32_t x, int32_t y) {
if (Input::s_mouseMode == 1) {
NSEvent* event = [NSApp currentEvent];
int32_t deltaX = static_cast<int32_t>(floor(event.deltaX));
int32_t deltaY = static_cast<int32_t>(floor(event.deltaY));
OsQueuePut(OS_INPUT_MOUSE_MOVE_RELATIVE, 0, deltaX, deltaY, 0);
} else {
Input::s_currentMouse = { x, y };
OsQueuePut(OS_INPUT_MOUSE_MOVE, 0, x, y, 0);
}
}
void MacOnMouseUp(int16_t button, int32_t x, int32_t y) {
NSEvent* event = [NSApp currentEvent];
uint32_t modifierFlags = event.modifierFlags;
int16_t buttonNumber = button + 1;
int16_t buttonIndex = button;
if (buttonNumber > 0xF) {
return;
}
if (!Input::s_buttonDown[buttonIndex]) {
return;
}
int16_t effectiveButtonNumber = buttonNumber;
Input::s_buttonDown[buttonIndex] = 0;
if (buttonNumber == 1) {
effectiveButtonNumber = 1;
if (Input::s_simulatedRightButtonClick) {
effectiveButtonNumber = 2;
Input::s_simulatedRightButtonClick = 0;
// TODO
// if (Input::byte_12B94E2) {
// return;
// }
}
}
if (buttonNumber == 2) {
if (Input::s_simulatedRightButtonClick) {
return;
} else {
effectiveButtonNumber = 2;
}
}
MOUSEBUTTON mouseButton = ConvertButtonNumberToMOUSEBUTTON(effectiveButtonNumber);
if (mouseButton) {
if (Input::s_mouseMode != 0) {
Input::s_currentMouse = { x, y };
}
OsQueuePut(OS_INPUT_MOUSE_UP, mouseButton, x, y, 0);
}
}
void MacOnResized(int32_t width, int32_t height, bool a3) {
if (a3) {
return;
}
static_cast<CGxDeviceGLL*>(g_theGxDevicePtr)->Resize(width, height);
OsQueuePut(OS_INPUT_SIZE, width, height, 0, 0);
// TODO SubA61E60(width, height)
auto bounds = GetSavedWindowBounds();
Rect newBounds = {
bounds->top,
bounds->left,
static_cast<int16_t>(bounds->top + height),
static_cast<int16_t>(bounds->left + width)
};
SetSavedWindowBounds(newBounds);
}

View File

@ -0,0 +1,11 @@
#ifndef APP_MAC_WOW_APPLICATION_H
#define APP_MAC_WOW_APPLICATION_H
#include <AppKit/AppKit.h>
#include <Foundation/Foundation.h>
@interface WoWApplication : NSApplication
@end
#endif

View File

@ -0,0 +1,24 @@
#include "app/mac/WoWApplication.h"
#include "gx/gll/GLLayerView.h"
@implementation WoWApplication
- (void)sendEvent:(NSEvent*)event {
auto responder = [[NSApp keyWindow] firstResponder];
if (responder && [responder isKindOfClass: [GLLayerView class]]) {
NSEventType type = [event type];
if (type == NSKeyDown && (event.keyCode == 114 || (event.keyCode == 48 && event.modifierFlags & NSControlKeyMask))) {
[responder keyDown: event];
return;
} else if (type == NSKeyUp) {
[responder keyUp: event];
return;
}
}
[super sendEvent:event];
}
@end

143
src/async/AsyncFile.cpp Normal file
View File

@ -0,0 +1,143 @@
#include "async/AsyncFile.hpp"
#include "async/AsyncFileRead.hpp"
#include "async/CAsyncQueue.hpp"
#include "event/Event.hpp"
#include "util/SFile.hpp"
#include <common/Prop.hpp>
#include <common/Time.hpp>
CAsyncObject* AsyncFileReadAllocObject() {
AsyncFileRead::s_queueLock.Enter();
CAsyncObject* object = AsyncFileRead::s_asyncFileReadFreeList.Head();
if (!object) {
object = AsyncFileRead::s_asyncFileReadFreeList.NewNode(1, 0, 0x0);
}
object->link.Unlink();
AsyncFileRead::s_queueLock.Leave();
object->file = nullptr;
object->buffer = nullptr;
object->size = 0;
object->userArg = nullptr;
object->userPostloadCallback = nullptr;
object->userFailedCallback = nullptr;
object->queue = nullptr;
object->isProcessed = 0;
object->isRead = 0;
object->isCurrent = 0;
object->char24 = 0;
object->char25 = 0;
object->ptr1C = 0;
object->priority = 126;
return object;
}
void AsyncFileReadDestroyObject(CAsyncObject* object) {
AsyncFileRead::s_queueLock.Enter();
if (object->isCurrent) {
// TODO
// nullsub_3();
AsyncFileRead::s_queueLock.Leave();
while (object->isCurrent) {
OsSleep(1);
}
AsyncFileRead::s_queueLock.Enter();
}
object->link.Unlink();
if (object->file) {
SFile::Close(object->file);
}
AsyncFileRead::s_asyncFileReadFreeList.LinkToHead(object);
AsyncFileRead::s_queueLock.Leave();
}
void AsyncFileReadInitialize(uint32_t threadSleep, uint32_t handlerTimeout) {
AsyncFileRead::s_threadSleep = std::min(threadSleep, 100u);
AsyncFileRead::s_handlerTimeout = std::max(handlerTimeout, 20u);
EventRegisterEx(EVENT_ID_POLL, &AsyncFileReadPollHandler, nullptr, 0.0f);
if (SFile::IsStreamingMode()) {
// TODO
// EventRegisterEx(EVENT_ID_IDLE, &Sub4B9F40, nullptr, -1.0f);
}
AsyncFileRead::s_asyncWaitObject = nullptr;
AsyncFileRead::s_progressCallback = nullptr;
AsyncFileRead::s_progressParam = nullptr;
AsyncFileRead::s_ingameProgressCallback = nullptr;
AsyncFileRead::s_ingameStartCallback = nullptr;
AsyncFileRead::s_propContext = PropGetSelectedContext();
AsyncFileRead::s_shutdownEvent.Reset();
int32_t numQueues = SFile::IsStreamingMode() != 0 ? 3 : 1;
for (int32_t i = 0; i < numQueues; i++) {
CAsyncQueue* queue = AsyncFileReadCreateQueue();
const char* queueName = AsyncFileRead::s_asyncQueueNames[i];
AsyncFileRead::s_asyncQueues[i] = queue;
AsyncFileReadCreateThread(queue, queueName);
}
if (SFile::IsStreamingMode()) {
AsyncFileRead::s_asyncQueues[2]->int20 = 1;
}
// TODO
// - Something related to AsyncFileRead::s_userQueueLock
}
void AsyncFileReadObject(CAsyncObject* object, int32_t a2) {
CAsyncQueue* queue = AsyncFileRead::s_asyncQueues[0];
if (SFile::IsStreamingMode()) {
// TODO
// int32_t v3 = SFile::FileIsLocal(object->file, 6);
//
// if (!v3 || v3 == 2) {
// int32_t v4 = object->priority <= 127;
// object->char24 = 1;
// queue = AsyncFileRead::s_asyncQueues[1];
//
// if (!v4) {
// queue = AsyncFileRead::s_asyncQueues[2];
// }
// }
}
AsyncFileRead::s_queueLock.Enter();
object->queue = queue;
if (AsyncFileRead::s_asyncWaitObject == object) {
object->priority = object->priority > 127 ? 128 : 0;
// TODO
// object->ptr1C = g_theGxDevicePtr + 3944;
object->char25 = 0;
} else if (queue->int20) {
// TODO
// Sub4BA530(object, a2);
} else {
AsyncFileReadLinkObject(object, a2);
}
AsyncFileRead::s_queueLock.Leave();
if (SFile::IsStreamingMode()) {
// TODO
// SFile::LogFileAccess(object->file, 0, 0);
}
}

14
src/async/AsyncFile.hpp Normal file
View File

@ -0,0 +1,14 @@
#ifndef ASYNC_ASYNC_FILE_HPP
#define ASYNC_ASYNC_FILE_HPP
#include "async/CAsyncObject.hpp"
CAsyncObject* AsyncFileReadAllocObject(void);
void AsyncFileReadDestroyObject(CAsyncObject* object);
void AsyncFileReadInitialize(uint32_t threadSleep, uint32_t handlerTimeout);
void AsyncFileReadObject(CAsyncObject* object, int32_t a2);
#endif

196
src/async/AsyncFileRead.cpp Normal file
View File

@ -0,0 +1,196 @@
#include "async/AsyncFileRead.hpp"
#include "util/SFile.hpp"
#include <common/Prop.hpp>
#include <common/Time.hpp>
uint32_t AsyncFileRead::s_threadSleep;
uint32_t AsyncFileRead::s_handlerTimeout = 100;
CAsyncObject* AsyncFileRead::s_asyncWaitObject;
void* AsyncFileRead::s_progressCallback;
void* AsyncFileRead::s_progressParam;
int32_t AsyncFileRead::s_progressCount;
void* AsyncFileRead::s_ingameProgressCallback;
void* AsyncFileRead::s_ingameStartCallback;
void* AsyncFileRead::s_propContext;
SEvent AsyncFileRead::s_shutdownEvent = SEvent(1, 0);
const char* AsyncFileRead::s_asyncQueueNames[NUM_ASYNC_QUEUES] = {
"Disk Queue",
"Net Geometry Queue",
"Net Texture Queue"
};
CAsyncQueue* AsyncFileRead::s_asyncQueues[NUM_ASYNC_QUEUES];
SCritSect AsyncFileRead::s_queueLock;
SCritSect AsyncFileRead::s_userQueueLock;
TSList<CAsyncQueue, TSGetLink<CAsyncQueue>> AsyncFileRead::s_asyncQueueList;
TSList<CAsyncThread, TSGetLink<CAsyncThread>> AsyncFileRead::s_asyncThreadList;
STORM_EXPLICIT_LIST(CAsyncObject, link) AsyncFileRead::s_asyncFileReadPostList;
STORM_EXPLICIT_LIST(CAsyncObject, link) AsyncFileRead::s_asyncFileReadFreeList;
CAsyncQueue* AsyncFileReadCreateQueue() {
CAsyncQueue* queue = AsyncFileRead::s_asyncQueueList.NewNode(0, 2, 0x8);
return queue;
}
void AsyncFileReadCreateThread(CAsyncQueue* queue, const char* queueName) {
CAsyncThread* thread = AsyncFileRead::s_asyncThreadList.NewNode(0, 2, 0x8);
thread->queue = queue;
thread->currentObject = nullptr;
SThread::Create(AsyncFileReadThread, thread, thread->thread, const_cast<char*>(queueName), 0);
}
void AsyncFileReadLinkObject(CAsyncObject* object, int32_t a2) {
if (!object->queue) {
return;
}
object->link.Unlink();
auto& readList = object->queue->readList;
for (auto currentObject = readList.Head(); currentObject; currentObject = readList.Link(currentObject)->Next()) {
uint8_t priority = object->priority;
uint8_t currentPriority = currentObject->priority;
if (priority <= currentPriority && (a2 || priority != currentPriority)) {
readList.LinkNode(object, 2, currentObject);
object->char25 = 0;
return;
}
}
readList.LinkToTail(object);
object->char25 = 0;
}
int32_t AsyncFileReadPollHandler(const void*, void*) {
uint32_t start = OsGetAsyncTimeMsPrecise();
while (1) {
AsyncFileRead::s_queueLock.Enter();
CAsyncObject* object = AsyncFileRead::s_asyncFileReadPostList.Head();
if (!object) {
AsyncFileRead::s_queueLock.Leave();
break;
}
AsyncFileRead::s_asyncFileReadPostList.UnlinkNode(object);
if (AsyncFileRead::s_asyncWaitObject == object) {
AsyncFileRead::s_asyncWaitObject = nullptr;
}
object->isProcessed = 1;
AsyncFileRead::s_queueLock.Leave();
object->userPostloadCallback(object->userArg);
AsyncFileRead::s_progressCount--;
// Check if we're exceeded the allowed running time
if (OsGetAsyncTimeMsPrecise() - start > AsyncFileRead::s_handlerTimeout) {
break;
}
}
// TODO
// for (int32_t i = 0; i < DwordB4A224; i++) {
// DwordB4A228[i]();
// }
return 1;
}
uint32_t AsyncFileReadThread(void* param) {
CAsyncThread* thread = static_cast<CAsyncThread*>(param);
PropSelectContext(AsyncFileRead::s_propContext);
while (AsyncFileRead::s_shutdownEvent.Wait(0)) {
uint32_t sleep = 0;
CAsyncObject* object;
while (1) {
AsyncFileRead::s_queueLock.Enter();
object = thread->queue->readList.Head();
if (object && thread->queue->int20 && /* TODO */ true) {
// TODO
// Sub4BA530(object, 1);
AsyncFileRead::s_queueLock.Leave();
continue;
}
if (!object) {
object = thread->queue->list14.Head();
}
if (!object) {
AsyncFileRead::s_queueLock.Leave();
break;
}
object->link.Unlink();
object->queue = nullptr;
object->isCurrent = 1;
thread->currentObject = object;
AsyncFileRead::s_queueLock.Leave();
int32_t tries = 10;
while (1) {
if (SFile::IsStreamingMode() && object->file) {
// TODO
// Sub421820(object->file, (object->priority > 127) + 1, 1);
}
if (SFile::Read(object->file, object->buffer, object->size, nullptr, nullptr, nullptr)) {
break;
}
tries--;
// Handle failure
if (tries == 0) {
// TODO
// Sub421850((object->file, v17, 512);
// v10 = Sub7717E0();
// Sub771A80(v10, v18, 512);
// nullsub_3(v17);
break;
}
}
AsyncFileRead::s_queueLock.Enter();
AsyncFileRead::s_asyncFileReadPostList.LinkToTail(object);
thread->currentObject = nullptr;
object->isCurrent = 0;
object->isRead = 1;
AsyncFileRead::s_queueLock.Leave();
if (AsyncFileRead::s_threadSleep) {
sleep++;
if (sleep == AsyncFileRead::s_threadSleep) {
OsSleep(1);
sleep = 0;
}
}
}
OsSleep(1);
}
return 0;
}

View File

@ -0,0 +1,46 @@
#ifndef ASYNC_ASYNC_FILE_READ_HPP
#define ASYNC_ASYNC_FILE_READ_HPP
#include "async/CAsyncQueue.hpp"
#include "async/CAsyncThread.hpp"
#include <common/Prop.hpp>
#include <storm/Thread.hpp>
#define NUM_ASYNC_QUEUES 3
class CAsyncObject;
class AsyncFileRead {
public:
// Static variables
static uint32_t s_threadSleep;
static uint32_t s_handlerTimeout;
static CAsyncObject* s_asyncWaitObject;
static void* s_progressCallback;
static void* s_progressParam;
static int32_t s_progressCount;
static void* s_ingameProgressCallback;
static void* s_ingameStartCallback;
static HPROPCONTEXT s_propContext;
static SEvent s_shutdownEvent;
static const char* s_asyncQueueNames[];
static CAsyncQueue* s_asyncQueues[];
static SCritSect s_queueLock;
static SCritSect s_userQueueLock;
static TSList<CAsyncQueue, TSGetLink<CAsyncQueue>> s_asyncQueueList;
static TSList<CAsyncThread, TSGetLink<CAsyncThread>> s_asyncThreadList;
static STORM_EXPLICIT_LIST(CAsyncObject, link) s_asyncFileReadPostList;
static STORM_EXPLICIT_LIST(CAsyncObject, link) s_asyncFileReadFreeList;
};
CAsyncQueue* AsyncFileReadCreateQueue(void);
void AsyncFileReadCreateThread(CAsyncQueue* queue, const char* queueName);
void AsyncFileReadLinkObject(CAsyncObject* object, int32_t a2);
int32_t AsyncFileReadPollHandler(const void*, void*);
uint32_t AsyncFileReadThread(void* thread);
#endif

View File

@ -0,0 +1,30 @@
#ifndef ASYNC_C_ASYNC_OBJECT_HPP
#define ASYNC_C_ASYNC_OBJECT_HPP
#include <storm/List.hpp>
class SFile;
class CAsyncQueue;
class CAsyncObject {
public:
// Member variables
SFile* file;
void* buffer;
uint32_t size;
void* userArg;
void (*userPostloadCallback)(void*);
void (*userFailedCallback)(void*);
CAsyncQueue* queue;
void* ptr1C;
uint8_t priority;
uint8_t isProcessed;
uint8_t isRead;
uint8_t isCurrent;
uint8_t char24;
uint8_t char25;
uint8_t padding[2];
TSLink<CAsyncObject> link;
};
#endif

16
src/async/CAsyncQueue.hpp Normal file
View File

@ -0,0 +1,16 @@
#ifndef ASYNC_C_ASYNC_QUEUE_HPP
#define ASYNC_C_ASYNC_QUEUE_HPP
#include "async/CAsyncObject.hpp"
#include <cstdint>
#include <storm/List.hpp>
class CAsyncQueue : public TSLinkedNode<CAsyncQueue> {
public:
// Member variables
STORM_EXPLICIT_LIST(CAsyncObject, link) readList;
STORM_EXPLICIT_LIST(CAsyncObject, link) list14;
int32_t int20;
};
#endif

View File

@ -0,0 +1,19 @@
#ifndef ASYNC_C_ASYNC_THREAD_HPP
#define ASYNC_C_ASYNC_THREAD_HPP
#include <cstdint>
#include <storm/List.hpp>
#include <storm/Thread.hpp>
class CAsyncObject;
class CAsyncQueue;
class CAsyncThread : public TSLinkedNode<CAsyncThread> {
public:
// Member variables
SThread thread;
CAsyncQueue* queue;
CAsyncObject* currentObject;
};
#endif

19
src/async/CMakeLists.txt Normal file
View File

@ -0,0 +1,19 @@
file(GLOB PRIVATE_SOURCES "*.cpp")
add_library(async STATIC
${PRIVATE_SOURCES}
)
target_include_directories(async
PRIVATE
${CMAKE_SOURCE_DIR}/src
)
target_link_libraries(async
PRIVATE
event
util
PUBLIC
common
storm
)

25
src/client/CMakeLists.txt Normal file
View File

@ -0,0 +1,25 @@
file(GLOB PRIVATE_SOURCES "*.cpp")
add_library(client STATIC
${PRIVATE_SOURCES}
)
target_include_directories(client
PRIVATE
${CMAKE_SOURCE_DIR}/src
)
target_link_libraries(client
PRIVATE
async
event
gx
model
net
ui
util
world
PUBLIC
common
storm
)

437
src/client/Client.cpp Normal file
View File

@ -0,0 +1,437 @@
#include "client/Client.hpp"
#include "client/ClientServices.hpp"
#include "client/Console.hpp"
#include "async/AsyncFile.hpp"
#include "glue/CGlueMgr.hpp"
#include "gx/Device.hpp"
#include "gx/Screen.hpp"
#include "gx/Texture.hpp"
#include "model/Model2.hpp"
#include "ui/FrameScript.hpp"
#include "ui/FrameXML.hpp"
#include "util/BlizzardCore.hpp"
#include "util/CVar.hpp"
#include "world/World.hpp"
#include <cstring>
#include <common/Prop.hpp>
#include <storm/Error.hpp>
CVar* Client::g_accountListVar;
HEVENTCONTEXT Client::g_clientEventContext;
void AsyncFileInitialize() {
// TODO
AsyncFileReadInitialize(0, 100);
}
void BaseInitializeGlobal() {
PropInitialize();
}
void ClientMiscInitialize() {
// TODO
Client::g_accountListVar = CVar::Register(
"accountList",
"List of wow accounts for saved Blizzard account",
0,
"",
nullptr,
4,
false,
nullptr,
false
);
// TODO
}
void ClientPostClose(int32_t a1) {
// TODO s_finalDialog = a1;
EventPostCloseEx(nullptr);
}
int32_t DestroyEngineCallback(const void* a1, void* a2) {
// TODO
return 1;
}
int32_t InitializeEngineCallback(const void* a1, void* a2) {
// TODO
// sub_4D2A30();
AsyncFileInitialize();
TextureInitialize();
// ModelBlobLoad("world\\model.blob");
// if (SFile::IsStreamingMode()) {
// TextureLoadBlob("world\\liquid.tex");
// }
ScrnInitialize(0);
// ConsoleScreenInitialize(a2);
// s_cvarTextureFilteringMode = CVar::Register(
// "textureFilteringMode",
// "Texture filtering mode",
// 1,
// "1",
// &TextureFilteringCallback,
// 1,
// 0,
// 0,
// 0
// );
// s_cvarUIFaster = CVar::Register(
// "UIFaster",
// "UI acceleration option",
// 0,
// "3",
// &UIFasterCalllback,
// 1,
// 0,
// 0,
// 0
// );
// s_cvarTextureCacheSize = CVar::Register(
// "textureCacheSize",
// "Texture cache size in bytes",
// 1,
// "32",
// &TextureCacheSizeCallback,
// 1,
// 0,
// 0,
// 0
// );
// sub_4B6580(*(_DWORD *)(dword_B2F9FC + 48) << 20);
// AddConsoleDeviceDefaultCallback(SetDefaults);
// if (ConsoleDeviceHardwareChanged()) {
// v3 = 0;
// do {
// SetDefaults(v3++);
// } while (v3 < 3);
// }
auto m2Flags = M2RegisterCVars();
M2Initialize(m2Flags, 0);
// v4 = *(_DWORD *)(dword_B2FA00 + 48);
// sub_4B61C0(dword_AB6128[v4]);
// sub_4B6230(dword_AB6140[v4]);
WowClientInit();
return 1;
}
int32_t InitializeGlobal() {
// TODO
// SCmdRegisterArgList(&ProcessCommandLine(void)::s_wowArgList, 17u);
// CmdLineProcess();
// sub_403600("WoW.mfil");
// if (dword_B2FA10 != 2) {
// sub_403560();
// }
// LOBYTE(v24) = 0;
// if (sub_422140()) {
// LOBYTE(v24) = OsDirectoryExists((int)"WTF/Account") == 0;
// }
// ClientServices::LoadCDKey();
ConsoleInitializeClientCommand();
ConsoleInitializeClientCVar("Config.wtf");
// sub_7663F0();
// v18 = 0;
// v19 = 0;
// ptr = 0;
// v21 = 0;
// sub_406740(&v18, &CVar::Load);
// if (ptr) {
// SMemFree(ptr, a_pad, -2, 0);
// }
// CVar::Register("dbCompress", "Database compression", 0, "-1", 0, 5, 0, 0, 0);
// v2 = CVar::Register("locale", "Set the game locale", 0, "****", &LocaleChangedCallback, 5, 0, 0, 0);
// if (!SStrCmp(v2->m_stringValue.m_str, "****", 0x7FFFFFFFu)) {
// CVar::Set(v2, "enUS", 1, 0, 0, 1);
// }
// CVar::Register("useEnglishAudio", "override the locale and use English audio", 0, "0", 0, 5, 0, 0, 0);
// if (sub_422140()) {
// sub_4036B0(v24, 0, a2, (int)v2, (char)v24);
// }
// SStrCopy(&a1a, v2->m_stringValue.m_str, 5);
// sub_402D50(&a1a);
// CVar::Set(v2, &a1a, 1, 0, 0, 1);
// SStrPrintf(dest, 260, "%s%s", *(_DWORD *)off_AB6158, v2->m_stringValue.m_str);
// sub_421B50(dest);
// sub_423D70();
// sub_405DD0();
// CVar* v3 = CVar::Register(
// "processAffinityMask",
// "Sets which core(s) WoW may execute on - changes require restart to take effect",
// 2,
// "0",
// &sub_4022E0,
// 0,
// 0,
// 0,
// 0
// );
// CVar* v4 = CVar::Lookup("videoOptionsVersion");
// if (!v4 || v4->m_intValue < 3) {
// SStrPrintf(v23, 8, "%u", 0);
// CVar::Set(v3, v23, 1, 0, 0, 1);
// CVar::Update((int)v3);
// }
// v5 = v3->m_intValue;
// if (v5) {
// SSetCurrentProcessAffinityMask(v5);
// }
BaseInitializeGlobal();
EventInitialize(1, 0);
// CVar* v6 = CVar::Register(
// "timingTestError",
// "Error reported by the timing validation system",
// 6,
// "0",
// 0,
// 5,
// 0,
// 0,
// 0
// );
// v7 = v6;
// CVar* v8 = CVar::Register(
// "timingMethod",
// "Desired method for game timing",
// 2,
// "0",
// &sub_403200,
// 5,
// 0,
// v6,
// 0
// );
// sub_86D430(v8->m_intValue);
// ConsoleCommandRegister("timingInfo", (int)sub_4032A0, 0, 0);
// v9 = sub_86AD50();
// v10 = v9 == v7->m_intValue;
// dword_B2F9D8 = v9;
// if (!v10) {
// sprintf(&v17, "%d", v9);
// CVar::SetReadOnly((int)v7, 0);
// CVar::Set(v7, &v17, 1, 0, 0, 1);
// CVar::Update((int)v7);
// CVar::SetReadOnly((int)v7, 1);
// ConsolePrintf("Timing test error: %d", (int)v7);
// }
// WowClientDB<Startup_StringsRec>::Load(&g_Startup_StringsDB, 0, ".\\Client.cpp", 0x12E3u);
// Startup_StringsRec* v11 = g_Startup_StringsDB.GetRecordByIndex(1);
// const char* v12;
// if (v11) {
// v12 = v11->m_text;
// } else {
// v12 = "World of Warcraft";
// }
// TODO
// - replace with above logic for loading from Startup_Strings.dbc
const char* v12 = "World of Warcraft";
char v15[260];
SStrCopy(v15, v12, 0x7FFFFFFF);
ConsoleDeviceInitialize(v15);
// OsIMEInitialize();
// uint32_t v13 = OsGetAsyncTimeMs();
// g_rndSeed.SetSeed(v13);
Client::g_clientEventContext = EventCreateContextEx(
1,
&InitializeEngineCallback,
&DestroyEngineCallback,
0,
0
);
return 1;
}
void CommonMain() {
StormInitialize();
// TODO
// - error log setup
// - misc other setup
if (InitializeGlobal()) {
EventDoMessageLoop();
// TODO
// sub_406B70();
}
// TODO
// - misc cleanup
}
void BlizzardAssertCallback(const char* a1, const char* a2, const char* a3, uint32_t a4) {
if (*a2) {
SErrDisplayError(0, a3, a4, a2, 0, 1, 0x11111111);
} else {
SErrDisplayError(0, a3, a4, a1, 0, 1, 0x11111111);
}
}
void StormInitialize() {
// TODO
// SStrInitialize();
// SErrInitialize();
// SLogInitialize();
// SFile::Initialize();
Blizzard::Debug::SetAssertHandler(BlizzardAssertCallback);
}
void WowClientInit() {
// TODO
// EventRegister(EVENT_ID_5, (int)sub_4020E0);
// _cfltcvt_init_0();
ClientMiscInitialize();
// sub_401B60();
// ClientDBInitialize();
// LoadingScreenInitialize();
FrameScript_Initialize(0);
// TODO
// SI2::Init(0);
// sub_6F66B0();
FrameXML_RegisterDefault();
GlueScriptEventsInitialize();
ScriptEventsInitialize();
// TODO
// sub_6F75E0();
// sub_401FF0();
ClientServices::Initialize();
// TODO ClientServices::SetMessageHandler(SMSG_TUTORIAL_FLAGS, (int)sub_530920, 0);
// TODO
// v2 = CVar::Lookup("EnableVoiceChat");
// if (v2 && *(_DWORD *)(v2 + 48)) {
// ComSatClient_Init();
// }
// TODO
// DBCache_RegisterHandlers();
// DBCache_Initialize(a1);
// TODO
// sub_78E400();
CWorld::Initialize();
// TODO
// ShadowInit();
// GxuLightInitialize();
// GxuLightBucketSizeSet(16.665001);
// InputControlInitialize();
CGlueMgr::Initialize();
// TODO
// if (GetConsoleMessage()) {
// v3 = (const char *)GetConsoleMessage();
// CGlueMgr::AddChangedOptionWarning(v3);
// SetConsoleMessage(0);
// }
// TODO
// if (sub_422140()) {
// sub_421630();
// }
// TODO
// if (byte_B2F9E1 != 1) {
// if ((g_playIntroMovie + 48) == 1) {
// CVar::Set(g_playIntroMovie, "0", 1, 0, 0, 1);
// CGlueMgr::SetScreen("movie");
// } else {
// CGlueMgr::SetScreen("login");
// }
// } else {
// if ((dword_B2F980 + 48) == 1) {
// CVar::Set(dword_B2F980, "0", 1, 0, 0, 1);
// CVar::Set(g_playIntroMovie, "0", 1, 0, 0, 1);
// CGlueMgr::SetScreen("movie");
// } else {
// CGlueMgr::SetScreen("login");
// }
// }
// TODO
// - temporary until above logic is implemented
CGlueMgr::SetScreen("login");
// TODO
// CGlueMgr::m_pendingTimerAlert = dword_B2F9D8;
// sub_7FC5A0();
// EventRegister(EVENT_ID_POLL, &PollNet);
}

22
src/client/Client.hpp Normal file
View File

@ -0,0 +1,22 @@
#ifndef CLIENT_CLIENT_HPP
#define CLIENT_CLIENT_HPP
#include "event/Event.hpp"
#include <cstdint>
class CVar;
namespace Client {
extern CVar* g_accountListVar;
extern HEVENTCONTEXT g_clientEventContext;
}
void ClientPostClose(int32_t);
void CommonMain(void);
void StormInitialize(void);
void WowClientInit(void);
#endif

View File

@ -0,0 +1,10 @@
#ifndef CLIENT_CLIENT_REALM_RESPONSE_ADAPTER_HPP
#define CLIENT_CLIENT_REALM_RESPONSE_ADAPTER_HPP
#include "net/Connection.hpp"
class ClientRealmResponseAdapter : public RealmResponse {
public:
};
#endif

View File

@ -0,0 +1,92 @@
#include "client/ClientServices.hpp"
#include "client/ClientRealmResponseAdapter.hpp"
#include "net/Connection.hpp"
#include "net/Login.hpp"
#include <storm/Memory.hpp>
#include <storm/String.hpp>
#include <new>
ClientConnection* g_clientConnection;
RealmResponse* ClientServices::s_clientRealmResponse;
ClientConnection* ClientServices::s_currentConnection;
ClientServices* ClientServices::s_instance;
Login* ClientServices::s_loginObj;
bool ClientServices::s_newLogin;
ClientConnection* ClientServices::Connection() {
// TODO assertion?
return ClientServices::s_currentConnection;
}
ClientServices* ClientServices::GetInstance() {
if (ClientServices::s_instance) {
return ClientServices::s_instance;
}
auto instanceMem = SMemAlloc(sizeof(ClientServices), __FILE__, __LINE__, 0x0);
auto instance = new (instanceMem) ClientServices();
ClientServices::s_instance = instance;
return ClientServices::s_instance;
}
void ClientServices::Initialize() {
if (!g_clientConnection) {
auto adapterMem = SMemAlloc(sizeof(ClientRealmResponseAdapter), __FILE__, __LINE__, 0x0);
auto clientRealmResponse = new (adapterMem) ClientRealmResponseAdapter();
ClientServices::s_clientRealmResponse = clientRealmResponse;
auto connectionMem = SMemAlloc(sizeof(ClientConnection), __FILE__, __LINE__, 0x0);
auto clientConnection = new (connectionMem) ClientConnection(ClientServices::s_clientRealmResponse);
g_clientConnection = clientConnection;
}
ClientServices::s_currentConnection = g_clientConnection;
// TODO ConsoleCommandRegister("logout", &Sub6B2030, 5, nullptr);
}
Login* ClientServices::LoginConnection() {
return ClientServices::s_loginObj;
}
void ClientServices::Logon(const char* accountName, const char* password) {
if (ClientServices::s_newLogin) {
if (ClientServices::s_loginObj) {
// TODO
// ClientServices::s_loginObj->Vfunc48(1);
ClientServices::s_loginObj = nullptr;
}
ClientServices::s_newLogin = false;
}
auto useBattlenet = SStrChr(accountName, '@') != 0;
Login* loginObj;
if (useBattlenet) {
// TODO
} else {
auto loginMem = SMemAlloc(sizeof(GruntLogin), __FILE__, __LINE__, 0x0);
loginObj = new (loginMem) GruntLogin();
}
ClientServices::s_loginObj = loginObj;
ClientServices::s_loginObj->Init(ClientServices::GetInstance());
// TODO
ClientServices::s_loginObj->SetLogonCreds(accountName, password);
// TODO
ClientServices::s_loginObj->Logon(nullptr, nullptr);
}
void ClientServices::LoginServerStatus(LOGIN_STATE state, LOGIN_RESULT result, const char* addrStr, const char* stateStr, const char* resultStr, uint16_t a7) {
// TODO
}

View File

@ -0,0 +1,30 @@
#ifndef CLIENT_CLIENT_SERVICES_HPP
#define CLIENT_CLIENT_SERVICES_HPP
#include "net/login/LoginResponse.hpp"
class ClientConnection;
class Login;
class RealmResponse;
class ClientServices : public LoginResponse {
public:
// Static variables
static RealmResponse* s_clientRealmResponse;
static ClientConnection* s_currentConnection;
static ClientServices* s_instance;
static Login* s_loginObj;
static bool s_newLogin;
// Static functions
static ClientConnection* Connection();
static ClientServices* GetInstance();
static void Initialize();
static Login* LoginConnection();
static void Logon(const char* accountName, const char* password);
// Virtual member functions
virtual void LoginServerStatus(LOGIN_STATE state, LOGIN_RESULT result, const char* addrStr, const char* stateStr, const char* resultStr, uint16_t a7);
};
#endif

191
src/client/Console.cpp Normal file
View File

@ -0,0 +1,191 @@
#include "client/Console.hpp"
#include "gx/Device.hpp"
#include "util/CVar.hpp"
#include <cstring>
CVar* s_cvGxMaximize;
CVar* s_cvGxResolution;
CVar* s_cvGxWidescreen;
CVar* s_cvGxWindow;
DefaultSettings s_defaults;
bool s_hwDetect;
bool s_hwChanged;
CGxFormat s_requestedFormat;
bool CVGxMaximizeCallback(CVar*, const char*, const char*, void*) {
// TODO
return true;
}
bool CVGxResolutionCallback(CVar*, const char*, const char*, void*) {
// TODO
return true;
}
bool CVGxWindowCallback(CVar*, const char*, const char*, void*) {
// TODO
return true;
}
void RegisterGxCVars() {
auto& format = s_defaults.format;
// TODO CURRENT_LANGUAGE check?
auto v1 = true;
s_cvGxWidescreen = CVar::Register(
"widescreen",
"Allow widescreen support",
0x0,
"1",
nullptr,
1,
false,
nullptr,
false
);
s_cvGxWindow = CVar::Register(
"gxWindow",
"toggle fullscreen/window",
0x1 | 0x2,
v1 ? "1" : "0",
&CVGxWindowCallback,
1,
0,
0,
0
);
s_cvGxMaximize = CVar::Register(
"gxMaximize",
"maximize game window",
0x1 | 0x2,
v1 ? "1" : "0",
&CVGxMaximizeCallback,
1,
0,
0,
0
);
// TODO s_cvGxColorBits
// TODO s_cvGxDepthBits
char resolution[260];
SStrPrintf(resolution, 260, "%dx%d", format.size.x, format.size.y);
s_cvGxResolution = CVar::Register(
"gxResolution",
"resolution",
0x1 | 0x2,
resolution,
&CVGxResolutionCallback,
1,
false,
nullptr,
false
);
// TODO s_cvGxRefresh
// TODO s_cvGxTripleBuffer
// TODO s_cvGxApi
// TODO s_cvGxVSync
// TODO s_cvGxAspect
// TODO s_cvGxCursor
// TODO s_cvGxMultisample
// TODO s_cvGxFixLag
// TODO s_cvGxStereoEnabled
// TODO s_cvGxOverride
// TODO s_cvGxAspect
// TODO s_cvGxMaxFPS
// TODO s_cvGxMaxFPSBk
// TODO s_cvWindowResizeLock
// TODO s_cvFixedFunction
}
void UpdateGxCVars() {
// TODO others
s_cvGxWindow->Update();
s_cvGxResolution->Update();
// TODO others
s_cvGxMaximize->Update();
// TODO others
}
void SetGxCVars(const CGxFormat& format) {
char value[1024];
// TODO s_cvGxColorBits
// TODO s_cvGxDepthBits
SStrPrintf(value, sizeof(value), "%d", format.window);
s_cvGxWindow->Set(value, true, false, false, true);
SStrPrintf(value, sizeof(value), "%dx%d", format.size.x, format.size.y);
s_cvGxResolution->Set(value, true, false, false, true);
// TODO s_cvGxRefresh
// TODO others
SStrPrintf(value, sizeof(value), "%d", format.maximize);
s_cvGxMaximize->Set(value, true, false, false, true);
// TODO others
UpdateGxCVars();
}
void ConsoleInitializeClientCommand() {
// TODO
}
void ConsoleInitializeClientCVar(const char* a1) {
// TODO
}
void ConsoleDeviceInitialize(const char* title) {
// TODO
// TODO proper logic
s_hwDetect = true;
// TODO
RegisterGxCVars();
// TODO ConsoleCommandRegister("gxRestart", &CCGxRestart, 1, nullptr);
// TODO
// TODO
// - source the size values correctly
s_requestedFormat.size.x = 1024;
s_requestedFormat.size.y = 768;
s_requestedFormat.colorFormat = CGxFormat::Fmt_Argb8888;
s_requestedFormat.depthFormat = CGxFormat::Fmt_Ds248;
if (s_hwDetect || s_hwChanged) {
// TODO Sub76B3F0(&UnkCABAF0, &UnkCABB38);
// TODO s_cvFixedFunction->Set("0", 1, 0, 0, 1);
// TODO memcpy(&s_requestedFormat, &s_defaults.format, sizeof(s_requestedFormat));
s_requestedFormat.window = s_cvGxWindow->GetInt() != 0;
s_requestedFormat.maximize = s_cvGxMaximize->GetInt() != 0;
// TODO temporary override
s_requestedFormat.maximize = 0;
SetGxCVars(s_requestedFormat);
}
CGxFormat format;
memcpy(&format, &s_requestedFormat, sizeof(s_requestedFormat));
CGxDevice* device = GxDevCreate(GxApi_GLL, nullptr, format);
// TODO
}

16
src/client/Console.hpp Normal file
View File

@ -0,0 +1,16 @@
#ifndef CLIENT_CONSOLE_HPP
#define CLIENT_CONSOLE_HPP
#include "gx/CGxFormat.hpp"
struct DefaultSettings {
CGxFormat format;
};
void ConsoleInitializeClientCommand();
void ConsoleInitializeClientCVar(const char* a1);
void ConsoleDeviceInitialize(const char* title);
#endif

40
src/event/CEvent.cpp Normal file
View File

@ -0,0 +1,40 @@
#include "event/CEvent.hpp"
#include "gx/Coordinate.hpp"
CCharEvent& CCharEvent::operator=(const EVENT_DATA_CHAR& data) {
this->ch = data.ch;
this->metaKeyState = data.metaKeyState;
this->repeat = data.repeat;
return *this;
}
CKeyEvent& CKeyEvent::operator=(const EVENT_DATA_KEY& data) {
this->key = data.key;
this->metaKeyState = data.metaKeyState;
this->repeat = data.repeat;
this->time = data.time;
return *this;
}
CMouseEvent& CMouseEvent::operator=(const EVENT_DATA_MOUSE& data) {
this->mode = data.mode;
this->button = data.button;
this->buttonState = data.buttonState;
this->metaKeyState = data.metaKeyState;
this->flags = data.flags;
this->time = data.time;
this->wheelDistance = data.wheelDistance;
NDCToDDC(data.x, data.y, &this->x, &this->y);
return *this;
}
CSizeEvent& CSizeEvent::operator=(const EVENT_DATA_SIZE& data) {
this->w = data.w;
this->h = data.h;
return *this;
}

39
src/event/CEvent.hpp Normal file
View File

@ -0,0 +1,39 @@
#ifndef EVENT_C_EVENT_HPP
#define EVENT_C_EVENT_HPP
#include "event/Types.hpp"
#include <cstdint>
#include <common/Ref.hpp>
class CEvent : public TRefCnt {
public:
// Member variables
uint32_t id;
void* param;
};
class CCharEvent : public CEvent, public EVENT_DATA_CHAR {
public:
// Member functions
CCharEvent& operator=(const EVENT_DATA_CHAR&);
};
class CKeyEvent : public CEvent, public EVENT_DATA_KEY {
public:
// Member functions
CKeyEvent& operator=(const EVENT_DATA_KEY&);
};
class CMouseEvent : public CEvent, public EVENT_DATA_MOUSE {
public:
// Member functions
CMouseEvent& operator=(const EVENT_DATA_MOUSE&);
};
class CSizeEvent : public CEvent, public EVENT_DATA_SIZE {
public:
// Member functions
CSizeEvent& operator=(const EVENT_DATA_SIZE&);
};
#endif

27
src/event/CMakeLists.txt Normal file
View File

@ -0,0 +1,27 @@
file(GLOB PRIVATE_SOURCES "*.cpp")
if(WHOA_SYSTEM_MAC)
file(GLOB MAC_SOURCES
"mac/*.cpp"
"mac/*.mm"
)
list(APPEND PRIVATE_SOURCES ${MAC_SOURCES})
endif()
add_library(event STATIC
${PRIVATE_SOURCES}
)
target_include_directories(event
PRIVATE
${CMAKE_SOURCE_DIR}/src
)
target_link_libraries(event
PRIVATE
gx
PUBLIC
common
storm
tempest
)

112
src/event/Context.cpp Normal file
View File

@ -0,0 +1,112 @@
#include "event/Context.hpp"
#include "event/Event.hpp"
#include "event/EvtThread.hpp"
#include <common/Time.hpp>
#include <storm/Atomic.hpp>
HEVENTCONTEXT AttachContextToThread(EvtContext* context) {
SInterlockedIncrement(&Event::s_threadListContention);
Event::s_threadListCritsect.Enter();
// Select the thread with the highest weight total
EvtThread* thread = nullptr;
EvtThread* t = Event::s_threadList.Head();
while (t) {
if (!thread || t->m_weightTotal < thread->m_weightTotal) {
thread = t;
}
t = t->Next();
}
if (thread) {
TSingletonInstanceId<EvtContext, offsetof(EvtContext, m_id)>::s_idTable.Insert(context);
uint32_t v13 = OsGetAsyncTimeMs();
if (v13 != context->m_schedNextWakeTime.m_val) {
context->m_schedNextWakeTime.m_val = v13;
context->m_schedNextWakeTime.Relink();
}
Event::s_threadSlotCritsects[thread->m_threadSlot].Enter();
thread->m_contextQueue.Enqueue(context);
Event::s_threadSlotCritsects[thread->m_threadSlot].Leave();
thread->m_wakeEvent.Set();
uint32_t v14 = context->m_schedWeight + thread->m_weightTotal;
uint32_t v15 = thread->m_contextCount + 1;
thread->m_contextCount = v15;
thread->m_weightTotal = v14;
thread->m_weightAvg = v14 / v15;
} else {
// TODO
}
Event::s_threadListCritsect.Leave();
SInterlockedDecrement(&Event::s_threadListContention);
return context;
}
void DetachContextFromThread(uint32_t a1, EvtContext* a2) {
// TODO
}
EvtContext* GetNextContext(uint32_t hThread) {
EvtContext* context;
Event::s_threadSlotCritsects[hThread].Enter();
context = Event::s_threadSlots[hThread]->m_contextQueue.Dequeue();
Event::s_threadSlotCritsects[hThread].Leave();
if (hThread == Event::s_mainThread) {
Event::s_currentEvtContext = context;
}
return context;
}
void PutContext(uint32_t nextWakeTime, uint32_t newSmoothWeight, EvtContext* context, uint32_t hThread) {
if (nextWakeTime != context->m_schedNextWakeTime.m_val) {
context->m_schedNextWakeTime.m_val = nextWakeTime;
context->m_schedNextWakeTime.Relink();
}
if (context->m_schedSmoothWeight != newSmoothWeight) {
uint32_t v8 = context->m_schedWeight;
context->m_schedSmoothWeight = newSmoothWeight;
int32_t v9;
if (newSmoothWeight <= v8) {
v9 = v8 - newSmoothWeight;
} else {
v9 = newSmoothWeight - v8;
}
context->m_schedRebalance = v9 >= v8 >> 3;
}
if (!SInterlockedIncrement(&Event::s_threadListContention)) {
Event::s_threadListCritsect.Enter();
// TODO
Event::s_threadListCritsect.Leave();
}
SInterlockedDecrement(&Event::s_threadListContention);
if (hThread < Event::s_threadSlotCount) {
Event::s_threadSlotCritsects[hThread].Enter();
Event::s_threadSlots[hThread]->m_contextQueue.Enqueue(context);
Event::s_threadSlotCritsects[hThread].Leave();
}
}

17
src/event/Context.hpp Normal file
View File

@ -0,0 +1,17 @@
#ifndef EVENT_CONTEXT_HPP
#define EVENT_CONTEXT_HPP
#include "event/Types.hpp"
#include <cstdint>
class EvtContext;
HEVENTCONTEXT AttachContextToThread(EvtContext* context);
void DetachContextFromThread(uint32_t a1, EvtContext* a2);
EvtContext* GetNextContext(uint32_t hThread);
void PutContext(uint32_t nextWakeTime, uint32_t newSmoothWeight, EvtContext* context, uint32_t hThread);
#endif

136
src/event/Event.cpp Normal file
View File

@ -0,0 +1,136 @@
#include "event/Event.hpp"
#include "event/EvtContext.hpp"
#include "event/EvtThread.hpp"
#include "event/Input.hpp"
#include "event/Queue.hpp"
#include "event/Scheduler.hpp"
#include <cstring>
#include <common/Prop.hpp>
#include <common/Time.hpp>
#include <storm/String.hpp>
SEvent Event::s_startEvent = SEvent(1, 0);
SEvent Event::s_shutdownEvent = SEvent(1, 0);
int32_t Event::s_netServer;
int32_t Event::s_threadSlotCount;
SCritSect* Event::s_threadSlotCritsects;
EvtThread** Event::s_threadSlots;
uint32_t Event::s_mainThread;
TSGrowableArray<SThread*> Event::s_schedulerThreads;
ATOMIC32 Event::s_threadListContention { -1 };
SCritSect Event::s_threadListCritsect;
TSList<EvtThread, TSGetLink<EvtThread>> Event::s_threadList;
EvtContext* Event::s_currentEvtContext;
ATOMIC32 Event::s_interactiveCount;
#if defined(WHOA_SYSTEM_MAC)
bool Event::s_shouldLoopTerminate;
#endif
void OsNetPump(uint32_t timeout) {
// TODO
}
void EventInitialize(int32_t threadCount, int32_t netServer) {
IEvtInputInitialize();
int32_t v2 = threadCount;
if (threadCount < 1) {
v2 = 1;
}
IEvtSchedulerInitialize(v2, netServer);
// TODO
// OsInputSetEventPollProc(&sub_47DCA0);
}
int32_t EventIsControlKeyDown() {
return EventIsKeyDown(KEY_LCONTROL) || EventIsKeyDown(KEY_RCONTROL);
}
int32_t EventIsKeyDown(KEY key) {
// TODO
return 0;
}
int32_t EventIsShiftKeyDown() {
return EventIsKeyDown(KEY_LSHIFT) || EventIsKeyDown(KEY_RSHIFT);
}
HEVENTCONTEXT EventCreateContextEx(int32_t interactive, int32_t (*initializeHandler)(const void*, void*), int32_t (*destroyHandler)(const void*, void*), uint32_t idleTime, uint32_t debugFlags) {
return IEvtSchedulerCreateContext(interactive, initializeHandler, destroyHandler, idleTime, debugFlags);
}
void EventDoMessageLoop() {
IEvtSchedulerProcess();
}
void EventPostCloseEx(HEVENTCONTEXT contextHandle) {
if (!contextHandle) {
contextHandle = PropGet(PROP_EVENTCONTEXT);
}
if (contextHandle) {
uint32_t contextId = *reinterpret_cast<uint32_t*>(contextHandle);
int32_t findMask;
EvtContext* context = TSingletonInstanceId<EvtContext, offsetof(EvtContext, m_id)>::s_idTable.Ptr(
contextId,
0,
&findMask
);
if (context) {
context->m_critsect.Enter();
if (context->m_schedState == EvtContext::SCHEDSTATE_ACTIVE) {
context->m_schedState = EvtContext::SCHEDSTATE_CLOSED;
}
context->m_critsect.Leave();
if (findMask != -1) {
TSingletonInstanceId<EvtContext, offsetof(EvtContext, m_id)>::s_idTable.Unlock(
findMask & (INSTANCE_TABLE_SLOT_COUNT - 1),
findMask >= INSTANCE_TABLE_SLOT_COUNT
);
}
}
}
}
void EventRegister(EVENTID id, EVENTHANDLERFUNC handler) {
EventRegisterEx(id, handler, nullptr, 0.0f);
}
void EventRegisterEx(EVENTID id, EVENTHANDLERFUNC handler, void* param, float priority) {
if (id < 0 || id > EVENTIDS || handler == nullptr) {
// TODO
// SErrSetLastError(0x57u);
return;
}
HEVENTCONTEXT hContext = PropGet(PROP_EVENTCONTEXT);
uint32_t contextId = *reinterpret_cast<uint32_t*>(hContext);
int32_t findMask;
EvtContext* context = TSingletonInstanceId<EvtContext, offsetof(EvtContext, m_id)>::s_idTable.Ptr(
contextId,
0,
&findMask
);
if (context) {
IEvtQueueRegister(context, id, handler, param, priority);
if (findMask != -1) {
TSingletonInstanceId<EvtContext, offsetof(EvtContext, m_id)>::s_idTable.Unlock(
findMask & (INSTANCE_TABLE_SLOT_COUNT - 1),
findMask >= INSTANCE_TABLE_SLOT_COUNT
);
}
}
}

56
src/event/Event.hpp Normal file
View File

@ -0,0 +1,56 @@
#ifndef EVENT_EVENT_HPP
#define EVENT_EVENT_HPP
#include "event/CEvent.hpp"
#include "event/Types.hpp"
#include <cstdint>
#include <storm/Array.hpp>
#include <storm/Atomic.hpp>
#include <storm/List.hpp>
#include <storm/Thread.hpp>
class EvtContext;
class EvtThread;
namespace Event {
extern SEvent s_startEvent;
extern SEvent s_shutdownEvent;
extern int32_t s_netServer;
extern int32_t s_originalThreadPriority;
extern int32_t s_threadSlotCount;
extern SCritSect* s_threadSlotCritsects;
extern EvtThread** s_threadSlots;
extern uint32_t s_mainThread;
extern TSGrowableArray<SThread*> s_schedulerThreads;
extern ATOMIC32 s_threadListContention;
extern SCritSect s_threadListCritsect;
extern TSList<EvtThread, TSGetLink<EvtThread>> s_threadList;
extern EvtContext* s_currentEvtContext;
extern ATOMIC32 s_interactiveCount;
#if defined(WHOA_SYSTEM_MAC)
extern bool s_shouldLoopTerminate;
#endif
}
HEVENTCONTEXT EventCreateContextEx(int32_t interactive, int32_t (*initializeHandler)(const void*, void*), int32_t (*destroyHandler)(const void*, void*), uint32_t idleTime, uint32_t debugFlags);
void EventDoMessageLoop();
void EventInitialize(int32_t threadCount, int32_t netServer);
int32_t EventIsControlKeyDown();
int32_t EventIsKeyDown(KEY key);
int32_t EventIsShiftKeyDown();
void EventPostCloseEx(HEVENTCONTEXT contextHandle);
void EventRegister(EVENTID id, int32_t (*handler)(const void*, void*));
void EventRegisterEx(EVENTID id, int32_t (*handler)(const void*, void*), void* param, float priority);
void OsNetPump(uint32_t timeout);
#endif

30
src/event/EvtContext.cpp Normal file
View File

@ -0,0 +1,30 @@
#include "event/EvtContext.hpp"
#include <common/Time.hpp>
EvtContext::EvtContext(uint32_t flags, uint32_t idleTime, uint32_t schedWeight, void* callContext, int32_t startWatchdog) :
TSingletonInstanceId<EvtContext, offsetof(TInstanceId<EvtContext>, m_id)>(),
m_critsect(),
m_schedNextWakeTime(),
m_queueHandlerList(),
m_queueMessageList(),
m_queueSyncKeyDownList()
// TODO
// m_timerIdTable()
{
this->m_currTime = 0;
this->m_schedState = SCHEDSTATE_ACTIVE;
this->m_schedLastIdle = OsGetAsyncTimeMs();
this->m_schedFlags = flags;
this->m_schedIdleTime = idleTime;
this->m_schedInitialIdleTime = idleTime;
this->m_schedWeight = schedWeight;
this->m_schedSmoothWeight = schedWeight;
this->m_schedRebalance = 0;
this->m_queueSyncButtonState = 0;
this->m_propContext = PropCreateContext();
this->m_callContext = callContext;
this->m_startWatchdog = startWatchdog;
}
EvtContextQueue::EvtContextQueue() : TSPriorityQueue<EvtContext>(offsetof(EvtContext, m_schedNextWakeTime)) {
}

57
src/event/EvtContext.hpp Normal file
View File

@ -0,0 +1,57 @@
#ifndef EVENT_EVT_CONTEXT_HPP
#define EVENT_EVT_CONTEXT_HPP
#include "event/EvtHandler.hpp"
#include "event/EvtKeyDown.hpp"
#include "event/EvtMessage.hpp"
#include "event/EvtTimer.hpp"
#include "event/Types.hpp"
#include <cstdint>
#include <common/Instance.hpp>
#include <common/Prop.hpp>
#include <storm/Queue.hpp>
#include <storm/Thread.hpp>
class EvtContext : public TSingletonInstanceId<EvtContext, offsetof(TInstanceId<EvtContext>, m_id)> {
public:
// Types
enum SCHEDSTATE {
SCHEDSTATE_ACTIVE = 0x0,
SCHEDSTATE_CLOSED = 0x1,
SCHEDSTATE_DESTROYED = 0x2,
_UNIQUE_SYMBOL_SCHEDSTATE_96 = 0xFFFFFFFF,
};
// Member variables
SCritSect m_critsect;
uint32_t m_currTime;
SCHEDSTATE m_schedState;
TSTimerPriority<uint32_t> m_schedNextWakeTime;
uint32_t m_schedLastIdle;
uint32_t m_schedFlags;
uint32_t m_schedIdleTime;
uint32_t m_schedInitialIdleTime;
uint32_t m_schedWeight;
uint32_t m_schedSmoothWeight;
int32_t m_schedRebalance;
TSExplicitList<EvtHandler, offsetof(EvtHandler, link)> m_queueHandlerList[EVENTIDS];
TSExplicitList<EvtMessage, offsetof(EvtMessage, link)> m_queueMessageList;
uint32_t m_queueSyncButtonState;
TSExplicitList<EvtKeyDown, offsetof(EvtKeyDown, link)> m_queueSyncKeyDownList;
// TODO
// EvtIdTable<EvtTimer*> m_timerIdTable;
EvtTimerQueue m_timerQueue;
HPROPCONTEXT m_propContext;
void* m_callContext;
uint32_t m_startWatchdog;
// Member functions
EvtContext(uint32_t, uint32_t, uint32_t, void*, int32_t);
};
class EvtContextQueue : public TSPriorityQueue<EvtContext> {
public:
EvtContextQueue();
};
#endif

17
src/event/EvtHandler.hpp Normal file
View File

@ -0,0 +1,17 @@
#ifndef EVENT_EVT_HANDLER_HPP
#define EVENT_EVT_HANDLER_HPP
#include <cstdint>
#include <storm/List.hpp>
class EvtHandler {
public:
// Member variables
TSLink<EvtHandler> link;
int32_t (*func)(const void*, void*);
void* param;
float priority;
int32_t marker;
};
#endif

14
src/event/EvtKeyDown.hpp Normal file
View File

@ -0,0 +1,14 @@
#ifndef EVENT_EVT_KEY_DOWN_HPP
#define EVENT_EVT_KEY_DOWN_HPP
#include "event/Types.hpp"
#include <storm/List.hpp>
class EvtKeyDown {
public:
// Member variables
TSLink<EvtKeyDown> link;
KEY key;
};
#endif

16
src/event/EvtMessage.hpp Normal file
View File

@ -0,0 +1,16 @@
#ifndef EVENT_EVT_MESSAGE_HPP
#define EVENT_EVT_MESSAGE_HPP
#include "event/Types.hpp"
#include <common/Instance.hpp>
#include <storm/List.hpp>
class EvtMessage : public TExtraInstanceRecyclable<EvtMessage> {
public:
// Member variables
TSLink<EvtMessage> link;
EVENTID id;
char data[4];
};
#endif

4
src/event/EvtThread.cpp Normal file
View File

@ -0,0 +1,4 @@
#include "event/EvtThread.hpp"
EvtThread::EvtThread() : TSLinkedNode<EvtThread>() {
}

25
src/event/EvtThread.hpp Normal file
View File

@ -0,0 +1,25 @@
#ifndef EVENT_EVT_THREAD_HPP
#define EVENT_EVT_THREAD_HPP
#include "event/EvtContext.hpp"
#include <cstdint>
#include <storm/List.hpp>
#include <storm/Thread.hpp>
class EvtThread : public TSLinkedNode<EvtThread> {
public:
// Member variables
uint32_t m_threadSlot;
uint32_t m_threadCount;
uint32_t m_weightTotal;
uint32_t m_weightAvg;
uint32_t m_contextCount;
uint32_t m_rebalance;
SEvent m_wakeEvent = SEvent(0, 0);
EvtContextQueue m_contextQueue;
// Member functions
EvtThread();
};
#endif

27
src/event/EvtTimer.hpp Normal file
View File

@ -0,0 +1,27 @@
#ifndef EVENT_EVT_TIMER_HPP
#define EVENT_EVT_TIMER_HPP
#include <cstdint>
#include <storm/Queue.hpp>
class EvtTimer {
public:
// Member variables
uint32_t id;
TSTimerPriority<uint32_t> targetTime;
float timeout;
int32_t (*handler)(const void*, void*);
void* param;
int32_t (*guidHandler)(const void*, uint64_t, void*);
uint64_t guidParam;
void* guidParam2;
};
class EvtTimerQueue : public TSPriorityQueue<EvtTimer> {
public:
EvtTimerQueue()
: TSPriorityQueue<EvtTimer>(offsetof(EvtTimer, targetTime))
{};
};
#endif

686
src/event/Input.cpp Normal file
View File

@ -0,0 +1,686 @@
#include "event/Input.hpp"
#include "event/EvtContext.hpp"
#include "event/Queue.hpp"
#include "gx/Window.hpp"
#include <common/Time.hpp>
#include <storm/String.hpp>
#include <storm/Unicode.hpp>
#include <tempest/Rect.hpp>
#include <tempest/Vector.hpp>
#if defined(WHOA_SYSTEM_MAC)
#include "app/mac/MacClient.h"
#endif
namespace Input {
CRect s_boundingRect;
int32_t s_queueHead;
int32_t s_queueTail;
OSEVENT s_queue[32];
MOUSEBUTTON s_buttonConversion[16] = {
MOUSE_BUTTON_NONE,
MOUSE_BUTTON_LEFT,
MOUSE_BUTTON_RIGHT,
MOUSE_BUTTON_MIDDLE,
MOUSE_BUTTON_XBUTTON1,
MOUSE_BUTTON_XBUTTON2,
MOUSE_BUTTON_XBUTTON3,
MOUSE_BUTTON_XBUTTON4,
MOUSE_BUTTON_XBUTTON5,
MOUSE_BUTTON_XBUTTON6,
MOUSE_BUTTON_XBUTTON7,
MOUSE_BUTTON_XBUTTON8,
MOUSE_BUTTON_XBUTTON9,
MOUSE_BUTTON_XBUTTON10,
MOUSE_BUTTON_XBUTTON11,
MOUSE_BUTTON_XBUTTON12,
};
}
int32_t Input::s_buttonDown[16];
uint32_t Input::s_buttonState;
C2iVector Input::s_currentMouse;
uint32_t Input::s_mouseHoldButton;
MOUSEMODE Input::s_mouseMode;
int32_t Input::s_numlockState;
int32_t Input::s_simulatedRightButtonClick;
uint32_t Input::s_metaKeyState;
#if defined(WHOA_SYSTEM_WIN)
int32_t Input::s_savedMouseSpeed;
#endif
#if defined(WHOA_SYSTEM_MAC)
double Input::s_savedMouseSpeed;
#endif
void PostChar(EvtContext* context, int32_t ch, int32_t repeat) {
EVENT_DATA_CHAR data;
data.ch = ch;
data.metaKeyState = Input::s_metaKeyState;
data.repeat = repeat;
IEvtQueueDispatch(context, EVENT_ID_CHAR, &data);
}
void PostKeyDown(EvtContext* context, int32_t key, int32_t repeat, int32_t time) {
if (key <= KEY_LASTMETAKEY) {
if ((1 << key) & Input::s_metaKeyState) {
return;
}
Input::s_metaKeyState |= 1 << key;
}
EVENT_DATA_KEY data;
data.key = static_cast<KEY>(key);
data.metaKeyState = Input::s_metaKeyState;
data.repeat = repeat;
data.time = time;
IEvtQueueDispatch(context, EVENT_ID_KEYDOWN, &data);
}
void PostKeyUp(EvtContext* context, int32_t key, int32_t repeat, int32_t time) {
if (key <= KEY_LASTMETAKEY) {
if ( !((1 << key) & Input::s_metaKeyState) ) {
return;
}
Input::s_metaKeyState &= ~(1 << key);
}
EVENT_DATA_KEY data;
data.key = static_cast<KEY>(key);
data.metaKeyState = Input::s_metaKeyState;
data.repeat = repeat;
data.time = time;
IEvtQueueDispatch(context, EVENT_ID_KEYUP, &data);
}
void PostMouseDown(EvtContext* context, MOUSEBUTTON button, int32_t x, int32_t y, int32_t time) {
Input::s_buttonState |= button;
EVENT_DATA_MOUSE data;
data.mode = Input::s_mouseMode;
data.button = button;
data.buttonState = Input::s_buttonState;
data.metaKeyState = Input::s_metaKeyState;
data.flags = GenerateMouseFlags();
data.time = time;
ConvertPosition(x, y, &data.x, &data.y);
IEvtQueueDispatch(context, EVENT_ID_MOUSEDOWN, &data);
}
void PostMouseMove(EvtContext* context, int32_t x, int32_t y, int32_t time) {
EVENT_DATA_MOUSE data;
data.mode = Input::s_mouseMode;
data.button = MOUSE_BUTTON_NONE;
data.buttonState = Input::s_buttonState;
data.metaKeyState = Input::s_metaKeyState;
data.flags = GenerateMouseFlags();
data.time = time;
ConvertPosition(x, y, &data.x, &data.y);
IEvtQueueDispatch(context, EVENT_ID_MOUSEMOVE, &data);
}
void PostMouseUp(EvtContext* context, MOUSEBUTTON button, int32_t x, int32_t y, uint32_t flags, int32_t time) {
Input::s_buttonState &= ~button;
EVENT_DATA_MOUSE data;
data.mode = Input::s_mouseMode;
data.button = button;
data.buttonState = Input::s_buttonState;
data.metaKeyState = Input::s_metaKeyState;
data.flags = flags | GenerateMouseFlags();
data.time = time;
ConvertPosition(x, y, &data.x, &data.y);
IEvtQueueDispatch(context, EVENT_ID_MOUSEUP, &data);
CheckMouseModeState();
}
void PostSize(EvtContext* context, int32_t w, int32_t h) {
EVENT_DATA_SIZE data;
data.w = w;
data.h = h;
IEvtQueueDispatch(context, EVENT_ID_SIZE, &data);
}
void ProcessInput(const int32_t param[], OSINPUT id, int32_t* shutdown, EvtContext* context) {
if (!context) {
// TODO
// nullsub_3();
// SErrSetLastError(0x57u);
}
switch (id) {
case OS_INPUT_CAPTURE_CHANGED:
// TODO
break;
case OS_INPUT_CHAR:
PostChar(
context,
param[0],
param[1]
);
break;
case OS_INPUT_STRING:
// TODO
break;
case OS_INPUT_IME:
// TODO
break;
case OS_INPUT_SIZE:
PostSize(
context,
param[0],
param[1]
);
break;
case OS_INPUT_CLOSE:
// TODO
break;
case OS_INPUT_FOCUS:
// TODO
break;
case OS_INPUT_KEY_DOWN:
PostKeyDown(
context,
param[0],
param[1],
param[3]
);
break;
case OS_INPUT_KEY_UP:
PostKeyUp(
context,
param[0],
param[1],
param[3]
);
break;
case OS_INPUT_MOUSE_DOWN:
PostMouseDown(
context,
static_cast<MOUSEBUTTON>(param[0]),
param[1],
param[2],
param[3]
);
break;
case OS_INPUT_MOUSE_MOVE:
PostMouseMove(
context,
param[1],
param[2],
param[3]
);
break;
case OS_INPUT_MOUSE_WHEEL:
// TODO
break;
case OS_INPUT_MOUSE_MOVE_RELATIVE:
// TODO
break;
case OS_INPUT_MOUSE_UP:
PostMouseUp(
context,
static_cast<MOUSEBUTTON>(param[0]),
param[1],
param[2],
0,
param[3]
);
break;
case OS_INPUT_14:
// TODO
break;
case OS_INPUT_15:
// TODO
break;
case OS_INPUT_16:
// TODO
break;
case OS_INPUT_17:
// TODO
break;
case OS_INPUT_18:
// TODO
break;
case OS_INPUT_SHUTDOWN:
// TODO
break;
}
}
void CheckMouseModeState() {
if (Input::s_mouseHoldButton) {
if (Input::s_mouseHoldButton != (Input::s_mouseHoldButton & Input::s_buttonState)) {
// TODO
// EventSetMouseMode(0, 0);
}
}
}
MOUSEBUTTON ConvertButtonNumberToMOUSEBUTTON(int32_t buttonNumber) {
return Input::s_buttonConversion[buttonNumber];
}
void ConvertPosition(int32_t clientx, int32_t clienty, float* x, float* y) {
if (Input::s_boundingRect.maxX - Input::s_boundingRect.minX != 0.0 && Input::s_boundingRect.maxY - Input::s_boundingRect.minY != 0.0) {
C2Vector pt = {
static_cast<float>(clientx),
static_cast<float>(clienty)
};
if (!Input::s_boundingRect.IsPointInside(pt)) {
// TODO
// - handle out of bounds positions
}
}
tagRECT windowDim;
OsGetDefaultWindowRect(&windowDim);
*x = static_cast<float>(clientx) / static_cast<float>(windowDim.right - windowDim.left);
*y = 1.0 - (static_cast<float>(clienty) / static_cast<float>(windowDim.bottom - windowDim.top));
}
uint32_t GenerateMouseFlags() {
uint32_t flags = 0;
if (Input::s_mouseMode == MOUSE_MODE_RELATIVE) {
flags |= 0x2;
}
return flags;
}
const char* GetButtonName(int32_t button) {
switch (button) {
case 0x1:
return "LeftButton";
case 0x2:
return "MiddleButton";
case 0x4:
return "RightButton";
case 0x8:
return "Button4";
case 0x10:
return "Button5";
case 0x20:
return "Button6";
case 0x40:
return "Button7";
case 0x80:
return "Button8";
case 0x100:
return "Button9";
case 0x200:
return "Button10";
case 0x400:
return "Button11";
case 0x800:
return "Button12";
case 0x1000:
return "Button13";
case 0x2000:
return "Button14";
case 0x4000:
return "Button15";
case 0x8000:
return "Button16";
case 0x10000:
return "Button17";
case 0x20000:
return "Button18";
case 0x40000:
return "Button19";
case 0x80000:
return "Button20";
case 0x100000:
return "Button21";
case 0x200000:
return "Button22";
case 0x400000:
return "Button23";
case 0x800000:
return "Button24";
case 0x1000000:
return "Button25";
case 0x2000000:
return "Button26";
case 0x4000000:
return "Button27";
case 0x8000000:
return "Button28";
case 0x10000000:
return "Button29";
case 0x20000000:
return "Button30";
case 0x40000000:
return "Button31";
default:
return "UNKNOWN";
}
}
void IEvtInputInitialize() {
OsInputInitialize();
}
int32_t IEvtInputProcess(EvtContext* context, int32_t* shutdown) {
if (context) {
// TODO
// nullsub_3();
int32_t v4 = 0;
OSINPUT id;
int32_t param[4];
while (OsInputGet(&id, &param[0], &param[1], &param[2], &param[3])) {
v4 = 1;
ProcessInput(param, id, shutdown, context);
}
return v4;
} else {
// TODO
// nullsub_3();
// SErrSetLastError(0x57u);
return 0;
}
}
const char* KeyCodeToString(KEY key) {
static char charBuf[8];
if (key - 33 <= 222) {
SUniSPutUTF8(key, charBuf);
return charBuf;
}
if (key <= KEY_SPACE) {
switch (key) {
case KEY_NONE:
return "NONE";
case KEY_LSHIFT:
return "LSHIFT";
case KEY_RSHIFT:
return "RSHIFT";
case KEY_LCONTROL:
return "LCTRL";
case KEY_RCONTROL:
return "RCTRL";
case KEY_LALT:
return "LALT";
case KEY_RALT:
return "RALT";
case KEY_SPACE:
return "SPACE";
default:
return "UNKNOWN";
}
}
if (key <= KEY_ESCAPE) {
switch (key) {
case KEY_NUMPAD0:
case KEY_NUMPAD1:
case KEY_NUMPAD2:
case KEY_NUMPAD3:
case KEY_NUMPAD4:
case KEY_NUMPAD5:
case KEY_NUMPAD6:
case KEY_NUMPAD7:
case KEY_NUMPAD8:
case KEY_NUMPAD9:
SStrPrintf(charBuf, sizeof(charBuf), "NUMPAD%d", key);
return charBuf;
case KEY_NUMPAD_PLUS:
return "NUMPADPLUS";
case KEY_NUMPAD_MINUS:
return "NUMPADMINUS";
case KEY_NUMPAD_MULTIPLY:
return "NUMPADMULTIPLY";
case KEY_NUMPAD_DIVIDE:
return "NUMPADDIVIDE";
case KEY_NUMPAD_DECIMAL:
return "NUMPADDECIMAL";
case KEY_ESCAPE:
return "ESCAPE";
default:
return "UNKNOWN";
}
}
if (key <= KEY_PRINTSCREEN) {
switch (key) {
case KEY_ENTER:
return "ENTER";
case KEY_BACKSPACE:
return "BACKSPACE";
case KEY_TAB:
return "TAB";
case KEY_LEFT:
return "LEFT";
case KEY_UP:
return "UP";
case KEY_RIGHT:
return "RIGHT";
case KEY_DOWN:
return "DOWN";
case KEY_INSERT:
return "INSERT";
case KEY_DELETE:
return "DELETE";
case KEY_HOME:
return "HOME";
case KEY_END:
return "END";
case KEY_PAGEUP:
return "PAGEUP";
case KEY_PAGEDOWN:
return "PAGEDOWN";
case KEY_CAPSLOCK:
return "CAPSLOCK";
case KEY_NUMLOCK:
return "NUMLOCK";
case KEY_PRINTSCREEN:
return "PRINTSCREEN";
default:
return "UNKNOWN";
}
}
if (key <= KEY_F12) {
switch (key) {
case KEY_F1:
case KEY_F2:
case KEY_F3:
case KEY_F4:
case KEY_F5:
case KEY_F6:
case KEY_F7:
case KEY_F8:
case KEY_F9:
case KEY_F10:
case KEY_F11:
case KEY_F12:
SStrPrintf(charBuf, sizeof(charBuf), "F%d", key - KEY_F1 + 1);
return charBuf;
default:
return "UNKNOWN";
}
}
if (key == KEY_NUMPAD_EQUALS) {
return "NUMPADEQUALS";
}
return "UNKNOWN";
}
int32_t OsInputGet(OSINPUT* id, int32_t* param0, int32_t* param1, int32_t* param2, int32_t* param3) {
#if defined(WHOA_SYSTEM_WIN)
// TODO
#endif
#if defined(WHOA_SYSTEM_MAC)
// TODO
// Unknown logic
if (!OsInputIsUsingCocoaEventLoop()) {
// Legacy Carbon input handling
return 0;
}
// TODO
// Steelseries WoW Mouse logic
if (Input::s_queueTail == Input::s_queueHead) {
return 0;
}
OsQueueSetParam(3, OsGetAsyncTimeMs());
return OsQueueGet(id, param0, param1, param2, param3);
#endif
}
void OsInputInitialize() {
#if defined(WHOA_SYSTEM_WIN)
Input::s_numlockState = GetAsyncKeyState(144);
PVOID pvParam = 10;
SystemParametersInfoA(SPI_GETMOUSESPEED, 0, &pvParam, 0);
Input::s_savedMouseSpeed = pvParam;
#endif
#if defined(WHOA_SYSTEM_MAC)
// Legacy Carbon input handling
// if (!byte_143EFE0) {
// Carbon_OsInputRegisterHICommandHandler(0x71756974, sub_A4F230);
// }
MacClient::SetMouseCoalescingEnabled(true);
Input::s_savedMouseSpeed = MacClient::GetMouseSpeed();
#endif
}
bool OsInputIsUsingCocoaEventLoop() {
// TODO
return true;
}
void OsInputPostEvent(OSINPUT id, int32_t param0, int32_t param1, int32_t param2, int32_t param3) {
// TODO
}
int32_t OsQueueGet(OSINPUT* id, int32_t* param0, int32_t* param1, int32_t* param2, int32_t* param3) {
if (Input::s_queueTail == Input::s_queueHead) {
return 0;
}
OSEVENT event = Input::s_queue[Input::s_queueTail];
*id = event.id;
*param0 = event.param[0];
*param1 = event.param[1];
*param2 = event.param[2];
*param3 = event.param[3];
if (Input::s_queueTail == OS_QUEUE_SIZE - 1) {
Input:: s_queueTail = 0;
} else {
++Input::s_queueTail;
}
return 1;
}
void OsQueuePut(OSINPUT id, int32_t param0, int32_t param1, int32_t param2, int32_t param3) {
int32_t nextTail = 0;
int32_t nextHead = 0;
if (Input::s_queueHead != OS_QUEUE_SIZE - 1) {
nextHead = Input::s_queueHead + 1;
}
if (nextHead == Input::s_queueTail) {
if (nextHead != OS_QUEUE_SIZE - 1) {
nextTail = nextHead + 1;
}
Input::s_queueTail = nextTail;
}
OSEVENT* event = &Input::s_queue[Input::s_queueHead];
event->id = id;
event->param[0] = param0;
event->param[1] = param1;
event->param[2] = param2;
event->param[3] = param3;
Input::s_queueHead = nextHead;
}
void OsQueueSetParam(int32_t index, int32_t param) {
int32_t pos = Input::s_queueTail;
while (pos != Input::s_queueHead) {
OSEVENT* event = &Input::s_queue[pos];
event->param[index] = param;
if (pos == OS_QUEUE_SIZE - 1) {
pos = 0;
} else {
++pos;
}
}
}

62
src/event/Input.hpp Normal file
View File

@ -0,0 +1,62 @@
#ifndef EVENT_INPUT_HPP
#define EVENT_INPUT_HPP
#include "event/Types.hpp"
#include <cstdint>
#define OS_QUEUE_SIZE 32
class C2iVector;
class CRect;
class EvtContext;
namespace Input {
extern int32_t s_buttonDown[16];
extern uint32_t s_buttonState;
extern C2iVector s_currentMouse;
extern uint32_t s_mouseHoldButton;
extern MOUSEMODE s_mouseMode;
extern int32_t s_numlockState;
extern int32_t s_simulatedRightButtonClick;
extern uint32_t s_metaKeyState;
#if defined(WHOA_SYSTEM_WIN)
extern int32_t s_savedMouseSpeed;
#endif
#if defined(WHOA_SYSTEM_MAC)
extern double s_savedMouseSpeed;
#endif
}
void CheckMouseModeState(void);
MOUSEBUTTON ConvertButtonNumberToMOUSEBUTTON(int32_t);
void ConvertPosition(int32_t, int32_t, float*, float*);
uint32_t GenerateMouseFlags(void);
const char* GetButtonName(int32_t);
void IEvtInputInitialize();
int32_t IEvtInputProcess(EvtContext* context, int32_t* shutdown);
const char* KeyCodeToString(KEY);
int32_t OsInputGet(OSINPUT*, int32_t*, int32_t*, int32_t*, int32_t*);
void OsInputInitialize(void);
bool OsInputIsUsingCocoaEventLoop(void);
void OsInputPostEvent(OSINPUT, int32_t, int32_t, int32_t, int32_t);
int32_t OsQueueGet(OSINPUT*, int32_t*, int32_t*, int32_t*, int32_t*);
void OsQueuePut(OSINPUT, int32_t, int32_t, int32_t, int32_t);
void OsQueueSetParam(int32_t, int32_t);
#endif

74
src/event/Queue.cpp Normal file
View File

@ -0,0 +1,74 @@
#include "event/Queue.hpp"
#include "event/EvtContext.hpp"
#include "event/EvtHandler.hpp"
#include <storm/Error.hpp>
void IEvtQueueDispatch(EvtContext* context, EVENTID id, const void* data) {
STORM_ASSERT(context);
// TODO
// UpdateSyncState(data, &id, context, v3);
// TODO
// if (SErrIsDisplayingError()) {
// return;
// }
auto handlerList = &context->m_queueHandlerList[id];
EvtHandler marker;
marker.marker = 1;
handlerList->LinkNode(&marker, 1, nullptr);
EvtHandler* handler;
while (1) {
handler = marker.link.Next();
if (!handler) {
break;
}
handlerList->LinkNode(&marker, 1, marker.link.Next());
if (!handler->marker && !handler->func(data, handler->param)) {
break;
}
}
handlerList->UnlinkNode(&marker);
}
void IEvtQueueDispatchAll(EvtContext* context) {
// TODO
}
void IEvtQueueRegister(EvtContext* context, EVENTID id, int32_t (*handler)(const void*, void*), void* param, float priority) {
STORM_ASSERT(context);
auto handlerList = &context->m_queueHandlerList[id];
EvtHandler* evtHandler;
void* m = SMemAlloc(sizeof(EvtHandler), __FILE__, __LINE__, 0x8);
if (m) {
evtHandler = new (m) EvtHandler();
} else {
evtHandler = nullptr;
}
evtHandler->priority = priority;
evtHandler->param = param;
evtHandler->func = handler;
evtHandler->marker = 0;
EvtHandler* h = handlerList->Head();
while (h && (priority < h->priority || h->marker)) {
h = handlerList->Link(h)->Next();
}
handlerList->LinkNode(evtHandler, 1, h);
}

14
src/event/Queue.hpp Normal file
View File

@ -0,0 +1,14 @@
#ifndef EVENT_QUEUE_HPP
#define EVENT_QUEUE_HPP
#include "event/Types.hpp"
class EvtContext;
void IEvtQueueDispatch(EvtContext* context, EVENTID id, const void* data);
void IEvtQueueDispatchAll(EvtContext* context);
void IEvtQueueRegister(EvtContext* context, EVENTID id, int32_t (*handler)(const void*, void*), void* param, float priority);
#endif

382
src/event/Scheduler.cpp Normal file
View File

@ -0,0 +1,382 @@
#include "event/Scheduler.hpp"
#include "event/Context.hpp"
#include "event/Event.hpp"
#include "event/EvtContext.hpp"
#include "event/EvtThread.hpp"
#include "event/Input.hpp"
#include "event/Queue.hpp"
#include "event/Synthesize.hpp"
#include "event/Timer.hpp"
#include <algorithm>
#include <cstring>
#include <common/Call.hpp>
#include <common/Prop.hpp>
#include <common/Time.hpp>
#include <storm/Memory.hpp>
#include <storm/String.hpp>
#include <storm/Thread.hpp>
#if defined(WHOA_SYSTEM_MAC)
#include "event/mac/Event.h"
#endif
void DestroySchedulerThread(uint32_t a1) {
// TODO
}
HEVENTCONTEXT IEvtSchedulerCreateContext(int32_t interactive, int32_t (*initializeHandler)(const void*, void*), int32_t (*destroyHandler)(const void*, void*), uint32_t idleTime, uint32_t debugFlags) {
if (idleTime < 1) {
idleTime = 1;
}
char contextName[256];
void* callContext = nullptr;
if (debugFlags & 0x1) {
SStrPrintf(contextName, 256, "Context: interactive = %u, idleTime = %u", interactive, idleTime);
callContext = OsCallInitializeContext(contextName);
}
void* m = SMemAlloc(sizeof(EvtContext), __FILE__, __LINE__, 0);
EvtContext* context;
if (m) {
context = new (m) EvtContext(
interactive != 0 ? 2 : 0,
idleTime,
interactive != 0 ? 1000 : 1,
callContext,
(debugFlags >> 1) & 1
);
} else {
context = nullptr;
}
if (interactive) {
SInterlockedIncrement(&Event::s_interactiveCount);
}
if (initializeHandler) {
IEvtQueueRegister(context, EVENT_ID_INITIALIZE, initializeHandler, 0, 1000.0);
}
if (destroyHandler) {
IEvtQueueRegister(context, EVENT_ID_DESTROY, destroyHandler, 0, 1000.0);
}
return AttachContextToThread(context);
}
void IEvtSchedulerInitialize(int32_t threadCount, int32_t netServer) {
if (Event::s_threadSlotCount) {
// SErrDisplayAppFatal("IEvtScheduler already initialized");
}
Event::s_netServer = netServer;
// TODO
// Thread::s_originalThreadPriority = SGetCurrentThreadPriority();
int32_t threadSlotCount = 1;
while (threadSlotCount < threadCount) {
threadSlotCount *= 2;
}
Event::s_threadSlotCount = threadSlotCount;
// Allocate SCritSects for each thread slot
int32_t v4 = sizeof(SCritSect) * threadSlotCount;
void* v5 = SMemAlloc((v4 + 4), ".\\EvtSched.cpp", 791, 0);
if (v5) {
Event::s_threadSlotCritsects = new (v5) SCritSect[threadSlotCount];
} else {
Event::s_threadSlotCritsects = nullptr;
}
// Allocate EvtThread pointers for each thread slot
Event::s_threadSlots = static_cast<EvtThread**>(SMemAlloc(sizeof(EvtThread*) * threadSlotCount, __FILE__, __LINE__, 0));
memset(Event::s_threadSlots, 0, sizeof(EvtThread*) * threadSlotCount);
Event::s_startEvent.Reset();
Event::s_shutdownEvent.Reset();
Event::s_mainThread = InitializeSchedulerThread();
for (int32_t i = 0; i < threadCount - 1; ++i) {
void* m = SMemAlloc(sizeof(SThread), __FILE__, __LINE__, 0);
SThread* thread;
if (m) {
thread = new (m) SThread();
} else {
thread = nullptr;
}
Event::s_schedulerThreads.SetCount(Event::s_schedulerThreads.Count() + 1);
Event::s_schedulerThreads[Event::s_schedulerThreads.Count() - 1] = thread;
char threadName[16];
SStrPrintf(threadName, 16, "EvtSched#%d", i);
if (!SThread::Create(&SchedulerThreadProc, 0, *thread, threadName, 0)) {
// TODO
}
}
}
void IEvtSchedulerProcess() {
#if defined(WHOA_SYSTEM_WIN)
Event::s_startEvent.Set();
SchedulerThreadProc(1);
Event::s_mainThread = 0;
#endif
#if defined(WHOA_SYSTEM_MAC)
Event::s_startEvent.Set();
if (OsInputIsUsingCocoaEventLoop()) {
PropSelectContext(0);
Event::s_startEvent.Wait(0xFFFFFFFF);
uintptr_t v0 = SGetCurrentThreadId();
char v2[64];
SStrPrintf(v2, 64, "Engine %x", v0);
OsCallInitialize(v2);
RunCocoaEventLoop();
DestroySchedulerThread(Event::s_mainThread);
OsCallDestroy();
Event::s_mainThread = 0;
} else {
// Legacy
// sub_890180(1);
// dword_141B3C8 = 0;
}
#endif
}
void IEvtSchedulerShutdown() {
// TODO
}
uint32_t InitializeSchedulerThread() {
SInterlockedIncrement(&Event::s_threadListContention);
Event::s_threadListCritsect.Enter();
uint32_t slot = Event::s_threadSlotCount;
for (int32_t i = 0; i < Event::s_threadSlotCount; ++i) {
if (slot == Event::s_threadSlotCount
|| Event::s_threadSlots[i] == nullptr
|| Event::s_threadSlots[i]->m_threadCount < Event::s_threadSlots[slot]->m_threadCount)
{
slot = i;
if (!Event::s_threadSlots[i]) {
break;
}
}
}
EvtThread* v4 = Event::s_threadSlots[slot];
if (!v4) {
v4 = Event::s_threadList.NewNode(1, 0, 0x8);
v4->m_threadCount = 0;
v4->m_weightTotal = 0;
v4->m_weightAvg = 0;
v4->m_contextCount = 0;
v4->m_rebalance = 0;
v4->m_threadSlot = slot;
Event::s_threadSlotCritsects[slot].Enter();
Event::s_threadSlots[slot] = v4;
Event::s_threadSlotCritsects[slot].Leave();
}
++v4->m_threadCount;
Event::s_threadListCritsect.Leave();
SInterlockedDecrement(&Event::s_threadListContention);
return slot;
}
bool SchedulerMainProcess() {
return SchedulerThreadProcProcess(Event::s_mainThread) != 0;
}
uint32_t SchedulerThreadProc(void* mainThread) {
uint32_t v1;
if (mainThread) {
v1 = Event::s_mainThread;
} else {
v1 = InitializeSchedulerThread();
}
PropSelectContext(0);
Event::s_startEvent.Wait(0xFFFFFFFF);
uintptr_t v2 = SGetCurrentThreadId();
char v4[64];
SStrPrintf(v4, 64, "Engine %x", v2);
OsCallInitialize(v4);
while (!SchedulerThreadProcProcess(v1));
DestroySchedulerThread(v1);
OsCallDestroy();
return 0;
}
int32_t SchedulerThreadProcProcess(uint32_t a1) {
// TODO
// if (SGetCurrentThreadPriority() != Event::s_originalThreadPriority) {
// SSetCurrentThreadPriority(Event::s_originalThreadPriority);
// }
if (!Event::s_shutdownEvent.Wait(0)) {
return 1;
}
EvtContext* context = GetNextContext(a1);
int32_t v11;
if (context) {
v11 = context->m_schedNextWakeTime.m_val - OsGetAsyncTimeMs();
if (v11 < 0) {
v11 = 0;
}
}
uint32_t v14;
if (Event::s_netServer) {
if (v11 == -1) {
v11 = 100;
}
OsNetPump(v11);
v14 = 258;
} else {
v14 = Event::s_threadSlots[a1]->m_wakeEvent.Wait(v11);
}
if (!context) {
return 0;
}
PropSelectContext(context->m_propContext);
PropSet(PROP_EVENTCONTEXT, &context->m_id);
OsCallSetContext(context->m_callContext);
uint32_t currTime = OsGetAsyncTimeMs();
uint32_t v19 = context->m_id;
if (v14 == 258) {
if (SynthesizeInitialize(context)) {
if (context->m_startWatchdog) {
// nullsub_5(20, 1);
// *a2 = 1;
}
}
uint32_t v9 = (currTime - context->m_schedLastIdle);
context->m_schedLastIdle = currTime;
double elapsedSec = v9 * 0.001;
// TODO
// FrameTime::Update(currTime, elapsedSec);
IEvtTimerDispatch(context);
if (context->m_schedFlags & 0x2) {
int32_t shutdown = 0;
IEvtInputProcess(context, &shutdown);
if (shutdown) {
context->m_critsect.Enter();
if (context->m_schedState == EvtContext::SCHEDSTATE_ACTIVE) {
context->m_schedState = EvtContext::SCHEDSTATE_CLOSED;
}
context->m_critsect.Leave();
IEvtSchedulerShutdown();
}
}
SynthesizePoll(context);
IEvtQueueDispatchAll(context);
SynthesizeIdle(context, currTime, elapsedSec);
SynthesizePaint(context);
}
if (a1 == Event::s_mainThread) {
// TODO
// dword_B417C4 = 0;
}
context->m_critsect.Enter();
uint32_t closed = context->m_schedState == EvtContext::SCHEDSTATE_CLOSED;
context->m_critsect.Leave();
if (closed) {
DetachContextFromThread(a1, context);
SynthesizeDestroy(context);
return 0;
}
uint32_t nextDelay;
if (context->m_schedFlags & 0x4) {
nextDelay = 0;
} else {
int32_t v15 = IEvtTimerGetNextTime(context, currTime);
int32_t v16 = context->m_schedIdleTime;
nextDelay = v15;
if (v16 != context->m_schedInitialIdleTime) {
nextDelay = context->m_schedIdleTime;
}
nextDelay = std::min(
nextDelay,
std::max((uint32_t)0, v16 + context->m_schedLastIdle - currTime)
);
}
OsCallResetContext(context->m_callContext);
PropSelectContext(nullptr);
PutContext(nextDelay + currTime, context->m_schedSmoothWeight, context, a1);
return 0;
}

25
src/event/Scheduler.hpp Normal file
View File

@ -0,0 +1,25 @@
#ifndef EVENT_SCHEDULER_HPP
#define EVENT_SCHEDULER_HPP
#include "event/Types.hpp"
#include <cstdint>
void DestroySchedulerThread(uint32_t a1);
HEVENTCONTEXT IEvtSchedulerCreateContext(int32_t interactive, int32_t (*initializeHandler)(const void*, void*), int32_t (*destroyHandler)(const void*, void*), uint32_t idleTime, uint32_t debugFlags);
void IEvtSchedulerInitialize(int32_t threadCount, int32_t netServer);
void IEvtSchedulerProcess();
void IEvtSchedulerShutdown();
uint32_t InitializeSchedulerThread();
bool SchedulerMainProcess();
uint32_t SchedulerThreadProc(void* mainThread);
int32_t SchedulerThreadProcProcess(uint32_t a1);
#endif

81
src/event/Synthesize.cpp Normal file
View File

@ -0,0 +1,81 @@
#include "event/Synthesize.hpp"
#include "event/EvtContext.hpp"
#include "event/Queue.hpp"
#include <common/Time.hpp>
void SynthesizeDestroy(EvtContext* context) {
// TODO
exit(0);
}
void SynthesizeIdle(EvtContext* context, uint32_t currTime, float elapsedSec) {
bool closed;
context->m_critsect.Enter();
closed = context->m_schedState == EvtContext::SCHEDSTATE_CLOSED;
context->m_critsect.Leave();
if (closed) {
return;
}
uint32_t schedFlags = context->m_schedFlags;
if (schedFlags & 0x2) {
context->m_schedFlags = schedFlags | 0x4;
}
EVENT_DATA_IDLE data;
data.elapsedSec = elapsedSec;
data.time = currTime;
IEvtQueueDispatch(context, EVENT_ID_IDLE, &data);
}
int32_t SynthesizeInitialize(EvtContext* context) {
uint32_t schedFlags = context->m_schedFlags;
if (schedFlags & 0x1) {
return 0;
}
context->m_schedFlags = schedFlags | 0x1;
context->m_schedLastIdle = OsGetAsyncTimeMs();
IEvtQueueDispatch(context, EVENT_ID_INITIALIZE, nullptr);
return 1;
}
void SynthesizePaint(EvtContext* context) {
bool closed;
context->m_critsect.Enter();
closed = context->m_schedState == EvtContext::SCHEDSTATE_CLOSED;
context->m_critsect.Leave();
if (closed) {
return;
}
uint32_t schedFlags = context->m_schedFlags;
if (schedFlags & 0x4) {
context->m_schedFlags = schedFlags & ~0x4;
IEvtQueueDispatch(context, EVENT_ID_PAINT, nullptr);
}
}
void SynthesizePoll(EvtContext* context) {
bool closed;
context->m_critsect.Enter();
closed = context->m_schedState == EvtContext::SCHEDSTATE_CLOSED;
context->m_critsect.Leave();
if (closed) {
return;
}
IEvtQueueDispatch(context, EVENT_ID_POLL, nullptr);
}

18
src/event/Synthesize.hpp Normal file
View File

@ -0,0 +1,18 @@
#ifndef EVENT_SYNTHESIZE_HPP
#define EVENT_SYNTHESIZE_HPP
#include <cstdint>
class EvtContext;
void SynthesizeDestroy(EvtContext* context);
void SynthesizeIdle(EvtContext* context, uint32_t currTime, float elapsedSec);
int32_t SynthesizeInitialize(EvtContext* context);
void SynthesizePaint(EvtContext* context);
void SynthesizePoll(EvtContext* context);
#endif

29
src/event/Timer.cpp Normal file
View File

@ -0,0 +1,29 @@
#include "event/Timer.hpp"
#include "event/EvtContext.hpp"
#include "event/EvtTimer.hpp"
#include <storm/Error.hpp>
int32_t IEvtTimerDispatch(EvtContext* context) {
// TODO
return 0;
}
uint32_t IEvtTimerGetNextTime(EvtContext* context, uint32_t currTime) {
STORM_ASSERT(context);
context->m_critsect.Enter();
uint32_t nextTime = -1;
if (context->m_timerQueue.Count()) {
auto queue = static_cast<EvtTimer*>(context->m_timerQueue[0]);
auto targetTime = queue->targetTime.m_val;
nextTime = targetTime - currTime;
nextTime = nextTime < 0 ? 0 : nextTime;
}
context->m_critsect.Leave();
return nextTime;
}

12
src/event/Timer.hpp Normal file
View File

@ -0,0 +1,12 @@
#ifndef EVENT_TIMER_HPP
#define EVENT_TIMER_HPP
#include <cstdint>
class EvtContext;
int32_t IEvtTimerDispatch(EvtContext* context);
uint32_t IEvtTimerGetNextTime(EvtContext* context, uint32_t currTime);
#endif

252
src/event/Types.hpp Normal file
View File

@ -0,0 +1,252 @@
#ifndef EVENT_TYPES_HPP
#define EVENT_TYPES_HPP
#include <cstdint>
typedef void* HEVENTCONTEXT;
typedef int32_t (*EVENTHANDLERFUNC)(const void*, void*);
enum EVENTID {
EVENT_ID_0 = 0,
EVENT_ID_CHAR = 1,
EVENT_ID_FOCUS = 2,
EVENT_ID_3 = 3,
EVENT_ID_DESTROY = 4,
EVENT_ID_5 = 5,
EVENT_ID_IDLE = 6,
EVENT_ID_POLL = 7,
EVENT_ID_INITIALIZE = 8,
EVENT_ID_KEYDOWN = 9,
EVENT_ID_KEYUP = 10,
EVENT_ID_KEYDOWN_REPEATING = 11,
EVENT_ID_MOUSEDOWN = 12,
EVENT_ID_MOUSEMOVE = 13,
EVENT_ID_MOUSEMOVE_RELATIVE = 14,
EVENT_ID_MOUSEUP = 15,
EVENT_ID_MOUSEMODE_CHANGED = 16,
EVENT_ID_MOUSEWHEEL = 17,
EVENT_ID_18 = 18,
EVENT_ID_19 = 19,
EVENT_ID_20 = 20,
EVENT_ID_21 = 21,
EVENT_ID_22 = 22,
EVENT_ID_PAINT = 23,
EVENT_ID_24 = 24,
EVENT_ID_25 = 25,
EVENT_ID_26 = 26,
EVENT_ID_27 = 27,
EVENT_ID_28 = 28,
EVENT_ID_29 = 29,
EVENT_ID_30 = 30,
EVENT_ID_31 = 31,
EVENT_ID_32 = 32,
EVENT_ID_33 = 33,
EVENT_ID_IME = 34,
EVENT_ID_SIZE = 35,
EVENTIDS = 36
};
enum KEY {
KEY_NONE = 0xFFFFFFFF,
KEY_LSHIFT = 0x0,
KEY_RSHIFT = 0x1,
KEY_LCONTROL = 0x2,
KEY_RCONTROL = 0x3,
KEY_LALT = 0x4,
KEY_RALT = 0x5,
KEY_LASTMETAKEY = 0x5,
KEY_SPACE = 0x20,
KEY_0 = 0x30,
KEY_1 = 0x31,
KEY_2 = 0x32,
KEY_3 = 0x33,
KEY_4 = 0x34,
KEY_5 = 0x35,
KEY_6 = 0x36,
KEY_7 = 0x37,
KEY_8 = 0x38,
KEY_9 = 0x39,
KEY_A = 0x41,
KEY_B = 0x42,
KEY_C = 0x43,
KEY_D = 0x44,
KEY_E = 0x45,
KEY_F = 0x46,
KEY_G = 0x47,
KEY_H = 0x48,
KEY_I = 0x49,
KEY_J = 0x4A,
KEY_K = 0x4B,
KEY_L = 0x4C,
KEY_M = 0x4D,
KEY_N = 0x4E,
KEY_O = 0x4F,
KEY_P = 0x50,
KEY_Q = 0x51,
KEY_R = 0x52,
KEY_S = 0x53,
KEY_T = 0x54,
KEY_U = 0x55,
KEY_V = 0x56,
KEY_W = 0x57,
KEY_X = 0x58,
KEY_Y = 0x59,
KEY_Z = 0x5A,
KEY_TILDE = 0x60,
KEY_NUMPAD0 = 0x100,
KEY_NUMPAD1 = 0x101,
KEY_NUMPAD2 = 0x102,
KEY_NUMPAD3 = 0x103,
KEY_NUMPAD4 = 0x104,
KEY_NUMPAD5 = 0x105,
KEY_NUMPAD6 = 0x106,
KEY_NUMPAD7 = 0x107,
KEY_NUMPAD8 = 0x108,
KEY_NUMPAD9 = 0x109,
KEY_NUMPAD_PLUS = 0x10A,
KEY_NUMPAD_MINUS = 0x10B,
KEY_NUMPAD_MULTIPLY = 0x10C,
KEY_NUMPAD_DIVIDE = 0x10D,
KEY_NUMPAD_DECIMAL = 0x10E,
KEY_NUMPAD_EQUALS = 0x30C,
KEY_PLUS = 0x3D,
KEY_MINUS = 0x2D,
KEY_BRACKET_OPEN = 0x5B,
KEY_BRACKET_CLOSE = 0x5D,
KEY_SLASH = 0x2F,
KEY_BACKSLASH = 0x5C,
KEY_SEMICOLON = 0x3B,
KEY_APOSTROPHE = 0x27,
KEY_COMMA = 0x2C,
KEY_PERIOD = 0x2E,
KEY_ESCAPE = 0x200,
KEY_ENTER = 0x201,
KEY_BACKSPACE = 0x202,
KEY_TAB = 0x203,
KEY_LEFT = 0x204,
KEY_UP = 0x205,
KEY_RIGHT = 0x206,
KEY_DOWN = 0x207,
KEY_INSERT = 0x208,
KEY_DELETE = 0x209,
KEY_HOME = 0x20A,
KEY_END = 0x20B,
KEY_PAGEUP = 0x20C,
KEY_PAGEDOWN = 0x20D,
KEY_CAPSLOCK = 0x20E,
KEY_NUMLOCK = 0x20F,
KEY_SCROLLLOCK = 0x210,
KEY_PAUSE = 0x211,
KEY_PRINTSCREEN = 0x212,
KEY_F1 = 0x300,
KEY_F2 = 0x301,
KEY_F3 = 0x302,
KEY_F4 = 0x303,
KEY_F5 = 0x304,
KEY_F6 = 0x305,
KEY_F7 = 0x306,
KEY_F8 = 0x307,
KEY_F9 = 0x308,
KEY_F10 = 0x309,
KEY_F11 = 0x30A,
KEY_F12 = 0x30B,
KEY_F13 = 0x212,
KEY_F14 = 0x30D,
KEY_F15 = 0x30E,
KEY_F16 = 0x30F,
KEY_F17 = 0x310,
KEY_F18 = 0x311,
KEY_F19 = 0x312,
KEY_LAST = 0x313
};
enum MOUSEBUTTON {
MOUSE_BUTTON_NONE = 0x0,
MOUSE_BUTTON_LEFT = 0x1,
MOUSE_BUTTON_MIDDLE = 0x2,
MOUSE_BUTTON_RIGHT = 0x4,
MOUSE_BUTTON_XBUTTON1 = 0x8,
MOUSE_BUTTON_XBUTTON2 = 0x10,
MOUSE_BUTTON_XBUTTON3 = 0x20,
MOUSE_BUTTON_XBUTTON4 = 0x40,
MOUSE_BUTTON_XBUTTON5 = 0x80,
MOUSE_BUTTON_XBUTTON6 = 0x100,
MOUSE_BUTTON_XBUTTON7 = 0x200,
MOUSE_BUTTON_XBUTTON8 = 0x400,
MOUSE_BUTTON_XBUTTON9 = 0x800,
MOUSE_BUTTON_XBUTTON10 = 0x1000,
MOUSE_BUTTON_XBUTTON11 = 0x2000,
MOUSE_BUTTON_XBUTTON12 = 0x4000,
MOUSE_BUTTON_ALL = 0xFFFFFFFF
};
enum MOUSEMODE {
MOUSE_MODE_NORMAL = 0x0,
MOUSE_MODE_RELATIVE = 0x1,
MOUSE_MODES = 0x2
};
enum OSINPUT {
OS_INPUT_CAPTURE_CHANGED = 0,
OS_INPUT_CHAR = 1,
OS_INPUT_STRING = 2,
OS_INPUT_IME = 3,
OS_INPUT_SIZE = 4,
OS_INPUT_CLOSE = 5,
OS_INPUT_FOCUS = 6,
OS_INPUT_KEY_DOWN = 7,
OS_INPUT_KEY_UP = 8,
OS_INPUT_MOUSE_DOWN = 9,
OS_INPUT_MOUSE_MOVE = 10,
OS_INPUT_MOUSE_WHEEL = 11,
OS_INPUT_MOUSE_MOVE_RELATIVE = 12,
OS_INPUT_MOUSE_UP = 13,
OS_INPUT_14 = 14,
OS_INPUT_15 = 15,
OS_INPUT_16 = 16,
OS_INPUT_17 = 17,
OS_INPUT_18 = 18,
OS_INPUT_SHUTDOWN = 19
};
struct OSEVENT {
OSINPUT id;
int32_t param[4];
};
struct EVENT_DATA_CHAR {
int32_t ch;
uint32_t metaKeyState;
uint32_t repeat;
};
struct EVENT_DATA_IDLE {
float elapsedSec;
uint32_t time;
};
struct EVENT_DATA_KEY {
KEY key;
uint32_t metaKeyState;
uint32_t repeat;
uint32_t time;
};
struct EVENT_DATA_MOUSE {
MOUSEMODE mode;
MOUSEBUTTON button;
uint32_t buttonState;
uint32_t metaKeyState;
uint32_t flags;
float x;
float y;
int32_t wheelDistance;
uint32_t time;
};
struct EVENT_DATA_SIZE {
int32_t w;
int32_t h;
};
#endif

6
src/event/mac/Event.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef EVENT_MAC_EVENT_H
#define EVENT_MAC_EVENT_H
void RunCocoaEventLoop();
#endif

9
src/event/mac/Event.mm Normal file
View File

@ -0,0 +1,9 @@
#include "event/mac/Event.h"
#include "event/Event.hpp"
#include <AppKit/AppKit.h>
void RunCocoaEventLoop() {
if (!Event::s_shouldLoopTerminate) {
[NSApp run];
}
}

View File

@ -0,0 +1,3 @@
#include "glue/CCharacterSelection.hpp"
TSGrowableArray<CharacterSelectionDisplay> CCharacterSelection::s_characterList;

View File

@ -0,0 +1,16 @@
#ifndef GLUE_C_CHARACTER_SELECTION_HPP
#define GLUE_C_CHARACTER_SELECTION_HPP
#include <storm/Array.hpp>
struct CharacterSelectionDisplay {
// TODO
};
class CCharacterSelection {
public:
// Static variables
static TSGrowableArray<CharacterSelectionDisplay> s_characterList;
};
#endif

452
src/glue/CGlueMgr.cpp Normal file
View File

@ -0,0 +1,452 @@
#include "glue/CGlueMgr.hpp"
#include "client/Client.hpp"
#include "client/ClientServices.hpp"
#include "gx/Coordinate.hpp"
#include "gx/Device.hpp"
#include "math/Utils.hpp"
#include "net/Connection.hpp"
#include "net/Login.hpp"
#include "sound/SI2.hpp"
#include "ui/CSimpleModelFFX.hpp"
#include "ui/CSimpleTop.hpp"
#include "ui/FrameScript.hpp"
#include "ui/FrameXML.hpp"
#include "ui/Interface.hpp"
#include "ui/ScriptFunctions.hpp"
#include "util/CVar.hpp"
#include "util/Filesystem.hpp"
#include "util/Log.hpp"
#include <cstdio>
#include <common/MD5.hpp>
unsigned char InterfaceKey[256] = {
0xC3, 0x5B, 0x50, 0x84, 0xB9, 0x3E, 0x32, 0x42, 0x8C, 0xD0, 0xC7, 0x48, 0xFA, 0x0E, 0x5D, 0x54,
0x5A, 0xA3, 0x0E, 0x14, 0xBA, 0x9E, 0x0D, 0xB9, 0x5D, 0x8B, 0xEE, 0xB6, 0x84, 0x93, 0x45, 0x75,
0xFF, 0x31, 0xFE, 0x2F, 0x64, 0x3F, 0x3D, 0x6D, 0x07, 0xD9, 0x44, 0x9B, 0x40, 0x85, 0x59, 0x34,
0x4E, 0x10, 0xE1, 0xE7, 0x43, 0x69, 0xEF, 0x7C, 0x16, 0xFC, 0xB4, 0xED, 0x1B, 0x95, 0x28, 0xA8,
0x23, 0x76, 0x51, 0x31, 0x57, 0x30, 0x2B, 0x79, 0x08, 0x50, 0x10, 0x1C, 0x4A, 0x1A, 0x2C, 0xC8,
0x8B, 0x8F, 0x05, 0x2D, 0x22, 0x3D, 0xDB, 0x5A, 0x24, 0x7A, 0x0F, 0x13, 0x50, 0x37, 0x8F, 0x5A,
0xCC, 0x9E, 0x04, 0x44, 0x0E, 0x87, 0x01, 0xD4, 0xA3, 0x15, 0x94, 0x16, 0x34, 0xC6, 0xC2, 0xC3,
0xFB, 0x49, 0xFE, 0xE1, 0xF9, 0xDA, 0x8C, 0x50, 0x3C, 0xBE, 0x2C, 0xBB, 0x57, 0xED, 0x46, 0xB9,
0xAD, 0x8B, 0xC6, 0xDF, 0x0E, 0xD6, 0x0F, 0xBE, 0x80, 0xB3, 0x8B, 0x1E, 0x77, 0xCF, 0xAD, 0x22,
0xCF, 0xB7, 0x4B, 0xCF, 0xFB, 0xF0, 0x6B, 0x11, 0x45, 0x2D, 0x7A, 0x81, 0x18, 0xF2, 0x92, 0x7E,
0x98, 0x56, 0x5D, 0x5E, 0x69, 0x72, 0x0A, 0x0D, 0x03, 0x0A, 0x85, 0xA2, 0x85, 0x9C, 0xCB, 0xFB,
0x56, 0x6E, 0x8F, 0x44, 0xBB, 0x8F, 0x02, 0x22, 0x68, 0x63, 0x97, 0xBC, 0x85, 0xBA, 0xA8, 0xF7,
0xB5, 0x40, 0x68, 0x3C, 0x77, 0x86, 0x6F, 0x4B, 0xD7, 0x88, 0xCA, 0x8A, 0xD7, 0xCE, 0x36, 0xF0,
0x45, 0x6E, 0xD5, 0x64, 0x79, 0x0F, 0x17, 0xFC, 0x64, 0xDD, 0x10, 0x6F, 0xF3, 0xF5, 0xE0, 0xA6,
0xC3, 0xFB, 0x1B, 0x8C, 0x29, 0xEF, 0x8E, 0xE5, 0x34, 0xCB, 0xD1, 0x2A, 0xCE, 0x79, 0xC3, 0x9A,
0x0D, 0x36, 0xEA, 0x01, 0xE0, 0xAA, 0x91, 0x20, 0x54, 0xF0, 0x72, 0xD8, 0x1E, 0xC7, 0x89, 0xD2
};
int32_t CGlueMgr::m_acceptedEULA = 1; // TODO
int32_t CGlueMgr::m_acceptedTerminationWithoutNotice;
int32_t CGlueMgr::m_acceptedTOS = 1; // TODO
char CGlueMgr::m_accountName[1280];
float CGlueMgr::m_aspect;
bool CGlueMgr::m_authenticated;
char CGlueMgr::m_currentScreen[64];
CGlueMgr::GLUE_IDLE_STATE CGlueMgr::m_idleState;
int32_t CGlueMgr::m_initialized;
int32_t CGlueMgr::m_lastLoginResult;
int32_t CGlueMgr::m_lastLoginState;
int32_t CGlueMgr::m_loginResult;
int32_t CGlueMgr::m_loginState;
int32_t CGlueMgr::m_matrixRemaining;
int32_t CGlueMgr::m_reload;
int32_t CGlueMgr::m_scandllOkayToLogIn = 1; // TODO
float CGlueMgr::m_screenHeight;
float CGlueMgr::m_screenWidth;
int32_t CGlueMgr::m_showedDisconnect;
CSimpleTop* CGlueMgr::m_simpleTop;
int32_t CGlueMgr::m_suspended;
float CalculateAspectRatio() {
auto widescreenVar = CVar::Lookup("widescreen");
auto resolutionVar = CVar::Lookup("gxResolution");
int32_t width = 4;
int32_t height = 3;
if (widescreenVar && widescreenVar->GetInt() && resolutionVar) {
char separator;
sscanf(resolutionVar->GetString(), "%d%c%d", &width, &separator, &height);
}
return static_cast<float>(width) / static_cast<float>(height);
}
int32_t CGlueMgr::HandleDisplaySizeChanged(const CSizeEvent& event) {
if (
CGlueMgr::m_screenWidth > 0
&& CGlueMgr::m_screenWidth == event.w
&& CGlueMgr::m_screenHeight > 0
&& CGlueMgr::m_screenHeight == event.h
) {
return 1;
}
CGlueMgr::m_screenWidth = event.w;
CGlueMgr::m_screenHeight = event.h;
float aspect = CalculateAspectRatio();
auto glueParent = static_cast<CSimpleFrame*>(CScriptObject::GetScriptObjectByName("GlueParent", CSimpleFrame::GetObjectType()));
if (glueParent) {
glueParent->SetFrameScale(1.0f, true);
CLayoutFrame::ResizePending();
}
if (AreEqual(CGlueMgr::m_aspect, aspect, 0.0099999998)) {
return 1;
}
CGlueMgr::m_aspect = aspect;
CGlueMgr::m_reload = 1;
return 1;
}
// TODO a1: const EVENT_DATA_IDLE*
int32_t CGlueMgr::Idle(const void* a1, void* a2) {
// TODO
if (CGlueMgr::m_idleState == IDLE_NONE) {
if (CGlueMgr::m_reload) {
if (!CGlueMgr::m_suspended) {
// TODO CGlueMgr::Suspend();
// TODO CGlueMgr::Resume();
// TODO Sub4DA360();
// TODO CGlueMgr::SetScreen(ByteB6A9E0);
}
CGlueMgr::m_reload = 0;
}
// TODO
// if (CGlueMgr::m_accountMsgAvailable) {
// FrameScript_SignalEvent(0x22u, 0);
// CGlueMgr::m_accountMsgAvailable = 0;
// }
// TODO sub_4D84A0();
return 1;
}
// TODO
return 1;
}
void CGlueMgr::Initialize() {
CGlueMgr::m_initialized = 1;
// TODO
// - cvar stuff (tou, etc)
CRect windowSize;
g_theGxDevicePtr->CapsWindowSize(windowSize);
CSizeEvent sizeEvent;
sizeEvent.id = -1;
sizeEvent.w = windowSize.maxX - windowSize.minX;
sizeEvent.h = windowSize.maxY - windowSize.minY;
CGlueMgr::HandleDisplaySizeChanged(sizeEvent);
FrameXML_RegisterFactory("ModelFFX", &CSimpleModelFFX::Create, 0);
CGlueMgr::Resume();
// TODO
// CRealmList::Initialize();
EventRegisterEx(EVENT_ID_IDLE, &CGlueMgr::Idle, 0, 0.0);
// TODO
// CGLCD::Initialize();
// sub_552380();
// TODO
// - options changed warning stuff
// TODO
// AccountDataInitializeBasicSystem();
}
void CGlueMgr::LoginServerLogin(const char* accountName, const char* password) {
if (!CGlueMgr::m_scandllOkayToLogIn || !CGlueMgr::m_acceptedTOS || !CGlueMgr::m_acceptedEULA || CGlueMgr::m_idleState != IDLE_NONE) {
return;
}
if (!accountName || !*accountName) {
auto prompt = FrameScript_GetText("LOGIN_ENTER_NAME", -1, GENDER_NOT_APPLICABLE);
FrameScript_SignalEvent(3, "%s%s", "OKAY", prompt);
return;
}
if (!password || !*password) {
auto prompt = FrameScript_GetText("LOGIN_ENTER_PASSWORD", -1, GENDER_NOT_APPLICABLE);
FrameScript_SignalEvent(3, "%s%s", "OKAY", prompt);
return;
}
CGlueMgr::m_loginResult = -1;
CGlueMgr::m_loginState = -1;
CGlueMgr::m_lastLoginResult = -1;
CGlueMgr::m_lastLoginState = -1;
CGlueMgr::m_authenticated = false;
CGlueMgr::m_matrixRemaining = 0;
CGlueMgr::m_idleState = IDLE_ACCOUNT_LOGIN;
CGlueMgr::m_showedDisconnect = 0;
char* dest = CGlueMgr::m_accountName;
for (const char* src = accountName; *src && dest < CGlueMgr::m_accountName + sizeof(CGlueMgr::m_accountName); src++, dest++) {
if (src[0] == '|' && src[1] == '|') {
src++;
}
*dest = *src;
}
*dest = '\0';
SStrUpper(CGlueMgr::m_accountName);
// Show prompt
FrameScript_SignalEvent(3, "%s", "CANCEL");
ClientServices::Logon(CGlueMgr::m_accountName, password);
// Zero out password
memset(const_cast<char*>(password), 0, SStrLen(password));
}
void CGlueMgr::QuitGame() {
ClientPostClose(0);
}
void CGlueMgr::Resume() {
// TODO
// CGlueMgr::m_disconnectPending = 0;
// CGlueMgr::m_reconnect = 0;
CGlueMgr::m_idleState = IDLE_NONE;
// TODO
// CGlueMgr::m_showedDisconnect = 0;
// CGlueMgr::m_characterInfo = 0;
CGlueMgr::m_suspended = 0;
CGlueMgr::m_reload = 0;
CRect screenRect;
g_theGxDevicePtr->CapsWindowSizeInScreenCoords(screenRect);
CGlueMgr::m_screenWidth = screenRect.maxX - screenRect.minX;
CGlueMgr::m_screenHeight = screenRect.maxY - screenRect.minY;
CGlueMgr::m_aspect = CalculateAspectRatio();
CoordinateSetAspectRatio(CGlueMgr::m_aspect);
// Create CSimpleTop
CSimpleTop* top;
void* m = SMemAlloc(sizeof(CSimpleTop), __FILE__, __LINE__, 0);
if (m) {
top = new (m) CSimpleTop();
} else {
top = nullptr;
}
CGlueMgr::m_simpleTop = top;
CGlueMgr::m_simpleTop->m_displaySizeCallback = &CGlueMgr::HandleDisplaySizeChanged;
// TODO
// - setting cursor texture
// - setting mouse mode
FrameScript_Flush();
SystemRegisterFunctions();
RegisterSimpleFrameScriptMethods();
GlueScriptEventsRegisterFunctions();
CharSelectRegisterScriptFunctions();
CharacterCreateRegisterScriptFunctions();
// TODO
// RealmListRegisterScriptFunctions();
SI2::RegisterScriptFunctions();
// TODO
// AccountMsg_RegisterScriptFunctions();
// CGVideoOptions::RegisterScriptFunctions();
// TODO
// FrameScript::s_scriptFunctionsLoaded = 1;
FrameScript_CreateEvents(g_glueScriptEvents, NUM_GLUE_SCRIPT_EVENTS);
OsCreateDirectory("Logs", 0);
CWOWClientStatus status;
if (!SLogCreate("Logs\\GlueXML.log", 0, status.m_logFile)) {
SysMsgPrintf(SYSMSG_WARNING, "Cannot create WOWClient log file \"%s\"!", "Logs\\GlueXML.log");
}
DeleteInterfaceFiles();
MD5_CTX md5;
unsigned char digest1[16];
unsigned char digest2[16];
int32_t v8;
unsigned char* v9;
unsigned char* v10;
MD5Init(&md5);
switch (FrameXML_CheckSignature("Interface\\GlueXML\\GlueXML.toc", 0, InterfaceKey, digest1)) {
case 0:
status.Add(STATUS_WARNING, "GlueXML missing signature");
ClientPostClose(9);
return;
case 1:
status.Add(STATUS_WARNING, "GlueXML has corrupt signature");
ClientPostClose(9);
return;
case 2:
status.Add(STATUS_WARNING, "GlueXML is modified or corrupt");
ClientPostClose(9);
return;
case 3:
FrameXML_FreeHashNodes();
FrameXML_CreateFrames("Interface\\GlueXML\\GlueXML.toc", 0, &md5, &status);
MD5Final(digest2, &md5);
v8 = 16;
v9 = digest2;
v10 = digest1;
break;
default:
ClientPostClose(9);
return;
}
// TODO
// - some kind of digest validation?
FrameScript_SignalEvent(22, nullptr);
// TODO
// CGlueMgr::InitializeFFX();
// TODO
// ClientServices::SetMessageHandler(SMSG_CHARACTER_RENAME_RESULT, CGlueMgr::OnCharRenameResult, 0);
// ClientServices::SetMessageHandler(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, CGlueMgr::OnCharDeclineResult, 0);
// ClientServices::SetMessageHandler(SMSG_CHAR_CUSTOMIZE, CGlueMgr::OnCharCustomizeResult, 0);
// ClientServices::SetMessageHandler(SMSG_REALM_SPLIT, CGlueMgr::OnRealmSplitMsg, 0);
// ClientServices::SetMessageHandler(SMSG_KICK_REASON, CGlueMgr::OnKickReasonMsg, 0);
// ClientServices::SetMessageHandler(SMSG_CHAR_FACTION_CHANGE, CGlueMgr::OnCharFactionChangeResult, 0);
// TODO
// CGlueMgr::m_pendingServerAlert = 1;
// CGlueMgr::m_processServerAlert = 0;
// CGlueMgr::m_serverAlert[0] = 0;
// v21 = (const char *)ClientServices::GetServerAlertURL();
// v22 = (const CHAR *)FrameScript_GetText(v21, -1, 0);
// if (!OsURLDownload(v22, CGlueMgr::ServerAlertURLCallback, 0)) {
// CGlueMgr::m_pendingServerAlert = 0;
// }
}
void CGlueMgr::SetScreen(const char* screen) {
FrameScript_SignalEvent(0, "%s", screen);
}
void CGlueMgr::StatusDialogClick() {
if (!SStrCmpI(CGlueMgr::m_currentScreen, "patchdownload", STORM_MAX_STR)) {
CGlueMgr::SetScreen("login");
}
switch (CGlueMgr::m_idleState) {
case IDLE_NONE: {
ClientServices::Connection()->Cleanup();
break;
}
case IDLE_ACCOUNT_LOGIN: {
ClientServices::LoginConnection()->Logoff();
CGlueMgr::m_showedDisconnect = 0;
CGlueMgr::m_idleState = IDLE_NONE;
break;
}
case IDLE_2:
case IDLE_3: {
ClientServices::Connection()->Cancel(2);
break;
}
case IDLE_4:
case IDLE_5:
case IDLE_6:
case IDLE_10: {
ClientServices::Connection()->Cancel(2);
CGlueMgr::m_showedDisconnect = 0;
CGlueMgr::m_idleState = IDLE_NONE;
break;
}
case IDLE_7:
case IDLE_8:
case IDLE_9: {
CGlueMgr::m_showedDisconnect = 0;
CGlueMgr::m_idleState = IDLE_NONE;
break;
}
case IDLE_11: {
CGlueMgr::m_showedDisconnect = 0;
CGlueMgr::m_idleState = IDLE_NONE;
// TODO
// CGlueMgr::GetCharacterList();
break;
}
case IDLE_12:
case IDLE_13: {
// TODO
break;
}
}
}
void CGlueMgr::Suspend() {
// TODO
}
void CGlueMgr::UpdateCurrentScreen(const char* screen) {
// TODO
SStrCopy(CGlueMgr::m_currentScreen, screen, sizeof(CGlueMgr::m_currentScreen));
// TODO
}

66
src/glue/CGlueMgr.hpp Normal file
View File

@ -0,0 +1,66 @@
#ifndef GLUE_C_GLUE_MGR_HPP
#define GLUE_C_GLUE_MGR_HPP
#include "event/Event.hpp"
#include <cstdint>
class CSimpleTop;
class CGlueMgr {
public:
// Types
enum GLUE_IDLE_STATE {
IDLE_NONE = 0,
IDLE_ACCOUNT_LOGIN = 1,
IDLE_2 = 2,
IDLE_3 = 3,
IDLE_4 = 4,
IDLE_5 = 5,
IDLE_6 = 6,
IDLE_7 = 7,
IDLE_8 = 8,
IDLE_9 = 9,
IDLE_10 = 10,
IDLE_11 = 11,
IDLE_12 = 12,
IDLE_13 = 13
};
// Static variables
static int32_t m_acceptedEULA;
static int32_t m_acceptedTerminationWithoutNotice;
static int32_t m_acceptedTOS;
static char m_accountName[];
static float m_aspect;
static bool m_authenticated;
static char m_currentScreen[];
static GLUE_IDLE_STATE m_idleState;
static int32_t m_initialized;
static int32_t m_lastLoginResult;
static int32_t m_lastLoginState;
static int32_t m_loginResult;
static int32_t m_loginState;
static int32_t m_matrixRemaining;
static int32_t m_reload;
static int32_t m_scandllOkayToLogIn;
static float m_screenHeight;
static float m_screenWidth;
static int32_t m_showedDisconnect;
static CSimpleTop* m_simpleTop;
static int32_t m_suspended;
// Static functions
// TODO a1: const EVENT_DATA_IDLE*
static int32_t HandleDisplaySizeChanged(const CSizeEvent& event);
static int32_t Idle(const void*, void*);
static void Initialize();
static void LoginServerLogin(const char* accountName, const char* password);
static void QuitGame();
static void Resume();
static void SetScreen(const char*);
static void StatusDialogClick();
static void Suspend();
static void UpdateCurrentScreen(const char* screen);
};
#endif

23
src/glue/CMakeLists.txt Normal file
View File

@ -0,0 +1,23 @@
file(GLOB PRIVATE_SOURCES "*.cpp")
add_library(glue STATIC
${PRIVATE_SOURCES}
)
target_include_directories(glue
PRIVATE
${CMAKE_SOURCE_DIR}/src
)
target_link_libraries(glue
PRIVATE
client
event
gx
net
sound
ui
util
PUBLIC
storm
)

236
src/gx/Blit.cpp Normal file
View File

@ -0,0 +1,236 @@
#include "gx/Blit.hpp"
#include <algorithm>
#include <cstring>
#include <tempest/Vector.hpp>
int32_t initBlit = 0;
BLIT_FUNCTION s_blits[BlitFormats_Last][BlitFormats_Last][BlitAlphas_Last];
BlitFormat GxGetBlitFormat(EGxTexFormat format) {
static BlitFormat blitTable[] = {
BlitFormat_Unknown, // GxTex_Unknown
BlitFormat_Abgr8888, // GxTex_Abgr8888
BlitFormat_Argb8888, // GxTex_Argb8888
BlitFormat_Argb4444, // GxTex_Argb4444
BlitFormat_Argb1555, // GxTex_Argb1555
BlitFormat_Rgb565, // GxTex_Rgb565
BlitFormat_Dxt1, // GxTex_Dxt1
BlitFormat_Dxt3, // GxTex_Dxt3
BlitFormat_Dxt5, // GxTex_Dxt5
BlitFormat_Uv88, // GxTex_Uv88
BlitFormat_Gr1616F, // GxTex_Gr1616F
BlitFormat_R32F, // GxTex_R32F
BlitFormat_D24X8 // GxTex_D24X8
};
return blitTable[format];
}
void Blit_uint16_uint16(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
if (inStride == 2 * size.x && outStride == 2 * size.x) {
memcpy(out, in, 2 * size.x * size.y);
return;
}
const char* in_ = reinterpret_cast<const char*>(in);
char* out_ = reinterpret_cast<char*>(out);
for (int32_t i = 0; i < size.y; i++) {
memcpy(out, in, 2 * size.x);
in_ += inStride;
out_ += outStride;
}
}
void Blit_uint32_uint32(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
if (inStride == 4 * size.x && outStride == 4 * size.x) {
memcpy(out, in, 4 * size.x * size.y);
return;
}
const char* in_ = reinterpret_cast<const char*>(in);
char* out_ = reinterpret_cast<char*>(out);
for (int32_t i = 0; i < size.y; i++) {
memcpy(out, in, 4 * size.x);
in_ += inStride;
out_ += outStride;
}
}
void Blit_Argb8888_Abgr8888(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Argb8888_Argb8888(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
Blit_uint32_uint32(size, in, inStride, out, outStride);
}
void Blit_Argb8888_Argb8888_A1(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Argb8888_Argb8888_A8(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Argb8888_Argb4444(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Argb8888_Argb1555(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Argb8888_Rgb565(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Argb4444_Abgr8888(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Argb4444_Argb4444(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
Blit_uint16_uint16(size, in, inStride, out, outStride);
}
void Blit_Argb1555_Argb1555(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Rgb565_Rgb565(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Dxt1_Argb8888(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Dxt1_Argb1555(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Dxt1_Rgb565(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Dxt1_Dxt1(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
const char* in_ = static_cast<const char*>(in);
char* out_ = static_cast<char*>(out);
int32_t v6 = std::max(size.x, 4);
int32_t v7 = std::max(size.y, 4);
memcpy(out_, in_, (4 * v6 * v7) >> 3);
}
void Blit_Dxt3_Argb8888(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Dxt3_Argb4444(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Dxt35_Dxt35(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
int32_t v5 = std::max(size.x, 4);
int32_t v6 = std::max(size.y / 4, 1);
const char* in_ = static_cast<const char*>(in);
char* out_ = static_cast<char*>(out);
if (inStride == v5 * 4 && outStride == v5 * 4) {
memcpy(out_, in_, v5 * v6 * 4);
return;
}
for (int32_t i = v6; i > 0; i--) {
memcpy(out_, in_, v5 * 4);
in_ += inStride;
out_ += outStride;
}
}
void Blit_Dxt5_Argb8888(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Dxt5_Argb4444(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Uv88_Uv88(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_Gr1616F_Gr1616F(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_R32F_R32F(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void Blit_D24X8_D24X8(const C2iVector& size, const void* in, uint32_t inStride, void* out, uint32_t outStride) {
// TODO
}
void InitBlit() {
// Source: Argb8888
s_blits [BlitFormat_Argb8888] [BlitFormat_Abgr8888] [BlitAlpha_0] = &Blit_Argb8888_Abgr8888;
s_blits [BlitFormat_Argb8888] [BlitFormat_Argb8888] [BlitAlpha_0] = &Blit_Argb8888_Argb8888;
s_blits [BlitFormat_Argb8888] [BlitFormat_Argb8888] [BlitAlpha_1] = &Blit_Argb8888_Argb8888_A1;
s_blits [BlitFormat_Argb8888] [BlitFormat_Argb8888] [BlitAlpha_8] = &Blit_Argb8888_Argb8888_A8;
s_blits [BlitFormat_Argb8888] [BlitFormat_Argb4444] [BlitAlpha_0] = &Blit_Argb8888_Argb4444;
s_blits [BlitFormat_Argb8888] [BlitFormat_Argb1555] [BlitAlpha_0] = &Blit_Argb8888_Argb1555;
s_blits [BlitFormat_Argb8888] [BlitFormat_Rgb565] [BlitAlpha_0] = &Blit_Argb8888_Rgb565;
// Source: Argb4444
s_blits [BlitFormat_Argb4444] [BlitFormat_Abgr8888] [BlitAlpha_0] = &Blit_Argb4444_Abgr8888;
s_blits [BlitFormat_Argb4444] [BlitFormat_Argb4444] [BlitAlpha_0] = &Blit_Argb4444_Argb4444;
// Source: Argb1555
s_blits [BlitFormat_Argb1555] [BlitFormat_Argb1555] [BlitAlpha_0] = &Blit_Argb1555_Argb1555;
// Source: Rgb565
s_blits [BlitFormat_Rgb565] [BlitFormat_Rgb565] [BlitAlpha_0] = &Blit_Rgb565_Rgb565;
// Source: Dxt1
s_blits [BlitFormat_Dxt1] [BlitFormat_Argb8888] [BlitAlpha_0] = &Blit_Dxt1_Argb8888;
s_blits [BlitFormat_Dxt1] [BlitFormat_Argb1555] [BlitAlpha_0] = &Blit_Dxt1_Argb1555;
s_blits [BlitFormat_Dxt1] [BlitFormat_Rgb565] [BlitAlpha_0] = &Blit_Dxt1_Rgb565;
s_blits [BlitFormat_Dxt1] [BlitFormat_Dxt1] [BlitAlpha_0] = &Blit_Dxt1_Dxt1;
// Source: Dxt3
s_blits [BlitFormat_Dxt3] [BlitFormat_Argb8888] [BlitAlpha_0] = &Blit_Dxt3_Argb8888;
s_blits [BlitFormat_Dxt3] [BlitFormat_Argb4444] [BlitAlpha_0] = &Blit_Dxt3_Argb4444;
s_blits [BlitFormat_Dxt3] [BlitFormat_Dxt3] [BlitAlpha_0] = &Blit_Dxt35_Dxt35;
// Source: Dxt5
s_blits [BlitFormat_Dxt5] [BlitFormat_Argb8888] [BlitAlpha_0] = &Blit_Dxt5_Argb8888;
s_blits [BlitFormat_Dxt5] [BlitFormat_Argb4444] [BlitAlpha_0] = &Blit_Dxt5_Argb4444;
s_blits [BlitFormat_Dxt5] [BlitFormat_Dxt5] [BlitAlpha_0] = &Blit_Dxt35_Dxt35;
// Source: Uv88
s_blits [BlitFormat_Uv88] [BlitFormat_Uv88] [BlitAlpha_0] = &Blit_Uv88_Uv88;
// Source: Gr1616F
s_blits [BlitFormat_Gr1616F] [BlitFormat_Gr1616F] [BlitAlpha_0] = &Blit_Gr1616F_Gr1616F;
// Source: R32F
s_blits [BlitFormat_R32F] [BlitFormat_R32F] [BlitAlpha_0] = &Blit_R32F_R32F;
// Source: D24X8
s_blits [BlitFormat_D24X8] [BlitFormat_D24X8] [BlitAlpha_0] = &Blit_D24X8_D24X8;
}
void Blit(const C2iVector& size, BlitAlpha alpha, const void* src, uint32_t srcStride, BlitFormat srcFmt, void* dst, uint32_t dstStride, BlitFormat dstFmt) {
if (!initBlit) {
InitBlit();
initBlit = 1;
}
BLIT_FUNCTION blit = s_blits[srcFmt][dstFmt][alpha];
blit(size, src, srcStride, dst, dstStride);
}

15
src/gx/Blit.hpp Normal file
View File

@ -0,0 +1,15 @@
#ifndef GX_BLIT_HPP
#define GX_BLIT_HPP
#include "gx/Types.hpp"
#include <cstdint>
class C2iVector;
typedef void (*BLIT_FUNCTION)(const C2iVector&, const void*, uint32_t, void*, uint32_t);
void Blit(const C2iVector&, BlitAlpha, const void*, uint32_t, BlitFormat, void*, uint32_t, BlitFormat);
BlitFormat GxGetBlitFormat(EGxTexFormat);
#endif

213
src/gx/Buffer.cpp Normal file
View File

@ -0,0 +1,213 @@
#include "gx/Buffer.hpp"
#include "gx/Device.hpp"
CGxVertexAttrib vertexAttribsP[] = {
{ GxVA_Position, 4, GxVertexAttribOffset(GxVBF_P, GxVA_Position), 12 }
};
CGxVertexAttrib vertexAttribsPN[] = {
{ GxVA_Position, 4, GxVertexAttribOffset(GxVBF_PN, GxVA_Position), 24 },
{ GxVA_Normal, 4, GxVertexAttribOffset(GxVBF_PN, GxVA_Normal), 24 }
};
CGxVertexAttrib vertexAttribsPNC[] = {
{ GxVA_Position, 4, GxVertexAttribOffset(GxVBF_PNC, GxVA_Position), 28 },
{ GxVA_Normal, 4, GxVertexAttribOffset(GxVBF_PNC, GxVA_Normal), 28 },
{ GxVA_Color0, 0, GxVertexAttribOffset(GxVBF_PNC, GxVA_Color0), 28 }
};
CGxVertexAttrib vertexAttribsPNT[] = {
{ GxVA_Position, 4, GxVertexAttribOffset(GxVBF_PNT, GxVA_Position), 32 },
{ GxVA_Normal, 4, GxVertexAttribOffset(GxVBF_PNT, GxVA_Normal), 32 },
{ GxVA_TexCoord0, 3, GxVertexAttribOffset(GxVBF_PNT, GxVA_TexCoord0), 32 }
};
CGxVertexAttrib vertexAttribsPNCT[] = {
{ GxVA_Position, 4, GxVertexAttribOffset(GxVBF_PNCT, GxVA_Position), 36 },
{ GxVA_Normal, 4, GxVertexAttribOffset(GxVBF_PNCT, GxVA_Normal), 36 },
{ GxVA_Color0, 0, GxVertexAttribOffset(GxVBF_PNCT, GxVA_Color0), 36 },
{ GxVA_TexCoord0, 3, GxVertexAttribOffset(GxVBF_PNCT, GxVA_TexCoord0), 36 }
};
CGxVertexAttrib vertexAttribsPNT2[] = {
{ GxVA_Position, 4, GxVertexAttribOffset(GxVBF_PNT2, GxVA_Position), 40 },
{ GxVA_Normal, 4, GxVertexAttribOffset(GxVBF_PNT2, GxVA_Normal), 40 },
{ GxVA_TexCoord0, 3, GxVertexAttribOffset(GxVBF_PNT2, GxVA_TexCoord0), 40 },
{ GxVA_TexCoord1, 3, GxVertexAttribOffset(GxVBF_PNT2, GxVA_TexCoord1), 40 }
};
CGxVertexAttrib vertexAttribsPNCT2[] = {
{ GxVA_Position, 4, GxVertexAttribOffset(GxVBF_PNCT2, GxVA_Position), 44 },
{ GxVA_Normal, 4, GxVertexAttribOffset(GxVBF_PNCT2, GxVA_Normal), 44 },
{ GxVA_Color0, 0, GxVertexAttribOffset(GxVBF_PNCT2, GxVA_Color0), 44 },
{ GxVA_TexCoord0, 3, GxVertexAttribOffset(GxVBF_PNCT2, GxVA_TexCoord0), 44 },
{ GxVA_TexCoord1, 3, GxVertexAttribOffset(GxVBF_PNCT2, GxVA_TexCoord1), 44 }
};
CGxVertexAttrib vertexAttribsPC[] = {
{ GxVA_Position, 4, GxVertexAttribOffset(GxVBF_PC, GxVA_Position), 16 },
{ GxVA_Color0, 0, GxVertexAttribOffset(GxVBF_PC, GxVA_Color0), 16 }
};
CGxVertexAttrib vertexAttribsPCT[] = {
{ GxVA_Position, 4, GxVertexAttribOffset(GxVBF_PCT, GxVA_Position), 24 },
{ GxVA_Color0, 0, GxVertexAttribOffset(GxVBF_PCT, GxVA_Color0), 24 },
{ GxVA_TexCoord0, 3, GxVertexAttribOffset(GxVBF_PCT, GxVA_TexCoord0), 24 }
};
CGxVertexAttrib vertexAttribsPCT2[] = {
{ GxVA_Position, 4, GxVertexAttribOffset(GxVBF_PCT2, GxVA_Position), 32 },
{ GxVA_Color0, 0, GxVertexAttribOffset(GxVBF_PCT2, GxVA_Color0), 32 },
{ GxVA_TexCoord0, 3, GxVertexAttribOffset(GxVBF_PCT2, GxVA_TexCoord0), 32 },
{ GxVA_TexCoord1, 3, GxVertexAttribOffset(GxVBF_PCT2, GxVA_TexCoord1), 32 }
};
CGxVertexAttrib vertexAttribsPT[] = {
{ GxVA_Position, 4, GxVertexAttribOffset(GxVBF_PT, GxVA_Position), 20 },
{ GxVA_TexCoord0, 3, GxVertexAttribOffset(GxVBF_PT, GxVA_TexCoord0), 20 }
};
CGxVertexAttrib vertexAttribsPT2[] = {
{ GxVA_Position, 4, GxVertexAttribOffset(GxVBF_PT2, GxVA_Position), 28 },
{ GxVA_TexCoord0, 3, GxVertexAttribOffset(GxVBF_PT2, GxVA_TexCoord0), 28 },
{ GxVA_TexCoord1, 3, GxVertexAttribOffset(GxVBF_PT2, GxVA_TexCoord1), 28 }
};
CGxVertexAttrib vertexAttribsPBNT2[] = {
{ GxVA_Position, 4, GxVertexAttribOffset(GxVBF_PBNT2, GxVA_Position), 48 },
{ GxVA_BlendWeight, 2, GxVertexAttribOffset(GxVBF_PBNT2, GxVA_BlendWeight), 48 },
{ GxVA_BlendIndices, 1, GxVertexAttribOffset(GxVBF_PBNT2, GxVA_BlendIndices), 48 },
{ GxVA_Normal, 4, GxVertexAttribOffset(GxVBF_PBNT2, GxVA_Normal), 48 },
{ GxVA_TexCoord0, 3, GxVertexAttribOffset(GxVBF_PBNT2, GxVA_TexCoord0), 48 },
{ GxVA_TexCoord1, 3, GxVertexAttribOffset(GxVBF_PBNT2, GxVA_TexCoord1), 48 }
};
CGxVertexAttrib vertexAttribsPNC2T2[] = {
{ GxVA_Position, 4, GxVertexAttribOffset(GxVBF_PNC2T2, GxVA_Position), 48 },
{ GxVA_Normal, 4, GxVertexAttribOffset(GxVBF_PNC2T2, GxVA_Normal), 48 },
{ GxVA_Color0, 0, GxVertexAttribOffset(GxVBF_PNC2T2, GxVA_Color0), 48 },
{ GxVA_Color1, 0, GxVertexAttribOffset(GxVBF_PNC2T2, GxVA_Color0), 48 },
{ GxVA_TexCoord0, 3, GxVertexAttribOffset(GxVBF_PNC2T2, GxVA_TexCoord0), 48 },
{ GxVA_TexCoord1, 3, GxVertexAttribOffset(GxVBF_PNC2T2, GxVA_TexCoord1), 48 }
};
VertexBufDesc Buffer::s_vertexBufDesc[] = {
// GxVBF_P
{ vertexAttribsP, 1, 12, GxPrim_Position },
// GxVBF_PN
{ vertexAttribsPN, 2, 24, GxPrim_Position | GxPrim_Normal },
// GxVBF_PNC
{ vertexAttribsPNC, 3, 28, GxPrim_Position | GxPrim_Normal | GxPrim_Color0 },
// GxVBF_PNT
{ vertexAttribsPNT, 3, 32, GxPrim_Position | GxPrim_Normal | GxPrim_TexCoord0 },
// GxVBF_PNCT
{ vertexAttribsPNCT, 4, 36, GxPrim_Position | GxPrim_Normal | GxPrim_Color0 | GxPrim_TexCoord0 },
// GxVBF_PNT2
{ vertexAttribsPNT2, 4, 40, GxPrim_Position | GxPrim_Normal | GxPrim_TexCoord0 | GxPrim_TexCoord1 },
// GxVBF_PNCT2
{ vertexAttribsPNCT2, 5, 44, GxPrim_Position | GxPrim_Normal | GxPrim_Color0 | GxPrim_TexCoord0 | GxPrim_TexCoord1 },
// GxVBF_PC
{ vertexAttribsPC, 2, 16, GxPrim_Position | GxPrim_Color0 },
// GxVBF_PCT
{ vertexAttribsPCT, 3, 24, GxPrim_Position | GxPrim_Color0 | GxPrim_TexCoord0 },
// GxVBF_PCT2
{ vertexAttribsPCT2, 4, 32, GxPrim_Position | GxPrim_Color0 | GxPrim_TexCoord0 | GxPrim_TexCoord1 },
// GxVBF_PT
{ vertexAttribsPT, 2, 20, GxPrim_Position | GxPrim_TexCoord0 },
// GxVBF_PT2
{ vertexAttribsPT2, 3, 28, GxPrim_Position | GxPrim_TexCoord0 | GxPrim_TexCoord1 },
// GxVBF_PBNT2
{ vertexAttribsPBNT2, 6, 48, GxPrim_Position | GxPrim_BlendWeight | GxPrim_BlendIndices | GxPrim_Normal | GxPrim_TexCoord0 | GxPrim_TexCoord1 },
// GxVBF_PNC2T2
{ vertexAttribsPNC2T2, 6, 48, GxPrim_Position | GxPrim_Normal | GxPrim_Color0 | GxPrim_Color1 | GxPrim_TexCoord0 | GxPrim_TexCoord1 }
};
int32_t Buffer::s_vertexBufOffset[GxVertexBufferFormats_Last][GxVAs_Last] = {
// GxVBF_P
{ 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
// GxVBF_PN
{ 0, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
// GxVBF_PNC
{ 0, -1, -1, 12, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
// GxVBF_PNT
{ 0, -1, -1, 12, -1, -1, 24, -1, -1, -1, -1, -1, -1, -1 },
// GxVBF_PNCT
{ 0, -1, -1, 12, 24, -1, 28, -1, -1, -1, -1, -1, -1, -1 },
// GxVBF_PNT2
{ 0, -1, -1, 12, -1, -1, 24, 32, -1, -1, -1, -1, -1, -1 },
// GxVBF_PNCT2
{ 0, -1, -1, 12, 24, -1, 28, 36, -1, -1, -1, -1, -1, -1 },
// GxVBF_PC
{ 0, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
// GxVBF_PCT
{ 0, -1, -1, -1, 12, -1, 16, -1, -1, -1, -1, -1, -1, -1 },
// GxVBF_PCT2
{ 0, -1, -1, -1, 12, -1, 16, 24, -1, -1, -1, -1, -1, -1 },
// GxVBF_PT
{ 0, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1 },
// GxVBF_PT2
{ 0, -1, -1, -1, -1, -1, 12, 20, -1, -1, -1, -1, -1, -1 },
// GxVBF_PBNT2
{ 0, 12, 16, 20, -1, -1, 32, 40, -1, -1, -1, -1, -1, -1 },
// GxVBF_PNC2T2
{ 0, -1, -1, 12, 24, 28, 32, 40, -1, -1, -1, -1, -1, -1 }
};
uint32_t GxVertexAttribOffset(EGxVertexBufferFormat format, EGxVertexAttrib attrib) {
return Buffer::s_vertexBufOffset[format][attrib];
}
CGxBuf* GxBufCreate(CGxPool* pool, uint32_t itemSize, uint32_t itemCount, uint32_t index) {
return g_theGxDevicePtr->BufCreate(pool, itemSize, itemCount, index);
}
char* GxBufLock(CGxBuf* buf) {
return g_theGxDevicePtr->BufLock(buf);
}
void GxBufUnlock(CGxBuf* buf, uint32_t size) {
g_theGxDevicePtr->BufUnlock(buf, size);
buf->unk1C = 1;
}
CGxPool* GxPoolCreate(EGxPoolTarget target, EGxPoolUsage usage, uint32_t size, EGxPoolHintBits hint, char* name) {
return g_theGxDevicePtr->PoolCreate(target, usage, size, hint, name);
}
void GxPrimIndexPtr(CGxBuf* buf) {
g_theGxDevicePtr->PrimIndexPtr(buf);
}
void GxPrimVertexPtr(CGxBuf* buf, EGxVertexBufferFormat format) {
auto desc = &Buffer::s_vertexBufDesc[format];
g_theGxDevicePtr->PrimVertexFormat(buf, desc->attribs, desc->attribCount);
g_theGxDevicePtr->PrimVertexMask(desc->mask);
g_theGxDevicePtr->PrimVertexPtr(buf, format);
}

38
src/gx/Buffer.hpp Normal file
View File

@ -0,0 +1,38 @@
#ifndef GX_BUFFER_HPP
#define GX_BUFFER_HPP
#include "gx/buffer/CGxBuf.hpp"
#include "gx/buffer/CGxPool.hpp"
#include "gx/buffer/Types.hpp"
#include <cstdint>
class CGxBuf;
class CGxPool;
struct VertexBufDesc {
CGxVertexAttrib* attribs;
uint32_t attribCount;
uint32_t size;
uint32_t mask;
};
namespace Buffer {
extern VertexBufDesc s_vertexBufDesc[GxVertexBufferFormats_Last];
extern int32_t s_vertexBufOffset[GxVertexBufferFormats_Last][GxVAs_Last];
}
uint32_t GxVertexAttribOffset(EGxVertexBufferFormat, EGxVertexAttrib);
CGxBuf* GxBufCreate(CGxPool*, uint32_t, uint32_t, uint32_t);
char* GxBufLock(CGxBuf* buf);
void GxBufUnlock(CGxBuf*, uint32_t);
CGxPool* GxPoolCreate(EGxPoolTarget, EGxPoolUsage, uint32_t, EGxPoolHintBits, char*);
void GxPrimIndexPtr(CGxBuf*);
void GxPrimVertexPtr(CGxBuf*, EGxVertexBufferFormat);
#endif

58
src/gx/CCamera.cpp Normal file
View File

@ -0,0 +1,58 @@
#include "gx/CCamera.hpp"
#include "gx/Shader.hpp"
#include "gx/Transform.hpp"
#include <cmath>
#include <tempest/Math.hpp>
#include <tempest/Matrix.hpp>
#include <tempest/Rect.hpp>
const C3Vector CCamera::DEFAULT_POSITION = { 100.0f, 0.0f, 0.0f };
const float CCamera::DEFAULT_DIST = 100.0f;
const float CCamera::DEFAULT_FARZ = 5000.0f;
const float CCamera::DEFAULT_NEARZ = 8.0f;
float CAngle::ClampTo2Pi(float angle) {
double v1 = floor(static_cast<double>(CMath::OO_TWO_PI) * angle) * CMath::TWO_PI;
if (angle < 0.0f) {
v1 -= CMath::TWO_PI;
}
return angle - v1;
}
void CAngle::Set(const float& angle) {
float clampedAngle = CAngle::ClampTo2Pi(angle);
if (this->m_data != clampedAngle) {
this->m_flags |= CBaseManaged::UPDATED;
this->m_data = clampedAngle;
}
this->m_cos = cos(this->m_data);
this->m_sin = sin(this->m_data);
}
void CCamera::SetupWorldProjection(const CRect& projectionRect, uint32_t flags) {
C44Matrix projMat;
float aspect = (projectionRect.maxX - projectionRect.minX) / (projectionRect.maxY - projectionRect.minY);
GxuXformCreateProjection_SG(this->m_fov.m_data, aspect, this->m_zNear.m_data, this->m_zFar.m_data, projMat);
GxXformSetProjection(projMat);
C44Matrix viewMat;
C3Vector cameraPos = { 0.0f, 0.0f, 0.0f };
C3Vector cameraVec = {
this->m_target.m_data.x - this->m_position.m_data.x,
this->m_target.m_data.y - this->m_position.m_data.y,
this->m_target.m_data.z - this->m_position.m_data.z
};
C3Vector upVec = {
this->m_rotation.m_sin * this->m_roll.m_sin,
-(this->m_rotation.m_cos * this->m_roll.m_sin),
this->m_roll.m_cos
};
GxuXformCreateLookAtSgCompat(cameraPos, cameraVec, upVec, viewMat);
GxXformSetView(viewMat);
CShaderEffect::UpdateProjMatrix();
}

70
src/gx/CCamera.hpp Normal file
View File

@ -0,0 +1,70 @@
#ifndef GX_C_CAMERA_HPP
#define GX_C_CAMERA_HPP
#include <common/DataMgr.hpp>
class CRect;
class CAngle : public TManaged<float> {
public:
// Static functions
static float ClampTo2Pi(float angle);
// Member variables
float m_cos;
float m_sin;
// Virtual member functions
virtual void Set(const float& angle);
// Member functions
CAngle(float angle) {
this->Set(angle);
};
};
class CCamera : public CDataMgr {
public:
static const C3Vector DEFAULT_POSITION;
static const float DEFAULT_DIST;
static const float DEFAULT_FARZ;
static const float DEFAULT_NEARZ;
// Member variables
TManaged<C3Vector> m_position;
TManaged<C3Vector> m_target;
TManaged<float> m_distance;
TManaged<float> m_zFar;
TManaged<float> m_zNear;
CAngle m_aoa;
CAngle m_fov;
CAngle m_roll;
CAngle m_rotation;
// Member functions
CCamera()
: m_position(DEFAULT_POSITION)
, m_distance(DEFAULT_DIST)
, m_zFar(DEFAULT_FARZ)
, m_zNear(DEFAULT_NEARZ)
, m_aoa(0.0f)
, m_fov(0.0f)
, m_roll(0.0f)
, m_rotation(0.0f)
{
this->m_managedArray.SetCount(9);
this->AddManaged(&this->m_position, 7, 0x0);
this->AddManaged(&this->m_target, 8, 0x0);
this->AddManaged(&this->m_distance, 1, 0x0);
this->AddManaged(&this->m_zFar, 2, 0x0);
this->AddManaged(&this->m_zNear, 3, 0x0);
this->AddManaged(&this->m_aoa, 0, 0x0);
this->AddManaged(&this->m_fov, 4, 0x0);
this->AddManaged(&this->m_roll, 5, 0x0);
this->AddManaged(&this->m_rotation, 6, 0x0);
}
void SetupWorldProjection(const CRect& projectionRect, uint32_t flags);
};
#endif

17
src/gx/CGxBatch.hpp Normal file
View File

@ -0,0 +1,17 @@
#ifndef GX_C_GX_BATCH_HPP
#define GX_C_GX_BATCH_HPP
#include "gx/Types.hpp"
#include <cstdint>
class CGxBatch {
public:
// Member variables
EGxPrim m_primType;
uint32_t m_start;
uint32_t m_count;
uint16_t m_minIndex;
uint16_t m_maxIndex;
};
#endif

28
src/gx/CGxCaps.hpp Normal file
View File

@ -0,0 +1,28 @@
#ifndef GX_C_GX_CAPS_HPP
#define GX_C_GX_CAPS_HPP
#include "gx/Types.hpp"
#include <cstdint>
class CGxCaps {
public:
int32_t m_pixelCenterOnEdge = 0;
int32_t m_texelCenterOnEdge = 0;
EGxColorFormat m_colorFormat = GxCF_argb;
int32_t m_generateMipMaps = 0;
uint32_t m_maxTextureSize = 0;
int32_t m_texFmtDxt1 = 0;
int32_t m_texFmtDxt3 = 0;
int32_t m_texFmtDxt5 = 0;
EGxShVS m_vertexShaderTarget = GxShVS_none;
EGxShPS m_pixelShaderTarget = GxShPS_none;
int32_t m_texFilterAnisotropic = 0;
uint32_t m_maxTexAnisotropy = 0;
int32_t m_texTarget[GxTexTargets_Last];
uint32_t m_texMaxSize[GxTexTargets_Last];
int32_t int130 = 1;
int32_t int134 = 0;
int32_t int138 = 0;
};
#endif

1020
src/gx/CGxDevice.cpp Normal file

File diff suppressed because it is too large Load Diff

160
src/gx/CGxDevice.hpp Normal file
View File

@ -0,0 +1,160 @@
#ifndef GX_C_GX_DEVICE_HPP
#define GX_C_GX_DEVICE_HPP
#include "gx/Buffer.hpp"
#include "gx/CGxCaps.hpp"
#include "gx/CGxFormat.hpp"
#include "gx/CGxMatrixStack.hpp"
#include "gx/CGxStateBom.hpp"
#include "gx/Types.hpp"
#include "gx/Shader.hpp"
#include <cstdint>
#include <storm/Hash.hpp>
#include <tempest/Box.hpp>
#include <tempest/Rect.hpp>
class CGxBatch;
class CGxTex;
class CGxTexFlags;
struct CGxAppRenderState {
CGxStateBom m_value;
uint32_t m_stackDepth;
int32_t m_dirty;
};
struct CGxPushedRenderState {
EGxRenderState m_which;
CGxStateBom m_value;
uint32_t m_stackDepth;
};
struct ShaderConstants {
C4Vector constants[256];
uint32_t unk1;
uint32_t unk2;
};
class CGxDevice {
public:
// Static variables
static uint32_t s_alphaRef[];
static C3Vector s_pointScaleIdentity;
static ShaderConstants s_shadowConstants[2];
static uint32_t s_streamPoolSize[];
static uint32_t s_texFormatBitDepth[];
static uint32_t s_texFormatBytesPerBlock[];
// Static functions
static CGxDevice* NewGLL(void);
static CGxDevice* NewOpenGl(void);
// Member variables
TSGrowableArray<CGxPushedRenderState> m_pushedStates;
TSGrowableArray<size_t> m_stackOffsets;
TSGrowableArray<EGxRenderState> m_dirtyStates;
CRect m_defWindowRect;
CRect m_curWindowRect;
EGxApi m_api = GxApis_Last;
CGxFormat m_format;
CGxCaps m_caps;
int32_t m_shaderProfiles[GxShTargets_Last] = { 6, 0, 0, 0, 12, 0 }; // TODO placeholder
TSHashTable<CGxShader, HASHKEY_STRI> m_shaderList[GxShTargets_Last];
int32_t m_context = 0;
CBoundingBox m_viewport;
C44Matrix m_projection;
C44Matrix m_projNative;
CGxMatrixStack m_xforms[GxXforms_Last];
uint32_t m_appMasterEnables = 0;
uint32_t m_hwMasterEnables = 0;
TSList<CGxPool, TSGetLink<CGxPool>> m_poolList;
CGxBuf* m_bufLocked[GxPoolTargets_Last];
CGxPool* m_vertexPool = nullptr;
CGxPool* m_indexPool = nullptr;
CGxBuf* m_streamBufs[GxPoolTargets_Last];
CGxVertexAttrib m_primVertexFormatAttrib[GxVertexBufferFormats_Last];
CGxBuf* m_primVertexFormatBuf[GxVertexBufferFormats_Last];
uint32_t m_primVertexMask = 0;
uint32_t m_primVertexDirty = 0;
EGxVertexBufferFormat m_primVertexFormat = GxVertexBufferFormats_Last;
CGxBuf* m_primVertexBuf = nullptr;
uint32_t m_primVertexSize;
CGxBuf* m_primIndexBuf = nullptr;
int32_t m_primIndexDirty = 0;
TSFixedArray<CGxAppRenderState> m_appRenderStates;
TSFixedArray<CGxStateBom> m_hwRenderStates;
uint32_t m_baseMipLevel = 0; // TODO placeholder
// Virtual member functions
virtual void ITexMarkAsUpdated(CGxTex*) = 0;
virtual void IRsSendToHw(EGxRenderState) = 0;
virtual void ICursorCreate(const CGxFormat& format);
virtual int32_t DeviceCreate(long (*)(void*, uint32_t, uint32_t, long), const CGxFormat&);
virtual int32_t DeviceSetFormat(const CGxFormat&);
virtual void CapsWindowSize(CRect&) = 0;
virtual void CapsWindowSizeInScreenCoords(CRect& dst) = 0;
virtual void ScenePresent(void);
virtual void SceneClear(uint32_t, CImVector) {};
virtual void XformSetProjection(const C44Matrix&);
virtual void XformSetView(const C44Matrix&);
virtual void Draw(CGxBatch*, int32_t) {};
virtual void ValidateDraw(CGxBatch*, int32_t);
virtual void MasterEnableSet(EGxMasterEnables, int32_t);
virtual void PoolSizeSet(CGxPool*, uint32_t) = 0;
virtual char* BufLock(CGxBuf*);
virtual int32_t BufUnlock(CGxBuf*, uint32_t);
virtual int32_t TexCreate(EGxTexTarget, uint32_t, uint32_t, uint32_t, EGxTexFormat, EGxTexFormat, CGxTexFlags, void*, void (*)(EGxTexCommand, uint32_t, uint32_t, uint32_t, uint32_t, void*, uint32_t&, const void*&), const char*, CGxTex*&);
virtual void TexDestroy(CGxTex* texId);
virtual void ShaderCreate(CGxShader*[], EGxShTarget, const char*, const char*, int32_t);
virtual void ShaderConstantsSet(EGxShTarget, uint32_t, const float*, uint32_t);
virtual void IShaderCreate(CGxShader*) = 0;
virtual int32_t StereoEnabled(void) = 0;
// Member functions
CGxDevice();
CGxBuf* BufCreate(CGxPool*, uint32_t, uint32_t, uint32_t);
CGxBuf* BufStream(EGxPoolTarget, uint32_t, uint32_t);
void DeviceCreatePools(void);
void DeviceCreateStreamBufs(void);
const CRect& DeviceCurWindow(void);
void DeviceSetCurWindow(const CRect&);
void DeviceSetDefWindow(CRect const&);
const CRect& DeviceDefWindow(void);
int32_t IDevIsWindowed();
void IRsDirty(EGxRenderState);
void IRsForceUpdate(void);
void IRsForceUpdate(EGxRenderState);
void IRsInit(void);
void IRsSync(int32_t);
void IShaderBind(void) {};
void IShaderLoad(CGxShader*[], EGxShTarget, const char*, const char*, int32_t);
void ITexBind(void) {};
void ITexWHDStartEnd(CGxTex*, uint32_t&, uint32_t&, uint32_t&, uint32_t&);
int32_t MasterEnable(EGxMasterEnables);
CGxPool* PoolCreate(EGxPoolTarget, EGxPoolUsage, uint32_t, EGxPoolHintBits, const char*);
void PrimIndexPtr(CGxBuf*);
void PrimVertexFormat(CGxBuf*, CGxVertexAttrib*, uint32_t);
void PrimVertexMask(uint32_t);
void PrimVertexPtr(CGxBuf*, EGxVertexBufferFormat);
void RsGet(EGxRenderState, int32_t&);
void RsSet(EGxRenderState, int32_t);
void RsSet(EGxRenderState, void*);
void RsSetAlphaRef(void);
void RsPop(void);
void RsPush(void);
void ShaderConstantsClear(void);
char* ShaderConstantsLock(EGxShTarget target);
void ShaderConstantsUnlock(EGxShTarget target, uint32_t index, uint32_t count);
void TexMarkForUpdate(CGxTex*, const CiRect&, int32_t);
void TexSetWrap(CGxTex* texId, EGxTexWrapMode wrapU, EGxTexWrapMode wrapV);
void XformPop(EGxXform xf);
void XformProjection(C44Matrix&);
void XformProjNative(C44Matrix&);
void XformPush(EGxXform xf);
void XformSet(EGxXform xf, const C44Matrix& matrix);
void XformSetViewport(float, float, float, float, float, float);
void XformView(C44Matrix&);
void XformViewport(float&, float&, float&, float&, float&, float&);
};
#endif

32
src/gx/CGxFormat.hpp Normal file
View File

@ -0,0 +1,32 @@
#ifndef GX_C_GX_FORMAT_HPP
#define GX_C_GX_FORMAT_HPP
#include <cstdint>
#include <tempest/Vector.hpp>
class CGxFormat {
public:
// Types
enum Format {
Fmt_Rgb565 = 0,
Fmt_ArgbX888 = 1,
Fmt_Argb8888 = 2,
Fmt_Argb2101010 = 3,
Fmt_Ds160 = 4,
Fmt_Ds24X = 5,
Fmt_Ds248 = 6,
Fmt_Ds320 = 7,
Formats_Last = 8
};
// Member variables
int8_t window;
int32_t maximize;
Format depthFormat;
C2iVector size;
uint32_t sampleCount;
Format colorFormat;
uint32_t refreshRate;
};
#endif

30
src/gx/CGxMatrixStack.cpp Normal file
View File

@ -0,0 +1,30 @@
#include "gx/CGxMatrixStack.hpp"
CGxMatrixStack::CGxMatrixStack() {
this->m_flags[0] = 0x1;
}
void CGxMatrixStack::Pop() {
if (this->m_level > 0) {
this->m_level--;
}
this->m_dirty = 1;
}
void CGxMatrixStack::Push() {
if (this->m_level < 3) {
this->m_level++;
}
this->m_mtx[this->m_level] = this->m_mtx[this->m_level - 1];
this->m_flags[this->m_level] = this->m_flags[this->m_level - 1];
this->m_dirty = 1;
}
C44Matrix& CGxMatrixStack::Top() {
this->m_dirty = 1;
this->m_flags[this->m_level] &= 0xFFFFFFFE;
return this->m_mtx[this->m_level];
}

22
src/gx/CGxMatrixStack.hpp Normal file
View File

@ -0,0 +1,22 @@
#ifndef GX_C_GX_MATRIX_STACK_HPP
#define GX_C_GX_MATRIX_STACK_HPP
#include <cstdint>
#include <tempest/Matrix.hpp>
class CGxMatrixStack {
public:
// Member variables
uint32_t m_level = 0;
int8_t m_dirty = 0;
C44Matrix m_mtx[4];
uint32_t m_flags[4] = {};
// Member functions
CGxMatrixStack();
void Pop(void);
void Push(void);
C44Matrix& Top(void);
};
#endif

85
src/gx/CGxStateBom.cpp Normal file
View File

@ -0,0 +1,85 @@
#include "gx/CGxStateBom.hpp"
#include <tempest/Vector.hpp>
const CGxStateBom& CGxStateBom::operator=(int32_t value) {
this->m_data.i[0] = value;
return *this;
}
const CGxStateBom& CGxStateBom::operator=(uint32_t value) {
this->m_data.i[0] = value;
return *this;
}
const CGxStateBom& CGxStateBom::operator=(float value) {
this->m_data.f[0] = value;
return *this;
}
const CGxStateBom& CGxStateBom::operator=(void* value) {
this->m_data.p = value;
return *this;
}
const CGxStateBom& CGxStateBom::operator=(C3Vector& value) {
this->m_data.f[0] = value.x;
this->m_data.f[1] = value.y;
this->m_data.f[2] = value.z;
return *this;
}
bool CGxStateBom::operator!=(int32_t value) {
return this->m_data.i[0] != value;
}
bool CGxStateBom::operator!=(uint32_t value) {
return this->m_data.i[0] != value;
}
bool CGxStateBom::operator!=(float value) {
return this->m_data.f[0] != value;
}
bool CGxStateBom::operator!=(void* value) {
return this->m_data.p != value;
}
bool CGxStateBom::operator!=(C3Vector& value) {
return this->m_data.f[0] != value.x
|| this->m_data.f[1] != value.y
|| this->m_data.f[2] != value.z;
}
bool CGxStateBom::operator!=(CGxStateBom& value) {
return (this->m_data.i[0] - value.m_data.i[0])
| (this->m_data.i[1] - value.m_data.i[1])
| (this->m_data.i[2] - value.m_data.i[2])
| (this->filler - value.filler);
}
CGxStateBom::operator CImVector() const {
CImVector color;
color.value = this->m_data.i[0];
return color;
}
CGxStateBom::operator float() const {
return this->m_data.f[0];
}
CGxStateBom::operator int32_t() const {
return this->m_data.i[0];
}
CGxStateBom::operator uint32_t() const {
return this->m_data.i[0];
}
CGxStateBom::operator void*() const {
return this->m_data.p;
}

39
src/gx/CGxStateBom.hpp Normal file
View File

@ -0,0 +1,39 @@
#ifndef GX_C_GX_STATE_BOM_HPP
#define GX_C_GX_STATE_BOM_HPP
#include <cstdint>
class C3Vector;
class CImVector;
class CGxStateBom {
public:
// Member variables
union {
int32_t i[3];
float f[3];
void* p;
} m_data;
int32_t filler;
// Member functions
const CGxStateBom& operator=(float);
const CGxStateBom& operator=(int32_t);
const CGxStateBom& operator=(uint32_t);
const CGxStateBom& operator=(void*);
const CGxStateBom& operator=(C3Vector&);
bool operator!=(float);
bool operator!=(int32_t);
bool operator!=(uint32_t);
bool operator!=(void*);
bool operator!=(C3Vector&);
bool operator!=(CGxStateBom&);
explicit operator CImVector() const;
explicit operator float() const;
explicit operator int32_t() const;
explicit operator uint32_t() const;
explicit operator void*() const;
};
#endif

43
src/gx/CMakeLists.txt Normal file
View File

@ -0,0 +1,43 @@
file(GLOB GX_SOURCES
"*.cpp"
"buffer/*.cpp"
"font/*.cpp"
"shader/*.cpp"
"texture/*.cpp"
)
if(WHOA_SYSTEM_MAC)
file(GLOB GLL_SOURCES "gll/*.cpp" "gll/*.mm")
set_source_files_properties(${GLL_SOURCES}
PROPERTIES COMPILE_FLAGS "-x objective-c++"
)
list(APPEND GX_SOURCES ${GLL_SOURCES})
endif()
add_library(gx STATIC ${GX_SOURCES})
target_include_directories(gx
PRIVATE
${CMAKE_SOURCE_DIR}/src
)
target_link_libraries(gx
PRIVATE
event
math
model
ui
util
PUBLIC
freetype-2.0
storm
tempest
)
if(WHOA_SYSTEM_MAC)
target_link_libraries(gx
PRIVATE
"-framework AppKit"
"-framework OpenGL"
)
endif()

Some files were not shown because too many files have changed in this diff Show More