|
32 | 32 | #importonce |
33 | 33 |
|
34 | 34 | #import "labels/lib/kernal.asm" |
| 35 | +#import "labels/lib/screeneditor.asm" |
35 | 36 | #import "labels/lib/vdc.asm" |
36 | 37 |
|
37 | 38 | .filenamespace c128lib |
@@ -399,6 +400,272 @@ InitText: { |
399 | 400 | stx $d600; bit $d600; bpl *-3; sta $d601 |
400 | 401 | } |
401 | 402 |
|
| 403 | +/** |
| 404 | + * @brief Read from Vdc internal memory and write it to Vic screen memory by |
| 405 | + * using coordinates. |
| 406 | + * |
| 407 | + * @param[in] xPos X coord on Vdc screen |
| 408 | + * @param[in] yPos Y coord on Vdc screen |
| 409 | + * @param[in] destination Vic screen memory absolute address |
| 410 | + * @param[in] qty Number of byte to copy |
| 411 | + * |
| 412 | + * @note Use c128lib_ReadFromVdcMemoryByCoordinates in vdc-global.asm |
| 413 | + * |
| 414 | + * @since 1.1.0 |
| 415 | + */ |
| 416 | +.macro ReadFromVdcMemoryByCoordinates(xPos, yPos, destination, qty) { |
| 417 | + .errorif (xPos == -1 && yPos != -1), "xPos and yPos must be -1 at same time" |
| 418 | + .errorif (xPos != -1 && yPos == -1), "xPos and yPos must be -1 at same time" |
| 419 | + .errorif (xPos < -1 || yPos < -1), "xPos and yPos can't be lower than -1" |
| 420 | + .errorif (qty <= 0), "qty must be greater than 0" |
| 421 | + .errorif (qty > 255), "qty must be lower than 256" |
| 422 | + .if (xPos != -1 && yPos != -1) { |
| 423 | + ldx #$12 |
| 424 | + lda #>getTextOffset80Col(xPos, yPos) |
| 425 | + jsr ScreenEditor.WRITEREG |
| 426 | + lda #<getTextOffset80Col(xPos, yPos) |
| 427 | + inx |
| 428 | + jsr ScreenEditor.WRITEREG |
| 429 | + } |
| 430 | + ldy #0 |
| 431 | + CopyLoop: |
| 432 | + jsr ScreenEditor.READ80 |
| 433 | + sta destination, y |
| 434 | + iny |
| 435 | + cpy #qty |
| 436 | + bne CopyLoop |
| 437 | +} |
| 438 | +.asserterror "ReadFromVdcMemoryByCoordinates(-1, 0, $beef, 100)", { ReadFromVdcMemoryByCoordinates(-1, 0, $beef, 100) } |
| 439 | +.asserterror "ReadFromVdcMemoryByCoordinates(0, -1, $beef, 100)", { ReadFromVdcMemoryByCoordinates(0, -1, $beef, 100) } |
| 440 | +.asserterror "ReadFromVdcMemoryByCoordinates(-2, 0, $beef, 100)", { ReadFromVdcMemoryByCoordinates(-2, 0, $beef, 100) } |
| 441 | +.asserterror "ReadFromVdcMemoryByCoordinates(0, -2, $beef, 100)", { ReadFromVdcMemoryByCoordinates(0, -2, $beef, 100) } |
| 442 | +.asserterror "ReadFromVdcMemoryByCoordinates(-2, -2, $beef, 100)", { ReadFromVdcMemoryByCoordinates(-2, -2, $beef, 100) } |
| 443 | +.asserterror "ReadFromVdcMemoryByCoordinates(2, 2, $beef, 0)", { ReadFromVdcMemoryByCoordinates(2, 2, $beef, 0) } |
| 444 | +.asserterror "ReadFromVdcMemoryByCoordinates(2, 2, $beef, 256)", { ReadFromVdcMemoryByCoordinates(2, 2, $beef, 256) } |
| 445 | +.assert "ReadFromVdcMemoryByCoordinates(-1, -1, $beef, 100)", { ReadFromVdcMemoryByCoordinates(-1, -1, $beef, 100) }, |
| 446 | +{ |
| 447 | + ldy #0; jsr $CDD8; sta $beef, y; iny; cpy #100; bne *-9; |
| 448 | +} |
| 449 | +.assert "ReadFromVdcMemoryByCoordinates(1, 1, $beef, 100)", { ReadFromVdcMemoryByCoordinates(1, 1, $beef, 100) }, |
| 450 | +{ |
| 451 | + ldx #$12; lda #0; jsr $CDCC; lda #81; inx; jsr $CDCC; |
| 452 | + ldy #0; jsr $CDD8; sta $beef, y; iny; cpy #100; bne *-9; |
| 453 | +} |
| 454 | +.assert "ReadFromVdcMemoryByCoordinates(1, 1, $beef, 255)", { ReadFromVdcMemoryByCoordinates(1, 1, $beef, 255) }, |
| 455 | +{ |
| 456 | + ldx #$12; lda #0; jsr $CDCC; lda #81; inx; jsr $CDCC; |
| 457 | + ldy #0; jsr $CDD8; sta $beef, y; iny; cpy #255; bne *-9; |
| 458 | +} |
| 459 | + |
| 460 | +/** |
| 461 | + * @brief Read from Vdc internal memory and write it to Vic screen memory by |
| 462 | + * using source address. |
| 463 | + * |
| 464 | + * @param[in] source Vdc memory absolute address |
| 465 | + * @param[in] destination Vic screen memory absolute address |
| 466 | + * @param[in] qty Number of byte to copy |
| 467 | + * |
| 468 | + * @note Use c128lib_ReadFromVdcMemoryByAddress in vdc-global.asm |
| 469 | + * |
| 470 | + * @since 1.1.0 |
| 471 | + */ |
| 472 | +.macro ReadFromVdcMemoryByAddress(source, destination, qty) { |
| 473 | + .errorif (qty <= 0), "qty must be greater than 0" |
| 474 | + .errorif (qty > 255), "qty must be lower than 256" |
| 475 | + ldx #$12 |
| 476 | + lda #>source |
| 477 | + jsr c128lib.ScreenEditor.WRITEREG |
| 478 | + lda #<source |
| 479 | + inx |
| 480 | + jsr c128lib.ScreenEditor.WRITEREG |
| 481 | + |
| 482 | + ldy #0 |
| 483 | + CopyLoop: |
| 484 | + jsr c128lib.ScreenEditor.WRITE80 |
| 485 | + sta destination, y |
| 486 | + iny |
| 487 | + cpy #qty |
| 488 | + bne CopyLoop |
| 489 | +} |
| 490 | +.asserterror "ReadFromVdcMemoryByAddress($beef, $baab, 0)", { ReadFromVdcMemoryByAddress($beef, $baab, 0) } |
| 491 | +.asserterror "ReadFromVdcMemoryByAddress($beef, $baab, 256)", { ReadFromVdcMemoryByAddress($beef, $baab, 256) } |
| 492 | +.assert "ReadFromVdcMemoryByAddress($beef, $baab, 100)", { ReadFromVdcMemoryByAddress($beef, $baab, 100) }, |
| 493 | +{ |
| 494 | + ldx #$12; lda #$be; jsr $CDCC; lda #$ef; inx; jsr $CDCC; |
| 495 | + ldy #0; jsr $CDCA; sta $baab, y; iny; cpy #100; bne *-9; |
| 496 | +} |
| 497 | +.assert "ReadFromVdcMemoryByAddress($beef, $baab, 255)", { ReadFromVdcMemoryByAddress($beef, $baab, 255) }, |
| 498 | +{ |
| 499 | + ldx #$12; lda #$be; jsr $CDCC; lda #$ef; inx; jsr $CDCC; |
| 500 | + ldy #0; jsr $CDCA; sta $baab, y; iny; cpy #255; bne *-9; |
| 501 | +} |
| 502 | + |
| 503 | +/** |
| 504 | + * @brief Read from Vic screen memory and write it to Vdc internal memory by |
| 505 | + * using coordinates. |
| 506 | + * |
| 507 | + * @param[in] xPos X coord on Vic screen |
| 508 | + * @param[in] yPos Y coord on Vic screen |
| 509 | + * @param[in] destination Vdc internal memory absolute address |
| 510 | + * @param[in] qty Number of byte to copy |
| 511 | + * |
| 512 | + * @note Use c128lib_WriteToVdcMemoryByCoordinates in vdc-global.asm |
| 513 | + * |
| 514 | + * @since 1.1.0 |
| 515 | + */ |
| 516 | +.macro WriteToVdcMemoryByCoordinates(source, xPos, yPos, qty) { |
| 517 | + .errorif (xPos == -1 && yPos != -1), "xPos and yPos must be -1 at same time" |
| 518 | + .errorif (xPos != -1 && yPos == -1), "xPos and yPos must be -1 at same time" |
| 519 | + .errorif (xPos < -1 || yPos < -1), "xPos and yPos can't be lower than -1" |
| 520 | + .errorif (qty <= 0), "qty must be greater than 0" |
| 521 | + .errorif (qty > 255), "qty must be lower than 256" |
| 522 | + .if (xPos != -1 && yPos != -1) { |
| 523 | + ldx #$12 |
| 524 | + lda #>getTextOffset80Col(xPos, yPos) |
| 525 | + jsr c128lib.ScreenEditor.WRITEREG |
| 526 | + lda #<getTextOffset80Col(xPos, yPos) |
| 527 | + inx |
| 528 | + jsr c128lib.ScreenEditor.WRITEREG |
| 529 | + } |
| 530 | + ldy #0 |
| 531 | + CopyLoop: |
| 532 | + lda source, y |
| 533 | + jsr c128lib.ScreenEditor.WRITE80 |
| 534 | + iny |
| 535 | + cpy #qty |
| 536 | + bne CopyLoop |
| 537 | +} |
| 538 | +.asserterror "WriteToVdcMemoryByCoordinates($beef, -1, 0, 100)", { WriteToVdcMemoryByCoordinates($beef, -1, 0, 100) } |
| 539 | +.asserterror "WriteToVdcMemoryByCoordinates($beef, 0, -1, 100)", { WriteToVdcMemoryByCoordinates($beef, 0, -1, 100) } |
| 540 | +.asserterror "WriteToVdcMemoryByCoordinates($beef, -2, 0, 100)", { WriteToVdcMemoryByCoordinates($beef, -2, 0, 100) } |
| 541 | +.asserterror "WriteToVdcMemoryByCoordinates($beef, 0, -2, 100)", { WriteToVdcMemoryByCoordinates($beef, 0, -2, 100) } |
| 542 | +.asserterror "WriteToVdcMemoryByCoordinates($beef, -2, -2, 100)", { WriteToVdcMemoryByCoordinates($beef, -2, -2, 100) } |
| 543 | +.asserterror "WriteToVdcMemoryByCoordinates($beef, 2, 2, 0)", { WriteToVdcMemoryByCoordinates($beef, 2, 2, 0) } |
| 544 | +.asserterror "WriteToVdcMemoryByCoordinates($beef, 2, 2, 256)", { WriteToVdcMemoryByCoordinates($beef, 2, 2, 256) } |
| 545 | +.assert "WriteToVdcMemoryByCoordinates($beef, -1, -1, 100)", { WriteToVdcMemoryByCoordinates($beef, -1, -1, 100) }, |
| 546 | +{ |
| 547 | + ldy #0; lda $beef, y; jsr $CDCA; iny; cpy #100; bne *-9; |
| 548 | +} |
| 549 | +.assert "WriteToVdcMemoryByCoordinates($beef, 1, 1, 100)", { WriteToVdcMemoryByCoordinates($beef, 1, 1, 100) }, |
| 550 | +{ |
| 551 | + ldx #$12; lda #0; jsr $CDCC; lda #81; inx; jsr $CDCC; |
| 552 | + ldy #0; lda $beef, y; jsr $CDCA; iny; cpy #100; bne *-9; |
| 553 | +} |
| 554 | +.assert "WriteToVdcMemoryByCoordinates($beef, 1, 1, 255)", { WriteToVdcMemoryByCoordinates($beef, 1, 1, 255) }, |
| 555 | +{ |
| 556 | + ldx #$12; lda #0; jsr $CDCC; lda #81; inx; jsr $CDCC; |
| 557 | + ldy #0; lda $beef, y; jsr $CDCA; iny; cpy #255; bne *-9; |
| 558 | +} |
| 559 | + |
| 560 | +/** |
| 561 | + * @brief Read from Vic screen memory and write it to Vdc internal memory by |
| 562 | + * using coordinates. |
| 563 | + * |
| 564 | + * @param[in] source Vdc memory absolute address |
| 565 | + * @param[in] destination Vic screen memory absolute address |
| 566 | + * @param[in] qty Number of byte to copy |
| 567 | + * |
| 568 | + * @note Use c128lib_WriteToVdcMemoryByAddress in vdc-global.asm |
| 569 | + * |
| 570 | + * @since 1.1.0 |
| 571 | + */ |
| 572 | +.macro WriteToVdcMemoryByAddress(source, destination, qty) { |
| 573 | + .errorif (qty <= 0), "qty must be greater than 0" |
| 574 | + .errorif (qty > 255), "qty must be lower than 256" |
| 575 | + ldx #$12 |
| 576 | + lda #>destination |
| 577 | + jsr c128lib.ScreenEditor.WRITEREG |
| 578 | + lda #<destination |
| 579 | + inx |
| 580 | + jsr c128lib.ScreenEditor.WRITEREG |
| 581 | + |
| 582 | + ldy #0 |
| 583 | + CopyLoop: |
| 584 | + lda source, y |
| 585 | + jsr c128lib.ScreenEditor.WRITE80 |
| 586 | + iny |
| 587 | + cpy #qty |
| 588 | + bne CopyLoop |
| 589 | +} |
| 590 | +.asserterror "WriteToVdcMemoryByAddress($beef, $baab, 0)", { WriteToVdcMemoryByAddress($beef, $baab, 0) } |
| 591 | +.asserterror "WriteToVdcMemoryByAddress($beef, $baab, 256)", { WriteToVdcMemoryByAddress($beef, $baab, 256) } |
| 592 | +.assert "WriteToVdcMemoryByAddress($beef, $baab, 100)", { WriteToVdcMemoryByAddress($beef, $baab, 100) }, |
| 593 | +{ |
| 594 | + ldx #$12; lda #$ba; jsr $CDCC; lda #$ab; inx; jsr $CDCC; |
| 595 | + ldy #0; lda $beef, y; jsr $CDCA; iny; cpy #100; bne *-9; |
| 596 | +} |
| 597 | +.assert "WriteToVdcMemoryByAddress($beef, $baab, 255)", { WriteToVdcMemoryByAddress($beef, $baab, 255) }, |
| 598 | +{ |
| 599 | + ldx #$12; lda #$ba; jsr $CDCC; lda #$ab; inx; jsr $CDCC; |
| 600 | + ldy #0; lda $beef, y; jsr $CDCA; iny; cpy #255; bne *-9; |
| 601 | +} |
| 602 | + |
| 603 | +/** |
| 604 | + * @brief Calculates memory offset of text cell specified by given coordinates |
| 605 | + * on 80 cols screen |
| 606 | + * |
| 607 | + * @param[in] xPos X coord on Vdc screen |
| 608 | + * @param[in] yPos Y coord on Vdc screen |
| 609 | + * @return Memory offset of Vdc specified coordinate |
| 610 | + * |
| 611 | + * @note Use c128lib_WriteToVdcMemoryByAddress in vdc-global.asm |
| 612 | + * |
| 613 | + * @since 1.1.0 |
| 614 | + */ |
| 615 | +.function getTextOffset80Col(xPos, yPos) { |
| 616 | + .return xPos + Vdc.TEXT_SCREEN_80_COL_WIDTH * yPos |
| 617 | +} |
| 618 | +.assert "getTextOffset80Col(0,0) gives 0", getTextOffset80Col(0, 0), 0 |
| 619 | +.assert "getTextOffset80Col(79,0) gives 79", getTextOffset80Col(79, 0), 79 |
| 620 | +.assert "getTextOffset80Col(0,1) gives 80", getTextOffset80Col(0, 1), 80 |
| 621 | +.assert "getTextOffset80Col(19,12) gives 979", getTextOffset80Col(19, 12), 979 |
| 622 | +.assert "getTextOffset80Col(79,24) gives 1999", getTextOffset80Col(79, 24), 1999 |
| 623 | + |
| 624 | +/** |
| 625 | + * @brief Returns the address start of Vdc display memory data. This |
| 626 | + * is stored in Vdc register SCREEN_MEMORY_STARTING_HIGH_ADDRESS and |
| 627 | + * SCREEN_MEMORY_STARTING_LOW_ADDRESS. |
| 628 | + * The 16-bit value is stored in $FB and $FC. |
| 629 | + * |
| 630 | + * @note Use c128lib_GetVdcDisplayStart in vdc-global.asm |
| 631 | + * |
| 632 | + * @since 1.1.0 |
| 633 | + */ |
| 634 | +.macro GetVdcDisplayStart() { |
| 635 | + ldx #Vdc.SCREEN_MEMORY_STARTING_HIGH_ADDRESS |
| 636 | + ReadVdc() |
| 637 | + |
| 638 | + sta $fb |
| 639 | + inx |
| 640 | + ReadVdc() |
| 641 | + sta $fc |
| 642 | +} |
| 643 | + |
| 644 | +/** |
| 645 | + * @brief Set the pointer to the RAM area that is to be updated. |
| 646 | + * The update pointer is stored in Vdc register CURRENT_MEMORY_HIGH_ADDRESS |
| 647 | + * and CURRENT_MEMORY_LOW_ADDRESS. |
| 648 | + * |
| 649 | + * @param[in] address Address of update area |
| 650 | + * |
| 651 | + * @note Use c128lib_SetVdcUpdateAddress in vdc-global.asm |
| 652 | + * |
| 653 | + * @since 1.1.0 |
| 654 | + */ |
| 655 | +.macro SetVdcUpdateAddress(address) { |
| 656 | + ldx #Vdc.CURRENT_MEMORY_HIGH_ADDRESS |
| 657 | + lda #>address |
| 658 | + WriteVdc(); |
| 659 | + |
| 660 | + inx |
| 661 | + .var a1 = <address |
| 662 | + .var a2 = >address |
| 663 | + .if (a1 != a2) { |
| 664 | + lda #<address // include if different from hi-byte. |
| 665 | + } |
| 666 | + WriteVdc() |
| 667 | +} |
| 668 | + |
402 | 669 | /** |
403 | 670 | * @brief Write a value into Vdc register without using kernal |
404 | 671 | * routine instead of pure instruction. It needs register |
|
0 commit comments