Skip to content

Commit 7aa5384

Browse files
authored
docs(GeneratedCode): describe observed behavior for low-level functions
1 parent fa8ca31 commit 7aa5384

1 file changed

Lines changed: 135 additions & 12 deletions

File tree

GeneratedCode.cs

Lines changed: 135 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@ public void DefineGeneratedCodeOverrides()
2929
}
3030

3131
/// <summary>
32-
/// First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation)
32+
/// Program entry point. Builds the "LOGO.HNM" filename, opens the file via DOS Int21 OpenFile,
33+
/// switches the VGA to mode 13h, runs the circles intro animation, then quits to DOS. The trailing
34+
/// PrintString / second QuitWithExitCode after the main quit are unreachable in normal execution.
3335
/// </summary>
36+
/// <remarks>First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation).</remarks>
3437
public virtual Action EntryPoint_OpenLogoHnmFileAndRun_1000_0000_10000(int offset)
3538
{
3639
DS = 0x111C;
@@ -84,6 +87,10 @@ public void SetVideoMode_1000_0970_10970()
8487

8588
}
8689

90+
/// <summary>
91+
/// Sleeps ~one VGA frame (~16.67 ms) then writes <c>CX * 3</c> palette bytes (RGB triples)
92+
/// starting at <c>DS:DX</c> into the VGA DAC, using <c>BL</c> as the starting DAC index.
93+
/// </summary>
8794
public void CommonCirclesWaitFrameAndWriteNextPaletteData_1000_09D8_109D8()
8895
{
8996
int colors = CX;
@@ -99,17 +106,23 @@ public void CommonCirclesWaitFrameAndWriteNextPaletteData_1000_09D8_109D8()
99106
}
100107

101108
/// <summary>
102-
/// First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation)
109+
/// Computes a linear VGA mode 13h screen offset for a given row/column: <c>DI = BX * 320 + DX</c>.
103110
/// </summary>
111+
/// <remarks>First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation).</remarks>
104112
public void ConvertLineNumberToArrayIndex_1000_0A22_10A22()
105113
{
106114
DI = (ushort)(BX * 320 + DX);
107115

108116
}
109117

110118
/// <summary>
111-
/// First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation)
119+
/// Blits a rectangle of <c>BX</c> rows by <c>BP</c> columns from <c>DS:SI</c> to <c>ES:DI</c>
120+
/// with a 320-byte row stride (VGA mode 13h). The exact code path depends on the value of
121+
/// <c>CH</c> (0xFE vs 0xFF) and the sign of <c>DI</c>: it performs either a plain word/byte copy,
122+
/// or a sparse copy where a zero byte from the source skips one destination byte and a non-zero
123+
/// byte is written. Used to draw the animated circles into the VGA framebuffer.
112124
/// </summary>
125+
/// <remarks>First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation).</remarks>
113126
public void CommonUnknown_1000_0B9A_10B9A()
114127
{
115128
Alu8.Sub(CH, 0xFE);
@@ -250,8 +263,12 @@ public void CommonUnknown_1000_0B9A_10B9A()
250263
}
251264

252265
/// <summary>
253-
/// First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation)
266+
/// Performs a vertical mirror/flip blit of the VGA mode 13h framebuffer (segment 0xA000):
267+
/// the first pass copies the top 100 lines into rows 1..100 with per-word byte-swap,
268+
/// the second pass copies them into the area starting at offset 0xF8C0. Effectively
269+
/// produces the symmetric reflection used by the circles animation backdrop.
254270
/// </summary>
271+
/// <remarks>First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation).</remarks>
255272
public void CirclesUnknown_display_1000_0C72_10C72()
256273
{
257274
Stack.Push16(DS);
@@ -302,8 +319,13 @@ public void CirclesUnknown_display_1000_0C72_10C72()
302319
}
303320

