# 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
.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` ```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
]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` ```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
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` ```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
]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` ```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
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` ```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
]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` ```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
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` ```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
]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` ```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
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` ```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
]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` ```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
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` ```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
]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
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
]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` ```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
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` ```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 ```