AppleIIAsm-Collection/documentation/AppleIIAsm Library Collecti.../0.6.1/37.0 Detailed_Reference_D8_...

119 KiB

Disk 8: LoRes


Part I: The LoRes Collection

The eighth disk in the AppleIIAsm Library consists of macros and subroutines used in low-resolution graphics mode. This includes procedures for managing viewing and working pages, plotting "pixels," lines, shapes and characters, and retrieving the state of a pixel at its given coordinates.


LoRes Components

The LoRes Collection contains the following components:

  • A header file that includes number of hooks and vectors used for low resolution graphics, as well as a plotting routine that is used by the rest of the collection.
  • A macro library that includes all of the macros used for low-resolution graphics.
  • Subroutines used by the macros.
  • A demonstration file that illustrates how each of the macros work.

LoRes Collection Header File

Condition Value
Name File: HEAD.LORES.ASM
Type Header File
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin 8 Pro
OS Apple DOS 3.3
Purpose Provide appropriate hooks and routines for the LoRes Collection
Dependencies none
Bytes 169+
Notes none
See Also none

DETAILS

The LoRes Header file includes a number of hooks and vectors used for low resolution graphics as well as a subroutine used for plotting to the screen, which is shared by the rest of the collection to function properly.

LISTING 8.00: HEAD.LORES.ASM Heading Source

*``````````````````````````````*
* HOOKS.LORES                  *
*                              *
* THIS FILE INCLUDES HOODS AND *
* A FEW SUBROUTINES AND TABLES *
* USED BY THE REST OF THE LOW  *
* RESOLUTION SUBROUTINES.      *
*                              *
* AUTHOR:    NATHAN RIGGS      *
* CONTACT:   NATHAN.RIGGS@     *
*            OUTLOOK.COM       *
*                              *
* DATE:      11-MAY-2021       *
* ASSEMBLER: MERLIN 8 PRO      *
* LICENSE:   APACHE 2.0        *
* OS:        DOS 3.3           *
*                              *
* SIZE: 169 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
TEXTOFF  EQU   $C050      ; TURN ON GRAPHICS MODE
TEXTON   EQU   $C051      ; TURN ON TEXT MODE
MIXEDOFF EQU   $C052      ; SET FULLSCREEN MODE FOR GRAPHICS
MIXEDON  EQU   $C053      ; SET MIXED MODE FOR GRAPHICS
LORES    EQU   $C056      ; SOFT SWITCH FOR USING LORES GRAPHICS
HIRES    EQU   $C057      ; SOFT SWITCH TO SPECIFY HIRES GRAPHICS
VPG1     EQU   $C054      ; SET THE VIEWING PAGE TO PAGE 1
VPG2     EQU   $C055      ; SET THE VIEWING PAGE TO PAGE 2
LRGBCALC EQU   $F847      ; FOR CALCULATING LORES COORDINATES
GBASLO   EQU   $26        ; LOW BYTE OF A PIXEL ADDRESS
GBASHI   EQU   $27        ; HIGHT BYTE OF PIXEL ADDRESS
*
]BLACK   EQU   $00        ; LORES COLOR BLACK
]MAGENTA EQU   $01        ; LORES COLOR MAGENTA
]DBLUE   EQU   $02        ; LORES DARK BLUE
]PURPLE  EQU   $03        ; LORES COLOR PURPLE
]DGREEN  EQU   $04        ; LORES COLOR DARK GREEN
]GREY1   EQU   $05        ; LORES COLOR FIRST GREY SHADE
]MBLUE   EQU   $06        ; LORES COLOR MEDIUM BLUE
]LBLUE   EQU   $07        ; LORES COLOR LIGHT BLUE
]BROWN   EQU   $08        ; LORES COLOR BROWN
]ORANGE  EQU   $09        ; LORES COLOR ORANGE
]GREY2   EQU   $0A        ; LORES COLORE GREY SHADE 2
]PINK    EQU   $0B        ; LORES COLOR PINK
MGREEN   EQU   $0C        ; LORES COLOR MEDIUM GREEN
]YELLOW  EQU   $0D        ; LORES COLOR YELLOW
]AQUA    EQU   $0E        ; LORES COLOR AQUAMARINE
]WHITE   EQU   $0F        ; LORES COLOR WHITE
*
** THE LOCPLOT SUBROUTINE IS IN THE HOOKS FILE
** BECAUSE IT IS USED, IN SOME CAPACITY, BY THE
** REST OF THE LORES LIBRARY.
*
         JMP   ]EOF       {3C3B}
*
]LOCCOL  DS    1          ; {0C1B} LOCAL PLOT COLOR
]MASK    DS    2          ; {0C2B} MASK FOR ISOLATING NIBBLE
]COLMASK DS    2          ; {0C2B} COLOR MASK
]X       DS    1          ; {OC1B} X COORDINATE FOR PLOT
]Y       DS    1          ; {0C1B} Y COORDINATE FOR PLOT
]PAGEOFF DS    1          ; {0C1B} PAGE OFFSET
*

THE LOCPLOT SUBROUTINE

SUMMARY

Condition Value
Name LOCPLOT
Type Subroutine
File HEAD.LORES.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose plot a low-resolution pixel
Input .X = X position
.Y = Y position
.A = Color
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 168+
Bytes 109
Notes This shares the same source as the LRPLOT subroutine
See Also LRPLOT

DETAILS

The LOCPLOT subroutine accepts an X-coordinate, a Y-coordinate and a color code to plot a low-resolution pixel at the given coordinate and in the given color. This subroutine is used for most of the plotting subroutines and macros in the library.

LISTING 8.01: The HEAD.LORES.ASM LOCPLOT Subroutine Source

*
*``````````````````````````````*
* LOCPLOT                      *
*                              *
* PLOT AT A GIVEN X,Y POINT IN *
* A GIVEN COLOR.               *
*                              *
* INPUT                        *
*                              *
*  .X = X POSITION             *
*  .Y = Y POSITION             *
*  .A = COLOR CODE             *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 168+                 *
* SIZE: 109 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
LOCPLOT
*
         STY   ]Y         ; {4C3B} Y POSITION PASSED IN .Y
         STX   ]X         ; {4C3B} X POSITION PASSED IN .X
         STA   ]LOCCOL    ; {4C3B} COLOR PASSED IN .A
         LDA   ]LOCCOL    ; {4C3B} TAKE THE COLOR SENT
         ASL              ; {2C1B} AND MOVE IT LEFT 4 BITS
         ASL              ; {2C1B} TO THE HIGH BYTE
         ASL              ; {2C1B}
         ASL              ; {2C1B}
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]LOCCOL    ; {4C3B} NOW ADD THE LOW BYTE, MEANING
         STA   ]LOCCOL    ; {4C3B} COLOR WILL BE REPEATING NIBBLES
         LDA   LWP        ; {4C3B} LOAD THE WORKING PAGE FLAG
         CMP   #2         ; {3C2B} IF WORKING PAGE IS NOT PAGE 2,
         BNE   :PG1       ; {3C2B} THEN ASSUME IT'S PAGE 1.
         LDA   #4         ; {3C2B} ELSE, SET OFFSET FOR PAGE 2
         STA   ]PAGEOFF   ; {4C3B} STORE IN THE PAGE OFFSET
         JMP   :CNT       ; {3C3B} SKIP TO CONTINUE ROUTINE
:PG1
         LDA   #0         ; {3C2B} OTHERWISE, IT'S PAGE ONE
         STA   ]PAGEOFF   ; {4C3B} SO THERE IS NO PAGE OFFSET
:CNT
         LDA   #0         ; {3C2B}
         LDY   #0         ; {3C2B}
         LDX   #0         ; {3C2B}
         LDA   ]Y         ; {4C3B} GET Y COORDINATE
         LSR              ; {2C1B} SHIFT BOTTOM BIT TO CARRY
         BCC   :EVEN      ; {3C2B} IF CARRY = 0, THEN ROW IS EVEN
         LDX   #$F0       ; {3C2B} OTHERWISE, IT IS ODD; SO MASK
                          ; THE LEFT NIBBLE
         BCS   :LPLOT     ; {3C2B} IF CARRY SET, BR TO PLOTTING
:EVEN
         LDX   #$0F       ; {3C2B} EVEN, SO MASK LOW BYTE
:LPLOT
         STX   ]MASK      ; {3C2B} STORE THE EVEN OR ODD MASK
         ASL              ; {2C1B} SHIFT CARRY BACK INTO BYTE
         TAY              ; {2C1B} HOLD VALUE INTO .Y
         LDA   LROFF,Y    ; {5C3B} GET LORES MEMORY ADDRESS
         CLC              ; {2C1B} CLEAR THE CARRY
         ADC   ]X         ; {4C3B} ADD THE X COORDINATE
         STA   GBASLO     ; {4C3B} STORE LOW BYTE FOR GBASCALC
         INY              ; {2C1B} INCREASE Y OFFSET
         LDA   LROFF,Y    ; {5C3B} GET LORESS MEMORY ADDRESS
         ADC   ]PAGEOFF   ; {4C3B} ADJUST FOR PAGE AND CARRY HIGH
         STA   GBASHI     ; {4C3B} STORE HIGH BYTE FOR GBASCALC
         LDY   #0         ; {3C2B}
         LDA   ]MASK      ; {4C3B} RELOAD THE MASK
         EOR   #$FF       ; {2C2B} EXCLUSIVE OR THE MASK
         AND   (GBASLO),Y ; {6C2B} AND THE LOW FOR GBAS
         STA   ]COLMASK   ; {4C3B} STORE THE COLOR MASK
         LDA   ]LOCCOL    ; {4C3B} LOAD THE COLOR
         AND   ]MASK      ; {4C3B} AND THE MASK
         ORA   ]COLMASK   ; {4C3B} OR WITH THE COLOR MASK
         STA   (GBASLO),Y ; {6C2B} STORE INTO GBAS LOW BYTE
         RTS              ; {6C1B}
*
LWP      DS    1,1        ; {OC1B} BYTE TO DETERMIN WORK PAGE
*
** THE FOLLOWING TABLE HELPS WITH FASTER PLOTTING TO THE
** LOW RESOLUTION SCREEN.
*
LROFF    DW    $400,$480,$500,$580,$600,$680,$700,$780 ; {0C16B}
         DW    $428,$4A8,$528,$5A8,$628,$6A8,$728,$7A8 ; {0C16B}
         DW    $450,$4D0,$550,$5D0,$650,$6D0,$750,$7D0 ; {0C16B}
*
]EOF

LoRes Macros and Subroutines

The MAC.LORES.ASM file contains all of the macros used for manipulating low-resolution graphics. All subroutines, save for LOCPLOT in the collection header file, are located in their own respective files.

LISTING 8.02: The MAC.LORES.ASM Heading

*``````````````````````````````*
* MAC.LORES                    *
*                              *
* THIS IS A MACRO LIBRARY FOR  *
* LOW RESOLUTION GRAPHICS.     *
*                              *
* AUTHOR:    NATHAN RIGGS      *
* CONTACT:   NATHAN.RIGGS@     *
*            OUTLOOK.COM       *
*                              *
* DATE:      12-MAY-2021       *
* ASSEMBLER: MERLIN 8 PRO      *
* OS:        DOS 3.3           *
*                              *
* SUBROUTINE FILES NEEDED      *
*                              *
*  SUB.LRBLINE                 *
*  SUB.LRCHAR                  *
*  SUB.LRCIRCLE                *
*  SUB.LRGETPIX                *
*  SUB.LRGFCLR                 *
*  SUB.LRGPCLR                 *
*  SUB.LRHLINE                 *
*  SUB.LRPLOT                  *
*  SUB.LRVLINE                 *
*                              *
* LIST OF MACROS               *
*                              *
* LWORKPG : SET DRAWING PAGE   *
* LVIEWPG : SET VIEWING PAGE   *
* LRGF    : INIT FULL SCREEN   *
* LRGP    : INIT PART SCREEN   *
* LFCLR   : CLEAR FULL SCREEN  *
* LPCLR   : CLEAR MIXED SCREEN *
* LPLOT   : PLT TO SCREEN      *
* LLINE   : DIAGONAL LINE      *
* LCIRC   : LORES CIRCLE       *
* LVLIN   : LORES VERT LINE    *
* LHLIN   : LORES HORIZ LINE   *
* LRGET   : GET COLOR OF PIXEL *
* LCHAR   : OUTPUT LORES TEXT  *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*

THE LWORKPG MACRO

SUMMARY

Condition Value
Name LWORKPG
Type Macro
File MAC.LORES.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose set the current plotting page
Input ]1 = page number (#1 or #2)
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 27+
Bytes 20
Notes none
See Also LVIEWPG

DETAILS

The LWORKPG macro allows the user to set which low-resolution graphics page to plot on; this is limited to page #1 or page #2. If the work page is set to the same page as the viewing page (see LVIEWPG), then plotting will happen on screen in the order a plotting routine is called. Likewise, if the work page is different from the viewing page, the plotting will not be immediately visible; the viewing page must be switched to the same as the working page in order for the result of plotting to be seen. This can be useful for animation, or holding a static page in memory that is easily flipped to.

LISTING 8.03: The LWORKPG Macro Source

*
*``````````````````````````````*
* LWORKPG                      *
*                              *
* SET THE WORKING PAGE TO      *
* EITHER PAGE 1 OR PAGE 2.     *
* THIS MEANS THAT ALL COMMANDS *
* IN THE LORES LIBRARY WILL    *
* PLOT TO THIS PAGE, NO MATTER *
* WHICH PAGE IS BEING VIEWED.  *
*                              *
* PARAMETERS:                  *
*                              *
*  ]1 = PAGE NUMBER            *
*                              *
* CYCLES: 27+                  *
* SIZE: 20 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
LWORKPG  MAC
         LDA   ]1         ; {4C3B} LOAD PAGE NUMBER
         CMP   #2         ; {3C2B} IF IT IS NOT PAGE 2,
         BNE   ]__P1      ; {3C2B} THEN ASSUME PAGE 1
         LDA   #2         ; {3C2B} ELSE SET WORKING PAGE
         STA   LWP        ; {4C3B} TO PAGE 2
         JMP   ]EXIT      ; {3C3B}
]__P1
         LDA   #1         ; {3C2B} SET WORKING PAGE TO PAGE 1
         STA   LWP        ; {4C3B}
]EXIT
         <<<
*

THE LVIEWPG MACRO

SUMMARY

Condition Value
Name LVIEWPG
Type Macro
File MAC.LORES.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose set the current viewing page
Input ]1 = page number (#1 or #2)
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 21+
Bytes 16
Notes none
See Also LWORKPG

DETAILS

The LVIEWPG macro sets the current viewing page, either page 1 (#1 being passed) or page 2 (#2 being passed). The viewing page is the page that the end user sees; thus, if the working page is page 1, and the viewing page is also page 1, then the user will see plotting to the screen as it happens. In most cases, this is not an issue, as the speed of the subroutines are adequate enough to make most low-resolution operations seem nearly instantaneous. However, in cases like heavy animation, it would be better to set the working page to a different page than the viewing page, then flipping the viewing page once all of the plotting has finished on the working page. This leads to smoother animation, and the plotting is, essentially, truly instantaneous to the viewer.

LISTING 8.04: The LVIEWPG Macro Source

*
*``````````````````````````````*
* LVIEWPG                      *
*                              *
* SET THE VIEWING PAGE FOR LOW *
* RSEOLUTION GRAPHICS.         *
*                              *
* PARAMETERS:                  *
*                              *
*  ]1 = PAGE NUMBER            *
*                              *
* CYCLES: 21+                  *
* SIZE: 16 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
LVIEWPG  MAC
         LDA   ]1         ; {4C3B} GET PAGE NUMBER PASSED
         CMP   #2         ; {3C2B} IF IT ISN'T 2, THEN
         BNE   ]P1        ; {3C2B} ASSUME VIEWING PAGE 2
         BIT   VPG2       ; {4C3B} SET VIEWING PAGE TO PAGE 2
         JMP   ]EXIT      ; {3C3B}
]P1
         BIT   VPG1       ; {4C3B} SET VIEW PAGE TO PAGE 1
]EXIT
         <<<
*

THE LRGF MACRO

SUMMARY

Condition Value
Name LRGF
Type Macro
File MAC.LORES.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose set full screen low resolution mode
Input none
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 12+
Bytes 9
Notes none
See Also LRGP

DETAILS

The LRGF macro sets the graphics to full-screen, low resolution mode, with columns numbering 0..39 and rows numbering 0..47.

LISTING 8.05: The LRGF Macro Source

*
*``````````````````````````````*
* LRGF                         *
*                              *
* SET LOW-RESOLUTION MODE WITH *
* FULL-SCREEN 40X48 RESOLUTION *
*                              *
* PARAMETERS:                  *
*                              *
*  NONE                        *
*                              *
* CYCLES: 12                   *
* SIZE: 9 BYTES                *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
LRGF     MAC
         BIT   LORES      ; {4C3B}
         BIT   MIXEDOFF   ; {4C3B}
         BIT   TEXTOFF    ; {4C3B} GRAPHICS SOFT SWITCH
         <<<
*

THE LRGP MACRO

SUMMARY

Condition Value
Name LRGP
Type Macro
File MAC.LORES.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose set partial/mixed low resolution mode
Input none
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 12+
Bytes 9
Notes none
See Also LRGF

DETAILS

The LRGF macro sets the graphics to partial, low resolution mode (mixed mode), with columns numbering 0..39 and rows numbering 0..39. This mode allows for four lines of text at the bottom of the screen.

LISTING 8.06: The LRGP Macro Source

*
*``````````````````````````````*
* LRGP                         *
*                              *
* SETS THE GRAPHICS MODE TO    *
* LORES WITH FOR BOTTOM LINES  *
* OF TEXT.                     *
*                              *
* PARAMETERS:                  *
*                              *
*  NONE                        *
*                              *
* CYCLES: 12                   *
* SIZE: 9 BYTES                *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
LRGP     MAC
         BIT   LORES      ; {4C3B}
         BIT   MIXEDON    ; {4C3B}
         BIT   TEXTOFF    ; {4C3B} GRAPHICS SOFT SWITCH
         <<<
*

THE LFCLR MACRO

SUMMARY

Condition Value
Name LFCLR
Type Macro
File MAC.LORES.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose fill the screen with a given color
Input ]1 = Color code
Output none
Dependencies LRGFCLR
Flags Destroyed NZCV
Cycles 139+
Bytes 92
Notes none
See Also LPCLR LRGFCLR LRGF

DETAILS

The LFCLR macro clears the screen in full screen mode, filling it with the specified color in the parameter. Note that this should only be used when the low resolution graphics mode has been set to full screen, not mixed mode. For the latter, see LPCLR.

LISTING 8.07: The LFCLR Macro Source

*
*``````````````````````````````*
* LFCLR                        *
*                              *
* CLEAR THE LOW RESOLUTION     *
* SCREEN IN FULL SCREEN MODE   *
* WITH A GIVEN COLOR.          *
*                              *
* PARAMETERS:                  *
*                              *
*  ]1 = FILL COLOR             *
*                              *
* CYCLES: 135+                 *
* SIZE: 92 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
LFCLR    MAC
         LDA   ]1         ; {4C3B}
         JSR   LRGFCLR    ; {131C89B}
         <<<
*

THE LRGFCLR SUBROUTINE

SUMMARY

Condition Value
Name LRGFCLR
Type Subroutine
File SUB.LRGFCLR.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose fill the screen with a given color
Input .A = Color code
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 125+
Bytes 86
Notes none
See Also LPCLR LRGFCLR LRGF

DETAILS

The LRGFCLR subroutine accepts a color code passed in the .A register and fill the entire screen (or page) with that color. This should be used only when the graphics mode is set to low resolution and full screen, as set by the LRGF macro.

LISTING 8.08: The LRGFCLR Subroutine Source

*``````````````````````````````*
* LRGFCLR       (NATHAN RIGGS) *
*                              *
* FILLS THE LORES SCREEN WITH  *
* THE SPECIFIED COLOR.         *
*                              *
* INPUT:                       *
*                              *
*  .A = BACKGROUND COLOR       *
*                              *
*  NONE                        *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 125+                 *
* SIZE: 86 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]C       EQU   VARTAB     ; TEMPORARY COLOR STORAGE
*
LRGFCLR
         STA   ]C         ; {4C3B} STORE COLOR
         ASL              ; {2C1B} SHIFT LOW BYTE OF COLOR
         ASL              ; {2C1B} INTO THE HIGH BYTE, SINCE
         ASL              ; {2C1B} THE HIGH BYTE IS ALWAYS 0
         ASL              ; {2C1B}
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]C         ; {4C3B} ADD LOW BYTE TO NEW HIGH
         STA   ]C         ; {4C3B} SO IT'S A REPEATING NIBBLE
         LDY   #$78       ; {3C2B} BYTE LENGTH FOR EACH LINE
                          ; THIS ALLOWS FOR FILLING EVERY PIXEL
         LDX   LWP        ; {4C3B} CHECK WHICH PAGE TO CLEAR
         CPX   #2         ; {3C2B} IS IT PAGE 2?
         BEQ   :P2        ; {3C2B} IF SO, CLEAR PAGE 2
                          ; OTHERWISE, ASSUME PAGE 1
:LP1
         STA   $400,Y     ; {4C3B} PLOT FIRST SECTION
         STA   $480,Y     ; {4C3B} PLOT SECOND
         STA   $500,Y     ; {4C3B} THIRD
         STA   $580,Y     ; {4C3B} FOURTH
         STA   $600,Y     ; {4C3B} FIFTH
         STA   $680,Y     ; {4C3B} SIXTH
         STA   $700,Y     ; {4C3B} SEVENTH
         STA   $780,Y     ; {4C3B} EIGHTH
         DEY              ; {2C1B} DECREASE OFFSET COUNTER
         BPL   :LP1       ; {3C2B} IF NOT NEGATIVE, KEEP LOOPING
         JMP   :EXIT      ; {3C3B}
:P2
         LDA   ]C         ; {4C3B}
         LDY   #$78       ; {3C2B}
:LP2
         STA   $800,Y     ; {4C3B} PLOT FIRST SECTION
         STA   $880,Y     ; {4C3B} PLOT SECOND
         STA   $900,Y     ; {4C3B} THIRD
         STA   $980,Y     ; {4C3B} FOURTH
         STA   $0A00,Y    ; {4C3B} FIFTH
         STA   $0A80,Y    ; {4C3B} SIXTH
         STA   $0B00,Y    ; {4C3B} SEVENTH
         STA   $0B80,Y    ; {4C3B} EIGHTH
         DEY              ; {2C1B} DECREASE OFFSET COUNTER
         BPL   :LP2       ; {3C2B} IF NOT NEGATIVE, KEEP LOOPING
:EXIT
         RTS              ; {6C1B}

THE LPCLR MACRO

SUMMARY

Condition Value
Name LPCLR
Type Macro
File MAC.LORES.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose fill the screen with a given color
Input ]1 = Color code
Output none
Dependencies LRGPCLR
Flags Destroyed NZCV
Cycles 147+
Bytes 100
Notes none
See Also LFCLR LRGPCLR LRGP

DETAILS

The LPCLR macro clears the screen in partial screen mode (mixed mode), filling it with the specified color in the parameter. Note that this should only be used when the low resolution graphics mode has been set to partial screen, not full screen. For the latter, see LPCLR.

LISTING 8.09: The LPCLR Macro Source

*
*``````````````````````````````*
* LPCLR                        *
*                              *
* CLEAR A PARTIAL LORES SCREEN *
* WITH A GIVEN COLOR.          *
*                              *
* PARAMETERS:                  *
*                              *
*  ]1 = FILL COLOR             *
*                              *
* CYCLES: 147+                 *
* SIZE: 100 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
LPCLR    MAC
         LDA   ]1         ; {4C3B}
         JSR   LRGPCLR    ; {143C97B}
         <<<
*

THE LRGPCLR SUBROUTINE

SUMMARY

Condition Value
Name LRGPCLR
Type Subroutine
File SUB.LRGPCLR.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose fill the mixed mode screen with a given color
Input .A = Color code
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 137+
Bytes 94
Notes none
See Also LPCLR LRGFCLR LRGP

DETAILS

The LRGPCLRsubroutine is used to clear a mixed mode, or partial, low resolution graphics page. The screen is filled with the color passed via the .A register except for the four text lines at the bottom of the screen, which remain untouched. This subroutine should be used only when mixed mode is in use, as initialized by the LRGP macro.

LISTING 8.10: The LRGPCLR Subroutine Source

*``````````````````````````````*
* LRGPCLR       (NATHAN RIGGS) *
*                              *
* FILLS THE LORES SCREEN WITH  *
* THE SPECIFIED COLOR.         *
*                              *
* INPUT:                       *
*                              *
*  .A = BACKGROUND COLOR       *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 137+                 *
* SIZE: 94 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]C       EQU   VARTAB     ; TEMPORARY COLOR STORAGE
*
LRGPCLR
         STA   ]C         ; {4C3B} STORE COLOR
         ASL              ; {2C1B} SHIFT LOW BYTE OF COLOR
         ASL              ; {2C1B} INTO THE HIGH BYTE, SINCE
         ASL              ; {2C1B} THE HIGH BYTE IS ALWAYS 0
         ASL              ; {2C1B}
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]C         ; {4C3B} ADD LOW BYTE TO NEW HIGH
         STA   ]C         ; {4C3B} SO IT'S A REPEATING NIBBLE
         LDY   #$78       ; {3C2B} BYTE LENGTH FOR EACH LINE
                          ; THIS ALLOWS FOR FILLING EVERY PIXEL
*
         LDX   LWP        ; {4C3B} CHECK WHICH PAGE TO CLEAR
         CPX   #2         ; {3C2B} IS IT PAGE 2?
         BEQ   :P2        ; {3C2B} IF SO, CLEAR PAGE 2
                          ; OTHERWISE, ASSUME PAGE 1
*
:LP1
         STA   $400,Y     ; {4C3B} PLOT FIRST SECTION
         STA   $480,Y     ; {4C3B} PLOT SECOND
         STA   $500,Y     ; {4C3B} THIRD
         STA   $580,Y     ; {4C3B} FOURTH
         CPY   #80        ; {3C2B}
         BPL   :NDB       ; {3C2B}
         STA   $600,Y     ; {4C3B} FIFTH
         STA   $680,Y     ; {4C3B} SIXTH
         STA   $700,Y     ; {4C3B} SEVENTH
         STA   $780,Y     ; {4C3B} EIGHTH
:NDB
         DEY              ; {2C1B} DECREASE OFFSET COUNTER
         BPL   :LP1       ; {3C2B} IF NOT NEGATIVE, KEEP LOOPING
         JMP   :EXIT      ; {3C3B}
*
:P2
         LDA   ]C         ; {4C3B}
         LDY   #$78       ; {3C2B}
:LP2
         STA   $800,Y     ; {4C3B} PLOT FIRST SECTION
         STA   $880,Y     ; {4C3B} PLOT SECOND
         STA   $900,Y     ; {4C3B} THIRD
         STA   $980,Y     ; {4C3B} FOURTH
         CPY   #80        ; {3C2B}
         BPL   :NDB2      ; {3C2B}
         STA   $0A00,Y    ; {4C3B} FIFTH
         STA   $0A80,Y    ; {4C3B} SIXTH
         STA   $0B00,Y    ; {4C3B} SEVENTH
         STA   $0B80,Y    ; {4C3B} EIGHTH
:NDB2
         DEY              ; {2C1B} DECREASE OFFSET COUNTER
         BPL   :LP2       ; {3C2B} IF NOT NEG, KEEP LOOPING
:EXIT
         RTS              ; {6C1B}

THE LPLOT MACRO

SUMMARY

Condition Value
Name LPLOT
Type Macro
File MAC.LORES.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose plot a point on low resolution screen
Input ]1 = X-coordinate
]2 = Y-coordinate
]3 = Color code
Output none
Dependencies LRPLOT
Flags Destroyed NZCV
Cycles 148+
Bytes 107
Notes none
See Also none

DETAILS

The LPLOT macro plots a low-resolution pixel at the given X,Y coordinate in the specified color.

LISTING 8.11: The LPLOT Macro Source

*
*``````````````````````````````*
* LPLOT                        *
*                              *
* PLOT A PIXEL TO THE LORES    *
* SCREEN IN THE GIVEN COLOR AT *
* THE GIVEN COORDINATES.       *
*                              *
* PARAMETERS:                  *
*                              *
*  ]1 = X COORDINATE           *
*  ]2 = Y COORDINATE           *
*  ]3 = COLOR                  *
*                              *
* CYCLES: 148+                 *
* SIZE: 107 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
LPLOT    MAC
         LDX   ]1         ; {4C3B}
         LDY   ]2         ; {4C3B}
         LDA   ]3         ; {4C3B}
         JSR   LRPLOT     ; {136C98B}
         <<<
*

THE LRPLOT SUBROUTINE

SUMMARY

Condition Value
Name LRPLOT
Type Subroutine
File SUB.LRPLOT.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose Plot a point to the low resolution screen
Input BPAR1 = Color
BPAR2 = X-coordinate
BPAR3 = Y-coordinate
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 130+
Bytes 95
Notes none
See Also LPLOT

DETAILS

The LRPLOT subroutine plots a point in a given color at the provided X, Y coordinate.

LISTING 8.12: The LRPLOT Subroutine Source

*``````````````````````````````*
* LRPLOT        (NATHAN RIGGS) *
*                              *
* PLOTS A LOW RESOLUTION       *
* PIXEL AT THE GIVEN COLOR AND *
* COORDINATES.                 *
*                              *
* INPUT:                       *
*                              *
*  BPAR1 = COLOR               *
*  BPAR2 = X COORDINATE        *
*  BPAR3 = Y COORDINATE        *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 130+                 *
* SIZE: 95 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]COLOR   EQU   BPAR1      ; PLOT COLOR
]X       EQU   BPAR2      ; X COORDINATE
]Y       EQU   BPAR3      ; Y COORDINATE
]MASK    EQU   VARTAB     ; MASK FOR ISOLATING NIBBLE
]COLMASK EQU   VARTAB+2   ; COLOR MASK
]PAGEOFF EQU   VARTAB+4   ; PAGE OFFSET
*
LRPLOT
         STY   ]Y         ; {3C2B} Y POSITION PASSED IN .Y
         STX   ]X         ; {3C2B} X POSITION PASSED IN .X
         STA   ]COLOR     ; {3C2B} COLOR PASSED IN .A
         LDA   ]COLOR     ; {3C2B} TAKE THE COLOR SENT
         ASL              ; {2C1B} AND MOVE IT LEFT 4 BITS
         ASL              ; {2C1B} TO THE HIGH BYTE
         ASL              ; {2C1B}
         ASL              ; {2C1B}
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]COLOR     ; {3C2B} NOW ADD LOW BYTE BACK, MEANING
         STA   ]COLOR     ; {3C2B} THE COLOR WILL REPEAT NIBBLES
         LDA   LWP        ; {4C3B} TEST WHICH PAGE IS THE WORKING
         CMP   #2         ; {3C2B} PAGE--IF NOT #2, ASSUME PAGE 1
         BNE   :PG1       ; {3C2B}
         LDA   #4         ; {3C2B} ADD TO BASE TO PLOT TO PAGE 2
         STA   ]PAGEOFF   ; {4C3B} STORE AS PAGE OFFSET
         JMP   :CNT       ; {3C3B}
:PG1
         LDA   #0         ; {3C2B} PAGE 1 HAS NO OFFSET, SO #0
         STA   ]PAGEOFF   ; {4C3B}
:CNT
         LDA   ]Y         ; {3C2B} GET Y COORDINATE
         LSR              ; {2C1B} SHIFT BOTTOM BIT TO CARRY
         BCC   :EVEN      ; {3C2B} IF CARRY = 0, ROW IS EVEN
         LDX   #$F0       ; {3C2B} ELSE, IT IS ODD; SO MASK
                          ; THE LEFT NIBBLE
         BCS   :PLOT      ; {3C2B} IF CARRY SET, BR TO PLOTTING
:EVEN
         LDX   #$0F       ; {3C2B} EVEN, SO MASK LOW BYTE
:PLOT
         STX   ]MASK      ; {4C3B} STORE THE EVEN OR ODD MASK
         ASL              ; {2C1B} SHIFT CARRY BACK INTO BYTE
         TAY              ; {2C1B} HOLD VALUE INTO .Y
         LDA   LROFF,Y    ; {5C3B} GET LORES MEMORY ADDRESS
         CLC              ; {2C1B} CLEAR THE CARRY
         ADC   ]X         ; {3C2B} ADD THE X COORDINATE
         STA   GBASLO     ; {4C3B} STORE LOW BYTE FOR GBASCALC
         INY              ; {2C1B} INCREASE Y OFFSET
         LDA   LROFF,Y    ; {5C3B} GET LORESS MEMORY ADDRESS
         ADC   ]PAGEOFF   ; {4C3B} ADJUST FOR PAGE & CARRY HIGH
         STA   GBASHI     ; {4C3B} STORE HIGH BYTE FOR GBASCALC
         LDY   #0         ; {3C2B}
         LDA   ]MASK      ; {4C3B} RELOAD THE MASK
         EOR   #$FF       ; {2C2B} EXCLUSIVE OR THE MASK
         AND   (GBASLO),Y ; {6C2B} AND THE LOW FOR GBAS
         STA   ]COLMASK   ; {4C3B} STORE THE COLOR MASK
         LDA   ]COLOR     ; {3C2B} LOAD THE COLOR
         AND   ]MASK      ; {4C3B} AND THE MASK
         ORA   ]COLMASK   ; {4C3B} OR WITH THE COLOR MASK
         STA   (GBASLO),Y ; {6C2B} STORE INTO GBAS LOW BYTE
         RTS              ; {6C1B}

THE LLINE MACRO

SUMMARY

Condition Value
Name LLINE
Type Macro
File MAC.LORES.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose plot a diagonal line on low resolution screen
Input ]1 = X-origin
]2 = X-destination
]3 = Y-origin
]4 = Y-destination
]5 = color
Output none
Dependencies LRBLINE
Flags Destroyed NZCV
Cycles 441+
Bytes 297
Notes none
See Also LRBLINE

DETAILS

The LLINE macro creates a line with an arbitrary slope in low-resolution graphics mode.

LISTING 8.13: The LLINE Macro Source

*
*``````````````````````````````*
* LLINE                        *
*                              *
* CREATES A DIAGONAL LINE IN   *
* LORES GRAPHICS MODE VIA THE  *
* BRESSANHAM LINE ALGORITHM.   *
*                              *
* PARAMETERS:                  *
*                              *
*  ]1 = X ORIGIN               *
*  ]2 = X DESTINATION          *
*  ]3 = Y ORIGIN               *
*  ]4 = Y DESTINATION          *
*  ]5 = COLOR                  *
*                              *
* CYCLES: 441+                 *
* SIZE: 297 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
LLINE    MAC
         LDA   ]1         ; {4C3B}
         STA   WPAR1      ; {3C2B}
         LDA   ]2         ; {4C3B}
         STA   WPAR1+1    ; {3C2B}
         LDA   ]3         ; {4C3B}
         STA   WPAR2      ; {3C2B}
         LDA   ]4         ; {4C3B}
         STA   WPAR2+1    ; {3C2B}
         LDA   ]5         ; {4C3B}
         STA   BPAR1      ; {3C2B}
         JSR   LRBLINE    ; {400C152B}
         <<<
*

THE LRBLINE SUBROUTINE

SUMMARY

Condition Value
Name LRBLINE
Type Subroutine
File SUB.LRBLINE.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose plot a diagonal low resolution line
Input WPAR1 = X-origin
WPAR1+1 = Y-origin
WPAR2 = X-destination
WPAR2+1 = Y-destination
BPAR1 = Color
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 400+
Bytes 152
Notes none
See Also LLINE

DETAILS

The LRBLINE subroutine uses Bressenham's line algorithm to create a line with an arbitrary slope on the low-resolution screen.

LISTING 8.14: The LRBLINE Subroutine Source

*``````````````````````````````*
* LRBLINE       (NATHAN RIGGS) *
*                              *
* THIS SUBROUTINE USES THE     *
* BRESSENHAM LINE ALGORITHM TO *
* DRAW A DIAGONAL LINE FROM    *
* PONT X1,Y1 TO X2,Y2 IN THE   *
* SPECIFIED COLOR.             *
*                              *
* INPUT:                       *
*                              *
*  WPAR1 = X START POSITION    *
*  WPAR1+1 = Y START POSITION  *
*  WPAR2 = X ENDING POINT      *
*  WPAR2+1 = Y ENDING POINT    *
*  BPAR1 = COLOR OF LINE       *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 400+                 *
* SIZE: 152 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]X0      EQU   WPAR1      ; STARTING X POINT
]Y0      EQU   WPAR1+1    ; STARTING Y POINT
]X1      EQU   WPAR2      ; ENDING X POINT
]Y1      EQU   WPAR2+1    ; ENDING Y POINT
]COLOR   EQU   BPAR1      ; COLOR OF LINE
*
]DX      EQU   ADDR1      ; CHANGE IN X
]DY      EQU   ADDR1+1    ; CHANGE IN Y
]SX      EQU   ADDR2      ; X POSITION STEP
]SY      EQU   ADDR2+1    ; Y POSITION STEP
]ERR     EQU   ADDR3      ; SLOPE ERROR
]ERRX2   EQU   ADDR3+1    ; COMPARISON COPY OF ]ERR
*
LRBLINE
         LDA   ]X1        ; {3C2B} SUBTRACT X0 FROM X1
         SEC              ; {2C1B}
         SBC   ]X0        ; {3C2B}
         BPL   :ABSF1     ; {3C2B} IF POS, SKIP ABSOLUTE VALUE
         SEC              ; {2C1B} SUBTRACT 1 AND EOR #$FF
         SBC   #1         ; {3C2B} TO GET THE ABSOLUTE VALUE
         EOR   #$FF       ; {2C2B}
:ABSF1
         STA   ]DX        ; {3C2B} STORE VALUE AS CHANGE IN X
*
         LDA   ]Y1        ; {3C2B} SUBTRACT Y0 FROM Y1
         SEC              ; {2C1B}
         SBC   ]Y0        ; {3C2B}
         BPL   :ABSF2     ; {3C2B} IF POSITIVE, SKIP ABS VALUE
         SEC              ; {2C1B} SUBTRACT 1 AND EOR #$FF
         SBC   #1         ; {3C2B} TO GET THE ABSOLUTE VALUE
         EOR   #$FF       ; {2C2B}
:ABSF2
         STA   ]DY        ; {3C2B} STORE VALUE AS CHANGE IN Y
*
         LDA   ]DX        ; {3C2B} ]ERR = DX - DY
         SEC              ; {2C1B}
         SBC   ]DY        ; {3C2B}
         STA   ]ERR       ; {3C2B}
*
         LDX   #$FF       ; {3C2B} .X = -1
         LDA   ]X0        ; {3C2B} IF X0 >= X1
         CMP   ]X1        ; {3C2B}
         BCS   :NONEG     ; {3C2B} THEN SKIP CHANGE IN .X
         LDX   #$01       ; {3C2B} ELSE, CHANGE .X TO +1
:NONEG   STX   ]SX        ; {3C2B} STORE EITHER -1 OR +1 IN SX
*
         LDX   #$FF       ; {3C2B} .X = -1
         LDA   ]Y0        ; {3C2B} IF Y0 >= Y1
         CMP   ]Y1        ; {3C2B}
         BCS   :NONEG2    ; {3C2B} THEN SKIP CHANGE IN .X
         LDX   #$01       ; {3C2B} ELSE CHANGE .X TO +1
:NONEG2  STX   ]SY        ; {3C2B} STORE EITHER -1 OR +1 IN SY
*
** MAIN LOOP
*
:LOOP
         LDA   ]COLOR     ; {3C2B} .A = COLOR TO PASS
         LDY   ]Y0        ; {3C2B} .Y = Y POS TO PASS
         LDX   ]X0        ; {3C2B} .X = X POS TO PASS
         JSR   LOCPLOT    ; {168C109B} JUMP TO PLOTTING ROUTINE
*
         LDA   ]X0        ; {3C2B} IF X0 != X1, KEEP LOOPING
         CMP   ]X1        ; {3C2B}
         BNE   :CONT      ; {3C2B}
         LDA   ]Y0        ; {3C2B} IF Y0 != Y1, KEEP LOOPING
         CMP   ]Y1        ; {3C2B}
         BNE   :CONT      ; {3C2B}
         JMP   TBLEXIT    ; {3C3B} ELSE, EXIT LOOP
:CONT
*
         LDA   ]ERR       ; {3C2B} ]ERR = ]ERR * 2
         ASL              ; {2C1B}
         STA   ]ERRX2     ; {3C2B}
*
         LDA   ]DY        ; {3C2B} NEGATE ]DY
         EOR   #$FF       ; {3C2B}
         CLC              ; {2C1B}
         ADC   #1         ; {3C2B}
         SEC              ; {2C1B} USE SBC FOR SIGNED COMPARE
         SBC   ]ERRX2     ; {3C2B}
         BMI   :NFSETX    ; {3C2B} IF N FLAG SET, GO CHECK V FLAG
         BVC   :GEX       ; {3C2B} IF V = 0 & N = 0, VAL >= .A REG
:LTX                      ;        N = 0 AND V = 1, SO LESS THAN
         LDA   ]ERR       ; {3C2B} ]ERR = ]ERR - ]DY
         SEC              ; {2C1B}
         SBC   ]DY        ; {3C2B}
         STA   ]ERR       ; {3C2B}
         LDA   ]X0        ; {3C2B} X0 = X0 + SX
         CLC              ; {2C1B}
         ADC   ]SX        ; {3C2B}
         STA   ]X0        ; {3C2B}
         JMP   :GEX       ; {3C3B}
:NFSETX  BVC   :LTX       ; {3C2B} IF N = 1 & V = 0, VAL < .A REG
:GEX                      ;        N = 1 & V = 1, SO VAL >= .A REG
*
         LDA   ]ERRX2     ; {3C2B} IF ER * 2 < DX, GOTO :LTY
         SEC              ; {2C1B}
         SBC   ]DX        ; {3C2B}
         BMI   :SKIPY     ; {3C2B} IF N FLAG = 1, GO CHECK V FLAG
         BVC   :GEY       ; {3C2B} N = 0 & V = 0, SO VAL >= .A REG