304321
/// <summary>
305-
/// First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation)
322+
/// Main loop driving the circles animation. Performs the initial framebuffer flip blit, then
323+
/// initializes the per-frame counters at <c>EntrySegment:0xCB6/0xCBA/0xCB0/0xCB2/0xCB4</c>
324+
/// (frames-remaining, palette-stream pointer, R/G/B accumulators) and iterates
325+
/// <see cref="CirclesDrawStep_1000_0D22_10D22"/> 0xFB (251) times, polling the keyboard
326+
/// between frames to allow an early exit.
306327
/// </summary>
328+
/// <remarks>First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation).</remarks>
307329
public void CircleMainLoop_1000_0CF4_10CF4()
308330
{
309331
CirclesUnknown_display_1000_0C72_10C72();
@@ -330,8 +352,12 @@ public void CircleMainLoop_1000_0CF4_10CF4()
330352
}
331353

332354
/// <summary>
333-
/// First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation)
355+
/// One step of the circles animation. While the frames-remaining counter is non-negative,
356+
/// copies the next ring of palette source bytes into the working buffer at offset 0x160,
357+
/// computes the next interpolated RGB triple via <see cref="CommonComputeNextVgaPalette_1000_0D5F_10D5F"/>,
358+
/// then waits one frame and pushes 0x50 (80) palette entries to the VGA DAC.
334359
/// </summary>
360+
/// <remarks>First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation).</remarks>
335361
public void CirclesDrawStep_1000_0D22_10D22()
336362
{
337363
Stack.Push16(DS);
@@ -372,8 +398,14 @@ public void CirclesDrawStep_1000_0D22_10D22()
372398
}
373399

374400
/// <summary>
375-
/// First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation)
401+
/// Computes the next RGB triple for the rolling circles palette. For each of the R, G and B
402+
/// channels the per-channel accumulator stored at <c>EntrySegment:0xCB0/0xCB2/0xCB4</c> is
403+
/// advanced by a delta read from the current palette-stream entry, and the high byte
404+
/// (shifted left by 1) masked with 0x3F is written to the destination at <c>ES:DI</c>.
405+
/// When the frames-remaining counter at <c>0xCB6</c> reaches zero the palette-stream
406+
/// pointer at <c>0xCBA</c> is advanced by 8 bytes to the next segment.
376407
/// </summary>
408+
/// <remarks>First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation).</remarks>
377409
public void CommonComputeNextVgaPalette_1000_0D5F_10D5F()
378410
{
379411
SI = UInt16[EntrySegmentAddress, 0xCBA];
@@ -415,6 +447,13 @@ public void CommonComputeNextVgaPalette_1000_0D5F_10D5F()
415447

416448
}
417449

450+
/// <summary>
451+
/// Refills the palette/HNM data buffer pointed to by <c>DS:[0x4C]:[0x4E]</c>: records the
452+
/// current address, compares the remaining capacity against 0x3A02, calls
453+
/// <see cref="HNMReadFile_AdvancePointer_CloseFile_1000_109A_1109A"/> to read the next chunk
454+
/// from the HNM file, then advances <c>DI</c> by the bytes-read count and zero-terminates
455+
/// the buffer.
456+
/// </summary>
418457
public void CirclesUnknown_1000_0DBC_10DBC()
419458
{
420459
// LES DI,[0x4c] (1000_0DBC / 0x10DBC)
@@ -445,8 +484,13 @@ public void CirclesUnknown_1000_0DBC_10DBC()
445484
}
446485

447486
/// <summary>
448-
/// First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation)
487+
/// Top-level orchestrator for the circles animation phase. Stores the file handle, primes
488+
/// the HNM data buffer via <see cref="CirclesUnknown_1000_0DBC_10DBC"/>, loads the initial
489+
/// VGA palette, then runs <see cref="CircleMainLoop_1000_0CF4_10CF4"/> followed by the HNM
490+
/// per-frame loop calling <see cref="HNMUnknown_1000_0FEA_10FEA"/> until the remaining-frames
491+
/// counter at <c>DS:0x52</c> hits zero, and finally verifies the "LO" signature at offset 0xEE.
449492
/// </summary>
493+
/// <remarks>First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation).</remarks>
450494
public void CirclesAnimation_1000_0DDE_10DDE()
451495
{
452496
// Read File
@@ -486,6 +530,11 @@ public void CirclesAnimation_1000_0DDE_10DDE()
486530

487531
}
488532

