]> git.sur5r.net Git - cc65/blob - testcode/lib/cpeek-test.c
PET screen memory is at $8000, not $0800
[cc65] / testcode / lib / cpeek-test.c
1 /* Test that the cpeek...() functions are the inverses of cputc(),
2 ** revers(), and textcolor() for the full range of character codes.
3 **
4 ** 2017-07-15, Greg King
5 */
6
7 #include <conio.h>
8 #include <cc65.h>
9
10 /* Standard location of the screen */
11
12 #if defined(__C128__) || defined(__C64__)
13 /* only 40-column screen */
14 #  define SCREEN_RAM ((unsigned char*)0x0400)
15 #elif defined(__C16__)                  /* Plus4 also */
16 #  define SCREEN_RAM ((unsigned char*)0x0C00)
17 #elif defined(__CBM510__)
18 #  define SCREEN_RAM ((unsigned char*)0xF000)
19 #elif defined(__CBM610__)
20 #  define SCREEN_RAM ((unsigned char*)0xD000)
21 #elif defined(__PET__)
22 #  define SCREEN_RAM ((unsigned char*)0x8000)
23 #elif defined(__VIC20__)
24 #  define SCREEN_RAM ((unsigned char*)0x1000)
25 #else
26 #  error This program cannot test that target.
27 #  define SCREEN_RAM ((unsigned char*)0)
28 #endif
29
30 static unsigned char width;
31
32
33 /* Move the cursor backward one char with
34 ** the recognition of a row change.
35 */
36 static void chBack (void)
37 {
38     unsigned char y = wherey ();
39     unsigned char x = wherex ();
40
41     if (x == 0) {
42         x = width;
43         --y;
44     }
45     --x;
46
47     gotoxy (x, y);
48 }
49
50
51 /* Move the cursor forward one char with
52 ** the recognition of a row change.
53 */
54 static void chForth (void)
55 {
56     unsigned char y = wherey ();
57     unsigned char x = wherex ();
58
59     if (++x >= width) {
60         x = 0;
61         ++y;
62     }
63
64     gotoxy (x, y);
65 }
66
67
68 /* A hack to get an unmodified byte from the
69 ** screen memory at the current cursor position.
70 */
71 static unsigned char peekChWithoutTranslation (void)
72 {
73 #if defined(__CBM610__)
74     return peekbsys ((unsigned)&SCREEN_RAM[wherey () * width + wherex ()]);
75 #else
76     return SCREEN_RAM[wherey () * width + wherex ()];
77 #endif
78 }
79
80
81 /* A test which outputs the given char, reads it back from
82 ** screen memory, outputs the returned char at the next position,
83 ** then compares the two screen memory bytes for identity.
84 **
85 ** Note:  cpeekc() must be tested indirectly because some platforms "fold" their
86 ** character code-set into a smaller screen code-set.  Therefore, cpeekc() might
87 ** return an equivalent, but not equal, character to the one that was cputc().
88 */
89 static unsigned char testCPeekC (char ch)
90 {
91     unsigned char ch2_a, ch2_b, ch2_c;
92
93     /* Test the given char-code, but not the
94     ** special characters NEWLINE and RETURN
95     ** (they don't put anything on the screen).
96     */
97     if (('\n' == ch) || ('\r' == ch)
98         ) {
99         return 1;
100     }
101
102     /* Output the char to the screen. */
103     cputc (ch);
104
105     /* Move the cursor pos. to the previous output. */
106     chBack ();
107
108     /* Get back the written char without any translation. */
109     ch2_b = peekChWithoutTranslation ();
110
111     /* Get back the written char,
112     ** including the translation, screen-code -> text.
113     */
114     ch2_a = cpeekc ();
115
116     /* Move the cursor to the following writing position. */
117     chForth ();
118
119     /* Output again the char which was read back by cpeekc(). */
120     cputc (ch2_a);
121
122     /* Move the cursor pos. to the second output. */
123     chBack ();
124
125     /* Get back the second written char without any translation;
126     ** and, compare it to the first untranslated char.
127     */
128     ch2_c = peekChWithoutTranslation ();
129     if (ch2_c != ch2_b) {
130         /* The test was NOT succesful.
131         ** Output a diagnostic; and, return FAILURE.
132         */
133         revers(0);
134         cprintf ("\r\nError on char: %#x was %#x instead.", ch, ch2_a);
135         cprintf ("\r\nRaw screen codes: %#x, %#x.", ch2_b, ch2_c);
136         return 0;
137     }
138
139     /* The test was succesful.
140     ** Move the cursor to the following writing position.
141     */
142     chForth ();
143     return 1;
144 }
145
146
147 /* The main code initiates the screen for the tests, and sets the reverse flag.
148 ** Then, it calls testCPeekC() for every char within 0..255.
149 ** Returns zero for success, one for failure.
150 */
151 int main (void)
152 {
153     unsigned char i;
154     int ret = 0;
155
156     clrscr ();
157     revers (1);
158     screensize (&width, &i);
159
160 #if defined(__VIC20__)
161     /* The VIC-20's screen is too small to hold the full test. */
162     i = 2;
163 #else
164     i = 0;
165 #endif
166     do {
167         if (!testCPeekC (i)) {
168             ret = 1;
169             break;
170         }
171     } while (++i != 0);         /* will wrap around when finished */
172
173     if (doesclrscrafterexit()) {
174         cgetc();
175     }
176     return ret;
177 }