back to project page

MODULE.SHIP.CUBE Disassembly

                   ********************************************************************************
                   * Disassembly of a module generated by Bill Budge's 3-D Graphics System and    *
                   * Game Tool.                                                                   *
                   *                                                                              *
                   * The tool itself is copyright 1980 California Pacific Computer Co.  Modules   *
                   * may be marketed and sold so long as they provide a credit notice.            *
                   *                                                                              *
                   * The HRCG (code and font) is credited to Christopher Espinosa.                *
                   ********************************************************************************
                   * Disassembly by Andy McFadden, using 6502bench SourceGen v1.6.                *
                   * Last updated 2020/03/11                                                      *
                   *                                                                              *
                   * The manual refers to "points" and "lines" rather than "vertices" and         *
                   * "edges".  For consistency the same nomenclature is used here.                *
                   *                                                                              *
                   * Two shapes are defined: the space shuttle model from the manual, and a       *
                   * simple cube 11 units on a side.  The module is configured for XOR drawing,   *
                   * Applesoft BASIC interface, and includes the hi-res character generator.      *
                   *                                                                              *
                   * This makes extensive use of self-modifying code.  Labels that begin with an  *
                   * underscore indicate self-modification targets.                               *
                   ********************************************************************************
                   * Code interacts with the module by setting values in arrays and calling known *
                   * entry points.  The basic setup for Applesoft BASIC is:                       *
                   *                                                                              *
                   *  1  DIM CODE%(15), X%(15), Y%(15), SCALE%(15), XROT%(15), YROT%(15),         *
                   * ZROT%(15), SX%(15), SY%(15)                                                  *
                   *  2 RESET% = 7932:CLR% = 7951:HIRES% = 7983:CRNCH% = 7737:TXTGEN% = 768       *
                   *                                                                              *
                   * You can define up to 16 shapes.  Their parameters are stored in the various  *
                   * arrays:                                                                      *
                   *                                                                              *
                   *   CODE%(n): 0 (do nothing), 1 (transform & draw), 2 (erase previous,         *
                   * transform, draw new), 3 (erase).                                             *
                   *   X%(n): X coordinate of center (0-255).                                     *
                   *   Y%(n): Y coordinate of center (0-191).                                     *
                   *   SCALE%(n): scale factor, 0-15.  15 is full size, 0 is 1/16th.              *
                   *   XROT%(n): rotation about X axis, 0-27.  0 is no rotation, 27 is just shy   *
                   * of 360 degrees.                                                              *
                   *   YROT%(n): rotation about Y axis.                                           *
                   *   ZROT%(n): rotation about Z axis.                                           *
                   *   SX%(n): (output) X coordinate of last point drawn.                         *
                   *   SY%(n): (output) Y coordinate of last point drawn.                         *
                   *                                                                              *
                   * The code entry points are:                                                   *
                   *                                                                              *
                   *   RESET%: initializes graphics module, clears the screen, switches display   *
                   * to primary hi-res page.                                                      *
                   *   CLR%: clears both hi-res screens and switches to primary hi-res page.      *
                   *   HIRES%: turns on primary hi-res page.                                      *
                   *   CRNCH%: primary animation function.                                        *
                   *                                                                              *
                   * The "CRUNCH" function:                                                       *
                   *  - erases objects whose CODE value is 2 or 3                                 *
                   *  - computes new transformations for objects whose CODE value is 1 or 2       *
                   *  - draws objects whose CODE value is 1 or 2                                  *
                   *  - flips the display to the other page                                       *
                   *                                                                              *
                   * When configured for Integer BASIC, some of the array management is simpler,  *
                   * and an additional "missile" facility is available.                           *
                   *                                                                              *
                   * When configured for use with assembly language, the various arrays live at   *
                   * fixed offsets starting around $6000.                                         *
                   ********************************************************************************
                   OpDEY           equ     $88    {const}    ;DEY opcode
                   OpINY           equ     $c8    {const}    ;INY opcode
                   OpDEX           equ     $ca    {const}    ;DEX opcode
                   OpINX           equ     $e8    {const}    ;INX opcode
                   OpNOP           equ     $ea    {const}    ;NOP opcode
                   MON_WNDLEFT     equ     $20               ;left column of scroll window
                   MON_WNDWDTH     equ     $21               ;width of scroll window
                   MON_WNDTOP      equ     $22               ;top of scroll window
                   MON_WNDBTM      equ     $23               ;bottom of scroll window
                   MON_CH          equ     $24               ;cursor horizontal displacement
                   MON_CV          equ     $25               ;cursor vertical displacement
                   MON_CSWL        equ     $36               ;character output hook (lo)
                   MON_CSWH        equ     $37               ;character output hook (hi)
                   BAS_ARYTAB      equ     $6b    {addr/2}   ;pointer to start of Applesoft array space (2b)
                   CODE_arr        equ     $6008             ;CODE array (dummy address)
                   X_arr           equ     $602f             ;X array (dummy address)
                   Y_arr           equ     $6056             ;Y array (dummy address)
                   SCALE_arr       equ     $607d             ;SCALE array (dummy address)
                   XROT_arr        equ     $60a4             ;XROT array (dummy address)
                   YROT_arr        equ     $60cb             ;YROT array (dummy address)
                   ZROT_arr        equ     $60f2             ;ZROT array (dummy address)
                   SX_arr          equ     $6119             ;SX array (dummy address)
                   SY_arr          equ     $6140             ;SY array (dummy address)
                   TXTCLR          equ     $c050             ;RW display graphics
                   MIXCLR          equ     $c052             ;RW display full screen
                   TXTPAGE1        equ     $c054             ;RW display page 1
                   TXTPAGE2        equ     $c055             ;RW display page 2 (or read/write aux mem)
                   HIRES           equ     $c057             ;RW display hi-res graphics

                                   org     $0300
                   ********************************************************************************
                   * TXTGEN -- initialization entry point for the Hi-Res Character Generator      *
                   * (HRCG).                                                                      *
                   *                                                                              *
                   * Just sets up the character output vector and returns.                        *
                   ********************************************************************************
0300: a0 03        TXTGEN          ldy     #>TextOut         ;2
0302: 84 37                        sty     MON_CSWH          ;3
0304: a0 8c                        ldy     #<TextOut         ;2
0306: 84 36                        sty     MON_CSWL          ;3
0308: 60                           rts                       ;6

                   ********************************************************************************
                   * Draw a character.  This function preserves the contents of the registers,    *
                   * going so far as to avoid using the X register entirely, which makes the code *
                   * less efficient than it could be.                                             *
                   *                                                                              *
                   * One uncommon feature: this draws on both hi-res screens at the same time.    *
                   ********************************************************************************
                   ]ysave          equ     $00    {addr/1}
                   ]ytmp           equ     $01    {addr/1}
                   ]glyph_ptr      equ     $26    {addr/2}
                   ]hbasl          equ     $2a    {addr/2}

0309: 48           DrawChar        pha                       ;3  save original char
030a: 84 00                        sty     ]ysave            ;3
030c: c9 8d                        cmp     #$8d              ;2  carriage return?
030e: f0 68                        beq     NewLine           ;2+ yes, don't output a glyph
                   ; Compute Y coordinate.  This is simpler than the full HPOSN because the line
                   ; we're interested in is a multiple of 8.  (This could have used the Y-lookup
                   ; table in the module.)
0310: a5 25                        lda     MON_CV            ;3  vtab
0312: 4a                           lsr     A                 ;2
0313: 29 03                        and     #$03              ;2
0315: 09 20                        ora     #$20              ;2
0317: 85 2b                        sta     ]hbasl+1          ;3
0319: a5 25                        lda     MON_CV            ;3
031b: 6a                           ror     A                 ;2
031c: 08                           php                       ;3
031d: 0a                           asl     A                 ;2
031e: 29 18                        and     #$18              ;2
0320: 85 2a                        sta     ]hbasl            ;3
0322: 0a                           asl     A                 ;2
0323: 0a                           asl     A                 ;2
0324: 05 2a                        ora     ]hbasl            ;3
0326: 0a                           asl     A                 ;2
0327: 28                           plp                       ;4
0328: 6a                           ror     A                 ;2
0329: 18                           clc                       ;2
032a: 65 24                        adc     MON_CH            ;3  htab
032c: 85 2a                        sta     ]hbasl            ;3
                   ; Now compute the address of the glyph.
032e: 68                           pla                       ;4  recover original char
032f: 29 7f                        and     #$7f              ;2  (this was done by the caller)
0331: 48                           pha                       ;3  save it again
0332: a9 00                        lda     #$00              ;2  (why not use Y-reg?)
0334: 85 27                        sta     ]glyph_ptr+1      ;3
0336: 68                           pla                       ;4
0337: 48                           pha                       ;3
0338: 2a                           rol     A                 ;2  multiply by 8
0339: 26 27                        rol     ]glyph_ptr+1      ;5
033b: 2a                           rol     A                 ;2
033c: 26 27                        rol     ]glyph_ptr+1      ;5
033e: 2a                           rol     A                 ;2
033f: 26 27                        rol     ]glyph_ptr+1      ;5
0341: 85 26                        sta     ]glyph_ptr        ;3
0343: a5 27                        lda     ]glyph_ptr+1      ;3
0345: 18                           clc                       ;2
0346: 69 04                        adc     #>Glyphs          ;2
0348: 85 27                        sta     ]glyph_ptr+1      ;3
034a: a0 00                        ldy     #$00              ;2  count = 0
034c: b1 26        CharLoop        lda     (]glyph_ptr),y    ;5+ get byte of glyph data
034e: 48                           pha                       ;3
034f: 84 01                        sty     ]ytmp             ;3  save counter
0351: a0 00                        ldy     #$00              ;2
0353: d1 2a                        cmp     (]hbasl),y        ;5+ does nothing
0355: 91 2a                        sta     (]hbasl),y        ;6  write to hi-res
0357: a5 2b                        lda     ]hbasl+1          ;3
0359: 49 60                        eor     #$60              ;2  page flip
035b: 85 2b                        sta     ]hbasl+1          ;3
035d: 68                           pla                       ;4
035e: d1 2a                        cmp     (]hbasl),y        ;5+ does nothing
0360: 91 2a                        sta     (]hbasl),y        ;6  write to other hi-res
0362: a4 01                        ldy     ]ytmp             ;3  restore counter
0364: a5 2b                        lda     ]hbasl+1          ;3  advance hi-res address
0366: 18                           clc                       ;2
0367: 69 04                        adc     #$04              ;2  within a block of 8 lines, it's this simple
0369: 85 2b                        sta     ]hbasl+1          ;3
036b: c8                           iny                       ;2
036c: c0 08                        cpy     #$08              ;2  drawn 8 bytes?
036e: d0 dc                        bne     CharLoop          ;2+ no, keep going
0370: e6 24                        inc     MON_CH            ;5  advance htab
0372: a5 24                        lda     MON_CH            ;3
0374: c5 21                        cmp     MON_WNDWDTH       ;3  reached right edge of window?
0376: 90 10                        bcc     L0388             ;2+ no, exit
0378: a5 20        NewLine         lda     MON_WNDLEFT       ;3  move down a line and to left edge
037a: 85 24                        sta     MON_CH            ;3
037c: e6 25                        inc     MON_CV            ;5
037e: a5 25                        lda     MON_CV            ;3
0380: c5 23                        cmp     MON_WNDBTM        ;3  hit bottom?
0382: 90 04                        bcc     L0388             ;2+ nope
0384: a5 22                        lda     MON_WNDTOP        ;3  yes, wrap around to top
0386: 85 25                        sta     MON_CV            ;3
0388: a4 00        L0388           ldy     ]ysave            ;3  restore original Y-reg
038a: 68                           pla                       ;4
038b: 60                           rts                       ;6