533+
/// <summary>
534+
/// ASM fall-through wrapper: invokes <see cref="CirclesDrawStep_1000_0D22_10D22"/> and then
535+
/// continues straight into <see cref="CommonUnknown_1000_0E49_10E49"/> without an intervening
536+
/// return.
537+
/// </summary>
489538
public void HNMUnknown_1000_0E46_10E46()
490539
{
491540
// CALL 0x1000:0d22 (1000_0E46 / 0x10E46)
@@ -494,6 +543,10 @@ public void HNMUnknown_1000_0E46_10E46()
494543
CommonUnknown_1000_0E49_10E49();
495544
}
496545

546+
/// <summary>
547+
/// ASM fall-through wrapper: invokes <see cref="CommonUnknown_display_1000_0E59_10E59"/> and
548+
/// then continues straight into <see cref="CommonUnknown_1000_0E4C_10E4C"/>.
549+
/// </summary>
497550
public void CommonUnknown_1000_0E49_10E49()
498551
{
499552
// CALL 0x1000:0e59 (1000_0E49 / 0x10E49)
@@ -503,8 +556,12 @@ public void CommonUnknown_1000_0E49_10E49()
503556
}
504557

505558
/// <summary>
506-
/// First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation)
559+
/// Advances the HNM/palette stream pointer via
560+
/// <see cref="UpdatePaletteDataAddress_1000_0E86_10E86"/>. When the new chunk reports a size
561+
/// of zero (ZeroFlag set on return), zeroes the remaining-frames counter at <c>DS:0x52</c>,
562+
/// which terminates the outer animation loop and allows the program to exit.
507563
/// </summary>
564+
/// <remarks>First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation).</remarks>
508565
public void CommonUnknown_1000_0E4C_10E4C()
509566
{
510567
UpdatePaletteDataAddress_1000_0E86_10E86();
@@ -519,6 +576,12 @@ public void CommonUnknown_1000_0E4C_10E4C()
519576
}
520577

521578
/// <summary>
579+
/// Reads the next HNM frame header from the current palette/HNM stream (flags into <c>DI</c>,
580+
/// length into <c>CX</c>, two command words into <c>DX</c> and <c>BX</c>). If the 0x200 flag
581+
/// bit is set the auxiliary buffer decoder <see cref="CommonUnknown_1000_0EBD_10EBD"/> is
582+
/// invoked first; then the main HNM bitstream decoder
583+
/// <see cref="CommonUnknown_1000_0B9A_10B9A"/> is called to draw the decoded pixels into
584+
/// the VGA framebuffer at <c>ES = 0xA000</c>.
522585
/// TODO: High level rewrite this first.
523586
/// </summary>
524587
public void CommonUnknown_display_1000_0E59_10E59()
@@ -555,6 +618,12 @@ public void CommonUnknown_display_1000_0E59_10E59()
555618

556619
}
557620

621+
/// <summary>
622+
/// Advances <see cref="PaletteDataAddress"/> by the chunk-size word stored at its current
623+
/// location, normalizing the result back to a seg:offset pair, and updates the cached
624+
/// chunk size via <see cref="CommonUnknown_1000_0EB2_10EB2"/> (sets <c>CX = size - 2</c>
625+
/// and <c>ZeroFlag</c>).
626+
/// </summary>
558627
public void UpdatePaletteDataAddress_1000_0E86_10E86()
559628
{
560629
SegmentedAddress pointer = PaletteDataAddress;
@@ -565,11 +634,20 @@ public void UpdatePaletteDataAddress_1000_0E86_10E86()
565634
CommonUnknown_1000_0EB2_10EB2(newSegment, newOffset);
566635
}
567636

