AppleIIAsm-Collection/documentation/AppleIIAsm Library Collection Technical Manual/0.6.1/37.0 Detailed_Reference_D8_LORES.md
Nathan D Riggs c28c9d87da Disk 1: REQUIRED disk and documentation
Cleaned up disk one documentation, both inline and in the manual
2021-06-06 21:50:54 -04:00

3351 lines
119 KiB
Markdown

# Disk 8: LoRes
- [Part I: The LoRes Collection](#part-i-the-lores-collection)
- [LoRes Components](#lores-components)
- [LoRes Header File](#lores-collection-header-file)
- [LOCPLOT](#the-locplot-subroutine)
- [LoRes Macros and Subroutines](#lores-macros-and-subroutines)
- [LWORKPG](#the-lworkpg-macro)
- [LVIEWPG](#the-lviewpg-macro)
- [LRGF](#the-lrgf-macro)
- [LRGP](#the-lrgp-macro)
- [LFCLR](#the-lfclr-macro)
- [LRGFCLR](#the-lrgfclr-subroutine)
- [LPCLR](#the-lpclr-macro)
- [LRGPCLR](#the-lrgpclr-subroutine)
- [LPLOT](#the-lplot-macro)
- [LRPLOT](#the-lrplot-subroutine)
- [LLINE](#the-lline-macro)
- [LRBLINE](#the-lrbline-subroutine)
- [LCIRC](#the-lcirc-macro)
- [LRCIRCLE](#the-lrcircle-subroutine)
- [LVLIN](#the-lvlin-macro)
- [LRVLINE](#the-lrvline-subroutine)
- [LHLIN](#the-lhlin-macro)
- [LRHLINE](#the-lrhline-subroutine)
- [LRGET](#the-lrget-macro)
- [LRGETPIX](#the-lrgetpix-subroutine)
- [LCHAR](#the-lchar-macro)
- [LRCHAR](#the-lrchar-subroutine)
- [Part II: LoRes Collection Demo](#lores-collection-demo)
---
## 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`
```assembly
*``````````````````````````````*
* 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<br />.Y = Y position<br />.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`
```assembly
*
*``````````````````````````````*
* 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`
```assembly
*``````````````````````````````*
* 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`
```assembly
*
*``````````````````````````````*
* 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`
```assembly
*
*``````````````````````````````*
* 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`
```assembly
*
*``````````````````````````````*
* 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`
```assembly
*
*``````````````````````````````*
* 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`
```assembly
*``````````````````````````````*
* 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 `LRGPCLR`subroutine 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`
```assembly
*``````````````````````````````*
* 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<br />]2 = Y-coordinate<br />]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`
```assembly
*
*``````````````````````````````*
* 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<br />BPAR2 = X-coordinate<br />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`
```assembly
*``````````````````````````````*
* 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<br />]2 = X-destination<br />]3 = Y-origin<br />]4 = Y-destination<br />]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`
```assembly
*
*``````````````````````````````*
* 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<br />WPAR1+1 = Y-origin<br />WPAR2 = X-destination<br />WPAR2+1 = Y-destination<br />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`
```assembly
*``````````````````````````````*
* 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<br />]2 = Center Y-position<br />]3 = Circle radius<br />]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`
```assembly
*
*``````````````````````````````*
* 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<br />WPAR2 = Y-center<br />WPAR3 = Radius<br />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`
```assembly
*``````````````````````````````*
* 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<br />]2 = Y-destination<br />]3 = X-coordinate<br />]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`
```assembly
*
*``````````````````````````````*
* 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<br />WPAR1+1 = Y-destination<br />BPAR1 = X-position<br />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`
```assembly
*``````````````````````````````*
* 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<br />]2 = X-destination<br />]3 = Y-coordinate<br />]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`
```assembly
*
*``````````````````````````````*
* 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<br />WPAR1+1 = X-destination<br />BPAR1 = Y-position<br />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`
```assembly
*``````````````````````````````*
* 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<br />]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`
```assembly
*
*``````````````````````````````*
* 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<br />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`
```assembly
* 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<br />]2 = Y-coordinate<br />]3 = address of 3 byte character<br />]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`
```assembly
*
*``````````````````````````````*
* 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<br />BPAR2 = Y-coordinate<br />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`
```assembly
*``````````````````````````````*
* 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`
```assembly
*
*``````````````````````````````*
* 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
```