Merge branch 'master' into feature/plus4-tgi-driver

This commit is contained in:
Bob Andrews
2025-06-01 23:12:27 +02:00
committed by GitHub
2213 changed files with 191473 additions and 27985 deletions

View File

@@ -92,15 +92,15 @@ ifneq ($(filter disk samples.%,$(MAKECMDGOALS)),)
# For this one, see https://www.horus.com/~hias/atari/
DIR2ATR ?= dir2atr
DISK_c64 = samples.d64
DISK_plus4 = samples.d64
DISK_apple2 = samples.dsk
DISK_apple2enh = samples.dsk
DISK_atari = samples.atr
DISK_atarixl = samples.atr
endif
DISK_c64 = samples.d64
DISK_apple2 = samples.dsk
DISK_apple2enh = samples.dsk
DISK_atari = samples.atr
DISK_atarixl = samples.atr
DISK_plus4 = samples.d64
# --------------------------------------------------------------------------
# System-dependent settings
# For convenience, these groups and lines are sorted alphabetically, first
@@ -133,7 +133,7 @@ LDFLAGS_tgidemo_atarixl = --start-addr 0x4000
# --------------------------------------------------------------------------
# Generic rules
.PHONY: all mostlyclean clean install zip samples disk
.PHONY: samples all mostlyclean clean install zip disk platforms
%: %.c
%: %.s
@@ -154,36 +154,18 @@ else
$(CL) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -t $(SYS) -m $@.map $^ $(SYS).lib
endif
# --------------------------------------------------------------------------
# Lists of subdirectories
# disasm depends on cpp
DIRLIST = tutorial geos atari2600 atari5200 apple2 gamate lynx supervision sym1 kim1 cbm
# --------------------------------------------------------------------------
# Lists of executables
EXELIST_c64 = \
ascii \
enumdevdir \
fire \
gunzip65 \
hello \
mandelbrot \
mousedemo \
multdemo \
nachtm \
ovrldemo \
plasma \
sieve \
tgidemo
EXELIST_plus4 = \
ascii \
enumdevdir \
gunzip65 \
hello \
mandelbrot \
plasma \
sieve \
tgidemo
EXELIST_apple2 = \
ascii \
checkversion \
diodemo \
enumdevdir \
gunzip65 \
@@ -193,12 +175,15 @@ EXELIST_apple2 = \
multdemo \
ovrldemo \
sieve \
terminal \
tinyshell \
tgidemo
EXELIST_apple2enh = $(EXELIST_apple2)
EXELIST_atari = \
ascii \
checkversion \
gunzip65 \
hello \
mandelbrot \
@@ -206,15 +191,178 @@ EXELIST_atari = \
multdemo \
ovrldemo \
sieve \
terminal \
tinyshell \
tgidemo
EXELIST_atarixl = $(EXELIST_atari)
EXELIST_atari2600 = \
atari2600hello
notavailable
EXELIST_atari5200 = \
notavailable
EXELIST_atmos = \
ascii \
checkversion \
hello \
mandelbrot \
sieve \
terminal \
tgidemo
EXELIST_bbc = \
notavailable
EXELIST_c64 = \
ascii \
checkversion \
enumdevdir \
gunzip65 \
hello \
mandelbrot \
mousedemo \
multdemo \
ovrldemo \
sieve \
terminal \
tinyshell \
tgidemo
EXELIST_c128 = \
ascii \
checkversion \
enumdevdir \
gunzip65 \
hello \
mandelbrot \
mousedemo \
sieve \
terminal \
tinyshell \
tgidemo
EXELIST_c16 = \
ascii \
checkversion \
enumdevdir \
tinyshell \
hello
EXELIST_cbm510 = \
ascii \
checkversion \
gunzip65 \
hello \
mousedemo \
terminal \
tinyshell \
sieve
EXELIST_cbm610 = \
ascii \
checkversion \
gunzip65 \
hello \
terminal \
tinyshell \
sieve
EXELIST_creativision = \
ascii \
hello
EXELIST_cx16 = \
ascii \
checkversion \
enumdevdir \
gunzip65 \
hello \
mandelbrot \
mousedemo \
sieve \
tinyshell \
tgidemo
EXELIST_gamate = \
hello
EXELIST_geos-cbm = \
ascii \
checkversion \
diodemo
EXELIST_geos-apple = \
ascii
EXELIST_lunix = \
notavailable
EXELIST_lynx = \
notavailable
EXELIST_nes = \
hello
EXELIST_osic1p = \
notavailable
EXELIST_pce = \
hello
EXELIST_pet = \
ascii \
checkversion \
enumdevdir \
hello \
tinyshell \
sieve
EXELIST_plus4 = \
ascii \
checkversion \
enumdevdir \
gunzip65 \
hello \
mandelbrot \
terminal \
tinyshell \
sieve \
tgidemo
EXELIST_sim6502 = \
checkversion \
gunzip65
EXELIST_sim65c02 = $(EXELIST_sim6502)
EXELIST_supervision = \
supervisionhello
notavailable
EXELIST_sym1 = \
notavailable
EXELIST_kim1 = \
notavailable
EXELIST_telestrat = \
ascii \
checkversion \
gunzip65 \
hello \
mandelbrot \
sieve \
tgidemo
EXELIST_vic20 = \
ascii \
checkversion \
enumdevdir \
hello \
mandelbrot \
sieve \
tgidemo
# Unlisted targets will try to build everything.
# That lets us learn what they cannot build, and what settings
@@ -223,15 +371,76 @@ ifndef EXELIST_$(SYS)
EXELIST_$(SYS) := ${patsubst %.c,%,$(wildcard *.c)}
endif
define SUBDIR_recipe
@+$(MAKE) -C $(dir) --no-print-directory $@
endef # SUBDIR_recipe
# --------------------------------------------------------------------------
# Rules to make the binaries and the disk
samples: $(EXELIST_$(SYS))
$(foreach dir,$(DIRLIST),$(SUBDIR_recipe))
# empty target used to skip systems that will not work with any program in this dir
notavailable:
ifeq ($(MAKELEVEL),0)
@echo "info: generic samples not available for" $(SYS)
endif
disk: $(DISK_$(SYS))
all:
# --------------------------------------------------------------------------
# List of every supported platform
TARGETS := \
apple2 \
apple2enh \
atari \
atarixl \
atari2600 \
atari5200 \
atmos \
bbc \
c128 \
c16 \
c64 \
cbm510 \
cbm610 \
creativision \
cx16 \
gamate \
kim1 \
lunix \
lynx \
nes \
osic1p \
pce \
pet \
plus4 \
sim6502 \
sim65c02 \
supervision \
sym1 \
telestrat \
vic20
# --------------------------------------------------------------------------
# Rule to make the binaries for every platform
define TARGET_recipe
@echo making samples for: $(T)
@$(MAKE) -j2 SYS:=$(T)
@$(MAKE) --no-print-directory clean SYS:=$(T)
endef # TARGET_recipe
platforms:
$(foreach T,$(TARGETS),$(TARGET_recipe))
# --------------------------------------------------------------------------
# Overlay rules. Overlays need special ld65 configuration files. Also, the
# overlay file-names are shortenned to fit the Atari's 8.3-character limit.
@@ -252,21 +461,58 @@ ifneq ($(filter multdemo,$(EXELIST_$(SYS))),)
OVERLAYLIST += $(foreach I,1 2 3,multdemo.$I)
endif
# --------------------------------------------------------------------------
# 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
# --------------------------------------------------------------------------
# some programs link against getsp.o
getsp.o: getsp.s
$(AS) $(ASFLAGS) -t $(SYS) $<
ifneq ($(SYS),vic20)
tinyshell: tinyshell.o getsp.o
$(LD) $(LDFLAGS) -t $(SYS) -o $@ $^ $(SYS).lib
endif
# some programs need more memory on the vic20
ifeq ($(SYS),vic20)
tinyshell: tinyshell.o getsp.o
$(LD) $(LDFLAGS) -o $@ -C vic20-32k.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.
define D64_WRITE_recipe
define D64_WRITE_PRG_recipe
$(C1541) -attach $@ -write "$(subst ?,$(SPACE),$(file))" $(notdir $(file)) >$(NULLDEV)
$(C1541) -attach $@ -write "$(subst ?,$(SPACE),$(file))" $(notdir $(file)),p >$(NULLDEV)
endef # D64_WRITE_recipe
endef # D64_WRITE_PRG_recipe
define D64_WRITE_SEQ_recipe
$(C1541) -attach $@ -write "$(subst ?,$(SPACE),$(file))" $(notdir $(file)),s >$(NULLDEV)
endef # D64_WRITE_SEQ_recipe
samples.d64: samples
@$(C1541) -format samples,AA d64 $@ >$(NULLDEV)
$(foreach file,$(EXELIST_$(SYS)),$(D64_WRITE_recipe))
$(foreach file,$(OVERLAYLIST),$(D64_WRITE_recipe))
$(foreach file,$(EMD) $(MOU) $(TGI),$(D64_WRITE_recipe))
@$(C1541) -format "samples,00" d64 $@ >$(NULLDEV)
$(foreach file,$(EXELIST_$(SYS)),$(D64_WRITE_PRG_recipe))
$(foreach file,$(OVERLAYLIST),$(D64_WRITE_PRG_recipe))
$(foreach file,$(EMD) $(MOU) $(TGI),$(D64_WRITE_SEQ_recipe))
# --------------------------------------------------------------------------
# Rule to make an Apple II disk with all samples. Needs the AppleCommander
@@ -321,15 +567,36 @@ INSTALL = install
samplesdir = $(PREFIX)/share/cc65/samples
install:
$(if $(PREFIX),,$(error variable "PREFIX" must be set))
$(INSTALL) -d $(DESTDIR)$(samplesdir)
$(INSTALL) -d $(DESTDIR)$(samplesdir)/geos
$(INSTALL) -d $(DESTDIR)$(samplesdir)/tutorial
$(INSTALL) -d $(DESTDIR)$(samplesdir)/atari2600
$(INSTALL) -d $(DESTDIR)$(samplesdir)/atari5200
$(INSTALL) -d $(DESTDIR)$(samplesdir)/apple2
$(INSTALL) -d $(DESTDIR)$(samplesdir)/cbm
$(INSTALL) -d $(DESTDIR)$(samplesdir)/gamate
$(INSTALL) -d $(DESTDIR)$(samplesdir)/supervision
$(INSTALL) -d $(DESTDIR)$(samplesdir)/disasm
$(INSTALL) -d $(DESTDIR)$(samplesdir)/kim1
$(INSTALL) -d $(DESTDIR)$(samplesdir)/lynx
$(INSTALL) -d $(DESTDIR)$(samplesdir)/sim65
$(INSTALL) -d $(DESTDIR)$(samplesdir)/sym1
$(INSTALL) -m0644 *.* $(DESTDIR)$(samplesdir)
$(INSTALL) -m0644 README $(DESTDIR)$(samplesdir)
$(INSTALL) -m0644 readme.txt $(DESTDIR)$(samplesdir)
$(INSTALL) -m0644 Makefile $(DESTDIR)$(samplesdir)
$(INSTALL) -m0644 geos/*.* $(DESTDIR)$(samplesdir)/geos
$(INSTALL) -m0644 tutorial/*.* $(DESTDIR)$(samplesdir)/tutorial
$(INSTALL) -m0644 atari2600/*.* $(DESTDIR)$(samplesdir)/atari2600
$(INSTALL) -m0644 atari5200/*.* $(DESTDIR)$(samplesdir)/atari5200
$(INSTALL) -m0644 apple2/*.* $(DESTDIR)$(samplesdir)/apple2
$(INSTALL) -m0644 cbm/*.* $(DESTDIR)$(samplesdir)/cbm
$(INSTALL) -m0644 gamate/*.* $(DESTDIR)$(samplesdir)/gamate
$(INSTALL) -m0644 supervision/*.* $(DESTDIR)$(samplesdir)/supervision
$(INSTALL) -m0644 disasm/*.* $(DESTDIR)$(samplesdir)/disasm
$(INSTALL) -m0644 kim1/*.* $(DESTDIR)$(samplesdir)/kim1
$(INSTALL) -m0644 lynx/*.* $(DESTDIR)$(samplesdir)/lynx
$(INSTALL) -m0644 sim65/*.* $(DESTDIR)$(samplesdir)/sim65
$(INSTALL) -m0644 sym1/*.* $(DESTDIR)$(samplesdir)/sym1
# --------------------------------------------------------------------------
# Packaging rules
@@ -341,8 +608,11 @@ zip:
# Clean-up rules
mostlyclean:
@$(DEL) *.lbl *.map *.o *.s 2>$(NULLDEV)
@$(DEL) *.lbl *.map *.o 2>$(NULLDEV)
# we cant use .s since we have asm files in the directory that we want to keep
@$(DEL) ${patsubst %.c,%.s,$(wildcard *.c)} 2>$(NULLDEV)
clean: mostlyclean
@$(DEL) $(EXELIST_$(SYS)) $(DISK_$(SYS)) 2>$(NULLDEV)
@$(DEL) multdemo.? ovrldemo.? 2>$(NULLDEV)
$(foreach dir,$(DIRLIST),$(SUBDIR_recipe))

94
samples/apple2/Makefile Normal file
View File

@@ -0,0 +1,94 @@
# Run 'make SYS=<target>'; or, set a SYS env.
# var. to build for another target system.
SYS ?= apple2
# For this one see https://applecommander.github.io/
AC ?= ac.jar
# Just the usual way to find out if we're
# using cmd.exe to execute make rules.
ifneq ($(shell echo),)
CMD_EXE = 1
endif
ifdef CMD_EXE
NULLDEV = nul:
DEL = -del /f
RMDIR = rmdir /s /q
else
NULLDEV = /dev/null
DEL = $(RM)
RMDIR = $(RM) -r
endif
ifdef CC65_HOME
AS = $(CC65_HOME)/bin/ca65
CC = $(CC65_HOME)/bin/cc65
CL = $(CC65_HOME)/bin/cl65
LD = $(CC65_HOME)/bin/ld65
else
AS := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
CC := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65)
CL := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
endif
EXELIST_apple2 = \
hgrshow \
hgrtest \
dhgrshow
ifneq ($(EXELIST_$(SYS)),)
samples: $(EXELIST_$(SYS))
else
samples: notavailable
endif
# empty target used to skip systems that will not work with any program in this dir
notavailable:
ifeq ($(MAKELEVEL),0)
@echo "info: apple2 tests not available for" $(SYS)
else
# suppress the "nothing to be done for 'samples' message
@echo > $(NULLDEV)
endif
disk: hgr.dsk dhgr.dsk
hgr.dsk: hgrshow hgrtest
cp prodos.dsk $@
java -jar $(AC) -as $@ hgrshow <hgrshow
java -jar $(AC) -as $@ hgrtest <hgrtest
java -jar $(AC) -p $@ astronaut.hgr bin 0x2000 <astronaut.hgr
java -jar $(AC) -p $@ chips.hgr bin 0x2000 <chips.hgr
java -jar $(AC) -p $@ macrometer.hgr bin 0x2000 <macrometer.hgr
java -jar $(AC) -p $@ mariner.hgr bin 0x2000 <mariner.hgr
java -jar $(AC) -p $@ rose.hgr bin 0x2000 <rose.hgr
java -jar $(AC) -p $@ werner.hgr bin 0x2000 <werner.hgr
java -jar $(AC) -p $@ winston.hgr bin 0x2000 <winston.hgr
hgrshow: hgrshow.c
$(CL) -Oirs -t apple2 --start-addr 0x4000 -m hgrshow.map $^
hgrtest: hgrtest.c werner.s
$(CL) -Oirs -t apple2 -C apple2-hgr.cfg -m hgrtest.map $^
dhgr.dsk: dhgrshow
cp prodos.dsk $@
java -jar $(AC) -as $@ dhgrshow <dhgrshow
java -jar $(AC) -p $@ catface.dhgr bin 0x2000 <catface.dhgr
java -jar $(AC) -p $@ gatsby.dhgr bin 0x2000 <gatsby.dhgr
java -jar $(AC) -p $@ girl.dhgr bin 0x2000 <girl.dhgr
java -jar $(AC) -p $@ monarch.dhgr bin 0x2000 <monarch.dhgr
java -jar $(AC) -p $@ superman.dhgr bin 0x2000 <superman.dhgr
java -jar $(AC) -p $@ venice.dhgr bin 0x2000 <venice.dhgr
dhgrshow: dhgrshow.c
$(CL) -Oirs -t apple2enh --start-addr 0x4000 -m dhgrshow.map $^
clean:
@$(DEL) hgr.dsk dhgr.dsk 2>$(NULLDEV)
@$(DEL) hgrshow hgrshow.map 2>$(NULLDEV)
@$(DEL) hgrtest hgrtest.map 2>$(NULLDEV)
@$(DEL) dhgrshow dhgrshow.map 2>$(NULLDEV)

Binary file not shown.

BIN
samples/apple2/catface.dhgr Normal file

Binary file not shown.

BIN
samples/apple2/chips.hgr Normal file

Binary file not shown.

46
samples/apple2/dhgrshow.c Normal file
View File

@@ -0,0 +1,46 @@
// cl65 -t apple2enh --start-addr 0x4000 dhgrshow.c
#include <tgi.h>
#include <conio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <peekpoke.h>
void main (void)
{
unsigned old;
DIR *dir;
struct dirent *ent;
old = videomode (VIDEOMODE_80x24);
tgi_install (a2e_hi_tgi);
tgi_init ();
POKE (0xC05E, 0);
dir = opendir (".");
while (ent = readdir (dir)) {
char *ext;
int hgr;
ext = strrchr (ent->d_name, '.');
if (!ext || strcasecmp (ext, ".dhgr"))
continue;
hgr = open (ent->d_name, O_RDONLY);
POKE (0xC055, 0);
read (hgr, (void*)0x2000, 0x2000);
POKE (0xC054, 0);
read (hgr, (void*)0x2000, 0x2000);
close (hgr);
if (cgetc () == '\r')
break;
}
closedir (dir);
POKE (0xC05F, 0);
tgi_uninstall ();
videomode (old);
}

BIN
samples/apple2/gatsby.dhgr Normal file

Binary file not shown.

BIN
samples/apple2/girl.dhgr Normal file

Binary file not shown.

37
samples/apple2/hgrshow.c Normal file
View File

@@ -0,0 +1,37 @@
// cl65 -t apple2 --start-addr 0x4000 hgrshow.c
#include <tgi.h>
#include <conio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
void main (void)
{
DIR *dir;
struct dirent *ent;
tgi_install (a2_hi_tgi);
tgi_init ();
dir = opendir (".");
while (ent = readdir (dir)) {
char *ext;
int hgr;
ext = strrchr (ent->d_name, '.');
if (!ext || strcasecmp (ext, ".hgr"))
continue;
hgr = open (ent->d_name, O_RDONLY);
read (hgr, (void*)0x2000, 0x2000);
close (hgr);
if (cgetc () == '\r')
break;
}
closedir (dir);
tgi_uninstall ();
}

26
samples/apple2/hgrtest.c Normal file
View File

@@ -0,0 +1,26 @@
// cl65 -t apple2 -C apple2-hgr.cfg hgrtest.c werner.s
#include <tgi.h>
#include <conio.h>
#pragma code-name (push, "LOWCODE")
void say (const char* text)
{
tgi_setcolor (TGI_COLOR_BLACK);
tgi_outtextxy (41, 33, text);
}
#pragma code-name (pop)
void main (void)
{
tgi_install (a2_hi_tgi);
tgi_init ();
cgetc ();
say ("Hi Dude !");
cgetc ();
tgi_uninstall ();
}

Binary file not shown.

BIN
samples/apple2/mariner.hgr Normal file

Binary file not shown.

BIN
samples/apple2/monarch.dhgr Normal file

Binary file not shown.

BIN
samples/apple2/rose.hgr Normal file

Binary file not shown.

Binary file not shown.

BIN
samples/apple2/venice.dhgr Normal file

Binary file not shown.

BIN
samples/apple2/werner.hgr Normal file

Binary file not shown.

2
samples/apple2/werner.s Normal file
View File

@@ -0,0 +1,2 @@
.segment "HGR"
.incbin "werner.hgr"

BIN
samples/apple2/winston.hgr Normal file

Binary file not shown.

View File

@@ -0,0 +1,59 @@
# Run 'make SYS=<target>'; or, set a SYS env.
# var. to build for another target system.
SYS ?= atari2600
# Just the usual way to find out if we're
# using cmd.exe to execute make rules.
ifneq ($(shell echo),)
CMD_EXE = 1
endif
ifdef CMD_EXE
NULLDEV = nul:
DEL = -del /f
RMDIR = rmdir /s /q
else
NULLDEV = /dev/null
DEL = $(RM)
RMDIR = $(RM) -r
endif
ifdef CC65_HOME
AS = $(CC65_HOME)/bin/ca65
CC = $(CC65_HOME)/bin/cc65
CL = $(CC65_HOME)/bin/cl65
LD = $(CC65_HOME)/bin/ld65
SP = $(CC65_HOME)/bin/sp65
else
AS := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
CC := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65)
CL := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
SP := $(if $(wildcard ../../bin/sp65*),../../bin/sp65,sp65)
endif
EXELIST_atari2600 = \
hello
ifneq ($(EXELIST_$(SYS)),)
samples: $(EXELIST_$(SYS))
else
samples: notavailable
endif
# empty target used to skip systems that will not work with any program in this dir
notavailable:
ifeq ($(MAKELEVEL),0)
@echo "info: atari 2600 samples not available for" $(SYS)
else
# suppress the "nothing to be done for 'samples' message
@echo > $(NULLDEV)
endif
hello: hello.c
$(CL) -t $(SYS) -O -o hello -m hello.map hello.c
clean:
@$(DEL) $(EXELIST_atari2600) 2>$(NULLDEV)
@$(DEL) *.map 2>$(NULLDEV)

View File

@@ -0,0 +1,56 @@
# Run 'make SYS=<target>'; or, set a SYS env.
# var. to build for another target system.
SYS ?= atari5200
# Just the usual way to find out if we're
# using cmd.exe to execute make rules.
ifneq ($(shell echo),)
CMD_EXE = 1
endif
ifdef CMD_EXE
NULLDEV = nul:
DEL = -del /f
RMDIR = rmdir /s /q
else
NULLDEV = /dev/null
DEL = $(RM)
RMDIR = $(RM) -r
endif
ifdef CC65_HOME
AS = $(CC65_HOME)/bin/ca65
CC = $(CC65_HOME)/bin/cc65
CL = $(CC65_HOME)/bin/cl65
LD = $(CC65_HOME)/bin/ld65
else
AS := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
CC := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65)
CL := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
endif
EXELIST_atari5200 = \
hello
ifneq ($(EXELIST_$(SYS)),)
samples: $(EXELIST_$(SYS))
else
samples: notavailable
endif
# empty target used to skip systems that will not work with any program in this dir
notavailable:
ifeq ($(MAKELEVEL),0)
@echo "info: atari 5200 tests not available for" $(SYS)
else
# suppress the "nothing to be done for 'samples' message
@echo > $(NULLDEV)
endif
hello: hello.c
$(CL) -t atari5200 -o hello hello.c
clean:
@$(DEL) hello 2>$(NULLDEV)

109
samples/atari5200/hello.c Normal file
View File

@@ -0,0 +1,109 @@
/*
** Fancy hello world program using cc65.
**
** Ullrich von Bassewitz (ullrich@von-bassewitz.de)
**
** TEST version for atari5200 conio, using all four colors
*/
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <joystick.h>
/*****************************************************************************/
/* Data */
/*****************************************************************************/
static const char Text [] = "Hello world!";
static unsigned char colors[] = { COLOR_WHITE, COLOR_GREEN, COLOR_RED, COLOR_BLACK };
/*****************************************************************************/
/* Code */
/*****************************************************************************/
int main (void)
{
unsigned char XSize, YSize;
unsigned char PosY;
unsigned char i = 0;
/* Set screen colors */
(void) textcolor (COLOR_WHITE);
(void) bordercolor (COLOR_BLACK);
(void) bgcolor (COLOR_BLACK);
/* Clear the screen, put cursor in upper left corner */
clrscr ();
/* Ask for the screen size */
screensize (&XSize, &YSize);
/* Install joystick driver */
joy_install (joy_static_stddrv);
while (1) {
/* Draw a border around the screen */
/* Top line */
cputc (CH_ULCORNER);
chline (XSize - 2);
cputc (CH_URCORNER);
/* Vertical line, left side */
cvlinexy (0, 1, YSize - 2);
/* Bottom line */
cputc (CH_LLCORNER);
chline (XSize - 2);
cputc (CH_LRCORNER);
/* Vertical line, right side */
cvlinexy (XSize - 1, 1, YSize - 2);
/* Write the greeting in the mid of the screen */
gotoxy ((XSize - strlen (Text)) / 2, YSize / 2);
cprintf ("%s", Text);
PosY = wherey ();
textcolor (colors[i]); /* switch to color #0 */
cputsxy(3, ++PosY, "COLOR 0");
textcolor ((colors[i] + 1) & 3); /* switch to color #1 */
cputsxy(3, ++PosY, "COLOR 1");
textcolor ((colors[i] + 2) & 3); /* switch to color #2 */
cputsxy(3, ++PosY, "COLOR 2");
textcolor ((colors[i] + 3) & 3); /* switch to color #3 */ /* color #3 is the background color. So written text isn't visible. */
cputsxy(3, ++PosY, "COLOR 3");
/* Wait for the user to press and release a button */
while (!joy_read (JOY_1))
;
while (joy_read (JOY_1))
;
i = (i + 1) & 3;
/* Change colors */
textcolor (colors[i]);
bgcolor ((colors[i] + 3) & 3);
/* Clear the screen again */
clrscr ();
}
/* not reached */
joy_uninstall ();
/* Done */
return EXIT_SUCCESS;
}

