|
- /* vscreen.c - screen and keyboard for the c64 vim clone.
- *
- * The editor writes straight into the screen matrix at $0400 and colour ram at
- * $d800 rather than going through the kernal, and it selects the lower/upper
- * case character set at $1800 so that petscii $41-$5a draws as real lowercase.
- *
- * Everything here returns int, so the other compilation unit can call these
- * without declaring them (power c is K&R C).
- */
-
- char *scr; /* screen matrix, $0400 */
- char *colr; /* colour ram, $d800 */
-
- /* petscii byte -> screen code */
- s2v(p)
- int p;
- {
- if (p >= 0xc0) return p - 0x80;
- if (p >= 0xa0) return p - 0x40;
- if (p >= 0x60) return p - 0x20;
- if (p >= 0x40) return p - 0x40;
- return p;
- }
-
- /* raw screen code at row r, column c */
- sraw(r, c, v)
- int r, c, v;
- {
- int i;
-
- if (r < 0) return 0;
- if (r > 24) return 0;
- if (c < 0) return 0;
- if (c > 39) return 0;
- i = r * 40 + c;
- scr[i] = v;
- colr[i] = 1;
- return 0;
- }
-
- /* one petscii character */
- spc(r, c, p)
- int r, c, p;
- {
- sraw(r, c, s2v(p));
- return 0;
- }
-
- /* one petscii character, inverted: the cursor and the status row */
- srpc(r, c, p)
- int r, c, p;
- {
- sraw(r, c, s2v(p) + 128);
- return 0;
- }
-
- /* a reversed space, for the cursor sitting past the end of a line */
- sblk(r, c)
- int r, c;
- {
- sraw(r, c, 160);
- return 0;
- }
-
- /* a zero terminated petscii string */
- sps(r, c, s)
- int r, c;
- char *s;
- {
- while (*s) spc(r, c++, *s++);
- return 0;
- }
-
- /* n blanks from (r,c) */
- sclr(r, c, n)
- int r, c, n;
- {
- while (n-- > 0) sraw(r, c++, 32);
- return 0;
- }
-
- /* take over the machine: black on blue, lower case, no blinking cursor */
- sinit()
- {
- int i;
- char *p;
-
- scr = (char *) 0x0400;
- colr = (char *) 0xd800;
- p = (char *) 0xd018;
- *p = 0x17;
- p = (char *) 0xd020;
- *p = 0;
- p = (char *) 0xd021;
- *p = 6;
- p = (char *) 0x00cc;
- *p = 0;
- p = (char *) 0x0091; /* run/stop flag: drop whatever boot left */
- *p = 0;
- for (i = 0; i < 1000; i++) {
- scr[i] = 32;
- colr[i] = 1;
- }
- return 0;
- }
-
- /* give the machine back the way basic expects it */
- sdone()
- {
- char *p;
- char a, x, y;
-
- p = (char *) 0xd018;
- *p = 0x15;
- p = (char *) 0xd020;
- *p = 14;
- p = (char *) 0xd021;
- *p = 6;
- /* do not return to basic: power c owns zero page 43-74, which is where
- basic keeps its program and variable pointers, so basic carries on with
- garbage and prints a mangled error instead of READY. restart the
- machine through the kernal reset instead - banner and READY, like
- switching on. the file has been saved (or abandoned with :q!) by now. */
- a = 0;
- x = 0;
- y = 0;
- sys(0xfce2, &a, &x, &y); /* never comes back */
- return 0;
- }
-
- /* ---------------------------------------------------------------- keyboard
- *
- * Keys come straight out of the kernal's keyboard buffer: $c6 says how many
- * are waiting and they queue from $0277. The kernal's own irq handler scans
- * the keyboard matrix and fills that buffer, so this gets each press as it
- * happens - and it also catches anything typed before the program started.
- *
- * (GETIN through sys() once "crashed" - but that was sys() called with the
- * c128 bank argument; on the c64 it is sys(addr, &a, &x, &y).) And the library's getchar() is line buffered - it
- * echoes through the screen editor and only hands characters over after RETURN.
- */
-
- /* next key, or 0 if none is waiting */
- skeyp()
- {
- int n, k, i;
- char *cnt, *buf;
-
- cnt = (char *) 0x00c6;
- n = *cnt;
- n = n & 255;
- if (n == 0) return 0;
- buf = (char *) 0x0277;
- k = buf[0];
- k = k & 255;
- for (i = 1; i < n; i++) buf[i - 1] = buf[i];
- *cnt = (char) (n - 1);
- return k;
- }
-
- /* wait for a key */
- skey()
- {
- int k;
-
- for (;;) {
- k = skeyp();
- if (k != 0) return k;
- }
- }
|