Cite as
n64decomp/pw64
Original
https://github.com/n64decomp/pw64
Pinned
n64decomp/pw64 @ cb66cb2a3b093412285d381829c8ab7787660298
Accessed
2026-10-22
Licence
MIT (LICENSE, copyright 2026 Garrett Smith), for the decompilers' own work; the game is Nintendo's
Credit
Garrett Smith and contributors' work-in-progress matching C decompilation of Pilotwings 64 (README title Pilotwings64Decomp, also at github.com/gcsmith/Pilotwings64Decomp), which builds the North American ROM. Names and comments quoted in pw64 claims are theirs.
Notes
The README names one supported release, North America (U), with the ROM's SHA-1 ec771aedf54ee1b214c25404fb4ec51cfd43191a, and says the repo holds no game assets or assembly; the build extracts assets from a copy of the game. Task data (start pads, thermals, point curves) is read from the ROM at run time, so its values aren't in the repo. At the pinned commit src/ has no INCLUDE_ASM or GLOBAL_ASM: every vehicle file is C, but most functions and struct fields still carry address names (`func_80307EA8`, `unkB4`). The gyrocopter is in src/app/gyrocopter.c and code_7CF30.c, the hang glider in hang_glider0-2.c, thermals in thermals.c, the summed air at a point in environment.c, and scoring in code_B2900.c. Some files carry `VERSION_JP` conditionals; claims read the US side.

Cited on

Claims (5)