176
samples/cbm/Makefile Normal file
View File

@@ -0,0 +1,176 @@
# Run 'make SYS=<target>'; or, set a SYS env.
# var. to build for another target system.
SYS ?= c64
# Just the usual way to find out if we're
# using cmd.exe to execute make rules.
ifneq ($(shell echo),)
CMD_EXE = 1
endif
ifdef CMD_EXE
NULLDEV = nul:
DEL = -del /f
RMDIR = rmdir /s /q
else
NULLDEV = /dev/null
DEL = $(RM)
RMDIR = $(RM) -r
endif
ifdef CC65_HOME
AS = $(CC65_HOME)/bin/ca65
CC = $(CC65_HOME)/bin/cc65
CL = $(CC65_HOME)/bin/cl65
LD = $(CC65_HOME)/bin/ld65
SP = $(CC65_HOME)/bin/sp65
else
AS := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
CC := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65)
CL := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
SP := $(if $(wildcard ../../bin/sp65*),../../bin/sp65,sp65)
endif
ifneq ($(filter disk samples.%,$(MAKECMDGOALS)),)
ifdef CC65_HOME
TARGET_PATH = $(CC65_HOME)/target
else
TARGET_PATH := $(if $(wildcard ../target),../target,$(shell $(CL) --print-target-path))
endif
# If TARGET_PATH contains spaces then it is presumed to contain escaped spaces. GNU make
# has very limited support for paths containing spaces. $(wildcard) is the only function
# that is aware of escaped spaces. However, $(wildcard) never returns paths with escaped
# spaces !!! So if it e.g. finds 4 files in a path with 2 spaces then one ends up with a
# return value consisting of 12 plain words :-((
#
# Fortunately we can work around that behaviour here because we know that the files we
# are looking for have known extensions. So we can $(filter) the in our example above 12
# words for file extensions so we come up with 4 path fragments. Then we remove those
# path fragments with $(notdir) from the file names.
#
# So far so good. But here we want to process files from different paths in a single
# recipe further down below and therefore want to prepend the paths to the files with
# $(addprefix). However, $(foreach) isn't aware of escaped spaces (only $(wildcard) is).
# Therefore, we need to replace the spaces with some other character temporarily in order
# to have $(foreach) generate one invocation per file. We use the character '?' for that
# purpose here, just because it is known to not be part of file names.
#
# Inside the recipe generated per file we then replace the '?' again with a space. As we
# want to be compatible with cmd.exe for execution we're not using an escaped space but
# rather double-quote the whole path.
#
# Note: The "strange" $(wildcard) further down below just serves the purpose to unescape
# spaces for cmd.exe. This could have as well been done with another $(subst).
SUBST_TARGET_PATH := $(subst \$(SPACE),?,$(TARGET_PATH))
EMD := $(wildcard $(TARGET_PATH)/$(SYS)/drv/emd/*)
MOU := $(wildcard $(TARGET_PATH)/$(SYS)/drv/mou/*)
TGI := $(wildcard $(TARGET_PATH)/$(SYS)/drv/tgi/*)
EMD := $(addprefix $(SUBST_TARGET_PATH)/$(SYS)/drv/emd/,$(notdir $(filter %.emd,$(EMD))))
MOU := $(addprefix $(SUBST_TARGET_PATH)/$(SYS)/drv/mou/,$(notdir $(filter %.mou,$(MOU))))
TGI := $(addprefix $(SUBST_TARGET_PATH)/$(SYS)/drv/tgi/,$(notdir $(filter %.tgi,$(TGI))))
# This one comes with the VICE emulator.
# See http://vice-emu.sourceforge.net/
C1541 ?= c1541
endif
DISK_$(SYS) = samples.d64
EXELIST_c64 = \
fire \
plasma \
nachtm \
hello
EXELIST_c128 = \
fire \
plasma \
nachtm \
hello
EXELIST_cbm510 = \
fire \
plasma \
nachtm
EXELIST_cbm610 = \
nachtm
EXELIST_plus4 = \
plasma \
hello
EXELIST_c16 = \
hello
EXELIST_pet = \
notavailable
EXELIST_vic20 = \
hello
ifneq ($(EXELIST_$(SYS)),)
samples: $(EXELIST_$(SYS))
else
samples: notavailable
endif
disk: $(DISK_$(SYS))
# empty target used to skip systems that will not work with any program in this dir
notavailable:
ifeq ($(MAKELEVEL),0)
@echo "info: cbm samples not available for" $(SYS)
else
# suppress the "nothing to be done for 'samples' message
@echo > $(NULLDEV)
endif
fire: fire.c
$(CL) -t $(SYS) -O -o fire -m fire.map fire.c
plasma: plasma.c
$(CL) -t $(SYS) -O -o plasma -m plasma.map plasma.c
nachtm: nachtm.c
$(CL) -t $(SYS) -O -o nachtm -m nachtm.map nachtm.c
hello: hello-asm.s
# Use separate assembler ...
$(AS) -t $(SYS) hello-asm.s
# ... and linker commands ...
$(LD) -C $(SYS)-asm.cfg -o hello -m hello-asm.map -u __EXEHDR__ hello-asm.o $(SYS).lib
@$(DEL) hello-asm.o 2>$(NULLDEV)
# ... or compile & link utility
# $(CL) -C $(SYS)-asm.cfg -o hello -m hello-asm.map -u __EXEHDR__ hello-asm.s
# --------------------------------------------------------------------------
# Rule to make a CBM disk with all samples. Needs the c1541 program that comes
# with the VICE emulator.
define D64_WRITE_PRG_recipe
$(C1541) -attach $@ -write "$(subst ?,$(SPACE),$(file))" $(notdir $(file)),p >$(NULLDEV)
endef # D64_WRITE_PRG_recipe
define D64_WRITE_SEQ_recipe
$(C1541) -attach $@ -write "$(subst ?,$(SPACE),$(file))" $(notdir $(file)),s >$(NULLDEV)
endef # D64_WRITE_SEQ_recipe
samples.d64: samples
@$(C1541) -format "samples,00" d64 $@ >$(NULLDEV)
$(foreach file,$(EXELIST_$(SYS)),$(D64_WRITE_PRG_recipe))
# $(foreach file,$(OVERLAYLIST),$(D64_WRITE_PRG_recipe))
# $(foreach file,$(EMD) $(MOU) $(TGI),$(D64_WRITE_SEQ_recipe))
clean:
@$(DEL) $(EXELIST_$(SYS)) 2>$(NULLDEV)
@$(DEL) *.map 2>$(NULLDEV)
@$(DEL) $(DISK_$(SYS)) 2>$(NULLDEV)

View File

@@ -56,7 +56,7 @@
/* Use static local variables for speed */
#pragma static-locals (1);
#pragma static-locals (1)

15
samples/cbm/hello-asm.s Normal file
View File

@@ -0,0 +1,15 @@
;
; Sample assembly program for Commodore machines
;
.include "cbm_kernal.inc"
ldx #$00
: lda text,x
beq out
jsr CHROUT
inx
bne :-
out: rts
text: .asciiz "hello world!"

View File

@@ -972,12 +972,12 @@ static void MakeNiceScreen (void)
/* Clear the screen hide the cursor, set colors */
#ifdef __CBM610__
textcolor (COLOR_WHITE);
(void)textcolor (COLOR_WHITE);
#else
textcolor (COLOR_GRAY3);
(void)textcolor (COLOR_GRAY3);
#endif
bordercolor (COLOR_BLACK);
bgcolor (COLOR_BLACK);
(void)bordercolor (COLOR_BLACK);
(void)bgcolor (COLOR_BLACK);
clrscr ();
cursor (0);

View File

@@ -1,7 +1,7 @@
/*****************************************************************************\
** plasma test program for cc65. **
** **
** (w)2001 by groepaz/hitmen **
** (w)2001 by groepaz **
** **
** Cleanup and porting by Ullrich von Bassewitz. **
** **
@@ -51,8 +51,7 @@
/* Use static local variables for speed */
#pragma static-locals (1);
#pragma static-locals (1)
static const unsigned char sinustable[0x100] = {
@@ -131,8 +130,6 @@ static void doplasma (register unsigned char* scrn)
}
}
static void makechar (void)
{
static const unsigned char bittab[8] = {
@@ -147,7 +144,7 @@ static void makechar (void)
for (i = 0; i < 8; ++i){
b = 0;
for (ii = 0; ii < 8; ++ii) {
if ((rand() & 0xFF) > s) {
if ((rand() & 0xFFu) > s) {
b |= bittab[ii];
}
}

40
samples/checkversion.c Normal file
View File

@@ -0,0 +1,40 @@
/* Until 2.19 the __CC65__ macro was defined as (VER_MAJOR * 0x100) + (VER_MINOR * 0x10),
* which caused it to contain broken values in compiler releases 2.16 to 2.19. The
* macro was fixed some time after 2.19 to (VER_MAJOR * 0x100) + VER_MINOR.
*
* The following strategy can be used to still compare for less or greater versions,
* should this really be necessary or wanted - it is not recommended afterall.
*/
#include <stdio.h>
#include <stdlib.h>
#if ((__CC65__ >> 8) > 3) || ((__CC65__ & 0x000f) > 0)
/* compiler version is 2.19-git or higher */
# define VER_MAJOR ((__CC65__ >> 8) & 0xff)
# define VER_MINOR (__CC65__ & 0xff)
#elif ((__CC65__ >> 8) == 3)
/* broken values in version 2.16 - 2.19-git before the bug was fixed */
# define VER_MAJOR 2
# define VER_MINOR (((__CC65__ >> 4) & 0x0f) + 16)
#else
/* values before 2.16 */
# define VER_MAJOR ((__CC65__ >> 8) & 0xff)
# define VER_MINOR ((__CC65__ >> 4) & 0x0f)
#endif
/* define a new value that will work for comparing all versions */
#define VERSION ((VER_MAJOR << 8) + VER_MINOR)
int main(void)
{
printf("__CC65__ defined as %04x\n", __CC65__);
printf("compiler version is %u.%u\n", VER_MAJOR, VER_MINOR);
if (__CC65__ == VERSION) {
printf("__CC65__ is defined correctly as (VER_MAJOR * 0x100) + VER_MINOR\n");
return EXIT_SUCCESS;
}
printf("__CC65__ is incorrectly defined as (VER_MAJOR * 0x100) + (VER_MINOR * 0x10)\n");
return EXIT_FAILURE;
}

2
samples/disasm/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*.s
image.bin

59
samples/disasm/Makefile Normal file
View File

@@ -0,0 +1,59 @@
# Sample makefile using a preprocessor against info files
# and the --sync-lines option
# Just the usual way to find out if we're
# using cmd.exe to execute make rules.
ifneq ($(shell echo),)
CMD_EXE = 1
endif
ifdef CMD_EXE
NULLDEV = nul:
DEL = -del /f
RMDIR = rmdir /s /q
else
NULLDEV = /dev/null
DEL = $(RM)
RMDIR = $(RM) -r
endif
ifdef CC65_HOME
AS = $(CC65_HOME)/bin/ca65
CC = $(CC65_HOME)/bin/cc65
CL = $(CC65_HOME)/bin/cl65
LD = $(CC65_HOME)/bin/ld65
DA = $(CC65_HOME)/bin/da65
else
AS := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
CC := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65)
CL := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
DA := $(if $(wildcard ../../bin/da65*),../../bin/da65,da65)
endif
CPP = cpp
#CPPFLAGS = -DTEST_ERROR
ASMS = fixed.s bank0.s bank1.s
DAIS = fixed.dai bank0.dai bank1.dai
.SUFFIXES: .da .dai .s
samples: image.bin $(ASMS)
$(DAIS): fixed.da
.da.dai:
$(CPP) -o $@ $(CPPFLAGS) $<
.dai.s:
$(DA) --sync-lines -o $@ -i $< image.bin
image.bin: image.s image.cfg
$(CL) -t none -C image.cfg -o image.bin image.s
clean:
@$(DEL) $(ASMS) 2>$(NULLDEV)
@$(DEL) $(DAIS) 2>$(NULLDEV)
@$(DEL) image.bin 2>$(NULLDEV)

16
samples/disasm/bank0.da Normal file
View File

@@ -0,0 +1,16 @@
// Da65 input file before preprocessed by cpp
// Bank0 ROM map
#define TARGET_BANK 0
global {
inputoffs $00010;
inputsize $4000;
startaddr $8000;
cpu "6502";
};
#include "fixed.da"
label { addr $8000; name "Bank0ProcA"; };
label { addr $8123; name "Bank0ProcB"; };
range { start $A000; end $BFFF; name "Bank0Data"; type ByteTable; };

16
samples/disasm/bank1.da Normal file
View File

@@ -0,0 +1,16 @@
// Da65 input file before preprocessed by cpp
// Bank1 ROM map
#define TARGET_BANK 1
global {
inputoffs $04010;
inputsize $4000;
startaddr $8000;
cpu "6502";
};
#include "fixed.da"
range { start $8000; end $AFFF; name "Bank1Data"; type ByteTable; };
label { addr $B000; name "Bank1ProcA"; };
label { addr $B123; name "Bank1ProcB"; };

30
samples/disasm/fixed.da Normal file
View File

@@ -0,0 +1,30 @@
// Da65 input file before preprocessed by cpp
// RAM and Fixed ROM map
#ifndef FIXED_DA_INCLUDED
#define FIXED_DA_INCLUDED
#ifndef TARGET_BANK
#define TARGET_BANK -1
global {
inputoffs $0C010;
inputsize $4000;
startaddr $C000;
cpu "6502";
};
#endif /* !defined(TARGET_BANK) */
// ---- RAM map ----
label { addr $00; name "VariableA"; };
label { addr $01; name "VariableB"; };
label { addr $0100; name "Stack"; size $0100; };
#if defined(TEST_ERROR) && TARGET_BANK == 0
erroneous_line;
#endif
// ---- Fixed ROM map ----
label { addr $C000; name "CommonProcA"; };
label { addr $C123; name "CommonProcB"; };
range { start $E123; end $FFFF; name "CommonData"; type ByteTable; };
#endif /* !defined(FIXED_DA_INCLUDED) */

15
samples/disasm/image.cfg Normal file
View File

@@ -0,0 +1,15 @@
MEMORY {
HEADER: file = %O, start = $0000, size = $0010, fill = yes;
BANK00: file = %O, start = $8000, size = $4000, fill = yes;
BANK01: file = %O, start = $8000, size = $4000, fill = yes;
BANK02: file = %O, start = $8000, size = $4000, fill = yes;
FIXED: file = %O, start = $c000, size = $4000, fill = yes;
}
SEGMENTS {
HDR: load = HEADER, type = rw, optional = yes, define = yes;
BANK0: load = BANK00, type = rw, optional = yes, define = yes;
BANK1: load = BANK01, type = rw, optional = yes, define = yes;
BANK2: load = BANK02, type = rw, optional = yes, define = yes;
FIX: load = FIXED, type = rw, optional = yes, define = yes;
}

View File

@@ -11,36 +11,52 @@
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <device.h>
#include <dirent.h>
#include <cc65.h>
void printdir (char *newdir)
/* returns true for error, false for OK */
bool printdir (char *newdir)
{
char olddir[FILENAME_MAX];
char curdir[FILENAME_MAX];
char *olddir;
char *curdir;
DIR *dir;
struct dirent *ent;
char *subdirs = NULL;
unsigned dirnum = 0;
unsigned num;
getcwd (olddir, sizeof (olddir));
olddir = malloc (FILENAME_MAX);
if (olddir == NULL) {
perror ("cannot allocate memory");
return true;
}
getcwd (olddir, FILENAME_MAX);
if (chdir (newdir)) {
/* If chdir() fails we just print the
** directory name - as done for files.
*/
printf (" Dir %s\n", newdir);
return;
free (olddir);
return false;
}
curdir = malloc (FILENAME_MAX);
if (curdir == NULL) {
perror ("cannot allocate memory");
return true;
}
/* We call getcwd() in order to print the
** absolute pathname for a subdirectory.
*/
getcwd (curdir, sizeof (curdir));
getcwd (curdir, FILENAME_MAX);
printf (" Dir %s:\n", curdir);
free (curdir);
/* Calling opendir() always with "." avoids
** fiddling around with pathname separators.
@@ -65,18 +81,27 @@ void printdir (char *newdir)
closedir (dir);
for (num = 0; num < dirnum; ++num) {
printdir (subdirs + FILENAME_MAX * num);
if (printdir (subdirs + FILENAME_MAX * num))
break;
}
free (subdirs);
chdir (olddir);
free (olddir);
return false;
}
void main (void)
{
unsigned char device;
char devicedir[FILENAME_MAX];
char *devicedir;
devicedir = malloc (FILENAME_MAX);
if (devicedir == NULL) {
perror ("cannot allocate memory");
return;
}
/* Calling getfirstdevice()/getnextdevice() does _not_ turn on the motor
** of a drive-type device and does _not_ check for a disk in the drive.
@@ -88,7 +113,7 @@ void main (void)
/* Calling getdevicedir() _does_ check for a (formatted) disk in a
** floppy-disk-type device and returns NULL if that check fails.
*/
if (getdevicedir (device, devicedir, sizeof (devicedir))) {
if (getdevicedir (device, devicedir, FILENAME_MAX)) {
printdir (devicedir);
} else {
printf (" N/A\n");
@@ -100,4 +125,6 @@ void main (void)
if (doesclrscrafterexit ()) {
getchar ();
}
free (devicedir);
}

57
samples/gamate/Makefile Normal file
View File

@@ -0,0 +1,57 @@
# Run 'make SYS=<target>'; or, set a SYS env.
# var. to build for another target system.
SYS ?= gamate
# Just the usual way to find out if we're
# using cmd.exe to execute make rules.
ifneq ($(shell echo),)
CMD_EXE = 1
endif
ifdef CMD_EXE
NULLDEV = nul:
DEL = -del /f
RMDIR = rmdir /s /q
else
NULLDEV = /dev/null
DEL = $(RM)
RMDIR = $(RM) -r
endif
ifdef CC65_HOME
AS = $(CC65_HOME)/bin/ca65
CC = $(CC65_HOME)/bin/cc65
CL = $(CC65_HOME)/bin/cl65
LD = $(CC65_HOME)/bin/ld65
else
AS := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
CC := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65)
CL := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
endif
EXELIST_gamate = \
nachtm.bin
ifneq ($(EXELIST_$(SYS)),)
samples: $(EXELIST_$(SYS))
else
samples: notavailable
endif
# empty target used to skip systems that will not work with any program in this dir
notavailable:
ifeq ($(MAKELEVEL),0)
@echo "info: gamate tests not available for" $(SYS)
else
# suppress the "nothing to be done for 'samples' message
@echo > $(NULLDEV)
endif
nachtm.bin: nachtm.c
$(CL) -Os -l nachtm.lst -t gamate -o nachtm.bin nachtm.c
../../util/gamate/gamate-fixcart nachtm.bin
clean:
@$(DEL) nachtm.bin nachtm.lst 2>$(NULLDEV)

1157
samples/gamate/nachtm.c Normal file

File diff suppressed because it is too large Load Diff

146
samples/geos/Makefile Normal file
View File

@@ -0,0 +1,146 @@
# Run 'make SYS=<target>'; or, set a SYS env.
# var. to build for another target system.
SYS ?= geos-cbm
# Comes with the VICE emulator, see http://vice-emu.sourceforge.net/
C1541 ?= c1541
# If SYS was given on the commandline, redirect "c64" to "geos-cbm" and
# "apple2enh" to "geos-apple"
ifeq ($(origin SYS),command line)
ifeq ($(SYS),c64)
override SYS = geos-cbm
$(info GEOS: c64 -> geos-cbm)
endif
ifeq ($(SYS),apple2enh)
override SYS = geos-apple
$(info GEOS: apple2enh -> geos-apple)
endif
endif
# Just the usual way to find out if we're
# using cmd.exe to execute make rules.
ifneq ($(shell echo),)
CMD_EXE = 1
endif
ifdef CMD_EXE
NULLDEV = nul:
DEL = -del /f
RMDIR = rmdir /s /q
else
NULLDEV = /dev/null
DEL = $(RM)
RMDIR = $(RM) -r
endif
ifdef CC65_HOME
AS = $(CC65_HOME)/bin/ca65
CC = $(CC65_HOME)/bin/cc65
CL = $(CC65_HOME)/bin/cl65
LD = $(CC65_HOME)/bin/ld65
SP = $(CC65_HOME)/bin/sp65
else
AS := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
CC := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65)
CL := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
SP := $(if $(wildcard ../../bin/sp65*),../../bin/sp65,sp65)
endif
DIRLIST = grc
define SUBDIR_recipe
@+$(MAKE) SYS=$(SYS) -C $(dir) --no-print-directory $@
endef # SUBDIR_recipe
EXELIST_geos-cbm = \
bitmap-demo.cvt \
filesel.cvt \
geosver.cvt \
getid.cvt \
hello1.cvt \
hello2.cvt \
overlay-demo.cvt \
vector-demo.cvt \
yesno.cvt
EXELIST_geos-apple = \
bitmap-demo.cvt \
filesel.cvt \
hello1.cvt \
hello2.cvt \
overlay-demo.cvt \
vector-demo.cvt \
yesno.cvt
# omitted: dialog.c grphstr.c inittab.c menu.c
# TODO: geosconio.cvt rmvprot.cvt
ifneq ($(EXELIST_$(SYS)),)
samples: $(EXELIST_$(SYS))
$(foreach dir,$(DIRLIST),$(SUBDIR_recipe))
define samples-geos
$(C1541) -attach $(0).d64 -geoswrite $(1);
endef
samples-geos: $(EXELIST_$(SYS))
$(C1541) -format "$@,01" d64 $@.d64
$(foreach tool,$(EXELIST_$(SYS)),$(call samples-geos,$(tool)))
else
samples:
ifeq ($(MAKELEVEL),0)
@echo "info: geos samples not available for" $(SYS)
else
# suppress the "nothing to be done for 'samples' message
@echo > $(NULLDEV)
endif
endif
bitmap.c: logo.pcx
$(SP) -r logo.pcx -c geos-bitmap -w bitmap.c,ident=bitmap
bitmap-demo.cvt: bitmap.c bitmap-demores.grc bitmap-demo.c
$(CL) -t $(SYS) -O -o $@ -m bitmap-demo.map bitmap-demores.grc bitmap-demo.c
filesel.cvt: fileselres.grc filesel.c
$(CL) -t $(SYS) -O -o $@ -m filesel.map fileselres.grc filesel.c
geosconio.cvt: geosconiores.grc geosconio.c
$(CL) -t $(SYS) -O -o $@ -m geosconio.map geosconiores.grc geosconio.c
geosver.cvt: geosverres.grc geosver.c
$(CL) -t $(SYS) -O -o $@ -m geosver.map geosverres.grc geosver.c
getid.cvt: getidres.grc getid.c
$(CL) -t $(SYS) -O -o $@ -m getid.map getidres.grc getid.c
hello1.cvt: hello1res.grc hello1.c
$(CL) -t $(SYS) -O -o $@ -m hello1.map hello1res.grc hello1.c
hello2.cvt: hello2res.grc hello2.c
$(CL) -t $(SYS) -O -o $@ -m hello2.map hello2res.grc hello2.c
overlay-demo.cvt: overlay-demores.grc overlay-demo.c
$(CL) -t $(SYS) -O -o $@ -m overlay-demo.map overlay-demores.grc overlay-demo.c
rmvprot.cvt: rmvprotres.grc rmvprot.c
$(CL) -t $(SYS) -O -o $@ -m rmvprot.map rmvprotres.grc rmvprot.c
vector-demo.cvt: vector-demores.grc vector-demo.c
$(CL) -t $(SYS) -O -o $@ -m vector-demo.map vector-demores.grc vector-demo.c
yesno.cvt: yesnores.grc yesno.c
$(CL) -t $(SYS) -O -o $@ -m yesno.map yesnores.grc yesno.c
clean:
@$(DEL) overlay-demores.h 2>$(NULLDEV)
@$(DEL) bitmap.c 2>$(NULLDEV)
@$(DEL) *.cvt 2>$(NULLDEV)
@$(DEL) *.map 2>$(NULLDEV)
$(foreach dir,$(DIRLIST),$(SUBDIR_recipe))

View File

@@ -1,4 +1,4 @@
/* Note:
/* Note:
** This is just a sample piece of code that shows how to use some structs -
** it may not even run.
*/
@@ -28,5 +28,5 @@ static const dlgBoxStr myDialog = {
void main (void)
{
DoDlgBox (&myDialog);
DoDlgBox (&myDialog);
}

View File

@@ -1,11 +1,11 @@
/*
GEOSLib example
using DlgBoxFileSelect
Maciej 'YTM/Elysium' Witkowiak
<ytm@elysium.pl>
26.12.1999
*/

View File

@@ -9,16 +9,16 @@ void main(void)
char ch;
DlgBoxOk("Now the screen will be", "cleared.");
clrscr();
DlgBoxOk("Now a character will be", "written at 20,20");
gotoxy(20, 20);
cputc('A');
DlgBoxOk("Now a string will be", "written at 0,1");
cputsxy(0, 1, CBOLDON "Just" COUTLINEON "a " CITALICON "string." CPLAINTEXT );
DlgBoxOk("Write text and finish it", "with a dot.");
@@ -31,7 +31,7 @@ void main(void)
cursor(0);
DlgBoxOk("Seems that it is all for conio.", "Let's test mouse routines.");
mouse_init(1);
cputsxy(0, 2, CBOLDON "Now you can't see mouse (press any key)" CPLAINTEXT);
mouse_hide();

View File

@@ -8,8 +8,8 @@ struct window wholeScreen = {0, SC_PIX_HEIGHT-1, 0, SC_PIX_WIDTH-1};
void main (void)
{
unsigned char os = get_ostype();
unsigned char *machine = NULL;
unsigned char *version = NULL;
char *machine = NULL;
char *version = NULL;
unsigned char good = 1;
SetPattern(0);
@@ -57,6 +57,6 @@ void main (void)
}
Sleep(10*50);
return;
}

View File

@@ -16,7 +16,7 @@ const graphicStr Table = {
void Exit(void)
{
exit(0);
exit(EXIT_SUCCESS);
}
void Menu = {

70
samples/geos/grc/Makefile Normal file
View File

@@ -0,0 +1,70 @@
# Run 'make SYS=<target>'; or, set a SYS env.
# var. to build for another target system.
SYS ?= geos-cbm
# Just the usual way to find out if we're
# using cmd.exe to execute make rules.
ifneq ($(shell echo),)
CMD_EXE = 1
endif
ifdef CMD_EXE
NULLDEV = nul:
DEL = -del /f
RMDIR = rmdir /s /q
else
NULLDEV = /dev/null
DEL = $(RM)
RMDIR = $(RM) -r
endif
ifdef CC65_HOME
AS = $(CC65_HOME)/bin/ca65
CC = $(CC65_HOME)/bin/cc65
CL = $(CC65_HOME)/bin/cl65
LD = $(CC65_HOME)/bin/ld65
GRC = $(CC65_HOME)/bin/grc65
else
AS := $(if $(wildcard ../../../bin/ca65*),../../../bin/ca65,ca65)
CC := $(if $(wildcard ../../../bin/cc65*),../../../bin/cc65,cc65)
CL := $(if $(wildcard ../../../bin/cl65*),../../../bin/cl65,cl65)
LD := $(if $(wildcard ../../../bin/ld65*),../../../bin/ld65,ld65)
GRC := $(if $(wildcard ../../../bin/grc65*),../../../bin/grc65,grc65)
endif
EXELIST_geos-cbm = \
test.s \
vlir.cvt
ifneq ($(EXELIST_$(SYS)),)
samples: $(EXELIST_$(SYS))
else
samples:
ifeq ($(MAKELEVEL),0)
@echo "info: grc sample not available for" $(SYS)
else
# suppress the "nothing to be done for 'samples' message
@echo > $(NULLDEV)
endif
endif
test.s: test.grc
$(GRC) -s test.s test.grc
vlir.cvt: vlir.grc vlir0.s vlir1.s vlir2.s
# using separate calls here for demonstration purposes:
$(GRC) -t $(SYS) -s vlir.s vlir.grc
$(AS) -t $(SYS) vlir.s
$(AS) -t $(SYS) vlir0.s
$(AS) -t $(SYS) vlir1.s
$(AS) -t $(SYS) vlir2.s
$(LD) -t $(SYS) -o vlir.cvt vlir.o vlir0.o vlir1.o vlir2.o $(SYS).lib
# you can also do the above in one command:
# $(CL) -t $(SYS) -o vlir.cvt vlir.grc vlir0.s vlir1.s vlir2.s
clean:
@$(DEL) test.s test.h 2>$(NULLDEV)
@$(DEL) vlir.s vlir.cvt vlir.c vlir.h 2>$(NULLDEV)
@$(DEL) *.o 2>$(NULLDEV)

35
samples/geos/grc/test.grc Normal file
View File

@@ -0,0 +1,35 @@
; This is the proposed syntax of a general GEOS resource file for the upcoming resource compiler.
; token MENU, topname (will be escaped with _), x,y of top-left corner, bottom-right will be
; counted according to BSW font table (in x) and a multiply 15 (14?) in y
; Note that MENU is either MENU and SUBMENU
; Note that if you want to use any C operators (like '|', '&' etc.) do it WITHOUT spaces
; between arguments (parser is simple and weak)
; format: MENU "name" left,top ALIGN { "itemname" TYPE pointer ... }
MENU subMenu1 15,0 VERTICAL
{
"subitem1" MENU_ACTION smenu1
"mubitem2" MENU_ACTION|DYN_SUB_MENU smenu2
"subitem3" MENU_ACTION smenu3
}
MENU mainMenu 0,0 HORIZONTAL
{
"sub menu1" SUB_MENU subMenu1 ; goes for _subMenu1
"quit" MENU_ACTION EnterDeskTop ; goes for _EnterDeskTop
}
; format: HEADER GEOS_TYPE "dosname" "classname" "version"
HEADER APPLICATION "123456789 1234567" "Class Name" "V1.0.0"
{
; not all fields are required, default and current values will be used
author "Maciej Witkowiak" ; always in quotes!
info "Information text" ; always in quotes!
; date yy mm dd hh ss ; always 5 fields!
; dostype seq ; can be PRG, SEQ, USR
mode c64only ; can be any, 40only, 80only, c64only
}

12
samples/geos/grc/vlir.grc Normal file
View File

@@ -0,0 +1,12 @@
HEADER APPLICATION "test" "TestApp" "V1.0" {
structure VLIR
dostype USR
author "Maciej Witkowiak"
info "This is just an example."
}
MEMORY {
stacksize 0x0000
overlaysize 0x1000
overlaynums 0 1 2
}

78
samples/geos/grc/vlir0.s Normal file
View File

@@ -0,0 +1,78 @@
; Maciej 'YTM/Elysium' Witkowiak
; 06.06.2002
; This is the source for the main VLIR-structured program part
; include some GEOS defines
.include "../../../libsrc/geos-common/const.inc"
.include "../../../libsrc/geos-cbm/jumptab.inc"
.include "../../../libsrc/geos-cbm/geossym.inc"
.include "../../../libsrc/geos-common/geosmac.inc"
; import load addresses for all VLIR chains
; these labels are defined upon linking with ld65
.import __OVERLAYADDR__
.import __OVERLAYSIZE__
; import names of functions defined (and exported) in each VLIR part
; of your application
; here I used an OVERLAYx_ prefix to prevent name clashes
.import OVERLAY1_Function1
.import OVERLAY2_Function1
; segments "STARTUP", "CODE", "DATA", "RODATA" and "BSS" all go to VLIR0 chain
.segment "STARTUP"
; code segment for VLIR 0 chain
ProgExec:
LoadW r0, paramString ; show something
jsr DoDlgBox
MoveW dirEntryBuf+OFF_DE_TR_SC, r1
LoadW r4, fileHeader
jsr GetBlock ; load back VLIR t&s table
bnex error
lda #1
jsr PointRecord ; we want next module (#1)
LoadW r2, __OVERLAYSIZE__ ; length - as many bytes as we have room for
LoadW r7, __OVERLAYADDR__ ; all VLIR segments have the same load address
jsr ReadRecord ; load it
bnex error
jsr OVERLAY1_Function1 ; execute something
lda #2
jsr PointRecord ; next module
LoadW r2, __OVERLAYSIZE__
LoadW r7, __OVERLAYADDR__
jsr ReadRecord ; load it
bnex error
jsr OVERLAY2_Function1 ; execute something
error: jmp EnterDeskTop ; end of application
.segment "RODATA"
; read-only data segment
paramString:
.byte DEF_DB_POS | 1
.byte DBTXTSTR, TXT_LN_X, TXT_LN_2_Y
.word line1
.byte DBTXTSTR, TXT_LN_X, TXT_LN_3_Y
.word line2
.byte OK, DBI_X_0, DBI_Y_2
.byte NULL
line1: .byte BOLDON, "Hello World!",0
line2: .byte OUTLINEON,"Hello",PLAINTEXT," world!",0
.segment "DATA"
; read/write initialized data segment
counter: .word 0
.segment "BSS"
; read/write uninitialized data segment
; this space doesn't go into output file, only its size and
; position is remembered

45
samples/geos/grc/vlir1.s Normal file
View File

@@ -0,0 +1,45 @@
; Maciej 'YTM/Elysium' Witkowiak
; 06.06.2002
; This is the source for the loadable VLIR-structured program part
; include some GEOS defines
.include "../../../libsrc/geos-common/const.inc"
.include "../../../libsrc/geos-cbm/jumptab.inc"
.include "../../../libsrc/geos-cbm/geossym.inc"
.include "../../../libsrc/geos-common/geosmac.inc"
; export names of functions that will be used in the main program
.export OVERLAY1_Function1
.export OVERLAY1_Function2
; go into OVERLAY1 segment - everything that is here will go into
; VLIR chain #1
.segment "OVERLAY1"
OVERLAY1_Function1: jmp Function1 ; jump table, not really necessary
OVERLAY1_Function2: jmp Function2
; etc.
; rodata - if this is defined in .segment "RODATA"
; it will end up in the VLIR0 part, you don't want that
paramString:
.byte DEF_DB_POS | 1
.byte DBTXTSTR, TXT_LN_X, TXT_LN_2_Y
.word line1
.byte DBTXTSTR, TXT_LN_X, TXT_LN_3_Y
.word line2
.byte OK, DBI_X_0, DBI_Y_2
.byte NULL
line1: .byte "This is in module 1",0
line2: .byte "This is in module 1",0
; code
Function1: LoadW r0, paramString
jsr DoDlgBox
Function2: rts

36
samples/geos/grc/vlir2.s Normal file
View File

@@ -0,0 +1,36 @@
; Maciej 'YTM/Elysium' Witkowiak
; 06.06.2002
; This is the source for the loadable VLIR-structured program part
; similar to vlir1.s except the fact that this is chain #2
.include "../../../libsrc/geos-common/const.inc"
.include "../../../libsrc/geos-cbm/jumptab.inc"
.include "../../../libsrc/geos-cbm/geossym.inc"
.include "../../../libsrc/geos-common/geosmac.inc"
.export OVERLAY2_Function1
.export OVERLAY2_Function2
.segment "OVERLAY2"
OVERLAY2_Function1: jmp Function1
OVERLAY2_Function2: jmp Function2
; etc.
paramString:
.byte DEF_DB_POS | 1
.byte DBTXTSTR, TXT_LN_X, TXT_LN_2_Y
.word line1
.byte DBTXTSTR, TXT_LN_X, TXT_LN_3_Y
.word line2
.byte OK, DBI_X_0, DBI_Y_2
.byte NULL
Function2: LoadW r0, paramString
jsr DoDlgBox
Function1: rts
line1: .byte "This is in module 2",0
line2: .byte "This is in module 2",0

View File

@@ -1,11 +1,11 @@
/*
GEOSLib example
Hello, world example - with DBox
Maciej 'YTM/Elysium' Witkowiak
<ytm@elysium.pl>
26.12.1999
*/
@@ -18,7 +18,7 @@ void main (void)
DlgBoxOk(CBOLDON "Hello, world" CPLAINTEXT,
"This is written in C!");
// Normal apps exit from main into system's mainloop, and app finish
// when user selects it from icons or menu, but here we want to exit
// immediately.
@@ -26,7 +26,7 @@ void main (void)
// MainLoop();
// we can do:
// (nothing as this is the end of main function)
// exit(0);
// exit(EXIT_SUCCESS);
// return;
return;

View File

@@ -1,11 +1,11 @@
/*
GEOSLib example
Hello, world example - using graphic functions
Maciej 'YTM/Alliance' Witkowiak
<ytm@friko.onet.pl>
26.12.1999
*/
@@ -25,18 +25,18 @@ void main (void)
SetPattern(0);
InitDrawWindow(&wholeScreen);
Rectangle();
// Now some texts
PutString(COUTLINEON "This is compiled using cc65!" CPLAINTEXT, 20, 10);
PutString(CBOLDON "This is bold", 30, 10);
PutString(CULINEON "and this is bold and underline!", 40, 10);
PutString(CPLAINTEXT "This is plain text", 50, 10);
// Wait for 5 secs...
// Note that this is multitasking sleep, and if there are any icons/menus onscreen,
// they would be usable, in this case you have only pointer usable
Sleep(5*50);
// Normal apps exit from main into system's mainloop, and app finish
// when user selects it from icons or menu, but here we want to exit
// immediately.
@@ -44,7 +44,7 @@ void main (void)
// MainLoop();
// we can do:
// (nothing as this is the end of main function)
// exit(0);
// exit(EXIT_SUCCESS);
// return;
return;

View File

@@ -27,39 +27,39 @@ void show(char *name)
** rather place the all the code of certain source files into the overlay by
** compiling them with --code-name OVERLAY1.
*/
#pragma code-name(push, "OVERLAY1");
#pragma code-name(push, "OVERLAY1")
void foo(void)
{
/* Functions resident in an overlay can access all program variables and
** constants at any time without any precautions because those are never
** placed in overlays. The string constant "One" is an example for such
** placed in overlays. The string constant "One" is an example for such
** a constant resident in the main program.
*/
show("One");
}
#pragma code-name(pop);
#pragma code-name(pop)
#pragma code-name(push, "OVERLAY2");
#pragma code-name(push, "OVERLAY2")
void bar(void)
{
show("Two");
}
#pragma code-name(pop);
#pragma code-name(pop)
#pragma code-name(push, "OVERLAY3");
#pragma code-name(push, "OVERLAY3")
void foobar (void)
{
show("Three");
}
#pragma code-name(pop);
#pragma code-name(pop)
void main(int /*argc*/, char *argv[])

View File

@@ -1,12 +1,12 @@
/*
GEOSLib example
This small application removes GEOS disk write protection tag.
e.g. boot disk is always protected after boot-up
Maciej 'YTM/Elysium' Witkowiak
<ytm@elysium.pl>
21.03.2000
*/
@@ -60,7 +60,7 @@ void main(void)
{
// Here we clear the screen. Not really needed anyway...
GraphicsString(&clearScreen);
// Get the name of current disk to show it in dialog box
GetPtrCurDkNm(diskName);

12
samples/getsp.s Normal file
View File

@@ -0,0 +1,12 @@
.export _getsp
.importzp sp
.proc _getsp
ldx sp+1
lda sp
rts
.endproc

117
samples/kim1/Makefile Normal file
View File

@@ -0,0 +1,117 @@
# Run 'make SYS=<target>'; or, set a SYS env.
# var. to build for another target system.
SYS ?= kim1
# Just the usual way to find out if we're
# using cmd.exe to execute make rules.
ifneq ($(shell echo),)
CMD_EXE = 1
endif
ifdef CMD_EXE
NULLDEV = nul:
DEL = -del /f
RMDIR = rmdir /s /q
else
NULLDEV = /dev/null
DEL = $(RM)
RMDIR = $(RM) -r
endif
ifdef CC65_HOME
AS = $(CC65_HOME)/bin/ca65
CC = $(CC65_HOME)/bin/cc65
CL = $(CC65_HOME)/bin/cl65
LD = $(CC65_HOME)/bin/ld65
else
AS := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
CC := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65)
CL := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
endif
EXELIST_kim1 = \
kimHello.bin \
kimSieve.bin \
kimLife.bin \
kimTest.bin \
kimGFX.bin
ifneq ($(EXELIST_$(SYS)),)
samples: $(EXELIST_$(SYS))
else
samples: notavailable
endif
# empty target used to skip systems that will not work with any program in this dir
notavailable:
ifeq ($(MAKELEVEL),0)
@echo "info: kim1 tests not available for" $(SYS)
else
# suppress the "nothing to be done for 'samples' message
@echo > $(NULLDEV)
endif
subs.o: subs.asm
$(AS) subs.asm -o subs.o
ramfont.o: ramfont.asm
$(AS) ramfont.asm -o ramfont.o
kimLife.bin: kimLife.c
$(CL) -t kim1 -C kim1-60k.cfg -Oi -o kimLife.bin kimLife.c
kimTest.bin: kimTest.c
$(CL) -t kim1 -C kim1-60k.cfg -Oi -o kimTest.bin kimTest.c
kimGFX.bin: kimGFX.c subs.o ramfont.o
$(CL) -t kim1 --listing kimGFX.lst -C kim1-mtuE000.cfg -o kimGFX.bin kimGFX.c subs.o ramfont.o -Ln kimgfx.lbl
kimSieve.bin: kimSieve.c
$(CL) -t kim1 -C kim1-60k.cfg -O -o kimSieve.bin kimSieve.c
kimHello.bin: kimHello.c
$(CL) -t kim1 -O -o kimHello.bin kimHello.c
# To build an intel-format file for the CORSHAM SD card reader
kimLife.hex: kimLife.bin
srec_cat kimLife.bin -binary -offset 0x2000 -o kimLife.hex -Intel -address-length=2
kimTest.hex: kimTest.bin
srec_cat kimTest.bin -binary -offset 0x2000 -o kimTest.hex -Intel -address-length=2
kimGFX.hex: kimGFX.bin ramfont.o
srec_cat kimGFX.bin -binary -offset 0x2000 -o kimGFX.hex -Intel -address-length=2
# To build a paper tape file for uploading to the KIM-1 via terminal
kimLife.ptp: kimLife.bin
srec_cat kimLife.bin -binary -offset 0x2000 -o kimLife.ptp -MOS_Technologies
kimGFX.ptp: kimGFX.bin
srec_cat kimGFX.bin -binary -offset 0x2000 -o kimGFX.ptp -MOS_Technologies
kimTest.ptp: kimTest.bin
srec_cat kimTest.bin -binary -offset 0x2000 -o kimTest.ptp -MOS_Technologies
clean:
@$(DEL) kimSieve.bin 2>$(NULLDEV)
@$(DEL) kimHello.bin 2>$(NULLDEV)
@$(DEL) kimLife.bin 2>$(NULLDEV)
@$(DEL) kimLife.ptp 2>$(NULLDEV)
@$(DEL) kimLife.hex 2>$(NULLDEV)
@$(DEL) kimTest.bin 2>$(NULLDEV)
@$(DEL) kimTest.ptp 2>$(NULLDEV)
@$(DEL) kimTest.hex 2>$(NULLDEV)
@$(DEL) kimGFX.bin 2>$(NULLDEV)
@$(DEL) kimGFX.ptp 2>$(NULLDEV)
@$(DEL) kimGFX.hex 2>$(NULLDEV)
@$(DEL) kimgfx.lbl 2>$(NULLDEV)
@$(DEL) kimGFX.lst 2>$(NULLDEV)
@$(DEL) subs.o 2>$(NULLDEV)
@$(DEL) ramfont.o 2>$(NULLDEV)

0
samples/kim1/font.rom Normal file
View File

290
samples/kim1/kimGFX.c Normal file
View File

@@ -0,0 +1,290 @@
// --------------------------------------------------------------------------
// Simple Graphics Test for KIM-1 with MTU Visible Memory Board
//
// Assumes the MTU Visible Memory Board mapped at 0xA000 for 8K of video RAM
//
// davepl@davepl.com
// --------------------------------------------------------------------------
#include <stdio.h> // For printf
#include <stdlib.h> // For rand, srand
#include <string.h> // For memcpy
#include <ctype.h>
typedef unsigned char byte;
extern void ClearScreen(void); // In subs.asm
extern void ScrollScreen(void);
extern void DrawCircle(void);
extern void SetPixel(void);
extern void ClearPixel(void);
extern void DrawChar(void);
extern void Demo(void);
extern void __fastcall__ Delay(byte loops);
extern void __fastcall__ DrawLine(byte bSet);
extern byte __fastcall__ AscToPet(byte in);
extern byte __fastcall__ PetToAsc(byte in);
extern byte __fastcall__ ReverseBits(byte in);
extern void __fastcall__ CharOut(byte asci_char);
extern byte __fastcall__ getch();
extern unsigned char font8x8_basic[256][8];
extern int x1cord;
extern int y1cord;
extern int x2cord;
extern int y2cord;
extern int cursorX;
extern int cursorY;
// If in zeropage:
//
// #pragma zpsym("x1cord")
// #pragma zpsym("x2cord")
// #pragma zpsym("y1cord")
// #pragma zpsym("y2cord")
// Screen memory is placed at A000-BFFF, 320x200 pixels, mapped right to left within each horizontal byte
byte * screen = (byte *) 0xA000;
// Cursor position
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 200
#define CHARWIDTH 8
#define CHARHEIGHT 8
#define BYTESPERROW (SCREEN_WIDTH / 8)
#define BYTESPERCHARROW (BYTESPERROW * 8)
#define CHARSPERROW (SCREEN_WIDTH / CHARWIDTH)
#define ROWSPERCOLUMN (SCREEN_HEIGHT / CHARHEIGHT)
// SETPIXEL
//
// 0 <= x < 320
// 0 <= y < 200
//
// Draws a pixel on the screen in white or black at pixel pos x, y
void SETPIXEL(int x, int y, byte b)
{
x1cord = x;
y1cord = y;
if (b)
SetPixel();
else
ClearPixel();
}
// DRAWPIXEL
//
// 0 <= x < 320
// 0 <= y < 200
//
// Turns on a screen pixel at pixel pos x,y
void DRAWPIXEL(int x, int y)
{
x1cord = x;
y1cord = y;
SetPixel();
}
int c;
void DrawText(char * psz)
{
while (*psz)
{
while (cursorX >= CHARSPERROW)
{
cursorX -= CHARSPERROW;
cursorY += 1;
}
// If we've gone off the bottom of the screen, we scroll the screen and back up to the last line again
if (cursorY >= ROWSPERCOLUMN)
{
cursorY = ROWSPERCOLUMN - 1;
ScrollScreen();
}
// If we output a newline we advanced the cursor down one line and reset it to the left
if (*psz == 0x0A)
{
cursorX = 0;
cursorY++;
psz++;
}
else
{
c = *psz;
__asm__ ("ldx %v", cursorX);
__asm__ ("ldy %v", cursorY);
__asm__ ("lda %v", c);
DrawChar();
cursorX++;
psz++;
}
}
}
void DrawTextAt(int x, int y, char * psz)
{
cursorX = x;
cursorY = y;
DrawText(psz);
}
// Something like Bresenham's algorithm for drawing a line
/*
void DrawLine(int x0, int y0, int x1, int y1, byte val)
{
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
int err = (dx > dy ? dx : -dy) / 2, e2;
while (1)
{
SETPIXEL(x0, y0, val);
if (x0 == x1 && y0 == y1)
break;
e2 = err;
if (e2 > -dx)
{
err -= dy;
x0 += sx;
}
if (e2 < dy)
{
err += dx;
y0 += sy;
}
}
}
*/
// DrawCircle
//
// Draw a circle without sin, cos, or floating point!
void DrawCircleC(int x0, int y0, int radius, byte)
{
x1cord = x0;
y1cord = y0;
y2cord = radius;
DrawCircle();
}
void DrawLineC(int x1, int y1, int x2, int y2, byte bSet)
{
x1cord = x1;
y1cord = y1;
x2cord = x2;
y2cord = y2;
DrawLine(bSet);
}
// MirrorFont
//
// RAM font is backwards left-right relative to the way memory is laid out on the KIM-1, so we swap all the
// bytes in place by reversing the order of the bits in every byte
void MirrorFont()
{
int c;
byte * pb = (byte *) font8x8_basic;
for (c = 0; c < 128 * 8; c++)
pb[c] = ReverseBits(pb[c]);
}
// DrawScreenMoire
//
// Draws a moire pattern on the screen without clearing it first
void DrawMoire(int left, int top, int right, int bottom, byte pixel)
{
int x, y;
for (x = left; x < right; x += 6)
DrawLineC(x, top, right - x + left, bottom, pixel);
for (y = top; y < bottom; y += 6)
DrawLineC(left, y, right, bottom - y + top, pixel);
}
void DrawScreenMoire(int left, int top, int right, int bottom)
{
int x, y;
DrawLineC(left, top, right, top, 1);
DrawLineC(left, bottom, right, bottom, 1);
DrawLineC(left, top, left, bottom, 1);
DrawLineC(right, top, right, bottom, 1);
left++; top++; right--; bottom--;
for (x = left; x < right; x += 6)
DrawLineC(x, top, right - x + left, bottom, 1);
for (y = top; y < bottom; y += 6)
DrawLineC(left, y, right, bottom - y + top, 1);
for (x = left; x < right; x += 6)
DrawLineC(x, top, right - x + left, bottom, 0);
for (y = top; y < bottom; y += 6)
DrawLineC(left, y, right, bottom - y + top, 0);
}
int main (void)
{
int i;
int c = 0;
Demo();
CharOut('R');
CharOut('E');
CharOut('A');
CharOut('D');
CharOut('Y');
CharOut('.');
CharOut('\n');
while(1)
{
c = toupper(getch());
if (c != EOF)
CharOut(c);
}
// Clear the screen memory
while(1)
{
Demo();
DrawScreenMoire(0,30, 319, 199);
Delay(10);
Demo();
for (i = 5; i < 80; i+=5)
{
DrawCircleC(SCREEN_WIDTH/2, SCREEN_HEIGHT/2 + 20, i, 1);
DrawCircleC(SCREEN_WIDTH/4, SCREEN_HEIGHT/2 + 20, i, 1);
DrawCircleC(SCREEN_WIDTH*3/4, SCREEN_HEIGHT/2 + 20, i, 1);
}
Delay(10);
}
printf("Done, exiting...\r\n");
return 0;
}

24
samples/kim1/kimHello.c Normal file
View File

@@ -0,0 +1,24 @@
// --------------------------------------------------------------------------
// Hello World for KIM-1
//
// Dave Plummer based on Sym-1 sample by Wayne Parham
//
// davepl@davepl.com
// --------------------------------------------------------------------------
#include <stdio.h>
#include <kim1.h>
int main (void)
{
char str[100];
char c = 0x00;
printf ("\nHello World!\n\n");
printf ("Type a line and press ENTER, please.\n\n");
gets( str );
printf ("\n\nThanks: %s\n\n", str);
return 0;
}

52
samples/kim1/kimKeyDisp.c Normal file
View File

@@ -0,0 +1,52 @@
/* Example illustrating scandisplay() and getkey() functions. */
#include <stdio.h>
#include <kim1.h>
int main (void)
{
int i, j, k, l;
int last = 15;
printf("\nKIM-1 Demo\n");
for (i = 0; i < 16; i++) {
for (j = 0; j < 16; j++) {
for (k = 0; k < 16; k++) {
scandisplay(i, j, k);
l = getkey();
if (l != last) {
switch (l) {
case 0x0: case 0x1: case 0x2: case 0x3:
case 0x4: case 0x5: case 0x6: case 0x7:
case 0x8: case 0x9: case 0xa: case 0xb:
case 0xc: case 0xd: case 0xe: case 0xf:
printf("Key pressed: %X\n", l);
break;
case 0x10:
printf("Key pressed: AD\n");
break;
case 0x11:
printf("Key pressed: DA\n");
break;
case 0x12:
printf("Key pressed: +\n");
break;
case 0x13:
printf("Key pressed: GO\n");
break;
case 0x14:
printf("Key pressed: PC\n");
break;
}
last = l;
}
}
}
}
return 0;
}

144
samples/kim1/kimLife.c Normal file
View File

@@ -0,0 +1,144 @@
// --------------------------------------------------------------------------
// Conway's Game of Life for KIM-1
//
// Assumes the MTU Visible Memory Board mapped at 0x8000 for 8K of video RAM
//
// Dave Plummer on a rainy Thursday
//
// davepl@davepl.com
// --------------------------------------------------------------------------
#include <stdio.h> // For printf
#include <stdlib.h> // For rand, srand
#include <string.h> // For memcpy
typedef unsigned char byte;
// World size
#define WIDTH 320
#define HEIGHT 200
#define NUMBITS 64000
#define NUMBYTES 8000
#define DENSITY 50
// Screen memory is placed at 8000, our world copy at A000, and they use the same layout so
// that we can memcpy from one to the other without translating
byte * world = (byte *) 0x8000;
byte * new_world = (byte *) 0xA000;
// BITARRAY
//
// Access individual bits in a block of memory
// Access to the screen bitmap
byte GETBIT(byte *p, int n)
{
return (p[n >> 3] & (1 << (n & 7))) ? 1 : 0;
}
void SETBIT(byte *p, int n)
{
p[n >> 3] |= (1 << (n & 7));
}
void CLRBIT(byte *p, int n)
{
p[n >> 3] &= ~(1 << (n & 7));
}
void SETPIXEL(byte * p, int x, int y, byte b)
{
if (b)
SETBIT(p, y * WIDTH + x);
else
CLRBIT(p, y * WIDTH + x);
}
byte GETPIXEL(byte *p, int x, int y)
{
return GETBIT(p, y * WIDTH + x);
}
// RandomFillWorld
//
// Populates the initial world with random cells
void RandomFillWorld()
{
int x, y;
// I need a better way to see the RNG or it'll be the same game every time!
srand(0);
for (x = 0; x < WIDTH; x++)
{
for (y = 0; y < HEIGHT; y++)
{
byte b = ((rand() % 100) < DENSITY) ? 1 : 0;
SETPIXEL(world, x, y, b);
}
}
}
// CountNeighbors
//
// Count the number of live cells around the given spot, excluding the actual spot specified
int CountNeighbors(int x, int y)
{
int i, j, nx, ny, count = 0;
for (j = -1; j <= 1; j++)
{
for (i = -1; i <= 1; i++)
{
if (i != 0 || j != 0)
{
nx = (x + i + WIDTH) % WIDTH;
ny = (y + j + HEIGHT) % HEIGHT;
count += GETPIXEL(world, nx, ny) ? 1 : 0;
}
}
}
return count;
}
// UpdateWorld
//
// Applies the rules of Conway's Game of Life to the cells
void UpdateWorld()
{
int x, y;
for (y = 0; y < HEIGHT; y++)
{
for (x = 0; x < WIDTH; x++)
{
int neighbors = CountNeighbors(x, y);
if (GETPIXEL(world, x, y))
SETPIXEL(new_world, x, y, (neighbors == 2 || neighbors == 3));
else
SETPIXEL(new_world, x, y, (neighbors == 3));
}
}
}
int main (void)
{
printf("\r\nStarting Conway's Game of Life: Randomizing World...\r\n");
RandomFillWorld();
printf("World Ready, Running!\r\n");
for (;;)
{
UpdateWorld();
printf("[");
memcpy(world, new_world, NUMBYTES);
printf("]");
}
return 0;
}

125
samples/kim1/kimSieve.c Normal file
View File

@@ -0,0 +1,125 @@
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char byte;
typedef unsigned short int ushort;
typedef unsigned long int ulong;
#define LIMIT 100000L
// BITARRAY
//
// My bit-access macros pre-divide by two on the presumption that you'll never
// try try access both odd and even bits!
#define GETBIT(array, bit) (array[bit >> 4] & (1 << ((bit >> 1) & 7)))
#define SETBIT(array, bit) (array[bit >> 4] |= (1 << ((bit >> 1) & 7)))
#define CLRBIT(array, bit) (array[bit >> 4] &= ~(1 << ((bit >> 1) & 7)))
// RepeatChar
//
// Outputs a given character N times
void RepeatChar(char c, size_t count)
{
while (count--)
putc(c, stdout);
}
// sqrti
//
// Binary search integer square root
ushort sqrti(ulong num)
{
long i;
ulong ret = 0;
for(i = 15; i >= 0; i--)
{
ulong temp = ret | (1L << (ulong)i);
if(temp * temp <= num)
{
ret = temp;
}
}
return ret;
}
// main()
//
// CC65 main function receives no parameters
int main(void)
{
// CC65 cannot mix code and data so we have to declare all variables here in the function prolog
ulong iNumber;
ushort currentFactor;
ulong numBytesAllocated, rootOfLimit;
byte *array;
ulong countOfPrimes;
rootOfLimit = sqrti(LIMIT);
puts("\r\n\r\n");
RepeatChar('*', 70);
puts("\r\n** Prime Number Sieve - Dave Plummer 2022 **");
RepeatChar('*', 70);
printf("\r\n\r\nCalculating primes to %ld using a sqrt of %ld...\r\n", LIMIT, rootOfLimit);
// Calculate how much memory should be allocated
numBytesAllocated = (LIMIT + 15) / 16;
array = malloc(numBytesAllocated);
if (!array)
{
printf("Unable to allocate %ld bytes for %ld bits\r\n", numBytesAllocated, LIMIT);
return 0;
}
else
{
printf("Allocated %ld bytes for %ld slots\r\n", numBytesAllocated, LIMIT);
// Preset all the bits to true
for (iNumber = 0; iNumber < numBytesAllocated; iNumber++)
array[iNumber] = 0xFF;
}
// Search for next unmarked factor
currentFactor = 3;
while (currentFactor <= rootOfLimit)
{
ulong num, n;
for (num = currentFactor; num <= LIMIT; num += 2)
{
if (GETBIT(array, num))
{
currentFactor = num;
break;
}
}
for (n = (ulong) currentFactor * currentFactor; n <= LIMIT; n += currentFactor * 2)
CLRBIT(array, n);
currentFactor += 2;
}
// Display results
//
// printf("The following primes were found at or below %ld:\r\n2, ", LIMIT);
countOfPrimes = 1;
for (iNumber = 3; iNumber <= LIMIT; iNumber += 2)
if (GETBIT(array, iNumber))
countOfPrimes++;
printf("[END: Count = %ld]\r\n", countOfPrimes);
free(array);
return 1;
}

262
samples/kim1/kimTest.c Normal file
View File

@@ -0,0 +1,262 @@
// --------------------------------------------------------------------------
// Diagnostics Test for KIM-1
//
// Dave Plummer
// davepl@davepl.com
//
// Memory test examples by Michael Barr
//
// --------------------------------------------------------------------------
#include <stdio.h> // For printf
#include <stdlib.h> // For rand, srand
#include <string.h> // For memcpy
typedef unsigned char byte;
// RepeatChar
//
// Outputs a given character N times
void RepeatChar(char c, size_t count)
{
while (count--)
putc(c, stdout);
}
/**********************************************************************
*
* Function: memTestDataBus()
*
* Description: Test the data bus wiring in a memory region by
* performing a walking 1's test at a fixed address
* within that region. The address (and hence the
* memory region) is selected by the caller.
*
* Returns: 0 if the test succeeds.
* A non-zero result is the first pattern that failed.
*
**********************************************************************/
byte memTestDataBus(volatile byte * address)
{
byte pattern;
// Perform a walking 1's test at the given address.
for (pattern = 1; pattern != 0; pattern <<= 1)
{
// Write the test pattern.
*address = pattern;
// Read it back and check it
if (*address != pattern)
{
printf("\r\nmemTestDataBus: FAILED at %04x with pattern %02x\r\n", address, pattern);
return (pattern);
}
}
return (0);
}
/**********************************************************************
*
* Function: memTestAddressBus()
*
* Description: Test the address bus wiring in a memory region by
* performing a walking 1's test on the relevant bits
* of the address and checking for aliasing. This test
* will find single-bit address failures such as stuck
* -high, stuck-low, and shorted pins. The base address
* and size of the region are selected by the caller.
*
* Notes: For best results, the selected base address should
* have enough LSB 0's to guarantee single address bit
* changes. For example, to test a 64-Kbyte region,
* select a base address on a 64-Kbyte boundary. Also,
* select the region size as a power-of-two--if at all
* possible.
*
* Returns: NULL if the test succeeds.
* A non-zero result is the first address at which an
* aliasing problem was uncovered. By examining the
* contents of memory, it may be possible to gather
* additional information about the problem.
*
**********************************************************************/
byte * memTestAddressBus(volatile byte * baseAddress, unsigned long nBytes)
{
unsigned long addressMask = (nBytes/sizeof(byte) - 1);
unsigned long offset;
unsigned long testOffset;
byte pattern = (byte) 0xAAAAAAAA;
byte antipattern = (byte) 0x55555555;
//Write the default pattern at each of the power-of-two offsets.
for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
{
baseAddress[offset] = pattern;
}
// Check for address bits stuck high.
testOffset = 0;
baseAddress[testOffset] = antipattern;
for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
{
if (baseAddress[offset] != pattern)
{
printf("\r\nmemTestAddressBus: FAILED at %04x with pattern %02x\r\n", baseAddress+offset, pattern);
return ((byte *) &baseAddress[offset]);
}
if (offset % 1024 == 0)
printf(".");
}
baseAddress[testOffset] = pattern;
// Check for address bits stuck low or shorted.
for (testOffset = 1; (testOffset & addressMask) != 0; testOffset <<= 1)
{
baseAddress[testOffset] = antipattern;
if (baseAddress[0] != pattern)
{
return ((byte *) &baseAddress[testOffset]);
}
for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
{
if ((baseAddress[offset] != pattern) && (offset != testOffset))
{
printf("\r\nmemTestAddressBus: FAILED at %04x with pattern %02x\r\n", baseAddress+offset, pattern);
return ((byte *) &baseAddress[testOffset]);
}
}
baseAddress[testOffset] = pattern;
}
return (NULL);
}
/**********************************************************************
*
* Function: memTestDevice()
*
* Description: Test the integrity of a physical memory device by
* performing an increment/decrement test over the
* entire region. In the process every storage bit
* in the device is tested as a zero and a one. The
* base address and the size of the region are
* selected by the caller.
*
* Returns: NULL if the test succeeds.
*
* A non-zero result is the first address at which an
* incorrect value was read back. By examining the
* contents of memory, it may be possible to gather
* additional information about the problem.
*
**********************************************************************/
byte * memTestDevice(volatile byte * baseAddress, unsigned long nBytes)
{
unsigned long offset;
unsigned long nWords = nBytes / sizeof(byte);
byte pattern;
byte antipattern;
// Fill memory with a known pattern.
for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
baseAddress[offset] = pattern;
// Check each location and invert it for the second pass.
for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
{
if (offset % 1024 == 0)
printf("%04X ", (int) &baseAddress[offset]);
if (baseAddress[offset] != pattern)
{
printf("\r\nmemTestDevice: FAILED at %04x with pattern %02x\r\n", (int) &baseAddress[offset], pattern);
return ((byte *) &baseAddress[offset]);
}
antipattern = ~pattern;
baseAddress[offset] = antipattern;
}
// Check each location for the inverted pattern and zero it.
for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
{
if (offset % 1024 == 0)
printf("%04X ", (int) &baseAddress[offset]);
antipattern = ~pattern;
if (baseAddress[offset] != antipattern)
{
printf("\r\nmemTestDevice: FAILED at %04x with antipattern %02x\r\n", (int) &baseAddress[offset], pattern);
return ((byte *) &baseAddress[offset]);
}
}
return (NULL);
}
// TestMemory
//
// Run all three memory tests
byte TestMemory(byte * startAddress, unsigned long size)
{
if ((memTestDataBus(startAddress) != 0) ||
(memTestAddressBus(startAddress, size) != NULL) ||
(memTestDevice(startAddress, size) != NULL))
{
return (-1);
}
else
{
return (0);
}
}
int main (void)
{
printf("\r\nTesting KIM-1...\r\n");
RepeatChar('-', 39);
printf("\r\nTesting RIOT RAM: 1780-17BF\r\n");
if (TestMemory((byte *)0x1780, 0x17BF - 0x1780))
return 0;
printf("\r\nTesting RIOT RAM: 17C0-17E6\r\n");
if (TestMemory((byte *)0x17C0, 0x17E6 - 0x17C0))
return 0;
printf("\r\nTesting Memory: 0400-13FF\r\n");
if (TestMemory((byte *)0x0400, 0x13FF - 0x0400))
return 0;
printf("\r\nTesting Memory: 4000-DFFF\r\n");
if (TestMemory((byte *)0x4000, 0xDFFF - 0x4000))
return 0;
printf("\r\nPASS!\r\n");
return 1;
}

272
samples/kim1/ramfont.asm Normal file
View File

@@ -0,0 +1,272 @@
;-----------------------------------------------------------------------------------
; KIMGFX: Simple pixel graphics for the MOS/Commodore KIM-1
;-----------------------------------------------------------------------------------
; (c) Plummer's Software Ltd, 04/25/2023 Created
; David Plummer
;-----------------------------------------------------------------------------------
;
; File: ramfont.s
; Magnetic OCR (check number style) Font data
;
;-----------------------------------------------------------------------------------
.segment "CODE"
.export _font8x8_basic
_font8x8_basic:
.byte $1c, $22, $4a, $56, $4c, $20, $1e, $00 ; PETSCII code 0
.byte $3c, $24, $24, $7e, $62, $62, $62, $00 ; PETSCII code 1
.byte $78, $44, $44, $7c, $62, $62, $7e, $00 ; PETSCII code 2
.byte $7e, $42, $40, $60, $60, $62, $7e, $00 ; PETSCII code 3
.byte $7c, $46, $42, $62, $62, $66, $7c, $00 ; PETSCII code 4
.byte $7e, $40, $40, $7c, $60, $60, $7e, $00 ; PETSCII code 5
.byte $7e, $40, $40, $7e, $60, $60, $60, $00 ; PETSCII code 6
.byte $7e, $42, $40, $6e, $62, $62, $7e, $00 ; PETSCII code 7
.byte $42, $42, $42, $7e, $62, $62, $62, $00 ; PETSCII code 8
.byte $08, $08, $08, $0c, $0c, $0c, $0c, $00 ; PETSCII code 9
.byte $04, $04, $04, $06, $06, $46, $7e, $00 ; PETSCII code 10
.byte $42, $44, $48, $7c, $62, $62, $62, $00 ; PETSCII code 11
.byte $40, $40, $40, $60, $60, $60, $7e, $00 ; PETSCII code 12
.byte $7e, $4a, $4a, $6a, $6a, $6a, $6a, $00 ; PETSCII code 13
.byte $7e, $42, $42, $62, $62, $62, $62, $00 ; PETSCII code 14
.byte $7e, $46, $42, $42, $42, $42, $7e, $00 ; PETSCII code 15
.byte $7e, $42, $42, $7e, $60, $60, $60, $00 ; PETSCII code 16
.byte $7e, $42, $42, $42, $4a, $4e, $7e, $00 ; PETSCII code 17
.byte $7c, $44, $44, $7c, $62, $62, $62, $00 ; PETSCII code 18
.byte $7e, $42, $40, $7e, $06, $46, $7e, $00 ; PETSCII code 19
.byte $3e, $10, $10, $18, $18, $18, $18, $00 ; PETSCII code 20
.byte $42, $42, $42, $62, $62, $62, $7e, $00 ; PETSCII code 21
.byte $62, $62, $62, $66, $24, $24, $3c, $00 ; PETSCII code 22
.byte $4a, $4a, $4a, $6a, $6a, $6a, $7e, $00 ; PETSCII code 23
.byte $42, $42, $66, $18, $66, $62, $62, $00 ; PETSCII code 24
.byte $22, $22, $22, $3e, $18, $18, $18, $00 ; PETSCII code 25
.byte $7e, $42, $06, $18, $60, $62, $7e, $00 ; PETSCII code 26
.byte $3c, $20, $20, $20, $20, $20, $3c, $00 ; PETSCII code 27
.byte $00, $40, $20, $10, $08, $04, $02, $00 ; PETSCII code 28
.byte $3c, $04, $04, $04, $04, $04, $3c, $00 ; PETSCII code 29
.byte $00, $08, $1c, $2a, $08, $08, $14, $14 ; PETSCII code 30
.byte $00, $00, $10, $20, $7f, $20, $10, $00 ; PETSCII code 31
.byte $00, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 32
.byte $08, $08, $08, $0c, $0c, $00, $0c, $00 ; PETSCII code 33
.byte $6c, $24, $6c, $00, $00, $00, $00, $00 ; PETSCII code 34
.byte $24, $24, $7e, $24, $7e, $24, $24, $00 ; PETSCII code 35
.byte $08, $3e, $20, $3e, $06, $3e, $08, $00 ; PETSCII code 36
.byte $00, $62, $64, $08, $10, $26, $46, $00 ; PETSCII code 37
.byte $3c, $20, $24, $7e, $64, $64, $7c, $00 ; PETSCII code 38
.byte $1c, $18, $10, $00, $00, $00, $00, $00 ; PETSCII code 39
.byte $04, $08, $10, $10, $10, $08, $04, $00 ; PETSCII code 40
.byte $20, $10, $08, $08, $08, $10, $20, $00 ; PETSCII code 41
.byte $08, $2a, $1c, $3e, $1c, $2a, $08, $00 ; PETSCII code 42
.byte $00, $08, $08, $3e, $08, $08, $00, $00 ; PETSCII code 43
.byte $00, $00, $00, $00, $00, $18, $18, $08 ; PETSCII code 44
.byte $00, $00, $00, $7e, $00, $00, $00, $00 ; PETSCII code 45
.byte $00, $00, $00, $00, $00, $18, $18, $00 ; PETSCII code 46
.byte $00, $02, $04, $08, $10, $20, $40, $00 ; PETSCII code 47
.byte $7e, $62, $52, $4a, $46, $46, $7e, $00 ; PETSCII code 48
.byte $18, $08, $08, $18, $18, $1a, $3e, $00 ; PETSCII code 49
.byte $7e, $42, $02, $7e, $60, $60, $7e, $00 ; PETSCII code 50
.byte $7c, $44, $04, $1e, $06, $46, $7e, $00 ; PETSCII code 51
.byte $44, $44, $44, $44, $7e, $0c, $0c, $00 ; PETSCII code 52
.byte $7e, $40, $7e, $06, $06, $46, $7e, $00 ; PETSCII code 53
.byte $7e, $42, $40, $7e, $46, $46, $7e, $00 ; PETSCII code 54
.byte $7e, $02, $02, $06, $06, $06, $06, $00 ; PETSCII code 55
.byte $3c, $24, $24, $7e, $46, $46, $7e, $00 ; PETSCII code 56
.byte $7e, $42, $42, $7e, $06, $06, $06, $00 ; PETSCII code 57
.byte $00, $00, $18, $00, $00, $18, $00, $00 ; PETSCII code 58
.byte $00, $00, $18, $00, $00, $18, $18, $08 ; PETSCII code 59
.byte $0e, $18, $30, $60, $30, $18, $0e, $00 ; PETSCII code 60
.byte $00, $00, $7e, $00, $7e, $00, $00, $00 ; PETSCII code 61
.byte $70, $18, $0c, $06, $0c, $18, $70, $00 ; PETSCII code 62
.byte $7e, $02, $02, $7e, $60, $00, $60, $00 ; PETSCII code 63
.byte $00, $00, $00, $00, $ff, $00, $00, $00 ; PETSCII code 64
.byte $08, $1c, $3e, $7f, $7f, $1c, $3e, $00 ; PETSCII code 65
.byte $10, $10, $10, $10, $10, $10, $10, $10 ; PETSCII code 66
.byte $00, $00, $00, $ff, $00, $00, $00, $00 ; PETSCII code 67
.byte $00, $00, $ff, $00, $00, $00, $00, $00 ; PETSCII code 68
.byte $00, $ff, $00, $00, $00, $00, $00, $00 ; PETSCII code 69
.byte $00, $00, $00, $00, $00, $ff, $00, $00 ; PETSCII code 70
.byte $20, $20, $20, $20, $20, $20, $20, $20 ; PETSCII code 71
.byte $04, $04, $04, $04, $04, $04, $04, $04 ; PETSCII code 72
.byte $00, $00, $00, $00, $e0, $10, $08, $08 ; PETSCII code 73
.byte $08, $08, $08, $04, $03, $00, $00, $00 ; PETSCII code 74
.byte $08, $08, $08, $10, $e0, $00, $00, $00 ; PETSCII code 75
.byte $80, $80, $80, $80, $80, $80, $80, $ff ; PETSCII code 76
.byte $80, $40, $20, $10, $08, $04, $02, $01 ; PETSCII code 77
.byte $01, $02, $04, $08, $10, $20, $40, $80 ; PETSCII code 78
.byte $ff, $80, $80, $80, $80, $80, $80, $80 ; PETSCII code 79
.byte $ff, $01, $01, $01, $01, $01, $01, $01 ; PETSCII code 80
.byte $00, $3c, $7e, $7e, $7e, $7e, $3c, $00 ; PETSCII code 81
.byte $00, $00, $00, $00, $00, $00, $ff, $00 ; PETSCII code 82
.byte $36, $7f, $7f, $7f, $3e, $1c, $08, $00 ; PETSCII code 83
.byte $40, $40, $40, $40, $40, $40, $40, $40 ; PETSCII code 84
.byte $00, $00, $00, $00, $03, $04, $08, $08 ; PETSCII code 85
.byte $81, $42, $24, $18, $18, $24, $42, $81 ; PETSCII code 86
.byte $00, $3c, $42, $42, $42, $42, $3c, $00 ; PETSCII code 87
.byte $08, $1c, $2a, $77, $2a, $08, $08, $00 ; PETSCII code 88
.byte $02, $02, $02, $02, $02, $02, $02, $02 ; PETSCII code 89
.byte $08, $1c, $3e, $7f, $3e, $1c, $08, $00 ; PETSCII code 90
.byte $08, $08, $08, $08, $ff, $08, $08, $08 ; PETSCII code 91
.byte $a0, $50, $a0, $50, $a0, $50, $a0, $50 ; PETSCII code 92
.byte $08, $08, $08, $08, $08, $08, $08, $08 ; PETSCII code 93
.byte $00, $00, $01, $3e, $54, $14, $14, $00 ; PETSCII code 94
.byte $ff, $7f, $3f, $1f, $0f, $07, $03, $01 ; PETSCII code 95
.byte $00, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 96
.byte $f0, $f0, $f0, $f0, $f0, $f0, $f0, $f0 ; PETSCII code 97
.byte $00, $00, $00, $00, $ff, $ff, $ff, $ff ; PETSCII code 98
.byte $ff, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 99
.byte $00, $00, $00, $00, $00, $00, $00, $ff ; PETSCII code 100
.byte $80, $80, $80, $80, $80, $80, $80, $80 ; PETSCII code 101
.byte $aa, $55, $aa, $55, $aa, $55, $aa, $55 ; PETSCII code 102
.byte $01, $01, $01, $01, $01, $01, $01, $01 ; PETSCII code 103
.byte $00, $00, $00, $00, $aa, $55, $aa, $55 ; PETSCII code 104
.byte $ff, $fe, $fc, $f8, $f0, $e0, $c0, $80 ; PETSCII code 105
.byte $03, $03, $03, $03, $03, $03, $03, $03 ; PETSCII code 106
.byte $08, $08, $08, $08, $0f, $08, $08, $08 ; PETSCII code 107
.byte $00, $00, $00, $00, $0f, $0f, $0f, $0f ; PETSCII code 108
.byte $08, $08, $08, $08, $0f, $00, $00, $00 ; PETSCII code 109
.byte $00, $00, $00, $00, $f8, $08, $08, $08 ; PETSCII code 110
.byte $00, $00, $00, $00, $00, $00, $ff, $ff ; PETSCII code 111
.byte $00, $00, $00, $00, $0f, $08, $08, $08 ; PETSCII code 112
.byte $08, $08, $08, $08, $ff, $00, $00, $00 ; PETSCII code 113
.byte $00, $00, $00, $00, $ff, $08, $08, $08 ; PETSCII code 114
.byte $08, $08, $08, $08, $f8, $08, $08, $08 ; PETSCII code 115
.byte $c0, $c0, $c0, $c0, $c0, $c0, $c0, $c0 ; PETSCII code 116
.byte $e0, $e0, $e0, $e0, $e0, $e0, $e0, $e0 ; PETSCII code 117
.byte $07, $07, $07, $07, $07, $07, $07, $07 ; PETSCII code 118
.byte $ff, $ff, $00, $00, $00, $00, $00, $00 ; PETSCII code 119
.byte $ff, $ff, $ff, $00, $00, $00, $00, $00 ; PETSCII code 120
.byte $00, $00, $00, $00, $00, $ff, $ff, $ff ; PETSCII code 121
.byte $01, $01, $01, $01, $01, $01, $01, $ff ; PETSCII code 122
.byte $00, $00, $00, $00, $f0, $f0, $f0, $f0 ; PETSCII code 123
.byte $0f, $0f, $0f, $0f, $00, $00, $00, $00 ; PETSCII code 124
.byte $08, $08, $08, $08, $f8, $00, $00, $00 ; PETSCII code 125
.byte $f0, $f0, $f0, $f0, $00, $00, $00, $00 ; PETSCII code 126
.byte $f0, $f0, $f0, $f0, $0f, $0f, $0f, $0f ; PETSCII code 127
.byte $1c, $22, $4a, $56, $4c, $20, $1e, $00 ; PETSCII code 128
.byte $00, $00, $3c, $04, $7c, $64, $7c, $00 ; PETSCII code 129
.byte $40, $40, $7e, $42, $62, $62, $7e, $00 ; PETSCII code 130
.byte $00, $00, $7e, $42, $60, $62, $7e, $00 ; PETSCII code 131
.byte $02, $02, $7e, $42, $62, $62, $7e, $00 ; PETSCII code 132
.byte $00, $00, $7e, $42, $7e, $60, $7e, $00 ; PETSCII code 133
.byte $1e, $12, $10, $7c, $18, $18, $18, $00 ; PETSCII code 134
.byte $00, $00, $7e, $42, $62, $7e, $02, $7e ; PETSCII code 135
.byte $40, $40, $7e, $42, $62, $62, $62, $00 ; PETSCII code 136
.byte $18, $00, $10, $10, $18, $18, $18, $00 ; PETSCII code 137
.byte $0c, $00, $08, $0c, $0c, $0c, $44, $7c ; PETSCII code 138
.byte $40, $40, $44, $48, $78, $64, $64, $00 ; PETSCII code 139
.byte $10, $10, $10, $10, $18, $18, $18, $00 ; PETSCII code 140
.byte $00, $00, $7f, $49, $6d, $6d, $6d, $00 ; PETSCII code 141
.byte $00, $00, $7e, $42, $62, $62, $62, $00 ; PETSCII code 142
.byte $00, $00, $7e, $42, $62, $62, $7e, $00 ; PETSCII code 143
.byte $00, $00, $7e, $42, $62, $7e, $40, $40 ; PETSCII code 144
.byte $00, $00, $7e, $42, $46, $7e, $02, $02 ; PETSCII code 145
.byte $00, $00, $7e, $40, $60, $60, $60, $00 ; PETSCII code 146
.byte $00, $00, $7e, $40, $7e, $06, $7e, $00 ; PETSCII code 147
.byte $10, $10, $7c, $10, $18, $18, $18, $00 ; PETSCII code 148
.byte $00, $00, $42, $42, $62, $62, $7e, $00 ; PETSCII code 149
.byte $00, $00, $62, $62, $66, $24, $3c, $00 ; PETSCII code 150
.byte $00, $00, $49, $49, $6d, $6d, $7f, $00 ; PETSCII code 151
.byte $00, $00, $42, $42, $3c, $62, $62, $00 ; PETSCII code 152
.byte $00, $00, $62, $62, $42, $7e, $02, $7e ; PETSCII code 153
.byte $00, $00, $7e, $06, $18, $60, $7e, $00 ; PETSCII code 154
.byte $3c, $20, $20, $20, $20, $20, $3c, $00 ; PETSCII code 155
.byte $00, $40, $20, $10, $08, $04, $02, $00 ; PETSCII code 156
.byte $3c, $04, $04, $04, $04, $04, $3c, $00 ; PETSCII code 157
.byte $00, $08, $1c, $2a, $08, $08, $14, $14 ; PETSCII code 158
.byte $00, $00, $10, $20, $7f, $20, $10, $00 ; PETSCII code 159
.byte $00, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 160
.byte $08, $08, $08, $0c, $0c, $00, $0c, $00 ; PETSCII code 161
.byte $6c, $24, $6c, $00, $00, $00, $00, $00 ; PETSCII code 162
.byte $24, $24, $7e, $24, $7e, $24, $24, $00 ; PETSCII code 163
.byte $08, $3e, $20, $3e, $06, $3e, $08, $00 ; PETSCII code 164
.byte $00, $62, $64, $08, $10, $26, $46, $00 ; PETSCII code 165
.byte $3c, $20, $24, $7e, $64, $64, $7c, $00 ; PETSCII code 166
.byte $1c, $18, $10, $00, $00, $00, $00, $00 ; PETSCII code 167
.byte $04, $08, $10, $10, $10, $08, $04, $00 ; PETSCII code 168
.byte $20, $10, $08, $08, $08, $10, $20, $00 ; PETSCII code 169
.byte $08, $2a, $1c, $3e, $1c, $2a, $08, $00 ; PETSCII code 170
.byte $00, $08, $08, $3e, $08, $08, $00, $00 ; PETSCII code 171
.byte $00, $00, $00, $00, $00, $18, $18, $08 ; PETSCII code 172
.byte $00, $00, $00, $7e, $00, $00, $00, $00 ; PETSCII code 173
.byte $00, $00, $00, $00, $00, $18, $18, $00 ; PETSCII code 174
.byte $00, $02, $04, $08, $10, $20, $40, $00 ; PETSCII code 175
.byte $7e, $62, $52, $4a, $46, $46, $7e, $00 ; PETSCII code 176
.byte $38, $08, $08, $18, $18, $1a, $3e, $00 ; PETSCII code 177
.byte $7e, $42, $02, $7e, $60, $60, $7e, $00 ; PETSCII code 178
.byte $7c, $44, $04, $1e, $06, $46, $7e, $00 ; PETSCII code 179
.byte $44, $44, $44, $44, $7e, $0c, $0c, $00 ; PETSCII code 180
.byte $7e, $40, $7e, $06, $06, $46, $7e, $00 ; PETSCII code 181
.byte $7e, $42, $40, $7e, $46, $46, $7e, $00 ; PETSCII code 182
.byte $7e, $02, $02, $06, $06, $06, $06, $00 ; PETSCII code 183
.byte $3c, $24, $24, $7e, $46, $46, $7e, $00 ; PETSCII code 184
.byte $7e, $42, $42, $7e, $06, $06, $06, $00 ; PETSCII code 185
.byte $00, $00, $18, $00, $00, $18, $00, $00 ; PETSCII code 186
.byte $00, $00, $18, $00, $00, $18, $18, $08 ; PETSCII code 187
.byte $0e, $18, $30, $60, $30, $18, $0e, $00 ; PETSCII code 188
.byte $00, $00, $7e, $00, $7e, $00, $00, $00 ; PETSCII code 189
.byte $70, $18, $0c, $06, $0c, $18, $70, $00 ; PETSCII code 190
.byte $7e, $02, $02, $7e, $60, $00, $60, $00 ; PETSCII code 191
.byte $00, $00, $00, $00, $ff, $00, $00, $00 ; PETSCII code 192
.byte $3c, $24, $24, $7e, $62, $62, $62, $00 ; PETSCII code 193
.byte $78, $44, $44, $7c, $62, $62, $7e, $00 ; PETSCII code 194
.byte $7e, $42, $40, $60, $60, $62, $7e, $00 ; PETSCII code 195
.byte $7c, $46, $42, $62, $62, $66, $7c, $00 ; PETSCII code 196
.byte $7e, $40, $40, $78, $60, $60, $7e, $00 ; PETSCII code 197
.byte $7e, $40, $40, $7e, $60, $60, $60, $00 ; PETSCII code 198
.byte $7e, $42, $40, $6e, $62, $62, $7e, $00 ; PETSCII code 199
.byte $42, $42, $42, $7e, $62, $62, $62, $00 ; PETSCII code 200
.byte $08, $08, $08, $0c, $0c, $0c, $0c, $00 ; PETSCII code 201
.byte $04, $04, $04, $06, $06, $46, $7e, $00 ; PETSCII code 202
.byte $42, $44, $48, $7c, $62, $62, $62, $00 ; PETSCII code 203
.byte $40, $40, $40, $60, $60, $60, $7e, $00 ; PETSCII code 204
.byte $7e, $4a, $4a, $6a, $6a, $6a, $6a, $00 ; PETSCII code 205
.byte $7e, $42, $42, $62, $62, $62, $62, $00 ; PETSCII code 206
.byte $7e, $46, $42, $42, $42, $42, $7e, $00 ; PETSCII code 207
.byte $7e, $42, $42, $7e, $60, $60, $60, $00 ; PETSCII code 208
.byte $7e, $42, $42, $42, $4a, $4e, $7e, $00 ; PETSCII code 209
.byte $7c, $44, $44, $7c, $62, $62, $62, $00 ; PETSCII code 210
.byte $7e, $42, $40, $7e, $06, $46, $7e, $00 ; PETSCII code 211
.byte $3e, $10, $10, $18, $18, $18, $18, $00 ; PETSCII code 212
.byte $42, $42, $42, $62, $62, $62, $7e, $00 ; PETSCII code 213
.byte $62, $62, $62, $66, $24, $24, $3c, $00 ; PETSCII code 214
.byte $4a, $4a, $4a, $6a, $6a, $6a, $7e, $00 ; PETSCII code 215
.byte $42, $42, $66, $3c, $66, $62, $62, $00 ; PETSCII code 216
.byte $22, $22, $22, $3e, $18, $18, $18, $00 ; PETSCII code 217
.byte $7e, $42, $06, $18, $60, $62, $7e, $00 ; PETSCII code 218
.byte $08, $08, $08, $08, $ff, $08, $08, $08 ; PETSCII code 219
.byte $a0, $50, $a0, $50, $a0, $50, $a0, $50 ; PETSCII code 220
.byte $08, $08, $08, $08, $08, $08, $08, $08 ; PETSCII code 221
.byte $cc, $cc, $33, $33, $cc, $cc, $33, $33 ; PETSCII code 222
.byte $cc, $66, $33, $99, $cc, $66, $33, $99 ; PETSCII code 223
.byte $00, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 224
.byte $f0, $f0, $f0, $f0, $f0, $f0, $f0, $f0 ; PETSCII code 225
.byte $00, $00, $00, $00, $ff, $ff, $ff, $ff ; PETSCII code 226
.byte $ff, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 227
.byte $00, $00, $00, $00, $00, $00, $00, $ff ; PETSCII code 228
.byte $80, $80, $80, $80, $80, $80, $80, $80 ; PETSCII code 229
.byte $aa, $55, $aa, $55, $aa, $55, $aa, $55 ; PETSCII code 230
.byte $01, $01, $01, $01, $01, $01, $01, $01 ; PETSCII code 231
.byte $00, $00, $00, $00, $aa, $55, $aa, $55 ; PETSCII code 232
.byte $99, $33, $66, $cc, $99, $33, $66, $cc ; PETSCII code 233
.byte $03, $03, $03, $03, $03, $03, $03, $03 ; PETSCII code 234
.byte $08, $08, $08, $08, $0f, $08, $08, $08 ; PETSCII code 235
.byte $00, $00, $00, $00, $0f, $0f, $0f, $0f ; PETSCII code 236
.byte $08, $08, $08, $08, $0f, $00, $00, $00 ; PETSCII code 237
.byte $00, $00, $00, $00, $f8, $08, $08, $08 ; PETSCII code 238
.byte $00, $00, $00, $00, $00, $00, $ff, $ff ; PETSCII code 239
.byte $00, $00, $00, $00, $0f, $08, $08, $08 ; PETSCII code 240
.byte $08, $08, $08, $08, $ff, $00, $00, $00 ; PETSCII code 241
.byte $00, $00, $00, $00, $ff, $08, $08, $08 ; PETSCII code 242
.byte $08, $08, $08, $08, $f8, $08, $08, $08 ; PETSCII code 243
.byte $c0, $c0, $c0, $c0, $c0, $c0, $c0, $c0 ; PETSCII code 244
.byte $e0, $e0, $e0, $e0, $e0, $e0, $e0, $e0 ; PETSCII code 245
.byte $07, $07, $07, $07, $07, $07, $07, $07 ; PETSCII code 246
.byte $ff, $ff, $00, $00, $00, $00, $00, $00 ; PETSCII code 247
.byte $ff, $ff, $ff, $00, $00, $00, $00, $00 ; PETSCII code 248
.byte $00, $00, $00, $00, $00, $ff, $ff, $ff ; PETSCII code 249
.byte $01, $02, $44, $48, $50, $60, $40, $00 ; PETSCII code 250
.byte $00, $00, $00, $00, $f0, $f0, $f0, $f0 ; PETSCII code 251
.byte $0f, $0f, $0f, $0f, $00, $00, $00, $00 ; PETSCII code 252
.byte $08, $08, $08, $08, $f8, $00, $00, $00 ; PETSCII code 253
.byte $f0, $f0, $f0, $f0, $00, $00, $00, $00 ; PETSCII code 254
.byte $f0, $f0, $f0, $f0, $0f, $0f, $0f, $0f ; PETSCII code 255

1140
samples/kim1/subs.asm Normal file

File diff suppressed because it is too large Load Diff

59
samples/lynx/Makefile Normal file
View File

@@ -0,0 +1,59 @@
# Run 'make SYS=<target>'; or, set a SYS env.
# var. to build for another target system.
SYS ?= lynx
# Just the usual way to find out if we're
# using cmd.exe to execute make rules.
ifneq ($(shell echo),)
CMD_EXE = 1
endif
ifdef CMD_EXE
NULLDEV = nul:
DEL = -del /f
else
NULLDEV = /dev/null
DEL = $(RM)
endif
ifdef CC65_HOME
AS = $(CC65_HOME)/bin/ca65
CC = $(CC65_HOME)/bin/cc65
CL = $(CC65_HOME)/bin/cl65
LD = $(CC65_HOME)/bin/ld65
else
AS := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
CC := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65)
CL := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
endif
EXELIST_lynx = \
hello.lnx \
mandelbrot.lnx \
tgidemo.lnx
.PHONY: samples clean
ifneq ($(EXELIST_$(SYS)),)
samples: $(EXELIST_$(SYS))
else
samples:
# recipe used to skip systems that will not work with any program in this dir
ifeq ($(MAKELEVEL),0)
@echo "info: Lynx tests not available for" $(SYS)
else
# Suppress the "nothing to be done for 'samples' message.
@echo "" > $(NULLDEV)
endif
endif
.SUFFIXES:
.SUFFIXES: .c .lnx
%.lnx : %.c
$(CL) -t $(SYS) -Oris -m $*.map -o $@ $<
clean:
@$(DEL) *.o *.map *.lnx 2>$(NULLDEV)

43
samples/lynx/hello.c Normal file
View File

@@ -0,0 +1,43 @@
/* Atari Lynx version of samples/hello.c, using TGI instead of conio */
#include <tgi.h>
/*****************************************************************************/
/* Data */
/*****************************************************************************/
static const char Text[] = "Hello world!";
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void main (void)
{
unsigned int XMax, YMax;
tgi_install (tgi_static_stddrv);
tgi_init ();
/* Set screen color. */
tgi_setcolor (TGI_COLOR_WHITE);
/* Clear the screen. */
tgi_clear();
/* Ask for the screen size. */
XMax = tgi_getmaxx ();
YMax = tgi_getmaxy ();
/* Draw a frame around the screen. */
tgi_line (0, 0, XMax, 0);
tgi_lineto (XMax, YMax);
tgi_lineto (0, YMax);
tgi_lineto (0, 0);
/* Write the greeting in the middle of the screen. */
tgi_outtextxy ((tgi_getxres () - tgi_gettextwidth (Text)) / 2,
(tgi_getyres () - tgi_gettextheight (Text)) / 2, Text);
}

86
samples/lynx/mandelbrot.c Normal file
View File

@@ -0,0 +1,86 @@
/*****************************************************************************\
** mandelbrot sample program for Atari Lynx **
** **
** (w) 2002 by groepaz/hitmen, TGI support by Stefan Haubenthal **
\*****************************************************************************/
#include <stdlib.h>
#include <tgi.h>
/* Graphics definitions */
#define SCREEN_X (tgi_getxres())
#define SCREEN_Y (tgi_getyres())
#define MAXCOL (tgi_getcolorcount())
#define maxiterations 32
#define fpshift (10)
#define tofp(_x) ((_x)<<fpshift)
#define fromfp(_x) ((_x)>>fpshift)
#define fpabs(_x) (abs(_x))
#define mulfp(_a,_b) ((((signed long)_a)*(_b))>>fpshift)
#define divfp(_a,_b) ((((signed long)_a)<<fpshift)/(_b))
/* Use static local variables for speed */
#pragma static-locals (1)
static void mandelbrot (signed short x1, signed short y1, signed short x2,
signed short y2)
{
/* */
register signed short r, r1, i;
register signed short xs, ys, xx, yy;
register signed short x, y;
register unsigned char count;
register unsigned char maxcol = MAXCOL;
/* Calc stepwidth */
xs = ((x2 - x1) / (SCREEN_X));
ys = ((y2 - y1) / (SCREEN_Y));
yy = y1;
for (y = 0; y < (SCREEN_Y); y++) {
yy += ys;
xx = x1;
for (x = 0; x < (SCREEN_X); x++) {
xx += xs;
/* Do iterations */
r = 0;
i = 0;
for (count = 0; (count < maxiterations) &&
(fpabs (r) < tofp (2)) && (fpabs (i) < tofp (2));
++count) {
r1 = (mulfp (r, r) - mulfp (i, i)) + xx;
/* i = (mulfp(mulfp(r,i),tofp(2)))+yy; */
i = (((signed long) r * i) >> (fpshift - 1)) + yy;
r = r1;
}
if (count == maxiterations) {
tgi_setcolor (0);
} else {
tgi_setcolor (count % maxcol);
}
/* Set pixel */
tgi_setpixel (x, y);
}
}
}
void main (void)
{
/* Install the graphics driver */
tgi_install (tgi_static_stddrv);
/* Initialize graphics */
tgi_init ();
tgi_clear ();
/* Calc mandelbrot set */
mandelbrot (tofp (-2), tofp (-2), tofp (2), tofp (2));
}

179
samples/lynx/tgidemo.c Normal file
View File

@@ -0,0 +1,179 @@
/* Tgidemo modified for the Atari Lynx.
**
** Press any of the Lynx's option buttons to go to the next screen.
*/
#include <cc65.h>
#include <conio.h>
#include <tgi.h>
#include <time.h>
#define COLOR_BACK TGI_COLOR_BLACK
#define COLOR_FORE TGI_COLOR_WHITE
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Driver stuff */
static unsigned MaxX;
static unsigned MaxY;
static unsigned AspectRatio;
/*****************************************************************************/
/* Code */
/*****************************************************************************/
/* The Lynx draws too fast. This function delays
** the drawing so that we can watch it.
*/
static void wait (unsigned char ticks)
{
clock_t T = clock () + ticks;
while (clock () < T) {}
}
static void DoCircles (void)
{
unsigned char I;
unsigned char Color = COLOR_BACK;
const unsigned X = MaxX / 2;
const unsigned Y = MaxY / 2;
const unsigned Limit = (X < Y) ? Y : X;
tgi_setcolor (COLOR_FORE);
tgi_clear ();
tgi_line (0, 0, MaxX, MaxY);
tgi_line (0, MaxY, MaxX, 0);
while (!kbhit ()) {
Color = (Color == COLOR_FORE) ? COLOR_BACK : COLOR_FORE;
tgi_setcolor (Color);
for (I = 10; I <= Limit; I += 10) {
tgi_ellipse (X, Y, I, tgi_imulround (I, AspectRatio));
wait (9);
}
}
cgetc ();
}
static void DoCheckerboard (void)
{
unsigned X, Y;
unsigned char Color = COLOR_BACK;
tgi_clear ();
while (1) {
for (Y = 0; Y <= MaxY - 2; Y += 10) {
for (X = 0; X <= MaxX; X += 10) {
Color = (Color == COLOR_FORE) ? COLOR_BACK : COLOR_FORE;
tgi_setcolor (Color);
tgi_bar (X, Y, X+9, Y+9);
if (kbhit ()) {
cgetc ();
return;
}
wait (1);
}
Color = Color == COLOR_FORE ? COLOR_BACK : COLOR_FORE;
}
Color = Color == COLOR_FORE ? COLOR_BACK : COLOR_FORE;
}
}
static void DoDiagram (void)
{
int XOrigin, YOrigin;
int Amp;
int X, Y;
unsigned I;
tgi_setcolor (COLOR_FORE);
tgi_clear ();
/* Determine zero and amplitude */
YOrigin = MaxY / 2;
XOrigin = 10;
Amp = (MaxY - 19) / 2;
/* Y axis */
tgi_line (XOrigin, 10, XOrigin, MaxY-10);
tgi_line (XOrigin-2, 12, XOrigin, 10);
tgi_lineto (XOrigin+2, 12);
/* X axis */
tgi_line (XOrigin, YOrigin, MaxX-10, YOrigin);
tgi_line (MaxX-12, YOrigin-2, MaxX-10, YOrigin);
tgi_lineto (MaxX-12, YOrigin+2);
/* Sine */
tgi_gotoxy (XOrigin, YOrigin);
for (I = 0; I <= 360; ++I) {
/* Calculate the next points */
X = (int)(((long)(MaxX - 19) * I) / 360);
Y = (int)(((long)Amp * -_sin (I)) / 256);
/* Draw the line */
tgi_lineto (XOrigin + X, YOrigin + Y);
}
cgetc ();
}
static void DoLines (void)
{
unsigned X;
const unsigned Min = (MaxX < MaxY) ? MaxX : MaxY;
tgi_setcolor (COLOR_FORE);
tgi_clear ();
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);
wait (9);
}
cgetc ();
}
void main (void)
{
/* Install the driver */
tgi_install (tgi_static_stddrv);
tgi_init ();
/* Get stuff from the driver */
MaxX = tgi_getmaxx ();
MaxY = tgi_getmaxy ();
AspectRatio = tgi_getaspectratio ();
/* Do graphics stuff */
DoCircles ();
DoCheckerboard ();
DoDiagram ();
DoLines ();
}

View File

@@ -31,6 +31,7 @@
/* Workaround missing clock stuff */
#ifdef __APPLE2__
# define clock() 0
# undef CLK_TCK
# define CLK_TCK 1
#endif
@@ -40,7 +41,7 @@
#endif
/* Use static local variables for speed */
#pragma static-locals (1);
#pragma static-locals (1)
@@ -51,6 +52,7 @@ void mandelbrot (signed short x1, signed short y1, signed short x2,
register signed short r, r1, i;
register signed short xs, ys, xx, yy;
register signed short x, y;
register unsigned char maxcol = MAXCOL;
/* Calc stepwidth */
xs = ((x2 - x1) / (SCREEN_X));
@@ -76,10 +78,15 @@ void mandelbrot (signed short x1, signed short y1, signed short x2,
if (count == maxiterations) {
tgi_setcolor (0);
} else {
if (MAXCOL == 2) {
switch (maxcol) {
case 2:
tgi_setcolor (1);
} else {
tgi_setcolor (count % MAXCOL);
break;
case 0: /* 256 colors */
tgi_setcolor (count);
break;
default:
tgi_setcolor (count % maxcol);
}
}
/* Set pixel */

View File

@@ -64,34 +64,34 @@ void log (char *msg)
** rather place all the code of certain source files into the overlay by
** compiling them with --code-name OVERLAY1.
*/
#pragma code-name (push, "OVERLAY1");
#pragma code-name (push, "OVERLAY1")
void foo (void)
{
log ("Calling main from overlay 1");
}
#pragma code-name (pop);
#pragma code-name (pop)
#pragma code-name (push, "OVERLAY2");
#pragma code-name (push, "OVERLAY2")
void bar (void)
{
log ("Calling main from overlay 2");
}
#pragma code-name (pop);
#pragma code-name (pop)
#pragma code-name (push, "OVERLAY3");
#pragma code-name (push, "OVERLAY3")
void foobar (void)
{
log ("Calling main from overlay 3");
}
#pragma code-name(pop);
#pragma code-name(pop)
unsigned char loademdriver (void)
@@ -237,7 +237,7 @@ void main (void)
/* The linker makes sure that the call to foo() ends up at the right mem
** addr. However it's up to user to make sure that the - right - overlay
** is actually loaded before making the the call.
** is actually loaded before making the call.
*/
foo ();
}

View File

@@ -39,7 +39,7 @@ void log (char *msg)
** rather place all the code of certain source files into the overlay by
** compiling them with --code-name OVERLAY1.
*/
#pragma code-name (push, "OVERLAY1");
#pragma code-name (push, "OVERLAY1")
void foo (void)
{
@@ -51,27 +51,27 @@ void foo (void)
log ("Calling main from overlay 1");
}
#pragma code-name (pop);
#pragma code-name (pop)
#pragma code-name (push, "OVERLAY2");
#pragma code-name (push, "OVERLAY2")
void bar (void)
{
log ("Calling main from overlay 2");
}
#pragma code-name (pop);
#pragma code-name (pop)
#pragma code-name (push, "OVERLAY3");
#pragma code-name (push, "OVERLAY3")
void foobar (void)
{
log ("Calling main from overlay 3");
}
#pragma code-name(pop);
#pragma code-name(pop)
unsigned char loadfile (char *name, void *addr, void *size)
@@ -112,7 +112,7 @@ void main (void)
/* The linker makes sure that the call to foo() ends up at the right mem
** addr. However it's up to user to make sure that the - right - overlay
** is actually loaded before making the the call.
** is actually loaded before making the call.
*/
foo ();
}

View File

@@ -1,6 +1,14 @@
This directory contains sample programs for the cc65 compiler.
The programs contained here are
- used as samples and referenced from within the documentation (this is their
main purpose)
- installed into the filesystem
- compiled (but NOT run) by the CI test
-----------------------------------------------------------------------------
Below is a short description for each of the programs, together with a list
of the supported platforms.
@@ -10,12 +18,19 @@ Please note:
similar systems. If you're using Windows, then consider installing Cygwin
or MSys2.
* The makefile specifies the C64 as the default target system because all
but three of the programs run on that platform. When compiling for another
system, you will have to change the line that specifies the target system
at the top of the makefile, specify the system with SYS=<target> on the
make command line, or set a SYS environment variable.
* The makefile specifies the C64 as the default target system because most
of the programs run on that platform. When compiling for another system,
you will have to change the line that specifies the target system at the
top of the makefile, specify the system with SYS=<target> on the make
command line, or set a SYS environment variable. For example:
make SYS=apple2
* Use "make disk" to build a disk image with all sample programs.
* All programs in the root of the "samples" directory have been written to
be portable and work on more than one target. Programs that are specific
to a certain target live in a subdirectory with the name of the target.
List of supplied sample programs:
@@ -26,11 +41,6 @@ Description: Shows the ASCII (or ATASCII, PETSCII) codes of typed
<greg.king5@verizon.com>.
Platforms: All platforms with conio or stdio (compile time configurable).
-----------------------------------------------------------------------------
Name: atari2600hello
Description: A "Hello world" type program.
Platforms: Runs on only the Atari 2600 Video Console System.
-----------------------------------------------------------------------------
Name: diodemo
Description: A disc copy program written and contributed by Oliver
@@ -47,12 +57,6 @@ Platforms: All systems with device enumeration and directory access
(currently the Commodore machines, the Commander X16,
and the Apple ][).
-----------------------------------------------------------------------------
Name: fire
Description: Another graphics demo written by groepaz/hitmen.
Platforms: The program currently is running on only the C64, but should
be portable to the C128 and CBM510 (and maybe more machines).
-----------------------------------------------------------------------------
Name: gunzip65
Description: A gunzip utility for 6502-based machines, written by Piotr
@@ -71,11 +75,11 @@ Platforms: Runs on all platforms that support conio, which means:
-----------------------------------------------------------------------------
Name: mandelbrot
Description: A mandelbrot demo using integer arithmetic. The demo was
written by groepaz/hitmen, and converted to cc65 using TGI
graphics by Stephan Haubenthal.
written by groepaz, and converted to cc65 using TGI graphics
by Stefan Haubenthal.
Platforms: Runs on all platforms that have TGI support:
Apple ][, Atari, C64, C128, Oric Atmos and Telestrat, GEOS,
NES, and Lynx.
and NES.
-----------------------------------------------------------------------------
Name: mousedemo
@@ -92,13 +96,6 @@ Platforms: All systems with an overlay linker config., disk directory
access, and EMD support (currently the C64, the C128,
the Atari, and the Apple ][).
-----------------------------------------------------------------------------
Name: nachtm
Description: Plays "Eine kleine Nachtmusik" by Wolfgang Amadeus Mozart.
Platforms: All systems that have the Commodore SID (Sound Interface
Device):
C64, C128, CBM510, CBM610.
-----------------------------------------------------------------------------
Name: overlaydemo
Description: Shows how to load overlay files from disk. Written and
@@ -106,13 +103,6 @@ Description: Shows how to load overlay files from disk. Written and
Platforms: All systems with an overlay linker config. (currently the C64,
the C128, the Atari, and the Apple ][).
-----------------------------------------------------------------------------
Name: plasma
Description: A fancy graphics demo written by groepaz/hitmen.
Platforms: The program needs a VIC-II or a TED, so it runs on the following
systems:
C64, C128, CBM510, Plus/4.
-----------------------------------------------------------------------------
Name: sieve
Description: Implements the "Sieve of Eratosthenes" as a way to find all
@@ -124,9 +114,9 @@ Platforms: All systems with conio and clock support:
support).
-----------------------------------------------------------------------------
Name: supervisionhello
Description: A "Hello world" type program.
Platforms: Runs on only the Watara Supervision game console.
Name: tinyshell
Description: Simple ("tiny") shell to test filename and directory functions.
Platforms: Runs on all platforms that have stdio support
-----------------------------------------------------------------------------
Name: tgidemo
@@ -135,3 +125,124 @@ Description: Shows some of the graphics capabilities of the "Tiny Graphics
Platforms: Runs on all platforms that have TGI support:
Apple ][, Atari, C64, C128, Oric Atmos and Telestrat, GEOS,
NES, and Lynx.
=============================================================================
Platform-specific samples follow:
atari 2600:
-----------
Name: hello
Description: A "Hello world" type program.
Platforms: Runs on only the Atari 2600 Video Console System.
-----------------------------------------------------------------------------
atari 5200:
-----------
Name: hello
Description: A "Hello world" type program.
Platforms: Runs on only the Atari 5200 Video Console System.
-----------------------------------------------------------------------------
apple2:
-------
Name: hgrtest
Description: shows how to incorporate a hires screen right into the binary,
thus allowing to place content both below and above the hires
video ram without multiple files nor copying stuff around (plus
having a nice splash screen as bonus). It basically demos how to
make use of apple2-hgr.cfg.
Name: hgrshow
Description: is a (single) hires program showing how to load (single) hires
screens from files without support from TGI. TGI could be used
to "paint" on the loaded screens.
Name: dhgrshow
Description: is a double hires program showing how to load double hires
screens from files. TGI is used for most of the I/O address
manipulation, but (in contrast to hgrshow) is not actually
functional.
-----------------------------------------------------------------------------
cbm:
----
Name: fire
Description: Another graphics demo written by groepaz.
Platforms: C64, C128, CBM510
-----------------------------------------------------------------------------
Name: nachtm
Description: Plays "Eine kleine Nachtmusik" by Wolfgang Amadeus Mozart.
Platforms: All systems that have the Commodore SID (Sound Interface
Device):
C64, C128, CBM510, CBM610.
-----------------------------------------------------------------------------
Name: plasma
Description: A fancy graphics demo written by groepaz.
Platforms: The program needs a VIC-II or a TED, so it runs on the following
systems:
C64, C128, CBM510, Plus/4.
-----------------------------------------------------------------------------
gamate:
-------
Name: nachtm
Description: Plays "Eine kleine Nachtmusik" by Wolfgang Amadeus Mozart.
-----------------------------------------------------------------------------
lynx:
-----
These programs are adapted for the Atari Lynx because its library has no conio
output or stdio.
Name: hello
Description: A nice "Hello world" type program that uses the TGI graphics
library for output.
Name: mandelbrot
Description: A mandelbrot demo using integer arithmetic. The demo was
written by groepaz, and converted to cc65 using TGI graphics
by Stefan Haubenthal.
Name: tgidemo
Description: Shows some of the graphics capabilities of the "Tiny Graphics
Interface".
-----------------------------------------------------------------------------
sym1:
-----
Name: symHello
Description: Hello World for Sym-1
Name: symTiny
Description: Hello World for Sym-1 (tiny version without printf)
Name: symDisplay
Description: Sym-1 front panel display example
Name: symIO
Description: Sym-1 digital I/O interface example
Name: symNotepad
Description: Sym-1 Notepad
-----------------------------------------------------------------------------
supervision:
------------
Name: hello
Description: A "Hello world" type program.
Platforms: Runs on only the Watara Supervision game console.
----------------------------------------------------------------------------

View File

@@ -38,7 +38,7 @@ static unsigned char Sieve[COUNT];
#pragma static-locals(1);
#pragma static-locals(1)

61
samples/sim65/Makefile Normal file
View File

@@ -0,0 +1,61 @@
# Run 'make SYS=<target>'; or, set a SYS env.
# var. to build for another target system.
SYS ?= sim6502
# Just the usual way to find out if we're
# using cmd.exe to execute make rules.
ifneq ($(shell echo),)
CMD_EXE = 1
endif
ifdef CMD_EXE
NULLDEV = nul:
DEL = -del /f
RMDIR = rmdir /s /q
else
NULLDEV = /dev/null
DEL = $(RM)
RMDIR = $(RM) -r
endif
ifdef CC65_HOME
AS = $(CC65_HOME)/bin/ca65
CC = $(CC65_HOME)/bin/cc65
CL = $(CC65_HOME)/bin/cl65
LD = $(CC65_HOME)/bin/ld65
else
AS := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
CC := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65)
CL := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
endif
EXELIST_sim6502 = \
cpumode_example.bin \
timer_example.bin \
trace_example.bin
ifneq ($(EXELIST_$(SYS)),)
samples: $(EXELIST_$(SYS))
else
samples: notavailable
endif
# empty target used to skip systems that will not work with any program in this dir
notavailable:
ifeq ($(MAKELEVEL),0)
@echo "info: sim65 tests not available for" $(SYS)
else
# suppress the "nothing to be done for 'samples' message
@echo > $(NULLDEV)
endif
.SUFFIXES:
.SUFFIXES: .c .bin
%.bin : %.c
$(CL) -t $(SYS) -Oris -m $*.map -o $@ $<
clean:
@$(DEL) *.o *.map *.bin 2>$(NULLDEV)

View File

@@ -0,0 +1,104 @@
/*
* Sim65 cpu-mode switching example.
*
* Description
* -----------
*
* We can inspect and manipulate the CPU model that sim65 emulates at runtime.
*
* Sim65 always runs in one of three modes:
*
* - 6502 mode: the 151 documented opcodes are supported; if the processor encounters
* one of the 105 undocumented opcodes, the simulator ends with an
* 'illegal opcode' message.
* - 65C02 mode: the 105 undocumented opcodes now have well-defined behavior. Some
* do useful things, while all others are now defined as NOPs.
* - 6502X mode: the 105 undocumented opcodes don't have documented behavior, but
* they /do/ have behavior on a real 6502. This behavior has been
* figured out, and is deterministic (with minor exceptions).
* In this mode, sim65 mimics the behavior of a real 6502 when
* it encounters an undocumented opcode, rather than terminating.
*
* In the example below, we first switch to 6502X mode and execute a small
* assembly code fragment, then repeat this in 65C02 mode.
*
* The code fragment is designed to distinguish between a 6502 and a 65C02
* processor based on the behavior of the ADC function in decimal mode.
*
* Important Note:
*
* When running in a program compiled for the "sim6502" target, it is safe to switch to
* 65C02 or 6502X mode, since the runtime library will only use plain 6502 opcodes, and
* those work the same in 65C02 and 6502X mode.
*
* However, when running in a program compiled for the "sim65c02" target, it is NOT safe
* to switch to 6502 or 6502X mode, since many routines in the runtime library use
* 65C02-specific opcodes, and these will not work as expected when the CPU is switched
* to 6502 or 6502X mode. When such an instruction is encountered, the program will
* exhibit undefined behavior.
*
* For this reason, this program will only work when compiled for the "sim6502" target.
*
* Running the example
* -------------------
*
* cl65 -t sim6502 -O cpumode_example.c -o cpumode_example.prg
* sim65 cpumode_example.prg
*
*/
#include <stdio.h>
#include <stdbool.h>
#include <sim65.h>
static bool __fastcall__ is_65c02(void)
{
/* This assembly routine loads 0 into AX on a 6502 (also on a 6502 on which decimal
* mode is not implemented), and 1 on a 65C02.
*
* Note: this implementation triggers a "control reaches end of non-void function"
* warning that can be safely ignored. While no return statement is present, the
* return value is correctly loaded into AX by the assembly code.
*/
__asm__("sed");
__asm__("ldx #0");
__asm__("txa");
__asm__("sbc #155");
__asm__("asl");
__asm__("rol");
__asm__("and #1");
__asm__("cld");
}
int main(void)
{
printf("CPU mode at startup ....... : %u\n", GET_CPU_MODE());
printf("Is 65C02? ................. : %s\n", is_65c02() ? "YES" : "NO");
printf("\n");
printf("Switching to 6502 mode ....\n");
SET_CPU_MODE(SIM65_CPU_MODE_6502);
printf("Current CPU mode .......... : %u\n", GET_CPU_MODE());
printf("Is 65C02? ................. : %s\n", is_65c02() ? "YES" : "NO");
printf("\n");
printf("Switching to 65C02 mode ...\n");
SET_CPU_MODE(SIM65_CPU_MODE_65C02);
printf("Current CPU mode .......... : %u\n", GET_CPU_MODE());
printf("Is 65C02? ................. : %s\n", is_65c02() ? "YES" : "NO");
printf("\n");
printf("Switching to 6502X mode ...\n");
SET_CPU_MODE(SIM65_CPU_MODE_6502X);
printf("Current CPU mode .......... : %u\n", GET_CPU_MODE());
printf("Is 65C02? ................. : %s\n", is_65c02() ? "YES" : "NO");
printf("\n");
printf("Bye!\n");
return 0;
}

View File

@@ -0,0 +1,117 @@
/*
* Sim65 timer example.
*
* Description
* -----------
*
* This example tests the clock cycle counter feature of sim65.
*
* The function 'timestamp' obtains the lower 32-bits of the clock cycle counter.
*
* The function 'calc_sum_terms' calculates the sum of a range of integers
* starting at zero. It simply iterates over all terms, which means that its
* runtime is a linear function of its input value.
*
* In the main function, we first derive an 'offset' value by getting two timestamp
* values, with nothing happening in between. Ideally this should yield a 0 clock
* cycle duration, but due to the overhead of calling the 'timestamp' function,
* and the 'timestamp' function itself, the difference between these timestamp
* will be non-zero. We store this value in the 'overhead' variable, and subtract
* this value in later measurements.
*
* Next, we measure the duration of calling the function 'calc_sum_terms' with two
* input values, 0, and 1. The duration includes storing the result in the 'result'
* variable.
*
* Extrapolating from these two measurements, and assuming that the runtime of
* calling 'calc_sum_terms' and storing its result scales linearly with its argument,
* we can predict the duration of a call to 'calc_sum_terms' with a much larger
* argument (max_terms = 10000).
*
* Finally, we actually measure the duration with max_terms = 10000. If the
* duration measured is equal to the predicted value, we exit successfully. If not,
* we exit with failure.
*
* Running the example
* -------------------
*
* cl65 -t sim6502 -O timer_example.c -o timer_example.prg
* sim65 timer_example.prg
*
*/
#include <stdio.h>
#include <sim65.h>
static uint32_t timestamp(void)
{
peripherals.counter.select = COUNTER_SELECT_CLOCKCYCLE_COUNTER;
peripherals.counter.latch = 0;
return peripherals.counter.value32[0];
}
static unsigned long calc_sum_terms(unsigned max_term)
/* A function with a runtime that scales linearly with its argument. */
{
unsigned k;
unsigned long sum = 0;
for (k = 0; k <= max_term; ++k)
{
sum += k;
}
return sum;
}
int main(void)
{
unsigned max_term;
unsigned long result;
uint32_t t1, t2, overhead;
int32_t d0, d1, duration;
int32_t predicted_duration;
/* Calibration measurement of zero clock cycles, to determine the overhead. */
overhead = 0;
t1 = timestamp();
t2 = timestamp() - overhead;
overhead = (t2 - t1);
/* Calculate call duration (including assignment of result) for argument value 0. */
max_term = 0;
t1 = timestamp();
result = calc_sum_terms(max_term);
t2 = timestamp();
d0 = (t2 - t1) - overhead;
printf("max_term = %u -> result = %lu; duration = %ld\n", max_term, result, d0);
/* Calculate call duration (including assignment of result) for argument value 1. */
max_term = 1;
t1 = timestamp();
result = calc_sum_terms(max_term);
t2 = timestamp();
d1 = (t2 - t1) - overhead;
printf("max_term = %u -> result = %lu; duration = %ld\n", max_term, result, d1);
/* Predict runtime for a much bigger argument value, 10000. */
max_term = 10000;
predicted_duration = d0 + max_term * (d1 - d0);
printf("predicted duration for max_term = %u: %ld\n", max_term, predicted_duration);
/* Do the actual measurement for max_term = 10000.
* Note: equality between the prediction and the measurement is only achieved if we compile with -O.
*/
t1 = timestamp();
result = calc_sum_terms(max_term);
t2 = timestamp();
duration = (t2 - t1) - overhead;
printf("max_term = %u -> result = %lu; duration = %ld\n", max_term, result, duration);
return 0;
}

View File

@@ -0,0 +1,40 @@
/*
* Sim65 trace functionailty example.
*
* Description
* -----------
*
* The easiest way to use tracing in sim65 is to pass the '--trace' option
* to sim65 while starting a program.
*
* However, it is also possiblke to enable and disable the trace functionality
* at runtime, from within the C code itself. This can be useful to produce
* runtime traces of small code fragments for debugging purposes.
*
* In this example, We use the TRACE_ON and TRACE_OFF macros provided in sim65.h
* to trace what the CPU is doing during a single statement: the assignment of
* a constant to a global variable.
*
* Running the example
* -------------------
*
* cl65 -t sim6502 -O trace_example.c -o trace_example.prg
* sim65 trace_example.prg
*
* Compiling and running the program like this will produce a trace of six 6502 instructions.
* The first four instructions correspond to the 'x = 0x1234' assignment statement.
* The last two instructions (ending in a store to address $FFCB) disable the trace facility.
*
*/
#include <sim65.h>
unsigned x;
int main(void)
{
TRACE_ON();
x = 0x1234;
TRACE_OFF();
return 0;
}

View File

@@ -0,0 +1,59 @@
# Run 'make SYS=<target>'; or, set a SYS env.
# var. to build for another target system.
SYS ?= supervision
# Just the usual way to find out if we're
# using cmd.exe to execute make rules.
ifneq ($(shell echo),)
CMD_EXE = 1
endif
ifdef CMD_EXE
NULLDEV = nul:
DEL = -del /f
RMDIR = rmdir /s /q
else
NULLDEV = /dev/null
DEL = $(RM)
RMDIR = $(RM) -r
endif
ifdef CC65_HOME
AS = $(CC65_HOME)/bin/ca65
CC = $(CC65_HOME)/bin/cc65
CL = $(CC65_HOME)/bin/cl65
LD = $(CC65_HOME)/bin/ld65
SP = $(CC65_HOME)/bin/sp65
else
AS := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
CC := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65)
CL := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
SP := $(if $(wildcard ../../bin/sp65*),../../bin/sp65,sp65)
endif
EXELIST_supervision = \
hello
ifneq ($(EXELIST_$(SYS)),)
samples: $(EXELIST_$(SYS))
else
samples: notavailable
endif
# empty target used to skip systems that will not work with any program in this dir
notavailable:
ifeq ($(MAKELEVEL),0)
@echo "info: supervision samples not available for" $(SYS)
else
# suppress the "nothing to be done for 'samples' message
@echo > $(NULLDEV)
endif
hello: hello.c
$(CL) -t $(SYS) -O -o hello -m hello.map hello.c
clean:
@$(DEL) $(EXELIST_supervision) 2>$(NULLDEV)
@$(DEL) *.map 2>$(NULLDEV)

View File

@@ -0,0 +1,95 @@
/*****************************************************************************/
/* */
/* Watara Supervision sample C program */
/* */
/* Fabrizio Caruso (fabrizio_caruso@hotmail.com), 2019 */
/* Greg King (greg.king5@verizon.net), 2021 */
/* */
/*****************************************************************************/
#include <supervision.h>
#include <string.h>
/* Number of words per screen line (Remark: Last 4 words aren't displayed) */
#define WORDS_PER_LINE (160/8+4)
struct sv_vram {
unsigned int v[160/8][8][WORDS_PER_LINE];
};
#define SV_VRAM ((*(struct sv_vram *)0x4000).v)
/* Character definitions in 8x8 format */
/* That format gives us a screen of 20 columns and 20 rows */
static const unsigned char h_char[] = {0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00};
static const unsigned char e_char[] = {0x7E,0x60,0x60,0x78,0x60,0x60,0x7E,0x00};
static const unsigned char l_char[] = {0x60,0x60,0x60,0x60,0x60,0x60,0x7E,0x00};
static const unsigned char o_char[] = {0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x00};
static const unsigned char w_char[] = {0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00};
static const unsigned char r_char[] = {0x7C,0x66,0x66,0x7C,0x78,0x6C,0x66,0x00};
static const unsigned char d_char[] = {0x78,0x6C,0x66,0x66,0x66,0x6C,0x78,0x00};
static void clear_screen(void)
{
memset(SV_VIDEO, 0, 0x2000);
}
/* Necessary conversion to have 2 bits per pixel with darkest hue */
/* Remark: The Supervision uses 2 bits per pixel, and bits are mapped into pixels in reversed order */
static unsigned int __fastcall__ double_reversed_bits(unsigned char)
{
__asm__("stz ptr2");
__asm__("stz ptr2+1");
__asm__("ldy #$08");
L1: __asm__("lsr a");
__asm__("php");
__asm__("rol ptr2");
__asm__("rol ptr2+1");
__asm__("plp");
__asm__("rol ptr2");
__asm__("rol ptr2+1");
__asm__("dey");
__asm__("bne %g", L1);
__asm__("lda ptr2");
__asm__("ldx ptr2+1");
return __AX__;
}
static void display_char(const unsigned char x, const unsigned char y, const unsigned char *ch)
{
unsigned char k;
for(k=0;k<8;++k)
{
SV_VRAM[y][k][x] = double_reversed_bits(ch[k]);
}
}
static void init_lcd(void)
{
SV_LCD.width = 160;
SV_LCD.height = 160;
}
static void hello(unsigned char x, unsigned char y)
{
display_char(x+ 0,y,h_char);
display_char(x+ 1,y,e_char);
display_char(x+ 2,y,l_char);
display_char(x+ 3,y,l_char);
display_char(x+ 4,y,o_char);
display_char(x+ 6,y,w_char);
display_char(x+ 7,y,o_char);
display_char(x+ 8,y,r_char);
display_char(x+ 9,y,l_char);
display_char(x+10,y,d_char);
}
void main(void)
{
init_lcd();
clear_screen();
hello(2,3);
hello(7,16);
}

View File

@@ -1,91 +0,0 @@
/*****************************************************************************/
/* */
/* Watara Supervision sample C program */
/* */
/* Fabrizio Caruso (fabrizio_caruso@hotmail.com), 2019 */
/* */
/*****************************************************************************/
#include <supervision.h>
#include <peekpoke.h>
// Number of bytes per screen line (Remark: Last 8 bytes are not displayed)
#define BYTES_PER_LINE 48
// Character definitions in 8x8 format
const unsigned char h_char[] = {0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00};
const unsigned char e_char[] = {0x7E,0x60,0x60,0x78,0x60,0x60,0x7E,0x00};
const unsigned char l_char[] = {0x60,0x60,0x60,0x60,0x60,0x60,0x7E,0x00};
const unsigned char o_char[] = {0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x00};
const unsigned char w_char[] = {0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00};
const unsigned char r_char[] = {0x7C,0x66,0x66,0x7C,0x78,0x6C,0x66,0x00};
const unsigned char d_char[] = {0x78,0x6C,0x66,0x66,0x66,0x6C,0x78,0x00};
void clear_screen(void)
{
unsigned short i;
for(i=0;i<0x2000;++i)
{
POKE(SV_VIDEO+i,0);
}
}
// Necessary conversion to have 2 bits per pixel with darkest hue
// Remark: The Supervision uses 2 bits per pixel and bits are mapped into pixel in reversed order
unsigned char reversed_map_one_to_two_lookup[16] =
{
0x00, 0xC0, 0x30, 0xF0, 0x0C, 0xCC, 0x3C, 0xFC,
0x03, 0xC3, 0x33, 0xF3, 0x0F, 0xCF, 0x3F, 0xFF
};
unsigned char left_map_one_to_two(unsigned char n)
{
return reversed_map_one_to_two_lookup[n >> 4];
}
unsigned char right_map_one_to_two(unsigned char n)
{
return reversed_map_one_to_two_lookup[n&0x0F];
}
void display_char(const unsigned char x, const unsigned char y, const unsigned char *ch)
{
unsigned char k;
for(k=0;k<8;++k)
{ \
SV_VIDEO[2*(y)+BYTES_PER_LINE*k+BYTES_PER_LINE*(x<<3)] = left_map_one_to_two(ch[k]);
SV_VIDEO[2*(y)+BYTES_PER_LINE*k+BYTES_PER_LINE*(x<<3)+1] = right_map_one_to_two(ch[k]);
}
}
void init_lcd(void)
{
SV_LCD.width = 160;
SV_LCD.height = 160;
}
int main()
{
init_lcd();
clear_screen();
display_char(3,2, h_char);
display_char(3,3, e_char);
display_char(3,4, l_char);
display_char(3,5, l_char);
display_char(3,6, o_char);
display_char(3,8, w_char);
display_char(3,9, o_char);
display_char(3,10,r_char);
display_char(3,11,l_char);
display_char(3,12,d_char);
while(1) {};
return 0;
}

77
samples/sym1/Makefile Normal file
View File

@@ -0,0 +1,77 @@
# Run 'make SYS=<target>'; or, set a SYS env.
# var. to build for another target system.
SYS ?= sym1
# Just the usual way to find out if we're
# using cmd.exe to execute make rules.
ifneq ($(shell echo),)
CMD_EXE = 1
endif
ifdef CMD_EXE
NULLDEV = nul:
DEL = -del /f
RMDIR = rmdir /s /q
else
NULLDEV = /dev/null
DEL = $(RM)
RMDIR = $(RM) -r
endif
ifdef CC65_HOME
AS = $(CC65_HOME)/bin/ca65
CC = $(CC65_HOME)/bin/cc65
CL = $(CC65_HOME)/bin/cl65
LD = $(CC65_HOME)/bin/ld65
else
AS := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
CC := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65)
CL := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
endif
EXELIST_sym1 = \
symHello.bin symTiny.bin symDisplay.bin symIO.bin symNotepad.bin symExtendedMemory.bin
ifneq ($(EXELIST_$(SYS)),)
samples: $(EXELIST_$(SYS))
else
samples: notavailable
endif
# empty target used to skip systems that will not work with any program in this dir
notavailable:
ifeq ($(MAKELEVEL),0)
@echo "info: sym1 tests not available for" $(SYS)
else
# suppress the "nothing to be done for 'samples' message
@echo > $(NULLDEV)
endif
symHello.bin: symHello.c
$(CL) -t sym1 -O -o symHello.bin symHello.c
symTiny.bin: symTiny.c
$(CL) -t sym1 -O -o symTiny.bin symTiny.c
symDisplay.bin: symDisplay.c
$(CL) -t sym1 -O -o symDisplay.bin symDisplay.c
symIO.bin: symIO.c
$(CL) -t sym1 -C sym1-32k.cfg -O -o symIO.bin symIO.c
symNotepad.bin: symNotepad.c
$(CL) -t sym1 -C sym1-32k.cfg -O -o symNotepad.bin symNotepad.c
symExtendedMemory.bin: symExtendedMemory.c
$(CL) -t sym1 -C sym1-32k.cfg -O -o symExtendedMemory.bin symExtendedMemory.c
clean:
@$(DEL) symHello.bin 2>$(NULLDEV)
@$(DEL) symTiny.bin 2>$(NULLDEV)
@$(DEL) symDisplay.bin 2>$(NULLDEV)
@$(DEL) symIO.bin 2>$(NULLDEV)
@$(DEL) symNotepad.bin 2>$(NULLDEV)
@$(DEL) symExtendedMemory.bin 2>$(NULLDEV)