038c: 48           TextOut         pha                       ;3
038d: c9 8d                        cmp     #$8d              ;2  carriage return?
038f: f0 1d                        beq     L03AE             ;2+ yes, draw it unmodified
0391: 29 7f                        and     #$7f              ;2  strip hi bit
0393: c9 04                        cmp     #$04              ;2  is it one of our special characters?
0395: 90 1c                        bcc     SetRangeSel       ;2+ yes, branch
0397: c9 40                        cmp     #$40              ;2  numbers or symbols?
0399: 90 03                        bcc     L039E             ;2+ yes, don't modify it
039b: 4d bd 03                     eor     CharRangeSel      ;4  modify character range
039e: 48           L039E           pha                       ;3  save char (high bit stripped)
                   ; If you disable this next bit of code and print values like '/' ($2F), '?'
                   ; ($3F), 'O' ($4F), '_' ($5F), or 'o' ($6F) the characters are partially
                   ; corrupted.  The reason is not at all obvious until you look at the addresses
                   ; used to store them:
                   ; 
                   ;  $2F = $578
                   ;  $3F = $5F8
                   ;  $4F = $678
                   ;  $5F = $6F8
                   ; 
                   ; Those are "screen holes", some of which are used to store values for DOS and
                   ; peripheral slots.  See https://retrocomputing.stackexchange.com/a/2541/56
                   ; 
                   ; The characters that get trampled are duplicated in the first seven control
                   ; characters, the first four of which are used as special HRCG codes anyway (see
                   ; below).  $07 uses a bell glyph, since $7F (DEL) isn't really printable.
039f: 29 0f                        and     #$0f              ;2  check if it ends in $0f
03a1: c9 0f                        cmp     #$0f              ;2  if it's $4F,5F,6F,7f ...
03a3: d0 08                        bne     L03AD             ;2+ not, just draw it
03a5: 68                           pla                       ;4  restore char
03a6: 29 70                        and     #$70              ;2  convert to $40,50,60,70
03a8: 4a                           lsr     A                 ;2
03a9: 4a                           lsr     A                 ;2
03aa: 4a                           lsr     A                 ;2  convert to $4,5,6,7
03ab: 4a                           lsr     A                 ;2  (the AND #$70 seems unnecessary)
03ac: 48                           pha                       ;3
03ad: 68           L03AD           pla                       ;4
03ae: 20 09 03     L03AE           jsr     DrawChar          ;6
03b1: 68                           pla                       ;4  restore unmodified char
03b2: 60                           rts                       ;6

                   ; The HRCG recognizes 4 special characters:
                   ; 
                   ;  - Ctrl+@ - CHR$(0) - shift to upper case ($40-5F)
                   ;  - Ctrl+A - CHR$(1) - shift to lower case ($60-7F)
                   ;  - Ctrl+B - CHR$(2) - shift to graphics symbols ($00-1F)
                   ;  - Ctrl+C - CHR$(3) - shift to digits/punctuation ($20-$3F)
                   ; 
                   ; It might seem odd to include digits & punctuation, but the original ][/][+
                   ; keyboards lacked keys for ASCII symbols like brackets and curly braces.  This
                   ; provided an easy way to generate such characters, especially in Integer BASIC
                   ; which didn't have a CHR$() function.
03b3: 0a           SetRangeSel     asl     A                 ;2  convert 0/1/2/3...
03b4: 0a                           asl     A                 ;2
03b5: 0a                           asl     A                 ;2
03b6: 0a                           asl     A                 ;2
03b7: 0a                           asl     A                 ;2  ...to $00/$20/$40/$60
03b8: 8d bd 03                     sta     CharRangeSel      ;4  save
03bb: 68                           pla                       ;4
03bc: 60                           rts                       ;6

                   ; 
                   ; Value to EOR with characters in the $40-5F range to get other ranges.
                   ; 
03bd: 00           CharRangeSel    dfb     $00
03be: 00 00 00 00+                 .junk   18
                   ; 
                   ; This chunk overwrites various DOS and system vectors.
                   ; 
03d0: 4c bf 9d 4c+                 hex     4cbf9d4c849d4cfdaa4cb5b7ad0f9dac0e9d60adc2aaacc1aa604c51a8eaea4c
                                    +      59fabf9d384c58ff4c65ff4c65ff65ff

                   ; 
                   ; HRCG glyphs, 8 bytes per character (1x8x127).  Note this tramples the screen
                   ; holes, which is why every 16th character looks slightly mangled.
                   ; 
                   ; If the HRCG is not configured in, the program loads at $07FD instead.
                   ; 
                   vis
0400: 00 00 00 7c+ Glyphs          hex     0000007c2a282c000000081c1c081c3e80402010080402003c42403008000800
                                    +      3c42424242423c0000000000000000ff00003844444438000814222222417f08
                                    +      1008047e040810000810207e20100800080808492a1c0800081c2a4908080800
                                    +      08492a1c492a1c0840607078706040004040202013140c081f00007c2a283e00
                                    +      367f7f7f3e1c0800081c3e7f3e1c0800081c3e7f7f2a0800081c1c2a7f7f2a08
                                    +      3e080822362a22000022140814220000040e0404000000000008003e00080000
                                    +      1824081408120c001038040438100000081c081c3e1c3e7f083e1c081c1c3e7f
                                    +      002a3e1c1c1c3e7f00103c3e180c1e3f0008183a7b3e1c7f0400081c1c081c3e
                                    +      00000000000000001010101000001000242424000000000024247e247e242400
                                    +      10781438503c100000462610086462000c12120c52225c002010080000000000
                                    +      201008080810200004081010100804001054387c385410000010107c10100000
                                    +      000000000018180c0000007e0000000000000000001818002f40201008040200
                                    +      3c42625a46423c001018141010107c003c4240300c027e003c42403840423c00
                                    +      203028247e2020007e021e2040221c003804023e42423c007e42201008080800
                                    +      3c42423c42423c003c42427c40201c000000181800181800000018180018180c
                                    +      201008040810200000003e003e00000004081020100804006042403008000800
                                    +      3844526a320478001824427e424242003e44443c44443e003c42020202423c00
                                    +      3e44444444443e007e02021e02027e007e02021e020202003c42027242423c00
                                    +      4242427e4242420038101010101038007020202020221c004222120e12224200
                                    +      0202020202027e0042665a5a4242420042464a52624242006042424242423c00
                                    +      3e42423e020202003c42424252225c003e42423e122242003c42023c40423c00
                                    +      7c101010101010004242424242423c0042424224241818004242425a5a664200
                                    +      424224182442420044444438101010007e40201804027e003c04040404043c00
                                    +      00020408102040003c20202020203c00102844000000000002000000000000ff
                                    +      081020000000000000001c203c225c0002023a4642463a0000003c0202023c00
                                    +      40405c6242625c0000003c427e023c003048083e0808080000005c62625c403c
                                    +      02023a46424242001000181010103800200030202020221c020222120a162200
                                    +      181010101010380000002e545454540000003e44444444000000384444443800
                                    +      00003a46463a020200005c62625c404000003a460202020000007c023c403e00
                                    +      08083e08084830000000424242625c0000004242422418000000444454546c00
                                    +      000042241824420000004242625c403c00007e2018047e003804040604043800
                                    +      08080808080808080e10103010100e002814000000000000
07f8: ff ff ff ff+                 .junk   5                 ;unused

                   ********************************************************************************
                   *                                                                              *
                   * If configured without the HRCG, the module starts here.                      *
                   *                                                                              *
                   * Note that all tables are page-aligned for performance.                       *
                   *                                                                              *
                   ********************************************************************************
                   vis vis
07fd: 02           NumObjects      dfb     2                 ;number of objects
07fe: 23                           dfb     35                ;number of points (unused)
07ff: 29                           dfb     41                ;number of lines (unused)
                   ; 
                   ; The next five tables represent the data as it was entered into the shape
                   ; editor.  There are two shapes.  The first (space shuttle) starts at offset 0,
                   ; has 27 points, and 29 lines.  The second (cube) starts immediately after the
                   ; first, has 8 points, and 12 lines.
                   ; 
                   ; 3D mesh X coordinates (-60, -57, ...)
0800: c4 c7 c7 c7+ ShapeXCoords    hex     c4c7c7c7c7d6d6d6d6f1f1000015151e1e1e1e24242424091b151efb0505fbfb
                                    +      0505fbecfc0c1828304450747c05fb00c4cacacacad6d6d6d6f1f1000015151e
                                    +      1e1e1e24242424091b151ed8e8f80818289cc4ec143c64c937b54b22dedef20e
                                    +      2222dedef20e22283946d8c7ba0000004d4d3f3fb3b3c1c1f90707f911efef11
                                    +      08f80af619e719e700fa060000fc04fc04fa06f60afc04f40cfa06fa06f60af6
                                    +      0af40cf40cd030d030d030d030d030d030d306fc1aba00da03161ab000ba0210
                                    +      341a98192bda031bab3ba0a0aba401df82d90bf20cd806062b7c105b083f1916
                                    +      0f019c19230f0197f21824000cc0f806ed2b7c421aac00ba5c06f11a0300da06
                   ; 3D mesh Y coordinates (0, 3, ...)
0900: 00 03 03 fd+ ShapeYCoords    hex     000303fdfd0609faf709f70ff124dc24dc09f709f706fa00000000fbfb0505fb
                                    +      fb0505d0e0bcb0c4d8d0e0e0d00a0a22000505fbfb0609faf709f70ff124dc24
                                    +      dc09f709f706fa00000000202020202020e0e0e0e0e0e01010fafaf4f40c2020
                                    +      0cf4f40c20200c000000000000283946f90707f9f90707f94d4d3f3fefef1111
                                    +      0e0e1b1b1111e7e7000606fa0a0a0a0a0a06060606fafa06060606fafa0404fc
                                    +      fc0404fcfc0c0cf4f40c0cf4f40c0cf4f406004f0cd0d2a302002c0dc5e4e9f4
                                    +      040600a20dc1000000204d0aa9ff8531a000a524c927d009208efd8531a90685
                                    +      24b112c530d013e631a431c010b00bbef000e4249004862490d620edfde612d0
                   ; 3D mesh Z coordinates (0, 3, ...)
0a00: 00 03 fd 03+ ShapeZCoords    hex     0003fd03fd09fa09fafafafafafafafafafafafafa090909091b1bfbfbfbfb05
                                    +      050505000000000000000000000000000005fb05fb09fa09fafafafafafafafa
                                    +      fafafafafa090909091e1e000000000000000000000000000000000000000000
                                    +      00e2e2e0e0e0e0fddec9fddec9fbdbc6c9c6c6c9c9c6c6c9c6c6c9c928282a2a
                                    +      1616030320201e1e5a1e1e1e2422220c0c121210100c0ce8e8e2e2e8e8fafafa
                                    +      fae8e8e8e8f4f4f4f4eeeeeeee0000000089f601e21027e80364000a0001002b
                                    +      352537004c45082bd702583601f52089f66c3b3808ed0702ebf84c07036c38ec
                                    +      28db02a500208e0a2089f629d703e2006000208efd20ce0a20d50e20c9092089
                   ; 3D mesh line definition: start points (0, 0, 0, ...)
0b00: 00 00 00 00+ LineStartPoint  hex     00000000010203040608090a0b0c0d0e0f10111213050713141517191a1b1c1d
                                    +      1e1f2021221b1c1d1e262728292a2b2d2e30303030313233343638393a3b3c3d
                                    +      3e3f4041424335374344454749484b4c4d4e4f504b5759515d635d5e5f655f60
                                    +      5b606166675c5d62636a5e5f64656d707172737475767778797a7b7c7d7e7f80
                                    +      817e7f7e7f8485848586878888888c8c8d8e898a9192939493948b8b97989997
                                    +      98999a9da1a99fa3ab9ea2aaa0a4ac39a338010aa5034dd6034a37382539113c
                                    +      00297128710020da0b4c45082089f6e8113c0032b071e07122006c080014cdfe
                                    +      0020ce0a2089f6293a283beb00208e0a2089f629382a39f828b9f80020cc0b20
                   ; 3D mesh line definition: end points (1, 2, 3, ...)
0c00: 01 02 03 04+ LineEndPoint    hex     0102030405060708090a0b0c0d0e0f1011121314141516151616191a181c1d1e
                                    +      1b2021221f1f2021222728292a2b2c2f2f3132333435363738393a3b3c3d3e3f
                                    +      4041424344444546454646494a4a51525354555650585a565e64636460666566
                                    +      67676868696a6a6b6b6c6d6d6e6e6f7172737075767774797a7b787d7e7f7c82
                                    +      83818085848081605d8485898a8b8d8e8f9091929394959697989b9c999a9a9b
                                    +      9c9b9ca5a9ada7abafa6aaaea8acb010dd083f196b0f0020d009200cfdc9d366
                                    +      3320ce0aa9ff852fd00020610c2089f611000229d40604495101f84a06035101
                                    +      fa213af24251d307fb190002117c0324712a7100207b0d2433100c200cfdc983
                   ; 
                   ; For shape N, the index of the first point.
                   ; 
                   ; Shape #0 uses points $00-1A, shape #1 uses points $1B-22.  (Data at offsets 2-
                   ; 15 is junk.)