:LTY     LDA   ]ERR       ; {3C2B} N = 0 AND V = 1, SO LESS THAN
         CLC              ; {2C1B}
         ADC   ]DX        ; {3C2B} ]ERR = ]ERR + ]DX
         STA   ]ERR       ; {3C2B}
         LDA   ]Y0        ; {3C2B} ]Y0 = ]Y0 + ]SY
         CLC              ; {2C1B}
         ADC   ]SY        ; {3C2B}
         STA   ]Y0        ; {3C2B}
         JMP   :GEY       ; {3C3B}
:SKIPY   BVC   :LTY       ; {3C2B} IF N = 1 & V = 0, VAL < .A REG
:GEY                      ; {3C2B} N = 1 & V = 1, SO VAL >= .A REG
*
         JMP   :LOOP      ; {3C3B}
TBLEXIT
         RTS              ; {6C1B}


THE LCIRC MACRO

SUMMARY

Condition Value
Name LCIRC
Type Macro
File MAC.LORES.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose plot a circle on low resolution screen
Input ]1 = Center X-position
]2 = Center Y-position
]3 = Circle radius
]4 = Color
Output none
Dependencies LRCIRCLE
Flags Destroyed NZCV
Cycles 2437+
Bytes 520
Notes none
See Also LRCIRCLE

DETAILS

The LCIRC macro draws a circle on the low resolution screen with a center X, Y position and a given radius, plotted in the specified color.

LISTING 8.15: The LCIRC Macro Source

*
*``````````````````````````````*
* LCIRC                        *
*                              *
* CREATE A CIRCLE IN LORES     *
* GRAPHICS MODE AT THE CENTER  *
* COORDINATES AND RADIUS GIVEN *
* AS WELL AS THE COLOR. BASED  *
* ON BRESSENHAM'S CIRCLE ALGO. *
*                              *
* PARAMETERS:                  *
*                              *
*  ]1 = CENTER X POSITION      *
*  ]2 = CENTER Y POSITION      *
*  ]3 = CIRCLE RADIUS          *
*  ]4 = COLOR                  *
*                              *
* CYCLES: 2437+                *
* SIZE: 520 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
LCIRC    MAC
         LDA   ]1         ; {4C3B}
         STA   WPAR1      ; {3C2B}
         LDA   ]2         ; {4C3B}
         STA   WPAR2      ; {3C2B}
         LDA   ]3         ; {4C3B}
         STA   WPAR3      ; {3C2B}
         LDA   ]4         ; {4C3B}
         STA   BPAR2      ; {3C2B}
         JSR   LRCIRCLE   ; {2410C500B}
         <<<
*

THE LRCIRCLE SUBROUTINE

SUMMARY

Condition Value
Name LRCIRCLE
Type Subroutine
File SUB.LRCIRCLE.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose plot a low resolution circle
Input WPAR1 = X-center
WPAR2 = Y-center
WPAR3 = Radius
BPAR1 = Color
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 2404+
Bytes 457
Notes none
See Also LCIRC

DETAILS

The LRCIRCLE subroutine uses Bressenham's circle algorithm to create a circle with an X, Y center and a given radius and color.

LISTING 8.16: The LRCIRCLE Subroutine Source

*``````````````````````````````*
* LRCIRCLE      (NATHAN RIGGS) *
*                              *
* THIS SUBROUTINE DRAWS A      *
* CIRCLE ON THE CURRENT WORK   *
* PAGE AT THE GIVEN COORDINATE *
* AND COLOR.                   *
*                              *
* INPUT:                       *
*                              *
*  WPAR1 = CIRCLE X CENTER     *
*  WPAR2 = CIRCLE Y CENTER     *
*  WPAR3 = CIRCLE RADIUS       *
*  BPAR1 = CIRCLE COLOR        *
*                              *
* OUTPUT:                      *
*                              *
*  NONE                        *
*                              *
* DESTROY: AXYNVBDIZCMS        *
*          ^^^^^   ^^^         *
*                              *
* CYCLES: 2404+                *
* SIZE: 457 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]XC      EQU   WPAR1      ; CIRCLE X CENTER
]YC      EQU   WPAR2      ; CIRCLE Y CENTER
]R       EQU   WPAR3      ; RADIUS
]COLOR   EQU   BPAR2      ; COLOR
*
]YY      EQU   VARTAB+5   ; WORKING Y POSITION
]XX      EQU   VARTAB+7   ; WORKING X POSITION
]DX      EQU   VARTAB+9   ; CHANGE IN X
]DY      EQU   VARTAB+11  ; CHANGE IN Y
]ERR     EQU   VARTAB+13  ; ERROR POSSIBILITY
]DIAM    EQU   VARTAB+15  ; CIRCLE DIAMETER
]XT      EQU   VARTAB+17  ; NEGATIVE OF X
]YT      EQU   VARTAB+19  ; NEGATIVE OF Y
*
LRCIRCLE
*
** FIRST, INITIALIZE VARIABLES
*
         LDA   #0         ; {3C2B} CLEAR YPOS
         STA   ]YY        ; {4C3B}
         LDA   ]R         ; {4C3B} LOAD RADIUS
         STA   ]XX        ; {4C3B} X = RADIUS
         STA   ]ERR       ; {4C3B} ERROR = RADIUS
         ASL              ; {2C1B} R * 2
         STA   ]DIAM      ; {4C3B} STORE DIAMETER
*
** NOW DRAW FIRST PART OF CIRCLE
*
** CALCULATE -X AND -Y
*
         LDA   ]XX        ; {4C3B} GET XPOS
         EOR   #$FF       ; {2C2B} NEGATE
         CLC              ; {2C1B}
         ADC   #1         ; {3C2B}
         STA   ]XT        ; {4C3B} STORE NEGATED IN XT
         LDA   ]YY        ; {4C3B} GET YPOS
         EOR   #$FF       ; {2C2B} NEGATE
         CLC              ; {2C1B}
         ADC   #1         ; {3C2B}
         STA   ]YT        ; {4C3B} STORE NEGATED IN YT
*
** PLOT XC+X,YC
*
         LDA   ]XC        ; {4C3B} LOAD CIRCLE CENTER XPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]XX        ; {4C3B} ADD CURRENT XPOS
         TAX              ; {2C1B}
         TAY              ; {2C1B} TRANSER TO .Y
         LDA   ]YC        ; {4C3B} LOAD CIRCLE CENTER YPOS
         TAY              ; {2C1B}
         LDA   ]COLOR     ; {3C2B}
         JSR   LOCPLOT    ; {168C109B}
*
** PLOT XC-X,YC
*
         LDA   ]XC        ; {4C3B} LOAD CIRCLE CENTER XPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]XT        ; {4C3B} ADD NEGATED CURRENT XPOS
         TAX              ; {2C1B}
         TAY              ; {2C1B} AND .Y
         LDA   ]YC        ; {4C3B} LOAD CIRCLE CENTER YPOS
         TAY              ; {2C1B}
         LDA   ]COLOR     ; {3C2B}
         JSR   LOCPLOT    ; {168C0B}
*
** PLOT XC,YC+X
*
         LDA   ]XC        ; {4C3B} LOAD CIRCLE CENTER XPOS
         TAY              ; {2C1B} TRANSFER TO .Y
         TAX              ; {2C1B} AND .X
         LDA   ]YC        ; {4C3B} LOAD CIRCLE CENTER YPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]XX        ; {4C3B} ADD CURRENT XPOS
         TAY              ; {2C1B}
         LDA   ]COLOR     ; {3C2B}
         JSR   LOCPLOT    ; {168C0B}
*
** PLOT XC,YC-X
*
         LDA   ]XC        ; {4C3B} LOAD CIRCLE CENTER XPOS
         TAY              ; {2C1B} TRANSFER TO .Y
         TAX              ; {2C1B} AND .X
         LDA   ]YC        ; {4C3B} LOAD CIRCLE CENTER YPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]XT        ; {4C3B} ADD NEGATED CURRENT XPOS
         TAY              ; {2C1B}
         LDA   ]COLOR     ; {3C2B}
         JSR   LOCPLOT    ; {168C0B}
*
** NOW LOOP UNTIL CIRCLE IS FINISHED
*
:LOOP
*
** CHECK IF CIRCLE FINISHED
*
         LDA   ]YY        ; {4C3B} IF Y > X
         CMP   ]XX        ; {3C2B}
         BCC   :LPCONT    ; {3C2B} CONTINUE LOOPING
         JMP   :EXIT      ; {3C3B} OTHERWISE, CIRCLE DONE
:LPCONT
:STEPY                    ; STEP THE Y POSITION
         LDA   ]YY        ; {4C3B} LOAD YPOS
         ASL              ; {2C2B} MULTIPLY BY 2
*CLC
         ADC   #1         ; {3C2B} ADD +1
         STA   ]DY        ; {4C3B} STORE CHANGE OF Y
         INC   ]YY        ; {6C3B} INCREASE YPOS
         LDA   ]DY        ; {4C3B} NEGATE
         EOR   #$FF       ; {3C2B}
         CLC              ; {2C1B}
         ADC   #1         ; {3C2B}
         ADC   ]ERR       ; {4C3B} ADD ERR
         STA   ]ERR       ; {4C3B} ERR = ERR - DY
         BPL   :PLOT      ; {3C2B} IF ERR IS +, SKIP TO PLOT
:STEPX
         LDA   ]XX        ; {4C3B} LOAD XPOS
         ASL              ; {2C2B} MULTIPLY BY 2
         EOR   #$FF       ; {2C2B} NEGATE
         CLC              ; {2C1B}
         ADC   #1         ; {3C2B}
         ADC   #1         ; {3C2B} (X*2) + 1
         STA   ]DX        ; {4C3B} STORE CHANGE OF X
         DEC   ]XX        ; {6C3B} DECREASE YPOS
         LDA   ]DX        ; {4C3B} NEGATE
         EOR   #$FF       ; {2C2B}
         CLC              ; {2C1B}
         ADC   #1         ; {3C2B}
         ADC   ]ERR       ; {4C3B} ADD ERR
         STA   ]ERR       ; {4C3B} ERR = ERR - DX
*
:PLOT
*
** NOW CALCULATE -X AND -Y
*
         LDA   ]XX        ; {4C3B}
         EOR   #$FF       ; {2C2B} NEGATE
         CLC              ; {2C1B}
         ADC   #1         ; {3C2B}
         STA   ]XT        ; {4C3B}
         LDA   ]YY        ; {4C3B}
         EOR   #$FF       ; {2C2B} NEGATE
         CLC              ; {2C1B}
         ADC   #1         ; {3C2B}
         STA   ]YT        ; {4C3B}
*
** NOW PLOT CIRCLE OCTANTS
*
** PLOT XC+X,YC+Y
*
         LDA   ]XC        ; {4C3B} LOAD CIRCLE CENTER XPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]XX        ; {4C3B} ADD CURRENT XPOS
         TAY              ; {2C1B} TRANSFER TO .Y
         TAX              ; {2C1B} AND .X
         LDA   ]YC        ; {4C3B} LOAD CIRCLE CENTER YPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]YY        ; {4C3B} ADD CURRENT YPOS
         TAY              ; {2C1B}
         LDA   ]COLOR     ; {3C2B}
         JSR   LOCPLOT    ; {168C0B}
*
** PLOT XC-X,YC+Y
*
         LDA   ]XC        ; {4C3B} LOAD CIRCLE CENTER XPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]XT        ; {4C3B} ADD NEGATED CURRENT XPOS
         TAY              ; {2C1B} TRANSFER TO .Y
         TAX              ; {2C1B} AND TO .X
         LDA   ]YC        ; {4C3B} LOAD CIRCLE CENTER YPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]YY        ; {4C3B} ADD CURRENT YPOS
         TAY              ; {2C1B}
         LDA   ]COLOR     ; {3C2B}
         JSR   LOCPLOT    ; {168C0B}
*
** PLOT XC-X,YC-Y
*
         LDA   ]XC        ; {4C3B} LOAD CIRCLE CENTER XPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]XT        ; {3C2B} ADD NEGATED CURRENT XPOS
         TAY              ; {2C1B} TRANSFER TO .Y
         TAX              ; {2C1B} AND .X
         LDA   ]YC        ; {4C3B} LOAD CIRCLE CENTER YPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]YT        ; {4C3B} ADD NEGATED CURRENT YPOS
         TAY              ; {2C1B}
         LDA   ]COLOR     ; {3C2B}
         JSR   LOCPLOT    ; {168C0B}
*
** PLOT XC+X,YC-Y
*
         LDA   ]XC        ; {4C3B} LOAD CIRCLE CENTER XPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]XX        ; {4C3B} ADD CURRENT XPOS
         TAY              ; {2C1B} TRANSFER TO .Y
         TAX              ; {2C1B} AND .X
         LDA   ]YC        ; {4C3B} LOAD CIRCLE CENTER YPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]YT        ; {4C3B} ADD NEGATE CURRENT YPOS
         TAY              ; {2C1B}
         LDA   ]COLOR     ; {3C2B}
         JSR   LOCPLOT    ; {168C0B}
*
** PLOT XC+Y,YC+X
*
         LDA   ]XC        ; {4C3B} LOAD CIRCLE CENTER XPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]YY        ; {4C3B} ADD CURRENT YPOS
         TAX              ; {2C1B} TRANSFER TO .X
         TAY              ; {2C1B} AND .Y
         LDA   ]YC        ; {4C3B} LOAD CIRCLE CENTER YPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]XX        ; {4C3B} ADD CURRENT XPOS
         TAY              ; {2C1B}
         LDA   ]COLOR     ; {3C2B}
         JSR   LOCPLOT    ; {168C0B}
*
** PLOT XC-Y,YC+X
*
         LDA   ]XC        ; {4C3B} LOAD CIRCLE CENTER XPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]YT        ; {4C3B} ADD NEGATED CURRENT YPOS
         TAX              ; {2C1B} TRANSFER TO .X
         TAY              ; {2C1B} AND .Y
         LDA   ]YC        ; {4C3B} LOAD CIRCLE CENTER YPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]XX        ; {4C3B} ADD CURRENT XPOS
         TAY              ; {2C1B}
         LDA   ]COLOR     ; {3C2B}
         JSR   LOCPLOT    ; {168C0B}
*
** PLOT XC-Y,YC-X
*
         LDA   ]XC        ; {4C3B} LOAD CIRCLE CENTER XPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]YT        ; {4C3B} ADD NEGATED CURRENT YPOS
         TAX              ; {2C1B} TRANSFER TO .X
         TAY              ; {2C1B} AND .Y
         LDA   ]YC        ; {4C3B} LOAD CIRCLE CENTER YPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]XT        ; {4C3B} ADD NEGATED CURRENT XPOS
         TAY              ; {2C1B}
         LDA   ]COLOR     ; {3C2B}
         JSR   LOCPLOT    ; {168C0B}