358
samples/sym1/symDisplay.c Normal file
View File

@@ -0,0 +1,358 @@
// --------------------------------------------------------------------------
// Sym-1 front panel display example
//
// Wayne Parham
//
// wayne@parhamdata.com
// --------------------------------------------------------------------------
#include <stdio.h>
#include <sym1.h>
int main (void) {
int delay = 10;
int flashes = 255;
int displayable = 1;
int e = 0;
int r = 0;
int d = 0;
int i = 0;
int l = 0;
int t = 0;
int z = 0;
char c = 0x00;
char buffer[41] = { 0x00 };
puts ("\nType a message (40 chars max) and press ENTER, please:\n");
while ( (c != '\n') && (i < 40) ) {
c = getchar();
buffer[i] = c;
i++;
if ( i == 40 ) {
puts ("\n\n--- Reached 40 character limit. ---");
}
}
i--; // index is one past end
while ( z == 0 ) {
puts ("\n\nHow many times (0 for forever) to repeat?");
c = getchar();
if ( (c >= '0') && (c <= '9') ) {// between 1 and 9 loops allowed
z = 1; // a number was pressed
t = c - '0'; // convert char to int
puts ("\n\nLook at the front panel.\n");
}
else {
puts ("\nWhat?");
z = 0; // keep asking for a number
}
}
z = 0;
while ( (z < t) || (t == 0) ) {
z++;
putchar ( '\r' ); // Send CR to console
DISPLAY.d0 = DISP_SPACE; // Clear the display
DISPLAY.d1 = DISP_SPACE;
DISPLAY.d2 = DISP_SPACE;
DISPLAY.d3 = DISP_SPACE;
DISPLAY.d4 = DISP_SPACE;
DISPLAY.d5 = DISP_SPACE;
DISPLAY.d6 = DISP_SPACE;
for ( d = 0; d < flashes ; d++ ) {
fdisp(); // Display
}
for ( l = 0; l <= i; l++ ) {
displayable = 1; // Assume character is mapped
switch ( buffer[l] ) { // Put the typed charaters
case '1': // into the display buffer
DISPLAY.d6 = DISP_1; // one at a time
break;
case '2':
DISPLAY.d6 = DISP_2;
break;
case '3':
DISPLAY.d6 = DISP_3;
break;
case '4':
DISPLAY.d6 = DISP_4;
break;
case '5':
DISPLAY.d6 = DISP_5;
break;
case '6':
DISPLAY.d6 = DISP_6;
break;
case '7':
DISPLAY.d6 = DISP_7;
break;
case '8':
DISPLAY.d6 = DISP_8;
break;
case '9':
DISPLAY.d6 = DISP_9;
break;
case '0':
DISPLAY.d6 = DISP_0;
break;
case 'A':
DISPLAY.d6 = DISP_A;
break;
case 'a':
DISPLAY.d6 = DISP_A;
break;
case 'B':
DISPLAY.d6 = DISP_b;
break;
case 'b':
DISPLAY.d6 = DISP_b;
break;
case 'C':
DISPLAY.d6 = DISP_C;
break;
case 'c':
DISPLAY.d6 = DISP_c;
break;
case 'D':
DISPLAY.d6 = DISP_d;
break;
case 'd':
DISPLAY.d6 = DISP_d;
break;
case 'E':
DISPLAY.d6 = DISP_E;
break;
case 'e':
DISPLAY.d6 = DISP_e;
break;
case 'F':
DISPLAY.d6 = DISP_F;
break;
case 'f':
DISPLAY.d6 = DISP_F;
break;
case 'G':
DISPLAY.d6 = DISP_G;
break;
case 'g':
DISPLAY.d6 = DISP_g;
break;
case 'H':
DISPLAY.d6 = DISP_H;
break;
case 'h':
DISPLAY.d6 = DISP_h;
break;
case 'I':
DISPLAY.d6 = DISP_I;
break;
case 'i':
DISPLAY.d6 = DISP_i;
break;
case 'J':
DISPLAY.d6 = DISP_J;
break;
case 'j':
DISPLAY.d6 = DISP_J;
break;
case 'K':
DISPLAY.d6 = DISP_K;
break;
case 'k':
DISPLAY.d6 = DISP_K;
break;
case 'L':
DISPLAY.d6 = DISP_L;
break;
case 'l':
DISPLAY.d6 = DISP_L;
break;
case 'M':
DISPLAY.d0 = DISPLAY.d1;
DISPLAY.d1 = DISPLAY.d2;
DISPLAY.d2 = DISPLAY.d3;
DISPLAY.d3 = DISPLAY.d4;
DISPLAY.d4 = DISPLAY.d5;
DISPLAY.d5 = DISP_M_1;
DISPLAY.d6 = DISP_M_2;
break;
case 'm':
DISPLAY.d0 = DISPLAY.d1;
DISPLAY.d1 = DISPLAY.d2;
DISPLAY.d2 = DISPLAY.d3;
DISPLAY.d3 = DISPLAY.d4;
DISPLAY.d4 = DISPLAY.d5;
DISPLAY.d5 = DISP_M_1;
DISPLAY.d6 = DISP_M_2;
break;
case 'N':
DISPLAY.d6 = DISP_n;
break;
case 'n':
DISPLAY.d6 = DISP_n;
break;
case 'O':
DISPLAY.d6 = DISP_O;
break;
case 'o':
DISPLAY.d6 = DISP_o;
break;
case 'P':
DISPLAY.d6 = DISP_P;
break;
case 'p':
DISPLAY.d6 = DISP_P;
break;
case 'Q':
DISPLAY.d6 = DISP_q;
break;
case 'q':
DISPLAY.d6 = DISP_q;
break;
case 'R':
DISPLAY.d6 = DISP_r;
break;
case 'r':
DISPLAY.d6 = DISP_r;
break;
case 'S':
DISPLAY.d6 = DISP_S;
break;
case 's':
DISPLAY.d6 = DISP_S;
break;
case 'T':
DISPLAY.d6 = DISP_t;
break;
case 't':
DISPLAY.d6 = DISP_t;
break;
case 'U':
DISPLAY.d6 = DISP_U;
break;
case 'u':
DISPLAY.d6 = DISP_u;
break;
case 'V':
DISPLAY.d0 = DISPLAY.d1;
DISPLAY.d1 = DISPLAY.d2;
DISPLAY.d2 = DISPLAY.d3;
DISPLAY.d3 = DISPLAY.d4;
DISPLAY.d4 = DISPLAY.d5;
DISPLAY.d5 = DISP_V_1;
DISPLAY.d6 = DISP_V_2;
break;
case 'v':
DISPLAY.d0 = DISPLAY.d1;
DISPLAY.d1 = DISPLAY.d2;
DISPLAY.d2 = DISPLAY.d3;
DISPLAY.d3 = DISPLAY.d4;
DISPLAY.d4 = DISPLAY.d5;
DISPLAY.d5 = DISP_V_1;
DISPLAY.d6 = DISP_V_2;
break;
case 'W':
DISPLAY.d0 = DISPLAY.d1;
DISPLAY.d1 = DISPLAY.d2;
DISPLAY.d2 = DISPLAY.d3;
DISPLAY.d3 = DISPLAY.d4;
DISPLAY.d4 = DISPLAY.d5;
DISPLAY.d5 = DISP_W_1;
DISPLAY.d6 = DISP_W_2;
break;
case 'w':
DISPLAY.d0 = DISPLAY.d1;
DISPLAY.d1 = DISPLAY.d2;
DISPLAY.d2 = DISPLAY.d3;
DISPLAY.d3 = DISPLAY.d4;
DISPLAY.d4 = DISPLAY.d5;
DISPLAY.d5 = DISP_W_1;
DISPLAY.d6 = DISP_W_2;
break;
case 'Y':
DISPLAY.d6 = DISP_Y;
break;
case 'y':
DISPLAY.d6 = DISP_Y;
break;
case 'Z':
DISPLAY.d6 = DISP_Z;
break;
case 'z':
DISPLAY.d6 = DISP_Z;
break;
case ' ':
DISPLAY.d6 = DISP_SPACE;
break;
case '.':
DISPLAY.d6 = DISP_PERIOD;
break;
case '-':
DISPLAY.d6 = DISP_HYPHEN;
break;
case '\'':
DISPLAY.d6 = DISP_APOSTR;
break;
case '"':
DISPLAY.d6 = DISP_APOSTR;
break;
case '=':
DISPLAY.d6 = DISP_EQUAL;
break;
case '_':
DISPLAY.d6 = DISP_BOTTOM;
break;
case '/':
DISPLAY.d6 = DISP_SLASH;
break;
case '\\':
DISPLAY.d6 = DISP_BACKSLASH;
break;
default:
displayable = 0; // Character not mapped
}
if ( displayable ) {
putchar ( buffer[l] ); // Send it to the console
DISPLAY.d0 = DISPLAY.d1; // Scroll to the left
DISPLAY.d1 = DISPLAY.d2;
DISPLAY.d2 = DISPLAY.d3;
DISPLAY.d3 = DISPLAY.d4;
DISPLAY.d4 = DISPLAY.d5;
DISPLAY.d5 = DISPLAY.d6;
for ( d = 0; d < flashes ; d++ ) {
fdisp(); // Display
}
}
}
for ( e = 0; e < 6; e++ ) { // Gradually fill the
DISPLAY.d0 = DISPLAY.d1; // display with spaces
DISPLAY.d1 = DISPLAY.d2;
DISPLAY.d2 = DISPLAY.d3;
DISPLAY.d3 = DISPLAY.d4;
DISPLAY.d4 = DISPLAY.d5;
DISPLAY.d5 = DISP_SPACE;
DISPLAY.d6 = DISP_SPACE;
for ( d = 0; d < flashes ; d++ ) {
fdisp(); // Display
}
}
}
puts ("\n\nEnjoy your day!\n\n");
return 0;
}

