Skip to content

Instantly share code, notes, and snippets.

@jimbob88
Created February 6, 2025 07:43
Show Gist options
  • Save jimbob88/ca4ee00fbceac137047e7e0113fa6089 to your computer and use it in GitHub Desktop.
Save jimbob88/ca4ee00fbceac137047e7e0113fa6089 to your computer and use it in GitHub Desktop.
Draw a Christian cross in the centre of the screen on C64

Create a Christian Cross on C64

vice-screen-2025020607431083

Compilation

$ gmake disk
#include <cc65.h>
#include <conio.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <tgi.h>
#define COLOR_BACK TGI_COLOR_BLACK
#define COLOR_FORE TGI_COLOR_WHITE
static unsigned MaxX;
static unsigned MaxY;
static unsigned AspectRatio;
/**
* Checks for a tgi error, failing if one occurred.
*
* @param where Prints "{where}: {error message}"
*/
static void AssertNoError(const char *where) {
unsigned char Error = tgi_geterror();
if (Error != TGI_ERR_OK) {
printf("%s: %u\n", where, Error);
if (doesclrscrafterexit()) {
cgetc();
}
exit(EXIT_FAILURE);
}
}
/** Warn the user that the dynamic TGI driver is needed for this program */
static void DoWarning(void) {
printf("Warning: This program needs the TGI\n"
"driver on disk! Press 'y' if you have\n"
"it - any other key exits.\n");
if (tolower(cgetc()) != 'y') {
exit(EXIT_SUCCESS);
}
printf("OK. Please wait patiently...\n");
}
static void DoCross(void) {
static const unsigned char Palette[2] = {TGI_COLOR_WHITE, TGI_COLOR_BLUE};
unsigned char Color = COLOR_BACK;
const unsigned CentreX = MaxX / 2;
const unsigned CentreY = MaxY / 2;
const unsigned VerticalHeight =
(unsigned)MaxY * 6 / 10; // Taller vertical beam
const unsigned HorizontalWidth =
(unsigned)MaxX * 3 / 10; // Shorter horizontal beam
const unsigned BarThickness = 10; // Thickness of the bars
const unsigned VerticalBarStartX = CentreX - (BarThickness / 2);
const unsigned VerticalBarStartY = CentreY - (VerticalHeight / 2);
const unsigned HorizontalBarStartX = CentreX - (HorizontalWidth / 2);
const unsigned HorizontalBarStartY =
VerticalBarStartY + (VerticalHeight / 4) - (BarThickness / 2);
tgi_setpalette(Palette);
tgi_setcolor(COLOR_FORE);
tgi_clear();
while (!kbhit()) {
tgi_bar(VerticalBarStartX, VerticalBarStartY,
VerticalBarStartX + BarThickness,
VerticalBarStartY + VerticalHeight);
tgi_bar(HorizontalBarStartX, HorizontalBarStartY,
HorizontalBarStartX + HorizontalWidth,
HorizontalBarStartY + BarThickness);
}
cgetc();
}
int main(void) {
unsigned char Border;
// Requires dynamically-loadable tgi
DoWarning();
tgi_load_driver(tgi_stddrv);
AssertNoError("tgi_load_driver");
tgi_init();
AssertNoError("tgi_init");
Border = bordercolor(COLOR_BLACK);
MaxX = tgi_getmaxx();
MaxY = tgi_getmaxy();
AspectRatio = tgi_getaspectratio();
DoCross();
/* Clean-up */
(void)bordercolor(Border);
tgi_unload();
printf("Done\n");
return EXIT_SUCCESS;
}
# Stripped version of cc65/samples/Makefile for simple tgi project
SYS = c64
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
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
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))))
# Requires VICE Emulator
C1541 ?= c1541
endif
DISK_c64 = samples.d64
.PHONY: mostlyclean clean platforms samples clean disk
%: %.c
%: %.s
.c.o:
$(CC) $(CFLAGS) -Ors --codesize 500 -T -g -t $(SYS) $<
$(AS) $(<:.c=.s)
.s.o:
$(AS) $(ASFLAGS) -t $(SYS) $<
.PRECIOUS: %.o
.o:
ifeq ($(SYS),vic20)
$(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -C vic20-32k.cfg -m $@.map $^ $(SYS).lib
else
$(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -t $(SYS) -m $@.map $^ $(SYS).lib
endif
# --------------------------------------------------------------------------
# Lists of subdirectories
DIRLIST =
define SUBDIR_recipe
@+$(MAKE) -C $(dir) --no-print-directory $@
endef # SUBDIR_recipe
# --------------------------------------------------------------------------
# Lists of executables
EXELIST_c64 = \
draw_cross_tgi
# --------------------------------------------------------------------------
# Rules to make the binaries and the disk
samples: $(EXELIST_$(SYS))
$(foreach dir,$(DIRLIST),$(SUBDIR_recipe))
disk: $(DISK_$(SYS))
# --------------------------------------------------------------------------
# List of every supported platform
TARGETS := \
c64
# --------------------------------------------------------------------------
# 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))
# --------------------------------------------------------------------------
# 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-up rules
ifdef CMD_EXE
NULLDEV = nul:
DEL = -del /f
RMDIR = rmdir /s /q
else
NULLDEV = /dev/null
DEL = $(RM)
RMDIR = $(RM) -r
endif
mostlyclean:
@$(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))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment