1
0

write shit

This commit is contained in:
2026-01-06 16:27:19 +08:00
parent 52916db08f
commit 4cdc56a32d
24 changed files with 512 additions and 135 deletions

View File

@@ -1,4 +1,4 @@
#include <basalt_export.hpp>
#include <basalt/export_macro.hpp>
BS_EXPORT void* BSCreateInstance() {
return nullptr;

View File

@@ -1,5 +1,5 @@
#include <basalt_export.hpp>
#include <engine.hpp>
#include <basalt/export_macro.hpp>
#include <basalt/kernel.hpp>
#include <windows.h>
#include <d3d11.h>
#include <d3dcompiler.h>
@@ -161,8 +161,8 @@ const char* g_PS = R"(
}
)";
using ::Basalt::Shared::Engine::EngineConfig;
using ::Basalt::Shared::Engine::IEngine;
using ::Basalt::Shared::Kernel::EngineConfig;
using ::Basalt::Shared::Kernel::IEngine;
class DirectX11Engine : public IEngine {
public:
@@ -383,9 +383,9 @@ public:
};
BS_EXPORT void* BSCreateInstance() {
return new DirectX11Engine();
return static_cast<IEngine*>(new DirectX11Engine());
}
BS_EXPORT void BSDestroyInstance(void* instance) {
delete reinterpret_cast<DirectX11Engine*>(instance);
delete dynamic_cast<DirectX11Engine*>(static_cast<IEngine*>(instance));
}

View File