View File

@@ -0,0 +1,101 @@
// --------------------------------------------------------------------------
// Sym-1 Extended Memory
//
// Wayne Parham
//
// wayne@parhamdata.com
// --------------------------------------------------------------------------
//
// Note: This program examines memory above the monitor ROM (8000-8FFF) to
// Determine what, if any, memory is available. It then adds whatever
// 4K segments it finds to the heap.
//
// Memory Segment Remark
// 0x9000 Usually available
// 0xA000 System I/O, always unavailable
// 0xB000 Used by RAE, but normally available
// 0xC000 Used by BASIC, normally unavailable
// 0xD000 Used by BASIC, normally unavailable
// 0xE000 Used by RAE, but normally available
// 0xF000 Normally available, but only to FF7F
//
// --------------------------------------------------------------------------
#include <sym1.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STD_MEM 0x7FFF // Last address of standard memory
#define SEGMENT 0x9000 // First 4K segment of extended memory
#define SEG_END 0x0FFF // Last location of segment
#define BLOCK_SIZE 0x1000 // Size of segment
#define TOP_END 0x0F7F // Last location of memory
#define TOP_SIZE 0x0F80 // Size of top segment
#define UNAVAILABLE 0xA000 // System I/O area
int main (void) {
int error = 0;
unsigned heap_size = 0x0000;
char* segment = (char*) SEGMENT;
printf ( "Analyzing memory.\n\n" );
heap_size = _heapmemavail();
printf ( "Main memory has %u bytes available.\n", heap_size );
if ( heap_size > STD_MEM ) {
printf ( "Extended memory already installed.\n" );
} else {
while ( (int) segment < 0xEFFF ) { // Iterate through 4K memory blocks
if( (int) segment != UNAVAILABLE ) {
segment[0] = 0x00; // Check beginning of segment
if ( segment[0] != 0x00 )
error = 1;
segment[0] = 0xFF;
if ( segment[0] != 0xFF )
error = 1;
segment[SEG_END] = 0x00; // Check end of segment
if ( segment[SEG_END] != 0x00 )
error = 1;
segment[SEG_END] = 0xFF;
if ( segment[SEG_END] != 0xFF )
error = 1;
if ( ! error ) { // If memory found, add to the heap
printf ( "Memory found at location %p, ", segment );
_heapadd ( segment, BLOCK_SIZE );
heap_size = _heapmemavail();
printf( "so the system now has %u bytes available.\n", heap_size );
} else {
error = 0;
}
}
segment += 0x1000; // Increment to next segment
}
segment[0] = 0x00; // Check beginning of top memory segment
if ( segment[0] != 0x00 )
error = 1;
segment[0] = 0xFF;
if ( segment[0] != 0xFF )
error = 1;
segment[TOP_END] = 0x00; // Check end of usable memory
if ( segment[TOP_END] != 0x00 )
error = 1;
segment[TOP_END] = 0xFF;
if ( segment[TOP_END] != 0xFF )
error = 1;
if ( ! error ) { // If memory found, add to the heap
printf ( "Memory found at location %p, ", segment );
_heapadd ( segment, TOP_SIZE );
heap_size = _heapmemavail();
printf( "so the system now has %u bytes available.\n", heap_size );
}
}
puts ("\nEnjoy your day!\n");
return 0;
}

