* * tetrattack! * * Mini-3D rendering package * * - Motion in the x-z plane => rotations about one axis only * - Plots to charmap * * SLJ 9/01 * ; org $1000 org $0ef0 NUMOBJS = 9 temp = $02 dx = $03 dy = $04 point = $05 AUX = $03 ACC = $04 CX = $07 CZ = $08 rottemp = $09 ;0 initially zpoint = $0a ;low byte already set to zero zpoint2 = $0c count = $0e angle = $0f cenx = $14 Py = $40 XCoord = $50 YCoord = $60 theta = $70 cenz = $7d ; $ac taken by screen setup routine ; final value = $10 Pz = $ab base = $ce ;$20 initially ;alternate: ($81) p4000 = $8f ;$4000 initially p6000 = $89 ;$60xx initially p8000 = $9c ;$8000 tagged = $e0 sin = $f7 ;0 low byte cos = $f9 curobj = $ff bitp = $1c00 bitplo = $1d00 bitphi = $1e00 bitphi2 = $1f00 SINTAB = $4000 PROJTAB = $8000 DEY = $88 INY = $c8 INX = $e8 ADC = $65 STA = $85 start sta $8f ;set up p4000 * * Set up VIC * sta $d021 sta $0286 ;clear color jsr $e544 ;clr scr lda #$18 sta $d018 * * Line drawing tables * ldx #$90 ldy #$7f lda #$01 :l1 sta bitp,y cmp #$80 rol pha tya lsr lsr lsr lsr sta bitphi,y lda #00 sta bitp+128,y ;0 = dont draw ror sta bitplo,y * * Extend sin table to 0..31 * lda sin0,y sta sin0+17,x ;sta sin0+32,x inx pla dey bpl :l1 ;.y=$ff ;.x=$10 * * Set up sin tables * InitRot iny sty p6000 ;rats :( ; ldy #00 ;rats :( ; ; sty temp ;:l3 ldx rottemp ; lda sin0,x ; sta aux ;sin(theta) ; ;:l4 ; ; clc ; jsr MULT8 ;.Y * AUX ; ; AUX*.Y -> ACC,.A (low,hi) 16-bit result ; AUX, .Y unaffected ; .Y can be negative ; :Mult8 sty temp ;dumb multiply ; sty acc ; lda #00 ; tay ;:mloop clc ; adc sin0-$10,x ; bcc :skip ; iny ;:skip dec acc ; bne :mloop ; tya sty acc lda #00 ldy #9 clc :mloop ror ror acc bcc :mul2 ; clc ;dec sin0 table by 1 instead adc sin0-$10,x :mul2 dey bne :mloop ldy temp bpl :pos sec sbc sin0-$10,x :pos sta (p4000),y eor #$ff clc adc #1 STA (p6000),y iny bne :mult8 inx inc p4000+1 inc p6000+1 bpl :mult8 ;to $8000 ;.x=$20 ;.y=0 * * Set up Screen * ; lda #00 ;bah! ; tya :l2a ; pha jsr $e8ea ;scroll up ; pla ;.A = ($AC) ;.X=00 clc ;necessary? :l2 ;set one line sta $0720+12,x inc $db20+12,x inx adc #16 bcc :l2 ; adc #$00 inc $ac cmp #15 bne :l2a :done ;.X=$10 stx $40 ;rats :( ;init Py * * Main program loop: * - get input * - update positions/angles * - render * - swap buffers * MainLoop ; Clear buffer and swap lda base eor #$08 sta base sta zpoint+1 ldy #00 tya ldx #8 :l0 sta (zpoint),y iny bne :l0 inc zpoint+1 dex bne :l0 ; Get Input ; .X=0 lda $dc00 lsr lsr lsr bcs :c1 inc theta :c1 lsr bcs :c2 dec theta :c2 and #$01 sta tagged eor #$01 ora $23c0+6 sta $23c0+6 ;shot fired ; lda $cb ; and #3 ; beq :skip ; lsr ; bcc :inc ; dec theta ; lsr ; bcc :skip ; jsr Forwards ;:inc inc theta ;:skip ObjLoop ; Compute relative center inx stx curobj dec cenz,x ;Update pos lda cenx,x ; sec ; sbc cenx sta Px+4 lda cenz,x ; sbc cenz sta Pz+4 ; Rotate Rot lda theta,x adc theta sta angle lda theta ldx #4 ldy #STA jsr RotProj lda cz sbc #14 ; bmi :skip cmp #125 bcs NoDraw cmp cx bmi NoDraw adc cx bmi NoDraw ; If in view, rotate project & plot dex stx count :loop lda angle ldy #ADC jsr RotProj sta YCoord,X dex bpl :loop ; Plot :ploop ldy count :l2 ldx count dey tya pha jsr DrawLine pla tay bne :l2 dec count bne :ploop ;.y=0 NoDraw ldx curobj ; Update lda tagged,x beq :zip lda cx ora tagged sta tagged,x dfb $2c :zip inc theta,x cpx #NUMOBJS bcc ObjLoop jsr $eb59 ;Swap buffer ;.Y=1 .A=$7F jmp MainLoop * * Line routine * - Draws from L to R * - Forces dx>0 (x1 < x2) * - Numbers are +128 offset, to allow * - DX and DY to be 0..255 for long lines * - Uses same core routine for stepinx * and stepiny by changing variables * * On input: * .X = index into point list, point 1 * .Y = index of point 2 * Pswap sty temp txa tay ldx temp DrawLine lda xcoord,y sec sbc xcoord,x bcc Pswap ;x2 >= x1 sta dx lda ycoord,y sbc ycoord,x ;dy = y2-y1 bcs :posy ldy #DEY eor #$ff adc #1 dfb $2c :posy ldy #INY sta dy cmp dx lda #INX ; bcs stepiny bcs :noswap tya ldy #INX :noswap sty mod5 sta mod4 stepinx ; sta mod5 ; sty mod4 ;INY/DEY lda dy ldy dx bcc mod stepiny ; sta mod4 ; sty mod5 ;iny/dey lda dx ldy dy mod ; sty mod1+1 sty temp sty mod3+1 sta mod2+1 Draw lda ycoord,x sec sbc #64 tay lda xcoord,x sec sbc #64 tax ;mod1 lda #dy lda temp beq done ;no steps! ; sta temp lsr plot pha tya bmi calcline lda bitphi,x ora base sta point+1 lda bitplo,x sta point lda bitp,x beq calcline ora (point),y sta (point),y calcline pla mod2 sbc #dx bcs mod5 mod3 adc #dy mod4 inx mod5 iny dec temp bne plot done rts * * Rotate and project point * * On entry: * .X = index into point list * .A = rotation angle * .Y = ADC/STA for points/centers * CX,CZ = location of object * * On exit: * Points stored in xcoord,x ycoord,x * RotProj AND #$3F ORA #>SINTAB STA sin+1 SBC #$2F ;-3*pi/4 ; ADC #$10 ; AND #$3F ORA #>SINTAB STA cos+1 STY RotM1 STY RotM2 RotProj2 LDY Pz,X LDA (sin),Y PHA LDA (cos),Y LDY Px,X SEC SBC (sin),Y CLC RotM1 ADC CZ STA aux ; LDY Px,X ; LDA (cos),Y ; LDY Pz,X ; CLC ; ADC (sin),Y PLA CLC ADC (cos),Y CLC RotM2 ADC CX JSR Div8 STA XCoord,X LDA Py,X ; JSR Div8 ; STA YCoord,X ; RTS * * Signed division routine * * 64*.A/AUX -> .A * Only valid for .Y/AUX < 1 * .A pos or neg, AUX > 0 * AUX, .X unaffected * DIV8 ; STY ACC ; tya php bpl :pos ;.A just loaded eor #$ff :pos sta acc LDA #0 LDY #14 :DLOOP ASL ACC ROL CMP AUX BCC :DIV2 SBC AUX INC ACC :DIV2 DEY BNE :DLOOP ;RTS lda acc plp bpl :pos2 eor #$ff :pos2 eor #$80 ;+128 offset rts * * Point list * Last point is for relative cx,cz * ;Pz dfb 0,16,0,-16,0 ;Py dfb 16,0,8,0 Px dfb 0,-4,16,-4 ;note: px+4 intrudes on table below * * 128*sin(t), t=0..15 * * Table must be at end of code! * ;sin0 dfb 0,13,25,37,49,60,71,81 ; dfb 91,99,106,113 ; dfb 118,122,126,127,128 ;sin0 dfb 0,25,50,74,98,120,142,162 ; dfb 180,197,212,225,236,244,250,254,255 sin0 dfb 0,24,49,73,97,119,141,161 dfb 179,196,211,224,235,243,249,253,255 end