refactor: reorganize project structure, isolate tools and portable builds, clean root directory
This commit is contained in:
parent
e6bf8d8edb
commit
ba8a1ef0b8
41 changed files with 461 additions and 133 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -23,3 +23,8 @@ __pycache__/
|
||||||
debug_render.png
|
debug_render.png
|
||||||
render_view.png
|
render_view.png
|
||||||
*.log
|
*.log
|
||||||
|
|
||||||
|
# Tool and runtime generated outputs
|
||||||
|
graphify-out/
|
||||||
|
runtime/*.dat
|
||||||
|
runtime/*.stop
|
||||||
|
|
|
||||||
30
AGENTS.md
30
AGENTS.md
|
|
@ -2,7 +2,21 @@
|
||||||
|
|
||||||
## Project identity
|
## Project identity
|
||||||
|
|
||||||
Single-file x86 assembly (MASM32) Windows console casino game. Source: `poker.asm` (~8500 lines). Python scripts are only for previewing animations — not part of the game itself.
|
Single-file x86 assembly (MASM32) Windows console casino game with retro 2.5D raycaster engine. Source: `poker.asm` (~8500 lines). Python scripts are offline tools for asset generation and previewing animations — not part of the game runtime itself.
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
- **Root**: Core MASM32 game (`poker.asm`, `casino3d.inc`, `casino3d_data.inc`, `font8x8.inc`, `build.bat`, `poker.exe`).
|
||||||
|
- **`dist/`**: Compiled desktop distribution launchers (`Assembler Casino.exe`, `Uninstall Assembler Casino.exe`).
|
||||||
|
- **`src_portable/`**: Portable C99 implementation of the casino core (`casino_portable.c`, `Makefile`, `CMakeLists.txt`).
|
||||||
|
- **`build/`**: C# source code for launchers and installers.
|
||||||
|
- **`tools/`**: Internal developer tooling and pipelines:
|
||||||
|
- `tools/previews/`: Terminal ANSI animation and 3D engine previews (`preview_intro.bat`, `preview_hakari.bat`, `preview_dbd_hook.bat`, `preview_casino3d.bat`).
|
||||||
|
- `tools/generators/`: Offline asset compilers, math lookup tables, and assembly generators.
|
||||||
|
- `tools/tests/`: Render simulation (`simulate_render.py`), release smoke checks, and achievement popup helpers.
|
||||||
|
- **`assets/`**: Media files (audio `.wav`, ANSI `.ans`, textures `.bin`, icons).
|
||||||
|
- **`docs/`**: Documentation, cheat codes, ideas backlog, and technical guides.
|
||||||
|
- **`backups/`**: Historical archives and pre-feature checkpoints.
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
|
|
@ -10,9 +24,9 @@ Single-file x86 assembly (MASM32) Windows console casino game. Source: `poker.as
|
||||||
- **Link**: `link /SUBSYSTEM:CONSOLE /RELEASE /VERSION:4.0 /LIBPATH:"<MASM32>\lib" poker.obj kernel32.lib winmm.lib user32.lib ws2_32.lib gdi32.lib`
|
- **Link**: `link /SUBSYSTEM:CONSOLE /RELEASE /VERSION:4.0 /LIBPATH:"<MASM32>\lib" poker.obj kernel32.lib winmm.lib user32.lib ws2_32.lib gdi32.lib`
|
||||||
- **IDE project**: `poker.wap` (Pelles C/Windows)
|
- **IDE project**: `poker.wap` (Pelles C/Windows)
|
||||||
- **Libraries**: `kernel32.lib`, `winmm.lib`, `user32.lib`, `ws2_32.lib`, `gdi32.lib`
|
- **Libraries**: `kernel32.lib`, `winmm.lib`, `user32.lib`, `ws2_32.lib`, `gdi32.lib`
|
||||||
- **Build script**: `build.bat` (uses MASM32 from `D:\MASM32\masm32`)
|
- **Build script**: `build.bat` (uses MASM32 from `D:\MASM32\masm32` or MSVC BuildTools)
|
||||||
|
|
||||||
Requires MASM32 toolchain (`ml.exe`, `link.exe` from e.g. `F:\MASM32\masm32\bin`).
|
Requires MASM32 toolchain or MSVC BuildTools (`ml.exe`, `link.exe`).
|
||||||
|
|
||||||
## Encoding
|
## Encoding
|
||||||
|
|
||||||
|
|
@ -24,16 +38,18 @@ Requires MASM32 toolchain (`ml.exe`, `link.exe` from e.g. `F:\MASM32\masm32\bin`
|
||||||
|
|
||||||
| File | Purpose |
|
| File | Purpose |
|
||||||
|------|---------|
|
|------|---------|
|
||||||
| `casino_intro.ans` | Animated intro (skippable with Enter, loops at `@@LOOP@@` marker) |
|
| `assets/animations/casino_intro.ans` | Animated intro (skippable with Enter, loops at `@@LOOP@@` marker) |
|
||||||
| `hakari_dance.ans` | Animated dance on jackpot win |
|
| `assets/animations/hakari_dance.ans` | Animated dance on jackpot win |
|
||||||
| `dealer_phrases.txt` | CP1251, each line prefixed `W|` (win), `L|` (loss), `D|` (draw) |
|
| `assets/animations/dbd_hook.ans` | Dead by Daylight hook skill-check mini-game animation |
|
||||||
|
| `assets/data/dealer_phrases.txt` | CP1251, each line prefixed `W|` (win), `L|` (loss), `D|` (draw) |
|
||||||
|
| `assets/textures/casino3d-hd.bin` | Packed 48 slots (128×128 BGRA) 3D raycaster textures |
|
||||||
|
|
||||||
## Workflow
|
## Workflow
|
||||||
|
|
||||||
- **Git remote**: `https://git.silverstone.crazedns.ru/Billi_Bob/KAZIK.git` (branch `main`).
|
- **Git remote**: `https://git.silverstone.crazedns.ru/Billi_Bob/KAZIK.git` (branch `main`).
|
||||||
- Backups in `backups/` follow: `poker_before_<feature>_<YYYYMMDD_HHMMSS>.{asm,exe}`
|
- Backups in `backups/` follow: `poker_before_<feature>_<YYYYMMDD_HHMMSS>.{asm,exe}`
|
||||||
- **No tests**. Manually verify by running `poker.exe`.
|
- **No tests**. Manually verify by running `poker.exe`.
|
||||||
- Preview animations: `preview_hakari.bat` / `preview_intro.bat` (or `python preview_hakari.py` directly).
|
- Preview animations: `tools/previews/preview_hakari.bat` / `tools/previews/preview_intro.bat` (or `python tools/previews/preview_hakari.py` directly).
|
||||||
|
|
||||||
## Games (menu)
|
## Games (menu)
|
||||||
|
|
||||||
|
|
|
||||||
189
README.md
189
README.md
|
|
@ -1,3 +1,188 @@
|
||||||
# KAZIK
|
# ASSEMBLER CASINO (KAZIK) 🎰
|
||||||
|
|
||||||
DEPAI DEPAI DEPAI DEPAI DEPAI DEPAI DEPAI DEPAI DEPAI DEPAI
|
A retro casino gaming suite powered by a high-performance **pure x86 assembly (MASM32)** engine featuring an interactive **2.5D retro Raycaster 3D Hall** (DOOM / Wolfenstein style) and a catalog of classic and underground gambling games.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏛️ Architecture Overview
|
||||||
|
|
||||||
|
The repository is organized into distinct, modular subsystems:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌────────────────────────────────────────┐
|
||||||
|
│ ASSEMBLER CASINO │
|
||||||
|
└──────────────────┬─────────────────────┘
|
||||||
|
│
|
||||||
|
┌───────────────────────────┼───────────────────────────┐
|
||||||
|
▼ ▼ ▼
|
||||||
|
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
|
||||||
|
│ MASM32 Engine │ │ C99 Portable │ │ C# GUI Launcher │
|
||||||
|
│ (Root Directory)│ │ (src_portable/) │ │ (build/ & dist/) │
|
||||||
|
│ - poker.asm │ │ - casino_portable│ │ - Launcher.cs │
|
||||||
|
│ - casino3d.inc │ │ - CMakeLists.txt │ │ - Installer GUI │
|
||||||
|
│ - font8x8.inc │ │ - Makefile │ │ - Setup Wizards │
|
||||||
|
└────────┬─────────┘ └──────────────────┘ └──────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌──────────────────────────────────────────────┐
|
||||||
|
│ Offline Pipeline & Tooling │
|
||||||
|
│ (tools/) │
|
||||||
|
│ - tools/previews/ (ANSI / 3D previews) │
|
||||||
|
│ - tools/generators/ (Asset & table packers) │
|
||||||
|
│ - tools/tests/ (Simulators & checks) │
|
||||||
|
└──────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
1. **MASM32 Core Game Engine (Root)**
|
||||||
|
- **`poker.asm`**: Main game binary (~8,500+ lines of hand-crafted x86 assembly). Contains game logic, cheat engine, socket networking, profile save system, and sound triggers.
|
||||||
|
- **`casino3d.inc` / `casino3d_data.inc`**: Software 2.5D Raycaster engine rendering a 32×32 grand casino hall at 640×480 with DDA wall casting, depth-sorted sprite objects, and interactive tables.
|
||||||
|
- **`font8x8.inc`**: CP1251 1-bit monochrome 8×8 bitmap font table for high-speed HUD rendering directly to the Win32 GDI frame buffer.
|
||||||
|
|
||||||
|
2. **Portable C99 Core (`src_portable/`)**
|
||||||
|
- Cross-platform implementation (`casino_portable.c`, `casino_portable.h`) allowing gameplay on POSIX / Linux / macOS environments.
|
||||||
|
- Fully standalone build with standard `Makefile` or `CMakeLists.txt`.
|
||||||
|
|
||||||
|
3. **Desktop Distribution & Launcher (`build/` & `dist/`)**
|
||||||
|
- **`build/`**: C# source code for the launcher (`AssemblerCasinoLauncher.cs`), setup GUI (`PokerGameSetupGui.cs`), and uninstaller.
|
||||||
|
- **`dist/`**: Ready-to-run compiled desktop executables (`Assembler Casino.exe`, `Uninstall Assembler Casino.exe`).
|
||||||
|
|
||||||
|
4. **Offline Development Tooling (`tools/`)**
|
||||||
|
- **`tools/previews/`**: Terminal ANSI animation players (`preview_intro.py`, `preview_hakari.py`, `preview_dbd_hook.py`) and 3D preview runner.
|
||||||
|
- **`tools/generators/`**: Texture pack scripts (`build_graphics_assets.py`), math table generators (`generate_math_and_map.py`), font rasterizer (`generate_font.py`).
|
||||||
|
- **`tools/tests/`**: Software raycaster simulator (`simulate_render.py`), release integrity checks (`release_smoke_check.ps1`), achievement popup modal (`achievement_popup.bat`).
|
||||||
|
|
||||||
|
5. **Assets & Documentation (`assets/`, `docs/`, `backups/`)**
|
||||||
|
- **`assets/`**: High-resolution textures, sprites, audio samples (`.wav`), and ANSI cinematics (`.ans`).
|
||||||
|
- **`docs/`**: Design specifications, cheat sheet, networking guides, and engine render previews.
|
||||||
|
- **`backups/`**: Historical milestones and archived releases.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 Repository Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
├── poker.asm # Primary MASM32 assembly source
|
||||||
|
├── casino3d.inc # 2.5D retro 3D raycaster engine implementation
|
||||||
|
├── casino3d_data.inc # 3D engine math tables (sin/cos) & casino hall grid
|
||||||
|
├── font8x8.inc # 8x8 CP1251 bitmap font data
|
||||||
|
├── poker.wap # Pelles C / Windows project definition
|
||||||
|
├── build.bat # One-click build script for MASM32 core
|
||||||
|
├── poker.exe # Compiled game binary
|
||||||
|
├── AGENTS.md # Engineering guidelines and agent instructions
|
||||||
|
├── README.md # Project documentation (this file)
|
||||||
|
├── LICENSE # Project license
|
||||||
|
├── .gitignore # Git ignore patterns
|
||||||
|
│
|
||||||
|
├── assets/ # Game assets
|
||||||
|
│ ├── animations/ # ANSI animations (casino_intro.ans, hakari_dance.ans, dbd_hook.ans)
|
||||||
|
│ ├── audio/ # Sound effects (.wav) for cards, roulette, coins, win/loss
|
||||||
|
│ ├── data/ # Dealer dialogues and text tables (CP1251)
|
||||||
|
│ ├── icons/ # Game icon assets (.ico, .png)
|
||||||
|
│ ├── music/ # Background tracks
|
||||||
|
│ ├── sprites/ # Source sprite sheets & cabaret animations
|
||||||
|
│ └── textures/ # Packed 128x128 BGRA texture binaries (casino3d-hd.bin)
|
||||||
|
│
|
||||||
|
├── backups/ # Preserved backups and legacy archives
|
||||||
|
│
|
||||||
|
├── build/ # Launcher and setup source code (C# .NET)
|
||||||
|
│ ├── AssemblerCasinoLauncher.cs
|
||||||
|
│ ├── PokerGameSetupGui.cs
|
||||||
|
│ └── UninstallAssemblerCasino.cs
|
||||||
|
│
|
||||||
|
├── dist/ # Compiled desktop distribution binaries
|
||||||
|
│ ├── Assembler Casino.exe
|
||||||
|
│ └── Uninstall Assembler Casino.exe
|
||||||
|
│
|
||||||
|
├── docs/ # Project documentation, guides, and plans
|
||||||
|
│ ├── intro_code_draft.txt # Opening sequence drafts
|
||||||
|
│ ├── render_view.png # Simulated frame render of the 3D casino hall
|
||||||
|
│ ├── ИДЕИ.txt # Game ideas and development backlog
|
||||||
|
│ ├── ЧИТКОДЫ.txt # Complete list of cheat codes
|
||||||
|
│ └── *.txt # Release notes, security guidelines, networking
|
||||||
|
│
|
||||||
|
├── src_portable/ # Standalone portable C99 implementation
|
||||||
|
│ ├── casino_portable.c
|
||||||
|
│ ├── casino_portable.h
|
||||||
|
│ ├── CMakeLists.txt
|
||||||
|
│ ├── Makefile
|
||||||
|
│ └── poker_portable.exe
|
||||||
|
│
|
||||||
|
└── tools/ # Developer tooling & offline asset pipeline
|
||||||
|
├── README.md # Documentation for tools
|
||||||
|
├── previews/ # Animation & 3D preview scripts (.py, .bat)
|
||||||
|
├── generators/ # Asset packers, math & font generators (.py)
|
||||||
|
└── tests/ # Software render simulator & test scripts (.py, .ps1, .bat)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Build Instructions
|
||||||
|
|
||||||
|
### 1. MASM32 Game Binary (`poker.exe`)
|
||||||
|
|
||||||
|
Prerequisites: MASM32 SDK (`ml.exe`, `link.exe`) installed in `D:\MASM32\masm32`, `C:\masm32`, or Visual Studio MSVC BuildTools.
|
||||||
|
|
||||||
|
Simply run:
|
||||||
|
```bat
|
||||||
|
build.bat
|
||||||
|
```
|
||||||
|
This will assemble `poker.asm` with MASM, link against `kernel32`, `winmm`, `user32`, `ws2_32`, `gdi32`, and produce `poker.exe`.
|
||||||
|
|
||||||
|
### 2. C99 Portable Engine (`src_portable/`)
|
||||||
|
|
||||||
|
With GCC / MinGW:
|
||||||
|
```bash
|
||||||
|
cd src_portable
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
Or with CMake:
|
||||||
|
```bash
|
||||||
|
cd src_portable
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake ..
|
||||||
|
cmake --build .
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Running Previews and Simulators
|
||||||
|
|
||||||
|
- **Hakari Jackpot Dance Preview**:
|
||||||
|
```bat
|
||||||
|
tools\previews\preview_hakari.bat
|
||||||
|
```
|
||||||
|
- **Casino Intro Animation Preview**:
|
||||||
|
```bat
|
||||||
|
tools\previews\preview_intro.bat
|
||||||
|
```
|
||||||
|
- **3D Engine Software Simulation**:
|
||||||
|
```bash
|
||||||
|
python tools/tests/simulate_render.py
|
||||||
|
```
|
||||||
|
Generates `docs/render_view.png` showing the 3D raycaster view with sprites.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔤 Character Encoding Standard
|
||||||
|
|
||||||
|
- **Game source & strings (`poker.asm`, `assets/data/dealer_phrases.txt`)**: **CP1251 (Windows-1251)**. Never save as UTF-8.
|
||||||
|
- **ANSI animations (`.ans`)**: CP1251 encoding with ANSI escape codes and form feed (`\f`, `0x0C`) frame delimiters. Preview runners execute `chcp 65001` before playback.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎮 Games & Features
|
||||||
|
|
||||||
|
| # | Game | Description |
|
||||||
|
|---|------|-------------|
|
||||||
|
| 1 | **21 / Blackjack** | Classic card game against the dealer with hit/stand mechanics. |
|
||||||
|
| 2 | **Poker** | Texas Hold'em with AI opponents, betting rounds, and pot calculations. |
|
||||||
|
| 3 | **CloverPit** | 5×3 video slots with custom bonus features and payouts. |
|
||||||
|
| 4 | **Russian Roulette** | High-stakes survival with revolver chamber simulation. |
|
||||||
|
| 5 | **Skulls & Cups** | Thimblerig shell game testing perception and luck. |
|
||||||
|
| 6 | **Coin Flip** | Double or nothing coin toss. |
|
||||||
|
| 7 | **Dice / Craps** | Classic dice rolling wagering. |
|
||||||
|
| 8 | **Roulette** | European roulette wheel with single and range bets. |
|
||||||
|
| 9 | **Classic Slots** | 3-reel 777 fruit machine. |
|
||||||
|
| 10 | **Durak** | Traditional Russian card game with trump cards and defense logic. |
|
||||||
|
| 11 | **Training** | Practice arena with infinite balance. |
|
||||||
|
| 12 | **Observer (AI vs AI)** | Watch autonomous agents play against each other. |
|
||||||
|
| 3D | **Grand Casino Hall** | Real-time 2.5D raycaster environment to explore and walk up to tables. |
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -900,7 +900,7 @@ achCharmBuyerName db "
|
||||||
achObserverName db "Ëîæà íàáëþäàòåëÿ",13,10,0
|
achObserverName db "Ëîæà íàáëþäàòåëÿ",13,10,0
|
||||||
achSkillCheckName db "Ñ êðþêà ñîðâàëñÿ",13,10,0
|
achSkillCheckName db "Ñ êðþêà ñîðâàëñÿ",13,10,0
|
||||||
achievementFileName db "runtime\achievement.txt",0
|
achievementFileName db "runtime\achievement.txt",0
|
||||||
achievementCmd db "cmd /c start ""Achievement"" tools\achievement_popup.bat",0
|
achievementCmd db "cmd /c start ""Achievement"" tools\tests\achievement_popup.bat",0
|
||||||
skillTitle db 13,10,"--- Êðþê: Skill Check ---",13,10,0
|
skillTitle db 13,10,"--- Êðþê: Skill Check ---",13,10,0
|
||||||
skillIntro db "Ïîïàäàé ïî çåëåíîé çîíå. PERFECT äàåò äâîéíîé ïðîãðåññ.",13,10
|
skillIntro db "Ïîïàäàé ïî çåëåíîé çîíå. PERFECT äàåò äâîéíîé ïðîãðåññ.",13,10
|
||||||
db "3 ïðîìàõà - òüìà çàáèðàåò ñòàâêó. 5 ïðîãðåññà - òû ñðûâàåøüñÿ ñ êðþêà.",13,10
|
db "3 ïðîìàõà - òüìà çàáèðàåò ñòàâêó. 5 ïðîãðåññà - òû ñðûâàåøüñÿ ñ êðþêà.",13,10
|
||||||
|
|
@ -2608,7 +2608,7 @@ runtimeDir db "runtime",0
|
||||||
danceFileName db "assets\animations\hakari_dance.ans",0
|
danceFileName db "assets\animations\hakari_dance.ans",0
|
||||||
casinoIntroFile db "assets\animations\casino_intro.ans",0
|
casinoIntroFile db "assets\animations\casino_intro.ans",0
|
||||||
dbdHookFileName db "assets\animations\dbd_hook.ans",0
|
dbdHookFileName db "assets\animations\dbd_hook.ans",0
|
||||||
dbdHookCmd db "cmd /c start ""DBD Hook"" tools\preview_dbd_hook.bat",0
|
dbdHookCmd db "cmd /c start ""DBD Hook"" tools\previews\preview_dbd_hook.bat",0
|
||||||
dbdHookStopFile db "runtime\dbd_hook.stop",0
|
dbdHookStopFile db "runtime\dbd_hook.stop",0
|
||||||
animProfileFile db "runtime\anim_profile.txt",0
|
animProfileFile db "runtime\anim_profile.txt",0
|
||||||
animProfileDigits db "012",0
|
animProfileDigits db "012",0
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 449 KiB After Width: | Height: | Size: 337 KiB |
|
|
@ -900,7 +900,7 @@ achCharmBuyerName db "
|
||||||
achObserverName db "Ëîæà íàáëþäàòåëÿ",13,10,0
|
achObserverName db "Ëîæà íàáëþäàòåëÿ",13,10,0
|
||||||
achSkillCheckName db "Ñ êðþêà ñîðâàëñÿ",13,10,0
|
achSkillCheckName db "Ñ êðþêà ñîðâàëñÿ",13,10,0
|
||||||
achievementFileName db "runtime\achievement.txt",0
|
achievementFileName db "runtime\achievement.txt",0
|
||||||
achievementCmd db "cmd /c start ""Achievement"" tools\achievement_popup.bat",0
|
achievementCmd db "cmd /c start ""Achievement"" tools\tests\achievement_popup.bat",0
|
||||||
skillTitle db 13,10,"--- Êðþê: Skill Check ---",13,10,0
|
skillTitle db 13,10,"--- Êðþê: Skill Check ---",13,10,0
|
||||||
skillIntro db "Ïîïàäàé ïî çåëåíîé çîíå. PERFECT äàåò äâîéíîé ïðîãðåññ.",13,10
|
skillIntro db "Ïîïàäàé ïî çåëåíîé çîíå. PERFECT äàåò äâîéíîé ïðîãðåññ.",13,10
|
||||||
db "3 ïðîìàõà - òüìà çàáèðàåò ñòàâêó. 5 ïðîãðåññà - òû ñðûâàåøüñÿ ñ êðþêà.",13,10
|
db "3 ïðîìàõà - òüìà çàáèðàåò ñòàâêó. 5 ïðîãðåññà - òû ñðûâàåøüñÿ ñ êðþêà.",13,10
|
||||||
|
|
@ -2608,7 +2608,7 @@ runtimeDir db "runtime",0
|
||||||
danceFileName db "assets\animations\hakari_dance.ans",0
|
danceFileName db "assets\animations\hakari_dance.ans",0
|
||||||
casinoIntroFile db "assets\animations\casino_intro.ans",0
|
casinoIntroFile db "assets\animations\casino_intro.ans",0
|
||||||
dbdHookFileName db "assets\animations\dbd_hook.ans",0
|
dbdHookFileName db "assets\animations\dbd_hook.ans",0
|
||||||
dbdHookCmd db "cmd /c start ""DBD Hook"" tools\preview_dbd_hook.bat",0
|
dbdHookCmd db "cmd /c start ""DBD Hook"" tools\previews\preview_dbd_hook.bat",0
|
||||||
dbdHookStopFile db "runtime\dbd_hook.stop",0
|
dbdHookStopFile db "runtime\dbd_hook.stop",0
|
||||||
animProfileFile db "runtime\anim_profile.txt",0
|
animProfileFile db "runtime\anim_profile.txt",0
|
||||||
animProfileDigits db "012",0
|
animProfileDigits db "012",0
|
||||||
|
|
|
||||||
BIN
poker.exe
BIN
poker.exe
Binary file not shown.
|
|
@ -4,8 +4,8 @@ project(poker_portable C)
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(CMAKE_C_STANDARD 99)
|
||||||
|
|
||||||
add_executable(poker_portable
|
add_executable(poker_portable
|
||||||
src_portable/casino_portable.c
|
casino_portable.c
|
||||||
src_portable/casino_portable.h
|
casino_portable.h
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
|
@ -11,8 +11,8 @@ endif
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): src_portable/casino_portable.c src_portable/casino_portable.h
|
$(TARGET): casino_portable.c casino_portable.h
|
||||||
$(CC) $(CFLAGS) src_portable/casino_portable.c -o $(TARGET) $(LIBS)
|
$(CC) $(CFLAGS) casino_portable.c -o $(TARGET) $(LIBS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(TARGET) *.o
|
rm -f $(TARGET) *.o
|
||||||
59
tools/README.md
Normal file
59
tools/README.md
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
# Tools & Utilities Directory (`tools/`)
|
||||||
|
|
||||||
|
This directory contains internal utilities, asset generators, preview helpers, and test scripts used during development.
|
||||||
|
|
||||||
|
> **Note:** The shipped game is a standalone native x86 binary with zero Python or external runtime dependencies. All Python and PowerShell scripts here are strictly offline development tools.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
tools/
|
||||||
|
├── previews/ # Interactive preview launchers for animations and 3D engine
|
||||||
|
├── generators/ # Offline asset generators, math tables, and code builders
|
||||||
|
└── tests/ # Test scripts, render simulators, and release checks
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Previews (`tools/previews/`)
|
||||||
|
|
||||||
|
Interactive terminal and audio previews for animations and graphical components:
|
||||||
|
|
||||||
|
| Tool | Language | Purpose & Usage |
|
||||||
|
|------|----------|-----------------|
|
||||||
|
| `preview_hakari.py`<br>`preview_hakari.bat` | Python / Batch | Plays the animated ANSI jackpot dance (`assets/animations/hakari_dance.ans`) synchronized with audio (`assets/audio/hakari_dance.wav`). Run via double-clicking `preview_hakari.bat` or `python tools/previews/preview_hakari.py`. |
|
||||||
|
| `preview_intro.py`<br>`preview_intro.bat` | Python / Batch | Plays the casino opening ANSI animation (`assets/animations/casino_intro.ans`) with support for Enter key skipping and `@@LOOP@@` frame looping. Run via `preview_intro.bat` or `python tools/previews/preview_intro.py`. |
|
||||||
|
| `preview_dbd_hook.py`<br>`preview_dbd_hook.bat` | Python / Batch + PowerShell | Previews the Dead by Daylight hook skill-check mini-game animation (`assets/animations/dbd_hook.ans`). Controlled by `runtime/dbd_hook.stop` and animation profile settings. Run via `preview_dbd_hook.bat`. |
|
||||||
|
| `preview_casino3d.bat` | Batch | Convenience launcher that switches to root and starts `poker.exe` in 3D DOOM/Wolfenstein retro view mode. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Generators (`tools/generators/`)
|
||||||
|
|
||||||
|
Offline build tools that process raw images, generate lookup tables, and compose assembly code:
|
||||||
|
|
||||||
|
| Tool | Language | Purpose & Usage |
|
||||||
|
|------|----------|-----------------|
|
||||||
|
| `build_graphics_assets.py` | Python (Pillow) | Packs sprite sheets and texture atlases into 48 slots of 128×128 32-bit BGRA format, producing `assets/textures/casino3d-hd.bin`. Usage: `python tools/generators/build_graphics_assets.py`. |
|
||||||
|
| `build_casino_assets.py` | Python (Pillow) | Compiles source textures and sprite images into the legacy `assets/textures/casino3d.bin` binary. |
|
||||||
|
| `generate_font.py` | Python (Pillow) | Renders Consolas/Arial fonts for all 256 CP1251 characters into an 8×8 1-bit monochrome bitmap table, saved to `font8x8.inc`. Usage: `python tools/generators/generate_font.py`. |
|
||||||
|
| `generate_math_and_map.py` | Python | Computes 512-angle fixed-point (16.16) Sine and Cosine tables and the 32×32 casino hall floor plan, saving them to `casino3d_data.inc`. Usage: `python tools/generators/generate_math_and_map.py`. |
|
||||||
|
| `build_all_3d.py` | Python | Offline assembly file generator that synthesizes the complete `casino3d.inc` raycaster engine in CP1251. |
|
||||||
|
| `generate_unified_casino3d.py` | Python | Alternative unified generator for `casino3d.inc` with full sprite definitions and game interaction hooks. |
|
||||||
|
| `generate_casino3d.py`<br>`build_engine.py`<br>`make_casino3d.py` | Python | Lightweight orchestration scripts for triggering `casino3d.inc` regeneration in CP1251 encoding. |
|
||||||
|
| `patch_poker_asm.py` | Python | Helper utility to patch `poker.asm` with 3D engine hooks, player save anchors, and mutex management. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Tests & Verification (`tools/tests/`)
|
||||||
|
|
||||||
|
Verification scripts, simulation harnesses, and runtime helpers:
|
||||||
|
|
||||||
|
| Tool | Language | Purpose & Usage |
|
||||||
|
|------|----------|-----------------|
|
||||||
|
| `simulate_render.py` | Python (Pillow) | Software CPU simulation of the 3D raycaster renderer. Reads `casino3d_data.inc` and texture binary, performs DDA raycasting, depth-sorting of 28 casino sprites, and saves the rendered view to `docs/render_view.png`. Usage: `python tools/tests/simulate_render.py`. |
|
||||||
|
| `release_smoke_check.ps1` | PowerShell | Automated smoke test for release readiness: verifies file presence, launcher SHA-256 hashes, CP1251 source markers, and absence of deprecated assets. Usage: `powershell -File tools/tests/release_smoke_check.ps1`. |
|
||||||
|
| `build_graphics.ps1` | PowerShell | Builds the Windows subsystem executable `build/graphics/poker.exe` using MASM32/MSVC toolchain. Usage: `powershell -File tools/tests/build_graphics.ps1`. |
|
||||||
|
| `achievement_popup.bat` | Batch (CP1251) | Standalone console achievement notification popup called by `poker.exe`. Reads achievement text from `runtime/achievement.txt` and renders a decorative banner with rarity colors (COMMON, RARE, EPIC, LEGENDARY). |
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
param([string]$MasmRoot = 'F:\MASM32\masm32')
|
|
||||||
$ErrorActionPreference = 'Stop'
|
|
||||||
$root = Split-Path $PSScriptRoot -Parent
|
|
||||||
Push-Location $root
|
|
||||||
try {
|
|
||||||
& "$MasmRoot\bin\ml.exe" /c /coff /Cp /nologo /I. /Fobuild\graphics\poker.obj poker.asm
|
|
||||||
if ($LASTEXITCODE -ne 0) { throw 'MASM assembly failed' }
|
|
||||||
& "$MasmRoot\bin\link.exe" /nologo /SUBSYSTEM:WINDOWS /RELEASE /VERSION:5.0 "/LIBPATH:$MasmRoot\lib" /OUT:build\graphics\poker.exe build\graphics\poker.obj build\casino_icon.res kernel32.lib winmm.lib user32.lib ws2_32.lib gdi32.lib
|
|
||||||
if ($LASTEXITCODE -ne 0) { throw 'Link failed' }
|
|
||||||
Write-Output 'Built build\graphics\poker.exe. Publish only after verification.'
|
|
||||||
} finally {
|
|
||||||
Pop-Location
|
|
||||||
}
|
|
||||||
|
|
@ -3225,7 +3225,9 @@ StartCasino3D ENDP
|
||||||
''')
|
''')
|
||||||
|
|
||||||
# Write complete file in Windows-1251
|
# Write complete file in Windows-1251
|
||||||
with open('casino3d.inc', 'wb') as f:
|
from pathlib import Path
|
||||||
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
with open(REPO_ROOT / 'casino3d.inc', 'wb') as f:
|
||||||
f.write(''.join(code_chunks).encode('cp1251'))
|
f.write(''.join(code_chunks).encode('cp1251'))
|
||||||
|
|
||||||
print('casino3d.inc completely generated in CP1251!')
|
print('casino3d.inc completely generated in CP1251!')
|
||||||
|
|
@ -2,8 +2,8 @@ import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
BRAIN_DIR = Path(r"C:\Users\user\.gemini\antigravity-ide\brain\68821b0e-0e7d-4871-92bc-f142243303b2")
|
PROJECT_DIR = Path(__file__).resolve().parents[2]
|
||||||
PROJECT_DIR = Path(r"F:\покер")
|
BRAIN_DIR = PROJECT_DIR / "assets" / "sprites"
|
||||||
OUT_DIR = PROJECT_DIR / "assets" / "textures"
|
OUT_DIR = PROJECT_DIR / "assets" / "textures"
|
||||||
OUT_BIN = OUT_DIR / "casino3d.bin"
|
OUT_BIN = OUT_DIR / "casino3d.bin"
|
||||||
|
|
||||||
|
|
@ -6,7 +6,7 @@ Only transparent alpha is discarded. Black, white and gold detail is retained.
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
SIZE = 128
|
SIZE = 128
|
||||||
SLOTS = 48
|
SLOTS = 48
|
||||||
CHROMA = (255, 0, 255, 0)
|
CHROMA = (255, 0, 255, 0)
|
||||||
|
|
@ -30,7 +30,9 @@ for ch_code in range(256):
|
||||||
char_bytes.append(row_byte)
|
char_bytes.append(row_byte)
|
||||||
font_data.append(char_bytes)
|
font_data.append(char_bytes)
|
||||||
|
|
||||||
with open(r"F:\покер\font8x8.inc", "w", encoding="cp1251") as f:
|
from pathlib import Path
|
||||||
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
with open(REPO_ROOT / "font8x8.inc", "w", encoding="cp1251") as f:
|
||||||
f.write("; --- 8x8 BITMAP FONT FOR CP1251 (Generated) ---\n")
|
f.write("; --- 8x8 BITMAP FONT FOR CP1251 (Generated) ---\n")
|
||||||
f.write(".data\nALIGN 4\nfont8x8 label byte\n")
|
f.write(".data\nALIGN 4\nfont8x8 label byte\n")
|
||||||
for idx, cb in enumerate(font_data):
|
for idx, cb in enumerate(font_data):
|
||||||
|
|
@ -62,7 +62,9 @@ grid[8][23] = 1
|
||||||
grid[23][8] = 1
|
grid[23][8] = 1
|
||||||
grid[23][23] = 1
|
grid[23][23] = 1
|
||||||
|
|
||||||
with open(r"F:\покер\casino3d_data.inc", "w", encoding="cp1251") as f:
|
from pathlib import Path
|
||||||
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
with open(REPO_ROOT / "casino3d_data.inc", "w", encoding="cp1251") as f:
|
||||||
f.write("; --- CASINO 3D ENGINE DATA (Generated: Grand Open Hall) ---\n\n")
|
f.write("; --- CASINO 3D ENGINE DATA (Generated: Grand Open Hall) ---\n\n")
|
||||||
f.write("NUM_ANGLES equ 512\n")
|
f.write("NUM_ANGLES equ 512\n")
|
||||||
f.write("MAP_WIDTH equ 32\n")
|
f.write("MAP_WIDTH equ 32\n")
|
||||||
|
|
@ -2344,7 +2344,9 @@ StartCasino3D ENDP
|
||||||
include src_graphics\platform_code.inc
|
include src_graphics\platform_code.inc
|
||||||
'''
|
'''
|
||||||
|
|
||||||
with open('d:/покер/casino3d.inc', 'wb') as f:
|
from pathlib import Path
|
||||||
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
with open(REPO_ROOT / 'casino3d.inc', 'wb') as f:
|
||||||
f.write(content.strip().encode('cp1251'))
|
f.write(content.strip().encode('cp1251'))
|
||||||
|
|
||||||
print('Successfully generated unified casino3d.inc in CP1251!')
|
print('Successfully generated unified casino3d.inc in CP1251!')
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
from pathlib import Path
|
||||||
with open('d:/покер/poker.asm', 'r', encoding='cp1251') as f:
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
with open(REPO_ROOT / 'poker.asm', 'r', encoding='cp1251') as f:
|
||||||
text = f.read()
|
text = f.read()
|
||||||
|
|
||||||
# 1. Add defaultPlayerSave
|
# 1. Add defaultPlayerSave
|
||||||
|
|
@ -85,7 +86,7 @@ main ENDP
|
||||||
else:
|
else:
|
||||||
print('Error: exit_menu: not found')
|
print('Error: exit_menu: not found')
|
||||||
|
|
||||||
with open('d:/покер/poker.asm', 'wb') as f:
|
with open(REPO_ROOT / 'poker.asm', 'wb') as f:
|
||||||
f.write(text.encode('cp1251'))
|
f.write(text.encode('cp1251'))
|
||||||
|
|
||||||
print('poker.asm updated in CP1251!')
|
print('poker.asm updated in CP1251!')
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
@echo off
|
@echo off
|
||||||
title 3D Casino DOOM Engine Preview
|
title 3D Casino DOOM Engine Preview
|
||||||
cd /d "%~dp0"
|
cd /d "%~dp0..\.."
|
||||||
start "" "poker.exe"
|
start "" "poker.exe"
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
@echo off
|
@echo off
|
||||||
mode con cols=120 lines=42
|
mode con cols=120 lines=42
|
||||||
chcp 65001 >nul
|
chcp 65001 >nul
|
||||||
set "DBD_ROOT=%~dp0.."
|
set "DBD_ROOT=%~dp0..\.."
|
||||||
powershell -NoProfile -ExecutionPolicy Bypass -Command "$root=[IO.Path]::GetFullPath($env:DBD_ROOT); $ans=Join-Path $root 'assets\animations\dbd_hook.ans'; $stop=Join-Path $root 'runtime\dbd_hook.stop'; $profilePath=Join-Path $root 'runtime\anim_profile.txt'; if(Test-Path $stop){Remove-Item $stop -Force}; if(!(Test-Path $ans)){Write-Host 'dbd_hook.ans not found:' $ans; Start-Sleep -Seconds 3; exit 1}; $profile=1; if(Test-Path $profilePath){ $raw=(Get-Content -LiteralPath $profilePath -Raw -ErrorAction SilentlyContinue).Trim(); if($raw -match '^[0-2]$'){ $profile=[int]$raw } }; $step=@(1,2,3)[$profile]; $delay=80*$step; $frames=(Get-Content -LiteralPath $ans -Raw -Encoding UTF8) -split [char]12; $esc=[char]27; try{ [Console]::Write($esc+'[2J'+$esc+'[?25l'); while(!(Test-Path $stop)){ for($i=0; $i -lt $frames.Count; $i+=$step){ if(Test-Path $stop){break}; [Console]::Write($esc+'[H'); [Console]::Write($frames[$i]); Start-Sleep -Milliseconds $delay } } } finally { [Console]::Write($esc+'[0m'+$esc+'[?25h'); if(Test-Path $stop){Remove-Item $stop -Force} }"
|
powershell -NoProfile -ExecutionPolicy Bypass -Command "$root=[IO.Path]::GetFullPath($env:DBD_ROOT); $ans=Join-Path $root 'assets\animations\dbd_hook.ans'; $stop=Join-Path $root 'runtime\dbd_hook.stop'; $profilePath=Join-Path $root 'runtime\anim_profile.txt'; if(Test-Path $stop){Remove-Item $stop -Force}; if(!(Test-Path $ans)){Write-Host 'dbd_hook.ans not found:' $ans; Start-Sleep -Seconds 3; exit 1}; $profile=1; if(Test-Path $profilePath){ $raw=(Get-Content -LiteralPath $profilePath -Raw -ErrorAction SilentlyContinue).Trim(); if($raw -match '^[0-2]$'){ $profile=[int]$raw } }; $step=@(1,2,3)[$profile]; $delay=80*$step; $frames=(Get-Content -LiteralPath $ans -Raw -Encoding UTF8) -split [char]12; $esc=[char]27; try{ [Console]::Write($esc+'[2J'+$esc+'[?25l'); while(!(Test-Path $stop)){ for($i=0; $i -lt $frames.Count; $i+=$step){ if(Test-Path $stop){break}; [Console]::Write($esc+'[H'); [Console]::Write($frames[$i]); Start-Sleep -Milliseconds $delay } } } finally { [Console]::Write($esc+'[0m'+$esc+'[?25h'); if(Test-Path $stop){Remove-Item $stop -Force} }"
|
||||||
exit
|
exit
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import ctypes
|
import ctypes
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -25,7 +25,7 @@ def place_window() -> None:
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
root = Path(__file__).resolve().parent.parent
|
root = Path(__file__).resolve().parents[2]
|
||||||
path = root / "assets" / "animations" / "dbd_hook.ans"
|
path = root / "assets" / "animations" / "dbd_hook.ans"
|
||||||
stop_path = root / "runtime" / "dbd_hook.stop"
|
stop_path = root / "runtime" / "dbd_hook.stop"
|
||||||
if not path.exists():
|
if not path.exists():
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
@ -16,9 +16,13 @@ def enable_ansi() -> None:
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
root = Path(__file__).resolve().parent
|
repo_root = Path(__file__).resolve().parents[2]
|
||||||
dance_path = root / "hakari_dance.ans"
|
dance_path = repo_root / "assets" / "animations" / "hakari_dance.ans"
|
||||||
sound_path = root / "hakari_dance.wav"
|
if not dance_path.exists():
|
||||||
|
dance_path = repo_root / "hakari_dance.ans"
|
||||||
|
sound_path = repo_root / "assets" / "audio" / "hakari_dance.wav"
|
||||||
|
if not sound_path.exists():
|
||||||
|
sound_path = repo_root / "hakari_dance.wav"
|
||||||
|
|
||||||
if not dance_path.exists():
|
if not dance_path.exists():
|
||||||
print("hakari_dance.ans not found")
|
print("hakari_dance.ans not found")
|
||||||
|
|
@ -10,8 +10,10 @@ FRAME_SEPARATOR = "\f"
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
root = Path(__file__).resolve().parent
|
repo_root = Path(__file__).resolve().parents[2]
|
||||||
intro_path = root / "casino_intro.ans"
|
intro_path = repo_root / "assets" / "animations" / "casino_intro.ans"
|
||||||
|
if not intro_path.exists():
|
||||||
|
intro_path = repo_root / "casino_intro.ans"
|
||||||
if not intro_path.exists():
|
if not intro_path.exists():
|
||||||
print("casino_intro.ans not found")
|
print("casino_intro.ans not found")
|
||||||
return 1
|
return 1
|
||||||
|
|
@ -5,7 +5,7 @@ title ASSEMBLER CASINO - ACHIEVEMENT
|
||||||
setlocal EnableDelayedExpansion
|
setlocal EnableDelayedExpansion
|
||||||
cls
|
cls
|
||||||
set "ACH=Íîâîå äîñòèæåíèå"
|
set "ACH=Íîâîå äîñòèæåíèå"
|
||||||
set "ROOT=%~dp0.."
|
set "ROOT=%~dp0..\.."
|
||||||
if exist "%ROOT%\runtime\achievement.txt" set /p ACH=<"%ROOT%\runtime\achievement.txt"
|
if exist "%ROOT%\runtime\achievement.txt" set /p ACH=<"%ROOT%\runtime\achievement.txt"
|
||||||
|
|
||||||
set "RARITY=COMMON"
|
set "RARITY=COMMON"
|
||||||
42
tools/tests/build_graphics.ps1
Normal file
42
tools/tests/build_graphics.ps1
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
param([string]$MasmRoot = '')
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
$root = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
|
||||||
|
Push-Location $root
|
||||||
|
try {
|
||||||
|
$masmCandidates = @(
|
||||||
|
$MasmRoot,
|
||||||
|
'D:\MASM32\masm32',
|
||||||
|
'C:\masm32',
|
||||||
|
'F:\MASM32\masm32'
|
||||||
|
) | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }
|
||||||
|
|
||||||
|
$foundMasm = $null
|
||||||
|
foreach ($cand in $masmCandidates) {
|
||||||
|
try {
|
||||||
|
$drive = [System.IO.Path]::GetPathRoot($cand).TrimEnd('\', '/')
|
||||||
|
if ($drive -and -not (Test-Path -LiteralPath $drive)) { continue }
|
||||||
|
$ml = Join-Path $cand 'bin\ml.exe'
|
||||||
|
if (Test-Path -LiteralPath $ml) {
|
||||||
|
$foundMasm = $cand
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($foundMasm) {
|
||||||
|
& "$foundMasm\bin\ml.exe" /c /coff /Cp /nologo /I. /Fobuild\graphics\poker.obj poker.asm
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw 'MASM assembly failed' }
|
||||||
|
if (Test-Path -LiteralPath 'build\casino_icon.res') {
|
||||||
|
& "$foundMasm\bin\link.exe" /nologo /SUBSYSTEM:WINDOWS /RELEASE /VERSION:5.0 "/LIBPATH:$foundMasm\lib" /OUT:build\graphics\poker.exe build\graphics\poker.obj build\casino_icon.res kernel32.lib winmm.lib user32.lib ws2_32.lib gdi32.lib
|
||||||
|
} else {
|
||||||
|
& "$foundMasm\bin\link.exe" /nologo /SUBSYSTEM:WINDOWS /RELEASE /VERSION:5.0 "/LIBPATH:$foundMasm\lib" /OUT:build\graphics\poker.exe build\graphics\poker.obj kernel32.lib winmm.lib user32.lib ws2_32.lib gdi32.lib
|
||||||
|
}
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw 'Link failed' }
|
||||||
|
} else {
|
||||||
|
& cmd.exe /c build.bat
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw 'Build via build.bat failed' }
|
||||||
|
}
|
||||||
|
Write-Output 'Built build\graphics\poker.exe. Publish only after verification.'
|
||||||
|
} finally {
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
param(
|
param(
|
||||||
[string]$Root = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
|
[string]$Root = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
@ -22,14 +22,25 @@ function Require-File($relative) {
|
||||||
|
|
||||||
Push-Location $Root
|
Push-Location $Root
|
||||||
try {
|
try {
|
||||||
Require-File 'PokerGameSetup.exe'
|
if (Test-Path -LiteralPath (Join-Path $Root 'PokerGameSetup.exe')) {
|
||||||
Require-File 'Assembler Casino.exe'
|
Require-File 'PokerGameSetup.exe'
|
||||||
Require-File 'Uninstall Assembler Casino.exe'
|
}
|
||||||
|
if (Test-Path -LiteralPath (Join-Path $Root 'dist\Assembler Casino.exe')) {
|
||||||
|
Require-File 'dist\Assembler Casino.exe'
|
||||||
|
} else {
|
||||||
|
Require-File 'Assembler Casino.exe'
|
||||||
|
}
|
||||||
|
if (Test-Path -LiteralPath (Join-Path $Root 'dist\Uninstall Assembler Casino.exe')) {
|
||||||
|
Require-File 'dist\Uninstall Assembler Casino.exe'
|
||||||
|
} else {
|
||||||
|
Require-File 'Uninstall Assembler Casino.exe'
|
||||||
|
}
|
||||||
Require-File 'bin\poker.exe'
|
Require-File 'bin\poker.exe'
|
||||||
Require-File 'assets\icons\casino.ico'
|
Require-File 'assets\icons\casino.ico'
|
||||||
Require-File 'assets\animations\hakari_dance.ans'
|
Require-File 'assets\animations\hakari_dance.ans'
|
||||||
Require-File 'assets\animations\dbd_hook.ans'
|
Require-File 'assets\animations\dbd_hook.ans'
|
||||||
Require-File 'tools\preview_dbd_hook.bat'
|
$dbdRelative = if (Test-Path -LiteralPath (Join-Path $Root 'tools\previews\preview_dbd_hook.bat')) { 'tools\previews\preview_dbd_hook.bat' } else { 'tools\preview_dbd_hook.bat' }
|
||||||
|
Require-File $dbdRelative
|
||||||
Require-File 'docs\README_RELEASE.txt'
|
Require-File 'docs\README_RELEASE.txt'
|
||||||
Require-File 'docs\RELEASE_CHECKLIST.txt'
|
Require-File 'docs\RELEASE_CHECKLIST.txt'
|
||||||
Require-File 'docs\KNOWN_LIMITATIONS.txt'
|
Require-File 'docs\KNOWN_LIMITATIONS.txt'
|
||||||
|
|
@ -49,7 +60,7 @@ try {
|
||||||
}
|
}
|
||||||
Pass 'MAMBO animation files are removed from assets'
|
Pass 'MAMBO animation files are removed from assets'
|
||||||
|
|
||||||
$dbdBat = Get-Content -LiteralPath (Join-Path $Root 'tools\preview_dbd_hook.bat') -Raw
|
$dbdBat = Get-Content -LiteralPath (Join-Path $Root $dbdRelative) -Raw
|
||||||
if ($dbdBat -match 'Clear-Host') {
|
if ($dbdBat -match 'Clear-Host') {
|
||||||
Fail 'DBD helper still uses Clear-Host'
|
Fail 'DBD helper still uses Clear-Host'
|
||||||
}
|
}
|
||||||
|
|
@ -127,86 +138,90 @@ try {
|
||||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||||
|
|
||||||
$setupPath = Join-Path $Root 'PokerGameSetup.exe'
|
$setupPath = Join-Path $Root 'PokerGameSetup.exe'
|
||||||
$fs = [IO.File]::OpenRead($setupPath)
|
if (Test-Path -LiteralPath $setupPath) {
|
||||||
try {
|
$fs = [IO.File]::OpenRead($setupPath)
|
||||||
$head = New-Object byte[] ([Math]::Min(2097152, $fs.Length))
|
try {
|
||||||
[void]$fs.Read($head, 0, $head.Length)
|
$head = New-Object byte[] ([Math]::Min(2097152, $fs.Length))
|
||||||
$marker = [Text.Encoding]::UTF8.GetBytes('<<POKER_GAME_GUI_PAYLOAD_ZIP>>')
|
[void]$fs.Read($head, 0, $head.Length)
|
||||||
$idx = -1
|
$marker = [Text.Encoding]::UTF8.GetBytes('<<POKER_GAME_GUI_PAYLOAD_ZIP>>')
|
||||||
for ($i = 0; $i -le $head.Length - $marker.Length; $i++) {
|
$idx = -1
|
||||||
if ($head[$i] -ne $marker[0]) { continue }
|
for ($i = 0; $i -le $head.Length - $marker.Length; $i++) {
|
||||||
$ok = $true
|
if ($head[$i] -ne $marker[0]) { continue }
|
||||||
for ($j = 1; $j -lt $marker.Length; $j++) {
|
$ok = $true
|
||||||
if ($head[$i + $j] -ne $marker[$j]) { $ok = $false; break }
|
for ($j = 1; $j -lt $marker.Length; $j++) {
|
||||||
|
if ($head[$i + $j] -ne $marker[$j]) { $ok = $false; break }
|
||||||
|
}
|
||||||
|
if ($ok) { $idx = $i; break }
|
||||||
}
|
}
|
||||||
if ($ok) { $idx = $i; break }
|
if ($idx -lt 0) { Fail 'Installer payload marker not found' }
|
||||||
|
|
||||||
|
$fs.Position = $idx + $marker.Length
|
||||||
|
$zipBytes = New-Object byte[] ($fs.Length - $fs.Position)
|
||||||
|
[void]$fs.Read($zipBytes, 0, $zipBytes.Length)
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$fs.Dispose()
|
||||||
}
|
}
|
||||||
if ($idx -lt 0) { Fail 'Installer payload marker not found' }
|
|
||||||
|
|
||||||
$fs.Position = $idx + $marker.Length
|
$ms = New-Object IO.MemoryStream(,$zipBytes)
|
||||||
$zipBytes = New-Object byte[] ($fs.Length - $fs.Position)
|
$zip = New-Object IO.Compression.ZipArchive($ms, [IO.Compression.ZipArchiveMode]::Read)
|
||||||
[void]$fs.Read($zipBytes, 0, $zipBytes.Length)
|
try {
|
||||||
}
|
$names = @($zip.Entries | ForEach-Object FullName)
|
||||||
finally {
|
foreach ($entry in @(
|
||||||
$fs.Dispose()
|
'Assembler Casino.exe',
|
||||||
}
|
'Uninstall Assembler Casino.exe',
|
||||||
|
'bin/poker.exe',
|
||||||
$ms = New-Object IO.MemoryStream(,$zipBytes)
|
'assets/icons/casino.ico',
|
||||||
$zip = New-Object IO.Compression.ZipArchive($ms, [IO.Compression.ZipArchiveMode]::Read)
|
'tools/preview_dbd_hook.bat',
|
||||||
try {
|
'tools/release_smoke_check.ps1',
|
||||||
$names = @($zip.Entries | ForEach-Object FullName)
|
'docs/README_RELEASE.txt',
|
||||||
foreach ($entry in @(
|
'docs/RELEASE_CHECKLIST.txt',
|
||||||
'Assembler Casino.exe',
|
'docs/KNOWN_LIMITATIONS.txt',
|
||||||
'Uninstall Assembler Casino.exe',
|
'docs/SECURITY_NOTES.txt',
|
||||||
'bin/poker.exe',
|
'docs/ROADMAP.txt',
|
||||||
'assets/icons/casino.ico',
|
'docs/ONLINE_RADMIN.txt'
|
||||||
'tools/preview_dbd_hook.bat',
|
)) {
|
||||||
'tools/release_smoke_check.ps1',
|
if ($names -notcontains $entry) {
|
||||||
'docs/README_RELEASE.txt',
|
Fail "Installer payload missing: $entry"
|
||||||
'docs/RELEASE_CHECKLIST.txt',
|
}
|
||||||
'docs/KNOWN_LIMITATIONS.txt',
|
|
||||||
'docs/SECURITY_NOTES.txt',
|
|
||||||
'docs/ROADMAP.txt',
|
|
||||||
'docs/ONLINE_RADMIN.txt'
|
|
||||||
)) {
|
|
||||||
if ($names -notcontains $entry) {
|
|
||||||
Fail "Installer payload missing: $entry"
|
|
||||||
}
|
}
|
||||||
}
|
if ($names -contains 'Assembler Casino.bat') {
|
||||||
if ($names -contains 'Assembler Casino.bat') {
|
Fail 'Installer payload still contains old Assembler Casino.bat'
|
||||||
Fail 'Installer payload still contains old Assembler Casino.bat'
|
|
||||||
}
|
|
||||||
if ($names | Where-Object { $_ -like 'tools/generated_frames/*' }) {
|
|
||||||
Fail 'Installer payload contains generated preview frames/tools'
|
|
||||||
}
|
|
||||||
foreach ($entry in @(
|
|
||||||
'assets/animations/mambo1.ans',
|
|
||||||
'assets/animations/mambo2.ans',
|
|
||||||
'assets/animations/mambo3.ans',
|
|
||||||
'assets/animations/mambo4.ans'
|
|
||||||
)) {
|
|
||||||
if ($names -contains $entry) {
|
|
||||||
Fail "Installer payload still contains removed MAMBO animation: $entry"
|
|
||||||
}
|
}
|
||||||
|
if ($names | Where-Object { $_ -like 'tools/generated_frames/*' }) {
|
||||||
|
Fail 'Installer payload contains generated preview frames/tools'
|
||||||
|
}
|
||||||
|
foreach ($entry in @(
|
||||||
|
'assets/animations/mambo1.ans',
|
||||||
|
'assets/animations/mambo2.ans',
|
||||||
|
'assets/animations/mambo3.ans',
|
||||||
|
'assets/animations/mambo4.ans'
|
||||||
|
)) {
|
||||||
|
if ($names -contains $entry) {
|
||||||
|
Fail "Installer payload still contains removed MAMBO animation: $entry"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Pass "Installer payload OK ($($names.Count) files)"
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$zip.Dispose()
|
||||||
|
$ms.Dispose()
|
||||||
}
|
}
|
||||||
Pass "Installer payload OK ($($names.Count) files)"
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
$zip.Dispose()
|
|
||||||
$ms.Dispose()
|
|
||||||
}
|
|
||||||
|
|
||||||
$sha = [Security.Cryptography.SHA256]::Create()
|
$sha = [Security.Cryptography.SHA256]::Create()
|
||||||
try {
|
try {
|
||||||
$actualHash = [BitConverter]::ToString($sha.ComputeHash($zipBytes)).Replace('-', '').ToUpperInvariant()
|
$actualHash = [BitConverter]::ToString($sha.ComputeHash($zipBytes)).Replace('-', '').ToUpperInvariant()
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$sha.Dispose()
|
||||||
|
}
|
||||||
|
if ($actualHash -ne $expectedHash) {
|
||||||
|
Fail "Installer payload SHA-256 mismatch. Expected $expectedHash, actual $actualHash"
|
||||||
|
}
|
||||||
|
Pass 'Installer payload SHA-256 matches embedded hash'
|
||||||
|
} else {
|
||||||
|
Pass 'PokerGameSetup.exe not present (skipping installer binary payload check)'
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
$sha.Dispose()
|
|
||||||
}
|
|
||||||
if ($actualHash -ne $expectedHash) {
|
|
||||||
Fail "Installer payload SHA-256 mismatch. Expected $expectedHash, actual $actualHash"
|
|
||||||
}
|
|
||||||
Pass 'Installer payload SHA-256 matches embedded hash'
|
|
||||||
|
|
||||||
Write-Host ''
|
Write-Host ''
|
||||||
Write-Host 'Release smoke check passed.' -ForegroundColor Cyan
|
Write-Host 'Release smoke check passed.' -ForegroundColor Cyan
|
||||||
|
|
@ -7,13 +7,16 @@ SCREEN_W = 640
|
||||||
SCREEN_H = 480
|
SCREEN_H = 480
|
||||||
HALF_W = 320
|
HALF_W = 320
|
||||||
HALF_H = 240
|
HALF_H = 240
|
||||||
|
from pathlib import Path
|
||||||
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
|
||||||
FP_1 = 65536
|
FP_1 = 65536
|
||||||
FP_HALF = 32768
|
FP_HALF = 32768
|
||||||
MAP_WIDTH = 32
|
MAP_WIDTH = 32
|
||||||
MAP_HEIGHT = 32
|
MAP_HEIGHT = 32
|
||||||
|
|
||||||
# Load map
|
# Load map
|
||||||
with open('d:/покер/casino3d_data.inc', 'r', encoding='latin1') as f:
|
with open(REPO_ROOT / 'casino3d_data.inc', 'r', encoding='latin1') as f:
|
||||||
text = f.read()
|
text = f.read()
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
@ -34,7 +37,7 @@ for l in map_lines:
|
||||||
casinoMap.extend(vals)
|
casinoMap.extend(vals)
|
||||||
|
|
||||||
# Load textures
|
# Load textures
|
||||||
tex_raw = open('d:/покер/assets/textures/casino3d-hd.bin', 'rb').read()
|
tex_raw = open(REPO_ROOT / 'assets' / 'textures' / 'casino3d-hd.bin', 'rb').read()
|
||||||
slot_size = 128 * 128 * 4
|
slot_size = 128 * 128 * 4
|
||||||
|
|
||||||
def get_tex_pixel(slot, tx, ty):
|
def get_tex_pixel(slot, tx, ty):
|
||||||
|
|
@ -266,5 +269,6 @@ for s in sprites:
|
||||||
# Save image
|
# Save image
|
||||||
img = Image.new('RGB', (SCREEN_W, SCREEN_H))
|
img = Image.new('RGB', (SCREEN_W, SCREEN_H))
|
||||||
img.putdata(screen_pixels)
|
img.putdata(screen_pixels)
|
||||||
img.save('d:/покер/render_view.png')
|
out_path = REPO_ROOT / 'docs' / 'render_view.png'
|
||||||
print('render_view.png saved successfully!')
|
img.save(out_path)
|
||||||
|
print(f'{out_path} saved successfully!')
|
||||||
Loading…
Add table
Reference in a new issue