*
** PLOT XC+Y,YC-X
*
         LDA   ]XC        ; {4C3B} LOAD CIRCLE CENTER XPOS
         CLC              ; {2C1B} CLEAR CARRY
         ADC   ]YY        ; {4C3B} ADD CURRENT YPOS
         TAY              ; {2C1B} TRANSFER TO .Y
         TAX              ; {2C1B} AND .X
         LDA   ]YC        ; {4C3B} LOAD CIRCLE CENTER YPOS
         CLC              ; {2C1B}
         ADC   ]XT        ; {4C3B} ADD NEGATED CURRENT XPOS
         TAY              ; {2C1B}
         LDA   ]COLOR     ; {3C2B}
         JSR   LOCPLOT    ; {168C0B}
         JMP   :LOOP      ; {3C3B}
:EXIT
         RTS              ; {6C1B}

THE LVLIN MACRO

SUMMARY

Condition Value
Name LVLIN
Type Macro
File MAC.LORES.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose plot a vertical line to the low resolution screen
Input ]1 = Y-origin
]2 = Y-destination
]3 = X-coordinate
]4 = color
Output none
Dependencies LRVLINE
Flags Destroyed NZCV
Cycles 250+
Bytes 164
Notes none
See Also LRVLINE

DETAILS

The LVLIN macro creates a vertical line from a Y-origin to a Y-destination at a given X-coordinate on the low resolution screen. When it is known that a line will be perfectly vertical, this macro should be used instead of the more cycle-expensive LLINE macro.

LISTING 8.17: The LVLIN Macro Source

*
*``````````````````````````````*
* LVLIN                        *
*                              *
* CREATE A LORES VERTICAL LINE *
* FROM A Y ORIGIN TO DEST IN   *
* THE GIVEN COLOR.             *
*                              *
* PARAMETERS:                  *
*                              *
*  ]1 = Y ORIGIN               *
*  ]2 = Y DESTINATION          *
*  ]3 = X COORDINATE           *
*  ]4 = COLOR                  *
*                              *
* CYCLES: 250+                 *
* SIZE: 164 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
LVLIN    MAC
         LDA   ]1         ; {4C3B}
         STA   WPAR1      ; {3C2B}
         LDA   ]2         ; {4C3B}
         STA   WPAR1+1    ; {3C2B}
         LDA   ]3         ; {4C3B}
         STA   BPAR1      ; {3C2B}
         LDA   ]4         ; {4C3B}
         STA   BPAR2      ; {3C2B}
         JSR   LRVLINE    ; {222C144B}
         <<<
*

THE LRVLINE SUBROUTINE

SUMMARY

Condition Value
Name LRCIRCLE
Type Subroutine
File SUB.LRVLINE.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose plot a low resolution vertical line
Input WPAR1 = Y-origin
WPAR1+1 = Y-destination
BPAR1 = X-position
BPAR2 = Color
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 216
Bytes 141
Notes none
See Also LVLIN

DETAILS

The LRVLINE subroutine plots a vertical line from an origin to a destination at the given column. When possible, this should be used instead of the LLINE macro, as this macro costs significantly fewer cycles and bytes.

LISTING 8.18: The LRVLINE Subroutine Source

*``````````````````````````````*
* LRVLINE       (NATHAN RIGGS) *
*                              *
* PLOT A VERTICAL LINE IN LOW  *
* RESOLUTION GRAPHICS MODE.    *
*                              *
* INPUT:                       *
*                              *
*  WPAR1 = Y COORDINATE ORIGIN *
*  WPAR1+1 = Y DESTINATION     *
*  BPAR1 = X POSITION          *
*  BPAR2 = COLOR TO PLOT       *
*                              *
* OUTPUT:                      *
*                              *
*  NONE                        *
*                              *
* DESTROY: AXYNVBDIZCMS        *
*          ^^^^^   ^^^         *
*                              *
* CYCLES: 216+                 *
* SIZE: 141 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]Y1      EQU   WPAR1      ; Y COORDINATE ORIGIN
]Y2      EQU   WPAR1+1    ; Y COORDINATE DESTINATION
]X1      EQU   BPAR1      ; X COORDINATE
]COLOR   EQU   BPAR2      ; COLOR OF LINE
]X       EQU   VARTAB+6   ; WORKING XPOS
]Y       EQU   VARTAB+8   ; WORKING YPOS
*
LRVLINE
*
         LDA   ]X1        ; {4C3B} LOAD ROW
         STA   ]X         ; {4C3B} AND STORE IN WORKING VARIABLE
         LDY   ]Y1        ; {4C3B} LOAD Y START POS
         STY   ]Y         ; {4C3B} STORING IN WORKING Y VAR
:LOOP
         LDA   ]COLOR     ; {4C3B} LOAD COLOR
         LDX   ]X         ; {4C3B} LOAD X INTO .X
         LDY   ]Y         ; {4C3B} LOAD Y INTO .Y
         JSR   LOCPLOT    ; {168C109B} GOSUB PLOTTING SUBROUTINE
         INC   ]Y         ; {5C2B} INCREASE Y INDEX
         LDY   ]Y         ; {4C3B} LOAD Y FOR COMPARISON
         CPY   ]Y2        ; {3C2B} IF Y < Y2
         BNE   :LOOP      ; {3C2B} LOOP; ELSE, CONTINUE
:EXIT
         RTS              ; {6C1B}

THE LHLIN MACRO

SUMMARY

Condition Value
Name LHLIN
Type Macro
File MAC.LORES.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose plot a horizontal line to the low resolution screen
Input ]1 = X-origin
]2 = X-destination
]3 = Y-coordinate
]4 = color
Output none
Dependencies LRHLINE
Flags Destroyed NZCV
Cycles 246+
Bytes 161
Notes none
See Also LRHLINE

DETAILS

The LHLIN macro creates a horizontal line from an X-origin to an X-destination at a given Y-coordinate on the low resolution screen. When it is known that a line will be perfectly horizonal, this macro should be used instead of the more cycle-expensive LLINE macro.

LISTING 8.19: The LHLIN Macro Source

*
*``````````````````````````````*
* LHLIN                        *
*                              *
* CREATE A HORIZONTAL LINE IN  *
* LORES MODE FROMA GIVEN X     *
* ORIGIN TO DESTINATION AT A   *
* Y COORDINATE, IN GIVEN COLOR *
*                              *
* PARAMETERS:                  *
*                              *
*  ]1 = X ORIGIN               *
*  ]2 = X DESTINATION          *
*  ]3 = Y COORDINATE           *
*  ]4 = COLOR                  *
*                              *
* CYCLES: 246+                 *
* SIZE: 161 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
LHLIN    MAC
         LDA   ]1         ; {4C3B}
         STA   WPAR1      ; {3C2B}
         LDA   ]2         ; {4C3B}
         STA   WPAR1+1    ; {3C2B}
         LDA   ]3         ; {4C3B}
         STA   BPAR1      ; {3C2B}
         LDA   ]4         ; {4C3B}
         STA   BPAR2      ; {3C2B}
         JSR   LRHLINE    ; {218C141B}
         <<<
*

THE LRHLINE SUBROUTINE

SUMMARY

Condition Value
Name LRHLINE
Type Subroutine
File SUB.LRHLINE.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose plot a low resolution horizontal line
Input WPAR1 = X-origin
WPAR1+1 = X-destination
BPAR1 = Y-position
BPAR2 = Color
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 218+
Bytes 141
Notes none
See Also LHLIN

DETAILS

The LRHLINE subroutine plots a horizontal line from an origin to a destination at the given row. When possible, this should be used instead of the LLINE macro, as this macro costs significantly fewer cycles and bytes.

LISTING 8.20: The LRHLINE Subroutine Source

*``````````````````````````````*
* LRHLINE       (NATHAN RIGGS) *
*                              *
* CREATES A HORIZONTAL LINE IN *
* LOW RESOLUTION MODE FROM AN  *
* X ORIGIN TO X DESTINATION AT *
* A CONSTANT Y POSITION IN THE *
* GIVEN COLOR.                 *
*                              *
* INPUT:                       *
*                              *
*  WPAR1 = X ORIGIN            *
*  WPAR1+1 = X DESTINATION     *
*  BPAR1 = Y POSITION          *
*  BPAR2 = COLOR               *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 218+                 *
* SIZE: 141 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]X1      EQU   WPAR1      ; X COORD SOURCE
]X2      EQU   WPAR1+1    ; X COORD DESTINATION
]Y1      EQU   BPAR1      ; STATIC Y POSITION
]COLOR   EQU   BPAR2      ; LINE COLOR
]X       EQU   VARTAB     ; WORKING X VALUE
]Y       EQU   VARTAB+1   ; WORKING Y VALUE
*
LRHLINE
*
         LDA   ]Y1        ; {4C3B} LOAD Y COORDINATE
         STA   ]Y         ; {4C3B} TRANSFER TO WORKING VARIABLE
         LDY   ]X1        ; {4C3B} LOAD X ORIGIN COORDINATE
         STY   ]X         ; {4C3B} STORE IN WORKING VARIABLE
:LOOP
         LDA   ]COLOR     ; {4C3B} LOAD THE PLOTTING COLOR
         LDX   ]X         ; {4C3B} GET CURRENT X COORDINATE
         LDY   ]Y         ; {4C3B} GET CURRENT Y COORDINATE
         JSR   LOCPLOT    ; {168C109B} CALL PLOTTING ROUTINE
         INC   ]X         ; {5C2B} INCREASE CURRENT X COORDINATE
         LDY   ]X         ; {4C3B} LOAD FOR COMPARISON
         CPY   ]X2        ; {4C3B} IF LESS THAN X DESTINATION
         BNE   :LOOP      ; {3C2B} REPEAT UNTIL DONE
:EXIT
         RTS              ; {6C1B}


THE LRGET MACRO

SUMMARY

Condition Value
Name LRGET
Type Macro
File MAC.LORES.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose get the color at an X, Y coordinate
Input ]1 = X-coordinate
]2 = Y-coordinate
Output none
Dependencies LRGETPIX
Flags Destroyed NZCV
Cycles 110+
Bytes 71
Notes none
See Also LRGETPIX

DETAILS

The LRGET macro retrieves the color of a low-resolution pixel at the given X,Y coordinates and returns the color code in .A. Currently, this only works for retrieving a value from the viewing page, but this will likely change in the future.

LISTING 8.21: The LRGET Macro Source

*
*``````````````````````````````*
* LRGET                        *
*                              *
* GET THE COLOR OF THE LORES   *
* PIXEL AT THE GIVEN COORDS.   *
*                              *
* PARAMETERS:                  *
*                              *
*  ]1 = X COORDINATE           *
*  ]2 = Y COORDINATE           *
*                              *
* CYCLES: 110+                 *
* SIZE: 71 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
LRGET    MAC
         LDA   ]1         ; {4C3B}
         STA   BPAR1      ; {3C2B}
         LDA   ]2         ; {4C3B}
         STA   BPAR2      ; {3C2B}
         JSR   LRGETPIX   ; {96C61B}
         <<<
*

THE LRGETPIX SUBROUTINE

SUMMARY

Condition Value
Name LRGETPIX
Type Subroutine
File SUB.LRGETPIX.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose get the color of a pixel at X,Y
Input BPAR1 = X-coordinate
BPAR2 = Y-coordinate
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 90+
Bytes 58
Notes none
See Also LRGET

DETAILS

The LRGETPIX subroutine retrieves the color value from a low resolution pixel at the given X, Y coordinate, passing back the color code in the .A register. Note that this currently works only for the viewing page, but this may change in future revisions.

LISTING 8.22: The LRGETPIX Subroutine Source

* LRGETPIX      (NATHAN RIGGS) *
*                              *
* THIS SUBROUTINE RETURNS THE  *
* COLOR CODE OF A GIVEN LORES  *
* PIXEL AT THE X,Y COORDINATE. *
* NOTE THAT IF THE ROW IS EVEN *
* THE THE COLOR CODE IS PASSED *
* BACK VIA THE HIGH BYTE, AND  *
* IF THE ROW IS ODD THEN THE   *
* COLOR CODE IS PASSED IN THE  *
* LOW BYTE. THE UNUSED BYTE    *
* FOR EACH WILL ALWAYS BE 0.   *
*                              *
* INPUT:                       *
*                              *
*  BPAR1 = X COORDINATE        *
*  BPAR2 = Y COORDINATE        *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 90+                  *
* SIZE: 58 BYTES               *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]HALFX   EQU   VARTAB     ; X COORD / 2 FOR GBASCALC
]FULLX   EQU   VARTAB+1   ; ORIGINAL X COORD
]FULLY   EQU   VARTAB+2   ; ORIGINAL Y COORD
]MASK    EQU   VARTAB+3   ; MASK FOR DETERMINING COLOR CODE
]FULLCHAR EQU  VARTAB+4   ; THE FULL CHAR A POS HALFX,Y
*
LRGETPIX
*
         LDY   BPAR1      ; {3C2B} LOAD X POSITION
         STY   ]FULLX     ; {4C3B}
         TYA              ; {2C1B} TRANSFER T .A
         ASL              ; {2C1B} SHIFT LEFT TO DIVIDE IN HALF
         STA   ]HALFX     ; {4C3B} STORE AS HALFX
         LDA   BPAR2      ; {3C2B} GET Y POSITION
         STA   ]FULLY     ; {4C3B}
         LDY   ]HALFX     ; {4C3B} LOAD HALF-X POSITION
         LDA   ]FULLY     ; {4C3B} LOAD Y POSITION
         JSR   LRGBCALC   ; {?C?B} GET CHARACTER AT COORDINATES
         LDA   (GBASLO),Y ; {6C2B} GET FULL CHAR FROM SCREEN ADDR
         STA   ]FULLCHAR  ; {4C3B} AND STORE IN FULLCHAR
         LDA   ]FULLX     ; {4C3B} LOAD THE LORES FULL X COORD
         LSR              ; {2C1B} SHIFT LEAST BYTE INTO CARRY
         BCC   :EVEN      ; {3C2B} IF THAT BYTE IS 0, THEN GOTO EVEN
         LDX   #$F0       ; {3C2B} ELSE IT'S ODD; MASK IT
         BCS   :EXIT      ; {3C2B} JUMP TO EXIT