0d00: 00 1b 08 0c+ FirstPointIndex hex     001b080c0d1d2d304b5b887c036139e9
                   ; For shape N, the index of the last point + 1.
0d10: 1b 23 0c 0d+ LastPointIndex  hex     1b230c0d1d2d304b5b88b12a1a0002ba
                   ; 
                   ; For shape N, the index of the first line.
                   ; 
                   ; Shape #0 uses lines $00-1C, shape #1 uses lines $1D-28.  (Data at offsets 2-15
                   ; is junk.)
0d20: 00 1d 0c 01+ FirstLineIndex  hex     001d0c0112202f314e588b019c00a516
                   ; For shape N, the index of the last point + 1.
0d30: 1d 29 12 01+ LastLineIndex   hex     1d291201202f314e588baffe4c450820
                   ; 
                   ; Indexes into the rotation tables.  One entry for each rotation value (0-27). 
                   ; The "low" and "high" tables have the same value at each position, just shifted
                   ; over 4 bits.
                   ; 
                   ; Mathematically, cosine has the same shape as sine, but is shifted by PI/2 (one
                   ; quarter period) ahead of it.  That's why there are two sets of tables, one of
                   ; which is shifted by 7 bytes.
                   ; 
                   ; See the comments above RotTabLo for more details.
                   ; 
0d40: 70 60 50 40+ RotIndexLo_sin  hex     7060504030201000102030405060708090a0b0c0d0e0d0c0b0a09080
0d5c: 07 06 05 04+ RotIndexHi_sin  hex     07060504030201000102030405060708090a0b0c0d0e0d0c0b0a0908
0d78: 00 10 20 30+ RotIndexLo_cos  hex     00102030405060708090a0b0c0d0e0d0c0b0a0908070605040302010
0d94: 00 01 02 03+ RotIndexHi_cos  hex     000102030405060708090a0b0c0d0e0d0c0b0a090807060504030201
                   ; 
                   ; Indexes into the scale tables.  One entry for each scale value (0-15).  See
                   ; the comments above ScaleTabLo for more details.
                   ; 
0db0: 00 10 20 30+ ScaleIndexLo    hex     00102030405060708090a0b0c0d0e0f0
0dc0: 00 01 02 03+ ScaleIndexHi    hex     000102030405060708090a0b0c0d0e0f
                   ; 
                   ; Junk, pads to end of 256-byte page.
0dd0: 03 de 4c 3f+                 .align  $0100 (48 bytes)
                   ; 
                   ; These four buffers hold transformed points in screen coordinates.  The points
                   ; are in the same order as they are in the mesh definition.
                   ; 
                   ; One pair of tables holds the X/Y screen coordinates from the previous frame,
                   ; the other pair of tables holds the coordinates being transformed for the
                   ; current frame.  We need two sets because we're display set 0 while generating
                   ; set 1, and after we flip we need to use set 0 again to erase the display.
                   ; 
                   ; ----------
                   ; 
                   ; Computed X coordinate, set 0.
0e00: 00 01 02 03+ XCoord0_0E      .junk   256
                   ; Computed Y coordinate, set 0.
0f00: ff ff 00 00+ YCoord0_0F      .junk   256
                   ; Computed X coordinate, set 1.
1000: ff ff 00 00+ XCoord1_10      .junk   256
                   ; Computed Y coordinate, set 1.
1100: ff ff 00 00+ YCoord1_11      .junk   256
                   ; 
                   ; Math constants for rotation.
                   ; 
                   ; To compute X * cos(theta), start by converting theta (0-27) into a table base
                   ; address (using the 28-byte tables RotIndexLo_cos / RotIndexHi_cos).  Split the
                   ; X coordinate into nibbles, use the low 4 bits to index into the adjusted
                   ; RotTabLo pointer, and the high 4 bits to index into the adjusted RotTabHi
                   ; pointer.  Add the values at those locations together.
                   ; 
                   ; This is similar to the way the scale table works.  See ScaleTableLo, below,
                   ; for a longer explanation of how the nibbles are used.
                   ; 
                   ; As an example, suppose we have a point at (36,56), and we want to rotate it 90
                   ; degrees (rot=7).  We use the RotIndex tables to get the table base addresses:
                   ; sin=$00/$00 ($1200/$1300), cos=$70/$07 ($1270/$1307).  We split the
                   ; coordinates into nibbles without shifting ($24,$38 --> $20 $04, $30 $08), and
                   ; use the nibbles as indexes into the tables:
                   ; 
                   ;  X * cos(theta) = ($1274)+($1327) = $00+$00 = 0
                   ;  Y * sin(theta) = ($1208)+($1330) = $08+$30 = 56
                   ;  X * sin(theta) = ($1204)+($1320) = $04+$20 = 36
                   ;  Y * cos(theta) = ($1278)+($1337) = $00+$00 = 0
                   ; 
                   ;  XC = X*cos(theta) - Y*sin(theta) = -56
                   ;  YC = X*sin(theta) + Y*cos(theta) = 36
                   ; 
                   ; which is exactly what we expected (counter-clockwise).
                   ; 
                   ; The largest value from the index table is $EE, so that last 17 bytes in each
                   ; table are unused.
                   ; 
1200: 00 01 02 03+ RotTabLo        hex     000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f
                                    +      00010203040505060708090a0b0c0d0e000102020304050506070809090a0b0c
                                    +      0001010202030404050606070708090900000101020203030304040505060607
                                    +      0000000101010102020202020303030300000000000000000000000000000000
                                    +      000000fffffffffefefefefefdfdfdfd0000fffffefefdfdfdfcfcfbfbfafaf9
                                    +      00fffffefefdfcfcfbfafaf9f9f8f7f700fffefefdfcfbfbfaf9f8f7f7f6f5f4
                                    +      00fffefdfcfbfbfaf9f8f7f6f5f4f3f200fffefdfcfbfbfaf8f7f6f5f4f3f2f1
                                    +      00fffefdfcfbfaf9f8f7f6f5f4f3f2f100000000000000000000000000000000
1300: 00 00 00 00+ RotTabHi        hex     0000000000000000000000000000000010100e0d0a070400fcf9f6f3f2f0f000
                                    +      201f1d19140e0700f9f2ece7e3e1e000302f2b261e150b00f5ebe2dad5d1d000
                                    +      403e3a32281c0e00f2e4d8cec6c2c000504e483f32231200eeddcec1b8b2b000
                                    +      605e564b3c2a1500ebd6c4b5aaa2a000706d655846311900e7cfbaa89b939000
                                    +      80838d9cb0c8e4001c385064737d800090939ba8bacfe70019314658656d7000
                                    +      a0a2aab5c4d6eb00152a3c4b565e6000b0b2b8c1ceddee001223323f484e5000
                                    +      c0c2c6ced8e4f2000e1c28323a3e4000d0d1d5dae2ebf5000b151e262b2f3000
                                    +      e0e1e3e7ecf2f900070e14191d1f2000f0f0f2f3f6f9fc0004070a0d0e101000
                   ; 
                   ; Divide-by-7 table.  Used to divide the X coordinate (0-255) by 7, yielding a
                   ; byte offset for the hi-res screen column.
                   ; 
1400: 00 00 00 00+ Div7Tab         hex     0000000000000001010101010101020202020202020303030303030304040404
                                    +      0404040505050505050506060606060606070707070707070808080808080809
                                    +      0909090909090a0a0a0a0a0a0a0b0b0b0b0b0b0b0c0c0c0c0c0c0c0d0d0d0d0d
                                    +      0d0d0e0e0e0e0e0e0e0f0f0f0f0f0f0f10101010101010111111111111111212
                                    +      1212121212131313131313131414141414141415151515151515161616161616
                                    +      161717171717171718181818181818191919191919191a1a1a1a1a1a1a1b1b1b
                                    +      1b1b1b1b1c1c1c1c1c1c1c1d1d1d1d1d1d1d1e1e1e1e1e1e1e1f1f1f1f1f1f1f
                                    +      2020202020202021212121212121222222222222222323232323232324242424
                   ; 
                   ; Hi-res bit table.  Converts the X coordinate (0-255) into a bit position
                   ; within a byte.  (Essentially 2 to the power of the remainder of the coordinate
                   ; divided by 7.)
                   ; 
1500: 01 02 04 08+ HiResBitTab     hex     0102040810204001020408102040010204081020400102040810204001020408
                                    +      1020400102040810204001020408102040010204081020400102040810204001
                                    +      0204081020400102040810204001020408102040010204081020400102040810
                                    +      2040010204081020400102040810204001020408102040010204081020400102
                                    +      0408102040010204081020400102040810204001020408102040010204081020
                                    +      4001020408102040010204081020400102040810204001020408102040010204
                                    +      0810204001020408102040010204081020400102040810204001020408102040
                                    +      0102040810204001020408102040010204081020400102040810204001020408
                   ; 
                   ; Hi-res Y-coordinate lookup table, low byte.  Values 0-191 are meaningful, 192-
                   ; 255 are junk.
                   ; 
1600: 00 00 00 00+ YTableLo        hex     0000000000000000808080808080808000000000000000008080808080808080
                                    +      0000000000000000808080808080808000000000000000008080808080808080
                                    +      2828282828282828a8a8a8a8a8a8a8a82828282828282828a8a8a8a8a8a8a8a8
                                    +      2828282828282828a8a8a8a8a8a8a8a82828282828282828a8a8a8a8a8a8a8a8
                                    +      5050505050505050d0d0d0d0d0d0d0d05050505050505050d0d0d0d0d0d0d0d0
                                    +      5050505050505050d0d0d0d0d0d0d0d05050505050505050d0d0d0d0d0d0d0d0
16c0: 00 00 00 00+                 .align  $0100 (64 bytes)
                   ; 
                   ; Hi-res Y-coordinate lookup table, high byte.
                   ; 
1700: 00 04 08 0c+ YTableHi        hex     0004080c1014181c0004080c1014181c0105090d1115191d0105090d1115191d
                                    +      02060a0e12161a1e02060a0e12161a1e03070b0f13171b1f03070b0f13171b1f
                                    +      0004080c1014181c0004080c1014181c0105090d1115191d0105090d1115191d
                                    +      02060a0e12161a1e02060a0e12161a1e03070b0f13171b1f03070b0f13171b1f
                                    +      0004080c1014181c0004080c1014181c0105090d1115191d0105090d1115191d
                                    +      02060a0e12161a1e02060a0e12161a1e03070b0f13171b1f03070b0f13171b1f