39
samples/sym1/symHello.c Normal file
View File

@@ -0,0 +1,39 @@
// --------------------------------------------------------------------------
// Hello World for Sym-1
//
// Wayne Parham
//
// wayne@parhamdata.com
// --------------------------------------------------------------------------
#include <stdio.h>
#include <sym1.h>
int main (void) {
char c = 0x00;
int d = 0x00;
int l = 0x00;
printf ("\nHello World!\n\n");
for ( l = 0; l < 2; l++ ) {
beep();
for ( d = 0; d < 10 ; d++ ) {
}
}
printf ("Type a line and press ENTER, please.\n\n");
while ( c != '\n' ) {
c = getchar();
}
printf ("\n\nThanks!\n\n");
for ( l = 0; l < 5; l++ ) {
beep();
for ( d = 0; d < 10 ; d++ ) {
}
}
return 0;
}

172
samples/sym1/symIO.c Normal file
View File

@@ -0,0 +1,172 @@
// --------------------------------------------------------------------------
// Sym-1 digital I/O interface example
//
// Wayne Parham
//
// wayne@parhamdata.com
// --------------------------------------------------------------------------
#include <sym1.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (void) {
unsigned char ddr1a = 0x00;
unsigned char ior1a = 0x00;
unsigned char ddr1b = 0x00;
unsigned char ior1b = 0x00;
unsigned char ddr2a = 0x00;
unsigned char ior2a = 0x00;
unsigned char ddr2b = 0x00;
unsigned char ior2b = 0x00;
unsigned char ddr3a = 0x00;
unsigned char ior3a = 0x00;
unsigned char ddr3b = 0x00;
unsigned char ior3b = 0x00;
unsigned char val = 0x00;
int going = 0x01;
int instr = 0x01;
int l = 0x00;
char* vp = 0x00;
char cmd[20] = { 0x00 };
while ( going ) {
putchar ( '\r' );
for ( l = 0; l < 25; l++ ) {
putchar ( '\n' );
}
ddr1a = VIA1.ddra;
ior1a = VIA1.pra;
ddr1b = VIA1.ddrb;
ior1b = VIA1.prb;
ddr2a = VIA2.ddra;
ior2a = VIA2.pra;
ddr2b = VIA2.ddrb;
ior2b = VIA2.prb;
ddr3a = VIA3.ddra;
ior3a = VIA3.pra;
ddr3b = VIA3.ddrb;
ior3b = VIA3.prb;
puts ("================== Digital I/O Status ==================");
puts (" Port1A Port1B Port2A Port2B Port3A Port3B" );
printf ("DDR %02X %02X %02X %02X %02X %02X\n\r",ddr1a,ddr1b,ddr2a,ddr2b,ddr3a,ddr3b);
printf ("IOR %02X %02X %02X %02X %02X %02X\n\r",ior1a,ior1b,ior2a,ior2b,ior3a,ior3b);
puts ("========================================================\n");
if ( instr ) {
puts ("You can set any register by typing 'register value' so");
puts ("as an example, to set register IOR2A with the top five");
puts ("bits off and the bottom three on, type 'IOR2A 07'.");
puts ("Press ENTER without any command to see register values");
puts ("without changing any of them. Type 'help' to see these");
puts ("instructions again and type 'quit' to end the program.\n");
puts ("Available registers: DDR1A, IOR1A, DDR1B, IOR1B, DDR2A");
puts ("IOR2A, DDR2B, IOR2B, DDR3A, IOR3A, DDR3B and IOR3B.");
instr = 0;
}
printf ("\n Command: ");
fgets ( cmd, sizeof(cmd)-1, stdin );
cmd[strlen(cmd)-1] = '\0';
if ( strncasecmp(cmd, "quit", 4) == 0 ) {
going = 0;
}
else if ( strncasecmp(cmd, "help", 4) == 0 ) {
instr = 1;
}
else if ( strncasecmp(cmd, "ddr1a", 5) == 0 ) {
vp = strchr ( cmd, ' ' );
if ( vp ) {
val = (unsigned char) strtol( vp, NULL, 0 );
VIA1.ddra = val;
}
}
else if ( strncasecmp(cmd, "ior1a", 5) == 0 ) {
vp = strchr ( cmd, ' ' );
if ( vp ) {
val = (unsigned char) strtol( vp, NULL, 0 );
VIA1.pra = val;
}
}
else if ( strncasecmp(cmd, "ddr1b", 5) == 0 ) {
vp = strchr ( cmd, ' ' );
if ( vp ) {
val = (unsigned char) strtol( vp, NULL, 0 );
VIA1.ddrb = val;
}
}
else if ( strncasecmp(cmd, "ior1b", 5) == 0 ) {
vp = strchr ( cmd, ' ' );
if ( vp ) {
val = (unsigned char) strtol( vp, NULL, 0 );
VIA1.prb = val;
}
}
else if ( strncasecmp(cmd, "ddr2a", 5) == 0 ) {
vp = strchr ( cmd, ' ' );
if ( vp ) {
val = (unsigned char) strtol( vp, NULL, 0 );
VIA2.ddra = val;
}
}
else if ( strncasecmp(cmd, "ior2a", 5) == 0 ) {
vp = strchr ( cmd, ' ' );
if ( vp ) {
val = (unsigned char) strtol( vp, NULL, 0 );
VIA2.pra = val;
}
}
else if ( strncasecmp(cmd, "ddr2b", 5) == 0 ) {
vp = strchr ( cmd, ' ' );
if ( vp ) {
val = (unsigned char) strtol( vp, NULL, 0 );
VIA2.ddrb = val;
}
}
else if ( strncasecmp(cmd, "ior2b", 5) == 0 ) {
vp = strchr ( cmd, ' ' );
if ( vp ) {
val = (unsigned char) strtol( vp, NULL, 0 );
VIA2.prb = val;
}
}
else if ( strncasecmp(cmd, "ddr3a", 5) == 0 ) {
vp = strchr ( cmd, ' ' );
if ( vp ) {
val = (unsigned char) strtol( vp, NULL, 0 );
VIA3.ddra = val;
}
}
else if ( strncasecmp(cmd, "ior3a", 5) == 0 ) {
vp = strchr ( cmd, ' ' );
if ( vp ) {
val = (unsigned char) strtol( vp, NULL, 0 );
VIA3.pra = val;
}
}
else if ( strncasecmp(cmd, "ddr3b", 5) == 0 ) {
vp = strchr ( cmd, ' ' );
if ( vp ) {
val = (unsigned char) strtol( vp, NULL, 0 );
VIA3.ddrb = val;
}
}
else if ( strncasecmp(cmd, "ior3b", 5) == 0 ) {
vp = strchr (cmd, ' ' );
if ( vp ) {
val = (unsigned char) strtol( vp, NULL, 0 );
VIA3.prb = val;
}
}
}
puts ("\n\nEnjoy your day!\n\n");
return 0;
}

