Test 3a: the wave turns
In test 2a, the wave had depth. Here, the wave goes straight from the back to the front, through the center of the 3D space. Then it turns around that center, like a record on a turntable, and the dot moves along it. At a quarter turn, the wave goes from left to right, as intest 1.

A What the machine does
The routines spin_point and project, for the dot on the screen now.
Waiting for the copy of the PC to start…
Magenta: the ring, the circle that the two ends of the wave follow. Gray: the wave. Cyan: its footprint on the floor. The wave turns one step for each two steps of the dot. A full turn has 256 steps.

B The maths behind it
The turn, seen from above, and the same point with decimal-point numbers.
What is new in test 3a
- A A second angle, the turn. Each point of the wave has its place on the wave, d = 128 − angle. Before the turn, the point is at X = 0 and Z = d: the wave goes from the back to the front. After a turn T, the point is at X = d · sin(T) and Z = d · cos(T). The routine is
spin_pointinsrc/spin3d.inc. - B The same table again. The cosine of the turn is the sine a quarter turn later. A full turn has 256 steps, so a quarter turn is 64 steps. Thus the A side reads the cosine from
sine.binat T + 64. Test 3b shows what happens with a wrong quarter turn. - A A product that is too large for AX. d · sin(T) can be 128 · 256 = 32768. That number does not fit in AX with a sign.
IMULputs the full product in DX:AX, and the program keeps the middle two bytes: a division by 256. - A Double buffering. In tests 1 and 2, the program drew the curve once. Here, the wave turns, so the whole picture changes at each step. If the program draws on the screen, you see the wave go away and come back. Thus the program keeps two pictures of 64000 bytes in the memory after the program: the background (the floor and the ring, drawn once) and the work buffer. For each step, it copies the background into the work buffer, draws the wave and the dot there, and copies the finished picture to the screen. The 8086 word
REP MOVSWcopies 32000 words with one instruction. The shared routines for the keys, the pixels and the screen refresh are now insrc/common.inc. - A B The check. The test (
test/check3r.asm) runs the routines for 16 turns (0, 16, 32 … 240) and all 256 angles: 4096 points. The checker (lab/check_spin.f90) calculates them again and compares them.
The words that each program uses
The pills show the words that the dictionary already has. "New words" are real words of the language that the dictionary does not have yet.
A src/spin3d.asm· 253 lines · The game (test 3a): draws the floor and the ring, and turns the wave with the dot on it
44 dictionary words: MOVPUSHPOPAXBXCXDXSIDIBPDSESCS[ ]BYTEDBDWADDINCANDXORCMPTESTJMPJE / JZJNE / JNZJB / JACALLRETlabel:REPMOVSWSTOSWCLDORGBITS%includeINCBIN;,hINTINT 10h, AX=0013hA000h
New words (10): AHALBHBLCHCLCPUDLJGEJLE
A src/spin3d.inc· 60 lines · The shared routine: one angle along the wave and one turn in, one 3D point out
20 dictionary words: MOVPUSHPOPAXBXCXSIBP[ ]EQUADDSUBIMULSHLANDRETlabel:;,h
New words (3): AHALDL
A src/common.inc· 75 lines · The shared routines of tests 2 and 3: the keys, the pixels and the screen refresh
33 dictionary words: MOVPUSHPOPAXBXDXDI[ ]BYTEDBXLATADDSUBMULORXORCMPTESTJMPJE / JZJNE / JNZJB / JARETlabel:;,hINTINT 16h, AH=00hINT 16h, AH=01hINT 10h, AX=0003hIN3DAh
New words (1): AL
A test/check3r.asm· 68 lines · The test: runs the routines for 16 turns and 256 angles, and writes the positions to a file
28 dictionary words: MOVPUSHPOPAXBXCXDXSIDIBP[ ]DBEQUADDINCXORCMPJB / JACALLlabel:ORGBITS%includeINCBIN;,hINT
New words (3): AHCPUJC
B lab/check_spin.f90· 86 lines · The checker: compares the A-side positions with its own answers
43 dictionary words: INTEGERREALCHARACTER::=PARAMETERINT8 / INT16REAL64+ -* /( )ABSSIN / COSNINTFLOORINT( )MODULOISHFT / SHIFTAIF ... THEN ... END IFDOSTOPERROR STOPMERGE== /= < > <= >=SUMMAXVAL / MINVALCOUNTANY / ALLPROGRAMENDUSEIMPLICIT NONECALL!&PRINTWRITEREADOPENCLOSEGET_COMMAND_ARGUMENT'(F8.2)'ISO_FORTRAN_ENV
New words (7): ACOSCOMMAND_ARGUMENT_COUNTDIMINTRINSICLENONLYTRIM
Next: test 3b runs this program with one wrong value, and shows how it breaks the game and how the check finds it.