********************************************************************************
* 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.
;
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. *
* *
********************************************************************************
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)