@@ -54,8 +54,9 @@ namespace Basalt::Presenter {
dll_path /= filename;
#if defined(BASALT_OS_WINDOWS)
dll_path.replace_extension(BSTEXT(".dll"));
#else
dll_path.replace_extension(BSTEXT(".so"));
#endif
// Load DLL
#if defined(BASALT_OS_WINDOWS)
m_Handle = LoadLibraryW(dll_path.wstring().c_str());

View File

@@ -1,4 +1,4 @@
#include <basalt_char.hpp>
#include <basalt/char_types.hpp>
#include <string_view>
#if defined(BASALT_OS_WINDOWS)

View File

@@ -1,15 +1,17 @@
#include "dll_loader.hpp"
#include <basalt_char.hpp>
#include <engine.hpp>
#include <basalt/char_types.hpp>
#include <basalt/kernel.hpp>
namespace Presenter = ::Basalt::Presenter;
namespace Shared = ::Basalt::Shared;
namespace Kernel = ::Basalt::Shared::Kernel;
int main(int argc, char* argv[]) {
auto engine_dll = Presenter::DllLoader(Presenter::DllKind::Engine, BSTEXT("BasaltDirectX11Engine"));
auto* engine = engine_dll.CreateInstance<Shared::Engine::IEngine>();
auto deliver_dll = Presenter::DllLoader(Presenter::DllKind::Deliver, BSTEXT("BasaltPipeDeliver"));
auto* engine = engine_dll.CreateInstance<Kernel::IEngine>();
auto* deliver = deliver_dll.CreateInstance<Kernel::IDeliver>();
Shared::Engine::EngineConfig engine_config{.headless = false, .title = BSTEXT("Fuck You"), .width = 800, .height = 600};
Kernel::EngineConfig engine_config{.headless = false, .title = BSTEXT("Fuck You"), .width = 800, .height = 600};
engine->Startup(std::move(engine_config));
while (true) {

View File

@@ -0,0 +1,15 @@
# Basalt Presenter
## Dependencies
* [tinyobjloader](https://github.com/tinyobjloader/tinyobjloader)
* [cgltf](https://github.com/jkuhlmann/cgltf)
## Warning
This project was not written robustly.
So please confirm following conditions when running this program.
- ASCII-only path. It would be better to have English-chars-only path. No space, tab or weird chars.
- Not too long path. It would be better that less than 200 chars.
- ASCII-only command line arguments.

View File

@@ -2,9 +2,9 @@ add_library(BasaltShared STATIC "")
target_sources(BasaltShared
PRIVATE
# Sources
pipe_operator.cpp
engine.cpp
deliver.cpp
basalt/pipe_operator.cpp
basalt/kernel.cpp
basalt/math.cpp
)
target_sources(BasaltShared
@@ -12,11 +12,11 @@ PUBLIC
FILE_SET HEADERS
FILES
# Headers
basalt_char.hpp
basalt_export.hpp
pipe_operator.hpp
engine.hpp
deliver.hpp
basalt/char_types.hpp
basalt/export_macro.hpp
basalt/pipe_operator.hpp
basalt/kernel.hpp
basalt/math.hpp
)
target_include_directories(BasaltShared
PUBLIC

View File

@@ -1,3 +1,4 @@
#pragma once
#include <cwchar>
#include <string>
#include <string_view>

View File

@@ -0,0 +1,65 @@
#include "kernel.hpp"
#include <stdexcept>
namespace Basalt::Shared::Kernel {
#pragma region Engine
IEngine::IEngine() : config(), status(EngineStatus::Ready) {}
IEngine::~IEngine() {
if (this->status != EngineStatus::Stop) {
this->Shutdown();
}
}
Guid IEngine::GetGuid() const {
throw std::logic_error("unimplemented function");
}
void IEngine::Startup(EngineConfig &&config) {
if (this->status != EngineStatus::Ready) throw std::runtime_error("unexpected engine status");
this->config = std::move(config);
this->status = EngineStatus::Running;
}
bool IEngine::Tick() {
if (this->status != EngineStatus::Running) throw std::runtime_error("unexpected engine status");
return false;
}
void IEngine::Shutdown() {
if (this->status != EngineStatus::Running) throw std::runtime_error("unexpected engine status");
this->status = EngineStatus::Stop;
}
#pragma endregion
#pragma region Deliver
IDeliver::IDeliver() {}
IDeliver::~IDeliver() {}
Guid IDeliver::GetGuid() const {
throw std::logic_error("unimplemented function");
}
void IDeliver::Startup(DeliverConfig &&config) {
if (this->status != DeliverStatus::Ready) throw std::runtime_error("unexpected deliver status");
this->config = std::move(config);
this->status = DeliverStatus::Running;
}
void IDeliver::Transmit() {
if (this->status != DeliverStatus::Running) throw std::runtime_error("unexpected deliver status");
}
void IDeliver::Shutdown() {
if (this->status != DeliverStatus::Running) throw std::runtime_error("unexpected deliver status");
this->status = DeliverStatus::Stop;
}
#pragma endregion
} // namespace Basalt::Shared::Kernel

View File

@@ -0,0 +1,123 @@
#pragma once
#include "char_types.hpp"
#include <string>
#include <cinttypes>
namespace Basalt::Shared::Kernel {
#pragma region Guid & Predefined Guid
struct Guid {
std::uint32_t d1, d2;
constexpr Guid(std::uint32_t gd1 = 0, std::uint32_t gd2 = 0) : d1(gd1), d2(gd2) {}
Guid(const Guid& rhs) : d1(rhs.d1), d2(rhs.d2) {}
Guid(Guid&& rhs) noexcept : d1(rhs.d1), d2(rhs.d2) {}
Guid& operator=(const Guid& rhs) {
this->d1 = rhs.d1;
this->d2 = rhs.d2;
return *this;
}
Guid& operator=(Guid&& rhs) noexcept {
this->d1 = rhs.d1;
this->d2 = rhs.d2;
return *this;
}
auto operator<=>(const Guid& rhs) const {
if (auto cmp = this->d1 <=> rhs.d1; cmp != 0) return cmp;
return this->d2 <=> rhs.d2;
}
bool operator==(const Guid& rhs) const { return ((this->d1 == rhs.d1) && (this->d2 == rhs.d2)); }
};
constexpr Guid DIRECTX8_ENGINE{0x0, 0x1};
constexpr Guid DIRECTX9_ENGINE{0x0, 0x2};
constexpr Guid DIRECTX11_ENGINE{0x0, 0x3};
constexpr Guid DIRECTX12_ENGINE{0x0, 0x4};
constexpr Guid OPENGL_ENGINE{0x0, 0x5};
constexpr Guid VULKAN_ENGINE{0x0, 0x6};
constexpr Guid CUDA_DELIVER{0x1, 0x1};
constexpr Guid ROCM_DELIVER{0x1, 0x2};
constexpr Guid PIPE_DELIVER{0x1, 0x3};
constexpr Guid TCP_DELIVER{0x1, 0x4};
constexpr Guid MMAP_DELIVER{0x1, 0x5};
constexpr Guid TINYOBJLOADER_OBJECT_LOADER{0x2, 0x1};
constexpr Guid CGLTF_OBJECT_LOADER{0x2, 0x2};
constexpr Guid ASSIMP_OBJECT_LOADER{0x2, 0x3};
constexpr Guid HOMEBREW_ANIME_LOADER{0x3, 0x1};
#pragma endregion
#pragma region Engine
struct EngineConfig {
bool headless; ///< Whether enable headless mode (No Window created).
std::basic_string<BSCHAR> title; ///< Window title.
std::uint32_t width; ///< Window width.
std::uint32_t height; ///< Window height.
Guid deliver; ///< The GUID of deliver.
};
enum class EngineStatus {
Ready, ///< Engine was allocated but not initialized.
Running, ///< Engine has been initialized and running.
Stop, ///< Engine is shutdown.
};
class IEngine {
public:
IEngine();
virtual ~IEngine();
public:
virtual Guid GetGuid() const;
virtual void Startup(EngineConfig&& config);
/**
* @brief
* @return True for active exit.
*/
virtual bool Tick();
virtual void Shutdown();
protected:
EngineConfig config;
EngineStatus status;
};
#pragma endregion
#pragma region Deliver
struct DeliverConfig {
Guid engine; ///< The GUID of render engine.
};
enum class DeliverStatus {
Ready, ///< Engine was allocated but not initialized.
Running, ///< Engine has been initialized and running.
Stop, ///< Engine is shutdown.
};
class IDeliver {
public:
IDeliver();
virtual ~IDeliver();
public:
virtual Guid GetGuid() const;
virtual void Startup(DeliverConfig&& config);
virtual void Transmit();
virtual void Shutdown();
protected:
DeliverConfig config;
DeliverStatus status;
};
#pragma endregion
} // namespace Basalt::Shared::Kernel

View File

@@ -0,0 +1,5 @@
#include "math.hpp"
namespace Basalt::Shared::Math {
}

View File

@@ -0,0 +1,34 @@
#pragma once
#include <stdexcept>
namespace Basalt::Shared::Math {
using FloatPoint = float;
struct Vector3 {
FloatPoint x, y, z;
};
struct Vector4 {
FloatPoint x, y, z, w;
};
struct Matrix4x4 {
Vector4 data[4];
};
//template<typename TEle, size_t VCnt>
// requires(std::integral<TEle> || std::floating_point<TEle>)
//struct Vector {
// TEle factor[VCnt];
//};
#define NOT_IMPLEMENTED throw std::logic_error("not implemented function");
template<typename TNum, typename TVec>
struct Vector3Traits {};
template<typename TNum, typename TMat>
struct Matrix4x4Traits {};
#undef NOT_IMPLEMENTED
} // namespace Basalt::Shared::Math

View File

@@ -1,4 +1,4 @@
#include "basalt_char.hpp"
#include "char_types.hpp"
#include <string_view>
#if defined(BASALT_OS_WINDOWS)

View File

@@ -1,9 +0,0 @@
#include "deliver.hpp"
namespace Basalt::Shared::Deliver {
IDeliver::IDeliver() {}
IDeliver::~IDeliver() {}
} // namespace Basalt::Shared::Deliver

View File

@@ -1,18 +0,0 @@
#pragma once
namespace Basalt::Shared::Deliver {
struct DeliverConfig {
};
class IDeliver {
public:
IDeliver();
virtual ~IDeliver();
public:
virtual void Transmit() = 0;
};
}

View File

@@ -1,30 +0,0 @@
#include "engine.hpp"
#include <stdexcept>
namespace Basalt::Shared::Engine {
IEngine::IEngine() : config(), status(EngineStatus::Ready) {}
IEngine::~IEngine() {
if (this->status != EngineStatus::Stop) {
this->Shutdown();
}
}
void IEngine::Startup(EngineConfig &&config) {
if (this->status != EngineStatus::Ready) throw std::runtime_error("unexpected engine status");
this->config = std::move(config);
this->status = EngineStatus::Running;
}
bool IEngine::Tick() {
if (this->status != EngineStatus::Running) throw std::runtime_error("unexpected engine status");
return false;
}
void IEngine::Shutdown() {
if (this->status != EngineStatus::Running) throw std::runtime_error("unexpected engine status");
this->status = EngineStatus::Stop;
}
} // namespace Basalt::Shared::Engine

View File

@@ -1,49 +0,0 @@
#pragma once
#include "basalt_char.hpp"
#include <string>
#include <cinttypes>
namespace Basalt::Shared::Engine {
enum class EngineKind {
DirectX8,
DirectX9,
DirectX11,
DirectX12,
OpenGL,
Vulkan,
};
struct EngineConfig {
bool headless; ///< Whether enable headless mode (No Window created).
std::basic_string<BSCHAR> title; ///< Window title.
std::uint32_t width; ///< Window width.
std::uint32_t height; ///< Window height.
};
enum class EngineStatus {
Ready, ///< Engine was allocated but not initialized.
Running, ///< Engine has been initialized and running.
Stop, ///< Engine is shutdown.
};
class IEngine {
public:
IEngine();
virtual ~IEngine();
public:
virtual void Startup(EngineConfig&& config);
/**
* @brief
* @return True for active exit.
*/
virtual bool Tick();
virtual void Shutdown();
protected:
EngineConfig config;
EngineStatus status;
};
}

View File

@@ -1,3 +1,6 @@
# VSCode
.vscode/
# Python-generated files
__pycache__/
*.py[oc]

View File

@@ -0,0 +1,203 @@
import os
import sys
from typing import Optional, Any
IS_WINDOWS: bool = sys.platform == "win32"
if IS_WINDOWS:
import win32pipe
import win32file
import pywintypes
else:
import errno
class PipeOperator:
"""
A Python implementation of the pipe operator similar to the C++ version.
Uses win32pipe on Windows and os.mkfifo on POSIX systems.
"""
pipe_handle: Optional[int]
pipe_name: str
def __init__(self, name: str):
"""
Initialize the PipeOperator.
:param name: Name of the pipe
:param is_server: True if this instance should create the pipe (server), False if connecting to existing pipe (client)
"""
self.pipe_handle = None
if IS_WINDOWS:
self.pipe_name = f"\\\\.\\pipe\\{name}"
self.pipe_handle = win32pipe.CreateNamedPipe(
self.pipe_name,
win32pipe.PIPE_ACCESS_DUPLEX,
win32pipe.PIPE_TYPE_BYTE | win32pipe.PIPE_READMODE_BYTE
| win32pipe.PIPE_WAIT,
1, # Number of pipe instances
65536, # Output buffer size
65536, # Input buffer size
0, # Default timeout
None # Security attributes
)
if self.pipe_handle == win32file.INVALID_HANDLE_VALUE:
raise RuntimeError("Failed to create named pipe.")
# Wait for client to connect
win32pipe.ConnectNamedPipe(self.pipe_handle, None)
else:
# POSIX implementation
self.pipe_name = f"/tmp/{name}"
try:
os.mkfifo(self.pipe_name)
except OSError as e:
if e.errno != errno.EEXIST:
raise RuntimeError(f"Failed to create named pipe: {e}")
# Open the FIFO for reading and writing (blocks until client connects)
self.pipe_handle = os.open(self.pipe_name, os.O_RDWR)
def __del__(self):
"""Cleanup resources when object is destroyed."""
self.close()
def close(self):
"""Close the pipe handle."""
if self.pipe_handle is not None:
if IS_WINDOWS:
win32file.CloseHandle(self.pipe_handle)
else:
os.close(self.pipe_handle)
# Remove the FIFO file if it is existing
if os.path.exists(self.pipe_name):
os.unlink(self.pipe_name)
self.pipe_handle = None
def read(self, size: int) -> bytes:
"""
Read data from the pipe. This is a blocking operation.
:param size: Number of bytes to read
:return: Bytes read from the pipe
"""
if size <= 0:
return b""
if self.pipe_handle is None:
raise RuntimeError("Pipe is not open")
if IS_WINDOWS:
try:
# The result is a tuple of (hr, string/PyOVERLAPPEDReadBuffer).
# You can convert this to a string (str(object)) [py2k] or (bytes(object)) [py3k] to obtain the data.
# I can't visit PyOVERLAPPEDReadBuffer so I simply set it to Any
data: Any
(hr, data) = win32file.ReadFile(self.pipe_handle, size)
if hr != 0: # Error occurred
raise RuntimeError(
f"Failed to read from pipe, error code: {hr}")
data = bytes(data)
if len(data) != size:
raise RuntimeError(
f"Incomplete read from pipe: expected {size} bytes, got {len(data)} bytes"
)
return data
except pywintypes.error as e:
raise RuntimeError(f"Failed to read from named pipe: {e}")
else:
# POSIX implementation
data = b""
while len(data) < size:
try:
chunk = os.read(self.pipe_handle, size - len(data))
if not chunk:
raise RuntimeError("Named pipe closed during read")
data += chunk
except OSError as e:
raise RuntimeError(f"Failed to read from named pipe: {e}")
if len(data) != size:
raise RuntimeError(
f"Incomplete read from pipe: expected {size} bytes, got {len(data)} bytes"
)
return data
def write(self, data: bytes) -> None:
"""
Write data to the pipe. This is a blocking operation.
:param data: Data to write to the pipe
"""
if len(data) == 0:
return
if self.pipe_handle is None:
raise RuntimeError("Pipe is not open")
if IS_WINDOWS:
try:
win32file.WriteFile(self.pipe_handle, data)
except pywintypes.error as e:
raise RuntimeError(f"Failed to write to named pipe: {e}")
else:
# POSIX implementation
total_written = 0
while total_written < len(data):
try:
bytes_written = os.write(self.pipe_handle,
data[total_written:])
total_written += bytes_written
except OSError as e:
raise RuntimeError(f"Failed to write to named pipe: {e}")
# class PipeServer:
# """
# A convenience class for creating a pipe server that can handle connections in a separate thread.
# """
# def __init__(self, name: str):
# self._name = name
# self._pipe_operator: Optional[PipeOperator] = None
# self._server_thread: Optional[threading.Thread] = None
# self._stop_event = threading.Event()
# def start_server(self, handler_func):
# """
# Start the pipe server in a separate thread.
# :param handler_func: Function to handle the connected pipe (takes PipeOperator as parameter)
# """
# self._server_thread = threading.Thread(target=self._server_worker,
# args=(handler_func, ))
# self._server_thread.start()
# def _server_worker(self, handler_func):
# """Internal method to handle server operations."""
# try:
# # Create pipe server
# pipe_op = PipeOperator(self._name, is_server=True)
# self._pipe_operator = pipe_op
# # Call the handler function with the connected pipe
# handler_func(pipe_op)
# except Exception as e:
# print(f"Error in pipe server: {e}")
# finally:
# if self._pipe_operator:
# self._pipe_operator.close()
# def stop_server(self):
# """Stop the pipe server."""
# self._stop_event.set()
# if self._server_thread:
# self._server_thread.join()
# def get_pipe(self) -> Optional[PipeOperator]:
# """Get the connected pipe operator (only valid after client connects)."""
# return self._pipe_operator

View File

@@ -8,6 +8,7 @@ dependencies = [
"datasets>=4.3.0",
"matplotlib>=3.10.7",
"numpy>=2.3.4",
"pywin32>=311 ; sys_platform == 'win32'",
"torch>=2.9.0",
"torchvision>=0.24.0",
]

21
BasaltTrainer/uv.lock generated
View File

@@ -165,6 +165,7 @@ dependencies = [
{ name = "datasets" },
{ name = "matplotlib" },
{ name = "numpy" },
{ name = "pywin32", marker = "sys_platform == 'win32'" },
{ name = "torch", version = "2.9.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform != 'linux' and sys_platform != 'win32'" },
{ name = "torch", version = "2.9.0+cu126", source = { registry = "https://download.pytorch.org/whl/cu126" }, marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "torchvision", version = "0.24.0", source = { registry = "https://download.pytorch.org/whl/cu126" }, marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },
@@ -177,6 +178,7 @@ requires-dist = [
{ name = "datasets", specifier = ">=4.3.0" },
{ name = "matplotlib", specifier = ">=3.10.7" },
{ name = "numpy", specifier = ">=2.3.4" },
{ name = "pywin32", marker = "sys_platform == 'win32'", specifier = ">=311" },
{ name = "torch", marker = "sys_platform != 'linux' and sys_platform != 'win32'", specifier = ">=2.9.0" },
{ name = "torch", marker = "sys_platform == 'linux' or sys_platform == 'win32'", specifier = ">=2.9.0", index = "https://download.pytorch.org/whl/cu126" },
{ name = "torchvision", marker = "sys_platform != 'linux' and sys_platform != 'win32'", specifier = ">=0.24.0" },
@@ -1648,6 +1650,25 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" },
]
[[package]]
name = "pywin32"
version = "311"
source = { registry = "https://pypi.org/simple" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7c/af/449a6a91e5d6db51420875c54f6aff7c97a86a3b13a0b4f1a5c13b988de3/pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151", size = 8697031, upload-time = "2025-07-14T20:13:13.266Z" },
{ url = "https://files.pythonhosted.org/packages/51/8f/9bb81dd5bb77d22243d33c8397f09377056d5c687aa6d4042bea7fbf8364/pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503", size = 9508308, upload-time = "2025-07-14T20:13:15.147Z" },
{ url = "https://files.pythonhosted.org/packages/44/7b/9c2ab54f74a138c491aba1b1cd0795ba61f144c711daea84a88b63dc0f6c/pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2", size = 8703930, upload-time = "2025-07-14T20:13:16.945Z" },
{ url = "https://files.pythonhosted.org/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31", size = 8706543, upload-time = "2025-07-14T20:13:20.765Z" },
{ url = "https://files.pythonhosted.org/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067", size = 9495040, upload-time = "2025-07-14T20:13:22.543Z" },
{ url = "https://files.pythonhosted.org/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" },
{ url = "https://files.pythonhosted.org/packages/a5/be/3fd5de0979fcb3994bfee0d65ed8ca9506a8a1260651b86174f6a86f52b3/pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d", size = 8705700, upload-time = "2025-07-14T20:13:26.471Z" },
{ url = "https://files.pythonhosted.org/packages/e3/28/e0a1909523c6890208295a29e05c2adb2126364e289826c0a8bc7297bd5c/pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d", size = 9494700, upload-time = "2025-07-14T20:13:28.243Z" },
{ url = "https://files.pythonhosted.org/packages/04/bf/90339ac0f55726dce7d794e6d79a18a91265bdf3aa70b6b9ca52f35e022a/pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a", size = 8709318, upload-time = "2025-07-14T20:13:30.348Z" },
{ url = "https://files.pythonhosted.org/packages/c9/31/097f2e132c4f16d99a22bfb777e0fd88bd8e1c634304e102f313af69ace5/pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee", size = 8840714, upload-time = "2025-07-14T20:13:32.449Z" },
{ url = "https://files.pythonhosted.org/packages/90/4b/07c77d8ba0e01349358082713400435347df8426208171ce297da32c313d/pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87", size = 9656800, upload-time = "2025-07-14T20:13:34.312Z" },
{ url = "https://files.pythonhosted.org/packages/c0/d2/21af5c535501a7233e734b8af901574572da66fcc254cb35d0609c9080dd/pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42", size = 8932540, upload-time = "2025-07-14T20:13:36.379Z" },
]
[[package]]
name = "pyyaml"
version = "6.0.3"

View File

@@ -4,18 +4,27 @@ This document introduce the protocol used between Basalt Presenter and Basalt Tr
## Command Protocol
Before introducing command protocol, it would be better to the priniciple,
that Presenter is the slave application, and Trainer is the master application.
|Code|Direction|Comment|
|:---|:---|:---|
|`0x61`|Presenter<--Trainer|Handshake code (Are Presenter ready?)|
|`0x62`|Presenter-->Trainer|Handshake code (Presenter is ready).|
|`0x01`|Presenter-->Trainer|Data was ready. Please Trainer receive it.|
|`0x02`|Presenter<--Trainer|Data has been received. Please go into next loop.|
|`0x61`|Presenter<--Trainer|Handshake code (Are Presenter ready?)|
|`0x62`|Presenter-->Trainer|Handshake code (Presenter is ready)|
|`0x71`|Presenter-->Trainer|Actively Stop (Presenter request stop).|
|`0x71`|Presenter<--Trainer|Stop (Trainer agree the stop request, or trainer actively stop).|
### Handshake
At the beginning of execution, Trainer send handshake code to Presenter first and then Presenter send another handshake code to Trainer back. After this, both 2 applications start running.
At the beginning of execution,
Trainer send handshake code to Presenter first and then Presenter send another handshake code to Trainer back.
After this, both 2 applications start running.
When Presenter send handshake code back, Presenter should attach some values following it to indicate some essential properties of data which will be passed to Trainer in future. There is a table introduce these properties:
When Presenter send handshake code back,
Presenter should attach some values following it to indicate some essential properties of data which will be passed to Trainer in future.
There is a table introduce these properties:
|Data Type|Comment|
|:---|:---|