From: mrdudz Date: Mon, 11 Dec 2017 18:49:14 +0000 (+0100) Subject: cbm stuff from greggs pull request X-Git-Tag: V2.17~59^2~7 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=8902730756f7dc6037cea35ea08c7511eb89cb4b;p=cc65 cbm stuff from greggs pull request --- diff --git a/asminc/c128.inc b/asminc/c128.inc index 745a3ad6d..45ac3935b 100644 --- a/asminc/c128.inc +++ b/asminc/c128.inc @@ -15,7 +15,7 @@ FNAM := $BB ; Address of filename FNAM_BANK := $C7 ; Bank for filename KEY_COUNT := $D0 ; Number of keys in input buffer FKEY_COUNT := $D1 ; Characters for function key -MODE := $D7 ; 40/80 column mode flag +MODE := $D7 ; 40-/80-column mode (bit 7: 80 columns) CURS_X := $EC ; Cursor column CURS_Y := $EB ; Cursor row SCREEN_PTR := $E0 ; Pointer to current char in text screen @@ -167,8 +167,14 @@ SID_Read3 := $D41C ; --------------------------------------------------------------------------- ; I/O: VDC (128 only) -VDC_INDEX := $D600 -VDC_DATA := $D601 +VDC_INDEX := $D600 ; register address port +VDC_DATA := $D601 ; data port + +; Registers +VDC_DATA_HI = 18 ; video RAM address (big endian) +VDC_DATA_LO = 19 +VDC_CSET = 28 +VDC_RAM_RW = 31 ; RAM port ; --------------------------------------------------------------------------- ; I/O: Complex Interface Adapters diff --git a/doc/funcref.sgml b/doc/funcref.sgml index d997e0a8f..b198adcf8 100644 --- a/doc/funcref.sgml +++ b/doc/funcref.sgml @@ -4,7 +4,7 @@ cc65 function reference <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> <url url="mailto:greg.king5@verizon.net" name="Greg King"> -<date>2017-11-21 +<date>2017-12-09 <abstract> cc65 is a C compiler for 6502 based systems. This function reference describes @@ -240,6 +240,10 @@ function. <item><ref id="chline" name="chline"> <item><ref id="chlinexy" name="chlinexy"> <item><ref id="clrscr" name="clrscr"> +<item><ref id="cpeekc" name="cpeekc"> +<item><ref id="cpeekcolor" name="cpeekcolor"> +<item><ref id="cpeekrevers" name="cpeekrevers"> +<item><ref id="cpeeks" name="cpeeks"> <item><ref id="cprintf" name="cprintf"> <item><ref id="cputc" name="cputc"> <item><ref id="cputcxy" name="cputcxy"> @@ -2363,6 +2367,121 @@ be used in presence of a prototype. </quote> +<sect1>cpeekc<label id="cpeekc"><p> + +<quote> +<descrip> +<tag/Function/Get a character from the display memory. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/char cpeekc (void);/ +<tag/Description/The function gets the character that's at the current location +of the cursor in the display screen RAM. That character is converted, if +needed, into the encoding that can be passed to <tt/cputc()/. +<tag/Notes/<itemize> +<item>Conio peek functions don't have <tt/cpeek...xy()/ versions. That was +done to make it obvious that peeking doesn't move the cursor in any way. Your +program must place the cursor where it wants to peek before it calls any of +those functions. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cpeekcolor" name="cpeekcolor">, +<ref id="cpeekrevers" name="cpeekrevers">, +<ref id="cpeeks" name="cpeeks">, +<ref id="cputc" name="cputc"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cpeekcolor<label id="cpeekcolor"><p> + +<quote> +<descrip> +<tag/Function/Get a color from the display memory. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/unsigned char cpeekcolor (void);/ +<tag/Description/The function gets the color number that's at the current +location of the cursor in the display screen RAM. That number can be passed to +<tt/textcolor()/. +<tag/Notes/<itemize> +<item>Conio peek functions don't have <tt/cpeek...xy()/ versions. That was +done to make it obvious that peeking doesn't move the cursor in any way. Your +program must place the cursor where it wants to peek before it calls any of +those functions. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cpeekc" name="cpeekc">, +<ref id="cpeekrevers" name="cpeekrevers">, +<ref id="cpeeks" name="cpeeks">, +<ref id="cputc" name="cputc">, +<ref id="textcolor" name="textcolor"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cpeekrevers<label id="cpeekrevers"><p> + +<quote> +<descrip> +<tag/Function/Get a reverse-character attribute from the display memory. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/unsigned char cpeekrevers (void);/ +<tag/Description/The function gets the "reverse-mode" attribute of the +character that's at the current location of the cursor in the display screen +RAM. It returns a boolean value (0/1) that can be passed to <tt/revers()/. +<tag/Notes/<itemize> +<item>Conio peek functions don't have <tt/cpeek...xy()/ versions. That was +done to make it obvious that peeking doesn't move the cursor in any way. Your +program must place the cursor where it wants to peek before it calls any of +those functions. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cpeekc" name="cpeekc">, +<ref id="cpeekcolor" name="cpeekcolor">, +<ref id="cpeeks" name="cpeeks">, +<ref id="cputc" name="cputc">, +<ref id="revers" name="revers"> +<tag/Example/None. +</descrip> +</quote> + + +<sect1>cpeeks<label id="cpeeks"><p> + +<quote> +<descrip> +<tag/Function/Get a string from the display memory. +<tag/Header/<tt/<ref id="conio.h" name="conio.h">/ +<tag/Declaration/<tt/void __fastcall__ cpeeks (char* s, unsigned length);/ +<tag/Description/The function gets a fixed-length string ('\0'-terminated) of +characters that start at the current location of the cursor in the display +screen RAM. Those characters are converted, if needed, into the encoding that +can be passed to <tt/cputs()/. The first argument must point to a RAM area +that's large enough to hold "length + 1" bytes. +<tag/Notes/<itemize> +<item>Conio peek functions don't have <tt/cpeek...xy()/ versions. That was +done to make it obvious that peeking doesn't move the cursor in any way. Your +program must place the cursor where it wants to peek before it calls any of +those functions. +<item>The function is available as only a fastcall function; +so, it may be used only in the presence of a prototype. +</itemize> +<tag/Availability/cc65 +<tag/See also/ +<ref id="cpeekc" name="cpeekc">, +<ref id="cpeekcolor" name="cpeekcolor">, +<ref id="cpeekrevers" name="cpeekrevers">, +<ref id="cputc" name="cputc">, +<ref id="cputs" name="cputs"> +<tag/Example/None. +</descrip> +</quote> + + <sect1>creat<label id="creat"><p> <quote> diff --git a/include/cbm610.h b/include/cbm610.h index 79d498431..b0486044b 100644 --- a/include/cbm610.h +++ b/include/cbm610.h @@ -144,11 +144,9 @@ void __fastcall__ pokewsys (unsigned addr, unsigned val); #define _textcolor(color) COLOR_WHITE #define _bgcolor(color) COLOR_BLACK #define _bordercolor(color) COLOR_BLACK +#define _cpeekcolor(color) COLOR_WHITE /* End of cbm610.h */ #endif - - - diff --git a/include/conio.h b/include/conio.h index baf55dd08..9cd505766 100644 --- a/include/conio.h +++ b/include/conio.h @@ -148,6 +148,23 @@ int cscanf (const char* format, ...); int __fastcall__ vcscanf (const char* format, va_list ap); /* Like vscanf(), but uses direct keyboard input */ +char cpeekc (void); +/* Return the character from the current cursor position */ + +unsigned char cpeekcolor (void); +/* Return the color from the current cursor position */ + +unsigned char cpeekrevers (void); +/* Return the reverse attribute from the current cursor position. +** If the character is reversed, then return 1; return 0 otherwise. +*/ + +void __fastcall__ cpeeks (char* s, unsigned int length); +/* Return a string of the characters that start at the current cursor position. +** Put the string into the buffer to which "s" points. The string will have +** "length" characters, then will be '\0'-terminated. +*/ + unsigned char __fastcall__ cursor (unsigned char onoff); /* If onoff is 1, a cursor is displayed when waiting for keyboard input. If ** onoff is 0, the cursor is hidden when waiting for keyboard input. The @@ -224,6 +241,9 @@ void __fastcall__ cputhex16 (unsigned val); #if defined(_bordercolor) # define bordercolor(x) _bordercolor(x) #endif +#if defined(_cpeekcolor) +# define cpeekcolor(x) _cpeekcolor(x) +#endif diff --git a/include/pet.h b/include/pet.h index e9659d524..249d8b608 100644 --- a/include/pet.h +++ b/include/pet.h @@ -105,6 +105,7 @@ extern void pet_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ #define _textcolor(color) COLOR_WHITE #define _bgcolor(color) COLOR_BLACK #define _bordercolor(color) COLOR_BLACK +#define _cpeekcolor(color) COLOR_WHITE diff --git a/libsrc/c128/cpeekc.s b/libsrc/c128/cpeekc.s new file mode 100644 index 000000000..ce6bb4ff5 --- /dev/null +++ b/libsrc/c128/cpeekc.s @@ -0,0 +1,65 @@ +; +; 2016-02-28, Groepaz +; 2017-06-26, Greg King +; +; char cpeekc (void); +; + + .export _cpeekc + + .import plot, popa + + .include "zeropage.inc" + .include "c128.inc" + + +_cpeekc: + lda MODE + bmi @c80 + + ldy CURS_X + lda (SCREEN_PTR),y ; get char + +@return: + and #<~$80 ; remove reverse flag + +; Convert the screen code into a PetSCII code. +; $00 - $1F: +$40 +; $20 - $3F +; $40 - $7F: +$80 + + cmp #$20 + bcs @sk1 ;(bge) + ora #$40 + rts + +@sk1: cmp #$40 + bcc @end ;(blt) + ora #$80 +@end: ldx #0 + rts + +@c80: + lda SCREEN_PTR + ldy SCREEN_PTR+1 + clc + adc CURS_X + bcc @s + iny + + ; get byte from VDC mem +@s: ldx #VDC_DATA_LO + stx VDC_INDEX +@L0: bit VDC_INDEX + bpl @L0 + sta VDC_DATA + dex + stx VDC_INDEX + sty VDC_DATA + + ldx #VDC_RAM_RW + stx VDC_INDEX +@L1: bit VDC_INDEX + bpl @L1 ; wait for blanking + lda VDC_DATA + jmp @return diff --git a/libsrc/c128/cpeekcolor.s b/libsrc/c128/cpeekcolor.s new file mode 100644 index 000000000..9a8c3bfdc --- /dev/null +++ b/libsrc/c128/cpeekcolor.s @@ -0,0 +1,56 @@ +; +; 2016-02-28, Groepaz +; 2017-06-26, Greg King +; +; unsigned char cpeekcolor (void); +; + + .export _cpeekcolor + + .include "c128.inc" + + +_cpeekcolor: + bit MODE + bmi @c80 + + ldy CURS_X + lda (CRAM_PTR),y ; get color + and #$0F + ldx #>$0000 + rts + +@c80: lda CRAM_PTR + ldy CRAM_PTR+1 + clc + adc CURS_X + bcc @s + iny + + ; get byte from VDC mem +@s: ldx #VDC_DATA_LO + stx VDC_INDEX +@L0: bit VDC_INDEX + bpl @L0 + sta VDC_DATA + dex + stx VDC_INDEX + sty VDC_DATA + + ldx #VDC_RAM_RW + stx VDC_INDEX +@L1: bit VDC_INDEX + bpl @L1 ; wait for blanking + lda VDC_DATA + and #$0F + +; translate VDC->VIC colour + +vdctovic: + ldy #$0F + 1 +@L2: dey + cmp $CE5C,y + bne @L2 + tya + ldx #>$0000 + rts diff --git a/libsrc/c128/cpeekrevers.s b/libsrc/c128/cpeekrevers.s new file mode 100644 index 000000000..c36e4ac44 --- /dev/null +++ b/libsrc/c128/cpeekrevers.s @@ -0,0 +1,51 @@ +; +; 2016-02-28, Groepaz +; 2017-06-26, Greg King +; +; unsigned char cpeekrevers (void); +; + + .export _cpeekrevers + + .include "zeropage.inc" + .include "c128.inc" + + +_cpeekrevers: + lda MODE + bmi @c80 + + ldy CURS_X + lda (SCREEN_PTR),y ; get char + +@return: + and #$80 ; get reverse flag + asl a + tax ; ldx #>$0000 + rol a ; return boolean value + rts + +@c80: + lda SCREEN_PTR + ldy SCREEN_PTR+1 + clc + adc CURS_X + bcc @s + iny + + ; get byte from VDC mem +@s: ldx #VDC_DATA_LO + stx VDC_INDEX +@L0: bit VDC_INDEX + bpl @L0 + sta VDC_DATA + dex + stx VDC_INDEX + sty VDC_DATA + + ldx #VDC_RAM_RW + stx VDC_INDEX +@L1: bit VDC_INDEX + bpl @L1 ; wait for blanking + lda VDC_DATA + jmp @return diff --git a/libsrc/c128/cpeeks.s b/libsrc/c128/cpeeks.s new file mode 100644 index 000000000..c9d806ef3 --- /dev/null +++ b/libsrc/c128/cpeeks.s @@ -0,0 +1,15 @@ +; +; 2017-11-23, Greg King +; +; void cpeeks (char* s, unsigned length); +; +; C128 can't use "cbm/cpeeks.s" because both 40 and 80 columns must be handled. +; Stub file, for now, so that its library can be built. + + .export _cpeeks + + .import popax + + +_cpeeks: + jmp popax ; pop s diff --git a/libsrc/cbm/cpeekc.s b/libsrc/cbm/cpeekc.s new file mode 100644 index 000000000..05c7fc718 --- /dev/null +++ b/libsrc/cbm/cpeekc.s @@ -0,0 +1,53 @@ +; +; 2016-02-28, Groepaz +; 2017-06-22, Greg King +; +; char cpeekc (void); +; + + .export _cpeekc + +; Get a system-specific file. +; Note: The cbm610, and c128 targets need special +; versions that handle RAM banking and the 80-column VDC. + +.if .def(__C16__) + .include "plus4.inc" ; both C16 and Plus4 +.elseif .def(__C64__) + .include "c64.inc" +.elseif .def(__CBM510__) + .import CURS_X: zp, SCREEN_PTR: zp + .include "cbm510.inc" +.elseif .def(__PET__) + .include "pet.inc" +.elseif .def(__VIC20__) + .include "vic20.inc" +.endif + + +_cpeekc: + ldy CURS_X + lda (SCREEN_PTR),y ; get screen code + ldx #>$0000 + and #<~$80 ; remove reverse bit + +; Convert the screen code into a PetSCII code. +; $00 - $1F: +$40 +; $20 - $3F +; $40 - $5f: +$20 +; $60 - $7F: +$40 + + cmp #$20 + bcs @sk1 ;(bge) + ora #$40 + rts + +@sk1: cmp #$40 + bcc @end ;(blt) + cmp #$60 + bcc @sk2 ;(blt) + ;sec + adc #$20 - $01 +@sk2: ;clc ; both above cmp and adc clear carry flag + adc #$20 +@end: rts diff --git a/libsrc/cbm/cpeekcolor.s b/libsrc/cbm/cpeekcolor.s new file mode 100644 index 000000000..9c961b771 --- /dev/null +++ b/libsrc/cbm/cpeekcolor.s @@ -0,0 +1,28 @@ +; +; 2016-02-28, Groepaz +; 2017-06-22, Greg King +; +; unsigned char cpeekcolor (void); +; + + .export _cpeekcolor + +; Get a system-specific file. +; Note: The cbm510, cbm610, c128, and Pet targets need special +; versions that handle RAM banking, the 80-column VDC, and monochrome. + +.if .def(__C16__) + .include "plus4.inc" ; both C16 and Plus4 +.elseif .def(__C64__) + .include "c64.inc" +.elseif .def(__VIC20__) + .include "vic20.inc" +.endif + + +_cpeekcolor: + ldy CURS_X + lda (CRAM_PTR),y ; get color + and #$0F + ldx #>$0000 + rts diff --git a/libsrc/cbm/cpeekrevers.s b/libsrc/cbm/cpeekrevers.s new file mode 100644 index 000000000..e8e210167 --- /dev/null +++ b/libsrc/cbm/cpeekrevers.s @@ -0,0 +1,35 @@ +; +; 2016-02-28, Groepaz +; 2017-06-15, Greg King +; +; unsigned char cpeekrevers (void); +; + + .export _cpeekrevers + +; Get a system-specific file. +; Note: The cbm610, and c128 targets need special +; versions that handle RAM banking and the 80-column VDC. + +.if .def(__C16__) + .include "plus4.inc" ; both C16 and Plus4 +.elseif .def(__C64__) + .include "c64.inc" +.elseif .def(__CBM510__) + .import CURS_X: zp, SCREEN_PTR: zp + .include "cbm510.inc" +.elseif .def(__PET__) + .include "pet.inc" +.elseif .def(__VIC20__) + .include "vic20.inc" +.endif + + +_cpeekrevers: + ldy CURS_X + lda (SCREEN_PTR),y ; get screen code + and #$80 ; get reverse bit + asl a + tax ; ldx #>$0000 + rol a ; return boolean value + rts diff --git a/libsrc/cbm/cpeeks.s b/libsrc/cbm/cpeeks.s new file mode 100644 index 000000000..215998e37 --- /dev/null +++ b/libsrc/cbm/cpeeks.s @@ -0,0 +1,93 @@ +; +; 2017-07-05, Greg King +; +; void cpeeks (char* s, unsigned length); +; + + .export _cpeeks + + .import popax + .importzp ptr1, ptr2, ptr3, tmp1, tmp2 + + .macpack generic + +; Get a system-specific file. +; Note: The cbm610, and c128 targets need special +; versions that handle RAM banking and the 80-column VDC. + +.if .def(__C16__) + .include "plus4.inc" ; both C16 and Plus4 +.elseif .def(__C64__) + .include "c64.inc" +.elseif .def(__CBM510__) + .import CURS_X: zp, SCREEN_PTR: zp + .include "cbm510.inc" +.elseif .def(__PET__) + .include "pet.inc" +.elseif .def(__VIC20__) + .include "vic20.inc" +.endif + + +_cpeeks: + eor #<$FFFF ; counting a word upward is faster + sta ptr3 ; so, we use -(length + 1) + txa + eor #>$FFFF + sta ptr3+1 + + lda SCREEN_PTR + ldx SCREEN_PTR+1 + sta ptr2 + stx ptr2+1 + ldy CURS_X + sty tmp2 + + jsr popax + sta tmp1 ; (will be a .Y index) + stx ptr1+1 + ldx #<$0000 + stx ptr1 + bze L3 ; branch always + +L4: ldy tmp2 + lda (ptr2),y ; get char + iny + bnz L2 + inc ptr2+1 +L2: sty tmp2 + and #<~$80 ; remove reverse bit + +; Convert the screen code into a PetSCII code. +; $00 - $1F: +$40 +; $20 - $3F +; $40 - $5f: +$20 +; $60 - $7F: +$40 + + cmp #$20 + blt @sk1 ;(bcc) + cmp #$40 + blt L5 + cmp #$60 + blt @sk2 ;(bcc) + clc +@sk1: adc #$20 +@sk2: ;clc ; both above cmp and adc clear carry flag + adc #$20 + +L5: ldy tmp1 + sta (ptr1),y + iny + bnz L1 + inc ptr1+1 +L1: sty tmp1 + +L3: inc ptr3 ; count length + bnz L4 + inc ptr3+1 + bnz L4 + + txa ; terminate the string + ldy tmp1 + sta (ptr1),y + rts diff --git a/libsrc/cbm510/cpeekcolor.s b/libsrc/cbm510/cpeekcolor.s new file mode 100644 index 000000000..44c0a1595 --- /dev/null +++ b/libsrc/cbm510/cpeekcolor.s @@ -0,0 +1,24 @@ +; +; 2016-02-28, Groepaz +; 2017-06-19, Greg King +; +; unsigned char cpeekcolor (void); +; + + .export _cpeekcolor + + .import CURS_X: zp, CRAM_PTR: zp + + .include "cbm510.inc" + + +_cpeekcolor: + ldx IndReg + lda #$0F + sta IndReg + ldy CURS_X + lda (CRAM_PTR),y ; get color + stx IndReg + and #$0F + ldx #>$0000 + rts diff --git a/libsrc/cbm510/doesclrscr.s b/libsrc/cbm510/doesclrscr.s new file mode 100644 index 000000000..e0f57374c --- /dev/null +++ b/libsrc/cbm510/doesclrscr.s @@ -0,0 +1,16 @@ +; +; 2016-06, Christian Groessler +; 2017-07-05, Greg King +; +; unsigned char doesclrscrafterexit (void); +; +; Returns 0/1 if, after program termination, the screen isn't/is cleared. +; + + .import return1 + +; cc65's CBM510 programs switch to a display screen in the program RAM bank; +; then, they switch back to the system bank when they exit. +; The screen is cleared. + + .export _doesclrscrafterexit := return1 diff --git a/libsrc/cbm610/cpeekc.s b/libsrc/cbm610/cpeekc.s new file mode 100644 index 000000000..295d096f3 --- /dev/null +++ b/libsrc/cbm610/cpeekc.s @@ -0,0 +1,45 @@ +; +; 2016-02-28, Groepaz +; 2017-06-19, Greg King +; +; char cpeekc (void); +; + + .export _cpeekc + + .import CURS_X: zp, CharPtr: zp + + .include "cbm610.inc" + + +_cpeekc: + ldx IndReg + ldy #$0F + sty IndReg + + ldy CURS_X + lda (CharPtr),y ; get char from system bank + stx IndReg + ldx #>$0000 + and #<~$80 ; remove reverse bit + +; Convert the screen code into a PetSCII code. +; $00 - $1F: +$40 +; $20 - $3F +; $40 - $5f: +$20 +; $60 - $7F: +$40 + + cmp #$20 + bcs @sk1 ;(bge) + ora #$40 + rts + +@sk1: cmp #$40 + bcc @end ;(blt) + cmp #$60 + bcc @sk2 ;(blt) + ;sec + adc #$20 - $01 +@sk2: ;clc ; both above cmp and adc clear carry flag + adc #$20 +@end: rts diff --git a/libsrc/cbm610/cpeekcolor.s b/libsrc/cbm610/cpeekcolor.s new file mode 100644 index 000000000..ed275ec95 --- /dev/null +++ b/libsrc/cbm610/cpeekcolor.s @@ -0,0 +1,8 @@ +; +; 2017-06-03, Greg King +; +; unsigned char cpeekcolor (void); +; + + .import return1 + .export _cpeekcolor := return1 ; always COLOR_WHITE diff --git a/libsrc/cbm610/cpeekrevers.s b/libsrc/cbm610/cpeekrevers.s new file mode 100644 index 000000000..52e166e85 --- /dev/null +++ b/libsrc/cbm610/cpeekrevers.s @@ -0,0 +1,29 @@ +; +; 2016-02-28, Groepaz +; 2017-06-19, Greg King +; +; unsigned char cpeekrevers (void); +; + + .export _cpeekrevers + + .import plot + .import CURS_X: zp, CharPtr: zp + + .include "cbm610.inc" + + +_cpeekrevers: + ldx IndReg + ldy #$0F + sty IndReg + + ldy CURS_X + lda (CharPtr),y ; get char from system bank + stx IndReg + ldx #>$0000 + and #$80 ; get reverse bit + asl a + tax ; ldx #>$0000 + rol a ; return boolean value + rts diff --git a/libsrc/cbm610/cpeeks.s b/libsrc/cbm610/cpeeks.s new file mode 100644 index 000000000..91aae8957 --- /dev/null +++ b/libsrc/cbm610/cpeeks.s @@ -0,0 +1,82 @@ +; +; 2017-07-05, Greg King +; +; void cpeeks (char* s, unsigned length); +; + + .export _cpeeks + + .import popax + .importzp ptr1, ptr2, ptr3, tmp1, tmp2 + .importzp CURS_X, SCREEN_PTR + + .include "cbm610.inc" + .macpack generic + + +_cpeeks: + eor #<$FFFF ; counting a word upward is faster + sta ptr3 ; so, we use -(length + 1) + txa + eor #>$FFFF + sta ptr3+1 + + lda SCREEN_PTR + ldx SCREEN_PTR+1 + sta ptr2 + stx ptr2+1 + ldy CURS_X + sty tmp2 + + jsr popax + sta tmp1 ; (will be a .Y index) + stx ptr1+1 + ldx IndReg + ldy #<$0000 + sty ptr1 + bze L3 ; branch always + +L4: ldy #$0F + sty IndReg + ldy tmp2 + lda (ptr2),y ; get char from system bank + stx IndReg + iny + bnz L2 + inc ptr2+1 +L2: sty tmp2 + and #<~$80 ; remove reverse bit + +; Convert the screen code into a PetSCII code. +; $00 - $1F: +$40 +; $20 - $3F +; $40 - $5f: +$20 +; $60 - $7F: +$40 + + cmp #$20 + blt @sk1 ;(bcc) + cmp #$40 + blt L5 + cmp #$60 + blt @sk2 ;(bcc) + clc +@sk1: adc #$20 +@sk2: ;clc ; both above cmp and adc clear carry flag + adc #$20 + +L5: ldy tmp1 + sta (ptr1),y + iny + bnz L1 + inc ptr1+1 +L1: sty tmp1 + +L3: inc ptr3 ; count length + bnz L4 + inc ptr3+1 + bnz L4 + + lda #$00 ; terminate the string + ldy tmp1 + sta (ptr1),y + rts diff --git a/libsrc/pet/cpeekcolor.s b/libsrc/pet/cpeekcolor.s new file mode 100644 index 000000000..ed275ec95 --- /dev/null +++ b/libsrc/pet/cpeekcolor.s @@ -0,0 +1,8 @@ +; +; 2017-06-03, Greg King +; +; unsigned char cpeekcolor (void); +; + + .import return1 + .export _cpeekcolor := return1 ; always COLOR_WHITE diff --git a/testcode/lib/cpeek-test.c b/testcode/lib/cpeek-test.c new file mode 100644 index 000000000..27923432b --- /dev/null +++ b/testcode/lib/cpeek-test.c @@ -0,0 +1,177 @@ +/* Test that the cpeek...() functions are the inverses of cputc(), +** revers(), and textcolor() for the full range of character codes. +** +** 2017-07-15, Greg King +*/ + +#include <conio.h> +#include <cc65.h> + +/* Standard location of the screen */ + +#if defined(__C128__) || defined(__C64__) +/* only 40-column screen */ +# define SCREEN_RAM ((unsigned char*)0x0400) +#elif defined(__C16__) /* Plus4 also */ +# define SCREEN_RAM ((unsigned char*)0x0C00) +#elif defined(__CBM510__) +# define SCREEN_RAM ((unsigned char*)0xF000) +#elif defined(__CBM610__) +# define SCREEN_RAM ((unsigned char*)0xD000) +#elif defined(__PET__) +# define SCREEN_RAM ((unsigned char*)0x0800) +#elif defined(__VIC20__) +# define SCREEN_RAM ((unsigned char*)0x1000) +#else +# error This program cannot test that target. +# define SCREEN_RAM ((unsigned char*)0) +#endif + +static unsigned char width; + + +/* Move the cursor backward one char with +** the recognition of a row change. +*/ +static void chBack (void) +{ + unsigned char y = wherey (); + unsigned char x = wherex (); + + if (x == 0) { + x = width; + --y; + } + --x; + + gotoxy (x, y); +} + + +/* Move the cursor forward one char with +** the recognition of a row change. +*/ +static void chForth (void) +{ + unsigned char y = wherey (); + unsigned char x = wherex (); + + if (++x >= width) { + x = 0; + ++y; + } + + gotoxy (x, y); +} + + +/* A hack to get an unmodified byte from the +** screen memory at the current cursor position. +*/ +static unsigned char peekChWithoutTranslation (void) +{ +#if defined(__CBM610__) + return peekbsys ((unsigned)&SCREEN_RAM[wherey () * width + wherex ()]); +#else + return SCREEN_RAM[wherey () * width + wherex ()]; +#endif +} + + +/* A test which outputs the given char, reads it back from +** screen memory, outputs the returned char at the next position, +** then compares the two screen memory bytes for identity. +** +** Note: cpeekc() must be tested indirectly because some platforms "fold" their +** character code-set into a smaller screen code-set. Therefore, cpeekc() might +** return an equivalent, but not equal, character to the one that was cputc(). +*/ +static unsigned char testCPeekC (char ch) +{ + unsigned char ch2_a, ch2_b, ch2_c; + + /* Test the given char-code, but not the + ** special characters NEWLINE and RETURN + ** (they don't put anything on the screen). + */ + if (('\n' == ch) || ('\r' == ch) + ) { + return 1; + } + + /* Output the char to the screen. */ + cputc (ch); + + /* Move the cursor pos. to the previous output. */ + chBack (); + + /* Get back the written char without any translation. */ + ch2_b = peekChWithoutTranslation (); + + /* Get back the written char, + ** including the translation, screen-code -> text. + */ + ch2_a = cpeekc (); + + /* Move the cursor to the following writing position. */ + chForth (); + + /* Output again the char which was read back by cpeekc(). */ + cputc (ch2_a); + + /* Move the cursor pos. to the second output. */ + chBack (); + + /* Get back the second written char without any translation; + ** and, compare it to the first untranslated char. + */ + ch2_c = peekChWithoutTranslation (); + if (ch2_c != ch2_b) { + /* The test was NOT succesful. + ** Output a diagnostic; and, return FAILURE. + */ + revers(0); + cprintf ("\r\nError on char: %#x was %#x instead.", ch, ch2_a); + cprintf ("\r\nRaw screen codes: %#x, %#x.", ch2_b, ch2_c); + return 0; + } + + /* The test was succesful. + ** Move the cursor to the following writing position. + */ + chForth (); + return 1; +} + + +/* The main code initiates the screen for the tests, and sets the reverse flag. +** Then, it calls testCPeekC() for every char within 0..255. +** Returns zero for success, one for failure. +*/ +int main (void) +{ + unsigned char i; + int ret = 0; + + clrscr (); + revers (1); + screensize (&width, &i); + +#if defined(__VIC20__) + /* The VIC-20's screen is too small to hold the full test. */ + i = 2; +#else + i = 0; +#endif + do { + if (!testCPeekC (i)) { + ret = 1; + break; + } + } while (++i != 0); /* will wrap around when finished */ + + if (doesclrscrafterexit()) { + cgetc(); + } + return ret; +}