migrate source and build files

This commit is contained in:
4am 2021-02-16 01:01:22 -05:00
parent 68b07b6fc4
commit 5df5f326db
319 changed files with 200309 additions and 0 deletions

96
Makefile Normal file
View File

@ -0,0 +1,96 @@
#
# 4sports Makefile
# assembles source code, optionally builds a disk image and mounts it
# note: Windows users should probably use winmake.bat instead
#
# original by Quinn Dunki on 2014-08-15
# One Girl, One Laptop Productions
# http://www.quinndunki.com/blondihacks
#
# adapted by 4am on 2021-02-12
#
DISK=4sports.hdv
VOLUME=INSTANT.REPLAY
# third-party tools required to build
# https://sourceforge.net/projects/acme-crossass/
ACME=acme
# https://github.com/sicklittlemonkey/cadius
# version 1.4.0 or later
CADIUS=cadius
# https://bitbucket.org/magli143/exomizer/wiki/Home
EXOMIZER=exomizer mem -q -P23 -lnone
dsk: asm
cp res/blank.hdv build/"$(DISK)" >>build/log
cp res/_FileInformation.txt build/ >>build/log
$(CADIUS) ADDFILE build/"$(DISK)" "/$(VOLUME)/" "build/LAUNCHER.SYSTEM" >>build/log
rsync -aP res/PREFS.CONF build/PREFS.CONF >> build/log
bin/padto.sh 512 build/PREFS.CONF >>build/log
for f in res/TITLE res/COVER res/HELP res/GAMES.CONF res/ATTRACT.CONF res/FX.CONF res/DFX.CONF build/PREFS.CONF res/CREDITS res/HELPTEXT res/DECRUNCH res/JOYSTICK res/Finder.Data res/Finder.Root; do $(CADIUS) ADDFILE build/"$(DISK)" "/$(VOLUME)/" "$$f" >>build/log; done
bin/buildfileinfo.sh res/TITLE.HGR "06" "4000" >>build/log
bin/buildfileinfo.sh res/TITLE.DHGR "06" "4000" >>build/log
bin/buildfileinfo.sh res/ACTION.HGR "06" "3FF8" >>build/log
bin/buildfileinfo.sh res/ACTION.DHGR "06" "3FF8" >>build/log
bin/buildfileinfo.sh res/ACTION.GR "06" "6000" >>build/log
bin/buildfileinfo.sh res/ARTWORK.SHR "06" "1FF8" >>build/log
bin/buildfileinfo.sh res/ATTRACT "04" "8000" >>build/log
bin/buildfileinfo.sh res/SS "04" "4000" >>build/log
bin/buildfileinfo.sh res/ICONS "CA" "0000" >>build/log
for f in res/TITLE.HGR res/TITLE.DHGR res/ACTION.HGR res/ACTION.DHGR res/ACTION.GR res/ARTWORK.SHR res/ATTRACT res/SS res/DEMO res/ICONS; do rm -f "$$f"/.DS_Store; $(CADIUS) ADDFOLDER build/"$(DISK)" "/$(VOLUME)/$$(basename $$f)" "$$f" >>build/log; done
$(CADIUS) ADDFOLDER build/"$(DISK)" "/$(VOLUME)/FX" "build/FX" >>build/log
for f in res/dsk/*.po; do $(CADIUS) EXTRACTVOLUME "$${f}" build/X/ >> build/log; done
rm -f build/X/**/.DS_Store build/X/**/PRODOS* build/X/**/LOADER.SYSTEM*
$(CADIUS) CREATEFOLDER build/"$(DISK)" "/$(VOLUME)/X/" >>build/log
for f in build/X/*; do $(CADIUS) ADDFOLDER build/"$(DISK)" "/$(VOLUME)/X/$$(basename $$f)" "$$f"; done >>build/log
bin/buildfileinfo.sh build/PRELAUNCH "06" "0106" >>build/log
$(CADIUS) ADDFOLDER build/"$(DISK)" "/$(VOLUME)/PRELAUNCH" "build/PRELAUNCH" >>build/log
rsync -aP --exclude=STANDARD res/GAMEHELP build/ >>build/log
for f in res/TITLE.HGR/*; do rsync --ignore-existing res/GAMEHELP/STANDARD build/GAMEHELP/$$(basename $$f); done
bin/buildfileinfo.sh build/GAMEHELP "04" "8000" >>build/log
$(CADIUS) ADDFOLDER build/"$(DISK)" "/$(VOLUME)/GAMEHELP" "build/GAMEHELP" >>build/log
bin/changebootloader.sh build/"$(DISK)" res/proboothd
asm: asmlauncher asmfx asmprelaunch
asmlauncher: md
$(ACME) -DBUILDNUMBER=`git rev-list --count HEAD` src/4sports.a 2>build/relbase.log
$(ACME) -r build/4sports.lst -DBUILDNUMBER=`git rev-list --count HEAD` -DRELBASE=`cat build/relbase.log | grep "RELBASE =" | cut -d"=" -f2 | cut -d"(" -f2 | cut -d")" -f1` src/4sports.a
asmfx: md
for f in src/fx/*.a; do grep "^\!to" $${f} >/dev/null && $(ACME) $${f} >> build/log || true; done
bin/buildfileinfo.sh build/FX "06" "6000" >>build/log
asmprelaunch: md
for f in src/prelaunch/*.a; do grep "^\!to" $${f} >/dev/null && $(ACME) $${f} >> build/log; done
for f in res/TITLE.HGR/*; do rsync --ignore-existing build/PRELAUNCH/STANDARD build/PRELAUNCH/$$(basename $$f); done
chd: dsk
chdman createhd -c none -i build/"$(DISK)" -o build/"$(DISK)".chd >>build/log
compress: md
for f in res/ACTION.HGR.UNCOMPRESSED/*; do o=res/ACTION.HGR/$$(basename $$f); [ -f "$$o" ] || ${EXOMIZER} "$$f"@0x4000 -o "$$o" >>build/log; done
#for f in res/ACTION.DHGR.UNCOMPRESSED/*; do o=res/ACTION.DHGR/$$(basename $$f); [ -f "$$o" ] || ${EXOMIZER} "$$f"@0x4000 -o "$$o" >>build/log; done
#for f in res/ARTWORK.SHR.UNCOMPRESSED/*; do o=res/ARTWORK.SHR/$$(basename $$f); [ -f "$$o" ] || ${EXOMIZER} "$$f"@0x2000 -o "$$o" >>build/log; done
attract: compress
bin/check-attract-mode.sh
bin/generate-mini-attract-mode.sh
mount: dsk
osascript bin/V2Make.scpt "`pwd`" bin/4sports.vii build/"$(DISK)"
md:
mkdir -p build/X build/FX build/PRELAUNCH build/GAMEHELP
touch build/log
clean:
rm -rf build/ || rm -rf build
all: clean dsk mount
al: all

92
README.md Normal file
View File

@ -0,0 +1,92 @@
# Building the code
## Mac OS X
You will need
- [Xcode command line tools](https://www.google.com/search?q=xcode+command+line+tools)
- [ACME](https://sourceforge.net/projects/acme-crossass/)
- [sicklittlemonkey's Cadius fork](https://github.com/sicklittlemonkey/cadius)
- [Exomizer](https://bitbucket.org/magli143/exomizer/wiki/Home)
Then open a terminal window and type
```
$ cd 4sports/
$ make
```
If all goes well, the `build/` subdirectory will contain a `4sports.hdv` image which can be mounted in emulators like [OpenEmulator](https://archive.org/details/OpenEmulatorSnapshots) or [Virtual II](http://virtualii.com/).
## Windows
You will need
- [ACME](https://sourceforge.net/projects/acme-crossass/)
- [Cadius for Windows](https://www.brutaldeluxe.fr/products/crossdevtools/cadius/)
- [Exomizer](https://bitbucket.org/magli143/exomizer/wiki/Home)
(Those tools will need to be added to your command-line PATH.)
Then open a `CMD.EXE` window and type
```
C:\> CD 4SPORTS
C:\4SPORTS> WINMAKE
```
If all goes well, the `BUILD\` subdirectory will contain a `4SPORTS.HDV` image which can be mounted in emulators like [AppleWin](https://github.com/AppleWin/AppleWin).
# Navigating the code
## Initialization
[`4sports.a`](https://github.com/a2-4am/4cade/blob/master/src/4sports.a) is the main assembler target. It builds the launcher itself. Launcher code is split into code that can be run once from main memory then discarded, and code which is relocated to the language card and persists throughout the lifetime of the launcher. As the language card is only 16KB and will also need to store some persistent data structures, memory is precious and tightly managed.
[`4sports.init.a`](https://github.com/a2-4am/4cade/blob/master/src/4sports.init.a) contains the code that is run once at program startup. First, we do some hardware detection, like how much memory you have, whether you have a joystick, and whether you have a IIgs. Then we relocate selected code to the language card. [`constants.a`](https://github.com/a2-4am/4sports/blob/master/src/constants.a) has a rough map of what ends up where, within the language card and its overlapping memory regions. Then we load and parse the global preferences file ([`PREFS.CONF`](https://github.com/a2-4am/4sports/blob/master/res/prefs.conf)) and master game list ([`GAMES.CONF`](https://github.com/a2-4am/4sports/blob/master/res/games.conf)) and store the results in the language card. Finally, we jump to the main entry point (`Reenter`). The launcher is initialized; anything left in main memory is discarded.
## Search mode
There are three major modes in the launcher: search mode, browse mode, and mega-attract mode. Search mode is the default, and it is always the first mode you enter when launching the program. [`ui.search.mode.a`](https://github.com/a2-4am/4sports/blob/master/src/ui.search.mode.a) tracks your keystrokes to determine the best match within the game list for the keys you have typed, then loads the game's title screenshot and displays the game name and other information at the bottom of the screen. If you have not yet typed any keys, it displays the title page and welcome message instead. The `InputKeys` table documents all other recognized keys.
The text ranking algorithm is in [`textrank.a`](https://github.com/a2-4am/4sports/blob/master/src/textrank.a). It was inspired by [Quicksilver](https://github.com/quicksilver/Quicksilver) but is an independent implementation.
## Browse mode
The user enters browse mode by pressing the right or down arrow key. [`ui.browse.mode.a`](https://github.com/a2-4am/4sports/blob/master/src/ui.browse.mode.a) then watches for other arrow keys and displays the next or previous game in the game list. The `BrowseKeys` table documents all other recognized keys.
## Mega-Attract mode
If the user presses `Esc` from any other mode, or does not type anything for 30 seconds, the launcher goes into Mega-Attract mode, a.k.a. screensaver mode. [`ui.attract.mode.a`](https://github.com/a2-4am/4sports/blob/master/src/ui.attract.mode.a) manages loading and executing attract mode modules. An attract mode module can be a short slideshow, a self-running demo, or just a single screenshot. Modules are listed in [`ATTRACT.CONF`](https://github.com/a2-4am/4sports/blob/master/res/attract.conf) and are run in order until end-of-file, then it starts over from the beginning. The entire cycle is quite long (several hours), and some screenshots appear in multiple slideshows, but there is no actual randomness in selecting the next attract mode module.
# Navigating the configuration files
## `GAMES.CONF`
[`GAMES.CONF`](https://github.com/a2-4am/4sports/blob/master/res/GAMES.CONF) is the master games list. It contains 1 record for every game in Total Replay. However, not every game is playable on every device, so each record also contains metadata, e.g. "this game requires a joystick," or "this game requires 128K," or "this game has a double hi-res title screen" (which is not identical to "this game requires 128K").
The format of the `GAMES.CONF` file has changed as new requirements have appeared, and it may change again in the future. There is up-to-date format information at the bottom of the file itself, which I will not duplicate here. However, in general, each record is 1 line and contains the name and flags for 1 game. The file is parsed once at program startup, and the (possibly filtered) list of available games is stored persistently in the language card.
Many records in `GAMES.CONF` do not list the game's display name, i.e. the mixed-case, human-readable name displayed in search mode, browse mode, and slideshows. Wherever possible, display names are calculated from a game's filename, so `WAVY.NAVY` is displayed as `Wavy Navy`, while `SUMMER.GAMES.II` is displayed as `Summer Games II`, and so on.
Each game's filename is used as a "foreign key" (in database terms) to build directory paths, to locate files in subdirectories, and to reference the game in other configuration files.
- A game's main executable is always `X/FILENAME/FILENAME`
- A game's HGR title screenshot is always `TITLE.HGR/FILENAME`
- A game's super hi-res box art is always `ARTWORk.SHR/FILENAME`
- A game's mini-attract mode configuration file is always `ATTRACT/FILENAME`
- Games are included in other attract mode configuration files by `FILENAME`
- The source disk image of a game (in [`res/dsk`](https://github.com/a2-4am/4sports/tree/master/res/dsk)) must have a volume name of `FILENAME`, and there must be a file in the disk image's root directory also named `FILENAME` which is the game's main executable
## `ATTRACT.CONF`
TODO
## `FX.CONF`, `DFX.CONF`
[`FX.CONF`](https://github.com/a2-4am/4sports/blob/master/res/FX.CONF) and its sister [`DFX.CONF`](https://github.com/a2-4am/4sports/blob/master/res/DFX.CONF) list the HGR and DHGR transition effects used in hi-res and double hi-res slideshows. Each record is a filename of a transition effect file, which is an executable file [assembled at build time](https://github.com/a2-4am/4sports/tree/master/src/fx) and stored in the `FX/` subdirectory. At the beginning of each slideshow, we query the global preferences to find the filename of the FX or DFX file, then update the global preferences with the next filename (wrapping around to the beginning of the list). If you watch the Mega-Attract mode long enough, you will eventually see all the transition effects, and since the cycle of transition effects is separate from the cycle of slideshows, you will eventually see the same slideshow with different transition effects.
These files are read from disk and parsed every time they are needed. Due to memory restrictions, the parsed data is not persisted.
## `PREFS.CONF`
[`PREFS.CONF`](https://github.com/a2-4am/4sports/blob/master/res/PREFS.CONF) contains persistent global state, including Mega-Attract mode state and whether cheats are enabled. There is up-to-date format information in the file itself.
This file is read and parsed once at program startup, and the parsed data is stored persistently in the language card. It is written to disk every time global state changes, which is often during Mega-Attract mode, or if the user toggles cheat mode.

BIN
bin/4sports.vii Normal file

Binary file not shown.

BIN
bin/V2Make.scpt Normal file

Binary file not shown.

12
bin/buildfileinfo.js Normal file
View File

@ -0,0 +1,12 @@
a = new ActiveXObject("scripting.filesystemobject")
fileinfo = "# This file is automatically generated\r\n"
for (b = new Enumerator(a.GetFolder(WScript.Arguments(0)).files); !b.atEnd(); b.moveNext())
{
if (b.item().Name.toUpperCase() != "_FILEINFORMATION.TXT")
{
fileinfo += "\r\n" + b.item().Name.toUpperCase() + "=Type(" + WScript.Arguments(1) + "),AuxType(" + WScript.Arguments(2) + "),Access(C3)"
}
}
fileinfo += "\r\n" + "_FileInformation.txt=Type(" + WScript.Arguments(1) + "),AuxType(" + WScript.Arguments(2) + "),Access(C3)\r\n"
a.createtextfile(WScript.Arguments(0)+"\\_FILEINFORMATION.TXT", 1).write(fileinfo)

11
bin/buildfileinfo.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/sh
indir=$1
intype=$2
inaddress=$3
cd "$indir"
rm -f _FileInformation.txt
(echo "# This file is automatically generated\n"
for f in *; do
echo "$f=Type($intype),AuxType($inaddress),Access(C3)"
done) > _FileInformation.txt

6
bin/changebootloader.js Normal file
View File

@ -0,0 +1,6 @@
a = new ActiveXObject("scripting.filesystemobject")
b = a.opentextfile(WScript.Arguments(0))
b.skip(0x200)
d = b.read(a.getfile(WScript.Arguments(0)).size-0x200)
b.close()
b=a.createtextfile(WScript.Arguments(0), 1).write(a.opentextfile(WScript.Arguments(1)).read(512)+d)

3
bin/changebootloader.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
dd of="$1" bs=1 count=512 conv=notrunc < "$2"

76
bin/check-attract-mode.sh Executable file
View File

@ -0,0 +1,76 @@
#!/bin/bash
# run from project root directory
fatal_error() {
echo "$1" "$2"
exit 1
}
check_title_slideshow() {
[ -f "$1" ] ||
fatal_error "Can't find HGR title slideshow" "$1"
cat "$1" |
grep -v "^#" |
grep -v "^\[" |
grep -v "^$" |
while read ssline; do
[ -f "$2"/"$ssline" ] ||
fatal_error "Can't find title screenshot" "$ssline"
done
}
check_action_slideshow() {
[ -f "$1" ] ||
fatal_error "Can't find HGR action slideshow" "$1"
cat "$1" |
grep -v "^#" |
grep -v "^\[" |
grep -v "^$" |
while read ssline; do
IFS="=" read -r filename gamename <<< "$ssline"
if [ -z "$gamename" ]; then
gamename=$filename
fi
[ -f "$2"/"$filename" ] ||
fatal_error "Can't find action screenshot" "$filename"
grep "^$gamename$" /tmp/games >/dev/null ||
fatal_error "Action screenshot links to non-existent game" "$gamename"
done
}
cat res/GAMES.CONF |
grep -v "^#" |
grep -v "^\[" |
grep -v "^$" |
cut -d"," -f2 |
cut -d"=" -f1 > /tmp/games
cat res/ATTRACT.CONF |
grep "=" |
grep -v "^#" |
while read line; do
IFS="=" read -r module_name module_type <<< "$line"
# echo "$module_name" "$module_type"
if [ "$module_type" = "0" ]; then
[ -f res/DEMO/"$module_name" ] ||
[ "${module_name%???}" = "SPCARTOON" ] ||
fatal_error "Can't find demo" $module_name
elif [ "$module_type" = "1" ]; then
check_title_slideshow res/SS/"$module_name" res/TITLE.HGR/
elif [ "$module_type" = "2" ]; then
check_action_slideshow res/SS/"$module_name" res/ACTION.HGR/
elif [ "$module_type" = "3" ]; then
check_title_slideshow res/SS/"$module_name" res/TITLE.DHGR/
elif [ "$module_type" = "4" ]; then
check_action_slideshow res/SS/"$module_name" res/ACTION.DHGR/
elif [ "$module_type" = "5" ]; then
check_title_slideshow res/SS/"$module_name" res/ARTWORK.SHR/
elif [ "$module_type" = "6" ]; then
check_action_slideshow res/SS/"$module_name" res/ACTION.GR/
else
fatal_error "Unknown module type" $module_type
fi
done
#rm -f /tmp/games

17
bin/dumpcr.js Normal file
View File

@ -0,0 +1,17 @@
a = new ActiveXObject("scripting.filesystemobject")
b = WScript.Arguments(0).lastIndexOf('\\') + 1
c = WScript.Arguments(0).substr(0, b)
d = WScript.Arguments(0).substr(b)
if (d.substr(0, 2) == '*.')
{
d = d.substr(2)
}
for (b = new Enumerator(a.GetFolder(c).files); !b.atEnd(); b.moveNext())
{
if ((d == '*') || (d == b.item().name) || (d == a.getextensionname(b.item().name)))
{
e = a.opentextfile(c + b.item().name).readall()
e = e.replace(/\r\n/g, "\n")
a.createtextfile(c + b.item().name).write(e)
}
}

View File

@ -0,0 +1,69 @@
#!/bin/bash
# run from project root directory
cat res/GAMES.CONF |
grep "," |
grep -v "^#" |
cut -d"," -f2 |
cut -d"=" -f1 | \
while read game; do
# initialize attract mode configuration file for this game
echo -e "#\n# Attract mode for $game\n# This file is automatically generated\n#\n" > /tmp/g
# add box art, if any
[ -f res/ARTWORK.SHR/"$game" ] &&
echo "ARTWORK.SHR/$game=C" >> /tmp/g
# add DHGR action screenshots, if any
cat res/SS/ACTDHGR*.CONF |
egrep "(^|=)""$game""$" |
cut -d"=" -f1 |
sed -e "s/^/ACTION.DHGR\//g" |
sed -e "s/$/=B/g" |
sort |
uniq >> /tmp/g
# add HGR action screenshots, if any
cat res/SS/ACTION*.CONF |
egrep "(^|=)""$game""$" |
cut -d"=" -f1 |
sed -e "s/^/ACTION.HGR\//g" |
sed -e "s/$/=A/g" |
sort |
uniq >> /tmp/g
# add GR action screenshots, if any
cat res/SS/ACTGR*.CONF |
egrep "(^|=)""$game""$" |
cut -d"=" -f1 |
sed -e "s/^/ACTION.GR\//g" |
sed -e "s/$/=D/g" |
sort |
uniq >> /tmp/g
# add self-running demo, if any
cat res/ATTRACT.CONF |
grep "^$game=0" >> /tmp/g
if [ "$game" == "SPARE.CHANGE" ]; then
echo "SPCARTOON.1=0" >> /tmp/g
echo "SPCARTOON.2=0" >> /tmp/g
echo "SPCARTOON.3=0" >> /tmp/g
echo "SPCARTOON.4=0" >> /tmp/g
echo "SPCARTOON.5=0" >> /tmp/g
echo "SPCARTOON.6=0" >> /tmp/g
fi
if [ "$game" == "PRINCEUNP" ]; then
echo "ARTWORK.SHR/POP.END=C" >> /tmp/g
fi
# add eof
echo -e "\n[eof]" >> /tmp/g
cat /tmp/g > res/ATTRACT/"$game"
# clean up
rm /tmp/g
done

5
bin/padto.js Normal file
View File

@ -0,0 +1,5 @@
a = new ActiveXObject("scripting.filesystemobject")
b = a.opentextfile(WScript.Arguments(1))
c = b.readall()
b.close()
a.createtextfile(WScript.Arguments(1)).write(String(c + Array(512).join(" ")).substr(0, 512))

11
bin/padto.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash
totalsize=$1
outfile=$2
[[ "$OSTYPE" == "linux-gnu" ]] \
&& filesize=$(stat -c "%s" "$outfile") \
|| filesize=$(stat -f "%z" "$outfile")
padsize=$((512-$filesize))
dd if=/dev/zero bs=1 count=$padsize >> "$outfile"

143
bin/rename.py Executable file
View File

@ -0,0 +1,143 @@
#!/usr/bin/env python3
import fileinput
import glob
import subprocess
import sys
def replace_string_in_file(filename, old_string, new_string):
for line in fileinput.input(glob.glob(filename), inplace=True):
print(line.replace(old_string, new_string), end='')
def rename_files_in_directory(dirname, old_filename, new_filename):
for filename in glob.glob(f'{dirname}/{old_filename}*'):
subprocess.run(['git', 'mv', filename, filename.replace(old_filename, new_filename)])
def rename_one_file_in_directory(dirname, old_filename, new_filename):
for filename in glob.glob(f'{dirname}/{old_filename}'):
subprocess.run(['git', 'mv', f'{dirname}/{old_filename}', f'{dirname}/{new_filename}'])
def rename_inside_disk_image(filename, old_name, new_name):
rt = subprocess.run(['cadius', 'CATALOG', filename], stdout=subprocess.PIPE, text=True)
if not [line for line in rt.stdout.split('\n') if line == f'/{old_name}/']:
return
subprocess.run(['cadius', 'RENAMEFILE', filename, f'/{old_name}/{old_name}', new_name], stdout=subprocess.PIPE, text=True)
subprocess.run(['cadius', 'RENAMEVOLUME', filename, new_name], stdout=subprocess.PIPE, text=True)
def rename(old_game_name, new_game_name):
print(old_game_name)
for filename in glob.glob('res/dsk/*'):
rename_inside_disk_image(filename, old_game_name, new_game_name)
for filename in ('res/GAMES.CONF',
f'res/ATTRACT/{old_game_name}',
'res/SS/*'):
replace_string_in_file(filename, old_game_name, new_game_name)
for dirname in ('res/DEMO',):
rename_one_file_in_directory(dirname, old_game_name, new_game_name)
replace_string_in_file('res/DEMO/_FileInformation.txt', f'{old_game_name}=', f'{new_game_name}=')
for filename in ('res/ATTRACT.CONF',):
replace_string_in_file(filename, f'{old_game_name}=0', f'{new_game_name}=0')
replace_string_in_file('src/prelaunch/*', f'build/PRELAUNCH/{old_game_name}', f'build/PRELAUNCH/{new_game_name}')
for dirname in ('res/ACTION.DHGR',
'res/ACTION.DHGR.UNCOMPRESSED',
'res/ACTION.GR',
'res/ACTION.HGR',
'res/ACTION.HGR.UNCOMPRESSED',
'res/ARTWORK.SHR',
'res/ARTWORK.SHR.UNCOMPRESSED',
'res/ATTRACT',
'res/GAMEHELP',
'res/TITLE.ANIMATED',
'res/TITLE.DHGR',
'res/TITLE.HGR'):
rename_files_in_directory(dirname, old_game_name, new_game_name)
def driver():
rename("SLICKS", "S8")
rename("CIDER.SPIDER", "AC")
rename("ARCADE.BT.CAMP", "AB")
rename("ARDY.AARDVARK", "AA")
rename("ASTEROID.BLASTR", "AS")
rename("BCS.QUEST", "BQ")
rename("BEACH.HEAD.II", "B2")
rename("BEACH.HEAD", "B1")
rename("BEYOND.WOLFEN", "BW")
rename("BUDGETRILOGY", "BT")
rename("BLOCKCHAIN", "BC")
rename("BOP.N.WRESTLE", "BN")
rename("BOUNCING.KMNGAS", "BK")
rename("BRAINTEASERBLVD", "BB")
rename("BUCK.ROGERS", "BR")
rename("BURGERTIME", "BU")
rename("CALI.GAMES", "CA")
rename("CANNONBALL.BLTZ", "CB")
rename("CAPTN.GOODNIGHT", "CG")
rename("SMURFEN", "CS")
rename("WOLFEN84", "CW")
rename("CAVRNS.CALLISTO", "CC")
rename("CHAMP.LODERUN", "CL")
rename("COPTS.ROBBERS", "CR")
rename("D.GENERATION", "DG")
rename("DARKSTAR.UNHNGD", "DU")
rename("DAVIDS.MAGIC", "DM")
rename("EGGS.IT", "EI")
rename("FUJI.SPEED.WAY", "FC")
rename("IMPOSSIBLE.MISS", "I1")
rename("IMPOSSIBLE.M.II", "I2")
rename("INTL.GRAN.PRIX", "IG")
rename("EAGLES.NEST", "IE")
rename("I.O.SILVER", "IO")
rename("LITTLE.COMP.PPL", "LP")
rename("LOCK.N.CHASE", "LC")
rename("MARIO.BROS", "MB")
rename("MATTERHORN", "MS")
rename("MINGS.CHALLENGE", "MI")
rename("THUNDERHEAD", "MT")
rename("MONTEZUMA", "MZ")
rename("MR.COOL", "MC")
rename("MR.DO", "MD")
rename("MR.ROBOT", "MR")
rename("MS.PACMAN", "MP")
rename("NIGHT.MISSION", "NM")
rename("NIGHTMARE", "NI")
rename("ONE.ON.ONE", "OO")
rename("ORILEYS.MINE", "OM")
rename("OOTW", "OW")
rename("PANDORAS.BOX", "PB")
rename("PHARAOHS.REVNG", "PR")
rename("PIEMAN", "PM")
rename("PRINCEUNP", "PP")
rename("RAID.OVR.MOSCOW", "RM")
rename("REALM.IMPOSS", "RI")
rename("SITUATION.CRTCL", "SC")
rename("SOKO.BAN", "SO")
rename("SPDWAY.CLASSIC", "SP")
rename("SPYS.DEMISE", "SD")
rename("SS.BASEBALL", "SB")
rename("SS.BASKETBALL", "SK")
rename("SS.FOOTBALL", "SF")
rename("SS.SOCCER", "SS")
rename("SUICIDE", "SU")
rename("TAG.TEAM", "TT")
rename("TECHNOCOP", "TC")
rename("THAROLIAN.TUNLS", "TU")
rename("ASTEROID.FIELD", "AF")
rename("SUMMER.EDITION", "SE")
rename("WINTER.EDITION", "WE")
rename("LAST.GLADIATOR", "LG")
rename("SPY.STRIKES.BAK", "S2")
rename("TRACK.AND.FIELD", "TF")
rename("TUBEWAY", "TB")
rename("UP.N.DOWN", "UD")
rename("ROGER.RABBIT", "RR")
rename("WINGS.OF.FURY", "WF")
rename("WORLD.KARATE", "WK")
if __name__ == '__main__':
driver()

19
bin/rsync.js Normal file
View File

@ -0,0 +1,19 @@
a = new ActiveXObject("scripting.filesystemobject")
b = WScript.Arguments(0).lastIndexOf('\\') + 1
c = WScript.Arguments(0).substr(0, b)
d = WScript.Arguments(0).substr(b)
if (d.substr(0, 2) == '*.')
{
d = d.substr(2)
}
for (b = new Enumerator(a.GetFolder(c).files); !b.atEnd(); b.moveNext())
{
if ((d == '*') || (d == b.item().name) || (d == a.getextensionname(b.item().name)))
{
e = WScript.Arguments(1) + "\\" + b.item().Name
if (!a.fileexists(e) || (a.getfile(e).datelastmodified < b.item().datelastmodified))
{
new ActiveXObject("wscript.shell").run('cmd /c copy "' + c + b.item().name + '" ' + WScript.Arguments(1)+"\\"+b.item().name.toUpperCase(), 0, 1)
}
}
}

View File

@ -0,0 +1,3 @@
# This file is automatically generated
_FileInformation.txt=Type(06),AuxType(3FF8),Access(C3)

View File

@ -0,0 +1,3 @@
# This file is automatically generated
_FileInformation.txt=Type(06),AuxType(6000),Access(C3)

View File

@ -0,0 +1,5 @@
# This file is automatically generated
BLACK.BELT=Type(06),AuxType(3FF8),Access(C3)
BLACK.BELT2=Type(06),AuxType(3FF8),Access(C3)
_FileInformation.txt=Type(06),AuxType(3FF8),Access(C3)

View File

@ -0,0 +1,3 @@
# This file is automatically generated
_FileInformation.txt=Type(06),AuxType(1FF8),Access(C3)

37
res/ATTRACT.CONF Normal file
View File

@ -0,0 +1,37 @@
KARATE.CONF=1
ACTIONKAR.CONF=2
[eof]
#
# Mega-Attract-Mode configuration file
#
# Mega-Attract-Mode is split into modules. Each module can be a short
# slideshow, a self-running demo (like a game's built-in 'attract mode'), or
# even just a single screenshot. Modules are run in the order listed here, one
# after the next, until interrupted by user input. The last-run module is
# tracked in the global prefs file.
#
# The same format is used by the per-game attract mode configuration files.
#
# Format:
# key=value
#
# |key| must be unique within this file
#
# |value| must be one of
# 0 = self-running demo (|key| is an executable binary file in /DEMO/)
# 1 = HGR title slideshow (|key| is a file in /SS/ containing files in /TITLE.HGR/)
# 2 = HGR action slideshow (|key| is a file in /SS/ containing files in /ACTION.HGR/)
# 3 = DHGR title slideshow (|key| is a file in /SS/ containing files in /TITLE.DHGR/)
# 4 = DHGR action slideshow (|key| is a file in /SS/ containing files in /ACTION.DHGR/)
# 5 = SHR box art slideshow (|key| is a file in /SS/ containing files in /ARTWORK.SHR/)
# 6 = GR action slideshow (|key| is a file in /SS/ containing files in /ACTION.GR/)
# A = single HGR file (|key| is arbitrary path from program root directory)
# B = single DHGR file (|key| is arbitrary path from program root directory)
# C = single SHR file (|key| is arbitrary path from program root directory)
# D = single GR file (|key| is arbitrary path from program root directory)
#
# Blank lines and lines beginning with '#' are ignored (like this one!)
# A line beginning with '[' terminates the parsing
#

9
res/ATTRACT/BLACK.BELT Normal file
View File

@ -0,0 +1,9 @@
#
# Attract mode for BLACK.BELT
# This file is automatically generated
#
ACTION.HGR/BLACK.BELT2=A
ACTION.HGR/BLACK.BELT=A
[eof]

View File

@ -0,0 +1,4 @@
# This file is automatically generated
BLACK.BELT=Type(04),AuxType(8000),Access(C3)
_FileInformation.txt=Type(04),AuxType(8000),Access(C3)

BIN
res/COVER Normal file

Binary file not shown.

21
res/CREDITS Normal file
View File

@ -0,0 +1,21 @@
T O T A L
R E P L A Y
2
~
revision 01 / serial number 20210216
~
design & interface * * * * * * * * * 4am
ports & rwts * * * * * * * * * * *qkumba
~
archive.org/details/TotalReplay
[eof]

BIN
res/DECRUNCH Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
# This file is maintained by hand

85
res/DFX.CONF Normal file
View File

@ -0,0 +1,85 @@
DHGR.FIZZLE2BIT
DHGR.RIPPLE
DHGR.SOFT.DIAG
DHGR.48BOXES
DHGR.BUBBLES
DHGR.RADIAL
DHGR.SOFT.IRIS
DHGR.WAVY.RIP
DHGR.48.SNAKE
DHGR.SNOWFL.IN
DHGR.MAPLE
DHGR.SLOW.STAR
DHGR.48.SNAKEC
DHGR.HEART.RIP
DHGR.CORNER4
DHGR.STAR.IN
DHGR.48.ARROW
DHGR.REDLINES
DHGR.BUTTERFLY
DHGR.BLOOM.IN
DHGR.48.SYNCC
DHGR.RADIAL4
DHGR.TWOPASS.LR
DHGR.WAVY.IN
DHGR.CORNER4RIP
DHGR.STAR
DHGR.48.LDIAGON
DHGR.MAPLE.IN
DHGR.BAR.DISSLV
DHGR.BLOOM
DHGR.SLOW.STARI
DHGR.HEART
DHGR.48.2SNAKES
DHGR.RADIAL3
DHGR.STAR.RIP
DHGR.BFLY.IN
DHGR.DIAGONAL
DHGR.SNOWFLAKE
DHGR.48.DOWN
DHGR.SOFTIRISIN
DHGR.RADIAL2
DHGR.IRIS
DHGR.BUBBLES.IN
DHGR.SLOWST.RIP
DHGR.48.SPIRAL
DHGR.RADIAL5
DHGR.FIZZLE
DHGR.BFLY.RIP
DHGR.IRIS.IN
DHGR.SWIRL
DHGR.48.SPIRALC
DHGR.MAPLE.RIP
DHGR.R.BY.PIXEL
DHGR.HEART.IN
DHGR.SNOWFL.RIP
DHGR.48.SIDES
DHGR.CORNER4.IN
DHGR.WAVY.IRIS
DHGR.BLOOM.RIP
DHGR.48.SYNC
DHGR.FLICK
[eof]
#
# transition effects for DHGR slideshows
#
# Each Mega-Attract Module that is a DHGR slideshow (see attract.conf)
# will use a single transition effect for the length of the module.
# Transition effects are loaded in the order listed in this file. Each line
# of this file is a filename (not including comments, like this one). The
# name of the next transition effect is stored in the global prefs, so this
# file should not contain duplicates.
#
# Transition effects are binary files loaded at $6000 and called with main
# memory banked in, DHGR page 1 showing, and the next DHGR graphic already
# loaded at $4000/main and $4000/aux. A transition effect has full use of
# auxiliary memory, zero pages (both), text pages (both, but preserve screen
# holes), and main memory $6000-$BEFF. $BF00-$BFFF/main is reserved for the
# ProDOS shim. LC RAM banks 1 and 2 are reserved for the launcher.
#
# Important: LC RAM bank 1 will be read/write on entry and must be read/write
# on exit. If you need ROM routines, you are responsible for switching to ROM
# then switching back to RAM bank 1 (read/write) before returning.
#

143
res/FX.CONF Normal file
View File

@ -0,0 +1,143 @@
BOXES48.SNAKE
RIPPLE
SOFT.DIAGONAL
MANDELBROT.IN
RADIAL
STAGGER.LR
SOFT.UD
HEART.IN
CRYSTAL
STAR.RIPPLE
BIT2.FIZZLE
MEETINTHEMIDDLE
BOXES48
APPLE.IN
FLOWER.RAD.RIP
SOFT.IRIS
W.RIPPLE.BLOOM
DIAGONAL
PINWHEELS
STAGGERWHITE.UD
BOXES48.SYNCC
CORNER4.RIP
BOLT
RADIAL2
STAR
FLOWER.IN
R.BY.PIXEL
WAVY.IRIS
BIT.FIZZLE
STAR.IN
APPLE
MANDELBROT.RIP
SOFT.L
HEART.RIPPLE
FLOWER.RAD
SLOW.STAR.IN
IRIS.IN
BUTTERFLYRIPPLE
BOXES48.SPIRALC
W.IRIS.BLOOM.IN
CENTER.BY.PIXEL
RADBUBBLES
SNOWFLAKE.IN
FLOWER
APPLE.RIPPLE
DIAGONAL2
STAR.BLOOM
BOXES48.SYNC
PALETTE.FIZZLE
BUTTERFLY
BUBBLES
FLOWER.RIPPLE
SPLIT.UD.INTRO
WAVY.IRIS.IN
R.BY.2
HALF.FIZZLE
BOXES48.LDIAGON
SNOWFLAKE.RIP
RADIAL3
HEART
BOLT.IN
FLOWER.RAD.IN
DIAGONAL3
MANDELBROT
BOXES48.SPIRAL
WAVY.RIPPLE
CORNER4.OUT
LATTICE
BAR.DISSOLVE
R.BY.PALETTE
FOURSPIRAL
SOFT.R
MAPLE.IN
BOXES48.SNAKEC
RADIAL4
IRIS
CASCADE
SNOWFLAKE
VERTICAL.BLINDS
BUTTERFLY.IN
LR.BY.PIXEL
CHECKERB.FIZZLE
BOXES48.SIDES
STAGGERWHITE.LR
SOFT.UD.OUT
ONESQUARE
W.IRIS.BLOOM
MAPLE
SWIRL
FIZZLE
SLOW.STAR
ARROW.WHITE
TRI.FIZZLE
BOXES48.DOWN
SOFT.IRIS.IN
DIAMOND
BUBBLES.IN
TWOPASS.LR
RADIAL5
HALF.MOSAIC
BOLT.RIPPLE
ARROW
FOURSQUARE
FULL.OF.STARS
BLOCK.FIZZLE
BOXES48.2SNAKES
DIAGONAL4
STAGGER.UD
INTERLOCK.LR
SOFT.UD.IN
BLOCK.MOSAIC
CORNER4.IN
MAPLE.RIPPLE
INTERLOCK.UD
LITTLE.BOXES
SPIRAL
SLOW.STAR.RIP
BOXES48.ARROW
REDLINES
FLICK
[eof]
#
# transition effects for HGR slideshows
#
# Each Mega-Attract Module that is an HGR slideshow (see attract.conf)
# will use a single transition effect for the length of the module.
# Transition effects are loaded in the order listed in this file. Each line
# of this file is a filename (not including comments, like this one). The
# name of the next transition effect is stored in the global prefs, so this
# file should not contain duplicates.
#
# Transition effects are binary files loaded at $6000 and called with
# hi-res page 1 showing and the next HGR graphic already loaded at $4000.
# A transition effect can use $6000-$BEFF in main memory, zero page, and
# text page if needed (but preserve the screen holes). $800-$1FFF is reserved
# for the slideshow data. $BF00-$BFFF is reserved for the ProDOS shim.
# LC RAM banks 1 and 2 are reserved for the launcher.
#
# Important: LC RAM bank 1 will be read/write on entry and must be read/write
# on exit. If you need ROM routines, you are responsible for switching to ROM
# then switching back to RAM bank 1 (read/write) before returning.
#

BIN
res/Finder.Data Normal file

Binary file not shown.

BIN
res/Finder.Root Normal file

Binary file not shown.

12
res/GAMEHELP/STANDARD Normal file
View File

@ -0,0 +1,12 @@
T O D O
[eof]

26
res/GAMES.CONF Executable file
View File

@ -0,0 +1,26 @@
0000,BLACK.BELT
[eof]
#
# 4cade master game list
#
# Format:
# ABCD,directory=name
#
# A=1 if game requires joystick, 0 if playable on keyboard
# B=1 if game requires 128K, 0 if playable on 64K
# C=1 if game has DHGR title, 0 if HGR
# D=cheat mode category
# 0=no cheats (yet!)
# 1=infinite lives
# 2=infinite weapons
# 3=infinite lives & weapons
# 4=invincibility
# 5=has in-game cheats
#
# if no name, it will be calculated from the directory when we need to display it
#
# all other values for A -> ignore entire line (allows inline comments)
# A line beginning with '[' terminates the parsing
#

BIN
res/HELP Normal file

Binary file not shown.

20
res/HELPTEXT Normal file
View File

@ -0,0 +1,20 @@
< and > to browse games
T Y P E to find a game
[Return] to play
[Space] to preview
[Esc] to go back
[Ctrl-C] to cheat
[Ctrl-P] joystick
[Ctrl-A] credits
[eof]

BIN
res/ICONS/TR.ICONS Normal file

Binary file not shown.

View File

@ -0,0 +1,4 @@
# This file is automatically generated
TR.ICONS=Type(CA),AuxType(0000),Access(C3)
_FileInformation.txt=Type(CA),AuxType(0000),Access(C3)

BIN
res/JOYSTICK Normal file

Binary file not shown.

17
res/PREFS.CONF Normal file
View File

@ -0,0 +1,17 @@
# Total Replay preferences file
# Do not edit by hand.
# Or do. I'm a comment, not a cop.
# value=attract mode module listed in ATTRACT.CONF, or empty
NEXTATTRACT=
# value=transition effect listed in FX.CONF, or empty
NEXTFX=
# value=transition effect listed in DFX.CONF, or empty
NEXTDFX=
# value=0 or 1
CHEAT=0
[eof]

8
res/SS/ACTIONKAR.CONF Normal file
View File

@ -0,0 +1,8 @@
#
# Karate action slideshow
#
BLACK.BELT
BLACK.BELT2=BLACK.BELT
[eof]

7
res/SS/KARATE.CONF Normal file
View File

@ -0,0 +1,7 @@
#
# Karate slideshow
#
BLACK.BELT
[eof]

View File

@ -0,0 +1,5 @@
# This file is automatically generated
ACTIONKAR.CONF=Type(04),AuxType(4000),Access(C3)
KARATE.CONF=Type(04),AuxType(4000),Access(C3)
_FileInformation.txt=Type(04),AuxType(4000),Access(C3)

BIN
res/TITLE Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
# This file is maintained by hand

View File

@ -0,0 +1,3 @@
# This file is automatically generated
_FileInformation.txt=Type(06),AuxType(4000),Access(C3)

View File

@ -0,0 +1,4 @@
# This file is automatically generated
BLACK.BELT=Type(06),AuxType(4000),Access(C3)
_FileInformation.txt=Type(06),AuxType(4000),Access(C3)

17
res/_FileInformation.txt Normal file
View File

@ -0,0 +1,17 @@
# This file is maintained by hand
LAUNCHER.SYSTEM=Type(FF),AuxType(2000),Access(C3)
PREFS.CONF=Type(04),AuxType(8000),Access(C3)
GAMES.CONF=Type(04),AuxType(8000),Access(C3)
ATTRACT.CONF=Type(04),AuxType(8000),Access(C3)
FX.CONF=Type(04),AuxType(8000),Access(C3)
DFX.CONF=Type(04),AuxType(8000),Access(C3)
COVER=Type(06),AuxType(2000),Access(C3)
TITLE=Type(06),AuxType(2000),Access(C3)
HELP=Type(06),AuxType(2000),Access(C3)
CREDITS=Type(04),AuxType(8000),Access(C3)
HELPTEXT=Type(04),AuxType(8000),Access(C3)
DECRUNCH=Type(06),AuxType(0200),Access(C3)
JOYSTICK=Type(06),AuxType(0800),Access(C3)
Finder.Data=Type(C9),AuxType(0000),Access(E7)
Finder.Root=Type(C9),AuxType(0000),Access(E7)

9
res/history.md Normal file
View File

@ -0,0 +1,9 @@
# Revision 1 / unreleased
## New games
- Black Belt
## Migrated from Total Replay
- ...

BIN
res/proboothd Normal file

Binary file not shown.

205
src/4sports.a Normal file
View File

@ -0,0 +1,205 @@
;license:MIT
;(c) 2018-2021 by 4am
;
!cpu 6502
!to "build/LAUNCHER.SYSTEM",plain
*=$2000
!ifndef RELBASE {
RELBASE=$2000
}
!source "src/constants.a" ; no code in these
!source "src/macros.a"
; first-run initialization, relocates code to language card and jumps
; to |Reenter|
!source "src/4sports.init.a"
!source "src/4sports.init.cffa.a"
!source "src/4sports.init.gs.a"
FirstMover
!pseudopc RELBASE {
;------------------------------------------------------------------------------
; Reenter
; This is the primary entry point for returning to the launcher from anywhere.
; - Self-running demos call this when the user presses a key or when the demo
; cycles ends naturally.
; - It is set as the reset vector, so the user can play a game then press
; Ctrl-Reset to return to the launcher and choose another.
; - It also functions as a reset vector while the launcher is running.
; - It is also called on program startup, after the first-run initialization.
;
; When execution reaches this point, we may have previously backed up the stack
; and stack pointer, in which case it is now our job to restore it and return
; to the caller. This allows magic like 'JSR PlayGame' then continuing once the
; JSR returns.
;
; If there is no stack to restore, this exits via SearchMode.
;
; in: none
; out: see above
;------------------------------------------------------------------------------
Reenter
cld
ldx #$ff
txs ; so that we never trash the reset vector
jsr SwitchToBank2
jsr DisableAccelerator ; back to 1 MHz (especially important on IIgs
; which restores default speed on Ctrl-Reset)
jsr CloseHandles ; close any open handles to restore ProRWTS
ldx #(end_promote-promote-1)
- lda promote,x ; copy ProDOS shim to main memory for GS/OS exit
sta $bf00,x
dex
bpl -
ldx #5
- lda ResetVector,x ; copy reentry wrapper to bottom of stack
sta $100,x ; (used as reset vector because //e always
dex ; switches to ROM on Ctrl-Reset)
bpl -
inx
stx $3F2 ; page 3 reset vector to ($100)
sei
stx $3FE ; page 3 IRQ vector to ($100)
inx
stx $3FF
cli
stx $3F3
ldx #$A4
stx $3F4
RestoreStackNextTime
bne SearchMode ; (SMC) not an unconditional branch because code
; might change the branch target to the next opcode
; If we fall through to here, it's because we backed up the stack and
; stack pointer and wanted this routine to restore it and return to
; caller.
lda #(SearchMode - RestoreStackNextTime) - 2
; reset to branch so we don't try to
sta RestoreStackNextTime + 1
; restore the same stack twice
ldx #$F1
- lda STACKBASE - $EF,x ; restore stack
sta $100,x
inx
bne -
STACKPTR
ldx #$D1 ; SMC, restore stack pointer
txs
SwitchToBank1
+READ_RAM1_WRITE_RAM1
rts
ResetVector ; 6 bytes, copied to $100
+READ_RAM1_NO_WRITE
jmp Reenter
; these routines will only be called after relocating to language card
!source "src/ui.search.mode.a" ; \__ execution falls through
!source "src/ui.animation.a" ; /
!source "src/ui.browse.mode.a"
!source "src/ui.attract.mode.a"
!source "src/ui.attract.hgr.a"
!source "src/ui.attract.dhgr.a"
!source "src/ui.attract.shr.a"
!source "src/ui.attract.gr.a"
!source "src/ui.offscreen.a"
!source "src/ui.cheats.a"
!source "src/ui.credits.a"
!source "src/ui.reboot.a"
!source "src/ui.common.a"
!source "src/ui.font.a"
!source "src/ui.overlay.a"
!source "src/parse.prefs.a"
!source "src/parse.common.a"
!source "src/glue.launch.a"
!source "src/glue.prorwts2.a"
!source "src/glue.decompress.a"
!source "src/textrank.a"
!source "src/okvs.a"
!source "src/wait.a"
; add new files above here
!source "src/hw.vbl.a"
!source "src/ui.wait.a"
gAttractModeStore
gFXStore
gDFXStore
!word $6000
gSearchStore
!word $8200
gSlideshowStore
!word $0800
gGlobalPrefsStore
!word $D001 ; leave $D000 alone because FastChip accelerator
; flips out if it has certain values (it will
; be set to $55 as part of the 64K memory test,
; which is apparently one of the acceptable values)
gGamesListStore
!word $FDFD ; SMC
SwitchToBank2
+READ_RAM2_WRITE_RAM2
rts
!source "src/prodos.path.a" ; paths end up on the same page
; WaitForVBL (label is in constants.a)
jmp WaitForVBL_iie ; SMC to RTS on a II+
; UnwaitForVBL (label is in constants.a)
rts ; SMC to JMP on a IIc
!word iUnwaitForVBL
; MockingboardStuff (label is in constants.a)
; slot number where Mockingboard was detected and type of board
; #$00 if no Mockingboard detected
!byte $FD ; MockingboardStuff ($FFF8)
; MachineStatus (label is in constants.a so prelaunchers can use it)
; 7 6 5 4 3 2 1 0
; | | | | | | | +- bit 0 reserved
; | | | | | | +--- bit 1 reserved
; | | | | | +----- bit 2 reserved
; | | | | +------- bit 3 = 1 if cheats are enabled
; | | | +--------- bit 4 = 1 if VidHD
; | | +----------- bit 5 = 1 if IIgs
; | +------------- bit 6 = 1 if 128K
; +--------------- bit 7 = 1 if joystick
; Use the bit masks defined in constants.a
!byte $FD ; MachineStatus ($FFF9)
!word Reenter ; NMI vector ($FFFA-B)
!word Reenter ; reset vector ($FFFC-D)
!word Ignore ; IRQ vector ($FFFE-F)
}
LastMover
COPYSRC = *
!pseudopc hdddataend {
COPYDST = *
!source "src/prodos.impl.lc2.a"
!source "src/ui.font.lc2.a"
!source "src/glue.prorwts2.lc2.a"
!source "src/glue.launch.lc2.a"
!source "src/hw.accel.lc2.a"
STACKBASE = *
LCRAM2_END = STACKBASE + 15
!if LCRAM2_END >= DisableAccelerator {
!error "code is too large: ends at ", LCRAM2_END
}
FONTDST = (LCRAM2_END + 255) and -256
}
EvenLasterMover
FONTSRC = *
!pseudopc FONTDST {
!source "src/ui.font.data.lc2.a"
!if * > $E000 {
!error "code is too large: ends at ", *
}
}
!if RELBASE = $2000 {
!ifdef PASS2 {
} else { ;PASS2
!set PASS2=1
!warn "ProRWTS ends at ", hdddataend - 1
!warn "STACK at ", STACKBASE
!warn "LCRAM2 ends at ", LCRAM2_END
!warn "RELBASE = ", $10000 - (LastMover - FirstMover)
}
}

462
src/4sports.init.a Normal file
View File

@ -0,0 +1,462 @@
;license:MIT
;(c) 2018-2020 by 4am
;
; first-run initialization code
;
; This file is included directly and is run from $2000/main as soon as the
; .SYSTEM file is loaded
;
+READ_ROM_NO_WRITE
sta PRIMARYCHARSET
sta CLR80VID
sta STOREOFF
sta READMAINMEM
sta WRITEMAINMEM
jsr ROM_TEXT
jsr ROM_HOME
jsr ROM_NORMAL
jsr ROM_IN0
jsr ROM_PR0
jsr Has64K ; check for 64K (required)
bcc +
ldy #@no64Klen
- lda @s_no64K,y
sta $6B6,y
dey
bpl -
@hang bmi @hang
@s_no64K !scrxor $80,"REQUIRES 64K"
@no64Klen=(*-@s_no64K)-1
+
lda #0
sta zpMachineStatus
sta SETC3ROM
jsr HasVidHDCard ; check for VidHD card (allows super hi-res artwork even on non-IIgs machines)
sta CLRC3ROM
ror zpMachineStatus
lda ROM_MACHINEID
cmp #$06
bne @NotGS
sec
jsr $FE1F ; check for IIgs (allows super hi-res artwork)
bcs @NotGS
sec
+HIDE_NEXT_BYTE
@NotGS clc
ror zpMachineStatus
jsr Has128K ; check for 128K (allows DHGR slideshows and 128K games)
ror zpMachineStatus
jsr HasJoystick ; check for joystick (absence is OK but we filter out some games that require a joystick)
ror zpMachineStatus
; now bit 4 = 1 if VidHD
; bit 5 = 1 if IIgs
; bit 6 = 1 if 128K
; bit 7 = 1 if joystick
; and all other bits are 0 (we'll set bit 3 after copying it to LC RAM)
; accommodate uppercase-only machines (64K ][+ is supported)
lda ROM_MACHINEID
cmp #$A0
beq + ; Spectrum ED
cmp #$06
beq +
lda #$DF
+HIDE_NEXT_2_BYTES
+ lda #$FF
sta zpCharMask
; print text title in same place as graphical title will appear
ldy #8
- lda TOTAL,y
ora #$80
sta $04B7,y
dey
bpl -
ldy #10
- lda REPLAY,y
ora #$80
sta $0536,y
dey
bpl -
; increase text window width so we can print to the edge of the screen without scrolling
inc $21
; print version or build number in lower right corner
ldx #30
ldy #23
jsr SetCursorPosition
+LDADDR LoadingVersion
jsr LoadingPrint
!ifndef RELEASE {
lda LoadingBuild
ldx LoadingBuild+1
ldy #0
jsr PrintAsDecimal
}
; set up text window so it only covers lower left corner
lda #30
sta $21
lda #19
sta $22
; print machine configuration in lower left corner
ldx #0
ldy #23
jsr SetCursorPosition
; if zpMachineStatus AND IS_IIGS then print 'IIgs'
; else if zpMachineStatus AND HAS_128K then print '128K'
; else print '64K'
lda zpMachineStatus
and #IS_IIGS
beq +
+LDADDR LoadingIIgs
bne @printMem
+ lda zpMachineStatus
and #HAS_128K
beq +
+LDADDR Loading128K
bne @printMem
+
+LDADDR Loading64K
@printMem
jsr LoadingPrint
; if zpMachineStatus AND HAS_JOYSTICK then CR & print 'joystick'
lda zpMachineStatus
and #HAS_JOYSTICK
beq +
jsr LoadingCR
+LDADDR LoadingJoystick
jsr LoadingPrint
+
; if zpMachineStatus AND HAS_VIDHD then CR & print 'VidHD'
lda zpMachineStatus
and #HAS_VIDHD
beq +
jsr LoadingCR
+LDADDR LoadingVidHD
jsr LoadingPrint
+
@Relocate
; if zpMachineStatus AND IS_IIGS then check for CFFA
; before performing any further disk access
lda zpMachineStatus
and #IS_IIGS
beq +
jsr HackThaCFFA
+
+READ_ROM_WRITE_RAM2
jsr init ; initialize and relocate ProRWTS2 to $D400 in RAM bank 2
; ProRWTS2 disk-data live at $D000-D3FF
ldx #$00 ; relocate program code to top of language card
; since we end at $0000 now, adjust low offset to avoid destroying zpage
@FM lda FirstMover - (RELBASE & $FF),x
sta RELBASE & $FF00,x
inx
bne @FM
inc @FM+2
inc @FM+5
bne @FM
ldy #>(255 + EvenLasterMover - LastMover)
@LM lda COPYSRC,x ; relocate pseudo-ProDOS to RAM bank 2
sta COPYDST,x
inx
bne @LM
inc @LM+2
inc @LM+5
dey
bne @LM
ldy #4
@ELM lda FONTSRC,x
; relocate font data to RAM bank 2
sta FONTDST,x
inx
bne @ELM
inc @ELM+2
inc @ELM+5
dey
bne @ELM
+READ_ROM_NO_WRITE
jsr BuildAcceleratorFunction
+READ_RAM2_WRITE_RAM2
+ST16 @accelSrc
dex
-
@accelSrc=*+1
lda $FDFD,x ; copy (de)acceleration functions to RAM bank 2
sta DisableAccelerator,x
dex
bpl -
+READ_ROM_WRITE_RAM2
jsr BuildVBLFunction
+DISABLE_ACCEL ; cycle counting in Mockingboard detection requires 1MHz
+LDADDR FoundMockingboardCallback
jsr GetMockingboardStuff
+READ_RAM2_WRITE_RAM2
stx MockingboardStuff ; save mockingboard slot and type in LC RAM
+READ_ROM_NO_WRITE
; if Mockingboard AND HAS_SPEECH then print CR & '...and it talks!'
txa
and #HAS_SPEECH
beq +
jsr LoadingCR
+LDADDR LoadingMockingboardSpeech
jsr LoadingPrint
+
+READ_RAM2_WRITE_RAM2
jsr EnableAccelerator
jmp OneTimeSetup
; ProRWTS2 has its own function to relocate itself
!source "src/prorwts2.a"
ProRWTSBuffer
; these routines will only be called once, from main memory, before relocating to language card
!source "src/hw.vidhd.a"
!source "src/hw.memcheck.a"
!source "src/hw.joystick.a"
!source "src/hw.mockingboard.a"
SetCursorPosition
stx HTAB
sty VTAB
jmp $FC22
LoadingPrint
+ST16 PTR
ldy #0
lda (PTR),y
sta @max
sty i
- inc i
ldy i
lda (PTR),y
ora #$80
+FORCE_UPPERCASE_IF_REQUIRED
jsr ROM_COUT
ldy i
@max=*+1
cpy #$FD ; SMC
bne -
rts
LoadingCR
lda #$8D
jmp ROM_COUT
FoundMockingboardCallback
; in: zp$81 contains slot number in form $Cx
jsr LoadingCR
+LDADDR LoadingMockingboard
jsr LoadingPrint
lda $81
and #$0F
ora #$B0
jmp ROM_COUT
TOTAL
!text "T O T A L"
REPLAY
!text "R E P L A Y"
!ifndef RELEASE {
LoadingVersion
!byte 9
!text "build 000"
LoadingBuild
!word BUILDNUMBER
} else {
LoadingVersion
!byte 10
!text " v1.0"
}
Loading64K
!byte 3
!text "64K"
Loading128K
!byte 4
!text "128K"
LoadingIIgs
!byte 4
!text "IIgs"
LoadingJoystick
!byte 8
!text "joystick"
LoadingVidHD
!byte 5
!text "VidHD"
LoadingMockingboard
!byte 21
!text "Mockingboard in slot "
LoadingMockingboardSpeech
!byte 16
!text "...and it talks!"
!ifndef RELEASE {
PrintAsDecimal
jsr $FF4A
lda $FDE2
cmp #$EA
bne +
dec @addr+1 ; fix for Laser
+
-- lda #$00
clv
ldx #$18
- cmp #$05
bcc +
sbc #$85
sec
+ rol $45
rol $46
rol $47
rol
dex
bne -
pha
lda #$FD
pha
@addr lda #$E1
pha
bvs --
rts
}
!source "src/hw.accel.a"
!source "src/hw.vbl.init.a"
!source "src/parse.games.a"
OneTimeSetup
lda zpMachineStatus
sta MachineStatus ; save machine status in LC RAM
and #IS_IIGS
beq @NotGSOS
!cpu 65816
lda $E100BD ; Make sure GS/OS was the boot OS
!cpu 6502
beq @NotGSOS
jsr PrepareGSOS
@NotGSOS
ldy #$0b
CopyDevs
lda $BF13,y
sta promote + $13,y
dey
bpl CopyDevs
lda $BF30
sta promote + ProDOS_unit - $bf00
; save unit in LC bank 2 while overriding !pseudopc
lda hddopendir+1 ; save current directory as 'root'
ldy hddopendir+3
jsr SwitchToBank1
+ST16 gRootDirectory
jsr LoadFile ; load preferences file into $8000
!word kRootDirectory
!word kGlobalPrefsFilename
- !word $8000
jsr ParseKeyValueList ; parse contents into OKVS data structure into LC RAM bank
!word gGlobalPrefsStore
!word -
!byte 16
+LD16 SRC ; (SRC) points to free space after the OKVS data structure we just created
+ST16 gGamesListStore ; save pointer to free space for next store
jsr LoadFile ; load games list file into $8200
!word kRootDirectory
!word @kGameListConfFile
- !word $8200
jsr ParseGamesList ; parse games list into OKVS data structure in LC RAM bank
!word gGamesListStore
!word -
!ifndef RELEASE {
+READ_ROM_NO_WRITE
lda #40
sta $21
lda #36
sta $24
dec $25
jsr $FC22
lda SRC+1
jsr $FDDA
lda SRC
jsr $FDDA
+READ_RAM1_WRITE_RAM1
}
+LDADDR gGamesListStore
jsr okvs_len
+LD16 WCOUNT
+ST16 GameCount
+ST16 SAVE
jsr pref_get ; see if cheats are enabled by default
!word kCheat
!word 0
+ST16 PTR ; (PTR) -> cheat pref value as length-prefixed string '1' or '0'
ldy #1
lda (PTR),y ; A = #$B1 or #$B0
and #1 ; A = #$01 or #$00
asl
asl
asl ; A = #$08 or #$00
ora MachineStatus
sta MachineStatus ; set bit 3 of MachineStatus
; calculate and update visible game count (3-digit decimal number as ASCII string)
dey ; Y = 0
@outer
lda #0
pha
@inner
lda SAVE
sec
sbc @kPowersOfTen,y
sta SAVE
lda SAVE+1
sbc #0
bcc @digitDone
sta SAVE+1
pla
adc #0
pha
jmp @inner
@digitDone
lda SAVE
adc @kPowersOfTen,y
sta SAVE
pla
ora #$30
sta VisibleGameCount,y
iny
cpy #$03
bcc @outer
bit CLEARKBD
jmp Reenter
@kGameListConfFile
!byte 10
!text "GAMES.CONF"
@kPowersOfTen
!byte 100
!byte 10
!byte 1

89
src/4sports.init.cffa.a Normal file
View File

@ -0,0 +1,89 @@
;license:MIT
;(c) 2020 by qkumba
;
; CFFA-specific work-around for an issue on the GS
;
HackThaCFFA
ldx #0
beq @CFFAbase1
@loopCFFA
cmp @CFFA_ID-1,x
bne @nextslot
@CFFAbase1
lda $C7F6,x
inx
cpx #5
bne @loopCFFA
sbc #'0'
cmp #2 ; only 3.0x and 3.1x
bcc @foundCFFA
rts
@nextslot
dec @CFFAbase1+2
lda @CFFAbase1+2
cmp #$C0
bne HackThaCFFA
rts
@foundCFFA
lda @CFFAbase1+2
sta @CFFAbase2+2
!cpu 65816
clc
xce
ldx #0
- inx
lda $FE0002,x
cmp #$FE ; find anything we can use as bank==#$FE
bne -
stx @patchROM+1
rep #$30
!al
!rl
sei
ldx #$00A0
lda $CFFF
@CFFAbase2
lda $D100 ; SMC
- dex
beq @returnCFFA
lda $CC04,x
eor #$02AE
bne -
tay
- lda @patchCFFA_b,y
sta $CC00,x
inx
inx
iny
iny
cpy #(@patchCFFA_e-@patchCFFA_b)
bcc -
@returnCFFA
cli
sec
xce
rts
!as
!rs
@patchCFFA_b
stz $C806
stz $C807 ; no error
@patchROM
lda #$D1 ; SMC
sta $C808
stz $C809
lda #$FE
sta $C80A ; handle at FE/00xx
stz $C80B
rts
@patchCFFA_e
@CFFA_ID !text "CF3K"
!cpu 6502

105
src/4sports.init.gs.a Normal file
View File

@ -0,0 +1,105 @@
;license:MIT
;(c) 2020 by qkumba
;
; GS-specific code to support return-to-GS/OS
;
PrepareGSOS
!cpu 65816
clc
xce
rep #$30
!al
!rl
pha ; reserve word return
pea $1100 ; application-type, auxId #1
ldx #$2003 ; GetNewID
jsl $E10000
ply
sty @userID+1
pha
pha ; reserve dword return
pha
pea @return_e-@return_b ; dword size
phy ; ID
pea $8010 ; attrib (locked, can't cross bank)
pha
pha ; dword 0
ldx #$0902 ; NewHandle
jsl $E10000
plx
ply ; handle
pha
pea @return_b ; ptr
phy
phx ; handle
pha
pea @return_e-@return_b ; size
tya
xba
sta @handle2+2
stx @handle2+1
inx
inx
sta @handle1+2
stx @handle1+1
lda #$FB18 ; CLC / XCE
sta PatchQuit
lda #$005C ; JML
sta PatchQuit+2
@handle1
lda $D1D1D1 ; SMC
sta PatchQuit+5
xba
sta @copycallback+2
@handle2
lda $D1D1D1 ; SMC
sta PatchQuit+3
adc #@callback_b-@return_b
sta @copycallback+1
ldx #$2802 ; PtrToHand
jsl $E10000 ; copy hook code to allocated memory
sec
xce
rts
@return_b
rep #$30 ; called from 8-bit code but with e=0
ldx #((@callback_e-@callback_b)+1) and -2
@copycallback
lda $D1D1D1,x ; SMC
sta $BF00,x
dex
dex
bpl @copycallback
@userID pea $D1D1 ; SMC
ldx #$1102 ; DisposeAll
phb
pea ($BF00+@jmpGSOS-@callback_b)-1
jmp $E10000
@callback_b
!cpu 65C02
plx
inx
inx
inx
phx
lda #$B3
sta $204
lda #0
sta $280
rts
!cpu 65816
@jmpGSOS
sep #$30 ; revert to 8-bit mode
jmp $E0D000
@callback_e
@return_e
!cpu 6502

161
src/constants.a Normal file
View File

@ -0,0 +1,161 @@
;license:MIT
;(c) 2018-2020 by 4am
;
;------------------------------------------------------------------------------
; YE OLDE GRAND UNIFIED MEMORY MAP
;
; LC RAM BANK 1
; D000..E92C - persistent data structures (gGlobalPrefsStore, gGamesListStore)
; E92D..FFF1 - main program code
; FFF2..FFF9 - API functions and global constants available for main program
; code, prelaunchers, transition effects, &c.
; (Wait/UnwaitForVBL, MockingboardStuff, MachineStatus)
; FFFA..FFFF - NMI, reset, IRQ vectors
;
; LC RAM BANK 2
; D000..D3FF - ProRWTS data
; D400..D677 - ProRWTS code
; D678..DB9D - HGR font code & ProRWTS glue code
; DB9E..DBAD - backup of stack (during gameplay and self-running demos)
; ...unused...
; DBB4..DBFF - (de)acceleration function
; DC00..DFFF - HGR font data
;------------------------------------------------------------------------------
!ifndef _CONSTANTS_ {
; soft switches
KBD = $C000 ; last key pressed (if any)
CLEARKBD = $C010 ; clear last key pressed
STOREOFF = $C000 ; STA then use the following 4 flags:
READMAINMEM = $C002 ; STA to read from main mem
READAUXMEM = $C003 ; STA to read from aux mem
WRITEMAINMEM = $C004 ; STA to write to main mem
WRITEAUXMEM = $C005 ; STA to write to aux mem
CLRC3ROM = $C00A ; STA to use internal Slot 3 ROM (required to use 128K and DHGR)
SETC3ROM = $C00B ; STA to use external Slot 3 ROM (required to detect VidHD in slot 3)
CLR80VID = $C00C ; 40 columns (also used to get out of DHGR mode)
SET80VID = $C00D ; 80 columns (also used to get into DHGR mode)
PRIMARYCHARSET= $C00E ; no mousetext for you
SLOT3STATUS = $C017 ; bit 7 only
TBCOLOR = $C022 ; IIgs text foreground and background colors (also VidHD)
NEWVIDEO = $C029 ; IIgs graphics modes (also VidHD)
SPEAKER = $C030 ; chirp chirp
CLOCKCTL = $C034 ; bits 0-3 are IIgs border color (also VidHD)
SHADOW = $C035 ; IIgs auxmem-to-bank-E1 shadowing (also VidHD)
TEXTMODE = $C051
PAGE1 = $C054 ; page 1 (affects text, HGR, DHGR)
PAGE2 = $C055 ; page 2 (affects text, HGR, DHGR)
DHIRESON = $C05E ; double hi-res on switch
DHIRESOFF = $C05F ; double hi-res off switch
; ROM routines and addresses
; (prefixed because so much of the program runs from LC RAM, so don't call
; these without thinking about memory banks first)
ROM_TEXT2COPY =$F962 ; turn on alternate display mode on IIgs
ROM_REBOOT = $FAA6
ROM_TEXT = $FB2F
ROM_MACHINEID =$FBB3
ROM_HOME = $FC58
ROM_COUT = $FDED
ROM_NORMAL = $FE84 ; NORMAL text (instead of INVERSE or FLASH)
ROM_IN0 = $FE89 ; SETKBD
ROM_PR0 = $FE93 ; SETVID
; zero page during init ONLY
zpMachineStatus= $F0 ; bit 7 = 1 if machine has joystick
; bit 6 = 1 if machine has 128K
; bit 5 = 1 if machine has a VidHD card
; bit 4 = 1 if machine is a IIgs
; only used during init, then copied to MachineStatus in LC RAM
zpCharMask = $F1 ; only used during init, then clobbered
; zero page
PARAM = $00 ; word (used by PARAMS_ON_STACK macro, so basically everywhere)
PTR = $02 ; word
SRC = $04 ; word
DEST = $06 ; word
SAVE = $08 ; word
WINDEX = $0A ; word
WCOUNT = $0C ; word
HTAB = $24 ; byte
VTAB = $25 ; byte
RNDSEED = $4E ; word
; textrank
BestMatchIndex = $E5 ; word
tmpx = $E7 ; byte
remainder = $E8 ; word
num1 = $EA ; word
num2 = $EC ; byte
Timeout = $ED ; 3 bytes (used by SearchMode)
zpword = $F0 ; word
zpstring = $F2 ; word
runningscore= $F4 ; word
startat = $F6 ; byte
i = $F7 ; byte
tmp = $F8 ; byte
gamelength= $F9 ; byte
firstletter= $FA ; byte
MatchCount = $FB ; byte
BestMatchScore = $FC ; byte
; $FE ; used by ParseGamesList
; $FF ; used by ParseGamesList
; main memory
gPathname = $BFD0 ; used by SetPath/AddToPath
gKeyLen = $1F00 ; used by ParseGamesList
gKey = $1F01
UILine1 = $1FB0
UILine2 = $1FD8
UI_ToPlay = $1FF7
gValLen = $1F80
gVal = $1F81
; LC RAM 1
WaitForVBL = $FFF2
UnwaitForVBL = $FFF5
MockingboardStuff = $FFF8 ; bit 7 = 1 if speech chip present (Mockingboard "C")
; bit 6 = 1 if Mockingboard "B" (stereo) found (else Mockingboard "A")
; bit 4-5 unused
; bits 0-3: slot number
MachineStatus = $FFF9
; LC RAM 2
DisableAccelerator = $DBB4
EnableAccelerator = DisableAccelerator+3
; AND masks for MockingboardStuff
MOCKINGBOARD_SLOT = %00001111
HAS_SPEECH = %10000000
; AND masks for game info bitfield (after game display name in gGamesListStore)
HAS_DHGR_TITLE = %10000000 ; this one is hard-coded via BMI instead of AND/BNE
CHEAT_CATEGORY = %00001111
; AND masks for MachineStatus
HAS_JOYSTICK = %10000000
HAS_128K = %01000000
IS_IIGS = %00100000 ; /!\ do not use this to gate SHR, use SUPPORTS_SHR instead
HAS_VIDHD = %00010000
SUPPORTS_SHR = %00110000
CHEATS_ENABLED = %00001000
; shared symbols for prelaunch and effects to call ProRWTS2 functions
iCurBlockLo = $D401
iCurBlockHi = $D403
iProDOS_enter = $D678
LoadFileDirect = $DB01
iAuxReq = $DB27
launchpatch = $D616
iAddToPath = $FEC3
itraverse = $D8E0
ldrhi = $56
namlo = $57
namhi = $58
_CONSTANTS_=*
}

453
src/decrunch/exodecrunch.a Normal file
View File

@ -0,0 +1,453 @@
; This source code is altered and is not the original version found on
; the Exomizer homepage.
; It contains modifications made by qkumba to work with ACME assembler.
!cpu 6502
!to "DECRUNCH",plain
*=$200
;
; Copyright (c) 2002 - 2018 Magnus Lind.
;
; This software is provided 'as-is', without any express or implied warranty.
; In no event will the authors be held liable for any damages arising from
; the use of this software.
;
; Permission is granted to anyone to use this software for any purpose,
; including commercial applications, and to alter it and redistribute it
; freely, subject to the following restrictions:
;
; 1. The origin of this software must not be misrepresented; you must not
; claim that you wrote the original software. If you use this software in a
; product, an acknowledgment in the product documentation would be
; appreciated but is not required.
;
; 2. Altered source versions must be plainly marked as such, and must not
; be misrepresented as being the original software.
;
; 3. This notice may not be removed or altered from any distribution.
;
; 4. The names of this software and/or it's copyright holders may not be
; used to endorse or promote products derived from this software without
; specific prior written permission.
;
; -------------------------------------------------------------------
; The decruncher jsr:s to the get_crunched_byte address when it wants to
; read a crunched byte into A. This subroutine has to preserve X and Y
; register and must not modify the state of the carry nor the overflow flag.
; -------------------------------------------------------------------
;.import get_crunched_byte
; -------------------------------------------------------------------
; this function is the heart of the decruncher.
; It initializes the decruncher zeropage locations and precalculates the
; decrunch tables and decrunches the data
; This function will not change the interrupt status bit and it will not
; modify the memory configuration.
; -------------------------------------------------------------------
;.export decrunch
; -------------------------------------------------------------------
; Controls if the shared get_bits routines should be inlined or not.
;INLINE_GET_BITS=1
; -------------------------------------------------------------------
; if literal sequences is not used (the data was crunched with the -c
; flag) then the following line can be uncommented for shorter and.
; slightly faster code.
;LITERAL_SEQUENCES_NOT_USED = 1
; -------------------------------------------------------------------
; if the sequence length is limited to 256 (the data was crunched with
; the -M256 flag) then the following line can be uncommented for
; shorter and slightly faster code.
;MAX_SEQUENCE_LENGTH_256 = 1
; -------------------------------------------------------------------
; if the sequence length 3 has its own offset table then the following
; line can be uncommented for in some situations slightly better
; compression at the cost of a larger decrunch table.
EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE = 1
; -------------------------------------------------------------------
; zero page addresses used
; -------------------------------------------------------------------
zp_len_lo = $a7
zp_len_hi = $a8
zp_src_lo = $ae
zp_src_hi = zp_src_lo + 1
zp_bits_hi = $fc
zp_bitbuf = $fd
zp_dest_lo = zp_bitbuf + 1 ; dest addr lo
zp_dest_hi = zp_bitbuf + 2 ; dest addr hi
!IFDEF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE {
encoded_entries = 68
} ELSE {
encoded_entries = 52
}
tabl_bi = decrunch_table
tabl_lo = decrunch_table + encoded_entries
tabl_hi = decrunch_table + encoded_entries * 2
;; refill bits is always inlined
!MACRO mac_refill_bits {
pha
jsr get_crunched_byte
rol
sta zp_bitbuf
pla
}
!IFDEF INLINE_GET_BITS {
!MACRO mac_get_bits {
adc #$80 ; needs c=0, affects v
asl
bpl gb_skip
gb_next:
asl zp_bitbuf
bne gb_ok
mac_refill_bits
gb_ok:
rol
bmi gb_next
gb_skip:
bvc skip
gb_get_hi:
sec
sta zp_bits_hi
jsr get_crunched_byte
skip:
}
} ELSE {
!MACRO mac_get_bits {
jsr get_bits
}
}
; -------------------------------------------------------------------
; no code below this comment has to be modified in order to generate
; a working decruncher of this source file.
; However, you may want to relocate the tables last in the file to a
; more suitable address.
; -------------------------------------------------------------------
; -------------------------------------------------------------------
; jsr this label to decrunch, it will in turn init the tables and
; call the decruncher
; no constraints on register content, however the
; decimal flag has to be #0 (it almost always is, otherwise do a cld)
decrunch:
; -------------------------------------------------------------------
; init zeropage, x and y regs. (12 bytes)
;
ldy #0
ldx #3
init_zp:
jsr get_crunched_byte
sta zp_bitbuf - 1,x
dex
bne init_zp
; -------------------------------------------------------------------
; calculate tables (62 bytes) + get_bits macro
; x and y must be #0 when entering
;
clc
table_gen:
tax
tya
and #$0f
sta tabl_lo,y
beq shortcut ; start a new sequence
; -------------------------------------------------------------------
txa
adc tabl_lo - 1,y
sta tabl_lo,y
lda zp_len_hi
adc tabl_hi - 1,y
shortcut:
sta tabl_hi,y
; -------------------------------------------------------------------
lda #$01
sta <zp_len_hi
lda #$78 ; %01111000
+mac_get_bits
; -------------------------------------------------------------------
lsr
tax
beq rolled
php
rolle:
asl zp_len_hi
sec
ror
dex
bne rolle
plp
rolled:
ror
sta tabl_bi,y
bmi no_fixup_lohi
lda zp_len_hi
stx zp_len_hi
!BYTE $24
no_fixup_lohi:
txa
; -------------------------------------------------------------------
iny
cpy #encoded_entries
bne table_gen
; -------------------------------------------------------------------
; prepare for main decruncher
ldy zp_dest_lo
stx zp_dest_lo
stx zp_bits_hi
; -------------------------------------------------------------------
; copy one literal byte to destination (11(10) bytes)
;
literal_start1:
tya
bne no_hi_decr
dec zp_dest_hi
no_hi_decr:
dey
jsr get_crunched_byte
sta (zp_dest_lo),y
; -------------------------------------------------------------------
; fetch sequence length index (15 bytes)
; x must be #0 when entering and contains the length index + 1
; when exiting or 0 for literal byte
next_round:
dex
lda zp_bitbuf
no_literal1:
asl
bne nofetch8
jsr get_crunched_byte
rol
nofetch8:
inx
bcc no_literal1
sta zp_bitbuf
; -------------------------------------------------------------------
; check for literal byte (2 bytes)
;
beq literal_start1
; -------------------------------------------------------------------
; check for decrunch done and literal sequences (4 bytes)
;
cpx #$11
!IFDEF INLINE_GET_BITS {
bcc skip_jmp
jmp exit_or_lit_seq
skip_jmp:
} ELSE {
bcs exit_or_lit_seq
}
; -------------------------------------------------------------------
; calulate length of sequence (zp_len) (18(11) bytes) + get_bits macro
;
lda tabl_bi - 1,x
+mac_get_bits
adc tabl_lo - 1,x ; we have now calculated zp_len_lo
sta zp_len_lo
!IFNDEF MAX_SEQUENCE_LENGTH_256 {
lda zp_bits_hi
adc tabl_hi - 1,x ; c = 0 after this.
sta zp_len_hi
; -------------------------------------------------------------------
; here we decide what offset table to use (27(26) bytes) + get_bits_nc macro
; z-flag reflects zp_len_hi here
;
ldx zp_len_lo
} ELSE {
tax
}
lda #$e1
!IFDEF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE {
cpx #$04
} ELSE {
cpx #$03
}
bcs gbnc2_next
lda tabl_bit - 1,x
gbnc2_next:
asl zp_bitbuf
bne gbnc2_ok
tax
jsr get_crunched_byte
rol
sta zp_bitbuf
txa
gbnc2_ok:
rol
bcs gbnc2_next
tax
; -------------------------------------------------------------------
; calulate absolute offset (zp_src) (21(23) bytes) + get_bits macro
;
!IFNDEF MAX_SEQUENCE_LENGTH_256 {
lda #0
sta zp_bits_hi
}
lda tabl_bi,x
+mac_get_bits
adc tabl_lo,x
sta zp_src_lo
lda zp_bits_hi
adc tabl_hi,x
adc zp_dest_hi
sta zp_src_hi
; -------------------------------------------------------------------
; prepare for copy loop (2 bytes)
;
pre_copy:
ldx zp_len_lo
; -------------------------------------------------------------------
; main copy loop (30 bytes)
;
copy_next:
tya
bne copy_skip_hi
dec zp_dest_hi
dec zp_src_hi
copy_skip_hi:
dey
!IFNDEF LITERAL_SEQUENCES_NOT_USED {
bcs get_literal_byte
}
lda (zp_src_lo),y
literal_byte_gotten:
sta (zp_dest_lo),y
dex
bne copy_next
!IFNDEF MAX_SEQUENCE_LENGTH_256 {
lda zp_len_hi
!IFDEF INLINE_GET_BITS {
bne copy_next_hi
}
}
begin_stx:
stx zp_bits_hi
!IFNDEF INLINE_GET_BITS {
beq next_round
} ELSE {
jmp next_round
}
!IFNDEF MAX_SEQUENCE_LENGTH_256 {
copy_next_hi:
dec zp_len_hi
jmp copy_next
}
!IFNDEF LITERAL_SEQUENCES_NOT_USED {
get_literal_byte:
jsr get_crunched_byte
bcs literal_byte_gotten
}
; -------------------------------------------------------------------
; exit or literal sequence handling (16(12) bytes)
;
exit_or_lit_seq:
!IFNDEF LITERAL_SEQUENCES_NOT_USED {
beq decr_exit
jsr get_crunched_byte
!IFNDEF MAX_SEQUENCE_LENGTH_256 {
sta zp_len_hi
}
jsr get_crunched_byte
tax
bcs copy_next
decr_exit:
}
rts
!IFDEF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE {
; -------------------------------------------------------------------
; the static stable used for bits+offset for lengths 1, 2 and 3 (3 bytes)
; bits 2, 4, 4 and offsets 64, 48, 32 corresponding to
; %10010000, %11100011, %11100010
tabl_bit:
!BYTE $90, $e3, $e2
} ELSE {
; -------------------------------------------------------------------
; the static stable used for bits+offset for lengths 1 and 2 (2 bytes)
; bits 2, 4 and offsets 48, 32 corresponding to %10001100, %11100010
tabl_bit:
!BYTE $8c, $e2
}
; -------------------------------------------------------------------
; end of decruncher
; -------------------------------------------------------------------
!IFNDEF INLINE_GET_BITS {
get_bits:
adc #$80 ; needs c=0, affects v
asl
bpl gb_skip
gb_next:
asl zp_bitbuf
bne gb_ok
+mac_refill_bits
gb_ok:
rol
bmi gb_next
gb_skip:
bvs gb_get_hi
rts
gb_get_hi:
sec
sta zp_bits_hi
; fall through
}
get_crunched_byte:
lda _byte_lo
bne _byte_skip_hi
dec _byte_hi
_byte_skip_hi:
dec _byte_lo
_byte_lo = * + 1
_byte_hi = * + 2
lda $d1d1 ; needs to be set correctly before
; decrunch_file is called.
rts
; -------------------------------------------------------------------
; this 156 (204) byte table area may be relocated. It may also be
; clobbered by other data between decrunches.
; -------------------------------------------------------------------
decrunch_table:
!warn "entry=",*
pla
tay
pla
tax
clc
pla
adc #$F8
sta _byte_lo
pla
sta zp_bitbuf
pla
adc zp_bitbuf
sta _byte_hi
txa
pha
tya
pha
jmp decrunch
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;;.IFDEF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;;.ENDIF
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0
; -------------------------------------------------------------------
; end of decruncher
; -------------------------------------------------------------------

131
src/fx/fx.cover.fade.a Normal file
View File

@ -0,0 +1,131 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
; randomized fade-to-black routine customized for a specific piece of cover art
; with 75 fill rectangles
;
!cpu 6502
!to "build/FX/COVERFADE",plain
*=$6000
!source "src/fx/macros.a"
+READ_ROM_NO_WRITE
;init RNG
lda $C050
and #$7F
bne +
lda #$01
+ sta @rnd+1
sta @exit+1
lda #$20
sta $e6
;iterate
@loop ldy @rnd+1
tya
lsr
bcc +
;feedback polynomial forms #$41 for period of 127
eor #$41
+ sta @rnd+1
cpy #75+1
bcs +
lda width - 1, y
sta $fd
lda height - 1, y
sta $fe
lda startx - 1, y
sta $ff
lda starty - 1, y
-- pha
ldx #0
ldy #0
jsr $f411 ;hposn
lda #0
ldx $fd
ldy $ff
- sta ($26), y
iny
dex
bne -
pla
clc
adc #1
dec $fe
bne --
lda #80
sec
@wait1 pha
@wait2 sbc #1
bne @wait2
pla
sbc #1
bne @wait1
+
@rnd lda #0
@exit cmp #1
bne @loop
+READ_RAM1_WRITE_RAM1
rts
width
!byte 02, 03, 03, 05, 03, 03, 03, 03
!byte 03, 03, 03, 03, 04, 04, 03, 02
!byte 03, 03, 04, 07, 03, 02, 03, 03
!byte 03, 03, 03, 03, 03, 03, 03, 03
!byte 02, 03, 07, 04, 05, 03, 05, 05
!byte 03, 04, 06, 07, 04, 03, 03, 03
!byte 03, 02, 04, 05, 03, 03, 04, 06
!byte 03, 02, 04, 06, 03, 03, 03, 03
!byte 04, 03, 02, 03, 02, 03, 03, 03
!byte 03, 03, 02
height
!byte 12, 16, 26, 13, 15, 09, 24, 18
!byte 11, 23, 17, 15, 13, 20, 22, 13
!byte 16, 12, 21, 18, 10, 15, 10, 21
!byte 17, 12, 12, 12, 17, 12, 08, 26
!byte 18, 13, 44, 23, 21, 19, 17, 30
!byte 11, 10, 25, 18, 07, 14, 13, 15
!byte 11, 12, 28, 16, 15, 17, 35, 17
!byte 07, 13, 12, 06, 11, 12, 19, 15
!byte 11, 08, 13, 07, 16, 12, 24, 16
!byte 23, 22, 11
startx
!byte 000, 000, 001, 000, 000, 000, 000, 002
!byte 003, 001, 004, 003, 003, 003, 006, 007
!byte 005, 006, 006, 007, 008, 009, 008, 009
!byte 010, 011, 011, 012, 012, 012, 013, 014
!byte 015, 015, 014, 016, 017, 018, 017, 018
!byte 020, 020, 021, 021, 022, 022, 024, 025
!byte 024, 026, 027, 026, 028, 029, 028, 027
!byte 030, 031, 031, 032, 034, 033, 033, 033
!byte 032, 033, 034, 035, 036, 037, 037, 037
!byte 037, 037, 038
starty
!byte 000, 016, 042, 076, 103, 153, 167, 003
!byte 027, 123, 049, 098, 152, 172, 008, 036
!byte 139, 119, 071, 154, 101, 131, 181, 009
!byte 040, 070, 115, 134, 091, 177, 008, 030
!byte 068, 109, 128, 169, 003, 031, 058, 091
!byte 150, 179, 117, 072, 025, 046, 002, 151
!byte 178, 095, 008, 046, 069, 094, 118, 173
!byte 040, 018, 058, 003, 015, 034, 079, 106
!byte 147, 163, 178, 133, 051, 178, 148, 106
!byte 073, 022, 000

View File

@ -0,0 +1,121 @@
;license:MIT
;(c) 2017-2020 by qkumba/4am/John Brooks
!cpu 6502
!to "build/FX/DHGR.FIZZLE2BIT",plain
*=$6000
addrs = $6100 ; [256 bytes, page-aligned, duplicated in auxmem]
copymasks = $6200 ; [256 bytes, page-aligned, duplicated in auxmem]
ldx #(end-start) ; copy LFSR code to zero page
- lda start-1, x
sta $FF, x
dex
bne -
-- ldy #$40 ; create identical copymask tables in main and aux memory
ora #%10000000
- sta copymasks, x
sta $C005
sta copymasks, x
sta $C004
inx
dey
bne -
asl
asl
bne --
clc
-- ldy #$20 ; create identical address tables in main and aux memory
tya
- sta addrs, x
sta $C005
sta addrs, x
sta $C004
eor #$A0
sta addrs+1, x
sta $C005
sta addrs+1, x
sta $C004
eor #$A0
adc #1
inx
inx
dey
bne -
txa
bne --
jmp copyaux ; exit via LFSR code on zero page
start
!pseudopc 0 {
!byte %00000011
copyaux sta $C003 ; copy $4000/aux to $8000/main
ldx #$20
ldy #$00
a lda $4000, y
b sta $8000, y
iny
bne a
inc a+2
inc b+2
dex
bne a
sta $C002
sta $C001 ; 80STORE mode
; X,Y=0 on entry to LFSR
loop txa
loop1 eor #$B4 ; LFSR form 0xB400 with period 65535
tax ; X is LFSR high byte, Y is LFSR low byte
loop2 lda addrs, x ; which means X is the index into the base address lookup table
bmi aux ; and Y is the offset from the base address
sta $C054 ; switch $2000 access to main memory
sta <dst+2
eor #$60
sta <src+2
lda (<dst+1), y
src eor $FD00, y ; merge source and destination bits
and copymasks, x ; isolate the bits to replace, zero the rest
eor (<dst+1), y ; unmerge source and destination bits, leaves 'to keep' destination bits intact
dst sta $FD00, y ; write the result
txa
lsr
tax
tya
ror
tay
bcc loop2 ; C modified by ror
bne loop ; Z modified by tay
lda $C000
bmi exit
txa
bne loop1
exit lda $4000 ; last lousy byte (because LFSR never hits 0)
sta $2000
sta $C000 ; 80STORE mode off
rts
aux sta $C055 ; switch $2000 access to aux memory (read/write!)
sta <auxsrc+2
eor #$A0
sta <auxdst+2
lda (<auxdst+1), y
auxsrc eor $FD00, y
and copymasks, x
eor (<auxdst+1), y
auxdst sta $FD00, y
txa
lsr
tax
tya
ror
tay
bcc loop2
bne loop
lda $C000
bmi exit
txa
bne loop1
beq exit
}
end

62
src/fx/fx.dhgr.2pass.lr.a Normal file
View File

@ -0,0 +1,62 @@
;license:MIT
;(c) 2018 by 4am
;
!cpu 6502
!to "build/FX/DHGR.TWOPASS.LR",plain
*=$6000
hgrlo = $0200 ; [$C0 bytes, main memory only]
hgr1hi = $0300 ; [$C0 bytes, main memory only]
!source "src/fx/macros.a"
ldx #(end-start) ; copy code to zero page
- lda start-1, x
sta $FF, x
dex
bne -
+BUILD_HGR_LOOKUP_TABLES_X_IS_ALREADY_0 hgrlo, hgr1hi
jmp loop
start
!pseudopc 0 {
loop ldy #$00
inc <startx
columnloop
startx=*+1
ldx #$FF
rowloop
lda hgrlo, x
sta <src+1
sta <dst+1
lda hgr1hi, x
sta <dst+2
eor #$60
sta <src+2
clc
!byte $A9
- sec
src lda $FDFD, y ; SMC
dst sta $FDFD ,y ; SMC
sta $C003
sta $C005
bcc -
sta $C002
sta $C004
inx
inx
cpx #$C0
bcc rowloop
lda #$10
jsr WaitForKeyWithTimeout
bmi exit
iny
cpy #$28
bne columnloop
lda <startx
beq loop
exit rts
!source "src/wait.a"
}
end

View File

@ -0,0 +1,36 @@
;license:MIT
;(c) 2020 by 4am & qkumba
;
!cpu 6502
!to "build/FX/DHGR.48.2SNAKES",plain
*=$6000
USES_CLEAR = 0
!source "src/fx/fx.dhgr.48boxes.common.a"
!byte $00,$FE,$FC,$FA,$D8,$D6,$D4,$D2
!byte $F2,$F4,$F6,$F8,$DA,$DC,$DE,$E0
!byte $F0,$EE,$EC,$EA,$E8,$E6,$E4,$E2
!byte $E2,$E4,$E6,$E8,$EA,$EC,$EE,$F0
!byte $E0,$DE,$DC,$DA,$F8,$F6,$F4,$F2
!byte $D2,$D4,$D6,$D8,$FA,$FC,$FE,$00
StagesHi ; high bytes of address of drawing routine for each stage
!byte copy0F
!byte copy0E
!byte copy0D
!byte copy0C
!byte copy0B
!byte copy0A
!byte copy09
!byte copy08
!byte copy07
!byte copy06
!byte copy05
!byte copy04
!byte copy03
!byte copy02
!byte copy01
!byte copy00
EndStagesHi

52
src/fx/fx.dhgr.48boxes.a Normal file
View File

@ -0,0 +1,52 @@
;license:MIT
;(c) 2020 by 4am & qkumba
;
!cpu 6502
!to "build/FX/DHGR.48BOXES",plain
*=$6000
!source "src/fx/fx.dhgr.48boxes.common.a"
!byte $EC,$E8,$E4,$E0,$DC,$D8,$D4,$D0
!byte $F0,$EC,$E8,$E4,$E0,$DC,$D8,$D4
!byte $F4,$F0,$EC,$E8,$E4,$E0,$DC,$D8
!byte $F8,$F4,$F0,$EC,$E8,$E4,$E0,$DC
!byte $FC,$F8,$F4,$F0,$EC,$E8,$E4,$E0
!byte $00,$FC,$F8,$F4,$F0,$EC,$E8,$E4
StagesHi ; high bytes of address of drawing routine for each stage
!byte clear00
!byte clear01
!byte clear02
!byte clear03
!byte clear04
!byte clear05
!byte clear06
!byte clear07
!byte clear08
!byte clear09
!byte clear0A
!byte clear0B
!byte clear0C
!byte clear0D
!byte clear0E
!byte clear0F
!byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
!byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
!byte copy0F
!byte copy0E
!byte copy0D
!byte copy0C
!byte copy0B
!byte copy0A
!byte copy09
!byte copy08
!byte copy07
!byte copy06
!byte copy05
!byte copy04
!byte copy03
!byte copy02
!byte copy01
!byte copy00
EndStagesHi

View File

@ -0,0 +1,36 @@
;license:MIT
;(c) 2020 by 4am & qkumba
;
!cpu 6502
!to "build/FX/DHGR.48.ARROW",plain
*=$6000
USES_CLEAR = 0
!source "src/fx/fx.dhgr.48boxes.common.a"
!byte $FA,$F6,$F4,$F0,$EE,$EA,$E8,$E4
!byte $FC,$FA,$F6,$F4,$F0,$EE,$EA,$E8
!byte $00,$FC,$FA,$F6,$F4,$F0,$EE,$EA
!byte $FF,$FD,$F9,$F7,$F3,$F1,$ED,$EB
!byte $FD,$F9,$F7,$F3,$F1,$ED,$EB,$E7
!byte $F9,$F7,$F3,$F1,$ED,$EB,$E7,$E5
StagesHi ; high bytes of address of drawing routine for each stage
!byte copy00
!byte copy01
!byte copy02
!byte copy03
!byte copy04
!byte copy05
!byte copy06
!byte copy07
!byte copy08
!byte copy09
!byte copy0A
!byte copy0B
!byte copy0C
!byte copy0D
!byte copy0E
!byte copy0F
EndStagesHi

View File

@ -0,0 +1,759 @@
;license:MIT
;(c) 2020 by 4am & qkumba
;
; The screen is separated into 48 boxes.
; Boxes are laid out in a grid, left-to-right, top-down:
;
; 0 1 2 3 4 5 6 7
; 8 9 10 11 12 13 14 15
; 16 17 18 19 20 21 22 23
; 24 25 26 27 28 29 30 31
; 32 33 34 35 36 37 38 39
; 40 41 42 43 44 45 46 47
;
; Each box is 70x32 pixels, so each row of each box is 5 consecutive
; bytes in main memory and another 5 in auxiliary memory, all of which
; are easy to find once you calculate the base address for that row.
;
; |BoxInitialStages| defines the initial grid of stages for each box.
; Each stage is used an index into the |StagesHi| array
; to find the drawing routine for that stage (if any).
; Each box's stage is incremented after each iteration through the main loop.
; When the main loop iterates through all 48 boxes without drawing anything,
; the program exits.
;
; There are 16 clear routines that set certain bits to 0 (black),
; labeled clear00..clear0F. clear00 clears the inner-most box, and
; clear0F clears the outermost box (see diagram).
; There are 16 copy routines that copy certain bits from the source
; image on page 2 to the destination image on page 1, labeled copy00..copy0F.
;
; row| pixels
; ---+---------------------------------------
; 00 |FFFFFFF|FFFFFFF|FFFFFFF|FFFFFFF|FFFFFFF
; 01 |FEEEEEE|EEEEEEE|EEEEEEE|EEEEEEE|EEEEEEF
; 02 |FEDDDDD|DDDDDDD|DDDDDDD|DDDDDDD|DDDDDEF
; 03 |FEDCCCC|CCCCCCC|CCCCCCC|CCCCCCC|CCCCDEF
; 04 |FEDCBBB|BBBBBBB|BBBBBBB|BBBBBBB|BBBCDEF
; 05 |FEDCBAA|AAAAAAA|AAAAAAA|AAAAAAA|AABCDEF
; 06 |FEDCBA9|9999999|9999999|9999999|9ABCDEF
; 07 |FEDCBA9|8888888|8888888|8888888|9ABCDEF
; ---+-------+-------+-------+-------+-------
; 08 |FEDCBA9|8777777|7777777|7777778|9ABCDEF
; 09 |FEDCBA9|8766666|6666666|6666678|9ABCDEF
; 0A |FEDCBA9|8765555|5555555|5555678|9ABCDEF
; 0B |FEDCBA9|8765444|4444444|4445678|9ABCDEF
; 0C |FEDCBA9|8765433|3333333|3345678|9ABCDEF
; 0D |FEDCBA9|8765432|2222222|2345678|9ABCDEF
; 0E |FEDCBA9|8765432|1111111|2345678|9ABCDEF
; 0F |FEDCBA9|8765432|1000001|2345678|9ABCDEF
; ---+-------+-------+-------+-------+-------
; 10 |FEDCBA9|8765432|1000001|2345678|9ABCDEF
; 11 |FEDCBA9|8765432|1111111|2345678|9ABCDEF
; 12 |FEDCBA9|8765432|2222222|2345678|9ABCDEF
; 13 |FEDCBA9|8765433|3333333|3345678|9ABCDEF
; 14 |FEDCBA9|8765444|4444444|4445678|9ABCDEF
; 15 |FEDCBA9|8765555|5555555|5555678|9ABCDEF
; 16 |FEDCBA9|8766666|6666666|6666678|9ABCDEF
; 17 |FEDCBA9|8777777|7777777|7777778|9ABCDEF
; ---+-------+-------+-------+-------+-------
; 18 |FEDCBA9|8888888|8888888|8888888|9ABCDEF
; 19 |FEDCBA9|9999999|9999999|9999999|9ABCDEF
; 1A |FEDCBAA|AAAAAAA|AAAAAAA|AAAAAAA|AABCDEF
; 1B |FEDCBBB|BBBBBBB|BBBBBBB|BBBBBBB|BBBCDEF
; 1C |FEDCCCC|CCCCCCC|CCCCCCC|CCCCCCC|CCCCDEF
; 1D |FEDDDDD|DDDDDDD|DDDDDDD|DDDDDDD|DDDDDEF
; 1E |FEEEEEE|EEEEEEE|EEEEEEE|EEEEEEE|EEEEEEF
; 1F |FFFFFFF|FFFFFFF|FFFFFFF|FFFFFFF|FFFFFFF
;
!ifndef USES_CLEAR {
; if an effect doesn't use any clear stages, you can reduce code size
; by setting USES_CLEAR=0 before including this file
USES_CLEAR = 1
}
src = $00 ; [word][must be at $00] used by drawing routines
dst = $02 ; [word] used by drawing routines
rowcount = $04 ; [byte] used by drawing routines
tmpy = $05 ; [byte] used by drawing routines
box = $0E ; [byte] counter in main loop
any = $0F ; [byte][must be at $0F] counter in main loop
BoxStages = $10 ; [$30 bytes] current stage for each box
auxsrc_hgrhi = $BC00 ; [$C0 bytes] HGR base addresses (hi) starting at $9000
hgrhi = $BD00 ; [$C0 bytes] HGR base addresses (hi) starting at $2000
hgrlo = $BE00 ; [$C0 bytes] HGR base addresses (lo) starting at $2000
BoxesX = $BDC0 ; [$30 bytes] starting row for each box
BoxesY = $BEC0 ; [$30 bytes] starting byte offset for each box
; High bytes of drawing routines for each stage (actual routines will be page-aligned).
; To minimize code size, we build drawing routines in this order:
; - copy01 (STAGE1 template)
; - copy00 (STAGE0 template)
; - copy0F..copy09 (OUTER_STAGE template)
; - copy08..copy02 (MIDDLE_STAGE template)
; - change some opcodes to turn the 'copy' routines into 'clear' routines
; - clear0F..clear08 (OUTER_STAGE)
; - clear07..clear02 (MIDDLE_STAGE)
; - clear01 (STAGE1)
; - clear00 (STAGE0)
clear00 = $70
clear01 = $71
clear02 = $72
clear03 = $73
clear04 = $74
clear05 = $75
clear06 = $76
clear07 = $77
clear08 = $78
clear09 = $79
clear0A = $7A
clear0B = $7B
clear0C = $7C
clear0D = $7D
clear0E = $7E
clear0F = $7F
copy02 = $80
copy03 = $81
copy04 = $82
copy05 = $83
copy06 = $84
copy07 = $85
copy08 = $86
copy09 = $87
copy0A = $88
copy0B = $89
copy0C = $8A
copy0D = $8B
copy0E = $8C
copy0F = $8D
copy00 = $8E
copy01 = $8F
; tokens for code generation
; used as indexes into |codegen_pieces| and |codegen_piece_lengths|,
; so keep all three in sync
k_rts = 0 ; must be 0
k_edge_left_mask_main = 1 ; must be 1
k_edge_right_mask_main = 2 ; must be 2
k_left_mask_main = 3 ; must be 3
k_right_mask_main = 4 ; must be 4
k_edge_left_mask_aux = 5 ; must be 5
k_edge_right_mask_aux = 6 ; must be 6
k_left_mask_aux = 7 ; must be 7
k_right_mask_aux = 8 ; must be 8
k_current_page = 9
k_switch_to_main = 10
k_switch_to_aux = 11
k_switch_to_aux_and_byte_copy = 12
k_inx_and_recalc = 13
k_recalc = 14
k_set_row_count = 15
k_set_first_row = 16
k_iny2 = 17
k_iny = 18
k_dey = 19
k_save_y = 20
k_restore_y = 21
k_middle_jsr = 22
k_outer_jsr = 23
k_middle_branch = 24
k_outer_branch = 25
k_mask_copy_pre = 26
k_mask_copy_post = 27
k_byte_copy = 28
k_byte_copy_and_iny = 29
k_bitcopy = 30 ; must be last token
!source "src/fx/macros.a"
; generate |BoxesX| and |BoxesY| arrays
ldx #48
ldy #$A0
lda #$23
pha
- tya
sta BoxesX-1, x
pla
sta BoxesY-1, x
sec
sbc #5
bcs +
lda #$23
+ pha
dex
txa
and #7
bne -
tya
sec
sbc #$20
tay
txa
bne -
pla
; construct drawing routines for each stage
jsr BuildDrawingRoutines
; A=0 here
; set up zero page for drawing phase
tax
- ldy BoxInitialStages-BoxStages, x
sty $00, x
sta EndStagesHi, x
inx
bne -
; X=0 here
+BUILD_HGR_LOOKUP_TABLES_X_IS_ALREADY_0 hgrlo, hgrhi
; X=$C0 here
- lda hgrhi-1, x
clc
adc #$70
sta auxsrc_hgrhi-1, x
dex
bne -
sta $C001 ; 80STORE mode so we can bank $2000/aux in & out with STA $C055 & $C054
MainLoop ldx #48
BoxLoop stx box
ldy BoxStages-1, x ; for each box, get its current stage
inc BoxStages-1, x ; increment every box's stage every time through the loop
lda StagesHi, y
beq NextBox ; if stage's drawing routine is 0, nothing to do
sta j+2
lda BoxesX-1, x
ldy BoxesY-1, x ; Y = starting byte offset for this box
tax ; X = starting HGR row for this box
inc any ; was initialized by the BoxStages copy loop
clc
j jsr $FD00 ; [SMC] call drawing routine for this stage
ldx box
NextBox dex
bne BoxLoop
lda any
beq + ; if we didn't draw anything in any box, we're done
stx any ; X=0 here
bit $C000 ; check for key
bpl MainLoop
+ sta $C000 ; 80STORE off
; execution falls through here
; These are all the pieces of code we need to construct the drawing routines.
; There are 32 drawing routines (16 if USES_CLEAR=0), which we construct from
; four templates (below). Templates use tokens to refer to these code pieces.
; Note that several pieces overlap in order to minimize code size.
; Everything from CODEGEN_COPY_START and onward is copied to zero page for
; the code generation phase on program startup.
EDGE_LEFT_MASK_MAIN = $01 ; address $01 to match token
EDGE_RIGHT_MASK_MAIN = $02 ; address $02 to match token
LEFT_MASK_MAIN = $03 ; address $03 to match token
RIGHT_MASK_MAIN = $04 ; address $04 to match token
EDGE_LEFT_MASK_AUX = $05 ; address $05 to match token
EDGE_RIGHT_MASK_AUX = $06 ; address $06 to match token
LEFT_MASK_AUX = $07 ; address $07 to match token
RIGHT_MASK_AUX = $08 ; address $08 to match token
CODEGEN_COPY_START
!pseudopc 9 {
RTS0
SWITCH_TO_MAIN
sta $C054
SWITCH_TO_MAIN_E
rts ; also terminates MainLoop
RTS0_E
;
SWITCH_TO_AUX_AND_BYTE_COPY
SWITCH_TO_AUX
sta $C055
lda auxsrc_hgrhi, x
sta src+1
SWITCH_TO_AUX_E
BYTECOPY_AND_INY
BYTECOPY
lda (src), y
sta (dst), y
BYTECOPY_E
SWITCH_TO_AUX_AND_BYTE_COPY_E
INY2
INY1
iny
INY1_E
BYTECOPY_AND_INY_E
iny
INY2_E
;
DEY1
dey
DEY1_E
;
SAVE_Y
sty tmpy
SAVE_Y_E
;
RESTORE_Y
ldy tmpy
RESTORE_Y_E
;
INX_AND_RECALC
inx
RECALC
lda hgrlo, x
sta src
sta dst
lda hgrhi, x
sta dst+1
eor #$60
sta src+1
RECALC_E
INX_AND_RECALC_E
;
SET_ROW_COUNT
ROW_COUNT=*+1
lda #$1D ; SMC
sta rowcount
SET_ROW_COUNT_E
;
SET_FIRST_ROW
txa
FIRST_ROW=*+1
adc #$0E ; SMC
tax
SET_FIRST_ROW_E
;
MASKCOPY_PRE
lda (dst), y
BIT_FOR_CLEAR
eor (src), y
!byte $29 ; (AND #$44 opcode)
MASKCOPY_PRE_E
;
codegen_pieces ; address of each of the pieces (on zero page, so 1 byte)
!byte <RTS0
; these 8 addresses are never used so we stuff 8 bytes of unrelated data here
;!byte <EDGE_LEFT_MASK_MAIN
;!byte <EDGE_RIGHT_MASK_MAIN
;!byte <LEFT_MASK_MAIN
;!byte <RIGHT_MASK_MAIN
;!byte <EDGE_LEFT_MASK_AUX
;!byte <EDGE_RIGHT_MASK_AUX
;!byte <LEFT_MASK_AUX
;!byte <RIGHT_MASK_AUX
;
MIDDLE_BRANCH
dec rowcount
!byte $10,$C8
MIDDLE_BRANCH_E
;
OUTER_BRANCH
dec rowcount
!byte $10,$C6
OUTER_BRANCH_E
;
!byte <codegen_dst ; current page
!byte <SWITCH_TO_MAIN
!byte <SWITCH_TO_AUX
!byte <SWITCH_TO_AUX_AND_BYTE_COPY
!byte <INX_AND_RECALC
!byte <RECALC
!byte <SET_ROW_COUNT
!byte <SET_FIRST_ROW
!byte <INY2
!byte <INY1
!byte <DEY1
!byte <SAVE_Y
!byte <RESTORE_Y
!byte <MIDDLE_JSR
!byte <OUTER_JSR
!byte <MIDDLE_BRANCH
!byte <OUTER_BRANCH
!byte <MASKCOPY_PRE
!byte <MASKCOPY_POST
!byte <BYTECOPY
!byte <BYTECOPY_AND_INY
;!byte 0 ; bitcopy pseudo-opcode has no piece of its own
codegen_piece_lengths ; length of each of the pieces
!byte RTS0_E-RTS0
; these 8 lengths are never used so we stuff 8 bytes of unrelated data here
;!byte 1 ; edge left mask main
;!byte 1 ; edge right mask main
;!byte 1 ; left mask main
;!byte 1 ; right mask main
;!byte 1 ; edge left mask aux
;!byte 1 ; edge right mask aux
;!byte 1 ; left mask aux
;!byte 1 ; right mask aux
;
MASKCOPY_POST
eor (dst), y
sta (dst), y
MASKCOPY_POST_E
;
MIDDLE_JSR
!byte $20,$47
MIDDLE_JSR_E
OUTER_JSR
!byte $20,$48
OUTER_JSR_E
;
!byte 1 ; current page
!byte SWITCH_TO_MAIN_E-SWITCH_TO_MAIN
!byte SWITCH_TO_AUX_E-SWITCH_TO_AUX
!byte SWITCH_TO_AUX_AND_BYTE_COPY_E-SWITCH_TO_AUX_AND_BYTE_COPY
!byte INX_AND_RECALC_E-INX_AND_RECALC
!byte RECALC_E-RECALC
!byte SET_ROW_COUNT_E-SET_ROW_COUNT
!byte SET_FIRST_ROW_E-SET_FIRST_ROW
!byte INY2_E-INY2
!byte INY1_E-INY1
!byte DEY1_E-DEY1
!byte SAVE_Y_E-SAVE_Y
!byte RESTORE_Y_E-RESTORE_Y
!byte MIDDLE_JSR_E-MIDDLE_JSR
!byte OUTER_JSR_E-OUTER_JSR
!byte MIDDLE_BRANCH_E-MIDDLE_BRANCH
!byte OUTER_BRANCH_E-OUTER_BRANCH
!byte MASKCOPY_PRE_E-MASKCOPY_PRE
!byte MASKCOPY_POST_E-MASKCOPY_POST
!byte BYTECOPY_E-BYTECOPY
!byte BYTECOPY_AND_INY_E-BYTECOPY_AND_INY
;!byte $FF ; negative length -> do special bitcopy logic during codegen
BuildDrawingRoutineFrom
sta <codegen_token_src ; STA opcode ($85) also serves as 'length' of k_bitcopy token
BuildDrawingRoutine
ldy #0
sty <codegen_token_x
- jsr GetNextToken
pha
jsr ProcessToken
pla
bne -
dec <codegen_dst
inc <FIRST_ROW
rts
GetNextToken
codegen_token_x=*+1
ldx #$00
codegen_token_src=*+1
lda OUTER_STAGE, x
inc <codegen_token_x
rts
ProcessBitcopyToken
jsr GetNextToken
sta <bitcopy_mask
bitcopy_mask=*+1
lda $FD ; SMC
beq ExitProcessToken ; copymask=0 -> nothing to generate
bmi + ; copymask>=$80 -> assume full byte
lda #k_mask_copy_pre
jsr ProcessToken
lda #1
sta <piece_length
lda <bitcopy_mask
jsr ProcessMaskToken
lda #k_mask_copy_post
+HIDE_NEXT_2_BYTES
+ lda #k_byte_copy
; execution falls through here
ProcessToken
tax
lda <codegen_piece_lengths, x
bmi ProcessBitcopyToken ; only bitcopy has length>=$80
sta <piece_length
lda <codegen_pieces, x
; execution falls through here
ProcessMaskToken
sta <piece_src
ldx #0
-
piece_src=*+1
lda $FD, x ; SMC
!byte $99,$00 ; STA $4400, Y
codegen_dst
!byte copy01 ; SMC
iny
inx
piece_length=*+1
cpx #$FD ; SMC
bcc -
ExitProcessToken
rts
codegen_stage
!byte 27
codegen_maskindex
!byte 0
CopyAuxDHGRToMain
; X=0
sta $C003 ; copy $4000-5FFF/aux to $9000-AFFF/main
ldy #$20
@a lda $4000, x
@b sta $9000, x
inx
bne @a
inc <@a+2
inc <@b+2
dey
bne @a
sta $C002
; X=0,Y=0
rts
}
EdgeRightMasks
!byte %00000000
!byte %00000000
!byte %00000000
!byte %00000001
!byte %00000111
!byte %00011111
!byte %11111111
LeftMasks
!byte %01100000
!byte %00011000
!byte %00000111
!byte %00000000
RightMasks
!byte %00000000
!byte %00000000
!byte %00000000 ; also terminates LeftMasks
!byte %00000001
!byte %00000110
!byte %00011000
EdgeLeftMasks
!byte %01100000 ; also terminates RightMasks
!byte %01111000
!byte %11111111
!byte %11111111
!byte %11111111
!byte %11111111
!byte %11111111
EdgeLeftMasksAux
!byte %00000000
!byte %00000000
!byte %00000000
!byte %01000000
!byte %01110000
!byte %01111100
!byte %11111111
RightMasksAux
!byte %00000011
!byte %00001100
!byte %01110000
!byte %00000000
LeftMasksAux
!byte %00000000
!byte %00000000
!byte %00000000 ; also terminates RightMasksAux
!byte %01000000
!byte %00110000
!byte %00001100
EdgeRightMasksAux
!byte %00000011 ; also terminates LeftMasksAux
!byte %00001111
!byte %11111111
!byte %11111111
!byte %11111111
!byte %11111111
!byte %11111111
BuildDrawingRoutines
; copy codegen data to zero page
ldx #0
- lda CODEGEN_COPY_START, x
sta $09, x
inx
bne -
;X=0 here
; copy the half of the source image from $4000/aux to main memory
jsr CopyAuxDHGRToMain
;X,Y=0 here
; generate drawing routines for copy01, then copy00
jsr BuildStage1And0
; A=0 here
sta <FIRST_ROW
; generate drawing routines for copy0F..copy02, then clear0F..clear02
lda #<MIDDLE_STAGE
--- eor #(<OUTER_STAGE XOR <MIDDLE_STAGE)
sta <codegen_token_src
ldx #6
-- stx <codegen_maskindex
lda EdgeLeftMasks, x
sta <EDGE_LEFT_MASK_MAIN
lda EdgeRightMasks, x
sta <EDGE_RIGHT_MASK_MAIN
lda LeftMasks, x
sta <LEFT_MASK_MAIN
lda RightMasks, x
sta <RIGHT_MASK_MAIN
lda EdgeLeftMasksAux, x
sta <EDGE_LEFT_MASK_AUX
lda EdgeRightMasksAux, x
sta <EDGE_RIGHT_MASK_AUX
lda LeftMasksAux, x
sta <LEFT_MASK_AUX
lda RightMasksAux, x
sta <RIGHT_MASK_AUX
jsr BuildDrawingRoutine
dec <ROW_COUNT
dec <ROW_COUNT
dec <codegen_stage
bmi BuildStage1And0
lda <codegen_stage
eor #13
bne +
!if USES_CLEAR {
; reset counts and switch from copy to clear
sta <FIRST_ROW
lda #$1D
sta <ROW_COUNT
lda #$A9
sta <BYTECOPY
lda #$24
sta <BIT_FOR_CLEAR
} else {
rts
}
+ lda <codegen_token_src
ldx <codegen_maskindex
dex
bmi ---
bpl -- ; always branches
; generate drawing routines for copy01, copy00 (or clear01, clear00)
BuildStage1And0
lda #%00011111
sta <LEFT_MASK_MAIN
lda #%01111100
sta <LEFT_MASK_AUX
lda #<STAGE1
jsr BuildDrawingRoutineFrom
lda #<STAGE0
jmp BuildDrawingRoutineFrom
; All template p-code must be on the same page
;!align 255,0
; Template for 'stage 0' routine (copy00), which copies the innermost
; part of the box (labeled '0' in diagram above).
STAGE0
!byte k_set_first_row
!byte k_iny2
!byte k_recalc
!byte k_bitcopy, k_left_mask_main
!byte k_switch_to_aux
!byte k_bitcopy, k_left_mask_main
!byte k_switch_to_main
!byte k_inx_and_recalc
!byte k_bitcopy, k_left_mask_aux
!byte k_switch_to_aux
!byte k_bitcopy, k_left_mask_aux
!byte k_rts ; also serves as an end-of-template marker
; Template for 'stage 1' routine (copy01), which copies the pixels
; around the innermost box (labeled '1' in diagram above).
STAGE1
!byte k_set_first_row
!byte k_iny2
!byte k_recalc
!byte k_byte_copy
!byte k_switch_to_aux_and_byte_copy
!byte k_switch_to_main
!byte k_inx_and_recalc
!byte k_byte_copy
!byte k_switch_to_aux_and_byte_copy
!byte k_switch_to_main
!byte k_inx_and_recalc
!byte k_byte_copy
!byte k_switch_to_aux_and_byte_copy
!byte k_switch_to_main
!byte k_inx_and_recalc
!byte k_byte_copy
!byte k_switch_to_aux_and_byte_copy
!byte k_rts ; also serves as an end-of-template marker
; Template for stages 2-8 (copy02..copy08)
MIDDLE_STAGE
!byte k_set_row_count
!byte k_set_first_row
!byte k_iny
!byte k_save_y
!byte k_middle_jsr, k_current_page
;-
!byte k_inx_and_recalc
!byte k_bitcopy, k_left_mask_main
!byte k_iny2
!byte k_bitcopy, k_right_mask_main
!byte k_switch_to_aux
!byte k_bitcopy, k_right_mask_aux
!byte k_restore_y
!byte k_bitcopy, k_left_mask_aux
!byte k_switch_to_main
!byte k_middle_branch
;+
!byte k_inx_and_recalc
!byte k_bitcopy, k_edge_left_mask_main
!byte k_iny
!byte k_byte_copy_and_iny
!byte k_bitcopy, k_edge_right_mask_main
!byte k_switch_to_aux
!byte k_bitcopy, k_edge_right_mask_aux
!byte k_dey
!byte k_byte_copy
!byte k_dey
!byte k_bitcopy, k_edge_left_mask_aux
!byte k_rts ; also serves as an end-of-template marker
; Template for stages 9-15 (copy09..copy0F)
OUTER_STAGE
!byte k_set_row_count
!byte k_set_first_row
!byte k_save_y
!byte k_outer_jsr, k_current_page
;-
!byte k_inx_and_recalc
!byte k_bitcopy, k_left_mask_main
!byte k_iny2
!byte k_iny2
!byte k_bitcopy, k_right_mask_main
!byte k_switch_to_aux
!byte k_bitcopy, k_right_mask_aux
!byte k_restore_y
!byte k_bitcopy, k_left_mask_aux
!byte k_switch_to_main
!byte k_outer_branch
;+
!byte k_inx_and_recalc
!byte k_bitcopy, k_edge_left_mask_main
!byte k_iny
!byte k_byte_copy_and_iny
!byte k_byte_copy_and_iny
!byte k_byte_copy_and_iny
!byte k_bitcopy, k_edge_right_mask_main
!byte k_switch_to_aux
!byte k_bitcopy, k_edge_right_mask_aux
!byte k_dey
!byte k_byte_copy
!byte k_dey
!byte k_byte_copy
!byte k_dey
!byte k_byte_copy
!byte k_dey
!byte k_bitcopy, k_edge_left_mask_aux
!byte k_rts ; also serves as an end-of-template marker
!if >* != >STAGE0 {
!error "Templates are not all on same page"
}
; Note: the final k_rts is later copied to zero page $0F and used in MainLoop,
; so don't put any more code before BoxInitialStages.
BoxInitialStages

View File

@ -0,0 +1,254 @@
!macro AUXMEM {
sta $C055
lda auxsrc_hgrhi, x
sta src+1
}
!macro MAINMEM {
sta $C054
}
!macro INX_AND_RECALC {
inx
lda hgrlo, x
sta src
sta dst
lda hgrhi, x
sta dst+1
eor #$60
sta src+1
}
!macro BITCOPY .copy, .mask {
!if .mask != %00000000 {
!if .mask = %11111111 {
!if .copy != 0 {
lda (src), y
} else {
lda #$00
}
sta (dst), y
} else {
lda (dst), y
!if .copy != 0 {
eor (src), y
} else {
bit src
}
and #.mask
eor (dst), y
sta (dst), y
}
}
}
!macro MIDDLE_STAGE_DHGR .copy, .rowcount, .firstrow, .edge_left_mask_main, .edge_right_mask_main, .left_mask_main, .right_mask_main, .edge_left_mask_aux, .edge_right_mask_aux, .left_mask_aux, .right_mask_aux {
lda #(.rowcount-2) ;k_set_row_count
sta rowcount
txa ;k_set_first_row
adc #(.firstrow-1)
tax
iny ;k_iny
sty tmpy ;k_save_y
jsr + ;k_middle_jsr, k_current_page
-
+INX_AND_RECALC ;k_inx_and_recalc
+BITCOPY .copy, .left_mask_main ;k_bitcopy, k_left_mask_main
iny ;k_iny
iny ;k_iny
+BITCOPY .copy, .right_mask_main ;k_bitcopy, k_right_mask_main
+AUXMEM ;k_switch_to_aux
+BITCOPY .copy, .right_mask_aux ;k_bitcopy, k_right_mask_aux
ldy tmpy ;k_restore_y
+BITCOPY .copy, .left_mask_aux ;k_bitcopy, k_left_mask_aux
+MAINMEM ;k_switch_to_main
dec rowcount ;k_middle_branch
bpl -
+
+INX_AND_RECALC ;k_inx_and_recalc
+BITCOPY .copy, .edge_left_mask_main ;k_bitcopy, k_edge_left_mask_main
iny ;k_iny
+BITCOPY .copy, %11111111 ;k_bitcopy, k_full_mask
iny ;k_iny
+BITCOPY .copy, .edge_right_mask_main ;k_bitcopy, k_edge_right_mask_main
+AUXMEM ;k_switch_to_aux
+BITCOPY .copy, .edge_right_mask_aux ;k_bitcopy, k_edge_right_mask_aux
dey ;k_dey
+BITCOPY .copy, %11111111 ;k_bitcopy, k_full_mask
dey ;k_dey
+BITCOPY .copy, .edge_left_mask_aux ;k_bitcopy, k_edge_left_mask_aux
+MAINMEM ;k_switch_to_main
rts
}
!macro OUTER_STAGE_DHGR .copy, .rowcount, .firstrow, .edge_left_mask_main, .edge_right_mask_main, .left_mask_main, .right_mask_main, .edge_left_mask_aux, .edge_right_mask_aux, .left_mask_aux, .right_mask_aux {
lda #(.rowcount-2) ;k_set_row_count
sta rowcount
txa ;k_set_first_row
adc #(.firstrow-1)
tax
sty tmpy ;k_save_y
jsr + ;k_outer_jsr
-
+INX_AND_RECALC ;k_inx_and_recalc
+BITCOPY .copy, .left_mask_main ;k_bitcopy, k_left_mask_main
iny ;k_iny
iny ;k_iny
iny ;k_iny
iny ;k_iny
+BITCOPY .copy, .right_mask_main ;k_bitcopy, k_right_mask_main
+AUXMEM ;k_switch_to_aux
+BITCOPY .copy, .right_mask_aux ;k_bitcopy, k_right_mask_aux
ldy tmpy ;k_restore_y
+BITCOPY .copy, .left_mask_aux ;k_bitcopy, k_left_mask_aux
+MAINMEM ;k_switch_to_main
dec rowcount ;k_outer_branch
bpl -
+
+INX_AND_RECALC ;k_inx_and_recalc
+BITCOPY .copy, .edge_left_mask_main ;k_bitcopy, k_edge_left_mask_main
iny ;k_iny
+BITCOPY .copy, %11111111 ;k_bitcopy, k_full_mask
iny ;k_iny
+BITCOPY .copy, %11111111 ;k_bitcopy, k_full_mask
iny ;k_iny
+BITCOPY .copy, %11111111 ;k_bitcopy, k_full_mask
iny ;k_iny
+BITCOPY .copy, .edge_right_mask_main ;k_bitcopy, k_edge_right_mask_main
+AUXMEM ;k_switch_to_aux
+BITCOPY .copy, .edge_right_mask_aux ;k_bitcopy, k_edge_right_mask_aux
dey ;k_dey
+BITCOPY .copy, %11111111 ;k_bitcopy, k_full_mask
dey ;k_dey
+BITCOPY .copy, %11111111 ;k_bitcopy, k_full_mask
dey ;k_dey
+BITCOPY .copy, %11111111 ;k_bitcopy, k_full_mask
dey ;k_dey
+BITCOPY .copy, .edge_left_mask_aux ;k_bitcopy, k_edge_left_mask_aux
+MAINMEM ;k_switch_to_main
rts
}
!macro STAGE0 .copy {
txa ;k_set_first_row
adc #($0F-1)
tax
iny ;k_iny
iny ;k_iny
+INX_AND_RECALC ;k_inx_and_recalc
+BITCOPY .copy, %00011111 ;k_bitcopy, k_left_mask_main
+AUXMEM ;k_switch_to_aux
+BITCOPY .copy, %01111100 ;k_bitcopy, k_left_mask_aux
+MAINMEM ;k_switch_to_main
+INX_AND_RECALC ;k_inx_and_recalc
+BITCOPY .copy, %00011111 ;k_bitcopy, k_left_mask_main
+AUXMEM ;k_switch_to_aux
+BITCOPY .copy, %01111100 ;k_bitcopy, k_left_mask_aux
+MAINMEM ;k_switch_to_main
rts
}
!macro STAGE1 .copy {
txa ;k_set_first_row
adc #($0E-1)
tax
iny ;k_iny
iny ;k_iny
+INX_AND_RECALC ;k_inx_and_recalc
+BITCOPY .copy, %11111111 ;k_bitcopy, k_full_mask
+AUXMEM ;k_switch_to_aux
+BITCOPY .copy, %11111111 ;k_bitcopy, k_full_mask
+MAINMEM ;k_switch_to_main
+INX_AND_RECALC ;k_inx_and_recalc
+BITCOPY .copy, %11111111 ;k_bitcopy, k_full_mask
+AUXMEM ;k_switch_to_aux
+BITCOPY .copy, %11111111 ;k_bitcopy, k_full_mask
+MAINMEM ;k_switch_to_main
+INX_AND_RECALC ;k_inx_and_recalc
+BITCOPY .copy, %11111111 ;k_bitcopy, k_full_mask
+AUXMEM ;k_switch_to_aux
+BITCOPY .copy, %11111111 ;k_bitcopy, k_full_mask
+MAINMEM ;k_switch_to_main
+INX_AND_RECALC ;k_inx_and_recalc
+BITCOPY .copy, %11111111 ;k_bitcopy, k_full_mask
+AUXMEM ;k_switch_to_aux
+BITCOPY .copy, %11111111 ;k_bitcopy, k_full_mask
+MAINMEM ;k_switch_to_main
rts
}
;clear00
*=$7000
+STAGE0 0
;clear01
*=$7100
+STAGE1 0
;clear02-0F
*=$7200
+MIDDLE_STAGE_DHGR 0, $05, $0D, %01100000, %00000000, %01100000, %00000000, %00000000, %00000011, %00000000, %00000011
*=$7300
+MIDDLE_STAGE_DHGR 0, $07, $0C, %01111000, %00000000, %00011000, %00000000, %00000000, %00001111, %00000000, %00001100
*=$7400
+MIDDLE_STAGE_DHGR 0, $09, $0B, %11111111, %00000000, %00000111, %00000000, %00000000, %11111111, %00000000, %01110000
*=$7500
+MIDDLE_STAGE_DHGR 0, $0B, $0A, %11111111, %00000001, %00000000, %00000001, %01000000, %11111111, %01000000, %00000000
*=$7600
+MIDDLE_STAGE_DHGR 0, $0D, $09, %11111111, %00000111, %00000000, %00000110, %01110000, %11111111, %00110000, %00000000
*=$7700
+MIDDLE_STAGE_DHGR 0, $0F, $08, %11111111, %00011111, %00000000, %00011000, %01111100, %11111111, %00001100, %00000000
*=$7800
+MIDDLE_STAGE_DHGR 0, $11, $07, %11111111, %11111111, %00000000, %01100000, %11111111, %11111111, %00000011, %00000000
*=$7900
+OUTER_STAGE_DHGR 0, $13, $06, %01100000, %00000000, %01100000, %00000000, %00000000, %00000011, %00000000, %00000011
*=$7A00
+OUTER_STAGE_DHGR 0, $15, $05, %01111000, %00000000, %00011000, %00000000, %00000000, %00001111, %00000000, %00001100
*=$7B00
+OUTER_STAGE_DHGR 0, $17, $04, %11111111, %00000000, %00000111, %00000000, %00000000, %11111111, %00000000, %01110000
*=$7C00
+OUTER_STAGE_DHGR 0, $19, $03, %11111111, %00000001, %00000000, %00000001, %01000000, %11111111, %01000000, %00000000
*=$7D00
+OUTER_STAGE_DHGR 0, $1B, $02, %11111111, %00000111, %00000000, %00000110, %01110000, %11111111, %00110000, %00000000
*=$7E00
+OUTER_STAGE_DHGR 0, $1D, $01, %11111111, %00011111, %00000000, %00011000, %01111100, %11111111, %00001100, %00000000
*=$7F00
+OUTER_STAGE_DHGR 0, $1F, $00, %11111111, %11111111, %00000000, %01100000, %11111111, %11111111, %00000011, %00000000
;copy02-08
; cp rowc frow edgeleft edgeright left right edgeltaux edgertaux leftaux rightaux
*=$A000
+MIDDLE_STAGE_DHGR 1, $05, $0D, %01100000, %00000000, %01100000, %00000000, %00000000, %00000011, %00000000, %00000011
*=$A100
+MIDDLE_STAGE_DHGR 1, $07, $0C, %01111000, %00000000, %00011000, %00000000, %00000000, %00001111, %00000000, %00001100
*=$A200
+MIDDLE_STAGE_DHGR 1, $09, $0B, %11111111, %00000000, %00000111, %00000000, %00000000, %11111111, %00000000, %01110000
*=$A300
+MIDDLE_STAGE_DHGR 1, $0B, $0A, %11111111, %00000001, %00000000, %00000001, %01000000, %11111111, %01000000, %00000000
*=$A400
+MIDDLE_STAGE_DHGR 1, $0D, $09, %11111111, %00000111, %00000000, %00000110, %01110000, %11111111, %00110000, %00000000
*=$A500
+MIDDLE_STAGE_DHGR 1, $0F, $08, %11111111, %00011111, %00000000, %00011000, %01111100, %11111111, %00001100, %00000000
*=$A600
+MIDDLE_STAGE_DHGR 1, $11, $07, %11111111, %11111111, %00000000, %01100000, %11111111, %11111111, %00000011, %00000000
;copy09-0F
*=$A700
+OUTER_STAGE_DHGR 1, $13, $06, %01100000, %00000000, %01100000, %00000000, %00000000, %00000011, %00000000, %00000011
*=$A800
+OUTER_STAGE_DHGR 1, $15, $05, %01111000, %00000000, %00011000, %00000000, %00000000, %00001111, %00000000, %00001100
*=$A900
+OUTER_STAGE_DHGR 1, $17, $04, %11111111, %00000000, %00000111, %00000000, %00000000, %11111111, %00000000, %01110000
*=$AA00
+OUTER_STAGE_DHGR 1, $19, $03, %11111111, %00000001, %00000000, %00000001, %01000000, %11111111, %01000000, %00000000
*=$AB00
+OUTER_STAGE_DHGR 1, $1B, $02, %11111111, %00000111, %00000000, %00000110, %01110000, %11111111, %00110000, %00000000
*=$AC00
+OUTER_STAGE_DHGR 1, $1D, $01, %11111111, %00011111, %00000000, %00011000, %01111100, %11111111, %00001100, %00000000
*=$AD00
+OUTER_STAGE_DHGR 1, $1F, $00, %11111111, %11111111, %00000000, %01100000, %11111111, %11111111, %00000011, %00000000
;copy00
*=$AE00
+STAGE0 1
;copy01
*=$AF00
+STAGE1 1

View File

@ -0,0 +1,36 @@
;license:MIT
;(c) 2020 by 4am & qkumba
;
!cpu 6502
!to "build/FX/DHGR.48.DOWN",plain
*=$6000
USES_CLEAR = 0
!source "src/fx/fx.dhgr.48boxes.common.a"
!byte $00,$FF,$00,$FF,$00,$FF,$00,$FF
!byte $FE,$FD,$FE,$FD,$FE,$FD,$FE,$FD
!byte $FC,$FB,$FC,$FB,$FC,$FB,$FC,$FB
!byte $FA,$F9,$FA,$F9,$FA,$F9,$FA,$F9
!byte $F8,$F7,$F8,$F7,$F8,$F7,$F8,$F7
!byte $F6,$F5,$F6,$F5,$F6,$F5,$F6,$F5
StagesHi ; high bytes of address of drawing routine for each stage
!byte copy0F
!byte copy0E
!byte copy0D
!byte copy0C
!byte copy0B
!byte copy0A
!byte copy09
!byte copy08
!byte copy07
!byte copy06
!byte copy05
!byte copy04
!byte copy03
!byte copy02
!byte copy01
!byte copy00
EndStagesHi

View File

@ -0,0 +1,36 @@
;license:MIT
;(c) 2020 by 4am & qkumba
;
!cpu 6502
!to "build/FX/DHGR.48.LDIAGON",plain
*=$6000
USES_CLEAR = 0
!source "src/fx/fx.dhgr.48boxes.common.a"
!byte $00,$FE,$FC,$FA,$F8,$F6,$F4,$F2
!byte $FE,$FC,$FA,$F8,$F6,$F4,$F2,$F0
!byte $FC,$FA,$F8,$F6,$F4,$F2,$F0,$EE
!byte $FA,$F8,$F6,$F4,$F2,$F0,$EE,$EC
!byte $F8,$F6,$F4,$F2,$F0,$EE,$EC,$EA
!byte $F6,$F4,$F2,$F0,$EE,$EC,$EA,$E8
StagesHi ; high bytes of address of drawing routine for each stage
!byte copy00
!byte copy01
!byte copy02
!byte copy03
!byte copy04
!byte copy05
!byte copy06
!byte copy07
!byte copy08
!byte copy09
!byte copy0A
!byte copy0B
!byte copy0C
!byte copy0D
!byte copy0E
!byte copy0F
EndStagesHi

View File

@ -0,0 +1,36 @@
;license:MIT
;(c) 2020 by 4am & qkumba
;
!cpu 6502
!to "build/FX/DHGR.48.SIDES",plain
*=$6000
USES_CLEAR = 0
!source "src/fx/fx.dhgr.48boxes.common.a"
!byte $00,$FC,$F8,$F4,$F0,$EC,$E8,$E4
!byte $E4,$E8,$EC,$F0,$F4,$F8,$FC,$00
!byte $00,$FC,$F8,$F4,$F0,$EC,$E8,$E4
!byte $E4,$E8,$EC,$F0,$F4,$F8,$FC,$00
!byte $00,$FC,$F8,$F4,$F0,$EC,$E8,$E4
!byte $E4,$E8,$EC,$F0,$F4,$F8,$FC,$00
StagesHi ; high bytes of address of drawing routine for each stage
!byte copy00
!byte copy01
!byte copy02
!byte copy03
!byte copy04
!byte copy05
!byte copy06
!byte copy07
!byte copy08
!byte copy09
!byte copy0A
!byte copy0B
!byte copy0C
!byte copy0D
!byte copy0E
!byte copy0F
EndStagesHi

View File

@ -0,0 +1,36 @@
;license:MIT
;(c) 2020 by 4am & qkumba
;
!cpu 6502
!to "build/FX/DHGR.48.SNAKE",plain
*=$6000
USES_CLEAR = 0
!source "src/fx/fx.dhgr.48boxes.common.a"
!byte $00,$FF,$FE,$FD,$FC,$FB,$FA,$F9
!byte $F1,$F2,$F3,$F4,$F5,$F6,$F7,$F8
!byte $F0,$EF,$EE,$ED,$EC,$EB,$EA,$E9
!byte $E1,$E2,$E3,$E4,$E5,$E6,$E7,$E8
!byte $E0,$DF,$DE,$DD,$DC,$DB,$DA,$D9
!Byte $D1,$D2,$D3,$D4,$D5,$D6,$D7,$D8
StagesHi ; high bytes of address of drawing routine for each stage
!byte copy0F
!byte copy0E
!byte copy0D
!byte copy0C
!byte copy0B
!byte copy0A
!byte copy09
!byte copy08
!byte copy07
!byte copy06
!byte copy05
!byte copy04
!byte copy03
!byte copy02
!byte copy01
!byte copy00
EndStagesHi

View File

@ -0,0 +1,53 @@
;license:MIT
;(c) 2020 by 4am & qkumba
;
!cpu 6502
!to "build/FX/DHGR.48.SNAKEC",plain
*=$6000
!source "src/fx/fx.dhgr.48boxes.common.a"
!byte $00,$FF,$FE,$FD,$FC,$FB,$FA,$F9
!byte $F1,$F2,$F3,$F4,$F5,$F6,$F7,$F8
!byte $F0,$EF,$EE,$ED,$EC,$EB,$EA,$E9
!byte $E1,$E2,$E3,$E4,$E5,$E6,$E7,$E8
!byte $E0,$DF,$DE,$DD,$DC,$DB,$DA,$D9
!Byte $D1,$D2,$D3,$D4,$D5,$D6,$D7,$D8
StagesHi ; high bytes of address of drawing routine for each stage
!byte clear0F
!byte clear0E
!byte clear0D
!byte clear0C
!byte clear0B
!byte clear0A
!byte clear09
!byte clear08
!byte clear07
!byte clear06
!byte clear05
!byte clear04
!byte clear03
!byte clear02
!byte clear01
!byte clear00
!byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
!byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
!byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
!byte copy0F
!byte copy0E
!byte copy0D
!byte copy0C
!byte copy0B
!byte copy0A
!byte copy09
!byte copy08
!byte copy07
!byte copy06
!byte copy05
!byte copy04
!byte copy03
!byte copy02
!byte copy01
!byte copy00
EndStagesHi

View File

@ -0,0 +1,36 @@
;license:MIT
;(c) 2020 by 4am & qkumba
;
!cpu 6502
!to "build/FX/DHGR.48.SPIRAL",plain
*=$6000
USES_CLEAR = 0
!source "src/fx/fx.dhgr.48boxes.common.a"
!byte $00,$E9,$EA,$EB,$EC,$ED,$EE,$EF
!byte $FF,$E8,$D9,$DA,$DB,$DC,$DD,$F0
!byte $FE,$E7,$D8,$D1,$D2,$D3,$DE,$F1
!byte $FD,$E6,$D7,$D6,$D5,$D4,$DF,$F2
!byte $FC,$E5,$E4,$E3,$E2,$E1,$E0,$F3
!byte $FB,$FA,$F9,$F8,$F7,$F6,$F5,$F4
StagesHi ; high bytes of address of drawing routine for each stage
!byte copy0F
!byte copy0E
!byte copy0D
!byte copy0C
!byte copy0B
!byte copy0A
!byte copy09
!byte copy08
!byte copy07
!byte copy06
!byte copy05
!byte copy04
!byte copy03
!byte copy02
!byte copy01
!byte copy00
EndStagesHi

View File

@ -0,0 +1,56 @@
;license:MIT
;(c) 2020 by 4am & qkumba
;
!cpu 6502
!to "build/FX/DHGR.48.SPIRALC",plain
*=$6000
!source "src/fx/fx.dhgr.48boxes.common.a"
!byte $00,$FE,$FC,$FA,$F8,$F6,$F4,$F2
!Byte $D0,$CE,$CC,$CA,$C8,$C6,$C4,$F0
!Byte $D2,$B0,$AE,$AC,$AA,$A8,$C2,$EE
!Byte $D4,$B2,$A0,$A2,$A4,$A6,$C0,$EC
!Byte $D6,$B4,$B6,$B8,$BA,$BC,$BE,$EA
!Byte $D8,$DC,$DE,$E0,$E2,$E4,$E6,$E8
StagesHi ; high bytes of address of drawing routine for each stage
!byte clear00
!byte clear01
!byte clear02
!byte clear03
!byte clear04
!byte clear05
!byte clear06
!byte clear07
!byte clear08
!byte clear09
!byte clear0A
!byte clear0B
!byte clear0C
!byte clear0D
!byte clear0E
!byte clear0F
!byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
!byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
!byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
!byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
!byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
!byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
!byte copy00
!byte copy01
!byte copy02
!byte copy03
!byte copy04
!byte copy05
!byte copy06
!byte copy07
!byte copy08
!byte copy09
!byte copy0A
!byte copy0B
!byte copy0C
!byte copy0D
!byte copy0E
!byte copy0F
EndStagesHi

View File

@ -0,0 +1,36 @@
;license:MIT
;(c) 2020 by 4am & qkumba
;
!cpu 6502
!to "build/FX/DHGR.48.SYNC",plain
*=$6000
USES_CLEAR = 0
!source "src/fx/fx.dhgr.48boxes.common.a"
!byte $00,$FF,$00,$FF,$00,$FF,$00,$FF
!byte $FF,$00,$FF,$00,$FF,$00,$FF,$00
!byte $00,$FF,$00,$FF,$00,$FF,$00,$FF
!byte $FF,$00,$FF,$00,$FF,$00,$FF,$00
!byte $00,$FF,$00,$FF,$00,$FF,$00,$FF
!byte $FF,$00,$FF,$00,$FF,$00,$FF,$00
StagesHi ; high bytes of address of drawing routine for each stage
!byte copy0F
!byte copy0E
!byte copy0D
!byte copy0C
!byte copy0B
!byte copy0A
!byte copy09
!byte copy08
!byte copy07
!byte copy06
!byte copy05
!byte copy04
!byte copy03
!byte copy02
!byte copy01
!byte copy00
EndStagesHi

View File

@ -0,0 +1,50 @@
;license:MIT
;(c) 2020 by 4am & qkumba
;
!cpu 6502
!to "build/FX/DHGR.48.SYNCC",plain
*=$6000
!source "src/fx/fx.dhgr.48boxes.common.a"
!byte $00,$FF,$00,$FF,$00,$FF,$00,$FF
!byte $FF,$00,$FF,$00,$FF,$00,$FF,$00
!byte $00,$FF,$00,$FF,$00,$FF,$00,$FF
!byte $FF,$00,$FF,$00,$FF,$00,$FF,$00
!byte $00,$FF,$00,$FF,$00,$FF,$00,$FF
!byte $FF,$00,$FF,$00,$FF,$00,$FF,$00
StagesHi ; high bytes of address of drawing routine for each stage
!byte clear0F
!byte clear0E
!byte clear0D
!byte clear0C
!byte clear0B
!byte clear0A
!byte clear09
!byte clear08
!byte clear07
!byte clear06
!byte clear05
!byte clear04
!byte clear03
!byte clear02
!byte clear01
!byte clear00
!byte copy00
!byte copy01
!byte copy02
!byte copy03
!byte copy04
!byte copy05
!byte copy06
!byte copy07
!byte copy08
!byte copy09
!byte copy0A
!byte copy0B
!byte copy0C
!byte copy0D
!byte copy0E
!byte copy0F
EndStagesHi

View File

@ -0,0 +1,81 @@
;license:MIT
;(c) 2020 by 4am
;
!cpu 6502
!to "build/FX/DHGR.BAR.DISSLV",plain
*=$6000
hgrlo = $0200 ; [$C0 bytes, main memory only]
hgr1hi = $0300 ; [$C0 bytes, main memory only]
!source "src/fx/macros.a"
ldx #(end-start) ; copy code to zero page
- lda start-1, x
sta $FF, x
dex
bne -
+BUILD_HGR_LOOKUP_TABLES_X_IS_ALREADY_0 hgrlo, hgr1hi
jmp loop
start
!pseudopc 0 {
row1=*+1
loop ldx #$40
lda hgrlo-$40, x
sta <src1+1
sta <dst1+1
lda hgr1hi-$40, x
sta <dst1+2
eor #$60
sta <src1+2
clc
+HIDE_NEXT_BYTE
- sec
ldy #$27
src1 lda $FDFD, y ; SMC
dst1 sta $FDFD, y ; SMC
dey
dey
bpl src1
jsr toaux
bcc -
jsr tomain
row2=*+1
ldx #$BF
lda hgrlo, x
sta <src2+1
sta <dst2+1
lda hgr1hi, x
sta <dst2+2
eor #$60
sta <src2+2
clc
+HIDE_NEXT_BYTE
- sec
ldy #$26
src2 lda $FDFD, y ; SMC
dst2 sta $FDFD, y ; SMC
dey
dey
bpl src2
jsr toaux
bcc -
jsr tomain
lda #$30
jsr WaitForKeyWithTimeout
bmi exit
dec row2
inc row1
bne loop
tomain sta $C002
sta $C004
exit rts
toaux sta $C003
sta $C005
rts
!source "src/wait.a"
}
end

16
src/fx/fx.dhgr.bubbles.a Normal file
View File

@ -0,0 +1,16 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.BUBBLES",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.1bit.a"
+FX_INITONCE_1BIT CoordinatesFile, Start
Start
+FX_PRECOMPUTED_1BIT_DHGR Coordinates1Bit
CoordinatesFile
!byte 15
!text "FX/BUBBLES.DATA"

View File

@ -0,0 +1,17 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.BUBBLES.IN",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.1bit.a"
+FX_INITONCE_1BIT CoordinatesFile, Start
+FX_REVERSE_1BIT
Start
+FX_PRECOMPUTED_1BIT_DHGR Coordinates1Bit
CoordinatesFile
!byte 15
!text "FX/BUBBLES.DATA"

View File

@ -0,0 +1,16 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.BUTTERFLY",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.2bit.a"
+FX_INITONCE_2BIT CoordinatesFile, Start
Start
+FX_PRECOMPUTED_2BIT_DHGR Coordinates2Bit
CoordinatesFile
!byte 17
!text "FX/BUTTERFLY.DATA"

View File

@ -0,0 +1,17 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.BFLY.IN",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.2bit.a"
+FX_INITONCE_2BIT CoordinatesFile, Start
+FX_REVERSE_2BIT
Start
+FX_PRECOMPUTED_2BIT_DHGR Coordinates2Bit
CoordinatesFile
!byte 17
!text "FX/BUTTERFLY.DATA"

View File

@ -0,0 +1,17 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.BFLY.RIP",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.2bit.a"
+FX_INITONCE_2BIT CoordinatesFile, Start
+FX_RIPPLE_2BIT
Start
+FX_PRECOMPUTED_2BIT_DHGR Coordinates2Bit
CoordinatesFile
!byte 17
!text "FX/BUTTERFLY.DATA"

21
src/fx/fx.dhgr.common.a Normal file
View File

@ -0,0 +1,21 @@
!macro COPY_TO_AUXMEM .startpage, .pagecount {
ldx #.pagecount
lda #.startpage
sta $FF
lda #$00
sta $FE
tay
sta $c005
- lda ($FE),y
sta ($FE),y
iny
bne -
inc $FF
dex
bne -
sta $c004
}
!macro COPY_SELF_TO_AUXMEM {
+COPY_TO_AUXMEM $60, $60
}

16
src/fx/fx.dhgr.corner4.a Normal file
View File

@ -0,0 +1,16 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.CORNER4",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.1bit.a"
+FX_INITONCE_1BIT CoordinatesFile, Start
Start
+FX_PRECOMPUTED_1BIT_DHGR Coordinates1Bit
CoordinatesFile
!byte 15
!text "FX/CORNER4.DATA"

View File

@ -0,0 +1,17 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.CORNER4.IN",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.1bit.a"
+FX_INITONCE_1BIT CoordinatesFile, Start
+FX_REVERSE_1BIT
Start
+FX_PRECOMPUTED_1BIT_DHGR Coordinates1Bit
CoordinatesFile
!byte 15
!text "FX/CORNER4.DATA"

View File

@ -0,0 +1,17 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.CORNER4RIP",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.1bit.a"
+FX_INITONCE_1BIT CoordinatesFile, Start
jsr EndCoordinates1Bit+1
Start
+FX_PRECOMPUTED_1BIT_DHGR Coordinates1Bit
CoordinatesFile
!byte 15
!text "FX/CORNER4.DATA"

166
src/fx/fx.dhgr.diagonal.a Normal file
View File

@ -0,0 +1,166 @@
;license:MIT
;(c) 2019 by 4am
;
!cpu 6502
!to "build/FX/DHGR.DIAGONAL",plain
*=$6000
hgrlo = $0200 ; [$C0 bytes, main memory only]
hgr1hi = $0300 ; [$C0 bytes, main memory only]
copymasks= $02C0 ; [$08 bytes, different values in main and auxmem]
!source "src/fx/macros.a"
ldx #(end-start) ; copy code to zero page
- lda start-1, x
sta $FF, x
dex
bne -
+BUILD_HGR_LOOKUP_TABLES_X_IS_ALREADY_0 hgrlo, hgr1hi
ldy #8 ; copy copymask arrays into place in main and auxmem
- lda copymasks_main-1, y
sta copymasks-1, y
lda copymasks_aux-1, y
sta $C005
sta copymasks-1, y
sta $C004
dey
bne -
jmp loop
;1GFEDCBA ->
;1GGFFEED (main) +
;1DCCBBAA (aux)
copymasks_aux ; used in reverse order
!byte %11111111
!byte %11111100
!byte %11110000
!byte %11000000
!byte %00000000
!byte %00000000
!byte %00000000
!byte %00000000
copymasks_main ; used in reverse order
!byte %11111111
!byte %11111111
!byte %11111111
!byte %11111111
!byte %11111110
!byte %11111000
!byte %11100000
!byte %00000000
start
!pseudopc 0 {
loop lda #23
sta <row
ldy <col
jsr WaitForVBL
rowloop lda <row
asl
asl
asl
tax
lda hgrlo, x
sta <src+1
sta <dst+1
lda hgr1hi, x
sta <dst+2
eor #$60
sta <src+2
cpy #40
bcs +
jsr DHGRBlockCopyWithMask
+ iny
cpy #40
bcs +
jsr DHGRBlockCopy
+ dec <row
bpl rowloop
lda $C000
bmi exit
dec <col
dec <counter
bne loop
exit jmp UnwaitForVBL
DHGRBlockCopyWithMask
; in: A = HGR row / 8 (0x00..0x17)
; Y = HGR column (0x00..0x27)
; mainmem banked in
; out: Y preserved
; A/X clobbered
lda #$02
sta <pass
-- ldx #7
clc
- lda (<dst+1), y
src eor $FDFD, y
and copymasks, x
eor (<dst+1), y
dst sta $FDFD, y
lda <src+2
adc #$04
sta <src+2
eor #$60
sta <dst+2
dex
bpl -
lda <src+2
sec
sbc #$20
sta <src+2
eor #$60
sta <dst+2
sta $C003
sta $C005
dec <pass
bne --
sta $C002
sta $C004
rts
DHGRBlockCopy
-- ldx #7
clc
- lda (<src+1), y
sta (<dst+1), y
lda <src+2
adc #$04
sta <src+2
eor #$60
sta <dst+2
dex
bpl -
lda <src+2
sec
sbc #$20
sta <src+2
eor #$60
sta <dst+2
sta $C003
sta $C005
ldx #7
clc
- lda (<src+1), y
sta (<dst+1), y
lda <src+2
adc #$04
sta <src+2
eor #$60
sta <dst+2
dex
bpl -
sta $C002
sta $C004
rts
row !byte 23
col !byte 39
counter !byte 64
pass
}
end

89
src/fx/fx.dhgr.fizzle.a Normal file
View File

@ -0,0 +1,89 @@
;license:MIT
;(c) 2017-2020 by qkumba/4am/John Brooks
;
!cpu 6502
!to "build/FX/DHGR.FIZZLE",plain
*=$6000
addrs=$C0 ; [$40 bytes]
ldx #$1F ; build address lookup table
- txa
eor #$20
sta addrs, x
eor #$A0
sta addrs+$20, x
dex
bpl -
ldx #(end-start) ; copy LFSR code to zero page
- lda start-1, x
sta $FF, x
dex
bne -
jmp copyaux
start
!pseudopc 0 {
copyaux sta $C003 ; copy $4000/aux to $8000/main
ldx #$20
ldy #$00
a lda $4000, y
b sta $8000, y
iny
bne a
inc a+2
inc b+2
dex
bne a
sta $C002
sta $C001 ; 80STORE mode
; X,Y=0 on entry to LFSR
; in: X,Y=0
loop txa
loop1 eor #$35 ; LFSR form 0x3500 with period 16383
tax
loop2 lda addrs, x
bmi aux
sta $C054 ; switch $2000 access to main memory
sta <dst+2
eor #$60
sta <src+2
src lda $FD00, y
dst sta $FD00, y
txa
lsr
tax
tya
ror
tay
bcc loop2
bne loop
bit $C000
bmi exit
txa
bne loop1
exit lda $4000 ; last lousy byte (because LFSR never hits 0)
sta $2000
sta $C000 ; 80STORE mode off
rts
aux sta $C055 ; switch $2000 access to aux memory (read/write!)
sta <auxsrc+2
eor #$A0
sta <auxdst+2
auxsrc lda $FD00, y
auxdst sta $FD00, y
txa
lsr
tax
tya
ror
tay
bcc loop2
bne loop
lda $C000
bmi exit
txa
bne loop1
beq exit
}
end

97
src/fx/fx.dhgr.flick.a Normal file
View File

@ -0,0 +1,97 @@
;license:MIT
;(c) 2020 by 4am
;
!cpu 6502
!to "build/FX/DHGR.FLICK",plain
*=$6000
hgrlo = $200 ; [$C0 bytes, main memory only]
startrows_by_column = $2C0 ; [$28 bytes, main memory only]
hgr1hi = $300 ; [$C0 bytes, main memory only]
!source "src/fx/macros.a"
ldx #(end-start) ; copy code to zero page
- lda start-1, x
sta $FF, x
lda #0
sta startrows_by_column-1, x
dex
bne -
+BUILD_HGR_LOOKUP_TABLES_X_IS_ALREADY_0 hgrlo, hgr1hi
jmp loop
start
!pseudopc 0 {
loop
ldy #$27
columnloop
ldx startrows_by_column, y
cpx #$C0
bcs nextcolumn
lda rowcounts_by_column, y
beq nextcolumn
bmi nextcolumn
sta <rowcount
rowloop lda hgrlo, x
sta <src+1
sta <dst+1
lda hgr1hi, x
sta <dst+2
eor #$60
sta <src+2
clc
!byte $A9
bankloop sec
src lda $FDFD, y
dst sta $FDFD, y
sta $C003
sta $C005
bcc bankloop
sta $C002
sta $C004
inx
dec <rowcount
bne rowloop
nextcolumn
dey
bpl columnloop
ldy #$27
- lda <rowcounts_by_column, y
bmi +
beq +
tax
clc
adc startrows_by_column, y
sta startrows_by_column, y
lda <next_rowcount, x
sta <rowcounts_by_column, y
bne ++ ; always branches
+ clc
adc #1
sta <rowcounts_by_column, y
++ dey
bpl -
lda $C000
bmi exit
lda <rowcounts_by_column+$27
cmp #$80
bne loop
exit rts
rowcounts_by_column
!byte $01,$01,$00,$00,$FF,$FF,$FE,$FE
!byte $FD,$FD,$FC,$FC,$FB,$FB,$FA,$FA
!byte $F9,$F9,$F8,$F8,$F7,$F7,$F6,$F6
!byte $F5,$F5,$F4,$F4,$F3,$F3,$F2,$F2
!byte $F1,$F1,$F0,$F0,$EF,$EF,$EE,$EE
next_rowcount
!byte $01,$03,$80,$05,$02,$07,$04,$09
!byte $06,$0B,$08,$0D,$0A,$0F,$0C,$11
!byte $0E,$15,$10,$FD,$FD,$12
rowcount
}
end

16
src/fx/fx.dhgr.heart.a Normal file
View File

@ -0,0 +1,16 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.HEART",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.2bit.a"
+FX_INITONCE_2BIT CoordinatesFile, Start
Start
+FX_PRECOMPUTED_2BIT_DHGR Coordinates2Bit
CoordinatesFile
!byte 13
!text "FX/HEART.DATA"

17
src/fx/fx.dhgr.heart.in.a Normal file
View File

@ -0,0 +1,17 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.HEART.IN",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.2bit.a"
+FX_INITONCE_2BIT CoordinatesFile, Start
+FX_REVERSE_2BIT
Start
+FX_PRECOMPUTED_2BIT_DHGR Coordinates2Bit
CoordinatesFile
!byte 13
!text "FX/HEART.DATA"

View File

@ -0,0 +1,17 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.HEART.RIP",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.2bit.a"
+FX_INITONCE_2BIT CoordinatesFile, Start
+FX_RIPPLE_2BIT
Start
+FX_PRECOMPUTED_2BIT_DHGR Coordinates2Bit
CoordinatesFile
!byte 13
!text "FX/HEART.DATA"

16
src/fx/fx.dhgr.iris.a Normal file
View File

@ -0,0 +1,16 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.IRIS",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.1bit.a"
+FX_INITONCE_1BIT CoordinatesFile, Start
Start
+FX_PRECOMPUTED_1BIT_DHGR Coordinates1Bit
CoordinatesFile
!byte 12
!text "FX/IRIS.DATA"

17
src/fx/fx.dhgr.iris.in.a Normal file
View File

@ -0,0 +1,17 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.IRIS.IN",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.1bit.a"
+FX_INITONCE_1BIT CoordinatesFile, Start
+FX_REVERSE_1BIT
Start
+FX_PRECOMPUTED_1BIT_DHGR Coordinates1Bit
CoordinatesFile
!byte 12
!text "FX/IRIS.DATA"

16
src/fx/fx.dhgr.maple.a Normal file
View File

@ -0,0 +1,16 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.MAPLE",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.2bit.a"
+FX_INITONCE_2BIT CoordinatesFile, Start
Start
+FX_PRECOMPUTED_2BIT_DHGR Coordinates2Bit
CoordinatesFile
!byte 13
!text "FX/MAPLE.DATA"

17
src/fx/fx.dhgr.maple.in.a Normal file
View File

@ -0,0 +1,17 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.MAPLE.IN",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.2bit.a"
+FX_INITONCE_2BIT CoordinatesFile, Start
+FX_REVERSE_2BIT
Start
+FX_PRECOMPUTED_2BIT_DHGR Coordinates2Bit
CoordinatesFile
!byte 13
!text "FX/MAPLE.DATA"

View File

@ -0,0 +1,17 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.MAPLE.RIP",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.2bit.a"
+FX_INITONCE_2BIT CoordinatesFile, Start
+FX_RIPPLE_2BIT
Start
+FX_PRECOMPUTED_2BIT_DHGR Coordinates2Bit
CoordinatesFile
!byte 13
!text "FX/MAPLE.DATA"

View File

@ -0,0 +1,149 @@
;license:MIT
;(c) 2020 by 4am
;
!source "src/fx/fx.hgr.precomputed.1bit.a"
!source "src/fx/fx.dhgr.common.a"
!macro BUILD_SPARSE_BITMASKS_DHGR .copymasks, .mirror_copymasks {
; build sparse lookup tables for bitmasks
ldx #$00
txa
- sta .copymasks, x
sta $C005
sta .copymasks, x
sta $C004
inx
bne -
lda #%00000111
sta .copymasks+$80
sta .mirror_copymasks+$40
lda #%00011000
sta .copymasks+$A0
sta .mirror_copymasks+$20
lda #%01100000
sta .copymasks+$C0
sta .mirror_copymasks
sta $C005
lda #%10000011
sta .copymasks
sta .mirror_copymasks+$C0
lda #%10001100
sta .copymasks+$20
sta .mirror_copymasks+$A0
lda #%10110000
sta .copymasks+$40
sta .mirror_copymasks+$80
lda #%11000000
sta .copymasks+$60
sta .mirror_copymasks+$60
sta $C004
; X=0
}
!macro FX_PRECOMPUTED_1BIT_DHGR .coords {
+BUILD_SPARSE_BITMASKS_DHGR copymasks, mirror_copymasks
+BUILD_HGR_LOOKUP_TABLES_X_IS_ALREADY_0 hgrlo, hgr1hi
+BUILD_HGR_MIRROR_LOOKUP_TABLES hgrlomirror, hgr1himirror
+BUILD_MIRROR_COLS mirror_cols
+COPY_SELF_TO_AUXMEM
ldx #(end-start) ; copy InputLoop code to zero page
- lda start-1, x
sta $FF, x
dex
bne -
jmp InputLoop
start
!pseudopc 0 {
Exit1Bit rts
InputLoop
ldy #0
input=*+1
ldx .coords, y ; first value: HGR row (only 0..95 will be in input array)
bmi Exit1Bit ; if > 127 then we're done
+ROW_X_TO_BASE_ADDRESSES
+ROW_X_TO_MIRROR_ADDRESSES
inc input
lda (input), y
+HIGH_3_LOW_5 input
sty <y
clc
bankloop
lda copymasks, x
beq +
sta <copymask
; main 1x2 block in top-left quadrant
src1=*+1
lda $FDFD, y
eor (<dest1), y
copymask=*+1
and #$FD ; SMC
eor (<dest1), y
dest1=*+1
sta $FDFD, y
src2=*+1
lda $FDFD, y
eor (<dest2), y
and <copymask
eor (<dest2), y
dest2=*+1
sta $FDFD, y
; corresponding 1x2 block in bottom-left quadrant (opposite row, original column)
+COPY_BIT_ZP mirror_src1, mirror_dest1, copymask
+COPY_BIT_ZP mirror_src2, mirror_dest2, copymask
+
lda mirror_copymasks, x
beq +
sta <mirror_copymask
; corresponding 1x2 block in bottom-right quadrant (opposite row, opposite column)
lda mirror_cols, y
tay
mirror_src1=*+1
lda $FDFD, y
eor (<mirror_dest1), y
mirror_copymask=*+1
and #$FD ; SMC
eor (<mirror_dest1), y
mirror_dest1=*+1
sta $FDFD, y
mirror_src2=*+1
lda $FDFD, y
eor (<mirror_dest2), y
and <mirror_copymask
eor (<mirror_dest2), y
mirror_dest2=*+1
sta $FDFD, y
; corresponding 1x2 block in top-right quadrant (same row, opposite column)
+COPY_BIT_ZP src1, dest1, mirror_copymask
+COPY_BIT_ZP src2, dest2, mirror_copymask
+
bcs +
sta $C003
sta $C005
y=*+1
ldy #$FD
sec
bcs bankloop
+ sta $C002
sta $C004
+INC_INPUT_AND_LOOP InputLoop
}
end
!if * and 1 {
!byte 0 ;align 2 but avoids the fake allocation bug if it was aligned already
}
}

View File

@ -0,0 +1,135 @@
;license:MIT
;(c) 2019-2020 by 4am
;
!source "src/fx/fx.hgr.precomputed.2bit.a"
!source "src/fx/fx.dhgr.common.a"
!macro BUILD_SPARSE_BITMASKS_2BIT_DHGR .copymasks, .mirror_copymasks {
; build sparse lookup tables for bitmasks
ldx #$00
txa
- sta .copymasks, x
sta $C005
sta .copymasks, x
sta $C004
inx
bne -
lda #%10011111
sta .copymasks+$40
sta .mirror_copymasks+$A0
lda #%11100000
sta .copymasks+$60
sta .mirror_copymasks+$80
lda #%10000111
sta .copymasks+$C0
sta .mirror_copymasks+$20
lda #%11111000
sta .copymasks+$E0
sta .mirror_copymasks
sta $C005
lda #%10001111
sta .copymasks
sta .mirror_copymasks+$E0
lda #%11110000
sta .copymasks+$20
sta .mirror_copymasks+$C0
lda #%10000011
sta .copymasks+$80
sta .mirror_copymasks+$60
lda #%11111100
sta .copymasks+$A0
sta .mirror_copymasks+$40
sta $C004
}
!macro FX_PRECOMPUTED_2BIT_DHGR .coords {
+BUILD_SPARSE_BITMASKS_2BIT_DHGR copymasks, mirror_copymasks
+BUILD_HGR_LOOKUP_TABLES_X_IS_ALREADY_0 hgrlo, hgr1hi
+BUILD_MIRROR_COLS mirror_cols
+COPY_SELF_TO_AUXMEM
ldx #(end-start) ; copy InputLoop code to zero page
- lda start-1, x
sta $FF, x
dex
bne -
jmp InputLoop
start
!pseudopc 0 {
Exit2Bit rts
InputLoop
ldy #0
input=*+1
ldx .coords, y ; first value: HGR row + 1
beq Exit2Bit ; if 0 then we're done
+ROW_X_TO_2BIT_BASE_ADDRESSES
inc <input
lda (<input), y
+HIGH_3_LOW_5 input
; main 2x2 block in left half
clc
- lda copymasks, x
beq +
src1=*+1
lda $FDFD, y
eor (<dest1), y
and copymasks, x
eor (<dest1), y
dest1=*+1
sta $FDFD, y
src2=*+1
lda $FDFD, y
eor (<dest2), y
and copymasks, x
eor (<dest2), y
dest2=*+1
sta $FDFD, y
+ bcs +
sta $C003
sta $C005
sec
bcs -
+ sta $C002
sta $C004
; corresponding 2x2 block in right half (same row, opposite column)
lda mirror_cols, y
tay
clc
- lda mirror_copymasks, x
beq +
+COPY_BIT src1, dest1, mirror_copymasks
+COPY_BIT src2, dest2, mirror_copymasks
+ bcs +
sta $C003
sta $C005
sec
bcs -
+ sta $C002
sta $C004
inc <input
+LBNE InputLoop
bit $c000
bmi +
inc <input+1
jmp InputLoop
+ rts
}
end
!if * and 1 {
!byte 0 ;align 2 but avoids the fake allocation bug if it was aligned already
}
}

101
src/fx/fx.dhgr.r.by.pixel.a Normal file
View File

@ -0,0 +1,101 @@
;license:MIT
;(c) 2018 by 4am
;
!cpu 6502
!to "build/FX/DHGR.R.BY.PIXEL",plain
*=$6000
hgrlo = $0201 ; [$C0 bytes, main memory only, offset by 1 because lookups will be based on $0200,x]
hgr1hi = $0301 ; [$C0 bytes, main memory only]
copymasks= $02C1 ; [$07 bytes, different values in main and auxmem]
!source "src/fx/macros.a"
ldx #(end-start) ; copy code to zero page
- lda start-1, x
sta $FF, x
dex
bne -
+BUILD_HGR_LOOKUP_TABLES_X_IS_ALREADY_0 hgrlo, hgr1hi
ldy #7 ; copy copymask arrays into place in main and auxmem
- lda copymasks_main-1, y
sta copymasks-1, y
lda copymasks_aux-1, y
sta $C005
sta copymasks-1, y
sta $C004
dey
bne -
jmp loop
;1GGFFEED (main) +
;1DCCBBAA (aux)
copymasks_aux ; used in reverse order
!byte %00000000
!byte %00000000
!byte %00000000
!byte %11111111
!byte %10111111
!byte %10001111
!byte %10000011
copymasks_main ; used in reverse order
!byte %11111111
!byte %10011111
!byte %10000111
!byte %10000001
!byte %00000000
!byte %00000000
!byte %00000000
start
!pseudopc 0 {
;in: Y=0 (HGR column index)
loop
lda #6 ; copymask index, 6 -> 0 inclusive
sta <maskindex
jsr WaitForVBL
maskloop
lda #$C0
sta <rowindex
rowloop
rowindex=*+1
ldx #$FD ; HGR row index, offset by 1 to simplify branch later
lda hgrlo-1, x
sta <src+1
sta <dst+1
lda hgr1hi-1, x
sta <dst+2
eor #$60
sta <src+2
maskindex=*+1
ldx #$FD ; SMC
clc
!byte $A9
- sec
lda copymasks, x ; Skip copy if we wouldn't copy anything. This speeds up the
beq + ; effect about 10% overall, even with the added instructions.
lda (<dst+1), y
src eor $FDFD, y ; SMC
and copymasks, x ; bank-specific copymasks are at the same address in main and auxmem, which is neat
eor (<dst+1), y
dst sta $FDFD, y ; SMC
+ sta $C003
sta $C005
bcc -
sta $C002
sta $C004
dec <rowindex
bne rowloop
dec <maskindex
bpl maskloop
bit $C000
bmi exit
iny
cpy #$28
bne loop
exit jmp UnwaitForVBL
}
end

141
src/fx/fx.dhgr.radial.a Normal file
View File

@ -0,0 +1,141 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.RADIAL",plain
*=$6000
mirror_src1 = $E8 ; word
mirror_dest1 = $EA ; word
mirror_src2 = $EC ; word
mirror_dest2 = $EE ; word
src1 = $F0 ; word
dest1 = $F2 ; word
src2 = $F4 ; word
dest2 = $F6 ; word
input = $FE ; word
!source "src/fx/fx.dhgr.precomputed.1bit.a"
+FX_INITONCE_1BIT CoordinatesFile, Start
lda #$80
sta Coordinates1Bit-2
Start
+BUILD_SPARSE_BITMASKS_DHGR copymasks, mirror_copymasks
+BUILD_HGR_LOOKUP_TABLES_X_IS_ALREADY_0 hgrlo, hgr1hi
+BUILD_HGR_MIRROR_LOOKUP_TABLES hgrlomirror, hgr1himirror
+BUILD_MIRROR_COLS mirror_cols
+COPY_SELF_TO_AUXMEM
+LDADDR EndCoordinates1Bit-2
+ST16 input
LoopBL ; bottom-left quadrant (opposite row, original column, reverse input order)
ldy #0
lda (input),y
bmi DoneBL
tax
+ROW_X_TO_MIRROR_ADDRESSES
iny
lda (input),y
+HIGH_3_LOW_5 input
clc
- lda copymasks, x
beq +
+COPY_BIT mirror_src1, mirror_dest1, copymasks
+COPY_BIT mirror_src2, mirror_dest2, copymasks
+ bcs +
sta $C003
sta $C005
sec
bcs -
+ sta $C002
sta $C004
+DEC_INPUT_AND_LOOP LoopBL
DoneBL
+LDADDR Coordinates1Bit
+ST16 input
LoopTL ; top-left quadrant
ldy #0
lda (input),y
bmi DoneTL
tax
+ROW_X_TO_BASE_ADDRESSES
inc input
lda (input),y
+HIGH_3_LOW_5 input
clc
- lda copymasks, x
beq +
+COPY_BIT src1, dest1, copymasks
+COPY_BIT src2, dest2, copymasks
+ bcs +
sta $C003
sta $C005
sec
bcs -
+ sta $C002
sta $C004
+INC_INPUT_AND_LOOP LoopTL
DoneTL
+LDADDR EndCoordinates1Bit-2
+ST16 input
LoopTR ; top-right quadrant (same row, opposite column, reverse input order)
ldy #0
lda (input),y
bmi DoneTR
tax
+ROW_X_TO_BASE_ADDRESSES
iny
lda (input),y
+HIGH_3_LOW_5 input
lda mirror_cols,y
tay
clc
- lda mirror_copymasks, x
beq +
+COPY_BIT src1, dest1, mirror_copymasks
+COPY_BIT src2, dest2, mirror_copymasks
+ bcs +
sta $C003
sta $C005
sec
bcs -
+ sta $C002
sta $C004
+DEC_INPUT_AND_LOOP LoopTR
DoneTR
+LDADDR Coordinates1Bit
+ST16 input
LoopBR ; bottom-right quadrant (opposite row, opposite column, original input order)
ldy #0
lda (input),y
bmi DoneBR
tax
+ROW_X_TO_MIRROR_ADDRESSES
inc input
lda (input),y
+HIGH_3_LOW_5 input
lda mirror_cols,y
tay
clc
- lda mirror_copymasks, x
beq +
+COPY_BIT mirror_src1, mirror_dest1, mirror_copymasks
+COPY_BIT mirror_src2, mirror_dest2, mirror_copymasks
+ bcs +
sta $C003
sta $C005
sec
bcs -
+ sta $C002
sta $C004
+INC_INPUT_AND_LOOP LoopBR
DoneBR
rts
CoordinatesFile
!byte 14
!text "FX/RADIAL.DATA"

View File

@ -0,0 +1,115 @@
mirror_src1 = $E8 ; word
mirror_dest1 = $EA ; word
mirror_src2 = $EC ; word
mirror_dest2 = $EE ; word
src1 = $F0 ; word
dest1 = $F2 ; word
src2 = $F4 ; word
dest2 = $F6 ; word
reverse_input = $FC ; word
input = $FE ; word
+BUILD_SPARSE_BITMASKS_DHGR copymasks, mirror_copymasks
+BUILD_HGR_LOOKUP_TABLES_X_IS_ALREADY_0 hgrlo, hgr1hi
+BUILD_HGR_MIRROR_LOOKUP_TABLES hgrlomirror, hgr1himirror
+BUILD_MIRROR_COLS mirror_cols
+COPY_SELF_TO_AUXMEM
+LDADDR Coordinates
+ST16 input
+LDADDR EndCoordinates-2
+ST16 reverse_input
jmp Loop
Exit rts
Loop ldy #0
lda (input),y
bmi Exit
tax
+ROW_X_TO_BASE_ADDRESSES
+ROW_X_TO_MIRROR_ADDRESSES
inc input
lda (input),y
+HIGH_3_LOW_5 input
; top-left quadrant (original row, original column, original input order)
clc
- lda copymasks, x
beq +
+COPY_BIT src1, dest1, copymasks
+COPY_BIT src2, dest2, copymasks
+ bcs +
sta $C003
sta $C005
sec
bcs -
+ sta $C002
sta $C004
; bottom-right quadrant (opposite row, opposite column, original input order)
lda mirror_cols,y
tay
clc
- lda mirror_copymasks, x
beq +
+COPY_BIT mirror_src1, mirror_dest1, mirror_copymasks
+COPY_BIT mirror_src2, mirror_dest2, mirror_copymasks
+ bcs +
sta $C003
sta $C005
sec
bcs -
+ sta $C002
sta $C004
ldy #0
lda (reverse_input),y
tax
+ROW_X_TO_BASE_ADDRESSES
+ROW_X_TO_MIRROR_ADDRESSES
iny
lda (reverse_input),y
+HIGH_3_LOW_5 reverse_input
; bottom-left quadrant (opposite row, original column, reverse input order)
clc
- lda copymasks, x
beq +
+COPY_BIT mirror_src1, mirror_dest1, copymasks
+COPY_BIT mirror_src2, mirror_dest2, copymasks
+ bcs +
sta $C003
sta $C005
sec
bcs -
+ sta $C002
sta $C004
; top-right quadrant (same row, opposite column, reverse input order)
lda mirror_cols,y
tay
clc
- lda mirror_copymasks, x
beq +
+COPY_BIT src1, dest1, mirror_copymasks
+COPY_BIT src2, dest2, mirror_copymasks
+ bcs +
sta $C003
sta $C005
sec
bcs -
+ sta $C002
sta $C004
inc input
bne +
inc input+1
+ lda reverse_input
php
dec reverse_input
dec reverse_input
plp
bne +
dec reverse_input+1
bit $c000
bmi ++
+ jmp Loop
++ rts

20
src/fx/fx.dhgr.radial2.a Normal file
View File

@ -0,0 +1,20 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.RADIAL2",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.1bit.a"
+FX_INITONCE_1BIT CoordinatesFile, Start
+FX_RIPPLE_1BIT aslmod
Start
!source "src/fx/fx.dhgr.radial.common.a"
CoordinatesFile
!byte 14
!text "FX/RADIAL.DATA"
Coordinates=Coordinates1Bit
EndCoordinates=EndCoordinates1Bit

132
src/fx/fx.dhgr.radial3.a Normal file
View File

@ -0,0 +1,132 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.RADIAL3",plain
*=$6000
mirror_src1 = $E8 ; word
mirror_dest1 = $EA ; word
mirror_src2 = $EC ; word
mirror_dest2 = $EE ; word
src1 = $F0 ; word
dest1 = $F2 ; word
src2 = $F4 ; word
dest2 = $F6 ; word
reverse_input = $FC ; word
input = $FE ; word
!source "src/fx/fx.dhgr.precomputed.1bit.a"
+FX_INITONCE_1BIT CoordinatesFile, Start
Start
+BUILD_SPARSE_BITMASKS_DHGR copymasks, mirror_copymasks
+BUILD_HGR_LOOKUP_TABLES_X_IS_ALREADY_0 hgrlo, hgr1hi
+BUILD_HGR_MIRROR_LOOKUP_TABLES hgrlomirror, hgr1himirror
+BUILD_MIRROR_COLS mirror_cols
+COPY_SELF_TO_AUXMEM
+LDADDR Coordinates1Bit
+ST16 input
+LDADDR EndCoordinates1Bit-2
+ST16 reverse_input
+HIDE_NEXT_BYTE
Exit rts
Loop ldy #0
lda (input),y
bmi Exit
tax
+ROW_X_TO_BASE_ADDRESSES
+ROW_X_TO_MIRROR_ADDRESSES
inc input
lda (input),y
+HIGH_3_LOW_5 input
; top-left quadrant (original row, original column, original input order)
clc
- lda copymasks, x
beq +
+COPY_BIT src1, dest1, copymasks
+COPY_BIT src2, dest2, copymasks
+ bcs +
sta $C003
sta $C005
sec
bcs -
+ sta $C002
sta $C004
; bottom-right quadrant (opposite row, opposite column, original input order)
lda mirror_cols,y
tay
clc
- lda mirror_copymasks, x
beq +
+COPY_BIT mirror_src1, mirror_dest1, mirror_copymasks
+COPY_BIT mirror_src2, mirror_dest2, mirror_copymasks
+ bcs +
sta $C003
sta $C005
sec
bcs -
+ sta $C002
sta $C004
ldy #0
lda (reverse_input),y
tax
+ROW_X_TO_BASE_ADDRESSES
+ROW_X_TO_MIRROR_ADDRESSES
iny
lda (reverse_input),y
+HIGH_3_LOW_5 reverse_input
; bottom-left quadrant (opposite row, original column, reverse input order)
clc
- lda copymasks, x
beq +
+COPY_BIT mirror_src1, mirror_dest1, copymasks
+COPY_BIT mirror_src2, mirror_dest2, copymasks
+ bcs +
sta $C003
sta $C005
sec
bcs -
+ sta $C002
sta $C004
; top-right quadrant (same row, opposite column, reverse input order)
lda mirror_cols,y
tay
clc
- lda mirror_copymasks, x
beq +
+COPY_BIT src1, dest1, mirror_copymasks
+COPY_BIT src2, dest2, mirror_copymasks
+ bcs +
sta $C003
sta $C005
sec
bcs -
+ sta $C002
sta $C004
inc input
bne +
inc input+1
+ lda reverse_input
beq +
dec reverse_input
dec reverse_input
jmp Loop
+ dec reverse_input
dec reverse_input
dec reverse_input+1
bit $c000
bmi +
jmp Loop
+ rts
CoordinatesFile
!byte 14
!text "FX/RADIAL.DATA"

20
src/fx/fx.dhgr.radial4.a Normal file
View File

@ -0,0 +1,20 @@
;license:MIT
;(c) 2019-2020 by 4am/qkumba
;
!cpu 6502
!to "build/FX/DHGR.RADIAL4",plain
*=$6000
!source "src/fx/fx.dhgr.precomputed.1bit.a"
+FX_INITONCE_1BIT CoordinatesFile, Start
jsr EndCoordinates1Bit+1
Start
!source "src/fx/fx.dhgr.radial.common.a"
CoordinatesFile
!byte 14
!text "FX/RADIAL.DATA"
Coordinates=Coordinates1Bit
EndCoordinates=EndCoordinates1Bit

Some files were not shown because too many files have changed in this diff Show More