feat: implement native billiards, scratch tickets, first-person dice, and city wake scene
- Billiards: add native Russian Pyramid & American Eight-Ball pool with physics prediction, controls, and regression tests - Scratch Tickets: add dedicated counter, mat presentation, elliptical coin scraping, 4 ticket types, and payout effects - First-Person Dice: add native dice scene, hand anchor frames, throwing animation, and table perspective - City Wake & Weather: add arrival cutscene, alley geometry, weather/rain effects, and lighter/rocker animation - World Dressing: add hall paintings, furniture packs, hall lighting, and scene regression tests - Build & Tooling: update build.bat for modern MSVC toolchain, update launcher hash, and refresh shipping binaries
5
.gitignore
vendored
|
|
@ -13,12 +13,17 @@ __pycache__/
|
|||
# Generated build/test output; keep packaging source and shipping exe files.
|
||||
/build/actions/
|
||||
/build/arrival/
|
||||
/build/billiards/
|
||||
/build/buckshot/
|
||||
/build/coin/
|
||||
/build/dice/
|
||||
/build/hall/
|
||||
/build/icon_work/
|
||||
/build/scratch/
|
||||
/build/startup/
|
||||
/build/tables/
|
||||
/build/wheel/
|
||||
/build/world/
|
||||
/build/*.res
|
||||
/build/payload_*.zip
|
||||
/build/PokerGameSetup_base.exe
|
||||
|
|
|
|||
BIN
assets/animations/arrival/alley-materials-v1.bin
Normal file
BIN
assets/animations/arrival/wake-knees-v1.bin
Normal file
BIN
assets/animations/arrival/wake-lighter-v1.bin
Normal file
BIN
assets/animations/arrival/wake-rocker-v1.bin
Normal file
BIN
assets/animations/arrival/wake-rocker-v2.bin
Normal file
BIN
assets/animations/arrival/wake-sleeve-v1.bin
Normal file
BIN
assets/animations/dice/hands-v1.bin
Normal file
BIN
assets/animations/dice/hands-v2.bin
Normal file
BIN
assets/animations/hall/world-dressing-v6.bin
Normal file
BIN
assets/animations/pyramid/pool-balls-v1.bin
Normal file
BIN
assets/animations/scratch/coin-edge-v1.bin
Normal file
BIN
assets/animations/scratch/counter-v1.bin
Normal file
BIN
assets/animations/scratch/foil-v1.bin
Normal file
BIN
assets/animations/scratch/payout-chips-v1.bin
Normal file
BIN
assets/animations/scratch/portrait-fields-v3.bin
Normal file
443
assets/animations/scratch/portrait-layouts-v3.json
Normal file
|
|
@ -0,0 +1,443 @@
|
|||
[
|
||||
{
|
||||
"file": "neon-ru-v3.png",
|
||||
"winning": 5,
|
||||
"players": 15,
|
||||
"fields": [
|
||||
{
|
||||
"x": 160,
|
||||
"y": 339,
|
||||
"w": 51,
|
||||
"h": 51,
|
||||
"area": 1999
|
||||
},
|
||||
{
|
||||
"x": 228,
|
||||
"y": 339,
|
||||
"w": 51,
|
||||
"h": 51,
|
||||
"area": 2015
|
||||
},
|
||||
{
|
||||
"x": 297,
|
||||
"y": 339,
|
||||
"w": 51,
|
||||
"h": 51,
|
||||
"area": 2012
|
||||
},
|
||||
{
|
||||
"x": 366,
|
||||
"y": 339,
|
||||
"w": 51,
|
||||
"h": 51,
|
||||
"area": 2010
|
||||
},
|
||||
{
|
||||
"x": 435,
|
||||
"y": 339,
|
||||
"w": 51,
|
||||
"h": 51,
|
||||
"area": 2032
|
||||
},
|
||||
{
|
||||
"x": 133,
|
||||
"y": 433,
|
||||
"w": 65,
|
||||
"h": 47,
|
||||
"area": 2973
|
||||
},
|
||||
{
|
||||
"x": 211,
|
||||
"y": 433,
|
||||
"w": 65,
|
||||
"h": 47,
|
||||
"area": 2976
|
||||
},
|
||||
{
|
||||
"x": 290,
|
||||
"y": 433,
|
||||
"w": 65,
|
||||
"h": 47,
|
||||
"area": 2972
|
||||
},
|
||||
{
|
||||
"x": 369,
|
||||
"y": 433,
|
||||
"w": 64,
|
||||
"h": 47,
|
||||
"area": 2962
|
||||
},
|
||||
{
|
||||
"x": 447,
|
||||
"y": 433,
|
||||
"w": 64,
|
||||
"h": 47,
|
||||
"area": 2940
|
||||
},
|
||||
{
|
||||
"x": 133,
|
||||
"y": 496,
|
||||
"w": 65,
|
||||
"h": 47,
|
||||
"area": 2977
|
||||
},
|
||||
{
|
||||
"x": 211,
|
||||
"y": 496,
|
||||
"w": 65,
|
||||
"h": 47,
|
||||
"area": 2978
|
||||
},
|
||||
{
|
||||
"x": 290,
|
||||
"y": 496,
|
||||
"w": 65,
|
||||
"h": 46,
|
||||
"area": 2965
|
||||
},
|
||||
{
|
||||
"x": 369,
|
||||
"y": 496,
|
||||
"w": 64,
|
||||
"h": 47,
|
||||
"area": 2932
|
||||
},
|
||||
{
|
||||
"x": 447,
|
||||
"y": 496,
|
||||
"w": 64,
|
||||
"h": 47,
|
||||
"area": 2926
|
||||
},
|
||||
{
|
||||
"x": 133,
|
||||
"y": 558,
|
||||
"w": 65,
|
||||
"h": 47,
|
||||
"area": 2962
|
||||
},
|
||||
{
|
||||
"x": 211,
|
||||
"y": 558,
|
||||
"w": 65,
|
||||
"h": 47,
|
||||
"area": 2975
|
||||
},
|
||||
{
|
||||
"x": 290,
|
||||
"y": 558,
|
||||
"w": 65,
|
||||
"h": 47,
|
||||
"area": 2981
|
||||
},
|
||||
{
|
||||
"x": 369,
|
||||
"y": 558,
|
||||
"w": 64,
|
||||
"h": 47,
|
||||
"area": 2951
|
||||
},
|
||||
{
|
||||
"x": 447,
|
||||
"y": 558,
|
||||
"w": 64,
|
||||
"h": 47,
|
||||
"area": 2942
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "ruby-ru-v3.png",
|
||||
"winning": 6,
|
||||
"players": 18,
|
||||
"fields": [
|
||||
{
|
||||
"x": 136,
|
||||
"y": 329,
|
||||
"w": 50,
|
||||
"h": 54,
|
||||
"area": 2138
|
||||
},
|
||||
{
|
||||
"x": 202,
|
||||
"y": 329,
|
||||
"w": 50,
|
||||
"h": 53,
|
||||
"area": 2130
|
||||
},
|
||||
{
|
||||
"x": 267,
|
||||
"y": 329,
|
||||
"w": 51,
|
||||
"h": 54,
|
||||
"area": 2138
|
||||
},
|
||||
{
|
||||
"x": 333,
|
||||
"y": 329,
|
||||
"w": 50,
|
||||
"h": 54,
|
||||
"area": 2143
|
||||
},
|
||||
{
|
||||
"x": 398,
|
||||
"y": 329,
|
||||
"w": 50,
|
||||
"h": 54,
|
||||
"area": 2122
|
||||
},
|
||||
{
|
||||
"x": 461,
|
||||
"y": 329,
|
||||
"w": 50,
|
||||
"h": 53,
|
||||
"area": 2125
|
||||
},
|
||||
{
|
||||
"x": 135,
|
||||
"y": 424,
|
||||
"w": 54,
|
||||
"h": 46,
|
||||
"area": 2424
|
||||
},
|
||||
{
|
||||
"x": 201,
|
||||
"y": 424,
|
||||
"w": 52,
|
||||
"h": 46,
|
||||
"area": 2336
|
||||
},
|
||||
{
|
||||
"x": 265,
|
||||
"y": 424,
|
||||
"w": 52,
|
||||
"h": 46,
|
||||
"area": 2359
|
||||
},
|
||||
{
|
||||
"x": 329,
|
||||
"y": 424,
|
||||
"w": 52,
|
||||
"h": 46,
|
||||
"area": 2351
|
||||
},
|
||||
{
|
||||
"x": 393,
|
||||
"y": 424,
|
||||
"w": 52,
|
||||
"h": 46,
|
||||
"area": 2335
|
||||
},
|
||||
{
|
||||
"x": 457,
|
||||
"y": 424,
|
||||
"w": 53,
|
||||
"h": 46,
|
||||
"area": 2380
|
||||
},
|
||||
{
|
||||
"x": 135,
|
||||
"y": 487,
|
||||
"w": 54,
|
||||
"h": 46,
|
||||
"area": 2432
|
||||
},
|
||||
{
|
||||
"x": 201,
|
||||
"y": 487,
|
||||
"w": 52,
|
||||
"h": 46,
|
||||
"area": 2338
|
||||
},
|
||||
{
|
||||
"x": 265,
|
||||
"y": 487,
|
||||
"w": 52,
|
||||
"h": 46,
|
||||
"area": 2362
|
||||
},
|
||||
{
|
||||
"x": 329,
|
||||
"y": 487,
|
||||
"w": 52,
|
||||
"h": 46,
|
||||
"area": 2353
|
||||
},
|
||||
{
|
||||
"x": 393,
|
||||
"y": 487,
|
||||
"w": 52,
|
||||
"h": 46,
|
||||
"area": 2349
|
||||
},
|
||||
{
|
||||
"x": 457,
|
||||
"y": 487,
|
||||
"w": 53,
|
||||
"h": 46,
|
||||
"area": 2381
|
||||
},
|
||||
{
|
||||
"x": 135,
|
||||
"y": 550,
|
||||
"w": 54,
|
||||
"h": 46,
|
||||
"area": 2423
|
||||
},
|
||||
{
|
||||
"x": 201,
|
||||
"y": 550,
|
||||
"w": 52,
|
||||
"h": 46,
|
||||
"area": 2335
|
||||
},
|
||||
{
|
||||
"x": 265,
|
||||
"y": 550,
|
||||
"w": 52,
|
||||
"h": 46,
|
||||
"area": 2361
|
||||
},
|
||||
{
|
||||
"x": 329,
|
||||
"y": 550,
|
||||
"w": 52,
|
||||
"h": 46,
|
||||
"area": 2340
|
||||
},
|
||||
{
|
||||
"x": 393,
|
||||
"y": 550,
|
||||
"w": 52,
|
||||
"h": 46,
|
||||
"area": 2350
|
||||
},
|
||||
{
|
||||
"x": 457,
|
||||
"y": 550,
|
||||
"w": 53,
|
||||
"h": 46,
|
||||
"area": 2381
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"file": "sea-ru-v3.png",
|
||||
"winning": 4,
|
||||
"players": 12,
|
||||
"fields": [
|
||||
{
|
||||
"x": 200,
|
||||
"y": 335,
|
||||
"w": 53,
|
||||
"h": 53,
|
||||
"area": 2213
|
||||
},
|
||||
{
|
||||
"x": 270,
|
||||
"y": 335,
|
||||
"w": 53,
|
||||
"h": 53,
|
||||
"area": 2213
|
||||
},
|
||||
{
|
||||
"x": 339,
|
||||
"y": 335,
|
||||
"w": 53,
|
||||
"h": 53,
|
||||
"area": 2209
|
||||
},
|
||||
{
|
||||
"x": 409,
|
||||
"y": 335,
|
||||
"w": 53,
|
||||
"h": 53,
|
||||
"area": 2212
|
||||
},
|
||||
{
|
||||
"x": 147,
|
||||
"y": 427,
|
||||
"w": 79,
|
||||
"h": 48,
|
||||
"area": 3758
|
||||
},
|
||||
{
|
||||
"x": 242,
|
||||
"y": 427,
|
||||
"w": 81,
|
||||
"h": 48,
|
||||
"area": 3836
|
||||
},
|
||||
{
|
||||
"x": 338,
|
||||
"y": 427,
|
||||
"w": 80,
|
||||
"h": 48,
|
||||
"area": 3765
|
||||
},
|
||||
{
|
||||
"x": 434,
|
||||
"y": 427,
|
||||
"w": 79,
|
||||
"h": 48,
|
||||
"area": 3758
|
||||
},
|
||||
{
|
||||
"x": 147,
|
||||
"y": 490,
|
||||
"w": 79,
|
||||
"h": 48,
|
||||
"area": 3714
|
||||
},
|
||||
{
|
||||
"x": 242,
|
||||
"y": 490,
|
||||
"w": 81,
|
||||
"h": 48,
|
||||
"area": 3797
|
||||
},
|
||||
{
|
||||
"x": 338,
|
||||
"y": 490,
|
||||
"w": 80,
|
||||
"h": 48,
|
||||
"area": 3719
|
||||
},
|
||||
{
|
||||
"x": 434,
|
||||
"y": 490,
|
||||
"w": 79,
|
||||
"h": 48,
|
||||
"area": 3718
|
||||
},
|
||||
{
|
||||
"x": 147,
|
||||
"y": 554,
|
||||
"w": 79,
|
||||
"h": 48,
|
||||
"area": 3756
|
||||
},
|
||||
{
|
||||
"x": 242,
|
||||
"y": 554,
|
||||
"w": 81,
|
||||
"h": 48,
|
||||
"area": 3843
|
||||
},
|
||||
{
|
||||
"x": 338,
|
||||
"y": 553,
|
||||
"w": 80,
|
||||
"h": 49,
|
||||
"area": 3762
|
||||
},
|
||||
{
|
||||
"x": 434,
|
||||
"y": 554,
|
||||
"w": 79,
|
||||
"h": 48,
|
||||
"area": 3766
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
BIN
assets/animations/scratch/portraits-v3.bin
Normal file
BIN
assets/animations/scratch/table-v1.bin
Normal file
BIN
assets/animations/scratch/ticket-v1.bin
Normal file
BIN
assets/audio/generated/scratch-paper.wav
Normal file
BIN
assets/audio/generated/scratch-payout.wav
Normal file
BIN
assets/audio/generated/scratch-scrape.wav
Normal file
|
|
@ -1,4 +1,11 @@
|
|||
{
|
||||
"cityWakeLine1": "Вставай, самурай,",
|
||||
"cityWakeLine2": "пора дэпнуть все в казино",
|
||||
"poolSelectTitle3D": "БИЛЬЯРД",
|
||||
"poolSelectPyramid3D": "1 ПИРАМИДА",
|
||||
"poolSelectEight3D": "2 ПУЛ ВОСЬМЕРКА",
|
||||
"poolCallText3D": "ЗАКАЗ",
|
||||
"poolPredictionText3D": "ПРОГНОЗ",
|
||||
"coinTitle3D": "МОНЕТКА",
|
||||
"coinHeadsText3D": "ОРЁЛ",
|
||||
"coinTailsText3D": "РЕШКА",
|
||||
|
|
@ -355,5 +362,45 @@
|
|||
"pyrBadEndText3D": "НЕВЕРНЫЙ УДАР",
|
||||
"pyrPlayerName3D": "ВЫ",
|
||||
"pyrAIName3D": "ИИ",
|
||||
"pyrSkipText3D": "ПРОПУСК"
|
||||
"pyrSkipText3D": "ПРОПУСК",
|
||||
"scratchTitle3D": "ЛОТЕРЕЯ",
|
||||
"scratchGame3D": "ЗОЛОТАЯ ТРОЙКА",
|
||||
"scratchBuy3D": "КУПИТЬ",
|
||||
"scratchNext3D": "НОВЫЙ",
|
||||
"scratchPrice3D": "ЦЕНА",
|
||||
"scratchWin3D": "ПРИЗ",
|
||||
"scratchLose3D": "БЕЗ ВЫИГРЫША",
|
||||
"scratchWait3D": "ОТКРЫТО",
|
||||
"scratchPoor3D": "МАЛО ФИШЕК",
|
||||
"scratchMissing3D": "НЕТ СПРАЙТОВ",
|
||||
"scratchHall3D": "E: ЛОТЕРЕЙНЫЕ БИЛЕТЫ",
|
||||
"scratchRule3D": "3 ОДИНАКОВЫХ = ПРИЗ",
|
||||
"scratchActive3D": "БИЛЕТ",
|
||||
"scratchNumbers3D": "СЧАСТЛИВЫЕ ЧИСЛА",
|
||||
"scratchRows3D": "ТРИ В РЯД",
|
||||
"scratchInstant3D": "МИГ УДАЧИ",
|
||||
"scratchNumberRule3D": "СОВПАДЕНИЕ = ПРИЗ ПОД ЧИСЛОМ",
|
||||
"scratchRowRule3D": "3 ОДИНАКОВЫХ В ОДНОМ РЯДУ",
|
||||
"scratchInstantRule3D": "ПРИЗ УКАЗАН ПОД ЗАЩИТОЙ",
|
||||
"scratchLucky3D": "ВЫИГРЫШНЫЕ ЧИСЛА",
|
||||
"scratchYours3D": "ВАШИ ЧИСЛА",
|
||||
"scratchAmount3D": "ВАШ ПРИЗ",
|
||||
"scratchNeon3D": "НЕОНОВАЯ УДАЧА",
|
||||
"scratchRuby3D": "РУБИНОВЫЙ ДЖЕКПОТ",
|
||||
"scratchSea3D": "ВОЛНА СОКРОВИЩ",
|
||||
"scratchBonusRule3D": "ЧИСЛО ИЛИ БОНУС = ПРИЗ",
|
||||
"scratchMatch3D": "СОВПАДЕНИЕ: ПРИЗ",
|
||||
"scratchNeonDouble3D": "x2: ДВОЙНОЙ ПРИЗ",
|
||||
"scratchNeonTen3D": "x10: ПРИЗ x10",
|
||||
"scratchRubyDouble3D": "x2: ДВОЙНОЙ ПРИЗ",
|
||||
"scratchRubyAll3D": "ВСЕ: ВСЕ ПРИЗЫ",
|
||||
"scratchSeaDouble3D": "x2: ДВОЙНОЙ ПРИЗ",
|
||||
"scratchSeaAll3D": "ВСЕ: ВСЕ ПРИЗЫ",
|
||||
"scratchAll3D": "ВСЕ",
|
||||
"scratchField3D": "ПОЛЕ",
|
||||
"scratchKind3D": "ВИД БИЛЕТА",
|
||||
"scratchCost3D": "ЦЕНА БИЛЕТА",
|
||||
"scratchPayout3D": "ВЫПЛАТА",
|
||||
"scratchNet3D": "ЧИСТЫЙ ИТОГ",
|
||||
"scratchPending3D": "БИЛЕТ НЕ ОТКРЫТ"
|
||||
}
|
||||
|
|
|
|||
BIN
assets/sprites/arrival/alley-materials-v1.png
Normal file
|
After Width: | Height: | Size: 3.2 MiB |
BIN
assets/sprites/arrival/wake-knees-v1.png
Normal file
|
After Width: | Height: | Size: 758 KiB |
BIN
assets/sprites/arrival/wake-lighter-v1.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
6
assets/sprites/arrival/wake-prompts.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"actor": "Use case: game-asset. Primary request: transparent 4 by 4 sprite animation atlas, exactly 16 equally spaced full-body poses of the SAME fictional homeless cyberpunk rocker, loosely reminiscent of Johnny Silverhand: long unwashed dark hair, scruffy beard, dark aviator sunglasses, weathered black leather vest under patched dark coat, faded grey shirt, worn jeans, battered boots, LEFT forearm a crude silver mechanical prosthesis. Friendly sardonic expression, no weapons. Consistent detailed hand-painted late-1990s Doom/Build-engine pixel art, not photographic, not smooth 3D render; muted cold skin and desaturated clothes with small warm highlights matching brick rainy night alley. Clean transparent gutters, no background or ground shadows. All poses face the viewer or turn slightly left with consistent proportions, camera and illumination, full boots visible. Exactly four columns and four rows read left to right. Frames 1-4 crouching on bent knees, leaning toward someone seated on the ground, raising RIGHT natural hand to wake them; frames 5-8 still crouched, subtle mouth speaking and beckoning hand gesture; frames 9-12 smoothly standing from crouch; frames 13-16 turning to his left and walking past the seated viewer. Shared cell coordinates, identical SCALE between poses: crouched poses must be shorter than standing, do NOT enlarge crouched bodies to fill the cell. All feet on the same cell baseline, maximum standing figure occupies 84 percent of cell height, crouched 55 percent, enough headroom. No text, no labels, no logo, no duplicates, no cropped limbs. True transparent background.",
|
||||
"lighter": "Use case: game-asset. Primary request: first-person LEFT HAND opening and igniting a battered silver flip-top lighter, transparent 4 by 4 sprite animation sheet with exactly 16 equally spaced frames. Crisp late-1990s Doom/Build-engine shaded PIXEL ART, not photographic, not flat cartoon. Adult light skin left hand, black worn leather jacket sleeve entering from lower LEFT of every cell. Natural anatomically correct fingers and LEFT thumb on spark wheel. NO RIGHT HAND, NO CIGARETTE. The ignition flame is meant to light a separate cigarette supplied by the game. Camera looking down at the lighter. Same hand identity, scale, position anchors and warm/cool lighting across all cells, clean transparent margins. Sequence read left to right: frames 1-3 closed lighter raised, frames 4-6 lid opens and thumb rolls spark wheel with tiny sparks, frames 7-12 bright small warm yellow flame fluttering ABOVE nozzle near the upper centre of the cell, frames 13-14 thumb stops flame and lid closes, frames 15-16 closed lighter lowers a little. Lighter nozzle always near x=50 percent, y=20 percent of cell, fingers and wrist below it; no flipping hand orientation. Solid opaque skin/metal/leather, transparency ONLY outside silhouettes and tiny flame wisps. No text, lettering, border, shadow matte or background. One square sprite sheet, exactly 4 rows by 4 columns.",
|
||||
"knees": "Use case: game-asset. Asset: transparent first-person foreground sprite, wide landscape composition. View of one's OWN bent knees and shins in faded charcoal-blue jeans while seated on the ground of a rainy alley, knees occupying bottom left and bottom right edges, a clear transparent wide gap through the centre and entire upper half, trouser legs descend out of the bottom edge naturally. NO HANDS, NO arms, NO other person, NO background, NO shoes in top area, NO cigarette, NO text. Detailed hand-painted late-1990s Doom / Build engine pixel art with crisp pixels, muted cool denim and subtle warm edge highlights; not photoreal or smooth render. Large creased bent kneecaps at left and right lower corners, believable seated first-person perspective, consistent player black jacket/jeans character. True transparent background outside legs.",
|
||||
"mode": "built-in"
|
||||
}
|
||||
BIN
assets/sprites/arrival/wake-rocker-v1.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
assets/sprites/arrival/wake-rocker-v2.png
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
assets/sprites/arrival/wake-sleeve-v1.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
7
assets/sprites/arrival/wake-v2-prompts.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"mode": "built-in",
|
||||
"actor": "Use case: identity-preserve. Production retro 2.5D game sprite animation atlas. Reference image is the approved scruffy homeless Johnny Silverhand-like rocker: preserve EXACT face, shoulder-length dark hair, dark sunglasses, beard, chrome LEFT arm, dirty black leather long coat, worn dark jeans, brown boots, pixel-art shading and proportions. Create ONE transparent atlas of EXACTLY 32 complete isolated character poses, 4 columns by 8 rows, read left-to-right top-to-bottom, clean generous transparent gutters, consistent ground anchor and common scale (do NOT enlarge crouching poses). First 16 frames form a smooth crouching speaking gesture cycle: tiny gradual head nod, mouth movement, shoulders breathing, extended right hand gradually gestures and returns, left chrome hand on knee. Next 8 frames are one smooth rise from crouch to standing then gradually turn away: frame16 crouched lean forward,17 lift hips,18 half rise,19 nearly straight,20 standing front,21 quarter turn,22 three-quarter back,23 full back. Last 8 frames show a smooth walking-away full-body cycle seen from back with gently swinging coat and chrome left arm. On every turned/back-facing coat clearly show Cyberpunk 2077 SAMURAI's large red horned skull/flame emblem with small SAMURAI lettering across upper back, NOT a generic samurai warrior. No new props, no scenery, no cell outlines, no captions, no watermarks. Same gritty detailed pixel-art style as input, no photorealism. Entire boots visible every frame. Transparent background.",
|
||||
"sleeve": "Use case: precise-object-edit. Input image is STYLE reference of the approved first-person male lighter-hand sprites, not a request for another hand. Generate ONE isolated LEFT FOREARM IN BLACK WORN LEATHER COAT SLEEVE ONLY, no hand, fingers, lighter or flame. This sleeve extends the cropped left wrist in a retro 2.5D first-person game. Tall 2:3 transparent canvas: top cuff opening at horizontal center (50% width) on the very TOP edge, broad enough to disappear underneath the existing wrist; forearm runs smoothly diagonally down and toward lower-left and extends out of the BOTTOM edge, not a floating amputated sleeve. Three-dimensional tapered cylinder with believable elbow perspective, detailed dark leather folds, stitching, subdued brown-grey highlights. Keep same gritty crisp pixel-art shaded texture and scale as reference, no photorealistic skin, no blur. Solid continuous silhouette from TOP to BOTTOM, transparent around sleeve. No black rectangular matte, no labels, no scenery, no detached objects.",
|
||||
"alley": "Use case: stylized-concept. Asset type: material atlas for retro 2.5D rain-soaked alley geometry. ONE square image exactly TWO columns and TWO rows of four square opaque game textures, no gaps or borders. Top-left: old dark galvanized ventilation grille with closely spaced horizontal louvers, rusty narrow frame, grimy bolts. Top-right: flat weathered pasted-over concert posters on dirty grey paper, small torn edges layered INSIDE the tile, faded crimson and ivory punk-print graphics, no readable modern advertisements. Bottom-left: battered wooden shipping crate planks with seams, dark wet grain, worn nails and diagonal wooden brace. Bottom-right: rusty dark electrical junction cabinet face, recessed door, hinges, small latch, peeling green-grey paint, NO luminous screen. Detailed gritty Doom/Build-engine pixel-art materials, crisp textured clusters, not photorealism, not vector illustration. All four textures orthographic front-on, no background scenery or perspective scene, no shadows outside tiles, entire canvas opaque, consistent subdued rainy-night palette. Each material must fill its own entire square.",
|
||||
"logo_reference": "https://www.cyberpunk.net/en/news/30631/pre-order-your-samurai-bomber-jacket-now"
|
||||
}
|
||||
4
assets/sprites/arrival/wake-walk-v2-prompt.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"mode": "built-in",
|
||||
"walk": "Use case: identity-preserve. Use reference ONLY for approved character identity and pixel-art style. Production game sprite sheet: exactly EIGHT full-body frames in a FOUR column TWO row atlas, generous transparent gutters, no extra row. SAME homeless Johnny Silverhand-like rocker, dark shoulder-length hair, scruffy beard, sunglasses, chrome LEFT arm, worn black leather LONG COAT, dark jeans, brown boots. Camera sees him FROM THE BACK in EVERY frame. Large red Cyberpunk 2077 SAMURAI horned skull/flame emblem centered on coat back, small SAMURAI name above. Eight successive frames of WALK-IN-PLACE animation: hips, knees, arms and coat hem move gradually; heel lifts, passing legs, alternate foot contacts. He DOES NOT move away from camera and DOES NOT SHRINK. Exactly SAME camera distance and SAME body scale in all eight cells, full standing head-to-foot height constant, boots on common ground baseline, same lighting. All frames occupy about 85% slot height. Crisp gritty detailed pixel art identical to reference, not photo. No scenery, no labels, no borders, no shadows outside silhouette, true transparent background. Keep full boots visible."
|
||||
}
|
||||
BIN
assets/sprites/arrival/wake-walk-v2.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
assets/sprites/dice/hands-v1.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
assets/sprites/dice/hands-v2.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
6
assets/sprites/dice/prompts-v1.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"mode": "built-in",
|
||||
"hands": "Use case: identity-preserve. Input image is approved STYLE and hand identity reference, NOT the coin to copy. Make a production first-person RIGHT HAND AND COMPLETE BLACK LEATHER FOREARM sprite atlas for throwing TWO dice supplied separately by the game. NO DICE AND NO COINS in this image. Exact 16 poses, 4 columns by 4 rows, transparent gutters. Same adult light skin, correct five fingers, gritty detailed retro pixel-art shading, black worn leather sleeve as reference. Forearm continues to bottom-right cell edge naturally, never cut at wrist. Palm opens upward, cupped near upper-left of each cell, fingers angled away from viewer. Frames0-3: subtly shifting cupped palm, enough room in palm for two dice. Frames4-7: palm smoothly pushes forward and fingers open to release dice. Frames8-11: open forward hand follows through. Frames12-15: gradually relax fingers and retract. Same camera, scale, light and palm anchor at approximately x=40%,y=28% in every cell; hand and long sleeve fill lower-right. No objects, no scenery, no labels, no mattes, no borders, no extra rows. Crisp pixel clusters matching reference, not photorealistic. Transparent background.",
|
||||
"table": "Reuses assets/animations/coin/table-v1.bin unchanged.",
|
||||
"dice": "Reuses the original cubeCorners3D/cubeFaces3D/cubeColors3D/DrawTumblingDie3D; no generated replacement dice."
|
||||
}
|
||||
8
assets/sprites/dice/prompts-v2.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"mode": "built-in image_gen",
|
||||
"asset": "hands-v2.png",
|
||||
"generation": "exec-4dd19e3a-0d6e-445e-bf78-4c4446b3105d",
|
||||
"prompt_specification": "Transparent 4 by 4 atlas, exactly sixteen consistent first-person right-hand poses in the same black leather cuff, crisp retro pixel-art. Preserve the reference dice identity: small ivory cubes with dark red pips. First four poses: upward cupped palm, two thumb-width dice physically resting together in the centre of the palm, tiny contact shadows and finger overlap, never on the thumb, wrist or fingertips. Remaining twelve poses: empty palm opening, throwing follow-through and retracting. Fixed character, camera, scale, lighting and materials; full forearm to bottom right. No scenery, labels or extra rows.",
|
||||
"references": ["previous native dice-ready screenshot", "hands-v1.png"],
|
||||
"note": "Specification retained from the preceding generation; this is not a verbatim tool-prompt transcript."
|
||||
}
|
||||
6
assets/sprites/hall/prompts-v6.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"mode": "built-in image_gen",
|
||||
"intent": "generate",
|
||||
"output": "wall-paintings-v6.png",
|
||||
"prompt": "Use case: stylized-concept. Asset type: two wall decoration textures for a retro 2.5D casino interior. Create a single sheet with EXACTLY TWO separate square framed paintings in a clean 2-column 1-row layout with generous transparent gutters. Both are strictly front-facing orthographic, identical compact aged brass/gold carved frames, no perspective tilt, no floor, no drop shadow outside the frames, no glow, no words, no letters, no price tags. Left painting: an old American brick downtown street on a rainy evening with warm shop windows and a small red awning; muted teal sky, no modern skyscrapers. Right painting: an atmospheric painted still life of playing cards with indistinct unlettered card faces, red/ivory/green casino chips, a short glass on deep green felt, not a diagram or game UI. Hand-painted, visibly pixel-art shading and crisp silhouettes appropriate to a classic software-rendered casino game, richly detailed but readable when each complete framed painting is reduced to 128x128 pixels. Both complete frames fully visible, each image square and aligned, solid opaque paint/canvas/frame, genuinely transparent background outside and between the two paintings. These will mount flush to actual wooden walls, not float as camera-facing billboards."
|
||||
}
|
||||
BIN
assets/sprites/hall/wall-paintings-v6.png
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
assets/sprites/pyramid/pool-balls-v1.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
4
assets/sprites/pyramid/pool-prompts.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"mode": "built-in",
|
||||
"prompt": "Use case: game-asset. Asset type: transparent sprite atlas for a retro 2.5D casino billiards minigame. Create exactly sixteen separate billiard ball sprites in a clean 4 by 4 equally spaced grid, orthographic straight overhead view, identical radius and center anchor, no perspective. Row 1: white cue ball, solid yellow, solid blue, solid red. Row 2: solid purple, solid orange, solid green, solid burgundy. Row 3: solid black eight ball, yellow stripe on white ball, blue stripe on white ball, red stripe on white ball. Row 4: purple stripe on white ball, orange stripe on white ball, green stripe on white ball, burgundy stripe on white ball. Every colored object ball has a small blank ivory circular number badge centered on top; NO numerals or lettering (engine adds correct digits). Each stripe goes horizontally through center with white caps above and below. Crisp polished shaded pixel art, recognizable high contrast colors, highlight upper left, subtle shading lower right, sharp round contours. Ball-only, no cast shadow outside the ball, no debris, no labels, no cloth, no decoration. Transparent background. Consistent sprite size occupying 65 percent of each grid cell with wide transparent gutters. Square atlas."
|
||||
}
|
||||
BIN
assets/sprites/scratch/coin-edge-v1.png
Normal file
|
After Width: | Height: | Size: 704 KiB |
BIN
assets/sprites/scratch/counter-v1.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
assets/sprites/scratch/foil-v1.png
Normal file
|
After Width: | Height: | Size: 2.6 MiB |
BIN
assets/sprites/scratch/neon-ru-v3.png
Normal file
|
After Width: | Height: | Size: 2.7 MiB |
BIN
assets/sprites/scratch/payout-chips-v1.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
17
assets/sprites/scratch/prompts-v1.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"mode": "built-in image_gen",
|
||||
"ticket": {
|
||||
"file": "ticket-v1.png",
|
||||
"prompt": "Use case: stylized-concept. Asset type: production pixel-art lottery scratch-ticket paper frame for a native retro casino game. Generate a single landscape rectangular ticket seen straight from above, aspect ratio 3:2, on a genuinely transparent background, isolated and unrotated. Same warm lighting and crisp detailed pixel clusters as a richly decorated 1990s casino game. Dark emerald and burgundy printed ornamental borders, fine gold-foil engraved trim, tiny clover and diamond motifs ONLY in the corners. A large clean warm white matte paper central area, entirely blank for the game to draw nine scratching zones. Leave a broad blank emerald header strip within the ticket and a small blank white footer strip. Slightly worn paper edges, tactile stock, subtly embossed decoration. No lettering, no numerals, no scratch windows, no symbols in the central area, no coin, no hands, no scenery, no perspective distortion, no drop shadow extending outside the paper. It must read as an actual printed lottery ticket, not a UI card or a painting."
|
||||
},
|
||||
"coin": {
|
||||
"file": "coin-edge-v1.png",
|
||||
"prompt": "Use case: stylized-concept. Production game sprite animation atlas: exactly FOUR identical small brass coins in one horizontal row, FOUR evenly spaced cells, same fixed scale and same centre anchor. Genuinely transparent background, no scenery or hands. A worn brass casino token tilted steeply up on its thin ridged edge, seen from a first-person overhead view of scratching a flat lottery ticket. Coin face is a narrow visible ellipse, NOT a flat front-facing circle. Its BOTTOM-CENTRE rim is the contact point touching paper; keep that exact bottom-centre point constant in all four poses. Four subtle scraping rock positions (-6 degrees, neutral, +6 degrees, neutral), not spinning/flipping. Detailed engraved diamond emblem with a rim of tiny beads, no text or numerals. Crisp retro pixel-art clusters matching 1990s detailed casino sprites, warm metal highlights, sharp readable reeded edge. A thin coin, not a chunky poker chip. Entire coin contained in each cell, no background shadow, no sparkles, no labels. Single atlas, exactly four poses, no extra rows."
|
||||
},
|
||||
"counter": {
|
||||
"file": "counter-v1.png",
|
||||
"prompt": "Use case: stylized-concept. Asset type: isolated native retro 2.5D casino furniture sprite, front elevation, full object, genuinely transparent background. A waist-height narrow wooden lottery ticket sales counter with a green leather writing top, brass trim, small display of neatly fanned emerald and burgundy paper scratch tickets, and a slim upright sign holder with a blank emerald face. No printed text anywhere. A small tray of brass coins next to the tickets. Warm casino lighting, detailed crisp 1990s pixel-art consistent with Doom-like billboard props, physically plausible furniture proportions. Entire counter legs and base visible, grounded feet, no backdrop, no people, no multiple objects separated as an atlas, no shadow beyond feet. This is one furniture object with its ticket display attached, not a whole room or decorative image."
|
||||
},
|
||||
"foil": {"file": "foil-v1.png", "prompt": "Use case: stylized-concept. Asset type: flat seamless material texture for a retro pixel-art scratch lottery coating. A full-frame opaque landscape swatch of matte SILVER scratch-off latex foil. Fine silvery grey grain, tiny graphite speckles, subtle diagonal security hatching, flat even illumination with restrained metallic highlights. No perspective, no objects, no paper edge, no frame, no letters, no symbols, no numerals, no gradients, no glare spots. Crisp detailed pixel-art texture designed to be readable when reduced to about 100 by 40 game pixels. The entire image is just the silver protective coating material."},
|
||||
"preserved": "Original Clover symbols are reused; the coin hotspot is the bottom-centre rim, not its face."
|
||||
}
|
||||
9
assets/sprites/scratch/prompts-v2.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"mode": "built-in image_gen",
|
||||
"prompts": {
|
||||
"scratch_table_prompt": "Use case: stylized-concept. Production background bitmap for a native retro casino scratch-ticket game, landscape FOUR-TO-THREE composition. A first-person view looking almost directly DOWN at a real lottery counter tabletop, not looking at a person across a gambling table. The entire central area (about 75 percent of image width and 70 percent of image height) is a clean empty dark emerald-green felt writing mat, perfectly flat and nearly orthographic, so a landscape lottery paper ticket can be composited there without floating. Walnut wood edging and restrained brass corner details around the outside. Along the extreme left edge: a small stack of emerald printed paper tickets and a brass coin tray, partly cropped, outside the clean centre. Along the extreme right edge: a warm desk lamp base and small paper slips, partly cropped, also outside the centre. Warm light from upper left, crisp detailed 1990s casino pixel-art clusters, no blur, same rich emerald/burgundy/gold material family as our lottery frame. No dealer, no people, no faces, no hands, no loose coin in the central area, no UI, no text, no numbers, no lottery ticket already placed in the central mat. Centre must be uninterrupted empty green surface extending behind the future ticket. No front-facing upright counter, no horizon, no room view, no gradients. This is a playable close-up tabletop background, not an illustration poster.",
|
||||
"scratch_numbers_prompt": "Use case: stylized-concept. Asset type: retro pixel casino scratch-off paper ticket, one landscape 14:9 flat rectangle viewed exactly from above, full frame. Primary request: a new 'lucky numbers' lottery ticket background in powder blue, deep petrol and metallic silver security-print guilloche, with small embossed number-ball motifs only in four corners. Detailed 1990s adventure-game bitmap art, crisp pixels, paper grain, consistent with an old luxurious casino. Layout: narrow ornate border, dark blank title band at top 8%-19%, absolutely empty light ivory writing area from x8%-92% y28%-80%, a narrow empty ivory footer strip y87%-95%. No letters, no numerals, no scratch panels, no shadows cast outside paper, no perspective, no UI, no watermark. Fill image with the ticket itself; all decorations confined to border/corners so program can overlay live text and scratch surfaces.",
|
||||
"scratch_rows_prompt": "Use case: stylized-concept. Asset type: retro pixel casino scratch-off paper ticket, single landscape 14:9 flat rectangle viewed exactly from above filling frame. Primary request: 'three in a row' themed scratch ticket background, vermilion/red, charcoal and antique gold, decorative embossed cherries and bells ONLY in four corners, subtle sunburst security-print border. Detailed 1990s adventure-game bitmap art, crisp pixels, fine paper grain, old luxurious casino. Layout: narrow ornate border, dark blank title band at top 8%-19%, absolutely empty light ivory writing area from x8%-92% y28%-80%, narrow empty ivory footer strip y87%-95%. No letters, no numbers, no scratch panels, no outside shadows, no perspective, no UI, no watermark. Decorations confined to border and corners so program can overlay live symbols and round scratch spots.",
|
||||
"scratch_instant_prompt": "Use case: stylized-concept. Asset type: retro pixel casino scratch-off paper ticket, one landscape 14:9 flat rectangle viewed exactly from above, full frame. Primary request: instant-prize lottery ticket background, turquoise teal with sunshine yellow and silver, embossed radiant lucky stars and coins confined to four corner motifs and guilloche border. Detailed 1990s adventure-game bitmap art, crisp pixels, fine paper grain, old luxurious casino. Layout: narrow ornate border, deep teal blank title band at top 8%-19%, absolutely empty light ivory writing area from x8%-92% y28%-80%, narrow empty ivory footer strip y87%-95%. No letters, numerals, scratch panels, outside shadows, perspective, UI or watermark. Image is the ticket itself, with empty central area large enough for a single big scratch panel and live prize."
|
||||
}
|
||||
}
|
||||
27
assets/sprites/scratch/prompts-v3.json
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"mode": "built-in image_gen",
|
||||
"intent": "text-localization",
|
||||
"prompt_record": "Recovered edit briefs, not verbatim tool prompts; the exact pre-compaction tool arguments were unavailable.",
|
||||
"shared_edit_brief": "Localize the supplied portrait scratch ticket into Russian. Preserve its illustrated theme, composition, borders and exact number and placement of silver scratch fields. Keep each field empty silver for runtime replacement. Remove the fixed dollar price and numerical maximum-prize advertising so it does not contradict the game's selectable prices and actual awards. Preserve a portrait 3:4 layout.",
|
||||
"assets": [
|
||||
{
|
||||
"input": "codex-clipboard-a52ed500-1ee3-4ee3-bff5-dd0970bfd3d8.png",
|
||||
"output": "neon-ru-v3.png",
|
||||
"generated_file": "exec-3ca37508-f784-4007-af7e-b9c49fcabb28.png",
|
||||
"edit_brief": "Retain the neon cyan/magenta city, chips and diamonds. Russian title: НЕОНОВАЯ УДАЧА. Five winning circles and fifteen player rectangles. Retain number-match and double/ten-times bonus semantics. Replace the numeric top prize with a generic large-prize heading."
|
||||
},
|
||||
{
|
||||
"input": "codex-clipboard-b32c02a1-cd6a-4b39-995d-eecafadf9a67.png",
|
||||
"output": "ruby-ru-v3.png",
|
||||
"generated_file": "exec-255460ed-b60a-43ac-8144-5d8fd5731880.png",
|
||||
"edit_brief": "Retain red rubies, gold ornament and original layout. Russian title: РУБИНОВЫЙ ДЖЕКПОТ. Six winning circles and eighteen player rectangles. Preserve double-prize and all-prizes bonus semantics without advertising a fixed prize ceiling."
|
||||
},
|
||||
{
|
||||
"input": "codex-clipboard-ea66185b-a5a8-4081-b022-e7e04556bded.png",
|
||||
"output": "sea-ru-v3.png",
|
||||
"generated_file": "exec-3bec4802-64d4-4f4b-9be1-4c779ab4b49b.png",
|
||||
"edit_brief": "Retain the blue tropical sea, treasure, ship and gold details. Russian title: ВОЛНА СОКРОВИЩ. Four winning circles and twelve player rectangles. Preserve double-prize and all-prizes bonus semantics without fixed numerical price or maximum-prize claims."
|
||||
}
|
||||
],
|
||||
"packing": "Offline pack_scratch_portraits.py resizes artwork to 540x720 BGRA and extracts 20/24/16 exact silver-region ID masks. All interactive rendering and gameplay remain MASM."
|
||||
}
|
||||
7
assets/sprites/scratch/prompts-v4.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"mode": "built-in image_gen",
|
||||
"intent": "generate",
|
||||
"output": "payout-chips-v1.png",
|
||||
"transparent_background": true,
|
||||
"prompt": "Use case: stylized-concept. Asset type: isolated game sprite, casino payout chips for a retro 2.5D pixel-art casino. Create ONE compact cluster of three short stacks of casino chips, one deep emerald with ivory edge marks, one red with ivory edge marks, one warm ivory with dark emerald edge marks, and two small brass tokens lying beside their bases. View is almost overhead, slightly tilted toward the player, matching an overhead green felt writing desk lit warmly from upper left. Entire cluster fully in frame, clearly separated object silhouette, transparent background including all empty space. No desk, no tray, no hands, no cards, no words, no denomination numerals, no borders, no glow, no floating parts. All stacks rest on the same contact plane and cast a short subtle contact shadow. Detailed hand-painted pixel-art edges, crisp distinguishable chip layers, restrained highlights, not glossy photorealistic 3D. Wide compact silhouette suitable for reduction to a 96 by 72 pixel sprite. This is a new asset, not a sprite sheet."
|
||||
}
|
||||
BIN
assets/sprites/scratch/ruby-ru-v3.png
Normal file
|
After Width: | Height: | Size: 2.6 MiB |
BIN
assets/sprites/scratch/sea-ru-v3.png
Normal file
|
After Width: | Height: | Size: 3 MiB |
BIN
assets/sprites/scratch/table-v1.png
Normal file
|
After Width: | Height: | Size: 2.9 MiB |
BIN
assets/sprites/scratch/ticket-instant-v1.png
Normal file
|
After Width: | Height: | Size: 3.4 MiB |
BIN
assets/sprites/scratch/ticket-numbers-v1.png
Normal file
|
After Width: | Height: | Size: 3.6 MiB |
BIN
assets/sprites/scratch/ticket-rows-v1.png
Normal file
|
After Width: | Height: | Size: 2.9 MiB |
BIN
assets/sprites/scratch/ticket-v1.png
Normal file
|
After Width: | Height: | Size: 2.8 MiB |
BIN
bin/poker.exe
31
build.bat
|
|
@ -1,7 +1,21 @@
|
|||
@echo off
|
||||
setlocal
|
||||
|
||||
rem Check standard MASM32 paths first
|
||||
rem Check Visual Studio / MSVC BuildTools first (modern Windows compatible)
|
||||
set "MSVC_BIN=C:\Program Files (x86)\Microsoft Visual Studio\18\BuildTools\VC\Tools\MSVC\14.50.35717\bin\Hostx64\x86"
|
||||
set "SDK_LIB=C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\um\x86"
|
||||
set "UCRT_LIB=C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\ucrt\x86"
|
||||
set "VC_LIB=C:\Program Files (x86)\Microsoft Visual Studio\18\BuildTools\VC\Tools\MSVC\14.50.35717\lib\x86"
|
||||
|
||||
if exist "%MSVC_BIN%\ml.exe" (
|
||||
set "ML_EXE=%MSVC_BIN%\ml.exe"
|
||||
set "LINK_EXE=%MSVC_BIN%\link.exe"
|
||||
set LIB_PATHS=/LIBPATH:"%SDK_LIB%" /LIBPATH:"%UCRT_LIB%" /LIBPATH:"%VC_LIB%"
|
||||
set "EXTRA_FLAGS=/NOLOGO /SUBSYSTEM:WINDOWS"
|
||||
goto do_build
|
||||
)
|
||||
|
||||
rem Check standard MASM32 paths
|
||||
if exist "D:\MASM32\masm32\bin\ml.exe" (
|
||||
set "ML_EXE=D:\MASM32\masm32\bin\ml.exe"
|
||||
set "LINK_EXE=D:\MASM32\masm32\bin\link.exe"
|
||||
|
|
@ -16,7 +30,6 @@ if exist "C:\masm32\bin\ml.exe" (
|
|||
set "EXTRA_FLAGS=/SUBSYSTEM:WINDOWS /RELEASE /VERSION:4.0"
|
||||
goto do_build
|
||||
)
|
||||
|
||||
if exist "F:\MASM32\masm32\bin\ml.exe" (
|
||||
set "ML_EXE=F:\MASM32\masm32\bin\ml.exe"
|
||||
set "LINK_EXE=F:\MASM32\masm32\bin\link.exe"
|
||||
|
|
@ -25,20 +38,6 @@ if exist "F:\MASM32\masm32\bin\ml.exe" (
|
|||
goto do_build
|
||||
)
|
||||
|
||||
rem Fallback to Visual Studio / MSVC BuildTools
|
||||
set "MSVC_BIN=C:\Program Files (x86)\Microsoft Visual Studio\18\BuildTools\VC\Tools\MSVC\14.50.35717\bin\Hostx64\x86"
|
||||
set "SDK_LIB=C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\um\x86"
|
||||
set "UCRT_LIB=C:\Program Files (x86)\Windows Kits\10\Lib\10.0.26100.0\ucrt\x86"
|
||||
set "VC_LIB=C:\Program Files (x86)\Microsoft Visual Studio\18\BuildTools\VC\Tools\MSVC\14.50.35717\lib\x86"
|
||||
|
||||
if exist "%MSVC_BIN%\ml.exe" (
|
||||
set "ML_EXE=%MSVC_BIN%\ml.exe"
|
||||
set "LINK_EXE=%MSVC_BIN%\link.exe"
|
||||
set LIB_PATHS=/LIBPATH:"%SDK_LIB%" /LIBPATH:"%UCRT_LIB%" /LIBPATH:"%VC_LIB%"
|
||||
set "EXTRA_FLAGS=/NOLOGO /SUBSYSTEM:WINDOWS"
|
||||
goto do_build
|
||||
)
|
||||
|
||||
echo [ERROR] No compatible MASM/MSVC assembler found!
|
||||
goto err
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace AssemblerCasinoLauncher
|
|||
{
|
||||
static class Program
|
||||
{
|
||||
const string ExpectedPokerSha256 = "7E7165F5B9287FCF0F7A7E8F526DD23C0DA5F3A6CF72F08D1A40EB548FFCD428";
|
||||
const string ExpectedPokerSha256 = "3CE946233ABE1D9139501EB56A75B2BE0D9A99714048C5F0A56A150D35F2295C";
|
||||
|
||||
[STAThread]
|
||||
static void Main()
|
||||
|
|
|
|||
144
casino3d.inc
|
|
@ -167,6 +167,8 @@ include src_graphics\unavailable_data.inc
|
|||
include src_graphics\native_slots_data.inc
|
||||
include src_graphics\native_clover_data.inc
|
||||
include src_graphics\native_coin_data.inc
|
||||
include src_graphics\native_dice_data.inc
|
||||
include src_graphics\scratch_data.inc
|
||||
|
||||
.data
|
||||
ALIGN 4
|
||||
|
|
@ -3081,13 +3083,15 @@ die_pips_done:
|
|||
DrawCrapsDie ENDP
|
||||
|
||||
InitDiceGame PROC
|
||||
call LoadNativeDiceArt3D
|
||||
mov diceExitQueued3D,0
|
||||
mov dice3d_state, 0
|
||||
mov dice3d_timer, 0
|
||||
mov dice3d_win, 0
|
||||
ret
|
||||
InitDiceGame ENDP
|
||||
|
||||
HandleDiceInput PROC
|
||||
HandleDiceRules3D PROC
|
||||
cmp dice3d_state, 0
|
||||
je dice_handle_idle
|
||||
cmp dice3d_state, 1
|
||||
|
|
@ -3233,121 +3237,10 @@ dice_handle_result:
|
|||
invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1
|
||||
dice_done:
|
||||
ret
|
||||
HandleDiceInput ENDP
|
||||
HandleDiceRules3D ENDP
|
||||
|
||||
RenderDiceGame PROC uses ebx esi edi
|
||||
local kx:DWORD
|
||||
|
||||
; Mahogany frame & Deep Felt Green table
|
||||
invoke DrawBox, 0, 0, 320, 240, 00140906h
|
||||
invoke DrawBoxBorder, 6, 6, 308, 228, 000A3816h, 00FFD700h, 2
|
||||
|
||||
; Header
|
||||
invoke DrawBoxBorder, 20, 12, 280, 26, 00072E13h, 00FFD700h, 2
|
||||
invoke DrawString8x8, 116, 21, OFFSET textDiceTitle, 00FFFF00h
|
||||
|
||||
; Status
|
||||
invoke DrawBoxBorder, 20, 44, 110, 18, 00072E13h, 001B4B22h, 1
|
||||
invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch
|
||||
invoke FormatNumber, bankroll, OFFSET hudNumBuffer
|
||||
invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch
|
||||
|
||||
invoke DrawBoxBorder, 190, 44, 110, 18, 00072E13h, 001B4B22h, 1
|
||||
invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h
|
||||
invoke FormatNumber, dice3d_bet, OFFSET hudNumBuffer
|
||||
invoke DrawString8x8, 258, 49, OFFSET hudNumBuffer, 00FFD700h
|
||||
|
||||
; [1] רÒ
|
||||
cmp dice3d_choice, 1
|
||||
jne dice_even_inactive
|
||||
invoke DrawBoxBorder, 16, 70, 88, 48, 00072E13h, 00FFFF00h, 2
|
||||
invoke DrawString8x8, 30, 76, OFFSET textDiceEven, 00FFFF00h
|
||||
invoke DrawString8x8, 22, 90, OFFSET textDiceEvenNums, 00FFD700h
|
||||
invoke DrawString8x8, 26, 104, OFFSET textCoinSelected, 003CFF3Ch
|
||||
jmp dice_odd_side
|
||||
dice_even_inactive:
|
||||
invoke DrawBoxBorder, 16, 70, 88, 48, 00072E13h, 001B4B22h, 1
|
||||
invoke DrawString8x8, 30, 76, OFFSET textDiceEven, 00D0D8E0h
|
||||
invoke DrawString8x8, 22, 90, OFFSET textDiceEvenNums, 0080B090h
|
||||
|
||||
dice_odd_side:
|
||||
; [2] ÍÅ×ÅÒ
|
||||
cmp dice3d_choice, 2
|
||||
jne dice_odd_inactive
|
||||
invoke DrawBoxBorder, 216, 70, 88, 48, 00072E13h, 00FFFF00h, 2
|
||||
invoke DrawString8x8, 226, 76, OFFSET textDiceOdd, 00FFFF00h
|
||||
invoke DrawString8x8, 224, 90, OFFSET textDiceOddNums, 00FFD700h
|
||||
invoke DrawString8x8, 226, 104, OFFSET textCoinSelected, 003CFF3Ch
|
||||
jmp dice_center_cubes
|
||||
dice_odd_inactive:
|
||||
invoke DrawBoxBorder, 216, 70, 88, 48, 00072E13h, 001B4B22h, 1
|
||||
invoke DrawString8x8, 226, 76, OFFSET textDiceOdd, 00D0D8E0h
|
||||
invoke DrawString8x8, 224, 90, OFFSET textDiceOddNums, 0080B090h
|
||||
|
||||
dice_center_cubes:
|
||||
call RenderDiceThrow3D
|
||||
|
||||
cmp dice3d_state, 1
|
||||
je dice_render_rolling
|
||||
cmp dice3d_state, 2
|
||||
je dice_render_result
|
||||
jmp dice_render_keys
|
||||
|
||||
dice_render_rolling:
|
||||
invoke DrawString8x8, 76, 138, OFFSET textDiceRolling, 00FFFF00h
|
||||
jmp dice_render_keys
|
||||
|
||||
dice_render_result:
|
||||
invoke DrawBoxBorder, 36, 130, 248, 36, 00072E13h, 00FFD700h, 1
|
||||
invoke DrawString8x8, 44, 135, OFFSET textDiceSumHdr, 00FFD700h
|
||||
invoke FormatNumber, dice3d_val1, OFFSET hudNumBuffer
|
||||
invoke DrawString8x8, 92, 135, OFFSET hudNumBuffer, 00FFFF00h
|
||||
invoke DrawString8x8, 110, 135, OFFSET textDicePlus, 00FFD700h
|
||||
invoke FormatNumber, dice3d_val2, OFFSET hudNumBuffer
|
||||
invoke DrawString8x8, 126, 135, OFFSET hudNumBuffer, 00FFFF00h
|
||||
invoke DrawString8x8, 144, 135, OFFSET textDiceEqual, 00FFD700h
|
||||
invoke FormatNumber, dice3d_sum, OFFSET hudNumBuffer
|
||||
invoke DrawString8x8, 168, 135, OFFSET hudNumBuffer, 00FFFF00h
|
||||
|
||||
mov eax, dice3d_sum
|
||||
and eax, 1
|
||||
jnz dice_render_odd_res
|
||||
invoke DrawString8x8, 186, 135, OFFSET textDiceEvenResult, 003CFF3Ch
|
||||
jmp dice_render_outcome
|
||||
dice_render_odd_res:
|
||||
invoke DrawString8x8, 186, 135, OFFSET textDiceOddResult, 003CFF3Ch
|
||||
|
||||
dice_render_outcome:
|
||||
mov eax, dice3d_win
|
||||
test eax, eax
|
||||
jz dice_render_loss_outcome
|
||||
invoke DrawString8x8, 68, 150, OFFSET textDiceWin, 003CFF3Ch
|
||||
invoke FormatNumber, dice3d_win, OFFSET hudNumBuffer
|
||||
invoke DrawString8x8, 156, 150, OFFSET hudNumBuffer, 003CFF3Ch
|
||||
invoke DrawString8x8, 188, 150, OFFSET textDiceWinMult, 003CFF3Ch
|
||||
jmp dice_render_keys
|
||||
|
||||
dice_render_loss_outcome:
|
||||
invoke DrawString8x8, 116, 150, OFFSET textDiceLose, 00FF6464h
|
||||
|
||||
dice_render_keys:
|
||||
mov kx, 16
|
||||
xor eax, eax
|
||||
cmp dice3d_choice, 1
|
||||
sete al
|
||||
invoke DrawKeycap3D, kx, 192, OFFSET textDiceKey1, eax
|
||||
add kx, eax
|
||||
|
||||
xor eax, eax
|
||||
cmp dice3d_choice, 2
|
||||
sete al
|
||||
invoke DrawKeycap3D, kx, 192, OFFSET textDiceKey2, eax
|
||||
add kx, eax
|
||||
|
||||
invoke DrawKeycap3D, kx, 192, OFFSET textDiceKeySpace, 1
|
||||
add kx, eax
|
||||
|
||||
invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0
|
||||
RenderDiceGame PROC
|
||||
call RenderNativeDice3D
|
||||
ret
|
||||
RenderDiceGame ENDP
|
||||
|
||||
|
|
@ -5140,6 +5033,8 @@ include src_graphics\scene_animation.inc
|
|||
include src_graphics\native_slots.inc
|
||||
include src_graphics\native_clover.inc
|
||||
include src_graphics\native_coin.inc
|
||||
include src_graphics\native_dice.inc
|
||||
include src_graphics\scratch.inc
|
||||
include src_graphics\graphic_profiles.inc
|
||||
include src_graphics\city_arrival_scene.inc
|
||||
include src_graphics\arrival_scene.inc
|
||||
|
|
@ -5212,6 +5107,16 @@ dispatch_frame:
|
|||
xor paused3D, 1
|
||||
jmp engine_tick
|
||||
leave_table:
|
||||
cmp engineMode,MODE_SCRATCH
|
||||
jne @F
|
||||
call LeaveScratch3D
|
||||
jmp engine_tick
|
||||
@@:
|
||||
cmp engineMode,MODE_DICE
|
||||
jne @F
|
||||
call DiceEscape3D
|
||||
jmp engine_tick
|
||||
@@:
|
||||
call CardTableEscape3D
|
||||
test eax, eax
|
||||
jnz engine_tick
|
||||
|
|
@ -5264,6 +5169,14 @@ check_walk_mode:
|
|||
call RenderMinimap
|
||||
jmp present_frame
|
||||
check_slots_mode:
|
||||
cmp engineMode,MODE_SCRATCH
|
||||
jne @F
|
||||
call HandleScratch3D
|
||||
cmp engineMode,MODE_WALK
|
||||
je check_walk_mode
|
||||
call RenderScratch3D
|
||||
jmp present_frame
|
||||
@@:
|
||||
cmp engineMode,MODE_CLOVER
|
||||
jne @F
|
||||
call HandleNativeClover3D
|
||||
|
|
@ -5494,6 +5407,7 @@ engine_idle:
|
|||
invoke Sleep, 50
|
||||
jmp engine_loop
|
||||
engine_shutdown:
|
||||
call SettleScratchOnQuit3D
|
||||
call UnlockMouse3D
|
||||
cmp hRaycastThread, 0
|
||||
je @F
|
||||
|
|
|
|||
BIN
dist/Assembler Casino.exe
vendored
103
docs/BILLIARDS_CURRENT.md
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
# Native Billiards
|
||||
|
||||
The casino table opens a selection of free Russian pyramid and American
|
||||
eight-ball pool. All game simulation, rules, input, rendering and prediction
|
||||
run in x86 MASM. Python only normalizes generated art and verifies captured
|
||||
frames; no Python or external physics engine ships as the game runtime.
|
||||
|
||||
## Eight-Ball Turn Regression
|
||||
|
||||
The previous implementation retained a default/previous called ball and pocket
|
||||
for human shots, while the AI supplied a new call before striking. A normal
|
||||
human pot could therefore pass the turn despite correct contact and no foul.
|
||||
Native regression case 12 reproduced that failure through aim, Space, rendering
|
||||
and actual fixed-step motion before the fix. Scoring also credited every pot
|
||||
to the shooter instead of the owner of the solid/striped group.
|
||||
|
||||
Automatic pre-shot calls now come from the existing physics prediction; manual
|
||||
ball and pocket overrides remain binding. Group credit is reconstructed from
|
||||
the actual pocketed balls and assigned groups. No collision, rail, pocket,
|
||||
friction, force or pyramid-rule formulas were changed for this correction.
|
||||
|
||||
## Controls
|
||||
|
||||
- Select a discipline with the mouse or 1/2.
|
||||
- Left-click/drag on the cloth to aim; arrows provide fine aim. Shift makes
|
||||
arrow aim slower. Up/down or the force slider changes shot power.
|
||||
- Space or the shot button strikes. P or the guide button toggles prediction.
|
||||
- Pyramid: right-click a ball, B or the cue button selects the cue ball.
|
||||
The break uses the colored ball; Shift-click places it in the home area.
|
||||
- Eight-ball: right-click a legal object ball or use the order button/B to
|
||||
call it. Right-click a pocket or click the pocket indicator to call a pocket.
|
||||
Without an explicit override, the shared physics preview supplies the obvious
|
||||
intended ball and pocket before striking, even with the guide hidden. Ball and
|
||||
pocket overrides are independent and reset after settlement, not before it.
|
||||
An unknown automatic call is shown as a dash rather than a stale previous call.
|
||||
After a foul, click a clear place on the cloth to position the cue ball.
|
||||
- Use the exit button or the casino's Escape flow to leave the table.
|
||||
|
||||
## Rules
|
||||
|
||||
Free pyramid uses fifteen white numbered balls and one colored ball, with
|
||||
any active ball eligible as cue after the break. The first player to eight
|
||||
credited balls wins. Legal cue-ball pots count after contact. Incorrectly
|
||||
potted balls are respotted; the incoming player may take one penalty ball
|
||||
and choose who plays next. Invalid breaks offer acceptance or a partial
|
||||
re-rack. Ordered cushion/crossing histories determine legal non-pot shots.
|
||||
|
||||
Eight-ball uses the white cue, seven solids, seven stripes and black eight.
|
||||
Groups are assigned by a legal called pot after the break. A wrong first
|
||||
contact, scratch or no post-contact cushion/pot gives ball in hand.
|
||||
The eight must be called and pocketed in the nominated pocket after clearing
|
||||
the player's group; an early eight loses. A break eight is respotted, not an
|
||||
automatic win. Invalid non-scratch breaks offer acceptance or a new break.
|
||||
Pocketed solids/stripes are credited to their group's player, independently of
|
||||
who struck or whether a foul occurred. Once groups are assigned, this includes
|
||||
balls pocketed earlier on the open table. The white and black balls never add
|
||||
to the group count. A legal called pot keeps the shooter at the table; a miss
|
||||
passes the turn and a foul gives the opponent ball in hand.
|
||||
|
||||
These are playable casino adaptations, not a complete tournament referee.
|
||||
Shot-clock/lag/protests, airborne balls, jump shots, deliberate push shots,
|
||||
and all special tournament options for scratch/eight on the break are not
|
||||
implemented. Backspin, topspin, side spin and curved trajectories are also
|
||||
not implemented. Do not describe this simulation as ideal real-world physics.
|
||||
|
||||
## Physics And Prediction
|
||||
|
||||
- Q16.16 positions/velocities; fixed 2 ms steps independent of frame timing.
|
||||
- Equal-mass normal impulses, separation, restitution and rolling deceleration.
|
||||
- Distinct narrow pyramid / wider pool pockets and rounded jaw colliders.
|
||||
- Pocket AABB rejection precedes squared-distance math, preventing long-vector
|
||||
overflow from deleting a ball at the opposite end of the table.
|
||||
- Fine aim uses 4096 interpolated phases and 64-bit projection numerators.
|
||||
- Preview calls the same `PoolStep3D` as actual play. It restores all ball
|
||||
arrays, collision histories and physics event fields before returning.
|
||||
- Cached preview depends on the layout, discipline, cue, direction and force.
|
||||
It samples up to 6000 steps (12 seconds), showing cue/object paths including
|
||||
rebounds. This is a bounded guide; a moving ball beyond that horizon is not
|
||||
claimed to have reached its final position.
|
||||
|
||||
## Verification
|
||||
|
||||
`tools/tests/test_casino_actions.ps1 -SkipPreview` runs native MASM assertions,
|
||||
including disappearance regression, all pockets, 100 breaks, pyramid scoring
|
||||
and penalties, eight-ball groups/fouls/wins, choice UI, and preview/live parity.
|
||||
`eightball_regression.inc` adds actual aim/Space/render/physics sequences for
|
||||
consecutive human pots, both actors, hidden/visible guides, manual calls and
|
||||
group-based credit. `test_billiards_module.ps1` runs these plus the pre-existing
|
||||
pyramid/choice tests against fresh MASM code and the native graphics helpers.
|
||||
`tools/tests/check_billiards.py --parity` checks actual framebuffer captures
|
||||
and equality of tested versus shipping machine-code procedures.
|
||||
|
||||
Generated art and exact built-in prompts are under `assets/sprites/pyramid`.
|
||||
Packed game assets are under `assets/animations/pyramid`.
|
||||
|
||||
## References
|
||||
|
||||
- [FBSR pyramid rules, September 2025](https://www.fbsrf.ru/sites/default/files/04-novaya_redakciya_pravil_piramidy_2025-09.pdf)
|
||||
- [WPA Rules of Play, January 2026](https://www.wpapool.com/wp-content/uploads/2026/01/2026.01.02-WPA-Rules.pdf)
|
||||
- [Pooltool physics model organization](https://pooltool.readthedocs.io/en/latest/resources/custom_physics.html)
|
||||
|
||||
Pooltool is a reference for separating motion and collision models, not a
|
||||
runtime dependency. No Pooltool source was copied into the MASM game.
|
||||
|
|
@ -1,5 +1,10 @@
|
|||
# Native Billiards
|
||||
|
||||
This is the historical first-implementation plan. Current disciplines,
|
||||
controls, physics coefficients and verification are documented in
|
||||
[BILLIARDS_CURRENT.md](BILLIARDS_CURRENT.md); use that document for the game
|
||||
now shipping rather than the older controls and coefficients below.
|
||||
|
||||
The first playable implementation is in `src_graphics/billiards.inc`, entirely
|
||||
MASM32. The simulation uses positions and velocities, not predetermined shots.
|
||||
|
||||
|
|
|
|||
52
docs/CITY_WAKE_SCENE.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Alley Wake-Up
|
||||
|
||||
The Eblan Games intro leads into the exterior cinematic on every launch.
|
||||
Runtime camera, weather, sprite playback, compositing and input remain MASM.
|
||||
PNG generation and normalization are offline tools only.
|
||||
|
||||
The protagonist opens their eyes while seated on the alley ground. Bent knees
|
||||
remain in the foreground while a scruffy cyberpunk rocker crouches nearby and
|
||||
speaks. The agreed dialogue is shown as Russian subtitles, without synthesized
|
||||
voice: "Вставай, самурай, пора дэпнуть все в казино".
|
||||
|
||||
The protagonist raises a cigarette, opens and ignites a flip-top lighter,
|
||||
looks into the cloudy sky and exhales, then rises smoothly, turns right and discards the butt
|
||||
into the existing projected dumpster mouth and follows the city route to the
|
||||
guards. Profile selection still happens at the casino entrance. Enter can
|
||||
skip to the guards; existing Escape handling is preserved.
|
||||
|
||||
The seated view faces east, toward the rocker. Dumpsters are south of the
|
||||
protagonist, off-screen to their right. The separate look-right phase rotates
|
||||
the camera only after standing; the throw then uses the real dumpster mouth.
|
||||
Traffic timing follows the pre-alley duration, preserving the safe red-light
|
||||
crossing after the longer wake-up sequence.
|
||||
|
||||
There are thirty-two grounded rocker poses and sixteen lighter poses. The
|
||||
speaking cycle has sixteen distinct crouched poses, then eight rise/turn poses
|
||||
and eight walking-away poses. The coat's red SAMURAI back emblem follows the
|
||||
[official jacket reference](https://www.cyberpunk.net/en/news/30631/pre-order-your-samurai-bomber-jacket-now).
|
||||
Character
|
||||
normalization uses whole connected silhouettes rather than nominal atlas cells,
|
||||
so neighbouring fragments cannot move the feet anchor. Generated assets and
|
||||
exact prompts are under `assets/sprites/arrival/wake-*`; packed runtime assets
|
||||
are under `assets/animations/arrival/wake-*`.
|
||||
|
||||
The lighter forearm is a separate continuous leather sleeve placed underneath
|
||||
the animated cuff using measured per-frame anchors. It extends out of the
|
||||
viewport rather than ending at a floating wrist. New vent/poster/crate/cabinet
|
||||
materials are in `alley-materials-v1.bin`; wall-mounted fittings, drainage
|
||||
pipes, stacked crates and a floor drain use actual ray/depth-tested surfaces.
|
||||
The centre walking strip and the right-hand dumpster reveal remain clear.
|
||||
`wake-v2-prompts.json` records all three built-in image-generation prompts.
|
||||
|
||||
Rain uses three visual-depth layers with different speeds, length and opacity.
|
||||
Streaks blend into the rendered scene rather than replacing it with blue blocks.
|
||||
Ground splashes are rejected behind nearer geometry. Weather reads cinematic
|
||||
time, not the gameplay random generator. Looking vertically into the sky blends
|
||||
the raycast view into the sky rather than abruptly switching projections.
|
||||
|
||||
Verification uses the actual native action-test renderer, camera continuity
|
||||
samples, route/vehicle checks, profile transitions, packed-asset checks and
|
||||
framebuffer sequences. `check_arrival_frames.py` writes wake/ignition preview
|
||||
GIFs from those native captures. `check_city_wake.py --parity` checks dialogue,
|
||||
anchors and equality of shipping/tested cinematic procedures.
|
||||
32
docs/DICE_FIRST_PERSON.md
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# First-Person Dice
|
||||
|
||||
The ivory/red identity and MASM triangle renderer are retained. Held dice are
|
||||
now integrated into the first four hand poses, with skin contact and shading,
|
||||
rather than painted as unrelated cubes over the palm. Once released, procedural
|
||||
MASM cubes take over at anchors measured from the last held sprite.
|
||||
|
||||
The scene reuses the coin table/dealer art and adds sixteen generated hand
|
||||
poses with a full black-leather cuff. Preparation lasts 240 ms, followed by the
|
||||
original three-bounce curve remapped into the remaining 1360 ms. The unchanged
|
||||
parity wager settles once at 1600 ms. The stationary top faces and explicit
|
||||
Russian sum/payout strip reveal the result. Ready and result states do not
|
||||
consume random numbers during rendering.
|
||||
|
||||
Rotation completes full revolutions with eased angular speed. The resting
|
||||
orientation is a yaw on the cloth plane, viewed from above, without sideways
|
||||
roll. A projected bottom-face contact shadow and soft ambient shadow attach
|
||||
each settled cube to the felt. Opposite faces sum to seven.
|
||||
|
||||
Mouse buttons map into the original keyboard rules. Escape or the Exit button
|
||||
queues departure during a paid throw; settlement occurs before returning to
|
||||
the hall. W/S, arrows, 1/2 and Space remain supported.
|
||||
|
||||
All rendering, input, animation, loading and gameplay are MASM. The Python
|
||||
script only normalizes a transparent sprite atlas offline. Built-in generation
|
||||
specification and provenance: `assets/sprites/dice/prompts-v2.json`.
|
||||
|
||||
Verification: the native action suite covers 300 paid throws at four update
|
||||
rates, queued exits, mouse controls, missing-art fallback, six checkpoints and
|
||||
forty production-renderer animation frames, release-boundary snapshots and all
|
||||
six top-face results. `check_dice_scene.py --parity`
|
||||
compares shipped and tested procedures and checks native Russian result glyphs.
|
||||
185
docs/SCRATCH_TICKETS.md
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
# Scratch Tickets
|
||||
|
||||
The runtime is MASM-only. Python only normalizes generated artwork and checks
|
||||
native framebuffer captures; there is no browser or console implementation.
|
||||
|
||||
## Scene
|
||||
|
||||
A dedicated ticket counter sits at hall coordinates (29,7.5), against the
|
||||
right-wing wall near Durak. Approach it from the north. It has a grounded sprite and a solid collision footprint. The
|
||||
interaction opens an overhead writing mat without launching another
|
||||
window. The tabletop, paper, silver foil, counter and four tilted-coin poses are original
|
||||
built-in ImageGen assets. Symbols reuse the existing Clover art.
|
||||
|
||||
The cursor hotspot is the bottom-centre scraping rim, (32,60) in a 64x64 sprite.
|
||||
Pointer coordinates use the presented viewport, including letterboxing. Left
|
||||
button capture ends on mouse-up, lost capture, lost focus or scene exit. Mouse
|
||||
events are processed individually, including gestures completed between ticks.
|
||||
Strokes interpolate a narrow elliptical rim every three native pixels.
|
||||
|
||||
## Presentation
|
||||
|
||||
Purchasing slides the entire ticket onto the mat, including its live coating
|
||||
and printed contents, with a paper-shaped contact shadow. Presentation lasts
|
||||
900 ms; pointer scratching and view changes are blocked until it settles.
|
||||
Portrait tickets arrive at full-ticket scale and smoothly zoom into the playing
|
||||
fields over the final 350 ms. Paper/zoom use an elapsed-time smoothstep, not a
|
||||
fixed animation-frame list. Exiting the scene cancels the presentation, not the
|
||||
already-paid ticket.
|
||||
|
||||
Fresh scratches emit three silver fragments into a 64-slot cosmetic pool.
|
||||
Positions/velocities use 8.8 fixed point, gravity advances in fixed 8 ms steps,
|
||||
and fragments settle on the mat before expiring. A private visual seed means
|
||||
particles never consume the ticket RNG. Hovering and already-erased coating
|
||||
produce neither fragments nor scraping audio; scraping audio is throttled to
|
||||
one short sound per 150 ms.
|
||||
|
||||
Positive gross payouts display a grounded chip stack beside the ticket and
|
||||
five small tokens travelling toward the bank display. The cosmetic payout
|
||||
clock lasts 1800 ms. Settlement itself remains immediate and single-shot;
|
||||
the animation cannot issue money, delay saving or block exit/new purchases.
|
||||
Portrait winning fields also receive a pale green substrate inside their exact
|
||||
source-space masks. Covered numbers are never tinted through the coating.
|
||||
|
||||
The payout-chip sprite was generated with built-in ImageGen, then normalized
|
||||
offline to 96x72 binary-alpha BGRA. Its exact prompt is stored in
|
||||
`assets/sprites/scratch/prompts-v4.json`. Three original short PCM effects
|
||||
(paper slide, scrape and payout tokens) are generated offline by
|
||||
`tools/generators/pack_scratch_polish.py`. Rendering, animation clocks, input
|
||||
gates, debris physics and audio triggers are all assembly.
|
||||
|
||||
Each coating has its own byte mask (up to 240x120, nine slots). Repeated strokes do not
|
||||
increment coverage twice, gutters and paper cannot be scratched, and a panel
|
||||
cleans its remaining fragments after 72 percent coverage. Particles use no
|
||||
gameplay randomness. Rendering is deterministic and cannot reroll a ticket.
|
||||
|
||||
## Rules
|
||||
|
||||
Prices: 50, 200 or 500 fictional chips. These are price tiers, not ticket types.
|
||||
The upper-right "VID BILETA" control opens a seven-row named catalogue with
|
||||
thumbnails. A short click keeps its original press coordinates even if the
|
||||
pointer moves before the next game tick. Escape closes the catalogue first,
|
||||
then returns to the hall on a subsequent press.
|
||||
|
||||
The original four tickets retain their distinct artwork and rules:
|
||||
|
||||
- Golden Triple: nine rectangular areas; three identical symbols anywhere pay
|
||||
the printed multiplier, including the stake. Exactly one winning triple or
|
||||
no triples at all.
|
||||
- Lucky Numbers: three winning numbers above six player numbers. A match pays
|
||||
the amount printed below the matching player number. All numbers are 1..30;
|
||||
winning numbers are distinct, with exactly one matching player number on a
|
||||
winning ticket and none on a losing ticket. The 104x34 panels leave separate
|
||||
printed labels for the winning-number row and player-number rows.
|
||||
- Three in a Row: nine circular areas. Only three matching symbols in the same
|
||||
horizontal row pay. A scattered or diagonal triple is not a win.
|
||||
- Instant Luck: one large 240x120 area reveals the direct gross prize, including
|
||||
zero for a losing ticket.
|
||||
|
||||
Three additional portrait tickets preserve the layouts of the user's supplied
|
||||
images, localized into Russian using built-in ImageGen:
|
||||
|
||||
- Neon Fortune: five winning-number circles and fifteen player fields.
|
||||
Matching numbers pay the amount below them; x2 pays twice the printed prize,
|
||||
x10 pays ten times the printed prize.
|
||||
- Ruby Jackpot: six winning-number circles and eighteen player fields.
|
||||
Matching numbers and x2 work as above; the ALL marker pays every player prize.
|
||||
- Treasure Wave: four winning-number circles and twelve player fields, with
|
||||
matching numbers, x2 and ALL as on Ruby Jackpot.
|
||||
|
||||
The native bonus markers are x2, x10 and the Russian ALL abbreviation; the
|
||||
adjacent native rules use the same markers. All-prizes overrides individual
|
||||
awards, never paying the same prize twice. Winning numbers are distinct 1..60.
|
||||
The original artwork's fixed prices and advertised maximum jackpots were
|
||||
removed: the actual selected price and payout are shown by the native HUD.
|
||||
|
||||
Full-ticket preview preserves the 3:4 aspect ratio. Purchase automatically
|
||||
zooms into the play area; the +/- control, Z and mouse wheel switch views.
|
||||
Amounts are printed under player numbers in the enlarged view. Hovering a
|
||||
fully uncovered field shows its actual award, never a covered field's prize.
|
||||
Each supplied silver region has an exact source-space ID mask. Rounded circles
|
||||
and decorated frames are not rectangular scratch surfaces. Scaling covers the
|
||||
whole source footprint of each screen pixel, so both views can be fully scratched
|
||||
and switching views cannot restore removed coating.
|
||||
|
||||
New tickets clear old coating particles, so the previous ticket cannot leave
|
||||
scraps over the next one's opaque fields. Ticket types can change only before
|
||||
purchase or after settlement.
|
||||
Prices and type are locked while a paid ticket is active. The rules, paper
|
||||
contents, outcome and amount are fixed at purchase, never while scratching.
|
||||
|
||||
| Outcome | Ideal 0..999 rolls | Gross Multiplier |
|
||||
| --- | --- | --- |
|
||||
| No prize | 600 | 0 |
|
||||
| Clover | 100 | 1 |
|
||||
| Lemon | 100 | 1 |
|
||||
| Cherries | 110 | 2 |
|
||||
| Bell | 50 | 3 |
|
||||
| Diamond | 25 | 5 |
|
||||
| Chest | 12 | 10 |
|
||||
| Seven | 3 | 25 |
|
||||
|
||||
The original four tickets' ideal table has 89% gross return; the existing engine's range generator has
|
||||
modulo bias, so this is not an exact measured return guarantee. The ticket is
|
||||
charged once. Revealing all panels settles it once, with the existing billion-
|
||||
chip balance cap (one panel for Instant Luck, nine for the other original types,
|
||||
20/24/16 for the portrait types). Buttons
|
||||
cannot buy a second ticket while one is active.
|
||||
|
||||
Portrait generation uses 0..999 outcome rolls: 600 lose, 300 have one number
|
||||
match, 80 have x2. Neon uses the remaining 20 for x10. Ruby and Sea use 15 for
|
||||
two matching numbers and 5 for all-prizes. One-match amounts are weighted
|
||||
1/2/5/25 times price (Neon cutoffs 700/900/990; Ruby/Sea 650/850/980).
|
||||
Two-match prizes each equal price; all-prizes fields each equal price/5.
|
||||
This is fictional-chip gameplay, not a representation of real ticket odds.
|
||||
|
||||
Completed tickets show gross PAYOUT and signed NET RESULT (gross minus price)
|
||||
separately. A 50-chip ticket paying 50 has net zero, not +50. Golden Triple
|
||||
highlights its three matching symbols and prints price x multiplier = payout.
|
||||
|
||||
An unfinished ticket survives trips into the hall during the current launch.
|
||||
On a normal application close its already-generated outcome is automatically
|
||||
settled and the balance saved. It is not resumed as a partially scratched
|
||||
ticket after relaunch. Forced termination can bypass normal shutdown handling,
|
||||
as with other in-progress games; no new per-profile save format is introduced.
|
||||
|
||||
## Verification
|
||||
|
||||
`scratch_syntax.asm` checks the isolated module before the full build.
|
||||
`test_scratch_module.ps1` is a fast native iteration harness: it links fresh
|
||||
scratch MASM against a test-only copy of completed native helper code. Only
|
||||
COFF symbol visibility changes in the copy; instructions and relocations are
|
||||
not modified. It is not a substitute for the full action/shipping builds.
|
||||
The native action suite checks capture/release/focus/negative input, viewport
|
||||
mapping, hover versus held input, fast connected strokes, disconnected strokes,
|
||||
coverage, hall-return preservation, all price tiers, 500 immutable ticket
|
||||
layouts, another 200 layouts for each of the four kinds, rule-derived prizes,
|
||||
type locks, circular clipping, full physical uncovering of every layout,
|
||||
single settlement and the balance cap. An additional 500 generated boards per
|
||||
portrait kind are checked against independently derived number/bonus payouts;
|
||||
fixed bonus fixtures cover x2/x10/all-prizes. Tests also cover all 60 physical
|
||||
fields, both scales, catalogue clicks after pointer movement, price selection,
|
||||
paid-type locks, modal Escape and positive/zero/negative net results.
|
||||
Presentation tests additionally compare 186 native captures at equal timestamps
|
||||
with 10/15/30 ms updates, exercise blocked scratching during delivery, compare
|
||||
25 payout frames, assert unchanged bankroll/RNG under cosmetic updates, check
|
||||
single-shot sound triggers/cooldowns and expire all 64 particle slots.
|
||||
The suite writes ready, covered,
|
||||
partly scratched, completed, missing-art and per-kind frames.
|
||||
|
||||
Generated asset prompts: `assets/sprites/scratch/prompts-v1.json` and
|
||||
`assets/sprites/scratch/prompts-v2.json`. Portrait provenance and recovered edit
|
||||
briefs are in `assets/sprites/scratch/prompts-v3.json` (briefs are not verbatim
|
||||
tool prompts). Native stroke sequences and the hall
|
||||
counter can be captured with `tools/tests/test_scratch_probe.ps1`; its 114 native
|
||||
frames include 26 scratch frames per portrait kind and view-switch coverage
|
||||
preservation assertions. The probe
|
||||
links the tested game's rendering procedures, not a Python recreation.
|
||||
|
||||
Mechanic references, not source-code or art dependencies:
|
||||
[Scratch the Ticket](https://store.steampowered.com/app/4626940/Scratch_the_Ticket/)
|
||||
and [Scritchy Scratchy](https://store.steampowered.com/app/3948120/Scritchy_Scratchy/?l=russian).
|
||||
Number-match inspiration: the official National Lottery
|
||||
[Double Match procedures](https://www.national-lottery.co.uk/c/files/scratchcards/doublematch.pdf~3).
|
||||
Our outcomes and prices are independent; the three portrait designs originate
|
||||
from images supplied by the user, not scraped from lottery websites.
|
||||
56
docs/WORLD_DRESSING.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# Hall and Street Dressing
|
||||
|
||||
The game still runs entirely in MASM32 assembly. The Python packer and capture
|
||||
checker are offline developer tools, not another game implementation.
|
||||
|
||||
## Hall
|
||||
|
||||
- Standing eye height is 1.05 world units. Basement eye height remains 0.85,
|
||||
including its stair elevation. Gameplay, table sizes and NPC routes are unchanged.
|
||||
- Six framed paintings and eight sconces are actual depth-tested wall planes.
|
||||
They stay attached to the architecture as the camera turns and do not occupy
|
||||
the walking area. They do not use camera-facing furniture billboards.
|
||||
- A static 256x256 light map is rebuilt when the hall map is initialized. It
|
||||
contains the existing chandeliers, lounge lamps, bar lights and new wall lights.
|
||||
Radial falloff is quadratic, and solid map tiles interrupt the light rays.
|
||||
- A separate contact map darkens the carpet underneath lounge furniture. This
|
||||
is not a full dynamic shadow renderer for every NPC and table.
|
||||
- The lighting pass runs after the world but before the HUD. It computes a gain
|
||||
per 2x2 area and shades each original pixel separately, retaining texture detail.
|
||||
It is skipped for the basement, outside scenes and when explicitly disabled.
|
||||
|
||||
## Street
|
||||
|
||||
- Walking eye height is 1.15 plus the six-centimetre pavement elevation. Seated
|
||||
eye height and the ignition/waking animation remain unchanged; the rising
|
||||
phase interpolates to the new standing height.
|
||||
- Building storeys are 1.8 units instead of 1.2. Their bases stay on the ground.
|
||||
- Hydrants, mailboxes, newspaper boxes, bollards and parking meters have individual
|
||||
dimensions, smaller than a standing person. Fence height is reduced as well.
|
||||
Bushes and the discarded billboard benches remain disabled.
|
||||
- Low curbs separate roadway and pavement. Paving is drawn in individual metre
|
||||
sections, not one stretched street-length texture. Raised sidewalk props share
|
||||
the curb's floor anchor. The anchor is recalculated after each pedestrian/car
|
||||
update, so newly positioned walkers do not keep their old ground height.
|
||||
Props beyond the raised section and road vehicles stay on the lower ground.
|
||||
- Three iron drains sit beside the curb, outside the walking strip. Existing
|
||||
window/lamppost light maps also shade the new paving.
|
||||
|
||||
## Artwork and Verification
|
||||
|
||||
`assets/sprites/hall/wall-paintings-v6.png` was produced with the built-in image
|
||||
generator. Its prompt is recorded in `prompts-v6.json`. The offline packer adds
|
||||
a small procedural iron material and writes `world-dressing-v6.bin` (three
|
||||
128x128 BGRA frames). Loading validates dimensions; missing art is safely skipped.
|
||||
|
||||
Run `tools/tests/test_casino_actions.ps1 -SkipPreview` for native checks of
|
||||
surface loading, light occlusion, repeatable baking, floor anchors, prop scale,
|
||||
unchanged gameplay RNG/bank/map, existing interaction paths and framebuffer captures.
|
||||
Then `tools/tests/check_world_dressing.py --parity` compares the tested and shipping
|
||||
procedures and validates the native captures under `build/actions/world-*.bmp`.
|
||||
|
||||
`test_world_dressing_probe.ps1` is a quick development preview against a saved
|
||||
prior-release object. It only changes COFF symbol visibility in a test copy and
|
||||
links current dressing/surface routines without patching instructions. It is
|
||||
not evidence of shipping integration; the complete native action suite and
|
||||
shipping parity check are required before publication.
|
||||
BIN
poker.exe
BIN
poker.obj
|
|
@ -18,4 +18,4 @@ DebOut=
|
|||
[FILES]
|
||||
1=poker.asm
|
||||
[SHOWFILE]
|
||||
1=0000000000000000140600007403000000000000030000004836000012
|
||||
1=000000000000000014060000740300000000000003000000F201000087
|
||||
|
|
|
|||
|
|
@ -8,7 +8,42 @@ PoolSqrt3D PROC squared:DWORD
|
|||
ret
|
||||
PoolSqrt3D ENDP
|
||||
|
||||
InitPool3D PROC uses ebx esi edi
|
||||
InitPool3D PROC
|
||||
call ResetPool3D
|
||||
mov poolState3D,POOL_SELECT
|
||||
ret
|
||||
InitPool3D ENDP
|
||||
|
||||
StartBilliards3D PROC variant:DWORD
|
||||
cmp variant,1
|
||||
ja @F
|
||||
mov eax,variant
|
||||
mov poolVariant3D,eax
|
||||
call ResetPool3D
|
||||
call ClearKeys3D
|
||||
@@:
|
||||
ret
|
||||
StartBilliards3D ENDP
|
||||
|
||||
ResetPool3D PROC uses ebx esi edi
|
||||
mov poolTraceValid3D,0
|
||||
mov poolCapture2Q8,480*480
|
||||
mov poolMiddleLeft3D,157*FP_1
|
||||
mov poolMiddleRight3D,163*FP_1
|
||||
lea esi,poolPyramidJawX3D
|
||||
lea edi,poolJawX3D
|
||||
mov ecx,24
|
||||
rep movsd
|
||||
cmp poolVariant3D,0
|
||||
je @F
|
||||
mov poolCapture2Q8,1024*1024
|
||||
mov poolMiddleLeft3D,153*FP_1
|
||||
mov poolMiddleRight3D,167*FP_1
|
||||
lea esi,poolEightJawX3D
|
||||
lea edi,poolJawX3D
|
||||
mov ecx,24
|
||||
rep movsd
|
||||
@@:
|
||||
lea edi, poolVX3D
|
||||
xor eax, eax
|
||||
mov ecx, 32
|
||||
|
|
@ -59,9 +94,10 @@ pool_rack_ball:
|
|||
mov poolStill3D, 1
|
||||
mov poolCalled3D, 1
|
||||
mov poolCalledPocket3D, 0
|
||||
mov poolCallManual3D,0
|
||||
call InitPyramidState3D
|
||||
ret
|
||||
InitPool3D ENDP
|
||||
ResetPool3D ENDP
|
||||
|
||||
; Symmetric equal-mass impulse plus separation; opening contacts never gain energy.
|
||||
PoolCollide3D PROC uses ebx esi edi a:DWORD,b:DWORD
|
||||
|
|
@ -182,24 +218,24 @@ PoolPocketBall3D PROC uses ebx esi ball:DWORD
|
|||
pool_pocket_test:
|
||||
mov eax, poolX3D[esi*4]
|
||||
sub eax, poolPocketX3D[ebx*4]
|
||||
cmp eax,2*FP_1
|
||||
cmp eax,5*FP_1
|
||||
jg pool_pocket_next
|
||||
cmp eax,-2*FP_1
|
||||
cmp eax,-5*FP_1
|
||||
jl pool_pocket_next
|
||||
sar eax, 8
|
||||
imul eax, eax
|
||||
mov ecx, eax
|
||||
mov eax, poolY3D[esi*4]
|
||||
sub eax, poolPocketY3D[ebx*4]
|
||||
cmp eax,2*FP_1
|
||||
cmp eax,5*FP_1
|
||||
jg pool_pocket_next
|
||||
cmp eax,-2*FP_1
|
||||
cmp eax,-5*FP_1
|
||||
jl pool_pocket_next
|
||||
sar eax, 8
|
||||
imul eax, eax
|
||||
add eax, ecx
|
||||
; Capture is deep inside the narrow mouth; jaws are separate colliders.
|
||||
cmp eax, 480*480
|
||||
cmp eax, poolCapture2Q8
|
||||
ja pool_pocket_next
|
||||
pool_pocket_capture:
|
||||
mov poolActive3D[esi*4], 0
|
||||
|
|
@ -398,9 +434,11 @@ pool_rail_y:
|
|||
jle pool_rail_throat_y
|
||||
cmp poolX3D[esi*4], 283*FP_1
|
||||
jge pool_rail_throat_y
|
||||
cmp poolX3D[esi*4], 157*FP_1
|
||||
mov eax,poolMiddleLeft3D
|
||||
cmp poolX3D[esi*4], eax
|
||||
jl pool_rail_test_y
|
||||
cmp poolX3D[esi*4], 163*FP_1
|
||||
mov eax,poolMiddleRight3D
|
||||
cmp poolX3D[esi*4], eax
|
||||
jg pool_rail_test_y
|
||||
pool_rail_throat_y:
|
||||
mov ebx, 51*FP_1
|
||||
|
|
@ -461,6 +499,12 @@ pool_friction_ball:
|
|||
test eax,eax
|
||||
jns @F
|
||||
neg eax
|
||||
@@:
|
||||
add pyrRoll3D[esi*4],eax
|
||||
mov eax,poolVY3D[esi*4]
|
||||
test eax,eax
|
||||
jns @F
|
||||
neg eax
|
||||
@@:
|
||||
add pyrRoll3D[esi*4],eax
|
||||
mov eax, poolVX3D[esi*4]
|
||||
|
|
@ -504,5 +548,7 @@ pool_friction_next:
|
|||
PoolStep3D ENDP
|
||||
|
||||
include src_graphics\pyramid_rules.inc
|
||||
include src_graphics\eightball.inc
|
||||
include src_graphics\pyramid_play.inc
|
||||
include src_graphics\billiards_prediction.inc
|
||||
include src_graphics\pyramid_render.inc
|
||||
|
|
|
|||
|
|
@ -8,7 +8,18 @@ POOL_RADIUS equ FP_1*5/2
|
|||
POOL_DIAMETER equ 5*FP_1
|
||||
POOL_PENALTY equ 5
|
||||
POOL_CHOICE equ 6
|
||||
POOL_SELECT equ 7
|
||||
InitPool3D PROTO
|
||||
ResetPool3D PROTO
|
||||
StartBilliards3D PROTO :DWORD
|
||||
EightLegal3D PROTO :DWORD
|
||||
EightCount3D PROTO
|
||||
EightFinish3D PROTO
|
||||
EightHand3D PROTO
|
||||
EightAutoCall3D PROTO
|
||||
EightSyncGroups3D PROTO
|
||||
PoolPredict3D PROTO
|
||||
PoolDrawPrediction3D PROTO
|
||||
HandlePool3D PROTO
|
||||
RenderPool3D PROTO
|
||||
PoolStep3D PROTO
|
||||
|
|
@ -44,6 +55,9 @@ poolPotted3D dd 0
|
|||
poolBreak3D dd 1
|
||||
poolCalled3D dd 1
|
||||
poolCalledPocket3D dd 0
|
||||
poolCallManual3D dd 0
|
||||
poolUnsetText3D db "-",0
|
||||
ALIGN 4
|
||||
poolAtStart3D dd 0
|
||||
poolFoul3D dd 0
|
||||
poolAngle3D dd 0
|
||||
|
|
@ -52,6 +66,38 @@ poolCharge3D dd 0
|
|||
poolAccumulator3D dd 0
|
||||
poolTime3D dd 0
|
||||
poolStill3D dd 0
|
||||
poolVariant3D dd 0
|
||||
poolCapture2Q8 dd 480*480
|
||||
poolMiddleLeft3D dd 157*FP_1
|
||||
poolMiddleRight3D dd 163*FP_1
|
||||
poolEightJawX3D dd 37*FP_1,30*FP_1,153*FP_1,167*FP_1,290*FP_1,283*FP_1
|
||||
dd 37*FP_1,30*FP_1,153*FP_1,167*FP_1,290*FP_1,283*FP_1
|
||||
poolEightJawY3D dd 50*FP_1,57*FP_1,50*FP_1,50*FP_1,57*FP_1,50*FP_1
|
||||
dd 180*FP_1,173*FP_1,180*FP_1,180*FP_1,173*FP_1,180*FP_1
|
||||
poolPyramidJawX3D dd FP_1*137/4,30*FP_1,157*FP_1,163*FP_1,290*FP_1,FP_1*1143/4
|
||||
dd FP_1*137/4,30*FP_1,157*FP_1,163*FP_1,290*FP_1,FP_1*1143/4
|
||||
poolPyramidJawY3D dd 50*FP_1,FP_1*217/4,50*FP_1,50*FP_1,FP_1*217/4,50*FP_1
|
||||
dd 180*FP_1,FP_1*703/4,180*FP_1,180*FP_1,FP_1*703/4,180*FP_1
|
||||
poolEightPack3D AnimPack3D <>
|
||||
poolEightPath3D db "assets\animations\pyramid\pool-balls-v1.bin",0
|
||||
poolSelectTitle3D db 193,200,203,220,223,208,196,0
|
||||
poolSelectPyramid3D db 49,32,207,200,208,192,204,200,196,192,0
|
||||
poolSelectEight3D db 50,32,207,211,203,32,194,206,209,220,204,197,208,202,192,0
|
||||
poolCallText3D db 199,192,202,192,199,0
|
||||
poolPredictionText3D db 207,208,206,195,205,206,199,0
|
||||
poolTraceValid3D dd 0
|
||||
poolTraceKey3D dd 0
|
||||
poolTraceCount3D dd 0
|
||||
poolTraceSteps3D dd 0
|
||||
poolTracePotted3D dd 0
|
||||
poolTraceFirst3D dd -1
|
||||
poolTraceX3D dd 8192 dup(0)
|
||||
poolTraceY3D dd 8192 dup(0)
|
||||
poolTraceActive3D dd 512 dup(0)
|
||||
poolTraceFinal3D dd 112 dup(0)
|
||||
poolPhysicsBackup3D dd 112 dup(0)
|
||||
poolHistoryBackup3D dd 80 dup(0)
|
||||
poolScalarBackup3D dd 7 dup(0)
|
||||
poolTitle3D db 207,211,203,32,47,32,56,0
|
||||
poolPlayerText3D db 200,195,208,206,202,0
|
||||
poolDealerText3D db 196,200,203,197,208,0
|
||||
|
|
|
|||
239
src_graphics/billiards_prediction.inc
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
; Prediction runs the shipping fixed-step integrator, without settlement or IO.
|
||||
; Every field touched by PoolStep3D is saved/restored before returning.
|
||||
PoolPredict3D PROC uses ebx esi edi
|
||||
local steps:DWORD,hash:DWORD
|
||||
cmp poolState3D,POOL_AIM
|
||||
jne predict_done
|
||||
call PyramidDirection3D
|
||||
mov eax,2166136261
|
||||
lea esi,poolX3D
|
||||
mov ecx,112
|
||||
predict_hash:
|
||||
xor eax,[esi]
|
||||
imul eax,16777619
|
||||
add esi,4
|
||||
loop predict_hash
|
||||
xor eax,pyrCue3D
|
||||
imul eax,16777619
|
||||
xor eax,poolPower3D
|
||||
imul eax,16777619
|
||||
xor eax,pyrDirX3D
|
||||
imul eax,16777619
|
||||
xor eax,pyrDirY3D
|
||||
xor eax,poolVariant3D
|
||||
mov hash,eax
|
||||
cmp poolTraceValid3D,0
|
||||
je predict_refresh
|
||||
cmp eax,poolTraceKey3D
|
||||
je predict_done
|
||||
predict_refresh:
|
||||
lea esi,poolX3D
|
||||
lea edi,poolPhysicsBackup3D
|
||||
mov ecx,112
|
||||
rep movsd
|
||||
lea esi,pyrRoll3D
|
||||
lea edi,poolHistoryBackup3D
|
||||
mov ecx,80
|
||||
rep movsd
|
||||
mov eax,poolFirst3D
|
||||
mov poolScalarBackup3D,eax
|
||||
mov eax,poolRail3D
|
||||
mov poolScalarBackup3D[4],eax
|
||||
mov eax,poolBreakRails3D
|
||||
mov poolScalarBackup3D[8],eax
|
||||
mov eax,poolPotted3D
|
||||
mov poolScalarBackup3D[12],eax
|
||||
mov eax,poolStill3D
|
||||
mov poolScalarBackup3D[16],eax
|
||||
mov eax,pyrValidEnd3D
|
||||
mov poolScalarBackup3D[20],eax
|
||||
mov eax,pyrRailSide3D
|
||||
mov poolScalarBackup3D[24],eax
|
||||
lea edi,poolVX3D
|
||||
xor eax,eax
|
||||
mov ecx,32
|
||||
rep stosd
|
||||
lea edi,pyrHistoryRails3D
|
||||
mov ecx,48
|
||||
rep stosd
|
||||
mov poolFirst3D,-1
|
||||
mov poolRail3D,0
|
||||
mov poolBreakRails3D,0
|
||||
mov poolPotted3D,0
|
||||
mov pyrValidEnd3D,0
|
||||
mov ebx,pyrCue3D
|
||||
mov eax,pyrDirX3D
|
||||
imul poolPower3D
|
||||
shrd eax,edx,16
|
||||
mov poolVX3D[ebx*4],eax
|
||||
mov eax,pyrDirY3D
|
||||
imul poolPower3D
|
||||
shrd eax,edx,16
|
||||
mov poolVY3D[ebx*4],eax
|
||||
mov poolTraceCount3D,0
|
||||
mov steps,0
|
||||
predict_sample:
|
||||
mov edi,poolTraceCount3D
|
||||
shl edi,6
|
||||
xor esi,esi
|
||||
xor ebx,ebx
|
||||
predict_sample_ball:
|
||||
mov eax,poolX3D[esi*4]
|
||||
mov poolTraceX3D[edi],eax
|
||||
mov eax,poolY3D[esi*4]
|
||||
mov poolTraceY3D[edi],eax
|
||||
cmp poolActive3D[esi*4],0
|
||||
je @F
|
||||
bts ebx,esi
|
||||
@@:
|
||||
add edi,4
|
||||
inc esi
|
||||
cmp esi,16
|
||||
jb predict_sample_ball
|
||||
mov ecx,poolTraceCount3D
|
||||
mov poolTraceActive3D[ecx*4],ebx
|
||||
inc poolTraceCount3D
|
||||
cmp steps,0
|
||||
je predict_step
|
||||
cmp poolStill3D,1
|
||||
je predict_restore
|
||||
cmp steps,6000
|
||||
jae predict_restore
|
||||
predict_step:
|
||||
call PoolStep3D
|
||||
inc steps
|
||||
cmp poolStill3D,1
|
||||
je predict_sample
|
||||
test steps,15
|
||||
jz predict_sample
|
||||
jmp predict_step
|
||||
predict_restore:
|
||||
mov eax,steps
|
||||
mov poolTraceSteps3D,eax
|
||||
mov eax,poolFirst3D
|
||||
mov poolTraceFirst3D,eax
|
||||
mov pyrTarget3D,eax
|
||||
mov eax,poolPotted3D
|
||||
mov poolTracePotted3D,eax
|
||||
lea esi,poolX3D
|
||||
lea edi,poolTraceFinal3D
|
||||
mov ecx,112
|
||||
rep movsd
|
||||
lea esi,poolPhysicsBackup3D
|
||||
lea edi,poolX3D
|
||||
mov ecx,112
|
||||
rep movsd
|
||||
lea esi,poolHistoryBackup3D
|
||||
lea edi,pyrRoll3D
|
||||
mov ecx,80
|
||||
rep movsd
|
||||
mov eax,poolScalarBackup3D
|
||||
mov poolFirst3D,eax
|
||||
mov eax,poolScalarBackup3D[4]
|
||||
mov poolRail3D,eax
|
||||
mov eax,poolScalarBackup3D[8]
|
||||
mov poolBreakRails3D,eax
|
||||
mov eax,poolScalarBackup3D[12]
|
||||
mov poolPotted3D,eax
|
||||
mov eax,poolScalarBackup3D[16]
|
||||
mov poolStill3D,eax
|
||||
mov eax,poolScalarBackup3D[20]
|
||||
mov pyrValidEnd3D,eax
|
||||
mov eax,poolScalarBackup3D[24]
|
||||
mov pyrRailSide3D,eax
|
||||
mov eax,hash
|
||||
mov poolTraceKey3D,eax
|
||||
mov poolTraceValid3D,1
|
||||
predict_done:
|
||||
ret
|
||||
PoolPredict3D ENDP
|
||||
|
||||
PoolTraceLine3D PROC uses ebx esi edi x1:DWORD,y1:DWORD,x2:DWORD,y2:DWORD,tint:DWORD
|
||||
local deltaX:DWORD,deltaY:DWORD,extent:DWORD
|
||||
mov eax,x2
|
||||
sub eax,x1
|
||||
mov deltaX,eax
|
||||
test eax,eax
|
||||
jns @F
|
||||
neg eax
|
||||
@@:
|
||||
mov extent,eax
|
||||
mov eax,y2
|
||||
sub eax,y1
|
||||
mov deltaY,eax
|
||||
test eax,eax
|
||||
jns @F
|
||||
neg eax
|
||||
@@:
|
||||
cmp eax,extent
|
||||
jbe @F
|
||||
mov extent,eax
|
||||
@@:
|
||||
cmp extent,0
|
||||
je trace_line_done
|
||||
xor esi,esi
|
||||
trace_line_pixel:
|
||||
mov eax,deltaX
|
||||
imul esi
|
||||
idiv extent
|
||||
add eax,x1
|
||||
mov ebx,eax
|
||||
mov eax,deltaY
|
||||
imul esi
|
||||
idiv extent
|
||||
add eax,y1
|
||||
invoke DrawPixel,ebx,eax,tint
|
||||
add esi,2
|
||||
cmp esi,extent
|
||||
jbe trace_line_pixel
|
||||
trace_line_done:
|
||||
ret
|
||||
PoolTraceLine3D ENDP
|
||||
|
||||
PoolDrawPrediction3D PROC uses ebx esi edi
|
||||
local sx:DWORD,sy:DWORD,ex:DWORD,ey:DWORD,tint:DWORD
|
||||
call PoolPredict3D
|
||||
xor ebx,ebx
|
||||
trace_draw_ball:
|
||||
cmp ebx,pyrCue3D
|
||||
je trace_draw_selected
|
||||
cmp ebx,poolTraceFirst3D
|
||||
jne trace_draw_next
|
||||
trace_draw_selected:
|
||||
mov tint,008DB5A9h
|
||||
cmp ebx,pyrCue3D
|
||||
jne @F
|
||||
mov tint,00E8EBD5h
|
||||
@@:
|
||||
mov esi,1
|
||||
trace_draw_segment:
|
||||
cmp esi,poolTraceCount3D
|
||||
jae trace_draw_next
|
||||
mov edi,esi
|
||||
dec edi
|
||||
mov eax,poolTraceActive3D[edi*4]
|
||||
bt eax,ebx
|
||||
jnc trace_draw_next
|
||||
shl edi,4
|
||||
add edi,ebx
|
||||
mov eax,poolTraceX3D[edi*4]
|
||||
sar eax,16
|
||||
mov sx,eax
|
||||
mov eax,poolTraceY3D[edi*4]
|
||||
sar eax,16
|
||||
mov sy,eax
|
||||
mov eax,poolTraceX3D[edi*4+64]
|
||||
sar eax,16
|
||||
mov ex,eax
|
||||
mov eax,poolTraceY3D[edi*4+64]
|
||||
sar eax,16
|
||||
mov ey,eax
|
||||
invoke PoolTraceLine3D,sx,sy,ex,ey,tint
|
||||
inc esi
|
||||
jmp trace_draw_segment
|
||||
trace_draw_next:
|
||||
inc ebx
|
||||
cmp ebx,16
|
||||
jb trace_draw_ball
|
||||
ret
|
||||
PoolDrawPrediction3D ENDP
|
||||
26
src_graphics/city_alley.inc
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
; Keep the cinematic's central walking strip clear; all fittings touch a wall
|
||||
; or the floor and use the same per-pixel depth buffer as the dumpster geometry.
|
||||
RenderCityAlley3D PROC
|
||||
cmp cityDecorPack3D.pixels,0
|
||||
je city_alley_done
|
||||
; East wall: louvres, layered posters and a shallow junction cabinet.
|
||||
invoke DrawCityVertical3D,0,FP_1*997/100,FP_1*111/5,FP_1*233/10,FP_1*5/4,FP_1*17/10,111
|
||||
invoke DrawCityVertical3D,0,FP_1*997/100,FP_1*119/5,FP_1*124/5,FP_1*11/20,FP_1*27/20,112
|
||||
invoke DrawCityBoxSides3D,FP_1*49/5,FP_1*199/20,FP_1*251/10,FP_1*128/5,FP_1*3/5,FP_1*7/5,114
|
||||
invoke DrawCityHorizontal3D,FP_1*49/5,FP_1*199/20,FP_1*251/10,FP_1*128/5,FP_1*7/5,110
|
||||
; West wall: service hatch and poster patch, mounted rather than billboards.
|
||||
invoke DrawCityVertical3D,0,FP_1*803/100,FP_1*183/10,FP_1*381/20,0,FP_1*17/10,114
|
||||
invoke DrawCityVertical3D,0,FP_1*803/100,FP_1*117/5,FP_1*121/5,FP_1*4/5,FP_1*17/10,112
|
||||
; Drain pipes rise along masonry, with a short overhead connection.
|
||||
invoke DrawCityBoxSides3D,FP_1*803/100,FP_1*811/100,FP_1*207/10,FP_1*104/5,0,FP_1*9/2,110
|
||||
invoke DrawCityBoxSides3D,FP_1*989/100,FP_1*997/100,FP_1*259/10,26*FP_1,0,FP_1*11/2,110
|
||||
invoke DrawCityBoxSides3D,8*FP_1,10*FP_1,FP_1*221/10,FP_1*222/10,FP_1*19/5,FP_1*39/10,110
|
||||
; Stacked crates and a low pallet stay against the walls, never in our path.
|
||||
invoke DrawCityBenchBlock3D,FP_1*803/100,FP_1*207/25,FP_1*201/10,FP_1*104/5,0,FP_HALF,113
|
||||
invoke DrawCityBenchBlock3D,FP_1*804/100,FP_1*827/100,FP_1*203/10,FP_1*207/10,FP_HALF,FP_1*39/50,113
|
||||
invoke DrawCityBenchBlock3D,FP_1*39/4,FP_1*497/50,FP_1*93/5,FP_1*191/10,0,FP_1*9/20,113
|
||||
invoke DrawCityBenchBlock3D,FP_1*803/100,FP_1*413/50,FP_1*223/10,FP_1*231/10,0,FP_1*3/25,113
|
||||
invoke DrawCityHorizontal3D,FP_1*167/20,FP_1*91/10,FP_1*213/10,FP_1*431/20,FP_1/200,111
|
||||
city_alley_done:
|
||||
ret
|
||||
RenderCityAlley3D ENDP
|
||||
|
|
@ -1,19 +1,40 @@
|
|||
CITY_BLACK equ 0
|
||||
CITY_WAKE equ 1
|
||||
CITY_SMOKE equ 2
|
||||
CITY_TOSS equ 3
|
||||
CITY_TURN_ALLEY equ 4
|
||||
CITY_ALLEY equ 5
|
||||
CITY_TURN_STREET equ 6
|
||||
CITY_STREET equ 7
|
||||
CITY_TURN_DOOR equ 8
|
||||
CITY_DOOR equ 9
|
||||
CITY_LIGHT equ 2
|
||||
CITY_SMOKE equ 3
|
||||
CITY_STAND equ 4
|
||||
CITY_LOOK_BIN equ 5
|
||||
CITY_TOSS equ 6
|
||||
CITY_TURN_ALLEY equ 7
|
||||
CITY_ALLEY equ 8
|
||||
CITY_TURN_STREET equ 9
|
||||
CITY_STREET equ 10
|
||||
CITY_TURN_DOOR equ 11
|
||||
CITY_DOOR equ 12
|
||||
CITY_BLACK_MS equ 700
|
||||
CITY_WAKE_MS equ 4500
|
||||
CITY_LIGHT_MS equ 2300
|
||||
CITY_SMOKE_MS equ 3600
|
||||
CITY_STAND_MS equ 1800
|
||||
CITY_LOOK_BIN_MS equ 1100
|
||||
CITY_TOSS_MS equ 1500
|
||||
CITY_TURN_ALLEY_MS equ 1200
|
||||
CITY_PRE_ALLEY_MS equ CITY_BLACK_MS+CITY_WAKE_MS+CITY_LIGHT_MS+CITY_SMOKE_MS+CITY_STAND_MS+CITY_LOOK_BIN_MS+CITY_TOSS_MS+CITY_TURN_ALLEY_MS
|
||||
CITY_TRAFFIC_OFFSET_MS equ CITY_PRE_ALLEY_MS-8900
|
||||
CITY_BUILDING_STOREYS equ 7
|
||||
CITY_STOREY_HEIGHT equ FP_1*6/5
|
||||
CITY_STOREY_HEIGHT equ FP_1*9/5
|
||||
HALL_STANDING_EYE equ FP_1*21/20
|
||||
CITY_STANDING_EYE equ FP_1*23/20
|
||||
LoadCityArrival3D PROTO
|
||||
RenderCityArrival3D PROTO
|
||||
HandleCityApproach3D PROTO
|
||||
PositionCityCamera3D PROTO
|
||||
DrawCityWakeActor3D PROTO
|
||||
DrawCitySeatedLegs3D PROTO
|
||||
DrawCityLighter3D PROTO
|
||||
DrawCityWakeSubtitle3D PROTO
|
||||
BlendCityWeatherPixel3D PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
||||
BlendCitySky3D PROTO :DWORD
|
||||
FadeCityFrame3D PROTO :DWORD
|
||||
CITY_LIGHT_W equ 512
|
||||
CITY_LIGHT_H equ 256
|
||||
|
|
@ -30,12 +51,12 @@ floorTexture3D dd 3
|
|||
outdoorRender3D dd 0
|
||||
cityLighting3D dd 1
|
||||
cityLightReady3D dd 0
|
||||
viewEye3D dd FP_1*17/20
|
||||
viewEye3D dd HALL_STANDING_EYE
|
||||
viewCeiling3D dd FP_1*5/2
|
||||
cityPhase3D dd CITY_BLACK
|
||||
cityTime3D dd 0
|
||||
cityClock3D dd 0
|
||||
cityDurations3D dd 700,3100,2400,1500,1200,5400,900,7500,900,2800
|
||||
cityDurations3D dd CITY_BLACK_MS,CITY_WAKE_MS,CITY_LIGHT_MS,CITY_SMOKE_MS,CITY_STAND_MS,CITY_LOOK_BIN_MS,CITY_TOSS_MS,CITY_TURN_ALLEY_MS,5400,900,7500,900,2800
|
||||
cityTilesPack3D AnimPack3D <>
|
||||
cityHandsPack3D AnimPack3D <>
|
||||
cityPropsPack3D AnimPack3D <>
|
||||
|
|
@ -43,6 +64,19 @@ citySmokePack3D AnimPack3D <>
|
|||
cityCarsPack3D AnimPack3D <>
|
||||
cityBinPack3D AnimPack3D <>
|
||||
cityCloudPack3D AnimPack3D <>
|
||||
cityWakePack3D AnimPack3D <>
|
||||
cityLighterPack3D AnimPack3D <>
|
||||
cityKneesPack3D AnimPack3D <>
|
||||
citySleevePack3D AnimPack3D <>
|
||||
cityDecorPack3D AnimPack3D <>
|
||||
cityWakePath3D db "assets\animations\arrival\wake-rocker-v2.bin",0
|
||||
cityLighterPath3D db "assets\animations\arrival\wake-lighter-v1.bin",0
|
||||
cityKneesPath3D db "assets\animations\arrival\wake-knees-v1.bin",0
|
||||
citySleevePath3D db "assets\animations\arrival\wake-sleeve-v1.bin",0
|
||||
cityDecorPath3D db "assets\animations\arrival\alley-materials-v1.bin",0
|
||||
include src_graphics\city_lighter_anchors.inc
|
||||
cityWakeLine1 db 194,241,242,224,226,224,233,44,32,241,224,236,243,240,224,233,44,0
|
||||
cityWakeLine2 db 239,238,240,224,32,228,253,239,237,243,242,252,32,226,241,229,32,226,32,234,224,231,232,237,238,0
|
||||
cityTilesPath3D db "assets\animations\arrival\city-tiles-v4.bin",0
|
||||
cityHandsPath3D db "assets\animations\arrival\city-hands.bin",0
|
||||
cityPropsPath3D db "assets\animations\arrival\city-props.bin",0
|
||||
|
|
@ -69,6 +103,7 @@ CityProp3D STRUCT
|
|||
asset dd ?
|
||||
groundZ dd 0
|
||||
CityProp3D ENDS
|
||||
cityWakeActor3D CityProp3D <FP_1*97/10,FP_1*49/2,FP_1*7/10,FP_1*7/5,0,OFFSET cityWakePack3D>
|
||||
CITY_PROP_COUNT equ 47
|
||||
CITY_FIRST_CAR equ 9
|
||||
CITY_TRAFFIC_EAST equ 14
|
||||
|
|
@ -165,6 +200,7 @@ cityObjectDepth3D dd CITY_PROP_COUNT dup(0)
|
|||
.data?
|
||||
cityLightMap3D dd CITY_LIGHT_W*CITY_LIGHT_H dup(?)
|
||||
cityDepthBuffer3D dd SCREEN_SIZE dup(?)
|
||||
citySkyBuffer3D dd SCREEN_SIZE dup(?)
|
||||
IFDEF CASINO_ACTION_TEST
|
||||
cityPixelOwner3D dd SCREEN_SIZE dup(?)
|
||||
ENDIF
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ include src_graphics\city_traffic.inc
|
|||
include src_graphics\city_objects.inc
|
||||
include src_graphics\city_bins.inc
|
||||
include src_graphics\city_furniture.inc
|
||||
include src_graphics\city_alley.inc
|
||||
include src_graphics\city_skyline.inc
|
||||
include src_graphics\city_lighting.inc
|
||||
ValidateCityPack3D PROC uses esi pack:DWORD,widthPx:DWORD,heightPx:DWORD,count:DWORD
|
||||
|
|
@ -30,6 +31,16 @@ LoadCityArrival3D PROC uses esi edi
|
|||
invoke LoadAnimPack3D, OFFSET cityCarsPack3D, OFFSET cityCarsPath3D
|
||||
invoke LoadAnimPack3D, OFFSET cityBinPack3D, OFFSET cityBinPath3D
|
||||
invoke LoadAnimPack3D, OFFSET cityCloudPack3D, OFFSET cityCloudPath3D
|
||||
invoke LoadAnimPack3D, OFFSET cityWakePack3D, OFFSET cityWakePath3D
|
||||
invoke LoadAnimPack3D, OFFSET cityLighterPack3D, OFFSET cityLighterPath3D
|
||||
invoke LoadAnimPack3D, OFFSET cityKneesPack3D, OFFSET cityKneesPath3D
|
||||
invoke LoadAnimPack3D, OFFSET citySleevePack3D, OFFSET citySleevePath3D
|
||||
invoke LoadAnimPack3D, OFFSET cityDecorPack3D, OFFSET cityDecorPath3D
|
||||
invoke ValidateCityPack3D, OFFSET cityWakePack3D, 192,320,32
|
||||
invoke ValidateCityPack3D, OFFSET cityLighterPack3D, 256,256,16
|
||||
invoke ValidateCityPack3D, OFFSET cityKneesPack3D, 640,240,1
|
||||
invoke ValidateCityPack3D, OFFSET citySleevePack3D, 256,384,1
|
||||
invoke ValidateCityPack3D, OFFSET cityDecorPack3D, 128,128,4
|
||||
invoke ValidateCityPack3D, OFFSET cityHandsPack3D, 256, 192, 16
|
||||
invoke ValidateCityPack3D, OFFSET cityPropsPack3D, 256, 256, 6
|
||||
invoke ValidateCityPack3D, OFFSET citySmokePack3D, 96, 128, 4
|
||||
|
|
@ -112,23 +123,62 @@ CityEase3D ENDP
|
|||
PositionCityCamera3D PROC uses ebx
|
||||
mov playerX, (8*FP_1+FP_HALF)
|
||||
mov playerY, (24*FP_1+FP_HALF)
|
||||
mov playerAngle, 128
|
||||
mov playerAngle, 0
|
||||
mov viewHorizon3D, 240
|
||||
mov viewEye3D,CITY_STANDING_EYE
|
||||
cmp arrivalState3D, ARRIVAL_WALK
|
||||
jne city_camera_at_door
|
||||
mov ebx, cityTime3D
|
||||
cmp cityPhase3D,CITY_STAND
|
||||
ja city_camera_turn_alley
|
||||
mov viewEye3D,FP_1*2/5
|
||||
cmp cityPhase3D, CITY_WAKE
|
||||
jne city_camera_turn_alley
|
||||
mov viewHorizon3D, 1600
|
||||
cmp ebx, 1800
|
||||
jne city_camera_light
|
||||
cmp ebx,2800
|
||||
jb city_camera_done
|
||||
sub ebx, 1800
|
||||
invoke CityEase3D, ebx, 1300
|
||||
imul eax, 1360
|
||||
sub ebx,2800
|
||||
invoke CityEase3D,ebx,1700
|
||||
imul eax,80
|
||||
shr eax, 16
|
||||
sub viewHorizon3D, eax
|
||||
add viewHorizon3D,eax
|
||||
jmp city_camera_done
|
||||
city_camera_light:
|
||||
cmp cityPhase3D,CITY_LIGHT
|
||||
jne city_camera_smoke
|
||||
mov viewHorizon3D,320
|
||||
jmp city_camera_done
|
||||
city_camera_smoke:
|
||||
cmp cityPhase3D,CITY_SMOKE
|
||||
jne city_camera_stand
|
||||
mov viewHorizon3D,320
|
||||
invoke CityEase3D,ebx,1200
|
||||
imul eax,1280
|
||||
shr eax,16
|
||||
add viewHorizon3D,eax
|
||||
jmp city_camera_done
|
||||
city_camera_stand:
|
||||
cmp cityPhase3D,CITY_STAND
|
||||
jne city_camera_done
|
||||
invoke CityEase3D,ebx,1800
|
||||
mov ebx,eax
|
||||
imul eax,CITY_STANDING_EYE-FP_1*2/5
|
||||
shr eax,16
|
||||
add viewEye3D,eax
|
||||
mov eax,ebx
|
||||
imul eax,1360
|
||||
shr eax,16
|
||||
mov viewHorizon3D,1600
|
||||
sub viewHorizon3D,eax
|
||||
jmp city_camera_done
|
||||
city_camera_turn_alley:
|
||||
cmp cityPhase3D,CITY_LOOK_BIN
|
||||
jne city_camera_bin_ready
|
||||
invoke CityEase3D,ebx,CITY_LOOK_BIN_MS
|
||||
shr eax,9
|
||||
mov playerAngle,eax
|
||||
jmp city_camera_done
|
||||
city_camera_bin_ready:
|
||||
mov playerAngle,128
|
||||
cmp cityPhase3D, CITY_TURN_ALLEY
|
||||
jb city_camera_done
|
||||
jne city_camera_alley
|
||||
|
|
@ -215,6 +265,12 @@ city_camera_bob:
|
|||
idiv ecx
|
||||
add viewHorizon3D, eax
|
||||
city_camera_done:
|
||||
cmp playerY,12*FP_1
|
||||
jb @F
|
||||
cmp playerY,13*FP_1
|
||||
jae @F
|
||||
add viewEye3D,FP_1*3/50
|
||||
@@:
|
||||
ret
|
||||
PositionCityCamera3D ENDP
|
||||
|
||||
|
|
@ -262,32 +318,7 @@ city_sky_pixel:
|
|||
ret
|
||||
DrawCitySky3D ENDP
|
||||
|
||||
DrawCityRain3D PROC uses ebx esi
|
||||
xor esi, esi
|
||||
city_rain_drop:
|
||||
mov eax, esi
|
||||
imul eax, 137
|
||||
mov ebx, cityClock3D
|
||||
shr ebx, 4
|
||||
sub eax, ebx
|
||||
and eax, 511
|
||||
imul eax, 5
|
||||
shr eax, 3
|
||||
mov ebx, eax
|
||||
mov eax, cityClock3D
|
||||
shr eax, 2
|
||||
mov ecx, esi
|
||||
imul ecx, 83
|
||||
add eax, ecx
|
||||
xor edx, edx
|
||||
mov ecx, 240
|
||||
div ecx
|
||||
invoke DrawBox, ebx, edx, 1, 4, 00395468h
|
||||
inc esi
|
||||
cmp esi, 70
|
||||
jb city_rain_drop
|
||||
ret
|
||||
DrawCityRain3D ENDP
|
||||
include src_graphics\city_weather.inc
|
||||
|
||||
|
||||
FadeCityFrame3D PROC uses ebx esi amount:DWORD
|
||||
|
|
@ -397,6 +428,11 @@ city_cigarette_ash:
|
|||
cmp u, eax
|
||||
jb city_cigarette_shade
|
||||
mov color, 00EC6325h
|
||||
cmp cityPhase3D,CITY_LIGHT
|
||||
jne city_cigarette_draw
|
||||
cmp cityTime3D,900
|
||||
jae city_cigarette_draw
|
||||
mov color,00DDD9C9h
|
||||
jmp city_cigarette_draw
|
||||
city_cigarette_shade:
|
||||
mov eax, v
|
||||
|
|
@ -474,6 +510,33 @@ DrawCitySmokingHand3D PROC uses ebx esi edi
|
|||
mov pinchX, 500
|
||||
mov pinchY, 310
|
||||
mov offsetY, 0
|
||||
cmp cityPhase3D,CITY_LIGHT
|
||||
jne city_hand_sky_lower
|
||||
invoke CityEase3D,cityTime3D,600
|
||||
neg eax
|
||||
add eax,FP_1
|
||||
imul eax,110
|
||||
shr eax,16
|
||||
mov offsetY,eax
|
||||
jmp city_hand_toss
|
||||
city_hand_sky_lower:
|
||||
cmp cityPhase3D,CITY_SMOKE
|
||||
jne city_hand_rising
|
||||
invoke CityEase3D,cityTime3D,900
|
||||
imul eax,240
|
||||
shr eax,16
|
||||
mov offsetY,eax
|
||||
jmp city_hand_toss
|
||||
city_hand_rising:
|
||||
cmp cityPhase3D,CITY_STAND
|
||||
jne city_hand_toss
|
||||
invoke CityEase3D,cityTime3D,1800
|
||||
neg eax
|
||||
add eax,FP_1
|
||||
imul eax,240
|
||||
shr eax,16
|
||||
mov offsetY,eax
|
||||
jmp city_hand_toss
|
||||
cmp cityPhase3D, CITY_WAKE
|
||||
jne city_hand_toss
|
||||
mov eax, 3100
|
||||
|
|
@ -601,7 +664,13 @@ city_hand_draw_held:
|
|||
imul eax, 55
|
||||
sar eax, 16
|
||||
add eax, cityCigaretteY3D
|
||||
cmp cityPhase3D,CITY_LIGHT
|
||||
jne city_hand_tip_smoke
|
||||
cmp cityTime3D,1000
|
||||
jb city_hand_unlit
|
||||
city_hand_tip_smoke:
|
||||
invoke DrawCityCigaretteSmoke3D, ebx, eax
|
||||
city_hand_unlit:
|
||||
invoke DrawCityCigarette3D, cityCigaretteX3D, cityCigaretteY3D, 320, 4
|
||||
city_hand_draw_sprite:
|
||||
; The opaque fingers cover the filter, with the paper extending out of the grip.
|
||||
|
|
@ -682,6 +751,8 @@ DrawCitySmokingHand3D ENDP
|
|||
|
||||
DrawCityExhaledSmoke3D PROC uses ebx esi edi
|
||||
mov esi, cityTime3D
|
||||
sub esi,600
|
||||
js city_exhale_done
|
||||
cmp esi, 2300
|
||||
jae city_exhale_done
|
||||
mov eax, esi
|
||||
|
|
@ -732,9 +803,12 @@ city_exhale_done:
|
|||
ret
|
||||
DrawCityExhaledSmoke3D ENDP
|
||||
|
||||
include src_graphics\city_wake_scene.inc
|
||||
|
||||
RenderCityArrival3D PROC uses ebx esi edi
|
||||
local savedX:DWORD,savedY:DWORD,savedAngle:DWORD,savedMap:DWORD
|
||||
local savedHorizon:DWORD,savedFloor:DWORD,savedOutdoor:DWORD,savedEye:DWORD,bar:DWORD
|
||||
local skyBlend:DWORD
|
||||
cmp arrivalState3D, ARRIVAL_WALK
|
||||
jne @F
|
||||
cmp cityPhase3D, CITY_BLACK
|
||||
|
|
@ -762,41 +836,79 @@ RenderCityArrival3D PROC uses ebx esi edi
|
|||
mov worldMap3D, OFFSET cityMap3D
|
||||
mov floorTexture3D, 60
|
||||
mov outdoorRender3D, 1
|
||||
mov viewEye3D, FP_1*17/20
|
||||
call UpdateCamera3D
|
||||
call DrawCitySky3D
|
||||
mov skyBlend,0
|
||||
cmp arrivalState3D, ARRIVAL_WALK
|
||||
jne city_render_world
|
||||
cmp cityPhase3D, CITY_WAKE
|
||||
cmp cityPhase3D,CITY_SMOKE
|
||||
jne city_render_stand_sky
|
||||
mov eax,cityTime3D
|
||||
sub eax,550
|
||||
js city_render_world
|
||||
invoke CityEase3D,eax,650
|
||||
shr eax,8
|
||||
mov skyBlend,eax
|
||||
jmp city_render_capture_sky
|
||||
city_render_stand_sky:
|
||||
cmp cityPhase3D,CITY_STAND
|
||||
jne city_render_world
|
||||
cmp cityTime3D, 1800
|
||||
jb city_render_sky_smoke
|
||||
invoke CityEase3D,cityTime3D,900
|
||||
shr eax,8
|
||||
neg eax
|
||||
add eax,256
|
||||
mov skyBlend,eax
|
||||
city_render_capture_sky:
|
||||
cmp skyBlend,256
|
||||
je city_render_sky_smoke
|
||||
lea esi,screenBuffer
|
||||
lea edi,citySkyBuffer3D
|
||||
mov ecx,SCREEN_SIZE
|
||||
rep movsd
|
||||
city_render_world:
|
||||
call RenderCeilingAndFloor
|
||||
call DrawCitySkyline3D
|
||||
call RenderWalls
|
||||
call PrepareCityDepth3D
|
||||
call RenderStreetDressing3D
|
||||
call RenderCityObjects3D
|
||||
call RenderCityFurniture3D
|
||||
call RenderCityBins3D
|
||||
call RenderCityAlley3D
|
||||
call RenderCityFacade3D
|
||||
call RenderCityGuards3D
|
||||
cmp arrivalState3D,ARRIVAL_WALK
|
||||
jne @F
|
||||
call DrawCityWakeActor3D
|
||||
@@:
|
||||
cmp skyBlend,0
|
||||
je @F
|
||||
invoke BlendCitySky3D,skyBlend
|
||||
@@:
|
||||
call DrawCityRain3D
|
||||
cmp arrivalState3D, ARRIVAL_WALK
|
||||
jne city_render_restore
|
||||
cmp cityPhase3D, CITY_TOSS
|
||||
ja city_render_restore
|
||||
call DrawCitySeatedLegs3D
|
||||
cmp cityPhase3D, CITY_WAKE
|
||||
jne @F
|
||||
call DrawCityExhaledSmoke3D
|
||||
@@:
|
||||
call DrawCitySmokingHand3D
|
||||
cmp cityPhase3D, CITY_WAKE
|
||||
jne city_render_restore
|
||||
call DrawCityWakeSubtitle3D
|
||||
jmp city_wake_eye_mask
|
||||
@@:
|
||||
call DrawCityLighter3D
|
||||
call DrawCitySmokingHand3D
|
||||
cmp cityPhase3D,CITY_SMOKE
|
||||
jne city_render_restore
|
||||
call DrawCityExhaledSmoke3D
|
||||
jmp city_render_restore
|
||||
city_render_sky_smoke:
|
||||
call DrawCityRain3D
|
||||
cmp cityPhase3D,CITY_SMOKE
|
||||
jne city_render_restore
|
||||
call DrawCitySmokingHand3D
|
||||
call DrawCityExhaledSmoke3D
|
||||
jmp city_render_restore
|
||||
city_wake_eye_mask:
|
||||
mov eax, cityTime3D
|
||||
cmp eax, 900
|
||||
|
|
|
|||
|
|
@ -2,6 +2,36 @@
|
|||
cityRayX3D dd SCREEN_W dup(?)
|
||||
cityRayY3D dd SCREEN_W dup(?)
|
||||
.code
|
||||
; Exterior-only materials do not consume or overwrite the hall's texture slots.
|
||||
ResolveCitySurface3D PROC material:DWORD
|
||||
mov eax,material
|
||||
cmp eax,115
|
||||
jb @F
|
||||
cmp eax,118
|
||||
jae @F
|
||||
invoke ResolveDressingSurface3D,material
|
||||
ret
|
||||
@@:
|
||||
cmp eax,111
|
||||
jb city_surface_shared
|
||||
cmp eax,115
|
||||
jae city_surface_shared
|
||||
cmp cityDecorPack3D.pixels,0
|
||||
je city_surface_missing
|
||||
sub eax,111
|
||||
shl eax,16
|
||||
add eax,cityDecorPack3D.pixels
|
||||
mov ecx,128
|
||||
mov edx,128
|
||||
ret
|
||||
city_surface_missing:
|
||||
xor eax,eax
|
||||
ret
|
||||
city_surface_shared:
|
||||
invoke ResolveWorldSurface3D,material
|
||||
ret
|
||||
ResolveCitySurface3D ENDP
|
||||
|
||||
PrepareCityDepth3D PROC uses ebx esi edi
|
||||
lea edi, cityDepthBuffer3D
|
||||
mov ebx, SCREEN_H
|
||||
|
|
@ -78,7 +108,7 @@ DrawCityVertical3D PROC uses ebx esi edi axis:DWORD,coordinate:DWORD,loBound:DWO
|
|||
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 textureW:DWORD,textureH:DWORD
|
||||
invoke ResolveWorldSurface3D,material
|
||||
invoke ResolveCitySurface3D,material
|
||||
test eax, eax
|
||||
jz city_vertical_done
|
||||
mov texture, eax
|
||||
|
|
@ -240,7 +270,7 @@ DrawCityHorizontal3D PROC uses ebx esi edi xMin:DWORD,xMax:DWORD,yMin:DWORD,yMax
|
|||
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 textureW:DWORD,textureH:DWORD,nearClipped:DWORD
|
||||
invoke ResolveWorldSurface3D,material
|
||||
invoke ResolveCitySurface3D,material
|
||||
test eax, eax
|
||||
jz city_horizontal_done
|
||||
mov texture, eax
|
||||
|
|
@ -411,6 +441,20 @@ city_horizontal_pixel:
|
|||
add esi, edx
|
||||
mov ebx, texture
|
||||
mov eax, [ebx+esi*4]
|
||||
cmp outdoorRender3D,0
|
||||
je city_horizontal_alpha
|
||||
cmp material,72
|
||||
jne city_horizontal_alpha
|
||||
mov ecx,depth
|
||||
shr ecx,14
|
||||
neg ecx
|
||||
add ecx,256
|
||||
cmp ecx,55
|
||||
jge @F
|
||||
mov ecx,55
|
||||
@@:
|
||||
invoke ShadeCityGround3D,eax,pointX,pointY,ecx
|
||||
city_horizontal_alpha:
|
||||
cmp material, 104
|
||||
jb @F
|
||||
cmp eax, 80000000h
|
||||
|
|
|
|||
2
src_graphics/city_lighter_anchors.inc
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
cityLighterCuffX3D dd 66,64,65,129,66,66,65,65,65,65,65,65,63,63,64,63
|
||||
cityLighterCuffY3D dd 232,232,232,224,220,220,222,222,222,222,222,222,219,215,215,215
|
||||
|
|
@ -353,6 +353,7 @@ IFDEF CASINO_ACTION_TEST
|
|||
ENDIF
|
||||
call AnimateCityCars3D
|
||||
call AnimateCityPedestrians3D
|
||||
call UpdateStreetGround3D
|
||||
xor esi, esi
|
||||
city_objects_depth:
|
||||
imul ebx, esi, SIZEOF CityProp3D
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@
|
|||
AnimateCityCars3D PROC uses ebx esi edi
|
||||
local trafficClock:DWORD
|
||||
mov eax, cityClock3D
|
||||
; Keep the crossing's safe stopped positions when the wake-up gets longer.
|
||||
sub eax,CITY_TRAFFIC_OFFSET_MS
|
||||
jns @F
|
||||
xor eax,eax
|
||||
@@:
|
||||
; A red-light interval lets the protagonist cross from the alley.
|
||||
; Resume from the stopped position instead of jumping forward in world space.
|
||||
cmp eax,7000
|
||||
|
|
|
|||
193
src_graphics/city_wake_scene.inc
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
DrawCityWakeActor3D PROC uses ebx
|
||||
mov cityWakeActor3D.posX,FP_1*97/10
|
||||
mov cityWakeActor3D.posY,FP_1*49/2
|
||||
cmp cityPhase3D,CITY_WAKE
|
||||
jne wake_actor_depart
|
||||
mov eax,cityTime3D
|
||||
cmp eax,2800
|
||||
jae wake_actor_straighten
|
||||
xor edx,edx
|
||||
mov ecx,175
|
||||
div ecx
|
||||
and eax,15
|
||||
jmp wake_actor_draw
|
||||
wake_actor_straighten:
|
||||
sub eax,2800
|
||||
imul eax,8
|
||||
xor edx,edx
|
||||
mov ecx,1700
|
||||
div ecx
|
||||
cmp eax,7
|
||||
jbe @F
|
||||
mov eax,7
|
||||
@@:
|
||||
add eax,16
|
||||
jmp wake_actor_draw
|
||||
wake_actor_depart:
|
||||
cmp cityPhase3D,CITY_LIGHT
|
||||
jne wake_actor_done
|
||||
mov eax,cityTime3D
|
||||
sub eax,350
|
||||
jns @F
|
||||
xor eax,eax
|
||||
@@:
|
||||
invoke CityEase3D,eax,1950
|
||||
imul eax,3
|
||||
sub cityWakeActor3D.posY,eax
|
||||
mov eax,cityTime3D
|
||||
xor edx,edx
|
||||
mov ecx,90
|
||||
div ecx
|
||||
and eax,7
|
||||
add eax,24
|
||||
wake_actor_draw:
|
||||
mov cityWakeActor3D.frame,eax
|
||||
invoke DrawCityObject3D,OFFSET cityWakeActor3D,0
|
||||
wake_actor_done:
|
||||
ret
|
||||
DrawCityWakeActor3D ENDP
|
||||
|
||||
DrawCitySeatedLegs3D PROC uses ebx
|
||||
cmp cityPhase3D,CITY_LIGHT
|
||||
jbe wake_legs_seated
|
||||
cmp cityPhase3D,CITY_SMOKE
|
||||
jne wake_legs_done
|
||||
invoke CityEase3D,cityTime3D,900
|
||||
imul eax,300
|
||||
shr eax,16
|
||||
add eax,240
|
||||
mov ebx,eax
|
||||
jmp wake_legs_draw
|
||||
wake_legs_seated:
|
||||
mov ebx,240
|
||||
wake_legs_draw:
|
||||
invoke DrawAnimSprite3D,OFFSET cityKneesPack3D,0,0,ebx,640,240
|
||||
wake_legs_done:
|
||||
ret
|
||||
DrawCitySeatedLegs3D ENDP
|
||||
|
||||
DrawCityLighter3D PROC uses ebx esi edi
|
||||
local px:DWORD,py:DWORD,sleeveX:DWORD,sleeveY:DWORD
|
||||
cmp cityPhase3D,CITY_LIGHT
|
||||
jne wake_lighter_done
|
||||
mov eax,cityTime3D
|
||||
imul eax,16
|
||||
xor edx,edx
|
||||
mov ecx,2300
|
||||
div ecx
|
||||
cmp eax,15
|
||||
jbe @F
|
||||
mov eax,15
|
||||
@@:
|
||||
mov esi,eax
|
||||
mov cityCigaretteX3D,500
|
||||
mov eax,cityClock3D
|
||||
shr eax,3
|
||||
and eax,511
|
||||
mov eax,tableCos[eax*4]
|
||||
sar eax,14
|
||||
add eax,310
|
||||
mov edi,eax
|
||||
invoke CityEase3D,cityTime3D,600
|
||||
neg eax
|
||||
add eax,FP_1
|
||||
imul eax,110
|
||||
shr eax,16
|
||||
add eax,edi
|
||||
mov cityCigaretteY3D,eax
|
||||
mov eax,cityCigaretteX3D
|
||||
sub eax,40
|
||||
sub eax,110
|
||||
mov px,eax
|
||||
mov eax,cityCigaretteY3D
|
||||
sub eax,40
|
||||
add eax,8
|
||||
sub eax,55
|
||||
mov py,eax
|
||||
cmp cityTime3D,1800
|
||||
jb @F
|
||||
mov eax,cityTime3D
|
||||
sub eax,1800
|
||||
invoke CityEase3D,eax,500
|
||||
imul eax,220
|
||||
shr eax,16
|
||||
add py,eax
|
||||
@@:
|
||||
; Measured cuff anchors join the real forearm underneath each animated wrist.
|
||||
mov eax,cityLighterCuffX3D[esi*4]
|
||||
imul eax,220
|
||||
shr eax,8
|
||||
add eax,px
|
||||
sub eax,110
|
||||
mov sleeveX,eax
|
||||
mov eax,cityLighterCuffY3D[esi*4]
|
||||
imul eax,220
|
||||
shr eax,8
|
||||
add eax,py
|
||||
sub eax,20
|
||||
mov sleeveY,eax
|
||||
invoke DrawAnimSprite3D,OFFSET citySleevePack3D,0,sleeveX,sleeveY,220,330
|
||||
invoke DrawAnimSprite3D,OFFSET cityLighterPack3D,esi,px,py,220,220
|
||||
wake_lighter_done:
|
||||
ret
|
||||
DrawCityLighter3D ENDP
|
||||
|
||||
DrawCityWakeSubtitle3D PROC
|
||||
cmp cityTime3D,1100
|
||||
jb wake_subtitle_done
|
||||
cmp cityTime3D,4300
|
||||
jae wake_subtitle_done
|
||||
invoke DrawBox,0,205,320,35,00151B1Dh
|
||||
invoke DrawString8x8,92,211,OFFSET cityWakeLine1,00E6DED2h
|
||||
invoke DrawString8x8,60,225,OFFSET cityWakeLine2,00E6DED2h
|
||||
wake_subtitle_done:
|
||||
ret
|
||||
DrawCityWakeSubtitle3D ENDP
|
||||
|
||||
; Sky-only raycasting cannot represent a vertical view. Blend the pitched world
|
||||
; into the already rendered sky instead of popping between the two projections.
|
||||
BlendCitySky3D PROC uses ebx esi edi amount:DWORD
|
||||
local inverse:DWORD,red:DWORD,green:DWORD
|
||||
mov ebx,amount
|
||||
mov eax,256
|
||||
sub eax,ebx
|
||||
mov inverse,eax
|
||||
xor esi,esi
|
||||
wake_sky_blend:
|
||||
mov eax,screenBuffer[esi*4]
|
||||
mov edi,citySkyBuffer3D[esi*4]
|
||||
movzx ecx,al
|
||||
imul ecx,inverse
|
||||
mov edx,edi
|
||||
and edx,255
|
||||
imul edx,ebx
|
||||
add ecx,edx
|
||||
shr ecx,8
|
||||
mov red,ecx
|
||||
movzx ecx,ah
|
||||
imul ecx,inverse
|
||||
mov edx,edi
|
||||
shr edx,8
|
||||
and edx,255
|
||||
imul edx,ebx
|
||||
add ecx,edx
|
||||
shr ecx,8
|
||||
shl ecx,8
|
||||
mov green,ecx
|
||||
shr eax,16
|
||||
and eax,255
|
||||
imul eax,inverse
|
||||
shr edi,16
|
||||
and edi,255
|
||||
imul edi,ebx
|
||||
add eax,edi
|
||||
shr eax,8
|
||||
shl eax,16
|
||||
or eax,green
|
||||
or eax,red
|
||||
mov screenBuffer[esi*4],eax
|
||||
inc esi
|
||||
cmp esi,SCREEN_SIZE
|
||||
jb wake_sky_blend
|
||||
ret
|
||||
BlendCitySky3D ENDP
|
||||
184
src_graphics/city_weather.inc
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
; All weather uses visual time and stable seeds, never gameplay RNG.
|
||||
BlendCityWeatherPixel3D PROC uses ebx esi edi px:DWORD,py:DWORD,tint:DWORD,opacity:DWORD
|
||||
cmp px,640
|
||||
jae weather_pixel_done
|
||||
cmp py,480
|
||||
jae weather_pixel_done
|
||||
mov esi,py
|
||||
imul esi,640
|
||||
add esi,px
|
||||
mov ebx,screenBuffer[esi*4]
|
||||
mov edi,256
|
||||
sub edi,opacity
|
||||
movzx eax,bl
|
||||
imul eax,edi
|
||||
mov ecx,tint
|
||||
and ecx,255
|
||||
imul ecx,opacity
|
||||
add eax,ecx
|
||||
shr eax,8
|
||||
mov edx,eax
|
||||
movzx eax,bh
|
||||
imul eax,edi
|
||||
mov ecx,tint
|
||||
shr ecx,8
|
||||
and ecx,255
|
||||
imul ecx,opacity
|
||||
add eax,ecx
|
||||
shr eax,8
|
||||
shl eax,8
|
||||
or edx,eax
|
||||
shr ebx,16
|
||||
and ebx,255
|
||||
imul ebx,edi
|
||||
mov eax,tint
|
||||
shr eax,16
|
||||
and eax,255
|
||||
imul eax,opacity
|
||||
add eax,ebx
|
||||
shr eax,8
|
||||
shl eax,16
|
||||
or eax,edx
|
||||
mov screenBuffer[esi*4],eax
|
||||
weather_pixel_done:
|
||||
ret
|
||||
BlendCityWeatherPixel3D ENDP
|
||||
|
||||
DrawCityRain3D PROC uses ebx esi edi
|
||||
local layer:DWORD,px:DWORD,py:DWORD,lengthPx:DWORD,opacity:DWORD
|
||||
local radius:DWORD,alpha:DWORD,rowStart:DWORD,age:DWORD,groundDepth:DWORD
|
||||
mov layer,0
|
||||
rain_layer:
|
||||
mov eax,layer
|
||||
imul eax,3
|
||||
add eax,4
|
||||
mov lengthPx,eax
|
||||
mov eax,layer
|
||||
imul eax,28
|
||||
add eax,50
|
||||
mov opacity,eax
|
||||
xor esi,esi
|
||||
rain_drop:
|
||||
mov eax,layer
|
||||
imul eax,3
|
||||
add eax,3
|
||||
imul eax,cityClock3D
|
||||
imul ecx,esi,829
|
||||
add eax,ecx
|
||||
xor edx,edx
|
||||
mov ecx,7680
|
||||
div ecx
|
||||
shr edx,4
|
||||
mov py,edx
|
||||
imul eax,esi,137
|
||||
imul ebx,layer,211
|
||||
add eax,ebx
|
||||
mov ecx,cityClock3D
|
||||
shr ecx,6
|
||||
sub eax,ecx
|
||||
and eax,1023
|
||||
imul eax,640
|
||||
shr eax,10
|
||||
mov px,eax
|
||||
xor edi,edi
|
||||
rain_streak:
|
||||
mov eax,edi
|
||||
shr eax,2
|
||||
mov ebx,px
|
||||
sub ebx,eax
|
||||
mov ecx,py
|
||||
add ecx,edi
|
||||
invoke BlendCityWeatherPixel3D,ebx,ecx,00B2C5CDh,opacity
|
||||
inc edi
|
||||
cmp edi,lengthPx
|
||||
jb rain_streak
|
||||
inc esi
|
||||
cmp esi,36
|
||||
jb rain_drop
|
||||
inc layer
|
||||
cmp layer,3
|
||||
jb rain_layer
|
||||
mov eax,viewHorizon3D
|
||||
add eax,50
|
||||
cmp eax,310
|
||||
jge @F
|
||||
mov eax,310
|
||||
@@:
|
||||
cmp eax,450
|
||||
jge rain_done
|
||||
mov rowStart,eax
|
||||
xor esi,esi
|
||||
rain_splash:
|
||||
imul eax,esi,97
|
||||
add eax,cityClock3D
|
||||
xor edx,edx
|
||||
mov ecx,800
|
||||
div ecx
|
||||
cmp edx,250
|
||||
jae rain_splash_next
|
||||
mov age,edx
|
||||
imul eax,esi,71
|
||||
add eax,43
|
||||
xor edx,edx
|
||||
mov ecx,600
|
||||
div ecx
|
||||
add edx,20
|
||||
mov px,edx
|
||||
imul eax,esi,37
|
||||
xor edx,edx
|
||||
mov ecx,468
|
||||
sub ecx,rowStart
|
||||
div ecx
|
||||
add edx,rowStart
|
||||
mov py,edx
|
||||
sub edx,viewHorizon3D
|
||||
mov eax,viewEye3D
|
||||
imul eax,480
|
||||
cdq
|
||||
mov ecx,py
|
||||
sub ecx,viewHorizon3D
|
||||
idiv ecx
|
||||
sub eax,1024
|
||||
mov groundDepth,eax
|
||||
mov ecx,py
|
||||
imul ecx,640
|
||||
add ecx,px
|
||||
mov eax,groundDepth
|
||||
cmp cityDepthBuffer3D[ecx*4],eax
|
||||
jl rain_splash_next
|
||||
mov eax,age
|
||||
xor edx,edx
|
||||
mov ecx,40
|
||||
div ecx
|
||||
inc eax
|
||||
mov radius,eax
|
||||
mov eax,250
|
||||
sub eax,age
|
||||
imul eax,100
|
||||
xor edx,edx
|
||||
mov ecx,250
|
||||
div ecx
|
||||
mov alpha,eax
|
||||
mov ebx,px
|
||||
sub ebx,radius
|
||||
invoke BlendCityWeatherPixel3D,ebx,py,00C5C6AEh,alpha
|
||||
mov ebx,px
|
||||
add ebx,radius
|
||||
invoke BlendCityWeatherPixel3D,ebx,py,00C5C6AEh,alpha
|
||||
mov eax,radius
|
||||
shr eax,1
|
||||
mov edi,py
|
||||
sub edi,eax
|
||||
invoke BlendCityWeatherPixel3D,px,edi,00C5C6AEh,alpha
|
||||
mov eax,radius
|
||||
shr eax,1
|
||||
mov edi,py
|
||||
add edi,eax
|
||||
invoke BlendCityWeatherPixel3D,px,edi,00C5C6AEh,alpha
|
||||
rain_splash_next:
|
||||
inc esi
|
||||
cmp esi,24
|
||||
jb rain_splash
|
||||
rain_done:
|
||||
ret
|
||||
DrawCityRain3D ENDP
|
||||
5
src_graphics/dice_anchors.inc
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
; Generated by pack_dice_assets.py from the last held pose.
|
||||
DICE_RELEASE_X1 EQU 213
|
||||
DICE_RELEASE_Y1 EQU 146
|
||||
DICE_RELEASE_X2 EQU 232
|
||||
DICE_RELEASE_Y2 EQU 141
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
; Moving cube geometry shares the existing 320x240 logical game canvas.
|
||||
include src_graphics/dice_anchors.inc
|
||||
.data
|
||||
cubeCorners3D dd -32768,-32768,-32768, 32768,-32768,-32768
|
||||
dd 32768,32768,-32768, -32768,32768,-32768
|
||||
|
|
@ -24,6 +25,7 @@ cubeCosZ3D dd 65536
|
|||
cubeVertices3D dd 16 dup(0)
|
||||
cubeFaceValues3D dd 6 dup(0)
|
||||
cubeQuad3D dd 8 dup(0)
|
||||
cubeContactShadow3D dd 0
|
||||
.code
|
||||
|
||||
; Fill clockwise triangles. Edges are incremented per pixel, avoiding divisions.
|
||||
|
|
@ -302,10 +304,10 @@ DrawTumblingDie3D PROC uses ebx esi edi centerX:DWORD,centerY:DWORD,pitch:DWORD,
|
|||
mov edx, tableCos[eax*4]
|
||||
mov cubeCosZ3D, edx
|
||||
mov eax, value
|
||||
mov cubeFaceValues3D, eax
|
||||
mov cubeFaceValues3D[16], eax
|
||||
mov edx, 7
|
||||
sub edx, eax
|
||||
mov cubeFaceValues3D[4], edx
|
||||
mov cubeFaceValues3D[20], edx
|
||||
dec eax
|
||||
mov edx, cubeRight3D[eax*4]
|
||||
mov cubeFaceValues3D[12], edx
|
||||
|
|
@ -313,10 +315,10 @@ DrawTumblingDie3D PROC uses ebx esi edi centerX:DWORD,centerY:DWORD,pitch:DWORD,
|
|||
sub ecx, edx
|
||||
mov cubeFaceValues3D[8], ecx
|
||||
mov edx, cubeTop3D[eax*4]
|
||||
mov cubeFaceValues3D[16], edx
|
||||
mov cubeFaceValues3D, edx
|
||||
mov ecx, 7
|
||||
sub ecx, edx
|
||||
mov cubeFaceValues3D[20], ecx
|
||||
mov cubeFaceValues3D[4], ecx
|
||||
xor esi, esi
|
||||
cube_project_loop:
|
||||
imul edi, esi, 12
|
||||
|
|
@ -326,6 +328,25 @@ cube_project_loop:
|
|||
inc esi
|
||||
cmp esi, 8
|
||||
jb cube_project_loop
|
||||
; A resting cube touches the cloth along its projected bottom face.
|
||||
; Reverse the underside winding; the normal face pass culls it.
|
||||
cmp cubeContactShadow3D,0
|
||||
je cube_no_contact_shadow
|
||||
mov eax,cubeVertices3D[28]
|
||||
inc eax
|
||||
mov ebx,cubeVertices3D[60]
|
||||
inc ebx
|
||||
mov edi,cubeVertices3D[52]
|
||||
inc edi
|
||||
invoke DrawTriangle3D,cubeVertices3D[24],eax,cubeVertices3D[56],ebx,cubeVertices3D[48],edi,00153122h
|
||||
mov eax,cubeVertices3D[28]
|
||||
inc eax
|
||||
mov ebx,cubeVertices3D[52]
|
||||
inc ebx
|
||||
mov edi,cubeVertices3D[20]
|
||||
inc edi
|
||||
invoke DrawTriangle3D,cubeVertices3D[24],eax,cubeVertices3D[48],ebx,cubeVertices3D[16],edi,00153122h
|
||||
cube_no_contact_shadow:
|
||||
mov face, 0
|
||||
cube_face_loop:
|
||||
mov esi, face
|
||||
|
|
@ -389,19 +410,48 @@ DrawTumblingDie3D ENDP
|
|||
|
||||
RenderDiceThrow3D PROC uses ebx esi edi
|
||||
local t:DWORD,ground:DWORD,lift:DWORD,pitch:DWORD,yaw:DWORD,roll:DWORD
|
||||
local cx1:DWORD,cx2:DWORD,cy:DWORD
|
||||
mov t, 1600
|
||||
local cx1:DWORD,cx2:DWORD,cy:DWORD,cy2:DWORD,oldScale:DWORD,shadowAlpha:DWORD
|
||||
; Held dice are painted into the cupped palm: no second pair over skin.
|
||||
cmp diceArtReady3D,1
|
||||
jne throw_begin
|
||||
cmp dice3d_state,0
|
||||
je throw_done
|
||||
cmp dice3d_state,1
|
||||
jne throw_begin
|
||||
cmp dice3d_timer,240
|
||||
jb throw_done
|
||||
throw_begin:
|
||||
mov eax,cubeScale3D
|
||||
mov oldScale,eax
|
||||
mov t,0
|
||||
cmp dice3d_state,2
|
||||
jne @F
|
||||
mov t,1600
|
||||
@@:
|
||||
cmp dice3d_state, 1
|
||||
jne throw_pose
|
||||
mov eax, dice3d_timer
|
||||
sub eax,240
|
||||
jns @F
|
||||
xor eax,eax
|
||||
@@:
|
||||
cmp eax,1360
|
||||
jbe @F
|
||||
mov eax,1360
|
||||
@@:
|
||||
imul eax,1600
|
||||
xor edx,edx
|
||||
mov ecx,1360
|
||||
div ecx
|
||||
mov t, eax
|
||||
throw_pose:
|
||||
mov eax, t
|
||||
imul eax, 59
|
||||
mov cubeScale3D,12
|
||||
mov eax,t
|
||||
imul eax, DICE_RELEASE_Y1-146
|
||||
xor edx, edx
|
||||
mov ecx, 1600
|
||||
div ecx
|
||||
mov ebx, 155
|
||||
mov ebx, DICE_RELEASE_Y1
|
||||
sub ebx, eax
|
||||
mov ground, ebx
|
||||
mov lift, 0
|
||||
|
|
@ -447,54 +497,88 @@ throw_position:
|
|||
sub eax, lift
|
||||
mov cy, eax
|
||||
mov eax, t
|
||||
imul eax, 12
|
||||
imul eax, DICE_RELEASE_X1-134
|
||||
xor edx, edx
|
||||
mov ecx, 1600
|
||||
div ecx
|
||||
mov ebx, 146
|
||||
mov ebx, DICE_RELEASE_X1
|
||||
sub ebx, eax
|
||||
mov cx1, ebx
|
||||
add eax, 174
|
||||
mov cx2, eax
|
||||
mov eax,t
|
||||
imul eax,DICE_RELEASE_X2-186
|
||||
xor edx,edx
|
||||
mov ecx,1600
|
||||
div ecx
|
||||
mov ebx,DICE_RELEASE_X2
|
||||
sub ebx,eax
|
||||
mov cx2,ebx
|
||||
mov eax, 1600
|
||||
sub eax, t
|
||||
mov esi, eax
|
||||
imul eax, 3
|
||||
shr eax, 2
|
||||
add eax, 40
|
||||
mov pitch, eax
|
||||
mov eax, esi
|
||||
imul eax, 3
|
||||
imul eax,eax
|
||||
imul eax,1024
|
||||
xor edx, edx
|
||||
mov ecx, 5
|
||||
mov ecx,2560000
|
||||
div ecx
|
||||
add eax, 44
|
||||
mov yaw, eax
|
||||
mov eax, esi
|
||||
imul eax, esi
|
||||
shl eax, 1
|
||||
xor edx, edx
|
||||
mov ecx, 1600
|
||||
div ecx
|
||||
mov roll, eax
|
||||
mov eax, cx1
|
||||
sub eax, 16
|
||||
mov edx, ground
|
||||
add edx, 18
|
||||
invoke DrawBox, eax, edx, 33, 3, 00082011h
|
||||
mov eax, cx2
|
||||
sub eax, 16
|
||||
mov edx, ground
|
||||
add edx, 18
|
||||
invoke DrawBox, eax, edx, 33, 3, 00082011h
|
||||
invoke DrawTumblingDie3D, cx1, cy, pitch, yaw, roll, dice3d_val1
|
||||
mov eax, roll
|
||||
neg eax
|
||||
mov edx, cy
|
||||
cmp dice3d_state, 1
|
||||
mov esi,1024
|
||||
sub esi,eax
|
||||
mov roll,esi
|
||||
mov eax,esi
|
||||
add eax,70
|
||||
mov pitch,eax
|
||||
mov eax,esi
|
||||
shr eax,1
|
||||
add eax,44
|
||||
mov yaw,eax
|
||||
mov cubeContactShadow3D,0
|
||||
cmp t,1600
|
||||
jne @F
|
||||
sub edx, 3
|
||||
mov cubeContactShadow3D,1
|
||||
@@:
|
||||
invoke DrawTumblingDie3D, cx2, edx, pitch, yaw, eax, dice3d_val2
|
||||
mov eax,t
|
||||
imul eax,DICE_RELEASE_Y1-DICE_RELEASE_Y2
|
||||
xor edx,edx
|
||||
mov ecx,1600
|
||||
div ecx
|
||||
add eax,cy
|
||||
sub eax,DICE_RELEASE_Y1-DICE_RELEASE_Y2
|
||||
mov cy2,eax
|
||||
cmp dice3d_state,0
|
||||
je throw_cubes
|
||||
cmp dice3d_state,1
|
||||
jne throw_shadows
|
||||
cmp dice3d_timer,240
|
||||
jb throw_cubes
|
||||
throw_shadows:
|
||||
cmp diceShadowPass3D,0
|
||||
je throw_cubes
|
||||
mov eax,85
|
||||
sub eax,lift
|
||||
mov shadowAlpha,eax
|
||||
mov eax,cx1
|
||||
shl eax,1
|
||||
mov edx,cubeScale3D
|
||||
shr edx,2
|
||||
add edx,ground
|
||||
shl edx,1
|
||||
invoke DrawCoinShadow3D,eax,edx,cubeScale3D,6,shadowAlpha
|
||||
mov eax,cx2
|
||||
shl eax,1
|
||||
mov edx,cubeScale3D
|
||||
shr edx,2
|
||||
add edx,ground
|
||||
shl edx,1
|
||||
invoke DrawCoinShadow3D,eax,edx,cubeScale3D,6,shadowAlpha
|
||||
throw_cubes:
|
||||
cmp diceShadowPass3D,0
|
||||
jne throw_restore
|
||||
invoke DrawTumblingDie3D, cx1, cy, pitch, yaw, roll, dice3d_val1
|
||||
mov eax,roll
|
||||
neg eax
|
||||
invoke DrawTumblingDie3D, cx2, cy2, pitch, yaw, eax, dice3d_val2
|
||||
throw_restore:
|
||||
mov eax,oldScale
|
||||
mov cubeScale3D,eax
|
||||
mov cubeContactShadow3D,0
|
||||
throw_done:
|
||||
ret
|
||||
RenderDiceThrow3D ENDP
|
||||
|
|
|
|||
338
src_graphics/eightball.inc
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
EightCount3D PROC uses ebx esi
|
||||
mov poolAtStart3D,0
|
||||
mov ecx,poolPlayer3D
|
||||
mov ebx,poolGroups3D[ecx*4]
|
||||
test ebx,ebx
|
||||
jz eight_count_done
|
||||
mov esi,1
|
||||
eight_count_loop:
|
||||
cmp esi,8
|
||||
je eight_count_next
|
||||
mov eax,1
|
||||
cmp esi,8
|
||||
jb @F
|
||||
mov eax,2
|
||||
@@:
|
||||
cmp eax,ebx
|
||||
jne eight_count_next
|
||||
mov eax,poolActive3D[esi*4]
|
||||
add poolAtStart3D,eax
|
||||
eight_count_next:
|
||||
inc esi
|
||||
cmp esi,16
|
||||
jb eight_count_loop
|
||||
eight_count_done:
|
||||
ret
|
||||
EightCount3D ENDP
|
||||
|
||||
EightLegal3D PROC uses ebx ball:DWORD
|
||||
xor eax,eax
|
||||
mov ecx,ball
|
||||
test ecx,ecx
|
||||
jle eight_legal_done
|
||||
cmp ecx,15
|
||||
ja eight_legal_done
|
||||
mov ebx,poolPlayer3D
|
||||
mov ebx,poolGroups3D[ebx*4]
|
||||
test ebx,ebx
|
||||
jz eight_legal_open
|
||||
cmp poolAtStart3D,0
|
||||
jne eight_legal_group
|
||||
cmp ecx,8
|
||||
sete al
|
||||
ret
|
||||
eight_legal_group:
|
||||
cmp ecx,8
|
||||
je eight_legal_done
|
||||
mov eax,1
|
||||
cmp ecx,8
|
||||
jb @F
|
||||
mov eax,2
|
||||
@@:
|
||||
cmp eax,ebx
|
||||
sete al
|
||||
movzx eax,al
|
||||
ret
|
||||
eight_legal_open:
|
||||
cmp ecx,8
|
||||
setne al
|
||||
eight_legal_done:
|
||||
ret
|
||||
EightLegal3D ENDP
|
||||
|
||||
; An obvious shot uses the same predictor as the visible guide. Explicit calls
|
||||
; lock either ball or pocket independently; cached prediction never settles play.
|
||||
EightAutoCall3D PROC uses ebx esi edi
|
||||
cmp poolVariant3D,1
|
||||
jne eight_auto_done
|
||||
cmp poolState3D,POOL_AIM
|
||||
jne eight_auto_done
|
||||
call EightCount3D
|
||||
call PoolPredict3D
|
||||
test poolCallManual3D,1
|
||||
jnz eight_auto_pocket
|
||||
mov poolCalled3D,0
|
||||
mov ebx,poolTraceFirst3D
|
||||
invoke EightLegal3D,ebx
|
||||
test eax,eax
|
||||
jz eight_auto_scan
|
||||
mov poolCalled3D,ebx
|
||||
bt poolTracePotted3D,ebx
|
||||
jnc eight_auto_scan
|
||||
test poolCallManual3D,2
|
||||
jz eight_auto_select
|
||||
mov eax,poolTraceFinal3D[80*4+ebx*4]
|
||||
cmp eax,poolCalledPocket3D
|
||||
je eight_auto_select
|
||||
eight_auto_scan:
|
||||
mov ebx,1
|
||||
eight_auto_next:
|
||||
bt poolTracePotted3D,ebx
|
||||
jnc eight_auto_advance
|
||||
invoke EightLegal3D,ebx
|
||||
test eax,eax
|
||||
jz eight_auto_advance
|
||||
eight_auto_filter:
|
||||
test poolCallManual3D,2
|
||||
jz eight_auto_select
|
||||
mov eax,poolTraceFinal3D[80*4+ebx*4]
|
||||
cmp eax,poolCalledPocket3D
|
||||
je eight_auto_select
|
||||
eight_auto_advance:
|
||||
inc ebx
|
||||
cmp ebx,16
|
||||
jb eight_auto_next
|
||||
jmp eight_auto_pocket
|
||||
eight_auto_select:
|
||||
mov poolCalled3D,ebx
|
||||
eight_auto_pocket:
|
||||
test poolCallManual3D,2
|
||||
jnz eight_auto_done
|
||||
mov poolCalledPocket3D,-1
|
||||
mov ebx,poolCalled3D
|
||||
cmp ebx,1
|
||||
jb eight_auto_done
|
||||
cmp ebx,15
|
||||
ja eight_auto_done
|
||||
bt poolTracePotted3D,ebx
|
||||
jnc eight_auto_done
|
||||
mov eax,poolTraceFinal3D[80*4+ebx*4]
|
||||
cmp eax,5
|
||||
ja eight_auto_done
|
||||
mov poolCalledPocket3D,eax
|
||||
eight_auto_done:
|
||||
ret
|
||||
EightAutoCall3D ENDP
|
||||
|
||||
; In pool the group owns the ball, not whoever happened to pocket it.
|
||||
; Recounting also assigns balls pocketed while the table was still open.
|
||||
EightSyncGroups3D PROC uses ebx esi edi
|
||||
mov pyrScore3D,0
|
||||
mov pyrScore3D[4],0
|
||||
mov pyrOwner3D,-1
|
||||
mov esi,1
|
||||
eight_sync_ball:
|
||||
mov pyrOwner3D[esi*4],-1
|
||||
cmp esi,8
|
||||
je eight_sync_next
|
||||
cmp poolActive3D[esi*4],0
|
||||
jne eight_sync_next
|
||||
mov eax,1
|
||||
cmp esi,8
|
||||
jb @F
|
||||
mov eax,2
|
||||
@@:
|
||||
xor ebx,ebx
|
||||
cmp eax,poolGroups3D
|
||||
je eight_sync_credit
|
||||
inc ebx
|
||||
cmp eax,poolGroups3D[4]
|
||||
jne eight_sync_next
|
||||
eight_sync_credit:
|
||||
mov pyrOwner3D[esi*4],ebx
|
||||
inc pyrScore3D[ebx*4]
|
||||
eight_sync_next:
|
||||
inc esi
|
||||
cmp esi,16
|
||||
jb eight_sync_ball
|
||||
ret
|
||||
EightSyncGroups3D ENDP
|
||||
|
||||
; Called-ball eight-ball rules share only simulation and aiming with pyramid.
|
||||
EightFinish3D PROC uses ebx esi edi
|
||||
local originalPots:DWORD
|
||||
cmp pyrSettled3D,0
|
||||
jne eight_finish_done
|
||||
mov pyrSettled3D,1
|
||||
mov poolCallManual3D,0
|
||||
mov poolTraceValid3D,0
|
||||
mov eax,poolPotted3D
|
||||
mov originalPots,eax
|
||||
mov poolFoul3D,0
|
||||
cmp poolActive3D,0
|
||||
je eight_finish_foul
|
||||
cmp poolFirst3D,-1
|
||||
je eight_finish_foul
|
||||
cmp poolBreak3D,0
|
||||
jne eight_finish_break
|
||||
invoke EightLegal3D,poolFirst3D
|
||||
test eax,eax
|
||||
jz eight_finish_foul
|
||||
cmp poolRail3D,0
|
||||
jne eight_finish_eight
|
||||
cmp poolPotted3D,0
|
||||
jne eight_finish_eight
|
||||
jmp eight_finish_foul
|
||||
eight_finish_break:
|
||||
mov eax,poolPotted3D
|
||||
and eax,0FFFEh
|
||||
jnz eight_finish_eight
|
||||
mov eax,poolBreakRails3D
|
||||
and eax,0FFFEh
|
||||
xor ecx,ecx
|
||||
eight_break_rails:
|
||||
test eax,eax
|
||||
jz @F
|
||||
lea edx,[eax-1]
|
||||
and eax,edx
|
||||
inc ecx
|
||||
jmp eight_break_rails
|
||||
@@:
|
||||
cmp ecx,4
|
||||
jae eight_finish_eight
|
||||
mov pyrIllegalBreak3D,1
|
||||
mov pyrFoulReason3D,2
|
||||
mov eax,poolPlayer3D
|
||||
xor eax,1
|
||||
mov poolPlayer3D,eax
|
||||
mov pyrChoiceActor3D,eax
|
||||
mov poolState3D,POOL_CHOICE
|
||||
mov poolTime3D,0
|
||||
call EightSyncGroups3D
|
||||
ret
|
||||
eight_finish_foul:
|
||||
mov poolFoul3D,1
|
||||
eight_finish_eight:
|
||||
bt poolPotted3D,8
|
||||
jnc eight_finish_continue
|
||||
cmp poolBreak3D,0
|
||||
je eight_finish_result
|
||||
invoke PyramidRespot3D,8
|
||||
btr poolPotted3D,8
|
||||
jmp eight_finish_continue
|
||||
eight_finish_result:
|
||||
mov eax,poolPlayer3D
|
||||
cmp poolFoul3D,0
|
||||
jne eight_finish_lost
|
||||
cmp poolAtStart3D,0
|
||||
jne eight_finish_lost
|
||||
mov ecx,poolGroups3D[eax*4]
|
||||
test ecx,ecx
|
||||
jz eight_finish_lost
|
||||
cmp poolCalled3D,8
|
||||
jne eight_finish_lost
|
||||
mov ecx,poolCalledPocket3D
|
||||
cmp poolPocket3D[32],ecx
|
||||
je eight_finish_winner
|
||||
eight_finish_lost:
|
||||
xor eax,1
|
||||
eight_finish_winner:
|
||||
mov poolWinner3D,eax
|
||||
mov poolState3D,POOL_RESULT
|
||||
call EightSyncGroups3D
|
||||
ret
|
||||
eight_finish_continue:
|
||||
cmp poolFoul3D,0
|
||||
jne eight_finish_hand
|
||||
cmp poolBreak3D,0
|
||||
je eight_finish_called
|
||||
mov eax,originalPots
|
||||
and eax,0FFFEh
|
||||
jnz eight_finish_aim
|
||||
jmp eight_finish_switch
|
||||
eight_finish_called:
|
||||
mov ebx,poolCalled3D
|
||||
cmp ebx,1
|
||||
jb eight_finish_switch
|
||||
cmp ebx,15
|
||||
ja eight_finish_switch
|
||||
bt poolPotted3D,ebx
|
||||
jnc eight_finish_switch
|
||||
mov eax,poolCalledPocket3D
|
||||
cmp poolPocket3D[ebx*4],eax
|
||||
jne eight_finish_switch
|
||||
invoke EightLegal3D,ebx
|
||||
test eax,eax
|
||||
jz eight_finish_switch
|
||||
mov ecx,poolPlayer3D
|
||||
cmp poolGroups3D[ecx*4],0
|
||||
jne eight_finish_aim
|
||||
mov eax,1
|
||||
cmp ebx,8
|
||||
jb @F
|
||||
mov eax,2
|
||||
@@:
|
||||
mov poolGroups3D[ecx*4],eax
|
||||
xor ecx,1
|
||||
xor eax,3
|
||||
mov poolGroups3D[ecx*4],eax
|
||||
jmp eight_finish_aim
|
||||
eight_finish_hand:
|
||||
xor poolPlayer3D,1
|
||||
mov poolState3D,POOL_HAND
|
||||
mov poolBreak3D,0
|
||||
mov poolTime3D,0
|
||||
mov pyrCue3D,0
|
||||
mov poolActive3D,0
|
||||
call EightSyncGroups3D
|
||||
ret
|
||||
eight_finish_switch:
|
||||
xor poolPlayer3D,1
|
||||
eight_finish_aim:
|
||||
mov poolState3D,POOL_AIM
|
||||
mov poolBreak3D,0
|
||||
mov poolTime3D,0
|
||||
mov pyrCue3D,0
|
||||
call EightCount3D
|
||||
call EightSyncGroups3D
|
||||
eight_finish_done:
|
||||
ret
|
||||
EightFinish3D ENDP
|
||||
|
||||
EightHand3D PROC uses ebx esi
|
||||
cmp poolPlayer3D,1
|
||||
jne eight_hand_human
|
||||
cmp poolAI3D,0
|
||||
je eight_hand_human
|
||||
mov esi,55*FP_1
|
||||
eight_hand_row:
|
||||
mov ebx,40*FP_1
|
||||
eight_hand_cell:
|
||||
invoke PoolPlaceCue3D,ebx,esi
|
||||
test eax,eax
|
||||
jnz eight_hand_placed
|
||||
add ebx,6*FP_1
|
||||
cmp ebx,280*FP_1
|
||||
jle eight_hand_cell
|
||||
add esi,6*FP_1
|
||||
cmp esi,175*FP_1
|
||||
jle eight_hand_row
|
||||
ret
|
||||
eight_hand_human:
|
||||
cmp mouseClick3D,0
|
||||
je eight_hand_done
|
||||
mov mouseClick3D,0
|
||||
mov eax,mouseX3D
|
||||
shl eax,16
|
||||
mov ebx,mouseY3D
|
||||
shl ebx,16
|
||||
invoke PoolPlaceCue3D,eax,ebx
|
||||
test eax,eax
|
||||
jz eight_hand_done
|
||||
eight_hand_placed:
|
||||
mov poolState3D,POOL_AIM
|
||||
mov poolTime3D,0
|
||||
mov poolTraceValid3D,0
|
||||
eight_hand_done:
|
||||
ret
|
||||
EightHand3D ENDP
|
||||
|
|
@ -165,4 +165,5 @@ stairsTime3D dd 0
|
|||
stairsReturnX3D dd 0
|
||||
stairsReturnY3D dd 0
|
||||
stairsReturnAngle3D dd 0
|
||||
include src_graphics\world_dressing_data.inc
|
||||
.code
|
||||
|
|
|
|||
383
src_graphics/hall_lighting.inc
Normal file
|
|
@ -0,0 +1,383 @@
|
|||
; Static world-space light and contact maps, shaded only before the HUD.
|
||||
HallLightVisible3D PROC uses ebx esi lx:DWORD,ly:DWORD,tx:DWORD,ty:DWORD
|
||||
mov esi,1
|
||||
hall_light_ray:
|
||||
mov eax,tx
|
||||
sub eax,lx
|
||||
imul eax,esi
|
||||
sar eax,3
|
||||
add eax,lx
|
||||
sar eax,3
|
||||
mov ebx,eax
|
||||
mov eax,ty
|
||||
sub eax,ly
|
||||
imul eax,esi
|
||||
sar eax,3
|
||||
add eax,ly
|
||||
sar eax,3
|
||||
shl eax,5
|
||||
add eax,ebx
|
||||
cmp casinoMap[eax],0
|
||||
jne hall_light_blocked
|
||||
inc esi
|
||||
cmp esi,8
|
||||
jb hall_light_ray
|
||||
mov eax,1
|
||||
ret
|
||||
hall_light_blocked:
|
||||
xor eax,eax
|
||||
ret
|
||||
HallLightVisible3D ENDP
|
||||
|
||||
AddHallLight3D PROC uses ebx esi edi wx:DWORD,wy:DWORD,radius:DWORD,power:DWORD
|
||||
local lightX:DWORD,lightY:DWORD,gx:DWORD,gy:DWORD,minX:DWORD,maxX:DWORD,maxY:DWORD
|
||||
local radiusSq:DWORD,weight:DWORD
|
||||
mov eax,wx
|
||||
sar eax,13
|
||||
mov lightX,eax
|
||||
mov eax,wy
|
||||
sar eax,13
|
||||
mov lightY,eax
|
||||
mov eax,radius
|
||||
imul eax,eax
|
||||
mov radiusSq,eax
|
||||
mov eax,lightX
|
||||
sub eax,radius
|
||||
jns @F
|
||||
xor eax,eax
|
||||
@@:
|
||||
mov minX,eax
|
||||
mov eax,lightX
|
||||
add eax,radius
|
||||
cmp eax,255
|
||||
jle @F
|
||||
mov eax,255
|
||||
@@:
|
||||
mov maxX,eax
|
||||
mov eax,lightY
|
||||
sub eax,radius
|
||||
jns @F
|
||||
xor eax,eax
|
||||
@@:
|
||||
mov gy,eax
|
||||
mov eax,lightY
|
||||
add eax,radius
|
||||
cmp eax,255
|
||||
jle @F
|
||||
mov eax,255
|
||||
@@:
|
||||
mov maxY,eax
|
||||
hall_light_bake_row:
|
||||
mov eax,minX
|
||||
mov gx,eax
|
||||
hall_light_bake_cell:
|
||||
mov eax,gx
|
||||
sub eax,lightX
|
||||
imul eax,eax
|
||||
mov ebx,gy
|
||||
sub ebx,lightY
|
||||
imul ebx,ebx
|
||||
add eax,ebx
|
||||
cmp eax,radiusSq
|
||||
jae hall_light_bake_next
|
||||
neg eax
|
||||
add eax,radiusSq
|
||||
shl eax,8
|
||||
xor edx,edx
|
||||
div radiusSq
|
||||
imul eax,eax
|
||||
imul eax,power
|
||||
shr eax,16
|
||||
test eax,eax
|
||||
jz hall_light_bake_next
|
||||
mov weight,eax
|
||||
invoke HallLightVisible3D,lightX,lightY,gx,gy
|
||||
test eax,eax
|
||||
jz hall_light_bake_next
|
||||
mov edi,gy
|
||||
shl edi,8
|
||||
add edi,gx
|
||||
movzx eax,hallLightMap3D[edi]
|
||||
add eax,weight
|
||||
cmp eax,160
|
||||
jbe @F
|
||||
mov eax,160
|
||||
@@:
|
||||
mov hallLightMap3D[edi],al
|
||||
hall_light_bake_next:
|
||||
inc gx
|
||||
mov eax,gx
|
||||
cmp eax,maxX
|
||||
jle hall_light_bake_cell
|
||||
inc gy
|
||||
mov eax,gy
|
||||
cmp eax,maxY
|
||||
jle hall_light_bake_row
|
||||
ret
|
||||
AddHallLight3D ENDP
|
||||
|
||||
AddHallContact3D PROC uses ebx esi edi wx:DWORD,wy:DWORD,worldWidth:DWORD
|
||||
local centerX:DWORD,centerY:DWORD,radius:DWORD,gx:DWORD,gy:DWORD,minX:DWORD,maxX:DWORD,maxY:DWORD
|
||||
mov eax,wx
|
||||
sar eax,13
|
||||
mov centerX,eax
|
||||
mov eax,wy
|
||||
sar eax,13
|
||||
mov centerY,eax
|
||||
mov eax,worldWidth
|
||||
shr eax,14
|
||||
add eax,2
|
||||
mov radius,eax
|
||||
mov eax,centerX
|
||||
sub eax,radius
|
||||
jns @F
|
||||
xor eax,eax
|
||||
@@:
|
||||
mov minX,eax
|
||||
mov eax,centerX
|
||||
add eax,radius
|
||||
cmp eax,255
|
||||
jle @F
|
||||
mov eax,255
|
||||
@@:
|
||||
mov maxX,eax
|
||||
mov eax,centerY
|
||||
sub eax,4
|
||||
jns @F
|
||||
xor eax,eax
|
||||
@@:
|
||||
mov gy,eax
|
||||
mov eax,centerY
|
||||
add eax,4
|
||||
cmp eax,255
|
||||
jle @F
|
||||
mov eax,255
|
||||
@@:
|
||||
mov maxY,eax
|
||||
hall_contact_row:
|
||||
mov eax,minX
|
||||
mov gx,eax
|
||||
hall_contact_cell:
|
||||
mov eax,gx
|
||||
sub eax,centerX
|
||||
imul eax,256
|
||||
cdq
|
||||
idiv radius
|
||||
imul eax,eax
|
||||
mov ebx,eax
|
||||
mov eax,gy
|
||||
sub eax,centerY
|
||||
imul eax,64
|
||||
imul eax,eax
|
||||
add eax,ebx
|
||||
cmp eax,65536
|
||||
jae hall_contact_next
|
||||
neg eax
|
||||
add eax,65536
|
||||
imul eax,40
|
||||
shr eax,16
|
||||
mov edi,gy
|
||||
shl edi,8
|
||||
add edi,gx
|
||||
cmp al,hallContactMap3D[edi]
|
||||
jbe hall_contact_next
|
||||
mov hallContactMap3D[edi],al
|
||||
hall_contact_next:
|
||||
inc gx
|
||||
mov eax,gx
|
||||
cmp eax,maxX
|
||||
jle hall_contact_cell
|
||||
inc gy
|
||||
mov eax,gy
|
||||
cmp eax,maxY
|
||||
jle hall_contact_row
|
||||
ret
|
||||
AddHallContact3D ENDP
|
||||
|
||||
BuildHallLighting3D PROC uses ebx esi edi
|
||||
lea edi,hallLightMap3D
|
||||
xor eax,eax
|
||||
mov ecx,WORLD_LIGHT_W*WORLD_LIGHT_H
|
||||
rep stosb
|
||||
lea edi,hallContactMap3D
|
||||
mov ecx,WORLD_LIGHT_W*WORLD_LIGHT_H
|
||||
rep stosb
|
||||
lea esi,hallLights3D
|
||||
mov edi,HALL_LIGHT_COUNT
|
||||
hall_bake_chandelier:
|
||||
invoke AddHallLight3D,[esi].CityProp3D.posX,[esi].CityProp3D.posY,32,86
|
||||
add esi,SIZEOF CityProp3D
|
||||
dec edi
|
||||
jnz hall_bake_chandelier
|
||||
lea esi,hallLoungeDecor3D
|
||||
mov edi,HALL_DECOR_COUNT
|
||||
hall_bake_furniture:
|
||||
cmp [esi].CityProp3D.asset,OFFSET hallRopeFurniture3D
|
||||
je hall_bake_furniture_next
|
||||
invoke AddHallContact3D,[esi].CityProp3D.posX,[esi].CityProp3D.posY,[esi].CityProp3D.worldW
|
||||
cmp [esi].CityProp3D.asset,OFFSET hallLampFurniture3D
|
||||
jne hall_bake_furniture_next
|
||||
invoke AddHallLight3D,[esi].CityProp3D.posX,[esi].CityProp3D.posY,20,110
|
||||
hall_bake_furniture_next:
|
||||
add esi,SIZEOF CityProp3D
|
||||
dec edi
|
||||
jnz hall_bake_furniture
|
||||
xor esi,esi
|
||||
hall_bake_sconce:
|
||||
invoke AddHallLight3D,FP_1*5/4,hallSconceY3D[esi*4],22,110
|
||||
invoke AddHallLight3D,FP_1*123/4,hallSconceY3D[esi*4],22,110
|
||||
inc esi
|
||||
cmp esi,4
|
||||
jb hall_bake_sconce
|
||||
invoke AddHallLight3D,4*FP_1,23*FP_1,22,90
|
||||
invoke AddHallLight3D,6*FP_1,23*FP_1,22,90
|
||||
invoke AddHallLight3D,8*FP_1,23*FP_1,22,90
|
||||
mov hallLightReady3D,1
|
||||
ret
|
||||
BuildHallLighting3D ENDP
|
||||
|
||||
ApplyHallLighting3D PROC uses ebx esi edi
|
||||
local rowY:DWORD,columnX:DWORD,planeDepth:DWORD,planeFloor:DWORD
|
||||
local gainR:DWORD,gainG:DWORD,gainB:DWORD,cell:DWORD,floorHit:DWORD
|
||||
local light:DWORD,contact:DWORD,pixelRow:DWORD,pixelColumn:DWORD
|
||||
cmp hallLighting3D,0
|
||||
je hall_light_draw_done
|
||||
cmp hallLightReady3D,0
|
||||
je hall_light_draw_done
|
||||
cmp outdoorRender3D,0
|
||||
jne hall_light_draw_done
|
||||
cmp hallLevel3D,0
|
||||
jne hall_light_draw_done
|
||||
mov rowY,0
|
||||
hall_light_draw_row:
|
||||
mov eax,rowY
|
||||
mov planeFloor,0
|
||||
cmp eax,viewHorizon3D
|
||||
jge hall_light_floor_depth
|
||||
mov ecx,viewHorizon3D
|
||||
sub ecx,eax
|
||||
mov eax,viewCeiling3D
|
||||
sub eax,viewEye3D
|
||||
jmp hall_light_plane_depth
|
||||
hall_light_floor_depth:
|
||||
sub eax,viewHorizon3D
|
||||
inc eax
|
||||
mov ecx,eax
|
||||
mov eax,viewEye3D
|
||||
mov planeFloor,1
|
||||
hall_light_plane_depth:
|
||||
imul eax,480
|
||||
cdq
|
||||
idiv ecx
|
||||
mov planeDepth,eax
|
||||
mov columnX,0
|
||||
hall_light_draw_column:
|
||||
imul edi,rowY,640
|
||||
add edi,columnX
|
||||
mov eax,cityDepthBuffer3D[edi*4]
|
||||
mov floorHit,0
|
||||
cmp eax,planeDepth
|
||||
jl @F
|
||||
mov eax,planeDepth
|
||||
mov edx,planeFloor
|
||||
mov floorHit,edx
|
||||
@@:
|
||||
mov esi,eax
|
||||
mov ebx,columnX
|
||||
imul cityRayX3D[ebx*4]
|
||||
shrd eax,edx,16
|
||||
add eax,playerX
|
||||
sar eax,13
|
||||
cmp eax,256
|
||||
jae hall_light_ambient
|
||||
mov cell,eax
|
||||
mov eax,esi
|
||||
imul cityRayY3D[ebx*4]
|
||||
shrd eax,edx,16
|
||||
add eax,playerY
|
||||
sar eax,13
|
||||
cmp eax,256
|
||||
jae hall_light_ambient
|
||||
shl eax,8
|
||||
add eax,cell
|
||||
movzx ecx,hallLightMap3D[eax]
|
||||
mov light,ecx
|
||||
mov contact,0
|
||||
cmp floorHit,0
|
||||
je hall_light_gains
|
||||
movzx eax,hallContactMap3D[eax]
|
||||
mov contact,eax
|
||||
jmp hall_light_gains
|
||||
hall_light_ambient:
|
||||
mov light,0
|
||||
mov contact,0
|
||||
hall_light_gains:
|
||||
mov eax,light
|
||||
add eax,184
|
||||
sub eax,contact
|
||||
mov gainR,eax
|
||||
mov eax,light
|
||||
imul eax,7
|
||||
shr eax,3
|
||||
add eax,188
|
||||
sub eax,contact
|
||||
mov gainG,eax
|
||||
mov eax,light
|
||||
shr eax,1
|
||||
add eax,200
|
||||
sub eax,contact
|
||||
mov gainB,eax
|
||||
mov pixelRow,0
|
||||
hall_light_pixel_row:
|
||||
mov pixelColumn,0
|
||||
hall_light_pixel:
|
||||
mov eax,pixelRow
|
||||
imul eax,640
|
||||
add eax,pixelColumn
|
||||
add eax,edi
|
||||
mov esi,eax
|
||||
mov ebx,screenBuffer[esi*4]
|
||||
movzx eax,bl
|
||||
imul eax,gainB
|
||||
shr eax,8
|
||||
cmp eax,255
|
||||
jbe @F
|
||||
mov eax,255
|
||||
@@:
|
||||
mov ecx,eax
|
||||
movzx eax,bh
|
||||
imul eax,gainG
|
||||
shr eax,8
|
||||
cmp eax,255
|
||||
jbe @F
|
||||
mov eax,255
|
||||
@@:
|
||||
shl eax,8
|
||||
or ecx,eax
|
||||
mov eax,ebx
|
||||
shr eax,16
|
||||
and eax,255
|
||||
imul eax,gainR
|
||||
shr eax,8
|
||||
cmp eax,255
|
||||
jbe @F
|
||||
mov eax,255
|
||||
@@:
|
||||
shl eax,16
|
||||
or eax,ecx
|
||||
mov screenBuffer[esi*4],eax
|
||||
inc pixelColumn
|
||||
cmp pixelColumn,2
|
||||
jb hall_light_pixel
|
||||
inc pixelRow
|
||||
cmp pixelRow,2
|
||||
jb hall_light_pixel_row
|
||||
add columnX,2
|
||||
cmp columnX,640
|
||||
jb hall_light_draw_column
|
||||
add rowY,2
|
||||
cmp rowY,480
|
||||
jb hall_light_draw_row
|
||||
hall_light_draw_done:
|
||||
ret
|
||||
ApplyHallLighting3D ENDP
|
||||
|
|
@ -280,7 +280,7 @@ InitHall3D PROC uses esi edi
|
|||
rep movsd
|
||||
mov hallLevel3D, 0
|
||||
mov worldMap3D, OFFSET casinoMap
|
||||
mov viewEye3D, FP_1*17/20
|
||||
mov viewEye3D, HALL_STANDING_EYE
|
||||
mov viewCeiling3D, FP_1*5/2
|
||||
mov floorTexture3D, 100
|
||||
mov casinoSprites[14*SIZEOF SpriteObject].interactId, 0
|
||||
|
|
@ -303,10 +303,13 @@ init_plane_lut:
|
|||
init_plane_done:
|
||||
call InitCasinoNpcMind
|
||||
call InitNpcLife3D
|
||||
call BuildHallLighting3D
|
||||
ret
|
||||
InitHall3D ENDP
|
||||
|
||||
LoadHallAssets3D PROC
|
||||
call LoadWorldDressing3D
|
||||
call LoadScratchArt3D
|
||||
invoke LoadAnimPack3D, OFFSET hallCardFurniture3D, OFFSET hallCardFurniturePath3D
|
||||
invoke LoadAnimPack3D, OFFSET hallWheelFurniture3D, OFFSET hallWheelFurniturePath3D
|
||||
invoke LoadAnimPack3D, OFFSET hallBackFurniture3D, OFFSET hallBackFurniturePath3D
|
||||
|
|
@ -376,6 +379,7 @@ hall_load_sign:
|
|||
LoadHallAssets3D ENDP
|
||||
|
||||
FreeHallAssets3D PROC
|
||||
call FreeWorldDressing3D
|
||||
call FreeNativeWheelArt3D
|
||||
call FreeNativeCoinArt3D
|
||||
invoke FreeAnimPack3D, OFFSET hallCardFurniture3D
|
||||
|
|
@ -556,6 +560,9 @@ hall_render_lounge:
|
|||
cmp esi, HALL_DECOR_COUNT
|
||||
jb hall_render_lounge
|
||||
call RenderPatrons3D
|
||||
invoke DrawCityObject3D,OFFSET scrStation3D,0
|
||||
call RenderHallDressing3D
|
||||
call ApplyHallLighting3D
|
||||
ret
|
||||
hall_render_bunker:
|
||||
mov esi, 0
|
||||
|
|
@ -649,6 +656,7 @@ CheckHallInteractions3D PROC
|
|||
; A point on the serving edge remains in front even when standing close.
|
||||
invoke HallTarget3D, playerX,23*FP_1+FP_HALF,INTERACT_BAR,OFFSET hallBarPrompt3D
|
||||
hall_check_other:
|
||||
invoke HallTarget3D,scrStation3D.posX,scrStation3D.posY,INTERACT_SCRATCH,OFFSET scratchHall3D
|
||||
invoke HallTarget3D, 28*FP_1+FP_HALF,10*FP_1+FP_HALF,INTERACT_BASEMENT,OFFSET hallBunkerPrompt3D
|
||||
invoke HallTarget3D, 27*FP_1,25*FP_1,INTERACT_BILLIARDS,OFFSET hallPoolPrompt3D
|
||||
call CheckNpcInteractions3D
|
||||
|
|
@ -662,6 +670,12 @@ hall_check_bunker:
|
|||
CheckHallInteractions3D ENDP
|
||||
|
||||
TriggerHallInteraction3D PROC
|
||||
cmp interactTargetId,INTERACT_SCRATCH
|
||||
jne @F
|
||||
call BeginScratch3D
|
||||
mov eax,1
|
||||
ret
|
||||
@@:
|
||||
cmp interactTargetId,INTERACT_NPC
|
||||
jne @F
|
||||
call OpenNpcDialog3D
|
||||
|
|
@ -737,6 +751,10 @@ stairs_back_to_hall:
|
|||
mov playerAngle, eax
|
||||
stairs_complete:
|
||||
mov viewEye3D, FP_1*17/20
|
||||
cmp hallLevel3D,0
|
||||
jne @F
|
||||
mov viewEye3D,HALL_STANDING_EYE
|
||||
@@:
|
||||
mov engineMode, MODE_WALK
|
||||
call ClearKeys3D
|
||||
stairs_handle_done:
|
||||
|
|
@ -915,7 +933,7 @@ RenderBar3D PROC uses ebx
|
|||
mov playerY, 25*FP_1+FP_1/3
|
||||
mov playerAngle, 384
|
||||
mov viewHorizon3D, HALF_H
|
||||
mov viewEye3D, FP_1*17/20
|
||||
mov viewEye3D, HALL_STANDING_EYE
|
||||
call UpdateCamera3D
|
||||
call RenderCeilingAndFloor
|
||||
call RenderWalls
|
||||
|
|
@ -1027,6 +1045,9 @@ RenderCityGuards3D ENDP
|
|||
CanWalkHall3D PROC uses esi ebx px:DWORD,py:DWORD
|
||||
cmp hallLevel3D, 0
|
||||
jne hall_collision_bunker
|
||||
invoke ScratchCanWalk3D,px,py
|
||||
test eax,eax
|
||||
jz hall_collision_blocked
|
||||
xor esi, esi
|
||||
hall_collision_decor:
|
||||
imul ebx, esi, SIZEOF CityProp3D
|
||||
|
|
@ -1204,7 +1225,10 @@ UpdateHall3D PROC
|
|||
mov viewHorizon3D, HALF_H
|
||||
mov viewEye3D, FP_1*17/20
|
||||
cmp hallLevel3D, 0
|
||||
je @F
|
||||
jne hall_update_bunker_eye
|
||||
mov viewEye3D,HALL_STANDING_EYE
|
||||
jmp @F
|
||||
hall_update_bunker_eye:
|
||||
mov eax, playerY
|
||||
sub eax, 24*FP_1
|
||||
jle @F
|
||||
|
|
@ -1327,3 +1351,5 @@ patron_render_loop:
|
|||
jb patron_render_loop
|
||||
ret
|
||||
RenderPatrons3D ENDP
|
||||
include src_graphics\world_dressing.inc
|
||||
include src_graphics\hall_lighting.inc
|
||||
|
|
|
|||
249
src_graphics/native_dice.inc
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
LoadNativeDiceArt3D PROC
|
||||
cmp diceArtReady3D,1
|
||||
je dice_art_loaded
|
||||
invoke LoadAnimPack3D,OFFSET diceTableArt3D,OFFSET diceTablePath3D
|
||||
invoke LoadAnimPack3D,OFFSET diceHandsArt3D,OFFSET diceHandsPath3D
|
||||
invoke ValidateCityPack3D,OFFSET diceTableArt3D,640,480,1
|
||||
invoke ValidateCityPack3D,OFFSET diceHandsArt3D,256,320,16
|
||||
cmp diceTableArt3D.pixels,0
|
||||
je dice_art_failed
|
||||
cmp diceHandsArt3D.pixels,0
|
||||
je dice_art_failed
|
||||
mov diceArtReady3D,1
|
||||
dice_art_loaded:
|
||||
mov eax,1
|
||||
ret
|
||||
dice_art_failed:
|
||||
call FreeNativeDiceArt3D
|
||||
xor eax,eax
|
||||
ret
|
||||
LoadNativeDiceArt3D ENDP
|
||||
|
||||
FreeNativeDiceArt3D PROC
|
||||
invoke FreeAnimPack3D,OFFSET diceTableArt3D
|
||||
invoke FreeAnimPack3D,OFFSET diceHandsArt3D
|
||||
mov diceArtReady3D,0
|
||||
ret
|
||||
FreeNativeDiceArt3D ENDP
|
||||
|
||||
DiceEscape3D PROC
|
||||
mov paused3D,0
|
||||
cmp dice3d_state,1
|
||||
jne dice_escape_now
|
||||
mov diceExitQueued3D,1
|
||||
call ClearKeys3D
|
||||
ret
|
||||
dice_escape_now:
|
||||
mov diceExitQueued3D,0
|
||||
mov engineMode,MODE_WALK
|
||||
call ClearKeys3D
|
||||
invoke PlayCasinoSound3D,0,0,0
|
||||
ret
|
||||
DiceEscape3D ENDP
|
||||
|
||||
HandleDiceMouse3D PROC
|
||||
cmp mouseClick3D,0
|
||||
je dice_mouse_done
|
||||
mov mouseClick3D,0
|
||||
cmp mouseY3D,3
|
||||
jb dice_mouse_done
|
||||
cmp mouseY3D,17
|
||||
jae dice_mouse_footer
|
||||
cmp mouseX3D,252
|
||||
jb dice_mouse_done
|
||||
cmp mouseX3D,312
|
||||
jae dice_mouse_done
|
||||
call DiceEscape3D
|
||||
ret
|
||||
dice_mouse_footer:
|
||||
cmp dice3d_state,1
|
||||
je dice_mouse_done
|
||||
cmp mouseY3D,218
|
||||
jb dice_mouse_stake
|
||||
cmp mouseY3D,236
|
||||
jae dice_mouse_done
|
||||
cmp mouseX3D,198
|
||||
jb dice_mouse_choice
|
||||
cmp mouseX3D,312
|
||||
jae dice_mouse_done
|
||||
mov pressedKeys3D[20h],1
|
||||
ret
|
||||
dice_mouse_choice:
|
||||
cmp dice3d_state,0
|
||||
jne dice_mouse_done
|
||||
cmp mouseX3D,8
|
||||
jb dice_mouse_done
|
||||
cmp mouseX3D,96
|
||||
jae @F
|
||||
mov pressedKeys3D[31h],1
|
||||
ret
|
||||
@@:
|
||||
cmp mouseX3D,100
|
||||
jb dice_mouse_done
|
||||
cmp mouseX3D,188
|
||||
jae dice_mouse_done
|
||||
mov pressedKeys3D[32h],1
|
||||
ret
|
||||
dice_mouse_stake:
|
||||
cmp dice3d_state,0
|
||||
jne dice_mouse_done
|
||||
cmp mouseY3D,199
|
||||
jb dice_mouse_done
|
||||
cmp mouseY3D,215
|
||||
jae dice_mouse_done
|
||||
cmp mouseX3D,118
|
||||
jb dice_mouse_done
|
||||
cmp mouseX3D,134
|
||||
jae @F
|
||||
mov pressedKeys3D[28h],1
|
||||
ret
|
||||
@@:
|
||||
cmp mouseX3D,140
|
||||
jb dice_mouse_done
|
||||
cmp mouseX3D,156
|
||||
jae dice_mouse_done
|
||||
mov pressedKeys3D[26h],1
|
||||
dice_mouse_done:
|
||||
ret
|
||||
HandleDiceMouse3D ENDP
|
||||
|
||||
; Original payment/parity rules remain a single command path for both inputs.
|
||||
HandleDiceInput PROC
|
||||
call HandleDiceMouse3D
|
||||
call HandleDiceRules3D
|
||||
cmp diceExitQueued3D,1
|
||||
jne dice_input_done
|
||||
cmp dice3d_state,1
|
||||
je dice_input_done
|
||||
call DiceEscape3D
|
||||
dice_input_done:
|
||||
ret
|
||||
HandleDiceInput ENDP
|
||||
|
||||
DrawDiceHand3D PROC uses ebx esi
|
||||
local frame:DWORD,py:DWORD
|
||||
mov frame,0
|
||||
mov py,90
|
||||
cmp dice3d_state,0
|
||||
je dice_hand_draw
|
||||
cmp dice3d_state,1
|
||||
jne dice_hand_done
|
||||
mov eax,dice3d_timer
|
||||
cmp eax,240
|
||||
jae dice_hand_release
|
||||
imul eax,4
|
||||
xor edx,edx
|
||||
mov ecx,240
|
||||
div ecx
|
||||
mov frame,eax
|
||||
jmp dice_hand_draw
|
||||
dice_hand_release:
|
||||
cmp eax,1000
|
||||
jae dice_hand_lower
|
||||
sub eax,240
|
||||
imul eax,12
|
||||
xor edx,edx
|
||||
mov ecx,760
|
||||
div ecx
|
||||
add eax,4
|
||||
mov frame,eax
|
||||
jmp dice_hand_draw
|
||||
dice_hand_lower:
|
||||
cmp eax,1250
|
||||
jae dice_hand_done
|
||||
sub eax,1000
|
||||
imul eax,260
|
||||
xor edx,edx
|
||||
mov ecx,250
|
||||
div ecx
|
||||
add py,eax
|
||||
mov frame,15
|
||||
dice_hand_draw:
|
||||
invoke DrawAnimSprite3D,OFFSET diceHandsArt3D,frame,320,py,256,320
|
||||
dice_hand_done:
|
||||
ret
|
||||
DrawDiceHand3D ENDP
|
||||
|
||||
RenderNativeDice3D PROC uses ebx esi edi
|
||||
local evenTint:DWORD,oddTint:DWORD
|
||||
cmp diceArtReady3D,1
|
||||
jne dice_scene_fallback
|
||||
mov esi,diceTableArt3D.pixels
|
||||
lea edi,screenBuffer
|
||||
mov ecx,SCREEN_SIZE
|
||||
rep movsd
|
||||
jmp dice_scene_objects
|
||||
dice_scene_fallback:
|
||||
invoke DrawBox,0,0,320,240,000B342Bh
|
||||
invoke DrawString8x8,96,64,OFFSET coinMissingText3D,00E5D29Eh
|
||||
dice_scene_objects:
|
||||
; Cloth shadows belong behind the foreground hand, never on its skin.
|
||||
mov diceShadowPass3D,1
|
||||
call RenderDiceThrow3D
|
||||
mov diceShadowPass3D,0
|
||||
call DrawDiceHand3D
|
||||
call RenderDiceThrow3D
|
||||
invoke DrawBox,0,0,320,20,0014191Dh
|
||||
invoke DrawString8x8,12,6,OFFSET textDiceTitle,00E5D29Eh
|
||||
invoke DrawBoxBorder,252,3,60,14,00252D2Ah,0086754Eh,1
|
||||
invoke DrawString8x8,266,6,OFFSET coinExitText3D,00E5D29Eh
|
||||
invoke DrawBox,4,23,132,15,0014191Dh
|
||||
invoke DrawString8x8,8,27,OFFSET textBankPrompt,00E5D29Eh
|
||||
invoke FormatNumber,bankroll,OFFSET hudNumBuffer
|
||||
invoke DrawString8x8,56,27,OFFSET hudNumBuffer,00FFFFFFh
|
||||
invoke DrawBox,0,194,320,46,0014191Dh
|
||||
invoke DrawString8x8,8,201,OFFSET coinStakeText3D,00E5D29Eh
|
||||
invoke FormatNumber,dice3d_bet,OFFSET hudNumBuffer
|
||||
invoke DrawString8x8,72,201,OFFSET hudNumBuffer,00FFFFFFh
|
||||
invoke DrawBoxBorder,118,199,16,16,00252D2Ah,0086754Eh,1
|
||||
invoke DrawString8x8,124,203,OFFSET coinMinusText3D,00E5D29Eh
|
||||
invoke DrawBoxBorder,140,199,16,16,00252D2Ah,0086754Eh,1
|
||||
invoke DrawString8x8,146,203,OFFSET coinPlusText3D,00E5D29Eh
|
||||
mov evenTint,0086754Eh
|
||||
mov oddTint,0086754Eh
|
||||
cmp dice3d_choice,1
|
||||
jne @F
|
||||
mov evenTint,00E5D29Eh
|
||||
jmp dice_scene_choices
|
||||
@@:
|
||||
mov oddTint,00E5D29Eh
|
||||
dice_scene_choices:
|
||||
invoke DrawBoxBorder,8,218,88,18,00252D2Ah,evenTint,1
|
||||
invoke DrawString8x8,26,223,OFFSET textDiceEven,evenTint
|
||||
invoke DrawBoxBorder,100,218,88,18,00252D2Ah,oddTint,1
|
||||
invoke DrawString8x8,112,223,OFFSET textDiceOdd,oddTint
|
||||
invoke DrawBoxBorder,198,218,114,18,00252D2Ah,0086754Eh,1
|
||||
cmp dice3d_state,2
|
||||
jne @F
|
||||
invoke DrawString8x8,224,223,OFFSET diceAgainText3D,00E5D29Eh
|
||||
jmp dice_scene_status
|
||||
@@:
|
||||
invoke DrawString8x8,226,223,OFFSET diceThrowText3D,00E5D29Eh
|
||||
dice_scene_status:
|
||||
cmp diceExitQueued3D,0
|
||||
je @F
|
||||
invoke DrawString8x8,164,201,OFFSET coinLeavingText3D,00E5D29Eh
|
||||
@@:
|
||||
cmp dice3d_state,2
|
||||
jne dice_scene_done
|
||||
invoke DrawBox,8,176,304,16,0014191Dh
|
||||
invoke DrawString8x8,12,180,OFFSET textDiceSumHdr,00E5D29Eh
|
||||
invoke FormatNumber,dice3d_val1,OFFSET hudNumBuffer
|
||||
invoke DrawString8x8,72,180,OFFSET hudNumBuffer,00FFFFFFh
|
||||
invoke DrawString8x8,86,180,OFFSET coinPlusText3D,00E5D29Eh
|
||||
invoke FormatNumber,dice3d_val2,OFFSET hudNumBuffer
|
||||
invoke DrawString8x8,98,180,OFFSET hudNumBuffer,00FFFFFFh
|
||||
invoke DrawString8x8,112,180,OFFSET textDiceEqual+1,00E5D29Eh
|
||||
invoke FormatNumber,dice3d_sum,OFFSET hudNumBuffer
|
||||
invoke DrawString8x8,126,180,OFFSET hudNumBuffer,00FFFFFFh
|
||||
cmp dice3d_win,0
|
||||
je dice_scene_loss
|
||||
invoke DrawString8x8,158,180,OFFSET textDiceWin,0090D5ADh
|
||||
invoke FormatNumber,dice3d_win,OFFSET hudNumBuffer
|
||||
invoke DrawString8x8,248,180,OFFSET hudNumBuffer,0090D5ADh
|
||||
jmp dice_scene_done
|
||||
dice_scene_loss:
|
||||
invoke DrawString8x8,192,180,OFFSET textDiceLose,00FF6464h
|
||||
dice_scene_done:
|
||||
ret
|
||||
RenderNativeDice3D ENDP
|
||||
17
src_graphics/native_dice_data.inc
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
LoadNativeDiceArt3D PROTO
|
||||
FreeNativeDiceArt3D PROTO
|
||||
RenderNativeDice3D PROTO
|
||||
HandleDiceInput PROTO
|
||||
HandleDiceRules3D PROTO
|
||||
DiceEscape3D PROTO
|
||||
.data
|
||||
diceTableArt3D AnimPack3D <>
|
||||
diceHandsArt3D AnimPack3D <>
|
||||
diceTablePath3D db "assets\animations\coin\table-v1.bin",0
|
||||
diceHandsPath3D db "assets\animations\dice\hands-v2.bin",0
|
||||
diceArtReady3D dd 0
|
||||
diceExitQueued3D dd 0
|
||||
diceShadowPass3D dd 0
|
||||
diceThrowText3D db 193,208,206,209,206,202,0
|
||||
diceAgainText3D db 197,217,168,32,208,192,199,0
|
||||
.code
|
||||
|
|
@ -1,5 +1,12 @@
|
|||
; Main and owned coin-detail windows are processed on the same thread; no CMD fallback.
|
||||
WindowEvents3D PROC uses ebx esi edi hwnd:DWORD, uMsg:DWORD, wp:DWORD, lp:DWORD
|
||||
cmp engineMode,MODE_SCRATCH
|
||||
jne @F
|
||||
invoke ScratchMouseEvent3D,hwnd,uMsg,wp,lp
|
||||
test eax,eax
|
||||
jz @F
|
||||
ret
|
||||
@@:
|
||||
cmp uMsg, 102h
|
||||
jne @F
|
||||
invoke ArrivalChar3D, wp
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
PyramidSelect3D PROC uses ebx ball:DWORD
|
||||
cmp poolVariant3D,1
|
||||
jne @F
|
||||
mov pyrCue3D,0
|
||||
ret
|
||||
@@:
|
||||
cmp poolBreak3D,0
|
||||
je @F
|
||||
mov pyrCue3D,0
|
||||
|
|
@ -135,6 +140,8 @@ PoolShoot3D PROC uses ebx esi
|
|||
cmp poolX3D,95*FP_1
|
||||
jge pyr_shoot_done
|
||||
@@:
|
||||
call PoolCountGroup3D
|
||||
call EightAutoCall3D
|
||||
mov poolFirst3D,-1
|
||||
mov poolRail3D,0
|
||||
mov poolBreakRails3D,0
|
||||
|
|
@ -234,6 +241,8 @@ PoolChooseAI3D PROC uses ebx esi edi
|
|||
local cue:DWORD,target:DWORD,pocket:DWORD,deltaX:DWORD,deltaY:DWORD,distance:DWORD
|
||||
local gx:DWORD,gy:DWORD,best:DWORD,bestCue:DWORD,bestX:DWORD,bestY:DWORD,bestPower:DWORD
|
||||
local shotLength:DWORD
|
||||
local bestTarget:DWORD,bestPocket:DWORD
|
||||
call PoolCountGroup3D
|
||||
cmp poolBreak3D,0
|
||||
je pyr_ai_search
|
||||
mov pyrCue3D,0
|
||||
|
|
@ -247,6 +256,11 @@ pyr_ai_search:
|
|||
mov cue,0
|
||||
pyr_ai_cue:
|
||||
mov ecx,cue
|
||||
cmp poolVariant3D,1
|
||||
jne @F
|
||||
test ecx,ecx
|
||||
jnz pyr_ai_search_done
|
||||
@@:
|
||||
cmp poolActive3D[ecx*4],1
|
||||
jne pyr_ai_next_cue
|
||||
mov target,0
|
||||
|
|
@ -256,6 +270,12 @@ pyr_ai_target:
|
|||
je pyr_ai_next_target
|
||||
cmp poolActive3D[esi*4],1
|
||||
jne pyr_ai_next_target
|
||||
cmp poolVariant3D,1
|
||||
jne @F
|
||||
invoke EightLegal3D,esi
|
||||
test eax,eax
|
||||
jz pyr_ai_next_target
|
||||
@@:
|
||||
mov pocket,0
|
||||
pyr_ai_pocket:
|
||||
mov edi,pocket
|
||||
|
|
@ -332,6 +352,10 @@ pyr_ai_pocket:
|
|||
mov bestX,ecx
|
||||
mov ecx,gy
|
||||
mov bestY,ecx
|
||||
mov ecx,target
|
||||
mov bestTarget,ecx
|
||||
mov ecx,pocket
|
||||
mov bestPocket,ecx
|
||||
; v^2/(2*rolling loss) estimates the travel budget, with margin for a cut.
|
||||
sar eax,16
|
||||
imul eax,220
|
||||
|
|
@ -353,6 +377,7 @@ pyr_ai_next_cue:
|
|||
inc cue
|
||||
cmp cue,16
|
||||
jb pyr_ai_cue
|
||||
pyr_ai_search_done:
|
||||
cmp bestCue,-1
|
||||
je pyr_ai_safety
|
||||
mov eax,bestCue
|
||||
|
|
@ -360,8 +385,17 @@ pyr_ai_next_cue:
|
|||
invoke PoolAimPoint3D,bestX,bestY
|
||||
mov eax,bestPower
|
||||
mov poolPower3D,eax
|
||||
cmp poolVariant3D,1
|
||||
jne @F
|
||||
mov eax,bestTarget
|
||||
mov poolCalled3D,eax
|
||||
mov eax,bestPocket
|
||||
mov poolCalledPocket3D,eax
|
||||
mov poolCallManual3D,3
|
||||
@@:
|
||||
ret
|
||||
pyr_ai_safety:
|
||||
mov poolCallManual3D,0
|
||||
invoke PyramidSelect3D,-1
|
||||
mov esi,pyrCue3D
|
||||
xor edi,edi
|
||||
|
|
@ -369,7 +403,10 @@ pyr_ai_safety_target:
|
|||
cmp edi,esi
|
||||
je @F
|
||||
cmp poolActive3D[edi*4],1
|
||||
je pyr_ai_safety_found
|
||||
jne @F
|
||||
invoke PoolBallLegal3D,edi
|
||||
test eax,eax
|
||||
jnz pyr_ai_safety_found
|
||||
@@:
|
||||
inc edi
|
||||
cmp edi,16
|
||||
|
|
@ -382,6 +419,45 @@ pyr_ai_safety_found:
|
|||
PoolChooseAI3D ENDP
|
||||
|
||||
HandlePool3D PROC uses ebx esi edi
|
||||
cmp poolState3D,POOL_SELECT
|
||||
jne pyr_normal_input
|
||||
invoke Pressed3D,31h
|
||||
test eax,eax
|
||||
jnz pyr_start_pyramid
|
||||
invoke Pressed3D,32h
|
||||
test eax,eax
|
||||
jnz pyr_start_eight
|
||||
cmp mouseClick3D,0
|
||||
je pyr_handle_done
|
||||
mov mouseClick3D,0
|
||||
cmp mouseX3D,252
|
||||
jb @F
|
||||
cmp mouseY3D,17
|
||||
jb pyr_selector_exit
|
||||
@@:
|
||||
cmp mouseX3D,40
|
||||
jb pyr_handle_done
|
||||
cmp mouseX3D,280
|
||||
jae pyr_handle_done
|
||||
cmp mouseY3D,80
|
||||
jb pyr_handle_done
|
||||
cmp mouseY3D,128
|
||||
jb pyr_start_pyramid
|
||||
cmp mouseY3D,144
|
||||
jb pyr_handle_done
|
||||
cmp mouseY3D,192
|
||||
jae pyr_handle_done
|
||||
pyr_start_eight:
|
||||
invoke StartBilliards3D,1
|
||||
ret
|
||||
pyr_start_pyramid:
|
||||
invoke StartBilliards3D,0
|
||||
ret
|
||||
pyr_selector_exit:
|
||||
mov engineMode,MODE_WALK
|
||||
call ClearKeys3D
|
||||
ret
|
||||
pyr_normal_input:
|
||||
xor esi,esi
|
||||
pyr_sink_tick:
|
||||
mov eax,deltaTime3D
|
||||
|
|
@ -409,6 +485,7 @@ pyr_sink_tick:
|
|||
call SaveProgress3D
|
||||
ret
|
||||
pyr_update:
|
||||
mov eax,deltaTime3D
|
||||
cmp poolState3D,POOL_MOVING
|
||||
jne pyr_strike
|
||||
add poolAccumulator3D,eax
|
||||
|
|
@ -451,9 +528,14 @@ pyr_idle:
|
|||
cmp mouseX3D,202
|
||||
jb pyr_handle_done
|
||||
pyr_restart:
|
||||
call InitPool3D
|
||||
call ResetPool3D
|
||||
ret
|
||||
pyr_actor:
|
||||
cmp poolState3D,POOL_HAND
|
||||
jne @F
|
||||
call EightHand3D
|
||||
ret
|
||||
@@:
|
||||
cmp poolPlayer3D,1
|
||||
jne pyr_human
|
||||
cmp poolAI3D,0
|
||||
|
|
@ -560,11 +642,45 @@ pyr_human_aim:
|
|||
cmp pyrPickClick3D,0
|
||||
je @F
|
||||
mov pyrPickClick3D,0
|
||||
cmp poolVariant3D,1
|
||||
jne pyr_pick_object
|
||||
xor esi,esi
|
||||
eight_pick_pocket:
|
||||
mov ecx,eax
|
||||
sub ecx,poolPocketX3D[esi*4]
|
||||
sar ecx,12
|
||||
imul ecx,ecx
|
||||
mov edx,ebx
|
||||
sub edx,poolPocketY3D[esi*4]
|
||||
sar edx,12
|
||||
imul edx,edx
|
||||
add ecx,edx
|
||||
cmp ecx,81*16*16
|
||||
jbe eight_pick_pocket_found
|
||||
inc esi
|
||||
cmp esi,6
|
||||
jb eight_pick_pocket
|
||||
pyr_pick_object:
|
||||
invoke PyramidPick3D,eax,ebx
|
||||
cmp eax,-1
|
||||
je pyr_handle_done
|
||||
cmp poolVariant3D,1
|
||||
jne pyr_pick_pyramid
|
||||
mov ebx,eax
|
||||
call EightCount3D
|
||||
invoke EightLegal3D,ebx
|
||||
test eax,eax
|
||||
jz pyr_handle_done
|
||||
mov poolCalled3D,ebx
|
||||
or poolCallManual3D,1
|
||||
ret
|
||||
pyr_pick_pyramid:
|
||||
invoke PyramidSelect3D,eax
|
||||
ret
|
||||
eight_pick_pocket_found:
|
||||
mov poolCalledPocket3D,esi
|
||||
or poolCallManual3D,2
|
||||
ret
|
||||
@@:
|
||||
cmp poolBreak3D,0
|
||||
je pyr_mouse_aim
|
||||
|
|
@ -578,6 +694,23 @@ pyr_mouse_aim:
|
|||
invoke PoolAimPoint3D,eax,ebx
|
||||
ret
|
||||
pyr_mouse_footer:
|
||||
cmp poolVariant3D,1
|
||||
jne @F
|
||||
cmp ebx,187
|
||||
jb @F
|
||||
cmp ebx,209
|
||||
ja @F
|
||||
cmp eax,128
|
||||
jb @F
|
||||
cmp eax,194
|
||||
ja @F
|
||||
inc poolCalledPocket3D
|
||||
or poolCallManual3D,2
|
||||
cmp poolCalledPocket3D,6
|
||||
jb pyr_handle_done
|
||||
mov poolCalledPocket3D,0
|
||||
ret
|
||||
@@:
|
||||
cmp ebx,193
|
||||
jb pyr_keys
|
||||
cmp ebx,209
|
||||
|
|
@ -669,6 +802,8 @@ pyr_toggle_guide:
|
|||
xor pyrGuideOn3D,1
|
||||
ret
|
||||
pyr_cycle_cue:
|
||||
cmp poolVariant3D,1
|
||||
je eight_cycle_call
|
||||
cmp poolBreak3D,0
|
||||
jne pyr_handle_done
|
||||
mov esi,pyrCue3D
|
||||
|
|
@ -683,6 +818,26 @@ pyr_cycle_scan:
|
|||
ret
|
||||
pyr_cycle_found:
|
||||
invoke PyramidSelect3D,esi
|
||||
ret
|
||||
eight_cycle_call:
|
||||
call EightCount3D
|
||||
mov esi,poolCalled3D
|
||||
mov edi,16
|
||||
eight_cycle_scan:
|
||||
inc esi
|
||||
and esi,15
|
||||
cmp poolActive3D[esi*4],0
|
||||
je eight_cycle_next
|
||||
invoke EightLegal3D,esi
|
||||
test eax,eax
|
||||
jnz eight_cycle_found
|
||||
eight_cycle_next:
|
||||
dec edi
|
||||
jnz eight_cycle_scan
|
||||
ret
|
||||
eight_cycle_found:
|
||||
mov poolCalled3D,esi
|
||||
or poolCallManual3D,1
|
||||
pyr_handle_done:
|
||||
ret
|
||||
HandlePool3D ENDP
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
PyramidBall3D PROC uses ebx esi ball:DWORD,x:DWORD,y:DWORD,sizePx:DWORD
|
||||
mov ebx,ball
|
||||
cmp poolVariant3D,1
|
||||
jne pyr_ball_palette
|
||||
mov eax,sizePx
|
||||
shr eax,1
|
||||
mov edx,x
|
||||
sub edx,eax
|
||||
mov ecx,y
|
||||
sub ecx,eax
|
||||
invoke DrawAnimSprite3D,OFFSET poolEightPack3D,ebx,edx,ecx,sizePx,sizePx
|
||||
jmp pyr_ball_number
|
||||
pyr_ball_palette:
|
||||
mov eax,pyrRoll3D[ebx*4]
|
||||
shr eax,17
|
||||
and eax,3
|
||||
|
|
@ -15,6 +26,7 @@ PyramidBall3D PROC uses ebx esi ball:DWORD,x:DWORD,y:DWORD,sizePx:DWORD
|
|||
mov ecx,y
|
||||
sub ecx,eax
|
||||
invoke DrawAnimSprite3D,OFFSET pyrBallsPack3D,esi,edx,ecx,sizePx,sizePx
|
||||
pyr_ball_number:
|
||||
cmp sizePx,12
|
||||
jne pyr_ball_done
|
||||
test ebx,ebx
|
||||
|
|
@ -126,13 +138,40 @@ RenderPool3D PROC uses ebx esi edi
|
|||
lea edi,screenBuffer
|
||||
mov ecx,SCREEN_SIZE
|
||||
rep movsd
|
||||
cmp poolState3D,POOL_SELECT
|
||||
jne pyr_render_game
|
||||
invoke DrawBox,0,0,320,35,00151D20h
|
||||
invoke DrawString8x8,16,12,OFFSET poolSelectTitle3D,00E8D7ADh
|
||||
invoke DrawBoxBorder,252,3,60,14,002C3637h,00687672h,1
|
||||
invoke DrawString8x8,258,6,OFFSET cardExitButton3D,00E9D8B0h
|
||||
invoke DrawBoxBorder,40,80,240,48,00192720h,00D6B971h,2
|
||||
invoke DrawString8x8,68,99,OFFSET poolSelectPyramid3D,00FFFFFFh
|
||||
invoke DrawBoxBorder,40,144,240,48,00192720h,00D6B971h,2
|
||||
invoke DrawString8x8,58,163,OFFSET poolSelectEight3D,00FFFFFFh
|
||||
ret
|
||||
pyr_render_game:
|
||||
call EightAutoCall3D
|
||||
xor esi,esi
|
||||
pyr_render_mouths:
|
||||
mov eax,poolPocketX3D[esi*4]
|
||||
sar eax,16
|
||||
mov ebx,poolPocketY3D[esi*4]
|
||||
sar ebx,16
|
||||
mov px,eax
|
||||
mov py,ebx
|
||||
invoke DrawCircle,eax,ebx,3,000B1010h
|
||||
cmp poolVariant3D,1
|
||||
jne @F
|
||||
mov eax,poolPocketX3D[esi*4]
|
||||
sar eax,16
|
||||
mov ebx,poolPocketY3D[esi*4]
|
||||
sar ebx,16
|
||||
invoke DrawCircle,px,py,5,000B1010h
|
||||
cmp esi,poolCalledPocket3D
|
||||
jne @F
|
||||
invoke DrawCircle,px,py,6,00D6B971h
|
||||
invoke DrawCircle,px,py,4,000B1010h
|
||||
@@:
|
||||
inc esi
|
||||
cmp esi,6
|
||||
jb pyr_render_mouths
|
||||
|
|
@ -148,7 +187,7 @@ pyr_render_mouths:
|
|||
call PyramidDirection3D
|
||||
cmp pyrGuideOn3D,0
|
||||
je pyr_render_objects
|
||||
call PyramidGuide3D
|
||||
call PoolDrawPrediction3D
|
||||
pyr_render_objects:
|
||||
xor esi,esi
|
||||
pyr_render_ball:
|
||||
|
|
@ -160,6 +199,16 @@ pyr_render_ball:
|
|||
mov eax,poolY3D[esi*4]
|
||||
sar eax,15
|
||||
mov py,eax
|
||||
cmp poolVariant3D,1
|
||||
jne @F
|
||||
cmp esi,poolCalled3D
|
||||
jne @F
|
||||
mov eax,px
|
||||
sar eax,1
|
||||
mov ebx,py
|
||||
sar ebx,1
|
||||
invoke DrawCircle,eax,ebx,4,00D6B971h
|
||||
@@:
|
||||
cmp esi,pyrCue3D
|
||||
jne @F
|
||||
cmp poolState3D,POOL_AIM
|
||||
|
|
@ -245,10 +294,20 @@ pyr_cue_draw:
|
|||
jnz pyr_cue_draw
|
||||
pyr_render_hud:
|
||||
invoke DrawBox,0,0,320,20,00151D20h
|
||||
invoke DrawString8x8,8,6,OFFSET pyrTitle3D,00E8D7ADh
|
||||
mov ebx,OFFSET pyrTitle3D
|
||||
cmp poolVariant3D,0
|
||||
je @F
|
||||
mov ebx,OFFSET poolTitle3D
|
||||
@@:
|
||||
invoke DrawString8x8,8,6,ebx,00E8D7ADh
|
||||
invoke DrawNumber,112,6,pyrScore3D,00F4F3E8h
|
||||
invoke DrawString8x8,128,6,OFFSET pyrScoreSep3D,00E8D7ADh
|
||||
invoke DrawNumber,144,6,pyrScore3D[4],00F4F3E8h
|
||||
cmp poolVariant3D,1
|
||||
jne @F
|
||||
invoke DrawString8x8,88,6,OFFSET pyrPlayerName3D,00E8D7ADh
|
||||
invoke DrawString8x8,160,6,OFFSET pyrAIName3D,00E8D7ADh
|
||||
@@:
|
||||
mov ebx,OFFSET pyrPlayerName3D
|
||||
cmp poolPlayer3D,0
|
||||
je @F
|
||||
|
|
@ -277,9 +336,20 @@ pyr_render_hud:
|
|||
cmp poolState3D,POOL_STRIKE
|
||||
jne @F
|
||||
mov ebx,OFFSET poolShotText3D
|
||||
@@:
|
||||
cmp poolState3D,POOL_HAND
|
||||
jne @F
|
||||
mov ebx,OFFSET poolPlaceText3D
|
||||
@@:
|
||||
invoke DrawBox,0,22,320,15,00151D20h
|
||||
invoke DrawString8x8,8,26,ebx,00E8D7ADh
|
||||
cmp poolVariant3D,1
|
||||
jne @F
|
||||
mov ecx,poolPlayer3D
|
||||
mov ecx,poolGroups3D[ecx*4]
|
||||
mov eax,poolGroupTexts3D[ecx*4]
|
||||
invoke DrawString8x8,176,26,eax,00E8D7ADh
|
||||
@@:
|
||||
cmp poolState3D,POOL_PENALTY
|
||||
je @F
|
||||
cmp poolState3D,POOL_CHOICE
|
||||
|
|
@ -330,9 +400,36 @@ pyr_shelf_next:
|
|||
add eax,201
|
||||
invoke DrawBox,eax,199,2,9,00F4F0DDh
|
||||
invoke DrawBoxBorder,12,215,74,22,0039412Fh,00AC9862h,1
|
||||
cmp poolVariant3D,1
|
||||
je eight_render_call
|
||||
invoke DrawString8x8,18,222,OFFSET pyrCueText3D,00FFFFFFh
|
||||
invoke DrawNumber,62,222,pyrCue3D,00EAD19Bh
|
||||
invoke DrawBoxBorder,92,215,104,22,0039412Fh,00AC9862h,1
|
||||
jmp eight_render_call_done
|
||||
eight_render_call:
|
||||
invoke DrawString8x8,18,222,OFFSET poolCallText3D,00FFFFFFh
|
||||
cmp poolCalled3D,0
|
||||
je eight_render_no_call
|
||||
invoke DrawNumber,64,222,poolCalled3D,00EAD19Bh
|
||||
jmp eight_render_pocket
|
||||
eight_render_no_call:
|
||||
invoke DrawString8x8,64,222,OFFSET poolUnsetText3D,00EAD19Bh
|
||||
eight_render_pocket:
|
||||
mov eax,poolCalledPocket3D
|
||||
inc eax
|
||||
jz eight_render_no_pocket
|
||||
invoke DrawNumber,173,187,eax,00EAD19Bh
|
||||
jmp eight_render_pocket_label
|
||||
eight_render_no_pocket:
|
||||
invoke DrawString8x8,173,187,OFFSET poolUnsetText3D,00EAD19Bh
|
||||
eight_render_pocket_label:
|
||||
invoke DrawString8x8,129,187,OFFSET poolPocketText3D,00FFFFFFh
|
||||
eight_render_call_done:
|
||||
mov ebx,0039412Fh
|
||||
cmp pyrGuideOn3D,0
|
||||
jne @F
|
||||
mov ebx,00242A2Ch
|
||||
@@:
|
||||
invoke DrawBoxBorder,92,215,104,22,ebx,00AC9862h,1
|
||||
invoke DrawString8x8,106,222,OFFSET pyrGuideText3D,00FFFFFFh
|
||||
invoke DrawBoxBorder,202,215,106,22,00425232h,00BBA76Fh,1
|
||||
mov ebx,OFFSET poolShotText3D
|
||||
|
|
|
|||
|
|
@ -23,12 +23,14 @@ pyr_init_records:
|
|||
jb pyr_init_records
|
||||
invoke LoadAnimPack3D,OFFSET pyrTablePack3D,OFFSET pyrTablePath3D
|
||||
invoke LoadAnimPack3D,OFFSET pyrBallsPack3D,OFFSET pyrBallsPath3D
|
||||
invoke LoadAnimPack3D,OFFSET poolEightPack3D,OFFSET poolEightPath3D
|
||||
ret
|
||||
InitPyramidState3D ENDP
|
||||
|
||||
FreePyramidAssets3D PROC
|
||||
invoke FreeAnimPack3D,OFFSET pyrTablePack3D
|
||||
invoke FreeAnimPack3D,OFFSET pyrBallsPack3D
|
||||
invoke FreeAnimPack3D,OFFSET poolEightPack3D
|
||||
ret
|
||||
FreePyramidAssets3D ENDP
|
||||
|
||||
|
|
@ -275,6 +277,11 @@ PoolPlaceCue3D PROC px:DWORD,py:DWORD
|
|||
PoolPlaceCue3D ENDP
|
||||
|
||||
PoolBallLegal3D PROC ball:DWORD
|
||||
cmp poolVariant3D,1
|
||||
jne @F
|
||||
invoke EightLegal3D,ball
|
||||
ret
|
||||
@@:
|
||||
mov ecx,ball
|
||||
xor eax,eax
|
||||
cmp ecx,15
|
||||
|
|
@ -288,11 +295,21 @@ PoolBallLegal3D PROC ball:DWORD
|
|||
PoolBallLegal3D ENDP
|
||||
|
||||
PoolCountGroup3D PROC
|
||||
cmp poolVariant3D,1
|
||||
jne @F
|
||||
call EightCount3D
|
||||
ret
|
||||
@@:
|
||||
mov poolAtStart3D,0
|
||||
ret
|
||||
PoolCountGroup3D ENDP
|
||||
|
||||
PoolFinishShot3D PROC uses ebx esi edi
|
||||
cmp poolVariant3D,1
|
||||
jne @F
|
||||
call EightFinish3D
|
||||
ret
|
||||
@@:
|
||||
cmp pyrSettled3D,0
|
||||
jne pyr_finish_done
|
||||
mov pyrSettled3D,1
|
||||
|
|
@ -426,6 +443,25 @@ PyramidChoice3D PROC uses ebx esi edi choice:DWORD
|
|||
jne pyr_choice_done
|
||||
cmp choice,3
|
||||
ja pyr_choice_done
|
||||
cmp poolVariant3D,1
|
||||
jne pyr_choice_pyramid
|
||||
mov ebx,pyrChoiceActor3D
|
||||
test choice,1
|
||||
jz @F
|
||||
xor ebx,1
|
||||
@@:
|
||||
cmp choice,2
|
||||
jb eight_choice_accept
|
||||
call ResetPool3D
|
||||
mov poolPlayer3D,ebx
|
||||
ret
|
||||
eight_choice_accept:
|
||||
mov poolPlayer3D,ebx
|
||||
mov poolBreak3D,0
|
||||
mov poolState3D,POOL_AIM
|
||||
mov poolTime3D,0
|
||||
ret
|
||||
pyr_choice_pyramid:
|
||||
cmp choice,2
|
||||
jb pyr_choice_actor
|
||||
cmp pyrIllegalBreak3D,0
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ LoadAnimPack3D PROC uses ebx esi edi pack:DWORD,path:DWORD
|
|||
mov ecx, [esi].AnimPack3D.height
|
||||
test ecx, ecx
|
||||
jz anim_close_failure
|
||||
cmp ecx, 480
|
||||
cmp ecx, 1024
|
||||
ja anim_close_failure
|
||||
imul eax, ecx
|
||||
shl eax, 2
|
||||
|
|
@ -293,6 +293,8 @@ props_copy_store:
|
|||
InstallHallProps3D ENDP
|
||||
|
||||
FreeArrivalAssets3D PROC
|
||||
call FreeScratchArt3D
|
||||
call FreeNativeDiceArt3D
|
||||
call FreeHallAssets3D
|
||||
invoke FreeAnimPack3D, OFFSET streetPack3D
|
||||
invoke FreeAnimPack3D, OFFSET guardPack3D
|
||||
|
|
@ -309,6 +311,11 @@ FreeArrivalAssets3D PROC
|
|||
invoke FreeAnimPack3D, OFFSET cityCarsPack3D
|
||||
invoke FreeAnimPack3D, OFFSET cityBinPack3D
|
||||
invoke FreeAnimPack3D, OFFSET cityCloudPack3D
|
||||
invoke FreeAnimPack3D, OFFSET cityWakePack3D
|
||||
invoke FreeAnimPack3D, OFFSET citySleevePack3D
|
||||
invoke FreeAnimPack3D, OFFSET cityDecorPack3D
|
||||
invoke FreeAnimPack3D, OFFSET cityLighterPack3D
|
||||
invoke FreeAnimPack3D, OFFSET cityKneesPack3D
|
||||
ret
|
||||
FreeArrivalAssets3D ENDP
|
||||
|
||||
|
|
|
|||