192
samples/sym1/symNotepad.c Normal file
View File

@@ -0,0 +1,192 @@
// --------------------------------------------------------------------------
// Sym-1 Notepad
//
// Wayne Parham
//
// wayne@parhamdata.com
// --------------------------------------------------------------------------
//
// Note: This program requires RAM memory in locations 0xE000 - 0xEFFF
// Alternatively, the tape I/O buffer location and size can be
// changed by altering the defined TAPIO values below.
//
// --------------------------------------------------------------------------
#include <sym1.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TAPIO_ADDRESS 0xE000
#define TAPIO_MAX_SIZE 0x0FFF
int main (void) {
char c = 0x00;
int l = 0x00;
int p = 0x00;
int error = 0x00;
int running = 0x01;
int writing = 0x01;
int instruction_needed = 0x01;
int heap_size = 0x00;
char* tapio = (char*) TAPIO_ADDRESS;
char* buffer;
heap_size = _heapmaxavail();
if ( heap_size > TAPIO_MAX_SIZE ) { // No need to malloc more than
heap_size = TAPIO_MAX_SIZE; // the interface allows
}
buffer = malloc ( heap_size );
memset ( buffer, 0x00, heap_size );
if ( buffer == 0x00 ) {
puts ("Memory full.");
running = 0;
}
tapio[0] = 0x00; // Check tape interface memory
if ( tapio[0] != 0x00 )
error = 1;
tapio[0] = 0xFF;
if ( tapio[0] != 0xFF )
error = 1;
tapio[TAPIO_MAX_SIZE] = 0x00;
if ( tapio[TAPIO_MAX_SIZE] != 0x00 )
error = 1;
tapio[TAPIO_MAX_SIZE] = 0xFF;
if ( tapio[TAPIO_MAX_SIZE] != 0xFF )
error = 1;
if ( error ) {
printf ("\nNo memory at location %p, aborting.\n", tapio);
running = 0;
}
else {
memset ( tapio, 0, TAPIO_MAX_SIZE );
}
while ( running ) {
putchar ( '\r' );
for ( l = 0; l < 25; l++ ) {
putchar ( '\n' );
}
puts ("===================== Sym-1 Notepad ====================");
if ( instruction_needed ) {
puts ("Enter text and you can save it to tape for reloading");
puts ("later. There are four special 'command' characters:\n");
puts (" Control-S Save to tape");
puts (" Control-L Load from tape");
puts (" Control-C Clear memory");
puts (" Control-X Exit");
puts ("========================================================\n");
}
while ( writing ) {
c = getchar();
if ( c == 0x08 ) { // Backspace
if ( p > 0 ) {
buffer[p] = 0x00;
p--;
}
}
else if ( c == 0x13 ) { // Save
puts ("\n========================= Save =========================");
puts ("\nPress any key to save.");
c = getchar();
for ( l = 0; l <= p; l++ ) {
tapio[l] = buffer[l];
}
l++;
tapio[l] = 0x00;
puts ("Saving to tape.");
error = dumpt ( 'N', tapio, tapio+p );
if ( error ) {
puts ("\nTape error.");
}
else
{
putchar ( '\r' );
for ( l = 0; l < 25; l++ ) {
putchar ( '\n' );
}
}
puts ("===================== Sym-1 Notepad ====================\n");
for ( l = 0; l <= p; l++ ) {
putchar ( buffer[l] );
}
}
else if ( c == 0x0C ) { // Load
p = 0;
puts ("\nLoading from tape.");
memset ( buffer, 0, heap_size );
memset ( tapio, 0, TAPIO_MAX_SIZE );
error = loadt ( 'N' );
if ( error ) {
puts ("\nTape error.");
puts ("===================== Sym-1 Notepad ====================\n");
}
else
{
for ( l = 0; l <= heap_size; l++ ) {
buffer[l] = tapio[l];
}
p = strlen ( buffer );
putchar ( '\r' );
for ( l = 0; l < 25; l++ ) {
putchar ( '\n' );
}
puts ("===================== Sym-1 Notepad ====================\n");
for ( l = 0; l <= p; l++ ) {
putchar ( buffer[l] );
}
}
}
else if ( c == 0x03 ) { // Clear
p = 0;
memset ( buffer, 0, heap_size );
putchar ( '\r' );
for ( l = 0; l < 25; l++ ) {
putchar ( '\n' );
}
puts ("===================== Sym-1 Notepad ====================\n");
}
else if ( c == 0x18 ) { // Exit
writing = 0;
running = 0;
}
else {
if ( p >= heap_size - 1 ) {
puts ("\n========================= End =========================");
puts ("Buffer full.");
}
else {
if ( c == '\n' ) {
putchar ( '\n' );
}
buffer[p] = c;
}
p++;
}
}
}
free ( buffer );
puts ("\nEnjoy your day!\n");
return 0;
}

