Added a 160x192x2 TGI (graphics) driver to the VIC-20 library.

The driver requires a special linker configuration: "vic20-tgi.cfg".
The VIC-20 computer needs at least 8K of expansion RAM!

"tgidemo.c" needed to be adjusted because the VIC-20's vertical (y) range is greater than its horizontal (x) range -- the opposite of most other platforms.  Also, the circle demo would jam on the VIC-20.
This commit is contained in:
Greg King 2020-07-08 05:55:30 -04:00
parent d1833cc441
commit 410e4502ee
11 changed files with 1253 additions and 23 deletions

50
cfg/vic20-tgi.cfg Normal file
View File

@ -0,0 +1,50 @@
# Memory configuration which supports the "vic20-hi.tgi" driver.
# Memory configuration for a VIC-20 with, at least, 8K expansion RAM.
FEATURES {
STARTADDRESS: default = $1201;
}
SYMBOLS {
__LOADADDR__: type = import;
__EXEHDR__: type = import;
__TGIHDR__: type = import;
__STACKSIZE__: type = weak, value = $0200; # 512-byte stack
__HIMEM__: type = weak, value = $4000;
}
MEMORY {
ZP: file = "", define = yes, start = $0002, size = $001A;
LOADADDR: file = %O, start = %S - 2, size = $0002;
HEADER: file = %O, define = yes, start = %S, size = $003E;
MAIN: file = %O, define = yes, start = $2000, size = __HIMEM__ - __MAIN_START__ - __STACKSIZE__;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
LOADADDR: load = LOADADDR, type = ro;
# The start-up code needs EXEHDR, TGI1HDR, TGI2HDR,
# and STARTUP to be next to each other, in that order.
EXEHDR: load = HEADER, type = ro;
TGI1HDR: load = HEADER, type = ro;
TGI2HDR: load = MAIN, type = ro;
STARTUP: load = MAIN, type = ro;
LOWCODE: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;
ONCE: load = MAIN, type = ro, optional = yes, define = yes;
INIT: load = MAIN, type = bss, optional = yes;
BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
segment = RODATA;
CONDES: type = interruptor,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__,
segment = RODATA,
import = __CALLIRQ__;
}

View File

@ -75,7 +75,6 @@ common to all CBM platforms.
There are currently no special VIC20 functions.
<sect1>CBM-specific functions<p>
Some functions are available for all (or at least most) of the Commodore
@ -143,7 +142,33 @@ The names in the parentheses denote the symbols to be used for static linking of
<sect1>Graphics drivers<p>
No graphics drivers are currently available for the VIC20.
<descrip>
<tag><tt/vic20-hi.tgi (vic20_hi_tgi)/</tag>
This driver features a resolution of 160&times;192 with two colors. The
background can be chosen from a sixteen-color palette. The foreground can
be chosen from an eight-color palette.
The driver will use memory from addresses $1000 to $1FFF as a graphics
buffer. Therefore, the VIC-20 must have, at least, 8K of expansion RAM.
Programs that use this driver must be linked by the <tt/vic20-tgi.cfg/
configuration file. It will link a special header into the program.
That header will do the housekeeping that's needed by TGI.
An example command line:
<tscreen><verb>
cl65 -D DYN_DRV=0 -t vic20 -C vic20-tgi.cfg samples/mandelbrot.c
</verb></tscreen>
When the program starts, it will move itself up in RAM, to make room for the
buffer. When the program finishes, it will reset the BASIC interpreter.
That means that graphics pictures won't be preserved between the executions
of programs. Also, the graphics buffer shares RAM with the text screen. If
a picture must be saved, then a program must put it somewhere else (such as
a disk file) before returning to the text mode.
</descrip>
<sect1>Extended memory drivers<p>

View File