17c0: bb bb bb bb+                 .align  $0100 (64 bytes)
                   ; 
                   ; Math constants for scaling.
                   ; 
                   ; Each table has 16 sets of 16 entries, with one set for each of the 16 possible
                   ; scale values.  The values within a set determine how one 4-bit nibble of the
                   ; coordinate is scaled.
                   ; 
                   ; Suppose you want to scale the value 100 ($64) by scale factor 8 (a bit over
                   ; half size).  We begin by using self-modifying code to select the table
                   ; subsets.  This is done in a clever way to avoid shifting.  The instructions
                   ; that load from ScaleTabLo are modified to reference $1800, $1810, $1820, and
                   ; so on.  The instructions that load from ScaleTabHi reference $1900, $1901,
                   ; $1902, etc.  The offset comes from the two 16-byte ScaleIndex tables.  For a
                   ; scale factor of 8, we'll be using $1880 and $1908 as the base addresses.
                   ; 
                   ; To do the actual scaling, we mask to get the low part of the value ($04) and
                   ; index into ScaleTabLo, at address $1884.  We mask the high part of the value
                   ; ($60) and index into ScaleTabHi, at $1968.  We add the values there ($02, $36)
                   ; to get $38 = 56, which is just over half size as expected.
                   ; 
                   ; This is an approximation, but so is any integer division, and it's done in
                   ; 512+32=544 bytes instead of the 16*256=4096 bytes that you'd need for a fully-
                   ; formed scale.  For hi-res graphics it's certainly good enough.
                   ; 
                   ;   32 = $20 = ($1880)+($1928) = 18 (.563)
                   ;   40 = $28 = ($1888)+($1928) = 22 (.55)
                   ;   47 = $2F = ($188F)+($1928) = 26 (.553)
                   ;   48 = $30 = ($1880)+($1938) = 27 (.563)
                   ;  100 = $64 = ($1884)+($1968) = 56 (.56)
                   ; 
1800: 00 00 00 00+ ScaleTabLo      hex     0000000000000000000000000000000000000000000000000101010101010101
                                    +      0000000000000101010101020202020200000000010101010202020203030303
                                    +      0000000001010102020203030304040400000001010102020303030404040505
                                    +      0000000101020203030304040505060600000101020203030404050506060707
                                    +      0000010102020303040505060607070800000101020303040505060607080809
                                    +      0000010202030404050606070808090a00000102030304050606070809090a0b
                                    +      000001020304040506070808090a0b0c0000010203040506070708090a0b0c0d
                                    +      00000102030405060708090a0b0c0d0e000102030405060708090a0b0c0d0e0f
1900: 00 00 00 00+ ScaleTabHi      hex     000000000000000000000000000000000102030405060708090a0b0c0d0e0f10
                                    +      020406080a0c0e10121416181a1c1e200306090c0f1215181b1e2124272a2d30
                                    +      04080c1014181c2024282c3034383c40050a0f14191e23282d32373c41464b50
                                    +      060c12181e242a30363c42484e545a60070e151c232a31383f464d545b626970
                                    +      f8f0e8e0d8d0c8c0b8b0a8a098908880f9f2ebe4ddd6cfc8c1bab3aca59e9790
                                    +      faf4eee8e2dcd6d0cac4beb8b2aca6a0fbf6f1ece7e2ddd8d3cec9c4bfbab5b0
                                    +      fcf8f4f0ece8e4e0dcd8d4d0ccc8c4c0fdfaf7f4f1eeebe8e5e2dfdcd9d6d3d0
                                    +      fefcfaf8f6f4f2f0eeeceae8e6e4e2e0fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0

                   ; 
                   ; Draw a list of lines using exclusive-or, which inverts the pixels.  Drawing
                   ; the same thing twice erases it.
                   ; 
                   ; On entry:
                   ;  $45 - index of first line
                   ;  $46 - index of last line
                   ;  XCoord_0E/YCoord_0F or XCoord_10/YCoord_11 have transformed points in screen
                   ; coordinates
                   ; 
                   ; When the module is configured for OR-mode drawing, this code is replaced with
                   ; a dedicated erase function.  The erase code is nearly identical to the draw
                   ; code, but saves a little time by simply zeroing out whole bytes instead of
                   ; doing a read-modify-write.
                   ; 
                   • Clear variables
                   ]hptr           equ     $06    {addr/2}
                   ]hpage          equ     $18    {addr/1}   ;hi-res page ($20 or $40)
                   ]xstart         equ     $1c    {addr/1}
                   ]ystart         equ     $1d    {addr/1}
                   ]xend           equ     $1e    {addr/1}
                   ]yend           equ     $1f    {addr/1}
                   ]delta_x        equ     $3c    {addr/1}
                   ]delta_y        equ     $3d    {addr/1}
                   ]line_adj       equ     $3e    {addr/1}
                   ]line_index     equ     $43    {addr/1}
                   ]ysave          equ     $44    {addr/1}
                   ]first_line     equ     $45    {addr/1}
                   ]last_line      equ     $46    {addr/1}

1a00: a6 45        DrawLineListEOR ldx     ]first_line       ;3  start with the first line in this object
1a02: bd 00 0b     DrawLoop        lda     LineStartPoint,x  ;4+ get X0,Y0
1a05: a8                           tay                       ;2
1a06: b9 00 0e     _0E_or_10_1     lda     XCoord0_0E,y      ;4+ the instructions here are modified to load from
1a09: 85 1c                        sta     ]xstart           ;3   the appropriate set of X/Y coordinate tables
1a0b: b9 00 0f     _0F_or_11_1     lda     YCoord0_0F,y      ;4+
1a0e: 85 1d                        sta     ]ystart           ;3
1a10: bd 00 0c                     lda     LineEndPoint,x    ;4+ get X1,Y1
1a13: a8                           tay                       ;2
1a14: b9 00 0e     _0E_or_10_2     lda     XCoord0_0E,y      ;4+
1a17: 85 1e                        sta     ]xend             ;3
1a19: b9 00 0f     _0F_or_11_2     lda     YCoord0_0F,y      ;4+
1a1c: 85 1f                        sta     ]yend             ;3
1a1e: 86 43                        stx     ]line_index       ;3  save this off
                   ; Prep the line draw code.  We need to compute deltaX/deltaY, and set a register
                   ; increment / decrement / no-op instruction depending on which way the line is
                   ; going.
1a20: a5 1c                        lda     ]xstart           ;3  compute delta X
1a22: 38                           sec                       ;2
1a23: e5 1e                        sbc     ]xend             ;3
1a25: b0 08                        bcs     L1A2F             ;2+ left to right
1a27: 49 ff                        eor     #$ff              ;2  right to left; invert value
1a29: 69 01                        adc     #$01              ;2
1a2b: a0 e8                        ldy     #OpINX            ;2
1a2d: d0 08                        bne     GotDeltaX         ;3

1a2f: f0 04        L1A2F           beq     IsVertical        ;2+ branch if deltaX=0
1a31: a0 ca                        ldy     #OpDEX            ;2
1a33: d0 02                        bne     GotDeltaX         ;3

1a35: a0 ea        IsVertical      ldy     #OpNOP            ;2  fully vertical, use no-op
1a37: 85 3c        GotDeltaX       sta     ]delta_x          ;3
1a39: 8c 8e 1a                     sty     _InxDexNop1       ;4
1a3c: 8c bb 1a                     sty     _InxDexNop2       ;4
1a3f: a5 1d                        lda     ]ystart           ;3  compute delta Y
1a41: 38                           sec                       ;2
1a42: e5 1f                        sbc     ]yend             ;3
1a44: b0 08                        bcs     L1A4E             ;2+ end < start, we're good
1a46: 49 ff                        eor     #$ff              ;2  invert value
1a48: 69 01                        adc     #$01              ;2
1a4a: a0 c8                        ldy     #OpINY            ;2
1a4c: d0 08                        bne     GotDeltaY         ;3

1a4e: f0 04        L1A4E           beq     IsHorizontal      ;2+ branch if deltaY=0
1a50: a0 88                        ldy     #OpDEY            ;2
1a52: d0 02                        bne     GotDeltaY         ;3

1a54: a0 ea        IsHorizontal    ldy     #OpNOP            ;2  fully horizontal, use no-op
1a56: 85 3d        GotDeltaY       sta     ]delta_y          ;3
1a58: 8c 70 1a                     sty     _InyDeyNop1       ;4
1a5b: 8c cd 1a                     sty     _InyDeyNop2       ;4
1a5e: a6 1c                        ldx     ]xstart           ;3
1a60: a4 1d                        ldy     ]ystart           ;3
1a62: a9 00                        lda     #$00              ;2
1a64: 85 3e                        sta     ]line_adj         ;3
1a66: a5 3c                        lda     ]delta_x          ;3
1a68: c5 3d                        cmp     ]delta_y          ;3
1a6a: b0 3f                        bcs     HorizDomLine      ;2+
                   ; Line draw: vertically dominant (move vertically every step)
                   ; 
                   ; On entry: X=xpos, Y=ypos
1a6c: c4 1f        VertDomLine     cpy     ]yend             ;3
1a6e: f0 30                        beq     LineDone          ;2+
1a70: ea           _InyDeyNop1     nop                       ;2  self-mod INY/DEY/NOP
1a71: b9 00 16                     lda     YTableLo,y        ;4+ new line, update Y position
1a74: 85 06                        sta     ]hptr             ;3
1a76: b9 00 17                     lda     YTableHi,y        ;4+
1a79: 05 18                        ora     ]hpage            ;3
1a7b: 85 07                        sta     ]hptr+1           ;3
1a7d: a5 3e                        lda     ]line_adj         ;3  Bresenham update
1a7f: 18                           clc                       ;2
1a80: 65 3c                        adc     ]delta_x          ;3
1a82: c5 3d                        cmp     ]delta_y          ;3
1a84: b0 04                        bcs     NewColumn         ;2+
1a86: 85 3e                        sta     ]line_adj         ;3
1a88: 90 05                        bcc     SameColumn        ;3

1a8a: e5 3d        NewColumn       sbc     ]delta_y          ;3
1a8c: 85 3e                        sta     ]line_adj         ;3
1a8e: ea           _InxDexNop1     nop                       ;2  self-mod INX/DEX/NOP
1a8f: 84 44        SameColumn      sty     ]ysave            ;3
1a91: bc 00 14                     ldy     Div7Tab,x         ;4+ XOR-draw the point
1a94: b1 06                        lda     (]hptr),y         ;5+
1a96: 5d 00 15                     eor     HiResBitTab,x     ;4+
1a99: 91 06                        sta     (]hptr),y         ;6
1a9b: a4 44                        ldy     ]ysave            ;3
1a9d: 4c 6c 1a                     jmp     VertDomLine       ;3

1aa0: a6 43        LineDone        ldx     ]line_index       ;3
1aa2: e8                           inx                       ;2
1aa3: e4 46                        cpx     ]last_line        ;3  reached end?
1aa5: f0 03                        beq     DrawDone          ;2+
1aa7: 4c 02 1a                     jmp     DrawLoop          ;3

1aaa: 60           DrawDone        rts                       ;6

                   ; Line draw: horizontally dominant (move horizontally every step)
                   ; 
                   ; On entry: X=xpos, Y=ypos
1aab: b9 00 16     HorizDomLine    lda     YTableLo,y        ;4+ set up hi-res pointer
1aae: 85 06                        sta     ]hptr             ;3
1ab0: b9 00 17                     lda     YTableHi,y        ;4+
1ab3: 05 18                        ora     ]hpage            ;3
1ab5: 85 07                        sta     ]hptr+1           ;3
1ab7: e4 1e        HorzLoop        cpx     ]xend             ;3  X at end?
1ab9: f0 e5                        beq     LineDone          ;2+ yes, finish
1abb: ea           _InxDexNop2     nop                       ;2
1abc: a5 3e                        lda     ]line_adj         ;3  Bresenham update
1abe: 18                           clc                       ;2
1abf: 65 3d                        adc     ]delta_y          ;3
1ac1: c5 3c                        cmp     ]delta_x          ;3
1ac3: b0 04                        bcs     NewRow            ;2+
1ac5: 85 3e                        sta     ]line_adj         ;3
1ac7: 90 11                        bcc     SameRow           ;3

1ac9: e5 3c        NewRow          sbc     ]delta_x          ;3
1acb: 85 3e                        sta     ]line_adj         ;3
1acd: ea           _InyDeyNop2     nop                       ;2
1ace: b9 00 16                     lda     YTableLo,y        ;4+ update Y position
1ad1: 85 06                        sta     ]hptr             ;3
1ad3: b9 00 17                     lda     YTableHi,y        ;4+
1ad6: 05 18                        ora     ]hpage            ;3
1ad8: 85 07                        sta     ]hptr+1           ;3
1ada: 84 44        SameRow         sty     ]ysave            ;3
1adc: bc 00 14                     ldy     Div7Tab,x         ;4+ XOR-draw the point
1adf: b1 06                        lda     (]hptr),y         ;5+
1ae1: 5d 00 15                     eor     HiResBitTab,x     ;4+
1ae4: 91 06                        sta     (]hptr),y         ;6
1ae6: a4 44                        ldy     ]ysave            ;3
1ae8: 4c b7 1a                     jmp     HorzLoop          ;3

                   ; Draw code calls here.  Since we're configured for XOR mode, this just jumps to
                   ; the exclusive-or version.  If we were configured for OR mode, this would be
                   ; LDX $45 / LDA $0B00,X instead of a JMP.
1aeb: 4c 00 1a     DrawLineList    jmp     DrawLineListEOR   ;3

                   ; 
                   ; Unused OR-mode implementation follows.
                   ; 
                   ; The code is substantially similar to the exclusive-or version, so it has not
                   ; been annotated.
                   ; 
1aee: 00                           dfb     $00
1aef: 0b                           dfb     $0b

1af0: a8                           tay                       ;2
1af1: b9 00 0e                     lda     XCoord0_0E,y      ;4+
1af4: 85 1c                        sta     ]xstart           ;3
1af6: b9 00 0f                     lda     YCoord0_0F,y      ;4+
1af9: 85 1d                        sta     ]ystart           ;3
1afb: bd 00 0c                     lda     LineEndPoint,x    ;4+
1afe: a8                           tay                       ;2
1aff: b9 00 0e                     lda     XCoord0_0E,y      ;4+
1b02: 85 1e                        sta     ]xend             ;3
1b04: b9 00 0f                     lda     YCoord0_0F,y      ;4+
1b07: 85 1f                        sta     ]yend             ;3
1b09: 86 43                        stx     ]line_index       ;3
1b0b: a5 1c                        lda     ]xstart           ;3
1b0d: 38                           sec                       ;2
1b0e: e5 1e                        sbc     ]xend             ;3
1b10: b0 08                        bcs     L1B1A             ;2+
1b12: 49 ff                        eor     #$ff              ;2
1b14: 69 01                        adc     #$01              ;2
1b16: a0 e8                        ldy     #$e8              ;2
1b18: d0 08                        bne     L1B22             ;3

1b1a: f0 04        L1B1A           beq     L1B20             ;2+
1b1c: a0 ca                        ldy     #$ca              ;2
1b1e: d0 02                        bne     L1B22             ;3

1b20: a0 ea        L1B20           ldy     #$ea              ;2
1b22: 85 3c        L1B22           sta     ]delta_x          ;3
1b24: 8c 79 1b                     sty     L1B79             ;4
1b27: 8c a6 1b                     sty     L1BA6             ;4
1b2a: a5 1d                        lda     ]ystart           ;3
1b2c: 38                           sec                       ;2
1b2d: e5 1f                        sbc     ]yend             ;3
1b2f: b0 08                        bcs     L1B39             ;2+
1b31: 49 ff                        eor     #$ff              ;2
1b33: 69 01                        adc     #$01              ;2
1b35: a0 c8                        ldy     #$c8              ;2
1b37: d0 08                        bne     L1B41             ;3

1b39: f0 04        L1B39           beq     L1B3F             ;2+
1b3b: a0 88                        ldy     #$88              ;2
1b3d: d0 02                        bne     L1B41             ;3

1b3f: a0 ea        L1B3F           ldy     #$ea              ;2
1b41: 85 3d        L1B41           sta     ]delta_y          ;3
1b43: 8c 5b 1b                     sty     L1B5B             ;4
1b46: 8c b8 1b                     sty     L1BB8             ;4
1b49: a6 1c                        ldx     ]xstart           ;3
1b4b: a4 1d                        ldy     ]ystart           ;3
1b4d: a9 00                        lda     #$00              ;2
1b4f: 85 3e                        sta     ]line_adj         ;3
1b51: a5 3c                        lda     ]delta_x          ;3
1b53: c5 3d                        cmp     ]delta_y          ;3
1b55: b0 3f                        bcs     L1B96             ;2+
1b57: c4 1f        L1B57           cpy     ]yend             ;3
1b59: f0 30                        beq     L1B8B             ;2+
1b5b: ea           L1B5B           nop                       ;2
1b5c: b9 00 16                     lda     YTableLo,y        ;4+
1b5f: 85 06                        sta     ]hptr             ;3
1b61: b9 00 17                     lda     YTableHi,y        ;4+
1b64: 05 18                        ora     ]hpage            ;3
1b66: 85 07                        sta     ]hptr+1           ;3
1b68: a5 3e                        lda     ]line_adj         ;3
1b6a: 18                           clc                       ;2
1b6b: 65 3c                        adc     ]delta_x          ;3
1b6d: c5 3d                        cmp     ]delta_y          ;3
1b6f: b0 04                        bcs     L1B75             ;2+
1b71: 85 3e                        sta     ]line_adj         ;3
1b73: 90 05                        bcc     L1B7A             ;3

1b75: e5 3d        L1B75           sbc     ]delta_y          ;3
1b77: 85 3e                        sta     ]line_adj         ;3
1b79: ea           L1B79           nop                       ;2
1b7a: 84 44        L1B7A           sty     ]ysave            ;3
1b7c: bc 00 14                     ldy     Div7Tab,x         ;4+
1b7f: b1 06                        lda     (]hptr),y         ;5+
1b81: 1d 00 15                     ora     HiResBitTab,x     ;4+
1b84: 91 06                        sta     (]hptr),y         ;6
1b86: a4 44                        ldy     ]ysave            ;3
1b88: 4c 57 1b                     jmp     L1B57             ;3

1b8b: a6 43        L1B8B           ldx     ]line_index       ;3
1b8d: e8                           inx                       ;2
1b8e: e4 46                        cpx     ]last_line        ;3
1b90: f0 03                        beq     L1B95             ;2+
1b92: 4c ed 1a                     jmp     DrawLineList+2    ;3

1b95: 60           L1B95           rts                       ;6

1b96: b9 00 16     L1B96           lda     YTableLo,y        ;4+
1b99: 85 06                        sta     ]hptr             ;3
1b9b: b9 00 17                     lda     YTableHi,y        ;4+
1b9e: 05 18                        ora     ]hpage            ;3
1ba0: 85 07                        sta     ]hptr+1           ;3
1ba2: e4 1e        L1BA2           cpx     ]xend             ;3
1ba4: f0 e5                        beq     L1B8B             ;2+
1ba6: ea           L1BA6           nop                       ;2
1ba7: a5 3e                        lda     ]line_adj         ;3
1ba9: 18                           clc                       ;2
1baa: 65 3d                        adc     ]delta_y          ;3
1bac: c5 3c                        cmp     ]delta_x          ;3
1bae: b0 04                        bcs     L1BB4             ;2+
1bb0: 85 3e                        sta     ]line_adj         ;3
1bb2: 90 11                        bcc     L1BC5             ;3

1bb4: e5 3c        L1BB4           sbc     ]delta_x          ;3
1bb6: 85 3e                        sta     ]line_adj         ;3
1bb8: ea           L1BB8           nop                       ;2
1bb9: b9 00 16                     lda     YTableLo,y        ;4+
1bbc: 85 06                        sta     ]hptr             ;3
1bbe: b9 00 17                     lda     YTableHi,y        ;4+
1bc1: 05 18                        ora     ]hpage            ;3
1bc3: 85 07                        sta     ]hptr+1           ;3
1bc5: 84 44        L1BC5           sty     ]ysave            ;3
1bc7: bc 00 14                     ldy     Div7Tab,x         ;4+
1bca: b1 06                        lda     (]hptr),y         ;5+
1bcc: 1d 00 15                     ora     HiResBitTab,x     ;4+
1bcf: 91 06                        sta     (]hptr),y         ;6
1bd1: a4 44                        ldy     ]ysave            ;3
1bd3: 4c a2 1b                     jmp     L1BA2             ;3

                   ; 
                   ; Unreferenced function that copies untransformed mesh X/Y values into the
                   ; screen-coordinate buffers.  Could be used for a static 2D effect, like a
                   ; background that doesn't move.
                   ; 
1bd6: a6 45                        ldx     ]first_line       ;3
1bd8: bd 00 08     UnusedCopyLoop  lda     ShapeXCoords,x    ;4+
1bdb: 18                           clc                       ;2
1bdc: 65 1d                        adc     ]ystart           ;3
1bde: 9d 00 0e     _unused_mod0    sta     XCoord0_0E,x      ;5
1be1: a5 1e                        lda     ]xend             ;3
1be3: 38                           sec                       ;2
1be4: fd 00 09                     sbc     ShapeYCoords,x    ;4+
1be7: 9d 00 0f     _unused_mod1    sta     YCoord0_0F,x      ;5
1bea: e8                           inx                       ;2
1beb: e4 46                        cpx     ]last_line        ;3
1bed: d0 e9                        bne     UnusedCopyLoop    ;2+
1bef: 60                           rts                       ;6

                   ; Current hi-res page.
                   ; 
                   ; $00 = draw page 1, show page 2
                   ; $FF = draw page 2, show page 1
1bf0: ff           CurPage         dfb     $ff

                   ; 
                   ; Switch to the other hi-res page.
                   ; 
1bf1: ad f0 1b     SwapPage        lda     CurPage           ;4
1bf4: 49 ff                        eor     #$ff              ;2  flip to other page
1bf6: 8d f0 1b                     sta     CurPage           ;4
1bf9: f0 0b                        beq     DrawOnPage1       ;3+
1bfb: 8d 54 c0                     sta     TXTPAGE1          ;4  draw on page 2, show page 1
1bfe: a9 40                        lda     #$40              ;2
1c00: a2 10                        ldx     #>XCoord1_10      ;2
1c02: a0 11                        ldy     #>YCoord1_11      ;2
1c04: d0 09                        bne     L1C0F             ;3

1c06: 8d 55 c0     DrawOnPage1     sta     TXTPAGE2          ;4  draw on page 1, show page 2
1c09: a9 20                        lda     #$20              ;2
1c0b: a2 0e                        ldx     #>XCoord0_0E      ;2
1c0d: a0 0f                        ldy     #>YCoord0_0F      ;2
                   ; Save the hi-res page, and modify the instructions that read from or write data
                   ; to the transformed point arrays.
