1include(`z88dk.m4') 2include(`config_private.inc') 3 4; ----------------------------------------------------------------------------- 5; NIRVANA+ ENGINE (32 columns) - by Einar Saukas 6; A Bicolor (Multicolor 8x2) Full-Screen Engine 7; Adapted to z88dk by aralbrec 8; ----------------------------------------------------------------------------- 9 10SECTION NIRVANAP 11 12PUBLIC org_nirvanap 13 14IF ((__NIRVANAP_OPTIONS & 0x3) = 0x3) 15defc org_nirvanap = 56073 16ELSE 17IF (__NIRVANAP_OPTIONS & 0x1) 18defc org_nirvanap = 56085 19ELSE 20defc org_nirvanap = 56323 21ENDIF 22ENDIF 23 24org org_nirvanap 25 26IF ((__NIRVANAP_OPTIONS & 0x3) = 0x3) 27 28; ----------------------------------------------------------------------------- 29; Internal routine that executes NIRVANA_drawT, but taking as long as 30; NIRVANA_drawW. This way, each wide sprite can freely switch between both, 31; without affecting timing. 32; ----------------------------------------------------------------------------- 33 34PUBLIC asm_NIRVANAP_drawTW 35 36asm_NIRVANAP_drawTW: 37; preserve stack pointer 38 ld (exit_wide+1), sp ; delay 20T in 4 bytes 39 ld bc, $2e00 ; delay 10T 40delay_sprite: 41 djnz delay_sprite ; delay 593T 42 jp asm_NIRVANAP_drawT ; execute NIRVANA_drawT with delay 10T 43 44ENDIF 45 46IF (__NIRVANAP_OPTIONS & 0x1) 47 48; ----------------------------------------------------------------------------- 49; Draw wide tile (24x16 pixels) at specified position (in 2345T) 50; 51; Params: 52; A = wide tile index (0-255) 53; D = pixel line (0-200, even values only) 54; E = char column (0-29) 55; 56; Address: 56085 57; 58; IMPORTANT: This routine is disabled by default, recompile this file 59; declaring 'ENABLE_WIDE_DRAW' before calling it!!! 60; 61; WARNING: Computer will crash if an interrupt occurs during execution! 62; ----------------------------------------------------------------------------- 63 64PUBLIC asm_NIRVANAP_drawW 65PUBLIC _NIRVANAP_WIDE_IMAGES 66 67asm_NIRVANAP_drawW: 68; preserve stack pointer 69 ld (exit_wide+1), sp 70 71; calculate screen bitmap lookup address 72 ld h, bitmaps/256 73 ld l, d 74 ld sp, hl 75 76; preserve values 77 ld b, e 78 ld c, h 79 80; calculate tile image address 81 ld h, 0 82 ld l, a 83 ld e, h 84 add hl, hl 85 add hl, hl 86 add hl, hl 87 rra 88 rr e 89 rra 90 rr e 91 ld d, a 92 add hl, de 93defc _NIRVANAP_WIDE_IMAGES = ASMPC + 1 94 ld de, __NIRVANAP_WIDE_IMAGES 95 add hl, de 96 97; draw bitmap lines 98Z88DK_FOR(`LOOP', `1', `8', 99` 100 pop de 101 ld a, e 102 add a, b 103 ld e, a 104 ldi 105 ldi 106 ld a, (hl) 107 ld (de), a 108 inc hl 109 dec e 110 dec e 111 inc d 112 ldi 113 ldi 114 ldi 115') 116; calculate routine attribute addresses 117 ex de, hl 118 ld hl, attribs - bitmaps - 16 119 add hl, sp 120 ld sp, hl 121 122; set routine attribute offsets 123 ld h, deltas/256 124 ld l, b 125 inc l 126 ld a, (hl) 127 ld (wide_1st+2), a 128 inc l 129 ld a, (hl) 130 ld (wide_2nd+2), a 131 inc l 132 ld a, (hl) 133 ld (wide_3rd+2), a 134 135; set routine attributes 136 ld b, 8 137loop_wide: 138 pop ix 139 ld a, (de) 140 inc de 141wide_1st: 142 ld (ix+0), a 143 ld a, (de) 144 inc de 145wide_2nd: 146 ld (ix+0), a 147 ld a, (de) 148 inc de 149wide_3rd: 150 ld (ix+0), a 151 djnz loop_wide 152 153exit_wide: 154; restore stack pointer 155 ld sp, 0 156 ret 157 158ENDIF 159 160; ----------------------------------------------------------------------------- 161; Print a 8x8 character at specified position, afterwards paint it with a 162; provided sequence of 4 attribute values (in 617T for positions matching 163; standard character rows, in 646T otherwise) 164; 165; Params: 166; A = character code (0-255) 167; BC = attributes address 168; D = pixel line (16-192, even values only) 169; E = char column (0-31) 170; 171; Address: 56323 172; ----------------------------------------------------------------------------- 173 174PUBLIC asm_NIRVANAP_printC 175PUBLIC _NIRVANAP_CHAR_TABLE 176 177asm_NIRVANAP_printC: 178; preserve paintC parameters 179 push de 180 push bc 181 182; calculate initial screen bitmap address 183 ld h, bitmaps/256 184 ld l, d 185 ld d, (hl) 186 inc l 187 ld h, (hl) 188 ld l, d 189 ld d, 0 190 add hl, de 191 ex de, hl 192 193; calculate initial character address 194 ld l, a 195 add hl, hl 196 add hl, hl 197 add hl, hl 198defc _NIRVANAP_CHAR_TABLE = ASMPC + 1 199 ld bc, __NIRVANAP_CHAR_TABLE 200 add hl, bc 201 202; draw bitmap lines 203Z88DK_FOR(`LOOP', `1', `3', 204` 205 ld a, (hl) 206 ld (de), a 207 inc hl 208 inc d 209 210 ld a, (hl) 211 ld (de), a 212 inc hl 213 inc d 214 215 ld a, d 216 and 7 217 jr nz, ASMPC+11 218 ld a, e 219 sub -32 220 ld e, a 221 sbc a, a 222 and -8 223 add a, d 224 ld d, a 225') 226 ld a, (hl) 227 ld (de), a 228 inc hl 229 inc d 230 ld a, (hl) 231 ld (de), a 232 233; restore paintC parameters 234 pop bc 235 pop de 236 237; ----------------------------------------------------------------------------- 238; Paint specified 8x8 block with a sequence of 4 attribute values (in 211T) 239; 240; Params: 241; BC = attributes address 242; D = pixel line (16-192, even values only) 243; E = char column (0-31) 244; 245; Address: 56418 246; ----------------------------------------------------------------------------- 247 248PUBLIC asm_NIRVANAP_paintC 249 250asm_NIRVANAP_paintC: 251; calculate initial routine attribute address 252 ld h, 0 253 ld l, d 254 ld d, deltas/256 255 inc e 256 ld a, (de) 257 ld de, attribs 258 add hl, de 259 add a, (hl) 260 ld e, a 261 inc l 262 adc a, (hl) 263 sub e 264 ld d, a 265 ex de, hl 266 267; update attributes 268 ld de, 82 269 270 ld a, (bc) 271 ld (hl), a 272 inc bc 273 add hl, de 274 275 ld a, (bc) 276 ld (hl), a 277 inc bc 278 add hl, de 279 280 ld a, (bc) 281 ld (hl), a 282 inc bc 283 add hl, de 284 285 ld a, (bc) 286 ld (hl), a 287 ret 288 289; ----------------------------------------------------------------------------- 290 291PUBLIC _NIRVANAP_ISR_HOOK 292PUBLIC _NIRVANAP_ISR_STOP 293 294main_engine: 295; preserve all registers 296 push af 297 push bc 298 push de 299 push hl 300 ex af, af' 301 exx 302 push af 303 push bc 304 push de 305 push hl 306 push ix 307 push iy 308 309IF ((__NIRVANAP_OPTIONS & 0x3) = 0x3) 310 311; draw 6 wide tiles 312 ld de, 0 ; D = pixel line, E = char column 313 ld a, 0 ; A = tile 314 call asm_NIRVANAP_drawW 315Z88DK_FOR(`LOOP', `1', `5', 316` 317 ld de, 0 ; D = pixel line, E = char column 318 ld a, 0 ; A = tile 319 call asm_NIRVANAP_drawW+4 320') 321 jr skip_wide 322Z88DK_FOR(`LOOP', `1', `7', 323` 324 nop 325') 326skip_wide: 327Z88DK_FOR(`LOOP', `1', `7', 328` 329 nop ; extra delay 330') 331 332; wait for the raster beam 333 ld b, 55-22 334 jr delay_wide 335delay_128k: 336delay_wide: 337 ld b, 57-22 338 339ELSE 340 341; draw 8 tiles 342Z88DK_FOR(`LOOP', `1', `6', 343` 344 ld de, 0 ; D = pixel line, E = char column 345 ld a, 0 ; A = tile 346 call asm_NIRVANAP_drawT 347') 348Z88DK_FOR(`LOOP', `1', `2', 349` 350 ld de, 0 ; D = pixel line, E = char column 351 ld a, 0 ; A = tile 352 call asm_NIRVANAP_drawT+4 353') 354 355; wait for the raster beam 356 ld b, 55 357 jr delay_128k 358delay_128k: 359 ld b, 57 360 361ENDIF 362 363wait_raster: 364 djnz wait_raster 365 366; preserve stack pointer 367 ld (exit_raster+1), sp 368 369IF (__SPECTRUM & __SPECTRUM_PENTAGON) 370 371; synchronize with raster beam 372; pentagon timing 373 374 ld b, 92 ; extra delay 375 djnz ASMPC ; extra delay 376 djnz ASMPC ; extra delay 377 nop ; extra delay 378 nop ; extra delay 379 jp race_raster 380 381 defs 56693 - org_nirvanap - ASMPC 382 383; race the raster beam to update attributes on screen at the right time 384race_raster: 385 ld a, 4 386Z88DK_FOR(`ROWREPT', `0', eval(__NIRVANAP_TOTAL_ROWS-1), 387` 388Z88DK_FOR(`LINREPT', `0', `3', 389` 390 ld c, a ; extra delay 391 dec c ; extra delay 392 jr nz, ASMPC-1 ; extra delay 393 inc bc ; extra delay 394 395 ld sp, $5822+(ROWREPT*32)+6 ; reference columns 6 and 7 396 ld hl, 0 ; attributes for columns 14 and 15 397 ld de, 0 ; attributes for columns 16 and 17 398 ld bc, 0 ; attributes for columns 18 and 19 399 exx 400 ld hl, 0 ; attributes for columns 0 and 1 401 ld de, 0 ; attributes for columns 4 and 5 402 ld bc, 0 ; attributes for columns 6 and 7 403 ld ($5820+(ROWREPT*32)), hl ; update columns 0 and 1 404 ld hl, 0 ; attributes for columns 2 and 3 405 push bc ; update columns 6 and 7 406 push de ; update columns 4 and 5 407 push hl ; update columns 2 and 3 408 ld sp, $5822+(ROWREPT*32)+24 ; reference columns 24 and 25 409 ld hl, 0 ; attributes for columns 20 and 21 410 ld de, 0 ; attributes for columns 22 and 23 411 ld bc, 0 ; attributes for columns 24 and 25 412 push bc ; update columns 24 and 25 413 push de ; update columns 22 and 23 414 push hl ; update columns 20 and 21 415 exx 416 push bc ; update columns 18 and 19 417 push de ; update columns 16 and 17 418 push hl ; update columns 14 and 15 419 ld hl, 0 ; attributes for columns 8 and 9 420 ld de, 0 ; attributes for columns 10 and 11 421 ld bc, 0 ; attributes for columns 12 and 13 422 push bc ; update columns 12 and 13 423 push de ; update columns 10 and 11 424 push hl ; update columns 8 and 9 425 ld sp, $5822+(ROWREPT*32)+30 ; reference columns 30 and 31 426 ld hl, 0 ; attributes for columns 26 and 27 427 ld de, 0 ; attributes for columns 28 and 29 428 ld bc, 0 ; attributes for columns 30 and 31 429 push bc ; update columns 30 and 31 430 push de ; update columns 28 and 29 431 push hl ; update columns 26 and 27 432') 433') 434 435ELSE 436 437; synchronize with raster beam while updating first attribute pair of each row 438; spectrum 48k/128k timing 439Z88DK_FOR(`ROWREPT', `0', `22', 440` 441IF ((ROWREPT = 4) || (ROWREPT = 9) || (ROWREPT = 14)) 442 ld b, 3 443 djnz ASMPC ; extra delay 444ELSE 445IF (ROWREPT = 20) 446 nop ; extra delay 447ENDIF 448ENDIF 449 450 ld hl, (race_raster+(ROWREPT*328)+25) 451IF (ROWREPT < __NIRVANAP_TOTAL_ROWS) 452 ld ($5820+(ROWREPT*32)), hl 453ELSE 454 ld hl, ($5820+(ROWREPT*32)) 455ENDIF 456') 457 458; race the raster beam to update attributes on screen at the right time 459race_raster: 460Z88DK_FOR(`ROWREPT', `0', eval(__NIRVANAP_TOTAL_ROWS-1), 461` 462Z88DK_FOR(`LINREPT', `0', `3', 463` 464 ld ix, 0 ; attributes for columns 14 and 15 465 ld iy, 0 ; attributes for columns 22 and 23 466 ld bc, 0 ; attributes for columns 8 and 9 467 ld de, 0 ; attributes for columns 10 and 11 468 ld hl, 0 ; attributes for columns 12 and 13 469 exx 470 ld bc, 0 ; attributes for columns 16 and 17 471 ld de, 0 ; attributes for columns 18 and 19 472 ld hl, 0 ; attributes for columns 0 and 1 473IF (LINREPT = 0) 474 ld sp, $5822+(ROWREPT*32)+24 ; reference columns 24 and 25 on next row 475 push hl ; trash columns 24 and 25 (fixed below) 476ELSE 477 ld a, (hl) ; extra delay 478 ld ($5820+(ROWREPT*32)), hl ; update columns 0 and 1 479ENDIF 480 ld hl, 0 ; attributes for columns 2 and 3 481 ld ($5820+(ROWREPT*32)+2), hl ; update columns 2 and 3 482 ld hl, 0 ; attributes for columns 4 and 5 483 ld ($5820+(ROWREPT*32)+4),hl ; update columns 4 and 5 484 ld hl, 0 ; attributes for columns 20 and 21 485 push iy ; update columns 22 and 23 486 push hl ; update columns 20 and 21 487 push de ; update columns 18 and 19 488 push bc ; update columns 16 and 17 489 exx 490 push ix ; update columns 14 and 15 491 push hl ; update columns 12 and 13 492 push de ; update columns 10 and 11 493 push bc ; update columns 8 and 9 494 ld hl, 0 ; attributes for columns 6 and 7 495 push hl ; update columns 6 and 7 496 ld sp, $5822+(ROWREPT*32)+28 ; reference columns 28 and 29 497 ld bc, 0 ; attributes for columns 24 and 25 498 ld de, 0 ; attributes for columns 26 and 27 499 ld hl, 0 ; attributes for columns 28 and 29 500 push hl ; update columns 28 and 29 501 push de ; update columns 26 and 27 502 push bc ; update columns 24 and 25 503 ld hl, 0 ; attributes for columns 30 and 31 504 ld ($5820+(ROWREPT*32)+30),hl ; update columns 30 and 31 505') 506') 507 508ENDIF 509 510exit_raster: 511; restore stack pointer 512 ld sp, 0 513 514; available entry-point for additional interrupt routines 515_NIRVANAP_ISR_HOOK: 516 ld hl, 0 517 518; restore all registers 519 pop iy 520 pop ix 521 pop hl 522 pop de 523 pop bc 524 pop af 525 exx 526 ex af, af' 527 pop hl 528 pop de 529 pop bc 530 pop af 531 532_NIRVANAP_ISR_STOP: 533 ei 534 reti 535 536; ----------------------------------------------------------------------------- 537; Insert Space Here 538; ----------------------------------------------------------------------------- 539 540defs 64262 - org_nirvanap - ASMPC 541 542; ----------------------------------------------------------------------------- 543; Draw tile at specified position (in 1712T) 544; 545; Params: 546; A = tile index (0-255) 547; D = pixel line (0-200, even values only) 548; E = char column (0-30) 549; 550; Address: 64262 551; 552; WARNING: Computer will crash if an interrupt occurs during execution! 553; ----------------------------------------------------------------------------- 554 555PUBLIC asm_NIRVANAP_drawT 556PUBLIC _NIRVANAP_TILE_IMAGES 557 558asm_NIRVANAP_drawT: 559; preserve stack pointer 560 ld (exit_draw+1), sp 561 562; calculate screen bitmap lookup address 563 ld h, bitmaps/256 564 ld l, d 565 ld sp, hl 566 567; preserve values 568 ld b, e 569 ld c, h 570 571; calculate tile image address 572 ld h, 0 573 ld l, a 574 ld d, h 575 ld e, l 576 add hl, hl 577 add hl, de 578 add hl, hl 579 add hl, hl 580 add hl, hl 581 add hl, hl 582defc _NIRVANAP_TILE_IMAGES = ASMPC + 1 583 ld de, __NIRVANAP_TILE_IMAGES 584 add hl, de 585 586; draw bitmap lines 587Z88DK_FOR(`LOOP', `1', `8', 588` 589 pop de 590 ld a, e 591 add a, b 592 ld e, a 593 ldi 594 ld a, (hl) 595 ld (de), a 596 inc hl 597 dec e 598 inc d 599 ldi 600 ldi 601') 602 603; calculate routine attribute address 604 ex de, hl 605 606 ld h, deltas/256 607 ld l, b 608 inc l 609 ld c, (hl) 610 inc l 611 ld a, (hl) 612 ex af, af' 613 614 ld hl, attribs - bitmaps - 16 615 ld b, h 616 add hl, sp 617 ld sp, hl 618 619; set 1st column of routine attributes 620Z88DK_FOR(`LOOP', `1', `8', 621` 622 pop hl 623 add hl, bc 624 ld a, (de) 625 ld (hl), a 626 inc de 627') 628 ex af, af' 629 ld c, a 630 ld hl, -16 631 add hl, sp 632 ld sp, hl 633 634; set 2nd column of routine attributes 635Z88DK_FOR(`LOOP', `1', `7', 636` 637 pop hl 638 add hl, bc 639 ld a, (de) 640 ld (hl), a 641 inc de 642') 643 pop hl 644 add hl, bc 645 ld a, (de) 646 ld (hl), a 647 648exit_draw: 649; restore stack pointer 650 ld sp, 0 651 ret 652 653; ----------------------------------------------------------------------------- 654bitmaps: 655; lookup table with screen coordinates 656Z88DK_FOR(`LOOP', `1', `8', 657` 658 defw 0 659') 660Z88DK_FOR(`ROWREPT', `0', eval(__NIRVANAP_TOTAL_ROWS-1), 661` 662Z88DK_FOR(`LIN2REPT', `0', `3', 663` 664 defw 16384 + (((ROWREPT+1)/8)*2048) + (LIN2REPT*512) + (((ROWREPT+1)%8)*32) 665') 666') 667 668Z88DK_FOR(`LOOP', `1', eval(4*(23-__NIRVANAP_TOTAL_ROWS)), 669` 670 defw 0 671') 672; ----------------------------------------------------------------------------- 673attribs: 674; lookup table with render attribute coordinates 675Z88DK_FOR(`LOOP', `1', `8', 676` 677 defw 0 678') 679Z88DK_FOR(`RACEREPT', `0', eval(4*__NIRVANAP_TOTAL_ROWS-1), 680` 681 defw race_raster + (RACEREPT*82) 682') 683Z88DK_FOR(`LOOP', `1', eval(4*(23-__NIRVANAP_TOTAL_ROWS)), 684` 685 defw 0 686') 687Z88DK_FOR(`LOOP', `1', `8', 688` 689 defw 0 690') 691; ----------------------------------------------------------------------------- 692; Insert Space Here 693; ----------------------------------------------------------------------------- 694 695defs 64928 - org_nirvanap - ASMPC 696 697; ----------------------------------------------------------------------------- 698; Fill specified tile position with attribute value (in 502T) 699; 700; Params: 701; A = attribute value (0-255) 702; D = pixel line (0-200, even values only) 703; E = char column (0-30) 704; 705; Address: 64928 706; 707; WARNING: Computer will crash if an interrupt occurs during execution! 708; ----------------------------------------------------------------------------- 709 710PUBLIC asm_NIRVANAP_fillT 711 712asm_NIRVANAP_fillT: 713; preserve stack pointer 714 ld (exit_fill+1), sp 715 716; calculate first routine attribute address 717 ld hl, attribs 718 ld b, 0 719 ld c, d ; pixel line 720 add hl, bc 721 ld sp, hl 722 723 ld h, deltas/256 724 ld l, e ; char column 725 inc l 726 ld c, (hl) ; BC = 1st delta (column offset) 727 inc l 728 ld l, (hl) ; HL = 2nd delta (column offset) 729 ld h, b 730 sbc hl, bc 731 ex de, hl ; DE = difference between column offsets 732 733; update attribute addresses to specified value 734Z88DK_FOR(`LOOP', `1', `8', 735` 736 pop hl 737 add hl, bc 738 ld (hl), a 739 add hl, de 740 ld (hl), a 741') 742exit_fill: 743; restore stack pointer 744 ld sp, 0 745 ret 746 747; ----------------------------------------------------------------------------- 748; Activate NIRVANA engine. 749; 750; Address: 64995 751; ----------------------------------------------------------------------------- 752 753PUBLIC asm_NIRVANAP_start 754 755asm_NIRVANAP_start: 756 di 757IF ((__SPECTRUM & __SPECTRUM_PENTAGON) = 0) 758 ld a, ($004c) 759 and 2 760 ld (delay_128k-1), a 761ENDIF 762 ld a, $fe 763 ld i, a 764 im 2 765 ld hl,main_engine 766 ld ($fdfe),hl 767 ei 768 ret 769 770; ----------------------------------------------------------------------------- 771; Deactivate NIRVANA engine. 772; replaced 773; ----------------------------------------------------------------------------- 774; 775;PUBLIC asm_NIRVANAP_stop 776; 777;asm_NIRVANAP_stop: 778; di 779; ld a, $3f 780; ld i, a 781; im 1 782; ei 783; ret 784 785; ----------------------------------------------------------------------------- 786; Insert Space Here 787; ----------------------------------------------------------------------------- 788 789defs 0xfdfd - org_nirvanap - ASMPC 790 791; ----------------------------------------------------------------------------- 792; interrupt address at $fdfd 793 jp main_engine 794 795; ----------------------------------------------------------------------------- 796; jump vector table at addresses $fe00-$ff00 797 defs 257, 0xfd 798 799; ----------------------------------------------------------------------------- 800deltas: 801IF (__SPECTRUM & __SPECTRUM_PENTAGON) 802; lookup table with deltas (column offsets) 803; pentagon 804 defb 21, 22, 33, 34, 24, 25, 27, 28, 58, 59, 61, 62, 64, 65, 11, 12 805 defb 14, 15, 17, 18, 42, 43, 45, 46, 48, 49, 73, 74, 76, 77, 79, 80 806ELSE 807; lookup table with deltas (column offsets) 808 defb 25, 26, 32, 33, 38, 39, 58, 59, 9, 10, 12, 13, 15, 16, 2, 3 809 defb 19, 20, 22, 23, 44, 45, 6, 7, 65, 66, 68, 69, 71, 72, 77, 78 810ENDIF 811; ----------------------------------------------------------------------------- 812; Fill specified 8x8 block with attribute value (in 165T) 813; 814; Params: 815; C = attribute value (0-255) 816; D = pixel line (16-192, even values only) 817; E = char column (0-31) 818; 819; Address: 65313 820; ----------------------------------------------------------------------------- 821 822PUBLIC asm_NIRVANAP_fillC 823 824asm_NIRVANAP_fillC: 825; calculate initial routine attribute address 826 ld h, 0 827 ld l, d 828 ld d, deltas/256 829 inc e 830 ld a, (de) 831 ld de, attribs 832 add hl, de 833 add a, (hl) 834 ld e, a 835 inc l 836 adc a, (hl) 837 sub e 838 ld d, a 839 ex de, hl 840 841; update attributes 842 ld de, 82 843 844 ld (hl), c 845 add hl, de 846 847 ld (hl), c 848 add hl, de 849 850 ld (hl), c 851 add hl, de 852 853 ld (hl), c 854 ret 855 856; ----------------------------------------------------------------------------- 857; Retrieve a sequence of 4 attribute values from specified 8x8 block (in 211T) 858; 859; Params: 860; D = pixel line (16-192, even values only) 861; E = char column (0-31) 862; BC = attributes address 863; 864; Address: 65342 865; ----------------------------------------------------------------------------- 866 867PUBLIC asm_NIRVANAP_readC 868 869asm_NIRVANAP_readC: 870; calculate initial routine attribute address 871 ld h, 0 872 ld l, d 873 ld d, deltas/256 874 inc e 875 ld a, (de) 876 ld de, attribs 877 add hl, de 878 add a, (hl) 879 ld e, a 880 inc l 881 adc a, (hl) 882 sub e 883 ld d, a 884 ex de, hl 885 886; read attributes 887 ld de, 82 888 889 ld a, (hl) 890 ld (bc), a 891 inc bc 892 add hl, de 893 894 ld a, (hl) 895 ld (bc), a 896 inc bc 897 add hl, de 898 899 ld a, (hl) 900 ld (bc), a 901 inc bc 902 add hl, de 903 904 ld a, (hl) 905 ld (bc), a 906 ret 907