refactor: reorganize project structure, isolate tools and portable builds, clean root directory

This commit is contained in:
Игорь Федосеев 2026-09-30 19:42:41 +03:00
parent e6bf8d8edb
commit ba8a1ef0b8
41 changed files with 461 additions and 133 deletions

5
.gitignore vendored
View file

@ -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

View file

@ -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
View file

@ -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.

View file

@ -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

View file

@ -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

Binary file not shown.

View file

@ -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)

View file

@ -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
View 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). |

View file

@ -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
}

View file

@ -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!')

View file

@ -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"

View file

@ -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)

View file

@ -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):

View file

@ -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")

View file

@ -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!')

View file

@ -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!')

View file

@ -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"

View file

@ -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

View file

@ -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():

View file

@ -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")

View file

@ -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

View file

@ -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"

View 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
}

View file

@ -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

View file

@ -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!')