1c0f: 85 18        L1C0F           sta     ]hpage            ;3
1c11: 8e 08 1a                     stx     _0E_or_10_1+2     ;4
1c14: 8e 16 1a                     stx     _0E_or_10_2+2     ;4
1c17: 8e 26 1e                     stx     _0E_or_10_3+2     ;4
1c1a: 8e e0 1b                     stx     _unused_mod0+2    ;4
1c1d: 8c 0d 1a                     sty     _0F_or_11_1+2     ;4
1c20: 8c 1b 1a                     sty     _0F_or_11_2+2     ;4
1c23: 8c 2e 1e                     sty     _0F_or_11_3+2     ;4
1c26: 8c e9 1b                     sty     _unused_mod1+2    ;4
1c29: 60                           rts                       ;6

                   ; Unreferenced junk
1c2a: f8 1a 8c 06+                 .junk   12

                   ; Coordinate transformation function.  Transforms all points in a single object.
                   ; 
                   ; On entry:
                   ;  1c = scale (00-0f)
                   ;  1d = xc (00-ff)
                   ;  1e = yc (00-bf)
                   ;  1f = zrot (00-1b)
                   ;  3c = yrot (00-1b)
                   ;  3d = xrot (00-1b)
                   ;  45 = index of first point to transform
                   ;  46 = index of last point to transform
                   ; 
                   ; Rotation values greater than $1B, and scale factors greater than $0F, disable
                   ; the calculation.  This has the same effect as a rotation value of 0 or a scale
                   ; of 15, but is more efficient, because this uses self-modifying code to skip
                   ; the computation entirely.
                   ; 
                   • Clear variables
                   ]xc             equ     $19    {addr/1}   ;transformed X coordinate
                   ]yc             equ     $1a    {addr/1}   ;transformed Y coordinate
                   ]zc             equ     $1b    {addr/1}   ;transformed Z coordinate
                   ]scale          equ     $1c    {addr/1}   ;$00-0F, where $0F is full size
                   ]xposn          equ     $1d    {addr/1}   ;X coordinate (0-255)
                   ]yposn          equ     $1e    {addr/1}   ;Y coordinate (0-191)
                   ]zrot           equ     $1f    {addr/1}   ;Z rotation ($00-1B)
                   ]yrot           equ     $3c    {addr/1}   ;Y rotation ($00-1B)
                   ]xrot           equ     $3d    {addr/1}   ;X rotation ($00-1B)
                   ]rot_tmp        equ     $3f    {addr/4}
                   ]out_index      equ     $43    {addr/1}
                   ]first_point    equ     $45    {addr/1}
                   ]last_point     equ     $46    {addr/1}

1c36: a6 45        CompTransform   ldx     ]first_point      ;3  get first point index; this stays in X for a while
                   ; Configure Z rotation.
1c38: a4 1f                        ldy     ]zrot             ;3
1c3a: c0 1c                        cpy     #$1c              ;2  valid rotation value?
1c3c: 90 07                        bcc     ConfigZrot        ;2+ yes, configure
1c3e: a9 65                        lda     #<DoYrot          ;2  no, modify code to skip Z-rot
1c40: 8d 1a 1d                     sta     _BeforeZrot+1     ;4
1c43: d0 29                        bne     NoZrot            ;3

1c45: a9 1c        ConfigZrot      lda     #<DoZrot          ;2
1c47: 8d 1a 1d                     sta     _BeforeZrot+1     ;4
1c4a: b9 40 0d                     lda     RotIndexLo_sin,y  ;4+
1c4d: 8d 45 1d                     sta     _zrotLS1+1        ;4
1c50: 8d 5a 1d                     sta     _zrotLS2+1        ;4
1c53: b9 5c 0d                     lda     RotIndexHi_sin,y  ;4+
1c56: 8d 49 1d                     sta     _zrotHS1+1        ;4
1c59: 8d 5e 1d                     sta     _zrotHS2+1        ;4
1c5c: b9 78 0d                     lda     RotIndexLo_cos,y  ;4+
1c5f: 8d 39 1d                     sta     _zrotLC1+1        ;4
1c62: 8d 4e 1d                     sta     _zrotLC2+1        ;4
1c65: b9 94 0d                     lda     RotIndexHi_cos,y  ;4+
1c68: 8d 3d 1d                     sta     _zrotHC1+1        ;4
1c6b: 8d 52 1d                     sta     _zrotHC2+1        ;4
                   ; Configure Y rotation.
1c6e: a4 3c        NoZrot          ldy     ]yrot             ;3
1c70: c0 1c                        cpy     #$1c              ;2  valid rotation value?
1c72: 90 07                        bcc     ConfigYrot        ;2+ yes, configure
1c74: a9 ae                        lda     #<DoXrot          ;2  no, modify code to skip Y-rot
1c76: 8d 63 1d                     sta     _BeforeYrot+1     ;4
1c79: d0 29                        bne     NoYrot            ;3

1c7b: a9 65        ConfigYrot      lda     #<DoYrot          ;2
1c7d: 8d 63 1d                     sta     _BeforeYrot+1     ;4
1c80: b9 40 0d                     lda     RotIndexLo_sin,y  ;4+
1c83: 8d 8e 1d                     sta     _yrotLS1+1        ;4
1c86: 8d a3 1d                     sta     _yrotLS2+1        ;4
1c89: b9 5c 0d                     lda     RotIndexHi_sin,y  ;4+
1c8c: 8d 92 1d                     sta     _yrotHS1+1        ;4
1c8f: 8d a7 1d                     sta     _yrotHS2+1        ;4
1c92: b9 78 0d                     lda     RotIndexLo_cos,y  ;4+
1c95: 8d 82 1d                     sta     _yrotLC1+1        ;4
1c98: 8d 97 1d                     sta     _yrotLC2+1        ;4
1c9b: b9 94 0d                     lda     RotIndexHi_cos,y  ;4+
1c9e: 8d 86 1d                     sta     _yrotHC1+1        ;4
1ca1: 8d 9b 1d                     sta     _yrotHC2+1        ;4
                   ; Configure X rotation.
1ca4: a4 3d        NoYrot          ldy     ]xrot             ;3
1ca6: c0 1c                        cpy     #$1c              ;2  valid rotation value?
1ca8: 90 07                        bcc     ConfigXrot        ;2+ yes, configure
1caa: a9 f7                        lda     #<DoScale         ;2  no, modify code to skip X-rot
1cac: 8d ac 1d                     sta     _BeforeXrot+1     ;4
1caf: d0 29                        bne     ConfigScale       ;3

1cb1: a9 ae        ConfigXrot      lda     #<DoXrot          ;2
1cb3: 8d ac 1d                     sta     _BeforeXrot+1     ;4
1cb6: b9 40 0d                     lda     RotIndexLo_sin,y  ;4+
1cb9: 8d d7 1d                     sta     _xrotLS1+1        ;4
1cbc: 8d ec 1d                     sta     _xrotLS2+1        ;4
1cbf: b9 5c 0d                     lda     RotIndexHi_sin,y  ;4+
1cc2: 8d db 1d                     sta     _xrotHS1+1        ;4
1cc5: 8d f0 1d                     sta     _xrotHS2+1        ;4
1cc8: b9 78 0d                     lda     RotIndexLo_cos,y  ;4+
1ccb: 8d cb 1d                     sta     _xrotLC1+1        ;4
1cce: 8d e0 1d                     sta     _xrotLC2+1        ;4
1cd1: b9 94 0d                     lda     RotIndexHi_cos,y  ;4+
1cd4: 8d cf 1d                     sta     _xrotHC1+1        ;4
1cd7: 8d e4 1d                     sta     _xrotHC2+1        ;4
                   ; Configure scaling.
1cda: a4 1c        ConfigScale     ldy     ]scale            ;3
1cdc: c0 10                        cpy     #$10              ;2  valid scale value?
1cde: 90 0c                        bcc     SetScale          ;2+ yes, configure it
1ce0: a9 1d                        lda     #<DoTranslate     ;2  no, skip it
1ce2: 8d f5 1d                     sta     _BeforeScale+1    ;4
1ce5: a9 1e                        lda     #>DoTranslate     ;2
1ce7: 8d f6 1d                     sta     _BeforeScale+2    ;4
1cea: d0 1c                        bne     TransformLoop     ;4

1cec: a9 f7        SetScale        lda     #<DoScale         ;2
1cee: 8d f5 1d                     sta     _BeforeScale+1    ;4
1cf1: a9 1d                        lda     #>DoScale         ;2
1cf3: 8d f6 1d                     sta     _BeforeScale+2    ;4
1cf6: b9 b0 0d                     lda     ScaleIndexLo,y    ;4+ $00, $10, $20, ... $F0
1cf9: 8d 02 1e                     sta     _scaleLX+1        ;4
1cfc: 8d 15 1e                     sta     _scaleLY+1        ;4
1cff: b9 c0 0d                     lda     ScaleIndexHi,y    ;4+ $00, $01, $02, ... $0F
1d02: 8d 06 1e                     sta     _scaleHX+1        ;4
1d05: 8d 19 1e                     sta     _scaleHY+1        ;4
                   ; 
                   ; Now that we've got the code modified, perform the computation for all points
                   ; in the object.
                   ; 
1d08: bd 00 08     TransformLoop   lda     ShapeXCoords,x    ;4+
1d0b: 85 19                        sta     ]xc               ;3
1d0d: bd 00 09                     lda     ShapeYCoords,x    ;4+
1d10: 85 1a                        sta     ]yc               ;3
1d12: bd 00 0a                     lda     ShapeZCoords,x    ;4+
1d15: 85 1b                        sta     ]zc               ;3
1d17: 86 43                        stx     ]out_index        ;3  save for later
1d19: 4c 1c 1d     _BeforeZrot     jmp     DoZrot            ;3

1d1c: a5 19        DoZrot          lda     ]xc               ;3  rotating about Z, so we need to update X/Y coords
1d1e: 29 0f                        and     #$0f              ;2  split X/Y into nibbles
1d20: 85 3f                        sta     ]rot_tmp          ;3
1d22: a5 19                        lda     ]xc               ;3
1d24: 29 f0                        and     #$f0              ;2
1d26: 85 40                        sta     ]rot_tmp+1        ;3
1d28: a5 1a                        lda     ]yc               ;3
1d2a: 29 0f                        and     #$0f              ;2
1d2c: 85 41                        sta     ]rot_tmp+2        ;3
1d2e: a5 1a                        lda     ]yc               ;3
1d30: 29 f0                        and     #$f0              ;2
1d32: 85 42                        sta     ]rot_tmp+3        ;3
1d34: a4 3f                        ldy     ]rot_tmp          ;3  transform X coord
1d36: a6 40                        ldx     ]rot_tmp+1        ;3  XC = X * cos(theta) - Y * sin(theta)
1d38: b9 00 12     _zrotLC1        lda     RotTabLo,y        ;4+
1d3b: 18                           clc                       ;2
1d3c: 7d 00 13     _zrotHC1        adc     RotTabHi,x        ;4+
1d3f: a4 41                        ldy     ]rot_tmp+2        ;3
1d41: a6 42                        ldx     ]rot_tmp+3        ;3
1d43: 38                           sec                       ;2
1d44: f9 00 12     _zrotLS1        sbc     RotTabLo,y        ;4+
1d47: 38                           sec                       ;2
1d48: fd 00 13     _zrotHS1        sbc     RotTabHi,x        ;4+
1d4b: 85 19                        sta     ]xc               ;3  save updated coord
1d4d: b9 00 12     _zrotLC2        lda     RotTabLo,y        ;4+ transform Y coord
1d50: 18                           clc                       ;2  YC = Y * cos(theta) + X * sin(theta)
1d51: 7d 00 13     _zrotHC2        adc     RotTabHi,x        ;4+
1d54: a4 3f                        ldy     ]rot_tmp          ;3
1d56: a6 40                        ldx     ]rot_tmp+1        ;3
1d58: 18                           clc                       ;2
1d59: 79 00 12     _zrotLS2        adc     RotTabLo,y        ;4+
1d5c: 18                           clc                       ;2
1d5d: 7d 00 13     _zrotHS2        adc     RotTabHi,x        ;4+
1d60: 85 1a                        sta     ]yc               ;3  save updated coord
1d62: 4c 65 1d     _BeforeYrot     jmp     DoYrot            ;3

