mads 2.1.5 build 3 (21 Feb 22) Source: gr_basics.asm 1 .IF *>0 ;this is a trick that prevents compiling this file alone 2 3 ; Basic hardware-dependent graphics routines. 4 5 ; ----------------------------------------- 6 .proc unPlot 7 ; plots a point and saves the plotted byte, reverts the previous plot. 8 ; ----------------------------------------- 9 ldx #0 ; only one pixel 10 unPlotAfterX 11 stx WhichUnPlot 12 13 ; first remake the oldie 14 lda oldplotL,x 15 sta oldplot 16 lda oldplotH,x 17 sta oldplot+1 18 19 ldy #0 20 lda oldora,x 21 sta (oldplot),y 22 23 24 ; is it not out of the screen ???? 25 cpw ydraw #screenheight 26 jcc CheckX 27 mwa #0 ydraw 28 CheckX 29 cpw xdraw #screenwidth 30 jcs EndOfUnPlot 31 MakeUnPlot 32 ; let's count coordinates taken from xdraw and ydraw 33 lda xdraw 34 and #%11111000 35 ;sta xbyte 36 ;--- 37 ldx ydraw 38 clc 39 adc linetableL,x 40 sta xbyte 41 sta oldplot 42 lda linetableH,x 43 adc xdraw+1 44 sta xbyte+1 45 sta oldplot+1 46 47 lda xdraw 48 and #$7 49 tax 50 ldy #0 51 52 lda color 53 bne ClearUnPlot 54 55 ;plotting here 56 lda (xbyte),y 57 sta OldOraTemp 58 ora bittable,x 59 sta (xbyte),y 60 bne ContinueUnPlot ; allways <>0 61 ClearUnPlot 62 lda (xbyte),y 63 sta OldOraTemp 64 and bittable2,x 65 sta (xbyte),y 66 ContinueUnPlot 67 ldx WhichUnPlot 68 lda OldOraTemp 69 sta oldora,x 70 lda oldplot 71 sta oldplotL,x 72 lda oldplot+1 73 sta oldplotH,x 74 ; and now we must solve the problem of several plots 75 ; in one byte 76 ldx #4 77 ldy WhichUnPlot 78 LetsCheckOverlapping 79 cpx WhichUnPlot 80 beq SkipThisPlot 81 lda oldplotL,x 82 cmp oldplotL,y 83 bne NotTheSamePlot 84 lda oldplotH,x 85 cmp oldplotH,y 86 bne NotTheSamePlot 87 ; the pixel is in the same byte so let's take correct contents 88 lda oldora,x 89 sta oldora,y 90 NotTheSamePlot 91 SkipThisPlot 92 dex 93 bpl LetsCheckOverlapping 94 EndOfUnPlot 95 rts 96 .endp 97 98 ; ----------------------------------------- 99 .proc plot ;plot (xdraw, ydraw, color) 100 ; color == 1 --> put pixel 101 ; color == 0 --> erase pixel 102 ; this is one of the most important routines in the whole 103 ; game. If you are going to speed up the game, start with 104 ; plot - it is used by every single effect starting from explosions 105 ; through line drawing and small text output!!! 106 ; 107 ; Optimized by 0xF (Fox) THXXXX!!! 108 109 ; ----------------------------------------- 110 ; is it not over the screen ??? 111 cpw ydraw #(screenheight+1); changed for one additional line. cpw ydraw #(screenheight-1) 112 bcs unPlot.EndOfUnPlot ;nearest RTS 113 CheckX02 114 cpw xdraw #screenwidth 115 bcs EndOfPlot 116 MakePlot 117 ; let's calculate coordinates from xdraw and ydraw 118 119 lda xdraw 120 and #%11111000 121 ;sta xbyte 122 ;--- 123 ldx ydraw 124 clc 125 adc linetableL,x 126 sta xbyte 127 lda linetableH,x 128 adc xdraw+1 129 sta xbyte+1 130 131 lda xdraw 132 and #$7 133 tax 134 ldy #0 135 lda color 136 bne ClearPlot 137 138 lda (xbyte),y 139 ora bittable,x 140 sta (xbyte),y 141 EndOfPlot 142 rts 143 ClearPlot 144 lda (xbyte),y 145 and bittable2,x 146 sta (xbyte),y 147 rts 148 .endp 149 150 ; ----------------------------------------- 151 .proc point_plot 152 ; ----------------------------------------- 153 ; checks state of the pixel (coordinates in xdraw and ydraw) 154 ; result is in A (zero or appropriate bit is set) 155 156 ; let's calculate coordinates from xdraw and ydraw 157 158 lda xdraw 159 and #%11111000 160 ;sta xbyte 161 ;--- 162 ldx ydraw 163 clc 164 adc linetableL,x 165 sta xbyte 166 lda linetableH,x 167 adc xdraw+1 168 sta xbyte+1 169 170 lda xdraw 171 and #$7 172 tax 173 ldy #0 174 lda (xbyte),y 175 eor #$ff 176 and bittable,x 177 rts 178 .endp 179 ;-------------------------------------------------- 180 .proc drawmountains 181 ;-------------------------------------------------- 182 mwa #0 xdraw 183 mwa #mountaintable modify 184 mva #1 color 185 186 drawmountainsloop 187 ldy #0 188 lda (modify),y 189 cmp #screenheight 190 beq NoMountain 191 sta ydraw 192 sty ydraw+1 193 .IF FASTER_GRAF_PROCS = 1 194 ; there was Drawline proc 195 lda #screenheight 196 sec 197 sbc ydraw 198 sta tempbyte01 199 jsr plot.MakePlot 200 ; X - index in bittable (number of bit) and nothing more (for use) in C64 :) 201 ; jmp IntoDraw ; jumps inside Draw routine 202 ; because one pixel is already plotted (and who cares? :) ) 203 @ 204 lda (xbyte),y 205 and bittable2,x 206 sta (xbyte),y 207 ;IntoDraw 208 inc ydraw 209 lda xdraw 210 and #%11111000 211 ;sta xbyte 212 ;--- 213 ldy ydraw 214 clc 215 adc linetableL,y 216 sta xbyte 217 lda linetableH,y 218 adc xdraw+1 219 sta xbyte+1 220 ldy #0 221 dec tempbyte01 222 bne @- 223 ; end of Drawline proc 224 .ELSE 225 ; there was Drawline proc 226 drawline 227 jsr plot.MakePlot 228 inc ydraw 229 lda ydraw 230 cmp #screenheight 231 bne drawline 232 ; end of Drawline proc 233 .ENDIF 234 NoMountain 235 inw modify 236 inw xdraw 237 cpw xdraw #screenwidth 238 bne drawmountainsloop 239 rts 240 .endp 241 ;-------------------------------------------------- 242 .proc TypeChar 243 ; puts char on the graphics screen 244 ; in: CharCode 245 ; in: left LOWER corner of the char coordinates (xdraw, ydraw) 246 ;-------------------------------------------------- 247 ; char to the table 248 lda CharCode 249 sta fontind 250 lda #$00 251 sta fontind+1 252 ; char intex times 8 253 aslw fontind 254 rolw fontind 255 rolw fontind 256 257 adw fontind #TankFont 258 259 ; and 8 bytes to the table 260 ldy #7 261 CopyChar 262 lda (fontind),y 263 eor #$ff 264 sta char1,y 265 lda #$ff 266 sta char2,y 267 dey 268 bpl CopyChar 269 ; and 8 subsequent bytes as a mask 270 adw fontind #8 271 ldy #7 272 CopyMask 273 lda (fontind),y 274 eor #$ff 275 sta mask1,y 276 lda #$00 277 sta mask2,y 278 dey 279 bpl CopyMask 280 281 .IF FASTER_GRAF_PROCS = 1 282 ; mask preparation and character shifting 283 lda xdraw 284 and #$7 285 tax 286 beq MaskOK00 287 MakeMask00 288 .rept 8 289 lsr mask1+# 290 ror mask2+# 291 .endr 292 sec 293 .rept 8 294 ror char1+# ; in second (and next) lines we have C=1 - one SEC enough 295 ror char2+# 296 .endr 297 dex 298 bne MakeMask00 299 MaskOK00 300 lda ydraw 301 sec 302 sbc #8 303 sta ydraw 304 ; X = 0 ! 305 lda Erase 306 beq CharLoopi ; it works, because x=0 307 lda #$ff 308 ldx #7 309 EmptyChar 310 sta char1,x 311 sta char2,x 312 dex 313 bpl EmptyChar 314 ldx #0 315 CharLoopi 316 ; calculating coordinates from xdraw and ydraw 317 ldy ydraw 318 lda xdraw 319 and #%11111000 320 clc 321 adc linetableL,y 322 sta xbyte 323 lda linetableH,y 324 adc xdraw+1 325 sta xbyte+1 326 ;-- 327 ldy #0 328 lda (xbyte),y 329 ora mask1,x 330 and char1,x 331 sta (xbyte),y 332 ldy #8 333 lda (xbyte),y 334 ora mask2,x 335 and char2,x 336 sta (xbyte),y 337 inc ydraw 338 inx 339 cpx #8 340 bne CharLoopi 341 .ELSE 342 mvx #7 temp ; line counter (Y) 343 CharLoop1 344 mva #7 temp+1 ; pixel counter (X) 345 CharLoop2 346 mva #0 color 347 rol mask1,x 348 bcc NoMaskNoPlot 349 rol char1,x 350 bcs NoPlot 351 MakeCharPlot 352 lda Erase 353 bne ErasingChar 354 inc color 355 ErasingChar 356 NoPlot 357 jsr plot.MakePlot 358 AfterCharPlot 359 inw xdraw 360 ldx temp 361 dec temp+1 362 bpl CharLoop2 363 sec 364 sbw xdraw #8 365 dec ydraw 366 ldx temp 367 dex 368 stx temp 369 bpl CharLoop1 370 clc 371 lda ydraw 372 adc #8 373 sta ydraw 374 bne EndPutChar 375 NoMaskNoPlot 376 rol char1,x 377 jmp AfterCharPlot 378 .ENDIF 379 EndPutChar 380 rts 381 .endp 382 383 ;-------------------------------------------------- 384 .proc PutChar4x4 385 ; puts 4x4 pixels char on the graphics screen 386 ; in: dx, dy (LOWER left corner of the char) 387 ; in: CharCode4x4 (.sbyte) 388 ; in: plot4x4color (0/255) 389 ; all pixels are being drawn 390 ; (empty and not empty) 391 ;-------------------------------------------------- 392 cpw dy #(screenheight-1) 393 jcs TypeChar.EndPutChar ;nearest RTS 394 cpw dy #(4) 395 jcc TypeChar.EndPutChar ;nearest RTS 396 cpw dx #(screenwidth-4) 397 jcs TypeChar.EndPutChar ;nearest RTS 398 ; checks ommited. 399 ; char to the table 400 lda CharCode4x4 401 and #%00000001 402 beq Upper4bits 403 lda #$ff ; better option to check (nibbler4x4 = $00 or $ff) 404 Upper4bits 405 sta nibbler4x4 406 lda CharCode4x4 407 lsr 408 sta fontind 409 lda #$00 410 sta fontind+1 411 412 adw fontind #font4x4 413 414 ; and 4 bytes to the table 415 ldy #0 416 ldx #3 417 CopyChar 418 lda (fontind),y ; Y must be 0 !!!! 419 bit nibbler4x4 420 bpl GetUpper4bits 421 :4 rol 422 GetUpper4bits 423 ora #$0f 424 sta char1,x 425 lda #$ff 426 sta char2,x 427 ; and 4 bytes as a mask 428 lda #$f0 429 sta mask1,x 430 lda #$00 431 sta mask2,x 432 adw fontind #32 ; next byte of 4x4 font 433 dex 434 bpl CopyChar 435 436 .IF FASTER_GRAF_PROCS = 1 437 ; calculating coordinates from xdraw and ydraw 438 mwa dx xbyte 439 440 lda xbyte 441 and #$7 442 sta ybit 443 444 :3 lsrw xbyte ; div 8 445 ; rorw xbyte 446 ; rorw xbyte 447 ;--- 448 ldy xbyte ; horizontal byte offet stored in Y 449 lda dy ; y = y - 3 because left lower. 450 sec 451 sbc #3 452 tax 453 454 lda linetableL,x 455 sta xbyte 456 lda linetableH,x 457 sta xbyte+1 458 ; mask preparation and character shifting 459 ldx ybit 460 beq MaskOK01 461 MakeMask01 462 .rept 4 463 lsr mask1+# 464 ror mask2+# 465 .endr 466 sec 467 .rept 4 468 ror char1+# ; in second (and next) lines we have C=1 - one SEC enough 469 ror char2+# 470 .endr 471 dex 472 bne MakeMask01 473 MaskOK01 474 ldx #0 475 CharLoopi4x4 476 lda (xbyte),y 477 ora mask1,x 478 bit plot4x4color 479 bpl PutInColor0_1 ; only mask - no char 480 and char1,x 481 PutInColor0_1 482 sta (xbyte),y 483 iny 484 lda (xbyte),y 485 ora mask2,x 486 bit plot4x4color 487 bpl PutInColor0_2 ; only mask - no char 488 and char2,x 489 PutInColor0_2 490 sta (xbyte),y 491 dey 492 adw xbyte #screenBytes 493 inx 494 cpx #4 495 bne CharLoopi4x4 496 .ELSE 497 mwa xdraw char2 498 mwa ydraw mask2 499 mva color mask2+2 500 mwa dx xdraw 501 mwa dy ydraw 502 mvx #3 temp ; line counter (Y) 503 CharLoop1 504 mva #3 temp+1 ; pixel counter (X) 505 CharLoop2 506 mva #0 color 507 rol mask1,x 508 bcc NoMaskNoPlot 509 rol char1,x 510 bcs NoPlot 511 MakeCharPlot 512 lda plot4x4color 513 beq ErasingChar 514 inc color 515 ErasingChar 516 NoPlot 517 jsr plot.MakePlot 518 AfterCharPlot 519 inw xdraw 520 ldx temp 521 dec temp+1 522 bpl CharLoop2 523 sec 524 sbw xdraw #4 525 dec ydraw 526 ldx temp 527 dex 528 stx temp 529 bpl CharLoop1 530 mwa char2 xdraw 531 mwa mask2 ydraw 532 mva mask2+2 color 533 bpl EndPut4x4 534 NoMaskNoPlot 535 rol char1,x 536 jmp AfterCharPlot 537 .ENDIF 538 EndPut4x4 539 rts 540 .endp 541 542 ;-------------------------------------------------- 543 .proc ClearScreen 544 ;-------------------------------------------------- 545 mwa #displayC64 temp 546 ldy #0 547 @ lda #$ff 548 sta (temp),y 549 inw temp 550 cpw temp #displayC64+screenheight*screenBytes+1 551 bne @- 552 rts 553 .endp 554 555 ;-------------------------------------------------- 556 .proc GenerateLineTable 557 558 mwa #displayC64 temp 559 mwa #linetableL temp2 560 mwa #linetableH modify 561 ldy #0 562 ldx #0 563 @ lda temp 564 sta (temp2),y 565 lda temp+1 566 sta (modify),y 567 cpx #7 568 bne NotChar 569 ldx #0 570 adw temp #(320-7) 571 jmp next8lines 572 NotChar 573 inw temp 574 inx 575 next8lines 576 iny 577 cpy #screenheight+1 578 bne @- 579 rts 580 .endp 581 ;-------------------------------------------------- 582 .proc SetMainScreen 583 lda #$b ; Grey background and border 584 lda WallsType 585 :4 rol 586 sta $d020 587 sta $d021 588 589 lda $dd00 ; Set video bank to start at 0 590 and #252 591 ora #3 592 sta $dd00 593 lda #$18 594 sta $d018 595 596 ; SwitchVICBank(0) 597 ; SetScreenMemory($2000) 598 SetHiresBitmapMode ; Hires mode on 599 lda #$00 600 sta 53281 601 ; clear color RAM 602 ldx #0 603 @ lda #1 604 sta $d800,x 605 sta $d900,x 606 sta $da00,x 607 sta $db00,x 608 lda #$0f 609 sta $0400,x 610 sta $0500,x 611 sta $0600,x 612 sta $0700,x 613 inx 614 bne @- 615 616 617 rts 618 .endp 619 620 .ENDIF