42
samples/sym1/symTiny.c Normal file
View File

@@ -0,0 +1,42 @@
// --------------------------------------------------------------------------
// Hello World for Sym-1
//
// Uses only getchar, putchar and puts, generating smaller code than printf
//
// Wayne Parham
//
// wayne@parhamdata.com
// --------------------------------------------------------------------------
#include <stdio.h>
#include <sym1.h>
int main (void) {
char c = 0x00;
int d = 0x00;
int l = 0x00;
puts ("Hello World!\n");
puts ("Type a line and press ENTER, please:\n");
for ( l = 0; l < 2; l++ ) {
beep();
for ( d = 0; d < 10 ; d++ ) {
}
}
while ( c != '\n' ) {
c = getchar();
}
puts ("\n\nThanks!\n");
for ( l = 0; l < 5; l++ ) {
beep();
for ( d = 0; d < 10 ; d++ ) {
}
}
return 0;
}

76
samples/terminal.c Normal file
View File

@@ -0,0 +1,76 @@
/*
** Minimalistic terminal program.
**
** Makes use of the serial drivers.
**
** 2022-12-23, Oliver Schmidt (ol.sc@web.de)
**
*/
#include <cc65.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <serial.h>
static void check (const char* msg, unsigned char err)
{
if (err == SER_ERR_OK) {
return;
}
printf ("%s:0x%02x\n", msg, err);
if (doesclrscrafterexit ()) {
cgetc ();
}
exit (1);
}
void main (void)
{
const struct ser_params par = {
SER_BAUD_9600,
SER_BITS_8,
SER_STOP_1,
SER_PAR_NONE,
SER_HS_HW
};
check ("ser_install", ser_install (ser_static_stddrv));
check ("ser_open", ser_open (&par));
atexit ((void (*)) ser_close);
printf ("Serial Port: 9600-8-1-N RTS/CTS\n"
"Simple Term: Press ESC for exit\n");
while (1)
{
char chr;
if (kbhit ())
{
chr = cgetc ();
if (chr == CH_ESC) {
putchar ('\n');
return;
}
if (ser_put (chr) == SER_ERR_OK) {
putchar (chr);
} else {
putchar ('\a');
}
}
if (ser_get (&chr) == SER_ERR_OK) {
putchar (chr);
}
}
}