1d65: a5 19        DoYrot          lda     ]xc               ;3  rotating about Y, so update X/Z
1d67: 29 0f                        and     #$0f              ;2
1d69: 85 3f                        sta     ]rot_tmp          ;3
1d6b: a5 19                        lda     ]xc               ;3
1d6d: 29 f0                        and     #$f0              ;2
1d6f: 85 40                        sta     ]rot_tmp+1        ;3
1d71: a5 1b                        lda     ]zc               ;3
1d73: 29 0f                        and     #$0f              ;2
1d75: 85 41                        sta     ]rot_tmp+2        ;3
1d77: a5 1b                        lda     ]zc               ;3
1d79: 29 f0                        and     #$f0              ;2
1d7b: 85 42                        sta     ]rot_tmp+3        ;3
1d7d: a4 3f                        ldy     ]rot_tmp          ;3
1d7f: a6 40                        ldx     ]rot_tmp+1        ;3
1d81: b9 00 12     _yrotLC1        lda     RotTabLo,y        ;4+
1d84: 18                           clc                       ;2
1d85: 7d 00 13     _yrotHC1        adc     RotTabHi,x        ;4+
1d88: a4 41                        ldy     ]rot_tmp+2        ;3
1d8a: a6 42                        ldx     ]rot_tmp+3        ;3
1d8c: 38                           sec                       ;2
1d8d: f9 00 12     _yrotLS1        sbc     RotTabLo,y        ;4+
1d90: 38                           sec                       ;2
1d91: fd 00 13     _yrotHS1        sbc     RotTabHi,x        ;4+
1d94: 85 19                        sta     ]xc               ;3
1d96: b9 00 12     _yrotLC2        lda     RotTabLo,y        ;4+
1d99: 18                           clc                       ;2
1d9a: 7d 00 13     _yrotHC2        adc     RotTabHi,x        ;4+
1d9d: a4 3f                        ldy     ]rot_tmp          ;3
1d9f: a6 40                        ldx     ]rot_tmp+1        ;3
1da1: 18                           clc                       ;2
1da2: 79 00 12     _yrotLS2        adc     RotTabLo,y        ;4+
1da5: 18                           clc                       ;2
1da6: 7d 00 13     _yrotHS2        adc     RotTabHi,x        ;4+
1da9: 85 1b                        sta     ]zc               ;3
1dab: 4c ae 1d     _BeforeXrot     jmp     DoXrot            ;3

1dae: a5 1b        DoXrot          lda     ]zc               ;3  rotating about X, so update Z/Y
1db0: 29 0f                        and     #$0f              ;2
1db2: 85 3f                        sta     ]rot_tmp          ;3
1db4: a5 1b                        lda     ]zc               ;3
1db6: 29 f0                        and     #$f0              ;2
1db8: 85 40                        sta     ]rot_tmp+1        ;3
1dba: a5 1a                        lda     ]yc               ;3
1dbc: 29 0f                        and     #$0f              ;2
1dbe: 85 41                        sta     ]rot_tmp+2        ;3
1dc0: a5 1a                        lda     ]yc               ;3
1dc2: 29 f0                        and     #$f0              ;2
1dc4: 85 42                        sta     ]rot_tmp+3        ;3
1dc6: a4 3f                        ldy     ]rot_tmp          ;3
1dc8: a6 40                        ldx     ]rot_tmp+1        ;3
1dca: b9 00 12     _xrotLC1        lda     RotTabLo,y        ;4+
1dcd: 18                           clc                       ;2
1dce: 7d 00 13     _xrotHC1        adc     RotTabHi,x        ;4+
1dd1: a4 41                        ldy     ]rot_tmp+2        ;3
1dd3: a6 42                        ldx     ]rot_tmp+3        ;3
1dd5: 38                           sec                       ;2
1dd6: f9 00 12     _xrotLS1        sbc     RotTabLo,y        ;4+
1dd9: 38                           sec                       ;2
1dda: fd 00 13     _xrotHS1        sbc     RotTabHi,x        ;4+
1ddd: 85 1b                        sta     ]zc               ;3
1ddf: b9 00 12     _xrotLC2        lda     RotTabLo,y        ;4+
1de2: 18                           clc                       ;2
1de3: 7d 00 13     _xrotHC2        adc     RotTabHi,x        ;4+
1de6: a4 3f                        ldy     ]rot_tmp          ;3
1de8: a6 40                        ldx     ]rot_tmp+1        ;3
1dea: 18                           clc                       ;2
1deb: 79 00 12     _xrotLS2        adc     RotTabLo,y        ;4+
1dee: 18                           clc                       ;2
1def: 7d 00 13     _xrotHS2        adc     RotTabHi,x        ;4+
1df2: 85 1a                        sta     ]yc               ;3
1df4: 4c f7 1d     _BeforeScale    jmp     DoScale           ;3

                   ; Apply scaling.  Traditionally this is applied before rotation.
1df7: a5 19        DoScale         lda     ]xc               ;3  scale the X coordinate
1df9: 29 f0                        and     #$f0              ;2
1dfb: aa                           tax                       ;2
1dfc: a5 19                        lda     ]xc               ;3
1dfe: 29 0f                        and     #$0f              ;2
1e00: a8                           tay                       ;2
1e01: b9 00 18     _scaleLX        lda     ScaleTabLo,y      ;4+
1e04: 18                           clc                       ;2
1e05: 7d 00 19     _scaleHX        adc     ScaleTabHi,x      ;4+
1e08: 85 19                        sta     ]xc               ;3
1e0a: a5 1a                        lda     ]yc               ;3  scale the Y coordinate
1e0c: 29 f0                        and     #$f0              ;2
1e0e: aa                           tax                       ;2
1e0f: a5 1a                        lda     ]yc               ;3
1e11: 29 0f                        and     #$0f              ;2
1e13: a8                           tay                       ;2
1e14: b9 00 18     _scaleLY        lda     ScaleTabLo,y      ;4+
1e17: 18                           clc                       ;2
1e18: 7d 00 19     _scaleHY        adc     ScaleTabHi,x      ;4+
1e1b: 85 1a                        sta     ]yc               ;3
                   ; 
                   ; Apply translation.
                   ; 
                   ; This is the final step, so the result is written to the transformed-point
                   ; arrays.
                   ; 
1e1d: a6 43        DoTranslate     ldx     ]out_index        ;3
1e1f: a5 19                        lda     ]xc               ;3
1e21: 18                           clc                       ;2
1e22: 65 1d                        adc     ]xposn            ;3  object center in screen coordinates
1e24: 9d 00 0e     _0E_or_10_3     sta     XCoord0_0E,x      ;5
1e27: a5 1e                        lda     ]yposn            ;3
1e29: 38                           sec                       ;2
1e2a: e5 1a                        sbc     ]yc               ;3
1e2c: 9d 00 0f     _0F_or_11_3     sta     YCoord0_0F,x      ;5
1e2f: e8                           inx                       ;2
1e30: e4 46                        cpx     ]last_point       ;3  done?
1e32: f0 03                        beq     TransformDone     ;2+ yes, bail
1e34: 4c 08 1d                     jmp     TransformLoop     ;3

1e37: 60           TransformDone   rts                       ;6

1e38: ad           SavedShapeIndex dfb     $ad               ;holds shape index while we work

                   ********************************************************************************
                   * CRUNCH/CRNCH% entry point                                                    *
                   *                                                                              *
                   * For each object, do what CODE%(n) tells us to:                               *
                   *                                                                              *
                   *  0 - do nothing                                                              *
                   *  1 - transform and draw                                                      *
                   *  2 - erase, transform, draw                                                  *
                   *  3 - erase                                                                   *
                   ********************************************************************************
                   ]first_line     equ     $45    {addr/1}
                   ]last_line      equ     $46    {addr/1}

1e39: 20 39 1f     CRUNCH          jsr     Setup             ;6  find Applesoft arrays
                   ; 
                   ; First pass: erase old shapes
1e3c: ad fd 07                     lda     NumObjects        ;4  number of defined objects
1e3f: 0a                           asl     A                 ;2  * 2
1e40: aa                           tax                       ;2  use as index
1e41: ca           ShapeLoop       dex                       ;2
1e42: ca                           dex                       ;2
1e43: 30 25                        bmi     Transform         ;2+ done
1e45: bd 08 60     _codeAR1        lda     CODE_arr,x        ;4+
1e48: c9 02                        cmp     #$02              ;2  2 or 3?
1e4a: 90 f5                        bcc     ShapeLoop         ;2+ no, move on
1e4c: 8e 38 1e                     stx     SavedShapeIndex   ;4
1e4f: 8a                           txa                       ;2
1e50: 4a                           lsr     A                 ;2
1e51: aa                           tax                       ;2
1e52: bd 20 0d                     lda     FirstLineIndex,x  ;4+
1e55: 85 45                        sta     ]first_line       ;3
1e57: bd 30 0d                     lda     LastLineIndex,x   ;4+
1e5a: 85 46                        sta     ]last_line        ;3
1e5c: c5 45                        cmp     ]first_line       ;3  is number of lines <= 0?
1e5e: 90 05                        bcc     NoLines1          ;2+
1e60: f0 03                        beq     NoLines1          ;2+ yes, skip draw
1e62: 20 00 1a                     jsr     DrawLineListEOR   ;6  erase with EOR version, regardless of config
1e65: ae 38 1e     NoLines1        ldx     SavedShapeIndex   ;4
1e68: 10 d7                        bpl     ShapeLoop         ;3  ...always

                   ; 
                   ; Second pass: transform shapes
                   ; 
1e6a: ad fd 07     Transform       lda     NumObjects        ;4
1e6d: 0a                           asl     A                 ;2
1e6e: aa                           tax                       ;2
1e6f: ca           TransLoop       dex                       ;2
1e70: ca                           dex                       ;2
1e71: 30 56                        bmi     DrawNew           ;2+
1e73: bd 08 60     _codeAR2        lda     CODE_arr,x        ;4+
1e76: f0 f7                        beq     TransLoop         ;2+ is it zero or three?
1e78: c9 03                        cmp     #$03              ;2
1e7a: f0 f3                        beq     TransLoop         ;2+ yes, we only draw on 1 or 2
                   ; Extract the scale, X/Y, and rotation values out of the arrays and copy them to
                   ; zero-page locations.