In the US version of Pilotwings 64, the gyrocopter's update routine func_8030399C clears a vector (unk31C) and has five routines add terms to it: func_80307A9C, func_80307E2C, func_80308478, func_80307BAC, and func_80307EA8. A routine chosen by state can add to it after them (func_80304B98, for states 1 and 4, does), and func_80309090 copies the result to unk1AC. In state 1 (unkC0), the routine adds unk1AC times the frame time to the craft's velocity (unk190), with no mass dividing it; in state 0 it first combines unk1AC with cross terms of the velocity and the turn rates (unk1B8). func_80307E2C adds (0, 0, −9.8), z being the world's vertical, turned into the craft's frame through the inverse of its matrix (by the atlas's reading, gravity). func_80307A9C adds, on each of the craft's axes, a curve of the square of unk364's component on that axis, signed like the component: 0 at 0, 4.2 at 2661.2188, and 7.56 at 6944.389 and above, linear between (by the atlas's reading, air resistance). Those squares are speeds of about 51.59 and 83.33 (computed). func_80308478 sets unk364 to the vector env_802E1754 returns for the craft's position, in the craft's frame, less the craft's velocity, and adds 0.21 of that vector as a term of its own; by the atlas's reading the vector is the air's velocity and unk364 the airspeed. Below a speed (unk1A8) of 51.587303 the vector is scaled by the square of the speed over 51.587303, and outside state 0 it's taken as zero. The other two routines are in pw64/gyrocopter-lift.src/app/gyrocopter.c L251–279src/app/gyrocopter.c L349–365src/app/gyrocopter.c L280–310src/app/gyrocopter.c L1818–1837src/app/gyrocopter.c L566–623src/app/gyrocopter.c L1442–1452src/app/gyrocopter.c L122–125src/app/gyrocopter.c L1360–1380src/app/code_9A960.c L257–280src/app/gyrocopter.c L1563–1605src/app/gyrocopter.c L410src/app/code_7CF30.c L471Code
In the US version of Pilotwings 64, two of the terms the gyrocopter's func_8030399C sums give it lift, by the atlas's reading. The one the atlas calls the rotor term (func_80307BAC) is 0.3 times the square of the airspeed's component on the z axis of the matrix unk25C, signed like that component and capped at 200 when positive, times the square of the airspeed's y component over 25, held between 0.05 and 1; it's added along the z axis of the matrix unk21C. The one it calls the engine term (func_80307EA8), while usingFuel is set, is 35 × power (unkB4) × a factor of height (spD8, the atlas's altitude factor), split 0.24 onto y and 0.76 onto z, the z part also times a curve of the negated y airspeed: 0 at 0, 0.15 at 10, 0.4 at 20, 1.2 at 50, and 1.5 at 100 and above. It too goes through unk21C, and its y component is cut to 0.9 when unk1F0 is nonzero, unk190.y is positive, and unk7C is 0. That factor is 1 up to a height of 700 and falls by 0.01 per unit above it, held at 0 from 800 up; that hold is under #if !defined(VERSION_JP), so a Japanese build lets the factor go negative. Neither term applies while unkC1 is set or in state 2 (unkC0).src/app/gyrocopter.c L1382–1440src/app/gyrocopter.c L1454–1463src/app/gyrocopter.c L1490–1516src/app/gyrocopter.c L74–79src/app/code_7CF30.c L470–474Code
In the US version of Pilotwings 64, the gyrocopter's fuel is a number from 0 to 1, starting at the value the task's first start pad holds, or 0 if the task has no start pad (db_getstart). While usingFuel is set, func_80307EA8 takes off each update the frame time times a rate read from a curve of the power (unkB4, the throttle that A raises and B lowers, which the HUD shows as power; in the throttle's case 0 A sets usingFuel, and in cases 1 and 2 A sets it only with fuel above 0): 0.001 at 0, 0.002 at 0.5, and 0.005 at full, linear between. The frame time (D_8034F854) is the time since the last frame held between 0.01 and 0.1, so the rate is per second, and a full tank lasts 200 s at full power and 1,000 s at none (computed). At 0 it clears usingFuel. In a Class B task, each update that func_802E08F4 returns nonzero for the craft's position sets the fuel to 1, and SFX_UI_FUEL_ADDED plays on the first. func_80307EA8 does none of this, refill or drain, while unkC1 is set or in state 2 (unkC0). Separately, the HUD update in code_7CF30.c warns below 0.15 (TEXT_FUEL_WAR) and at 0 (TEXT_FUEL_OUT).src/app/gyrocopter.c L84–88src/app/gyrocopter.c L1454–1488src/app/code_9A960.c L257–280src/app/code_9A960.c L9src/app/code_9A960.c L210–220src/app/code_7CF30.c L95src/app/code_66F70.c L260–294src/app/code_7CF30.c L248–309src/app/code_7CF30.c L473–474src/app/code_7CF30.c L494–499Code
In the US version of Pilotwings 64, a thermal is a vertical cylinder from the task's data (TaskTHER): a base position, a radius (scale), and a height. therm_80346C08 sums a vector from each thermal whose cylinder holds the point (by the atlas's reading, its air velocity): its horizontal distance d from the axis at most the radius r, and its height z above the base between 0 and the thermal's height. In therm_80346E04 the vector's vertical part (the atlas's updraft) is the thermal's unk24 × √((r − d)/r), full on the axis and 0 at the edge. Beyond 1 unit from the axis its horizontal part is at right angles to the axis direction, of length unk20 × (1 − 2|r/2 − d|/r) × d, longest halfway out (the atlas's swirl). Both fade in from 0 at the base to full at height unk18, and from unk1C fade out to 0 at the top. env_802E1754 adds the sum to the vector wind_8034D550 gives for the point (by the atlas's reading, the wind), along with, unless the task's unk8 is set, a further wind and a push from beyond 2050 units outside the map's bounds. The hang glider (hangGlider_802F391C) multiplies the total by its pilot's unk2F8: 1.2 for Lark and Kiwi, 1.0 for Goose and Ibis, and 0.8 for Hawk and Robin.src/app/task.h L274–283src/app/thermals.c L156–199src/app/thermals.c L201–235src/app/environment.c L338–382src/app/hang_glider2.c L574–591src/app/hang_glider1.c L519–569src/app/hang_glider1.c L572–618src/app/hang_glider1.c L623–669src/app/hang_glider1.c L674–722src/app/hang_glider1.c L725–771src/app/hang_glider1.c L776–822Code
In the US version of Pilotwings 64, the thermals switch off in one test: the hang glider's test with index 0 in the Pilot class (cls 3, CLASS_PILOT). There, from 240 on the clock D_8034F850 (by the decompilers' comment, the current time; the test's setup, gameUpdateStateTestSetup, sets it to 0, and each time func_80313D74 runs it adds the time since the last frame held between 0.01 and 0.1, so it counts seconds of game time), therm_8034695C narrows the drawn cylinders to nothing over the next 10, and at 250 (THERM_DISABLE_TIME) removes the thermals and shows TEXT_THERM_OFF. The narrowing scales only the model's matrix: the updraft reads the task's radius until the thermals are gone.src/app/thermals.c L14–18src/app/thermals.c L98–101src/app/task.h L53–56src/app/thermals.c L114–140src/app/thermals.c L182–184src/app/code_9A960.c L8src/app/code_9A960.c L210–221src/app/game.c L431–545src/app/code_9A960.c L225–227Code