637+
/// <summary>
638+
/// Reads the chunk size at the current <see cref="PaletteDataAddress"/> via
639+
/// <see cref="CommonUnknown_1000_0EB2_10EB2"/>, leaving <c>CX = size - 2</c> and the
640+
/// <c>ZeroFlag</c> set when the original chunk size is zero.
641+
/// </summary>
568642
public void CommonUnknown_1000_0EAD_10EAD()
569643
{
570644
CommonUnknown_1000_0EB2_10EB2(PaletteDataAddress.Segment, PaletteDataAddress.Offset);
571645
}
572646

647+
/// <summary>
648+
/// Reads the 16-bit chunk-size word at <c>segment:offset</c>, then sets <c>CX = value - 2</c>
649+
/// and the <c>ZeroFlag</c> to reflect whether the original word was zero (end-of-stream).
650+
/// </summary>
573651
public Action CommonUnknown_1000_0EB2_10EB2(ushort segment, ushort offset)
574652
{
575653
ushort value = UInt16[segment, offset];
@@ -578,6 +656,12 @@ public Action CommonUnknown_1000_0EB2_10EB2(ushort segment, ushort offset)
578656
return NearRet();
579657
}
580658

659+
/// <summary>
660+
/// Decodes an HNM stream into an auxiliary buffer at <c>0x1131:0000</c>. Saves caller's
661+
/// <c>CX</c> and <c>DI</c>, redirects the destination to the auxiliary segment, invokes the
662+
/// inner decoder <see cref="CommonUnknown_1000_0EFE_10EFE"/>, then restores the registers.
663+
/// Called when the HNM frame header indicates flag bit 0x200.
664+
/// </summary>
581665
public void CommonUnknown_1000_0EBD_10EBD()
582666
{
583667
// AND DI,0xfdff (1000_0EBD / 0x10EBD)
@@ -611,6 +695,11 @@ public void CommonUnknown_1000_0EBD_10EBD()
611695

612696
}
613697

698+
/// <summary>
699+
/// Decoder prologue: saves caller <c>CX</c>, <c>DI</c> and <c>DS</c>, skips the 6-byte HNM
700+
/// frame header by adding 6 to <c>SI</c>, zeros the bit-buffer <c>BP</c>, then enters the
701+
/// main HNM bitstream decoder loop <see cref="CommonUnknownSplit_1000_0F30_10F30"/>.
702+
/// </summary>
614703
public void CommonUnknown_1000_0EFE_10EFE()
615704
{
616705
Stack.Push16(CX);
@@ -622,8 +711,14 @@ public void CommonUnknown_1000_0EFE_10EFE()
622711
}
623712

624713
/// <summary>
625-
/// First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation)
714+
/// Core HNM bitstream decoder. Consumes a 16-bit prefix-code stream from <c>DS:SI</c>
715+
/// (re-filling the bit buffer <c>BP</c> from the stream when it empties) and writes the
716+
/// decoded byte run into <c>ES:DI</c>. Supports three encodings: literal bytes, short
717+
/// 2-bit length back-references with a one-byte near offset, and long back-references with
718+
/// a 13-bit far offset followed by an optional one-byte length. Terminates when the special
719+
/// end-of-stream code is reached, returning the number of bytes written in <c>CX</c>.
626720
/// </summary>
721+
/// <remarks>First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation).</remarks>
627722
public void CommonUnknownSplit_1000_0F30_10F30()
628723
{
629724
while (true)
@@ -759,13 +854,22 @@ void label_12()
759854

760855
}
761856