:EVEN
         LDX   #$0F       ; {3C2B} MASK COLOR RETURNED
:EXIT
         STX   ]MASK      ; {4C3B} STORE THE MASK TO ]MASK
         LDA   ]FULLCHAR  ; {4C3B} LOAD FULL CHARACTER
         AND   ]MASK      ; {3C2B} MASK APPROPRIATE NIBBLE
         STA   RETURN     ; {4C3B} STRE NEW BYTE IN RETURN
         LDA   #1         ; {3C2B}
         STA   RETLEN     ; {4C3B}
         LDA   RETURN     ; {4C3B} RETURN NEW COLOR BYTE IN .A
         RTS              ; {6C1B}

THE LCHAR MACRO

SUMMARY

Condition Value
Name LCHAR
Type Macro
File MAC.LORES.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose plot a character to the low resolution screen
Input ]1 = X-coordinate
]2 = Y-coordinate
]3 = address of 3 byte character
]4 = character color
Output none
Dependencies LRCHAR
Flags Destroyed NZCV
Cycles 441+
Bytes 439
Notes none
See Also LRCHAR

DETAILS

The LCHAR macro plots a character to the low resolution graphics screen, with a width of 4 pixels and a height of 6 pixels, at the specified color.

LISTING 8.23: The LCHAR Macro Source

*
*``````````````````````````````*
* LCHAR                        *
*                              *
* PRINT A LORES CHARACTER TO   *
* LORES SCREEN AT A GIVE COLOR *
* AT THE GIVEN COORDINATES.    *
*                              *
* PARAMETERS:                  *
*                              *
*  ]1 = X COORDINATE           *
*  ]2 = Y COORDINATE           *
*  ]3 = ADDRESS OF 3-BYTE CHAR *
*  ]4 = CHARACTER COLOR        *
*                              *
* CYCLES: 441+                 *
* SIZE: 439 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
LCHAR    MAC
         LDA   ]1         ; {4C3B}
         STA   BPAR1      ; {3C2B}
         LDA   ]2         ; {4C3B}
         STA   BPAR2      ; {3C2B}
*LDA #>]3
*STA WPAR1+1
*LDA #<]3
*STA WPAR1
         _MLIT ]3;WPAR1   ; {16C12B}
         LDA   ]4         ; {4C3B}
         STA   BPAR3      ; {3C2B}
         JSR   LRCHAR     ; {403C412B}
         <<<

THE LRCHAR SUBROUTINE

SUMMARY

Condition Value
Name LRCHAR
Type Subroutine
File SUB.LRCHAR.ASM
Author Nathan Riggs
Last Revision 13-MAY-2021
Assembler Merlin Pro 8
OS Apple DOS 3.3
Purpose get the color of a pixel at X,Y
Input BPAR1 = X-coordinate
BPAR2 = Y-coordinate
WPAR1 = Address of Char definition
Output none
Dependencies none
Flags Destroyed NZCV
Cycles 90+
Bytes 58
Notes none
See Also LCHAR

DETAILS

The LRCHAR subroutine plots a character to the low resolution screen at the given X,Y coordinate and color. Each character has a 4x6 aspect ratio, allowing for a total of 64 characters on a full low resolution screen (allowing for space between characters).

LISTING 8.24: The LRCHAR Subroutine Source

*``````````````````````````````*
* LRCHAR        (NATHAN RIGGS) *
*                              *
* THIS SUBROUTINE PLACES A     *
* LORES CHARACTER AT A GIVEN   *
* POSITION AND COLOR. ALL OF   *
* THE CHARACTERS ARE 4*6 IN    *
* ORDER TO ALLOW EIGHT LETTERS *
* BOTH HORIZONTALLY AND ALSO   *
* VERTICALLY.                  *
*                              *
* INPUT:                       *
*                              *
* BPAR1 = X POSITION OF CHAR   *
* BPAR2 = Y POSITION OF CHAR   *
* WPAR1 = ADDRESS OF CHAR DEF  *
*                              *
* DESTROY: NZCIDV              *
*          ^^^  ^              *
*                              *
* CYCLES: 397+                 *
* SIZE: 409 BYTES              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]ORGX    EQU   BPAR1      ; X POSITION OF CHAR
]ORGY    EQU   BPAR2      ; Y POSITION OF CHAR
]CADDR   EQU   WPAR1      ; ADDRESS OF 3-BYTE CHAR DEFINITION
]CBYTE1  EQU   VARTAB     ; COPY OF 1ST BYTE
]CBYTE2  EQU   VARTAB+1   ; COPY OF SECOND
]CBYTE3  EQU   VARTAB+2   ; COPY OF THIRD
]CX      EQU   ADDR1      ; PLOTTING X POSITION
]CY      EQU   ADDR2      ; PLOTTING Y POSITION
]CNT     EQU   VARTAB+5   ; COUNTER
]COLOR   EQU   BPAR3      ; CHARACTER COLOR
]TMPBYTE EQU   VARTAB+11  ; WORKING BYTE TO READ
]OFFSET  EQU   VARTAB+12  ; CHARACTER BYTE OFFSET
]NIBBLE  EQU   VARTAB+13  ; FLAG TO INDICATE 1ST OR 2ND NIBBLE
*
LRCHAR
         LDA   #0         ; {4C3B} RESET NIBBLE AND OFFSET
         STA   ]NIBBLE    ; {4C3B}
         STA   ]OFFSET    ; {4C3B}
*
         LDA   ]ORGX      ; {4C3B} COPY ORGX TO X TO START
         STA   ]CX        ; {4C3B} PLOTTING CHAR FROM LEFT TOP
         LDA   ]ORGY      ; {4C3B} DO THE SAME WITH ORGY AND Y
         STA   ]CY        ; {4C3B}
         LDA   ]CX        ; {4C3B}
         LDY   #0         ; {3C2B} RESET BYTE INDEX
         LDA   (]CADDR),Y ; {6C2B} GET APPROPRIATE BYTE
         STA   ]CBYTE1    ; {4C3B} STORE IN DEDICATED VAR
         INY              ; {2C1B} NOW DO SECOND BYTE
         LDA   (]CADDR),Y ; {6C2B}
         STA   ]CBYTE2    ; {4C3B}
         INY              ; {2C1B} AND THE THIRD
         LDA   (]CADDR),Y ; {6C2B}
         STA   ]CBYTE3    ; {4C3B}
*
         LDA   #0         ; {3C2B} RESET COUNTER
         STA   ]CNT       ; {4C3B} FOR BITS
:PRELOOP
         LDY   ]OFFSET
*LDA ]OFFSET ; {4C3B} GET CHAR BYTE OFFSET
         LDA   ]CBYTE1,Y  ; {5C3B} LOAD APPROPRIATE BYTE
         STA   ]TMPBYTE   ; {4C3B} STORE IN WORKING EMORY
:LP1
         SEC              ; {2C1B} SET CARRY
         LDA   ]TMPBYTE   ; {4C3B} LOAD WORKING BYTE
         ASL              ; {2C1B} SHIFT LEFT BYTE INTO CARRY
         STA   ]TMPBYTE   ; {4C3B} STORE NEW WORKING BYTE
         BCC   :NOPLOT    ; {3C2B} IF CARRY HOLDS A 0, DON'T PLOT
         LDA   ]COLOR     ; {4C3B} OTHERWISE, PLOT
         LDY   ]CY        ; {4C3B}
         LDX   ]CX        ; {4C3B}
         JSR   LOCPLOT    ; {174C112B}
:NOPLOT
         INC   ]CX        ; {5C2B} INCREASE X, WHETHER PLOTTED
         LDA   ]CNT       ; {4C3B} OR NOT
         CMP   #3         ; {3C2B} IF # OF BITS = 4, THEN
         BEQ   :NEXTLP    ; {3C2B} WE'RE DONE WITH THIS NIBBLE
         INC   ]CNT       ; {5C2B} INCREASE THE BIT COUNTER
         JMP   :LP1       ; {3C3B} LOOP AGAIN UNTIL NIBBLE DONE
:NEXTLP
         INC   ]NIBBLE    ; {5C2B} NOW INCREASE TO 2ND NIBBLE
         INC   ]CY        ; {5C2B} INCREASE Y PLOT POS, SINCE
         LDA   #0         ; {3C2B} EACH LINE IS 4 BITS LONG
         STA   ]CNT       ; {4C3B} RESET COUNTER
         LDA   ]ORGX      ; {4C3B} RESET X POSITION
         STA   ]CX        ; {4C3B}
         LDA   ]NIBBLE    ; {4C3B} CHECK IF NIBBLE 2 IS DONE
         CMP   #2         ; {3C2B} AND IF SO,
         BEQ   :NEXTLP2   ; {3C2B} GET OUT OF ANOTHER LOOP
         JMP   :LP1       ; {3C3B} ELSE, LOOP FOR 2ND NIBBLE
:NEXTLP2
         INC   ]OFFSET    ; {5C2B} NOW INC CHAR BYTE OFFSET
         LDA   #0         ; {3C2B} RESET NIBBLE TO FIRST NIBBLE
         STA   ]NIBBLE    ; {4C3B}
         LDA   ]ORGX      ; {4C3B} RESET X POSITION
         STA   ]CX        ; {4C3B}
         LDA   #0         ; {3C2B} RESET THE BIT COUNTER
         STA   ]CNT       ; {4C3B}
         LDA   ]OFFSET    ; {4C3B} IF OFFSET IS MORE THAN 2,
         CMP   #3         ; {3C2B} THEN DONE WITH THIS LOOP
         BEQ   :NEXT3     ; {3C2B} ELSE START OVER FOR NEXT BYTE
         JMP   :PRELOOP   ; {3C3B}
*
:NEXT3
         RTS              ; {6C1B}
*
** WHAT FOLLOWS ARE THE BINARY REPRESENTATIONS OF EACH
** CHARACTER AVAILABLE.
*
LR_A     DFB   %01101001  ; {OC1B} ".XX."
                          ;        "X..X"
         DFB   %11111001  ; {OC1B} "XXXX"
                          ;        "X..X"
         DFB   %10010000  ; {0C1B} "X..X"
                          ;        "...."
LR_B
         DFB   %11101001  ; {0C1B} "XXX."
                          ;        "X..X"
         DFB   %11101001  ; {0C1B} "XXX."
                          ;        "X..X"
         DFB   %11100000  ; {0C1B} "XXX."
                          ;        "...."
LR_C
         DFB   %11111000  ; {0C1B} "XXXX"
                          ;        "X..."
         DFB   %10001000  ; {0C1B} "X..."
                          ;        "X..."
         DFB   %11110000  ; {0C1B} "XXXX"
                          ;        "...."
LR_D
         DFB   %11101001  ; {0C1B} "XXX."
                          ;        "X..X"
         DFB   %10011001  ; {0C1B} "X..X"
                          ;        "X..X"
         DFB   %11100000  ; {0C1B} "XXX."
                          ;        "...."
LR_E
         DFB   %11111000  ; {0C1B} "XXXX"
                          ;        "X..."
         DFB   %11101000  ; {0C1B} "XXX."
                          ;        "X..."
         DFB   %11110000  ; {0C1B} "XXXX"
                          ;        "...."
LR_F
         DFB   %11111000  ; {0C1B} "XXXX"
                          ;        "X..."
         DFB   %11101000  ; {0C1B} "XXX."
                          ;        "X..."
         DFB   %10000000  ; {0C1B} "X..."
                          ;        "...."
LR_G
         DFB   %11111000  ; {0C1B} "XXXX"
                          ;        "X..."
         DFB   %10111001  ; {0C1B} "X.XX"
                          ;        "X..X"
         DFB   %11110000  ; {0C1B} "XXXX"
                          ;        "...."
LR_H
         DFB   %10011001  ; {0C1B} "X..X"
                          ;        "X..X"
         DFB   %11111001  ; {0C1B} "XXXX"
                          ;        "X..X"
         DFB   %10010000  ; {0C1B} "X..X"
                          ;        "...."
LR_I
         DFB   %11110110  ; {0C1B} "XXXX"
                          ;        ".XX."
         DFB   %01100110  ; {0C1B} ".XX."
                          ;        ".XX."
         DFB   %11110000  ; {0C1B} "XXXX"
                          ;        "...."
LR_J
         DFB   %00010001  ; {0C1B} "...X"
                          ;        "...X"
         DFB   %00011001  ; {0C1B} "...X"
                          ;        "X..X"
         DFB   %01100000  ; {0C1B} ".XX."
                          ;        "...."
LR_K
         DFB   %10011010  ; {0C1B} "X..X"
                          ;        "X.X."
         DFB   %11001010  ; {0C1B} "XX.."
                          ;        "X.X."
         DFB   %10010000  ; {0C1B} "X..X"
                          ;        "...."
LR_L
         DFB   %10001000  ; {0C1B} "X..."
                          ;        "X..."
         DFB   %10001000  ; {0C1B} "X..."
                          ;        "X..."
         DFB   %11110000  ; {0C1B} "XXXX"
                          ;        "...."
LR_M
         DFB   %10111101  ; {0C1B} "X.XX"
                          ;        "XX.X"
         DFB   %11011001  ; {0C1B} "XX.X"
                          ;        "X..X"
         DFB   %10010000  ; {0C1B} "X..X"
                          ;        "...."
LR_N
         DFB   %10011101  ; {0C1B} "X..X"
                          ;        "XX.X"
         DFB   %11011011  ; {0C1B} "XX.X"
                          ;        "X.XX"
         DFB   %10010000  ; {0C1B} "X..X"
                          ; "...."
LR_O
         DFB   %01101001  ; {0C1B} ".XX."
                          ;        "X..X"
         DFB   %10011001  ; {0C1B} "X..X"
                          ;        "X..X"
         DFB   %01100000  ; {0C1B} ".XX."
                          ;        "...."
LR_P
         DFB   %11101001  ; {0C1B} "XXX."
                          ;        "X..X"
         DFB   %11101000  ; {0C1B} "XXX."
                          ;        "X..."
         DFB   %10000000  ; {0C1B} "X..."
                          ; "...."
LR_Q
         DFB   %01101001  ; {0C1B} ".XX."
                          ;        "X..X"
         DFB   %10011011  ; {0C1B} "X..X"
                          ;        "X.XX"
         DFB   %01100001  ; {0C1B} ".XX."
                          ;        "...X"
