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