857+
/// <summary>
858+
/// Stores the current palette/HNM data segment and offset into <c>DS:[0x58]:[0x56]</c>,
859+
/// the two-word slot read back by <see cref="PaletteDataAddress"/>.
860+
/// </summary>
762861
public void WritePaletteDataAddress(ushort segment, ushort offset)
763862
{
764863
UInt16[DS, 0x58] = segment;
765864
UInt16[DS, 0x56] = offset;
766865
}
767866
private SegmentedAddress PaletteDataAddress => new(UInt16[DS, 0x58], UInt16[DS, 0x56]);
768867
private SegmentedAddress PaletteDataAddressPlusTwo => new(PaletteDataAddress.Segment, (ushort)(PaletteDataAddress.Offset + 2));
868+
/// <summary>
869+
/// Walks the linked list of <see cref="PaletteData"/> records that begins at
870+
/// <see cref="PaletteDataAddressPlusTwo"/> and loads each entry into the VGA DAC. Used to
871+
/// initialize the VGA palette before the HNM playback loop starts.
872+
/// </summary>
769873
public void CirclesChangeVgaPaletteLoop_1000_0FA4_10FA4()
770874
{
771875
PaletteData? current = new(Memory, PaletteDataAddressPlusTwo);
@@ -777,8 +881,13 @@ public void CirclesChangeVgaPaletteLoop_1000_0FA4_10FA4()
777881
}
778882

779883
/// <summary>
780-
/// First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation)
884+
/// Renders one HNM frame via <see cref="HNMUnknown_1000_0E46_10E46"/> and then sleeps until
885+
/// the BIOS Data Area tick counter at <c>0000:046C</c> has advanced by ~5/8 of the per-frame
886+
/// tick budget, polling <see cref="CSharpOverrideHelper.CheckExternalEvents"/> in the wait
887+
/// loop. After waking, polls the keyboard via
888+
/// <see cref="CommonCheckForAnyKeyStroke_1000_1085_11085"/> for an early-exit request.
781889
/// </summary>
890+
/// <remarks>First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation).</remarks>
782891
public void HNMUnknown_1000_0FEA_10FEA()
783892
{
784893
InterruptFlag = true;
@@ -812,6 +921,11 @@ public void HNMUnknown_1000_0FEA_10FEA()
812921

813922
}
814923

924+
/// <summary>
925+
/// String-scan helper. Reads bytes from <c>DS:DX</c> and walks <c>DI</c> forward; mirrors
926+
/// the layout of <see cref="CirclesUnknown_1000_105F_1105F"/> minus the explicit comparison
927+
/// against '.' (0x2E). Companion to that routine in the filename-handling code path.
928+
/// </summary>
815929
public void CirclesUnknown_1000_1019_11019()
816930
{
817931
DI = DX;
@@ -826,6 +940,11 @@ public void CirclesUnknown_1000_1019_11019()
826940
}
827941
}
828942

943+
/// <summary>
944+
/// Scans the zero-terminated string at <c>DS:DX</c> for the first '.' (0x2E) byte and
945+
/// returns with <c>DI</c> pointing at it. Used by the entry point to find the extension
946+
/// position before appending ".HNM" to build the filename to open.
947+
/// </summary>
829948
public void CirclesUnknown_1000_105F_1105F()
830949
{
831950
// MOV DI,DX (1000_105F / 0x1105F)
@@ -880,8 +999,12 @@ public void CommonCheckForAnyKeyStroke_1000_1085_11085()
880999
}
8811000

8821001
/// <summary>
883-
/// First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation)
1002+
/// Reads up to 0x8000 bytes from the currently-open file handle into <c>ES:DI</c> via
1003+
/// DOS Int21 ReadFile (AH=0x3F), leaving the bytes-actually-read count in <c>CX</c>, then
1004+
/// closes the file handle via DOS Int21 CloseFile (AH=0x3E). Used after the last HNM chunk
1005+
/// has been consumed.
8841006
/// </summary>
1007+
/// <remarks>First pass rewrite done by the .NET Roslyn compiler (ReadyToRun pre-compilation).</remarks>
8851008
public void HNMReadFile_AdvancePointer_CloseFile_1000_109A_1109A()
8861009
{
8871010
Stack.Push16(DS);

0 commit comments

Comments
 (0)