Moved to new home

The Apple 2 project now lives with the Commander X16 and other versions.
This commit is contained in:
Stefan Wessels 2023-11-01 01:08:48 -07:00
parent d657a819cc
commit 64e9ebb2a9
28 changed files with 4 additions and 11083 deletions

24
LICENSE
View File

@ -1,24 +0,0 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org>

354
Makefile
View File

@ -1,354 +0,0 @@
###############################################################################
### Generic Makefile for cc65 projects - full version with abstract options ###
### V1.3.0(w) 2010 - 2013 Oliver Schmidt & Patryk "Silver Dream !" Łogiewa ###
###############################################################################
###############################################################################
### In order to override defaults - values can be assigned to the variables ###
###############################################################################
# Space or comma separated list of cc65 supported target platforms to build for.
# Default: c64 (lowercase!)
TARGETS := apple2
# Name of the final, single-file executable.
# Default: name of the current dir with target name appended
PROGRAM :=
# Path(s) to additional libraries required for linking the program
# Use only if you don't want to place copies of the libraries in SRCDIR
# Default: none
LIBS :=
# Custom linker configuration file
# Use only if you don't want to place it in SRCDIR
# Default: none
CONFIG :=
# Additional C assembler flags and options.
# Default: none
CFLAGS =
# Additional assembler flags and options.
# Default: none
ASFLAGS = --debug-info --listing $@.lst
# Additional linker flags and options.
# Default: none
LDFLAGS = -vm -m $@.map -Ln $@.vice
# Path to the directory containing C and ASM sources.
# Default: src
SRCDIR :=
# Path to the directory where object files are to be stored (inside respective target subdirectories).
# Default: obj
OBJDIR :=
# Command used to run the emulator.
# Default: depending on target platform. For default (c64) target: x64 -kernal kernal -VICIIdsize -autoload
EMUCMD :=
# Optional commands used before starting the emulation process, and after finishing it.
# Default: none
#PREEMUCMD := osascript -e "tell application \"System Events\" to set isRunning to (name of processes) contains \"X11.bin\"" -e "if isRunning is true then tell application \"X11\" to activate"
#PREEMUCMD := osascript -e "tell application \"X11\" to activate"
#POSTEMUCMD := osascript -e "tell application \"System Events\" to tell process \"X11\" to set visible to false"
#POSTEMUCMD := osascript -e "tell application \"Terminal\" to activate"
PREEMUCMD :=
POSTEMUCMD :=
# On Windows machines VICE emulators may not be available in the PATH by default.
# In such case, please set the variable below to point to directory containing
# VICE emulators.
ifeq ($(OS),Windows_NT)
VICE_HOME :=
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
VICE_HOME := /Applications/Vice/x64.app/Contents/MacOS/
endif
endif
# Options state file name. You should not need to change this, but for those
# rare cases when you feel you really need to name it differently - here you are
STATEFILE := Makefile.options
###################################################################################
#### DO NOT EDIT BELOW THIS LINE, UNLESS YOU REALLY KNOW WHAT YOU ARE DOING! ####
###################################################################################
###################################################################################
### Mapping abstract options to the actual assembler, assembler and linker flags ###
### Predefined assembler, assembler and linker flags, used with abstract options ###
### valid for 2.14.x. Consult the documentation of your cc65 version before use ###
###################################################################################
# assembler flags used to tell the assembler to optimise for SPEED
define _optspeed_
CFLAGS += -Oris
endef
# assembler flags used to tell the assembler to optimise for SIZE
define _optsize_
CFLAGS += -Or
endef
# assembler and assembler flags for generating listings
define _listing_
CFLAGS += --listing $$(@:.o=.lst)
ASFLAGS += --listing $$(@:.o=.lst)
REMOVES += $(addsuffix .lst,$(basename $(OBJECTS)))
endef
# Linker flags for generating map file
define _mapfile_
LDFLAGS += --mapfile $$@.map
REMOVES += $(PROGRAM).map
endef
# Linker flags for generating VICE label file
define _labelfile_
LDFLAGS += -Ln $$@.lbl
REMOVES += $(PROGRAM).lbl
endef
# Linker flags for generating a debug file
define _debugfile_
LDFLAGS += -Wl --dbgfile,$$@.dbg
REMOVES += $(PROGRAM).dbg
endef
###############################################################################
### Defaults to be used if nothing defined in the editable sections above ###
###############################################################################
# Presume the C64 target like the cl65 compile & link utility does.
# Set TARGETS to override.
ifeq ($(TARGETS),)
TARGETS := c64
endif
# Presume we're in a project directory so name the program like the current
# directory. Set PROGRAM to override.
ifeq ($(PROGRAM),)
PROGRAM := $(notdir $(CURDIR))
endif
# Presume the C and asm source files to be located in the subdirectory 'src'.
# Set SRCDIR to override.
ifeq ($(SRCDIR),)
SRCDIR := src
endif
# Presume the object and dependency files to be located in the subdirectory
# 'obj' (which will be created). Set OBJDIR to override.
ifeq ($(OBJDIR),)
OBJDIR := obj
endif
TARGETOBJDIR := $(OBJDIR)/$(TARGETS)
# On Windows it is mandatory to have CC65_HOME set. So do not unnecessarily
# rely on cl65 being added to the PATH in this scenario.
ifdef CC65_HOME
CC := $(CC65_HOME)/bin/cl65
else
CC := cl65
endif
# Default emulator commands and options for particular targets.
# Set EMUCMD to override.
cx16_EMUCMD := $(VICE_HOME)x16emu -run -prg
c64_EMUCMD := $(VICE_HOME)x64 -kernal kernal -VICIIdsize -autostart
c128_EMUCMD := $(VICE_HOME)x128 -kernal kernal -VICIIdsize -autoload
vic20_EMUCMD := $(VICE_HOME)xvic -kernal kernal -VICdsize -autoload
pet_EMUCMD := $(VICE_HOME)xpet -Crtcdsize -autoload
plus4_EMUCMD := $(VICE_HOME)xplus4 -TEDdsize -autoload
apple2_EMUCMD := test.bat
# So far there is no x16 emulator in VICE (why??) so we have to use xplus4 with -memsize option
c16_EMUCMD := $(VICE_HOME)xplus4 -ramsize 16 -TEDdsize -autoload
cbm510_EMUCMD := $(VICE_HOME)xcbm2 -model 510 -VICIIdsize -autoload
cbm610_EMUCMD := $(VICE_HOME)xcbm2 -model 610 -Crtcdsize -autoload
atari_EMUCMD := atari800 -windowed -xl -pal -nopatchall -run
ifeq ($(EMUCMD),)
EMUCMD = $($(CC65TARGET)_EMUCMD)
endif
###############################################################################
### The magic begins ###
###############################################################################
# The "Native Win32" GNU Make contains quite some workarounds to get along with
# cmd.exe as shell. However it does not provide means to determine that it does
# actually activate those workarounds. Especially does $(SHELL) NOT contain the
# value 'cmd.exe'. So the usual way to determine if cmd.exe is being used is to
# execute the command 'echo' without any parameters. Only cmd.exe will return a
# non-empy string - saying 'ECHO is on/off'.
#
# Many "Native Win32" programs accept '/' as directory delimiter just fine. How-
# ever the internal commands of cmd.exe generally require '\' to be used.
#
# cmd.exe has an internal command 'mkdir' that doesn't understand nor require a
# '-p' to create parent directories as needed.
#
# cmd.exe has an internal command 'del' that reports a syntax error if executed
# without any file so make sure to call it only if there's an actual argument.
ifeq ($(shell echo),)
MKDIR = mkdir -p $1
RMDIR = rmdir $1
RMFILES = $(RM) $1
else
MKDIR = mkdir $(subst /,\,$1)
RMDIR = rmdir $(subst /,\,$1)
RMFILES = $(if $1,del /f $(subst /,\,$1))
endif
COMMA := ,
SPACE := $(N/A) $(N/A)
define NEWLINE
endef
# Note: Do not remove any of the two empty lines above !
TARGETLIST := $(subst $(COMMA),$(SPACE),$(TARGETS))
ifeq ($(words $(TARGETLIST)),1)
# Set PROGRAM to something like 'myprog.c64'.
override PROGRAM := $(PROGRAM).$(TARGETLIST)
# Set SOURCES to something like 'src/foo.c src/bar.s'.
# Use of assembler files with names ending differently than .s is deprecated!
SOURCES := $(wildcard $(SRCDIR)/*.c)
SOURCES += $(wildcard $(SRCDIR)/*.s)
SOURCES += $(wildcard $(SRCDIR)/*.asm)
SOURCES += $(wildcard $(SRCDIR)/*.a65)
# Add to SOURCES something like 'src/c64/me.c src/c64/too.s'.
# Use of assembler files with names ending differently than .s is deprecated!
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.c)
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.s)
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.asm)
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.a65)
# Set OBJECTS to something like 'obj/c64/foo.o obj/c64/bar.o'.
OBJECTS := $(addsuffix .o,$(basename $(addprefix $(TARGETOBJDIR)/,$(notdir $(SOURCES)))))
# Set DEPENDS to something like 'obj/c64/foo.d obj/c64/bar.d'.
DEPENDS := $(OBJECTS:.o=.d)
# Add to LIBS something like 'src/foo.lib src/c64/bar.lib'.
LIBS += $(wildcard $(SRCDIR)/*.lib)
LIBS += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.lib)
# Add to CONFIG something like 'src/c64/bar.cfg src/foo.cfg'.
CONFIG += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.cfg)
CONFIG += $(wildcard $(SRCDIR)/*.cfg)
# Select CONFIG file to use. Target specific configs have higher priority.
ifneq ($(word 2,$(CONFIG)),)
CONFIG := $(firstword $(CONFIG))
$(info Using config file $(CONFIG) for linking)
endif
.SUFFIXES:
.PHONY: all test clean zap love
all: $(PROGRAM)
-include $(DEPENDS)
-include $(STATEFILE)
# If OPTIONS are given on the command line then save them to STATEFILE
# if (and only if) they have actually changed. But if OPTIONS are not
# given on the command line then load them from STATEFILE. Have object
# files depend on STATEFILE only if it actually exists.
ifeq ($(origin OPTIONS),command line)
ifneq ($(OPTIONS),$(_OPTIONS_))
ifeq ($(OPTIONS),)
$(info Removing OPTIONS)
$(shell $(RM) $(STATEFILE))
$(eval $(STATEFILE):)
else
$(info Saving OPTIONS=$(OPTIONS))
$(shell echo _OPTIONS_=$(OPTIONS) > $(STATEFILE))
endif
$(eval $(OBJECTS): $(STATEFILE))
endif
else
ifeq ($(origin _OPTIONS_),file)
$(info Using saved OPTIONS=$(_OPTIONS_))
OPTIONS = $(_OPTIONS_)
$(eval $(OBJECTS): $(STATEFILE))
endif
endif
# Transform the abstract OPTIONS to the actual cc65 options.
$(foreach o,$(subst $(COMMA),$(SPACE),$(OPTIONS)),$(eval $(_$o_)))
# Strip potential variant suffix from the actual cc65 target.
CC65TARGET := $(firstword $(subst .,$(SPACE),$(TARGETLIST)))
# The remaining targets.
$(TARGETOBJDIR):
$(call MKDIR,$@)
vpath %.c $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
$(TARGETOBJDIR)/%.o: %.c | $(TARGETOBJDIR)
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(CFLAGS) -o $@ $<
vpath %.s $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
$(TARGETOBJDIR)/%.o: %.s | $(TARGETOBJDIR)
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
vpath %.asm $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
$(TARGETOBJDIR)/%.o: %.asm | $(TARGETOBJDIR)
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
vpath %.a65 $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
$(TARGETOBJDIR)/%.o: %.a65 | $(TARGETOBJDIR)
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
$(PROGRAM): $(CONFIG) $(OBJECTS) $(LIBS)
$(CC) -t $(CC65TARGET) $(LDFLAGS) -o $@ $(patsubst %.cfg,-C %.cfg,$^)
test: $(PROGRAM)
$(PREEMUCMD)
$(EMUCMD) $(notdir $(<))
$(POSTEMUCMD)
clean:
$(call RMFILES,$(OBJECTS))
$(call RMFILES,$(DEPENDS))
$(call RMFILES,$(REMOVES))
$(call RMFILES,$(PROGRAM))
else # $(words $(TARGETLIST)),1
all test clean:
$(foreach t,$(TARGETLIST),$(MAKE) TARGETS=$t $@$(NEWLINE))
endif # $(words $(TARGETLIST)),1
OBJDIRLIST := $(wildcard $(OBJDIR)/*)
zap:
$(foreach o,$(OBJDIRLIST),-$(call RMFILES,$o/*.o $o/*.d $o/*.lst)$(NEWLINE))
$(foreach o,$(OBJDIRLIST),-$(call RMDIR,$o)$(NEWLINE))
-$(call RMDIR,$(OBJDIR))
-$(call RMFILES,$(basename $(PROGRAM)).* $(STATEFILE))
love:
@echo "Not war, eh?"
###################################################################
### Place your additional targets in the additional Makefiles ###
### in the same directory - their names have to end with ".mk"! ###
###################################################################
-include *.mk

View File

@ -1,21 +0,0 @@
DSK = Penetrator.dsk
# For this one, see https://applecommander.github.io/
AC ?= ac.jar
# Unix or Windows
ifeq ($(shell echo),)
CP = cp $1
else
CP = copy $(subst /,\,$1)
endif
REMOVES += $(DSK)
.PHONY: dsk
dsk: $(DSK)
$(DSK): penetrator-apple2.apple2.loader penetrator-apple2.apple2
$(call CP, apple2/template.dsk $@)
java -jar $(AC) -p $@ penetrat.system sys < penetrator-apple2.apple2.loader
java -jar $(AC) -as $@ penetrat bin < penetrator-apple2.apple2

175
README.md
View File

@ -1,174 +1,7 @@
# penetrator
Remake of the ZX Spectrum game for the Apple II.
1. INTRODUCTION
This is a "port" of the Commander X16 version that's also in my repo's as just
penetrator. I had to rewrite quite a bit of the drawing code and make some
other changes to make it work on the Apple II, and to make it fast enough.
This is also my very first program for the Apple II. It was a learning
experience :)
2. CURRENT STATUS
The game is a pretty good replica of the original. It is missing the demo
attract mode, and the fireworks.
Video https://youtu.be/fVms0nNVDtY and here's Oliver Schmidt's son, Pascal,
playing the game on real hardware: https://www.youtube.com/watch?v=rXC2JKuN594
There's also a pre-built Apple II disk of the project, Penetrator.dsk under the
releases tab. This can be played directly in emulators.
3. TECHNICAL DETAILS
The game is written in 6502 assembly using the ca65 assembler.
Below is a CPU cycle profile of 1 game frame in stage 4. It's a busy frame with
bullets, bombs and enemies. Most importantly, it has a busy terrain at the top
and bottom.
Hex | Dec | Frame % | Item
--- | --- | --- | ---
148F3 | 84211 | 100% | Total Frame
61F | 1567 | 2.0% | inputGame
0A | 10 | 0.0% | Misc
73 | 115 | 0.1% | gameWorldMove
05 | 5 | 0.0% | Misc
19 | 25 | 0.0% | gameCheckStage
08 | 8 | 0.0% | Misc
B80 | 2944 | 3.5% | gameAI
17 | 23 | 0.0% | Misc
7267 | 29287 | 34.8% | drawClearRows
6721 | 26401 | 31.4% | terrainDraw
38A8 | 14504 | 17.2% | drawEnemies
985 | 2437 | 2.9% | drawPlayer
581 | 1409 | 1.7% | drawBullets
6E3 | 1763 | 2.1% | drawBombs
E14 | 3604 | 4.3% | drawExplosions
06 | 6 | 0.0% | Misc
1A | 26 | 0.0% | drawPresent
11 | 17 | 0.0% | Misc
3C | 60 | 0.1% | Emulator error
Remake of the ZX Spectrum game for the Apple II.
As can be seen, clearing the area where the world will be drawn takes almost 35%
of the frame and drawing the terrain takes another 31% of the frame. The
Emulator Error are unaccounted for cycles -discrepency between total cycles at
the start and end, vs. the cycles reported in each step. I modifies the
emulator myself to do step reporting and I assume I must have missed someting.
4. KEYS and JOYSTICK
The Apple 2 gameplay works only with a joystick since you cannot detect multiple
keys down on the Apple II. The UI works with the keyboard or joystick and the
world editor uses both.
The joystick can also drive the menu's. Pressing right, for example, is
equivalent to pressing 1 (the UI menu options are selected through numbers).
The menus all show the keys to advance. There's also a help screen in the
editor.
5. THE FILES
I tried to comment all the code very thoroughly in the CX16 version. Since this
version is derived from that version, the code is also well documented, but to
be honest, the comments may not always be accurate. I did not do a pass to see
if they are accurate.
There are actually 2 programs in this. The 1st is the game, and it's in
src/apple2.
* audio.inc - Routines to make the speaker beep
* defs.inc - Constants and definitions used throughout
* draw.inc - HGR buffer drawing. drawSprite, for example
* edit.inc - The built-in world editor
* file.inc - Load and Save code
* fontdata.inc - A ZX Spectrum font in reverse 8x8 - Apple II format
* game.inc - The in-game logic, AI etc. The bulk of the "game"
* input.inc - User controls for game and editor
* logo.hgr - 8Kb splash screen in HGR format
* logo.inc - File that simply does an incbin on logo.hgr
* logodata.inc - Line data for writing Penetrator and logo image data
* macros.inc - Print macros mostly
* penetrator.asm - Where the game starts, initial setup, etc.
* penetrator.cfg - ca65 configuration file
* rodata.inc - Read-only data such as lookup tables, sprites etc.
* terrain.inc - The terrain drawing routines
* text.inc - In game text and print functions
* trndata.inc - The world data (triplet - top, bottom and enemy pos)
* ui.inc - User facing screens, name input, etc.
* variables.inc - All non zero page variables (stats, scores, draw buffers)
* zpvars.inc - The zero page variables (most variables)
The second is the ProDos loader that will auto-load the game. It's in the
src/apple2.loader folder. It has these files (all provided to me by Oliver
Schmidt)
* loader.cfg - ca65 configuration file
* loader.s - file to load and start the game
6. BUILDING THE GAME
Making the game has a few steps. Use make and the Makefile on all OSs, that
would be the easiest.
Start by making the loader - this needs to be done once only.
make TARGETS=apple2.loader
Next, make the game with:
make
The next step is to make a bootable disk image. For this, you will need 3rd
party software. I use AppleCommander. This software will put the loader and
game into the disk image. You will need to install Java to use AppleCommander.
The apple2/template.dsk is a "blank ProDos floppy" that has the loader and the
game placed on it by AppleCommander.
To make the disc image, set an environment variable to point at apple commander
(see notes) and then use the command:
make dsk
This will make a disc named Penetrator.dsk which can be loaded up in an
emulator.
If you want to edit the code and get into some iterative development/testing,
you can edit the Makefile and fill in the commands commands neccesary to launch
an emulator as well. Look for apple2_EMUCMD and set that as neccesary. The
simplest is to call test.sh or test.bat and fill in a complete command in the
batch file or shell script. However you choose to do this, once done, you can
do everything with the command:
make dsk test
NOTES:
1) Find AppleCommander here (I used Version 1.5.0):
https://github.com/AppleCommander/AppleCommander/releases
2) Set the environment variable (or change the Makefile-dsk.md) to point at the
apple commander jar file. Here's how it's done for different shell's:
Powershell:
$env:AC = "path to apple commander.jar"
cmd.exe
set AC="path to apple commander.jar"
bash (Unix or MacOS terminal):
export AC="path to apple commander.jar"
7. CREDITS
* Phillip Mitchell and Beam Software for creating and publishing the game in
1982.
* A special call-out to Oliver Schmidt who provided me with invaluable
assistance to get me going on the Apple II.
* Everyone involved in the Apple II projects (AppleWin | AppleCommander).
* Everyone involved in making the cc65 tools, it's very good.
8. CONTACT
Feel free to contact me at swessels@email.com if you have thoughts or
suggestions.
Thank you
Stefan Wessels
16 December 2019 - Initial Revision
This project has moved to my original penetrator remake on GitHub. There are a few other versions consolidated in there now as well.
[penetrator for apple 2's new home](https://github.com/StewBC/penetrator)

Binary file not shown.

View File

@ -1,14 +0,0 @@
#################################################################################
# #
# LOADER.SYSTEM - an Apple][ ProDOS 8 loader for cc65 programs (Oliver Schmidt) #
# #
#################################################################################
MEMORY {
LOADER: start = $2000, size = $0200, file = %O;
}
SEGMENTS {
CODE: load = LOADER, type = ro;
DATA: load = LOADER, type = rw;
}

View File

@ -1,179 +0,0 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; LOADER.SYSTEM - an Apple][ ProDOS 8 loader for cc65 programs (Oliver Schmidt) ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
A1L := $3C
A1H := $3D
PATHNAME := $0280
MLI := $BF00
TXTCLR := $C050 ; Display graphics
TXTSET := $C051 ; Display text
MIXCLR := $C052 ; Disable 4 lines of text
LOWSCR := $C054 ; Page 1
HISCR := $C055 ; Page 2
HIRES := $C057 ; Hires graphics
VERSION := $FBB3
RDKEY := $FD0C
PRBYTE := $FDDA
COUT := $FDED
QUIT_CALL = $65
OPEN_CALL = $C8
READ_CALL = $CA
CLOSE_CALL = $CC
FILE_NOT_FOUND_ERR = $46
; ------------------------------------------------------------------------
.data
OPEN_PARAM:
.byte $03 ;PARAM_COUNT
.addr PATHNAME ;PATHNAME
.addr $4000 - $0400 ;IO_BUFFER
OPEN_REF: .byte $00 ;REF_NUM
READ_PARAM:
.byte $04 ;PARAM_COUNT
READ_REF: .byte $00 ;REF_NUM
.addr $4000 ;DATA_BUFFER
.word $FFFF ;REQUEST_COUNT
.word $0000 ;TRANS_COUNT
CLOSE_PARAM:
.byte $01 ;PARAM_COUNT
CLOSE_REF: .byte $00 ;REF_NUM
QUIT_PARAM:
.byte $04 ;PARAM_COUNT
.byte $00 ;QUIT_TYPE
.word $0000 ;RESERVED
.byte $00 ;RESERVED
.word $0000 ;RESERVED
LOADING:
.byte $0D
.asciiz "Loading "
ELLIPSES:
.byte " ...", $0D, $0D, $00
FILE_NOT_FOUND:
.asciiz "... File Not Found"
ERROR_NUMBER:
.asciiz "... Error $"
PRESS_ANY_KEY:
.asciiz " - Press Any Key "
; ------------------------------------------------------------------------
.code
; Reset stack
ldx #$FF
txs
; Remove ".SYSTEM" from pathname
lda PATHNAME
sec
sbc #.strlen(".SYSTEM")
sta PATHNAME
; Add trailing '\0' to pathname
tax
lda #$00
sta PATHNAME+1,x
; Provide some user feedback
lda #<LOADING
ldx #>LOADING
jsr PRINT
lda #<(PATHNAME+1)
ldx #>(PATHNAME+1)
jsr PRINT
lda #<ELLIPSES
ldx #>ELLIPSES
jsr PRINT
jsr MLI
.byte OPEN_CALL
.word OPEN_PARAM
bcc :+
jmp ERROR
; Copy file reference number
: lda OPEN_REF
sta READ_REF
sta CLOSE_REF
; Turn off 80-column firmware
lda VERSION
cmp #$06 ; //e ?
bne :+
lda #$15
jsr $C300
; Switch to hires page 2
: bit TXTCLR
bit MIXCLR
bit HISCR
bit HIRES
jsr MLI
.byte READ_CALL
.word READ_PARAM
bcs ERROR
jsr MLI
.byte CLOSE_CALL
.word CLOSE_PARAM
bcs ERROR
; Go for it ...
jmp $6000
PRINT:
sta A1L
stx A1H
ldx VERSION
ldy #$00
: lda (A1L),y
beq :++
cpx #$06 ; //e ?
beq :+
cmp #$60 ; lowercase ?
bcc :+
and #$5F ; -> uppercase
: ora #$80
jsr COUT
iny
bne :-- ; Branch always
: rts
ERROR:
bit TXTSET
bit LOWSCR
cmp #FILE_NOT_FOUND_ERR
bne :+
lda #<FILE_NOT_FOUND
ldx #>FILE_NOT_FOUND
jsr PRINT
beq :++ ; Branch always
: pha
lda #<ERROR_NUMBER
ldx #>ERROR_NUMBER
jsr PRINT
pla
jsr PRBYTE
: lda #<PRESS_ANY_KEY
ldx #>PRESS_ANY_KEY
jsr PRINT
jsr RDKEY
jsr MLI
.byte QUIT_CALL
.word QUIT_PARAM

View File

@ -1,114 +0,0 @@
;-----------------------------------------------------------------------------
; audio.inc
; Part of penetrator, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
.segment "CODE"
;-----------------------------------------------------------------------------
.proc serviceAudio
lda audioMask ; get the active channels
and audioFrame ; see if any channel needs to play this frame
bne makeSounds ; make a sound if a channel needs audio
rts
makeSounds:
bit Bit7Mask ; AUDIO_EXPLOSION
bne bombDrop
bit Bit6Mask ; AUDIO_FIRE
bne fire
bit Bit5Mask ; AUDIO_EXPLOSION
bne explosion
bit Bit8432Mask ; AUDIO_ENGINE - Not that bit 8 is erroneusly checked
bne engine ; only because I didn't want to make a new constant
bit Bit1Mask ; AUDIO_UI_TICK
bne ui
rts
explosion:
ldy audioExplFrame ; use the frame as an index
lda explDelay, y
tax
ldy #$6
jsr playNote
inc audioExplFrame ; make sure off-screen ticks to end
lda audioExplFrame
cmp #%00000011
bcc :+
lda #AUDIO_MOTOR_PLAY
sta audioFrame ; turn off the explosion
:
rts
bombDrop:
ldy #$30
ldx #$10
jmp playNote
fire:
ldy #$20
ldx #$10
jmp playNote
engine:
bit Bit4Mask ; AUDIO_MOTOR_FWD
beq :+
ldy #$25
ldx #$08
jmp playNote
:
bit Bit3Mask ; AUDIO_MOTOR_REW
beq :+
ldy #$35
ldx #$08
jmp playNote
:
ldy #$30
ldx #$08
jmp playNote
ui:
ldy #$40
ldx #$08
jmp playNote
.endproc
;-----------------------------------------------------------------------------
.proc playNote
delay = tempBlock + 21
sty delay
loop:
lda SPEAKER
ldy delay
:
nop
nop
nop
nop
dey
bne :- ; hold for the duration in y
dex
bne loop ; retrigger
lda #AUDIO_EXPLOSION ; reset the audio frame (serviced)
and audioFrame ; but keep explosion if it was set
ora #AUDIO_MOTOR_PLAY ; and always add the MOTOR
sta audioFrame
rts
.endproc

View File

@ -1,124 +0,0 @@
;-----------------------------------------------------------------------------
; defs.inc
; Part of penetrator, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2019
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
; System locations
PATHNAME = $0280
ram_layer0 = $2000 ; HGR Pages
ram_layer1 = $4000
MLI = $BF00 ; ProDOS API
SPEAKER = $C030 ; Access to toggle the speaker
PADDL0 = $C064 ; Read to get POT
PTRIG = $C070 ; Reset PADDLE values
;-----------------------------------------------------------------------------
; MLI call type bytes
QUIT_CALL = $65
OPEN_CALL = $C8
READ_CALL = $CA
WRITE_CALL = $CB
CLOSE_CALL = $CC
CREATE_CALL = $C0
;-----------------------------------------------------------------------------
; self-modifying address marker
PLACEHOLDER = $FFFF
;-----------------------------------------------------------------------------
; modes
GAME_MODE_PLAY = $00
GAME_MODE_TRAIN = $01
GAME_MODE_EDIT = $02
BRUSH_TERRAIN = $00
BRUSH_ENEMIES = $01
;-----------------------------------------------------------------------------
; digital input constants
KEY_RIGHT = %00000001
KEY_LEFT = %00000010
KEY_DOWN = %00000100
KEY_UP = %00001000
KEY_START = %00010000
KEY_SELECT = %00100000
KEY_FIRE = %01000000
KEY_BOMB = %10000000
;-----------------------------------------------------------------------------
; game constants
XINSET = 4 ; By how many BYTE cols the display is offset into X
XSIZE = (80 - (4 * XINSET)) ; columns on screen (1 BYTE col = 2 game cols)
YSIZE = 192 ; lines on screen
WORLD_START = $08 ; top line where world is drawn
WORLD_END = $B3 ; last line where world is drawn
BUFLENGTH = $100 ; size for buffers that hold enemies
NUM_LIVES = 5 ; How many lives to start with
NUM_STAGES = 5
NUM_BOMBS = 2 ; How many bombs the player can drop
NUM_INFLIGHT = 3 ; How many missiles can be in-flight at once
NUM_SKIP_MONST = 4 ; How many rockets to skip before making one a monster
DANGER_FONT = 4 ; Number of font characters that make one filled column
DANGER_LENGTH = ((textEnd-1)-textDangerBar) ; how many characters in the danger column (skip trailing 0)
DANGER_TICKS = ((((worldDataEnd-worldDataStart) / 3) / DANGER_LENGTH) / DANGER_FONT)
; audio constants
AUDIO_BOMB_DROP = %01000000 ; Releasing a bomb
AUDIO_FIRE = %00100000 ; Firing the gun
AUDIO_EXPLOSION = %00010000 ; An enemy exploding
AUDIO_MOTOR_FWD = %00001000 ; Speeding up
AUDIO_MOTOR_REW = %00000100 ; slowing down
AUDIO_MOTOR_PLAY = %00000010 ; flying at a constant speed
AUDIO_UI_TICK = %00000001 ; UI selection
; The enemyBuffer is filled with these values, which break down as:
;
; Bits 1 & 2 - Type. 0 - monster, 1 - missile, 2 - radar & 3 - nuke
; Bits 3 & 4 - Column of sprite - Missile 2 wide, radar 4 wide, etc.
; Bits 5, 6 & 7 - Animation frame number, 0 - 7 (Radar has 8 frames)
; Bit 8 - 1 - Flying, 0 - on ground
;
; For monsters, Bits 5, 6 and 7 mean the following:
; Monster Bit 5 - Direction - 0 is up and 1 is down
; Monster Bit 6 & 7 - The delay counter while it is stopped. 0 - moving, <> 0 paused
;
; All 0 means empty, no enemy at that location
SPR_MONSTER0 = %10000000 ; enemy buffer mask MONSTER left
SPR_MONSTER1 = %10000100 ; enemy buffer mask MONSTER col 2
SPR_MONSTER2 = %10001000 ; enemy buffer mask MONSTER right
SPR_MISSILE0 = %00000001 ; enemy buffer mask missile left
SPR_MISSILE1 = %00000101 ; enemy buffer mask missile right
SPR_RADAR0 = %00000010 ; enemy buffer mask radar left
SPR_RADAR1 = %00000110 ; enemy buffer mask radar col 2
SPR_RADAR2 = %00001010 ; enemy buffer mask radar col 3
SPR_RADAR3 = %00001110 ; enemy buffer mask radar right
SPR_NUKE0 = %00000011 ; enemy buffer mask nuke left
SPR_NUKE1 = %00000111 ; enemy buffer mask nuke right
MONSTER_HEIGHT = 13 ; rows in monster sprite
MONSTER_WIDTH = 3 ; cols in monster sprite
MONSTER_SPEED = 4 ; speed at which monster moves (in rows)
MISSILE_HEIGHT = 14 ; rows in missile sprite
RADAR_HEIGHT = 16 ; rows in radar sprite
NUKE_HEIGHT = 8 ; rows in nuke sprite
EXPLOSION_HEIGHT = 16 ; rows in explosion sprite
BOMB_HEIGHT = 6 ; rows in bomb sprite
BOMB_FRWRD_FRMS = 6 ; horz bomb travel duration
SHIP_HEIGHT = 12 ; rows in player ship sprite
SHIP_WIDTH = 4 ; cols in player ship sprite
SHIP_START = 16 ; height above world where ship starts

File diff suppressed because it is too large Load Diff

View File

@ -1,590 +0,0 @@
;-----------------------------------------------------------------------------
; edit.inc
; Part of penetrator, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2019
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
.segment "CODE"
;-----------------------------------------------------------------------------
.proc editLoop
jsr drawClearScreen ; make sure the screen is clear before adjusting the
jsr editInit
jsr editLoadStage
lda #2
sta updateHUD
loop:
jsr inputEdit
beq :+
jsr editHandleKeys
lda pause ; pause is quit flag in endit
beq :+
rts
:
clc
jsr terrainShow ; show terrain 1st because it collides with nothing
jsr drawEnemies ; enemies collide with nothing in edit mode
jsr editDrawCursor
lda updateHUD
beq :+
jsr uiShowEditLabels
:
jsr drawPresent ; flip layers 0/1 (bring backLayer to visible)
jmp loop
.endproc
;-----------------------------------------------------------------------------
.proc editHandleKeys
cmp #'6' ; 6 or bigger - not a stage command
bcs notnum
cmp #'1' ; less than 1 - not a stage command
bcc notnum
sbc #'1' ; stages are 0 based
sta stage
lda #AUDIO_UI_TICK ; make a sound
sta audioFrame
jsr serviceAudio
lda #0 ; reset where the buffers will start
sta bufferInsert
jsr drawClearScreen
jsr editLoadStage ; get the right stage at the right place
jmp uiShowEditLabels ; update the HUD
notnum:
cmp #$1b ; ESC key
bne notQuit
lda #AUDIO_UI_TICK ; make a sound
sta audioFrame
jsr serviceAudio
lda #1
sta pause ; abuse pause to signal quit
rts
notQuit:
cmp #'c' ; c or C for help
beq help
cmp #'C'
bne notHelp
help:
lda #AUDIO_UI_TICK ; make a sound
sta audioFrame
jsr serviceAudio
jmp uiShowEditHelp
notHelp:
cmp #'s' ; s or S for save
beq save
cmp #'S'
bne notSave
save:
lda #AUDIO_UI_TICK ; make a sound
sta audioFrame
jsr serviceAudio
lda #0 ; a 0 is save
jsr uiFileLoadSave
jmp editLoop
notSave:
cmp #'l' ; l or L for load
beq load
cmp #'L'
bne done
load:
lda #AUDIO_UI_TICK ; make a sound
sta audioFrame
jsr serviceAudio
lda #1 ; a 1 is load
jsr uiFileLoadSave
jmp editLoop
done:
clc
rts
.endproc
;-----------------------------------------------------------------------------
; Move the world left (feels like YOU are moving right)
; will update the stage when a stage boundary is crossed and will then
; update the HUD
.proc editGameWorldRight
zaWorldPtr = tempBlock + 14 ; 2 bytes for a ptr
lda stage ; only scroll right while the stage
cmp #4 ; isn't 5 (0 based so 4). Stage 5
bcc :+ ; cannot be edited
rts
:
jsr gameWorldMove ; use the game move code
lda zWorldPtr + 1 ; but then calculate a point where the stage marker might be
sta zaWorldPtr + 1
lda zWorldPtr
sec
sbc #((XSIZE+3)*3)
sta zaWorldPtr
bcs :+
dec zaWorldPtr + 1
:
ldy #2 ; and read the enemy byte
lda (zaWorldPtr), y
bit Bit7Mask ; and see if this is a stage change
beq :+
inc stage ; bit was set so change stage
lda #2 ; and update the HUD
sta updateHUD
:
inc bufferDraw ; the bufferDraw (col 0) is also one more to the right
rts
.endproc
;-----------------------------------------------------------------------------
; Scroll to the left, updating the stage boundary and adding enemies as needed.
.proc editGameWorldLeft
leftWorldPtr = tempBlock + 14
lda zWorldPtr + 1 ; get the left edge insert point by subtracting
sta leftWorldPtr + 1 ; XSIZE+3 from the right edge. XSIZE-1 is the current
lda zWorldPtr ; left screen col. +3 is 4 past, which is the width
sec ; of a radar that could now scroll on-screen
sbc #((XSIZE+3)*3) ; the buffer will have proper height data for at least
sta leftWorldPtr ; 2 of these 3 cols to the left - see editLoadStage
bcs :+
dec leftWorldPtr + 1
:
lda leftWorldPtr + 1 ; see if this new dest is <= the world start.
cmp #>worldDataStart ; if it is then don't scroll any further left, just exit
beq :+ ; hi equal to worldStart hi, so test low
bcs leftOk ; hi > worldStart hi so good to go
done:
rts
:
lda leftWorldPtr
cmp #<worldDataStart
bcc done ; lo < lo - too small, no go
beq done ; lo equal so also no go
leftOk:
lda zWorldPtr ; there's room to go left so move the right edge left
sec ; by 1 col, or one triplet of data, so 3 bytes
sbc #3
sta zWorldPtr
bcs :+
dec zWorldPtr + 1
:
dec bufferDraw ; adjust the draw and insert buffer "counters"
dec bufferInsert ; now points at the "new" screen locations
clc
ldx bufferDraw ; the bufferDraw is the left edge
dex ; back up 4 bytes (so 1 past where a radar
dex ; could be added) and write a 0 in there
dex ; to stomp any old circular buffer data
dex
lda #0
sta enemyBuffer, x
inx ; now move to the col where the heights will be added
ldy #0 ; get the world bottom
lda (leftWorldPtr), y
sta worldBBuffer, x ; and put it in the buffer
iny ; and get the world top
lda (leftWorldPtr), y
sta worldTBuffer, x ; and put it in the buffer
ldy #2 ; see if there's a radar to go with this height data
lda (leftWorldPtr), y ; get the enemy flag
bit Bit7Mask ; see if this is a stage change
beq radar ; no - check for radar
pha ; stage is changing so save a
dec stage ; dec the stage
lda #2 ; mark the HUD for update
sta updateHUD
pla ; restore a - could also hold a missile or radar
radar:
bit Bit2Mask ; is it a radar
beq missile ; no - go check for a missile
jmp gameWorldFlag ; add the radar - can't also be a missile so all done
missile:
inx ; the missile will start 2 cols later
inx
ldy #8 ; and is also 2 (past height)+(2*3) bytes later in the world
lda (leftWorldPtr), y ; get the enemy flag
bit Bit1Mask ; see if it's a missile
beq done ; if not a missile then done
jmp gameWorldFlag ; add the missile and finish
.endproc
;-----------------------------------------------------------------------------
; Prepare for editing by initializing the needed variables
.proc editInit
brushType = tempBlock + 16
lda #GAME_MODE_EDIT
sta gameMode
lda #0
sta brushType ; BRUSH_TERRAIN is also 0
sta direction ; go to the right
sta terrainOrigin ; don't scroll in, just be all there
sta zCollision
sta stopScrolling
sta bufferInsert
sta dangerTickIdx
sta pause
tax ; start at 0 for the buffers
:
sta worldBBuffer, x ; and init all 256 bytes of each buffer to 0
sta worldTBuffer, x
sta enemyBuffer, x
sta enemyHgtBuffer, x
sta explosionBuffer, x
sta bulletsBuffer, x
dex
bne :-
ldx #NUM_STAGES-1 ; mark all stages as all rockets, no monsters
:
sta makeMonster, x
dex
bpl :-
lda #$ff
sta lastInput ; set no keys down - all 1's
sta nextStage
lda #DANGER_TICKS
sta dangerTickCount
lda #(XSIZE/2) ; middle of the screen in X
sta playerShipX ; is where the cursor is
lda #(WORLD_START + (WORLD_END - WORLD_START) / 2)
sta playerShipY ; and in Y also in the middle
rts
.endproc
;-----------------------------------------------------------------------------
; Show a custom character as a cursor. Also redraw the down arrow
; since the cursor draws into the top 8 likes that don't get cleaned/updated
; with every frame. Drawing the arrow fixes up the out of bounds areas
.proc editDrawCursor
yPos = tempBlock + 14
xPos = tempBlock + 15
zaStrL = tempBlock + 1 ; parameter - string lo
zaStrH = tempBlock + 2 ; parameter - string hi
zaFontL = tempBlock + 4 ; internal - point at the character memory Lo
zaFontH = tempBlock + 5 ; internal - point at the character memory Hi
zaFontOffset = tempBlock + 6 ; 0-15 - index from zaFont
lda playerShipX
lsr
sta xPos
print textEditDnArrow, xPos, 0 ; redraw arrow to fix out of top cursor overwrite
lda #$87 ; cursor symbol
ldy #0
jsr setFont
lda playerShipY ; get the screen Y for cursor
sec ; but raise it so the horz bar is at the "ship" level
sbc #2
sta yPos ; init the row working buffer
ldx backLayer ; write to back layer
plotLoop:
ldy yPos ; at the working row offset
lda rowL, y ; get the memory address
clc
adc xPos ; add in column
sta write + 1 ; point lo at memory
lda rowH, y
adc layersH, x
sta write + 2
ldy zaFontOffset ; get the offset into the character
lda (zaFontL), y
write: ; get the actual left character byte
sta PLACEHOLDER ; plot the left hand side
cpy #$05 ; cursor character is 5 rows high
bcs done ; if 10 then done with the cursor
inc zaFontOffset ; move 2 bytes for last row plotted
inc zaFontOffset
inc yPos ; move down a row on screen
bne plotLoop ; always take this branch
done:
rts
.endproc
;-----------------------------------------------------------------------------
; Will set the terrain to the cursor, and will move enemies to be back
; on the terrain when needed. Will set both the draw buffers and the
; actual world data stream (the triplets)
.proc editSetTerrainBottom
zaColumn = tempBlock + 3
zaMidScreen = tempBlock + 4
lda zWorldPtr + 1 ; make a copy of the world pointer
sta zaMidScreen + 1 ; that corresponds with the position of the cursor
lda zWorldPtr
sec
sbc #((XSIZE/2)*3) ; 1/2 way in screen, 3 bytes per column
sta zaMidScreen
bcs :+
dec zaMidScreen + 1
:
ldy #3 ; index from ptr
lda playerShipY ; cursor height in playerShipY
sta (zaMidScreen), y ; store in the terrain bottom
lda bufferDraw ; now update the draw buffer
clc
adc playerShipX ; get to the correct column offset
tax ; save in x
lda playerShipY ; get the height
sta worldBBuffer, x ; update the buffer
lda enemyBuffer, x ; get the enemy flag
beq done ; no enemy - all done
bit Bit12Mask ; see if it's a radar or missile
beq done ; if bits 12 not set then not an enemy
ldy #2 ; assume a missile - 2 columns
and #%00001110 ; column and way to id enemy (10 is radar)
lsr ; move col to 1's position
lsr
bcc :+ ; if carry clear then this is a missile
ldy #4 ; a radar is 4 columns
:
sta zaColumn ; save the enemy column
txa ; get the screen column under the cursor (in the buffer)
sec
sbc zaColumn ; subtract the enemy column, giving the buffer column of the 1st enemy column
tax ; get the index into a
lda worldBBuffer, x ; get the world height
sec
sbc #1 ; and go 1 row higher (on top of ground)
:
sta enemyHgtBuffer, x ; write the world height to all
inx ; the columns of the enemy
dey
bne :-
done:
rts
.endproc
;-----------------------------------------------------------------------------
; Set the terrain top in the world data stream as well as the draw buffers
.proc editSetTerrainTop
zaMidScreen = tempBlock + 4
lda zWorldPtr + 1 ; make a ptr to the cursor
sta zaMidScreen + 1
lda zWorldPtr
sec
sbc #((XSIZE/2)*3)
sta zaMidScreen
bcs :+
dec zaMidScreen + 1
:
ldy #4 ; index from ptr
lda playerShipY
sta (zaMidScreen), y ; save the top in the world data
lda bufferDraw ; also update the draw buffer
clc
adc playerShipX
tax
lda playerShipY
sta worldTBuffer, x
rts
.endproc
;-----------------------------------------------------------------------------
; This routine will "kill" enemies that overlap with the cursor column.
; the zaDrawSprWidth is 4 (radar) or 2 (missile) for the type of enemy
; for which room needs to be created
; Enemies are removed from the world stream and the draw buffers
.proc editPreSetEnemy
zaDrawSprWidth = tempBlock + 3 ; Parameter
zaMidScreenL = tempBlock + 5
zaMidScreenH = tempBlock + 6
lda zWorldPtr + 1 ; calculate an offset for the cursor
sta zaMidScreenH
lda zWorldPtr
sec
sbc #(((XSIZE/2)+2)*3)
sta zaMidScreenL
bcs :+
dec zaMidScreenH
:
lda #3 ; check 3 columns before the cursor as a 4 col
clc ; radar could start 3 col earlier and still overlap
adc zaDrawSprWidth ; and add the length of the enemy (4 for radar, 2 for missile)
tax ; put the number of cols to check in x
ldy #2 ; index off of ptr to point at enemy bytes
krl:
lda (zaMidScreenL), y ; get the enemy byte
bit Bit2Mask ; see if it's a radar
beq :+
and #%11111100 ; mask off the enemy bits (making it blank but keeping stage data)
sta (zaMidScreenL), y ; and save the "deleted" enemy
:
iny ; advance the offset by 3 to the next enemy byte
iny
iny
dex ; and one less column to do
bne krl ; repeat till all cols checked
lda #1 ; now do the exact same but for missiles
clc ; but start only 1 column before the cursor as
adc zaDrawSprWidth ; a missile that overlaps can only overlap from 1 col earlier
tax
ldy #8
kml:
lda (zaMidScreenL), y
bit Bit1Mask
beq :+
and #%11111100
sta (zaMidScreenL), y
:
iny
iny
iny
dex
bne kml
lda #(XSIZE/2) ; get the offset of the cursor into the buffers
clc
adc bufferDraw
sta zEnemyCol ; and put it in the "enemy column"
jsr gameKillEnemy ; and call the game kill to see if there's an enemy to destroy
rts
.endproc
;-----------------------------------------------------------------------------
.proc editSetRadar
zaDrawSprWidth = tempBlock + 3 ; Parameter
zaMidScreenL = tempBlock + 5
lda #4 ; need room for a radar so 4 cols
sta zaDrawSprWidth
jsr editPreSetEnemy ; delete any overlapping enemies
lda enemyHitType ; if set, then an enemy was deleted. Just exit
bmi :+
rts
:
ldy #11 ; no overlapping enemies. The offset in the world stream from the ptr
lda #2 ; and the radar type
ora (zaMidScreenL), y ; add it to whatever is there (stage marker)
sta (zaMidScreenL), y ; and save it
lda bufferDraw ; and also insert it into the draw buffers
clc
adc #(XSIZE/2)
tax
clc
lda #2
jsr gameWorldFlag
rts
.endproc
;-----------------------------------------------------------------------------
.proc editSetMissile
zaDrawSprWidth = tempBlock + 3 ; Parameter
zaMidScreenL = tempBlock + 5
lda #2 ; need room for a missile (so 2 cols)
sta zaDrawSprWidth
jsr editPreSetEnemy ; delete overlapping enemies from the world and draw buffers
lda enemyHitType ; if set, enemies were deleted so exit
bmi :+
rts
:
ldy #11 ; no overlapping enemies. The offset in the world stream from the ptr
lda #1 ; and the missile type
ora (zaMidScreenL), y ; add it to whatever is there (stage marker)
sta (zaMidScreenL), y ; and save it
lda bufferDraw ; also add the missile to the draw buffers
clc
adc #(XSIZE/2)
tax
clc
lda #1
jsr gameWorldFlag
rts
.endproc
;-----------------------------------------------------------------------------
.proc editLoadStage
jsr gameFindStage ; find the stage
lda #(XSIZE+2) ; scroll it on-screen but make sure there are
sta tempBlock + 1 ; extra cols of data in the buffers
:
jsr gameWorldMove ; populate the buffers
dec tempBlock + 1
bpl :-
lda #4 ; start the screen draw 2 cols more to the right than
sta bufferDraw ; there's buffer data for so a left scroll will work
rts
.endproc

View File

@ -1,234 +0,0 @@
;-----------------------------------------------------------------------------
; file.inc
; Part of penetrator, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2019
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
.segment "DATA"
createParam:
.byte $07 ; param_count
createName:
.addr PATHNAME ; pathname
.byte $C3 ; access
.byte $06 ; file_type (6 is binay)
.word $0000 ; aux_type
.byte $01 ; storage_type
.word $0000 ; create_date
.word $0000 ; create_time
openParam:
.byte $03 ; param_count
openName:
.addr PATHNAME ; pathname
.addr $2000-$400 ; io_buffer
openRef:
.byte $00 ; ref_num
readParam:
.byte $04 ; param_count
readRef:
.byte $00 ; ref_num
readAddress:
.addr worldDataStart ; data_buffer
readLength:
.word $FFFF ; request_count
.word $0000 ; trans_count
writeParam:
.byte $04 ; param_count
writeRef:
.byte $00 ; ref_num
writeAddress:
.addr worldDataStart ; data_buffer
writeLength:
.word worldDataEnd-worldDataStart ; request_count
.word $0000 ; trans_count
closeParam:
.byte $01 ; param_count
closeRef:
.byte $00 ; ref_num
;-----------------------------------------------------------------------------
.segment "CODE"
;-----------------------------------------------------------------------------
.proc saveWorld
lda #<worldDataStart ; set the location
sta writeAddress
lda #>worldDataStart
sta writeAddress + 1
lda #<(worldDataEnd-worldDataStart) ; set the size
sta writeLength
lda #>(worldDataEnd-worldDataStart)
sta writeLength + 1
jmp saveFile ; save
.endproc
;-----------------------------------------------------------------------------
.proc loadWorld
lda #<worldDataStart ; set the location
sta readAddress
lda #>worldDataStart
sta readAddress + 1
lda #<(worldDataEnd-worldDataStart) ; set the length (size)
sta readLength
lda #>(worldDataEnd-worldDataStart)
sta readLength + 1
jmp loadFile ; load
.endproc
;-----------------------------------------------------------------------------
.proc saveHighScores
jsr setHighScoreFileNames ; set the name
lda #<scoresTable ; set the location
sta writeAddress
lda #>scoresTable
sta writeAddress + 1
lda #<(scoresTableEnd-scoresTable) ; set the size
sta writeLength
lda #>(scoresTableEnd-scoresTable)
sta writeLength + 1
jmp saveFile ; save
.endproc
;-----------------------------------------------------------------------------
.proc loadHighScores
jsr setHighScoreFileNames ; set the name
lda #<scoresTable ; set the location
sta readAddress
lda #>scoresTable
sta readAddress + 1
lda #<(scoresTableEnd-scoresTable) ; set the size
sta readLength
lda #>(scoresTableEnd-scoresTable)
sta readLength + 1
jmp loadFile ; load
.endproc
;-----------------------------------------------------------------------------
.proc setHighScoreFileNames
ldx pathPos ; append to the end of the path
ldy #0 ; from the 1st char pf the name
:
lda hihgScoreFileName, y ; copy name to path
sta PATHNAME, x
beq :+
iny
inx
bne :-
:
stx PATHNAME
dec PATHNAME ; don't count the trailing null
rts
.endproc
;-----------------------------------------------------------------------------
.proc setWorldFileName
zaEntryL = zWorldPtr ; internal - ptr to a string being entered (abusing world ptr)
tya ; add the file length to the path length
clc
adc pathPos
tax
stx PATHNAME
dec PATHNAME ; don't count the trailing null
:
lda (zaEntryL), y ; copy the file name to the end of the path
sta PATHNAME, x
dex
dey
bpl :-
rts
.endproc
;-----------------------------------------------------------------------------
.proc saveFile
jsr MLI ; create the file, ignoring errors
.byte CREATE_CALL
.word createParam
jsr MLI ; open the (now hopefully existing) file
.byte OPEN_CALL
.word openParam
bcc :+
jmp error
:
lda openRef
sta writeRef
sta closeRef
jsr MLI
.byte WRITE_CALL
.word writeParam
bcs error
jsr MLI
.byte CLOSE_CALL
.word closeParam
bcs error
error:
rts
.endproc
;-----------------------------------------------------------------------------
.proc loadFile
jsr MLI
.byte OPEN_CALL
.word openParam
bcc :+
jmp error
:
lda openRef
sta readRef
sta closeRef
jsr MLI
.byte READ_CALL
.word readParam
bcs error
jsr MLI
.byte CLOSE_CALL
.word closeParam
bcs error
error:
rts
.endproc

View File

@ -1,948 +0,0 @@
;-----------------------------------------------------------------------------
; fontdata.inc
; Part of penetrator, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2019
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
.segment "RODATA"
;-----------------------------------------------------------------------------
; The characters are listed in Apple format (backwards) and human-facing
; format (not backwards ;)
font:
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $24 ; --X--X-- --X--X--
.byte $24 ; --X--X-- --X--X--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $24 ; --X--X-- --X--X--
.byte $7E ; -XXXXXX- -XXXXXX-
.byte $24 ; --X--X-- --X--X--
.byte $24 ; --X--X-- --X--X--
.byte $7E ; -XXXXXX- -XXXXXX-
.byte $24 ; --X--X-- --X--X--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $10 ; ---X---- ----X---
.byte $78 ; -XXXX--- ---XXXX-
.byte $14 ; ---X-X-- --X-X---
.byte $38 ; --XXX--- ---XXX--
.byte $50 ; -X-X---- ----X-X-
.byte $3C ; --XXXX-- --XXXX--
.byte $10 ; ---X---- ----X---
.byte $00 ; -------- --------
.byte $46 ; -X---XX- -XX---X-
.byte $26 ; --X--XX- -XX--X--
.byte $10 ; ---X---- ----X---
.byte $08 ; ----X--- ---X----
.byte $64 ; -XX--X-- --X--XX-
.byte $62 ; -XX---X- -X---XX-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $08 ; ----X--- ---X----
.byte $14 ; ---X-X-- --X-X---
.byte $08 ; ----X--- ---X----
.byte $54 ; -X-X-X-- --X-X-X-
.byte $22 ; --X---X- -X---X--
.byte $5C ; -X-XXX-- --XXX-X-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $10 ; ---X---- ----X---
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $20 ; --X----- -----X--
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $20 ; --X----- -----X--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $04 ; -----X-- --X-----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $04 ; -----X-- --X-----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $28 ; --X-X--- ---X-X--
.byte $10 ; ---X---- ----X---
.byte $7C ; -XXXXX-- --XXXXX-
.byte $10 ; ---X---- ----X---
.byte $28 ; --X-X--- ---X-X--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $7C ; -XXXXX-- --XXXXX-
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $7C ; -XXXXX-- --XXXXX-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $18 ; ---XX--- ---XX---
.byte $18 ; ---XX--- ---XX---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $40 ; -X------ ------X-
.byte $20 ; --X----- -----X--
.byte $10 ; ---X---- ----X---
.byte $08 ; ----X--- ---X----
.byte $04 ; -----X-- --X-----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3C ; --XXXX-- --XXXX--
.byte $62 ; -XX---X- -X---XX-
.byte $52 ; -X-X--X- -X--X-X-
.byte $4A ; -X--X-X- -X-X--X-
.byte $46 ; -X---XX- -XX---X-
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $18 ; ---XX--- ---XX---
.byte $14 ; ---X-X-- --X-X---
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $7C ; -XXXXX-- --XXXXX-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3C ; --XXXX-- --XXXX--
.byte $42 ; -X----X- -X----X-
.byte $40 ; -X------ ------X-
.byte $3C ; --XXXX-- --XXXX--
.byte $02 ; ------X- -X------
.byte $7E ; -XXXXXX- -XXXXXX-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3C ; --XXXX-- --XXXX--
.byte $42 ; -X----X- -X----X-
.byte $30 ; --XX---- ----XX--
.byte $40 ; -X------ ------X-
.byte $42 ; -X----X- -X----X-
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $10 ; ---X---- ----X---
.byte $18 ; ---XX--- ---XX---
.byte $14 ; ---X-X-- --X-X---
.byte $12 ; ---X--X- -X--X---
.byte $7E ; -XXXXXX- -XXXXXX-
.byte $10 ; ---X---- ----X---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $7E ; -XXXXXX- -XXXXXX-
.byte $02 ; ------X- -X------
.byte $3E ; --XXXXX- -XXXXX--
.byte $40 ; -X------ ------X-
.byte $42 ; -X----X- -X----X-
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3C ; --XXXX-- --XXXX--
.byte $02 ; ------X- -X------
.byte $3E ; --XXXXX- -XXXXX--
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $7E ; -XXXXXX- -XXXXXX-
.byte $40 ; -X------ ------X-
.byte $20 ; --X----- -----X--
.byte $10 ; ---X---- ----X---
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3C ; --XXXX-- --XXXX--
.byte $42 ; -X----X- -X----X-
.byte $3C ; --XXXX-- --XXXX--
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3C ; --XXXX-- --XXXX--
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $7C ; -XXXXX-- --XXXXX-
.byte $40 ; -X------ ------X-
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $04 ; -----X-- --X-----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $20 ; --X----- -----X--
.byte $10 ; ---X---- ----X---
.byte $08 ; ----X--- ---X----
.byte $10 ; ---X---- ----X---
.byte $20 ; --X----- -----X--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $7C ; -XXXXX-- --XXXXX-
.byte $00 ; -------- --------
.byte $7C ; -XXXXX-- --XXXXX-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $08 ; ----X--- ---X----
.byte $10 ; ---X---- ----X---
.byte $20 ; --X----- -----X--
.byte $10 ; ---X---- ----X---
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3C ; --XXXX-- --XXXX--
.byte $42 ; -X----X- -X----X-
.byte $20 ; --X----- -----X--
.byte $10 ; ---X---- ----X---
.byte $00 ; -------- --------
.byte $10 ; ---X---- ----X---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3C ; --XXXX-- --XXXX--
.byte $52 ; -X-X--X- -X--X-X-
.byte $6A ; -XX-X-X- -X-X-XX-
.byte $7A ; -XXXX-X- -X-XXXX-
.byte $02 ; ------X- -X------
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3C ; --XXXX-- --XXXX--
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $7E ; -XXXXXX- -XXXXXX-
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3E ; --XXXXX- -XXXXX--
.byte $42 ; -X----X- -X----X-
.byte $3E ; --XXXXX- -XXXXX--
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $3E ; --XXXXX- -XXXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3C ; --XXXX-- --XXXX--
.byte $42 ; -X----X- -X----X-
.byte $02 ; ------X- -X------
.byte $02 ; ------X- -X------
.byte $42 ; -X----X- -X----X-
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $1E ; ---XXXX- -XXXX---
.byte $22 ; --X---X- -X---X--
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $22 ; --X---X- -X---X--
.byte $1E ; ---XXXX- -XXXX---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $7E ; -XXXXXX- -XXXXXX-
.byte $02 ; ------X- -X------
.byte $3E ; --XXXXX- -XXXXX--
.byte $02 ; ------X- -X------
.byte $02 ; ------X- -X------
.byte $7E ; -XXXXXX- -XXXXXX-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $7E ; -XXXXXX- -XXXXXX-
.byte $02 ; ------X- -X------
.byte $3E ; --XXXXX- -XXXXX--
.byte $02 ; ------X- -X------
.byte $02 ; ------X- -X------
.byte $02 ; ------X- -X------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3C ; --XXXX-- --XXXX--
.byte $42 ; -X----X- -X----X-
.byte $02 ; ------X- -X------
.byte $72 ; -XXX--X- -X--XXX-
.byte $42 ; -X----X- -X----X-
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $7E ; -XXXXXX- -XXXXXX-
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $7C ; -XXXXX-- --XXXXX-
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $7C ; -XXXXX-- --XXXXX-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $40 ; -X------ ------X-
.byte $40 ; -X------ ------X-
.byte $40 ; -X------ ------X-
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $22 ; --X---X- -X---X--
.byte $12 ; ---X--X- -X--X---
.byte $0E ; ----XXX- -XXX----
.byte $12 ; ---X--X- -X--X---
.byte $22 ; --X---X- -X---X--
.byte $42 ; -X----X- -X----X-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $02 ; ------X- -X------
.byte $02 ; ------X- -X------
.byte $02 ; ------X- -X------
.byte $02 ; ------X- -X------
.byte $02 ; ------X- -X------
.byte $7E ; -XXXXXX- -XXXXXX-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $42 ; -X----X- -X----X-
.byte $66 ; -XX--XX- -XX--XX-
.byte $5A ; -X-XX-X- -X-XX-X-
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $42 ; -X----X- -X----X-
.byte $46 ; -X---XX- -XX---X-
.byte $4A ; -X--X-X- -X-X--X-
.byte $52 ; -X-X--X- -X--X-X-
.byte $62 ; -XX---X- -X---XX-
.byte $42 ; -X----X- -X----X-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3C ; --XXXX-- --XXXX--
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3E ; --XXXXX- -XXXXX--
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $3E ; --XXXXX- -XXXXX--
.byte $02 ; ------X- -X------
.byte $02 ; ------X- -X------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3C ; --XXXX-- --XXXX--
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $4A ; -X--X-X- -X-X--X-
.byte $52 ; -X-X--X- -X--X-X-
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3E ; --XXXXX- -XXXXX--
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $3E ; --XXXXX- -XXXXX--
.byte $22 ; --X---X- -X---X--
.byte $42 ; -X----X- -X----X-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3C ; --XXXX-- --XXXX--
.byte $02 ; ------X- -X------
.byte $3C ; --XXXX-- --XXXX--
.byte $40 ; -X------ ------X-
.byte $42 ; -X----X- -X----X-
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $7F ; -XXXXXXX XXXXXXX-
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $24 ; --X--X-- --X--X--
.byte $18 ; ---XX--- ---XX---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $42 ; -X----X- -X----X-
.byte $5A ; -X-XX-X- -X-XX-X-
.byte $24 ; --X--X-- --X--X--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $42 ; -X----X- -X----X-
.byte $24 ; --X--X-- --X--X--
.byte $18 ; ---XX--- ---XX---
.byte $18 ; ---XX--- ---XX---
.byte $24 ; --X--X-- --X--X--
.byte $42 ; -X----X- -X----X-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $41 ; -X-----X X-----X-
.byte $22 ; --X---X- -X---X--
.byte $14 ; ---X-X-- --X-X---
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $7E ; -XXXXXX- -XXXXXX-
.byte $20 ; --X----- -----X--
.byte $10 ; ---X---- ----X---
.byte $08 ; ----X--- ---X----
.byte $04 ; -----X-- --X-----
.byte $7E ; -XXXXXX- -XXXXXX-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $70 ; -XXX---- ----XXX-
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $70 ; -XXX---- ----XXX-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $02 ; ------X- -X------
.byte $04 ; -----X-- --X-----
.byte $08 ; ----X--- ---X----
.byte $10 ; ---X---- ----X---
.byte $20 ; --X----- -----X--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $0E ; ----XXX- -XXX----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $0E ; ----XXX- -XXX----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $08 ; ----X--- ---X----
.byte $1C ; ---XXX-- --XXX---
.byte $2A ; --X-X-X- -X-X-X--
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $FF ; XXXXXXXX XXXXXXXX
.byte $00 ; -------- --------
.byte $38 ; --XXX--- ---XXX--
.byte $44 ; -X---X-- --X---X-
.byte $1E ; ---XXXX- -XXXX---
.byte $04 ; -----X-- --X-----
.byte $04 ; -----X-- --X-----
.byte $7E ; -XXXXXX- -XXXXXX-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $1C ; ---XXX-- --XXX---
.byte $20 ; --X----- -----X--
.byte $3C ; --XXXX-- --XXXX--
.byte $22 ; --X---X- -X---X--
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $04 ; -----X-- --X-----
.byte $04 ; -----X-- --X-----
.byte $3C ; --XXXX-- --XXXX--
.byte $44 ; -X---X-- --X---X-
.byte $44 ; -X---X-- --X---X-
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $38 ; --XXX--- ---XXX--
.byte $04 ; -----X-- --X-----
.byte $04 ; -----X-- --X-----
.byte $04 ; -----X-- --X-----
.byte $38 ; --XXX--- ---XXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $20 ; --X----- -----X--
.byte $20 ; --X----- -----X--
.byte $3C ; --XXXX-- --XXXX--
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $3C ; --XXXX-- --XXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $1C ; ---XXX-- --XXX---
.byte $22 ; --X---X- -X---X--
.byte $1E ; ---XXXX- -XXXX---
.byte $02 ; ------X- -X------
.byte $1C ; ---XXX-- --XXX---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $30 ; --XX---- ----XX--
.byte $08 ; ----X--- ---X----
.byte $18 ; ---XX--- ---XX---
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3C ; --XXXX-- --XXXX--
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $3C ; --XXXX-- --XXXX--
.byte $20 ; --X----- -----X--
.byte $1C ; ---XXX-- --XXX---
.byte $00 ; -------- --------
.byte $02 ; ------X- -X------
.byte $02 ; ------X- -X------
.byte $1E ; ---XXXX- -XXXX---
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
.byte $0C ; ----XX-- --XX----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $1C ; ---XXX-- --XXX---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $20 ; --X----- -----X--
.byte $00 ; -------- --------
.byte $20 ; --X----- -----X--
.byte $20 ; --X----- -----X--
.byte $20 ; --X----- -----X--
.byte $24 ; --X--X-- --X--X--
.byte $18 ; ---XX--- ---XX---
.byte $00 ; -------- --------
.byte $04 ; -----X-- --X-----
.byte $14 ; ---X-X-- --X-X---
.byte $0C ; ----XX-- --XX----
.byte $0C ; ----XX-- --XX----
.byte $14 ; ---X-X-- --X-X---
.byte $24 ; --X--X-- --X--X--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $30 ; --XX---- ----XX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $16 ; ---X-XX- -XX-X---
.byte $2A ; --X-X-X- -X-X-X--
.byte $2A ; --X-X-X- -X-X-X--
.byte $2A ; --X-X-X- -X-X-X--
.byte $2A ; --X-X-X- -X-X-X--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $1E ; ---XXXX- -XXXX---
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $1C ; ---XXX-- --XXX---
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $1C ; ---XXX-- --XXX---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $1E ; ---XXXX- -XXXX---
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $1E ; ---XXXX- -XXXX---
.byte $02 ; ------X- -X------
.byte $02 ; ------X- -X------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3C ; --XXXX-- --XXXX--
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $3C ; --XXXX-- --XXXX--
.byte $20 ; --X----- -----X--
.byte $40 ; -X------ ------X-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $38 ; --XXX--- ---XXX--
.byte $04 ; -----X-- --X-----
.byte $04 ; -----X-- --X-----
.byte $04 ; -----X-- --X-----
.byte $04 ; -----X-- --X-----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $1C ; ---XXX-- --XXX---
.byte $02 ; ------X- -X------
.byte $1C ; ---XXX-- --XXX---
.byte $20 ; --X----- -----X--
.byte $1E ; ---XXXX- -XXXX---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $08 ; ----X--- ---X----
.byte $1C ; ---XXX-- --XXX---
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $30 ; --XX---- ----XX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $1C ; ---XXX-- --XXX---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $14 ; ---X-X-- --X-X---
.byte $14 ; ---X-X-- --X-X---
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $22 ; --X---X- -X---X--
.byte $2A ; --X-X-X- -X-X-X--
.byte $2A ; --X-X-X- -X-X-X--
.byte $2A ; --X-X-X- -X-X-X--
.byte $14 ; ---X-X-- --X-X---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $22 ; --X---X- -X---X--
.byte $14 ; ---X-X-- --X-X---
.byte $08 ; ----X--- ---X----
.byte $14 ; ---X-X-- --X-X---
.byte $22 ; --X---X- -X---X--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $22 ; --X---X- -X---X--
.byte $3C ; --XXXX-- --XXXX--
.byte $20 ; --X----- -----X--
.byte $1C ; ---XXX-- --XXX---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $3E ; --XXXXX- -XXXXX--
.byte $10 ; ---X---- ----X---
.byte $08 ; ----X--- ---X----
.byte $04 ; -----X-- --X-----
.byte $3E ; --XXXXX- -XXXXX--
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $60 ; -XX----- -----XX-
.byte $10 ; ---X---- ----X---
.byte $0C ; ----XX-- --XX----
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $60 ; -XX----- -----XX-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $10 ; ---X---- ----X---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $06 ; -----XX- -XX-----
.byte $08 ; ----X--- ---X----
.byte $30 ; --XX---- ----XX--
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $06 ; -----XX- -XX-----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $28 ; --X-X--- ---X-X--
.byte $14 ; ---X-X-- --X-X---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $1C ; ---XXX-- --XXX---
.byte $22 ; --X---X- -X---X--
.byte $59 ; -X-XX--X X--XX-X-
.byte $45 ; -X---X-X X-X---X-
.byte $45 ; -X---X-X X-X---X-
.byte $59 ; -X-XX--X X--XX-X-
.byte $22 ; --X---X- -X---X--
.byte $1C ; ---XXX-- --XXX---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $02 ; ------X- -X------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $01 ; -------X X-------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $05 ; -----X-X X-X-----
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $15 ; ---X-X-X X-X-X---
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $55 ; -X-X-X-X X-X-X-X-
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $00 ; -------- --------
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $49 ; -X--X--X X--X--X-
.byte $3E ; --XXXXX- -XXXXX--
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $3E ; --XXXXX- -XXXXX--
.byte $49 ; -X--X--X X--X--X-
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
.byte $2A ; --X-X-X- -X-X-X--
.byte $00 ; -------- --------
.byte $08 ; ----X--- ---X----
.byte $00 ; -------- --------
endFont:

File diff suppressed because it is too large Load Diff

View File

@ -1,414 +0,0 @@
;-----------------------------------------------------------------------------
; input.inc
; Part of penetrator, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2019
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
.segment "CODE"
;-----------------------------------------------------------------------------
.proc inputReadJoystick
joyMask = tempBlock + 21
ldx #$0 ; start the x counter at 0
ldy #$0 ; start the y counter at 0
lda PTRIG ; trigger the fact that the joystick will be read
readBoth:
lda PADDL0 ; get the value for X axis
bpl :+ ; if MSB is zero, done with X
upX:
inx ; increment the counter
bne :+ ; while x <> 0 go check y
dex ; if x reaches 0 it's overflow, set to 255
:
lda PADDL0 + 1 ; read the value for the Y axis
bpl readX ; if MSB is zero Y is done
iny ; increment the Y counter
bne readBoth ; branch to the start to check both axis
dey ; if Y reaches 0 it's overflow, set to 255 and drop through to check x only
readX:
lda PADDL0 ; get the value for X axis
bmi upX ; Y is done but X is not so go increment x
lda #$ff ; Done analog. Start the digital mask with all On
cpx #$20 ; compare to the low end dead zone
bcs :+ ; if greater than, then not left
eor #KEY_LEFT ; the joystick is left (bit is off)
bne chkY ; JuMP as acc is now non-zero
:
cpx #$60 ; check the upper bound of the dead-zone
bcc chkY ; if less than, then not right
eor #KEY_RIGHT ; gt high end of dead zone so joystick is right
chkY:
cpy #$20 ; do the same for the Y axis as for the X axis
bcs :+
eor #KEY_UP
bne buttons
:
cpy #$60
bcc buttons
eor #KEY_DOWN
buttons:
ldx BUTN0 ; read the button 0 state
cpx #$80 ; if ge 128 the button is fully depressed
bcc :+
eor #KEY_FIRE ; mark the button as down
:
ldx BUTN1 ; do the same for button 1 as for button 0
cpx #$80
bcc :+
eor #KEY_BOMB
:
sta joyMask ; save the mask
rts
.endproc
;-----------------------------------------------------------------------------
; Reads the joystick and moves the player.
.proc inputGame
zaRawInput = tempBlock + 1
zaRawEor = tempBlock + 2
lda fireCoolDown
beq :+
dec fireCoolDown
:
jsr inputReadJoystick
sta zaRawInput ; save the input
eor #$ff ; invert the bits
sta zaRawEor ; save this state too
lda zaRawInput ; no vertical move so process vertical joystick
up:
bit Bit4Mask ; set when moving up
bne down
lda playerShipY ; and move the ship up 2 rows
sec
sbc #3
cmp #(SHIP_HEIGHT+WORLD_START) ; limit at the top
bcc preLeft ; if too high, just ignore saving the move
sta playerShipY ; save the new position
bcs preLeft ; up, so skip down and check horizontal
down:
bit Bit3Mask ; ser for joystick down
bne left
lda playerShipY ; move the ship 2 rows down
clc
adc #3
cmp #(WORLD_END+1) ; limit at the bottom
bcs preBomb ; skip saving the new position if too low
sta playerShipY ; new position okay so save it
preLeft:
lda zaRawInput ; no horizontal movement so process horiz joystick
left:
bit Bit2Mask ; left sets this bit
bne right ; not set see if right is set
ldx playerShipX ; the ship should move left
dex ; move left one column
bmi preBomb ; if off-screen to the left, ignore
stx playerShipX ; save the movement
lda audioFrame
ora #AUDIO_MOTOR_REW
sta audioFrame
bne preBomb
right:
bit Bit1Mask ; bit set when right joystick active
bne bomb ; if nothing, go process player movement
ldx playerShipX ; get the ship position
inx ; move one column to the right
cpx #(((XSIZE/3)*2) - SHIP_WIDTH - 1) ; limit to two-thirds toward the right
bcs preBomb ; if over limit, ignore
stx playerShipX ; save movement
lda audioFrame
ora #AUDIO_MOTOR_FWD
sta audioFrame
preBomb:
lda zaRawInput
bomb:
bit Bit8Mask ; Button_A = bomb
bne fire
lda lastInput ; debounce the key for single shot
and zaRawEor
and Bit8Mask
beq nobomb ; bomb key not down
lda playerShipY ; bomb requested but can't
cmp #(WORLD_END-BOMB_HEIGHT) ; drop it when there's no room
bcs nobomb ; before the world end (else it draws out of bounds)
ldx #NUM_BOMBS-1 ; iterate over all bombs
:
lda bombY, x
beq drop ; find one that's available
dex
bpl :-
bmi nobomb ; none available
drop:
lda playerShipX ; bomb is relative to player
clc
adc #2
sta bombX, x
lda playerShipY
adc #6
sta bombY, x
lda #BOMB_FRWRD_FRMS ; set it to fly forward
sta bombDir, x
lda audioFrame
ora #AUDIO_BOMB_DROP
sta audioFrame
nobomb:
lda zaRawInput
fire:
bit Bit7Mask ; Button_B = fire
bne joyDone
lda fireCoolDown
bne joyDone
lda lastInput ; debounce the key for single shot
and zaRawEor
and Bit7Mask
beq joyDone
lda playerShipX ; Put even/odd into carry
lsr
lda playerShipX ; bullets start relative to ship
adc #4 ; 4 for even, 5 for odd
adc bulletIndex
tax
lda playerShipY
sec
sbc #4
sta bulletsBuffer, x ; put height into 3 columns
lda #3
sta fireCoolDown
lda audioFrame
ora #AUDIO_FIRE
sta audioFrame
joyDone:
lda zaRawInput ; remember the key-state for next time
sta lastInput ; so that fire and bombs can be debounced
lda KBD ; leave with a key in the accumulator
bit KBDSTRB ; reset the key
clc ; keep carry clear between routines
rts
.endproc
;-----------------------------------------------------------------------------
.proc inputEdit
rawInput = tempBlock + 17
rawEor = tempBlock + 18
brushType = tempBlock + 16
lda KBD
bit Bit8Mask
beq :+
bit KBDSTRB
and #$7f
bne :++
:
lda #0
:
pha
jsr inputReadJoystick
sta rawInput ; save the input state
pla
pha
cmp #' '
bne :+
lda rawInput
eor #KEY_SELECT
sta rawInput
pla
pha
:
cmp #'B'
bne :+
lda rawInput
eor #KEY_START
sta rawInput
:
lda rawInput
eor #$ff ; invert the bits so 1 means button down
sta rawEor ; save the inverted bits
bit Bit6Mask ; see if select button is held
bne Button_B ; if it is down, key processing done
and lastInput ; otherwise debounce the keys
sta rawEor ; and save this state as the key state
Button_B:
bit Bit7Mask ; Button_B
beq Button_A
lda #AUDIO_UI_TICK ; make a sound
sta audioFrame
jsr serviceAudio
lda brushType
bne radar
ora #KEY_RIGHT ; when pressed, move right as well
sta rawEor
jsr editSetTerrainBottom
jmp :+
radar:
jsr editSetRadar
:
lda rawEor ; no horizontal movement so process horiz joystick
Button_A:
bit Bit8Mask ; Button_A
beq up
lda #AUDIO_UI_TICK ; make a sound
sta audioFrame
jsr serviceAudio
lda brushType
bne missile
ora #KEY_RIGHT
sta rawEor
jsr editSetTerrainTop
jmp :+
missile:
jsr editSetMissile
:
lda rawEor ; no horizontal movement so process horiz joystick
up:
bit Bit4Mask ; set when moving up
beq down
ldx playerShipY
cpx #9
bcc :+
dex
stx playerShipY
:
lda rawEor ; no horizontal movement so process horiz joystick
down:
bit Bit3Mask ; ser for joystick down
beq left
ldx playerShipY
cpx #WORLD_END
bcs :+
inx
stx playerShipY
:
lda rawEor ; no horizontal movement so process horiz joystick
left:
bit Bit2Mask ; left sets this bit
beq right ; not set see if right is set
jsr editGameWorldLeft
lda rawEor ; no horizontal movement so process horiz joystick
right:
bit Bit1Mask ; bit set when right joystick active
beq Button_Start
jsr editGameWorldRight
Button_Start:
lda rawInput ; This is a toggle so never auto-repeat
eor #$ff ; start from source
and lastInput ; and debounce
bit Bit5Mask ; test if Start button down
beq joyDone
lda #AUDIO_UI_TICK ; make a sound
sta audioFrame
jsr serviceAudio
lda brushType ; if down, toggle the brush type between terrain and enemies
eor #1
sta brushType
jsr uiShowEditLabels ; update the HUD
joyDone:
lda rawInput ; preserve this input for next frame as last input
sta lastInput ; so that fire and bombs can be debounced
pla ; get the keyboard in accumulator
clc ; keep carry clear between routines
rts
.endproc
;-----------------------------------------------------------------------------
; Checks for a user input on keyboard or joystick
; upon exit - acc 0 means nothing, <> 0 means user input detected
.proc inputCheckForInput
rawInput = tempBlock + 20 ; internal
lda KBD
bit Bit8Mask
bne done ; if there's a key then done here
jsr inputReadJoystick ; check the joystick
sta rawInput ; keep the raw bits
eor #$ff ; invert
and lastInput ; debounce
pha ; save this
lda rawInput ; back up the raw to the last
sta lastInput
pla ; and get back the debounced bits
beq done
bit Bit7Mask ; FIRE should eq 1 player
beq :+
lda #KEY_RIGHT
bne check ; JuMP
:
bit Bit8Mask ; BOMB should eq 2 player
beq check
lda #KEY_LEFT
check:
ldx #1
:
lsr
bcs :+
inx
bne :-
:
txa
done:
and #$7f
beq :+
pha ; Save the "key"
lda #AUDIO_UI_TICK ; make a sound
sta audioFrame
jsr serviceAudio
pla ; restore the "key"
:
rts ; upon return 0 means no interaction, anything else is a user input
.endproc

Binary file not shown.

View File

@ -1,10 +0,0 @@
;-----------------------------------------------------------------------------
; logo.inc
; Part of penetrator, the zx spectrum game, made for Apple II
;
; Oliver Schmidt, 2019
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
.segment "HGR"
.incbin "logo.hgr"

View File

@ -1,56 +0,0 @@
;-----------------------------------------------------------------------------
; logodata.inc
; Part of penetrator, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2019
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
.segment "RODATA"
;-----------------------------------------------------------------------------
; x/y coordinates for lines that spell out Penetrator
dataLogoLines:
.byte $00, $0C, $00, $26
.byte $01, $0D, $07, $13
.byte $06, $14, $01, $19
.byte $02, $21, $08, $1C
.byte $09, $1B, $02, $1B
.byte $02, $1C, $05, $22
.byte $06, $22, $0B, $1D
.byte $0C, $1C, $0C, $17
.byte $0D, $17, $10, $1F
.byte $11, $1E, $11, $16
.byte $14, $1B, $19, $15
.byte $19, $14, $14, $14
.byte $14, $15, $13, $16
.byte $13, $17, $17, $1D
.byte $17, $1C, $1B, $16
.byte $1B, $15, $1D, $09
.byte $1E, $0A, $1E, $1A
.byte $1D, $14, $21, $14
.byte $22, $15, $23, $16
.byte $22, $1B, $24, $12
.byte $25, $11, $28, $11
.byte $28, $12, $29, $13
.byte $25, $19, $26, $17
.byte $27, $16, $29, $16
.byte $29, $17, $2C, $1C
.byte $2B, $1D, $29, $1F
.byte $28, $1F, $27, $1F
.byte $26, $1E, $25, $1D
.byte $25, $1C, $27, $1A
.byte $28, $1A, $29, $1A
.byte $2C, $1C, $2E, $16
.byte $2E, $15, $30, $0E
.byte $31, $10, $31, $22
.byte $2F, $1A, $34, $1A
.byte $32, $21, $35, $1B
.byte $36, $1B, $39, $1E
.byte $39, $1F, $36, $22
.byte $36, $22, $34, $20
.byte $38, $26, $3A, $1C
.byte $3B, $1B, $3C, $1B
.byte $3D, $1B, $3E, $1B
.byte $3E, $1C, $3F, $1D
dataLogoLinesEnd:

View File

@ -1,128 +0,0 @@
;-----------------------------------------------------------------------------
; macros.inc
; Part of penetrator, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2019
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
.macro printZAStr sx, sy
.if .paramcount <> 2
.error "Parameters issue for macro printZAStr"
.endif
.local textX, textY
textX = tempBlock + 10
textY = tempBlock + 11
lda sx
sta textX
lda sy
sta textY
jsr textOut
.endmacro
;-----------------------------------------------------------------------------
.macro print szText, sx, sy
.if .paramcount <> 3
.error "Parameters issue for macro print"
.endif
.local zaStrL, zaStrH, textX, textY
zaStrL = tempBlock + 1
zaStrH = tempBlock + 2
lda #<szText
sta zaStrL
lda #>szText
sta zaStrH
printZAStr sx, sy
.endmacro
;-----------------------------------------------------------------------------
.macro printBCD number, digits, force, sx, sy
.if .paramcount <> 5
.error "Parameters issue for macro printBCD"
.endif
.local zaStrL, zaStrH
zaStrL = tempBlock + 1
zaStrH = tempBlock + 2
lda #<number
sta zaStrL
lda #>number
sta zaStrH
ldy digits
ldx force
jsr textBCDtoSZ
print textNumber, sx, sy
.endmacro
;-----------------------------------------------------------------------------
.macro printBig szText, sx, sy, wx, hy
.if .paramcount <> 5
.error "Parameters issue for macro printBig"
.endif
.local zaStrL, zaStrH, width, textX, textY, height
zaStrL = tempBlock + 1
zaStrH = tempBlock + 2
textX = tempBlock + 12
textY = tempBlock + 13
width = tempBlock + 14 ; shared with drawPlotXY
height = tempBlock + 15
lda #<szText
sta zaStrL
lda #>szText
sta zaStrH
lda sx
sta textX
lda sy
sta textY
lda wx
sta width
lda hy
sta height
jsr textBigPrint
.endmacro
;-----------------------------------------------------------------------------
.macro wait time
.if .paramcount <> 1
.error "Parameters issue for macro wait"
.endif
.local loop, loopo
lda time
sta tempBlock + 20
ldx #0
loopo:
ldy #$10
loop:
dex
bne loop
dey
bne loop
dec tempBlock + 20
bne loopo
.endmacro

View File

@ -1,114 +0,0 @@
;-----------------------------------------------------------------------------
; penetrator, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2019
; This is free and unencumbered software released into the public domain.
;
; Use the ca65 assembler and make to build
;-----------------------------------------------------------------------------
; assembler directives
.debuginfo on
.listbytes unlimited
;-----------------------------------------------------------------------------
.segment "CODE"
;-----------------------------------------------------------------------------
jmp main ; This ends up at $080d (sys 2061's target)
;-----------------------------------------------------------------------------
.include "apple2.inc" ; Apple II locations from cc65
.include "defs.inc" ; constants
.include "macros.inc" ; vpoke, vpeek, print* & wait.
.include "zpvars.inc" ; Zero Page usage (variables)
.include "audio.inc" ; Play notes fro audio events
.include "input.inc" ; Keyboard/Joystick routines
.include "ui.inc" ; The front-end code
.include "edit.inc" ; In-game editor
.include "game.inc" ; All gameplay code
.include "terrain.inc" ; Code that writes the terrain to HRG
.include "draw.inc" ; Code that writes to HRG
.include "text.inc" ; The text and text printing code
.include "file.inc" ; LOAD / SAVE routine
.include "variables.inc" ; Game Variables (DATA segment)
.include "trndata.inc" ; Terrain triplets
.include "fontdata.inc" ; The ZA Spectrum font as 2bpp, 2 bytes/char
.include "logodata.inc" ; Lines to spell Penetrator and intro graphic
.include "rodata.inc" ; Read Only (RODATA segment sprites, etc)
.include "logo.inc" ; The include to include the HGR image
;-----------------------------------------------------------------------------
.segment "CODE"
;-----------------------------------------------------------------------------
.proc main
jsr mainGameSetup
:
jsr inputCheckForInput ; wait for user interaction
beq :-
jsr drawClearScreen
jsr drawPresent
:
jsr uiTitleScreen
jsr uiMainMenu
jmp :-
.endproc
;-----------------------------------------------------------------------------
.proc mainGameSetup
lda #$0
sta backLayer ; set back layer to 0
sta audioFrame ; set all audio channels to off (0)
sta numPlayers ; Init initially to 0 (not set for training)
lda PATHNAME ; length of file path
tax ; put in index
:
lda PATHNAME, x ; get character
cmp #'/' ; look backwards for directory seperator
beq :+
dex
bne :-
:
inx ; 1 or 1 past / is where the file name starts
stx pathPos ; save that location
jsr loadHighScores ; load high scores from disc
bcc cont ; on success, skip the init
ldx #((textHSEnd-textHS) - 1) ; empty the high score names to spaces
store:
lda textHS, x
beq :+ ; skip the null terminators
lda #$20 ; load the space (" ") character
sta textHS, x ; write it to the text areas
:
dex
bpl store
lda #$0
ldx #((highScoresEnd-highScores) - 1) ; set high score table scores to 0
:
sta highScores, x
dex
bpl :-
cont:
lda #(AUDIO_EXPLOSION | AUDIO_BOMB_DROP | AUDIO_FIRE | AUDIO_UI_TICK)
sta audioMask ; set the mask for default ON channels
ldx #((BitMasksEnd - BitMasks) - 1)
:
lda BitMasks, x
sta Bit1Mask, x
dex
bpl :-
rts
.endproc

View File

@ -1,19 +0,0 @@
SYMBOLS {
__EXEHDR__: type = import;
__FILETYPE__: type = export, value = $0006;
}
MEMORY {
ZP: file = "", start = $0050, size = $0100 - $0050;
HEADER: file = %O, start = $4000 - $003A, size = $003A;
MAIN: file = %O, define = yes, start = $4000, size = $BF00 - $4000;
BSS: file = "", start = $0800, size = $2000 - $0800;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
EXEHDR: load = HEADER, type = ro;
HGR: load = MAIN, type = rw;
CODE: load = MAIN, type = rw, start = $6000;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;
BSS: load = BSS, type = bss;
}

View File

@ -1,797 +0,0 @@
;-----------------------------------------------------------------------------
; rodata.inc
; Part of penetrator, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2019
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
.segment "RODATA"
;-----------------------------------------------------------------------------
; the lo byte for the memory at the start of every screen row
rowL:
.repeat $C0, Row
.byte XINSET + Row & $08 << 4 | Row & $C0 >> 1 | Row & $C0 >> 3
.endrep
;-----------------------------------------------------------------------------
; the hi byte for the memory at the start of every screen row
rowH:
.repeat $C0, Row
.byte >$0000 | Row & $07 << 2 | Row & $30 >> 4
.endrep
;-----------------------------------------------------------------------------
; pixels in format for drawPlotXY
plotPix: .byte %00001111, %01111000
;-----------------------------------------------------------------------------
; Offsets for printing the high score table on the title screen
scoreTextOffset:
.byte textHighScore1-textHS
.byte textHighScore2-textHS
.byte textHighScore3-textHS
.byte textHighScore4-textHS
.byte textHighScore5-textHS
scoreTextPosX:
.byte 10, 02, 18, 1, 19
scoreTextPosY:
.byte 8 , 16, 16, 24, 24
scorePosX:
.byte 17, 09, 25, 08, 26
;-----------------------------------------------------------------------------
radarAL:
.byte <radar0A, <(radar0U + 1), <(radar0A + 1), <(radar0U + 2)
.byte <radar1A, <(radar1U + 1), <(radar1A + 1), <(radar1U + 2)
.byte <radar2A, <(radar2U + 1), <(radar2A + 1), <(radar2U + 2)
.byte <radar3A, <(radar3U + 1), <(radar3A + 1), <(radar3U + 2)
.byte <radar4A, <(radar4U + 1), <(radar4A + 1), <(radar4U + 2)
.byte <radar5A, <(radar5U + 1), <(radar5A + 1), <(radar5U + 2)
.byte <radar6A, <(radar6U + 1), <(radar6A + 1), <(radar6U + 2)
.byte <radar7A, <(radar7U + 1), <(radar7A + 1), <(radar7U + 2)
radarAH:
.byte >radar0A, >(radar0U + 1), >(radar0A + 1), >(radar0U + 2)
.byte >radar1A, >(radar1U + 1), >(radar1A + 1), >(radar1U + 2)
.byte >radar2A, >(radar2U + 1), >(radar2A + 1), >(radar2U + 2)
.byte >radar3A, >(radar3U + 1), >(radar3A + 1), >(radar3U + 2)
.byte >radar4A, >(radar4U + 1), >(radar4A + 1), >(radar4U + 2)
.byte >radar5A, >(radar5U + 1), >(radar5A + 1), >(radar5U + 2)
.byte >radar6A, >(radar6U + 1), >(radar6A + 1), >(radar6U + 2)
.byte >radar7A, >(radar7U + 1), >(radar7A + 1), >(radar7U + 2)
radarUL:
.byte <radar0U
.byte <radar1U
.byte <radar2U
.byte <radar3U
.byte <radar4U
.byte <radar5U
.byte <radar6U
.byte <radar7U
radarUH:
.byte >radar0U
.byte >radar1U
.byte >radar2U
.byte >radar3U
.byte >radar4U
.byte >radar5U
.byte >radar6U
.byte >radar7U
radarAS:
.byte 4, 3, 2, 1
radarAD:
.byte 2, 3, 2, 3
radarAR:
.byte 1, 1, 0, 0
;-----------------------------------------------------------------------------
missileAL:
.byte <missile0A, <missile1A, <(missile0U + 1), <(missile1U + 1)
missileAH:
.byte >missile0A, >missile1A, >(missile0U + 1), >(missile1U + 1)
missileUL:
.byte <missile0U, <missile1U
missileUH:
.byte >missile0U, >missile1U
missileAD:
.byte 1, 1, 2, 2
;-----------------------------------------------------------------------------
bombAL:
.byte <bomb0A, <bomb1A
bombAH:
.byte >bomb0A, >bomb1A
bombUL:
.byte <bomb0U, <bomb1U
bombUH:
.byte >bomb0U, >bomb1U
bombH:
.byte 6, 5
;-----------------------------------------------------------------------------
monsterAL:
.byte <monsterA, <(monsterU + 1), <(monsterA+1)
monsterAH:
.byte >monsterA, >(monsterU + 1), >(monsterA+1)
monsterAS:
.byte 3, 2, 1
monsterAR:
.byte 1, 0, 0
;-----------------------------------------------------------------------------
nukeAL:
.byte <nukeA, <(nukeU + 1)
nukeAH:
.byte >nukeA, >(nukeU + 1)
nukeUL:
.byte <nukeU
nukeUH:
.byte >nukeU
nukeAD:
.byte 1, 2
;-----------------------------------------------------------------------------
explosionAL:
.byte <explosion0A
.byte <explosion1A
.byte <explosion2A
.byte <explosion3A
explosionAH:
.byte >explosion0A
.byte >explosion1A
.byte >explosion2A
.byte >explosion3A
explosionUL:
.byte <explosion0U
.byte <explosion1U
.byte <explosion2U
.byte <explosion3U
explosionUH:
.byte >explosion0U
.byte >explosion1U
.byte >explosion2U
.byte >explosion3U
;-----------------------------------------------------------------------------
layersL:
.byte <ram_layer0, <ram_layer1
layersH:
.byte >ram_layer0, >ram_layer1
;-----------------------------------------------------------------------------
; nuke, missile, monster, radar
scoreTable:
.word $0100, $0001, $0002, $0010
;-----------------------------------------------------------------------------
BitMasks:
.byte %00000001
.byte %00000010
.byte %00000100
.byte %00001000
.byte %00010000
.byte %00100000
.byte %01000000
.byte %10000000
.byte %00000011
.byte %00001100
.byte %01100000
.byte %10001110
.byte %11110000
BitMasksEnd:
;-----------------------------------------------------------------------------
; Audio delay values
explDelay:
.byte $04, $08, $06, $04
;-----------------------------------------------------------------------------
; Sprite Information
; Images to the right in human form, not Apple II form (i.e. bytes don't
; neccesarily match visuals). Rendering is bottom up so stored upside-down.
missile0A:
.byte $41 ; X.....X
.byte $41 ; X.....X
.byte $41 ; X.....X
.byte $63 ; XX...XX
.byte $63 ; XX...XX
.byte $7F ; XXXXXXX
.byte $3E ; .XXXXX.
.byte $22 ; .X...X.
.byte $3E ; .XXXXX.
.byte $1C ; ..XXX..
.byte $1C ; ..XXX..
.byte $08 ; ...X...
.byte $08 ; ...X...
.byte $08 ; ...X...
missile0U:
.byte $10, $08 ; ....X.....X...
.byte $10, $08 ; ....X.....X...
.byte $10, $08 ; ....X.....X...
.byte $30, $0C ; ....XX...XX...
.byte $30, $0C ; ....XX...XX...
.byte $70, $0F ; ....XXXXXXX...
.byte $60, $07 ; .....XXXXX....
.byte $20, $04 ; .....X...X....
.byte $60, $07 ; .....XXXXX....
.byte $40, $03 ; ......XXX.....
.byte $40, $03 ; ......XXX.....
.byte $00, $01 ; .......X......
.byte $00, $01 ; .......X......
.byte $00, $01 ; .......X......
missile1A:
.byte $55 ; X.X.X.X
.byte $5D ; X.XXX.X
.byte $49 ; X..X..X
.byte $6B ; XX.X.XX
.byte $63 ; XX...XX
.byte $7F ; XXXXXXX
.byte $3E ; .XXXXX.
.byte $22 ; .X...X.
.byte $3E ; .XXXXX.
.byte $1C ; ..XXX..
.byte $1C ; ..XXX..
.byte $08 ; ...X...
.byte $08 ; ...X...
.byte $08 ; ...X...
missile1U:
.byte $50, $0A ; ....X.X.X.X...
.byte $50, $0B ; ....X.XXX.X...
.byte $10, $09 ; ....X..X..X...
.byte $30, $0D ; ....XX.X.XX...
.byte $30, $0C ; ....XX...XX...
.byte $70, $0F ; ....XXXXXXX...
.byte $60, $07 ; .....XXXXX....
.byte $20, $04 ; .....X...X....
.byte $60, $07 ; .....XXXXX....
.byte $40, $03 ; ......XXX.....
.byte $40, $03 ; ......XXX.....
.byte $00, $01 ; .......X......
.byte $00, $01 ; .......X......
.byte $00, $01 ; .......X......
radar0A:
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $70, $07 ; ....XXXXXX....
.byte $70, $07 ; ....XXXXXX....
.byte $20, $02 ; .....X..X.....
.byte $70, $07 ; ....XXXXXX....
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $7E, $3F ; .XXXXXXXXXXXX.
.byte $7F, $7F ; XXXXXXXXXXXXXX
.byte $7F, $7F ; XXXXXXXXXXXXXX
.byte $7F, $7F ; XXXXXXXXXXXXXX
.byte $7E, $3F ; .XXXXXXXXXXXX.
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $70, $07 ; ....XXXXXX....
.byte $40, $01 ; ......XX......
.byte $40, $01 ; ......XX......
radar0U:
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $24, $00 ; .........X..X........
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $60, $7F, $07 ; .....XXXXXXXXXXXX....
.byte $70, $7F, $0F ; ....XXXXXXXXXXXXXX...
.byte $70, $7F, $0F ; ....XXXXXXXXXXXXXX...
.byte $70, $7F, $0F ; ....XXXXXXXXXXXXXX...
.byte $60, $7F, $07 ; .....XXXXXXXXXXXX....
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $18, $00 ; ..........XX.........
.byte $00, $18, $00 ; ..........XX.........
radar1A:
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $70, $07 ; ....XXXXXX....
.byte $70, $07 ; ....XXXXXX....
.byte $20, $02 ; .....X..X.....
.byte $78, $03 ; ...XXXXXX.....
.byte $7C, $01 ; ..XXXXXX......
.byte $7C, $03 ; ..XXXXXXX.....
.byte $7C, $07 ; ..XXXXXXXX....
.byte $78, $0F ; ...XXXXXXXX...
.byte $70, $0F ; ....XXXXXXX...
.byte $60, $0F ; .....XXXXXX...
.byte $70, $0F ; ....XXXXXXX...
.byte $58, $07 ; ...XX.XXXX....
.byte $08, $02 ; ...X....X.....
.byte $00, $00 ; ..............
radar1U:
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $24, $00 ; .........X..X........
.byte $00, $3F, $00 ; .......XXXXXX........
.byte $40, $1F, $00 ; ......XXXXXX.........
.byte $40, $3F, $00 ; ......XXXXXXX........
.byte $40, $7F, $00 ; ......XXXXXXXX.......
.byte $00, $7F, $01 ; .......XXXXXXXX......
.byte $00, $7E, $01 ; ........XXXXXXX......
.byte $00, $7C, $01 ; .........XXXXXX......
.byte $00, $7E, $01 ; ........XXXXXXX......
.byte $00, $7B, $00 ; .......XX.XXXX.......
.byte $00, $21, $00 ; .......X....X........
.byte $00, $00, $00 ; .....................
radar2A:
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $70, $07 ; ....XXXXXX....
.byte $70, $07 ; ....XXXXXX....
.byte $20, $02 ; .....X..X.....
.byte $70, $03 ; ....XXXXX.....
.byte $78, $01 ; ...XXXXX......
.byte $7C, $03 ; ..XXXXXXX.....
.byte $60, $07 ; .....XXXXX....
.byte $40, $07 ; ......XXXX....
.byte $40, $07 ; ......XXXX....
.byte $60, $07 ; .....XXXXX....
.byte $30, $07 ; ....XX.XXX....
.byte $18, $03 ; ...XX..XX.....
.byte $00, $01 ; .......X......
.byte $00, $00 ; ..............
radar2U:
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $24, $00 ; .........X..X........
.byte $00, $3E, $00 ; ........XXXXX........
.byte $00, $1F, $00 ; .......XXXXX.........
.byte $40, $3F, $00 ; ......XXXXXXX........
.byte $00, $7C, $00 ; .........XXXXX.......
.byte $00, $78, $00 ; ..........XXXX.......
.byte $00, $78, $00 ; ..........XXXX.......
.byte $00, $7C, $00 ; .........XXXXX.......
.byte $00, $76, $00 ; ........XX.XXX.......
.byte $00, $33, $00 ; .......XX..XX........
.byte $00, $10, $00 ; ...........X.........
.byte $00, $00, $00 ; .....................
radar3A:
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $70, $07 ; ....XXXXXX....
.byte $70, $07 ; ....XXXXXX....
.byte $20, $02 ; .....X..X.....
.byte $78, $03 ; ...XXXXXX.....
.byte $7C, $01 ; ..XXXXXX......
.byte $44, $03 ; ..X...XXX.....
.byte $04, $07 ; ..X....XXX....
.byte $64, $0E ; ..X..XX.XXX...
.byte $68, $0C ; ...X.XX..XX...
.byte $10, $08 ; ....X.....X...
.byte $30, $08 ; ....XX....X...
.byte $48, $04 ; ...X..X..X....
.byte $08, $03 ; ...X...XX.....
.byte $00, $00 ; ..............
radar3U:
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $24, $00 ; .........X..X........
.byte $00, $3F, $00 ; .......XXXXXX........
.byte $40, $1F, $00 ; ......XXXXXX.........
.byte $40, $38, $00 ; ......X...XXX........
.byte $40, $70, $00 ; ......X....XXX.......
.byte $40, $6C, $01 ; ......X..XX.XXX......
.byte $00, $4D, $01 ; .......X.XX..XX......
.byte $00, $02, $01 ; ........X.....X......
.byte $00, $06, $01 ; ........XX....X......
.byte $00, $49, $00 ; .......X..X..X.......
.byte $00, $31, $00 ; .......X...XX........
.byte $00, $00, $00 ; .....................
radar4A:
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $70, $07 ; ....XXXXXX....
.byte $70, $07 ; ....XXXXXX....
.byte $20, $02 ; .....X..X.....
.byte $70, $07 ; ....XXXXXX....
.byte $0C, $18 ; ..XX......XX..
.byte $02, $20 ; .X..........X.
.byte $01, $40 ; X............X
.byte $41, $41 ; X.....XX.....X
.byte $41, $41 ; X.....XX.....X
.byte $42, $21 ; .X....XX....X.
.byte $4C, $19 ; ..XX..XX..XX..
.byte $70, $07 ; ....XXXXXX....
.byte $40, $01 ; ......XX......
.byte $40, $01 ; ......XX......
radar4U:
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $24, $00 ; .........X..X........
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $40, $01, $03 ; ......XX......XX.....
.byte $20, $00, $04 ; .....X..........X....
.byte $10, $00, $08 ; ....X............X...
.byte $10, $18, $08 ; ....X.....XX.....X...
.byte $10, $18, $08 ; ....X.....XX.....X...
.byte $20, $18, $04 ; .....X....XX....X....
.byte $40, $19, $03 ; ......XX..XX..XX.....
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $18, $00 ; ..........XX.........
.byte $00, $18, $00 ; ..........XX.........
radar5A:
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $70, $07 ; ....XXXXXX....
.byte $70, $07 ; ....XXXXXX....
.byte $20, $02 ; .....X..X.....
.byte $60, $0F ; .....XXXXXX...
.byte $40, $1F ; ......XXXXXX..
.byte $60, $11 ; .....XXX...X..
.byte $70, $10 ; ....XXX....X..
.byte $38, $13 ; ...XXX.XX..X..
.byte $18, $0B ; ...XX..XX.X...
.byte $08, $04 ; ...X.....X....
.byte $08, $06 ; ...X....XX....
.byte $10, $09 ; ....X..X..X...
.byte $60, $08 ; .....XX...X...
.byte $00, $00 ; ..............
radar5U:
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $24, $00 ; .........X..X........
.byte $00, $7C, $01 ; .........XXXXXX......
.byte $00, $78, $03 ; ..........XXXXXX.....
.byte $00, $1C, $02 ; .........XXX...X.....
.byte $00, $0E, $02 ; ........XXX....X.....
.byte $00, $37, $02 ; .......XXX.XX..X.....
.byte $00, $33, $01 ; .......XX..XX.X......
.byte $00, $41, $00 ; .......X.....X.......
.byte $00, $61, $00 ; .......X....XX.......
.byte $00, $12, $01 ; ........X..X..X......
.byte $00, $0C, $01 ; .........XX...X......
.byte $00, $00, $00 ; .....................
radar6A:
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $70, $07 ; ....XXXXXX....
.byte $70, $07 ; ....XXXXXX....
.byte $20, $02 ; .....X..X.....
.byte $60, $07 ; .....XXXXX....
.byte $40, $0F ; ......XXXXX...
.byte $60, $1F ; .....XXXXXXX..
.byte $70, $03 ; ....XXXXX.....
.byte $70, $01 ; ....XXXX......
.byte $70, $01 ; ....XXXX......
.byte $70, $03 ; ....XXXXX.....
.byte $70, $06 ; ....XXX.XX....
.byte $60, $0C ; .....XX..XX...
.byte $40, $00 ; ......X.......
.byte $00, $00 ; ..............
radar6U:
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $24, $00 ; .........X..X........
.byte $00, $7C, $00 ; .........XXXXX.......
.byte $00, $78, $01 ; ..........XXXXX......
.byte $00, $7C, $03 ; .........XXXXXXX.....
.byte $00, $3E, $00 ; ........XXXXX........
.byte $00, $1E, $00 ; ........XXXX.........
.byte $00, $1E, $00 ; ........XXXX.........
.byte $00, $3E, $00 ; ........XXXXX........
.byte $00, $6E, $00 ; ........XXX.XX.......
.byte $00, $4C, $01 ; .........XX..XX......
.byte $00, $08, $00 ; ..........X..........
.byte $00, $00, $00 ; .....................
radar7A:
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $7C, $1F ; ..XXXXXXXXXX..
.byte $70, $07 ; ....XXXXXX....
.byte $70, $07 ; ....XXXXXX....
.byte $20, $02 ; .....X..X.....
.byte $60, $0F ; .....XXXXXX...
.byte $40, $1F ; ......XXXXXX..
.byte $60, $1F ; .....XXXXXXX..
.byte $70, $1F ; ....XXXXXXXX..
.byte $78, $0F ; ...XXXXXXXX...
.byte $78, $07 ; ...XXXXXXX....
.byte $78, $03 ; ...XXXXXX.....
.byte $78, $07 ; ...XXXXXXX....
.byte $70, $0D ; ....XXXX.XX...
.byte $20, $08 ; .....X....X...
.byte $00, $00 ; ..............
radar7U:
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $40, $7F, $03 ; ......XXXXXXXXXX.....
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $24, $00 ; .........X..X........
.byte $00, $7C, $01 ; .........XXXXXX......
.byte $00, $78, $03 ; ..........XXXXXX.....
.byte $00, $7C, $03 ; .........XXXXXXX.....
.byte $00, $7E, $03 ; ........XXXXXXXX.....
.byte $00, $7F, $01 ; .......XXXXXXXX......
.byte $00, $7F, $00 ; .......XXXXXXX.......
.byte $00, $3F, $00 ; .......XXXXXX........
.byte $00, $7F, $00 ; .......XXXXXXX.......
.byte $00, $5E, $01 ; ........XXXX.XX......
.byte $00, $04, $01 ; .........X....X......
.byte $00, $00, $00 ; .....................
explosion0A:
.byte $04, $00 ; ..X...........
.byte $0C, $00 ; ..XX..........
.byte $00, $41 ; .......X.....X
.byte $00, $00 ; ..............
.byte $00, $10 ; ...........X..
.byte $49, $01 ; X..X..XX......
.byte $60, $07 ; .....XXXXX....
.byte $60, $0F ; .....XXXXXX...
.byte $60, $2F ; .....XXXXXX.X.
.byte $60, $03 ; .....XXXX.....
.byte $08, $02 ; ...X....X.....
.byte $00, $10 ; ...........X..
.byte $30, $00 ; ....XX........
.byte $31, $00 ; X...XX........
.byte $01, $62 ; X.......X...XX
.byte $00, $00 ; ..............
explosion0U:
.byte $20, $00, $00 ; .....X...............
.byte $60, $00, $00 ; .....XX..............
.byte $00, $08, $04 ; ..........X.....X....
.byte $00, $00, $00 ; .....................
.byte $00, $00, $01 ; ..............X......
.byte $48, $0C, $00 ; ...X..X..XX..........
.byte $00, $3E, $00 ; ........XXXXX........
.byte $00, $7E, $00 ; ........XXXXXX.......
.byte $00, $7E, $02 ; ........XXXXXX.X.....
.byte $00, $1E, $00 ; ........XXXX.........
.byte $40, $10, $00 ; ......X....X.........
.byte $00, $00, $01 ; ..............X......
.byte $00, $03, $00 ; .......XX............
.byte $08, $03, $00 ; ...X...XX............
.byte $08, $10, $06 ; ...X.......X...XX....
.byte $00, $00, $00 ; .....................
explosion1A:
.byte $06, $00 ; .XX...........
.byte $04, $42 ; ..X.....X....X
.byte $00, $00 ; ..............
.byte $00, $20 ; ............X.
.byte $44, $01 ; ..X...XX......
.byte $10, $0D ; ....X..X.XX...
.byte $50, $17 ; ....X.XXXX.X..
.byte $60, $0A ; .....XX.X.X...
.byte $60, $0C ; .....XX..XX...
.byte $68, $41 ; ...X.XXX.....X
.byte $18, $02 ; ...XX...X.....
.byte $00, $08 ; ..........X...
.byte $00, $20 ; ............X.
.byte $30, $00 ; ....XX........
.byte $14, $40 ; ..X.X........X
.byte $00, $04 ; .........X....
explosion1U:
.byte $30, $00, $00 ; ....XX...............
.byte $20, $10, $04 ; .....X.....X....X....
.byte $00, $00, $00 ; .....................
.byte $00, $00, $02 ; ...............X.....
.byte $20, $0C, $00 ; .....X...XX..........
.byte $00, $69, $00 ; .......X..X.XX.......
.byte $00, $3D, $01 ; .......X.XXXX.X......
.byte $00, $56, $00 ; ........XX.X.X.......
.byte $00, $66, $00 ; ........XX..XX.......
.byte $40, $0E, $04 ; ......X.XXX.....X....
.byte $40, $11, $00 ; ......XX...X.........
.byte $00, $40, $00 ; .............X.......
.byte $00, $00, $02 ; ...............X.....
.byte $00, $03, $00 ; .......XX............
.byte $20, $01, $04 ; .....X.X........X....
.byte $00, $20, $00 ; ............X........
explosion2A:
.byte $02, $04 ; .X.......X....
.byte $00, $00 ; ..............
.byte $20, $40 ; .....X.......X
.byte $01, $21 ; X......X....X.
.byte $04, $09 ; ..X....X..X...
.byte $10, $00 ; ....X.........
.byte $10, $14 ; ....X....X.X..
.byte $24, $20 ; ..X..X......X.
.byte $20, $08 ; .....X....X...
.byte $12, $00 ; .X..X.........
.byte $08, $02 ; ...X....X.....
.byte $0A, $21 ; .X.X...X....X.
.byte $00, $00 ; ..............
.byte $10, $40 ; ....X........X
.byte $04, $00 ; ..X...........
.byte $09, $40 ; X..X.........X
explosion2U:
.byte $10, $20, $00 ; ....X.......X........
.byte $00, $00, $00 ; .....................
.byte $00, $02, $04 ; ........X.......X....
.byte $08, $08, $02 ; ...X......X....X.....
.byte $20, $48, $00 ; .....X....X..X.......
.byte $00, $01, $00 ; .......X.............
.byte $00, $21, $01 ; .......X....X.X......
.byte $20, $02, $02 ; .....X..X......X.....
.byte $00, $42, $00 ; ........X....X.......
.byte $10, $01, $00 ; ....X..X.............
.byte $40, $10, $00 ; ......X....X.........
.byte $50, $08, $02 ; ....X.X...X....X.....
.byte $00, $00, $00 ; .....................
.byte $00, $01, $04 ; .......X........X....
.byte $20, $00, $00 ; .....X...............
.byte $48, $00, $04 ; ...X..X.........X....
explosion3A:
.byte $00, $00 ; ..............
.byte $02, $10 ; .X.........X..
.byte $20, $04 ; .....X...X....
.byte $01, $01 ; X......X......
.byte $00, $40 ; .............X
.byte $04, $00 ; ..X...........
.byte $08, $10 ; ...X.......X..
.byte $41, $00 ; X.....X.......
.byte $00, $20 ; ............X.
.byte $01, $01 ; X......X......
.byte $10, $00 ; ....X.........
.byte $00, $08 ; ..........X...
.byte $02, $02 ; .X......X.....
.byte $04, $00 ; ..X...........
.byte $00, $10 ; ...........X..
.byte $01, $00 ; X.............
explosion3U:
.byte $00, $00, $00 ; .....................
.byte $10, $00, $01 ; ....X.........X......
.byte $00, $22, $00 ; ........X...X........
.byte $08, $08, $00 ; ...X......X..........
.byte $00, $00, $04 ; ................X....
.byte $20, $00, $00 ; .....X...............
.byte $40, $00, $01 ; ......X.......X......
.byte $08, $04, $00 ; ...X.....X...........
.byte $00, $00, $02 ; ...............X.....
.byte $08, $08, $00 ; ...X......X..........
.byte $00, $01, $00 ; .......X.............
.byte $00, $40, $00 ; .............X.......
.byte $10, $10, $00 ; ....X......X.........
.byte $20, $00, $00 ; .....X...............
.byte $00, $00, $01 ; ..............X......
.byte $08, $00, $00 ; ...X.................
monsterA:
.byte $78, $00 ; ...XXXX.......
.byte $4C, $01 ; ..XX..XX......
.byte $7C, $01 ; ..XXXXXX......
.byte $7E, $03 ; .XXXXXXXX.....
.byte $37, $07 ; XXX.XX.XXX....
.byte $33, $06 ; XX..XX..XX....
.byte $33, $06 ; XX..XX..XX....
.byte $7B, $06 ; XX.XXXX.XX....
.byte $7F, $07 ; XXXXXXXXXX....
.byte $7E, $03 ; .XXXXXXXX.....
.byte $7F, $07 ; XXXXXXXXXX....
.byte $7B, $06 ; XX.XXXX.XX....
.byte $01, $04 ; X........X....
monsterU:
.byte $00, $0F ; .......XXXX...
.byte $40, $19 ; ......XX..XX..
.byte $40, $1F ; ......XXXXXX..
.byte $60, $3F ; .....XXXXXXXX.
.byte $70, $76 ; ....XXX.XX.XXX
.byte $30, $66 ; ....XX..XX..XX
.byte $30, $66 ; ....XX..XX..XX
.byte $30, $6F ; ....XX.XXXX.XX
.byte $70, $7F ; ....XXXXXXXXXX
.byte $60, $3F ; .....XXXXXXXX.
.byte $70, $7F ; ....XXXXXXXXXX
.byte $30, $6F ; ....XX.XXXX.XX
.byte $10, $40 ; ....X........X
nukeA:
.byte $3F ; XXXXXX.
.byte $12 ; .X..X..
.byte $0C ; ..XX...
.byte $12 ; .X..X..
.byte $2D ; X.XX.X.
.byte $2D ; X.XX.X.
.byte $12 ; .X..X..
.byte $0C ; ..XX...
nukeU:
.byte $70, $07 ; ....XXXXXX....
.byte $20, $02 ; .....X..X.....
.byte $40, $01 ; ......XX......
.byte $20, $02 ; .....X..X.....
.byte $50, $05 ; ....X.XX.X....
.byte $50, $05 ; ....X.XX.X....
.byte $20, $02 ; .....X..X.....
.byte $40, $01 ; ......XX......
bomb0A:
.byte $04 ; ..X....
.byte $04 ; ..X....
.byte $0E ; .XXX...
.byte $1F ; XXXXX..
.byte $15 ; X.X.X..
.byte $11 ; X...X..
bomb0U:
.byte $40, $00 ;......X.......
.byte $40, $00 ;......X.......
.byte $60, $01 ;.....XXX......
.byte $70, $03 ;....XXXXX.....
.byte $50, $02 ;....X.X.X.....
.byte $10, $02 ;....X...X.....
bomb1A:
.byte $07 ; XXX....
.byte $0C ; ..XX...
.byte $3E ; .XXXXX.
.byte $0C ; ..XX...
.byte $07 ; XXX....
bomb1U:
.byte $70, $00 ; ....XXX.......
.byte $40, $01 ; ......XX......
.byte $60, $07 ; .....XXXXX....
.byte $40, $01 ; ......XX......
.byte $70, $00 ; ....XXX.......
shipA:
.byte $7C, $7F, $03 ; ..XXXXXXXXXXXXXX.....
.byte $78, $03, $00 ; ...XXXXXX............
.byte $70, $1F, $00 ; ....XXXXXXXX.........
.byte $60, $7F, $0F ; .....XXXXXXXXXXXXX...
.byte $60, $7F, $7F ; .....XXXXXXXXXXXXXXXX
.byte $60, $63, $07 ; .....XXXX...XXXXX....
.byte $60, $31, $00 ; .....XXX...XX........
.byte $70, $1F, $00 ; ....XXXXXXXX.........
.byte $78, $03, $00 ; ...XXXXXX............
.byte $7C, $00, $00 ; ..XXXXX..............
.byte $1E, $00, $00 ; .XXXX................
.byte $7F, $07, $00 ; XXXXXXXXXX...........
shipU:
.byte $40, $7F, $3F, $00 ; ......XXXXXXXXXXXXXX.....
.byte $00, $3F, $00, $00 ; .......XXXXXX............
.byte $00, $7E, $07, $00 ; ........XXXXXXXXX........
.byte $00, $7C, $7F, $01 ; .........XXXXXXXXXXXXX...
.byte $00, $7C, $7F, $0F ; .........XXXXXXXXXXXXXXXX
.byte $00, $3C, $78, $00 ; .........XXXX....XXXX....
.byte $00, $1C, $0C, $00 ; .........XXX....XX.......
.byte $00, $7E, $07, $00 ; ........XXXXXXXXX........
.byte $00, $3F, $00, $00 ; .......XXXXXX............
.byte $40, $0F, $00, $00 ; ......XXXXX..............
.byte $60, $03, $00, $00 ; .....XXXX................
.byte $70, $7F, $00, $00 ; ....XXXXXXXXXX...........

View File

@ -1,402 +0,0 @@
;-----------------------------------------------------------------------------
; terrain.inc
; Part of penetrator, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2019
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
.segment "CODE"
;-----------------------------------------------------------------------------
.proc terrainShow
zaIndex = tempBlock + 1
zaWorldBot = tempBlock + 2
zaWorldTop = tempBlock + 3
zaSide = tempBlock + 4
ldy #WORLD_START ; start row
lda #(WORLD_END - WORLD_START + 1) ; no of rows to clear
ldx backLayer ; inactive (back) layer
jsr drawClearRows ; clean the part where the world must draw
lda terrainOrigin
lsr
sta zScreenCol
ldy bufferDraw ; make enemyBuffer relative to screen col 0
dey ; but back up 1 to the last drawn height
lda worldBBuffer, y ; prime the drawing with these heights
sta zaWorldBot ; as the last height is where the col 0
lda worldTBuffer, y ; draw needs to come from
sta zaWorldTop
iny ; get back to col 0 equivalent index
sty zaIndex ; and save this index
loop:
lda #0
sta zaSide
lda worldBBuffer, y
ldy zaWorldBot ; get the last height
sta zaWorldBot ; save new bottom as last
jsr terrainDrawLeftColumn
inc zaSide
ldy zaIndex
lda worldTBuffer, y
ldy zaWorldTop ; get the last height
sta zaWorldTop ; save new bottom as last
cmp #9
bcc :+
jsr terrainDrawLeftColumn
:
lda #0
sta zaSide
inc zaIndex
ldy zaIndex
lda worldBBuffer, y
ldy zaWorldBot ; get the last height
sta zaWorldBot ; save new bottom as last
jsr terrainDrawRightColumn
inc zaSide
ldy zaIndex
lda worldTBuffer, y
ldy zaWorldTop ; get the last height
sta zaWorldTop ; save new bottom as last
cmp #9
bcc :+
jsr terrainDrawRightColumn
:
ldy zaIndex
cpy bufferInsert
beq done
iny
sty zaIndex
inc zScreenCol
bne loop
done:
clc
rts
.endproc
;-----------------------------------------------------------------------------
; y is last height, a is new height
.proc terrainDrawLeftColumn
zaSide = tempBlock + 4
zaDiff = tempBlock + 5
zaDir = tempBlock + 6 ; 2 bytes used
sty zaDiff
sec
sbc zaDiff ; get the delta (new - old)
tax ; save delta in x
bcs eqdown ; new .ge. old
up: ; new < old so go up
lda rowL, y
adc zScreenCol
sta writeUpStart + 1
lda rowH, y
adc zVramH
sta writeUpStart + 2
lda #%00000011 ; start with a 2 pixel flat area
writeUpStart:
sta PLACEHOLDER
dey ; go 1 row up
inx
beq skup ; if at new height now, skip the "up line" portion
:
lda rowL, y ; draw the "up line" portion now
adc zScreenCol
sta writeUp + 1
lda rowH, y
adc zVramH
sta writeUp + 2
lda #%00000100 ; write a single pixel up the rows
writeUp:
sta PLACEHOLDER
dey ; row up
inx
bne :- ; keep going till old .eq. new
skup:
lda rowL, y ; finish off the transition
adc zScreenCol
sta writeUpEnd + 1
lda rowH, y
adc zVramH
sta writeUpEnd + 2
lda #%00001000 ; by writing a pixel to connect to new
writeUpEnd:
sta PLACEHOLDER ; (which will become old, in next column, to draw from)
lda #$ff
ldx zaSide
sta zaDir, x
rts
eqdown:
clc ; carry still set from subtract
beq eq ; if new .eq. old it's a flat line
down: ; new > old so go down - see up, same but inc|dec is reversed
lda rowL, y
adc zScreenCol
sta writeDownStart + 1
lda rowH, y
adc zVramH
sta writeDownStart + 2
lda #%00000011
writeDownStart:
sta PLACEHOLDER
iny
dex
beq skdn
:
lda rowL, y
adc zScreenCol
sta writeDown + 1
lda rowH, y
adc zVramH
sta writeDown + 2
lda #%00000100
writeDown:
sta PLACEHOLDER
iny
dex
bne :-
skdn:
lda rowL, y
adc zScreenCol
sta writeDownEnd + 1
lda rowH, y
adc zVramH
sta writeDownEnd + 2
lda #%00001000
writeDownEnd:
sta PLACEHOLDER
lda #$01
ldx zaSide
sta zaDir, x
rts
eq: ; flat line from old to new when equal
lda rowL, y
adc zScreenCol
sta writeFlat + 1
lda rowH, y
adc zVramH
sta writeFlat + 2
lda #%00001111
writeFlat: ; 4 pixels in a line
sta PLACEHOLDER
lda #$00
ldx zaSide
sta zaDir, x
rts
.endproc
;-----------------------------------------------------------------------------
; y is last height, a is new height
.proc terrainDrawRightColumn
zaSide = tempBlock + 4
zaDiff = tempBlock + 5
zaDir = tempBlock + 6 ; 2 bytes used
zaSaveX = tempBlock + 8
sty zaDiff
sec
sbc zaDiff ; get the delta (new - old)
tax ; save delta in x
bcc up
jmp eqdown ; new .ge. old
up: ; new < old so go up
lda rowL, y
adc zScreenCol
sta writeUpStart + 1
sta writeUpStart + 4
lda rowH, y
adc zVramH
sta writeUpStart + 2
sta writeUpStart + 5
lda #%00010000 ; start with a 2 pixel flat area
writeUpStart:
ora PLACEHOLDER
sta PLACEHOLDER
dey ; go 1 row up
inx
beq skup ; if at new height now, skip the "up line" portion
stx zaSaveX
ldx zaSide
lda zaDir, x
ldx zaSaveX
cmp #1
bne fastUp
clc
:
lda rowL, y ; draw the "up line" portion now
adc zScreenCol
sta writeUp + 1
sta writeUp + 4
lda rowH, y
adc zVramH
sta writeUp + 2
sta writeUp + 5
lda #%00100000 ; write a single pixel up the rows
writeUp:
ora PLACEHOLDER
sta PLACEHOLDER
dey ; row up
inx
bne :- ; keep going till old .eq. new
beq skup
fastUp:
clc
:
lda rowL, y ; draw the "up line" portion now
adc zScreenCol
sta writeUpFast + 1
lda rowH, y
adc zVramH
sta writeUpFast + 2
lda #%00100000 ; write a single pixel up the rows
writeUpFast:
sta PLACEHOLDER
dey ; row up
inx
bne :- ; keep going till old .eq. new
skup:
lda rowL, y ; finish off the transition
adc zScreenCol
sta writeUpEnd + 1
sta writeUpEnd + 4
lda rowH, y
adc zVramH
sta writeUpEnd + 2
sta writeUpEnd + 5
lda #%01000000 ; by writing a pixel to connect to new
writeUpEnd:
ora PLACEHOLDER
sta PLACEHOLDER ; (which will become old, in next column, to draw from)
rts
eqdown:
clc ; carry still set from subtract
bne down ; if new .eq. old it's a flat line
jmp eq
down: ; new > old so go down - see up, same but inc|dec is reversed
lda rowL, y
adc zScreenCol
sta writeDownStart + 1
sta writeDownStart + 4
lda rowH, y
adc zVramH
sta writeDownStart + 2
sta writeDownStart + 5
lda #%00010000
writeDownStart:
ora PLACEHOLDER
sta PLACEHOLDER
iny
dex
beq skdn
stx zaSaveX
ldx zaSide
lda zaDir, x
ldx zaSaveX
cmp #$ff
bne fastDown
clc
:
lda rowL, y
adc zScreenCol
sta writeDown + 1
sta writeDown + 4
lda rowH, y
adc zVramH
sta writeDown + 2
sta writeDown + 5
lda #%00100000
writeDown:
ora PLACEHOLDER
sta PLACEHOLDER
iny
dex
bne :-
beq skdn
fastDown:
clc
:
lda rowL, y
adc zScreenCol
sta writeDownFast + 1
lda rowH, y
adc zVramH
sta writeDownFast + 2
lda #%00100000
writeDownFast:
sta PLACEHOLDER
iny
dex
bne :-
skdn:
lda rowL, y
adc zScreenCol
sta writeDownEnd + 1
sta writeDownEnd + 4
lda rowH, y
adc zVramH
sta writeDownEnd + 2
sta writeDownEnd + 5
lda #%01000000
writeDownEnd:
ora PLACEHOLDER
sta PLACEHOLDER
rts
eq: ; flat line from old to new when equal
lda rowL, y
adc zScreenCol
sta writeFlat + 1
sta writeFlat + 4
lda rowH, y
adc zVramH
sta writeFlat + 2
sta writeFlat + 5
lda #%01110000
writeFlat: ; 4 pixels in a line
ora PLACEHOLDER
sta PLACEHOLDER
rts
.endproc

View File

@ -1,389 +0,0 @@
;-----------------------------------------------------------------------------
; text.inc
; Part of penetrator, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2019
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
.segment "RODATA"
.feature string_escapes
; In game text
textTopLine: .asciiz "Stage . Player - - Score 0"
textDanger: .asciiz "Danger"
textShips: .asciiz "Ships"
textTrainer: .asciiz "Trainer"
textPlayer: .asciiz "P L A Y E R "
; title screen
textHighScores: .asciiz "High Scores"
textPhilip: .asciiz " Written by - Philip Mitchell - "
textCopyright: .asciiz "** Copyright \"Beam Software\" **"
textApple2: .asciiz " Apple II version by "
textStefan: .asciiz " Stefan Wessels, Dec 2019 "
textSupport: .asciiz " Lots of great Apple II "
textOliver: .asciiz " Support from Oliver Schmidt "
textSource: .asciiz " Source on GitHub: "
textGitHub: .asciiz " StewBC/penetrator-apple2 "
textGameOver: .asciiz "********** GAME OVER **********"
; main menu
textInstructions: .asciiz "INSTRUCTIONS"
textPress: .asciiz "PRESS"
textUnderline: .asciiz "-----"
textOneTwo: .asciiz "\"1\" OR \"2\" FOR NUMBER OF PLAYERS"
textTrain: .asciiz "\"T\" FOR TRAINING CONTROL CENTER"
textEdit: .asciiz "\"E\" FOR THE LANDSCAPE EDITOR"
textLoad: .asciiz "\"L\" TO LOAD ANOTHER LANDSCAPE"
textSirens: .asciiz "\"S\" SET AUDIO: "
textQuit: .asciiz "\"Q\" QUIT"
; main menu audio options
textAudio1: .asciiz "ENGINE, SFX"
textAudio2: .asciiz "SFX "
textAudio3: .asciiz "NONE "
; training mode menu
textTrainingMode: .asciiz "TRAINING MODE"
textPressStage: .asciiz "PRESS NUMBER OF DESIRED STAGE"
textOneToFour: .asciiz "(1 - 4) TO START."
textBackup: .asciiz "ESC to back up or exit mode"
; edit mode screen
textEditStage: .asciiz "STAGE"
textEditHelp: .byte "PRESS 'C' FOR ",$86," COMMAND SUMMARY", $00
textEditBrush: .asciiz "BRUSH: "
textEditTerrain: .asciiz "TERRAIN"
textEditEnemies: .asciiz "ENEMIES"
textEditDnArrow: .byte $85, $00
; edit help screen
textEdtHlp01: .asciiz "LANDSCAPE EDITOR COMMANDS"
textEdtHlp02: .asciiz "--------- ------ --------"
textEdtHlp03: .asciiz "JOYSTICK- MOVE THE CURSOR"
textEdtHlp04: .asciiz "KBD-B - TOGGLE BETWEEN TERRAIN"
textEdtHlp05: .asciiz " AND ENEMY BRUSHES"
textEdtHlp06: .asciiz "SPACE - CONTINIOUS MOVEMENT"
textEdtHlp07: .asciiz ""
textEdtHlp08: .asciiz "JOYBTN1 - SET TERRAIN TOP"
textEdtHlp09: .asciiz " OR PLACE A MISSILE"
textEdtHlp10: .asciiz "JOYBTN0 - SET TERRAIN BOTTOM OR"
textEdtHlp11: .asciiz " PLACE A RADAR"
textEdtHlp12: .asciiz "1 - 5 - SKIP TO STAGE"
textEdtHlp13: .asciiz "S - SAVE THIS WORLD"
textEdtHlp14: .asciiz "L - LOAD A WORLD"
textEdtHlp15: .asciiz "ERASE ENEMIES USING A/B"
textEdtHlp16: .asciiz "WITH THE ENEMIES BRUSH"
textEdtHlp17: .asciiz "ESC - END THE EDIT SESSION"
; win screen
textBonus: .asciiz "BONUS"
textPoints: .asciiz "POINTS"
text1000: .asciiz "1000"
textWow: .asciiz "WOW"
textHome: .asciiz "HOME"
; high score name entry
textCongrats: .asciiz "***** CONGRATULATIONS *****"
textHSPlayer: .asciiz "PLAYER -- "
textTop5: .asciiz "Your score is in the top 5"
textTypeName: .asciiz "Please type in your name"
; file name entry
textFileLoad: .asciiz "FILE LOAD"
textFileSave: .asciiz "FILE SAVE"
textFileLines: .asciiz "---------"
textFileInfoL: .asciiz "Load"
textFileInfoS: .asciiz "Save"
textFileInfo: .asciiz "world data"
textFileEnter: .asciiz "Please enter a file name"
textFileSuccess: .asciiz "SUCCESS."
textFileThe: .asciiz "The"
textFileFailed: .asciiz "Failed. Error Code"
hihgScoreFileName:.asciiz "PENSCORES"
;-----------------------------------------------------------------------------
.segment "CODE"
;-----------------------------------------------------------------------------
; Use the print macro to call this code
; Writes a null-terminated string to the back buffer
; temp1/2 Ptr to the string
; textX - the string draw X position (in col coords)
; textY - the string draw Y position
.proc textOut
textX = tempBlock + 10
textY = tempBlock + 11
xPos = tempBlock + 12
yPos = tempBlock + 13
zaStrL = tempBlock + 1 ; parameter - string lo
zaStrH = tempBlock + 2 ; parameter - string hi
zaFontL = tempBlock + 4 ; internal - point at the character memory Lo
zaFontH = tempBlock + 5 ; internal - point at the character memory Hi
zaFontOffset = tempBlock + 6 ; 0-15 - index from zaFont
loop:
ldy #0
lda (zaStrL), y ; get the character in the string
bne :+ ; if non-null process it
rts ; exit on 0 terminator
:
jsr setFont
lda textY ; get the screen Y for text
sta yPos ; init the row working buffer
plotLoop:
ldy yPos ; at the working row offset
lda rowL, y ; get the memory address
adc textX ; add in column (x pos of text)
sta write + 1 ; point lo at memory
lda rowH, y
adc zVramH
sta write + 2
ldy zaFontOffset ; get the offset into the font
lda (zaFontL), y ; get the actual left character byte
write:
sta PLACEHOLDER ; plot the left hand side
cpy #7
bcs nextChar ; 0-7 then done with this character (bottom always blank)
inc zaFontOffset ; move a byte for last row plotted
inc yPos ; move down a row on screen
bne plotLoop ; always take this branch
nextChar:
inc textX ; character column
inc zaStrL ; next character in string
bne loop
inc zaStrH
bne loop ; always branch back
.endproc
;-----------------------------------------------------------------------------
; Like textOut but uses drawPoltXY to plot each pixel in the text
; so you can write big strings using width and height.
; a setting of width and height both 1 results in a character that's
; 32x32 on-screen
.proc textBigPrint
zaStrL = tempBlock + 1 ; parameter - string lo
zaStrH = tempBlock + 2 ; parameter - string hi
zaBitCnt = tempBlock + 3 ; internal - how many bits to process for a byte to write
zaFontL = tempBlock + 4 ; internal - point at the character memory Lo
zaFontH = tempBlock + 5 ; internal - point at the character memory Hi
zaFontOffset = tempBlock + 6 ; internal - 0-15 - index from zaFont
width = tempBlock + 14 ; shared with drawPlotXY
height = tempBlock + 15
textX = tempBlock + 12
textY = tempBlock + 13
xPos = tempBlock + 7
yPos = tempBlock + 8
loop:
ldy #0
lda (zaStrL), y ; get the character in the string
bne :+ ; if non-null process it
rts ; exit on 0 terminator
:
jsr setFont
lda textY ; get the screen Y for text
sta yPos
inc zaFontOffset
plotLoop:
lda textX
sta xPos
ldx #6 ; each font character byte uses 7 pixels
stx zaBitCnt
ldy zaFontOffset ; get the offset into the font
lda (zaFontL), y ; get the actual left character byte
lsr
jsr drawBits
inc zaFontOffset ; go to the next line
ldy zaFontOffset
cpy #7 ; characters are 8 bytes long, care about 7
bcs nextChar ; if 16 then done with this character
lda yPos ; adjust the "plot" down a line
clc
adc height
sta yPos
bne plotLoop ; always take this branch
nextChar:
lda width ; move along in X to the next character
asl ; 6x the width + 2
asl
adc width
adc width
adc #2
adc textX ; add to current "plot" position
sta textX
inc zaStrL ; next character in string
bne loop
inc zaStrH
bne loop ; always branch back
drawBits:
lsr ; shift a bit into carry
pha ; save the shifted byte
bcc :+ ; if carry is set, need to plot a pixel
clc
ldx xPos ; get the x and y of where to plot
ldy yPos
jsr drawPlotXY ; draw the pixel
:
lda xPos ; move along one "pixel"
clc
adc width
sta xPos
pla ; restore the shifted character
dec zaBitCnt ; see if all bytes were handled
ldx zaBitCnt
bne drawBits
rts
.endproc
;-----------------------------------------------------------------------------
; Point zaFont(H|L) at the character definition for the character in the accumulator
; y register must be 0 when calling this routine
.proc setFont
zaFontL = tempBlock + 4 ; internal - point at the character memory Lo
zaFontH = tempBlock + 5 ; internal - point at the character memory Hi
zaFontOffset = tempBlock + 6 ; internal - 0-15 - index from zaFont
sty zaFontOffset ; start at 0th byte in font
sty zaFontH
sty zaFontL
sec ; subtract 32 as font starts at char 32 (space)
sbc #$20
asl ; mult 8 as that's how many bytes per char
rol zaFontH
asl
rol zaFontH
asl
rol zaFontH
adc #<font ; add in the memory location
sta zaFontL
lda #>font
adc zaFontH
sta zaFontH ; now font points at the character data
rts
.endproc
;-----------------------------------------------------------------------------
; Turns a BCD number into a text string at textNumber.
; zaStr is a ptr to the number in BCD
; y reg is the number of bytes to convert
; x reg <> 0 means print at least one digit, even if 0
.proc textBCDtoSZ
zaStrL = tempBlock + 1
zaStrH = tempBlock + 2
zaForce = tempBlock + 3
stx zaForce
dey ; zero based so -1
ldx #0
leading: ; skip leading 0's with spaces
lda #' ' ; prep buffer with two spaces
sta textNumber, x ; if the byte to output is $00
sta textNumber + 1, x ; so leading 0's are skipped
lda (zaStrL), y ; get the high byte
bit Bit8765Mask ; check 1st digit
bne loop1 ; if not zero - start printing
inx ; skip the zero by accepting the space
and #$0f ; check the 2nd digit
beq :+ ; go skip if zero
jsr digit ; print the digit
bne loop2 ; and join the main print loop
:
inx ; skip the next char in the output string
dey ; go to next byte in the BCD number
bpl leading ; keep going till all bytes done
ldy zaForce ; nothing printed - see if at least 1 digit
beq done ; needs to be printed and if no - then done
dex ; step back one digit in the string
lda #'0' ; get a zero
sta textNumber, x ; put it in the string
inx
bne done ; JuMP to done
loop: ; main loop once a digit is found
lda (zaStrL), y ; get the 2 decimal digits
loop1:
jsr both ; print them both starting with left
loop2:
dey ; next score part
bpl loop ; keep going while there are score parts
done:
lda #0 ; load a null-terminator
sta textNumber, x ; store it in the output string
rts
both:
pha ; save the 2 digits
lsr ; shift right down
lsr
lsr
lsr
jsr digit ; go print it
pla ; restore both
and #$0f ; mask off the right leaving left
digit: ; print the digit
ora #$30 ; add "0" to the decimal
sta textNumber, x ; put it in the string
inx ; advance the string pointer
rts
.endproc
;-----------------------------------------------------------------------------
; Prints the accumulator to the szHez text as 2 hex bytes
.proc toHex
ldx #0 ; offset into the szHex buffer
pha ; save a for lower 4 bits
lsr ; move upper 4 bits to lo
lsr
lsr
lsr
jsr :+ ; process upper 4 bits
pla ; restore a to process lower 4 bits
:
and #$0f ; mask to only the 4 bits now in lo
cmp #10 ; see if it's > 9
bcc :+
adc #6 ; move from 10+ to a+
:
adc #$30 ; and move to '0' and beyond
sta szHex, x ; save this in the buffer
inx ; go to next buffer location
rts ; and return to self or caller
.endproc

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,66 +0,0 @@
;-----------------------------------------------------------------------------
; variables.inc
; Part of penetrator, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2019
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
.segment "DATA"
;-----------------------------------------------------------------------------
; Player specific variables
rsStart: ; runtime stats "struct". lives MUST be 1st
lives: .res 1 ; Chances the player gets (decimal mode), indexed by activePlayer
score: .res 3 ; activePlayer's score is copied here for gameplay
stage: .res 1 ; offset to stages in worldDataStart - needed for reset
direction: .res 1 ; 0 = right, 1 = left (fly reverse through level)
makeMonster: .res NUM_STAGES ; 1 in stage offset lookup turns missiles into monsters
rsEnd:
playerStats: .res ((rsEnd-rsStart) * 2) ; 2 copies of stats, for p1 and p2 is 2p game
;-----------------------------------------------------------------------------
; High scores table saved to disc
scoresTable:
highScores:
highScore1: .res 3
highScore2: .res 3
highScore3: .res 3
highScore4: .res 3
highScore5: .res 3
highScoresEnd:
textHS:
textHighScore1: .asciiz "123456"
textHighScore2: .asciiz "123456"
textHighScore3: .asciiz "123456"
textHighScore4: .asciiz "123456"
textHighScore5: .asciiz "123456"
textHSEnd:
scoresTableEnd:
;-----------------------------------------------------------------------------
; user facing text area
textStage: .asciiz "1"
textPlayerNum: .asciiz "1"
textNumber: .asciiz "1234567" ; score display 10x score - extra digit needed
textDangerBar: .asciiz "123"
textEnd:
textFileName: .asciiz "PENEWORLD01" ; default file name
textFilePad: .asciiz "" ; This makes the null terminator on textFileName viable and a 12 char filename
textFileNameEnd:
szHex: .asciiz " "
;-----------------------------------------------------------------------------
; per "run" buffers
bombX: .res NUM_BOMBS ; 2 bombs allowed, their x values
bombY: .res NUM_BOMBS ; Y values for 2 bombs (0=available)
bombDir: .res NUM_BOMBS ; direction of travel (and thus sprite)
worldTBuffer: .res BUFLENGTH ; holds the world bottom height
worldBBuffer: .res BUFLENGTH ; holds the world top height
enemyBuffer: .res BUFLENGTH ; holds enemy sprite draw data
enemyHgtBuffer: .res BUFLENGTH ; holds enemy sprite draw height data
bulletsBuffer: .res BUFLENGTH ; holds the bullet heights (0=no bullet)
explosionBuffer: .res BUFLENGTH ; holds the explosion heights (0=no explosion)

View File

@ -1,76 +0,0 @@
;-----------------------------------------------------------------------------
; zpvars.inc
; Part of penetrator, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2019
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
.segment "ZEROPAGE"
;-----------------------------------------------------------------------------
; zero page variables
zWorldPtr: .res 2 ; where data is next read from the world stream
zVramH: .res 1 ; for HRG writes, points at the Hi of the back bank RAM
zScreenCol: .res 1 ; used for drawing - the column to draw
zEnemyCol: .res 1 ; used for enemies - the column to process
zCollision: .res 1 ; drawSprite will put a 1 in when there's a write collision
tempBlock: .res 22 ; used by different routines that need local storage
;-----------------------------------------------------------------------------
; zero page constants
; Bit patterns for the bit instruction
Bit1Mask: .res 1
Bit2Mask: .res 1
Bit3Mask: .res 1
Bit4Mask: .res 1
Bit5Mask: .res 1
Bit6Mask: .res 1
Bit7Mask: .res 1
Bit8Mask: .res 1
Bit12Mask: .res 1
Bit34Mask: .res 1
Bit76Mask: .res 1
Bit8432Mask: .res 1
Bit8765Mask: .res 1
;-----------------------------------------------------------------------------
; Game variables
numPlayers: .res 1 ; [0|1] where 0 is a 1 player game, 1 = 2 player game
activePlayer: .res 1 ; 0 for player 1, 1 for player 2
gameMode: .res 1 ; 0 for gameplay, 1 for trainer, 2 for edit
; per "run" variables
playerShipX: .res 1 ; x position in columns
playerShipY: .res 1 ; y position in rows
terrainOrigin: .res 1 ; from 0 to XSize - where to start world draw on screen
stopScrolling: .res 1 ; 1 - world will not move (for death)
playerDead: .res 1 ; 0 - gamePlay flow, > 0 players dead
monsterCnt: .res 1 ; skip # missiles before turning one into a monster
inFlight: .res 2 ; count launched missiles for launch control
victory: .res 1 ; 0 = not done, 1 = hit the nuke so done with run
nextStage: .res 1 ; -1 nothing, 0 at next stage, >0 count down
bufferInsert: .res 1 ; index where data gets added to buffers (right hand of screen)
bufferDraw: .res 1 ; index that corresponds to draw start (usually col 0 of screen)
bulletIndex: .res 1 ; like bufferDraw but bullets "travel" in opposite direction
dangerTickCount: .res 1 ; how often a dot is added to the danger line, when the world moves
dangerTickIdx: .res 1 ; the index into the text that holds the danger line of dots
moveHorz: .res 1 ; keeps track of horizontal movement - only moves every 2nd frame
moveVert: .res 1 ; keeps track of vertical movement - moves 4 rows but over 2 frames
; helper variables
updateHUD: .res 1 ; 0 - don't draw, 1+ - clean and redraw
flipFlop: .res 1 ; counter to advance explosion frames
backLayer: .res 1 ; [0|1] - Layer not shown to user *=(to be drawn to)
enemyHit: .res 1 ; the flags of the enemy destroyed in gameKillEnemy
enemyHitType: .res 1 ; 0 = nuke, 1 = missile, 2 = monster, 3 = radar, $ff - nothing
lastInput: .res 1 ; holds the value of the prev joystick frame
pause: .res 1 ; <> 0 when the game is paused
fireCoolDown: .res 1 ; decay to zero before fire allowed
pathPos: .res 1 ; index to start of file name in path
; audio variables
audioMask: .res 1 ; which audio "channels" are active (and with audioFrame)
audioFrame: .res 1 ; prioritized mask for sounds to make (msb to lsb)
audioExplFrame: .res 1 ; explosion frame index, for sound