LR_R
         DFB   %11101001  ; {0C1B} "XXX."
                          ;        "X..X"
         DFB   %11101010  ; {0C1B} "XXX."
                          ;        "X.X."
         DFB   %10010000  ; {0C1B} "X..X"
                          ;        "...."
LR_S
         DFB   %01111000  ; {0C1B} ".XXX"
                          ;        "X..."
         DFB   %01100001  ; {0C1B} ".XX."
                          ;        "...X"
         DFB   %11100000  ; {0C1B} "XXX."
                          ;        "...."
LR_T
         DFB   %11110110  ; {0C1B} "XXXX"
                          ;        ".XX."
         DFB   %01100110  ; {0C1B} ".XX."
                          ;        ".XX."
         DFB   %01100000  ; {0C1B} ".XX."
                          ;        "...."
LR_U
         DFB   %10011001  ; {0C1B} "X..X"
                          ;        "X..X"
         DFB   %10011001  ; {0C1B} "X..X"
                          ;        "X..X"
         DFB   %11110000  ; {0C1B} "XXXX"
                          ;        "...."
LR_V
         DFB   %10011001  ; {0C1B} "X..X"
                          ;        "X..X"
         DFB   %10101010  ; {0C1B} "X.X."
                          ;        "X.X."
         DFB   %01000000  ; {0C1B} ".X.."
                          ;        "...."
LR_W
         DFB   %10011001  ; {0C1B} "X..X"
                          ;        "X..X"
         DFB   %10111011  ; {0C1B} "XX.X"
                          ;        "XX.X"
         DFB   %11010000  ; {0C1B} "X.XX"
                          ;        "...."
LR_X
         DFB   %10011001  ; {0C1B} "X..X"
                          ;        "X..X"
         DFB   %01101001  ; {0C1B} ".XX."
                          ;        "X..X"
         DFB   %10010000  ; {0C1B} "X..X"
                          ;        "...."
LR_Y
         DFB   %10011001  ; {0C1B} "X..X"
                          ;        "X..X"
         DFB   %01100110  ; {0C1B} ".XX."
                          ;        ".XX."
         DFB   %01100000  ; {0C1B} ".XX."
                          ;        "...."
LR_Z
         DFB   %11110001  ; {0C1B} "XXXX"
                          ;        "...X"
         DFB   %01101000  ; {0C1B} "..X."
                          ;        ".X.."
         DFB   %11110000  ; {0C1B} "XXXX"
                          ;        "...."
LR_0
         DFB   %11111001  ; {0C1B} "XXXX"
                          ;        "X..X"
         DFB   %10011001  ; {0C1B} "X..X"
                          ;        "X..X"
         DFB   %11110000  ; {0C1B} "XXXX"
                          ;        "...."
LR_1
         DFB   %01100110  ; {0C1B} ".XX."
                          ;        ".XX."
         DFB   %01100110  ; {0C1B} ".XX."
                          ;        ".XX."
         DFB   %01100000  ; {0C1B} ".XX."
                          ;        "...."
LR_2
         DFB   %01101001  ; {0C1B} ".XX."
                          ;        "X..X"
         DFB   %00100100  ; {0C1B} "..X."
                          ;        ".X.."
         DFB   %11110000  ; {0C1B} "XXXX"
                          ;        "...."
LR_3
         DFB   %11100001  ; {0C1B} "XXX."
                          ;        "...X"
         DFB   %01100001  ; {0C1B} ".XX."
                          ;        "...X"
         DFB   %11100000  ; {0C1B} "XXX."
                          ;        "...."
LR_4
         DFB   %10011001  ; {0C1B} "X..X"
                          ;        "X..X"
         DFB   %11110001  ; {0C1B} "XXXX"
                          ;        "...X"
         DFB   %00010000  ; {0C1B} "...X"
                          ;        "...."
LR_5
         DFB   %11111000  ; {0C1B} "XXXX"
                          ;        "X..."
         DFB   %11110001  ; {0C1B} "XXXX"
                          ;        "...X"
         DFB   %11110000  ; {0C1B} "XXXX"
                          ;        "...."
LR_6
         DFB   %01101000  ; {0C1B} ".XX."
                          ;        "X..."
         DFB   %11101001  ; {0C1B} "XXX."
                          ;        "X..X"
         DFB   %11110000  ; {0C1B} "XXXX"
                          ;        "...."
LR_7
         DFB   %11110001  ; {0C1B} "XXXX"
                          ;        "...X"
         DFB   %00100100  ; {0C1B} "..X."
                          ;        ".X.."
         DFB   %10000000  ; {0C1B} "X..."
                          ;        "...."
LR_8
         DFB   %01101001  ; {0C1B} ".XX."
                          ;        "X..X"
         DFB   %01101001  ; {0C1B} ".XX."
                          ;        "X..X"
         DFB   %01100000  ; {0C1B} ".XX."
                          ;        "...."
LR_9
         DFB   %01111001  ; {0C1B} ".XXX"
                          ;        "X..X"
         DFB   %01110001  ; {0C1B} ".XXX"
                          ;        "...X"
         DFB   %00010000  ; {0C1B} "...X"
                          ;        "...."
LR_EXC
         DFB   %01100110  ; {0C1B} ".XX."
                          ;        ".XX."
         DFB   %01100000  ; {0C1B} ".XX."
                          ;        "...."
         DFB   %01100000  ; {0C1B} ".XX."
                          ;        "...."
LR_QUEST
         DFB   %01101001  ; {0C1B} ".XX."
                          ;        "X..X"
         DFB   %00100000  ; {0C1B} "..X."
                          ;        "...."
         DFB   %00100000  ; {0C1B} "..X."
                          ;        "...."
LR_PRD
         DFB   %00000000  ; {0C1B} "...."
                          ;        "...."
         DFB   %00001100  ; {0C1B} "...."
                          ;        "XX.."
         DFB   %11000000  ; {0C1B} "XX.."
                          ;        "...."
LR_CMA
         DFB   %00000000  ; {0C1B} "...."
                          ;        "...."
         DFB   %00000100  ; {0C1B} "...."
                          ;        ".X.."
         DFB   %01001000  ; {0C1B} ".X.."
                          ;        "X..."
LR_APOST
         DFB   %00010001  ; {0C1B} "...X"
                          ;        "...X"
         DFB   %00100000  ; {0C1B} "..X."
                          ;        "...."
         DFB   %00000000  ; {0C1B} "...."
                          ;        "...."
LR_QUOT
         DFB   %10101010  ; {0C1B} "X.X."
                          ;        "X.X."
         DFB   %00000000  ; {0C1B} "...."
                          ;        "...."
         DFB   %00000000  ; {0C1B} "...."
                          ;        "...."
LR_COLON
         DFB   %00000100  ; {0C1B} "...."
                          ;        ".X.."
         DFB   %00000100  ; {0C1B} "...."
                          ;        ".X.."
         DFB   %00000000  ; {OC1B} "...."
                          ;        "...."
LR_SEMI
         DFB   %00000100  ; {0C1B} "...."
                          ;        ".X.."
         DFB   %00000100  ; {0C1B} "...."
                          ;        ".X.."
         DFB   %10000000  ; {0C1B} "X..."
                          ;        "...."
LR_MINUS
         DFB   %00000000  ; {0C1B} "...."
                          ;        "...."
         DFB   %11111111  ; {0C1B} "XXXX"
                          ;        "XXXX"
         DFB   %00000000  ; {0C1B} "...."
                          ;        "...."
LR_PLUS
         DFB   %00000110  ; {0C1B} "...."
                          ;        ".XX."
         DFB   %11111111  ; {0C1B} "XXXX"
                          ;        "XXXX"
         DFB   %01100000  ; {0C1B} ".XX."
                          ;        "...."
LR_EQUAL
         DFB   %00001111  ; {0C1B} "...."
                          ;        "XXXX"
         DFB   %00001111  ; {0C1B} "...."
                          ;        "XXXX"
         DFB   %00000000  ; {0C1B} "...."
                          ;        "...."
LR_FSLASH
         DFB   %00010010  ; {0C1B} "...X"
                          ;        "..X."
         DFB   %00100100  ; {0C1B} "..X."
                          ;        ".X.."
         DFB   %01001000  ; {0C1B} ".X.."
                          ;        "X..."
LR_BSLASH
         DFB   %10000100  ; {0C1B} "X..."
                          ;        ".X.."
         DFB   %01000010  ; {0C1B} ".X.."
                          ;        "..X."
         DFB   %00100001  ; {0C1B} "..X."
                          ;        "...X"
LR_LPAR
         DFB   %00010010  ; {0C1B} "...X"
                          ;        "..X."
         DFB   %01000100  ; {0C1B} ".X.."
                          ;        ".X.."
         DFB   %00100001  ; {0C1B} "..X."
                          ;        "...X"
LR_RPAR
         DFB   %10000100  ; {0C1B} "X..."
                          ;        ".X.."
         DFB   %00100010  ; {0C1B} "..X."
                          ;        "..X."
         DFB   %01001000  ; {0C1B} ".X.."
                          ;        "X..."


LoRes Collection Demo

Listing 8.25 contains demonstrations of how the low resolution macro collection works.

LISTING 8.25: The DEMO.LORES.ASM Source

*
*``````````````````````````````*
* DEMO.LORES                   *
*                              *
* A DEMO OF THE MACROS AND     *
* SUBROUTINES FOR USING LORES  *
* GRAPHICS.                    *
*                              *
* AUTHOR:    NATHAN RIGGS      *
* CONTACT:   NATHAN.RIGGS@     *
*            OUTLOOK.COM       *
*                              *
* DATE:      03-OCT-2019       *
* ASSEMBLER: MERLIN 8 PRO      *
* OS:        DOS 3.3           *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** ASSEMBLER DIRECTIVES
*
         CYC   AVE
         EXP   OFF
         TR    ON
         DSK   DEMO.LORES
         OBJ   $BFE0
         ORG   $6000
*
*``````````````````````````````*
*  TOP INCLUDES (PUTS, MACROS) *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
         PUT   MIN.HEAD.REQUIRED.ASM
         PUT   MIN.HEAD.LORES.ASM
         USE   MIN.MAC.REQUIRED.ASM
         USE   MIN.MAC.LORES.ASM