View File

@@ -38,8 +38,9 @@ static unsigned AspectRatio;
static void CheckError (const char* S)
{
unsigned char Error = tgi_geterror ();
if (Error != TGI_ERR_OK) {
printf ("%s: %d\n", S, Error);
printf ("%s: %u\n", S, Error);
if (doesclrscrafterexit ()) {
cgetc ();
}
@@ -67,26 +68,27 @@ static void DoWarning (void)
static void DoCircles (void)
{
static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_ORANGE };
static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLUE };
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);
tgi_clear ();
tgi_line (0, 0, MaxX, MaxY);
tgi_line (0, MaxY, MaxX, 0);
while (!kbhit ()) {
tgi_setcolor (COLOR_FORE);
tgi_line (0, 0, MaxX, MaxY);
tgi_line (0, MaxY, MaxX, 0);
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));
}
Color = Color == COLOR_FORE ? COLOR_BACK : COLOR_FORE;
}
cgetc ();
tgi_clear ();
}
@@ -95,19 +97,19 @@ static void DoCheckerboard (void)
{
static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLACK };
unsigned X, Y;
unsigned char Color;
unsigned char Color = COLOR_BACK;
tgi_setpalette (Palette);
Color = COLOR_BACK;
tgi_clear ();
while (1) {
for (Y = 0; Y <= MaxY; Y += 10) {
for (X = 0; X <= MaxX; X += 10) {
Color = (Color == COLOR_FORE) ? COLOR_BACK : COLOR_FORE;
tgi_setcolor (Color);
tgi_bar (X, Y, X+9, Y+9);
Color = Color == COLOR_FORE ? COLOR_BACK : COLOR_FORE;
if (kbhit ()) {
cgetc ();
tgi_clear ();
return;
}
}
@@ -129,8 +131,9 @@ static void DoDiagram (void)
tgi_setpalette (Palette);
tgi_setcolor (COLOR_FORE);
tgi_clear ();
/* Determine zero and aplitude */
/* Determine zero and amplitude */
YOrigin = MaxY / 2;
XOrigin = 10;
Amp = (MaxY - 19) / 2;
@@ -158,7 +161,6 @@ static void DoDiagram (void)
}
cgetc ();
tgi_clear ();
}
@@ -167,19 +169,20 @@ 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 ();
tgi_clear ();
}
@@ -203,7 +206,6 @@ int main (void)
tgi_init ();
CheckError ("tgi_init");
tgi_clear ();
/* Get stuff from the driver */
MaxX = tgi_getmaxx ();

503
samples/tinyshell.c Normal file
View File

@@ -0,0 +1,503 @@
/*
** Simple ("tiny") shell to test filename and directory functions.
** Copyright (c) 2013,2016 Christian Groessler, chris@groessler.org
*/
#define VERSION_ASC "0.91"
#ifdef __ATARI__
#define UPPERCASE /* define (e.g. for Atari) to convert filenames etc. to upper case */
#define HAVE_SUBDIRS
#endif
#ifdef __APPLE2__
#define HAVE_SUBDIRS
#endif
#ifdef __CC65__
#define CHECK_SP
#endif
#define KEYB_BUFSZ 127
#define PROMPT ">>> "
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#ifndef __CC65__
#include <sys/stat.h>
#include <sys/param.h>
#define HAVE_SUBDIRS
#else
#define MAXPATHLEN 64
#endif
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#ifdef CHECK_SP
extern unsigned int getsp(void); /* comes from getsp.s */
#endif
#define CMD_NOTHING 0
#define CMD_INVALID 1
#define CMD_HELP 2
#define CMD_QUIT 3
#define CMD_LS 4
#define CMD_MKDIR 5
#define CMD_RMDIR 6
#define CMD_CHDIR 7
#define CMD_RM 8
#define CMD_RENAME 9
#define CMD_COPY 10
#define CMD_PWD 11
#define CMD_CLS 12
#define CMD_VERBOSE 13
#define CMD_EXEC 14
static unsigned char verbose;
static unsigned char terminate;
static unsigned char cmd;
static char *cmd_asc, *arg1, *arg2, *arg3, *args; /* 'args': everything after command */
static char keyb_buf[KEYB_BUFSZ + 1];
static char keyb_buf2[KEYB_BUFSZ + 1];
static size_t cpbuf_sz = 4096;
struct cmd_table {
char *name;
unsigned char code;
} cmd_table[] = {
{ "help", CMD_HELP },
{ "quit", CMD_QUIT },
{ "q", CMD_QUIT },
{ "exit", CMD_QUIT },
{ "ls", CMD_LS },
{ "dir", CMD_LS },
{ "md", CMD_MKDIR },
#ifdef HAVE_SUBDIRS
{ "mkdir", CMD_MKDIR },
{ "rd", CMD_RMDIR },
{ "rmdir", CMD_RMDIR },
{ "cd", CMD_CHDIR },
{ "chdir", CMD_CHDIR },
#endif
{ "rm", CMD_RM },
{ "del", CMD_RM },
{ "cp", CMD_COPY },
{ "copy", CMD_COPY },
{ "mv", CMD_RENAME },
{ "ren", CMD_RENAME },
{ "pwd", CMD_PWD },
{ "exec", CMD_EXEC },
#ifdef __ATARI__
{ "cls", CMD_CLS },
#endif
{ "verbose", CMD_VERBOSE },
{ NULL, 0 }
};
static void banner(void)
{
puts("\"tiny\" command line shell, v" VERSION_ASC);
puts("written by chris@groessler.org");
puts("type 'help' for help\n");
}
static void get_command(void)
{
unsigned char i = 0;
#ifdef CHECK_SP
static char firstcall = 1;
static unsigned int good_sp;
unsigned int sp;
if (firstcall)
sp = good_sp = getsp();
else
sp = getsp();
if (sp != good_sp) {
printf("SP: 0x%04X ***MISMATCH*** 0x%04X\n", sp, good_sp);
}
else if (verbose)
printf("SP: 0x%04X\n", sp);
#endif
arg1 = arg2 = arg3 = NULL;
/* issue prompt */
printf(PROMPT);
/* get input from the user */
if (! fgets(keyb_buf, KEYB_BUFSZ, stdin)) {
puts("");
cmd = CMD_QUIT;
return;
}
/* put everything after first string into 'args' */
strcpy(keyb_buf2, keyb_buf); /* use a backup copy for 'args' */
/* skip over the first non-whitespace item */
cmd_asc = strtok(keyb_buf2, " \t\n");
if (cmd_asc)
args = strtok(NULL, ""); /* get everything */
else
*args = 0; /* no arguments */
/* split input into cmd, arg1, arg2, arg3 */
/* get and parse command */
cmd_asc = strtok(keyb_buf, " \t\n");
if (! cmd_asc) {
cmd = CMD_NOTHING;
return;
}
cmd = CMD_INVALID;
while (cmd_table[i].name) {
if (! strcmp(cmd_table[i].name, cmd_asc)) {
cmd = cmd_table[i].code;
break;
}
i++;
}
/* get arguments */
arg1 = strtok(NULL, " \t\n");
if (! arg1)
return;
arg2 = strtok(NULL, " \t\n");
if (! arg2)
return;
arg3 = strtok(NULL, " \t\n");
}
static void cmd_help(void)
{
puts("quit, exit - exit shell");
puts("ls, dir - display current directory");
puts(" and drive contents");
puts("rm, del - delete file");
puts("cp, copy - copy file");
puts("mv, ren - rename file");
puts("cd, chdir - change directory or drive");
puts("md, mkdir - make directory or drive");
puts("rd, rmdir - remove directory or drive");
puts("exec - run program");
#ifdef __ATARI__
puts("cls - clear screen");
#endif
puts("verbose - set verbosity level");
}
static void cmd_ls(void)
{
DIR *dir;
char *arg;
struct dirent *dirent;
#ifdef __ATARI__
char need_free = 0;
#endif
if (arg2) {
puts("usage: ls [dir]");
return;
}
/* print directory listing */
if (arg1) {
#ifdef UPPERCASE
strupr(arg1);
#endif
#ifdef __ATARI__
/* not sure if this shouldn't be done by the runtime lib */
if (*(arg1 + strlen(arg1) - 1) == ':' || *(arg1 + strlen(arg1) - 1) == '>') {
arg = malloc(strlen(arg1) + 4);
if (! arg) {
printf("malloc failed: %s", strerror(errno));
return;
}
need_free = 1;
memcpy(arg, arg1, strlen(arg1) + 1);
strcat(arg, "*.*");
}
else
#endif
arg = arg1;
}
else
arg = ".";
if (verbose)
printf("Buffer addr: %p\n", arg);
dir = opendir(arg);
#ifdef __ATARI__
if (need_free) free(arg);
#endif
if (! dir) {
puts("opendir failed");
return;
}
while (dirent = readdir(dir))
puts(dirent->d_name);
closedir(dir);
}
static void cmd_rm(void)
{
if (!arg1 || arg2) {
puts("usage: rm <file>");
return;
}
#ifdef UPPERCASE
strupr(arg1);
#endif
if (unlink(arg1))
printf("remove failed: %s\n", strerror(errno));
}
#ifdef HAVE_SUBDIRS
static void cmd_mkdir(void)
{
if (!arg1 || arg2) {
puts("usage: mkdir <dir>");
return;
}
#ifdef UPPERCASE
strupr(arg1);
#endif
if (mkdir(arg1, 0777))
printf("mkdir failed: %s\n", strerror(errno));
}
static void cmd_rmdir(void)
{
if (!arg1 || arg2) {
puts("usage: rmdir <dir>");
return;
}
#ifdef UPPERCASE
strupr(arg1);
#endif
if (rmdir(arg1))
printf("rmdir failed: %s\n", strerror(errno));
}
static void cmd_chdir(void)
{
if (!arg1 || arg2) {
puts("usage: cddir <dir>");
return;
}
#ifdef UPPERCASE
strupr(arg1);
#endif
if (chdir(arg1))
printf("chdir failed: %s\n", strerror(errno));
}
static void cmd_pwd(void)
{
char *buf;
if (arg1) {
puts("usage: pwd");
return;
}
buf = malloc(MAXPATHLEN);
if (! buf) {
printf("malloc %u bytes failed: %s\n", MAXPATHLEN, strerror(errno));
return;
}
if (verbose)
printf("Buffer addr: %p\n", buf);
if (!getcwd(buf, MAXPATHLEN)) {
printf("getcwd failed: %s\n", strerror(errno));
free(buf);
return;
}
puts(buf);
free(buf);
}
#endif /* #ifdef HAVE_SUBDIRS */
static void cmd_rename(void)
{
if (!arg2 || arg3) {
puts("usage: mv <oldname> <newname>");
return;
}
#ifdef UPPERCASE
strupr(arg1);
strupr(arg2);
#endif
if (rename(arg1, arg2))
printf("rename failed: %s\n", strerror(errno));
}
static void cmd_exec(void)
{
char *progname, *arguments;
progname = strtok(args, " \t\n");
if (! progname) {
puts("usage: exec <progname> [arguments]");
return;
}
arguments = strtok(NULL, "");
/*printf("exec: %s %s\n", progname, arguments ? arguments : "");*/
(void)exec(progname, arguments);
printf("exec error: %s\n", strerror(errno));
}
static void cmd_copy(void)
{
int srcfd = -1, dstfd = -1;
char *buf;
int readsz, writesz;
if (!arg2 || arg3) {
puts("usage: cp <src> <dest>");
return;
}
#ifdef UPPERCASE
strupr(arg1);
strupr(arg2);
#endif
buf = malloc(cpbuf_sz);
if (! buf) {
printf("malloc %u bytes failed: %s\n", cpbuf_sz, strerror(errno));
return;
}
if (verbose)
printf("Buffer addr: %p\n", buf);
while (1) {
if (srcfd == -1) {
srcfd = open(arg1, O_RDONLY);
if (srcfd < 0) {
printf("open(%s) failed: %s\n", arg1, strerror(errno));
break;
}
}
readsz = read(srcfd, buf, cpbuf_sz);
if (readsz < 0) {
printf("read error: %s\n", strerror(errno));
break;
}
if (! readsz)
break;
if (dstfd == -1) {
dstfd = open(arg2, O_WRONLY | O_CREAT | O_TRUNC, 0777);
if (dstfd < 0) {
printf("open(%s) failed: %s\n", arg2, strerror(errno));
break;
}
}
writesz = write(dstfd, buf, readsz);
if (writesz < 0 || writesz != readsz) {
printf("write error: %s\n", strerror(errno));
break;
}
if (readsz != cpbuf_sz)
break;
}
free(buf);
if (srcfd >= 0) close(srcfd);
if (dstfd >= 0) close(dstfd);
}
#ifdef __ATARI__
static void cmd_cls(void)
{
printf("\f");
}
#endif
static void cmd_verbose(void)
{
unsigned long verb;
char *endptr;
if (!arg1 || arg2) {
puts("usage: verbose <level>");
return;
}
verb = strtoul(arg1, &endptr, 10);
if (verb > 255 || *endptr) {
puts("invalid verbosity level");
return;
}
verbose = verb;
printf("verbosity level set to %d\n", verbose);
}
static void run_command(void)
{
switch (cmd) {
default: puts("internal error"); return;
case CMD_NOTHING: return;
case CMD_INVALID: puts("invalid command"); return;
case CMD_HELP: cmd_help(); return;
case CMD_QUIT: terminate = 1; return;
case CMD_LS: cmd_ls(); return;
case CMD_RM: cmd_rm(); return;
#ifdef HAVE_SUBDIRS
case CMD_CHDIR: cmd_chdir(); return;
case CMD_MKDIR: cmd_mkdir(); return;
case CMD_RMDIR: cmd_rmdir(); return;
case CMD_PWD: cmd_pwd(); return;
#endif
case CMD_EXEC: cmd_exec(); return;
case CMD_RENAME: cmd_rename(); return;
case CMD_COPY: cmd_copy(); return;
#ifdef __ATARI__
case CMD_CLS: cmd_cls(); return;
#endif
case CMD_VERBOSE: cmd_verbose(); return;
}
}
int main(void)
{
banner();
while (! terminate) {
get_command();
run_command();
}
return 0;
}
/* Local Variables: */
/* c-file-style: "cpg" */
/* c-basic-offset: 4 */
/* End: */

95
samples/tutorial/Makefile Normal file
View File

@@ -0,0 +1,95 @@
# Run 'make SYS=<target>'; or, set a SYS env.
# var. to build for another target system.
SYS ?= c64
# Just the usual way to find out if we're
# using cmd.exe to execute make rules.
ifneq ($(shell echo),)
CMD_EXE = 1
endif
ifdef CMD_EXE
NULLDEV = nul:
DEL = -del /f
RMDIR = rmdir /s /q
else
NULLDEV = /dev/null
DEL = $(RM)
RMDIR = $(RM) -r
endif
ifdef CC65_HOME
AS = $(CC65_HOME)/bin/ca65
CC = $(CC65_HOME)/bin/cc65
CL = $(CC65_HOME)/bin/cl65
LD = $(CC65_HOME)/bin/ld65
else
AS := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
CC := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65)
CL := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
LD := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
endif
EXELIST_atari2600 = \
notavailable
EXELIST_atari5200 = \
notavailable
EXELIST_bbc = \
notavailable
EXELIST_creativision = \
notavailable
EXELIST_gamate = \
notavailable
EXELIST_geos-cbm = \
notavailable
EXELIST_geos-apple = \
notavailable
EXELIST_lunix = \
notavailable
EXELIST_lynx = \
notavailable
EXELIST_nes = \
notavailable
EXELIST_osic1p = \
notavailable
EXELIST_pce = \
notavailable
EXELIST_supervision = \
notavailable
# Unlisted targets will try to build everything.
# That lets us learn what they cannot build, and what settings
# we need to use for programs that can be built and run.
ifndef EXELIST_$(SYS)
EXELIST_$(SYS) := ${patsubst %.c,%,$(wildcard *.c)}
endif
samples: $(EXELIST_$(SYS))
hello: hello.c text.s
$(CL) -t $(SYS) -o hello hello.c text.s
# empty target used to skip systems that will not work with any program in this dir
notavailable:
ifeq ($(MAKELEVEL),0)
@echo "info: tutorial sample not available for" $(SYS)
else
# suppress the "nothing to be done for 'samples' message
@echo > $(NULLDEV)
endif
clean:
@$(DEL) hello 2>$(NULLDEV)