246 lines of MSX-BASIC. The listing is at 100 % coverage: all 246 carry their own comment above them, and that comes to 702 lines of explanation for 718 statements of program.
| lines | what they do |
|---|---|
| 1-3 | STOP, the title screen and the DEFINT D |
| 10-90 | arrays, the thirteen clubs, hole 1's course and the wait |
| 110-130 | builds the hole's view and starts |
| 200-295 | the turn: stance, club, and the shot formula |
| 300-470 | the flight simulation |
| 500-630 | where the ball came to rest, and the camera for the next shot |
| 700-720 | hole finished, and the end of the round |
| 900-1260 | the ball in the view, and the three selection screens |
| 2000-2510 | reading the course out of the ROM |
| 3000-3070 | finding somewhere to drop the ball |
| 4000-4080 | the plan view |
| 5000-5690 | the 3D view engine |
| 6100-6900 | the five sounds and the silence |
| 7000-9900 | scaling, scoreboard, text, panel and compass |
| 10200-30000 | the nine holes' DATA and the STOP handler |
A classic conic perspective, written out by hand three times because there is no shared routine: in 370-372 for the ball, in 900-940 to mark where it came to rest, and in 5000-5690 for the terrain.
Subroutine 5000 makes four passes over the hole's data:
DN().Q1-Q9 matrix. Of its nine terms, six are constants: the camera turns on one axis only. It never tilts or rolls.The clipping (5190-5590) is the classic one against a 45-degree view frustum: a point is outside on the left if its x is less than minus its depth, and so on for all four walls. If both ends are outside the same wall, the whole segment is out. If not, the outside end is replaced by the exact intersection and the whole thing starts over, because the moved point may now fall outside another wall. With four walls, the loop cannot run more than four times.
The projection is two divisions by the depth, scaled to half the window's width and height (71 and 63) and centred on (79,63).
Subroutine 2500 reads one 16-bit value from the ROM. Since MSX-BASIC has no 16-bit PEEK, it builds one:
F1=PEEK(ZM) : F2=PEEK(ZM+1)
F1$=HEX$(F1) : F2$=HEX$(F2) : IF LEN(F2$)=1 THEN F2$="0"+F2$
DI(I)=VAL("&H"+F1$+F2$)
Two PEEKs, two conversions to hexadecimal text, a concatenation and a VAL. The second piece is padded with a zero when needed; the first is not, because it sits in the high position where a zero does no harm. And since VAL of a four-digit hexadecimal returns a signed integer, negative coordinates come out on their own.
It is desperately slow, and it shows: drawing hole 1 in full takes the interpreter more than five minutes of machine time.
There is no text console. Everything is written by opening the screen as if it were a file:
PSET(AX*8,AY*8),0 : OPEN"GRP:"FOR OUTPUT AS #1 : PRINT#1,E$ : CLOSE#1
The PSET is there to move the graphics cursor to the cell; the text comes out in COLOR's foreground, which is white. This was checked in the emulator's VRAM: the panel's cells read 0xF0, ink 15.
And the golfer is not a sprite or a drawing: it is eight strings, J$(0) to J$(7), written with that same trick using the graphic character set in the machine's own ROM. That is why a Japanese MSX is needed to see them properly.
There are only two, and they are the other way round from what you would guess: sprite 0, with the solid pattern, is the power meter's bar; sprite 1, with a two-pixel pattern, is the ball, and it moves across the plan view, not the 3D view. In the 3D view the ball is the shadow drawn by lines 390-393 - a filled circle whose radius shrinks with distance - and the dot left by subroutine 900.