*
*``````````````````````````````*
*      PROGRAM MAIN BODY       *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]COLOR   EQU   VARTAB+16
]HOME    EQU   $FC58
*
*``````````````````````````````*
* LO-RES GRAPHICS COLLECTION   *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** THIS DEMO ILLUSTRATES HOW TO USE THE MACROS DEDICATED
** TO CREATING LOW RESOLUTION GRAPHICS. THESE MACROS
** LARGELY CONSIST OF THE MOST BASIC FUNCTIONS NECESSARY
** TO BUILD MORE COMPLICATED ROUTINES, SUCH AS ANIMATION,
** SPRITES, AND SO ON. CURRENTLY, THE MACROS AVAILABLE ARE:
*
** - LVIEWPG : SET THE VIEWING PAGE
** - LWORKPG : SET THE WORKING (PLOTTING) PAGE
** - LRGF    : INIT LOW RESOLUTION FULL SCREEN MODE
** - LRGP    : INIT LOW RESOLUTION PARTIAL SCREEN MODE
** - LFCLR   : CLEAR FULL SCREEN TO SPECIFIED COLOR
** - LPCLR   : CLEAR PARTIAL SCREEN TO SPECIFIED COLOR
** - LPLOT   : PLOT A COLORED PIXEL AT A GIVEN X,Y COORDINATE
** - LLINE   : PLOT LINE FROM X1,Y1 TO X2,Y2
** - LCIRC   : PLOT A CIRCLE WITH A GIVEN CENTER AND RADIUS
** - LVLIN   : PLOT A VERTICAL LINE
** - LHLIN   : PLOT A HORIZONTAL LINE
** - LRGET   : GET COLOR OF A LOW RESOLUTION PIXEL AT X,Y
** - LRCHAR  : PRINT A LOW RESOLUTION CHARACTER AT X,Y
*
*``````````````````````````````*
* WORKING AND VIEWING PAGES    *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** WHILE USING THE LORES COLLECTION, THERE ARE TWO MODES
** TO CONSIDER WHEN PLOTTING: THE WORKING PAGE, WHICH IS
** THE PAGE BEING PLOTTED TO AT A GIVEN MOMENT, AND THE
** VIEWING PAGE, WHICH IS THE PAGE THAT IS CURRENTLY
** VISIBLE ON THE SCREEN. THESE DO NOT HAVE TO BE THE SAME
** PAGE; YOU CAN PLOT TO THE WORKING PAGE WHILE SHOWING THE
** VIEWING PAGE ON SCREEN, AND YOU CAN FLIP THE VIEWING PAGE
** TO THE WORKING PAGE AFTER THE DESIRED PLOTTING IS
** FINISHED. THIS IS MOSTLY HELPFUL FOR ANIMATION, BUT OTHER
** USES ARE BOUND TO BE FOUND. ONE OTHER SUCH USE IS HOLDING
** A STATIC PAGE IN MEMORY TO BE FLIPPED ON OR OFF DEPENDING
** ON THE STATE OF A PROGRAM.
*
** UNFORTUNATELY, MERLIN 8 PRO USES THE SECOND PAGE FOR
** STORING DATA OF ITS OWN, SO ITS USE CANNOT BE SHOWN HERE
** WITHOUT POSSIBLY DESTROYING DATA IN RAM OR PERHAPS EVEN
** ON THE DISK. THUS WE ARE LEFT TO ONLY SHOW THE FORMAT OF
** THE COMMANDS USED.
*
** TO SET THE WORKING PAGE, YOU WOULD USE THE
** LWORKPG MACRO, AS SUCH:
*
** LWORKPG #2
*
** WHICH SETS THE WORKING PAGE TO PAGE 2. TO SET
** THE VIEWING PAGE, YOU WOULD USE THE LVIEWPG MACRO:
*
** LVIEWPG #1
*
** WHICH WOULD SET THE VIEWING PAGE TO PAGE 1. NOTE THAT
** BOTH THE WORKING PAGE AND THE VIEWING PAGE ALWAYS
** DEFAULT TO PAGE 1.
*
*```````````````````````````````*
* LORES GRAPHICS INITIALIZATION *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** THERE ARE TWO MACROS FOR INITIALIZING LORES
** GRAPHICS MODE: LRFGR AND LRPGR. THE LRFGR MACRO,
** WHICH STANDS FOR ^LORES FULL GRAPHICS^, INITIALIZES
** THE FULL SCREEN GRAPHICS MODE IN LOW RESOLUTION,
** WHEREAS THE LRPGR MACRO, WHICH STANDS FOR LORES
** PARTIAL GRAPHICS, INITIALIZES THE PARTIAL (OR MIXED)
** GRAPHICS MODE, WHICH RESERVES FOR ROWS OF TEXT SPACE
** AT THE BOTTOM OF THE SCREEN.
*
** NEITHER OF THESE MACROS HAVE ANY PARAMETERS. THE
** LRFGR MACRO CREATES A 40 X 48 LORES SCREEN, AND THE
** LRPGR MACRO CREATES A 40 X 40 MATRIX LORES SCREEN.
*
*``````````````````````````````*
* CLEARING THE LORES SCREEN    *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** LIKE WITH INTIALIZING THE GRAPHICS MODE, THERE ARE
** TWO MACROS DEDICATED TO CLEARING THE SCREEN: LRFCLR
** AND LRPCLR. BOTH OF THESE FUNCTION THE SAME, WITH
** THE EXCEPTION THAT THE LRFCLR MACRO CLEARS THE WHOLE
** SCREEN AND THE LRPCLR MACRO CLEARS ALL BUT THE
** BOTTOM FOUR ROWS (MIXED MODE). IN THIS DEMO, WE WILL
** BE DEALING EXCLUSIVELY WITH FULL SCREEN MODE.
*
** BOTH OF THE SCREEN CLEARING MACROS ACCEPT A PARAMETER
** THAT INDICATES THE COLOR TO FILL THE SCREEN WITH.
*
** NOW WE CAN UTILIZE THE MACROS ABOVE TO SHOW HOW THE
** SCREEN CAN BE CLEARED WITH EVERY COLOR AVAILABLE
** IN LOW RESOLUTION GRAPHICS MODE.
*
         JSR   ]HOME
         LWORKPG #1       ; SET WORKING PAGE AND
         LVIEWPG #1       ; TO PAGE 1. PAGE 2 WILL NOT WORK
         LRGF             ; WITH MERLIN LOADED; THEN, INIT
         LDY   #$FF       ; LORES GRAPHICS FULL SCREEN MODE
         STY   ]COLOR     ; MAC COLOR - 1
:LP1
         INC   ]COLOR     ; INCREASE THE COLOR
         LFCLR ]COLOR     ; CLEAR FULL SCREEN WITH COLOR SELECTED
         _WAIT            ; WAIT UNTIL KEYPRESS
         LDA   ]COLOR     ; LOAD COLOR AGAIN
         CMP   #$F        ; IF IT'S $F (15), THEN
         BNE   :LP1       ; WE ARE DONE DEMOING SCREEN FILLS
*
*``````````````````````````````*
* RE-ENTERING TEXT MODE        *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** A SOFT SWITCH IS USED TO RE-ENTER TEXT MODE. ANY
** INSTRUCTION CAN BE USED ON THE ^TEXTON^ MEMORY
** ADDRESS IN ORDER TO DO THIS; I USUALLY USE THE BIT
** INSTRUCTION SINCE I RARELY USE IT FOR OTHER
** PURPOSES.
*
         BIT   TEXTON
         JSR   ]HOME
         _PRN  "LOOK MA, TEXT MODE!",8D8D
         _WAIT
*
*``````````````````````````````*
* PLOTTING MACROS              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** THERE ARE A NUMBER OF MACROS DEDICATED TO PLOTTING
** POINTS ONTO THE LOW RESOLUTION SCREEN. THESE ARE
** LPLOT, LHLIN, LVLIN, LLINE AND LCIRC. THESE WILL ALL
** BE SHOWN ON THE SAME GRAPHICS SCREEN, BUT EACH
** DESERVES A SHORT EXPLANATION.
*
*``````````````````````````````*
* THE LPLOT MACRO              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** THE LPLOT MACRO ACCEPTS AN X-COORDINATE AND A
** Y-COORDINATE, AS WELL AS A COLOR FOR THE LORES
** PIXEL TO BE PLOTTED.
*
*``````````````````````````````*
* THE LHLIN MACRO              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** THE LHLIN MACRO ACCEPTS A STARTING X POINT AND AN
** ENDING X-COORDINATE, FOLLOWED BY A Y-COORDINATE THAT
** THE LINE WILL APPEAR ON. OBVIOUSLY, THIS CREATES A
** HORIZONTAL LINE ON THE SCREEN. THE LAST PARAMETER
** SIGNIFIES THE COLOR OF THE LINE.
*
*``````````````````````````````*
* THE LVLIN MACRO              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** THE LVLIN MACRO WORKS MUCH THE SAME AS THE LHLIN
** MACRO, EXCEPT IT PRINTS A VERTICAL LINE. THE FIRST
** PARAMETER IS A STARTING Y-COORDINATE, FOLLOWED BY
** AN ENDING Y-COORDINATE. THE THIRD PARAMETER IS THE
** X-COORDINATE OF THE LINE, AND THE FOURTH PARAMETER
** IS THE COLOR TO BE USED FOR THE LINE.
*
*``````````````````````````````*
* THE LLINE MACRO              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** THE LLINE MACRO USES BRESSENHAM'S LINE ALGORITHM
** TO PLOT A LINE WITH AN ARBITRARY ANGLE TO THE
** LOW RESOLUTION SCREEN. ITS FORMAT IS AS FOLLOWS:
*
** LLINE X1;Y1;X2;Y2;COLOR
*
** NOTE THAT IF YOU KNOW BEFOREHAND THAT THE LINE WILL
** BE PERFECTLY VERTICAL OR HORIZONTAL, LHLIN OR LVLIN
** SHOULD ALWAYS BE USED INSTEAD IN ORDER TO SAVE
** CYCLES.
*
*``````````````````````````````*
* LCIRC                        *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** FINALLY, THE LCIRC MACRO PLOTS A CIRCLE TO THE LOW
** RESOLUTION SCREEN AT A GIVEN CENTER COORDINATE WITH
** A GIVEN RADIUS AND COLOR, AS SUCH:
*
** LCIRC X;Y;CENTER;COLOR
*
** THIS MACRO/SUBROUTINE USES BRESSENHAM'S CIRCLE
** ALGORITHM, WHICH SACRIFICES SOME ACCURACY IN THE
** NAME OF SPEED. EVEN IN HIGH RESOLUTION GRAPHICS ON
** THE APPLE II, THE POTENTIAL FOR ERROR IS NEGLIGIBLE
** DUE TO THE LIMITED RESOLUTION THAT THE MACHINE IS
** CAPABLE OF DISPLAYING.
*
         JSR   ]HOME
         LRGF
         LFCLR #]WHITE
         LPLOT #10;#10;#]MAGENTA ; PLOT MAGENTA PIXEL AT 10,10
         LPLOT #11;#11;#]PINK    ; PLOT PINK PIXEL AT 11,11
         _WAIT
*
         LHLIN #15;#30;#2;#]PURPLE ; NOW DRAW A HORIZONTAL
         _WAIT
*
         LVLIN #2;#17;#30;#]YELLOW ; NOW CREATE A YELLOW VERTICAL LINE
         _WAIT
         LLINE #1;#1;#20;#30;#]ORANGE ; NOW PLOT ORGANGE DIAGONAL
         _WAIT
*
         LCIRC #10;#10;#10;#]LBLUE ; NOW DRAW A LIGHT BLUE CIRCLE
         _WAIT
*
*``````````````````````````````*
* THE LRGET MACRO              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** THE LRGET MACRO RETRIEVES THE COLOR VALUE OF A
** LOW RESOLUTION PIXEL AT THE GIVEN COORDINATES, AS
** SUCH:
*
** LRGET X;Y
*
         LRGET #38;#38    ; NOW GET THE COLOR OF A GIVE PIXEL
         BIT   TEXTON
         JSR   ]HOME
         DUMP  #RETURN;#1
         _WAIT
*
*``````````````````````````````*
* THE LCHAR MACRO              *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** THE LCHAR MACRO PRINTS A 4 X 6 CHARACTER TO THE
** LOW RESOLUTION SCREEN AT THE SPECIFIED COLOR. THIS
** MEANS THAT A THE SCREEN CAN HOLD A TOTAL OF 8 X 8
** CHARACTERS ON THE SCREEN AT ONCE, WITH A SINGLE
** BLANK PIXEL BETWEEN EACH CHARACTER.
*
         LRGF             ; GO BACK TO FULL SCREEN LORES GRAPHICS
         LFCLR #]WHITE    ; CLEAR THE BACKGROUND TO WHITE
         LCHAR #0;#0;#LR_A;#0
         LCHAR #5;#0;#LR_B;#1
         LCHAR #10;#0;#LR_C;#2
         LCHAR #15;#0;#LR_D;#3
         LCHAR #20;#0;#LR_E;#4
         LCHAR #25;#0;#LR_F;#5
         LCHAR #30;#0;#LR_G;#6
         LCHAR #35;#0;#LR_H;#7
         LCHAR #0;#6;#LR_I;#8
         LCHAR #5;#6;#LR_J;#9
         LCHAR #10;#6;#LR_K;#10
         LCHAR #15;#6;#LR_L;#11
         LCHAR #20;#6;#LR_M;#12
         LCHAR #25;#6;#LR_N;#13
         LCHAR #30;#6;#LR_O;#14
         LCHAR #35;#6;#LR_P;#0
         LCHAR #0;#12;#LR_Q;#1
         LCHAR #5;#12;#LR_R;#2
         LCHAR #10;#12;#LR_S;#3
         LCHAR #15;#12;#LR_T;#4
         LCHAR #20;#12;#LR_U;#5
         LCHAR #25;#12;#LR_V;#6
         LCHAR #30;#12;#LR_W;#7
         LCHAR #35;#12;#LR_X;#8
         LCHAR #0;#18;#LR_Y;#9
         LCHAR #5;#18;#LR_Z;#10
         LCHAR #10;#18;#LR_0;#11
         LCHAR #15;#18;#LR_1;#12
         LCHAR #20;#18;#LR_2;#13
         LCHAR #25;#18;#LR_3;#14
         LCHAR #30;#18;#LR_4;#0
         LCHAR #35;#18;#LR_5;#1
         LCHAR #0;#24;#LR_6;#2
         LCHAR #5;#24;#LR_7;#3
         LCHAR #10;#24;#LR_8;#4
         LCHAR #15;#24;#LR_9;#5
         LCHAR #20;#24;#LR_EXC;#6
         LCHAR #25;#24;#LR_QUEST;#7
         LCHAR #30;#24;#LR_PRD;#8
         LCHAR #35;#24;#LR_CMA;#9
         LCHAR #0;#30;#LR_APOST;#10
         LCHAR #5;#30;#LR_QUOT;#11
         LCHAR #10;#30;#LR_COLON;#12
         LCHAR #15;#30;#LR_SEMI;#13
         LCHAR #20;#30;#LR_MINUS;#14
         LCHAR #25;#30;#LR_PLUS;#0
         LCHAR #30;#30;#LR_EQUAL;#1
         LCHAR #35;#30;#LR_FSLASH;#8
         LCHAR #05;#36;#LR_BSLASH;#9
         LCHAR #10;#36;#LR_LPAR;#10
         LCHAR #15;#36;#LR_RPAR;#11
         _WAIT
*
*``````````````````````````````*
* YEET                         *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** THE FOLLOWING SHOWS A QUICK EXAMPLE OF MANY
** OF THESE MACROS ACTING TOGETHER. THIS IS NOTHING
** TERRIBLY IMPRESSIVE, BUT IT DOES DEMONSTRATE SOME
** OF WHAT THE LIBRARY DOES.
*
         LRGF
         LFCLR #]BLACK
         LDA   #1
         STA   ]CC1
:RELOOP
         LVLIN #0;#47;]HH;]CC1
         INC   ]HH
         INC   ]CC1
         LDY   ]HH
         CPY   #39
         BNE   :CONTLP0
         LDA   #0
         STA   ]HH
*
:CONTLP0
         LCHAR #10;#37;#LR_K;#0
         LCHAR #15;#38;#LR_I;#0
         LCHAR #20;#39;#LR_L;#0
         LCHAR #25;#40;#LR_L;#0
         INC   ]CC1
         LDY   ]CC1
         CPY   #15
         BNE   :CONTLP
         LDY   #1
         STY   ]CC1
:CONTLP
         LDA   #1
         STA   ]CC
         STA   ]RR
:LPC
         LCIRC #19;#19;]RR;]CC
         INC   ]RR
         INC   ]CC
         LDY   ]RR
         CPY   #15
         BEQ   :QLPC
         JMP   :LPC
:QLPC
         LDA   #1
         STA   ]CC
:LPC2
         LCIRC #19;#19;]RR;]CC
         DEC   ]RR
         INC   ]CC
         LDY   ]RR
         CPY   #1
         BNE   :LPC2
         LDA   $C000      ; CHECK FOR KEYPRESS
         BPL   :LPLP      ; IF NONE, KEEP LOOPING
         AND   #$7F       ; SET HIGH BIT
         STA   $C010      ; RESET KEYBOARD STROBE
         JMP   EXIT
*JMP :RELOOP
*
:LPLP
         JMP   :RELOOP
EXIT
         BIT   TEXTON
         JSR   ]HOME
         _PRN  "FIN!",8D8D
         LDA   TEXTON
         JMP   $3D0
*
*``````````````````````````````*
*        BOTTOM INCLUDES       *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
** BOTTOM INCLUDES
*
         PUT   MIN.LIB.REQUIRED.ASM
*
** INDIVIDUAL SUBROUTINE INCLUDES
*
         PUT   MIN.SUB.LRGFCLR.ASM
         PUT   MIN.SUB.LRGPCLR.ASM
         PUT   MIN.SUB.LRPLOT.ASM
         PUT   MIN.SUB.LRHLINE.ASM
         PUT   MIN.SUB.LRVLINE.ASM
         PUT   MIN.SUB.LRBLINE.ASM
         PUT   MIN.SUB.LRCIRCLE.ASM
         PUT   MIN.SUB.LRGETPIX.ASM
         PUT   MIN.SUB.LRCHAR.ASM
*
]RR      DS    1
]CC      DS    1
]HH      DS    1
]CC1     DS    1