@ -216,7 +216,7 @@ void __fastcall__ tgi_arc (int x, int y, unsigned char rx, unsigned char ry,
/* Draw an ellipse arc with center at x/y and radii rx/ry using the current
** drawing color. The arc covers the angle between sa and ea (startangle and
** endangle), which must be in the range 0..360 (otherwise the function may
** bevave unextectedly).
** behave unexpectedly).
*/
void __fastcall__ tgi_pieslice (int x, int y, unsigned char rx, unsigned char ry,

View File

@ -2,12 +2,12 @@
/* */
/* vic20.h */
/* */
/* vic20 system specific definitions */
/* VIC-20 system-specific definitions */
/* */
/* */
/* */
/* (C) 1998-2004 Ullrich von Bassewitz */
/* Römerstraße 52 */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
@ -66,14 +66,39 @@
#define COLOR_GREEN 0x05
#define COLOR_BLUE 0x06
#define COLOR_YELLOW 0x07
/* Only the background and multi-color characters can have these colors. */
#define COLOR_ORANGE 0x08
#define COLOR_BROWN 0x09
#define COLOR_LIGHTRED 0x0A
#define COLOR_GRAY1 0x0B
#define COLOR_GRAY2 0x0C
#define COLOR_LIGHTORANGE 0x09
#define COLOR_PINK 0x0A
#define COLOR_LIGHTCYAN 0x0B
#define COLOR_LIGHTVIOLET 0x0C
#define COLOR_LIGHTGREEN 0x0D
#define COLOR_LIGHTBLUE 0x0E
#define COLOR_GRAY3 0x0F
#define COLOR_LIGHTYELLOW 0x0F
/* TGI color defines */
#define TGI_COLOR_BLACK COLOR_BLACK
#define TGI_COLOR_WHITE COLOR_WHITE
#define TGI_COLOR_RED COLOR_RED
#define TGI_COLOR_CYAN COLOR_CYAN
#define TGI_COLOR_VIOLET COLOR_VIOLET
#define TGI_COLOR_GREEN COLOR_GREEN
#define TGI_COLOR_BLUE COLOR_BLUE
#define TGI_COLOR_YELLOW COLOR_YELLOW
/* Only the background and multi-color graphics can have these colors. */
#define TGI_COLOR_ORANGE COLOR_ORANGE
#define TGI_COLOR_LIGHTORANGE COLOR_LIGHTORANGE
#define TGI_COLOR_PINK COLOR_PINK
#define TGI_COLOR_LIGHTCYAN COLOR_LIGHTCYAN
#define TGI_COLOR_LIGHTVIOLET COLOR_LIGHTVIOLET
#define TGI_COLOR_LIGHTGREEN COLOR_LIGHTGREEN
#define TGI_COLOR_LIGHTBLUE COLOR_LIGHTBLUE
#define TGI_COLOR_LIGHTYELLOW COLOR_LIGHTYELLOW
/* tgi_ioctl() commands */
#define TGI_IOCTL_VIC20_SET_PATTERN 0x01 /* Set 8-byte pattern for tgi_bar(). */
@ -108,5 +133,9 @@ extern void vic20_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */
extern void vic20_rama_emd[];
extern void vic20_georam_emd[];
extern void vic20_hi_tgi[]; /* Referred to by tgi_static_stddrv[] */
/* End of vic20.h */
#endif

View File

@ -1,10 +1,14 @@
;
; Oliver Schmidt, 2013-05-31
; 2013-05-31, Oliver Schmidt
; 2018-03-11, Sven Michael Klose
;
.export joy_libref
.export em_libref
.export joy_libref
.export tgi_libref
.import _exit
joy_libref := _exit
em_libref := _exit
joy_libref := _exit
tgi_libref := _exit

1018
libsrc/vic20/tgi/vic20-hi.s Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
;
; Address of the static standard TGI driver
;
; const void tgi_static_stddrv[];
;
.import _vic20_hi_tgi
.export _tgi_static_stddrv := _vic20_hi_tgi

13
libsrc/vic20/tgi_stddrv.s Normal file
View File

@ -0,0 +1,13 @@
;
; Name of the standard TGI driver
;
; 2018-03-11, Sven Michael Klose
;
; const char tgi_stddrv[];
;
.export _tgi_stddrv
.rodata
_tgi_stddrv: .asciiz "vic20-hi.tgi"

67
libsrc/vic20/tgihdr.s Normal file
View File

@ -0,0 +1,67 @@
;
; This code sits immediately after the BASIC stub program.
; Therefore, it's executed by that stub.
;
; 2018-04-17, Greg King
;
.export __TGIHDR__ : abs = 1 ; Mark as TGI housekeeper
.import __MAIN_LAST__
.importzp ptr1, ptr2, tmp1
basic_reset := $C000 ; vector to BASIC's cold-start code
; This code moves the program to $2000. That move allows $1000 - $1FFF
; to be used by the TGI driver to hold its graphics data.
.segment "TGI1HDR"
lda #<(tgi1end + prog_size) ; source
ldx #>(tgi1end + prog_size)
sta ptr1
stx ptr1+1
lda #<(tgi2hdr + prog_size) ; destination
ldx #>(tgi2hdr + prog_size)
sta ptr2
stx ptr2+1
ldx #<~prog_size
lda #>~prog_size ; use -(prog_size + 1)
sta tmp1
ldy #<$0000
; Copy loop
@L1: inx ; bump counter's low byte
beq @L4
@L2: tya ; will .Y underflow?
bne @L3
dec ptr1+1 ; yes, do next lower page
dec ptr2+1
@L3: dey
lda (ptr1),y
sta (ptr2),y
jmp @L1
@L4: inc tmp1 ; bump counter's high byte
bne @L2
jmp tgi2hdr ; go to moved program
tgi1end:
.segment "TGI2HDR"
tgi2hdr:
jsr tgi2end ; run actual program
jmp (basic_reset)
tgi2end:
; The length of the TGI program (including the TGI2HDR segment)
prog_size = __MAIN_LAST__ - tgi2hdr

View File

@ -230,6 +230,20 @@ ovrldemo: overlaydemo.o
OVERLAYLIST := $(foreach I,1 2 3,multdemo.$I ovrldemo.$I)
# --------------------------------------------------------------------------
# TGI programs on the VIC-20 need a special ld65 configuration file.
ifeq ($(SYS),vic20)
mandelbrot.o: override CFLAGS += -D DYN_DRV=0
mandelbrot: mandelbrot.o
$(LD) $(LDFLAGS) -o $@ -C vic20-tgi.cfg -m $@.map $^ $(SYS).lib
# tgidemo needs at least 16K of RAM expansion.
tgidemo.o: override CFLAGS += -D DYN_DRV=0
tgidemo: tgidemo.o
$(LD) -D __HIMEM__=0x6000 $(LDFLAGS) -o $@ -C vic20-tgi.cfg -m $@.map $^ $(SYS).lib
endif
# --------------------------------------------------------------------------
# Rule to make a CBM disk with all samples. Needs the c1541 program that comes
# with the VICE emulator.

View File

@ -70,9 +70,10 @@ static void DoCircles (void)
{
static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_ORANGE };
unsigned char I;
unsigned char Color = COLOR_FORE;
unsigned X = MaxX / 2;
unsigned Y = MaxY / 2;
unsigned char Color = COLOR_BACK;
const unsigned X = MaxX / 2;
const unsigned Y = MaxY / 2;
const unsigned Limit = (X < Y) ? Y : X;
tgi_setpalette (Palette);
tgi_setcolor (COLOR_FORE);
@ -82,7 +83,7 @@ static void DoCircles (void)
while (!kbhit ()) {
Color = (Color == COLOR_FORE) ? COLOR_BACK : COLOR_FORE;
tgi_setcolor (Color);
for (I = 10; I < 240; I += 10) {
for (I = 10; I <= Limit; I += 10) {
tgi_ellipse (X, Y, I, tgi_imulround (I, AspectRatio));
}
}
@ -132,7 +133,7 @@ static void DoDiagram (void)
tgi_setcolor (COLOR_FORE);
tgi_clear ();
/* Determine zero and aplitude */
/* Determine zero and amplitude */
YOrigin = MaxY / 2;
XOrigin = 10;
Amp = (MaxY - 19) / 2;
@ -168,16 +169,17 @@ static void DoLines (void)
{
static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLACK };
unsigned X;
const unsigned Min = (MaxX < MaxY) ? MaxX : MaxY;
tgi_setpalette (Palette);
tgi_setcolor (COLOR_FORE);
tgi_clear ();
for (X = 0; X <= MaxY; X += 10) {
tgi_line (0, 0, MaxY, X);
tgi_line (0, 0, X, MaxY);
tgi_line (MaxY, MaxY, 0, MaxY-X);
tgi_line (MaxY, MaxY, MaxY-X, 0);
for (X = 0; X <= Min; X += 10) {
tgi_line (0, 0, Min, X);
tgi_line (0, 0, X, Min);
tgi_line (Min, Min, 0, Min-X);
tgi_line (Min, Min, Min-X, 0);
}
cgetc ();