1e7c: bd 7d 60     _scaleAR        lda     SCALE_arr,x       ;4+
1e7f: 85 1c                        sta     ]scale            ;3
1e81: bd 2f 60     _xAR            lda     X_arr,x           ;4+
1e84: 85 1d                        sta     ]xposn            ;3
1e86: bd 56 60     _yAR            lda     Y_arr,x           ;4+
1e89: 85 1e                        sta     ]yposn            ;3
1e8b: bd f2 60     _zrotAR         lda     ZROT_arr,x        ;4+
1e8e: 85 1f                        sta     ]zrot             ;3
1e90: bd cb 60     _yrotAR         lda     YROT_arr,x        ;4+
1e93: 85 3c                        sta     ]yrot             ;3
1e95: bd a4 60     _xrotAR         lda     XROT_arr,x        ;4+
1e98: 85 3d                        sta     ]xrot             ;3
1e9a: 8e 38 1e                     stx     SavedShapeIndex   ;4  save this off
1e9d: 8a                           txa                       ;2
1e9e: 4a                           lsr     A                 ;2  convert to 1x index
1e9f: aa                           tax                       ;2
1ea0: bd 00 0d                     lda     FirstPointIndex,x ;4+
1ea3: 85 45                        sta     ]first_line       ;3  (actually first_point)
1ea5: bd 10 0d                     lda     LastPointIndex,x  ;4+
1ea8: 85 46                        sta     ]last_line        ;3
1eaa: c5 45                        cmp     ]first_line       ;3  is number of points <= 0?
1eac: 90 05                        bcc     NoPoints          ;2+
1eae: f0 03                        beq     NoPoints          ;2+ yes, skip transform
1eb0: 20 36 1c                     jsr     CompTransform     ;6  transform all points
1eb3: ae 38 1e     NoPoints        ldx     SavedShapeIndex   ;4
1eb6: a5 19                        lda     ]xc               ;3
1eb8: 18                           clc                       ;2
1eb9: 65 1d                        adc     ]xposn            ;3
1ebb: 9d 19 61     _sxAR           sta     SX_arr,x          ;5
1ebe: a5 1e                        lda     ]yposn            ;3
1ec0: 38                           sec                       ;2
1ec1: e5 1a                        sbc     ]yc               ;3
1ec3: 9d 40 61     _syAR           sta     SY_arr,x          ;5
1ec6: 4c 6f 1e                     jmp     TransLoop         ;3

                   ; 
                   ; Third pass: draw shapes
                   ; 
1ec9: ad fd 07     DrawNew         lda     NumObjects        ;4
1ecc: 0a                           asl     A                 ;2
1ecd: aa                           tax                       ;2
1ece: ca           L1ECE           dex                       ;2
1ecf: ca                           dex                       ;2
1ed0: 30 27                        bmi     L1EF9             ;2+
1ed2: bd 08 60     _codeAR3        lda     CODE_arr,x        ;4+ is it 0 or 3?
1ed5: f0 f7                        beq     L1ECE             ;2+
1ed7: c9 03                        cmp     #$03              ;2
1ed9: f0 f3                        beq     L1ECE             ;2+ yup, no draw
1edb: 8e 38 1e                     stx     SavedShapeIndex   ;4  save index
1ede: 8a                           txa                       ;2
1edf: 4a                           lsr     A                 ;2  convert it back to 1x index
1ee0: aa                           tax                       ;2
1ee1: bd 20 0d                     lda     FirstLineIndex,x  ;4+ draw all the lines in the shape
1ee4: 85 45                        sta     ]first_line       ;3
1ee6: bd 30 0d                     lda     LastLineIndex,x   ;4+
1ee9: 85 46                        sta     ]last_line        ;3
1eeb: c5 45                        cmp     ]first_line       ;3  is number of lines <= 0?
1eed: 90 05                        bcc     NoLines2          ;2+
1eef: f0 03                        beq     NoLines2          ;2+ yes, skip draw
1ef1: 20 eb 1a                     jsr     DrawLineList      ;6  draw all lines
1ef4: ae 38 1e     NoLines2        ldx     SavedShapeIndex   ;4
1ef7: 10 d5                        bpl     L1ECE             ;3  ...always

1ef9: 4c f1 1b     L1EF9           jmp     SwapPage          ;3

                   ********************************************************************************
                   * RESET entry point                                                            *
                   *                                                                              *
                   * Zeroes out the CODE% array, erases both hi-res screens, and enables display  *
                   * of the primary hi-res page.                                                  *
                   ********************************************************************************
1efc: 20 39 1f     RESET           jsr     Setup             ;6  sets A=0, Y=$1E
1eff: 99 08 60     _codeAR4        sta     CODE_arr,y        ;5  zero out CODE%
1f02: 88                           dey                       ;2
1f03: 10 fa                        bpl     _codeAR4          ;3+
1f05: 20 0f 1f                     jsr     CLEAR             ;6
1f08: 20 f1 1b                     jsr     SwapPage          ;6
1f0b: 20 f1 1b                     jsr     SwapPage          ;6
1f0e: 60                           rts                       ;6

                   ********************************************************************************
                   * CLEAR/CLR% entry point                                                       *
                   *                                                                              *
                   * Clears both hi-res pages.                                                    *
                   ********************************************************************************
                   • Clear variables
                   ]ptr1           equ     $1a    {addr/2}
                   ]ptr2           equ     $1c    {addr/2}

1f0f: a9 20        CLEAR           lda     #$20              ;2  hi-res page 1
1f11: 85 1b                        sta     ]ptr1+1           ;3
1f13: a9 40                        lda     #$40              ;2  hi-res page 2
1f15: 85 1d                        sta     ]ptr2+1           ;3
1f17: a0 00                        ldy     #$00              ;2
1f19: 84 1a                        sty     ]ptr1             ;3
1f1b: 84 1c                        sty     ]ptr2             ;3
1f1d: 98           L1F1D           tya                       ;2
1f1e: 91 1a        L1F1E           sta     (]ptr1),y         ;6  erase both pages
1f20: 91 1c                        sta     (]ptr2),y         ;6
1f22: c8                           iny                       ;2
1f23: d0 f9                        bne     L1F1E             ;2+
1f25: e6 1b                        inc     ]ptr1+1           ;5
1f27: e6 1d                        inc     ]ptr2+1           ;5
1f29: a5 1b                        lda     ]ptr1+1           ;3  (could hold counter in X-reg)
1f2b: 29 3f                        and     #$3f              ;2
1f2d: d0 ee                        bne     L1F1D             ;2+
                   ********************************************************************************
                   * HIRES entry point                                                            *
                   *                                                                              *
                   * Displays primary hi-res page.                                                *
                   ********************************************************************************
1f2f: 8d 57 c0     HI_RES          sta     HIRES             ;4
1f32: 8d 52 c0                     sta     MIXCLR            ;4
1f35: 8d 50 c0                     sta     TXTCLR            ;4
1f38: 60                           rts                       ;6

                   ; Locate Applesoft arrays.  This assumes the arrays are declared first, and in
                   ; the correct order, so that the start can be found at a fixed offset from the
                   ; BASIC array table pointer.
                   ; 
                   ; 1 DIM CODE%(15), X%(15), Y%(15), SCALE%(15), XROT%(15), YROT%(15), ZROT%(15),
                   ; SX%(15), SY%(15)
                   ; 
                   ; If you generate the module for Integer BASIC, this is the entry point for
                   ; MISSILE (7993).
1f39: a5 6b        Setup           lda     BAS_ARYTAB        ;3  CODE% is at +$0008
1f3b: 18                           clc                       ;2
1f3c: 69 08                        adc     #$08              ;2
1f3e: aa                           tax                       ;2
1f3f: a5 6c                        lda     BAS_ARYTAB+1      ;3
1f41: 69 00                        adc     #$00              ;2
1f43: 8e 46 1e                     stx     _codeAR1+1        ;4
1f46: 8d 47 1e                     sta     _codeAR1+2        ;4
1f49: 8e 74 1e                     stx     _codeAR2+1        ;4
1f4c: 8d 75 1e                     sta     _codeAR2+2        ;4
1f4f: 8e d3 1e                     stx     _codeAR3+1        ;4
1f52: 8d d4 1e                     sta     _codeAR3+2        ;4
1f55: 8e 00 1f                     stx     _codeAR4+1        ;4
1f58: 8d 01 1f                     sta     _codeAR4+2        ;4
1f5b: a5 6b                        lda     BAS_ARYTAB        ;3  X% is at +$002F
1f5d: 18                           clc                       ;2
1f5e: 69 2f                        adc     #$2f              ;2
1f60: aa                           tax                       ;2
1f61: a5 6c                        lda     BAS_ARYTAB+1      ;3
1f63: 69 00                        adc     #$00              ;2
1f65: 8e 82 1e                     stx     _xAR+1            ;4
1f68: 8d 83 1e                     sta     _xAR+2            ;4
1f6b: a5 6b                        lda     BAS_ARYTAB        ;3  Y% is at +$0056
1f6d: 18                           clc                       ;2
1f6e: 69 56                        adc     #$56              ;2
1f70: aa                           tax                       ;2
1f71: a5 6c                        lda     BAS_ARYTAB+1      ;3
1f73: 69 00                        adc     #$00              ;2
1f75: 8e 87 1e                     stx     _yAR+1            ;4
1f78: 8d 88 1e                     sta     _yAR+2            ;4
1f7b: a5 6b                        lda     BAS_ARYTAB        ;3  SCALE% is at + $007D
1f7d: 18                           clc                       ;2
1f7e: 69 7d                        adc     #$7d              ;2
1f80: aa                           tax                       ;2
1f81: a5 6c                        lda     BAS_ARYTAB+1      ;3
1f83: 69 00                        adc     #$00              ;2
1f85: 8e 7d 1e                     stx     _scaleAR+1        ;4
1f88: 8d 7e 1e                     sta     _scaleAR+2        ;4
1f8b: a5 6b                        lda     BAS_ARYTAB        ;3  XROT% is at +$00A4
1f8d: 18                           clc                       ;2
1f8e: 69 a4                        adc     #$a4              ;2
1f90: aa                           tax                       ;2
1f91: a5 6c                        lda     BAS_ARYTAB+1      ;3
1f93: 69 00                        adc     #$00              ;2
1f95: 8e 96 1e                     stx     _xrotAR+1         ;4
1f98: 8d 97 1e                     sta     _xrotAR+2         ;4
1f9b: a5 6b                        lda     BAS_ARYTAB        ;3  YROT% is at +$00CB
1f9d: 18                           clc                       ;2
1f9e: 69 cb                        adc     #$cb              ;2
1fa0: aa                           tax                       ;2
1fa1: a5 6c                        lda     BAS_ARYTAB+1      ;3
1fa3: 69 00                        adc     #$00              ;2
1fa5: 8e 91 1e                     stx     _yrotAR+1         ;4
1fa8: 8d 92 1e                     sta     _yrotAR+2         ;4
1fab: a5 6b                        lda     BAS_ARYTAB        ;3  ZROT% is at +$00F2
1fad: 18                           clc                       ;2
1fae: 69 f2                        adc     #$f2              ;2
1fb0: aa                           tax                       ;2
1fb1: a5 6c                        lda     BAS_ARYTAB+1      ;3
1fb3: 69 00                        adc     #$00              ;2
1fb5: 8e 8c 1e                     stx     _zrotAR+1         ;4
1fb8: 8d 8d 1e                     sta     _zrotAR+2         ;4
1fbb: a5 6b                        lda     BAS_ARYTAB        ;3  SX% is at +$0119
1fbd: 18                           clc                       ;2
1fbe: 69 19                        adc     #$19              ;2
1fc0: aa                           tax                       ;2
1fc1: a5 6c                        lda     BAS_ARYTAB+1      ;3
1fc3: 69 01                        adc     #$01              ;2
1fc5: 8e bc 1e                     stx     _sxAR+1           ;4
1fc8: 8d bd 1e                     sta     _sxAR+2           ;4
1fcb: a5 6b                        lda     BAS_ARYTAB        ;3  SY% is at +$0140
1fcd: 18                           clc                       ;2
1fce: 69 40                        adc     #$40              ;2
1fd0: aa                           tax                       ;2
1fd1: a5 6c                        lda     BAS_ARYTAB+1      ;3
1fd3: 69 01                        adc     #$01              ;2
1fd5: 8e c4 1e                     stx     _syAR+1           ;4
1fd8: 8d c5 1e                     sta     _syAR+2           ;4
1fdb: a0 1e                        ldy     #$1e              ;2  Set A and Y for RESET
1fdd: a9 00                        lda     #$00              ;2
1fdf: 60                           rts                       ;6

                   ; Junk; pads binary to end of page.
1fe0: 0e 00 65 38+                 .align  $0100 (32 bytes)

Symbol Table

CLEAR$1f0f
CRUNCH$1e39
HI_RES$1f2f
RESET$1efc
TXTGEN$0300