feat: add rooftop city and optimize native terrace rendering
Add rooftop elevator, lounge, volumetric city, river and animated traffic. Prune invisible mesh faces, clip CPU surfaces, streamline compositing and add automatic/F8 roof quality profiles with renderer diagnostics. Include dartboard/reticle improvements, tracked fortune orb numerals and fate-session visuals, native regression tests, compatible jukebox IDs and updated shipping executables.
BIN
assets/animations/darts/board-v2.bin
Normal file
BIN
assets/animations/fortune/orb-numerals-v1.bin
Normal file
BIN
assets/animations/rooftop/city-night-v1.bin
Normal file
BIN
assets/animations/rooftop/city-v1.bin
Normal file
BIN
assets/animations/rooftop/details-v1.bin
Normal file
BIN
assets/animations/rooftop/lighting-v1.bin
Normal file
BIN
assets/animations/rooftop/materials-v1.bin
Normal file
BIN
assets/animations/rooftop/mesh-boat-v1.bin
Normal file
BIN
assets/animations/rooftop/mesh-car-v1.bin
Normal file
BIN
assets/animations/rooftop/mesh-city-v1.bin
Normal file
BIN
assets/animations/rooftop/night-v1.bin
Normal file
BIN
assets/animations/rooftop/panorama-v1.bin
Normal file
BIN
assets/animations/rooftop/rail-hands-v1.bin
Normal file
BIN
assets/sprites/darts/board-v2.png
Normal file
|
After Width: | Height: | Size: 247 KiB |
|
|
@ -78,3 +78,7 @@ outside the image.
|
||||||
|
|
||||||
Deterministically generated exact 20-sector sports geometry, not AI artwork.
|
Deterministically generated exact 20-sector sports geometry, not AI artwork.
|
||||||
The sector order and scoring ring radii are shared with native scoring tests.
|
The sector order and scoring ring radii are shared with native scoring tests.
|
||||||
|
|
||||||
|
`board-v2.png` is the deterministic readability revision: larger, brighter
|
||||||
|
numerals and cleaner wires, drawn at 2x then reduced to the same 512px canvas.
|
||||||
|
It uses no image-generation model and does not change the board's world size.
|
||||||
|
|
|
||||||
BIN
assets/sprites/fortune/orb-numerals-v1.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
105
assets/sprites/fortune/orb-tracking-v1.json
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
{
|
||||||
|
"canvas": [
|
||||||
|
192,
|
||||||
|
192
|
||||||
|
],
|
||||||
|
"font": "Cambria Regular, rasterized at 4x; no font needed at runtime",
|
||||||
|
"frames": [
|
||||||
|
{
|
||||||
|
"cx": 107.0,
|
||||||
|
"cy": 85.60757294157031,
|
||||||
|
"rx": 72.68997989989911,
|
||||||
|
"ry": 74.69516621989159
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cx": 95.5,
|
||||||
|
"cy": 85.76519319889574,
|
||||||
|
"rx": 72.51196201438557,
|
||||||
|
"ry": 74.89806065214609
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cx": 95.5,
|
||||||
|
"cy": 85.71241583054908,
|
||||||
|
"rx": 72.69942242784161,
|
||||||
|
"ry": 74.83168393851604
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cx": 84.0,
|
||||||
|
"cy": 85.72005975738783,
|
||||||
|
"rx": 72.63601648302654,
|
||||||
|
"ry": 74.68751926061978
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cx": 106.5,
|
||||||
|
"cy": 82.20860810943547,
|
||||||
|
"rx": 72.87681495588859,
|
||||||
|
"ry": 74.48180234847793
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cx": 95.0,
|
||||||
|
"cy": 82.2684885845598,
|
||||||
|
"rx": 73.25393481375772,
|
||||||
|
"ry": 74.62519501114646
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cx": 95.0,
|
||||||
|
"cy": 82.35337687892542,
|
||||||
|
"rx": 73.02811219141157,
|
||||||
|
"ry": 74.66203440932597
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cx": 84.0,
|
||||||
|
"cy": 82.42039157417511,
|
||||||
|
"rx": 72.80858646484103,
|
||||||
|
"ry": 74.62208876727115
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cx": 106.5,
|
||||||
|
"cy": 81.72901899211435,
|
||||||
|
"rx": 74.34475334746573,
|
||||||
|
"ry": 73.78037632992753
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cx": 95.5,
|
||||||
|
"cy": 81.63668560751485,
|
||||||
|
"rx": 75.06807641776177,
|
||||||
|
"ry": 73.48706340594615
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cx": 95.5,
|
||||||
|
"cy": 81.67982777738753,
|
||||||
|
"rx": 75.12648691865994,
|
||||||
|
"ry": 73.49674962974022
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cx": 84.5,
|
||||||
|
"cy": 81.57452731727243,
|
||||||
|
"rx": 74.48750227516855,
|
||||||
|
"ry": 73.69652904057105
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cx": 106.0,
|
||||||
|
"cy": 72.23134647099609,
|
||||||
|
"rx": 75.09606781800167,
|
||||||
|
"ry": 75.52834001598418
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cx": 96.0,
|
||||||
|
"cy": 72.31864303902333,
|
||||||
|
"rx": 74.79155274675983,
|
||||||
|
"ry": 75.30939853900956
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cx": 94.5,
|
||||||
|
"cy": 72.10115208001082,
|
||||||
|
"rx": 74.92026723097523,
|
||||||
|
"ry": 75.46485386910284
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cx": 85.0,
|
||||||
|
"cy": 72.21051327527425,
|
||||||
|
"rx": 74.61593591942703,
|
||||||
|
"ry": 75.5076844695196
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
assets/sprites/rooftop/chair-views-v1.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
assets/sprites/rooftop/city-facades-v1.png
Normal file
|
After Width: | Height: | Size: 3 MiB |
BIN
assets/sprites/rooftop/cutouts-v1.png
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
6923
assets/sprites/rooftop/district-map-v1.json
Normal file
BIN
assets/sprites/rooftop/materials-v1.png
Normal file
|
After Width: | Height: | Size: 3.5 MiB |
6665
assets/sprites/rooftop/mesh-v1.json
Normal file
BIN
assets/sprites/rooftop/modern-facades-v1.png
Normal file
|
After Width: | Height: | Size: 2.8 MiB |
BIN
assets/sprites/rooftop/night-sky-v1.png
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
45
assets/sprites/rooftop/packed-v1.json
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"panorama": [
|
||||||
|
512,
|
||||||
|
512,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"materials": [
|
||||||
|
256,
|
||||||
|
256,
|
||||||
|
8
|
||||||
|
],
|
||||||
|
"details": [
|
||||||
|
256,
|
||||||
|
256,
|
||||||
|
15
|
||||||
|
],
|
||||||
|
"city": [
|
||||||
|
512,
|
||||||
|
512,
|
||||||
|
22
|
||||||
|
],
|
||||||
|
"city-night": [
|
||||||
|
512,
|
||||||
|
512,
|
||||||
|
22
|
||||||
|
],
|
||||||
|
"night": [
|
||||||
|
512,
|
||||||
|
512,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"rail-hands": [
|
||||||
|
640,
|
||||||
|
320,
|
||||||
|
32
|
||||||
|
],
|
||||||
|
"lighting": [
|
||||||
|
512,
|
||||||
|
512,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"city_renderer": "world-space MASM geometry; sky only is raster",
|
||||||
|
"source": "Built-in image generation; runtime geometry and interaction are assembly-only",
|
||||||
|
"reference": "https://www.loftprojectetagi.ru/visitors/krysha/"
|
||||||
|
}
|
||||||
BIN
assets/sprites/rooftop/panels-v1.png
Normal file
|
After Width: | Height: | Size: 3.1 MiB |
BIN
assets/sprites/rooftop/panorama-v1.png
Normal file
|
After Width: | Height: | Size: 2.4 MiB |
BIN
assets/sprites/rooftop/panorama-v2.png
Normal file
|
After Width: | Height: | Size: 2.4 MiB |
27
assets/sprites/rooftop/prompts-v2.md
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Rooftop City Source Art
|
||||||
|
|
||||||
|
Generated with the built-in image generation tool. The selected PNG originals
|
||||||
|
are preserved in this directory; the offline packer prepares runtime atlases.
|
||||||
|
The city itself is MASM world-space geometry, not a generated city background.
|
||||||
|
|
||||||
|
## Prompt Set
|
||||||
|
|
||||||
|
- `rail-hands-v1.png`: transparent eight-pose sprite sheet, two anatomical hands
|
||||||
|
and complete forearms reaching forward and resting naturally on a low rooftop
|
||||||
|
handrail, first-person view, dark sleeves, consistent camera and anatomy.
|
||||||
|
- `city-facades-v1.png`: eight detailed, straight-on Petersburg-inspired
|
||||||
|
classical building facades, varied pastel masonry, carved window surrounds,
|
||||||
|
cornices and realistic windows; no perspective, sky or ground.
|
||||||
|
- `modern-facades-v1.png`: varied straight-on contemporary glass, brick,
|
||||||
|
townhouse and civic building facades, suitable for wrapping real geometry.
|
||||||
|
- `roof-zinc-v1.png`: detailed weathered blue-grey standing-seam zinc roof
|
||||||
|
surface, evenly lit, seamless material texture, no building silhouette.
|
||||||
|
- `sunset-sky-v1.png`: panoramic sunset sky with fine pink and warm cloud
|
||||||
|
streaks fading into cool blue; no buildings, landscape or city silhouette.
|
||||||
|
- `night-sky-v1.png`: panoramic deep night sky with subtle clouds and stars;
|
||||||
|
no buildings, landscape or city silhouette.
|
||||||
|
|
||||||
|
These record the asset specifications. The generated images are originals,
|
||||||
|
not an exact reconstruction of any real venue or skyline. Alpha cleanup,
|
||||||
|
optical-flow in-betweens, window masks, light maps and mesh generation are
|
||||||
|
deterministic offline processing; no image service is used by the game.
|
||||||
BIN
assets/sprites/rooftop/rail-hands-v1.png
Normal file
|
After Width: | Height: | Size: 946 KiB |
BIN
assets/sprites/rooftop/roof-zinc-v1.png
Normal file
|
After Width: | Height: | Size: 3.2 MiB |
BIN
assets/sprites/rooftop/sofa-views-v1.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
assets/sprites/rooftop/sunset-sky-v1.png
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
bin/poker.exe
|
|
@ -8,7 +8,7 @@ namespace AssemblerCasinoLauncher
|
||||||
{
|
{
|
||||||
static class Program
|
static class Program
|
||||||
{
|
{
|
||||||
const string ExpectedPokerSha256 = "07D474A0223390E7AC4F4F779818D77CC2DAE5123F4BDB0F72DD975473267310";
|
const string ExpectedPokerSha256 = "63C04B59D74772621A7563EA70DFA6764C60684459EE7D046AF30B555A01FF15";
|
||||||
|
|
||||||
[STAThread]
|
[STAThread]
|
||||||
static void Main()
|
static void Main()
|
||||||
|
|
|
||||||
|
|
@ -5350,10 +5350,14 @@ check_walk_mode:
|
||||||
call UpdateInteriorTravel3D
|
call UpdateInteriorTravel3D
|
||||||
call UpdateInteriorEye3D
|
call UpdateInteriorEye3D
|
||||||
call UpdateCamera3D
|
call UpdateCamera3D
|
||||||
|
; The roof owns all planes/depth; an indoor prepass would be discarded.
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
je walk_world_ready
|
||||||
call RenderCeilingAndFloor
|
call RenderCeilingAndFloor
|
||||||
call RenderWalls
|
call RenderWalls
|
||||||
call PrepareCityDepth3D
|
call PrepareCityDepth3D
|
||||||
call RenderSprites
|
call RenderSprites
|
||||||
|
walk_world_ready:
|
||||||
call RenderHall3D
|
call RenderHall3D
|
||||||
call RenderHUD
|
call RenderHUD
|
||||||
call RenderMinimap
|
call RenderMinimap
|
||||||
|
|
|
||||||
BIN
dist/Assembler Casino.exe
vendored
|
|
@ -31,8 +31,12 @@ required by the game.
|
||||||
|
|
||||||
The throwing line is 2700 board millimetres from the target. The initial lens
|
The throwing line is 2700 board millimetres from the target. The initial lens
|
||||||
is adjusted so the board is only about 7 percent smaller on screen than the
|
is adjusted so the board is only about 7 percent smaller on screen than the
|
||||||
previous 2370mm/900px view. Its original 512px texture and scoring geometry are
|
previous 2370mm/900px view. Texture resolution and scoring geometry are preserved.
|
||||||
unchanged. Max watches the same moving aim point for a short release window;
|
The v2 board keeps the same physical bounds and 512px pack dimensions,
|
||||||
|
but uses larger high-contrast numerals, supersampled wires and lower grain.
|
||||||
|
The reticle is a 7x7 footprint containing only nine one-pixel marks, with no thick
|
||||||
|
outline. Individual marks adapt to bright/dark sectors for readability.
|
||||||
|
Max watches the same moving aim point for a short release window;
|
||||||
he does not reroll a hit or bypass the sway.
|
he does not reroll a hit or bypass the sway.
|
||||||
|
|
||||||
The independent
|
The independent
|
||||||
|
|
|
||||||
|
|
@ -25,22 +25,41 @@ steps after stalls. No neural worker or algorithmic reading generator is called.
|
||||||
|
|
||||||
## Crystal Ball
|
## Crystal Ball
|
||||||
|
|
||||||
The second selection raises a crystal ball and animates gloved hands with swirling
|
The second selection is a fictional, theatrical student-themed lottery, separate
|
||||||
blue mist. It ends with an explicit unavailable-result line. There is no real
|
from tarot and not an assessment of actual academic merit. The form asks for a
|
||||||
student grading, inference of merit, identity form or automated academic decision.
|
first name, surname, birth date (DD.MM.YYYY), group and inclusive score bounds
|
||||||
Again replays the visual sequence. This limitation is deliberate, not a hidden
|
from 0 to 100. Tab cycles fields, clicking focuses one, Backspace edits, and
|
||||||
random grade presented as a judgement.
|
Enter or the summon button submits. Empty fields, invalid calendar dates
|
||||||
|
(including leap years), reversed bounds and scores above 100 are rejected.
|
||||||
|
|
||||||
|
Identity fields only dress the scene: they never seed or weight the draw. One
|
||||||
|
native random draw is committed on valid submission. The ball rises for 1.4 s,
|
||||||
|
hands circle through 32 poses with 16 mist frames for 5 s, then a glowing number
|
||||||
|
appears inside the ball. Short typewriter speech accompanies the stages. The
|
||||||
|
result fades into view and stays readable while the identity and chosen bounds
|
||||||
|
remain at the bottom. Renders, duplicate submits and clicks during the ritual
|
||||||
|
cannot reroll. After the reveal, Edit returns to the filled form for another
|
||||||
|
session. No network, inference worker, profile or bankroll changes are involved.
|
||||||
|
Fields are kept only in session memory and cleared on exit; nothing is saved.
|
||||||
|
|
||||||
|
The number uses baked, antialiased Cambria numeral sprites with translucent blue
|
||||||
|
glow, not enlarged 3x5 block digits. Each of the 16 mist frames has its own measured
|
||||||
|
glass-centre anchor, excluding the pedestal. One assembly resolver chooses both
|
||||||
|
the ball frame and the matching number position, including the rising movement.
|
||||||
|
Numerals stay at a constant size and the fog remains visible through their glow.
|
||||||
|
The random draw and its probabilities are unchanged; identity never biases it.
|
||||||
|
|
||||||
## Assets
|
## Assets
|
||||||
|
|
||||||
Generated source art and production prompts: `assets/sprites/fortune/`.
|
Generated source art and production prompts: `assets/sprites/fortune/`.
|
||||||
Offline packer: `tools/generators/pack_fortune_session.py`.
|
Offline packers: `tools/generators/pack_fortune_session.py` and then
|
||||||
|
`tools/generators/pack_fortune_orb.py` (tracking metadata and numeral sprites).
|
||||||
Runtime packs: `assets/animations/fortune/` (ANM1 format).
|
Runtime packs: `assets/animations/fortune/` (ANM1 format).
|
||||||
|
|
||||||
Forty authored poses are arranged on one shared anchored 8x5 sheet. Shared-canvas
|
Forty authored poses are arranged on one shared anchored 8x5 sheet. Shared-canvas
|
||||||
in-betweens yield 64 shuffle, 32 deal, 32 gesture and 32 orb-hand frames. Sixteen
|
in-betweens yield 64 shuffle, 32 deal, 32 gesture and 32 orb-hand frames. Sixteen
|
||||||
mist frames, 44 oriented card faces, a back and a 640x480 room complete the scene.
|
mist frames, 44 oriented card faces, a back and a 640x480 room complete the scene.
|
||||||
Art loads only when seated and all seven packs are freed on exit/shutdown. The
|
Art loads only when seated and all eight packs are freed on exit/shutdown. The
|
||||||
seated view is independent of the walking room's existing asset packs and map.
|
seated view is independent of the walking room's existing asset packs and map.
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
@ -48,11 +67,17 @@ seated view is independent of the walking room's existing asset packs and map.
|
||||||
Run `C:/Python314/python.exe tools/tests/check_hall_expansion.py` after packing.
|
Run `C:/Python314/python.exe tools/tests/check_hall_expansion.py` after packing.
|
||||||
The fresh native x86 harness exercises real WM_CHAR input, length/backspace,
|
The fresh native x86 harness exercises real WM_CHAR input, length/backspace,
|
||||||
empty/double submission, all stage transitions, card uniqueness, speech growth,
|
empty/double submission, all stage transitions, card uniqueness, speech growth,
|
||||||
question persistence, crystal-ball stages, exit during animation, asset cleanup
|
question persistence, crystal-ball form validation, inclusive draws, fixed bounds,
|
||||||
|
input locking, duplicate submission, crystal-ball stages, exit during animation, asset cleanup
|
||||||
and unchanged player position/bank. It writes actual framebuffer BMP/PNG captures
|
and unchanged player position/bank. It writes actual framebuffer BMP/PNG captures
|
||||||
and a 64-frame shuffle GIF under `build/hall-expansion/`. Python additionally checks
|
and a 64-frame shuffle GIF under `build/hall-expansion/`. Python additionally checks
|
||||||
native-frame differences, question pixels, pack integrity and reversed artwork.
|
native-frame differences, question pixels, pack integrity and reversed artwork.
|
||||||
`--parity` checks these tested procedures against the shipping game object.
|
`--parity` checks these tested procedures against the shipping game object.
|
||||||
|
The orb regression captures each of the 16 native frames twice, with and without
|
||||||
|
the number. Pixel differences must stay centred on that frame's glass sphere;
|
||||||
|
this also checks that opacity is restored and the numeral pack is freed on exit.
|
||||||
|
`--prove-fate-anchor-regression` deliberately restores the old fixed coordinates
|
||||||
|
in a test-only module and must fail the native tracking assertions.
|
||||||
|
|
||||||
The old multi-gigabyte neural ZIP is not rebuilt by this feature. Distributions
|
The old multi-gigabyte neural ZIP is not rebuilt by this feature. Distributions
|
||||||
must include the new `assets/animations/fortune/` directory with the updated game.
|
must include the new `assets/animations/fortune/` directory with the updated game.
|
||||||
|
|
|
||||||
123
docs/ROOFTOP.md
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
# Rooftop Lounge "Vysota"
|
||||||
|
|
||||||
|
The terrace is an assembly-only walkable hall level (`HALL_ROOF = 4`), reached
|
||||||
|
by a real elevator cabin near the north wall to the right of the cabaret.
|
||||||
|
Existing games, basement stairs, scratch tickets and fortune room stay in place.
|
||||||
|
|
||||||
|
## Travel
|
||||||
|
|
||||||
|
Use E at the exterior call panel, then walk into the open cabin using the normal
|
||||||
|
movement keys. The inside panel offers the roof or the main hall depending on
|
||||||
|
the current landing. E starts a trip only when the player is fully inside.
|
||||||
|
Doors physically slide apart into projecting pockets. Movement is blocked during
|
||||||
|
closing/travel, while looking around remains possible. After one second of
|
||||||
|
closing and 3.2 seconds of travel the destination changes, doors open, and the
|
||||||
|
player walks out. Position, angle and standing height do not drift during travel.
|
||||||
|
|
||||||
|
An idle open door closes after 2.8 seconds away from the elevator. It reverses
|
||||||
|
if the player re-enters its approach, rather than shutting through them. Arrival
|
||||||
|
keeps the cabin coordinates and opens the other landing; there is no forced
|
||||||
|
camera path or automatic walking. The illuminated physical indicator changes
|
||||||
|
during travel and shows `1` or `R` at the landings.
|
||||||
|
|
||||||
|
## Terrace
|
||||||
|
|
||||||
|
- A fully volumetric Petersburg-inspired city, seen from a sixty-metre tower.
|
||||||
|
Only the sky is a painted texture; buildings, streets, roofs, parks, canal,
|
||||||
|
bridges, monuments, cars and boats are real world-space geometry.
|
||||||
|
- Finite HD decking, low railings and an open sky, rather than an indoor ceiling
|
||||||
|
or a floor extending to infinity beyond the roof edge.
|
||||||
|
- Three three-seat sofas, four armchairs, three bar stools and three stools at
|
||||||
|
a rail-side standing counter: 13 selectable furniture positions, 19 seat places.
|
||||||
|
- Seven coffee tables, eight potted trees, flowering troughs, eight varied guests,
|
||||||
|
two supported strings of lanterns, and a slatted pergola over a working bar.
|
||||||
|
- Sofas and chairs use closed native volumes with separate padded cushions.
|
||||||
|
Planter boxes contain soil and multiple foliage clusters at different depths.
|
||||||
|
Whole-object photographs are not pasted onto every furniture face.
|
||||||
|
- E at a railing eases into a leaning pose, with thirty-two hand/forearm frames
|
||||||
|
anchored to the actual rail height. E or movement releases the rail.
|
||||||
|
- While leaning, mouse, arrows and A/D can turn up to 73 degrees either way. The
|
||||||
|
rail contact is projected in world space so the hands do not follow head yaw.
|
||||||
|
- Guests walk on the terrace with collision checks, pauses and walking frames.
|
||||||
|
- In the open first-floor elevator, 1 selects sunset and 2 selects night.
|
||||||
|
- E sits/stands; walking forward/backward also stands and restores the approach
|
||||||
|
position. Stool views use bar height and rail-side stools face the city.
|
||||||
|
- The bar reuses the existing mixing/drinking system and prices (100/200/free
|
||||||
|
water). Its camera is temporarily positioned at the new counter and completely
|
||||||
|
restored after rendering. Drinks are the only new-location actions that spend
|
||||||
|
or save bankroll, through the existing purchase routine.
|
||||||
|
|
||||||
|
## Assets And Build
|
||||||
|
|
||||||
|
Generated sources are under `assets/sprites/rooftop/`; runtime ANM1 packs are under
|
||||||
|
`assets/animations/rooftop/`. Run `tools/generators/pack_rooftop.py` offline to pack
|
||||||
|
the sky, materials, semantic night-window textures, ground lighting, hands,
|
||||||
|
district layout and collision map. Run `pack_rooftop_gl.py` afterwards to build
|
||||||
|
the static city and moving vehicle triangle meshes. Python, Pillow, NumPy and
|
||||||
|
OpenCV are offline developer tools, not game dependencies.
|
||||||
|
|
||||||
|
The native MASM HD city renderer uses the Windows system OpenGL library, a
|
||||||
|
private hidden rendering context and an offscreen framebuffer up to 1280x960. It uses
|
||||||
|
textured mesh display lists, mipmaps, normals, directional dusk lighting,
|
||||||
|
distance fog and a separate emissive-window pass at night. The existing terrace,
|
||||||
|
hands and HUD are composited by direct native pixel copying into one DIB. Other games retain
|
||||||
|
their existing renderer. If the required GL capabilities are unavailable, the
|
||||||
|
assembly software city renderer remains the fallback. No C/C++ renderer, model
|
||||||
|
engine, browser runtime, cloud service or runtime downloader is introduced.
|
||||||
|
|
||||||
|
The eastern avenue is now a broad river with raised embankments, promenades,
|
||||||
|
trees, piers, three full-span bridges and further riverfront quarters. Water
|
||||||
|
texture flow and six moving boats keep it from being a static blue plane.
|
||||||
|
Street rectangles are clipped into disjoint junctions rather than coplanar,
|
||||||
|
overlapping strips. The terrace deck uses mipmapped HD geometry rather than
|
||||||
|
the unfiltered software floor when HD rendering is available. City, foreground
|
||||||
|
and HUD are composed into one offscreen DIB and copied to the window once;
|
||||||
|
there is no intermediate bare-city frame. glReadPixels supplies the required
|
||||||
|
readback synchronisation, without a redundant preceding glFinish.
|
||||||
|
|
||||||
|
## Rooftop Performance
|
||||||
|
|
||||||
|
- F8 cycles automatic, eco (640x480) and detailed (1280x960) city rendering.
|
||||||
|
Automatic starts at 960x720 and drops to eco after sustained frames over 34 ms.
|
||||||
|
Switching back to automatic retries 960x720. The scene, view distance, collisions
|
||||||
|
and gameplay do not change with the render profile; other rooms are unaffected.
|
||||||
|
- The offline mesh packer discards only triangles that face away from every
|
||||||
|
possible rooftop eye position. Runtime back-face culling handles head turns.
|
||||||
|
The static mesh now contains 35,386 triangles instead of 53,695.
|
||||||
|
- CPU foreground surfaces use projected screen bounds and camera-facing box
|
||||||
|
sides. The final frame avoids an extra GDI scaling/alpha-blending pass.
|
||||||
|
- Mipmap generation is optional on older OpenGL drivers. If hardware rendering
|
||||||
|
cannot initialise, the software ground renderer still draws roads and water,
|
||||||
|
including solid-colour fallback surfaces when a texture pack is absent.
|
||||||
|
- `runtime/roof-renderer.txt` records the local GL vendor, renderer, version,
|
||||||
|
initialisation stage, city-pack availability and render width. It contains no
|
||||||
|
personal data and is not sent anywhere. Stage 0 means successful initialisation.
|
||||||
|
|
||||||
|
Integrated Intel graphics use shared system memory; the small dedicated-memory
|
||||||
|
figure alone is not a useful rendering budget. Actual laptop performance must be
|
||||||
|
checked on that machine, not inferred from the desktop benchmark.
|
||||||
|
|
||||||
|
The art direction takes atmospheric inspiration from the rooftop reference:
|
||||||
|
https://www.loftprojectetagi.ru/visitors/krysha/ . It is an original game backdrop,
|
||||||
|
not an exact survey or reproduction of that venue. Generated source images are
|
||||||
|
preserved alongside the packer metadata. Older city panoramas and furniture
|
||||||
|
reference photographs remain source art, not the active city/furniture renderer.
|
||||||
|
|
||||||
|
Runtime sources: `src_graphics/rooftop*.inc` and the shared MASM city primitives.
|
||||||
|
The normal MASM build and root/bin publisher ship the feature. Rebuilding the
|
||||||
|
existing installer is separate from updating the ordinary game executable.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
`tools/tests/check_hall_expansion.py` compiles the real current MASM routines and
|
||||||
|
tests closed/open door collision, manual cabin entry/exit, both trips, timing,
|
||||||
|
camera/position/bankroll preservation, furniture/rail bounds, seating, automatic
|
||||||
|
closing, thirty repeated bar renders, asset loading/freeing and native screenshots.
|
||||||
|
|
||||||
|
It exports a 70x78 walk grid from actual `CanWalk3D` calls. Reachability checks
|
||||||
|
verify a connected route from the cabin to the bar, both sides of the terrace,
|
||||||
|
and every seating approach after the denser layout. Framebuffer captures are
|
||||||
|
written under `build/hall-expansion/roof-*.png`. `--parity` verifies tested
|
||||||
|
procedures against the full shipping object before publishing.
|
||||||
|
The native harness also checks all three resolution profiles, automatic downgrade,
|
||||||
|
F8 switching, and software roads/water with both present and missing city textures.
|
||||||
BIN
poker.exe
|
|
@ -5,12 +5,19 @@ cityRayY3D dd SCREEN_W dup(?)
|
||||||
; Exterior-only materials do not consume or overwrite the hall's texture slots.
|
; Exterior-only materials do not consume or overwrite the hall's texture slots.
|
||||||
ResolveCitySurface3D PROC material:DWORD
|
ResolveCitySurface3D PROC material:DWORD
|
||||||
mov eax,material
|
mov eax,material
|
||||||
cmp eax,161
|
cmp eax,MATERIAL_JACKBOX_FRONT
|
||||||
jb @F
|
jb @F
|
||||||
cmp eax,163
|
cmp eax,MATERIAL_JACKBOX_BACK
|
||||||
ja @F
|
ja @F
|
||||||
invoke ResolveJackboxSurface3D,material
|
invoke ResolveJackboxSurface3D,material
|
||||||
ret
|
ret
|
||||||
|
@@:
|
||||||
|
cmp eax,ROOF_DECK
|
||||||
|
jb @F
|
||||||
|
cmp eax,ROOF_LAST_MATERIAL
|
||||||
|
ja @F
|
||||||
|
invoke ResolveRoofSurface3D,material
|
||||||
|
ret
|
||||||
@@:
|
@@:
|
||||||
cmp eax,160
|
cmp eax,160
|
||||||
jne @F
|
jne @F
|
||||||
|
|
@ -116,6 +123,7 @@ city_prepare_ray:
|
||||||
PrepareCityRays3D ENDP
|
PrepareCityRays3D ENDP
|
||||||
|
|
||||||
CityRayPlane3D PROC coordinate:DWORD,origin:DWORD,direction:DWORD
|
CityRayPlane3D PROC coordinate:DWORD,origin:DWORD,direction:DWORD
|
||||||
|
local farDelta:DWORD
|
||||||
mov ecx, direction
|
mov ecx, direction
|
||||||
mov eax, ecx
|
mov eax, ecx
|
||||||
test eax, eax
|
test eax, eax
|
||||||
|
|
@ -124,6 +132,17 @@ CityRayPlane3D PROC coordinate:DWORD,origin:DWORD,direction:DWORD
|
||||||
@@:
|
@@:
|
||||||
cmp eax, 256
|
cmp eax, 256
|
||||||
jb city_ray_parallel
|
jb city_ray_parallel
|
||||||
|
; A long city ray can overflow IDIV before its depth is clipped. Reject
|
||||||
|
; intersections beyond the exterior far plane before forming the dividend.
|
||||||
|
shl eax,10
|
||||||
|
mov farDelta,eax
|
||||||
|
mov eax,coordinate
|
||||||
|
sub eax,origin
|
||||||
|
cdq
|
||||||
|
xor eax,edx
|
||||||
|
sub eax,edx
|
||||||
|
cmp eax,farDelta
|
||||||
|
jae city_ray_parallel
|
||||||
mov eax, coordinate
|
mov eax, coordinate
|
||||||
sub eax, origin
|
sub eax, origin
|
||||||
cdq
|
cdq
|
||||||
|
|
@ -140,14 +159,78 @@ CityRayPlane3D ENDP
|
||||||
DrawCityVertical3D PROC uses ebx esi edi axis:DWORD,coordinate:DWORD,loBound:DWORD,hiBound:DWORD,zLow:DWORD,zHigh:DWORD,material:DWORD
|
DrawCityVertical3D PROC uses ebx esi edi axis:DWORD,coordinate:DWORD,loBound:DWORD,hiBound:DWORD,zLow:DWORD,zHigh:DWORD,material:DWORD
|
||||||
local depth:DWORD,top:DWORD,bottom:DWORD,span:DWORD,column:DWORD
|
local depth:DWORD,top:DWORD,bottom:DWORD,span:DWORD,column:DWORD
|
||||||
local sourceX:DWORD,stepY:DWORD,sourceY:DWORD,destination:DWORD,row:DWORD,texture:DWORD
|
local sourceX:DWORD,stepY:DWORD,sourceY:DWORD,destination:DWORD,row:DWORD,texture:DWORD
|
||||||
local textureW:DWORD,textureH:DWORD
|
local textureW:DWORD,textureH:DWORD,faceLight:DWORD
|
||||||
|
local endColumn:DWORD,firstX:DWORD,firstDepth:DWORD,clipX:DWORD,clipY:DWORD
|
||||||
invoke ResolveCitySurface3D,material
|
invoke ResolveCitySurface3D,material
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz city_vertical_done
|
jz city_vertical_done
|
||||||
mov texture, eax
|
mov texture, eax
|
||||||
mov textureW, ecx
|
mov textureW, ecx
|
||||||
mov textureH, edx
|
mov textureH, edx
|
||||||
|
mov faceLight,230
|
||||||
|
cmp roofCityPass3D,0
|
||||||
|
je city_vertical_setup
|
||||||
|
cmp axis,0
|
||||||
|
jne city_vertical_light_y
|
||||||
|
mov eax,playerX
|
||||||
|
cmp eax,coordinate
|
||||||
|
jl city_vertical_setup
|
||||||
|
mov faceLight,142
|
||||||
|
jmp city_vertical_setup
|
||||||
|
city_vertical_light_y:
|
||||||
|
mov faceLight,165
|
||||||
|
mov eax,playerY
|
||||||
|
cmp eax,coordinate
|
||||||
|
jl city_vertical_setup
|
||||||
|
mov faceLight,218
|
||||||
|
city_vertical_setup:
|
||||||
mov column, 0
|
mov column, 0
|
||||||
|
mov endColumn,SCREEN_W
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
jne city_vertical_column
|
||||||
|
mov eax,coordinate
|
||||||
|
mov edx,loBound
|
||||||
|
cmp axis,0
|
||||||
|
je @F
|
||||||
|
xchg eax,edx
|
||||||
|
@@:
|
||||||
|
invoke ProjectCityPoint3D,eax,edx
|
||||||
|
mov firstX,eax
|
||||||
|
mov firstDepth,edx
|
||||||
|
mov eax,coordinate
|
||||||
|
mov edx,hiBound
|
||||||
|
cmp axis,0
|
||||||
|
je @F
|
||||||
|
xchg eax,edx
|
||||||
|
@@:
|
||||||
|
invoke ProjectCityPoint3D,eax,edx
|
||||||
|
cmp edx,4096
|
||||||
|
jg city_vertical_clip_second
|
||||||
|
cmp firstDepth,4096
|
||||||
|
jle city_vertical_done
|
||||||
|
jmp city_vertical_column
|
||||||
|
city_vertical_clip_second:
|
||||||
|
cmp firstDepth,4096
|
||||||
|
jle city_vertical_column
|
||||||
|
mov edx,firstX
|
||||||
|
cmp eax,edx
|
||||||
|
jge @F
|
||||||
|
xchg eax,edx
|
||||||
|
@@:
|
||||||
|
sub edx,2
|
||||||
|
add eax,3
|
||||||
|
test edx,edx
|
||||||
|
jns @F
|
||||||
|
xor edx,edx
|
||||||
|
@@:
|
||||||
|
cmp eax,SCREEN_W
|
||||||
|
jle @F
|
||||||
|
mov eax,SCREEN_W
|
||||||
|
@@:
|
||||||
|
cmp edx,eax
|
||||||
|
jge city_vertical_done
|
||||||
|
mov column,edx
|
||||||
|
mov endColumn,eax
|
||||||
city_vertical_column:
|
city_vertical_column:
|
||||||
mov ebx, column
|
mov ebx, column
|
||||||
cmp axis, 0
|
cmp axis, 0
|
||||||
|
|
@ -200,15 +283,15 @@ city_vertical_along:
|
||||||
mov sourceX, eax
|
mov sourceX, eax
|
||||||
mov eax, viewEye3D
|
mov eax, viewEye3D
|
||||||
sub eax, zHigh
|
sub eax, zHigh
|
||||||
imul eax, SCREEN_H
|
mov ecx,SCREEN_H
|
||||||
cdq
|
imul ecx
|
||||||
idiv depth
|
idiv depth
|
||||||
add eax, viewHorizon3D
|
add eax, viewHorizon3D
|
||||||
mov top, eax
|
mov top, eax
|
||||||
mov eax, viewEye3D
|
mov eax, viewEye3D
|
||||||
sub eax, zLow
|
sub eax, zLow
|
||||||
imul eax, SCREEN_H
|
mov ecx,SCREEN_H
|
||||||
cdq
|
imul ecx
|
||||||
idiv depth
|
idiv depth
|
||||||
add eax, viewHorizon3D
|
add eax, viewHorizon3D
|
||||||
mov bottom, eax
|
mov bottom, eax
|
||||||
|
|
@ -274,7 +357,10 @@ city_vertical_pixel:
|
||||||
@@:
|
@@:
|
||||||
mov edx, depth
|
mov edx, depth
|
||||||
mov cityDepthBuffer3D[edi], edx
|
mov cityDepthBuffer3D[edi], edx
|
||||||
|
cmp roofCityPass3D,0
|
||||||
|
jne city_vertical_scene_color
|
||||||
and eax, 00FFFFFFh
|
and eax, 00FFFFFFh
|
||||||
|
city_vertical_scene_color:
|
||||||
cmp cityBackdrop3D, 0
|
cmp cityBackdrop3D, 0
|
||||||
je @F
|
je @F
|
||||||
push eax
|
push eax
|
||||||
|
|
@ -288,7 +374,21 @@ city_vertical_pixel:
|
||||||
shr eax, 1
|
shr eax, 1
|
||||||
add eax, 00101828h
|
add eax, 00101828h
|
||||||
@@:
|
@@:
|
||||||
|
cmp roofCityPass3D,0
|
||||||
|
je city_vertical_color_ready
|
||||||
|
invoke ShadeRoofCityPixel3D,eax,depth,faceLight,material
|
||||||
|
mov ebx,edi
|
||||||
|
shr ebx,2
|
||||||
|
mov ecx,roofPixelGlow3D
|
||||||
|
mov roofGlowMask3D[ebx],cl
|
||||||
|
city_vertical_color_ready:
|
||||||
mov screenBuffer[edi], eax
|
mov screenBuffer[edi], eax
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
jne city_vertical_next_pixel
|
||||||
|
mov ebx,edi
|
||||||
|
shr ebx,2
|
||||||
|
mov ecx,roofCityPass3D
|
||||||
|
mov roofCityMask3D[ebx],cl
|
||||||
city_vertical_next_pixel:
|
city_vertical_next_pixel:
|
||||||
mov eax, stepY
|
mov eax, stepY
|
||||||
add sourceY, eax
|
add sourceY, eax
|
||||||
|
|
@ -299,7 +399,8 @@ city_vertical_next_pixel:
|
||||||
jb city_vertical_pixel
|
jb city_vertical_pixel
|
||||||
city_vertical_next_column:
|
city_vertical_next_column:
|
||||||
inc column
|
inc column
|
||||||
cmp column, SCREEN_W
|
mov eax,endColumn
|
||||||
|
cmp column,eax
|
||||||
jb city_vertical_column
|
jb city_vertical_column
|
||||||
city_vertical_done:
|
city_vertical_done:
|
||||||
ret
|
ret
|
||||||
|
|
@ -308,7 +409,7 @@ DrawCityVertical3D ENDP
|
||||||
DrawCityHorizontal3D PROC uses ebx esi edi xMin:DWORD,xMax:DWORD,yMin:DWORD,yMax:DWORD,z:DWORD,material:DWORD
|
DrawCityHorizontal3D PROC uses ebx esi edi xMin:DWORD,xMax:DWORD,yMin:DWORD,yMax:DWORD,z:DWORD,material:DWORD
|
||||||
local left:DWORD,right:DWORD,top:DWORD,bottom:DWORD,corner:DWORD,pointX:DWORD,pointY:DWORD
|
local left:DWORD,right:DWORD,top:DWORD,bottom:DWORD,corner:DWORD,pointX:DWORD,pointY:DWORD
|
||||||
local depth:DWORD,row:DWORD,column:DWORD,stepX:DWORD,stepY:DWORD,scaleX:DWORD,scaleY:DWORD,texture:DWORD
|
local depth:DWORD,row:DWORD,column:DWORD,stepX:DWORD,stepY:DWORD,scaleX:DWORD,scaleY:DWORD,texture:DWORD
|
||||||
local textureW:DWORD,textureH:DWORD,nearClipped:DWORD
|
local textureW:DWORD,textureH:DWORD,nearClipped:DWORD,visibleCorners:DWORD
|
||||||
invoke ResolveCitySurface3D,material
|
invoke ResolveCitySurface3D,material
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz city_horizontal_done
|
jz city_horizontal_done
|
||||||
|
|
@ -316,6 +417,7 @@ DrawCityHorizontal3D PROC uses ebx esi edi xMin:DWORD,xMax:DWORD,yMin:DWORD,yMax
|
||||||
mov textureW, ecx
|
mov textureW, ecx
|
||||||
mov textureH, edx
|
mov textureH, edx
|
||||||
mov nearClipped, 0
|
mov nearClipped, 0
|
||||||
|
mov visibleCorners,0
|
||||||
mov left, SCREEN_W
|
mov left, SCREEN_W
|
||||||
mov right, 0
|
mov right, 0
|
||||||
mov top, SCREEN_H
|
mov top, SCREEN_H
|
||||||
|
|
@ -338,6 +440,7 @@ city_horizontal_corner:
|
||||||
mov nearClipped, 1
|
mov nearClipped, 1
|
||||||
jmp city_horizontal_next_corner
|
jmp city_horizontal_next_corner
|
||||||
city_horizontal_visible_corner:
|
city_horizontal_visible_corner:
|
||||||
|
inc visibleCorners
|
||||||
mov esi, edx
|
mov esi, edx
|
||||||
cmp eax, left
|
cmp eax, left
|
||||||
jge @F
|
jge @F
|
||||||
|
|
@ -349,8 +452,8 @@ city_horizontal_visible_corner:
|
||||||
@@:
|
@@:
|
||||||
mov eax, viewEye3D
|
mov eax, viewEye3D
|
||||||
sub eax, z
|
sub eax, z
|
||||||
imul eax, SCREEN_H
|
mov ecx,SCREEN_H
|
||||||
cdq
|
imul ecx
|
||||||
idiv esi
|
idiv esi
|
||||||
add eax, viewHorizon3D
|
add eax, viewHorizon3D
|
||||||
cmp eax, top
|
cmp eax, top
|
||||||
|
|
@ -365,6 +468,11 @@ city_horizontal_next_corner:
|
||||||
inc corner
|
inc corner
|
||||||
cmp corner, 4
|
cmp corner, 4
|
||||||
jb city_horizontal_corner
|
jb city_horizontal_corner
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
jne @F
|
||||||
|
cmp visibleCorners,0
|
||||||
|
je city_horizontal_done
|
||||||
|
@@:
|
||||||
cmp nearClipped, 0
|
cmp nearClipped, 0
|
||||||
je @F
|
je @F
|
||||||
; Ray bounds/depth below clip the polygon; a behind-camera corner cannot discard it.
|
; Ray bounds/depth below clip the polygon; a behind-camera corner cannot discard it.
|
||||||
|
|
@ -414,8 +522,8 @@ city_horizontal_row:
|
||||||
jz city_horizontal_next_row
|
jz city_horizontal_next_row
|
||||||
mov eax, viewEye3D
|
mov eax, viewEye3D
|
||||||
sub eax, z
|
sub eax, z
|
||||||
imul eax, SCREEN_H
|
mov ebx,SCREEN_H
|
||||||
cdq
|
imul ebx
|
||||||
idiv ecx
|
idiv ecx
|
||||||
cmp eax, 4096
|
cmp eax, 4096
|
||||||
jle city_horizontal_next_row
|
jle city_horizontal_next_row
|
||||||
|
|
@ -508,7 +616,25 @@ city_horizontal_alpha:
|
||||||
mov ecx, depth
|
mov ecx, depth
|
||||||
mov cityDepthBuffer3D[edi], ecx
|
mov cityDepthBuffer3D[edi], ecx
|
||||||
and eax, 00FFFFFFh
|
and eax, 00FFFFFFh
|
||||||
|
cmp roofCityPass3D,0
|
||||||
|
je city_horizontal_color_ready
|
||||||
|
cmp material,ROOF_CITY_ROAD
|
||||||
|
jne @F
|
||||||
|
invoke SampleRoofGroundLight3D,eax,pointX,pointY
|
||||||
|
@@:
|
||||||
|
invoke ShadeRoofCityPixel3D,eax,depth,244,material
|
||||||
|
mov ebx,edi
|
||||||
|
shr ebx,2
|
||||||
|
mov ecx,roofPixelGlow3D
|
||||||
|
mov roofGlowMask3D[ebx],cl
|
||||||
|
city_horizontal_color_ready:
|
||||||
mov screenBuffer[edi], eax
|
mov screenBuffer[edi], eax
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
jne city_horizontal_advance
|
||||||
|
mov ebx,edi
|
||||||
|
shr ebx,2
|
||||||
|
mov ecx,roofCityPass3D
|
||||||
|
mov roofCityMask3D[ebx],cl
|
||||||
city_horizontal_advance:
|
city_horizontal_advance:
|
||||||
mov eax, stepX
|
mov eax, stepX
|
||||||
add pointX, eax
|
add pointX, eax
|
||||||
|
|
@ -529,6 +655,30 @@ city_horizontal_done:
|
||||||
DrawCityHorizontal3D ENDP
|
DrawCityHorizontal3D ENDP
|
||||||
|
|
||||||
DrawCityBoxSides3D PROC xMin:DWORD,xMax:DWORD,yMin:DWORD,yMax:DWORD,zLow:DWORD,zHigh:DWORD,material:DWORD
|
DrawCityBoxSides3D PROC xMin:DWORD,xMax:DWORD,yMin:DWORD,yMax:DWORD,zLow:DWORD,zHigh:DWORD,material:DWORD
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
jne city_box_all_sides
|
||||||
|
mov eax,playerX
|
||||||
|
cmp eax,xMin
|
||||||
|
jge @F
|
||||||
|
invoke DrawCityVertical3D,0,xMin,yMin,yMax,zLow,zHigh,material
|
||||||
|
@@:
|
||||||
|
mov eax,playerX
|
||||||
|
cmp eax,xMax
|
||||||
|
jle @F
|
||||||
|
invoke DrawCityVertical3D,0,xMax,yMin,yMax,zLow,zHigh,material
|
||||||
|
@@:
|
||||||
|
mov eax,playerY
|
||||||
|
cmp eax,yMin
|
||||||
|
jge @F
|
||||||
|
invoke DrawCityVertical3D,1,yMin,xMin,xMax,zLow,zHigh,material
|
||||||
|
@@:
|
||||||
|
mov eax,playerY
|
||||||
|
cmp eax,yMax
|
||||||
|
jle @F
|
||||||
|
invoke DrawCityVertical3D,1,yMax,xMin,xMax,zLow,zHigh,material
|
||||||
|
@@:
|
||||||
|
ret
|
||||||
|
city_box_all_sides:
|
||||||
invoke DrawCityVertical3D, 0, xMin, yMin, yMax, zLow, zHigh, material
|
invoke DrawCityVertical3D, 0, xMin, yMin, yMax, zLow, zHigh, material
|
||||||
invoke DrawCityVertical3D, 0, xMax, yMin, yMax, zLow, zHigh, material
|
invoke DrawCityVertical3D, 0, xMax, yMin, yMax, zLow, zHigh, material
|
||||||
invoke DrawCityVertical3D, 1, yMin, xMin, xMax, zLow, zHigh, material
|
invoke DrawCityVertical3D, 1, yMin, xMin, xMax, zLow, zHigh, material
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ DartsWallText3D PROTO :DWORD,:DWORD,:DWORD
|
||||||
DrawDartsScoreboard3D PROTO
|
DrawDartsScoreboard3D PROTO
|
||||||
DrawDartsProps3D PROTO
|
DrawDartsProps3D PROTO
|
||||||
DrawDartsArm3D PROTO :DWORD,:SDWORD,:SDWORD
|
DrawDartsArm3D PROTO :DWORD,:SDWORD,:SDWORD
|
||||||
|
DrawDartsReticle3D PROTO :SDWORD,:SDWORD
|
||||||
DartsScore3D PROTO :SDWORD,:SDWORD
|
DartsScore3D PROTO :SDWORD,:SDWORD
|
||||||
SettleDarts3D PROTO
|
SettleDarts3D PROTO
|
||||||
DrawDartsRoom3D PROTO
|
DrawDartsRoom3D PROTO
|
||||||
|
|
@ -45,7 +46,7 @@ dtWall3D AnimPack3D <>
|
||||||
dtChair3D AnimPack3D <>
|
dtChair3D AnimPack3D <>
|
||||||
dtTable3D AnimPack3D <>
|
dtTable3D AnimPack3D <>
|
||||||
dtRoom3D AnimPack3D <>
|
dtRoom3D AnimPack3D <>
|
||||||
dtBoardPath db "assets\animations\darts\board-v1.bin",0
|
dtBoardPath db "assets\animations\darts\board-v2.bin",0
|
||||||
dtHandsPath db "assets\animations\darts\arm-throw-v3.bin",0
|
dtHandsPath db "assets\animations\darts\arm-throw-v3.bin",0
|
||||||
dtDartPath db "assets\animations\darts\dart-views-v1.bin",0
|
dtDartPath db "assets\animations\darts\dart-views-v1.bin",0
|
||||||
dtWallPath db "assets\animations\darts\lounge-wall-v1.bin",0
|
dtWallPath db "assets\animations\darts\lounge-wall-v1.bin",0
|
||||||
|
|
@ -134,6 +135,7 @@ dtDouble db 68,0
|
||||||
dtTriple db 84,0
|
dtTriple db 84,0
|
||||||
dtSingle db 83,0
|
dtSingle db 83,0
|
||||||
dtTarget db 214,197,203,220,0
|
dtTarget db 214,197,203,220,0
|
||||||
|
dtReticleOffsets3D dd -3,0,-2,0,2,0,3,0,0,-3,0,-2,0,2,0,3,0,0
|
||||||
.data?
|
.data?
|
||||||
dtRayX3D dd 640 dup(?)
|
dtRayX3D dd 640 dup(?)
|
||||||
dtRayZ3D dd 640 dup(?)
|
dtRayZ3D dd 640 dup(?)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,39 @@
|
||||||
|
; Nine physical pixels, with contrast chosen from the surface beneath each one.
|
||||||
|
DrawDartsReticle3D PROC uses ebx esi edi targetX:SDWORD,targetY:SDWORD
|
||||||
|
lea esi,dtReticleOffsets3D
|
||||||
|
mov ebx,9
|
||||||
|
dt_reticle_point:
|
||||||
|
mov eax,targetX
|
||||||
|
add eax,[esi]
|
||||||
|
cmp eax,640
|
||||||
|
jae dt_reticle_next
|
||||||
|
mov edx,targetY
|
||||||
|
add edx,[esi+4]
|
||||||
|
cmp edx,32
|
||||||
|
jl dt_reticle_next
|
||||||
|
cmp edx,400
|
||||||
|
jge dt_reticle_next
|
||||||
|
imul edx,640
|
||||||
|
add edx,eax
|
||||||
|
lea edi,screenBuffer[edx*4]
|
||||||
|
movzx eax,byte ptr [edi]
|
||||||
|
movzx ecx,byte ptr [edi+1]
|
||||||
|
lea eax,[eax+ecx*2]
|
||||||
|
movzx ecx,byte ptr [edi+2]
|
||||||
|
add eax,ecx
|
||||||
|
mov ecx,00F6E6ADh
|
||||||
|
cmp eax,560
|
||||||
|
jb @F
|
||||||
|
mov ecx,00152021h
|
||||||
|
@@:
|
||||||
|
mov [edi],ecx
|
||||||
|
dt_reticle_next:
|
||||||
|
add esi,8
|
||||||
|
dec ebx
|
||||||
|
jnz dt_reticle_point
|
||||||
|
ret
|
||||||
|
DrawDartsReticle3D ENDP
|
||||||
|
|
||||||
; A single rigid sprite transform aligns the dart axis with the live target.
|
; A single rigid sprite transform aligns the dart axis with the live target.
|
||||||
DrawDartsArm3D PROC uses ebx esi edi pose:DWORD,targetX:SDWORD,targetY:SDWORD
|
DrawDartsArm3D PROC uses ebx esi edi pose:DWORD,targetX:SDWORD,targetY:SDWORD
|
||||||
local originX:DWORD,originY:DWORD,left:DWORD,right:DWORD,bottom:DWORD,row:DWORD,column:DWORD
|
local originX:DWORD,originY:DWORD,left:DWORD,right:DWORD,bottom:DWORD,row:DWORD,column:DWORD
|
||||||
|
|
|
||||||
|
|
@ -545,22 +545,7 @@ dt_render_pose:
|
||||||
invoke DrawDartsArm3D,pose,bx0,by0
|
invoke DrawDartsArm3D,pose,bx0,by0
|
||||||
cmp dtState3D,DT_AIM
|
cmp dtState3D,DT_AIM
|
||||||
jne dt_render_hud
|
jne dt_render_hud
|
||||||
mov eax,bx0
|
invoke DrawDartsReticle3D,bx0,by0
|
||||||
sub eax,7
|
|
||||||
mov edx,by0
|
|
||||||
sub edx,2
|
|
||||||
invoke DrawBuckshotPanel3D,eax,edx,15,5,00101112h
|
|
||||||
mov eax,by0
|
|
||||||
sub eax,7
|
|
||||||
mov edx,bx0
|
|
||||||
sub edx,2
|
|
||||||
invoke DrawBuckshotPanel3D,edx,eax,5,15,00101112h
|
|
||||||
mov eax,bx0
|
|
||||||
sub eax,6
|
|
||||||
invoke DrawBuckshotPanel3D,eax,by0,13,2,00F6E6ADh
|
|
||||||
mov eax,by0
|
|
||||||
sub eax,6
|
|
||||||
invoke DrawBuckshotPanel3D,bx0,eax,2,13,00F6E6ADh
|
|
||||||
dt_render_hud:
|
dt_render_hud:
|
||||||
invoke DrawBox,0,0,320,16,00151D20h
|
invoke DrawBox,0,0,320,16,00151D20h
|
||||||
invoke DrawString8x8,8,4,OFFSET dtTitle,00E8D7ADh
|
invoke DrawString8x8,8,4,OFFSET dtTitle,00E8D7ADh
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ fortune_session_load:
|
||||||
invoke LoadAnimPack3D,esi,fortuneSessionPaths3D[ebx*4]
|
invoke LoadAnimPack3D,esi,fortuneSessionPaths3D[ebx*4]
|
||||||
add esi,SIZEOF AnimPack3D
|
add esi,SIZEOF AnimPack3D
|
||||||
inc ebx
|
inc ebx
|
||||||
cmp ebx,7
|
cmp ebx,FORTUNE_SESSION_PACK_COUNT
|
||||||
jb fortune_session_load
|
jb fortune_session_load
|
||||||
mov engineMode,MODE_FORTUNE
|
mov engineMode,MODE_FORTUNE
|
||||||
mov paused3D,0
|
mov paused3D,0
|
||||||
|
|
@ -24,6 +24,7 @@ fortune_session_load:
|
||||||
mov fortuneQuestionLength3D,0
|
mov fortuneQuestionLength3D,0
|
||||||
mov fortuneQuestion3D,0
|
mov fortuneQuestion3D,0
|
||||||
mov fortuneWorkerState3D,0
|
mov fortuneWorkerState3D,0
|
||||||
|
call ResetFortuneFate3D
|
||||||
mov eax,animationClock3D
|
mov eax,animationClock3D
|
||||||
mov fortuneSessionClock3D,eax
|
mov fortuneSessionClock3D,eax
|
||||||
invoke SetFortuneSpeech3D,OFFSET fortuneWelcome3D
|
invoke SetFortuneSpeech3D,OFFSET fortuneWelcome3D
|
||||||
|
|
@ -35,13 +36,14 @@ BeginFortuneDialog3D ENDP
|
||||||
; Kept as the public exit/shutdown hook. No inference process is launched.
|
; Kept as the public exit/shutdown hook. No inference process is launched.
|
||||||
StopFortuneWorker3D PROC uses ebx esi
|
StopFortuneWorker3D PROC uses ebx esi
|
||||||
lea esi,fortuneSessionPacks3D
|
lea esi,fortuneSessionPacks3D
|
||||||
mov ebx,7
|
mov ebx,FORTUNE_SESSION_PACK_COUNT
|
||||||
fortune_session_free:
|
fortune_session_free:
|
||||||
invoke FreeAnimPack3D,esi
|
invoke FreeAnimPack3D,esi
|
||||||
add esi,SIZEOF AnimPack3D
|
add esi,SIZEOF AnimPack3D
|
||||||
dec ebx
|
dec ebx
|
||||||
jnz fortune_session_free
|
jnz fortune_session_free
|
||||||
mov fortuneWorkerState3D,0
|
mov fortuneWorkerState3D,0
|
||||||
|
call ResetFortuneFate3D
|
||||||
ret
|
ret
|
||||||
StopFortuneWorker3D ENDP
|
StopFortuneWorker3D ENDP
|
||||||
|
|
||||||
|
|
@ -129,11 +131,17 @@ fortune_char_tarot:
|
||||||
ret
|
ret
|
||||||
fortune_char_orb:
|
fortune_char_orb:
|
||||||
mov fortuneSubMode3D,FORTUNE_SUBMODE_ORB
|
mov fortuneSubMode3D,FORTUNE_SUBMODE_ORB
|
||||||
mov fortunePhase3D,1
|
call ResetFortuneFate3D
|
||||||
|
mov fortunePhase3D,0
|
||||||
mov fortunePhaseTime3D,0
|
mov fortunePhaseTime3D,0
|
||||||
invoke SetFortuneSpeech3D,OFFSET fortuneOrbStatus3D
|
invoke SetFortuneSpeech3D,OFFSET fortuneFateReady3D
|
||||||
ret
|
ret
|
||||||
fortune_char_question:
|
fortune_char_question:
|
||||||
|
cmp fortuneSubMode3D,FORTUNE_SUBMODE_ORB
|
||||||
|
jne @F
|
||||||
|
invoke FortuneFateChar3D,character
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
cmp fortuneSubMode3D,FORTUNE_SUBMODE_TAROT
|
cmp fortuneSubMode3D,FORTUNE_SUBMODE_TAROT
|
||||||
jne fortune_char_done
|
jne fortune_char_done
|
||||||
cmp fortunePhase3D,0
|
cmp fortunePhase3D,0
|
||||||
|
|
@ -277,6 +285,7 @@ fortune_update_orb:
|
||||||
jb fortune_update_done
|
jb fortune_update_done
|
||||||
mov fortunePhase3D,2
|
mov fortunePhase3D,2
|
||||||
mov fortunePhaseTime3D,0
|
mov fortunePhaseTime3D,0
|
||||||
|
invoke SetFortuneSpeech3D,OFFSET fortuneFateSwirl3D
|
||||||
jmp fortune_update_done
|
jmp fortune_update_done
|
||||||
fortune_orb_swirl:
|
fortune_orb_swirl:
|
||||||
cmp fortunePhase3D,2
|
cmp fortunePhase3D,2
|
||||||
|
|
@ -285,7 +294,7 @@ fortune_orb_swirl:
|
||||||
jb fortune_update_done
|
jb fortune_update_done
|
||||||
mov fortunePhase3D,3
|
mov fortunePhase3D,3
|
||||||
mov fortunePhaseTime3D,0
|
mov fortunePhaseTime3D,0
|
||||||
invoke SetFortuneSpeech3D,OFFSET fortuneOrbText3D
|
invoke SetFortuneSpeech3D,OFFSET fortuneFateReveal3D
|
||||||
fortune_update_done:
|
fortune_update_done:
|
||||||
ret
|
ret
|
||||||
UpdateFortuneSession3D ENDP
|
UpdateFortuneSession3D ENDP
|
||||||
|
|
@ -315,6 +324,37 @@ HandleFortuneDialog3D PROC
|
||||||
jae fortune_handle_reset
|
jae fortune_handle_reset
|
||||||
jmp fortune_handle_action
|
jmp fortune_handle_action
|
||||||
fortune_handle_menu_click:
|
fortune_handle_menu_click:
|
||||||
|
cmp fortuneSubMode3D,FORTUNE_SUBMODE_ORB
|
||||||
|
jne fortune_handle_selection_click
|
||||||
|
cmp fortunePhase3D,0
|
||||||
|
jne fortune_handle_done
|
||||||
|
; Form uses physical pixels; mouse input here uses half-resolution units.
|
||||||
|
mov eax,mouseY3D
|
||||||
|
sub eax,162
|
||||||
|
jb fortune_handle_done
|
||||||
|
xor edx,edx
|
||||||
|
mov ecx,21
|
||||||
|
div ecx
|
||||||
|
cmp eax,2
|
||||||
|
ja fortune_handle_done
|
||||||
|
cmp edx,11
|
||||||
|
ja fortune_handle_done
|
||||||
|
shl eax,1
|
||||||
|
cmp mouseX3D,156
|
||||||
|
jb fortune_handle_form_left
|
||||||
|
cmp mouseX3D,168
|
||||||
|
jb fortune_handle_done
|
||||||
|
cmp mouseX3D,312
|
||||||
|
ja fortune_handle_done
|
||||||
|
inc eax
|
||||||
|
jmp fortune_handle_form_focus
|
||||||
|
fortune_handle_form_left:
|
||||||
|
cmp mouseX3D,8
|
||||||
|
jb fortune_handle_done
|
||||||
|
fortune_handle_form_focus:
|
||||||
|
mov fortuneFateField3D,eax
|
||||||
|
ret
|
||||||
|
fortune_handle_selection_click:
|
||||||
cmp fortuneSubMode3D,FORTUNE_SUBMODE_MENU
|
cmp fortuneSubMode3D,FORTUNE_SUBMODE_MENU
|
||||||
jne fortune_handle_done
|
jne fortune_handle_done
|
||||||
cmp mouseY3D,196
|
cmp mouseY3D,196
|
||||||
|
|
@ -332,6 +372,11 @@ fortune_handle_orb:
|
||||||
fortune_handle_action:
|
fortune_handle_action:
|
||||||
cmp fortuneSubMode3D,FORTUNE_SUBMODE_MENU
|
cmp fortuneSubMode3D,FORTUNE_SUBMODE_MENU
|
||||||
je fortune_handle_tarot
|
je fortune_handle_tarot
|
||||||
|
cmp fortuneSubMode3D,FORTUNE_SUBMODE_ORB
|
||||||
|
jne @F
|
||||||
|
call SubmitFortuneFate3D
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
cmp fortuneSubMode3D,FORTUNE_SUBMODE_TAROT
|
cmp fortuneSubMode3D,FORTUNE_SUBMODE_TAROT
|
||||||
jne fortune_handle_done
|
jne fortune_handle_done
|
||||||
cmp fortunePhase3D,0
|
cmp fortunePhase3D,0
|
||||||
|
|
@ -367,9 +412,14 @@ fortune_handle_menu:
|
||||||
fortune_handle_reset:
|
fortune_handle_reset:
|
||||||
cmp fortuneSubMode3D,FORTUNE_SUBMODE_ORB
|
cmp fortuneSubMode3D,FORTUNE_SUBMODE_ORB
|
||||||
jne @F
|
jne @F
|
||||||
mov fortunePhase3D,1
|
cmp fortunePhase3D,3
|
||||||
|
jne fortune_handle_done
|
||||||
|
cmp fortunePhaseTime3D,1200
|
||||||
|
jb fortune_handle_done
|
||||||
|
mov fortunePhase3D,0
|
||||||
mov fortunePhaseTime3D,0
|
mov fortunePhaseTime3D,0
|
||||||
invoke SetFortuneSpeech3D,OFFSET fortuneOrbStatus3D
|
mov fortuneFateResult3D,-1
|
||||||
|
invoke SetFortuneSpeech3D,OFFSET fortuneFateReady3D
|
||||||
ret
|
ret
|
||||||
@@:
|
@@:
|
||||||
cmp fortunePhase3D,12
|
cmp fortunePhase3D,12
|
||||||
|
|
@ -692,6 +742,8 @@ fortune_render_hand_gesture:
|
||||||
mov esi,eax
|
mov esi,eax
|
||||||
jmp fortune_render_hands
|
jmp fortune_render_hands
|
||||||
fortune_render_orb_hands:
|
fortune_render_orb_hands:
|
||||||
|
cmp fortunePhase3D,0
|
||||||
|
je fortune_render_hands
|
||||||
mov ebx,OFFSET fortuneSessionOrbHands3D
|
mov ebx,OFFSET fortuneSessionOrbHands3D
|
||||||
mov eax,fortunePhaseTime3D
|
mov eax,fortunePhaseTime3D
|
||||||
shr eax,5
|
shr eax,5
|
||||||
|
|
@ -737,28 +789,24 @@ fortune_render_menu:
|
||||||
invoke DrawBuckshotText3D,364,404,OFFSET fortuneFate3D,00D2E8F2h
|
invoke DrawBuckshotText3D,364,404,OFFSET fortuneFate3D,00D2E8F2h
|
||||||
jmp fortune_render_footer
|
jmp fortune_render_footer
|
||||||
fortune_render_orb:
|
fortune_render_orb:
|
||||||
mov eax,fortunePhaseTime3D
|
cmp fortunePhase3D,0
|
||||||
shr eax,6
|
jne fortune_render_orb_active
|
||||||
and eax,15
|
call DrawFortuneFateForm3D
|
||||||
mov esi,eax
|
jmp fortune_render_footer
|
||||||
mov ebx,195
|
fortune_render_orb_active:
|
||||||
cmp fortunePhase3D,1
|
call ResolveFortuneOrb3D
|
||||||
|
invoke DrawAnimSprite3D,OFFSET fortuneSessionMist3D,fortuneOrbFrame3D,fortuneOrbX3D,fortuneOrbY3D,128,128
|
||||||
|
cmp fortunePhase3D,3
|
||||||
jne @F
|
jne @F
|
||||||
mov eax,fortunePhaseTime3D
|
call DrawFortuneFateResult3D
|
||||||
imul eax,135
|
|
||||||
xor edx,edx
|
|
||||||
mov ecx,1400
|
|
||||||
div ecx
|
|
||||||
mov ebx,330
|
|
||||||
sub ebx,eax
|
|
||||||
@@:
|
@@:
|
||||||
invoke DrawAnimSprite3D,OFFSET fortuneSessionMist3D,esi,214,ebx,128,128
|
call DrawFortuneFateIdentity3D
|
||||||
fortune_render_footer:
|
fortune_render_footer:
|
||||||
call DrawFortuneSpeech3D
|
call DrawFortuneSpeech3D
|
||||||
cmp fortuneSubMode3D,FORTUNE_SUBMODE_MENU
|
cmp fortuneSubMode3D,FORTUNE_SUBMODE_MENU
|
||||||
je fortune_render_exit_button
|
je fortune_render_exit_button
|
||||||
cmp fortuneSubMode3D,FORTUNE_SUBMODE_TAROT
|
cmp fortuneSubMode3D,FORTUNE_SUBMODE_TAROT
|
||||||
jne fortune_render_again_button
|
jne fortune_render_fate_button
|
||||||
invoke DrawBoxBorder,8,227,76,12,000B1E30h,00445F75h,1
|
invoke DrawBoxBorder,8,227,76,12,000B1E30h,00445F75h,1
|
||||||
mov esi,OFFSET fortuneAsk3D
|
mov esi,OFFSET fortuneAsk3D
|
||||||
cmp fortunePhase3D,0
|
cmp fortunePhase3D,0
|
||||||
|
|
@ -766,9 +814,20 @@ fortune_render_footer:
|
||||||
mov esi,OFFSET fortuneContinue3D
|
mov esi,OFFSET fortuneContinue3D
|
||||||
@@:
|
@@:
|
||||||
invoke DrawBuckshotText3D,24,458,esi,00CCE4F4h
|
invoke DrawBuckshotText3D,24,458,esi,00CCE4F4h
|
||||||
|
jmp fortune_render_again_button
|
||||||
|
fortune_render_fate_button:
|
||||||
|
cmp fortunePhase3D,0
|
||||||
|
jne fortune_render_again_button
|
||||||
|
invoke DrawBoxBorder,8,227,76,12,000B1E30h,00445F75h,1
|
||||||
|
invoke DrawBuckshotText3D,24,458,OFFSET fortuneFateStart3D,00CCE4F4h
|
||||||
fortune_render_again_button:
|
fortune_render_again_button:
|
||||||
invoke DrawBoxBorder,88,227,76,12,000B1E30h,00445F75h,1
|
invoke DrawBoxBorder,88,227,76,12,000B1E30h,00445F75h,1
|
||||||
invoke DrawBuckshotText3D,192,458,OFFSET fortuneAgain3D,0091A8BCh
|
mov esi,OFFSET fortuneAgain3D
|
||||||
|
cmp fortuneSubMode3D,FORTUNE_SUBMODE_ORB
|
||||||
|
jne @F
|
||||||
|
mov esi,OFFSET fortuneFateEdit3D
|
||||||
|
@@:
|
||||||
|
invoke DrawBuckshotText3D,192,458,esi,0091A8BCh
|
||||||
invoke DrawBoxBorder,172,227,64,12,000B1E30h,00445F75h,1
|
invoke DrawBoxBorder,172,227,64,12,000B1E30h,00445F75h,1
|
||||||
invoke DrawBuckshotText3D,368,458,OFFSET fortuneMenu3D,00CCE4F4h
|
invoke DrawBuckshotText3D,368,458,OFFSET fortuneMenu3D,00CCE4F4h
|
||||||
fortune_render_exit_button:
|
fortune_render_exit_button:
|
||||||
|
|
@ -776,3 +835,425 @@ fortune_render_exit_button:
|
||||||
invoke DrawBuckshotText3D,516,458,OFFSET fortuneExit3D,00CCE4F4h
|
invoke DrawBuckshotText3D,516,458,OFFSET fortuneExit3D,00CCE4F4h
|
||||||
ret
|
ret
|
||||||
RenderFortuneDialog3D ENDP
|
RenderFortuneDialog3D ENDP
|
||||||
|
|
||||||
|
ResetFortuneFate3D PROC uses edi
|
||||||
|
lea edi,fortuneFateLengths3D
|
||||||
|
xor eax,eax
|
||||||
|
mov ecx,6
|
||||||
|
rep stosd
|
||||||
|
lea edi,fortuneFateFields3D
|
||||||
|
mov ecx,96
|
||||||
|
rep stosd
|
||||||
|
mov fortuneFateField3D,0
|
||||||
|
mov fortuneFateResult3D,-1
|
||||||
|
mov fortuneFateFields3D[256],'9'
|
||||||
|
mov fortuneFateFields3D[320],'1'
|
||||||
|
mov fortuneFateFields3D[321],'0'
|
||||||
|
mov fortuneFateLengths3D[16],1
|
||||||
|
mov fortuneFateLengths3D[20],2
|
||||||
|
ret
|
||||||
|
ResetFortuneFate3D ENDP
|
||||||
|
|
||||||
|
FortuneFateChar3D PROC uses ebx esi edi character:DWORD
|
||||||
|
cmp fortunePhase3D,0
|
||||||
|
jne fate_char_done
|
||||||
|
mov ebx,fortuneFateField3D
|
||||||
|
cmp ebx,6
|
||||||
|
jae fate_char_done
|
||||||
|
mov eax,character
|
||||||
|
cmp eax,9
|
||||||
|
je fate_char_next
|
||||||
|
mov esi,ebx
|
||||||
|
shl esi,6
|
||||||
|
lea esi,fortuneFateFields3D[esi]
|
||||||
|
mov ecx,fortuneFateLengths3D[ebx*4]
|
||||||
|
cmp eax,8
|
||||||
|
je fate_char_backspace
|
||||||
|
cmp eax,32
|
||||||
|
jb fate_char_done
|
||||||
|
cmp eax,255
|
||||||
|
ja fate_char_done
|
||||||
|
cmp eax,127
|
||||||
|
je fate_char_done
|
||||||
|
cmp ecx,fortuneFateLimits3D[ebx*4]
|
||||||
|
jae fate_char_done
|
||||||
|
cmp ebx,2
|
||||||
|
je fate_char_date
|
||||||
|
cmp ebx,4
|
||||||
|
jae fate_char_digit
|
||||||
|
cmp eax,32
|
||||||
|
jne fate_char_store
|
||||||
|
test ecx,ecx
|
||||||
|
jz fate_char_done
|
||||||
|
cmp BYTE PTR [esi+ecx-1],32
|
||||||
|
je fate_char_done
|
||||||
|
jmp fate_char_store
|
||||||
|
fate_char_date:
|
||||||
|
cmp eax,'/'
|
||||||
|
jne @F
|
||||||
|
mov eax,'.'
|
||||||
|
@@:
|
||||||
|
cmp eax,'.'
|
||||||
|
jne fate_char_date_digit
|
||||||
|
cmp ecx,2
|
||||||
|
je fate_char_store
|
||||||
|
cmp ecx,5
|
||||||
|
je fate_char_store
|
||||||
|
jmp fate_char_done
|
||||||
|
fate_char_date_digit:
|
||||||
|
cmp eax,'0'
|
||||||
|
jb fate_char_done
|
||||||
|
cmp eax,'9'
|
||||||
|
ja fate_char_done
|
||||||
|
cmp ecx,2
|
||||||
|
je fate_char_date_dot
|
||||||
|
cmp ecx,5
|
||||||
|
jne fate_char_store
|
||||||
|
fate_char_date_dot:
|
||||||
|
mov BYTE PTR [esi+ecx],'.'
|
||||||
|
inc ecx
|
||||||
|
jmp fate_char_store
|
||||||
|
fate_char_digit:
|
||||||
|
cmp eax,'0'
|
||||||
|
jb fate_char_done
|
||||||
|
cmp eax,'9'
|
||||||
|
ja fate_char_done
|
||||||
|
fate_char_store:
|
||||||
|
mov [esi+ecx],al
|
||||||
|
inc ecx
|
||||||
|
mov fortuneFateLengths3D[ebx*4],ecx
|
||||||
|
mov BYTE PTR [esi+ecx],0
|
||||||
|
ret
|
||||||
|
fate_char_backspace:
|
||||||
|
test ecx,ecx
|
||||||
|
jz fate_char_done
|
||||||
|
dec ecx
|
||||||
|
mov fortuneFateLengths3D[ebx*4],ecx
|
||||||
|
mov BYTE PTR [esi+ecx],0
|
||||||
|
ret
|
||||||
|
fate_char_next:
|
||||||
|
inc ebx
|
||||||
|
cmp ebx,6
|
||||||
|
jb @F
|
||||||
|
xor ebx,ebx
|
||||||
|
@@:
|
||||||
|
mov fortuneFateField3D,ebx
|
||||||
|
fate_char_done:
|
||||||
|
ret
|
||||||
|
FortuneFateChar3D ENDP
|
||||||
|
|
||||||
|
; Validation is calendar-based, including leap years, not a birth-date heuristic.
|
||||||
|
ValidateFortuneBirth3D PROC uses ebx esi edi
|
||||||
|
local dayValue:DWORD,monthValue:DWORD
|
||||||
|
cmp fortuneFateLengths3D[8],10
|
||||||
|
jne fate_birth_bad
|
||||||
|
lea esi,fortuneFateFields3D[128]
|
||||||
|
cmp BYTE PTR [esi+2],'.'
|
||||||
|
jne fate_birth_bad
|
||||||
|
cmp BYTE PTR [esi+5],'.'
|
||||||
|
jne fate_birth_bad
|
||||||
|
xor ebx,ebx
|
||||||
|
xor edi,edi
|
||||||
|
fate_birth_parse:
|
||||||
|
movzx eax,BYTE PTR [esi+edi]
|
||||||
|
cmp edi,2
|
||||||
|
je fate_birth_day
|
||||||
|
cmp edi,5
|
||||||
|
je fate_birth_month
|
||||||
|
sub eax,'0'
|
||||||
|
cmp eax,9
|
||||||
|
ja fate_birth_bad
|
||||||
|
imul ebx,10
|
||||||
|
add ebx,eax
|
||||||
|
jmp fate_birth_next
|
||||||
|
fate_birth_day:
|
||||||
|
mov dayValue,ebx
|
||||||
|
xor ebx,ebx
|
||||||
|
jmp fate_birth_next
|
||||||
|
fate_birth_month:
|
||||||
|
mov monthValue,ebx
|
||||||
|
xor ebx,ebx
|
||||||
|
fate_birth_next:
|
||||||
|
inc edi
|
||||||
|
cmp edi,10
|
||||||
|
jb fate_birth_parse
|
||||||
|
cmp ebx,1900
|
||||||
|
jb fate_birth_bad
|
||||||
|
cmp ebx,2099
|
||||||
|
ja fate_birth_bad
|
||||||
|
mov eax,monthValue
|
||||||
|
dec eax
|
||||||
|
cmp eax,11
|
||||||
|
ja fate_birth_bad
|
||||||
|
movzx ecx,fortuneFateMonthDays3D[eax]
|
||||||
|
cmp eax,1
|
||||||
|
jne fate_birth_check_day
|
||||||
|
test ebx,3
|
||||||
|
jnz fate_birth_check_day
|
||||||
|
cmp ebx,1900
|
||||||
|
je fate_birth_check_day
|
||||||
|
inc ecx
|
||||||
|
fate_birth_check_day:
|
||||||
|
cmp dayValue,1
|
||||||
|
jb fate_birth_bad
|
||||||
|
cmp dayValue,ecx
|
||||||
|
ja fate_birth_bad
|
||||||
|
mov eax,1
|
||||||
|
ret
|
||||||
|
fate_birth_bad:
|
||||||
|
xor eax,eax
|
||||||
|
ret
|
||||||
|
ValidateFortuneBirth3D ENDP
|
||||||
|
|
||||||
|
ParseFortuneFateNumber3D PROC uses ebx esi slot:DWORD
|
||||||
|
mov eax,slot
|
||||||
|
mov ecx,fortuneFateLengths3D[eax*4]
|
||||||
|
test ecx,ecx
|
||||||
|
jz fate_number_bad
|
||||||
|
cmp ecx,3
|
||||||
|
ja fate_number_bad
|
||||||
|
shl eax,6
|
||||||
|
lea esi,fortuneFateFields3D[eax]
|
||||||
|
xor eax,eax
|
||||||
|
fate_number_parse:
|
||||||
|
movzx ebx,BYTE PTR [esi]
|
||||||
|
sub ebx,'0'
|
||||||
|
cmp ebx,9
|
||||||
|
ja fate_number_bad
|
||||||
|
imul eax,10
|
||||||
|
add eax,ebx
|
||||||
|
inc esi
|
||||||
|
loop fate_number_parse
|
||||||
|
cmp eax,100
|
||||||
|
ja fate_number_bad
|
||||||
|
ret
|
||||||
|
fate_number_bad:
|
||||||
|
mov eax,-1
|
||||||
|
ret
|
||||||
|
ParseFortuneFateNumber3D ENDP
|
||||||
|
|
||||||
|
SubmitFortuneFate3D PROC uses ebx
|
||||||
|
cmp fortuneSubMode3D,FORTUNE_SUBMODE_ORB
|
||||||
|
jne fate_submit_done
|
||||||
|
cmp fortunePhase3D,0
|
||||||
|
jne fate_submit_done
|
||||||
|
xor ebx,ebx
|
||||||
|
fate_submit_required:
|
||||||
|
cmp fortuneFateLengths3D[ebx*4],0
|
||||||
|
je fate_submit_missing
|
||||||
|
inc ebx
|
||||||
|
cmp ebx,6
|
||||||
|
jb fate_submit_required
|
||||||
|
call ValidateFortuneBirth3D
|
||||||
|
test eax,eax
|
||||||
|
jz fate_submit_date
|
||||||
|
invoke ParseFortuneFateNumber3D,4
|
||||||
|
cmp eax,-1
|
||||||
|
je fate_submit_low
|
||||||
|
mov fortuneFateLowValue3D,eax
|
||||||
|
invoke ParseFortuneFateNumber3D,5
|
||||||
|
cmp eax,-1
|
||||||
|
je fate_submit_high
|
||||||
|
cmp eax,fortuneFateLowValue3D
|
||||||
|
jb fate_submit_high
|
||||||
|
mov fortuneFateHighValue3D,eax
|
||||||
|
sub eax,fortuneFateLowValue3D
|
||||||
|
inc eax
|
||||||
|
; Exactly one draw, independent of identity. Renders and double clicks never reroll.
|
||||||
|
invoke RandomRange3D,eax
|
||||||
|
add eax,fortuneFateLowValue3D
|
||||||
|
mov fortuneFateResult3D,eax
|
||||||
|
mov fortunePhase3D,1
|
||||||
|
mov fortunePhaseTime3D,0
|
||||||
|
mov eax,animationClock3D
|
||||||
|
mov fortuneSessionClock3D,eax
|
||||||
|
invoke SetFortuneSpeech3D,OFFSET fortuneFateRising3D
|
||||||
|
fate_submit_done:
|
||||||
|
ret
|
||||||
|
fate_submit_missing:
|
||||||
|
mov fortuneFateField3D,ebx
|
||||||
|
invoke SetFortuneSpeech3D,OFFSET fortuneFateRequired3D
|
||||||
|
ret
|
||||||
|
fate_submit_date:
|
||||||
|
mov fortuneFateField3D,2
|
||||||
|
invoke SetFortuneSpeech3D,OFFSET fortuneFateDateError3D
|
||||||
|
ret
|
||||||
|
fate_submit_low:
|
||||||
|
mov fortuneFateField3D,4
|
||||||
|
jmp fate_submit_range
|
||||||
|
fate_submit_high:
|
||||||
|
mov fortuneFateField3D,5
|
||||||
|
fate_submit_range:
|
||||||
|
invoke SetFortuneSpeech3D,OFFSET fortuneFateRangeError3D
|
||||||
|
ret
|
||||||
|
SubmitFortuneFate3D ENDP
|
||||||
|
|
||||||
|
DrawFortuneFateForm3D PROC uses ebx esi edi
|
||||||
|
local px:DWORD,py:DWORD,edgeInk:DWORD
|
||||||
|
invoke DrawBoxBorder,8,149,304,74,00081322h,0046637Fh,1
|
||||||
|
invoke DrawBuckshotText3D,24,304,OFFSET fortuneFatePlay3D,0086ABBCh
|
||||||
|
xor esi,esi
|
||||||
|
fate_form_field:
|
||||||
|
mov eax,fortuneFateXs3D[esi*4]
|
||||||
|
mov px,eax
|
||||||
|
shr eax,1
|
||||||
|
mov ebx,fortuneFateYs3D[esi*4]
|
||||||
|
mov py,ebx
|
||||||
|
shr ebx,1
|
||||||
|
mov edgeInk,00314D65h
|
||||||
|
cmp esi,fortuneFateField3D
|
||||||
|
jne @F
|
||||||
|
mov edgeInk,0088DDEAh
|
||||||
|
@@:
|
||||||
|
invoke DrawBoxBorder,eax,ebx,144,11,000B1D30h,edgeInk,1
|
||||||
|
mov eax,px
|
||||||
|
add eax,8
|
||||||
|
mov ebx,py
|
||||||
|
sub ebx,9
|
||||||
|
invoke DrawBuckshotText3D,eax,ebx,fortuneFateLabels3D[esi*4],00A9C8D8h
|
||||||
|
mov edi,esi
|
||||||
|
shl edi,6
|
||||||
|
add edi,OFFSET fortuneFateFields3D
|
||||||
|
mov eax,px
|
||||||
|
add eax,8
|
||||||
|
mov ebx,py
|
||||||
|
add ebx,7
|
||||||
|
cmp esi,2
|
||||||
|
jne fate_form_value
|
||||||
|
cmp fortuneFateLengths3D[8],0
|
||||||
|
jne fate_form_value
|
||||||
|
invoke DrawBuckshotText3D,eax,ebx,OFFSET fortuneFateHint3D,005A7A95h
|
||||||
|
jmp fate_form_caret
|
||||||
|
fate_form_value:
|
||||||
|
invoke DrawBuckshotText3D,eax,ebx,edi,00E8EFF4h
|
||||||
|
fate_form_caret:
|
||||||
|
cmp esi,fortuneFateField3D
|
||||||
|
jne fate_form_next
|
||||||
|
test animationClock3D,200h
|
||||||
|
jnz fate_form_next
|
||||||
|
mov eax,fortuneFateLengths3D[esi*4]
|
||||||
|
shl eax,3
|
||||||
|
add eax,px
|
||||||
|
add eax,8
|
||||||
|
mov ebx,py
|
||||||
|
add ebx,7
|
||||||
|
invoke DrawBuckshotText3D,eax,ebx,OFFSET fortuneCaret3D,00B8F3FFh
|
||||||
|
fate_form_next:
|
||||||
|
inc esi
|
||||||
|
cmp esi,6
|
||||||
|
jb fate_form_field
|
||||||
|
ret
|
||||||
|
DrawFortuneFateForm3D ENDP
|
||||||
|
|
||||||
|
DrawFortuneFateIdentity3D PROC uses ebx esi edi
|
||||||
|
invoke DrawBoxBorder,8,190,304,33,00081322h,0046637Fh,1
|
||||||
|
xor esi,esi
|
||||||
|
fate_identity_field:
|
||||||
|
mov eax,fortuneFateXs3D[esi*4]
|
||||||
|
add eax,8
|
||||||
|
mov ebx,esi
|
||||||
|
shr ebx,1
|
||||||
|
imul ebx,20
|
||||||
|
add ebx,388
|
||||||
|
mov edi,esi
|
||||||
|
shl edi,6
|
||||||
|
add edi,OFFSET fortuneFateFields3D
|
||||||
|
cmp esi,4
|
||||||
|
jb @F
|
||||||
|
invoke DrawBuckshotText3D,eax,ebx,fortuneFateLabels3D[esi*4],0086ABBCh
|
||||||
|
mov eax,fortuneFateXs3D[esi*4]
|
||||||
|
add eax,40
|
||||||
|
@@:
|
||||||
|
invoke DrawBuckshotText3D,eax,ebx,edi,00E8EFF4h
|
||||||
|
inc esi
|
||||||
|
cmp esi,6
|
||||||
|
jb fate_identity_field
|
||||||
|
ret
|
||||||
|
DrawFortuneFateIdentity3D ENDP
|
||||||
|
|
||||||
|
; One resolver supplies the frame, sprite placement and its measured glass centre.
|
||||||
|
ResolveFortuneOrb3D PROC uses ebx
|
||||||
|
mov eax,fortunePhaseTime3D
|
||||||
|
shr eax,6
|
||||||
|
and eax,15
|
||||||
|
mov fortuneOrbFrame3D,eax
|
||||||
|
mov ebx,eax
|
||||||
|
mov fortuneOrbX3D,214
|
||||||
|
mov fortuneOrbY3D,195
|
||||||
|
cmp fortunePhase3D,1
|
||||||
|
jne fate_orb_anchor
|
||||||
|
mov eax,fortunePhaseTime3D
|
||||||
|
cmp eax,1400
|
||||||
|
jbe @F
|
||||||
|
mov eax,1400
|
||||||
|
@@:
|
||||||
|
imul eax,135
|
||||||
|
xor edx,edx
|
||||||
|
mov ecx,1400
|
||||||
|
div ecx
|
||||||
|
mov ecx,330
|
||||||
|
sub ecx,eax
|
||||||
|
mov fortuneOrbY3D,ecx
|
||||||
|
fate_orb_anchor:
|
||||||
|
mov eax,fortuneOrbAnchorX3D[ebx*4]
|
||||||
|
add eax,128
|
||||||
|
shr eax,8
|
||||||
|
add eax,fortuneOrbX3D
|
||||||
|
mov fortuneOrbCenterX3D,eax
|
||||||
|
mov eax,fortuneOrbAnchorY3D[ebx*4]
|
||||||
|
add eax,128
|
||||||
|
shr eax,8
|
||||||
|
add eax,fortuneOrbY3D
|
||||||
|
mov fortuneOrbCenterY3D,eax
|
||||||
|
ret
|
||||||
|
ResolveFortuneOrb3D ENDP
|
||||||
|
|
||||||
|
DrawFortuneFateResult3D PROC uses ebx esi edi
|
||||||
|
local numberX:DWORD,numberY:DWORD
|
||||||
|
cmp fortuneFateResult3D,100
|
||||||
|
ja fate_result_done
|
||||||
|
invoke FormatNumber,fortuneFateResult3D,OFFSET fortuneFateNumber3D
|
||||||
|
lea edi,fortuneFateNumber3D
|
||||||
|
xor ebx,ebx
|
||||||
|
fate_result_length:
|
||||||
|
cmp BYTE PTR [edi+ebx],0
|
||||||
|
je fate_result_place
|
||||||
|
inc ebx
|
||||||
|
jmp fate_result_length
|
||||||
|
fate_result_place:
|
||||||
|
dec ebx
|
||||||
|
imul ebx,20
|
||||||
|
add ebx,32
|
||||||
|
shr ebx,1
|
||||||
|
neg ebx
|
||||||
|
add ebx,fortuneOrbCenterX3D
|
||||||
|
mov numberX,ebx
|
||||||
|
mov eax,fortuneOrbCenterY3D
|
||||||
|
sub eax,24
|
||||||
|
mov numberY,eax
|
||||||
|
; Fade into the mist at a constant size; preserve opacity for later draws.
|
||||||
|
push animOpacity3D
|
||||||
|
mov eax,fortunePhaseTime3D
|
||||||
|
cmp eax,900
|
||||||
|
jbe @F
|
||||||
|
mov eax,900
|
||||||
|
@@:
|
||||||
|
imul eax,255
|
||||||
|
xor edx,edx
|
||||||
|
mov ecx,900
|
||||||
|
div ecx
|
||||||
|
mov animOpacity3D,eax
|
||||||
|
fate_result_digit:
|
||||||
|
movzx esi,BYTE PTR [edi]
|
||||||
|
test esi,esi
|
||||||
|
jz fate_result_restore
|
||||||
|
sub esi,'0'
|
||||||
|
invoke DrawAnimSprite3D,OFFSET fortuneSessionNumerals3D,esi,numberX,numberY,32,48
|
||||||
|
add numberX,20
|
||||||
|
inc edi
|
||||||
|
jmp fate_result_digit
|
||||||
|
fate_result_restore:
|
||||||
|
pop animOpacity3D
|
||||||
|
fate_result_done:
|
||||||
|
ret
|
||||||
|
DrawFortuneFateResult3D ENDP
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ MODE_FORTUNE equ 25
|
||||||
FORTUNE_SUBMODE_MENU equ 0
|
FORTUNE_SUBMODE_MENU equ 0
|
||||||
FORTUNE_SUBMODE_TAROT equ 1
|
FORTUNE_SUBMODE_TAROT equ 1
|
||||||
FORTUNE_SUBMODE_ORB equ 2
|
FORTUNE_SUBMODE_ORB equ 2
|
||||||
|
FORTUNE_SESSION_PACK_COUNT equ 8
|
||||||
BeginFortuneDialog3D PROTO
|
BeginFortuneDialog3D PROTO
|
||||||
HandleFortuneDialog3D PROTO
|
HandleFortuneDialog3D PROTO
|
||||||
RenderFortuneDialog3D PROTO
|
RenderFortuneDialog3D PROTO
|
||||||
|
|
@ -15,6 +16,15 @@ SetFortuneSpeech3D PROTO :DWORD
|
||||||
FortuneCardSpeech3D PROTO :DWORD
|
FortuneCardSpeech3D PROTO :DWORD
|
||||||
DrawFortuneSpeech3D PROTO
|
DrawFortuneSpeech3D PROTO
|
||||||
DrawFortuneSessionCard3D PROTO :DWORD
|
DrawFortuneSessionCard3D PROTO :DWORD
|
||||||
|
ResetFortuneFate3D PROTO
|
||||||
|
FortuneFateChar3D PROTO :DWORD
|
||||||
|
SubmitFortuneFate3D PROTO
|
||||||
|
ValidateFortuneBirth3D PROTO
|
||||||
|
ParseFortuneFateNumber3D PROTO :DWORD
|
||||||
|
DrawFortuneFateForm3D PROTO
|
||||||
|
DrawFortuneFateIdentity3D PROTO
|
||||||
|
DrawFortuneFateResult3D PROTO
|
||||||
|
ResolveFortuneOrb3D PROTO
|
||||||
.data
|
.data
|
||||||
fortuneSessionPacks3D LABEL BYTE
|
fortuneSessionPacks3D LABEL BYTE
|
||||||
fortuneSessionRoom3D AnimPack3D <>
|
fortuneSessionRoom3D AnimPack3D <>
|
||||||
|
|
@ -24,6 +34,7 @@ fortuneSessionGesture3D AnimPack3D <>
|
||||||
fortuneSessionOrbHands3D AnimPack3D <>
|
fortuneSessionOrbHands3D AnimPack3D <>
|
||||||
fortuneSessionMist3D AnimPack3D <>
|
fortuneSessionMist3D AnimPack3D <>
|
||||||
fortuneSessionCards3D AnimPack3D <>
|
fortuneSessionCards3D AnimPack3D <>
|
||||||
|
fortuneSessionNumerals3D AnimPack3D <>
|
||||||
fortuneSessionPath0 db "assets\animations\fortune\room-v1.bin",0
|
fortuneSessionPath0 db "assets\animations\fortune\room-v1.bin",0
|
||||||
fortuneSessionPath1 db "assets\animations\fortune\shuffle-v1.bin",0
|
fortuneSessionPath1 db "assets\animations\fortune\shuffle-v1.bin",0
|
||||||
fortuneSessionPath2 db "assets\animations\fortune\deal-v1.bin",0
|
fortuneSessionPath2 db "assets\animations\fortune\deal-v1.bin",0
|
||||||
|
|
@ -31,8 +42,10 @@ fortuneSessionPath3 db "assets\animations\fortune\gesture-v1.bin",0
|
||||||
fortuneSessionPath4 db "assets\animations\fortune\orb-hands-v1.bin",0
|
fortuneSessionPath4 db "assets\animations\fortune\orb-hands-v1.bin",0
|
||||||
fortuneSessionPath5 db "assets\animations\fortune\orb-mist-v1.bin",0
|
fortuneSessionPath5 db "assets\animations\fortune\orb-mist-v1.bin",0
|
||||||
fortuneSessionPath6 db "assets\animations\fortune\cards-v1.bin",0
|
fortuneSessionPath6 db "assets\animations\fortune\cards-v1.bin",0
|
||||||
|
fortuneSessionPath7 db "assets\animations\fortune\orb-numerals-v1.bin",0
|
||||||
fortuneSessionPaths3D dd OFFSET fortuneSessionPath0,OFFSET fortuneSessionPath1,OFFSET fortuneSessionPath2,OFFSET fortuneSessionPath3
|
fortuneSessionPaths3D dd OFFSET fortuneSessionPath0,OFFSET fortuneSessionPath1,OFFSET fortuneSessionPath2,OFFSET fortuneSessionPath3
|
||||||
dd OFFSET fortuneSessionPath4,OFFSET fortuneSessionPath5,OFFSET fortuneSessionPath6
|
dd OFFSET fortuneSessionPath4,OFFSET fortuneSessionPath5,OFFSET fortuneSessionPath6
|
||||||
|
dd OFFSET fortuneSessionPath7
|
||||||
fortuneSubMode3D dd 0
|
fortuneSubMode3D dd 0
|
||||||
fortunePhase3D dd 0
|
fortunePhase3D dd 0
|
||||||
fortunePhaseTime3D dd 0
|
fortunePhaseTime3D dd 0
|
||||||
|
|
@ -120,6 +133,46 @@ fortuneCardNames3D dd OFFSET fortuneCardName0,OFFSET fortuneCardName1,OFFSET for
|
||||||
dd OFFSET fortuneCardName12,OFFSET fortuneCardName13,OFFSET fortuneCardName14,OFFSET fortuneCardName15
|
dd OFFSET fortuneCardName12,OFFSET fortuneCardName13,OFFSET fortuneCardName14,OFFSET fortuneCardName15
|
||||||
dd OFFSET fortuneCardName16,OFFSET fortuneCardName17,OFFSET fortuneCardName18,OFFSET fortuneCardName19
|
dd OFFSET fortuneCardName16,OFFSET fortuneCardName17,OFFSET fortuneCardName18,OFFSET fortuneCardName19
|
||||||
dd OFFSET fortuneCardName20,OFFSET fortuneCardName21
|
dd OFFSET fortuneCardName20,OFFSET fortuneCardName21
|
||||||
|
; Local, ephemeral identity fields dress a fictional crystal-ball lottery.
|
||||||
|
fortuneFateField3D dd 0
|
||||||
|
fortuneFateLengths3D dd 6 dup(0)
|
||||||
|
fortuneFateFields3D db 384 dup(0)
|
||||||
|
fortuneFateLowValue3D dd 9
|
||||||
|
fortuneFateHighValue3D dd 10
|
||||||
|
fortuneFateResult3D dd -1
|
||||||
|
fortuneFateLimits3D dd 30,30,10,20,3,3
|
||||||
|
fortuneFateXs3D dd 16,336,16,336,16,336
|
||||||
|
fortuneFateYs3D dd 324,324,366,366,408,408
|
||||||
|
fortuneFateLabels3D dd OFFSET fortuneFateName3D,OFFSET fortuneFateSurname3D,OFFSET fortuneFateBirth3D,OFFSET fortuneFateGroup3D
|
||||||
|
dd OFFSET fortuneFateLow3D,OFFSET fortuneFateHigh3D
|
||||||
|
fortuneFateMonthDays3D db 31,28,31,30,31,30,31,31,30,31,30,31
|
||||||
|
fortuneFateNumber3D db 12 dup(0)
|
||||||
|
fortuneOrbFrame3D dd 0
|
||||||
|
fortuneOrbX3D dd 214
|
||||||
|
fortuneOrbY3D dd 195
|
||||||
|
fortuneOrbCenterX3D dd 0
|
||||||
|
fortuneOrbCenterY3D dd 0
|
||||||
|
include src_graphics\fortune_orb_art.inc
|
||||||
|
fortuneFateName3D db 200,204,223,0
|
||||||
|
fortuneFateSurname3D db 212,192,204,200,203,200,223,0
|
||||||
|
fortuneFateBirth3D db 196,192,210,192,32,208,206,198,196,197,205,200,223,0
|
||||||
|
fortuneFateGroup3D db 195,208,211,207,207,192,0
|
||||||
|
fortuneFateLow3D db 206,210,0
|
||||||
|
fortuneFateHigh3D db 196,206,0
|
||||||
|
fortuneFateStart3D db 207,208,200,199,194,192,210,220,0
|
||||||
|
fortuneFateEdit3D db 200,199,204,197,205,200,210,220,0
|
||||||
|
fortuneFateHint3D db 196,196,46,204,204,46,195,195,195,195,0
|
||||||
|
fortuneFateReady3D db 205,224,231,238,226,232,32,242,238,227,238,44,10,247,252,254,32,241,243,228,252,225,243,32,240,229,248,232,236,46,0
|
||||||
|
fortuneFateRising3D db 210,232,248,229,46,10,216,224,240,32,239,240,238,225,243,230,228,224,229,242,241,255,46,0
|
||||||
|
fortuneFateSwirl3D db 210,243,236,224,237,32,241,238,225,232,240,224,229,242,241,255,46,46,46,10,207,243,241,242,252,32,241,243,228,252,225,224,10,237,224,231,238,226,184,242,32,247,232,241,235,238,46,0
|
||||||
|
fortuneFateReveal3D db 208,229,248,229,237,232,229,32,239,240,232,237,255,242,238,46,10,216,224,240,32,237,224,231,226,224,235,32,247,232,241,235,238,46,0
|
||||||
|
fortuneFateRequired3D db 205,229,32,226,241,229,32,232,236,229,237,224,10,237,224,231,226,224,237,251,46,0
|
||||||
|
fortuneFateDateError3D db 210,224,234,238,233,32,228,224,242,251,32,237,229,242,46,10,205,224,231,238,226,232,32,228,229,237,252,32,240,238,230,228,229,237,232,255,46,0
|
||||||
|
fortuneFateRangeError3D db 205,224,231,238,226,232,32,227,240,224,237,232,246,251,58,10
|
||||||
|
db 238,242,32,236,229,237,252,248,229,227,238,32,234,32,225,238,235,252,248,229,236,243,44,10
|
||||||
|
db 238,242,32,48,32,228,238,32,49,48,48,46,0
|
||||||
|
fortuneFateCaption3D db 208,197,216,197,205,200,197,32,209,211,196,220,193,219,0
|
||||||
|
fortuneFatePlay3D db 200,195,208,206,194,206,201,32,208,200,210,211,192,203,0
|
||||||
.data?
|
.data?
|
||||||
fortuneBackground3D dd SCREEN_SIZE dup(?)
|
fortuneBackground3D dd SCREEN_SIZE dup(?)
|
||||||
.data
|
.data
|
||||||
|
|
|
||||||
3
src_graphics/fortune_orb_art.inc
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
; Generated by tools/generators/pack_fortune_orb.py; glass only, pedestal excluded.
|
||||||
|
fortuneOrbAnchorX3D dd 18261,16299,16299,14336,18176,16213,16213,14336,18176,16299,16299,14421,18091,16384,16128,14507
|
||||||
|
fortuneOrbAnchorY3D dd 14610,14637,14628,14630,14030,14040,14055,14066,13948,13933,13940,13922,12327,12342,12305,12324
|
||||||
|
|
@ -169,4 +169,5 @@ include src_graphics\hall_expansion_data.inc
|
||||||
include src_graphics\fortune_room_data.inc
|
include src_graphics\fortune_room_data.inc
|
||||||
include src_graphics\fortune_dialog_data.inc
|
include src_graphics\fortune_dialog_data.inc
|
||||||
include src_graphics\cabaret_data.inc
|
include src_graphics\cabaret_data.inc
|
||||||
|
include src_graphics\rooftop_data.inc
|
||||||
.code
|
.code
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,9 @@ interior_begin_finish:
|
||||||
BeginWalkableStairs3D ENDP
|
BeginWalkableStairs3D ENDP
|
||||||
|
|
||||||
UpdateInteriorTravel3D PROC
|
UpdateInteriorTravel3D PROC
|
||||||
|
call UpdateRoof3D
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
je interior_travel_done
|
||||||
call UpdateUpperEffects3D
|
call UpdateUpperEffects3D
|
||||||
call UpdateBasementDoor3D
|
call UpdateBasementDoor3D
|
||||||
call UpdateFortunePassage3D
|
call UpdateFortunePassage3D
|
||||||
|
|
@ -410,6 +413,11 @@ UpdateInteriorEye3D PROC
|
||||||
je UpdateStairHeight3D
|
je UpdateStairHeight3D
|
||||||
cmp engineMode,MODE_WALK
|
cmp engineMode,MODE_WALK
|
||||||
jne interior_eye_done
|
jne interior_eye_done
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
jne @F
|
||||||
|
call UpdateRoofEye3D
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
mov viewHorizon3D,HALF_H
|
mov viewHorizon3D,HALF_H
|
||||||
mov viewEye3D,HALL_STANDING_EYE
|
mov viewEye3D,HALL_STANDING_EYE
|
||||||
mov viewCeiling3D,FP_1*5/2
|
mov viewCeiling3D,FP_1*5/2
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,17 @@
|
||||||
RenderCeilingAndFloor PROC uses ebx esi edi
|
RenderCeilingAndFloor PROC uses ebx esi edi
|
||||||
local row:DWORD,distance:DWORD,sx:DWORD,sy:DWORD,wx:DWORD,wy:DWORD
|
local row:DWORD,distance:DWORD,sx:DWORD,sy:DWORD,wx:DWORD,wy:DWORD
|
||||||
local material:DWORD,shade:DWORD
|
local material:DWORD,shade:DWORD
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
jne @F
|
||||||
|
call DrawRoofSky3D
|
||||||
|
@@:
|
||||||
mov row, 0
|
mov row, 0
|
||||||
hall_plane_row:
|
hall_plane_row:
|
||||||
mov eax, row
|
mov eax, row
|
||||||
cmp eax, viewHorizon3D
|
cmp eax, viewHorizon3D
|
||||||
jge hall_plane_floor
|
jge hall_plane_floor
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
je hall_plane_next_row
|
||||||
cmp outdoorRender3D, 0
|
cmp outdoorRender3D, 0
|
||||||
jne hall_plane_next_row
|
jne hall_plane_next_row
|
||||||
mov ecx, viewHorizon3D
|
mov ecx, viewHorizon3D
|
||||||
|
|
@ -96,7 +102,18 @@ hall_plane_distance:
|
||||||
imul eax, SCREEN_W*4
|
imul eax, SCREEN_W*4
|
||||||
lea edi, screenBuffer[eax]
|
lea edi, screenBuffer[eax]
|
||||||
mov esi, SCREEN_W
|
mov esi, SCREEN_W
|
||||||
hall_plane_pixel:
|
hall_plane_pixel:
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
jne roof_floor_inside
|
||||||
|
cmp wx,FP_1*109/10
|
||||||
|
jl roof_floor_outside
|
||||||
|
cmp wx,FP_1*291/10
|
||||||
|
jg roof_floor_outside
|
||||||
|
cmp wy,FP_1*9/10
|
||||||
|
jl roof_floor_outside
|
||||||
|
cmp wy,FP_1*211/10
|
||||||
|
jg roof_floor_outside
|
||||||
|
roof_floor_inside:
|
||||||
mov ebx, material
|
mov ebx, material
|
||||||
cmp outdoorRender3D, 0
|
cmp outdoorRender3D, 0
|
||||||
je hall_plane_sample
|
je hall_plane_sample
|
||||||
|
|
@ -129,7 +146,13 @@ hall_plane_sample:
|
||||||
jl hall_plane_choose_hd
|
jl hall_plane_choose_hd
|
||||||
hall_plane_wood:
|
hall_plane_wood:
|
||||||
mov ebx, 85
|
mov ebx, 85
|
||||||
hall_plane_choose_hd:
|
hall_plane_choose_hd:
|
||||||
|
cmp ebx,ROOF_DECK
|
||||||
|
jne hall_plane_not_roof
|
||||||
|
mov ecx,roofMaterialArt3D.pixels
|
||||||
|
test ecx,ecx
|
||||||
|
jnz hall_plane_hd_coordinates
|
||||||
|
hall_plane_not_roof:
|
||||||
cmp ebx,132
|
cmp ebx,132
|
||||||
jb hall_plane_other_hd
|
jb hall_plane_other_hd
|
||||||
cmp ebx,135
|
cmp ebx,135
|
||||||
|
|
@ -237,6 +260,9 @@ hall_plane_next_row:
|
||||||
cmp row, SCREEN_H
|
cmp row, SCREEN_H
|
||||||
jb hall_plane_row
|
jb hall_plane_row
|
||||||
ret
|
ret
|
||||||
|
roof_floor_outside:
|
||||||
|
mov eax,[edi]
|
||||||
|
jmp hall_plane_store
|
||||||
RenderCeilingAndFloor ENDP
|
RenderCeilingAndFloor ENDP
|
||||||
|
|
||||||
RenderSprites PROC uses ebx esi edi
|
RenderSprites PROC uses ebx esi edi
|
||||||
|
|
@ -330,7 +356,8 @@ hall_sprites_done:
|
||||||
ret
|
ret
|
||||||
RenderSprites ENDP
|
RenderSprites ENDP
|
||||||
|
|
||||||
InitHall3D PROC uses esi edi
|
InitHall3D PROC uses esi edi
|
||||||
|
call InitRoof3D
|
||||||
lea esi, hallLayout3D
|
lea esi, hallLayout3D
|
||||||
lea edi, casinoMap
|
lea edi, casinoMap
|
||||||
mov ecx, 256
|
mov ecx, 256
|
||||||
|
|
@ -370,7 +397,8 @@ init_plane_done:
|
||||||
ret
|
ret
|
||||||
InitHall3D ENDP
|
InitHall3D ENDP
|
||||||
|
|
||||||
LoadHallAssets3D PROC
|
LoadHallAssets3D PROC
|
||||||
|
call LoadRoofAssets3D
|
||||||
call InitUpperSurfaces3D
|
call InitUpperSurfaces3D
|
||||||
call LoadFortuneArt3D
|
call LoadFortuneArt3D
|
||||||
invoke LoadAnimPack3D, OFFSET upperMaterialArt3D, OFFSET upperMaterialPath3D
|
invoke LoadAnimPack3D, OFFSET upperMaterialArt3D, OFFSET upperMaterialPath3D
|
||||||
|
|
@ -469,7 +497,8 @@ hall_load_sign:
|
||||||
ret
|
ret
|
||||||
LoadHallAssets3D ENDP
|
LoadHallAssets3D ENDP
|
||||||
|
|
||||||
FreeHallAssets3D PROC
|
FreeHallAssets3D PROC
|
||||||
|
call FreeRoofAssets3D
|
||||||
call FreeFortuneArt3D
|
call FreeFortuneArt3D
|
||||||
invoke FreeAnimPack3D, OFFSET upperMaterialArt3D
|
invoke FreeAnimPack3D, OFFSET upperMaterialArt3D
|
||||||
invoke FreeAnimPack3D,OFFSET upperGamesArt3D
|
invoke FreeAnimPack3D,OFFSET upperGamesArt3D
|
||||||
|
|
@ -574,6 +603,11 @@ surface_missing:
|
||||||
ResolveWorldSurface3D ENDP
|
ResolveWorldSurface3D ENDP
|
||||||
|
|
||||||
RenderHall3D PROC uses ebx esi
|
RenderHall3D PROC uses ebx esi
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
jne @F
|
||||||
|
call RenderRoof3D
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
cmp engineMode,MODE_STAIRS
|
cmp engineMode,MODE_STAIRS
|
||||||
je fortune_hall_stairs
|
je fortune_hall_stairs
|
||||||
cmp hallLevel3D,3
|
cmp hallLevel3D,3
|
||||||
|
|
@ -694,6 +728,7 @@ hall_render_lounge:
|
||||||
call RenderHallDressing3D
|
call RenderHallDressing3D
|
||||||
call RenderHallPortals3D
|
call RenderHallPortals3D
|
||||||
call RenderFortuneEntrance3D
|
call RenderFortuneEntrance3D
|
||||||
|
call RenderLift3D
|
||||||
call ApplyHallLighting3D
|
call ApplyHallLighting3D
|
||||||
call RenderInteriorViews3D
|
call RenderInteriorViews3D
|
||||||
call DrawBasementLeaf3D
|
call DrawBasementLeaf3D
|
||||||
|
|
@ -759,7 +794,12 @@ hall_target_done:
|
||||||
ret
|
ret
|
||||||
HallTarget3D ENDP
|
HallTarget3D ENDP
|
||||||
|
|
||||||
CheckHallInteractions3D PROC
|
CheckHallInteractions3D PROC
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
jne @F
|
||||||
|
call CheckRoofInteractions3D
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
cmp hallLevel3D,3
|
cmp hallLevel3D,3
|
||||||
jne @F
|
jne @F
|
||||||
call CheckFortuneInteractions3D
|
call CheckFortuneInteractions3D
|
||||||
|
|
@ -790,6 +830,7 @@ hall_check_other:
|
||||||
invoke HallTarget3D,FP_1*305/10,21*FP_1,0,OFFSET upperStairPrompt3D
|
invoke HallTarget3D,FP_1*305/10,21*FP_1,0,OFFSET upperStairPrompt3D
|
||||||
call CheckNpcInteractions3D
|
call CheckNpcInteractions3D
|
||||||
call CheckFortuneInteractions3D
|
call CheckFortuneInteractions3D
|
||||||
|
call CheckRoofInteractions3D
|
||||||
ret
|
ret
|
||||||
hall_check_bunker:
|
hall_check_bunker:
|
||||||
mov interactTargetId, 0
|
mov interactTargetId, 0
|
||||||
|
|
@ -805,6 +846,9 @@ TriggerHallInteraction3D PROC
|
||||||
mov eax,1
|
mov eax,1
|
||||||
ret
|
ret
|
||||||
@@:
|
@@:
|
||||||
|
call TryRoofInteraction3D
|
||||||
|
test eax,eax
|
||||||
|
jnz hall_trigger_handled
|
||||||
cmp interactTargetId,INTERACT_DARTS
|
cmp interactTargetId,INTERACT_DARTS
|
||||||
jne hall_not_darts
|
jne hall_not_darts
|
||||||
call BeginDarts3D
|
call BeginDarts3D
|
||||||
|
|
@ -978,6 +1022,11 @@ RenderBar3D PROC uses ebx
|
||||||
jne @F
|
jne @F
|
||||||
mov playerX,FP_1*25/2
|
mov playerX,FP_1*25/2
|
||||||
mov playerY,16*FP_1+FP_1/3
|
mov playerY,16*FP_1+FP_1/3
|
||||||
|
@@:
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
jne @F
|
||||||
|
mov playerX,15*FP_1
|
||||||
|
mov playerY,FP_1*63/10
|
||||||
@@:
|
@@:
|
||||||
mov viewHorizon3D, HALF_H
|
mov viewHorizon3D, HALF_H
|
||||||
mov viewEye3D, HALL_STANDING_EYE
|
mov viewEye3D, HALL_STANDING_EYE
|
||||||
|
|
@ -1007,6 +1056,10 @@ bar_draw_title:
|
||||||
cmp hallLevel3D,2
|
cmp hallLevel3D,2
|
||||||
jne @F
|
jne @F
|
||||||
mov eax,OFFSET upperBarName3D
|
mov eax,OFFSET upperBarName3D
|
||||||
|
@@:
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
jne @F
|
||||||
|
mov eax,OFFSET roofBarName3D
|
||||||
@@:
|
@@:
|
||||||
invoke DrawString8x8, 18,15,eax,00E7CA88h
|
invoke DrawString8x8, 18,15,eax,00E7CA88h
|
||||||
cmp barPhase3D, 2
|
cmp barPhase3D, 2
|
||||||
|
|
@ -1094,7 +1147,15 @@ city_world_guard_right:
|
||||||
ret
|
ret
|
||||||
RenderCityGuards3D ENDP
|
RenderCityGuards3D ENDP
|
||||||
|
|
||||||
CanWalkHall3D PROC uses esi ebx px:DWORD,py:DWORD
|
CanWalkHall3D PROC uses esi ebx px:DWORD,py:DWORD
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
jne @F
|
||||||
|
invoke RoofCanWalk3D,px,py
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
|
invoke LiftCanWalk3D,px,py
|
||||||
|
test eax,eax
|
||||||
|
jz hall_collision_blocked
|
||||||
cmp engineMode,MODE_STAIRS
|
cmp engineMode,MODE_STAIRS
|
||||||
je fortune_collision_stairs
|
je fortune_collision_stairs
|
||||||
cmp hallLevel3D,3
|
cmp hallLevel3D,3
|
||||||
|
|
@ -1404,6 +1465,7 @@ RenderPatrons3D ENDP
|
||||||
include src_graphics\world_dressing.inc
|
include src_graphics\world_dressing.inc
|
||||||
include src_graphics\terminal.inc
|
include src_graphics\terminal.inc
|
||||||
include src_graphics\hall_expansion.inc
|
include src_graphics\hall_expansion.inc
|
||||||
|
include src_graphics\rooftop.inc
|
||||||
include src_graphics\steel_door.inc
|
include src_graphics\steel_door.inc
|
||||||
include src_graphics\interior_portals.inc
|
include src_graphics\interior_portals.inc
|
||||||
include src_graphics\fortune_room.inc
|
include src_graphics\fortune_room.inc
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,15 @@
|
||||||
; ==============================================================================
|
; ==============================================================================
|
||||||
|
|
||||||
MODE_JACKBOX equ 28
|
MODE_JACKBOX equ 28
|
||||||
INTERACT_JACKBOX equ 48
|
INTERACT_JACKBOX equ 52
|
||||||
|
|
||||||
JACKBOX_X equ FP_1*306/10
|
JACKBOX_X equ FP_1*306/10
|
||||||
JACKBOX_Y equ FP_1*235/10
|
JACKBOX_Y equ FP_1*235/10
|
||||||
JACKBOX_TRACK_COUNT equ 3
|
JACKBOX_TRACK_COUNT equ 3
|
||||||
|
|
||||||
MATERIAL_JACKBOX_FRONT equ 161
|
MATERIAL_JACKBOX_FRONT equ 211
|
||||||
MATERIAL_JACKBOX_SIDE equ 121
|
MATERIAL_JACKBOX_SIDE equ 121
|
||||||
MATERIAL_JACKBOX_BACK equ 163
|
MATERIAL_JACKBOX_BACK equ 213
|
||||||
|
|
||||||
LoadJackboxArt3D PROTO
|
LoadJackboxArt3D PROTO
|
||||||
FreeJackboxArt3D PROTO
|
FreeJackboxArt3D PROTO
|
||||||
|
|
|
||||||
|
|
@ -431,6 +431,9 @@ present_geometry_ready:
|
||||||
jz @F
|
jz @F
|
||||||
invoke PatBlt, h3DDC, eax, 0, ecx, edi, 42h
|
invoke PatBlt, h3DDC, eax, 0, ecx, edi, 42h
|
||||||
@@:
|
@@:
|
||||||
|
invoke PresentRoofHD3D,h3DDC,offsetX,offsetY,viewW,viewH
|
||||||
|
test eax,eax
|
||||||
|
jnz present_done
|
||||||
invoke StretchDIBits, h3DDC, offsetX, offsetY, viewW, viewH, 0, 0, SCREEN_W, SCREEN_H, OFFSET screenBuffer, OFFSET bmi3D, 0, SRCCOPY
|
invoke StretchDIBits, h3DDC, offsetX, offsetY, viewW, viewH, 0, 0, SCREEN_W, SCREEN_H, OFFSET screenBuffer, OFFSET bmi3D, 0, SRCCOPY
|
||||||
present_done:
|
present_done:
|
||||||
ret
|
ret
|
||||||
|
|
|
||||||
1178
src_graphics/rooftop.inc
Normal file
382
src_graphics/rooftop_atmosphere.inc
Normal file
|
|
@ -0,0 +1,382 @@
|
||||||
|
; Directional dusk lighting and aerial perspective are applied to actual geometry.
|
||||||
|
ShadeRoofCityPixel3D PROC uses ebx esi edi color:DWORD,depth:DWORD,light:DWORD,material:DWORD
|
||||||
|
local fog:DWORD,inverseFog:DWORD,red:DWORD,green:DWORD,blue:DWORD,level:DWORD
|
||||||
|
local targetR:DWORD,targetG:DWORD,targetB:DWORD
|
||||||
|
mov roofPixelGlow3D,0
|
||||||
|
mov eax,depth
|
||||||
|
sar eax,16
|
||||||
|
test eax,eax
|
||||||
|
jns @F
|
||||||
|
xor eax,eax
|
||||||
|
@@:
|
||||||
|
cmp eax,1023
|
||||||
|
jbe @F
|
||||||
|
mov eax,1023
|
||||||
|
@@:
|
||||||
|
movzx eax,roofFog3D[eax]
|
||||||
|
mov fog,eax
|
||||||
|
neg eax
|
||||||
|
add eax,256
|
||||||
|
mov inverseFog,eax
|
||||||
|
mov eax,color
|
||||||
|
and eax,255
|
||||||
|
mov blue,eax
|
||||||
|
mov eax,color
|
||||||
|
shr eax,8
|
||||||
|
and eax,255
|
||||||
|
mov green,eax
|
||||||
|
mov eax,color
|
||||||
|
shr eax,16
|
||||||
|
and eax,255
|
||||||
|
mov red,eax
|
||||||
|
mov targetR,171
|
||||||
|
mov targetG,157
|
||||||
|
mov targetB,177
|
||||||
|
mov eax,light
|
||||||
|
mov level,eax
|
||||||
|
cmp roofNight3D,0
|
||||||
|
je roof_lighting_day
|
||||||
|
mov targetR,13
|
||||||
|
mov targetG,24
|
||||||
|
mov targetB,44
|
||||||
|
mov level,72
|
||||||
|
cmp material,ROOF_CITY_ROAD
|
||||||
|
jne @F
|
||||||
|
mov level,256
|
||||||
|
@@:
|
||||||
|
cmp material,ROOF_LIGHT
|
||||||
|
jne @F
|
||||||
|
mov level,256
|
||||||
|
mov roofPixelGlow3D,96
|
||||||
|
@@:
|
||||||
|
cmp roofLandmarkLight3D,0
|
||||||
|
je @F
|
||||||
|
mov level,148
|
||||||
|
@@:
|
||||||
|
cmp material,ROOF_BRASS
|
||||||
|
jne @F
|
||||||
|
mov level,228
|
||||||
|
cmp roofLandmarkLight3D,0
|
||||||
|
je @F
|
||||||
|
mov roofPixelGlow3D,12
|
||||||
|
@@:
|
||||||
|
; Emission is tagged in the actual window pixels, never inferred from gold trim.
|
||||||
|
cmp material,ROOF_FACADE
|
||||||
|
jb roof_lighting_apply
|
||||||
|
cmp material,ROOF_FACADE+7
|
||||||
|
jbe roof_lighting_window
|
||||||
|
cmp material,ROOF_MODERN_FACADE
|
||||||
|
jb roof_lighting_apply
|
||||||
|
cmp material,ROOF_MODERN_FACADE+7
|
||||||
|
ja roof_lighting_apply
|
||||||
|
roof_lighting_window:
|
||||||
|
mov eax,color
|
||||||
|
shr eax,24
|
||||||
|
cmp eax,255
|
||||||
|
jne roof_lighting_apply
|
||||||
|
mov level,310
|
||||||
|
mov roofPixelGlow3D,64
|
||||||
|
shr fog,1
|
||||||
|
mov eax,fog
|
||||||
|
neg eax
|
||||||
|
add eax,256
|
||||||
|
mov inverseFog,eax
|
||||||
|
jmp roof_lighting_apply
|
||||||
|
roof_lighting_day:
|
||||||
|
cmp material,ROOF_CITY_ROOF
|
||||||
|
jne @F
|
||||||
|
imul eax,red,180
|
||||||
|
shr eax,8
|
||||||
|
mov red,eax
|
||||||
|
imul eax,green,220
|
||||||
|
shr eax,8
|
||||||
|
mov green,eax
|
||||||
|
@@:
|
||||||
|
mov eax,red
|
||||||
|
imul eax,263
|
||||||
|
shr eax,8
|
||||||
|
cmp eax,255
|
||||||
|
jbe @F
|
||||||
|
mov eax,255
|
||||||
|
@@:
|
||||||
|
mov red,eax
|
||||||
|
imul eax,blue,235
|
||||||
|
shr eax,8
|
||||||
|
mov blue,eax
|
||||||
|
roof_lighting_apply:
|
||||||
|
mov eax,red
|
||||||
|
imul eax,level
|
||||||
|
shr eax,8
|
||||||
|
cmp eax,255
|
||||||
|
jbe @F
|
||||||
|
mov eax,255
|
||||||
|
@@:
|
||||||
|
imul eax,inverseFog
|
||||||
|
mov ecx,targetR
|
||||||
|
imul ecx,fog
|
||||||
|
add eax,ecx
|
||||||
|
shr eax,8
|
||||||
|
mov ebx,eax
|
||||||
|
shl ebx,16
|
||||||
|
mov eax,green
|
||||||
|
imul eax,level
|
||||||
|
shr eax,8
|
||||||
|
cmp eax,255
|
||||||
|
jbe @F
|
||||||
|
mov eax,255
|
||||||
|
@@:
|
||||||
|
imul eax,inverseFog
|
||||||
|
mov ecx,targetG
|
||||||
|
imul ecx,fog
|
||||||
|
add eax,ecx
|
||||||
|
shr eax,8
|
||||||
|
shl eax,8
|
||||||
|
or ebx,eax
|
||||||
|
mov eax,blue
|
||||||
|
imul eax,level
|
||||||
|
shr eax,8
|
||||||
|
cmp eax,255
|
||||||
|
jbe @F
|
||||||
|
mov eax,255
|
||||||
|
@@:
|
||||||
|
imul eax,inverseFog
|
||||||
|
mov ecx,targetB
|
||||||
|
imul ecx,fog
|
||||||
|
add eax,ecx
|
||||||
|
shr eax,8
|
||||||
|
or eax,ebx
|
||||||
|
ret
|
||||||
|
ShadeRoofCityPixel3D ENDP
|
||||||
|
|
||||||
|
SampleRoofGroundLight3D PROC uses ebx esi edi color:DWORD,wx:DWORD,wy:DWORD
|
||||||
|
mov eax,color
|
||||||
|
cmp roofLightingArt3D.pixels,0
|
||||||
|
je roof_ground_light_done
|
||||||
|
mov eax,wx
|
||||||
|
sar eax,17
|
||||||
|
add eax,256
|
||||||
|
cmp eax,511
|
||||||
|
ja roof_ground_light_original
|
||||||
|
mov ebx,eax
|
||||||
|
mov eax,wy
|
||||||
|
sar eax,17
|
||||||
|
add eax,256
|
||||||
|
cmp eax,511
|
||||||
|
ja roof_ground_light_original
|
||||||
|
shl eax,9
|
||||||
|
add eax,ebx
|
||||||
|
mov esi,roofLightingArt3D.pixels
|
||||||
|
cmp roofNight3D,0
|
||||||
|
je @F
|
||||||
|
add esi,512*512*4
|
||||||
|
@@:
|
||||||
|
mov edx,[esi+eax*4]
|
||||||
|
mov edi,edx
|
||||||
|
and edx,255
|
||||||
|
mov eax,color
|
||||||
|
and eax,255
|
||||||
|
imul eax,edx
|
||||||
|
shr eax,8
|
||||||
|
mov ebx,eax
|
||||||
|
mov edx,edi
|
||||||
|
shr edx,8
|
||||||
|
and edx,255
|
||||||
|
mov eax,color
|
||||||
|
shr eax,8
|
||||||
|
and eax,255
|
||||||
|
imul eax,edx
|
||||||
|
and eax,0FF00h
|
||||||
|
or ebx,eax
|
||||||
|
mov edx,edi
|
||||||
|
shr edx,16
|
||||||
|
and edx,255
|
||||||
|
mov eax,color
|
||||||
|
shr eax,16
|
||||||
|
and eax,255
|
||||||
|
imul eax,edx
|
||||||
|
and eax,0FF00h
|
||||||
|
shl eax,8
|
||||||
|
or eax,ebx
|
||||||
|
ret
|
||||||
|
roof_ground_light_original:
|
||||||
|
mov eax,color
|
||||||
|
roof_ground_light_done:
|
||||||
|
ret
|
||||||
|
SampleRoofGroundLight3D ENDP
|
||||||
|
|
||||||
|
PrepareRoofCityAA3D PROC uses ebx esi edi
|
||||||
|
mov roofAAStill3D,0
|
||||||
|
cmp roofAAValid3D,0
|
||||||
|
je roof_aa_moving
|
||||||
|
mov eax,playerX
|
||||||
|
cmp eax,roofAAX3D
|
||||||
|
jne roof_aa_moving
|
||||||
|
mov eax,playerY
|
||||||
|
cmp eax,roofAAY3D
|
||||||
|
jne roof_aa_moving
|
||||||
|
mov eax,playerAngle
|
||||||
|
cmp eax,roofAAAngle3D
|
||||||
|
jne roof_aa_moving
|
||||||
|
mov eax,viewEye3D
|
||||||
|
cmp eax,roofAAEye3D
|
||||||
|
jne roof_aa_moving
|
||||||
|
mov eax,viewHorizon3D
|
||||||
|
cmp eax,roofAAHorizon3D
|
||||||
|
jne roof_aa_moving
|
||||||
|
mov eax,roofNight3D
|
||||||
|
cmp eax,roofAATheme3D
|
||||||
|
jne roof_aa_moving
|
||||||
|
mov roofAAStill3D,1
|
||||||
|
inc roofAAFrame3D
|
||||||
|
and roofAAFrame3D,3
|
||||||
|
jmp roof_aa_save_view
|
||||||
|
roof_aa_moving:
|
||||||
|
mov roofAAFrame3D,0
|
||||||
|
roof_aa_save_view:
|
||||||
|
mov eax,playerX
|
||||||
|
mov roofAAX3D,eax
|
||||||
|
mov eax,playerY
|
||||||
|
mov roofAAY3D,eax
|
||||||
|
mov eax,playerAngle
|
||||||
|
mov roofAAAngle3D,eax
|
||||||
|
mov eax,viewEye3D
|
||||||
|
mov roofAAEye3D,eax
|
||||||
|
mov eax,viewHorizon3D
|
||||||
|
mov roofAAHorizon3D,eax
|
||||||
|
mov eax,roofNight3D
|
||||||
|
mov roofAATheme3D,eax
|
||||||
|
mov eax,roofAAFrame3D
|
||||||
|
shl eax,1
|
||||||
|
sub eax,3
|
||||||
|
mov ebx,eax
|
||||||
|
mov eax,playerPlaneX
|
||||||
|
imul ebx
|
||||||
|
cdq
|
||||||
|
mov ecx,SCREEN_W*4
|
||||||
|
idiv ecx
|
||||||
|
mov esi,eax
|
||||||
|
mov eax,playerPlaneY
|
||||||
|
imul ebx
|
||||||
|
cdq
|
||||||
|
idiv ecx
|
||||||
|
mov edi,eax
|
||||||
|
xor ebx,ebx
|
||||||
|
roof_aa_shift_ray:
|
||||||
|
add cityRayX3D[ebx*4],esi
|
||||||
|
add cityRayY3D[ebx*4],edi
|
||||||
|
inc ebx
|
||||||
|
cmp ebx,SCREEN_W
|
||||||
|
jb roof_aa_shift_ray
|
||||||
|
ret
|
||||||
|
PrepareRoofCityAA3D ENDP
|
||||||
|
|
||||||
|
FinishRoofCityAA3D PROC uses ebx esi edi
|
||||||
|
xor edi,edi
|
||||||
|
roof_aa_pixel:
|
||||||
|
mov eax,screenBuffer[edi*4]
|
||||||
|
cmp roofAAStill3D,0
|
||||||
|
je roof_aa_store
|
||||||
|
cmp roofCityMask3D[edi],1
|
||||||
|
jne roof_aa_store
|
||||||
|
and eax,00FCFCFCh
|
||||||
|
shr eax,2
|
||||||
|
mov edx,roofAAHistory3D[edi*4]
|
||||||
|
and edx,00FCFCFCh
|
||||||
|
shr edx,2
|
||||||
|
imul edx,3
|
||||||
|
add eax,edx
|
||||||
|
mov screenBuffer[edi*4],eax
|
||||||
|
roof_aa_store:
|
||||||
|
mov roofAAHistory3D[edi*4],eax
|
||||||
|
inc edi
|
||||||
|
cmp edi,SCREEN_SIZE
|
||||||
|
jb roof_aa_pixel
|
||||||
|
mov roofAAValid3D,1
|
||||||
|
ret
|
||||||
|
FinishRoofCityAA3D ENDP
|
||||||
|
|
||||||
|
RenderRoofCityBloom3D PROC uses ebx esi edi
|
||||||
|
local pixel:DWORD,color:DWORD,amount:DWORD,rowOffset:DWORD,columnOffset:DWORD
|
||||||
|
local target:DWORD,red:DWORD,green:DWORD,blue:DWORD
|
||||||
|
cmp roofNight3D,0
|
||||||
|
je roof_bloom_done
|
||||||
|
mov pixel,SCREEN_W+1
|
||||||
|
roof_bloom_source:
|
||||||
|
mov esi,pixel
|
||||||
|
movzx eax,roofGlowMask3D[esi]
|
||||||
|
test eax,eax
|
||||||
|
jz roof_bloom_next_source
|
||||||
|
shr eax,2
|
||||||
|
mov amount,eax
|
||||||
|
mov eax,screenBuffer[esi*4]
|
||||||
|
mov color,eax
|
||||||
|
mov rowOffset,-1
|
||||||
|
roof_bloom_row:
|
||||||
|
mov columnOffset,-1
|
||||||
|
roof_bloom_column:
|
||||||
|
mov eax,rowOffset
|
||||||
|
imul eax,SCREEN_W
|
||||||
|
add eax,columnOffset
|
||||||
|
add eax,pixel
|
||||||
|
cmp eax,SCREEN_SIZE
|
||||||
|
jae roof_bloom_next_column
|
||||||
|
mov target,eax
|
||||||
|
lea edi,screenBuffer[eax*4]
|
||||||
|
mov ebx,[edi]
|
||||||
|
mov eax,color
|
||||||
|
and eax,255
|
||||||
|
imul eax,amount
|
||||||
|
shr eax,8
|
||||||
|
movzx ecx,bl
|
||||||
|
add eax,ecx
|
||||||
|
cmp eax,255
|
||||||
|
jbe @F
|
||||||
|
mov eax,255
|
||||||
|
@@:
|
||||||
|
mov blue,eax
|
||||||
|
mov eax,color
|
||||||
|
shr eax,8
|
||||||
|
and eax,255
|
||||||
|
imul eax,amount
|
||||||
|
shr eax,8
|
||||||
|
mov ecx,ebx
|
||||||
|
shr ecx,8
|
||||||
|
and ecx,255
|
||||||
|
add eax,ecx
|
||||||
|
cmp eax,255
|
||||||
|
jbe @F
|
||||||
|
mov eax,255
|
||||||
|
@@:
|
||||||
|
mov green,eax
|
||||||
|
mov eax,color
|
||||||
|
shr eax,16
|
||||||
|
and eax,255
|
||||||
|
imul eax,amount
|
||||||
|
shr eax,8
|
||||||
|
shr ebx,16
|
||||||
|
and ebx,255
|
||||||
|
add eax,ebx
|
||||||
|
cmp eax,255
|
||||||
|
jbe @F
|
||||||
|
mov eax,255
|
||||||
|
@@:
|
||||||
|
shl eax,16
|
||||||
|
mov ecx,green
|
||||||
|
shl ecx,8
|
||||||
|
or eax,ecx
|
||||||
|
or eax,blue
|
||||||
|
mov [edi],eax
|
||||||
|
roof_bloom_next_column:
|
||||||
|
inc columnOffset
|
||||||
|
cmp columnOffset,1
|
||||||
|
jle roof_bloom_column
|
||||||
|
inc rowOffset
|
||||||
|
cmp rowOffset,1
|
||||||
|
jle roof_bloom_row
|
||||||
|
roof_bloom_next_source:
|
||||||
|
inc pixel
|
||||||
|
cmp pixel,SCREEN_SIZE-SCREEN_W-1
|
||||||
|
jb roof_bloom_source
|
||||||
|
roof_bloom_done:
|
||||||
|
ret
|
||||||
|
RenderRoofCityBloom3D ENDP
|
||||||
156
src_graphics/rooftop_city_life.inc
Normal file
|
|
@ -0,0 +1,156 @@
|
||||||
|
RenderRoofCityLamps3D PROC uses ebx esi edi
|
||||||
|
local px:DWORD,py:DWORD,x1:DWORD,y1:DWORD
|
||||||
|
xor esi,esi
|
||||||
|
roof_city_lamp:
|
||||||
|
mov eax,roofCityLamps3D[esi*8]
|
||||||
|
mov px,eax
|
||||||
|
mov edx,roofCityLamps3D[esi*8+4]
|
||||||
|
mov py,edx
|
||||||
|
invoke ProjectCityPoint3D,eax,edx
|
||||||
|
cmp edx,FP_1
|
||||||
|
jle roof_city_lamp_next
|
||||||
|
cmp edx,180*FP_1
|
||||||
|
ja roof_city_lamp_next
|
||||||
|
cmp eax,-8
|
||||||
|
jl roof_city_lamp_next
|
||||||
|
cmp eax,SCREEN_W+8
|
||||||
|
jg roof_city_lamp_next
|
||||||
|
mov eax,px
|
||||||
|
add eax,FP_1/12
|
||||||
|
mov x1,eax
|
||||||
|
mov eax,py
|
||||||
|
add eax,FP_1/12
|
||||||
|
mov y1,eax
|
||||||
|
invoke DrawRoofSolid3D,px,x1,py,y1,ROOF_CITY_STREET_Z,ROOF_CITY_STREET_Z+5*FP_1,ROOF_METAL
|
||||||
|
mov eax,px
|
||||||
|
sub eax,FP_1/5
|
||||||
|
mov edx,px
|
||||||
|
add edx,FP_1/5
|
||||||
|
mov ecx,py
|
||||||
|
sub ecx,FP_1/5
|
||||||
|
mov edi,py
|
||||||
|
add edi,FP_1/5
|
||||||
|
invoke DrawRoofSolid3D,eax,edx,ecx,edi,ROOF_CITY_STREET_Z+FP_1*49/10,ROOF_CITY_STREET_Z+FP_1*51/10,ROOF_LIGHT
|
||||||
|
roof_city_lamp_next:
|
||||||
|
inc esi
|
||||||
|
cmp esi,ROOF_CITY_LAMP_COUNT
|
||||||
|
jb roof_city_lamp
|
||||||
|
ret
|
||||||
|
RenderRoofCityLamps3D ENDP
|
||||||
|
|
||||||
|
DrawRoofCar3D PROC uses ebx esi edi centreX:DWORD,centreY:DWORD,axis:DWORD,style:DWORD
|
||||||
|
local x0:DWORD,x1:DWORD,y0:DWORD,y1:DWORD,bodyMat:DWORD,cabinX0:DWORD,cabinX1:DWORD
|
||||||
|
local cabinY0:DWORD,cabinY1:DWORD
|
||||||
|
invoke ProjectCityPoint3D,centreX,centreY
|
||||||
|
cmp edx,FP_1
|
||||||
|
jle roof_car_done
|
||||||
|
cmp eax,-30
|
||||||
|
jl roof_car_done
|
||||||
|
cmp eax,SCREEN_W+30
|
||||||
|
jg roof_car_done
|
||||||
|
mov ebx,FP_1*19/10
|
||||||
|
mov ecx,FP_1*8/10
|
||||||
|
cmp axis,0
|
||||||
|
je @F
|
||||||
|
xchg ebx,ecx
|
||||||
|
@@:
|
||||||
|
mov eax,centreX
|
||||||
|
sub eax,ebx
|
||||||
|
mov x0,eax
|
||||||
|
mov eax,centreX
|
||||||
|
add eax,ebx
|
||||||
|
mov x1,eax
|
||||||
|
mov eax,centreY
|
||||||
|
sub eax,ecx
|
||||||
|
mov y0,eax
|
||||||
|
mov eax,centreY
|
||||||
|
add eax,ecx
|
||||||
|
mov y1,eax
|
||||||
|
mov bodyMat,ROOF_CITY_ROOF
|
||||||
|
test style,1
|
||||||
|
jz @F
|
||||||
|
mov bodyMat,ROOF_BRASS
|
||||||
|
@@:
|
||||||
|
invoke DrawRoofSolid3D,x0,x1,y0,y1,ROOF_CITY_STREET_Z+FP_1/4,ROOF_CITY_STREET_Z+FP_1*85/100,bodyMat
|
||||||
|
mov ebx,FP_1*9/10
|
||||||
|
mov ecx,FP_1*65/100
|
||||||
|
cmp axis,0
|
||||||
|
je @F
|
||||||
|
xchg ebx,ecx
|
||||||
|
@@:
|
||||||
|
mov eax,centreX
|
||||||
|
sub eax,ebx
|
||||||
|
mov cabinX0,eax
|
||||||
|
mov eax,centreX
|
||||||
|
add eax,ebx
|
||||||
|
mov cabinX1,eax
|
||||||
|
mov eax,centreY
|
||||||
|
sub eax,ecx
|
||||||
|
mov cabinY0,eax
|
||||||
|
mov eax,centreY
|
||||||
|
add eax,ecx
|
||||||
|
mov cabinY1,eax
|
||||||
|
invoke DrawRoofSolid3D,cabinX0,cabinX1,cabinY0,cabinY1,ROOF_CITY_STREET_Z+FP_1*85/100,ROOF_CITY_STREET_Z+FP_1*135/100,ROOF_MODERN_FACADE+1
|
||||||
|
roof_car_done:
|
||||||
|
ret
|
||||||
|
DrawRoofCar3D ENDP
|
||||||
|
|
||||||
|
RenderRoofTraffic3D PROC uses ebx esi edi
|
||||||
|
local px:DWORD,py:DWORD,material:DWORD
|
||||||
|
xor esi,esi
|
||||||
|
roof_city_car:
|
||||||
|
mov eax,esi
|
||||||
|
imul eax,17000
|
||||||
|
add eax,animationClock3D
|
||||||
|
mov ecx,393
|
||||||
|
mul ecx
|
||||||
|
mov ecx,340*FP_1
|
||||||
|
div ecx
|
||||||
|
sub edx,160*FP_1
|
||||||
|
mov px,edx
|
||||||
|
mov py,-FP_1*59/10
|
||||||
|
test esi,1
|
||||||
|
jz @F
|
||||||
|
neg edx
|
||||||
|
mov px,edx
|
||||||
|
mov py,-FP_1*81/10
|
||||||
|
@@:
|
||||||
|
cmp esi,4
|
||||||
|
jb roof_city_car_x
|
||||||
|
mov eax,px
|
||||||
|
mov py,eax
|
||||||
|
mov px,FP_1*391/10
|
||||||
|
test esi,1
|
||||||
|
jz @F
|
||||||
|
mov px,FP_1*369/10
|
||||||
|
@@:
|
||||||
|
invoke DrawRoofCar3D,px,py,1,esi
|
||||||
|
jmp roof_city_car_next
|
||||||
|
roof_city_car_x:
|
||||||
|
invoke DrawRoofCar3D,px,py,0,esi
|
||||||
|
roof_city_car_next:
|
||||||
|
inc esi
|
||||||
|
cmp esi,8
|
||||||
|
jb roof_city_car
|
||||||
|
xor esi,esi
|
||||||
|
roof_city_boat:
|
||||||
|
imul eax,esi,47000
|
||||||
|
add eax,animationClock3D
|
||||||
|
mov ecx,98
|
||||||
|
mul ecx
|
||||||
|
mov ecx,340*FP_1
|
||||||
|
div ecx
|
||||||
|
sub edx,160*FP_1
|
||||||
|
mov px,edx
|
||||||
|
mov py,68*FP_1
|
||||||
|
invoke DrawRoofEllipsoid3D,px,py,ROOF_CITY_STREET_Z-FP_1*16/10,3*FP_1,FP_1,FP_1/2,ROOF_CITY_ROOF
|
||||||
|
mov eax,px
|
||||||
|
sub eax,FP_1
|
||||||
|
mov ebx,px
|
||||||
|
add ebx,FP_1
|
||||||
|
invoke DrawRoofSolid3D,eax,ebx,FP_1*674/10,FP_1*686/10,ROOF_CITY_STREET_Z-FP_1*14/10,ROOF_CITY_STREET_Z-FP_1*7/10,ROOF_PLASTER
|
||||||
|
inc esi
|
||||||
|
cmp esi,3
|
||||||
|
jb roof_city_boat
|
||||||
|
ret
|
||||||
|
RenderRoofTraffic3D ENDP
|
||||||
202
src_graphics/rooftop_data.inc
Normal file
|
|
@ -0,0 +1,202 @@
|
||||||
|
; Native walkable rooftop and elevator share the existing hall engine.
|
||||||
|
HALL_ROOF equ 4
|
||||||
|
INTERACT_LIFT_CALL equ 48
|
||||||
|
INTERACT_LIFT_TRAVEL equ 49
|
||||||
|
INTERACT_ROOF_SEAT equ 50
|
||||||
|
INTERACT_ROOF_RAIL equ 51
|
||||||
|
ROOF_STANDING_EYE equ FP_1*165/100
|
||||||
|
ROOF_SEATED_EYE equ FP_1*118/100
|
||||||
|
ROOF_RAIL_HEIGHT equ FP_1*102/100
|
||||||
|
ROOF_FAR_DEPTH equ FP_1*1024
|
||||||
|
ROOF_FACADE equ 186
|
||||||
|
ROOF_FOLIAGE equ 194
|
||||||
|
ROOF_EARTH equ 195
|
||||||
|
ROOF_CITY_ROOF equ 196
|
||||||
|
ROOF_CITY_ROAD equ 197
|
||||||
|
ROOF_CITY_WATER equ 198
|
||||||
|
ROOF_MODERN_FACADE equ 199
|
||||||
|
ROOF_CITY_LAWN equ 207
|
||||||
|
ROOF_LAST_MATERIAL equ 207
|
||||||
|
ROOF_CITY_STREET_Z equ -60*FP_1
|
||||||
|
ROOF_DECK equ 161
|
||||||
|
ROOF_STONE equ 162
|
||||||
|
ROOF_TEAL equ 163
|
||||||
|
ROOF_IVORY equ 164
|
||||||
|
ROOF_METAL equ 165
|
||||||
|
ROOF_BRASS equ 166
|
||||||
|
ROOF_MARBLE equ 167
|
||||||
|
ROOF_PLASTER equ 168
|
||||||
|
ROOF_DOOR equ 169
|
||||||
|
ROOF_BUTTON equ 170
|
||||||
|
ROOF_BAR_FRONT equ 171
|
||||||
|
ROOF_BOTTLES equ 172
|
||||||
|
ROOF_TREE equ 173
|
||||||
|
ROOF_GRASS equ 174
|
||||||
|
ROOF_LANTERN equ 175
|
||||||
|
ROOF_TABLE equ 176
|
||||||
|
ROOF_INDICATOR equ 177
|
||||||
|
ROOF_LIGHT equ 178
|
||||||
|
ROOF_SOFA_FRONT equ 179
|
||||||
|
ROOF_SOFA_SIDE equ 180
|
||||||
|
ROOF_SOFA_BACK equ 181
|
||||||
|
ROOF_CHAIR_FRONT equ 182
|
||||||
|
ROOF_CHAIR_SIDE equ 183
|
||||||
|
ROOF_CHAIR_BACK equ 184
|
||||||
|
ROOF_BAR_STOOL equ 185
|
||||||
|
ROOF_SEAT_COUNT equ 13
|
||||||
|
ROOF_TREE_COUNT equ 8
|
||||||
|
ROOF_GUEST_COUNT equ 8
|
||||||
|
LIFT_CENTRE_X equ FP_1*244/10
|
||||||
|
LIFT_FRONT_Y equ FP_1*345/100
|
||||||
|
InitRoof3D PROTO
|
||||||
|
LoadRoofAssets3D PROTO
|
||||||
|
FreeRoofAssets3D PROTO
|
||||||
|
ResolveRoofSurface3D PROTO :DWORD
|
||||||
|
DrawRoofSky3D PROTO
|
||||||
|
RenderRoof3D PROTO
|
||||||
|
RenderLift3D PROTO
|
||||||
|
UpdateRoof3D PROTO
|
||||||
|
CheckRoofInteractions3D PROTO
|
||||||
|
TryRoofInteraction3D PROTO
|
||||||
|
LiftCanWalk3D PROTO :DWORD,:DWORD
|
||||||
|
RoofCanWalk3D PROTO :DWORD,:DWORD
|
||||||
|
UpdateRoofEye3D PROTO
|
||||||
|
UpdateRoofLook3D PROTO
|
||||||
|
StandFromRoofSeat3D PROTO
|
||||||
|
DrawRoofSofa3D PROTO :DWORD,:DWORD
|
||||||
|
DrawRoofChair3D PROTO :DWORD,:DWORD,:DWORD
|
||||||
|
DrawRoofCoffee3D PROTO :DWORD,:DWORD
|
||||||
|
DrawRoofTree3D PROTO :DWORD,:DWORD,:DWORD
|
||||||
|
DrawRoofBulb3D PROTO :DWORD,:DWORD,:DWORD
|
||||||
|
UpdateRoofIndicator3D PROTO
|
||||||
|
DrawRoofSolid3D PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
DrawRoofUpholstery3D PROTO :DWORD,:DWORD,:DWORD
|
||||||
|
DrawRoofPlanter3D PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
RenderRoofDistrict3D PROTO
|
||||||
|
UpdateRoofGuests3D PROTO :DWORD
|
||||||
|
CheckRoofRail3D PROTO
|
||||||
|
StartRoofLean3D PROTO
|
||||||
|
RenderRoofLean3D PROTO
|
||||||
|
DrawRoofHandsPlane3D PROTO :DWORD,:DWORD,:DWORD
|
||||||
|
ShadeRoofNight3D PROTO
|
||||||
|
PrepareRoofFloorDepth3D PROTO
|
||||||
|
DrawRoofEllipsoid3D PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
DrawRoofPadding3D PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
RenderRoofCityGround3D PROTO
|
||||||
|
RenderRoofLandmarks3D PROTO
|
||||||
|
RenderRoofCityParks3D PROTO
|
||||||
|
ShadeRoofCityPixel3D PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
DrawRoofSlope3D PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
DrawRoofPyramid3D PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
SampleRoofGroundLight3D PROTO :DWORD,:DWORD,:DWORD
|
||||||
|
RenderRoofCityLamps3D PROTO
|
||||||
|
RenderRoofTraffic3D PROTO
|
||||||
|
DrawRoofCar3D PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
PrepareRoofCityAA3D PROTO
|
||||||
|
FinishRoofCityAA3D PROTO
|
||||||
|
RenderRoofCityBloom3D PROTO
|
||||||
|
include src_graphics\rooftop_district_data.inc
|
||||||
|
include src_graphics\rooftop_map.inc
|
||||||
|
include src_graphics\rooftop_gl_data.inc
|
||||||
|
.data
|
||||||
|
roofSkyArt3D AnimPack3D <>
|
||||||
|
roofMaterialArt3D AnimPack3D <>
|
||||||
|
roofDetailArt3D AnimPack3D <>
|
||||||
|
roofCityArt3D AnimPack3D <>
|
||||||
|
roofCityNightArt3D AnimPack3D <>
|
||||||
|
roofHandsArt3D AnimPack3D <>
|
||||||
|
roofNightArt3D AnimPack3D <>
|
||||||
|
roofLightingArt3D AnimPack3D <>
|
||||||
|
roofLightingPath3D db "assets\animations\rooftop\lighting-v1.bin",0
|
||||||
|
roofCityPath3D db "assets\animations\rooftop\city-v1.bin",0
|
||||||
|
roofCityNightPath3D db "assets\animations\rooftop\city-night-v1.bin",0
|
||||||
|
roofHandsPath3D db "assets\animations\rooftop\rail-hands-v1.bin",0
|
||||||
|
roofNightPath3D db "assets\animations\rooftop\night-v1.bin",0
|
||||||
|
roofNight3D dd 0
|
||||||
|
roofCityPass3D dd 0
|
||||||
|
roofLandmarkLight3D dd 0
|
||||||
|
roofPixelGlow3D dd 0
|
||||||
|
roofAAValid3D dd 0
|
||||||
|
roofAAStill3D dd 0
|
||||||
|
roofAAFrame3D dd 0
|
||||||
|
roofAAX3D dd 0
|
||||||
|
roofAAY3D dd 0
|
||||||
|
roofAAAngle3D dd 0
|
||||||
|
roofAAEye3D dd 0
|
||||||
|
roofAAHorizon3D dd 0
|
||||||
|
roofAATheme3D dd 0
|
||||||
|
roofSlopeMask3D dd 0
|
||||||
|
roofSlopeCentreX3D dd 0
|
||||||
|
roofSlopeCentreY3D dd 0
|
||||||
|
roofSlopeHalfX3D dd 0
|
||||||
|
roofSlopeHalfY3D dd 0
|
||||||
|
roofLean3D dd 0
|
||||||
|
roofLeanTime3D dd 0
|
||||||
|
roofLeanAngle3D dd 0
|
||||||
|
roofLeanSide3D dd 0
|
||||||
|
roofHandsContactX3D dd 320
|
||||||
|
roofHandsWidth3D dd 640
|
||||||
|
roofGuestClock3D dd 0
|
||||||
|
roofGroundRoadPixels3D dd 0
|
||||||
|
roofGroundWaterPixels3D dd 0
|
||||||
|
roofGuestStep3D dd ROOF_GUEST_COUNT dup(0)
|
||||||
|
roofGuestWait3D dd 1200,2400,3600,1800,3000,4200,2000,3300
|
||||||
|
roofGuestMoving3D dd ROOF_GUEST_COUNT dup(0)
|
||||||
|
roofGuestDistance3D dd ROOF_GUEST_COUNT dup(0)
|
||||||
|
roofGuestDir3D dd ROOF_GUEST_COUNT dup(0)
|
||||||
|
roofFloatFP3D REAL4 65536.0
|
||||||
|
roofFloatHalfTex3D REAL4 127.5
|
||||||
|
roofFloatShade3D REAL4 44.0
|
||||||
|
roofFloatAmbient3D REAL4 205.0
|
||||||
|
roofFloat4803D REAL4 480.0
|
||||||
|
roofSkyPath3D db "assets\animations\rooftop\panorama-v1.bin",0
|
||||||
|
roofMaterialPath3D db "assets\animations\rooftop\materials-v1.bin",0
|
||||||
|
roofDetailPath3D db "assets\animations\rooftop\details-v1.bin",0
|
||||||
|
liftPhase3D dd 0
|
||||||
|
liftDoor3D dd 0
|
||||||
|
liftTrip3D dd 0
|
||||||
|
liftDestination3D dd 0
|
||||||
|
liftRideTime3D dd 0
|
||||||
|
liftAwayTime3D dd 0
|
||||||
|
roofUpdateClock3D dd -1
|
||||||
|
roofIndicatorPixel3D dd 0FFFFE9BDh
|
||||||
|
roofSeat3D dd 0
|
||||||
|
roofReturnX3D dd 0
|
||||||
|
roofReturnY3D dd 0
|
||||||
|
roofReturnAngle3D dd 0
|
||||||
|
roofSeatX3D dd FP_1*145/10,FP_1*245/10,FP_1*195/10,FP_1*177/10,FP_1*206/10,FP_1*145/10,FP_1*245/10
|
||||||
|
dd 13*FP_1,15*FP_1,17*FP_1,13*FP_1,13*FP_1,13*FP_1
|
||||||
|
roofSeatY3D dd FP_1*95/10,FP_1*95/10,18*FP_1,FP_1*95/10,FP_1*95/10,15*FP_1,15*FP_1
|
||||||
|
dd FP_1*61/10,FP_1*61/10,FP_1*61/10,FP_1*124/10,FP_1*139/10,FP_1*154/10
|
||||||
|
roofSeatKind3D dd 0,0,0,1,1,1,1,2,2,2,3,3,3
|
||||||
|
roofTargetSeat3D dd 0
|
||||||
|
roofTreeX3D dd 12*FP_1,28*FP_1,12*FP_1,28*FP_1,FP_1*194/10,FP_1*215/10,FP_1*175/10,FP_1*278/10
|
||||||
|
roofTreeY3D dd FP_1*68/10,8*FP_1,FP_1*189/10,16*FP_1,FP_1*134/10,FP_1*195/10,FP_1*195/10,FP_1*45/10
|
||||||
|
roofPostX3D dd 12*FP_1,18*FP_1,12*FP_1,18*FP_1,FP_1*117/10,FP_1*283/10,FP_1*117/10,FP_1*283/10
|
||||||
|
roofPostY3D dd FP_1*15/10,FP_1*15/10,FP_1*62/10,FP_1*62/10,7*FP_1,7*FP_1,15*FP_1,15*FP_1
|
||||||
|
roofGuestX3D dd FP_1*188/10,FP_1*165/10,FP_1*265/10,FP_1*163/10,FP_1*221/10,FP_1*263/10,FP_1*155/10,FP_1*205/10
|
||||||
|
roofGuestY3D dd FP_1*65/10,FP_1*75/10,13*FP_1,FP_1*119/10,FP_1*122/10,FP_1*188/10,FP_1*188/10,FP_1*16/10+15*FP_1
|
||||||
|
roofGuestFrame3D dd 0,24,12,6,18,30,0,24
|
||||||
|
roofActor3D CityProp3D <0,0,FP_1*75/100,FP_1*175/100,0,OFFSET npcGuestArt3D>
|
||||||
|
roofTender3D CityProp3D <15*FP_1,FP_1*34/10,FP_1,FP_1,0,OFFSET hallBartender3D,FP_1*9/20>
|
||||||
|
roofBarName3D db 203,192,211,205,198,45,193,192,208,32,34,194,219,209,206,210,192,34,0
|
||||||
|
roofLiftCall3D db 69,58,32,194,219,199,194,192,210,220,32,203,200,212,210,0
|
||||||
|
roofLiftUp3D db 49,58,32,199,192,202,192,210,32,47,32,50,58,32,205,206,215,220,32,47,32,69,58,32,197,213,192,210,220,0
|
||||||
|
roofLeanPrompt3D db 69,58,32,206,193,203,206,202,206,210,200,210,220,209,223,0
|
||||||
|
roofLeanLeave3D db 69,58,32,206,210,206,201,210,200,0
|
||||||
|
roofSunsetName3D db 199,192,202,192,210,0
|
||||||
|
roofNightName3D db 205,206,215,220,0
|
||||||
|
roofLiftDown3D db 69,58,32,194,32,195,203,192,194,205,219,201,32,199,192,203,0
|
||||||
|
roofLiftBusy3D db 203,200,212,210,32,207,206,196,205,200,204,192,197,210,209,223,0
|
||||||
|
roofLiftBusyDown3D db 203,200,212,210,32,209,207,211,209,202,192,197,210,209,223,0
|
||||||
|
roofSeatPrompt3D db 69,58,32,207,208,200,209,197,209,210,220,0
|
||||||
|
roofStandPrompt3D db 69,58,32,194,209,210,192,210,220,0
|
||||||
|
roofBarPrompt3D db 69,58,32,203,192,211,205,198,45,193,192,208,32,34,194,219,209,206,210,192,34,0
|
||||||
|
roofArrival3D db 202,208,219,216,192,32,47,32,210,197,208,208,192,209,192,32,34,194,219,209,206,210,192,34,0
|
||||||
|
.data?
|
||||||
|
roofIndicatorPixels3D dd 4096 dup(?)
|
||||||
|
roofCityMask3D db SCREEN_SIZE dup(?)
|
||||||
|
roofGlowMask3D db SCREEN_SIZE dup(?)
|
||||||
|
roofSlopeRay3D dd SCREEN_W dup(?)
|
||||||
|
roofAAHistory3D dd SCREEN_SIZE dup(?)
|
||||||
|
.code
|
||||||
1496
src_graphics/rooftop_details.inc
Normal file
823
src_graphics/rooftop_district_data.inc
Normal file
|
|
@ -0,0 +1,823 @@
|
||||||
|
; Generated city block footprints and rooftop-relative heights.
|
||||||
|
ROOF_BUILDING_COUNT equ 518
|
||||||
|
.data
|
||||||
|
roofDistrict3D LABEL DWORD
|
||||||
|
dd 917504,1638400,-1966080,-1310720,-3538944,203,0
|
||||||
|
dd 3276800,3997696,-1966080,-1310720,-3211264,203,0
|
||||||
|
dd -1441792,-720896,-1966080,-1310720,-3407872,203,0
|
||||||
|
dd 393216,2228224,-3538944,-3080192,-2339635,192,1
|
||||||
|
dd 5111808,5570560,262144,1179648,-3014656,192,2
|
||||||
|
dd -1966080,-131072,-3538944,-3080192,-3126067,189,1
|
||||||
|
dd 2752512,4587520,-3538944,-3080192,-2274099,187,1
|
||||||
|
dd 5111808,5570560,-2097152,-1179648,-2949120,191,2
|
||||||
|
dd 393216,851968,-4456448,-3538944,-2359296,192,2
|
||||||
|
dd -4325376,-2490368,-196608,262144,-2949120,188,0
|
||||||
|
dd -4325376,-2490368,1179648,1638400,-2929459,188,1
|
||||||
|
dd 5111808,6946816,-196608,262144,-3014656,192,0
|
||||||
|
dd 5111808,6946816,1179648,1638400,-2994995,192,1
|
||||||
|
dd -589824,-131072,-4456448,-3538944,-3126067,189,3
|
||||||
|
dd 2752512,3211264,-4456448,-3538944,-2293760,187,2
|
||||||
|
dd -4325376,-2490368,-1179648,-720896,-2536243,187,1
|
||||||
|
dd 5111808,6946816,-1179648,-720896,-2929459,191,1
|
||||||
|
dd 393216,2228224,-4915200,-4456448,-2359296,192,0
|
||||||
|
dd -4325376,-3866624,262144,1179648,-2949120,188,2
|
||||||
|
dd 6488064,6946816,262144,1179648,-2994995,192,3
|
||||||
|
dd -1966080,-1507328,-4456448,-3538944,-3145728,189,2
|
||||||
|
dd 4128768,4587520,-4456448,-3538944,-2274099,187,3
|
||||||
|
dd -4325376,-2490368,-2555904,-2097152,-2555904,187,0
|
||||||
|
dd 5111808,6946816,-2555904,-2097152,-2949120,191,0
|
||||||
|
dd -1966080,-131072,-4915200,-4456448,-3145728,189,0
|
||||||
|
dd 2752512,4587520,-4915200,-4456448,-2293760,187,0
|
||||||
|
dd -4325376,-3866624,-2097152,-1179648,-2555904,187,2
|
||||||
|
dd -4325376,-2490368,-3538944,-3080192,-2143027,186,1
|
||||||
|
dd 5111808,6946816,-3538944,-3080192,-2536243,190,1
|
||||||
|
dd 5111808,5570560,-4456448,-3538944,-2555904,190,2
|
||||||
|
dd 393216,2228224,-5898240,-5439488,-2994995,191,1
|
||||||
|
dd -5308416,-4849664,262144,1179648,-2667315,193,3
|
||||||
|
dd -1966080,-131072,-5898240,-5439488,-3060531,188,1
|
||||||
|
dd -5308416,-4849664,-2097152,-1179648,-2274099,192,3
|
||||||
|
dd 7471104,7929856,-2097152,-1179648,-2863923,186,1
|
||||||
|
dd -1966080,-131072,6881280,7340032,-3014656,186,0
|
||||||
|
dd 2752512,4587520,6881280,7340032,-2883584,192,0
|
||||||
|
dd 7864320,8912896,65536,1376256,-1441792,199,0
|
||||||
|
dd 393216,851968,-6815744,-5898240,-3014656,191,2
|
||||||
|
dd -6684672,-4849664,-196608,262144,-2686976,193,0
|
||||||
|
dd -6684672,-4849664,1179648,1638400,-2667315,193,1
|
||||||
|
dd -4325376,-2490368,-4915200,-4456448,-2162688,186,0
|
||||||
|
dd -4325376,-3866624,-4456448,-3538944,-2162688,186,2
|
||||||
|
dd 5111808,6946816,-4915200,-4456448,-2555904,190,0
|
||||||
|
dd -589824,-131072,-6815744,-5898240,-3060531,188,3
|
||||||
|
dd -6684672,-4849664,-1179648,-720896,-2274099,192,1
|
||||||
|
dd 7471104,9306112,-1179648,-720896,-2883584,186,0
|
||||||
|
dd -589824,-131072,7340032,8257536,-2994995,186,3
|
||||||
|
dd 2752512,3211264,7340032,8257536,-2883584,192,2
|
||||||
|
dd 3145728,4194304,-7012352,-5701632,-2293760,204,0
|
||||||
|
dd -1966080,-1507328,-6815744,-5898240,-3080192,188,2
|
||||||
|
dd -6684672,-4849664,-2555904,-2097152,-2293760,192,0
|
||||||
|
dd -1966080,-1507328,7340032,8257536,-3014656,186,2
|
||||||
|
dd 393216,2228224,-7274496,-6815744,-3014656,191,0
|
||||||
|
dd -6684672,-6225920,262144,1179648,-2686976,193,2
|
||||||
|
dd 5111808,6946816,-5898240,-5439488,-2143027,189,1
|
||||||
|
dd 7471104,7929856,-4456448,-3538944,-2490368,193,2
|
||||||
|
dd 5111808,6946816,6881280,7340032,-3145728,187,0
|
||||||
|
dd -1966080,-131072,-7274496,-6815744,-3080192,188,0
|
||||||
|
dd -6684672,-6225920,-2097152,-1179648,-2293760,192,2
|
||||||
|
dd -1966080,-131072,8257536,8716288,-2994995,186,1
|
||||||
|
dd 2752512,4587520,8257536,8716288,-2863923,192,1
|
||||||
|
dd 5111808,5570560,-6815744,-5898240,-2162688,189,2
|
||||||
|
dd 7471104,9306112,-3538944,-3080192,-2470707,193,1
|
||||||
|
dd 5111808,5570560,7340032,8257536,-3145728,187,2
|
||||||
|
dd -3932160,-2883584,-7012352,-5701632,-2097152,204,0
|
||||||
|
dd -6291456,-5242880,-4653056,-3342336,-2293760,204,0
|
||||||
|
dd 393216,2228224,-8257536,-7798784,-2601779,190,1
|
||||||
|
dd 393216,2228224,9240576,9699328,-2293760,190,0
|
||||||
|
dd 7471104,9306112,-4915200,-4456448,-2490368,193,0
|
||||||
|
dd 6488064,6946816,7340032,8257536,-3126067,187,3
|
||||||
|
dd 2752512,4587520,-8257536,-7798784,-2863923,193,1
|
||||||
|
dd 2752512,4587520,9240576,9699328,-2228224,193,0
|
||||||
|
dd 5111808,6946816,-7274496,-6815744,-2162688,189,0
|
||||||
|
dd 8847360,9306112,-4456448,-3538944,-2470707,193,3
|
||||||
|
dd 5111808,6946816,8257536,8716288,-3126067,187,1
|
||||||
|
dd 393216,851968,-9175040,-8257536,-2621440,190,2
|
||||||
|
dd -9043968,-7208960,-196608,262144,-2752512,190,0
|
||||||
|
dd -9043968,-7208960,1179648,1638400,-2732851,190,1
|
||||||
|
dd 393216,851968,9699328,10616832,-2293760,190,2
|
||||||
|
dd 1769472,2228224,9699328,10616832,-2274099,190,3
|
||||||
|
dd -6684672,-4849664,-5898240,-5439488,-2863923,190,1
|
||||||
|
dd -5308416,-4849664,-6815744,-5898240,-2863923,190,3
|
||||||
|
dd 7471104,9306112,-5898240,-5439488,-3126067,192,1
|
||||||
|
dd 7471104,7929856,-6815744,-5898240,-3145728,192,2
|
||||||
|
dd 2752512,3211264,-9175040,-8257536,-2883584,193,2
|
||||||
|
dd -9043968,-7208960,-1179648,-720896,-2339635,189,1
|
||||||
|
dd 2752512,3211264,9699328,10616832,-2228224,193,2
|
||||||
|
dd -1572864,-524288,-9371648,-8060928,-1900544,204,0
|
||||||
|
dd 4128768,4587520,-9175040,-8257536,-2863923,193,3
|
||||||
|
dd -9043968,-7208960,-2555904,-2097152,-2359296,189,0
|
||||||
|
dd -4325376,-2490368,-8257536,-7798784,-2405171,192,1
|
||||||
|
dd 9830400,10289152,-4456448,-3538944,-2752512,188,2
|
||||||
|
dd -4325376,-2490368,9240576,9699328,-3145728,192,0
|
||||||
|
dd 393216,2228224,-9633792,-9175040,-2621440,190,0
|
||||||
|
dd -9043968,-8585216,262144,1179648,-2752512,190,2
|
||||||
|
dd 393216,2228224,10616832,11075584,-2274099,190,1
|
||||||
|
dd -9043968,-7208960,-3538944,-3080192,-2994995,188,1
|
||||||
|
dd 9830400,11665408,-3538944,-3080192,-2732851,188,1
|
||||||
|
dd -2949120,-2490368,9699328,10616832,-3126067,192,3
|
||||||
|
dd 5111808,5570560,9699328,10616832,-2470707,188,1
|
||||||
|
dd 2752512,4587520,-9633792,-9175040,-2883584,193,0
|
||||||
|
dd -9043968,-8585216,-2097152,-1179648,-2359296,189,2
|
||||||
|
dd 2752512,4587520,10616832,11075584,-2208563,193,1
|
||||||
|
dd -6684672,-4849664,-7274496,-6815744,-2883584,190,0
|
||||||
|
dd -6684672,-6225920,-6815744,-5898240,-2883584,190,2
|
||||||
|
dd 7471104,9306112,-7274496,-6815744,-3145728,192,0
|
||||||
|
dd 8847360,9306112,-6815744,-5898240,-3126067,192,3
|
||||||
|
dd -6684672,-4849664,8257536,8716288,-2818048,188,0
|
||||||
|
dd -6684672,-6225920,7340032,8257536,-2798387,188,1
|
||||||
|
dd 5505024,6553600,-9371648,-8060928,-2097152,204,0
|
||||||
|
dd -4325376,-3866624,-9175040,-8257536,-2424832,192,2
|
||||||
|
dd -9043968,-7208960,-4915200,-4456448,-3014656,188,0
|
||||||
|
dd 9830400,11665408,-4915200,-4456448,-2752512,188,0
|
||||||
|
dd -4325376,-3866624,9699328,10616832,-3145728,192,2
|
||||||
|
dd 393216,2228224,-10616832,-10158080,-2208563,189,1
|
||||||
|
dd -10027008,-9568256,262144,1179648,-2470707,187,3
|
||||||
|
dd -4325376,-2490368,-9633792,-9175040,-2424832,192,0
|
||||||
|
dd -9043968,-8585216,-4456448,-3538944,-3014656,188,2
|
||||||
|
dd -4325376,-2490368,10616832,11075584,-3126067,192,1
|
||||||
|
dd 5111808,6946816,10616832,11075584,-2490368,188,0
|
||||||
|
dd -6684672,-4849664,-8257536,-7798784,-2490368,189,0
|
||||||
|
dd 7471104,9306112,-8257536,-7798784,-3060531,191,1
|
||||||
|
dd 9830400,10289152,-6815744,-5898240,-2359296,187,2
|
||||||
|
dd 9830400,10289152,7340032,8257536,-2293760,193,2
|
||||||
|
dd -6684672,-4849664,9240576,9699328,-2883584,189,0
|
||||||
|
dd 7471104,9306112,9240576,9699328,-2424832,191,0
|
||||||
|
dd -1966080,-131072,-10616832,-10158080,-2274099,186,1
|
||||||
|
dd 2752512,4587520,-10616832,-10158080,-2490368,192,0
|
||||||
|
dd -10027008,-9568256,-2097152,-1179648,-3126067,186,3
|
||||||
|
dd 12189696,12648448,-2097152,-1179648,-3080192,192,2
|
||||||
|
dd -1966080,-131072,11599872,12058624,-2424832,188,0
|
||||||
|
dd 2752512,4587520,11599872,12058624,-2621440,186,0
|
||||||
|
dd 7471104,7929856,-9175040,-8257536,-3080192,191,2
|
||||||
|
dd -9043968,-7208960,-5898240,-5439488,-2601779,187,1
|
||||||
|
dd 9830400,11665408,-5898240,-5439488,-2339635,187,1
|
||||||
|
dd 9830400,11665408,6881280,7340032,-2293760,193,0
|
||||||
|
dd 7471104,7929856,9699328,10616832,-2424832,191,2
|
||||||
|
dd 786432,1835008,11862016,13172736,-1900544,204,0
|
||||||
|
dd 393216,851968,-11534336,-10616832,-2228224,189,2
|
||||||
|
dd -11403264,-9568256,-196608,262144,-2490368,187,0
|
||||||
|
dd -11403264,-9568256,1179648,1638400,-2470707,187,1
|
||||||
|
dd -589824,-131072,-11534336,-10616832,-2274099,186,3
|
||||||
|
dd 2752512,3211264,-11534336,-10616832,-2470707,192,1
|
||||||
|
dd -11403264,-9568256,-1179648,-720896,-3126067,186,1
|
||||||
|
dd 12189696,14024704,-1179648,-720896,-3060531,192,1
|
||||||
|
dd 2752512,3211264,12058624,12976128,-2621440,186,2
|
||||||
|
dd 5111808,6946816,-10616832,-10158080,-2405171,187,1
|
||||||
|
dd -10027008,-9568256,-4456448,-3538944,-3060531,193,3
|
||||||
|
dd 12189696,12648448,-4456448,-3538944,-2686976,191,2
|
||||||
|
dd 5111808,6946816,11599872,12058624,-2883584,189,0
|
||||||
|
dd -1966080,-1507328,-11534336,-10616832,-2293760,186,2
|
||||||
|
dd -11403264,-9568256,-2555904,-2097152,-3145728,186,0
|
||||||
|
dd 12189696,14024704,-2555904,-2097152,-3080192,192,0
|
||||||
|
dd -1966080,-1507328,12058624,12976128,-2424832,188,2
|
||||||
|
dd -6684672,-6225920,-9175040,-8257536,-2470707,189,1
|
||||||
|
dd 8847360,9306112,-9175040,-8257536,-3060531,191,3
|
||||||
|
dd -9043968,-7208960,-7274496,-6815744,-2621440,187,0
|
||||||
|
dd 9830400,11665408,-7274496,-6815744,-2359296,187,0
|
||||||
|
dd -9043968,-7208960,8257536,8716288,-2555904,193,0
|
||||||
|
dd 9830400,11665408,8257536,8716288,-2274099,193,1
|
||||||
|
dd -6684672,-6225920,9699328,10616832,-2883584,189,2
|
||||||
|
dd 7471104,9306112,-9633792,-9175040,-3080192,191,0
|
||||||
|
dd -9043968,-8585216,-6815744,-5898240,-2621440,187,2
|
||||||
|
dd -9043968,-8585216,7340032,8257536,-2536243,193,1
|
||||||
|
dd 11206656,11665408,7340032,8257536,-2274099,193,3
|
||||||
|
dd -6684672,-4849664,10616832,11075584,-2863923,189,1
|
||||||
|
dd 7471104,9306112,10616832,11075584,-2405171,191,1
|
||||||
|
dd 5111808,5570560,-11534336,-10616832,-2424832,187,2
|
||||||
|
dd -11403264,-9568256,-3538944,-3080192,-3060531,193,1
|
||||||
|
dd 12189696,14024704,-3538944,-3080192,-2667315,191,1
|
||||||
|
dd 5111808,5570560,12058624,12976128,-2883584,189,2
|
||||||
|
dd 393216,2228224,-11993088,-11534336,-2228224,189,0
|
||||||
|
dd -11403264,-10944512,262144,1179648,-2490368,187,2
|
||||||
|
dd -1966080,-131072,-11993088,-11534336,-2293760,186,0
|
||||||
|
dd -11403264,-10944512,-2097152,-1179648,-3145728,186,2
|
||||||
|
dd 13565952,14024704,-2097152,-1179648,-3060531,192,3
|
||||||
|
dd -1966080,-131072,12976128,13434880,-2405171,188,1
|
||||||
|
dd 2752512,4587520,12976128,13434880,-2601779,186,1
|
||||||
|
dd -9043968,-7208960,-8257536,-7798784,-2208563,186,1
|
||||||
|
dd 9830400,11665408,-8257536,-7798784,-2994995,186,1
|
||||||
|
dd 9830400,10289152,-9175040,-8257536,-3014656,186,2
|
||||||
|
dd -9043968,-7208960,9240576,9699328,-2949120,186,0
|
||||||
|
dd -7667712,-7208960,9699328,10616832,-2929459,186,3
|
||||||
|
dd -11403264,-9568256,-4915200,-4456448,-3080192,193,0
|
||||||
|
dd 12189696,14024704,-4915200,-4456448,-2686976,191,0
|
||||||
|
dd -4325376,-3866624,12058624,12976128,-2470707,193,1
|
||||||
|
dd 6488064,6946816,12058624,12976128,-2863923,189,3
|
||||||
|
dd -6684672,-4849664,-10616832,-10158080,-3126067,188,1
|
||||||
|
dd 12189696,12648448,-6815744,-5898240,-2293760,190,2
|
||||||
|
dd -10027008,-9568256,7340032,8257536,-2601779,190,3
|
||||||
|
dd 12189696,12648448,7340032,8257536,-2228224,188,2
|
||||||
|
dd -6684672,-4849664,11599872,12058624,-2228224,190,0
|
||||||
|
dd 10223616,11272192,9502720,10813440,-1900544,204,0
|
||||||
|
dd 5111808,6946816,-11993088,-11534336,-2424832,187,0
|
||||||
|
dd -11403264,-10944512,-4456448,-3538944,-3080192,193,2
|
||||||
|
dd 13565952,14024704,-4456448,-3538944,-2667315,191,3
|
||||||
|
dd -4325376,-2490368,12976128,13434880,-2490368,193,0
|
||||||
|
dd 5111808,6946816,12976128,13434880,-2863923,189,1
|
||||||
|
dd -5308416,-4849664,-11534336,-10616832,-3126067,188,3
|
||||||
|
dd 12189696,14024704,-5898240,-5439488,-2274099,190,1
|
||||||
|
dd -11403264,-9568256,6881280,7340032,-2621440,190,0
|
||||||
|
dd 12189696,14024704,6881280,7340032,-2228224,188,0
|
||||||
|
dd 7864320,8912896,-11730944,-10420224,-1900544,204,0
|
||||||
|
dd -11010048,-9961472,-7012352,-5701632,-1900544,204,0
|
||||||
|
dd 7864320,8912896,11862016,13172736,-2097152,204,0
|
||||||
|
dd -9043968,-7208960,-9633792,-9175040,-2228224,186,0
|
||||||
|
dd -9043968,-8585216,-9175040,-8257536,-2228224,186,2
|
||||||
|
dd 9830400,11665408,-9633792,-9175040,-3014656,186,0
|
||||||
|
dd -9043968,-7208960,10616832,11075584,-2929459,186,1
|
||||||
|
dd -9043968,-8585216,9699328,10616832,-2949120,186,2
|
||||||
|
dd -6684672,-6225920,-11534336,-10616832,-3145728,188,2
|
||||||
|
dd 12189696,14024704,-7274496,-6815744,-2293760,190,0
|
||||||
|
dd -11403264,-9568256,8257536,8716288,-2601779,190,1
|
||||||
|
dd 12189696,14024704,8257536,8716288,-2208563,188,1
|
||||||
|
dd -6684672,-6225920,12058624,12976128,-2228224,190,2
|
||||||
|
dd -6684672,-4849664,-11993088,-11534336,-3145728,188,0
|
||||||
|
dd 13565952,14024704,-6815744,-5898240,-2274099,190,3
|
||||||
|
dd -11403264,-10944512,7340032,8257536,-2621440,190,2
|
||||||
|
dd -6684672,-4849664,12976128,13434880,-2208563,190,1
|
||||||
|
dd -9043968,-7208960,-10616832,-10158080,-2863923,193,1
|
||||||
|
dd 9830400,11665408,-10616832,-10158080,-2601779,193,1
|
||||||
|
dd -10027008,-9568256,-9175040,-8257536,-2274099,191,3
|
||||||
|
dd -10027008,-9568256,9699328,10616832,-2994995,191,3
|
||||||
|
dd 12189696,12648448,9699328,10616832,-2621440,189,2
|
||||||
|
dd -9043968,-7208960,11599872,12058624,-2293760,187,0
|
||||||
|
dd 9830400,11665408,11599872,12058624,-3080192,187,0
|
||||||
|
dd 9830400,10289152,-11534336,-10616832,-2621440,193,2
|
||||||
|
dd -11403264,-9568256,-8257536,-7798784,-2274099,191,1
|
||||||
|
dd -11403264,-9568256,9240576,9699328,-3014656,191,0
|
||||||
|
dd 12189696,14024704,9240576,9699328,-2621440,189,0
|
||||||
|
dd -7667712,-7208960,12058624,12976128,-2274099,187,3
|
||||||
|
dd 9830400,10289152,12058624,12976128,-3080192,187,2
|
||||||
|
dd 12582912,13631488,-9371648,-8060928,-2293760,204,0
|
||||||
|
dd -9043968,-8585216,-11534336,-10616832,-2883584,193,2
|
||||||
|
dd -11403264,-9568256,-9633792,-9175040,-2293760,191,0
|
||||||
|
dd -11403264,-9568256,10616832,11075584,-2994995,191,1
|
||||||
|
dd 12189696,14024704,10616832,11075584,-2601779,189,1
|
||||||
|
dd -9043968,-8585216,12058624,12976128,-2293760,187,2
|
||||||
|
dd 11206656,11665408,12058624,12976128,-3060531,187,3
|
||||||
|
dd -9043968,-7208960,-11993088,-11534336,-2883584,193,0
|
||||||
|
dd 9830400,11665408,-11993088,-11534336,-2621440,193,0
|
||||||
|
dd -11403264,-10944512,-9175040,-8257536,-2293760,191,2
|
||||||
|
dd -11403264,-10944512,9699328,10616832,-3014656,191,2
|
||||||
|
dd -9043968,-7208960,12976128,13434880,-2274099,187,1
|
||||||
|
dd 9830400,11665408,12976128,13434880,-3060531,187,1
|
||||||
|
dd -11403264,-9568256,-10616832,-10158080,-2929459,190,1
|
||||||
|
dd -10027008,-9568256,-11534336,-10616832,-2929459,190,3
|
||||||
|
dd 12189696,14024704,-10616832,-10158080,-2863923,188,1
|
||||||
|
dd 12189696,12648448,-11534336,-10616832,-2883584,188,2
|
||||||
|
dd 12189696,14024704,11599872,12058624,-3014656,190,0
|
||||||
|
dd 12189696,12648448,12058624,12976128,-3014656,190,2
|
||||||
|
dd -65536,2686976,-17629184,-14483456,-2359296,190,4
|
||||||
|
dd -17170432,-13762560,-851968,2293760,-2686976,190,4
|
||||||
|
dd -131072,2752512,15925248,19070976,-2293760,190,4
|
||||||
|
dd -11403264,-9568256,-11993088,-11534336,-2949120,190,0
|
||||||
|
dd -11403264,-10944512,-11534336,-10616832,-2949120,190,2
|
||||||
|
dd 12189696,14024704,-11993088,-11534336,-2883584,188,0
|
||||||
|
dd 13565952,14024704,-11534336,-10616832,-2863923,188,3
|
||||||
|
dd 12189696,14024704,12976128,13434880,-2994995,190,1
|
||||||
|
dd -4587520,-1179648,-17629184,-14483456,-2686976,189,4
|
||||||
|
dd 3801088,7208960,-17629184,-14483456,-2031616,191,4
|
||||||
|
dd -17039360,-13893632,-5046272,-1900544,-1507328,189,4
|
||||||
|
dd 16384000,19791872,-5046272,-1900544,-2686976,189,4
|
||||||
|
dd -3997696,-1769472,15925248,19070976,-2621440,189,4
|
||||||
|
dd 4390912,6619136,15925248,19070976,-1966080,191,4
|
||||||
|
dd -8454144,-5701632,-17629184,-14483456,-3014656,188,4
|
||||||
|
dd 8323072,11075584,-17629184,-14483456,-1703936,192,4
|
||||||
|
dd -16973824,-13959168,-9240576,-6094848,-2228224,188,4
|
||||||
|
dd 16515072,19660800,-9240576,-6094848,-1507328,188,4
|
||||||
|
dd -16711680,-14221312,7536640,10682368,-3145728,192,4
|
||||||
|
dd 16777216,19398656,7536640,10682368,-2424832,192,4
|
||||||
|
dd -8519680,-5636096,15925248,19070976,-2949120,188,4
|
||||||
|
dd 8257536,11141120,15925248,19070976,-1638400,192,4
|
||||||
|
dd 0,2621440,-21823488,-18677760,-3080192,189,4
|
||||||
|
dd -12910592,-9633792,-17629184,-14483456,-1441792,187,4
|
||||||
|
dd 12779520,15007744,-17629184,-14483456,-3276800,193,4
|
||||||
|
dd -16908288,-14024704,-13434880,-10289152,-2949120,187,4
|
||||||
|
dd 16580608,19595264,-13434880,-10289152,-2228224,187,4
|
||||||
|
dd -21037056,-18284544,-851968,2293760,-3014656,189,4
|
||||||
|
dd -16777216,-14155776,11730944,14876672,-2424832,193,4
|
||||||
|
dd 16711680,19464192,11730944,14876672,-1703936,193,4
|
||||||
|
dd -12386304,-10158080,15925248,19070976,-3276800,187,4
|
||||||
|
dd 12713984,15073280,15925248,19070976,-3211264,193,4
|
||||||
|
dd -196608,2818048,20119552,23265280,-1572864,191,4
|
||||||
|
dd -4456448,-1310720,-21823488,-18677760,-1507328,188,4
|
||||||
|
dd 3866624,7143424,-21823488,-18677760,-2752512,190,4
|
||||||
|
dd -20905984,-18415616,-5046272,-1900544,-1835008,188,4
|
||||||
|
dd 20905984,23658496,-5046272,-1900544,-2359296,190,4
|
||||||
|
dd -4063232,-1703936,20119552,23265280,-1900544,190,4
|
||||||
|
dd 4259840,6750208,20119552,23265280,-3145728,192,4
|
||||||
|
dd 20447232,21495808,-9175040,-7864320,1966080,200,2
|
||||||
|
dd 20643840,21299200,-8978432,-8060928,2424832,200,2
|
||||||
|
dd -8323072,-5832704,-21823488,-18677760,-1835008,187,4
|
||||||
|
dd 8388608,11010048,-21823488,-18677760,-2424832,191,4
|
||||||
|
dd -20840448,-18481152,-9240576,-6094848,-2555904,187,4
|
||||||
|
dd 20971520,23592960,-9240576,-6094848,-3080192,189,4
|
||||||
|
dd -21168128,-18153472,7536640,10682368,-1572864,191,4
|
||||||
|
dd 20643840,23920640,7536640,10682368,-2097152,193,4
|
||||||
|
dd -8585216,-5570560,20119552,23265280,-2228224,189,4
|
||||||
|
dd 8126464,11272192,20119552,23265280,-2818048,193,4
|
||||||
|
dd -16777216,-14155776,-17629184,-14483456,-1769472,186,4
|
||||||
|
dd 16646144,19529728,-17629184,-14483456,-2949120,186,4
|
||||||
|
dd -16842752,-14090240,15925248,19070976,-1703936,186,4
|
||||||
|
dd 16580608,19595264,15925248,19070976,-2883584,186,4
|
||||||
|
dd -12845056,-9699328,-21823488,-18677760,-2162688,186,4
|
||||||
|
dd 12255232,15532032,-21823488,-18677760,-2097152,192,4
|
||||||
|
dd -20774912,-18546688,-13434880,-10289152,-3276800,186,4
|
||||||
|
dd 21102592,23461888,-13434880,-10289152,-1900544,188,4
|
||||||
|
dd -21299200,-18022400,11730944,14876672,-2752512,192,4
|
||||||
|
dd 21168128,23396352,11730944,14876672,-3276800,186,4
|
||||||
|
dd -12451840,-10092544,20119552,23265280,-2555904,188,4
|
||||||
|
dd 12648448,15138816,20119552,23265280,-2490368,186,4
|
||||||
|
dd 22740992,23789568,-11468800,-10158080,4325376,201,2
|
||||||
|
dd 22937600,23592960,-11272192,-10354688,4784128,201,2
|
||||||
|
dd 131072,2490368,-26017792,-22872064,-1900544,188,4
|
||||||
|
dd -25493504,-22216704,-851968,2293760,-1441792,188,4
|
||||||
|
dd -327680,2949120,24313856,27459584,-2752512,192,4
|
||||||
|
dd -4390912,-1376256,-26017792,-22872064,-2228224,187,4
|
||||||
|
dd 3997696,7012352,-26017792,-22872064,-1572864,189,4
|
||||||
|
dd -25427968,-22282240,-5046272,-1900544,-2162688,187,4
|
||||||
|
dd 24772608,28180480,-5046272,-1900544,-2031616,191,4
|
||||||
|
dd -4194304,-1572864,24313856,27459584,-3080192,191,4
|
||||||
|
dd 4194304,6815744,24313856,27459584,-2424832,193,4
|
||||||
|
dd 25034752,26083328,-8847360,-7536640,3145728,202,2
|
||||||
|
dd 25231360,25886720,-8650752,-7733248,3604480,202,2
|
||||||
|
dd 22085632,23134208,-15400960,-14090240,3604480,202,2
|
||||||
|
dd 22282240,22937600,-15204352,-14286848,4063232,202,2
|
||||||
|
dd -8257536,-5898240,-26017792,-22872064,-2555904,186,4
|
||||||
|
dd 8454144,10944512,-26017792,-22872064,-3145728,190,4
|
||||||
|
dd -25362432,-22347776,-9240576,-6094848,-2883584,186,4
|
||||||
|
dd 24838144,28114944,-9240576,-6094848,-2752512,190,4
|
||||||
|
dd -25034752,-22675456,7536640,10682368,-1900544,190,4
|
||||||
|
dd 25165824,27787264,7536640,10682368,-1769472,186,4
|
||||||
|
dd -8650752,-5505024,24313856,27459584,-1507328,190,4
|
||||||
|
dd 8060928,11337728,24313856,27459584,-2097152,186,4
|
||||||
|
dd -16711680,-14221312,-21823488,-18677760,-2490368,193,4
|
||||||
|
dd 16777216,19398656,-21823488,-18677760,-1769472,193,4
|
||||||
|
dd -21299200,-18022400,-17629184,-14483456,-2097152,193,4
|
||||||
|
dd 21168128,23396352,-17629184,-14483456,-2621440,187,4
|
||||||
|
dd -21364736,-17956864,15925248,19070976,-2031616,193,4
|
||||||
|
dd 21102592,23461888,15925248,19070976,-2555904,187,4
|
||||||
|
dd -16973824,-13959168,20119552,23265280,-2883584,187,4
|
||||||
|
dd 16515072,19660800,20119552,23265280,-2162688,187,4
|
||||||
|
dd -12779520,-9764864,-26017792,-22872064,-2883584,193,4
|
||||||
|
dd 12320768,15466496,-26017792,-22872064,-2818048,191,4
|
||||||
|
dd -25231360,-22478848,-13434880,-10289152,-1703936,193,4
|
||||||
|
dd 24969216,27983872,-13434880,-10289152,-1572864,189,4
|
||||||
|
dd -25165824,-22544384,11730944,14876672,-3080192,191,4
|
||||||
|
dd 25034752,27918336,11730944,14876672,-2949120,187,4
|
||||||
|
dd -12517376,-10027008,24313856,27459584,-1835008,189,4
|
||||||
|
dd 12582912,15204352,24313856,27459584,-1769472,187,4
|
||||||
|
dd 196608,2424832,-30212096,-27066368,-2621440,187,4
|
||||||
|
dd -29360128,-26738688,-851968,2293760,-1769472,187,4
|
||||||
|
dd -393216,3014656,28508160,31653888,-2031616,193,4
|
||||||
|
dd -4325376,-1441792,-30212096,-27066368,-2949120,186,4
|
||||||
|
dd 4063232,6946816,-30212096,-27066368,-2293760,188,4
|
||||||
|
dd -21233664,-18087936,-21823488,-18677760,-2818048,192,4
|
||||||
|
dd 20643840,23920640,-21823488,-18677760,-1441792,186,4
|
||||||
|
dd -29294592,-26804224,-5046272,-1900544,-2490368,186,4
|
||||||
|
dd 29294592,32047104,-5046272,-1900544,-1703936,192,4
|
||||||
|
dd -20840448,-18481152,20119552,23265280,-3211264,186,4
|
||||||
|
dd 21037056,23527424,20119552,23265280,-1835008,188,4
|
||||||
|
dd -4259840,-1507328,28508160,31653888,-2359296,192,4
|
||||||
|
dd 4128768,6881280,28508160,31653888,-1703936,186,4
|
||||||
|
dd 27328512,28377088,-13434880,-12124160,6225920,200,2
|
||||||
|
dd 27525120,28180480,-13238272,-12320768,6684672,200,2
|
||||||
|
dd -16646144,-14286848,-26017792,-22872064,-3211264,192,4
|
||||||
|
dd 16842752,19333120,-26017792,-22872064,-2490368,192,4
|
||||||
|
dd -25165824,-22544384,-17629184,-14483456,-2424832,192,4
|
||||||
|
dd 25034752,27918336,-17629184,-14483456,-2293760,188,4
|
||||||
|
dd -25231360,-22478848,15925248,19070976,-2359296,192,4
|
||||||
|
dd 24969216,27983872,15925248,19070976,-2228224,188,4
|
||||||
|
dd -17039360,-13893632,24313856,27459584,-2162688,188,4
|
||||||
|
dd 16449536,19726336,24313856,27459584,-1441792,188,4
|
||||||
|
dd -8192000,-5963776,-30212096,-27066368,-3276800,193,4
|
||||||
|
dd 8585216,10813440,-30212096,-27066368,-1966080,189,4
|
||||||
|
dd -29229056,-26869760,-9240576,-6094848,-3211264,193,4
|
||||||
|
dd 29360128,31981568,-9240576,-6094848,-2424832,191,4
|
||||||
|
dd -29556736,-26542080,7536640,10682368,-2228224,189,4
|
||||||
|
dd 29032448,32309248,7536640,10682368,-1441792,187,4
|
||||||
|
dd -8781824,-5373952,28508160,31653888,-2686976,191,4
|
||||||
|
dd 8585216,10813440,28508160,31653888,-3276800,187,4
|
||||||
|
dd 29622272,30670848,-10158080,-8847360,2752512,201,2
|
||||||
|
dd 29818880,30474240,-9961472,-9043968,3211264,201,2
|
||||||
|
dd 26017792,27066368,-17694720,-16384000,4718592,200,2
|
||||||
|
dd 26214400,26869760,-17498112,-16580608,5177344,200,2
|
||||||
|
dd -12648448,-9895936,-30212096,-27066368,-1703936,192,4
|
||||||
|
dd 12451840,15335424,-30212096,-27066368,-1638400,190,4
|
||||||
|
dd -29753344,-26345472,-13434880,-10289152,-2031616,192,4
|
||||||
|
dd 29425664,31916032,-13434880,-10289152,-3145728,190,4
|
||||||
|
dd -29622272,-26476544,11730944,14876672,-1507328,190,4
|
||||||
|
dd 29556736,31784960,11730944,14876672,-2621440,188,4
|
||||||
|
dd -12648448,-9895936,28508160,31653888,-3014656,190,4
|
||||||
|
dd 12451840,15335424,28508160,31653888,-2949120,188,4
|
||||||
|
dd -21102592,-18219008,-26017792,-22872064,-1638400,191,4
|
||||||
|
dd 20709376,23855104,-26017792,-22872064,-2162688,193,4
|
||||||
|
dd -25100288,-22609920,-21823488,-18677760,-3145728,191,4
|
||||||
|
dd 25100288,27852800,-21823488,-18677760,-3014656,187,4
|
||||||
|
dd -25296896,-22413312,20119552,23265280,-1638400,193,4
|
||||||
|
dd 24903680,28049408,20119552,23265280,-1507328,189,4
|
||||||
|
dd -20905984,-18415616,24313856,27459584,-2490368,187,4
|
||||||
|
dd 20905984,23658496,24313856,27459584,-3014656,189,4
|
||||||
|
dd -327680,2949120,-34406400,-31260672,-1441792,186,4
|
||||||
|
dd -33882112,-30605312,-851968,2293760,-2097152,186,4
|
||||||
|
dd 131072,2490368,32702464,35848192,-3211264,186,4
|
||||||
|
dd -4194304,-1572864,-34406400,-31260672,-1769472,193,4
|
||||||
|
dd 4128768,6881280,-34406400,-31260672,-3014656,187,4
|
||||||
|
dd -17170432,-13762560,-30212096,-27066368,-2031616,191,4
|
||||||
|
dd 16908288,19267584,-30212096,-27066368,-3211264,191,4
|
||||||
|
dd -29687808,-26411008,-17629184,-14483456,-2752512,191,4
|
||||||
|
dd 29556736,31784960,-17629184,-14483456,-1966080,189,4
|
||||||
|
dd -33816576,-30670848,-5046272,-1900544,-2818048,193,4
|
||||||
|
dd 33751040,35979264,-5046272,-1900544,-3276800,193,4
|
||||||
|
dd -29753344,-26345472,15925248,19070976,-2686976,191,4
|
||||||
|
dd 29491200,31850496,15925248,19070976,-1900544,189,4
|
||||||
|
dd -17104896,-13828096,28508160,31653888,-1441792,189,4
|
||||||
|
dd 16973824,19202048,28508160,31653888,-2621440,189,4
|
||||||
|
dd -4325376,-1441792,32702464,35848192,-1638400,193,4
|
||||||
|
dd 3997696,7012352,32702464,35848192,-2883584,187,4
|
||||||
|
dd 30605312,31653888,-16384000,-15073280,1835008,201,2
|
||||||
|
dd 30801920,31457280,-16187392,-15269888,2293760,201,2
|
||||||
|
dd -8716288,-5439488,-34406400,-31260672,-2097152,192,4
|
||||||
|
dd 7995392,11403264,-34406400,-31260672,-2686976,188,4
|
||||||
|
dd -33685504,-30801920,-9240576,-6094848,-1638400,192,4
|
||||||
|
dd 33226752,36503552,-9240576,-6094848,-2097152,192,4
|
||||||
|
dd -33423360,-31064064,7536640,10682368,-2555904,188,4
|
||||||
|
dd 33488896,36241408,7536640,10682368,-3014656,188,4
|
||||||
|
dd -8192000,-5963776,32702464,35848192,-1966080,192,4
|
||||||
|
dd 8519680,10878976,32702464,35848192,-2555904,188,4
|
||||||
|
dd -24969216,-22740992,-26017792,-22872064,-1966080,190,4
|
||||||
|
dd 25231360,27721728,-26017792,-22872064,-1835008,186,4
|
||||||
|
dd -25427968,-22282240,24313856,27459584,-2818048,186,4
|
||||||
|
dd 24772608,28180480,24313856,27459584,-2686976,190,4
|
||||||
|
dd -12582912,-9961472,-34406400,-31260672,-2424832,191,4
|
||||||
|
dd 12517376,15269888,-34406400,-31260672,-2359296,189,4
|
||||||
|
dd -33619968,-30867456,-13434880,-10289152,-2359296,191,4
|
||||||
|
dd 33292288,36438016,-13434880,-10289152,-2818048,191,4
|
||||||
|
dd -33488896,-30998528,11730944,14876672,-1835008,189,4
|
||||||
|
dd 33423360,36306944,11730944,14876672,-2293760,189,4
|
||||||
|
dd -12713984,-9830400,32702464,35848192,-2293760,191,4
|
||||||
|
dd 12386304,15400960,32702464,35848192,-2228224,189,4
|
||||||
|
dd 36634624,38076416,-262144,1048576,-2883584,186,4
|
||||||
|
dd -21037056,-18284544,-30212096,-27066368,-2359296,190,4
|
||||||
|
dd 20774912,23789568,-30212096,-27066368,-2883584,192,4
|
||||||
|
dd -29556736,-26542080,-21823488,-18677760,-1572864,190,4
|
||||||
|
dd 28966912,32374784,-21823488,-18677760,-2686976,188,4
|
||||||
|
dd -29163520,-26935296,20119552,23265280,-1966080,192,4
|
||||||
|
dd 29360128,31981568,20119552,23265280,-3080192,190,4
|
||||||
|
dd -20971520,-18350080,28508160,31653888,-1769472,188,4
|
||||||
|
dd 20840448,23724032,28508160,31653888,-2293760,190,4
|
||||||
|
dd 36634624,38076416,6291456,7602176,-2883584,186,4
|
||||||
|
dd -17104896,-13828096,-34406400,-31260672,-2752512,190,4
|
||||||
|
dd 16384000,19791872,-34406400,-31260672,-2031616,190,4
|
||||||
|
dd -33554432,-30932992,-17629184,-14483456,-3080192,190,4
|
||||||
|
dd 33423360,36306944,-17629184,-14483456,-1638400,190,4
|
||||||
|
dd -33619968,-30867456,15925248,19070976,-3014656,190,4
|
||||||
|
dd 33357824,36372480,15925248,19070976,-1572864,190,4
|
||||||
|
dd -16580608,-14352384,32702464,35848192,-2621440,190,4
|
||||||
|
dd 16908288,19267584,32702464,35848192,-1900544,190,4
|
||||||
|
dd 38862848,40304640,-786432,524288,-2424832,187,4
|
||||||
|
dd -25559040,-22151168,-30212096,-27066368,-2686976,189,4
|
||||||
|
dd 25296896,27656192,-30212096,-27066368,-2555904,193,4
|
||||||
|
dd -29491200,-26607616,-26017792,-22872064,-2293760,189,4
|
||||||
|
dd 29097984,32243712,-26017792,-22872064,-1507328,187,4
|
||||||
|
dd -29294592,-26804224,24313856,27459584,-3145728,193,4
|
||||||
|
dd 29294592,32047104,24313856,27459584,-2359296,191,4
|
||||||
|
dd -25493504,-22216704,28508160,31653888,-2097152,187,4
|
||||||
|
dd 25362432,27590656,28508160,31653888,-1966080,191,4
|
||||||
|
dd 38862848,40304640,6881280,8192000,-2424832,187,4
|
||||||
|
dd -20971520,-18350080,-34406400,-31260672,-3080192,189,4
|
||||||
|
dd 20905984,23658496,-34406400,-31260672,-1703936,191,4
|
||||||
|
dd -33423360,-31064064,-21823488,-18677760,-1900544,189,4
|
||||||
|
dd 33488896,36241408,-21823488,-18677760,-2359296,189,4
|
||||||
|
dd -33685504,-30801920,20119552,23265280,-2293760,191,4
|
||||||
|
dd 33226752,36503552,20119552,23265280,-2752512,191,4
|
||||||
|
dd -21102592,-18219008,32702464,35848192,-2949120,189,4
|
||||||
|
dd 20774912,23789568,32702464,35848192,-1572864,191,4
|
||||||
|
dd 41091072,42532864,-1310720,0,-1966080,188,4
|
||||||
|
dd 41091072,42532864,7471104,8781824,-1966080,188,4
|
||||||
|
dd -29425664,-26673152,-30212096,-27066368,-3014656,188,4
|
||||||
|
dd 29163520,32178176,-30212096,-27066368,-2228224,186,4
|
||||||
|
dd -29360128,-26738688,28508160,31653888,-2424832,186,4
|
||||||
|
dd 29229056,32112640,28508160,31653888,-1638400,192,4
|
||||||
|
dd -25427968,-22282240,-34406400,-31260672,-1507328,188,4
|
||||||
|
dd 25362432,27590656,-34406400,-31260672,-3276800,192,4
|
||||||
|
dd -33357824,-31129600,-26017792,-22872064,-2621440,188,4
|
||||||
|
dd 33554432,36175872,-26017792,-22872064,-3080192,188,4
|
||||||
|
dd -33751040,-30736384,24313856,27459584,-1572864,192,4
|
||||||
|
dd 33161216,36569088,24313856,27459584,-2031616,192,4
|
||||||
|
dd -24969216,-22740992,32702464,35848192,-3276800,188,4
|
||||||
|
dd 25231360,27721728,32702464,35848192,-3145728,192,4
|
||||||
|
dd 43319296,44761088,-262144,1048576,-1507328,189,4
|
||||||
|
dd 43319296,44761088,8060928,9371648,-1507328,189,4
|
||||||
|
dd -29294592,-26804224,-34406400,-31260672,-1835008,187,4
|
||||||
|
dd 29229056,32112640,-34406400,-31260672,-2949120,193,4
|
||||||
|
dd -33882112,-30605312,-30212096,-27066368,-1441792,187,4
|
||||||
|
dd 33685504,36044800,-30212096,-27066368,-1900544,187,4
|
||||||
|
dd -33882112,-30605312,28508160,31653888,-2752512,193,4
|
||||||
|
dd 33685504,36044800,28508160,31653888,-3211264,193,4
|
||||||
|
dd -29425664,-26673152,32702464,35848192,-1703936,187,4
|
||||||
|
dd 29097984,32243712,32702464,35848192,-2818048,193,4
|
||||||
|
dd 45547520,46989312,-786432,524288,-2621440,190,4
|
||||||
|
dd 45547520,46989312,6291456,7602176,-2621440,190,4
|
||||||
|
dd 47775744,49217536,-1310720,0,-2162688,191,4
|
||||||
|
dd -33816576,-30670848,-34406400,-31260672,-2162688,186,4
|
||||||
|
dd 33751040,35979264,-34406400,-31260672,-2621440,186,4
|
||||||
|
dd -33947648,-30539776,32702464,35848192,-2031616,186,4
|
||||||
|
dd 33619968,36110336,32702464,35848192,-2490368,186,4
|
||||||
|
dd 47775744,49217536,6881280,8192000,-2162688,191,4
|
||||||
|
dd 50003968,51445760,-262144,1048576,-1703936,192,4
|
||||||
|
dd 50003968,51445760,7471104,8781824,-1703936,192,4
|
||||||
|
dd 52232192,53673984,-786432,524288,-2818048,193,4
|
||||||
|
dd 52232192,53673984,8060928,9371648,-2818048,193,4
|
||||||
|
dd 54460416,55902208,-1310720,0,-2359296,186,4
|
||||||
|
dd 54460416,55902208,6291456,7602176,-2359296,186,4
|
||||||
|
dd 56688640,58130432,-262144,1048576,-1900544,187,4
|
||||||
|
dd 56688640,58130432,6881280,8192000,-1900544,187,4
|
||||||
|
ROOF_PARK_COUNT equ 9
|
||||||
|
roofCityParks3D LABEL DWORD
|
||||||
|
dd -3407872,-11075584
|
||||||
|
dd 10747904,-1638400
|
||||||
|
dd -1048576,720896
|
||||||
|
dd 3670016,720896
|
||||||
|
dd 13107200,720896
|
||||||
|
dd -3407872,7798784
|
||||||
|
dd 8388608,7798784
|
||||||
|
dd -1048576,10158080
|
||||||
|
dd -10485760,12517376
|
||||||
|
ROOF_CITY_LAMP_COUNT equ 227
|
||||||
|
roofCityLamps3D LABEL DWORD
|
||||||
|
dd -9515827,-11075584
|
||||||
|
dd -9515827,-9109504
|
||||||
|
dd -9515827,-7143424
|
||||||
|
dd -9515827,-5177344
|
||||||
|
dd -9515827,-3211264
|
||||||
|
dd -9515827,-1245184
|
||||||
|
dd -9515827,720896
|
||||||
|
dd -9515827,2686976
|
||||||
|
dd -9515827,6619136
|
||||||
|
dd -9515827,8585216
|
||||||
|
dd -9515827,10551296
|
||||||
|
dd -9515827,12517376
|
||||||
|
dd -7156531,-11075584
|
||||||
|
dd -7156531,-9109504
|
||||||
|
dd -7156531,-7143424
|
||||||
|
dd -7156531,-5177344
|
||||||
|
dd -7156531,-3211264
|
||||||
|
dd -7156531,-1245184
|
||||||
|
dd -7156531,720896
|
||||||
|
dd -7156531,2686976
|
||||||
|
dd -7156531,6619136
|
||||||
|
dd -7156531,8585216
|
||||||
|
dd -7156531,10551296
|
||||||
|
dd -7156531,12517376
|
||||||
|
dd -4797235,-11075584
|
||||||
|
dd -4797235,-9109504
|
||||||
|
dd -4797235,-7143424
|
||||||
|
dd -4797235,-5177344
|
||||||
|
dd -4797235,-3211264
|
||||||
|
dd -4797235,-1245184
|
||||||
|
dd -4797235,720896
|
||||||
|
dd -4797235,2686976
|
||||||
|
dd -4797235,6619136
|
||||||
|
dd -4797235,8585216
|
||||||
|
dd -4797235,10551296
|
||||||
|
dd -4797235,12517376
|
||||||
|
dd -2437939,-11075584
|
||||||
|
dd -2437939,-9109504
|
||||||
|
dd -2437939,-7143424
|
||||||
|
dd -2437939,-5177344
|
||||||
|
dd -2437939,-3211264
|
||||||
|
dd -2437939,-1245184
|
||||||
|
dd -2437939,720896
|
||||||
|
dd -2437939,2686976
|
||||||
|
dd -2437939,6619136
|
||||||
|
dd -2437939,8585216
|
||||||
|
dd -2437939,10551296
|
||||||
|
dd -2437939,12517376
|
||||||
|
dd -78643,-11075584
|
||||||
|
dd -78643,-9109504
|
||||||
|
dd -78643,-7143424
|
||||||
|
dd -78643,-5177344
|
||||||
|
dd -78643,-3211264
|
||||||
|
dd -78643,-1245184
|
||||||
|
dd -78643,720896
|
||||||
|
dd -78643,2686976
|
||||||
|
dd -78643,6619136
|
||||||
|
dd -78643,8585216
|
||||||
|
dd -78643,10551296
|
||||||
|
dd -78643,12517376
|
||||||
|
dd 2280653,-11075584
|
||||||
|
dd 2280653,-9109504
|
||||||
|
dd 2280653,-7143424
|
||||||
|
dd 2280653,-5177344
|
||||||
|
dd 2280653,-3211264
|
||||||
|
dd 2280653,-1245184
|
||||||
|
dd 2280653,720896
|
||||||
|
dd 2280653,2686976
|
||||||
|
dd 2280653,6619136
|
||||||
|
dd 2280653,8585216
|
||||||
|
dd 2280653,10551296
|
||||||
|
dd 2280653,12517376
|
||||||
|
dd 4639949,-11075584
|
||||||
|
dd 4639949,-9109504
|
||||||
|
dd 4639949,-7143424
|
||||||
|
dd 4639949,-5177344
|
||||||
|
dd 4639949,-3211264
|
||||||
|
dd 4639949,-1245184
|
||||||
|
dd 4639949,720896
|
||||||
|
dd 4639949,6619136
|
||||||
|
dd 4639949,8585216
|
||||||
|
dd 4639949,10551296
|
||||||
|
dd 4639949,12517376
|
||||||
|
dd 6999245,-11075584
|
||||||
|
dd 6999245,-9109504
|
||||||
|
dd 6999245,-7143424
|
||||||
|
dd 6999245,-5177344
|
||||||
|
dd 6999245,-3211264
|
||||||
|
dd 6999245,-1245184
|
||||||
|
dd 6999245,720896
|
||||||
|
dd 6999245,6619136
|
||||||
|
dd 6999245,8585216
|
||||||
|
dd 6999245,10551296
|
||||||
|
dd 6999245,12517376
|
||||||
|
dd 9358541,-11075584
|
||||||
|
dd 9358541,-9109504
|
||||||
|
dd 9358541,-7143424
|
||||||
|
dd 9358541,-5177344
|
||||||
|
dd 9358541,-3211264
|
||||||
|
dd 9358541,-1245184
|
||||||
|
dd 9358541,720896
|
||||||
|
dd 9358541,6619136
|
||||||
|
dd 9358541,8585216
|
||||||
|
dd 9358541,10551296
|
||||||
|
dd 9358541,12517376
|
||||||
|
dd 11717837,-11075584
|
||||||
|
dd 11717837,-9109504
|
||||||
|
dd 11717837,-7143424
|
||||||
|
dd 11717837,-5177344
|
||||||
|
dd 11717837,-3211264
|
||||||
|
dd 11717837,-1245184
|
||||||
|
dd 11717837,720896
|
||||||
|
dd 11717837,6619136
|
||||||
|
dd 11717837,8585216
|
||||||
|
dd 11717837,10551296
|
||||||
|
dd 11717837,12517376
|
||||||
|
dd 14077133,-11075584
|
||||||
|
dd 14077133,-9109504
|
||||||
|
dd 14077133,-7143424
|
||||||
|
dd 14077133,-5177344
|
||||||
|
dd 14077133,-3211264
|
||||||
|
dd 14077133,-1245184
|
||||||
|
dd 14077133,720896
|
||||||
|
dd 14077133,6619136
|
||||||
|
dd 14077133,8585216
|
||||||
|
dd 14077133,10551296
|
||||||
|
dd 14077133,12517376
|
||||||
|
dd -11141120,3833856
|
||||||
|
dd -11141120,5079040
|
||||||
|
dd -9961472,3833856
|
||||||
|
dd -9961472,5079040
|
||||||
|
dd -8781824,3833856
|
||||||
|
dd -8781824,5079040
|
||||||
|
dd -7602176,3833856
|
||||||
|
dd -7602176,5079040
|
||||||
|
dd -6422528,3833856
|
||||||
|
dd -6422528,5079040
|
||||||
|
dd -5242880,3833856
|
||||||
|
dd -5242880,5079040
|
||||||
|
dd -4063232,3833856
|
||||||
|
dd -4063232,5079040
|
||||||
|
dd -2883584,3833856
|
||||||
|
dd -2883584,5079040
|
||||||
|
dd -1703936,3833856
|
||||||
|
dd -1703936,5079040
|
||||||
|
dd -524288,3833856
|
||||||
|
dd -524288,5079040
|
||||||
|
dd 655360,3833856
|
||||||
|
dd 655360,5079040
|
||||||
|
dd 1835008,3833856
|
||||||
|
dd 1835008,5079040
|
||||||
|
dd 3014656,3833856
|
||||||
|
dd 3014656,5079040
|
||||||
|
dd 4194304,3833856
|
||||||
|
dd 4194304,5079040
|
||||||
|
dd 5373952,5079040
|
||||||
|
dd 6553600,5079040
|
||||||
|
dd 7733248,5079040
|
||||||
|
dd 8912896,5079040
|
||||||
|
dd 10092544,5079040
|
||||||
|
dd 11272192,5079040
|
||||||
|
dd 12451840,5079040
|
||||||
|
dd 13631488,5079040
|
||||||
|
dd 5636096,1769472
|
||||||
|
dd 5636096,5111808
|
||||||
|
dd 6815744,1769472
|
||||||
|
dd 6815744,5111808
|
||||||
|
dd 7995392,1769472
|
||||||
|
dd 7995392,5111808
|
||||||
|
dd 9175040,1769472
|
||||||
|
dd 9175040,5111808
|
||||||
|
dd 10354688,1769472
|
||||||
|
dd 10354688,5111808
|
||||||
|
dd 11534336,1769472
|
||||||
|
dd 11534336,5111808
|
||||||
|
dd 12713984,1769472
|
||||||
|
dd 12713984,5111808
|
||||||
|
dd 13893632,1769472
|
||||||
|
dd 13893632,5111808
|
||||||
|
dd 15073280,1769472
|
||||||
|
dd 15073280,5111808
|
||||||
|
dd 16252928,1769472
|
||||||
|
dd 16252928,5111808
|
||||||
|
dd 17432576,1769472
|
||||||
|
dd 17432576,5111808
|
||||||
|
dd 18612224,1769472
|
||||||
|
dd 18612224,5111808
|
||||||
|
dd 19791872,1769472
|
||||||
|
dd 19791872,5111808
|
||||||
|
dd 20971520,1769472
|
||||||
|
dd 20971520,5111808
|
||||||
|
dd 22151168,1769472
|
||||||
|
dd 22151168,5111808
|
||||||
|
dd 23330816,1769472
|
||||||
|
dd 23330816,5111808
|
||||||
|
dd 24510464,1769472
|
||||||
|
dd 24510464,5111808
|
||||||
|
dd 25690112,1769472
|
||||||
|
dd 25690112,5111808
|
||||||
|
dd 26869760,1769472
|
||||||
|
dd 26869760,5111808
|
||||||
|
dd 28049408,1769472
|
||||||
|
dd 28049408,5111808
|
||||||
|
dd 29229056,1769472
|
||||||
|
dd 29229056,5111808
|
||||||
|
dd 30408704,1769472
|
||||||
|
dd 30408704,5111808
|
||||||
|
dd 31588352,1769472
|
||||||
|
dd 31588352,5111808
|
||||||
|
dd 32768000,1769472
|
||||||
|
dd 32768000,5111808
|
||||||
|
dd 33947648,1769472
|
||||||
|
dd 33947648,5111808
|
||||||
|
dd 35127296,1769472
|
||||||
|
dd 35127296,5111808
|
||||||
|
dd 36306944,1769472
|
||||||
|
dd 36306944,5111808
|
||||||
|
dd 37486592,1769472
|
||||||
|
dd 37486592,5111808
|
||||||
|
dd 38666240,1769472
|
||||||
|
dd 38666240,5111808
|
||||||
|
dd 39845888,1769472
|
||||||
|
dd 39845888,5111808
|
||||||
|
dd 41025536,1769472
|
||||||
|
dd 41025536,5111808
|
||||||
|
dd 42205184,1769472
|
||||||
|
dd 42205184,5111808
|
||||||
|
ROOF_LANDMARK_PARTS equ 26
|
||||||
|
roofLandmarkParts3D LABEL DWORD
|
||||||
|
dd 0,131072,2490368,6619136,8978432,-3932160,-1441792,193
|
||||||
|
dd 0,524288,2097152,7012352,8585216,-1441792,-1048576,168
|
||||||
|
dd 0,1966080,2011955,7798784,7844659,-1048576,-655360,168
|
||||||
|
dd 0,1916194,1962069,8049579,8095455,-1048576,-655360,168
|
||||||
|
dd 0,1774130,1820005,8262194,8308069,-1048576,-655360,168
|
||||||
|
dd 0,1561515,1607391,8404258,8450133,-1048576,-655360,168
|
||||||
|
dd 0,1310720,1356595,8454144,8500019,-1048576,-655360,168
|
||||||
|
dd 0,1059925,1105800,8404258,8450133,-1048576,-655360,168
|
||||||
|
dd 0,847310,893186,8262194,8308069,-1048576,-655360,168
|
||||||
|
dd 0,705246,751122,8049579,8095455,-1048576,-655360,168
|
||||||
|
dd 0,655360,701235,7798784,7844659,-1048576,-655360,168
|
||||||
|
dd 0,705246,751122,7547989,7593864,-1048576,-655360,168
|
||||||
|
dd 0,847310,893186,7335374,7381250,-1048576,-655360,168
|
||||||
|
dd 0,1059925,1105800,7193310,7239186,-1048576,-655360,168
|
||||||
|
dd 0,1310720,1356595,7143424,7189299,-1048576,-655360,168
|
||||||
|
dd 0,1561515,1607391,7193310,7239186,-1048576,-655360,168
|
||||||
|
dd 0,1774130,1820005,7335374,7381250,-1048576,-655360,168
|
||||||
|
dd 0,1916194,1962069,7547989,7593864,-1048576,-655360,168
|
||||||
|
dd 0,524288,2097152,7012352,8585216,-655360,-602931,196
|
||||||
|
dd 1,1310720,7798784,-616038,773325,773325,655360,196
|
||||||
|
dd 0,1232077,1389363,7720141,7877427,0,262144,166
|
||||||
|
dd 0,1297613,1323827,7785677,7811891,262144,655360,166
|
||||||
|
dd 0,9830400,11665408,-196608,1638400,-3932160,-1703936,191
|
||||||
|
dd 0,10354688,11141120,327680,1114112,-1703936,-524288,206
|
||||||
|
dd 0,10485760,11010048,458752,983040,-524288,262144,191
|
||||||
|
dd 2,10747904,720896,262144,235930,235930,2621440,166
|
||||||
|
roofFog3D db 0,1,1,2,3,4,4,5,6,6,7,8,8,9,10,10,11,11,12,13,13,14,15,15,16,16,17,18,18,19,19,20
|
||||||
|
db 20,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,32,32,33,33,34,34,35,35,36,36
|
||||||
|
db 37,37,38,38,38,39,39,40,40,41,41,42,42,42,43,43,44,44,44,45,45,46,46,46,47,47,48,48,48,49,49,50
|
||||||
|
db 50,50,51,51,51,52,52,53,53,53,54,54,54,55,55,55,56,56,56,57,57,57,58,58,58,59,59,59,60,60,60,61
|
||||||
|
db 61,61,62,62,62,63,63,63,63,64,64,64,65,65,65,65,66,66,66,67,67,67,68,68,68,68,69,69,69,69,70,70
|
||||||
|
db 70,71,71,71,71,72,72,72,72,73,73,73,73,74,74,74,74,75,75,75,75,76,76,76,76,77,77,77,77,77,78,78
|
||||||
|
db 78,78,79,79,79,79,80,80,80,80,80,81,81,81,81,82,82,82,82,82,83,83,83,83,83,84,84,84,84,84,85,85
|
||||||
|
db 85,85,85,86,86,86,86,86,87,87,87,87,87,88,88,88,88,88,89,89,89,89,89,89,90,90,90,90,90,91,91,91
|
||||||
|
db 91,91,91,92,92,92,92,92,92,93,93,93,93,93,93,94,94,94,94,94,94,95,95,95,95,95,95,96,96,96,96,96
|
||||||
|
db 96,97,97,97,97,97,97,97,98,98,98,98,98,98,98,99,99,99,99,99,99,99,100,100,100,100,100,100,100,101,101,101
|
||||||
|
db 101,101,101,101,102,102,102,102,102,102,102,103,103,103,103,103,103,103,103,104,104,104,104,104,104,104,104,105,105,105,105,105
|
||||||
|
db 105,105,105,106,106,106,106,106,106,106,106,107,107,107,107,107,107,107,107,108,108,108,108,108,108,108,108,108,109,109,109,109
|
||||||
|
db 109,109,109,109,109,110,110,110,110,110,110,110,110,110,111,111,111,111,111,111,111,111,111,112,112,112,112,112,112,112,112,112
|
||||||
|
db 112,113,113,113,113,113,113,113,113,113,113,114,114,114,114,114,114,114,114,114,114,114,115,115,115,115,115,115,115,115,115,115
|
||||||
|
db 116,116,116,116,116,116,116,116,116,116,116,117,117,117,117,117,117,117,117,117,117,117,118,118,118,118,118,118,118,118,118,118
|
||||||
|
db 118,118,119,119,119,119,119,119,119,119,119,119,119,119,120,120,120,120,120,120,120,120,120,120,120,120,120,121,121,121,121,121
|
||||||
|
db 121,121,121,121,121,121,121,121,122,122,122,122,122,122,122,122,122,122,122,122,122,123,123,123,123,123,123,123,123,123,123,123
|
||||||
|
db 123,123,123,124,124,124,124,124,124,124,124,124,124,124,124,124,124,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125
|
||||||
|
db 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127
|
||||||
|
db 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129
|
||||||
|
db 129,129,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,131,131,131,131,131,131,131,131,131,131,131,131
|
||||||
|
db 131,131,131,131,131,131,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,133,133,133,133,133,133
|
||||||
|
db 133,133,133,133,133,133,133,133,133,133,133,133,133,133,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134
|
||||||
|
db 134,134,134,134,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,136,136,136,136,136,136
|
||||||
|
db 136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137
|
||||||
|
db 137,137,137,137,137,137,137,137,137,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138
|
||||||
|
db 138,138,138,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,140,140
|
||||||
|
db 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,141,141,141,141,141,141
|
||||||
|
db 141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,142,142,142,142,142,142,142,142,142
|
||||||
|
db 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,143,143,143,143,143,143,143,143,143
|
||||||
|
db 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,144,144,144,144,144,144,144,144,144
|
||||||
|
db 144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,145,145,145,145,145,145
|
||||||
|
.code
|
||||||
1118
src_graphics/rooftop_gl.inc
Normal file
91
src_graphics/rooftop_gl_api.inc
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
; Windows' system OpenGL entry points. All scene logic and calls are native MASM.
|
||||||
|
includelib opengl32.lib
|
||||||
|
includelib msimg32.lib
|
||||||
|
glBegin PROTO STDCALL :DWORD
|
||||||
|
glEnd PROTO STDCALL
|
||||||
|
glVertex3f PROTO STDCALL :DWORD,:DWORD,:DWORD
|
||||||
|
glNormal3f PROTO STDCALL :DWORD,:DWORD,:DWORD
|
||||||
|
glTexCoord2f PROTO STDCALL :DWORD,:DWORD
|
||||||
|
glColor4f PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
glEnable PROTO STDCALL :DWORD
|
||||||
|
glDisable PROTO STDCALL :DWORD
|
||||||
|
glClear PROTO STDCALL :DWORD
|
||||||
|
glClearColor PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
glViewport PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
glMatrixMode PROTO STDCALL :DWORD
|
||||||
|
glLoadIdentity PROTO STDCALL
|
||||||
|
glPushMatrix PROTO STDCALL
|
||||||
|
glPopMatrix PROTO STDCALL
|
||||||
|
glTranslatef PROTO STDCALL :DWORD,:DWORD,:DWORD
|
||||||
|
glRotatef PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
glFrustum PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
glOrtho PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
glGenTextures PROTO STDCALL :DWORD,:DWORD
|
||||||
|
glDeleteTextures PROTO STDCALL :DWORD,:DWORD
|
||||||
|
glBindTexture PROTO STDCALL :DWORD,:DWORD
|
||||||
|
glTexParameteri PROTO STDCALL :DWORD,:DWORD,:DWORD
|
||||||
|
glTexImage2D PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
glGenLists PROTO STDCALL :DWORD
|
||||||
|
glNewList PROTO STDCALL :DWORD,:DWORD
|
||||||
|
glEndList PROTO STDCALL
|
||||||
|
glCallList PROTO STDCALL :DWORD
|
||||||
|
glDeleteLists PROTO STDCALL :DWORD,:DWORD
|
||||||
|
glLightfv PROTO STDCALL :DWORD,:DWORD,:DWORD
|
||||||
|
glLightModelfv PROTO STDCALL :DWORD,:DWORD
|
||||||
|
glMaterialfv PROTO STDCALL :DWORD,:DWORD,:DWORD
|
||||||
|
glColorMaterial PROTO STDCALL :DWORD,:DWORD
|
||||||
|
glFogfv PROTO STDCALL :DWORD,:DWORD
|
||||||
|
glFogf PROTO STDCALL :DWORD,:DWORD
|
||||||
|
glFogi PROTO STDCALL :DWORD,:DWORD
|
||||||
|
glShadeModel PROTO STDCALL :DWORD
|
||||||
|
glBlendFunc PROTO STDCALL :DWORD,:DWORD
|
||||||
|
glDepthMask PROTO STDCALL :DWORD
|
||||||
|
glDepthFunc PROTO STDCALL :DWORD
|
||||||
|
glPolygonOffset PROTO STDCALL :DWORD,:DWORD
|
||||||
|
glReadPixels PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
glReadBuffer PROTO STDCALL :DWORD
|
||||||
|
glDrawBuffer PROTO STDCALL :DWORD
|
||||||
|
glGetError PROTO STDCALL
|
||||||
|
glGetString PROTO STDCALL :DWORD
|
||||||
|
glGetIntegerv PROTO STDCALL :DWORD,:DWORD
|
||||||
|
glFlush PROTO STDCALL
|
||||||
|
glFinish PROTO STDCALL
|
||||||
|
glCullFace PROTO STDCALL :DWORD
|
||||||
|
glFrontFace PROTO STDCALL :DWORD
|
||||||
|
wglCreateContext PROTO STDCALL :DWORD
|
||||||
|
wglDeleteContext PROTO STDCALL :DWORD
|
||||||
|
wglMakeCurrent PROTO STDCALL :DWORD,:DWORD
|
||||||
|
wglGetProcAddress PROTO STDCALL :DWORD
|
||||||
|
IFNDEF RegisterClassA
|
||||||
|
RegisterClassA PROTO STDCALL :DWORD
|
||||||
|
ENDIF
|
||||||
|
IFNDEF ChoosePixelFormat
|
||||||
|
ChoosePixelFormat PROTO STDCALL :DWORD,:DWORD
|
||||||
|
ENDIF
|
||||||
|
IFNDEF SetPixelFormat
|
||||||
|
SetPixelFormat PROTO STDCALL :DWORD,:DWORD,:DWORD
|
||||||
|
ENDIF
|
||||||
|
IFNDEF CreateDIBSection
|
||||||
|
CreateDIBSection PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
ENDIF
|
||||||
|
IFNDEF CreateCompatibleDC
|
||||||
|
CreateCompatibleDC PROTO STDCALL :DWORD
|
||||||
|
ENDIF
|
||||||
|
IFNDEF DeleteDC
|
||||||
|
DeleteDC PROTO STDCALL :DWORD
|
||||||
|
ENDIF
|
||||||
|
IFNDEF SelectObject
|
||||||
|
SelectObject PROTO STDCALL :DWORD,:DWORD
|
||||||
|
ENDIF
|
||||||
|
IFNDEF DeleteObject
|
||||||
|
DeleteObject PROTO STDCALL :DWORD
|
||||||
|
ENDIF
|
||||||
|
IFNDEF AlphaBlend
|
||||||
|
AlphaBlend PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
ENDIF
|
||||||
|
IFNDEF GdiFlush
|
||||||
|
GdiFlush PROTO STDCALL
|
||||||
|
ENDIF
|
||||||
|
IFNDEF StretchBlt
|
||||||
|
StretchBlt PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
ENDIF
|
||||||
189
src_graphics/rooftop_gl_data.inc
Normal file
|
|
@ -0,0 +1,189 @@
|
||||||
|
include src_graphics\rooftop_gl_api.inc
|
||||||
|
ROOF_HD_W equ 1280
|
||||||
|
ROOF_HD_H equ 960
|
||||||
|
ROOF_GL_TEXTURES equ 49
|
||||||
|
InitRoofHD3D PROTO
|
||||||
|
FreeRoofHD3D PROTO
|
||||||
|
RenderRoofHD3D PROTO
|
||||||
|
PresentRoofHD3D PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
LoadRoofMesh3D PROTO :DWORD,:DWORD
|
||||||
|
FreeRoofMesh3D PROTO :DWORD
|
||||||
|
RoofGLProc3D PROTO :DWORD,:DWORD
|
||||||
|
UploadRoofGLTexture3D PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
BuildRoofGLList3D PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
||||||
|
DrawRoofGLSky3D PROTO
|
||||||
|
DrawRoofGLTraffic3D PROTO
|
||||||
|
DrawRoofGLWater3D PROTO
|
||||||
|
UploadRoofGLSky3D PROTO :DWORD,:DWORD
|
||||||
|
UpdateRoofGLFog3D PROTO
|
||||||
|
UpdateRoofQuality3D PROTO
|
||||||
|
ComposeRoofFrame3D PROTO
|
||||||
|
RenderRoofQualityToast3D PROTO
|
||||||
|
WriteRoofRendererInfo3D PROTO
|
||||||
|
WriteRoofLogString3D PROTO :DWORD,:DWORD
|
||||||
|
.data
|
||||||
|
roofHDReady3D dd 0
|
||||||
|
roofHDStage3D dd 0
|
||||||
|
roofHDWindow3D dd 0
|
||||||
|
roofHDDC3D dd 0
|
||||||
|
roofHDRC3D dd 0
|
||||||
|
roofHDModule3D dd 0
|
||||||
|
roofHDBuffer3D dd 0
|
||||||
|
roofHDFBO3D dd 0
|
||||||
|
roofHDColorTex3D dd 0
|
||||||
|
roofHDDepth3D dd 0
|
||||||
|
roofHDLists3D dd 0
|
||||||
|
roofHDSkyTextures3D dd 2 dup(0)
|
||||||
|
roofHDDayTextures3D dd ROOF_GL_TEXTURES dup(0)
|
||||||
|
roofHDNightTextures3D dd ROOF_GL_TEXTURES dup(0)
|
||||||
|
roofHDEmissionTextures3D dd ROOF_GL_TEXTURES dup(0)
|
||||||
|
roofHDMeshScene3D dd 4 dup(0)
|
||||||
|
roofHDMeshCar3D dd 4 dup(0)
|
||||||
|
roofHDMeshBoat3D dd 4 dup(0)
|
||||||
|
roofHDScenePath3D db "assets\animations\rooftop\mesh-city-v1.bin",0
|
||||||
|
roofHDCarPath3D db "assets\animations\rooftop\mesh-car-v1.bin",0
|
||||||
|
roofHDBoatPath3D db "assets\animations\rooftop\mesh-boat-v1.bin",0
|
||||||
|
roofHDMeshPtrs3D dd OFFSET roofHDMeshScene3D,OFFSET roofHDMeshCar3D,OFFSET roofHDMeshBoat3D
|
||||||
|
roofHDClassName3D db "AssemblerCasinoRoofOffscreen",0
|
||||||
|
roofHDTitle3D db "Roof offscreen renderer",0
|
||||||
|
roofHDClass3D dd 20h,OFFSET DefWindowProcA,0,0,0,0,0,0,0,OFFSET roofHDClassName3D
|
||||||
|
; PIXELFORMATDESCRIPTOR: RGBA32, depth24, draw-to-window/OpenGL/double-buffer.
|
||||||
|
roofHDPixelFormat3D dw 40,1
|
||||||
|
dd 25h
|
||||||
|
db 0,32,0,0,0,0,0,0,8,0,0,0,0,0,0,24,8,0,0,0
|
||||||
|
dd 0,0,0
|
||||||
|
roofHDOverlayDC3D dd 0
|
||||||
|
roofHDOverlayBmp3D dd 0
|
||||||
|
roofHDOverlayOld3D dd 0
|
||||||
|
roofHDFinalDC3D dd 0
|
||||||
|
roofHDFinalBmp3D dd 0
|
||||||
|
roofHDFinalOld3D dd 0
|
||||||
|
roofHDFinalPixels3D dd 0
|
||||||
|
roofHDOverlayPixels3D dd 0
|
||||||
|
roofHDOverlayBMI3D dd 40,640,-480
|
||||||
|
dw 1,32
|
||||||
|
dd 0,640*480*4,0,0,0,0
|
||||||
|
roofHDBMI3D dd 40,ROOF_HD_W,ROOF_HD_H
|
||||||
|
dw 1,32
|
||||||
|
dd 0,ROOF_HD_W*ROOF_HD_H*4,0,0,0,0
|
||||||
|
roofGLGenFBO3D dd 0
|
||||||
|
roofGLBindFBO3D dd 0
|
||||||
|
roofGLAttachTexture3D dd 0
|
||||||
|
roofGLCheckFBO3D dd 0
|
||||||
|
roofGLDeleteFBO3D dd 0
|
||||||
|
roofGLGenRBO3D dd 0
|
||||||
|
roofGLBindRBO3D dd 0
|
||||||
|
roofGLStoreRBO3D dd 0
|
||||||
|
roofGLAttachRBO3D dd 0
|
||||||
|
roofGLDeleteRBO3D dd 0
|
||||||
|
roofGLMipmap3D dd 0
|
||||||
|
roofGLProcSlots3D dd OFFSET roofGLGenFBO3D,OFFSET roofGLBindFBO3D,OFFSET roofGLAttachTexture3D
|
||||||
|
dd OFFSET roofGLCheckFBO3D,OFFSET roofGLDeleteFBO3D,OFFSET roofGLGenRBO3D
|
||||||
|
dd OFFSET roofGLBindRBO3D,OFFSET roofGLStoreRBO3D,OFFSET roofGLAttachRBO3D
|
||||||
|
dd OFFSET roofGLDeleteRBO3D,OFFSET roofGLMipmap3D
|
||||||
|
roofGLProcNames3D dd OFFSET roofGLName0,OFFSET roofGLName1,OFFSET roofGLName2,OFFSET roofGLName3
|
||||||
|
dd OFFSET roofGLName4,OFFSET roofGLName5,OFFSET roofGLName6,OFFSET roofGLName7
|
||||||
|
dd OFFSET roofGLName8,OFFSET roofGLName9,OFFSET roofGLName10
|
||||||
|
roofGLProcExtNames3D dd OFFSET roofGLExt0,OFFSET roofGLExt1,OFFSET roofGLExt2,OFFSET roofGLExt3
|
||||||
|
dd OFFSET roofGLExt4,OFFSET roofGLExt5,OFFSET roofGLExt6,OFFSET roofGLExt7
|
||||||
|
dd OFFSET roofGLExt8,OFFSET roofGLExt9,OFFSET roofGLExt10
|
||||||
|
roofGLName0 db "glGenFramebuffers",0
|
||||||
|
roofGLName1 db "glBindFramebuffer",0
|
||||||
|
roofGLName2 db "glFramebufferTexture2D",0
|
||||||
|
roofGLName3 db "glCheckFramebufferStatus",0
|
||||||
|
roofGLName4 db "glDeleteFramebuffers",0
|
||||||
|
roofGLName5 db "glGenRenderbuffers",0
|
||||||
|
roofGLName6 db "glBindRenderbuffer",0
|
||||||
|
roofGLName7 db "glRenderbufferStorage",0
|
||||||
|
roofGLName8 db "glFramebufferRenderbuffer",0
|
||||||
|
roofGLName9 db "glDeleteRenderbuffers",0
|
||||||
|
roofGLName10 db "glGenerateMipmap",0
|
||||||
|
roofGLExt0 db "glGenFramebuffersEXT",0
|
||||||
|
roofGLExt1 db "glBindFramebufferEXT",0
|
||||||
|
roofGLExt2 db "glFramebufferTexture2DEXT",0
|
||||||
|
roofGLExt3 db "glCheckFramebufferStatusEXT",0
|
||||||
|
roofGLExt4 db "glDeleteFramebuffersEXT",0
|
||||||
|
roofGLExt5 db "glGenRenderbuffersEXT",0
|
||||||
|
roofGLExt6 db "glBindRenderbufferEXT",0
|
||||||
|
roofGLExt7 db "glRenderbufferStorageEXT",0
|
||||||
|
roofGLExt8 db "glFramebufferRenderbufferEXT",0
|
||||||
|
roofGLExt9 db "glDeleteRenderbuffersEXT",0
|
||||||
|
roofGLExt10 db "glGenerateMipmapEXT",0
|
||||||
|
roofGLFogDay3D REAL4 0.67,0.61,0.69,1.0
|
||||||
|
roofGLFogNight3D REAL4 0.05,0.09,0.17,1.0
|
||||||
|
roofGLFogCurrent3D REAL4 0.67,0.61,0.69,1.0
|
||||||
|
roofGLFogWhite3D REAL4 1.0,1.0,1.0,1.0
|
||||||
|
roofGLFogBlack3D REAL4 0.0,0.0,0.0,1.0
|
||||||
|
roofGLColorScale3D REAL4 255.0
|
||||||
|
roofGLWaveDiv3D REAL4 100000.0
|
||||||
|
roofGLHalf3D REAL4 0.5
|
||||||
|
roofGLWaterVertices3D REAL4 -2000.0,-62.0,76.0,-166.666667,6.333333
|
||||||
|
REAL4 2000.0,-62.0,76.0,166.666667,6.333333
|
||||||
|
REAL4 2000.0,-62.0,60.0,166.666667,5.0
|
||||||
|
REAL4 -2000.0,-62.0,60.0,-166.666667,5.0
|
||||||
|
REAL4 70.0,-62.0,60.0,5.833333,5.0
|
||||||
|
REAL4 2000.0,-62.0,60.0,166.666667,5.0
|
||||||
|
REAL4 2000.0,-62.0,29.0,166.666667,2.416667
|
||||||
|
REAL4 70.0,-62.0,29.0,5.833333,2.416667
|
||||||
|
roofGLAmbientDay3D REAL4 0.43,0.43,0.48,1.0
|
||||||
|
roofGLAmbientNight3D REAL4 0.20,0.23,0.32,1.0
|
||||||
|
roofGLSunColorDay3D REAL4 0.75,0.57,0.39,1.0
|
||||||
|
roofGLSunColorNight3D REAL4 0.12,0.15,0.25,1.0
|
||||||
|
roofGLSunDirection3D REAL4 -0.8,0.8,0.4,0.0
|
||||||
|
roofGLEmissionZero3D REAL4 0.0,0.0,0.0,1.0
|
||||||
|
roofGLEmissionGold3D REAL4 0.42,0.28,0.08,1.0
|
||||||
|
roofGLEmissionLamp3D REAL4 0.9,0.67,0.3,1.0
|
||||||
|
roofGLInvFP3D REAL4 0.0000152587890625
|
||||||
|
roofGLDegrees3D REAL4 0.703125
|
||||||
|
roofGLNinety3D REAL4 90.0
|
||||||
|
roofGLHalfWidth3D REAL8 0.66
|
||||||
|
roofGLLeft3D REAL8 -0.66
|
||||||
|
roofGLRight3D REAL8 0.66
|
||||||
|
roofGLNear3D REAL8 1.0
|
||||||
|
roofGLFar3D REAL8 2048.0
|
||||||
|
roofGLZeroD3D REAL8 0.0
|
||||||
|
roofGLOneD3D REAL8 1.0
|
||||||
|
roofGLMinusOneD3D REAL8 -1.0
|
||||||
|
roofGLScreenWidthD3D REAL8 1280.0
|
||||||
|
roofGLScreenHeightD3D REAL8 960.0
|
||||||
|
roofGLCameraH3D dd 480
|
||||||
|
roofHDRenderX3D dd -1
|
||||||
|
roofHDRenderY3D dd -1
|
||||||
|
roofHDRenderAngle3D dd -1
|
||||||
|
roofHDRenderEye3D dd -1
|
||||||
|
roofHDRenderHorizon3D dd -1
|
||||||
|
roofHDRenderTheme3D dd -1
|
||||||
|
roofHDRenderClock3D dd -1
|
||||||
|
roofRenderW3D dd 960
|
||||||
|
roofRenderH3D dd 720
|
||||||
|
roofQualityMode3D dd 0
|
||||||
|
roofAutoWidth3D dd 960
|
||||||
|
roofQualityMapW3D dd 0
|
||||||
|
roofQualityClock3D dd -1
|
||||||
|
roofQualitySlow3D dd 0
|
||||||
|
roofQualityToast3D dd 0
|
||||||
|
roofQualityAutoText3D db 202,208,219,216,192,58,32,192,194,210,206,0
|
||||||
|
roofQualityEcoText3D db 202,208,219,216,192,58,32,221,202,206,0
|
||||||
|
roofQualityHighText3D db 202,208,219,216,192,58,32,196,197,210,192,203,200,0
|
||||||
|
roofLogPath3D db "runtime\roof-renderer.txt",0
|
||||||
|
roofLogHeader3D db "Native MASM rooftop renderer",13,10,0
|
||||||
|
roofLogVendor3D db "Vendor: ",0
|
||||||
|
roofLogRenderer3D db "Renderer: ",0
|
||||||
|
roofLogVersion3D db "OpenGL: ",0
|
||||||
|
roofLogStage3D db "Init stage (0=ready): ",0
|
||||||
|
roofLogAssets3D db "City texture pack present: ",0
|
||||||
|
roofLogWidth3D db "Render width: ",0
|
||||||
|
roofLogSmall3D db "640",0
|
||||||
|
roofLogMedium3D db "960",0
|
||||||
|
roofLogLarge3D db "1280",0
|
||||||
|
roofLogUnknown3D db "unavailable",0
|
||||||
|
roofLogNL3D db 13,10,0
|
||||||
|
roofLogDigit3D db "0",0
|
||||||
|
.data?
|
||||||
|
roofHDBackdrop3D dd SCREEN_SIZE dup(?)
|
||||||
|
roofHDUsedMaterials3D db ROOF_GL_TEXTURES dup(?)
|
||||||
|
roofQualityX3D dd SCREEN_W dup(?)
|
||||||
|
roofQualityXCount3D dd SCREEN_W dup(?)
|
||||||
|
roofQualityY3D dd SCREEN_H dup(?)
|
||||||
|
roofQualityYCount3D dd SCREEN_H dup(?)
|
||||||
|
.code
|
||||||
74
src_graphics/rooftop_map.inc
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
; Generated by tools/generators/pack_rooftop.py.
|
||||||
|
.data
|
||||||
|
roofMap3D db 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102
|
||||||
|
db 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102
|
||||||
|
roofSkyColumns3D dd -190,-190,-189,-189,-188,-188,-187,-187,-186,-186,-185,-185,-184,-184,-184,-183
|
||||||
|
dd -183,-182,-182,-181,-181,-180,-180,-179,-179,-178,-178,-177,-177,-176,-176,-175
|
||||||
|
dd -175,-174,-174,-173,-173,-172,-172,-171,-171,-170,-170,-169,-169,-168,-168,-167
|
||||||
|
dd -167,-166,-166,-165,-165,-164,-164,-163,-163,-162,-161,-161,-160,-160,-159,-159
|
||||||
|
dd -158,-158,-157,-157,-156,-156,-155,-155,-154,-154,-153,-153,-152,-151,-151,-150
|
||||||
|
dd -150,-149,-149,-148,-148,-147,-147,-146,-145,-145,-144,-144,-143,-143,-142,-142
|
||||||
|
dd -141,-141,-140,-139,-139,-138,-138,-137,-137,-136,-135,-135,-134,-134,-133,-133
|
||||||
|
dd -132,-132,-131,-130,-130,-129,-129,-128,-128,-127,-126,-126,-125,-125,-124,-123
|
||||||
|
dd -123,-122,-122,-121,-121,-120,-119,-119,-118,-118,-117,-116,-116,-115,-115,-114
|
||||||
|
dd -113,-113,-112,-112,-111,-111,-110,-109,-109,-108,-108,-107,-106,-106,-105,-105
|
||||||
|
dd -104,-103,-103,-102,-101,-101,-100,-100,-99,-98,-98,-97,-97,-96,-95,-95
|
||||||
|
dd -94,-93,-93,-92,-92,-91,-90,-90,-89,-89,-88,-87,-87,-86,-85,-85
|
||||||
|
dd -84,-84,-83,-82,-82,-81,-80,-80,-79,-78,-78,-77,-77,-76,-75,-75
|
||||||
|
dd -74,-73,-73,-72,-71,-71,-70,-70,-69,-68,-68,-67,-66,-66,-65,-64
|
||||||
|
dd -64,-63,-62,-62,-61,-60,-60,-59,-59,-58,-57,-57,-56,-55,-55,-54
|
||||||
|
dd -53,-53,-52,-51,-51,-50,-49,-49,-48,-47,-47,-46,-45,-45,-44,-43
|
||||||
|
dd -43,-42,-41,-41,-40,-39,-39,-38,-37,-37,-36,-35,-35,-34,-33,-33
|
||||||
|
dd -32,-31,-31,-30,-29,-29,-28,-27,-27,-26,-25,-25,-24,-23,-23,-22
|
||||||
|
dd -21,-21,-20,-19,-19,-18,-17,-17,-16,-15,-15,-14,-13,-13,-12,-11
|
||||||
|
dd -11,-10,-9,-9,-8,-7,-7,-6,-5,-5,-4,-3,-3,-2,-1,-1
|
||||||
|
dd 0,1,1,2,3,3,4,5,5,6,7,7,8,9,9,10
|
||||||
|
dd 11,11,12,13,13,14,15,15,16,17,17,18,19,19,20,21
|
||||||
|
dd 21,22,23,23,24,25,25,26,27,27,28,29,29,30,31,31
|
||||||
|
dd 32,33,33,34,35,35,36,37,37,38,39,39,40,41,41,42
|
||||||
|
dd 43,43,44,45,45,46,47,47,48,49,49,50,51,51,52,53
|
||||||
|
dd 53,54,55,55,56,57,57,58,59,59,60,60,61,62,62,63
|
||||||
|
dd 64,64,65,66,66,67,68,68,69,70,70,71,71,72,73,73
|
||||||
|
dd 74,75,75,76,77,77,78,78,79,80,80,81,82,82,83,84
|
||||||
|
dd 84,85,85,86,87,87,88,89,89,90,90,91,92,92,93,93
|
||||||
|
dd 94,95,95,96,97,97,98,98,99,100,100,101,101,102,103,103
|
||||||
|
dd 104,105,105,106,106,107,108,108,109,109,110,111,111,112,112,113
|
||||||
|
dd 113,114,115,115,116,116,117,118,118,119,119,120,121,121,122,122
|
||||||
|
dd 123,123,124,125,125,126,126,127,128,128,129,129,130,130,131,132
|
||||||
|
dd 132,133,133,134,134,135,135,136,137,137,138,138,139,139,140,141
|
||||||
|
dd 141,142,142,143,143,144,144,145,145,146,147,147,148,148,149,149
|
||||||
|
dd 150,150,151,151,152,153,153,154,154,155,155,156,156,157,157,158
|
||||||
|
dd 158,159,159,160,160,161,161,162,163,163,164,164,165,165,166,166
|
||||||
|
dd 167,167,168,168,169,169,170,170,171,171,172,172,173,173,174,174
|
||||||
|
dd 175,175,176,176,177,177,178,178,179,179,180,180,181,181,182,182
|
||||||
|
dd 183,183,184,184,184,185,185,186,186,187,187,188,188,189,189,190
|
||||||
274
src_graphics/rooftop_quality.inc
Normal file
|
|
@ -0,0 +1,274 @@
|
||||||
|
; Quality changes only roof rendering. Simulation, collisions and other games stay native.
|
||||||
|
UpdateRoofQuality3D PROC uses ebx esi edi
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
jne roof_quality_apply
|
||||||
|
cmp engineMode,MODE_WALK
|
||||||
|
jne roof_quality_apply
|
||||||
|
mov eax,animationClock3D
|
||||||
|
cmp eax,roofQualityClock3D
|
||||||
|
je roof_quality_apply
|
||||||
|
mov roofQualityClock3D,eax
|
||||||
|
invoke Pressed3D,77h
|
||||||
|
test eax,eax
|
||||||
|
jz roof_quality_auto
|
||||||
|
inc roofQualityMode3D
|
||||||
|
cmp roofQualityMode3D,3
|
||||||
|
jb @F
|
||||||
|
mov roofQualityMode3D,0
|
||||||
|
mov roofAutoWidth3D,960
|
||||||
|
@@:
|
||||||
|
mov roofQualityToast3D,1800
|
||||||
|
mov roofQualitySlow3D,0
|
||||||
|
roof_quality_auto:
|
||||||
|
mov eax,deltaTime3D
|
||||||
|
cmp eax,100
|
||||||
|
jbe @F
|
||||||
|
mov eax,100
|
||||||
|
@@:
|
||||||
|
sub roofQualityToast3D,eax
|
||||||
|
jns @F
|
||||||
|
mov roofQualityToast3D,0
|
||||||
|
@@:
|
||||||
|
cmp roofQualityMode3D,0
|
||||||
|
jne roof_quality_apply
|
||||||
|
cmp roofAutoWidth3D,640
|
||||||
|
je roof_quality_apply
|
||||||
|
cmp deltaTime3D,34
|
||||||
|
jbe roof_quality_cool
|
||||||
|
add roofQualitySlow3D,eax
|
||||||
|
cmp roofQualitySlow3D,1000
|
||||||
|
jb roof_quality_apply
|
||||||
|
mov roofAutoWidth3D,640
|
||||||
|
mov roofQualitySlow3D,0
|
||||||
|
mov roofQualityToast3D,1800
|
||||||
|
jmp roof_quality_apply
|
||||||
|
roof_quality_cool:
|
||||||
|
sub roofQualitySlow3D,8
|
||||||
|
jns roof_quality_apply
|
||||||
|
mov roofQualitySlow3D,0
|
||||||
|
roof_quality_apply:
|
||||||
|
mov eax,roofAutoWidth3D
|
||||||
|
cmp roofQualityMode3D,0
|
||||||
|
je roof_quality_size
|
||||||
|
mov eax,640
|
||||||
|
cmp roofQualityMode3D,1
|
||||||
|
je roof_quality_size
|
||||||
|
mov eax,1280
|
||||||
|
roof_quality_size:
|
||||||
|
mov roofRenderW3D,eax
|
||||||
|
imul eax,3
|
||||||
|
shr eax,2
|
||||||
|
mov roofRenderH3D,eax
|
||||||
|
mov eax,roofRenderW3D
|
||||||
|
cmp eax,roofQualityMapW3D
|
||||||
|
je roof_quality_done
|
||||||
|
mov roofQualityMapW3D,eax
|
||||||
|
mov roofHDRenderClock3D,-1
|
||||||
|
xor esi,esi
|
||||||
|
roof_quality_x:
|
||||||
|
mov eax,esi
|
||||||
|
imul eax,roofRenderW3D
|
||||||
|
xor edx,edx
|
||||||
|
mov ecx,SCREEN_W
|
||||||
|
div ecx
|
||||||
|
mov ebx,eax
|
||||||
|
shl eax,2
|
||||||
|
mov roofQualityX3D[esi*4],eax
|
||||||
|
mov eax,esi
|
||||||
|
inc eax
|
||||||
|
imul eax,roofRenderW3D
|
||||||
|
xor edx,edx
|
||||||
|
div ecx
|
||||||
|
sub eax,ebx
|
||||||
|
mov roofQualityXCount3D[esi*4],eax
|
||||||
|
inc esi
|
||||||
|
cmp esi,SCREEN_W
|
||||||
|
jb roof_quality_x
|
||||||
|
xor esi,esi
|
||||||
|
roof_quality_y:
|
||||||
|
mov eax,esi
|
||||||
|
imul eax,roofRenderH3D
|
||||||
|
xor edx,edx
|
||||||
|
mov ecx,SCREEN_H
|
||||||
|
div ecx
|
||||||
|
mov ebx,eax
|
||||||
|
mov edi,ROOF_HD_H-1
|
||||||
|
sub edi,eax
|
||||||
|
imul edi,ROOF_HD_W*4
|
||||||
|
mov roofQualityY3D[esi*4],edi
|
||||||
|
mov eax,esi
|
||||||
|
inc eax
|
||||||
|
imul eax,roofRenderH3D
|
||||||
|
xor edx,edx
|
||||||
|
div ecx
|
||||||
|
sub eax,ebx
|
||||||
|
mov roofQualityYCount3D[esi*4],eax
|
||||||
|
inc esi
|
||||||
|
cmp esi,SCREEN_H
|
||||||
|
jb roof_quality_y
|
||||||
|
cmp roofHDReady3D,1
|
||||||
|
jne roof_quality_done
|
||||||
|
call WriteRoofRendererInfo3D
|
||||||
|
roof_quality_done:
|
||||||
|
ret
|
||||||
|
UpdateRoofQuality3D ENDP
|
||||||
|
|
||||||
|
ComposeRoofFrame3D PROC uses ebx esi edi
|
||||||
|
local rows:DWORD,y:DWORD,x:DWORD,targetRow:DWORD,repeatRow:DWORD
|
||||||
|
invoke GdiFlush
|
||||||
|
mov esi,roofHDBuffer3D
|
||||||
|
mov eax,ROOF_HD_H
|
||||||
|
sub eax,roofRenderH3D
|
||||||
|
imul eax,ROOF_HD_W*4
|
||||||
|
add eax,roofHDFinalPixels3D
|
||||||
|
mov edi,eax
|
||||||
|
mov eax,roofRenderH3D
|
||||||
|
mov rows,eax
|
||||||
|
roof_compose_background:
|
||||||
|
mov ecx,roofRenderW3D
|
||||||
|
rep movsd
|
||||||
|
mov eax,ROOF_HD_W
|
||||||
|
sub eax,roofRenderW3D
|
||||||
|
lea edi,[edi+eax*4]
|
||||||
|
dec rows
|
||||||
|
jnz roof_compose_background
|
||||||
|
xor esi,esi
|
||||||
|
mov y,0
|
||||||
|
roof_compose_row:
|
||||||
|
mov ebx,y
|
||||||
|
mov eax,roofQualityY3D[ebx*4]
|
||||||
|
add eax,roofHDFinalPixels3D
|
||||||
|
mov targetRow,eax
|
||||||
|
mov eax,roofQualityYCount3D[ebx*4]
|
||||||
|
mov repeatRow,eax
|
||||||
|
mov x,0
|
||||||
|
roof_compose_pixel:
|
||||||
|
mov eax,screenBuffer[esi*4]
|
||||||
|
cmp roofCityMask3D[esi],0
|
||||||
|
je roof_compose_opaque
|
||||||
|
cmp eax,roofHDBackdrop3D[esi*4]
|
||||||
|
je roof_compose_next
|
||||||
|
roof_compose_opaque:
|
||||||
|
mov ebx,x
|
||||||
|
mov edi,roofQualityX3D[ebx*4]
|
||||||
|
add edi,targetRow
|
||||||
|
mov [edi],eax
|
||||||
|
cmp roofQualityXCount3D[ebx*4],2
|
||||||
|
jne @F
|
||||||
|
mov [edi+4],eax
|
||||||
|
@@:
|
||||||
|
cmp repeatRow,2
|
||||||
|
jne roof_compose_next
|
||||||
|
mov [edi-ROOF_HD_W*4],eax
|
||||||
|
cmp roofQualityXCount3D[ebx*4],2
|
||||||
|
jne roof_compose_next
|
||||||
|
mov [edi-ROOF_HD_W*4+4],eax
|
||||||
|
roof_compose_next:
|
||||||
|
inc esi
|
||||||
|
inc x
|
||||||
|
cmp x,SCREEN_W
|
||||||
|
jb roof_compose_pixel
|
||||||
|
inc y
|
||||||
|
cmp y,SCREEN_H
|
||||||
|
jb roof_compose_row
|
||||||
|
ret
|
||||||
|
ComposeRoofFrame3D ENDP
|
||||||
|
|
||||||
|
RenderRoofQualityToast3D PROC
|
||||||
|
cmp roofQualityToast3D,0
|
||||||
|
je roof_quality_toast_done
|
||||||
|
mov eax,OFFSET roofQualityAutoText3D
|
||||||
|
cmp roofRenderW3D,640
|
||||||
|
jne @F
|
||||||
|
mov eax,OFFSET roofQualityEcoText3D
|
||||||
|
@@:
|
||||||
|
cmp roofQualityMode3D,2
|
||||||
|
jne @F
|
||||||
|
mov eax,OFFSET roofQualityHighText3D
|
||||||
|
@@:
|
||||||
|
push eax
|
||||||
|
invoke DrawBox,12,40,160,18,00151B1Eh
|
||||||
|
pop eax
|
||||||
|
invoke DrawString8x8,20,45,eax,00E8D7ADh
|
||||||
|
roof_quality_toast_done:
|
||||||
|
ret
|
||||||
|
RenderRoofQualityToast3D ENDP
|
||||||
|
|
||||||
|
WriteRoofLogString3D PROC uses ebx esi handle:DWORD,value:DWORD
|
||||||
|
local written:DWORD
|
||||||
|
mov ebx,handle
|
||||||
|
mov esi,value
|
||||||
|
test esi,esi
|
||||||
|
jnz @F
|
||||||
|
mov esi,OFFSET roofLogUnknown3D
|
||||||
|
@@:
|
||||||
|
xor ecx,ecx
|
||||||
|
roof_log_length:
|
||||||
|
cmp BYTE PTR [esi+ecx],0
|
||||||
|
je roof_log_write
|
||||||
|
inc ecx
|
||||||
|
jmp roof_log_length
|
||||||
|
roof_log_write:
|
||||||
|
invoke WriteFile,ebx,esi,ecx,ADDR written,0
|
||||||
|
ret
|
||||||
|
WriteRoofLogString3D ENDP
|
||||||
|
|
||||||
|
WriteRoofRendererInfo3D PROC uses ebx esi
|
||||||
|
invoke CreateDirectoryA,OFFSET runtime3D,0
|
||||||
|
invoke CreateFileA,OFFSET roofLogPath3D,40000000h,1,0,2,80h,0
|
||||||
|
cmp eax,-1
|
||||||
|
je roof_log_done
|
||||||
|
mov ebx,eax
|
||||||
|
invoke WriteRoofLogString3D,ebx,OFFSET roofLogHeader3D
|
||||||
|
mov esi,0
|
||||||
|
roof_log_gl_string:
|
||||||
|
mov eax,OFFSET roofLogVendor3D
|
||||||
|
cmp esi,0
|
||||||
|
je @F
|
||||||
|
mov eax,OFFSET roofLogRenderer3D
|
||||||
|
cmp esi,1
|
||||||
|
je @F
|
||||||
|
mov eax,OFFSET roofLogVersion3D
|
||||||
|
@@:
|
||||||
|
invoke WriteRoofLogString3D,ebx,eax
|
||||||
|
xor eax,eax
|
||||||
|
cmp roofHDRC3D,0
|
||||||
|
je @F
|
||||||
|
mov eax,esi
|
||||||
|
add eax,1F00h
|
||||||
|
invoke glGetString,eax
|
||||||
|
@@:
|
||||||
|
invoke WriteRoofLogString3D,ebx,eax
|
||||||
|
invoke WriteRoofLogString3D,ebx,OFFSET roofLogNL3D
|
||||||
|
inc esi
|
||||||
|
cmp esi,3
|
||||||
|
jb roof_log_gl_string
|
||||||
|
invoke WriteRoofLogString3D,ebx,OFFSET roofLogStage3D
|
||||||
|
mov eax,roofHDStage3D
|
||||||
|
add al,'0'
|
||||||
|
mov roofLogDigit3D,al
|
||||||
|
invoke WriteRoofLogString3D,ebx,OFFSET roofLogDigit3D
|
||||||
|
invoke WriteRoofLogString3D,ebx,OFFSET roofLogNL3D
|
||||||
|
invoke WriteRoofLogString3D,ebx,OFFSET roofLogAssets3D
|
||||||
|
mov roofLogDigit3D,'0'
|
||||||
|
cmp roofCityArt3D.pixels,0
|
||||||
|
je @F
|
||||||
|
mov roofLogDigit3D,'1'
|
||||||
|
@@:
|
||||||
|
invoke WriteRoofLogString3D,ebx,OFFSET roofLogDigit3D
|
||||||
|
invoke WriteRoofLogString3D,ebx,OFFSET roofLogNL3D
|
||||||
|
invoke WriteRoofLogString3D,ebx,OFFSET roofLogWidth3D
|
||||||
|
mov eax,OFFSET roofLogMedium3D
|
||||||
|
cmp roofRenderW3D,960
|
||||||
|
je @F
|
||||||
|
mov eax,OFFSET roofLogSmall3D
|
||||||
|
cmp roofRenderW3D,640
|
||||||
|
je @F
|
||||||
|
mov eax,OFFSET roofLogLarge3D
|
||||||
|
@@:
|
||||||
|
invoke WriteRoofLogString3D,ebx,eax
|
||||||
|
invoke WriteRoofLogString3D,ebx,OFFSET roofLogNL3D
|
||||||
|
invoke CloseHandle,ebx
|
||||||
|
roof_log_done:
|
||||||
|
ret
|
||||||
|
WriteRoofRendererInfo3D ENDP
|
||||||
317
src_graphics/rooftop_surfaces.inc
Normal file
|
|
@ -0,0 +1,317 @@
|
||||||
|
; Ray/plane intersection for real pitched roofs, including perspective depth.
|
||||||
|
DrawRoofSlope3D PROC uses ebx esi edi axis:DWORD,x0:DWORD,x1:DWORD,y0:DWORD,y1:DWORD,baseZ:DWORD,rise:DWORD,material:DWORD
|
||||||
|
local slope:DWORD,numerator:DWORD,leftPx:DWORD,rightPx:DWORD,topPx:DWORD,bottomPx:DWORD
|
||||||
|
local corner:DWORD,wx:DWORD,wy:DWORD,wz:DWORD,visible:DWORD,nearClip:DWORD
|
||||||
|
local row:DWORD,column:DWORD,rayZ:DWORD,depth:DWORD,along:DWORD,denominator:DWORD
|
||||||
|
local texture:DWORD,textureW:DWORD,textureH:DWORD,light:DWORD,sourceU:DWORD
|
||||||
|
invoke ResolveRoofSurface3D,material
|
||||||
|
test eax,eax
|
||||||
|
jz roof_slope_done
|
||||||
|
mov texture,eax
|
||||||
|
mov textureW,ecx
|
||||||
|
mov textureH,edx
|
||||||
|
mov eax,rise
|
||||||
|
cdq
|
||||||
|
shld edx,eax,16
|
||||||
|
shl eax,16
|
||||||
|
mov ecx,x1
|
||||||
|
sub ecx,x0
|
||||||
|
cmp axis,0
|
||||||
|
je @F
|
||||||
|
mov ecx,y1
|
||||||
|
sub ecx,y0
|
||||||
|
@@:
|
||||||
|
idiv ecx
|
||||||
|
mov slope,eax
|
||||||
|
mov light,242
|
||||||
|
test eax,eax
|
||||||
|
jns @F
|
||||||
|
mov light,184
|
||||||
|
@@:
|
||||||
|
mov eax,playerX
|
||||||
|
sub eax,x0
|
||||||
|
cmp axis,0
|
||||||
|
je @F
|
||||||
|
mov eax,playerY
|
||||||
|
sub eax,y0
|
||||||
|
@@:
|
||||||
|
imul slope
|
||||||
|
shrd eax,edx,16
|
||||||
|
neg eax
|
||||||
|
add eax,viewEye3D
|
||||||
|
sub eax,baseZ
|
||||||
|
mov numerator,eax
|
||||||
|
mov leftPx,SCREEN_W
|
||||||
|
mov rightPx,0
|
||||||
|
mov topPx,SCREEN_H
|
||||||
|
mov bottomPx,0
|
||||||
|
mov visible,0
|
||||||
|
mov nearClip,0
|
||||||
|
mov corner,0
|
||||||
|
roof_slope_corner:
|
||||||
|
mov eax,x0
|
||||||
|
test corner,1
|
||||||
|
jz @F
|
||||||
|
mov eax,x1
|
||||||
|
@@:
|
||||||
|
mov wx,eax
|
||||||
|
mov ebx,y0
|
||||||
|
test corner,2
|
||||||
|
jz @F
|
||||||
|
mov ebx,y1
|
||||||
|
@@:
|
||||||
|
mov wy,ebx
|
||||||
|
mov ecx,baseZ
|
||||||
|
mov eax,corner
|
||||||
|
cmp axis,0
|
||||||
|
jne @F
|
||||||
|
and eax,1
|
||||||
|
jmp roof_slope_corner_height
|
||||||
|
@@:
|
||||||
|
and eax,2
|
||||||
|
roof_slope_corner_height:
|
||||||
|
test eax,eax
|
||||||
|
jz @F
|
||||||
|
add ecx,rise
|
||||||
|
@@:
|
||||||
|
mov wz,ecx
|
||||||
|
invoke ProjectCityPoint3D,wx,wy
|
||||||
|
cmp edx,4096
|
||||||
|
jg roof_slope_projected_corner
|
||||||
|
mov nearClip,1
|
||||||
|
jmp roof_slope_corner_next
|
||||||
|
roof_slope_projected_corner:
|
||||||
|
inc visible
|
||||||
|
mov esi,edx
|
||||||
|
cmp eax,leftPx
|
||||||
|
jge @F
|
||||||
|
mov leftPx,eax
|
||||||
|
@@:
|
||||||
|
cmp eax,rightPx
|
||||||
|
jle @F
|
||||||
|
mov rightPx,eax
|
||||||
|
@@:
|
||||||
|
mov eax,viewEye3D
|
||||||
|
sub eax,wz
|
||||||
|
mov ecx,SCREEN_H
|
||||||
|
imul ecx
|
||||||
|
idiv esi
|
||||||
|
add eax,viewHorizon3D
|
||||||
|
cmp eax,topPx
|
||||||
|
jge @F
|
||||||
|
mov topPx,eax
|
||||||
|
@@:
|
||||||
|
cmp eax,bottomPx
|
||||||
|
jle @F
|
||||||
|
mov bottomPx,eax
|
||||||
|
@@:
|
||||||
|
roof_slope_corner_next:
|
||||||
|
inc corner
|
||||||
|
cmp corner,4
|
||||||
|
jb roof_slope_corner
|
||||||
|
cmp visible,0
|
||||||
|
je roof_slope_done
|
||||||
|
cmp nearClip,0
|
||||||
|
je @F
|
||||||
|
mov leftPx,0
|
||||||
|
mov rightPx,SCREEN_W-1
|
||||||
|
mov topPx,0
|
||||||
|
mov bottomPx,SCREEN_H-1
|
||||||
|
@@:
|
||||||
|
cmp leftPx,0
|
||||||
|
jge @F
|
||||||
|
mov leftPx,0
|
||||||
|
@@:
|
||||||
|
cmp rightPx,SCREEN_W-1
|
||||||
|
jle @F
|
||||||
|
mov rightPx,SCREEN_W-1
|
||||||
|
@@:
|
||||||
|
cmp topPx,0
|
||||||
|
jge @F
|
||||||
|
mov topPx,0
|
||||||
|
@@:
|
||||||
|
cmp bottomPx,SCREEN_H-1
|
||||||
|
jle @F
|
||||||
|
mov bottomPx,SCREEN_H-1
|
||||||
|
@@:
|
||||||
|
mov eax,leftPx
|
||||||
|
cmp eax,rightPx
|
||||||
|
jge roof_slope_done
|
||||||
|
mov eax,topPx
|
||||||
|
cmp eax,bottomPx
|
||||||
|
jge roof_slope_done
|
||||||
|
mov row,eax
|
||||||
|
mov ebx,leftPx
|
||||||
|
roof_slope_prepare:
|
||||||
|
mov eax,cityRayX3D[ebx*4]
|
||||||
|
cmp axis,0
|
||||||
|
je @F
|
||||||
|
mov eax,cityRayY3D[ebx*4]
|
||||||
|
@@:
|
||||||
|
imul slope
|
||||||
|
shrd eax,edx,16
|
||||||
|
mov roofSlopeRay3D[ebx*4],eax
|
||||||
|
inc ebx
|
||||||
|
cmp ebx,rightPx
|
||||||
|
jbe roof_slope_prepare
|
||||||
|
roof_slope_row:
|
||||||
|
mov eax,viewHorizon3D
|
||||||
|
sub eax,row
|
||||||
|
shl eax,16
|
||||||
|
cdq
|
||||||
|
mov ecx,SCREEN_H
|
||||||
|
idiv ecx
|
||||||
|
mov rayZ,eax
|
||||||
|
mov eax,row
|
||||||
|
imul eax,SCREEN_W*4
|
||||||
|
mov ebx,leftPx
|
||||||
|
lea edi,[eax+ebx*4]
|
||||||
|
mov column,ebx
|
||||||
|
roof_slope_pixel:
|
||||||
|
mov ebx,column
|
||||||
|
mov ecx,roofSlopeRay3D[ebx*4]
|
||||||
|
sub ecx,rayZ
|
||||||
|
mov denominator,ecx
|
||||||
|
mov eax,ecx
|
||||||
|
cdq
|
||||||
|
xor eax,edx
|
||||||
|
sub eax,edx
|
||||||
|
cmp eax,64
|
||||||
|
jb roof_slope_advance
|
||||||
|
shl eax,10
|
||||||
|
mov along,eax
|
||||||
|
mov eax,numerator
|
||||||
|
cdq
|
||||||
|
xor eax,edx
|
||||||
|
sub eax,edx
|
||||||
|
cmp eax,along
|
||||||
|
jae roof_slope_advance
|
||||||
|
mov eax,numerator
|
||||||
|
cdq
|
||||||
|
shld edx,eax,16
|
||||||
|
shl eax,16
|
||||||
|
idiv denominator
|
||||||
|
cmp eax,4096
|
||||||
|
jle roof_slope_advance
|
||||||
|
cmp eax,cityDepthBuffer3D[edi]
|
||||||
|
jae roof_slope_advance
|
||||||
|
mov depth,eax
|
||||||
|
imul cityRayX3D[ebx*4]
|
||||||
|
shrd eax,edx,16
|
||||||
|
add eax,playerX
|
||||||
|
cmp eax,x0
|
||||||
|
jl roof_slope_advance
|
||||||
|
cmp eax,x1
|
||||||
|
jge roof_slope_advance
|
||||||
|
mov wx,eax
|
||||||
|
sub eax,x0
|
||||||
|
sar eax,9
|
||||||
|
mov ecx,textureW
|
||||||
|
dec ecx
|
||||||
|
and eax,ecx
|
||||||
|
mov sourceU,eax
|
||||||
|
mov eax,depth
|
||||||
|
imul cityRayY3D[ebx*4]
|
||||||
|
shrd eax,edx,16
|
||||||
|
add eax,playerY
|
||||||
|
cmp eax,y0
|
||||||
|
jl roof_slope_advance
|
||||||
|
cmp eax,y1
|
||||||
|
jge roof_slope_advance
|
||||||
|
mov wy,eax
|
||||||
|
cmp roofSlopeMask3D,0
|
||||||
|
je roof_slope_sample
|
||||||
|
mov eax,wx
|
||||||
|
sub eax,roofSlopeCentreX3D
|
||||||
|
cdq
|
||||||
|
xor eax,edx
|
||||||
|
sub eax,edx
|
||||||
|
imul roofSlopeHalfY3D
|
||||||
|
shrd eax,edx,16
|
||||||
|
mov along,eax
|
||||||
|
mov eax,wy
|
||||||
|
sub eax,roofSlopeCentreY3D
|
||||||
|
cdq
|
||||||
|
xor eax,edx
|
||||||
|
sub eax,edx
|
||||||
|
imul roofSlopeHalfX3D
|
||||||
|
shrd eax,edx,16
|
||||||
|
cmp roofSlopeMask3D,1
|
||||||
|
jne @F
|
||||||
|
cmp eax,along
|
||||||
|
ja roof_slope_advance
|
||||||
|
jmp roof_slope_sample
|
||||||
|
@@:
|
||||||
|
cmp eax,along
|
||||||
|
jb roof_slope_advance
|
||||||
|
roof_slope_sample:
|
||||||
|
mov eax,wy
|
||||||
|
sub eax,y0
|
||||||
|
sar eax,9
|
||||||
|
mov ecx,textureH
|
||||||
|
dec ecx
|
||||||
|
and eax,ecx
|
||||||
|
imul eax,textureW
|
||||||
|
add eax,sourceU
|
||||||
|
mov esi,texture
|
||||||
|
mov eax,[esi+eax*4]
|
||||||
|
invoke ShadeRoofCityPixel3D,eax,depth,light,material
|
||||||
|
mov ecx,edi
|
||||||
|
shr ecx,2
|
||||||
|
mov edx,roofPixelGlow3D
|
||||||
|
mov roofGlowMask3D[ecx],dl
|
||||||
|
mov screenBuffer[edi],eax
|
||||||
|
mov eax,depth
|
||||||
|
mov cityDepthBuffer3D[edi],eax
|
||||||
|
mov eax,edi
|
||||||
|
shr eax,2
|
||||||
|
mov roofCityMask3D[eax],1
|
||||||
|
roof_slope_advance:
|
||||||
|
add edi,4
|
||||||
|
inc column
|
||||||
|
mov eax,column
|
||||||
|
cmp eax,rightPx
|
||||||
|
jbe roof_slope_pixel
|
||||||
|
inc row
|
||||||
|
mov eax,row
|
||||||
|
cmp eax,bottomPx
|
||||||
|
jbe roof_slope_row
|
||||||
|
roof_slope_done:
|
||||||
|
ret
|
||||||
|
DrawRoofSlope3D ENDP
|
||||||
|
|
||||||
|
DrawRoofPyramid3D PROC uses ebx esi centreX:DWORD,centreY:DWORD,baseZ:DWORD,halfX:DWORD,halfY:DWORD,height:DWORD,mat:DWORD
|
||||||
|
local x0:DWORD,x1:DWORD,y0:DWORD,y1:DWORD,topZ:DWORD,down:DWORD
|
||||||
|
mov eax,centreX
|
||||||
|
mov roofSlopeCentreX3D,eax
|
||||||
|
sub eax,halfX
|
||||||
|
mov x0,eax
|
||||||
|
mov eax,centreX
|
||||||
|
add eax,halfX
|
||||||
|
mov x1,eax
|
||||||
|
mov eax,centreY
|
||||||
|
mov roofSlopeCentreY3D,eax
|
||||||
|
sub eax,halfY
|
||||||
|
mov y0,eax
|
||||||
|
mov eax,centreY
|
||||||
|
add eax,halfY
|
||||||
|
mov y1,eax
|
||||||
|
mov eax,halfX
|
||||||
|
mov roofSlopeHalfX3D,eax
|
||||||
|
mov eax,halfY
|
||||||
|
mov roofSlopeHalfY3D,eax
|
||||||
|
mov eax,baseZ
|
||||||
|
add eax,height
|
||||||
|
mov topZ,eax
|
||||||
|
mov eax,height
|
||||||
|
neg eax
|
||||||
|
mov down,eax
|
||||||
|
mov roofSlopeMask3D,1
|
||||||
|
invoke DrawRoofSlope3D,0,x0,centreX,y0,y1,baseZ,height,mat
|
||||||
|
invoke DrawRoofSlope3D,0,centreX,x1,y0,y1,topZ,down,mat
|
||||||
|
mov roofSlopeMask3D,2
|
||||||
|
invoke DrawRoofSlope3D,1,x0,x1,y0,centreY,baseZ,height,mat
|
||||||
|
invoke DrawRoofSlope3D,1,x0,x1,centreY,y1,topZ,down,mat
|
||||||
|
mov roofSlopeMask3D,0
|
||||||
|
ret
|
||||||
|
DrawRoofPyramid3D ENDP
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
"""Exact clock-board geometry plus fixed-grid full-arm animation packing."""
|
"""Exact clock-board geometry plus fixed-grid full-arm animation packing."""
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import argparse
|
||||||
import math
|
import math
|
||||||
import random
|
import random
|
||||||
import struct
|
import struct
|
||||||
|
|
@ -19,58 +20,76 @@ def pack(name, frames):
|
||||||
|
|
||||||
def board():
|
def board():
|
||||||
rng = random.Random(301)
|
rng = random.Random(301)
|
||||||
image = Image.new("RGBA", (512, 512))
|
scale = 2
|
||||||
|
center = 256*scale
|
||||||
|
image = Image.new("RGBA", (512*scale, 512*scale))
|
||||||
pixels = image.load()
|
pixels = image.load()
|
||||||
for y in range(512):
|
for y in range(image.height):
|
||||||
for x in range(512):
|
for x in range(image.width):
|
||||||
dx, dy = x-256, 256-y
|
dx, dy = (x-center)/scale, (center-y)/scale
|
||||||
radius = math.hypot(dx, dy)
|
radius = math.hypot(dx, dy)
|
||||||
angle = math.atan2(dx, dy)
|
angle = math.atan2(dx, dy)
|
||||||
sector = int(((angle + math.pi/20) % math.tau) / (math.tau/20))
|
sector = int(((angle + math.pi/20) % math.tau) / (math.tau/20))
|
||||||
red = sector % 2 == 0
|
red = sector % 2 == 0
|
||||||
color = (30, 36, 39)
|
color = (30, 36, 39)
|
||||||
if radius < 170:
|
if radius < 170:
|
||||||
color = (35, 38, 37) if red else (214, 206, 178)
|
color = (23, 29, 31) if red else (232, 225, 201)
|
||||||
if 99 <= radius <= 107 or 162 <= radius:
|
if 99 <= radius <= 107 or 162 <= radius:
|
||||||
color = (174, 37, 47) if red else (28, 112, 87)
|
color = (191, 42, 55) if red else (24, 145, 103)
|
||||||
if radius <= 15.9:
|
if radius <= 15.9:
|
||||||
color = (28, 112, 87)
|
color = (24, 145, 103)
|
||||||
if radius <= 6.35:
|
if radius <= 6.35:
|
||||||
color = (187, 37, 47)
|
color = (191, 42, 55)
|
||||||
elif radius < 210:
|
elif radius < 220:
|
||||||
color = (20, 24, 25)
|
color = (10, 14, 17)
|
||||||
elif radius < 240:
|
elif radius < 240:
|
||||||
color = (72, 29, 35)
|
color = (72, 29, 35)
|
||||||
elif radius < 248:
|
elif radius < 248:
|
||||||
color = (31, 37, 41)
|
color = (31, 37, 41)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
grain = rng.randrange(-11, 12) if radius < 170 else rng.randrange(-3, 4)
|
grain = rng.randrange(-2, 3)
|
||||||
pixels[x, y] = tuple(max(0, min(255, c+grain)) for c in color) + (255,)
|
pixels[x, y] = tuple(max(0, min(255, c+grain)) for c in color) + (255,)
|
||||||
draw = ImageDraw.Draw(image)
|
draw = ImageDraw.Draw(image)
|
||||||
wire = (171, 178, 173, 255)
|
wire = (139, 158, 161, 255)
|
||||||
for r in (6.35, 15.9, 99, 107, 162, 170):
|
for r in (6.35, 15.9, 99, 107, 162, 170):
|
||||||
draw.ellipse((256-r, 256-r, 256+r, 256+r), outline=wire, width=1)
|
bounds = tuple(round(v*scale) for v in (256-r, 256-r, 256+r, 256+r))
|
||||||
|
draw.ellipse(bounds, outline=wire, width=2*scale)
|
||||||
for index in range(20):
|
for index in range(20):
|
||||||
theta = (index*18-9)*math.pi/180
|
theta = (index*18-9)*math.pi/180
|
||||||
draw.line([(256+math.sin(theta)*16, 256-math.cos(theta)*16),
|
ends = [(round((256+math.sin(theta)*r)*scale),
|
||||||
(256+math.sin(theta)*170, 256-math.cos(theta)*170)], fill=wire)
|
round((256-math.cos(theta)*r)*scale)) for r in (16,170)]
|
||||||
font = ImageFont.truetype("C:/Windows/Fonts/arialbd.ttf", 23)
|
draw.line(ends, fill=wire, width=2*scale)
|
||||||
|
font = ImageFont.truetype("C:/Windows/Fonts/arialbd.ttf", 32*scale)
|
||||||
|
labels = []
|
||||||
for index, value in enumerate(SECTORS):
|
for index, value in enumerate(SECTORS):
|
||||||
theta = index*math.tau/20
|
theta = index*math.tau/20
|
||||||
draw.text((256+math.sin(theta)*190, 256-math.cos(theta)*190), str(value),
|
point = ((256+math.sin(theta)*198)*scale, (256-math.cos(theta)*198)*scale)
|
||||||
font=font, fill=(227, 230, 220), anchor="mm", stroke_width=1)
|
labels.append(draw.textbbox(point, str(value), font=font, anchor="mm"))
|
||||||
draw.ellipse((12, 12, 500, 500), outline=(104, 114, 120), width=3)
|
draw.text(point, str(value),
|
||||||
image.save(ART / "board-v1.png")
|
font=font, fill=(249, 247, 232), anchor="mm")
|
||||||
|
for i, a in enumerate(labels):
|
||||||
|
for b in labels[i+1:]:
|
||||||
|
assert a[2] <= b[0] or b[2] <= a[0] or a[3] <= b[1] or b[3] <= a[1], "Overlapping board numbers"
|
||||||
|
draw.ellipse((12*scale, 12*scale, 500*scale, 500*scale),
|
||||||
|
outline=(104, 114, 120), width=3*scale)
|
||||||
|
image = image.resize((512,512), Image.Resampling.LANCZOS)
|
||||||
|
image.save(ART / "board-v2.png")
|
||||||
return image
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--board-only", action="store_true")
|
||||||
|
args = parser.parse_args()
|
||||||
ART.mkdir(parents=True, exist_ok=True)
|
ART.mkdir(parents=True, exist_ok=True)
|
||||||
OUT.mkdir(parents=True, exist_ok=True)
|
OUT.mkdir(parents=True, exist_ok=True)
|
||||||
pack("board-v1.bin", [board()])
|
pack("board-v2.bin", [board()])
|
||||||
|
if args.board_only:
|
||||||
|
print("Packed sharper 512px board: unchanged footprint and scoring radii.")
|
||||||
|
return
|
||||||
wall = Image.open(ART / "lounge-wall-v1.png").convert("RGBA")
|
wall = Image.open(ART / "lounge-wall-v1.png").convert("RGBA")
|
||||||
pack("lounge-wall-v1.bin", [wall.resize((512,512), Image.Resampling.LANCZOS)])
|
pack("lounge-wall-v1.bin", [wall.resize((512,512), Image.Resampling.LANCZOS)])
|
||||||
anchors = []
|
anchors = []
|
||||||
|
|
|
||||||
102
tools/generators/pack_fortune_orb.py
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
"""Offline orb tracking metadata and antialiased numeral sprites; no runtime Python."""
|
||||||
|
from pathlib import Path
|
||||||
|
import json
|
||||||
|
import struct
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from PIL import Image, ImageDraw, ImageFilter, ImageFont
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
OUT = ROOT / "assets/animations/fortune"
|
||||||
|
ART = ROOT / "assets/sprites/fortune"
|
||||||
|
PREVIEW = ROOT / "build/hall-expansion"
|
||||||
|
|
||||||
|
|
||||||
|
def load_orbs():
|
||||||
|
raw = (OUT / "orb-mist-v1.bin").read_bytes()
|
||||||
|
magic, width, height, count, length = struct.unpack_from("<4s4I", raw)
|
||||||
|
assert magic == b"ANM1" and count == 16
|
||||||
|
assert length == width * height * count * 4 == len(raw) - 20
|
||||||
|
stride = width * height * 4
|
||||||
|
return [Image.frombytes("RGBA", (width, height), raw[20+i*stride:20+(i+1)*stride],
|
||||||
|
"raw", "BGRA") for i in range(count)]
|
||||||
|
|
||||||
|
|
||||||
|
def sphere_geometry(frame):
|
||||||
|
# Fit the upper glass silhouette, explicitly excluding the metal pedestal.
|
||||||
|
alpha = np.asarray(frame.getchannel("A"))
|
||||||
|
rows, midpoints, half_widths = [], [], []
|
||||||
|
for y in range(12, round(frame.height * .70)):
|
||||||
|
xs = np.flatnonzero(alpha[y] >= 170)
|
||||||
|
if len(xs) < frame.width * .35:
|
||||||
|
continue
|
||||||
|
left, right = int(xs[0]), int(xs[-1])
|
||||||
|
rows.append(y)
|
||||||
|
midpoints.append((left + right) / 2)
|
||||||
|
half_widths.append((right - left) / 2)
|
||||||
|
a, b, c = np.polyfit(rows, np.square(half_widths), 2)
|
||||||
|
assert a < 0
|
||||||
|
cy = -b / (2*a)
|
||||||
|
cx = float(np.median(midpoints))
|
||||||
|
rx = float(np.sqrt(c - b*b/(4*a)))
|
||||||
|
ry = float(rx / np.sqrt(-a))
|
||||||
|
assert 70 < cx < 125 and 60 < cy < 115
|
||||||
|
assert 55 < rx < 95 and 55 < ry < 95
|
||||||
|
return {"cx": cx, "cy": cy, "rx": rx, "ry": ry}
|
||||||
|
|
||||||
|
|
||||||
|
def numeral(digit, font):
|
||||||
|
factor = 4
|
||||||
|
mask = Image.new("L", (32*factor, 48*factor))
|
||||||
|
draw = ImageDraw.Draw(mask)
|
||||||
|
box = draw.textbbox((0, 0), str(digit), font=font)
|
||||||
|
x = (mask.width-(box[2]-box[0]))/2-box[0]
|
||||||
|
y = (mask.height-(box[3]-box[1]))/2-box[1]
|
||||||
|
draw.text((round(x), round(y)), str(digit), font=font, fill=255)
|
||||||
|
mask = mask.resize((32, 48), Image.Resampling.LANCZOS)
|
||||||
|
shadow = Image.new("RGBA", mask.size, (8, 30, 66, 0))
|
||||||
|
shadow.putalpha(mask.filter(ImageFilter.MaxFilter(3)).point(lambda a: round(a*.65)))
|
||||||
|
halo = Image.new("RGBA", mask.size, (65, 168, 243, 0))
|
||||||
|
halo.putalpha(mask.filter(ImageFilter.GaussianBlur(2.0)).point(lambda a: round(a*.65)))
|
||||||
|
ink = Image.new("RGBA", mask.size, (200, 235, 255, 0))
|
||||||
|
ink.putalpha(mask.point(lambda a: round(a*.90)))
|
||||||
|
return Image.alpha_composite(Image.alpha_composite(halo, shadow), ink)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
PREVIEW.mkdir(parents=True, exist_ok=True)
|
||||||
|
orbs = load_orbs()
|
||||||
|
geometry = [sphere_geometry(frame) for frame in orbs]
|
||||||
|
# Q8 offsets in the exact 128px runtime drawing rectangle, not its centre.
|
||||||
|
lines = ["; Generated by tools/generators/pack_fortune_orb.py; glass only, pedestal excluded."]
|
||||||
|
for name, key in (("fortuneOrbAnchorX3D", "cx"), ("fortuneOrbAnchorY3D", "cy")):
|
||||||
|
values = [round(item[key] * 128 / 192 * 256) for item in geometry]
|
||||||
|
lines.append(name + " dd " + ",".join(map(str, values)))
|
||||||
|
(ROOT / "src_graphics/fortune_orb_art.inc").write_text("\n".join(lines)+"\n", encoding="ascii")
|
||||||
|
font = ImageFont.truetype("C:/Windows/Fonts/cambria.ttc", 34*4)
|
||||||
|
digits = [numeral(i, font) for i in range(10)]
|
||||||
|
payload = b"".join(frame.tobytes("raw", "BGRA") for frame in digits)
|
||||||
|
(OUT / "orb-numerals-v1.bin").write_bytes(struct.pack("<4s4I", b"ANM1", 32, 48, 10,
|
||||||
|
len(payload)) + payload)
|
||||||
|
sheet = Image.new("RGBA", (320, 48))
|
||||||
|
for i, digit in enumerate(digits):
|
||||||
|
sheet.alpha_composite(digit, (32*i, 0))
|
||||||
|
sheet.save(ART / "orb-numerals-v1.png")
|
||||||
|
(ART / "orb-tracking-v1.json").write_text(json.dumps({"canvas": [192, 192],
|
||||||
|
"font": "Cambria Regular, rasterized at 4x; no font needed at runtime",
|
||||||
|
"frames": geometry}, indent=2)+"\n", encoding="ascii")
|
||||||
|
sheet = Image.new("RGB", (192*4, 192*4), (5, 15, 28))
|
||||||
|
for i, (frame, item) in enumerate(zip(orbs, geometry)):
|
||||||
|
debug = frame.copy()
|
||||||
|
draw = ImageDraw.Draw(debug)
|
||||||
|
x, y = item["cx"], item["cy"]
|
||||||
|
draw.ellipse((x-item["rx"], y-item["ry"], x+item["rx"], y+item["ry"]), outline="yellow")
|
||||||
|
draw.line((x-5, y, x+5, y), fill="yellow")
|
||||||
|
draw.line((x, y-5, x, y+5), fill="yellow")
|
||||||
|
sheet.paste(debug, ((i%4)*192, (i//4)*192), debug)
|
||||||
|
sheet.save(PREVIEW / "fortune-orb-tracking.png")
|
||||||
|
print("Packed 10 antialiased Cambria numerals and 16 measured glass-centre anchors.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
369
tools/generators/pack_rooftop.py
Normal file
|
|
@ -0,0 +1,369 @@
|
||||||
|
"""Offline rooftop atlas/map compiler. Game rendering and travel remain MASM."""
|
||||||
|
from pathlib import Path
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
import struct
|
||||||
|
import numpy as np
|
||||||
|
import cv2
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
ART = ROOT / "assets/sprites/rooftop"
|
||||||
|
OUT = ROOT / "assets/animations/rooftop"
|
||||||
|
|
||||||
|
|
||||||
|
def grid(path, columns, rows):
|
||||||
|
source = Image.open(ART/path).convert("RGBA")
|
||||||
|
return [source.crop((round(x*source.width/columns), round(y*source.height/rows),
|
||||||
|
round((x+1)*source.width/columns), round((y+1)*source.height/rows)))
|
||||||
|
.resize((256, 256), Image.Resampling.LANCZOS)
|
||||||
|
for y in range(rows) for x in range(columns)]
|
||||||
|
|
||||||
|
|
||||||
|
def pack(name, frames):
|
||||||
|
w, h = frames[0].size
|
||||||
|
payload = b"".join(frame.tobytes("raw", "BGRA") for frame in frames)
|
||||||
|
(OUT/name).write_bytes(struct.pack("<4s4I", b"ANM1", w, h, len(frames), len(payload))+payload)
|
||||||
|
|
||||||
|
|
||||||
|
def clean_hands(frame):
|
||||||
|
pixels = np.asarray(frame).copy()
|
||||||
|
mask = (pixels[:,:,3] >= 128).astype(np.uint8)
|
||||||
|
mask = cv2.morphologyEx(mask,cv2.MORPH_OPEN,np.ones((3,3),np.uint8))
|
||||||
|
count,labels,stats,_ = cv2.connectedComponentsWithStats(mask)
|
||||||
|
keep = [i for i in range(1,count) if stats[i,cv2.CC_STAT_AREA] > 2500]
|
||||||
|
support = np.isin(labels,keep).astype(np.uint8)
|
||||||
|
support = cv2.erode(support,np.ones((3,3),np.uint8))
|
||||||
|
pixels[:,:,3] = support*255
|
||||||
|
pixels[support == 0,:3] = 0
|
||||||
|
return Image.fromarray(pixels)
|
||||||
|
|
||||||
|
|
||||||
|
def night_facade(frame, seed):
|
||||||
|
"""Identify window apertures; mark lit glass with FF alpha and unlit walls FE."""
|
||||||
|
pixels = np.asarray(frame).copy()
|
||||||
|
rgb = pixels[:,:,:3].astype(np.int16)
|
||||||
|
mask = ((rgb.max(axis=2)<145) & (rgb[:,:,2]>rgb[:,:,0]-10)).astype(np.uint8)*255
|
||||||
|
mask = cv2.morphologyEx(mask,cv2.MORPH_CLOSE,np.ones((7,5),np.uint8))
|
||||||
|
contours,_ = cv2.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
|
||||||
|
pixels[:,:,3] = 254
|
||||||
|
rng = np.random.default_rng(seed)
|
||||||
|
count = 0
|
||||||
|
for contour in contours:
|
||||||
|
x,y,w,h = cv2.boundingRect(contour)
|
||||||
|
if not (8 <= w <= 110 and 14 <= h <= 180 and .8 <= h/w <= 4):
|
||||||
|
continue
|
||||||
|
if rng.random() > .48:
|
||||||
|
continue
|
||||||
|
region = pixels[y+2:y+h-2,x+2:x+w-2]
|
||||||
|
source = region[:,:,:3].astype(np.int16)
|
||||||
|
glass = (source[:,:,2]>source[:,:,0]+4) & (source.max(axis=2)<155)
|
||||||
|
if glass.sum() < 15:
|
||||||
|
continue
|
||||||
|
yy,xx = np.mgrid[:h-4,:w-4]
|
||||||
|
glow = np.clip(1-((xx-(w-4)/2)/(w/2))**2*.22, .5, 1)
|
||||||
|
warmth = np.array([210,148,76])*rng.uniform(.7,1.1)
|
||||||
|
lit = np.clip(glow[:,:,None]*warmth,0,255).astype(np.uint8)
|
||||||
|
region[:,:,:3][glass] = lit[glass]
|
||||||
|
region[:,:,3][glass] = 255
|
||||||
|
count += 1
|
||||||
|
return Image.fromarray(pixels),count
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
OUT.mkdir(parents=True, exist_ok=True)
|
||||||
|
sky = Image.open(ART/"sunset-sky-v1.png").convert("RGBA").resize((2048,512),Image.Resampling.LANCZOS)
|
||||||
|
# A short symmetric overlap makes the cylindrical wrap continuous.
|
||||||
|
original = sky.copy()
|
||||||
|
for x in range(32):
|
||||||
|
mixed = Image.blend(original.crop((x,0,x+1,512)),
|
||||||
|
original.crop((2047-x,0,2048-x,512)), (32-x)/64)
|
||||||
|
sky.paste(mixed, (x,0))
|
||||||
|
mixed = Image.blend(original.crop((2047-x,0,2048-x,512)),
|
||||||
|
original.crop((x,0,x+1,512)), (32-x)/64)
|
||||||
|
sky.paste(mixed, (2047-x,0))
|
||||||
|
pack("panorama-v1.bin", [sky.crop((i*512,0,(i+1)*512,512)) for i in range(4)])
|
||||||
|
night = Image.open(ART/"night-sky-v1.png").convert("RGBA").resize((2048,512),Image.Resampling.LANCZOS)
|
||||||
|
pack("night-v1.bin",[night.crop((i*512,0,(i+1)*512,512)) for i in range(4)])
|
||||||
|
hands = Image.open(ART/"rail-hands-v1.png").convert("RGBA")
|
||||||
|
poses = [hands.crop((round(x*hands.width/4),round(y*hands.height/2),
|
||||||
|
round((x+1)*hands.width/4),round((y+1)*hands.height/2)))
|
||||||
|
.resize((640,320),Image.Resampling.LANCZOS)
|
||||||
|
for y in range(2) for x in range(4)]
|
||||||
|
# Offline bidirectional flow supplies in-between poses; playback is pure MASM.
|
||||||
|
coordinates = np.mgrid[:320,:640][::-1].transpose(1,2,0).astype(np.float32)
|
||||||
|
smooth = []
|
||||||
|
for first,second in zip(poses,poses[1:]):
|
||||||
|
a,b = np.asarray(first),np.asarray(second)
|
||||||
|
ag = cv2.cvtColor(a,cv2.COLOR_RGBA2GRAY)
|
||||||
|
bg = cv2.cvtColor(b,cv2.COLOR_RGBA2GRAY)
|
||||||
|
forward = cv2.calcOpticalFlowFarneback(ag,bg,None,.5,5,35,6,7,1.5,0)
|
||||||
|
backward = cv2.calcOpticalFlowFarneback(bg,ag,None,.5,5,35,6,7,1.5,0)
|
||||||
|
for index in range(4):
|
||||||
|
q = index/4
|
||||||
|
aw = cv2.remap(a,coordinates-forward*q,None,cv2.INTER_LINEAR,
|
||||||
|
borderMode=cv2.BORDER_CONSTANT)
|
||||||
|
bw = cv2.remap(b,coordinates-backward*(1-q),None,cv2.INTER_LINEAR,
|
||||||
|
borderMode=cv2.BORDER_CONSTANT)
|
||||||
|
smooth.append(Image.fromarray(cv2.addWeighted(aw,1-q,bw,q,0)))
|
||||||
|
smooth += [poses[-1]]*4
|
||||||
|
assert len(smooth) == 32
|
||||||
|
pack("rail-hands-v1.bin",[clean_hands(frame) for frame in smooth])
|
||||||
|
materials = grid("materials-v1.png",4,2)
|
||||||
|
pack("materials-v1.bin",materials)
|
||||||
|
panels = grid("panels-v1.png",4,2)[:4]
|
||||||
|
# One moving leaf, not a photograph of a whole elevator on each leaf.
|
||||||
|
panels[0] = panels[0].crop((72,16,126,235)).resize((256,256),Image.Resampling.LANCZOS)
|
||||||
|
# Use only the fluted facade, not the reference's pictured skyline above it.
|
||||||
|
panels[2] = panels[2].crop((0,116,256,240)).resize((256,256),Image.Resampling.LANCZOS)
|
||||||
|
cutouts = grid("cutouts-v1.png",2,2)
|
||||||
|
for frame in cutouts:
|
||||||
|
assert frame.getchannel("A").getextrema()[0] == 0, "cutouts require actual alpha"
|
||||||
|
sofas = Image.open(ART/"sofa-views-v1.png").convert("RGBA")
|
||||||
|
occupied = np.sum(np.asarray(sofas.getchannel("A")) > 128,axis=0) > 10
|
||||||
|
edges = np.flatnonzero(np.diff(np.r_[False,occupied,False]))
|
||||||
|
spans = [(int(a),int(b)) for a,b in zip(edges[::2],edges[1::2]) if b-a > 80]
|
||||||
|
assert len(spans) == 3, spans
|
||||||
|
boxes = []
|
||||||
|
for lo,hi in spans:
|
||||||
|
box = sofas.crop((lo,0,hi,sofas.height)).getchannel("A").point(lambda a:255 if a>128 else 0).getbbox()
|
||||||
|
boxes.append((lo,box[1],hi,box[3]))
|
||||||
|
top = min(box[1] for box in boxes)
|
||||||
|
bottom = max(box[3] for box in boxes)
|
||||||
|
views = [sofas.crop((box[0],top,box[2],bottom)).resize((256,256),Image.Resampling.LANCZOS)
|
||||||
|
for box in boxes]
|
||||||
|
chairs = Image.open(ART/"chair-views-v1.png").convert("RGBA")
|
||||||
|
split = round(chairs.width*.55)
|
||||||
|
boxes = [(0,0,split,chairs.height//2),(split,0,chairs.width,chairs.height//2),
|
||||||
|
(0,chairs.height//2,split,chairs.height),(split,chairs.height//2,chairs.width,chairs.height)]
|
||||||
|
chair_views = []
|
||||||
|
for box in boxes:
|
||||||
|
frame = chairs.crop(box)
|
||||||
|
tight = frame.getchannel("A").point(lambda a:255 if a>128 else 0).getbbox()
|
||||||
|
chair_views.append(frame.crop(tight).resize((256,256),Image.Resampling.LANCZOS))
|
||||||
|
pack("details-v1.bin",panels+cutouts+views+chair_views)
|
||||||
|
facade = Image.open(ART/"city-facades-v1.png").convert("RGBA")
|
||||||
|
city = [facade.crop((round(x*facade.width/4),round(y*facade.height/2),
|
||||||
|
round((x+1)*facade.width/4),round((y+1)*facade.height/2)))
|
||||||
|
.resize((512,512),Image.Resampling.LANCZOS)
|
||||||
|
for y in range(2) for x in range(4)]
|
||||||
|
# Foliage-only tuft, not a planter photographed on a vertical card.
|
||||||
|
city.append(cutouts[1].crop((0,0,256,160)).resize((512,512),Image.Resampling.LANCZOS))
|
||||||
|
earth = np.asarray(materials[1].resize((512,512))).copy()
|
||||||
|
earth[:,:,:3] = (earth[:,:,:3].astype(np.uint16)*np.array([37,31,24])//100).astype(np.uint8)
|
||||||
|
city.append(Image.fromarray(earth))
|
||||||
|
city.append(Image.open(ART/"roof-zinc-v1.png").convert("RGBA").resize((512,512),Image.Resampling.LANCZOS))
|
||||||
|
# Existing high-detail stone is also a road aggregate; water is a generated
|
||||||
|
# native texture below. Neither is a photograph of a whole city object.
|
||||||
|
road = np.asarray(materials[1].resize((512,512))).copy()
|
||||||
|
road[:,:,:3] = (road[:,:,:3].astype(np.uint16)*45//100).astype(np.uint8)
|
||||||
|
city.append(Image.fromarray(road))
|
||||||
|
yy,xx = np.mgrid[:512,:512]
|
||||||
|
ripple = (np.sin(xx*.17+np.sin(yy*.09)*2)+np.sin(yy*.31))*4
|
||||||
|
water = np.zeros((512,512,4),dtype=np.uint8)
|
||||||
|
for channel,base in enumerate((24,55,72)):
|
||||||
|
water[:,:,channel] = np.clip(base+ripple,0,255).astype(np.uint8)
|
||||||
|
water[:,:,3] = 255
|
||||||
|
city.append(Image.fromarray(water))
|
||||||
|
modern = Image.open(ART/"modern-facades-v1.png").convert("RGBA")
|
||||||
|
city += [modern.crop((round(x*modern.width/4),round(y*modern.height/2),
|
||||||
|
round((x+1)*modern.width/4),round((y+1)*modern.height/2)))
|
||||||
|
.resize((512,512),Image.Resampling.LANCZOS)
|
||||||
|
for y in range(2) for x in range(4)]
|
||||||
|
noise = np.random.default_rng(701).integers(-8,9,size=(512,512,1))
|
||||||
|
lawn = np.empty((512,512,4),dtype=np.uint8)
|
||||||
|
lawn[:,:,:3] = np.clip(np.array([39,68,43])+noise,0,255)
|
||||||
|
lawn[:,:,3] = 255
|
||||||
|
city.append(Image.fromarray(lawn))
|
||||||
|
pack("city-v1.bin",city)
|
||||||
|
night_city,lit_windows = [],0
|
||||||
|
for index,frame in enumerate(city):
|
||||||
|
if index < 8 or 13 <= index < 21:
|
||||||
|
frame,count = night_facade(frame,2000+index)
|
||||||
|
lit_windows += count
|
||||||
|
night_city.append(frame)
|
||||||
|
pack("city-night-v1.bin",night_city)
|
||||||
|
# A connected street/courtyard district, not a ring of independent props.
|
||||||
|
blocks = []
|
||||||
|
lots,parks = [],[]
|
||||||
|
for gy in range(-5,6):
|
||||||
|
for gx in range(-5,6):
|
||||||
|
x,y = 20+gx*36,11+gy*36
|
||||||
|
if gx == 0 and gy == 0:
|
||||||
|
continue
|
||||||
|
# The cross-city canal has continuous quays, not houses over water.
|
||||||
|
if y+14 > 54 and y-14 < 82:
|
||||||
|
continue
|
||||||
|
# Two open squares reserve space around the dome and golden spire.
|
||||||
|
if (gx,gy) in ((0,3),(4,0)):
|
||||||
|
continue
|
||||||
|
key = (gx*17+gy*31)%37
|
||||||
|
if key%11 == 0 or (gx,gy) in ((1,0),(-1,0)):
|
||||||
|
parks.append((x,y))
|
||||||
|
continue
|
||||||
|
facade = 186+(gx*3+gy)%8
|
||||||
|
if max(abs(gx),abs(gy)) <= 1:
|
||||||
|
top = -60+6+key%6
|
||||||
|
facade = 203
|
||||||
|
wings = [(x-6,x+5,y-5,y+5)]
|
||||||
|
elif key%7 == 0:
|
||||||
|
top = -60+24+key%17
|
||||||
|
facade = 199+(key%2)*5
|
||||||
|
wings = [(x-8,x+8,y-10,y+10)]
|
||||||
|
else:
|
||||||
|
top = -60+12+key%16
|
||||||
|
wings = [(x-14,x+14,y-14,y-7),(x-14,x+14,y+7,y+14),
|
||||||
|
(x-14,x-7,y-7,y+7),(x+7,x+14,y-7,y+7)]
|
||||||
|
if key%3 == 0:
|
||||||
|
wings = wings[:3]
|
||||||
|
elif key%5 == 0:
|
||||||
|
wings = wings[1:3]
|
||||||
|
lots.append({"centre":[x,y],"courtyard":[x-7,x+7,y-7,y+7],
|
||||||
|
"facade":facade,"height":top+60})
|
||||||
|
for index,wing in enumerate(wings):
|
||||||
|
blocks.append((*wing,top+(index%2)*.3,facade,index))
|
||||||
|
# Distant quarters are aggregated geometry, not a scaled city photograph.
|
||||||
|
for gy in range(-8,9):
|
||||||
|
for gx in range(-8,9):
|
||||||
|
if max(abs(gx),abs(gy)) <= 3:
|
||||||
|
continue
|
||||||
|
x,y = 20+gx*64,11+gy*64
|
||||||
|
if y+24 > 54 and y-24 < 82:
|
||||||
|
continue
|
||||||
|
key = (gx*5+gy*11)%29
|
||||||
|
top = -60+10+key
|
||||||
|
half = 17+key%10
|
||||||
|
blocks.append((x-half,x+half,y-24,y+24,top,186+(gx+gy)%8,4))
|
||||||
|
towers = [(320,-130,90),(355,-165,126),(390,-125,108),(425,-195,155),
|
||||||
|
(460,-145,102),(345,-225,115),(405,-260,132),(475,-240,88)]
|
||||||
|
for index,(x,y,height) in enumerate(towers):
|
||||||
|
blocks.append((x-8,x+8,y-10,y+10,-60+height,200+index%3,2))
|
||||||
|
blocks.append((x-5,x+5,y-7,y+7,-60+height+7,200+index%3,2))
|
||||||
|
# The eastern avenue opens into a broad river, not an endless paved corridor.
|
||||||
|
blocks = [b for b in blocks if not (b[1] > 68 and b[2] < 81 and b[3] > 26)]
|
||||||
|
# Far riverfront quarters break the empty, perfectly straight horizon.
|
||||||
|
for side in (-1,1):
|
||||||
|
for i in range(10):
|
||||||
|
x = 570+i*34
|
||||||
|
y = 6-(i%3)*8 if side < 0 else 106+(i%4)*9
|
||||||
|
h = 16+(i*7)%24
|
||||||
|
blocks.append((x-11,x+11,y-10,y+10,-60+h,186+i%8,4))
|
||||||
|
blocks.sort(key=lambda b:(((b[0]+b[1])/2-20)**2+((b[2]+b[3])/2-11)**2))
|
||||||
|
# Ground-only baked illumination follows the same real building footprints.
|
||||||
|
elevation = np.zeros((512,512),dtype=np.float32)
|
||||||
|
for x0,x1,y0,y1,z,_,_ in blocks:
|
||||||
|
loX,hiX = max(0,math.floor(x0/2)+256),min(512,math.ceil(x1/2)+256)
|
||||||
|
loY,hiY = max(0,math.floor(y0/2)+256),min(512,math.ceil(y1/2)+256)
|
||||||
|
if loX < hiX and loY < hiY:
|
||||||
|
elevation[loY:hiY,loX:hiX] = np.maximum(elevation[loY:hiY,loX:hiX],z+60)
|
||||||
|
occlusion = np.zeros_like(elevation)
|
||||||
|
padded = np.pad(elevation,128)
|
||||||
|
for step in range(1,100):
|
||||||
|
sx,sy = round(-step*.89),round(step*.45)
|
||||||
|
ray_height = step*2*math.tan(math.radians(18))
|
||||||
|
blocked = padded[128+sy:640+sy,128+sx:640+sx]-ray_height
|
||||||
|
occlusion = np.maximum(occlusion,blocked)
|
||||||
|
shadow = cv2.GaussianBlur(np.where(occlusion>0,155,250).astype(np.uint8),(5,5),1)
|
||||||
|
day = np.empty((512,512,4),dtype=np.uint8)
|
||||||
|
day[:,:,:3] = shadow[:,:,None]
|
||||||
|
day[:,:,3] = 255
|
||||||
|
lamps = []
|
||||||
|
for gx in range(-5,6):
|
||||||
|
for gy in range(-6,7):
|
||||||
|
lamps.append((34.8+36*gx,11+30*gy))
|
||||||
|
lamps += [(x,y) for x in range(-170,211,18) for y in (58.5,77.5)]
|
||||||
|
lamps = [(x,y) for x,y in lamps if not (60 < y < 76 or (x > 68 and 29 < y < 76))]
|
||||||
|
lamps += [(x,y) for x in range(86,650,18) for y in (27,78)]
|
||||||
|
yy,xx = np.mgrid[:512,:512]
|
||||||
|
world_x,world_y = (xx-256)*2,(yy-256)*2
|
||||||
|
illumination = np.zeros((512,512,3),dtype=np.float32)+[24,30,46]
|
||||||
|
for lx,ly in lamps:
|
||||||
|
energy = np.exp(-((world_x-lx)**2+(world_y-ly)**2)/(2*5.5**2))
|
||||||
|
illumination += energy[:,:,None]*np.array([215,150,64])
|
||||||
|
if ly in (27,78,58.5,77.5):
|
||||||
|
reflected = np.exp(-((world_x-lx)**2/(2*1.6**2)+(world_y-ly)**2/(2*13**2)))
|
||||||
|
reflected *= ((world_y>=60)&(world_y<=76)) | ((world_x>=70)&(world_y>=29)&(world_y<=76))
|
||||||
|
illumination += reflected[:,:,None]*np.array([180,125,60])
|
||||||
|
night_light = np.empty((512,512,4),dtype=np.uint8)
|
||||||
|
night_light[:,:,:3] = np.clip(illumination,0,255).astype(np.uint8)
|
||||||
|
night_light[:,:,3] = 255
|
||||||
|
glow = np.empty_like(night_light)
|
||||||
|
glow[:,:,:3] = np.clip((illumination-np.array([24,30,46]))*.38,0,255).astype(np.uint8)
|
||||||
|
glow[:,:,3] = 255
|
||||||
|
pack("lighting-v1.bin",[Image.fromarray(day),Image.fromarray(night_light),Image.fromarray(glow)])
|
||||||
|
district = ["; Generated city block footprints and rooftop-relative heights.",
|
||||||
|
f"ROOF_BUILDING_COUNT equ {len(blocks)}", ".data", "roofDistrict3D LABEL DWORD"]
|
||||||
|
for block in blocks:
|
||||||
|
district.append(" dd "+",".join(str(round(v*65536)) if i<5 else str(v)
|
||||||
|
for i,v in enumerate(block)))
|
||||||
|
district += [f"ROOF_PARK_COUNT equ {len(parks)}","roofCityParks3D LABEL DWORD"]
|
||||||
|
district += [f" dd {round(x*65536)},{round(y*65536)}" for x,y in parks]
|
||||||
|
district += [f"ROOF_CITY_LAMP_COUNT equ {len(lamps)}","roofCityLamps3D LABEL DWORD"]
|
||||||
|
district += [f" dd {round(x*65536)},{round(y*65536)}" for x,y in lamps]
|
||||||
|
pieces = []
|
||||||
|
def landmark_piece(kind,coords,material,pivot,target,scale=2):
|
||||||
|
ox,oy = pivot
|
||||||
|
tx,ty = target
|
||||||
|
if kind == 0:
|
||||||
|
a,b,c,d,e,f = coords
|
||||||
|
coords = ((a-ox)*scale+tx,(b-ox)*scale+tx,(c-oy)*scale+ty,(d-oy)*scale+ty,
|
||||||
|
(e+17)*scale-60,(f+17)*scale-60)
|
||||||
|
else:
|
||||||
|
a,b,c,d,e,f = coords
|
||||||
|
coords = ((a-ox)*scale+tx,(b-oy)*scale+ty,(c+17)*scale-60,d*scale,e*scale,f*scale)
|
||||||
|
pieces.append((kind,*[round(v*65536) for v in coords],material))
|
||||||
|
dome = lambda kind,coords,mat: landmark_piece(kind,coords,mat,(56,47),(20,119))
|
||||||
|
dome(0,(47,65,38,56,-17,2),193)
|
||||||
|
dome(0,(50,62,41,53,2,5),168)
|
||||||
|
for index in range(16):
|
||||||
|
angle = index*math.tau/16
|
||||||
|
x,y = 56+5*math.cos(angle),47+5*math.sin(angle)
|
||||||
|
dome(0,(x,x+.35,y,y+.35,5,8),168)
|
||||||
|
dome(0,(50,62,41,53,8,8.4),196)
|
||||||
|
dome(1,(56,47,8.3,5.9,5.9,5),196)
|
||||||
|
dome(0,(55.4,56.6,46.4,47.6,13,15),166)
|
||||||
|
dome(0,(55.9,56.1,46.9,47.1,15,18),166)
|
||||||
|
spire = lambda kind,coords,mat: landmark_piece(kind,coords,mat,(-16,-61),(164,11))
|
||||||
|
spire(0,(-23,-9,-68,-54,-17,0),191)
|
||||||
|
spire(0,(-19,-13,-64,-58,0,9),206)
|
||||||
|
spire(0,(-18,-14,-63,-59,9,15),191)
|
||||||
|
spire(2,(-16,-61,15,1.8,1.8,20),166)
|
||||||
|
district += [f"ROOF_LANDMARK_PARTS equ {len(pieces)}","roofLandmarkParts3D LABEL DWORD"]
|
||||||
|
district += [" dd "+",".join(map(str,piece)) for piece in pieces]
|
||||||
|
fog = [min(190,round(d*180/(d+250))) for d in range(1024)]
|
||||||
|
for start in range(0,1024,32):
|
||||||
|
district.append(("roofFog3D" if start == 0 else " ")+" db "+
|
||||||
|
",".join(map(str,fog[start:start+32])))
|
||||||
|
district.append(".code")
|
||||||
|
(ROOT/"src_graphics/rooftop_district_data.inc").write_text("\n".join(district)+"\n",encoding="ascii")
|
||||||
|
(ART/"district-map-v1.json").write_text(json.dumps({"extent":[-520,560,-530,550],
|
||||||
|
"casino":[10.9,29.1,.9,21.1],"street_spacing":36,"street_width":8,
|
||||||
|
"street_level":-60,"canal":[-190,230,60,76],"bridges":[-34,38,110],
|
||||||
|
"east_river":[70,1800,29,76],"river_bridges":[110,254,398],
|
||||||
|
"lots":lots,"parks":parks,"lamps":lamps,"towers":towers,"buildings":blocks,
|
||||||
|
"landmarks":{"dome":[20,119],"spire":[164,11]}},indent=2)+"\n",encoding="ascii")
|
||||||
|
# Collision-only enclosure uses a valid legacy prepass material; the final
|
||||||
|
# rooftop pass replaces its tall walls with low world-space railings.
|
||||||
|
roof = [[102]*32 for _ in range(32)]
|
||||||
|
for y in range(1,21):
|
||||||
|
for x in range(11,29):
|
||||||
|
roof[y][x] = 0
|
||||||
|
lines = ["; Generated by tools/generators/pack_rooftop.py.", ".data"]
|
||||||
|
for y,row in enumerate(roof):
|
||||||
|
lines.append(("roofMap3D" if y == 0 else " ")+" db "+",".join(map(str,row)))
|
||||||
|
columns = [round(math.atan((x/320-1)*.66)*2048/(2*math.pi)) for x in range(640)]
|
||||||
|
for start in range(0,640,16):
|
||||||
|
lines.append(("roofSkyColumns3D" if start == 0 else " ")+" dd "+
|
||||||
|
",".join(map(str,columns[start:start+16])))
|
||||||
|
(ROOT/"src_graphics/rooftop_map.inc").write_text("\n".join(lines)+"\n",encoding="ascii")
|
||||||
|
(ART/"packed-v1.json").write_text(json.dumps({"panorama":[512,512,4],
|
||||||
|
"materials":[256,256,8],"details":[256,256,15],"city":[512,512,22],
|
||||||
|
"city-night":[512,512,22],"night":[512,512,4],"rail-hands":[640,320,32],
|
||||||
|
"lighting":[512,512,3],"city_renderer":"world-space MASM geometry; sky only is raster",
|
||||||
|
"source":"Built-in image generation; runtime geometry and interaction are assembly-only",
|
||||||
|
"reference":"https://www.loftprojectetagi.ru/visitors/krysha/"},indent=2)+"\n",encoding="ascii")
|
||||||
|
print(f"Packed roof: sunset/night, {lit_windows} distinct lit window apertures, 32 hand frames, {len(blocks)} buildings.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
319
tools/generators/pack_rooftop_gl.py
Normal file
|
|
@ -0,0 +1,319 @@
|
||||||
|
"""Offline city meshes. Playback, GL submission and compositing remain MASM."""
|
||||||
|
from pathlib import Path
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
import struct
|
||||||
|
from collections import Counter
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
OUT = ROOT/"assets/animations/rooftop"
|
||||||
|
ART = ROOT/"assets/sprites/rooftop"
|
||||||
|
|
||||||
|
|
||||||
|
class Mesh:
|
||||||
|
def __init__(self):
|
||||||
|
self.triangles = []
|
||||||
|
|
||||||
|
def quad(self, material, points, uv=None, smooth=None):
|
||||||
|
# Points use the game's X/Y ground plane and Z up. GL receives X/Z/Y.
|
||||||
|
a,b,c = points[:3]
|
||||||
|
u = [b[i]-a[i] for i in range(3)]
|
||||||
|
v = [c[i]-a[i] for i in range(3)]
|
||||||
|
normal = (u[1]*v[2]-u[2]*v[1],u[2]*v[0]-u[0]*v[2],u[0]*v[1]-u[1]*v[0])
|
||||||
|
size = math.sqrt(sum(x*x for x in normal))
|
||||||
|
if size < 1e-8:
|
||||||
|
return
|
||||||
|
normal = tuple(x/size for x in normal)
|
||||||
|
uv = uv or [(0,0),(1,0),(1,1),(0,1)]
|
||||||
|
for ids in ((0,1,2),(0,2,3)):
|
||||||
|
if len({points[i] for i in ids}) < 3:
|
||||||
|
continue
|
||||||
|
vertices = []
|
||||||
|
for i in ids:
|
||||||
|
x,y,z = points[i]
|
||||||
|
nx,ny,nz = smooth[i] if smooth else normal
|
||||||
|
# Vertical texture convention: the top of a facade is v=0.
|
||||||
|
vertices.extend((x,z,y,nx,nz,ny,*uv[i]))
|
||||||
|
self.triangles.append((material,vertices))
|
||||||
|
|
||||||
|
def box(self, x0,x1,y0,y1,z0,z1,material,roof=None,repeat_v=1):
|
||||||
|
if min(x1-x0,y1-y0,z1-z0) <= 0:
|
||||||
|
return
|
||||||
|
# Explicit winding/normals face outwards; negative scale is never used.
|
||||||
|
uv = [(0,repeat_v),(1,repeat_v),(1,0),(0,0)]
|
||||||
|
self.quad(material,[(x0,y0,z0),(x1,y0,z0),(x1,y0,z1),(x0,y0,z1)],uv)
|
||||||
|
self.quad(material,[(x1,y1,z0),(x0,y1,z0),(x0,y1,z1),(x1,y1,z1)],uv)
|
||||||
|
self.quad(material,[(x0,y1,z0),(x0,y0,z0),(x0,y0,z1),(x0,y1,z1)],uv)
|
||||||
|
self.quad(material,[(x1,y0,z0),(x1,y1,z0),(x1,y1,z1),(x1,y0,z1)],uv)
|
||||||
|
self.horizontal(x0,x1,y0,y1,z1,roof or material)
|
||||||
|
|
||||||
|
def horizontal(self,x0,x1,y0,y1,z,material,uv=None):
|
||||||
|
points = [(x0,y1,z),(x1,y1,z),(x1,y0,z),(x0,y0,z)]
|
||||||
|
uv = uv or [(0,0),(1,0),(1,1),(0,1)]
|
||||||
|
self.quad(material,list(reversed(points)),list(reversed(uv)))
|
||||||
|
|
||||||
|
def ellipsoid(self,x,y,z,rx,ry,rz,material,upper=False,rings=10,sides=24):
|
||||||
|
end = math.pi/2 if upper else math.pi
|
||||||
|
def point(t,p):
|
||||||
|
nx,ny,nz = math.sin(t)*math.cos(p),math.sin(t)*math.sin(p),math.cos(t)
|
||||||
|
n = (nx/rx,ny/ry,nz/rz)
|
||||||
|
length = math.sqrt(sum(v*v for v in n))
|
||||||
|
return (x+rx*nx,y+ry*ny,z+rz*nz),tuple(v/length for v in n)
|
||||||
|
for row in range(rings):
|
||||||
|
t0,t1 = max(.0001,row*end/rings),(row+1)*end/rings
|
||||||
|
for col in range(sides):
|
||||||
|
p0,p1 = col*math.tau/sides,(col+1)*math.tau/sides
|
||||||
|
samples = [point(t0,p0),point(t1,p0),point(t1,p1),point(t0,p1)]
|
||||||
|
self.quad(material,[p for p,n in samples],
|
||||||
|
[(col/sides,row/rings),(col/sides,(row+1)/rings),
|
||||||
|
((col+1)/sides,(row+1)/rings),((col+1)/sides,row/rings)],
|
||||||
|
[n for p,n in samples])
|
||||||
|
|
||||||
|
def cylinder(self,x,y,z0,z1,radius,material,sides=16,repeat=1):
|
||||||
|
for col in range(sides):
|
||||||
|
a,b = col*math.tau/sides,(col+1)*math.tau/sides
|
||||||
|
na,nb = (math.cos(a),math.sin(a),0),(math.cos(b),math.sin(b),0)
|
||||||
|
self.quad(material,[(x+radius*na[0],y+radius*na[1],z0),
|
||||||
|
(x+radius*nb[0],y+radius*nb[1],z0),
|
||||||
|
(x+radius*nb[0],y+radius*nb[1],z1),
|
||||||
|
(x+radius*na[0],y+radius*na[1],z1)],
|
||||||
|
uv=[(col*repeat/sides,1),((col+1)*repeat/sides,1),
|
||||||
|
((col+1)*repeat/sides,0),(col*repeat/sides,0)],
|
||||||
|
smooth=[na,nb,nb,na])
|
||||||
|
self.quad(material,[(x,y,z1),(x+radius*na[0],y+radius*na[1],z1),
|
||||||
|
(x+radius*nb[0],y+radius*nb[1],z1),
|
||||||
|
(x+radius*nb[0],y+radius*nb[1],z1)])
|
||||||
|
|
||||||
|
def hip(self,x0,x1,y0,y1,z,height,material=196):
|
||||||
|
if x1-x0 >= y1-y0:
|
||||||
|
ridge = [(x0+1,(y0+y1)/2,z+height),(x1-1,(y0+y1)/2,z+height)]
|
||||||
|
self.quad(material,[(x0,y0,z),(x1,y0,z),ridge[1],ridge[0]],[(0,0),((x1-x0)/4,0),((x1-x0)/4,1),(0,1)])
|
||||||
|
self.quad(material,[(x1,y1,z),(x0,y1,z),ridge[0],ridge[1]],[(0,0),((x1-x0)/4,0),((x1-x0)/4,1),(0,1)])
|
||||||
|
self.quad(material,[(x0,y1,z),(x0,y0,z),ridge[0],ridge[0]])
|
||||||
|
self.quad(material,[(x1,y0,z),(x1,y1,z),ridge[1],ridge[1]])
|
||||||
|
else:
|
||||||
|
# Transposing X/Y reverses winding; save() normalises every triangle.
|
||||||
|
cy = (x0+x1)/2
|
||||||
|
a,b = (cy,y0+1,z+height),(cy,y1-1,z+height)
|
||||||
|
self.quad(material,[(x0,y1,z),(x0,y0,z),a,b],[(0,0),((y1-y0)/4,0),((y1-y0)/4,1),(0,1)])
|
||||||
|
self.quad(material,[(x1,y0,z),(x1,y1,z),b,a],[(0,0),((y1-y0)/4,0),((y1-y0)/4,1),(0,1)])
|
||||||
|
self.quad(material,[(x0,y0,z),(x1,y0,z),a,a])
|
||||||
|
self.quad(material,[(x1,y1,z),(x0,y1,z),b,b])
|
||||||
|
|
||||||
|
def save(self,name,static=False):
|
||||||
|
original_count = len(self.triangles)
|
||||||
|
oriented = []
|
||||||
|
for mat,packed in self.triangles:
|
||||||
|
vertices = [packed[i:i+8] for i in (0,8,16)]
|
||||||
|
a,b,c = [v[:3] for v in vertices]
|
||||||
|
u,v = [b[i]-a[i] for i in range(3)],[c[i]-a[i] for i in range(3)]
|
||||||
|
normal = [u[1]*v[2]-u[2]*v[1],u[2]*v[0]-u[0]*v[2],u[0]*v[1]-u[1]*v[0]]
|
||||||
|
if sum(x*x for x in normal) < 1e-16:
|
||||||
|
continue
|
||||||
|
expected = [sum(vertex[i+3] for vertex in vertices) for i in range(3)]
|
||||||
|
if sum(x*y for x,y in zip(normal,expected)) < 0:
|
||||||
|
vertices[1],vertices[2] = vertices[2],vertices[1]
|
||||||
|
normal = [-x for x in normal]
|
||||||
|
if static:
|
||||||
|
# Union of every standing/seated/leaning eye position, in GL X/Z/Y axes.
|
||||||
|
bounds = ((11.0,29.0),(1.05,1.8),(1.0,21.0))
|
||||||
|
maximum = sum(n*((hi if n >= 0 else lo)-p)
|
||||||
|
for n,(lo,hi),p in zip(normal,bounds,a))
|
||||||
|
if maximum < -1e-7:
|
||||||
|
continue
|
||||||
|
oriented.append((mat,[value for vertex in vertices for value in vertex]))
|
||||||
|
self.triangles = oriented
|
||||||
|
self.triangles.sort(key=lambda t:t[0])
|
||||||
|
payload = b"".join(struct.pack("<I24f",mat,*vertices) for mat,vertices in self.triangles)
|
||||||
|
assert len(payload) == len(self.triangles)*100
|
||||||
|
assert all(161 <= mat <= 209 for mat,_ in self.triangles)
|
||||||
|
assert all(math.isfinite(v) for _,vs in self.triangles for v in vs)
|
||||||
|
assert len(self.triangles) <= 65000
|
||||||
|
(OUT/name).write_bytes(struct.pack("<4sII",b"RGM1",len(self.triangles),len(payload))+payload)
|
||||||
|
self.removed = original_count-len(self.triangles)
|
||||||
|
return len(self.triangles)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
city = json.loads((ART/"district-map-v1.json").read_text())
|
||||||
|
scene = Mesh()
|
||||||
|
# The terrace is on a real sixty-metre high-rise, not a floating platform.
|
||||||
|
scene.box(10.9,29.1,.9,21.1,-60,0,200,roof=165,repeat_v=3)
|
||||||
|
scene.horizontal(10.9,29.1,.9,21.1,.004,161,[(0,10),(9,10),(9,0),(0,0)])
|
||||||
|
# Terrain is actual split geometry, leaving a lowered water channel.
|
||||||
|
def patches(lo,hi):
|
||||||
|
return [(lo,70,lo,60,False),(70,hi,lo,29,False),(lo,hi,76,hi,False),
|
||||||
|
(lo,hi,60,76,True),(70,hi,29,60,True)]
|
||||||
|
def world_uv(x0,x1,y0,y1,scale):
|
||||||
|
return [(x0/scale,y1/scale),(x1/scale,y1/scale),
|
||||||
|
(x1/scale,y0/scale),(x0/scale,y0/scale)]
|
||||||
|
for x0,x1,y0,y1,water in patches(-2000,2000):
|
||||||
|
scene.horizontal(x0,x1,y0,y1,-62 if water else -60,198 if water else 162,
|
||||||
|
world_uv(x0,x1,y0,y1,12 if water else 4))
|
||||||
|
def subtract(rect,obstacle):
|
||||||
|
a,b,c,d = rect
|
||||||
|
x0,x1,y0,y1 = obstacle
|
||||||
|
x0,x1,y0,y1 = max(a,x0),min(b,x1),max(c,y0),min(d,y1)
|
||||||
|
if x0 >= x1 or y0 >= y1:
|
||||||
|
return [rect]
|
||||||
|
return [r for r in ((a,x0,c,d),(x1,b,c,d),(x0,x1,c,y0),(x0,x1,y1,d))
|
||||||
|
if r[1]-r[0] > .01 and r[3]-r[2] > .01]
|
||||||
|
def road(rect,vertical=False):
|
||||||
|
pieces = [rect]
|
||||||
|
obstacles = [(-2000,2000,58,79),(68,2000,26,81)]
|
||||||
|
if vertical:
|
||||||
|
obstacles += [(-2000,2000,29+36*i-4,29+36*i+4) for i in range(-16,17)]
|
||||||
|
for obstacle in obstacles:
|
||||||
|
pieces = [p for r in pieces for p in subtract(r,obstacle)]
|
||||||
|
for a,b,c,d in pieces:
|
||||||
|
roads.append((a,b,c,d))
|
||||||
|
scene.horizontal(a,b,c,d,-59.98,197,world_uv(a,b,c,d,4))
|
||||||
|
roads = []
|
||||||
|
for i in range(-16,17):
|
||||||
|
x = 38+36*i
|
||||||
|
road((x-4,x+4,-600,600),vertical=True)
|
||||||
|
y = 29+36*i
|
||||||
|
road((-600,600,y-4,y+4))
|
||||||
|
# Small lane dashes and pedestrian crossings give the streets a readable scale.
|
||||||
|
for gx in range(-6,7):
|
||||||
|
x = 38+36*gx
|
||||||
|
for y in range(-205,231,9):
|
||||||
|
if not 54 < y < 82 and not (x > 68 and 24 < y < 82):
|
||||||
|
scene.horizontal(x-.07,x+.07,y,y+3,-59.965,168)
|
||||||
|
for gy in range(-6,7):
|
||||||
|
y = 29+36*gy
|
||||||
|
if 54 < y < 82 or (x > 68 and 24 < y < 82):
|
||||||
|
continue
|
||||||
|
for stripe in range(7):
|
||||||
|
sx = x-3.2+stripe*.95
|
||||||
|
scene.horizontal(sx,sx+.45,y+5,y+7,-59.96,168)
|
||||||
|
for index,(x0,x1,y0,y1,roof,mat,kind) in enumerate(city["buildings"]):
|
||||||
|
modern = mat >= 199
|
||||||
|
repeat = max(1,round((roof+60)/26)) if modern else 1
|
||||||
|
scene.box(x0,x1,y0,y1,-60,roof,mat,repeat_v=repeat)
|
||||||
|
scene.box(x0-.18,x1+.18,y0-.18,y1+.18,roof,roof+.18,165 if modern else 168)
|
||||||
|
distance = math.hypot((x0+x1)/2-20,(y0+y1)/2-11)
|
||||||
|
if not modern and distance < 220:
|
||||||
|
scene.box(x0-.12,x1+.12,y0-.12,y1+.12,-60,-58.8,162)
|
||||||
|
for z in (roof-.55,roof-.3):
|
||||||
|
scene.box(x0-.25,x1+.25,y0-.25,y1+.25,z,z+.12,168)
|
||||||
|
if distance < 150:
|
||||||
|
for x in (x0,x1-.28):
|
||||||
|
for y in (y0,y1-.28):
|
||||||
|
scene.box(x-.08,x+.36,y-.08,y+.36,-58.8,roof-.5,168)
|
||||||
|
scene.hip(x0-.25,x1+.25,y0-.25,y1+.25,roof+.18,2.4)
|
||||||
|
scene.box(x0+.8,x0+1.45,y0+.8,y0+1.35,roof+1.2,roof+3.2,190,roof=162)
|
||||||
|
# Recessed dormer volumes interrupt long, otherwise empty roof slopes.
|
||||||
|
if x1-x0 > 12 and distance < 150:
|
||||||
|
for x in range(math.ceil(x0+3),math.floor(x1-2),6):
|
||||||
|
scene.box(x-.55,x+.55,y0+.8,y0+1.55,roof+.45,roof+1.45,168)
|
||||||
|
scene.quad(200,[(x-.4,y0+.79,roof+.6),(x+.4,y0+.79,roof+.6),
|
||||||
|
(x+.4,y0+.79,roof+1.25),(x-.4,y0+.79,roof+1.25)])
|
||||||
|
scene.hip(x-.65,x+.65,y0+.7,y0+1.65,roof+1.45,.4)
|
||||||
|
else:
|
||||||
|
scene.horizontal(x0,x1,y0,y1,roof+.19,196)
|
||||||
|
# Static landmark records share their exact footprints with the MASM world.
|
||||||
|
data = (ROOT/"src_graphics/rooftop_district_data.inc").read_text()
|
||||||
|
section = data.split("roofLandmarkParts3D LABEL DWORD",1)[1].split("roofFog3D",1)[0]
|
||||||
|
for line in section.splitlines():
|
||||||
|
if not line.strip().startswith("dd "):
|
||||||
|
continue
|
||||||
|
values = list(map(int,line.strip()[3:].split(",")))
|
||||||
|
kind,coords,mat = values[0],[v/65536 for v in values[1:7]],values[7]
|
||||||
|
# The dome's old rectangular drum is replaced with a proper circular one.
|
||||||
|
if kind == 0 and 7 < coords[0] < 12 and 128 < coords[3] < 134 and coords[4] > -30:
|
||||||
|
continue
|
||||||
|
if kind == 0:
|
||||||
|
x0,x1,y0,y1,z0,z1 = coords
|
||||||
|
if x1-x0 < 1.1 and y1-y0 < 1.1 and z1-z0 > 3:
|
||||||
|
scene.cylinder((x0+x1)/2,(y0+y1)/2,z0,z1,(x1-x0)/2,mat)
|
||||||
|
scene.box(x0-.12,x1+.12,y0-.12,y1+.12,z1-.25,z1,mat)
|
||||||
|
else:
|
||||||
|
scene.box(*coords,mat)
|
||||||
|
elif kind == 1:
|
||||||
|
scene.ellipsoid(*coords,mat,upper=True,rings=14,sides=48)
|
||||||
|
elif kind == 2:
|
||||||
|
x,y,z,rx,ry,h = coords
|
||||||
|
h *= .65
|
||||||
|
for i in range(8):
|
||||||
|
a,b = i*math.tau/8,(i+1)*math.tau/8
|
||||||
|
scene.quad(mat,[(x+rx*math.cos(a),y+ry*math.sin(a),z),
|
||||||
|
(x+rx*math.cos(b),y+ry*math.sin(b),z),
|
||||||
|
(x,y,z+h),(x,y,z+h)])
|
||||||
|
# Cathedral drum, portico and a solid entablature under the copper dome.
|
||||||
|
scene.cylinder(20,119,-22,-10,9.5,191,sides=48,repeat=6)
|
||||||
|
for z,radius in ((-22,10.3),(-16,10.0),(-10.5,12.4)):
|
||||||
|
scene.cylinder(20,119,z,z+.45,radius,168,sides=48,repeat=6)
|
||||||
|
for step in range(4):
|
||||||
|
scene.box(3+step*.4,37-step*.4,95+step*.5,104,-60+step*.35,-59.65+step*.35,162)
|
||||||
|
for x in (6,11.5,17,22.5,28,33.5):
|
||||||
|
scene.cylinder(x,99,-58.6,-40,.55,168,sides=16)
|
||||||
|
scene.cylinder(x,99,-58.6,-57.8,.8,162,sides=16)
|
||||||
|
scene.cylinder(x,99,-40,-39.5,.8,168,sides=16)
|
||||||
|
scene.box(3,37,97,104,-39.5,-38.5,168)
|
||||||
|
scene.quad(168,[(3,96.99,-38.5),(37,96.99,-38.5),(20,96.99,-33),(20,96.99,-33)])
|
||||||
|
scene.hip(2.8,37.2,96.8,104.2,-38.5,5.5)
|
||||||
|
for x in sorted(set(city["bridges"]+city["river_bridges"])):
|
||||||
|
start,end = (28,77) if x >= 70 else (59,77)
|
||||||
|
scene.horizontal(x-3,x+3,start,end,-59.9,197,world_uv(x-3,x+3,start,end,4))
|
||||||
|
for side in (x-3,x+3):
|
||||||
|
for i in range(24):
|
||||||
|
y0,y1 = start+(end-start)*i/24,start+(end-start)*(i+1)/24
|
||||||
|
mid,radius = (start+end)/2,(end-start)/2
|
||||||
|
z0 = -62+1.8*math.sqrt(max(0,1-((y0-mid)/radius)**2))
|
||||||
|
z1 = -62+1.8*math.sqrt(max(0,1-((y1-mid)/radius)**2))
|
||||||
|
points = [(side,y0,z0),(side,y1,z1),(side,y1,-60),(side,y0,-60)]
|
||||||
|
scene.quad(162,list(reversed(points)) if side < x else points)
|
||||||
|
for y in range(start,end+1,2):
|
||||||
|
scene.box(side-.1,side+.1,y-.1,y+.1,-60,-59,165)
|
||||||
|
scene.box(side-.08,side+.08,start,end,-59.1,-59,165)
|
||||||
|
# Raised embankments, a tree-lined promenade and small piers follow the river.
|
||||||
|
for y0,y1 in ((26,29),(76,81)):
|
||||||
|
scene.box(70,1100,y0,y1,-62,-59.75,162)
|
||||||
|
for x in range(84,640,28):
|
||||||
|
y = (y0+y1)/2
|
||||||
|
if min(abs(x-b) for b in city["river_bridges"]) < 6:
|
||||||
|
continue
|
||||||
|
scene.cylinder(x,y,-59.75,-56,.14,162,sides=6)
|
||||||
|
scene.ellipsoid(x,y,-55,1.7,1.7,2.1,207,rings=4,sides=8)
|
||||||
|
scene.box(x+3,x+5,y-.3,y+.3,-59.75,-59.3,162)
|
||||||
|
for x in (156,300,444):
|
||||||
|
scene.box(x,x+7,28,34,-62,-60.3,196)
|
||||||
|
for x,y in city["parks"]:
|
||||||
|
scene.horizontal(x-12,x+12,y-12,y+12,-59.9,207)
|
||||||
|
scene.horizontal(x-1,x+1,y-12,y+12,-59.8,162)
|
||||||
|
for dx in (-8,8):
|
||||||
|
for dy in (-8,0,8):
|
||||||
|
scene.cylinder(x+dx,y+dy,-60,-56,.15,162,sides=8)
|
||||||
|
scene.ellipsoid(x+dx,y+dy,-55.5,2.0,2.0,2.4,207,rings=5,sides=10)
|
||||||
|
for x,y in city.get("lamps",[]):
|
||||||
|
scene.cylinder(x,y,-60,-55,.055,165,sides=6)
|
||||||
|
scene.box(x-.22,x+.22,y-.22,y+.22,-55.15,-54.9,178)
|
||||||
|
# A second ground pass multiplies the baked, geometry-derived light map.
|
||||||
|
for a,b,c,d,water in patches(-512,512):
|
||||||
|
uv = [((a+512)/1024,(d+512)/1024),((b+512)/1024,(d+512)/1024),
|
||||||
|
((b+512)/1024,(c+512)/1024),((a+512)/1024,(c+512)/1024)]
|
||||||
|
scene.horizontal(a,b,c,d,-61.94 if water else -59.94,208,uv)
|
||||||
|
scene.horizontal(a,b,c,d,-61.93 if water else -59.93,209,uv)
|
||||||
|
car = Mesh()
|
||||||
|
car.box(-1.9,1.9,-.8,.8,.25,.85,196)
|
||||||
|
car.box(-.9,.9,-.65,.65,.85,1.35,200)
|
||||||
|
for y in (-.57,.57):
|
||||||
|
car.box(1.88,1.93,y-.12,y+.12,.5,.68,178)
|
||||||
|
for x in (-1.2,1.2):
|
||||||
|
for y in (-.83,.83):
|
||||||
|
car.ellipsoid(x,y,.3,.32,.12,.32,197,rings=5,sides=10)
|
||||||
|
boat = Mesh()
|
||||||
|
boat.ellipsoid(0,0,-1.6,3,1,.5,196,rings=6,sides=16)
|
||||||
|
boat.box(-1,1,-.6,.6,-1.4,-.7,168)
|
||||||
|
counts = {"scene":scene.save("mesh-city-v1.bin",static=True),"car":car.save("mesh-car-v1.bin"),
|
||||||
|
"boat":boat.save("mesh-boat-v1.bin")}
|
||||||
|
(ART/"mesh-v1.json").write_text(json.dumps({"format":"RGM1: count/bytes + material/3*(position,normal,uv)",
|
||||||
|
"gl_axes":"X/Z/Y; normals explicitly outward; no runtime model engine", "triangles":counts,
|
||||||
|
"road_rectangles":roads,"river_patches":[p for p in patches(-2000,2000) if p[-1]],
|
||||||
|
"removed_invisible_triangles":scene.removed,"front_face":"CCW"},indent=2)+"\n")
|
||||||
|
print("Packed native GL meshes:",counts)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
@ -6,6 +6,7 @@ from pathlib import Path
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from check_card_exit_build import Coff
|
from check_card_exit_build import Coff
|
||||||
from check_coin_detail import font, text_matches
|
from check_coin_detail import font, text_matches
|
||||||
|
from check_terminals import signature
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[2]
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
OUT = ROOT / "build/actions"
|
OUT = ROOT / "build/actions"
|
||||||
|
|
@ -62,11 +63,11 @@ def main(parity=False):
|
||||||
contact.paste(frames[name], ((i % 3) * 640, (i // 3) * 480))
|
contact.paste(frames[name], ((i % 3) * 640, (i // 3) * 480))
|
||||||
contact.save(OUT / "billiards-contact.png")
|
contact.save(OUT / "billiards-contact.png")
|
||||||
if parity:
|
if parity:
|
||||||
tested = Coff(OUT / "actions-test.obj")
|
tested = Coff(ROOT / "build/billiards/module.obj")
|
||||||
shipped = Coff(ROOT / "build/graphics/poker.obj")
|
shipped = Coff(ROOT / "build/graphics/poker.obj")
|
||||||
for name, size in FUNCTIONS.items():
|
for name, size in FUNCTIONS.items():
|
||||||
symbol = f"_{name}@{size}"
|
symbol = f"_{name}@{size}"
|
||||||
assert tested.signature(symbol) == shipped.signature(symbol), name
|
assert signature(tested,symbol,tail_branches=True) == signature(shipped,symbol,tail_branches=True), name
|
||||||
print("PASS: Russian selection, both ball sets, native captures, rebound prediction" +
|
print("PASS: Russian selection, both ball sets, native captures, rebound prediction" +
|
||||||
(" and shipping/tested billiards parity" if parity else ""))
|
(" and shipping/tested billiards parity" if parity else ""))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,9 @@ def main():
|
||||||
print("PASS: dart scene, scoring, input and camera match the shipping object")
|
print("PASS: dart scene, scoring, input and camera match the shipping object")
|
||||||
return
|
return
|
||||||
masm = Path("F:/MASM32/masm32")
|
masm = Path("F:/MASM32/masm32")
|
||||||
subprocess.run([str(masm / "bin/ml.exe"), "/c", "/coff", "/Cp", "/nologo", "/I.",
|
modern_ml = Path("C:/Program Files/Microsoft Visual Studio/18/Community/VC/Tools/MSVC/14.51.36231/bin/Hostx64/x86/ml.exe")
|
||||||
|
assembler = modern_ml if modern_ml.is_file() else masm / "bin/ml.exe"
|
||||||
|
subprocess.run([str(assembler), "/c", "/coff", "/Cp", "/nologo", "/I.",
|
||||||
"/Fobuild/darts/module.obj", "build/darts/module.asm"], cwd=ROOT, check=True)
|
"/Fobuild/darts/module.obj", "build/darts/module.asm"], cwd=ROOT, check=True)
|
||||||
sdk = sorted(Path("C:/Program Files (x86)/Windows Kits/10/Lib").glob("*/um/x86"))[-1]
|
sdk = sorted(Path("C:/Program Files (x86)/Windows Kits/10/Lib").glob("*/um/x86"))[-1]
|
||||||
target = "ui" if args.interactive else "module"
|
target = "ui" if args.interactive else "module"
|
||||||
|
|
@ -165,7 +167,7 @@ def main():
|
||||||
sway[0].save(OUT / "sway.gif", save_all=True, append_images=sway[1:], duration=40, loop=0)
|
sway[0].save(OUT / "sway.gif", save_all=True, append_images=sway[1:], duration=40, loop=0)
|
||||||
triples, = struct.unpack("<I", (OUT / "aim-metrics.bin").read_bytes())
|
triples, = struct.unpack("<I", (OUT / "aim-metrics.bin").read_bytes())
|
||||||
print(f"PASS: stationary centre-of-T20 aim scored triples in {triples}/100 native samples")
|
print(f"PASS: stationary centre-of-T20 aim scored triples in {triples}/100 native samples")
|
||||||
print("PASS: 67 scoring vectors, 20 complete bot matches, bust/turn isolation, fine mouse/release, sway/fatigue, board footprint, Tab, orbit camera and native moving frames")
|
print("PASS: 67 scoring vectors, 20 complete bot matches, bust/turn isolation, fine mouse/release, sway/fatigue, board footprint, nine-pixel reticle, Tab, orbit camera and native moving frames")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
"""Compile and execute fresh MASM navigation, actors and room renderers."""
|
"""Compile and execute fresh MASM navigation, actors and room renderers."""
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import argparse
|
import argparse
|
||||||
|
import json
|
||||||
import re
|
import re
|
||||||
import struct
|
import struct
|
||||||
import subprocess
|
import subprocess
|
||||||
from PIL import Image, ImageStat
|
from PIL import Image, ImageStat, ImageChops
|
||||||
from check_card_exit_build import Coff
|
from check_card_exit_build import Coff
|
||||||
from check_terminals import signature
|
from check_terminals import signature
|
||||||
|
|
||||||
|
|
@ -36,6 +37,7 @@ def prepare():
|
||||||
code += "\n" + read("src_graphics/steel_door.inc")
|
code += "\n" + read("src_graphics/steel_door.inc")
|
||||||
code += "\n" + read("src_graphics/fortune_room.inc")
|
code += "\n" + read("src_graphics/fortune_room.inc")
|
||||||
code += "\n" + read("src_graphics/fortune_dialog.inc")
|
code += "\n" + read("src_graphics/fortune_dialog.inc")
|
||||||
|
code += "\n" + expand("src_graphics/rooftop.inc")
|
||||||
code += "\n" + proc(read("src_graphics/unavailable.inc"),"BeginUnavailable3D")
|
code += "\n" + proc(read("src_graphics/unavailable.inc"),"BeginUnavailable3D")
|
||||||
code += "\n" + read("src_graphics/observer.inc")
|
code += "\n" + read("src_graphics/observer.inc")
|
||||||
code += "\n" + expand("src_graphics/darts.inc").replace(":SDWORD", ":DWORD")
|
code += "\n" + expand("src_graphics/darts.inc").replace(":SDWORD", ":DWORD")
|
||||||
|
|
@ -48,7 +50,7 @@ def prepare():
|
||||||
"CheckHallInteractions3D","TriggerHallInteraction3D","HandleStairs3D","RenderStairs3D",
|
"CheckHallInteractions3D","TriggerHallInteraction3D","HandleStairs3D","RenderStairs3D",
|
||||||
"CanWalkHall3D","UpdateHall3D","UpdatePatrons3D","RenderPatrons3D","RenderBar3D",
|
"CanWalkHall3D","UpdateHall3D","UpdatePatrons3D","RenderPatrons3D","RenderBar3D",
|
||||||
"BuyBarDrink3D","HandleBar3D"]),
|
"BuyBarDrink3D","HandleBar3D"]),
|
||||||
("src_graphics/platform_code.inc",["CanWalk3D","WindowEvents3D"]),
|
("src_graphics/platform_code.inc",["CanWalk3D","WindowEvents3D","Present3D"]),
|
||||||
("casino3d.inc",["HandlePlayerInput","CheckInteractions","RenderWallsRange","RenderWalls","RaycastWorkerProc","Trigger3DInteraction"]),
|
("casino3d.inc",["HandlePlayerInput","CheckInteractions","RenderWallsRange","RenderWalls","RaycastWorkerProc","Trigger3DInteraction"]),
|
||||||
("src_graphics/city_bins.inc",["ResolveCitySurface3D","PrepareCityDepth3D","PrepareCityRays3D",
|
("src_graphics/city_bins.inc",["ResolveCitySurface3D","PrepareCityDepth3D","PrepareCityRays3D",
|
||||||
"CityRayPlane3D","DrawCityVertical3D","DrawCityHorizontal3D","DrawCityBoxSides3D"]),
|
"CityRayPlane3D","DrawCityVertical3D","DrawCityHorizontal3D","DrawCityBoxSides3D"]),
|
||||||
|
|
@ -60,10 +62,10 @@ def prepare():
|
||||||
own_funcs = set(re.findall(r"^(\w+) PROC",code,re.M))
|
own_funcs = set(re.findall(r"^(\w+) PROC",code,re.M))
|
||||||
npc = read("src_graphics/npc_life_data.inc")
|
npc = read("src_graphics/npc_life_data.inc")
|
||||||
npc = npc[npc.index("npcGuestArt3D "):npc.index("npcLifeClock3D ")]
|
npc = npc[npc.index("npcGuestArt3D "):npc.index("npcLifeClock3D ")]
|
||||||
data = "\n".join(read(path) for path in ("src_graphics/hall_expansion_data.inc",
|
data = "\n".join(expand(path) for path in ("src_graphics/hall_expansion_data.inc",
|
||||||
"src_graphics/cabaret_data.inc","src_graphics/hall_layout.inc",
|
"src_graphics/cabaret_data.inc","src_graphics/hall_layout.inc",
|
||||||
"src_graphics/fortune_room_data.inc","src_graphics/fortune_dialog_data.inc",
|
"src_graphics/fortune_room_data.inc","src_graphics/fortune_dialog_data.inc",
|
||||||
"src_graphics/observer_data.inc")) + "\n.data\n" + npc
|
"src_graphics/observer_data.inc","src_graphics/rooftop_data.inc")) + "\n.data\n" + npc
|
||||||
darts = read("src_graphics/darts_data.inc").replace(
|
darts = read("src_graphics/darts_data.inc").replace(
|
||||||
"include src_graphics\\darts_art.inc", read("src_graphics/darts_art.inc"))
|
"include src_graphics\\darts_art.inc", read("src_graphics/darts_art.inc"))
|
||||||
data += "\n" + re.sub(r"^\w+ PROTO[^\n]*\n", "", darts, flags=re.M)
|
data += "\n" + re.sub(r"^\w+ PROTO[^\n]*\n", "", darts, flags=re.M)
|
||||||
|
|
@ -134,7 +136,8 @@ def prepare():
|
||||||
# Win32 prototypes are not declarations in the helper object.
|
# Win32 prototypes are not declarations in the helper object.
|
||||||
for name,args in re.findall(r"^(\w+)\s+PROTO([^\n]*)",all_source,re.M):
|
for name,args in re.findall(r"^(\w+)\s+PROTO([^\n]*)",all_source,re.M):
|
||||||
protos.setdefault(name,args.count(":DWORD"))
|
protos.setdefault(name,args.count(":DWORD"))
|
||||||
protos.update({"ExitProcess":1,"WriteFile":5,"GetTickCount":0})
|
protos.update({"ExitProcess":1,"WriteFile":5,"GetTickCount":0,"SetUnhandledExceptionFilter":1,
|
||||||
|
"CreateDirectoryA":2})
|
||||||
header = ".386\n.model flat\noption casemap:none\n" + "\n".join(structures+ordered+externs)
|
header = ".386\n.model flat\noption casemap:none\n" + "\n".join(structures+ordered+externs)
|
||||||
header += "\noption language:stdcall\n" + "\n".join(
|
header += "\noption language:stdcall\n" + "\n".join(
|
||||||
name+" PROTO"+(" "+",".join([":DWORD"]*size) if size else "")
|
name+" PROTO"+(" "+",".join([":DWORD"]*size) if size else "")
|
||||||
|
|
@ -144,6 +147,56 @@ def prepare():
|
||||||
return own_funcs
|
return own_funcs
|
||||||
|
|
||||||
|
|
||||||
|
def check_rooftop_navigation():
|
||||||
|
for name,dimensions in (("panorama",(512,512,4)),("materials",(256,256,8)),
|
||||||
|
("details",(256,256,15)),("city",(512,512,22)),
|
||||||
|
("night",(512,512,4)),("rail-hands",(640,320,32))):
|
||||||
|
raw = (ROOT/f"assets/animations/rooftop/{name}-v1.bin").read_bytes()
|
||||||
|
magic,w,h,frames,payload = struct.unpack_from("<4s4I",raw)
|
||||||
|
assert magic == b"ANM1" and (w,h,frames) == dimensions
|
||||||
|
assert len(raw) == payload+20 and payload == w*h*frames*4
|
||||||
|
navigation = (OUT/"roof-navigation.bin").read_bytes()
|
||||||
|
width,height,ox,oy,step,count = struct.unpack_from("<6I",navigation)
|
||||||
|
assert count == 13
|
||||||
|
xs = struct.unpack_from(f"<{count}I",navigation,24)
|
||||||
|
ys = struct.unpack_from(f"<{count}I",navigation,24+count*4)
|
||||||
|
kinds = struct.unpack_from(f"<{count}I",navigation,24+count*8)
|
||||||
|
cells = navigation[24+count*12:]
|
||||||
|
assert len(cells) == width*height
|
||||||
|
def nav_point(x,y):
|
||||||
|
return round((x*65536-ox)/step),round((y*65536-oy)/step)
|
||||||
|
start = nav_point(24.5,2.5)
|
||||||
|
assert cells[start[1]*width+start[0]], "lift cabin must be walkable when open"
|
||||||
|
reached,pending = {start},[start]
|
||||||
|
while pending:
|
||||||
|
x,y = pending.pop()
|
||||||
|
for a,b in ((x-1,y),(x+1,y),(x,y-1),(x,y+1)):
|
||||||
|
if 0 <= a < width and 0 <= b < height and cells[b*width+a] and (a,b) not in reached:
|
||||||
|
reached.add((a,b))
|
||||||
|
pending.append((a,b))
|
||||||
|
assert len(reached) > 1500
|
||||||
|
for i,(sx,sy) in enumerate(zip(xs,ys)):
|
||||||
|
assert any((ox+x*step-sx)**2+(oy+y*step-sy)**2 < (1.8*65536)**2
|
||||||
|
for x,y in reached),(i,"seat has no reachable approach")
|
||||||
|
for point in ((15.5,6.75),(27,18),(13,17)):
|
||||||
|
assert nav_point(*point) in reached,(point,"blocked rooftop route")
|
||||||
|
assert list(kinds).count(0) == 3 and list(kinds).count(1) == 4
|
||||||
|
city = json.loads((ROOT/"assets/sprites/rooftop/district-map-v1.json").read_text())
|
||||||
|
assert city["street_level"] == -60
|
||||||
|
assert len(city["parks"]) >= 6 and len(city["towers"]) >= 8
|
||||||
|
assert len(city["buildings"]) > 400
|
||||||
|
heights = {round(b[4]+60,1) for b in city["buildings"]}
|
||||||
|
assert len(heights) >= 35 and min(heights) <= 6 and max(heights) >= 150
|
||||||
|
assert len({(round(b[1]-b[0],1),round(b[3]-b[2],1)) for b in city["buildings"]}) >= 15
|
||||||
|
assert {b[5] for b in city["buildings"]} >= {186,187,188,199,200,201,202,203,204}
|
||||||
|
for x0,x1,y0,y1,top,material,kind in city["buildings"]:
|
||||||
|
assert not (x0 < 29.1 and x1 > 10.9 and y0 < 21.1 and y1 > .9)
|
||||||
|
if max(abs((x0+x1)/2-20),abs((y0+y1)/2-11)) < 60:
|
||||||
|
assert top <= -19,"a neighbour must not block the sixty-metre-high terrace"
|
||||||
|
print(f"PASS: sixty-metre rooftop, {len(heights)} distinct city heights, streets/courtyards, parks, bridges and distant towers")
|
||||||
|
print(f"PASS: dense rooftop, {count} seats, {len(reached)} connected native walk points, lift/bar return and camera restore")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("--parity",action="store_true")
|
parser.add_argument("--parity",action="store_true")
|
||||||
|
|
@ -151,6 +204,7 @@ def main():
|
||||||
parser.add_argument("--prove-seam-regression",action="store_true")
|
parser.add_argument("--prove-seam-regression",action="store_true")
|
||||||
parser.add_argument("--prove-distance-regression",action="store_true")
|
parser.add_argument("--prove-distance-regression",action="store_true")
|
||||||
parser.add_argument("--prove-bar-camera-regression",action="store_true")
|
parser.add_argument("--prove-bar-camera-regression",action="store_true")
|
||||||
|
parser.add_argument("--prove-fate-anchor-regression",action="store_true")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
if args.parity:
|
if args.parity:
|
||||||
native,shipping = Coff(OUT/"module.obj"),Coff(ROOT/"build/graphics/poker.obj")
|
native,shipping = Coff(OUT/"module.obj"),Coff(ROOT/"build/graphics/poker.obj")
|
||||||
|
|
@ -162,10 +216,25 @@ def main():
|
||||||
print("PASS: all tested navigation, collision, hall/upper rendering, guests and cabaret procedures match the shipping assembly")
|
print("PASS: all tested navigation, collision, hall/upper rendering, guests and cabaret procedures match the shipping assembly")
|
||||||
return
|
return
|
||||||
prepare()
|
prepare()
|
||||||
|
walk = read("casino3d.inc").split("check_walk_mode:",1)[1].split("check_slots_mode:",1)[0]
|
||||||
|
assert walk.index("je walk_world_ready") < walk.index("call RenderCeilingAndFloor")
|
||||||
|
assert walk.index("walk_world_ready:") > walk.index("call RenderSprites")
|
||||||
room = proc(read("src_graphics/fortune_room.inc"), "RenderFortuneFurnishings3D")
|
room = proc(read("src_graphics/fortune_room.inc"), "RenderFortuneFurnishings3D")
|
||||||
assert "DrawCityObject3D" not in room, "tarot furniture must not face the camera"
|
assert "DrawCityObject3D" not in room, "tarot furniture must not face the camera"
|
||||||
assert room.count("DrawFortuneFixedProp3D") == 24
|
assert room.count("DrawFortuneFixedProp3D") == 24
|
||||||
stem = "module"
|
stem = "module"
|
||||||
|
if args.prove_fate_anchor_regression:
|
||||||
|
stem = "module-fate-anchor-regression"
|
||||||
|
source = (OUT/"module.asm").read_text(encoding="cp1251")
|
||||||
|
before = proc(source,"ResolveFortuneOrb3D")
|
||||||
|
broken = before.replace("mov fortuneOrbCenterX3D,eax", "mov fortuneOrbCenterX3D,278")
|
||||||
|
broken = broken.replace("mov fortuneOrbCenterY3D,eax", "mov fortuneOrbCenterY3D,259")
|
||||||
|
assert broken != before
|
||||||
|
source = source.replace(before,broken)
|
||||||
|
source = source.replace("include tools/tests/hall_expansion_test.inc",
|
||||||
|
expand("tools/tests/hall_expansion_test.inc"))
|
||||||
|
source = source.replace("build\\hall-expansion\\", "build\\hall-expansion\\anchor-regression-")
|
||||||
|
(OUT/(stem+".asm")).write_text(source,encoding="cp1251")
|
||||||
if args.prove_bar_camera_regression:
|
if args.prove_bar_camera_regression:
|
||||||
stem = "module-camera-regression"
|
stem = "module-camera-regression"
|
||||||
source = (OUT/"module.asm").read_text(encoding="cp1251")
|
source = (OUT/"module.asm").read_text(encoding="cp1251")
|
||||||
|
|
@ -199,7 +268,9 @@ def main():
|
||||||
"invoke ExpansionPortalSnapshot,OFFSET expansionUpEntry\n invoke ExitProcess,0")
|
"invoke ExpansionPortalSnapshot,OFFSET expansionUpEntry\n invoke ExitProcess,0")
|
||||||
(OUT/(stem+".asm")).write_text(source,encoding="cp1251")
|
(OUT/(stem+".asm")).write_text(source,encoding="cp1251")
|
||||||
masm = Path("F:/MASM32/masm32")
|
masm = Path("F:/MASM32/masm32")
|
||||||
subprocess.run([str(masm/"bin/ml.exe"),"/c","/coff","/Cp","/nologo","/I.",
|
modern_ml = Path("C:/Program Files/Microsoft Visual Studio/18/Community/VC/Tools/MSVC/14.51.36231/bin/Hostx64/x86/ml.exe")
|
||||||
|
assembler = modern_ml if modern_ml.is_file() else masm/"bin/ml.exe"
|
||||||
|
subprocess.run([str(assembler),"/c","/coff","/Cp","/nologo","/I.",
|
||||||
f"/Fobuild/hall-expansion/{stem}.obj",f"build/hall-expansion/{stem}.asm"],cwd=ROOT,check=True)
|
f"/Fobuild/hall-expansion/{stem}.obj",f"build/hall-expansion/{stem}.asm"],cwd=ROOT,check=True)
|
||||||
sdk = sorted(Path("C:/Program Files (x86)/Windows Kits/10/Lib").glob("*/um/x86"))[-1]
|
sdk = sorted(Path("C:/Program Files (x86)/Windows Kits/10/Lib").glob("*/um/x86"))[-1]
|
||||||
subprocess.run([str(masm/"bin/link.exe"),"/nologo","/SUBSYSTEM:CONSOLE","/ENTRY:ExpansionTestStart@0",
|
subprocess.run([str(masm/"bin/link.exe"),"/nologo","/SUBSYSTEM:CONSOLE","/ENTRY:ExpansionTestStart@0",
|
||||||
|
|
@ -207,6 +278,10 @@ def main():
|
||||||
f"build/hall-expansion/{stem}.obj","build/hall-expansion/helpers.obj",
|
f"build/hall-expansion/{stem}.obj","build/hall-expansion/helpers.obj",
|
||||||
"kernel32.lib","user32.lib","gdi32.lib","winmm.lib","ws2_32.lib"],cwd=ROOT,check=True)
|
"kernel32.lib","user32.lib","gdi32.lib","winmm.lib","ws2_32.lib"],cwd=ROOT,check=True)
|
||||||
result = subprocess.run([str(OUT/(stem+".exe"))],cwd=ROOT,timeout=360)
|
result = subprocess.run([str(OUT/(stem+".exe"))],cwd=ROOT,timeout=360)
|
||||||
|
if args.prove_fate_anchor_regression:
|
||||||
|
assert result.returncode == 81,result.returncode
|
||||||
|
print("PASS: restoring fixed screen coordinates fails the native crystal-ball tracking assertions")
|
||||||
|
return
|
||||||
if args.prove_bar_camera_regression:
|
if args.prove_bar_camera_regression:
|
||||||
assert result.returncode == 70,result.returncode
|
assert result.returncode == 70,result.returncode
|
||||||
print("PASS: removing camera recovery fails the native bar regression")
|
print("PASS: removing camera recovery fails the native bar regression")
|
||||||
|
|
@ -220,6 +295,8 @@ def main():
|
||||||
print("PASS: restoring eight-metre cutoff fails the native far-doorway assertion")
|
print("PASS: restoring eight-metre cutoff fails the native far-doorway assertion")
|
||||||
return
|
return
|
||||||
assert result.returncode == 0,f"native case {result.returncode}"
|
assert result.returncode == 0,f"native case {result.returncode}"
|
||||||
|
if not args.prove_seam_regression:
|
||||||
|
check_rooftop_navigation()
|
||||||
closed = Image.open(OUT/"fortune-closed.bmp").tobytes()
|
closed = Image.open(OUT/"fortune-closed.bmp").tobytes()
|
||||||
opened = Image.open(OUT/"fortune-open.bmp").tobytes()
|
opened = Image.open(OUT/"fortune-open.bmp").tobytes()
|
||||||
assert closed != opened, "secret panel must visibly reveal the stairwell"
|
assert closed != opened, "secret panel must visibly reveal the stairwell"
|
||||||
|
|
@ -246,6 +323,37 @@ def main():
|
||||||
assert len({im.crop((190,285,475,398)).tobytes() for im in frames}) >= 7
|
assert len({im.crop((190,285,475,398)).tobytes() for im in frames}) >= 7
|
||||||
question = frames[0].crop((18,400,620,444)).tobytes()
|
question = frames[0].crop((18,400,620,444)).tobytes()
|
||||||
assert all(im.crop((18,400,620,444)).tobytes() == question for im in frames)
|
assert all(im.crop((18,400,620,444)).tobytes() == question for im in frames)
|
||||||
|
fate_motion = [Image.open(OUT/f"fortune-fate-motion-{i:02}.bmp").convert("RGB")
|
||||||
|
for i in range(32)]
|
||||||
|
assert len({im.crop((134,32,414,323)).tobytes() for im in fate_motion}) >= 24
|
||||||
|
fate_motion[0].save(OUT/"fortune-fate-mist.gif", save_all=True,
|
||||||
|
append_images=fate_motion[1:], duration=32, loop=0)
|
||||||
|
fate_result = Image.open(OUT/"fortune-fate-result.bmp").convert("RGB")
|
||||||
|
fate_form = Image.open(OUT/"fortune-fate-form.bmp").convert("RGB")
|
||||||
|
assert fate_form.crop((16,298,624,446)).tobytes() != fate_result.crop((16,298,624,446)).tobytes()
|
||||||
|
# Difference captures isolate the actual numeral, independently of fog highlights.
|
||||||
|
tracking = (ROOT/"assets/sprites/fortune/orb-tracking-v1.json").read_text()
|
||||||
|
anchors = json.loads(tracking)["frames"]
|
||||||
|
tracked = []
|
||||||
|
for i, anchor in enumerate(anchors):
|
||||||
|
result = Image.open(OUT/f"fortune-fate-track-{i:02}.bmp").convert("RGB")
|
||||||
|
base = Image.open(OUT/f"fortune-fate-base-{i:02}.bmp").convert("RGB")
|
||||||
|
box = ImageChops.difference(result, base).getbbox()
|
||||||
|
assert box, (i, "no numeral rendered")
|
||||||
|
cx = 214 + int(anchor["cx"]*128/192 + .5)
|
||||||
|
cy = 195 + int(anchor["cy"]*128/192 + .5)
|
||||||
|
assert abs((box[0]+box[2])/2-cx) <= 2.5, (i, box, cx)
|
||||||
|
assert abs((box[1]+box[3])/2-cy) <= 2.5, (i, box, cy)
|
||||||
|
assert cx-42 <= box[0] < box[2] <= cx+42
|
||||||
|
assert cy-28 <= box[1] < box[3] <= cy+28
|
||||||
|
tracked.append(result)
|
||||||
|
assert max(a["cx"] for a in anchors)-min(a["cx"] for a in anchors) > 8
|
||||||
|
assert max(a["cy"] for a in anchors)-min(a["cy"] for a in anchors) > 8
|
||||||
|
tracked[0].save(OUT/"fortune-fate-tracked.gif", save_all=True,
|
||||||
|
append_images=tracked[1:], duration=64, loop=0)
|
||||||
|
numerals = (ROOT/"assets/animations/fortune/orb-numerals-v1.bin").read_bytes()
|
||||||
|
assert struct.unpack_from("<4s4I", numerals) == (b"ANM1", 32, 48, 10, 32*48*10*4)
|
||||||
|
assert len(set(numerals[23::4])) > 50, "font must retain soft edges and glow alpha"
|
||||||
for name in ("room","shuffle","deal","gesture","orb-hands","orb-mist","cards"):
|
for name in ("room","shuffle","deal","gesture","orb-hands","orb-mist","cards"):
|
||||||
path = ROOT/f"assets/animations/fortune/{name}-v1.bin"
|
path = ROOT/f"assets/animations/fortune/{name}-v1.bin"
|
||||||
data = path.read_bytes()
|
data = path.read_bytes()
|
||||||
|
|
@ -270,8 +378,35 @@ def main():
|
||||||
assert dominant < 0.5,"stair entrance must show textured continuation on both sides, not a solid rear-wall block"
|
assert dominant < 0.5,"stair entrance must show textured continuation on both sides, not a solid rear-wall block"
|
||||||
for path in OUT.glob("*.bmp"):
|
for path in OUT.glob("*.bmp"):
|
||||||
image = Image.open(path).convert("RGB")
|
image = Image.open(path).convert("RGB")
|
||||||
assert image.size == (640,480) and len(image.getcolors(640*480)) > 100
|
expected = (1280,960) if path.name.startswith("roof-hd-") else (640,480)
|
||||||
|
assert image.size == expected and len(image.getcolors(image.width*image.height)) > 100
|
||||||
image.save(path.with_suffix(".png"))
|
image.save(path.with_suffix(".png"))
|
||||||
|
hd_day = Image.open(OUT/"roof-hd-south.bmp").convert("RGB")
|
||||||
|
hd_night = Image.open(OUT/"roof-hd-night.bmp").convert("RGB")
|
||||||
|
assert ImageChops.difference(hd_day,hd_night).getbbox(), "day/night must change actual native geometry lighting"
|
||||||
|
white_ground = sum(1 for rgb in hd_night.crop((0,650,1280,960)).get_flattened_data() if min(rgb) > 235)
|
||||||
|
assert white_ground < 500, "uninitialised emission textures must not turn ground white"
|
||||||
|
traffic = Image.open(OUT/"roof-hd-traffic.bmp").convert("RGB")
|
||||||
|
east = Image.open(OUT/"roof-hd-east.bmp").convert("RGB")
|
||||||
|
assert ImageChops.difference(east,traffic).getbbox(), "native clock must move city vehicles"
|
||||||
|
left = Image.open(OUT/"roof-hd-look-left.bmp").convert("RGB")
|
||||||
|
right = Image.open(OUT/"roof-hd-look-right.bmp").convert("RGB")
|
||||||
|
assert left.tobytes() != east.tobytes() != right.tobytes(), "leaning must allow actual head turns"
|
||||||
|
mesh = json.loads((ROOT/"assets/sprites/rooftop/mesh-v1.json").read_text())
|
||||||
|
assert mesh["triangles"]["scene"] < 36000, "never-visible static faces must be pruned"
|
||||||
|
for profile in ("eco", "auto"):
|
||||||
|
low = Image.open(OUT/f"roof-hd-{profile}.bmp").convert("RGB")
|
||||||
|
difference = ImageStat.Stat(ImageChops.difference(low, east)).mean
|
||||||
|
assert max(difference) < 12, (profile, "quality must not remove scene geometry", difference)
|
||||||
|
roads = mesh["road_rectangles"]
|
||||||
|
for i,(a,b,c,d) in enumerate(roads):
|
||||||
|
for x0,x1,y0,y1 in roads[i+1:]:
|
||||||
|
assert min(b,x1)-max(a,x0) < 1e-6 or min(d,y1)-max(c,y0) < 1e-6, "coplanar street overlap"
|
||||||
|
millis,frames,cpu,gpu,present = struct.unpack("<5I",(OUT/"roof-hd-timing.bin").read_bytes())
|
||||||
|
print(f"Roof passes ms/frame: CPU {cpu/frames:.2f}, GPU/readback {gpu/frames:.2f}, composite {present/frames:.2f}")
|
||||||
|
print(f"PASS: non-overlapping roads, head turns with anchored hands, final offscreen composite; {millis/frames:.2f} ms/frame in 24-frame native roof probe")
|
||||||
|
print("PASS: native GL city at 640/960/1280, auto downgrade and F8, direct foreground composite")
|
||||||
|
print("PASS: sunset/night, animated traffic, software roads/water even with missing city textures")
|
||||||
gait = [Image.open(OUT/f"gait-{i}.bmp").convert("RGB") for i in range(8)]
|
gait = [Image.open(OUT/f"gait-{i}.bmp").convert("RGB") for i in range(8)]
|
||||||
assert len({frame.crop((245,360,410,480)).tobytes() for frame in gait}) == 8, "legs must visibly change in native renders"
|
assert len({frame.crop((245,360,410,480)).tobytes() for frame in gait}) == 8, "legs must visibly change in native renders"
|
||||||
gait[0].save(OUT/"gait-native.gif",save_all=True,append_images=gait[1:],duration=110,loop=0)
|
gait[0].save(OUT/"gait-native.gif",save_all=True,append_images=gait[1:],duration=110,loop=0)
|
||||||
|
|
|
||||||
|
|
@ -64,11 +64,11 @@ def test_code_structure():
|
||||||
|
|
||||||
# Check constants
|
# Check constants
|
||||||
assert "MODE_JACKBOX equ 28" in data_inc
|
assert "MODE_JACKBOX equ 28" in data_inc
|
||||||
assert "INTERACT_JACKBOX equ 48" in data_inc
|
assert "INTERACT_JACKBOX equ 52" in data_inc
|
||||||
assert "JACKBOX_X equ FP_1*306/10" in data_inc
|
assert "JACKBOX_X equ FP_1*306/10" in data_inc
|
||||||
assert "JACKBOX_Y equ FP_1*235/10" in data_inc
|
assert "JACKBOX_Y equ FP_1*235/10" in data_inc
|
||||||
assert "MATERIAL_JACKBOX_SIDE equ 121" in data_inc
|
assert "MATERIAL_JACKBOX_SIDE equ 121" in data_inc
|
||||||
assert "MATERIAL_JACKBOX_BACK equ 163" in data_inc
|
assert "MATERIAL_JACKBOX_BACK equ 213" in data_inc
|
||||||
|
|
||||||
# Check procs
|
# Check procs
|
||||||
procs = [
|
procs = [
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,51 @@ dtVectorCount3D equ 67
|
||||||
dtTestTriples3D dd 0
|
dtTestTriples3D dd 0
|
||||||
dtTestMetricPath db "build\darts\aim-metrics.bin",0
|
dtTestMetricPath db "build\darts\aim-metrics.bin",0
|
||||||
.code
|
.code
|
||||||
|
DartsTestReticle PROC uses ebx esi edi
|
||||||
|
mov edi,OFFSET screenBuffer
|
||||||
|
mov ecx,640*480
|
||||||
|
mov eax,00E0E0E0h
|
||||||
|
rep stosd
|
||||||
|
invoke DrawDartsReticle3D,320,214
|
||||||
|
mov esi,OFFSET screenBuffer
|
||||||
|
mov ecx,640*480
|
||||||
|
xor ebx,ebx
|
||||||
|
dt_test_reticle_light:
|
||||||
|
lodsd
|
||||||
|
cmp eax,00E0E0E0h
|
||||||
|
je @F
|
||||||
|
cmp eax,00152021h
|
||||||
|
jne dt_test_reticle_fail
|
||||||
|
inc ebx
|
||||||
|
@@:
|
||||||
|
loop dt_test_reticle_light
|
||||||
|
cmp ebx,9
|
||||||
|
jne dt_test_reticle_fail
|
||||||
|
mov edi,OFFSET screenBuffer
|
||||||
|
mov ecx,640*480
|
||||||
|
mov eax,00101010h
|
||||||
|
rep stosd
|
||||||
|
invoke DrawDartsReticle3D,0,32
|
||||||
|
mov esi,OFFSET screenBuffer
|
||||||
|
mov ecx,640*480
|
||||||
|
xor ebx,ebx
|
||||||
|
dt_test_reticle_dark:
|
||||||
|
lodsd
|
||||||
|
cmp eax,00101010h
|
||||||
|
je @F
|
||||||
|
cmp eax,00F6E6ADh
|
||||||
|
jne dt_test_reticle_fail
|
||||||
|
inc ebx
|
||||||
|
@@:
|
||||||
|
loop dt_test_reticle_dark
|
||||||
|
cmp ebx,5
|
||||||
|
jne dt_test_reticle_fail
|
||||||
|
ret
|
||||||
|
dt_test_reticle_fail:
|
||||||
|
invoke ExitProcess,8506
|
||||||
|
ret
|
||||||
|
DartsTestReticle ENDP
|
||||||
|
|
||||||
DartsTestWriteMetrics PROC uses ebx
|
DartsTestWriteMetrics PROC uses ebx
|
||||||
local written:DWORD
|
local written:DWORD
|
||||||
invoke CreateFileA,OFFSET dtTestMetricPath,40000000h,0,0,2,80h,0
|
invoke CreateFileA,OFFSET dtTestMetricPath,40000000h,0,0,2,80h,0
|
||||||
|
|
@ -88,6 +133,7 @@ DartsTestWriteMetrics ENDP
|
||||||
DartsTestStart PROC uses ebx esi edi
|
DartsTestStart PROC uses ebx esi edi
|
||||||
local legs:DWORD
|
local legs:DWORD
|
||||||
call InitPaths3D
|
call InitPaths3D
|
||||||
|
call DartsTestReticle
|
||||||
lea esi,dtVectors3D
|
lea esi,dtVectors3D
|
||||||
mov ebx,dtVectorCount3D
|
mov ebx,dtVectorCount3D
|
||||||
dt_test_vector:
|
dt_test_vector:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,18 @@
|
||||||
.data
|
.data
|
||||||
fortuneSessionBank dd 0
|
fortuneSessionBank dd 0
|
||||||
fortuneSessionPlayer dd 0
|
fortuneSessionPlayer dd 0
|
||||||
|
fortuneFateSavedResult dd 0
|
||||||
|
fortuneFateSavedSeed dd 0
|
||||||
|
fortuneFateTestText db "Ivan",0,"Petrov",0,"29022000",0,"IS-42",0
|
||||||
|
fortuneFateFormShot db "build\hall-expansion\fortune-fate-form.bmp",0
|
||||||
|
fortuneFateResultShot db "build\hall-expansion\fortune-fate-result.bmp",0
|
||||||
|
fortuneFateHundredShot db "build\hall-expansion\fortune-fate-hundred.bmp",0
|
||||||
|
fortuneFateMotion db "build\hall-expansion\fortune-fate-motion-"
|
||||||
|
fortuneFateDigits db "00.bmp",0
|
||||||
|
fortuneFateTracking db "build\hall-expansion\fortune-fate-track-"
|
||||||
|
fortuneFateTrackingDigits db "00.bmp",0
|
||||||
|
fortuneFateTrackingBase db "build\hall-expansion\fortune-fate-base-"
|
||||||
|
fortuneFateTrackingBaseDigits db "00.bmp",0
|
||||||
fortuneSessionMotion db "build\hall-expansion\fortune-session-motion-"
|
fortuneSessionMotion db "build\hall-expansion\fortune-session-motion-"
|
||||||
fortuneSessionDigits db "00.bmp",0
|
fortuneSessionDigits db "00.bmp",0
|
||||||
fortuneSessionQuestion db 193,243,228,229,242,32,235,232,32,231,224,226,242,240,224,32,228,238,230,228,252,63,0
|
fortuneSessionQuestion db 193,243,228,229,242,32,235,232,32,231,224,226,242,240,224,32,228,238,230,228,252,63,0
|
||||||
|
|
@ -43,6 +55,8 @@ FortuneDialogNativeTests PROC uses ebx esi edi
|
||||||
jne fortune_session_fail
|
jne fortune_session_fail
|
||||||
cmp fortuneSessionCards3D.frames,45
|
cmp fortuneSessionCards3D.frames,45
|
||||||
jne fortune_session_fail
|
jne fortune_session_fail
|
||||||
|
cmp fortuneSessionNumerals3D.frames,10
|
||||||
|
jne fortune_session_fail
|
||||||
cmp fortuneProcess3D,0
|
cmp fortuneProcess3D,0
|
||||||
jne fortune_session_fail
|
jne fortune_session_fail
|
||||||
cmp fortuneRead3D,0
|
cmp fortuneRead3D,0
|
||||||
|
|
@ -181,7 +195,7 @@ fortune_session_unique_next:
|
||||||
ja fortune_session_fail
|
ja fortune_session_fail
|
||||||
cmp fortuneSpeechHeight3D,140
|
cmp fortuneSpeechHeight3D,140
|
||||||
ja fortune_session_fail
|
ja fortune_session_fail
|
||||||
; Return to selection, then display the neutral, non-grading orb sequence.
|
; The fictional crystal-ball lottery requires a form, not a neural worker.
|
||||||
mov mouseX3D,200
|
mov mouseX3D,200
|
||||||
mov mouseY3D,232
|
mov mouseY3D,232
|
||||||
mov mouseClick3D,1
|
mov mouseClick3D,1
|
||||||
|
|
@ -191,6 +205,126 @@ fortune_session_unique_next:
|
||||||
invoke WindowEvents3D,0,102h,'2',0
|
invoke WindowEvents3D,0,102h,'2',0
|
||||||
cmp fortuneSubMode3D,FORTUNE_SUBMODE_ORB
|
cmp fortuneSubMode3D,FORTUNE_SUBMODE_ORB
|
||||||
jne fortune_session_fail
|
jne fortune_session_fail
|
||||||
|
cmp fortunePhase3D,0
|
||||||
|
jne fortune_session_fail
|
||||||
|
call SubmitFortuneFate3D
|
||||||
|
cmp fortunePhase3D,0
|
||||||
|
jne fortune_session_fail
|
||||||
|
cmp fortuneFateField3D,0
|
||||||
|
jne fortune_session_fail
|
||||||
|
; CP1251, control filtering and maximum field widths use the real input path.
|
||||||
|
mov ebx,40
|
||||||
|
fortune_fate_name_limit:
|
||||||
|
invoke WindowEvents3D,0,102h,200,0
|
||||||
|
dec ebx
|
||||||
|
jnz fortune_fate_name_limit
|
||||||
|
cmp fortuneFateLengths3D,30
|
||||||
|
jne fortune_session_fail
|
||||||
|
cmp fortuneFateFields3D[30],0
|
||||||
|
jne fortune_session_fail
|
||||||
|
invoke FortuneChar3D,127
|
||||||
|
cmp fortuneFateLengths3D,30
|
||||||
|
jne fortune_session_fail
|
||||||
|
call ResetFortuneFate3D
|
||||||
|
mov esi,OFFSET fortuneFateTestText
|
||||||
|
xor ebx,ebx
|
||||||
|
fortune_fate_input_fields:
|
||||||
|
movzx eax,BYTE PTR [esi]
|
||||||
|
inc esi
|
||||||
|
test eax,eax
|
||||||
|
jz fortune_fate_input_next
|
||||||
|
invoke WindowEvents3D,0,102h,eax,0
|
||||||
|
jmp fortune_fate_input_fields
|
||||||
|
fortune_fate_input_next:
|
||||||
|
invoke WindowEvents3D,0,102h,9,0
|
||||||
|
inc ebx
|
||||||
|
cmp ebx,4
|
||||||
|
jb fortune_fate_input_fields
|
||||||
|
cmp fortuneFateLengths3D[8],10
|
||||||
|
jne fortune_session_fail
|
||||||
|
call ValidateFortuneBirth3D
|
||||||
|
cmp eax,1
|
||||||
|
jne fortune_session_fail
|
||||||
|
mov fortuneFateFields3D[137],'1'
|
||||||
|
call ValidateFortuneBirth3D
|
||||||
|
test eax,eax
|
||||||
|
jnz fortune_session_fail
|
||||||
|
call SubmitFortuneFate3D
|
||||||
|
cmp fortuneFateField3D,2
|
||||||
|
jne fortune_session_fail
|
||||||
|
cmp fortunePhase3D,0
|
||||||
|
jne fortune_session_fail
|
||||||
|
mov fortuneFateFields3D[137],'0'
|
||||||
|
mov fortuneFateField3D,4
|
||||||
|
invoke FortuneChar3D,'x'
|
||||||
|
cmp fortuneFateLengths3D[16],1
|
||||||
|
jne fortune_session_fail
|
||||||
|
; A value larger than 100 is rejected, not clamped or used as an outcome.
|
||||||
|
mov fortuneFateFields3D[320],'1'
|
||||||
|
mov fortuneFateFields3D[321],'0'
|
||||||
|
mov fortuneFateFields3D[322],'1'
|
||||||
|
mov fortuneFateLengths3D[20],3
|
||||||
|
call SubmitFortuneFate3D
|
||||||
|
cmp fortunePhase3D,0
|
||||||
|
jne fortune_session_fail
|
||||||
|
mov fortuneFateFields3D[320],'8'
|
||||||
|
mov fortuneFateFields3D[321],0
|
||||||
|
mov fortuneFateFields3D[322],0
|
||||||
|
mov fortuneFateLengths3D[20],1
|
||||||
|
call SubmitFortuneFate3D
|
||||||
|
cmp fortunePhase3D,0
|
||||||
|
jne fortune_session_fail
|
||||||
|
cmp fortuneFateField3D,5
|
||||||
|
jne fortune_session_fail
|
||||||
|
mov fortuneFateFields3D[320],'1'
|
||||||
|
mov fortuneFateFields3D[321],'0'
|
||||||
|
mov fortuneFateLengths3D[20],2
|
||||||
|
invoke SetFortuneSpeech3D,OFFSET fortuneFateReady3D
|
||||||
|
mov fortuneSpeechTime3D,3000
|
||||||
|
call RenderFortuneDialog3D
|
||||||
|
invoke ExpansionSnapshot,OFFSET fortuneFateFormShot
|
||||||
|
; Mouse focus and backspace obey per-field limits and reject control bytes.
|
||||||
|
mov mouseX3D,200
|
||||||
|
mov mouseY3D,168
|
||||||
|
mov mouseClick3D,1
|
||||||
|
call HandleFortuneDialog3D
|
||||||
|
cmp fortuneFateField3D,1
|
||||||
|
jne fortune_session_fail
|
||||||
|
invoke FortuneChar3D,8
|
||||||
|
cmp fortuneFateLengths3D[4],5
|
||||||
|
jne fortune_session_fail
|
||||||
|
invoke FortuneChar3D,'v'
|
||||||
|
invoke WindowEvents3D,0,100h,0Dh,0
|
||||||
|
invoke WindowEvents3D,0,102h,0Dh,0
|
||||||
|
call HandleFortuneDialog3D
|
||||||
|
invoke WindowEvents3D,0,101h,0Dh,0
|
||||||
|
cmp fortunePhase3D,1
|
||||||
|
jne fortune_session_fail
|
||||||
|
mov eax,fortuneFateResult3D
|
||||||
|
cmp eax,9
|
||||||
|
jb fortune_session_fail
|
||||||
|
cmp eax,10
|
||||||
|
ja fortune_session_fail
|
||||||
|
mov fortuneFateSavedResult,eax
|
||||||
|
mov eax,rngSeed3D
|
||||||
|
mov fortuneFateSavedSeed,eax
|
||||||
|
call SubmitFortuneFate3D
|
||||||
|
invoke FortuneChar3D,'X'
|
||||||
|
cmp fortuneFateLengths3D[4],6
|
||||||
|
jne fortune_session_fail
|
||||||
|
mov eax,fortuneFateSavedResult
|
||||||
|
cmp fortuneFateResult3D,eax
|
||||||
|
jne fortune_session_fail
|
||||||
|
mov eax,rngSeed3D
|
||||||
|
cmp eax,fortuneFateSavedSeed
|
||||||
|
jne fortune_session_fail
|
||||||
|
; Again cannot bypass the ritual or reroll while hands are moving.
|
||||||
|
mov mouseX3D,120
|
||||||
|
mov mouseY3D,232
|
||||||
|
mov mouseClick3D,1
|
||||||
|
call HandleFortuneDialog3D
|
||||||
|
cmp fortunePhase3D,1
|
||||||
|
jne fortune_session_fail
|
||||||
mov fortunePhaseTime3D,700
|
mov fortunePhaseTime3D,700
|
||||||
call RenderFortuneDialog3D
|
call RenderFortuneDialog3D
|
||||||
invoke ExpansionSnapshot,OFFSET fortuneSessionShot13
|
invoke ExpansionSnapshot,OFFSET fortuneSessionShot13
|
||||||
|
|
@ -202,6 +336,27 @@ fortune_session_unique_next:
|
||||||
mov fortuneSpeechTime3D,3000
|
mov fortuneSpeechTime3D,3000
|
||||||
call RenderFortuneDialog3D
|
call RenderFortuneDialog3D
|
||||||
invoke ExpansionSnapshot,OFFSET fortuneSessionShot14
|
invoke ExpansionSnapshot,OFFSET fortuneSessionShot14
|
||||||
|
xor edi,edi
|
||||||
|
fortune_fate_motion:
|
||||||
|
mov eax,edi
|
||||||
|
xor edx,edx
|
||||||
|
mov ecx,10
|
||||||
|
div ecx
|
||||||
|
add al,'0'
|
||||||
|
add dl,'0'
|
||||||
|
mov fortuneFateDigits[0],al
|
||||||
|
mov fortuneFateDigits[1],dl
|
||||||
|
mov eax,edi
|
||||||
|
imul eax,32
|
||||||
|
mov fortunePhaseTime3D,eax
|
||||||
|
call RenderFortuneDialog3D
|
||||||
|
invoke ExpansionSnapshot,OFFSET fortuneFateMotion
|
||||||
|
mov eax,fortuneFateSavedResult
|
||||||
|
cmp fortuneFateResult3D,eax
|
||||||
|
jne fortune_session_fail
|
||||||
|
inc edi
|
||||||
|
cmp edi,32
|
||||||
|
jb fortune_fate_motion
|
||||||
mov fortunePhaseTime3D,5000
|
mov fortunePhaseTime3D,5000
|
||||||
call FortuneSessionStepTest
|
call FortuneSessionStepTest
|
||||||
cmp fortunePhase3D,3
|
cmp fortunePhase3D,3
|
||||||
|
|
@ -209,6 +364,102 @@ fortune_session_unique_next:
|
||||||
mov fortuneSpeechTime3D,3000
|
mov fortuneSpeechTime3D,3000
|
||||||
call RenderFortuneDialog3D
|
call RenderFortuneDialog3D
|
||||||
invoke ExpansionSnapshot,OFFSET fortuneSessionShot15
|
invoke ExpansionSnapshot,OFFSET fortuneSessionShot15
|
||||||
|
mov fortunePhaseTime3D,1200
|
||||||
|
call RenderFortuneDialog3D
|
||||||
|
invoke ExpansionSnapshot,OFFSET fortuneFateResultShot
|
||||||
|
xor edi,edi
|
||||||
|
fortune_fate_tracking_frames:
|
||||||
|
mov eax,edi
|
||||||
|
xor edx,edx
|
||||||
|
mov ecx,10
|
||||||
|
div ecx
|
||||||
|
add al,'0'
|
||||||
|
add dl,'0'
|
||||||
|
mov fortuneFateTrackingDigits[0],al
|
||||||
|
mov fortuneFateTrackingDigits[1],dl
|
||||||
|
mov fortuneFateTrackingBaseDigits[0],al
|
||||||
|
mov fortuneFateTrackingBaseDigits[1],dl
|
||||||
|
mov eax,edi
|
||||||
|
shl eax,6
|
||||||
|
add eax,2048
|
||||||
|
mov fortunePhaseTime3D,eax
|
||||||
|
call RenderFortuneDialog3D
|
||||||
|
cmp fortuneOrbFrame3D,edi
|
||||||
|
jne fortune_session_fail
|
||||||
|
mov eax,fortuneOrbAnchorX3D[edi*4]
|
||||||
|
add eax,128
|
||||||
|
shr eax,8
|
||||||
|
add eax,214
|
||||||
|
cmp fortuneOrbCenterX3D,eax
|
||||||
|
jne fortune_session_fail
|
||||||
|
mov eax,fortuneOrbAnchorY3D[edi*4]
|
||||||
|
add eax,128
|
||||||
|
shr eax,8
|
||||||
|
add eax,195
|
||||||
|
cmp fortuneOrbCenterY3D,eax
|
||||||
|
jne fortune_session_fail
|
||||||
|
cmp animOpacity3D,255
|
||||||
|
jne fortune_session_fail
|
||||||
|
invoke ExpansionSnapshot,OFFSET fortuneFateTracking
|
||||||
|
mov fortuneFateResult3D,-1
|
||||||
|
call RenderFortuneDialog3D
|
||||||
|
invoke ExpansionSnapshot,OFFSET fortuneFateTrackingBase
|
||||||
|
mov eax,fortuneFateSavedResult
|
||||||
|
mov fortuneFateResult3D,eax
|
||||||
|
inc edi
|
||||||
|
cmp edi,16
|
||||||
|
jb fortune_fate_tracking_frames
|
||||||
|
mov mouseX3D,120
|
||||||
|
mov mouseY3D,232
|
||||||
|
mov mouseClick3D,1
|
||||||
|
call HandleFortuneDialog3D
|
||||||
|
cmp fortunePhase3D,0
|
||||||
|
jne fortune_session_fail
|
||||||
|
cmp fortuneFateResult3D,-1
|
||||||
|
jne fortune_session_fail
|
||||||
|
cmp fortuneFateLengths3D[4],6
|
||||||
|
jne fortune_session_fail
|
||||||
|
; Test the full inclusive range, zero, fixed outcomes and both endpoints.
|
||||||
|
mov ebx,400
|
||||||
|
fortune_fate_range_samples:
|
||||||
|
mov fortunePhase3D,0
|
||||||
|
mov fortuneFateFields3D[256],'0'
|
||||||
|
mov fortuneFateLengths3D[16],1
|
||||||
|
mov fortuneFateFields3D[320],'1'
|
||||||
|
mov fortuneFateFields3D[321],'0'
|
||||||
|
mov fortuneFateFields3D[322],'0'
|
||||||
|
mov fortuneFateFields3D[323],0
|
||||||
|
mov fortuneFateLengths3D[20],3
|
||||||
|
call SubmitFortuneFate3D
|
||||||
|
cmp fortuneFateResult3D,100
|
||||||
|
ja fortune_session_fail
|
||||||
|
dec ebx
|
||||||
|
jnz fortune_fate_range_samples
|
||||||
|
; Endpoints are checked separately without relying on a random sample.
|
||||||
|
mov fortunePhase3D,0
|
||||||
|
mov fortuneFateFields3D[256],'0'
|
||||||
|
mov fortuneFateFields3D[320],'0'
|
||||||
|
mov fortuneFateFields3D[321],0
|
||||||
|
mov fortuneFateLengths3D[20],1
|
||||||
|
call SubmitFortuneFate3D
|
||||||
|
cmp fortuneFateResult3D,0
|
||||||
|
jne fortune_session_fail
|
||||||
|
mov fortunePhase3D,0
|
||||||
|
mov fortuneFateFields3D[256],'1'
|
||||||
|
mov fortuneFateFields3D[257],'0'
|
||||||
|
mov fortuneFateFields3D[258],'0'
|
||||||
|
mov fortuneFateLengths3D[16],3
|
||||||
|
mov fortuneFateFields3D[320],'1'
|
||||||
|
mov fortuneFateFields3D[321],'0'
|
||||||
|
mov fortuneFateFields3D[322],'0'
|
||||||
|
mov fortuneFateLengths3D[20],3
|
||||||
|
call SubmitFortuneFate3D
|
||||||
|
cmp fortuneFateResult3D,100
|
||||||
|
jne fortune_session_fail
|
||||||
|
mov fortunePhase3D,3
|
||||||
|
mov fortunePhaseTime3D,1200
|
||||||
|
call RenderFortuneDialog3D
|
||||||
|
invoke ExpansionSnapshot,OFFSET fortuneFateHundredShot
|
||||||
; Exit in the middle of an animation as well as after completion.
|
; Exit in the middle of an animation as well as after completion.
|
||||||
mov mouseX3D,260
|
mov mouseX3D,260
|
||||||
mov mouseY3D,232
|
mov mouseY3D,232
|
||||||
|
|
@ -218,6 +469,12 @@ fortune_session_unique_next:
|
||||||
jne fortune_session_fail
|
jne fortune_session_fail
|
||||||
cmp fortuneSessionRoom3D.pixels,0
|
cmp fortuneSessionRoom3D.pixels,0
|
||||||
jne fortune_session_fail
|
jne fortune_session_fail
|
||||||
|
cmp fortuneSessionNumerals3D.pixels,0
|
||||||
|
jne fortune_session_fail
|
||||||
|
cmp fortuneFateLengths3D,0
|
||||||
|
jne fortune_session_fail
|
||||||
|
cmp fortuneFateFields3D,0
|
||||||
|
jne fortune_session_fail
|
||||||
call BeginFortuneDialog3D
|
call BeginFortuneDialog3D
|
||||||
invoke FortuneChar3D,'1'
|
invoke FortuneChar3D,'1'
|
||||||
invoke FortuneChar3D,'a'
|
invoke FortuneChar3D,'a'
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
RoofTestCrashFilter PROTO :DWORD
|
||||||
.data
|
.data
|
||||||
expansionStage dd 1
|
expansionStage dd 1
|
||||||
expansionOcclusionPixel dd 0
|
expansionOcclusionPixel dd 0
|
||||||
|
|
@ -91,10 +92,13 @@ ExpansionSnapshot ENDP
|
||||||
|
|
||||||
ExpansionFrame PROC
|
ExpansionFrame PROC
|
||||||
call UpdateCamera3D
|
call UpdateCamera3D
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
je expansion_world_ready
|
||||||
call RenderCeilingAndFloor
|
call RenderCeilingAndFloor
|
||||||
call RenderWalls
|
call RenderWalls
|
||||||
call PrepareCityDepth3D
|
call PrepareCityDepth3D
|
||||||
call RenderSprites
|
call RenderSprites
|
||||||
|
expansion_world_ready:
|
||||||
call RenderHall3D
|
call RenderHall3D
|
||||||
ret
|
ret
|
||||||
ExpansionFrame ENDP
|
ExpansionFrame ENDP
|
||||||
|
|
@ -130,6 +134,7 @@ expansion_door_tick:
|
||||||
ExpansionDoorTicks ENDP
|
ExpansionDoorTicks ENDP
|
||||||
|
|
||||||
ExpansionTestStart PROC
|
ExpansionTestStart PROC
|
||||||
|
invoke SetUnhandledExceptionFilter,OFFSET RoofTestCrashFilter
|
||||||
call InitPaths3D
|
call InitPaths3D
|
||||||
call LoadTextures3D
|
call LoadTextures3D
|
||||||
call InitializeCasinoSprites3D
|
call InitializeCasinoSprites3D
|
||||||
|
|
@ -1164,6 +1169,7 @@ expansion_leaf_shut:
|
||||||
call BarCameraNativeTests
|
call BarCameraNativeTests
|
||||||
call FortuneDialogNativeTests
|
call FortuneDialogNativeTests
|
||||||
call ExpansionDartsTests
|
call ExpansionDartsTests
|
||||||
|
call RoofNativeTests
|
||||||
invoke ExitProcess,0
|
invoke ExitProcess,0
|
||||||
expansion_fail:
|
expansion_fail:
|
||||||
invoke ExitProcess,expansionStage
|
invoke ExitProcess,expansionStage
|
||||||
|
|
@ -1173,3 +1179,4 @@ include tools/tests/fortune_room_test.inc
|
||||||
include tools/tests/bar_camera_test.inc
|
include tools/tests/bar_camera_test.inc
|
||||||
include tools/tests/fortune_dialog_test.inc
|
include tools/tests/fortune_dialog_test.inc
|
||||||
include tools/tests/darts_hall_test.inc
|
include tools/tests/darts_hall_test.inc
|
||||||
|
include tools/tests/rooftop_test.inc
|
||||||
|
|
|
||||||
769
tools/tests/rooftop_test.inc
Normal file
|
|
@ -0,0 +1,769 @@
|
||||||
|
ROOF_NAV_W equ 70
|
||||||
|
ROOF_NAV_H equ 78
|
||||||
|
.data
|
||||||
|
roofTestHall db "build\hall-expansion\roof-lift-hall.bmp",0
|
||||||
|
roofTestOpening db "build\hall-expansion\roof-lift-opening.bmp",0
|
||||||
|
roofTestCabin db "build\hall-expansion\roof-lift-cabin.bmp",0
|
||||||
|
roofTestEntry db "build\hall-expansion\roof-arrival.bmp",0
|
||||||
|
roofTestSouth db "build\hall-expansion\roof-terrace.bmp",0
|
||||||
|
roofTestEast db "build\hall-expansion\roof-city-east.bmp",0
|
||||||
|
roofTestWest db "build\hall-expansion\roof-city-west.bmp",0
|
||||||
|
roofTestSeated db "build\hall-expansion\roof-seated.bmp",0
|
||||||
|
roofTestBar db "build\hall-expansion\roof-bar.bmp",0
|
||||||
|
roofTestMix db "build\hall-expansion\roof-bar-mixing.bmp",0
|
||||||
|
roofTestReturn db "build\hall-expansion\roof-return.bmp",0
|
||||||
|
roofTestChairSide db "build\hall-expansion\roof-chair-side.bmp",0
|
||||||
|
roofTestChairBack db "build\hall-expansion\roof-chair-back.bmp",0
|
||||||
|
roofTestPlanter db "build\hall-expansion\roof-planter.bmp",0
|
||||||
|
roofTestLean db "build\hall-expansion\roof-lean.bmp",0
|
||||||
|
roofTestNight db "build\hall-expansion\roof-night.bmp",0
|
||||||
|
roofTestHDEast db "build\hall-expansion\roof-hd-east.bmp",0
|
||||||
|
roofTestHDSouth db "build\hall-expansion\roof-hd-south.bmp",0
|
||||||
|
roofTestHDNight db "build\hall-expansion\roof-hd-night.bmp",0
|
||||||
|
roofTestHDComposite db "build\hall-expansion\roof-hd-terrace.bmp",0
|
||||||
|
roofTestHDMotion db "build\hall-expansion\roof-hd-traffic.bmp",0
|
||||||
|
roofTestHDLeft db "build\hall-expansion\roof-hd-look-left.bmp",0
|
||||||
|
roofTestHDRight db "build\hall-expansion\roof-hd-look-right.bmp",0
|
||||||
|
roofTestHDEco db "build\hall-expansion\roof-hd-eco.bmp",0
|
||||||
|
roofTestHDAuto db "build\hall-expansion\roof-hd-auto.bmp",0
|
||||||
|
roofTestSoftware db "build\hall-expansion\roof-software-ground.bmp",0
|
||||||
|
roofTestMissingArt db "build\hall-expansion\roof-missing-art-ground.bmp",0
|
||||||
|
roofTestHDTiming db "build\hall-expansion\roof-hd-timing.bin",0
|
||||||
|
roofTestDriver db "build\hall-expansion\roof-driver.txt",0
|
||||||
|
roofTestNewline db 13,10
|
||||||
|
roofTestHDMillis dd 0,24,0,0,0
|
||||||
|
roofTestHDBmp db 42h,4Dh
|
||||||
|
dd 54+ROOF_HD_W*ROOF_HD_H*4
|
||||||
|
dw 0,0
|
||||||
|
dd 54,40,ROOF_HD_W,-ROOF_HD_H
|
||||||
|
dw 1,32
|
||||||
|
dd 0,ROOF_HD_W*ROOF_HD_H*4,0,0,0,0
|
||||||
|
roofTestHDBMI dd 40,ROOF_HD_W,-ROOF_HD_H
|
||||||
|
dw 1,32
|
||||||
|
dd 0,ROOF_HD_W*ROOF_HD_H*4,0,0,0,0
|
||||||
|
roofTestHDDC dd 0
|
||||||
|
roofTestHDBitmap dd 0
|
||||||
|
roofTestHDPixels dd 0
|
||||||
|
roofTestHDOld dd 0
|
||||||
|
roofTestLeanMove db "build\hall-expansion\roof-lean-motion.bin",0
|
||||||
|
roofTestGuestX dd 0
|
||||||
|
roofTestFloorColor dd 0
|
||||||
|
roofTestBank dd 0
|
||||||
|
roofTestX dd 0
|
||||||
|
roofTestY dd 0
|
||||||
|
roofTestCrash db "build\hall-expansion\roof-crash.bin",0
|
||||||
|
roofTestNavPath db "build\hall-expansion\roof-navigation.bin",0
|
||||||
|
roofTestNavHeader dd ROOF_NAV_W,ROOF_NAV_H,FP_1*45/4,FP_1*5/4,FP_1/4,ROOF_SEAT_COUNT
|
||||||
|
.data?
|
||||||
|
roofTestWalkPixels db ROOF_NAV_W*ROOF_NAV_H dup(?)
|
||||||
|
.code
|
||||||
|
RoofTestHDSnapshot PROC uses ebx path:DWORD
|
||||||
|
local count:DWORD
|
||||||
|
call UpdateCamera3D
|
||||||
|
call RenderRoof3D
|
||||||
|
invoke PresentRoofHD3D,roofTestHDDC,0,0,ROOF_HD_W,ROOF_HD_H
|
||||||
|
test eax,eax
|
||||||
|
jz roof_test_hd_capture_failed
|
||||||
|
invoke GdiFlush
|
||||||
|
invoke CreateFileA,path,40000000h,0,0,2,80h,0
|
||||||
|
mov ebx,eax
|
||||||
|
invoke WriteFile,ebx,OFFSET roofTestHDBmp,54,ADDR count,0
|
||||||
|
invoke WriteFile,ebx,roofTestHDPixels,ROOF_HD_W*ROOF_HD_H*4,ADDR count,0
|
||||||
|
invoke CloseHandle,ebx
|
||||||
|
ret
|
||||||
|
roof_test_hd_capture_failed:
|
||||||
|
invoke ExitProcess,95
|
||||||
|
ret
|
||||||
|
RoofTestHDSnapshot ENDP
|
||||||
|
|
||||||
|
RoofTestHD PROC uses ebx esi
|
||||||
|
local started:DWORD,written:DWORD,driverPtr:DWORD,driverLen:DWORD
|
||||||
|
mov expansionStage,94
|
||||||
|
mov roofQualityMode3D,2
|
||||||
|
call InitRoofHD3D
|
||||||
|
test eax,eax
|
||||||
|
jnz roof_test_hd_ready
|
||||||
|
mov eax,roofHDStage3D
|
||||||
|
add eax,100
|
||||||
|
invoke ExitProcess,eax
|
||||||
|
roof_test_hd_ready:
|
||||||
|
invoke CreateFileA,OFFSET roofTestDriver,40000000h,0,0,2,80h,0
|
||||||
|
mov ebx,eax
|
||||||
|
mov esi,1F00h
|
||||||
|
roof_test_driver_string:
|
||||||
|
invoke glGetString,esi
|
||||||
|
mov driverPtr,eax
|
||||||
|
xor ecx,ecx
|
||||||
|
roof_test_driver_length:
|
||||||
|
cmp BYTE PTR [eax+ecx],0
|
||||||
|
je roof_test_driver_write
|
||||||
|
inc ecx
|
||||||
|
jmp roof_test_driver_length
|
||||||
|
roof_test_driver_write:
|
||||||
|
mov driverLen,ecx
|
||||||
|
invoke WriteFile,ebx,driverPtr,driverLen,ADDR written,0
|
||||||
|
invoke WriteFile,ebx,OFFSET roofTestNewline,2,ADDR written,0
|
||||||
|
inc esi
|
||||||
|
cmp esi,1F02h
|
||||||
|
jbe roof_test_driver_string
|
||||||
|
invoke CloseHandle,ebx
|
||||||
|
invoke CreateCompatibleDC,0
|
||||||
|
mov roofTestHDDC,eax
|
||||||
|
invoke CreateDIBSection,eax,OFFSET roofTestHDBMI,0,OFFSET roofTestHDPixels,0,0
|
||||||
|
mov roofTestHDBitmap,eax
|
||||||
|
invoke SelectObject,roofTestHDDC,eax
|
||||||
|
mov roofTestHDOld,eax
|
||||||
|
mov hallLevel3D,HALL_ROOF
|
||||||
|
mov engineMode,MODE_WALK
|
||||||
|
mov worldMap3D,OFFSET roofMap3D
|
||||||
|
mov floorTexture3D,ROOF_DECK
|
||||||
|
mov playerX,FP_1*275/10
|
||||||
|
mov playerY,10*FP_1
|
||||||
|
mov playerAngle,0
|
||||||
|
mov roofLean3D,2
|
||||||
|
mov roofLeanAngle3D,0
|
||||||
|
mov roofLeanTime3D,1100
|
||||||
|
mov roofNight3D,0
|
||||||
|
mov keys3D[41h],1
|
||||||
|
mov deltaTime3D,16
|
||||||
|
add animationClock3D,16
|
||||||
|
call UpdateRoof3D
|
||||||
|
cmp roofLean3D,2
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
cmp playerAngle,0
|
||||||
|
je roof_test_hd_failed
|
||||||
|
mov keys3D[41h],0
|
||||||
|
mov playerAngle,0
|
||||||
|
invoke RoofTestHDSnapshot,OFFSET roofTestHDEast
|
||||||
|
add animationClock3D,1600
|
||||||
|
invoke RoofTestHDSnapshot,OFFSET roofTestHDMotion
|
||||||
|
mov playerAngle,464
|
||||||
|
invoke RoofTestHDSnapshot,OFFSET roofTestHDLeft
|
||||||
|
cmp roofLean3D,2
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
cmp playerAngle,464
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
cmp roofHandsContactX3D,320
|
||||||
|
jle roof_test_hd_failed
|
||||||
|
mov playerAngle,48
|
||||||
|
invoke RoofTestHDSnapshot,OFFSET roofTestHDRight
|
||||||
|
cmp playerAngle,48
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
cmp roofHandsContactX3D,320
|
||||||
|
jge roof_test_hd_failed
|
||||||
|
mov playerAngle,180
|
||||||
|
call UpdateRoofLook3D
|
||||||
|
cmp playerAngle,104
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
call RenderRoof3D
|
||||||
|
invoke PresentRoofHD3D,roofTestHDDC,0,0,ROOF_HD_W,ROOF_HD_H
|
||||||
|
test eax,eax
|
||||||
|
jz roof_test_hd_failed
|
||||||
|
mov playerAngle,408
|
||||||
|
call RenderRoof3D
|
||||||
|
invoke PresentRoofHD3D,roofTestHDDC,0,0,ROOF_HD_W,ROOF_HD_H
|
||||||
|
test eax,eax
|
||||||
|
jz roof_test_hd_failed
|
||||||
|
mov roofLean3D,0
|
||||||
|
mov playerX,20*FP_1
|
||||||
|
mov playerY,20*FP_1
|
||||||
|
mov playerAngle,128
|
||||||
|
invoke RoofTestHDSnapshot,OFFSET roofTestHDSouth
|
||||||
|
mov roofNight3D,1
|
||||||
|
invoke RoofTestHDSnapshot,OFFSET roofTestHDNight
|
||||||
|
mov roofNight3D,0
|
||||||
|
mov playerX,20*FP_1
|
||||||
|
mov playerY,7*FP_1
|
||||||
|
invoke RoofTestHDSnapshot,OFFSET roofTestHDComposite
|
||||||
|
invoke GetTickCount
|
||||||
|
mov started,eax
|
||||||
|
mov esi,24
|
||||||
|
roof_test_hd_frame_time:
|
||||||
|
add animationClock3D,16
|
||||||
|
call RenderRoof3D
|
||||||
|
invoke PresentRoofHD3D,roofTestHDDC,0,0,ROOF_HD_W,ROOF_HD_H
|
||||||
|
test eax,eax
|
||||||
|
jz roof_test_hd_failed
|
||||||
|
dec esi
|
||||||
|
jnz roof_test_hd_frame_time
|
||||||
|
invoke GdiFlush
|
||||||
|
invoke GetTickCount
|
||||||
|
sub eax,started
|
||||||
|
mov roofTestHDMillis,eax
|
||||||
|
invoke GetTickCount
|
||||||
|
mov started,eax
|
||||||
|
mov esi,24
|
||||||
|
roof_test_cpu_only_time:
|
||||||
|
call RenderRoof3D
|
||||||
|
dec esi
|
||||||
|
jnz roof_test_cpu_only_time
|
||||||
|
invoke GetTickCount
|
||||||
|
sub eax,started
|
||||||
|
mov roofTestHDMillis[8],eax
|
||||||
|
invoke GetTickCount
|
||||||
|
mov started,eax
|
||||||
|
mov esi,24
|
||||||
|
roof_test_gpu_only_time:
|
||||||
|
add animationClock3D,33
|
||||||
|
call RenderRoofHD3D
|
||||||
|
dec esi
|
||||||
|
jnz roof_test_gpu_only_time
|
||||||
|
invoke GetTickCount
|
||||||
|
sub eax,started
|
||||||
|
mov roofTestHDMillis[12],eax
|
||||||
|
invoke GetTickCount
|
||||||
|
mov started,eax
|
||||||
|
mov esi,24
|
||||||
|
roof_test_present_only_time:
|
||||||
|
invoke PresentRoofHD3D,roofTestHDDC,0,0,ROOF_HD_W,ROOF_HD_H
|
||||||
|
dec esi
|
||||||
|
jnz roof_test_present_only_time
|
||||||
|
invoke GdiFlush
|
||||||
|
invoke GetTickCount
|
||||||
|
sub eax,started
|
||||||
|
mov roofTestHDMillis[16],eax
|
||||||
|
invoke CreateFileA,OFFSET roofTestHDTiming,40000000h,0,0,2,80h,0
|
||||||
|
mov ebx,eax
|
||||||
|
invoke WriteFile,ebx,OFFSET roofTestHDMillis,20,ADDR written,0
|
||||||
|
invoke CloseHandle,ebx
|
||||||
|
; Quality profiles retain the full scene and a correctly aligned foreground.
|
||||||
|
mov playerX,FP_1*275/10
|
||||||
|
mov playerY,10*FP_1
|
||||||
|
mov playerAngle,0
|
||||||
|
mov roofLean3D,2
|
||||||
|
mov roofLeanAngle3D,0
|
||||||
|
mov roofQualityMode3D,1
|
||||||
|
invoke RoofTestHDSnapshot,OFFSET roofTestHDEco
|
||||||
|
cmp roofRenderW3D,640
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
cmp roofRenderH3D,480
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
mov roofQualityMode3D,0
|
||||||
|
mov roofAutoWidth3D,960
|
||||||
|
invoke RoofTestHDSnapshot,OFFSET roofTestHDAuto
|
||||||
|
cmp roofRenderW3D,960
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
mov deltaTime3D,100
|
||||||
|
mov roofQualitySlow3D,0
|
||||||
|
mov esi,11
|
||||||
|
roof_test_auto_slow:
|
||||||
|
add animationClock3D,100
|
||||||
|
call UpdateRoofQuality3D
|
||||||
|
dec esi
|
||||||
|
jnz roof_test_auto_slow
|
||||||
|
cmp roofRenderW3D,640
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
call ClearKeys3D
|
||||||
|
invoke WindowEvents3D,0,100h,77h,0
|
||||||
|
add animationClock3D,16
|
||||||
|
call UpdateRoofQuality3D
|
||||||
|
cmp roofQualityMode3D,1
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
call ClearKeys3D
|
||||||
|
invoke WindowEvents3D,0,100h,77h,0
|
||||||
|
add animationClock3D,16
|
||||||
|
call UpdateRoofQuality3D
|
||||||
|
cmp roofQualityMode3D,2
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
cmp roofRenderW3D,1280
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
call ClearKeys3D
|
||||||
|
mov roofLean3D,0
|
||||||
|
invoke SelectObject,roofTestHDDC,roofTestHDOld
|
||||||
|
invoke DeleteObject,roofTestHDBitmap
|
||||||
|
invoke DeleteDC,roofTestHDDC
|
||||||
|
call FreeRoofHD3D
|
||||||
|
cmp roofHDWindow3D,0
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
cmp roofHDBuffer3D,0
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
cmp roofHDRC3D,0
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
cmp roofHDMeshScene3D[12],0
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
cmp roofHDFinalDC3D,0
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
cmp roofHDFinalBmp3D,0
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
; Capability failure must return to software, without repeatedly opening contexts.
|
||||||
|
mov roofHDReady3D,-1
|
||||||
|
invoke PresentRoofHD3D,0,0,0,1280,960
|
||||||
|
test eax,eax
|
||||||
|
jnz roof_test_hd_failed
|
||||||
|
cmp roofHDReady3D,-1
|
||||||
|
jne roof_test_hd_failed
|
||||||
|
; Software roads and water remain visible even if the city pack is missing.
|
||||||
|
mov deltaTime3D,16
|
||||||
|
mov roofQualityMode3D,0
|
||||||
|
mov roofAutoWidth3D,960
|
||||||
|
call UpdateCamera3D
|
||||||
|
call RenderRoof3D
|
||||||
|
cmp roofGroundRoadPixels3D,0
|
||||||
|
je roof_test_hd_failed
|
||||||
|
cmp roofGroundWaterPixels3D,0
|
||||||
|
je roof_test_hd_failed
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestSoftware
|
||||||
|
mov eax,roofCityArt3D.pixels
|
||||||
|
push eax
|
||||||
|
mov roofCityArt3D.pixels,0
|
||||||
|
call RenderRoof3D
|
||||||
|
cmp roofGroundRoadPixels3D,0
|
||||||
|
je roof_test_hd_failed
|
||||||
|
cmp roofGroundWaterPixels3D,0
|
||||||
|
je roof_test_hd_failed
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestMissingArt
|
||||||
|
pop eax
|
||||||
|
mov roofCityArt3D.pixels,eax
|
||||||
|
mov roofHDReady3D,0
|
||||||
|
ret
|
||||||
|
roof_test_hd_failed:
|
||||||
|
invoke ExitProcess,94
|
||||||
|
ret
|
||||||
|
RoofTestHD ENDP
|
||||||
|
|
||||||
|
RoofTestNavigation PROC uses ebx esi edi
|
||||||
|
local px:DWORD,py:DWORD,written:DWORD
|
||||||
|
lea edi,roofTestWalkPixels
|
||||||
|
xor esi,esi
|
||||||
|
roof_test_nav_row:
|
||||||
|
mov eax,esi
|
||||||
|
imul eax,FP_1/4
|
||||||
|
add eax,FP_1*5/4
|
||||||
|
mov py,eax
|
||||||
|
xor ebx,ebx
|
||||||
|
roof_test_nav_column:
|
||||||
|
mov eax,ebx
|
||||||
|
imul eax,FP_1/4
|
||||||
|
add eax,FP_1*45/4
|
||||||
|
mov px,eax
|
||||||
|
invoke CanWalk3D,px,py
|
||||||
|
mov [edi],al
|
||||||
|
inc edi
|
||||||
|
inc ebx
|
||||||
|
cmp ebx,ROOF_NAV_W
|
||||||
|
jb roof_test_nav_column
|
||||||
|
inc esi
|
||||||
|
cmp esi,ROOF_NAV_H
|
||||||
|
jb roof_test_nav_row
|
||||||
|
invoke CreateFileA,OFFSET roofTestNavPath,40000000h,0,0,2,80h,0
|
||||||
|
mov ebx,eax
|
||||||
|
invoke WriteFile,ebx,OFFSET roofTestNavHeader,24,ADDR written,0
|
||||||
|
invoke WriteFile,ebx,OFFSET roofSeatX3D,ROOF_SEAT_COUNT*4,ADDR written,0
|
||||||
|
invoke WriteFile,ebx,OFFSET roofSeatY3D,ROOF_SEAT_COUNT*4,ADDR written,0
|
||||||
|
invoke WriteFile,ebx,OFFSET roofSeatKind3D,ROOF_SEAT_COUNT*4,ADDR written,0
|
||||||
|
invoke WriteFile,ebx,OFFSET roofTestWalkPixels,ROOF_NAV_W*ROOF_NAV_H,ADDR written,0
|
||||||
|
invoke CloseHandle,ebx
|
||||||
|
ret
|
||||||
|
RoofTestNavigation ENDP
|
||||||
|
RoofTestCrashFilter PROC uses ebx esi pointers:DWORD
|
||||||
|
local written:DWORD
|
||||||
|
mov esi,pointers
|
||||||
|
mov esi,[esi+4]
|
||||||
|
invoke CreateFileA,OFFSET roofTestCrash,40000000h,0,0,2,80h,0
|
||||||
|
mov ebx,eax
|
||||||
|
invoke WriteFile,ebx,esi,204,ADDR written,0
|
||||||
|
invoke CloseHandle,ebx
|
||||||
|
invoke ExitProcess,expansionStage
|
||||||
|
mov eax,1
|
||||||
|
ret
|
||||||
|
RoofTestCrashFilter ENDP
|
||||||
|
RoofTestTicks PROC uses esi count:DWORD
|
||||||
|
mov esi,count
|
||||||
|
roof_test_tick:
|
||||||
|
mov deltaTime3D,16
|
||||||
|
add animationClock3D,16
|
||||||
|
call UpdateInteriorTravel3D
|
||||||
|
call UpdateInteriorEye3D
|
||||||
|
dec esi
|
||||||
|
jnz roof_test_tick
|
||||||
|
ret
|
||||||
|
RoofTestTicks ENDP
|
||||||
|
|
||||||
|
RoofNativeTests PROC uses ebx esi edi
|
||||||
|
invoke SetUnhandledExceptionFilter,OFFSET RoofTestCrashFilter
|
||||||
|
mov expansionStage,90
|
||||||
|
mov eax,bankroll
|
||||||
|
mov roofTestBank,eax
|
||||||
|
call InitRoof3D
|
||||||
|
call LoadRoofAssets3D
|
||||||
|
cmp roofSkyArt3D.imageWidth,512
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp roofSkyArt3D.frames,4
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp roofDetailArt3D.frames,15
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp roofHandsArt3D.frames,32
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp roofCityArt3D.frames,22
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp roofNightArt3D.frames,4
|
||||||
|
jne roof_test_fail
|
||||||
|
xor esi,esi
|
||||||
|
roof_test_surface_theme:
|
||||||
|
mov roofNight3D,esi
|
||||||
|
mov ebx,ROOF_DECK
|
||||||
|
roof_test_surface:
|
||||||
|
invoke ResolveRoofSurface3D,ebx
|
||||||
|
cmp eax,65535
|
||||||
|
jbe roof_test_fail
|
||||||
|
mov edx,256
|
||||||
|
cmp ebx,ROOF_FACADE
|
||||||
|
jb @F
|
||||||
|
mov edx,512
|
||||||
|
@@:
|
||||||
|
cmp ebx,ROOF_INDICATOR
|
||||||
|
jne @F
|
||||||
|
mov edx,64
|
||||||
|
@@:
|
||||||
|
cmp ebx,ROOF_LIGHT
|
||||||
|
jne @F
|
||||||
|
mov edx,1
|
||||||
|
@@:
|
||||||
|
cmp ecx,edx
|
||||||
|
jne roof_test_fail
|
||||||
|
inc ebx
|
||||||
|
cmp ebx,ROOF_LAST_MATERIAL
|
||||||
|
jbe roof_test_surface
|
||||||
|
inc esi
|
||||||
|
cmp esi,2
|
||||||
|
jb roof_test_surface_theme
|
||||||
|
mov roofNight3D,0
|
||||||
|
invoke CityRayPlane3D,-512*FP_1,24*FP_1,405
|
||||||
|
cmp eax,7FFFFFFFh
|
||||||
|
jne roof_test_fail
|
||||||
|
mov engineMode,MODE_WALK
|
||||||
|
mov hallLevel3D,0
|
||||||
|
mov worldMap3D,OFFSET casinoMap
|
||||||
|
mov floorTexture3D,100
|
||||||
|
mov playerX,LIFT_CENTRE_X
|
||||||
|
mov playerY,FP_1*63/10
|
||||||
|
mov playerAngle,384
|
||||||
|
call UpdateCamera3D
|
||||||
|
call UpdateInteriorEye3D
|
||||||
|
call ExpansionFrame
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestHall
|
||||||
|
mov playerY,FP_1*48/10
|
||||||
|
call UpdateCamera3D
|
||||||
|
invoke CanWalk3D,LIFT_CENTRE_X,FP_1*34/10
|
||||||
|
test eax,eax
|
||||||
|
jnz roof_test_fail
|
||||||
|
call CheckInteractions
|
||||||
|
cmp interactTargetId,INTERACT_LIFT_CALL
|
||||||
|
jne roof_test_fail
|
||||||
|
call TriggerHallInteraction3D
|
||||||
|
cmp liftPhase3D,1
|
||||||
|
jne roof_test_fail
|
||||||
|
invoke RoofTestTicks,32
|
||||||
|
call ExpansionFrame
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestOpening
|
||||||
|
invoke RoofTestTicks,36
|
||||||
|
cmp liftDoor3D,1000
|
||||||
|
jne roof_test_fail
|
||||||
|
invoke CanWalk3D,LIFT_CENTRE_X,FP_1*34/10
|
||||||
|
test eax,eax
|
||||||
|
jz roof_test_fail
|
||||||
|
; Walk through the opened doorway using the actual normal movement handler.
|
||||||
|
mov keys3D[57h],1
|
||||||
|
mov esi,120
|
||||||
|
roof_test_walk_in:
|
||||||
|
call ExpansionWalkFrame
|
||||||
|
cmp playerY,FP_1*26/10
|
||||||
|
jb roof_test_inside
|
||||||
|
dec esi
|
||||||
|
jnz roof_test_walk_in
|
||||||
|
jmp roof_test_fail
|
||||||
|
roof_test_inside:
|
||||||
|
call ClearKeys3D
|
||||||
|
mov eax,playerX
|
||||||
|
mov roofTestX,eax
|
||||||
|
mov eax,playerY
|
||||||
|
mov roofTestY,eax
|
||||||
|
cmp hallLevel3D,0
|
||||||
|
jne roof_test_fail
|
||||||
|
invoke WindowEvents3D,0,100h,32h,0
|
||||||
|
invoke RoofTestTicks,1
|
||||||
|
cmp roofNight3D,1
|
||||||
|
jne roof_test_fail
|
||||||
|
call ClearKeys3D
|
||||||
|
invoke WindowEvents3D,0,100h,31h,0
|
||||||
|
invoke RoofTestTicks,1
|
||||||
|
cmp roofNight3D,0
|
||||||
|
jne roof_test_fail
|
||||||
|
call ClearKeys3D
|
||||||
|
call CheckInteractions
|
||||||
|
cmp interactTargetId,INTERACT_LIFT_TRAVEL
|
||||||
|
jne roof_test_fail
|
||||||
|
call TriggerHallInteraction3D
|
||||||
|
cmp liftPhase3D,3
|
||||||
|
jne roof_test_fail
|
||||||
|
invoke CanWalk3D,LIFT_CENTRE_X,2*FP_1
|
||||||
|
test eax,eax
|
||||||
|
jnz roof_test_fail
|
||||||
|
invoke RoofTestTicks,68
|
||||||
|
cmp liftPhase3D,4
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp hallLevel3D,0
|
||||||
|
jne roof_test_fail
|
||||||
|
call ExpansionFrame
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestCabin
|
||||||
|
invoke RoofTestTicks,270
|
||||||
|
cmp hallLevel3D,HALL_ROOF
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp worldMap3D,OFFSET roofMap3D
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp liftPhase3D,2
|
||||||
|
jne roof_test_fail
|
||||||
|
mov eax,roofTestX
|
||||||
|
cmp playerX,eax
|
||||||
|
jne roof_test_fail
|
||||||
|
mov eax,roofTestY
|
||||||
|
cmp playerY,eax
|
||||||
|
jne roof_test_fail
|
||||||
|
mov playerAngle,128
|
||||||
|
call ExpansionFrame
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestEntry
|
||||||
|
mov keys3D[57h],1
|
||||||
|
mov esi,120
|
||||||
|
roof_test_walk_out:
|
||||||
|
call ExpansionWalkFrame
|
||||||
|
cmp playerY,FP_1*46/10
|
||||||
|
ja roof_test_outside
|
||||||
|
dec esi
|
||||||
|
jnz roof_test_walk_out
|
||||||
|
jmp roof_test_fail
|
||||||
|
roof_test_outside:
|
||||||
|
call ClearKeys3D
|
||||||
|
call RoofTestNavigation
|
||||||
|
mov expansionStage,91
|
||||||
|
invoke CanWalk3D,29*FP_1,10*FP_1
|
||||||
|
test eax,eax
|
||||||
|
jnz roof_test_fail
|
||||||
|
invoke CanWalk3D,15*FP_1,FP_1*45/10
|
||||||
|
test eax,eax
|
||||||
|
jnz roof_test_fail
|
||||||
|
invoke CanWalk3D,FP_1*145/10,10*FP_1
|
||||||
|
test eax,eax
|
||||||
|
jnz roof_test_fail
|
||||||
|
invoke CanWalk3D,FP_1*145/10,FP_1*77/10
|
||||||
|
test eax,eax
|
||||||
|
jnz roof_test_fail
|
||||||
|
invoke CanWalk3D,12*FP_1,FP_1*68/10
|
||||||
|
test eax,eax
|
||||||
|
jnz roof_test_fail
|
||||||
|
mov playerX,20*FP_1
|
||||||
|
mov playerY,FP_1*66/10
|
||||||
|
mov playerAngle,128
|
||||||
|
call UpdateCamera3D
|
||||||
|
call UpdateRoofEye3D
|
||||||
|
call RenderCeilingAndFloor
|
||||||
|
mov eax,screenBuffer[(460*640+320)*4]
|
||||||
|
mov roofTestFloorColor,eax
|
||||||
|
call ExpansionFrame
|
||||||
|
mov eax,roofTestFloorColor
|
||||||
|
cmp screenBuffer[(460*640+320)*4],eax
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp cityDepthBuffer3D[(460*640+320)*4],4*FP_1
|
||||||
|
ja roof_test_fail
|
||||||
|
cmp playerX,20*FP_1
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp playerY,FP_1*66/10
|
||||||
|
jne roof_test_fail
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestSouth
|
||||||
|
mov playerAngle,0
|
||||||
|
call ExpansionFrame
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestEast
|
||||||
|
mov playerAngle,256
|
||||||
|
call ExpansionFrame
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestWest
|
||||||
|
mov playerX,FP_1*145/10
|
||||||
|
mov playerY,FP_1*84/10
|
||||||
|
mov playerAngle,128
|
||||||
|
call UpdateCamera3D
|
||||||
|
call CheckInteractions
|
||||||
|
cmp interactTargetId,INTERACT_ROOF_SEAT
|
||||||
|
jne roof_test_fail
|
||||||
|
call TriggerHallInteraction3D
|
||||||
|
call UpdateInteriorEye3D
|
||||||
|
cmp roofSeat3D,1
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp viewEye3D,ROOF_SEATED_EYE
|
||||||
|
jne roof_test_fail
|
||||||
|
call ExpansionFrame
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestSeated
|
||||||
|
mov keys3D[57h],1
|
||||||
|
invoke RoofTestTicks,1
|
||||||
|
cmp roofSeat3D,0
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp playerY,FP_1*84/10
|
||||||
|
jne roof_test_fail
|
||||||
|
call ClearKeys3D
|
||||||
|
xor ebx,ebx
|
||||||
|
roof_test_all_seats:
|
||||||
|
mov playerX,20*FP_1
|
||||||
|
mov playerY,7*FP_1
|
||||||
|
mov playerAngle,128
|
||||||
|
mov roofTargetSeat3D,ebx
|
||||||
|
mov interactTargetId,INTERACT_ROOF_SEAT
|
||||||
|
call TryRoofInteraction3D
|
||||||
|
lea eax,[ebx+1]
|
||||||
|
cmp roofSeat3D,eax
|
||||||
|
jne roof_test_fail
|
||||||
|
call UpdateRoofEye3D
|
||||||
|
mov eax,ROOF_SEATED_EYE
|
||||||
|
cmp roofSeatKind3D[ebx*4],2
|
||||||
|
jb @F
|
||||||
|
mov eax,ROOF_STANDING_EYE
|
||||||
|
@@:
|
||||||
|
cmp viewEye3D,eax
|
||||||
|
jne roof_test_fail
|
||||||
|
mov eax,384
|
||||||
|
cmp roofSeatKind3D[ebx*4],3
|
||||||
|
jne @F
|
||||||
|
mov eax,256
|
||||||
|
@@:
|
||||||
|
cmp playerAngle,eax
|
||||||
|
jne roof_test_fail
|
||||||
|
mov interactTargetId,INTERACT_ROOF_SEAT
|
||||||
|
call TryRoofInteraction3D
|
||||||
|
cmp roofSeat3D,0
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp playerX,20*FP_1
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp playerY,7*FP_1
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp playerAngle,128
|
||||||
|
jne roof_test_fail
|
||||||
|
call UpdateRoofEye3D
|
||||||
|
inc ebx
|
||||||
|
cmp ebx,ROOF_SEAT_COUNT
|
||||||
|
jb roof_test_all_seats
|
||||||
|
mov expansionStage,92
|
||||||
|
mov playerX,20*FP_1
|
||||||
|
mov playerY,7*FP_1
|
||||||
|
mov engineMode,MODE_BAR
|
||||||
|
mov barPhase3D,0
|
||||||
|
mov esi,30
|
||||||
|
roof_test_bar_repeat:
|
||||||
|
call RenderBar3D
|
||||||
|
cmp playerX,20*FP_1
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp playerY,7*FP_1
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp viewEye3D,ROOF_STANDING_EYE
|
||||||
|
jne roof_test_fail
|
||||||
|
dec esi
|
||||||
|
jnz roof_test_bar_repeat
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestBar
|
||||||
|
mov barPhase3D,1
|
||||||
|
mov barSelection3D,1
|
||||||
|
mov barTime3D,1500
|
||||||
|
call RenderBar3D
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestMix
|
||||||
|
mov engineMode,MODE_WALK
|
||||||
|
mov barPhase3D,0
|
||||||
|
; Scale and full furniture volumes must survive side and back inspection.
|
||||||
|
mov expansionStage,93
|
||||||
|
mov playerX,FP_1*191/10
|
||||||
|
mov playerY,10*FP_1
|
||||||
|
mov playerAngle,256
|
||||||
|
call ExpansionFrame
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestChairSide
|
||||||
|
mov playerX,FP_1*177/10
|
||||||
|
mov playerY,FP_1*116/10
|
||||||
|
mov playerAngle,384
|
||||||
|
call ExpansionFrame
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestChairBack
|
||||||
|
mov playerX,FP_1*167/10
|
||||||
|
mov playerY,FP_1*197/10
|
||||||
|
mov playerAngle,256
|
||||||
|
call ExpansionFrame
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestPlanter
|
||||||
|
; The native gait advances position while every step respects roof collision.
|
||||||
|
mov eax,roofGuestX3D[0]
|
||||||
|
mov roofTestGuestX,eax
|
||||||
|
mov roofGuestWait3D[0],0
|
||||||
|
mov roofGuestDir3D[0],0
|
||||||
|
invoke RoofTestTicks,20
|
||||||
|
mov eax,roofGuestX3D[0]
|
||||||
|
cmp eax,roofTestGuestX
|
||||||
|
je roof_test_fail
|
||||||
|
cmp roofGuestMoving3D[0],1
|
||||||
|
jne roof_test_fail
|
||||||
|
mov playerX,FP_1*275/10
|
||||||
|
mov playerY,10*FP_1
|
||||||
|
mov playerAngle,0
|
||||||
|
call UpdateCamera3D
|
||||||
|
call CheckRoofInteractions3D
|
||||||
|
cmp interactTargetId,INTERACT_ROOF_RAIL
|
||||||
|
jne roof_test_fail
|
||||||
|
call TryRoofInteraction3D
|
||||||
|
cmp roofLean3D,1
|
||||||
|
jne roof_test_fail
|
||||||
|
invoke RoofTestTicks,75
|
||||||
|
cmp roofLean3D,2
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp roofLeanTime3D,1100
|
||||||
|
jne roof_test_fail
|
||||||
|
call ExpansionFrame
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestLean
|
||||||
|
invoke CanWalk3D,27*FP_1,10*FP_1
|
||||||
|
test eax,eax
|
||||||
|
jnz roof_test_fail
|
||||||
|
mov roofNight3D,1
|
||||||
|
call ExpansionFrame
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestNight
|
||||||
|
mov roofNight3D,0
|
||||||
|
mov interactTargetId,INTERACT_ROOF_RAIL
|
||||||
|
call TryRoofInteraction3D
|
||||||
|
invoke RoofTestTicks,40
|
||||||
|
cmp roofLean3D,0
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp playerX,FP_1*275/10
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp playerY,10*FP_1
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp viewEye3D,ROOF_STANDING_EYE
|
||||||
|
jne roof_test_fail
|
||||||
|
mov expansionStage,92
|
||||||
|
invoke RoofTestTicks,250
|
||||||
|
cmp liftDoor3D,0
|
||||||
|
jne roof_test_fail
|
||||||
|
mov playerX,LIFT_CENTRE_X
|
||||||
|
mov playerY,FP_1*48/10
|
||||||
|
mov playerAngle,384
|
||||||
|
call UpdateCamera3D
|
||||||
|
call CheckInteractions
|
||||||
|
call TriggerHallInteraction3D
|
||||||
|
invoke RoofTestTicks,70
|
||||||
|
mov playerY,FP_1*24/10
|
||||||
|
call CheckInteractions
|
||||||
|
cmp interactTargetId,INTERACT_LIFT_TRAVEL
|
||||||
|
jne roof_test_fail
|
||||||
|
call TriggerHallInteraction3D
|
||||||
|
invoke RoofTestTicks,340
|
||||||
|
cmp hallLevel3D,0
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp worldMap3D,OFFSET casinoMap
|
||||||
|
jne roof_test_fail
|
||||||
|
mov playerY,FP_1*48/10
|
||||||
|
call ExpansionFrame
|
||||||
|
invoke ExpansionSnapshot,OFFSET roofTestReturn
|
||||||
|
mov eax,bankroll
|
||||||
|
cmp eax,roofTestBank
|
||||||
|
jne roof_test_fail
|
||||||
|
call FreeRoofAssets3D
|
||||||
|
cmp roofSkyArt3D.pixels,0
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp roofMaterialArt3D.pixels,0
|
||||||
|
jne roof_test_fail
|
||||||
|
cmp roofDetailArt3D.pixels,0
|
||||||
|
jne roof_test_fail
|
||||||
|
call LoadRoofAssets3D
|
||||||
|
call RoofTestHD
|
||||||
|
mov hallLevel3D,0
|
||||||
|
mov worldMap3D,OFFSET casinoMap
|
||||||
|
ret
|
||||||
|
roof_test_fail:
|
||||||
|
invoke ExitProcess,expansionStage
|
||||||
|
ret
|
||||||
|
RoofNativeTests ENDP
|
||||||
|
|
@ -5,7 +5,10 @@ Push-Location $root
|
||||||
try {
|
try {
|
||||||
& 'C:\Python314\python.exe' tools\tests\prepare_billiards_module.py
|
& 'C:\Python314\python.exe' tools\tests\prepare_billiards_module.py
|
||||||
if ($LASTEXITCODE -ne 0) { throw 'Billiards helper preparation failed' }
|
if ($LASTEXITCODE -ne 0) { throw 'Billiards helper preparation failed' }
|
||||||
& "$MasmRoot\bin\ml.exe" /c /coff /Cp /nologo /I. /Fobuild\billiards\module.obj tools\tests\billiards_module.asm
|
$assembler = "$MasmRoot\bin\ml.exe"
|
||||||
|
$modernAssembler = 'C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.51.36231\bin\Hostx64\x86\ml.exe'
|
||||||
|
if (Test-Path -LiteralPath $modernAssembler) { $assembler = $modernAssembler }
|
||||||
|
& $assembler /c /coff /Cp /nologo /I. /Fobuild\billiards\module.obj tools\tests\billiards_module.asm
|
||||||
if ($LASTEXITCODE -ne 0) { throw 'Billiards module assembly failed' }
|
if ($LASTEXITCODE -ne 0) { throw 'Billiards module assembly failed' }
|
||||||
$sdk = Get-ChildItem -LiteralPath "${env:ProgramFiles(x86)}\Windows Kits\10\Lib" -Directory |
|
$sdk = Get-ChildItem -LiteralPath "${env:ProgramFiles(x86)}\Windows Kits\10\Lib" -Directory |
|
||||||
Sort-Object Name -Descending |
|
Sort-Object Name -Descending |
|
||||||
|
|
|
||||||