wipes: did get one sort of working

This commit is contained in:
Vince Weaver 2024-10-31 01:10:09 -04:00
parent 33b14ac070
commit cf3edebb70
17 changed files with 8339 additions and 17 deletions

View File

@ -4,13 +4,14 @@ DOS33 = ../../../utils/dos33fs-utils/dos33
TOKENIZE = ../../../utils/asoft_basic-utils/tokenize_asoft
LINKER_SCRIPTS = ../../../linker_scripts
EMPTY_DISK = ../../../empty_disk
ZX02 = ~/research/6502_compression/zx02.git/build/zx02 -f
all: wipes.dsk
wipes.dsk: HELLO WIPE_TEST
cp $(EMPTY_DISK)/empty.dsk wipes.dsk
$(DOS33) -y wipes.dsk SAVE A HELLO
$(DOS33) -y wipes.dsk BSAVE -a 0x6000 WIPE_TEST
$(DOS33) -y wipes.dsk BSAVE -a 0x5700 WIPE_TEST
###
@ -20,19 +21,32 @@ HELLO: hello.bas
###
WIPE_TEST: wipe_test.o
ld65 -o WIPE_TEST wipe_test.o -C $(LINKER_SCRIPTS)/apple2_6000.inc
ld65 -o WIPE_TEST wipe_test.o -C $(LINKER_SCRIPTS)/apple2_5700.inc
wipe_test.o: wipe_test.s \
zp.inc hardware.inc wait_keypress.s zx02_optim.s \
code.hgr.precomputed.1bit.s \
main_macros.s \
fx.hgr.bubbles.s \
fx.hgr.precomputed.1bit.s \
fx.hgr.bubbles.data \
fx.lib.s \
macros.s
ca65 -o wipe_test.o wipe_test.s -l wipe_test.lst
###
bubbles_data.zx02: fx.hgr.bubbles.data
$(ZX02) fx.hgr.bubbles.data bubbles_data.zx02
fx.hgr.bubbles.data: fx.hgr.bubbles.data.o
ld65 -o fx.hgr.bubbles.data fx.hgr.bubbles.data.o -C $(LINKER_SCRIPTS)/apple2_8800.inc
fx.hgr.bubbles.data.o: fx.hgr.bubbles.data.s
ca65 -o fx.hgr.bubbles.data.o fx.hgr.bubbles.data.s -l fx.hgr.bubbles.data.lst
###
clean:
rm -f *~ *.o *.lst HELLO WIPE_TEST
rm -f *~ *.o *.lst *.zx02 HELLO WIPE_TEST

17
graphics/hgr/wipes/README Normal file
View File

@ -0,0 +1,17 @@
Trying to figure out how the fancy wipes from Total Replay / 4cade work
Designed so can be modular and loaded on the fly, but for our purposes
that doesn't really matter
Summary here best I can tell:
+ FXCode = current effect, loaded to $6C00
+ Coordinates1Bit = $8600 = $3480 bytes of data?
+ Coordinates2Bit = $8100 = $3C00 bytes of data
+ Coordinates3Bit = $6D00 =
; depends on $300
$200
$BB00
$BC00
$BE00

View File

@ -0,0 +1,85 @@
;!cpu 6502
;!to "build/FXCODE/HGR1",plain
;*=$6200
; !source "src/fx/macros.a"
; .include "macros.s"
HGRPrecomputed1Bit:
; jsr BuildHGRTables
; jsr BuildHGRMirrorTables
; jsr BuildHGRMirrorCols
; jsr BuildHGRSparseBitmasks1Bit
COPY_TO_0 start, end ; copies to page0????
jmp InputLoop
start:
.org $00
;!pseudopc 0 {
Exit1Bit:
rts
InputLoop:
ldy #0
input=*+1
ldx Coordinates1Bit ; 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 src1, src2, dest1, dest2
ROW_X_TO_MIRROR_ADDRESSES mirror_src1, mirror_src2, mirror_dest1, mirror_dest2
inc input
lda (<input), y
HIGH_3_LOW_5 input
; main 1x2 block in top-left quadrant
src1=*+1
lda $FDFD, y
eor (<dest1), y
and copymasks1bit, x
eor (<dest1), y
dest1=*+1
sta $FDFD, y
src2=*+1
lda $FDFD, y
eor (<dest2), y
and copymasks1bit, x
eor (<dest2), y
dest2=*+1
sta $FDFD, y
; corresponding 1x2 block in top-right quadrant (same row, opposite column)
lda mirror_cols, y
tay
COPY_BIT src1, dest1, mirror_copymasks1bit
COPY_BIT src2, dest2, mirror_copymasks1bit
; corresponding 1x2 block in bottom-right quadrant (opposite row, opposite column)
mirror_src1=*+1
lda $FDFD, y
eor (<mirror_dest1), y
and mirror_copymasks1bit, x
eor (<mirror_dest1), y
mirror_dest1=*+1
sta $FDFD, y
mirror_src2=*+1
lda $FDFD, y
eor (<mirror_dest2), y
and mirror_copymasks1bit, x
eor (<mirror_dest2), y
mirror_dest2=*+1
sta $FDFD, y
; corresponding 1x2 block in bottom-left quadrant (opposite row, original column)
lda mirror_cols, y
tay
COPY_BIT mirror_src1, mirror_dest1, copymasks1bit
COPY_BIT mirror_src2, mirror_dest2, copymasks1bit
INC_INPUT_AND_LOOP input, InputLoop
;}
.reloc
end:

View File

@ -0,0 +1,401 @@
;license:MIT
;(c) 2018-2023 by 4am
;
;------------------------------------------------------------------------------
; YE OLDE GRAND UNIFIED MEMORY MAP
;
; LC RAM BANK 1
; D000 - reserved
; D001..D06E - gGlobalPrefsStore
; ...unused...
; D100..D4FF - HGR font data
; ...unused...
; E6C9..FFEB - main program code
; FFEC..FFF9 - API functions and global constants available for main program
; code, prelaunchers, transition effects, &c.
; (LoadFileDirect, Wait/UnwaitForVBL, MockingboardStuff, MachineStatus)
; FFFA..FFFF - NMI, reset, IRQ vectors
;
; LC RAM BANK 2
; D000..D5FF - ProRWTS data
; D600..D8BD - ProRWTS code
; D8BE..DCB7 - ProRWTS glue code
; DCB8..DCBD - backup of stack (during gameplay and self-running demos)
; DCBE..DCC2 - okvs cache (attract state saved across self-running demo)
; ...unused...
; DFB4..DFFF - (de)acceleration function
;
; MAIN MEMORY DURING SEARCH/BROWSE MODE
; 6000..9FFF - search index (499 games = $3C3C/$4000)
; A000..BCFF - search cache (499 games = $1837/$1D00)
; BD00..BEFF - prefs buffer (used to write PREFS.CONF if cheat mode changes)
; BF00..BFFF - ProRWTS glue (supports LoadIndexedFile)
;
; MAIN MEMORY DURING MEGA-ATTRACT MODE
; 0100..0105 - re-entry code for demos (reloaded before demo)
; 0106..01BF - prelaunch code (reloaded before demo)
; 0400..07FF - text screen (cleared before each module)
; 0800..1EFF - slideshow configuration file (persistent during slideshow module)
; 2000..5FFF - hi-res screens (cleared before each module)
; 4000..5FFF - slideshow index file (loaded before slideshow module)
; 6000.. - mega-attract configuration file (reloaded before each module)
; BD00..BEFF - prefs buffer (clobbered if cheat mode changes)
; BF00..BFFF - ProRWTS glue (reset after demo)
;
; MAIN MEMORY DURING MINI-ATTRACT MODE
; 0100..0105 - re-entry code for demos (reloaded before demo)
; 0106..01BF - prelaunch code (reloaded before demo)
; 0400..07FF - text screen (cleared before each module)
; 0800..1FFF - mini-attract index file (loaded once)
; 2000..5FFF - hi-res screens
; 6000.. - mini-attract configuration file (reloaded before each module)
; 6000.. - transition effect code (reloaded before each screenshot module)
; BF00..BFFF - ProRWTS glue (reset after demo)
;
; MAIN MEMORY DURING GAME LAUNCH
; 0100..0105 - re-entry code
; 0106..01BF - prelaunch code
; 0400..07FF - text screen cleared
; 2000..5FFF - hi-res screens cleared
; A000.. - prelaunch index file
;
; MAIN MEMORY DURING CREDITS (preserves search index and cache)
; 0800.. - credits text
;
; MAIN MEMORY DURING GLOBAL HELP (preserves search index and cache)
; 0800.. - help text
;
; MAIN MEMORY DURING PER-GAME HELP (clobbers search cache)
; 0800.. - help text
; A000.. - game help index file
;
;------------------------------------------------------------------------------
;!ifndef _CONSTANTS_ {
.ifndef _CONSTANTS_
; soft switches
KBD = $C000 ; last key pressed (if any)
CLEARKBD = $C010 ; clear last key pressed
STOREOFF = $C000 ; STA then use the following flags:
READMAINMEM = $C002 ; STA to read from main mem ($0200..$BFFF)
READAUXMEM = $C003 ; STA to read from aux mem ($0200..$BFFF)
WRITEMAINMEM = $C004 ; STA to write to main mem ($0200..$BFFF)
WRITEAUXMEM = $C005 ; STA to write to aux mem ($0200..$BFFF)
SETSTDZP = $C008 ; STA to r/w from main mem stack and zero page ($0000..$01FF)
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 ; STA to use 40 columns (also used to get out of DHGR mode)
SET80VID = $C00D ; STA to use 80 columns (also used to get into DHGR mode)
PRIMARYCHARSET= $C00E ; STA to use no-mousetext character set
SLOT3STATUS = $C017 ; bit 7 only
MONOCOLOR = $C021 ; IIgs bit 7 switches composite mono/color modes
;TBCOLOR = $C022 ; IIgs text foreground and background colors (also VidHD but write-only)
;NEWVIDEO = $C029 ; IIgs graphics modes (also VidHD)
;SPEAKER = $C030 ; chirp chirp
;CLOCKCTL = $C034 ; bits 0-3 are IIgs border color (also VidHD but write-only)
SHADOW = $C035 ; IIgs auxmem-to-bank-E1 shadowing (also VidHD but write-only)
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_MACHINE2C =$FBC0
ROM_HOME = $FC58
ROM_WAIT = $FCA8
ROM_CROUT= $FD8E
ROM_COUT = $FDED
ROM_NORMAL = $FE84 ; NORMAL text (instead of INVERSE or FLASH)
ROM_IN0 = $FE89 ; SETKBD
ROM_PR0 = $FE93 ; SETVID
; zero page addresses 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 addresses
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
PrelaunchInit= $EA
; 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
; main memory addresses
gKeyLen = $1F00 ; used by ParseKeyValueList
gKey = $1F01 ; ""
gValLen = $1F80 ; ""
gVal = $1F81 ; ""
UILine1 = $1FB0 ; used by DrawUI
UILine2 = $1FD8 ; ""
UI_ToPlay = $1FF7 ; ""
ProBootEntry = $2028 ; used by ProBoot
gSearchIndex = $6000
gSearchCache = $A000
gPathname = $BFD0 ; used by SetPath/AddToPath
; main memory addresses used by graphic effects
hgrlo = $0201 ; $C0 bytes
mirror_cols = $02C1 ; $28 bytes
hgrhi = $0301 ; $C0 bytes
hgr1hi = hgrhi
;FXCode = $6200
;Coordinates1Bit= $8600 ; $3481 bytes ($3480 on disk + 1 byte EOF marker added at runtime)
;EndCoordinates1Bit = Coordinates1Bit + $3480
;Coordinates2Bit= $8100 ; $3C01 bytes ($3C00 on disk + 1 byte EOF marker added at runtime)
;EndCoordinates2Bit = Coordinates2Bit + $3C00
;Coordinates3Bit= $6D00 ; $5001 bytes ($5000 on disk + 1 byte EOF marker added at runtime)
;EndCoordinates3Bit = Coordinates3Bit + $5000
hgrlomirror = $BB01 ; $C0 bytes
hgr1himirror = $BC01 ; $C0 bytes
dithermasks = $BDA8 ; $58 bytes, must not cross page boundary
evenrow_masks = dithermasks
oddrow_masks = dithermasks+2
no_masks = dithermasks+44
copymasks1bit = $BE00 ; $100 bytes but sparse, index is 0..6 but in high 3 bits, so $00,$20,$40,$60,$80,$A0,$C0
copymasks2bit = copymasks1bit ; $100 bytes but sparse, index is 0..4 but in high 3 bits, so $00,$20,$40,$60,$80
copymasks3bit = copymasks1bit ; $100 bytes but sparse, index is 0..7 but in high 3 bits, so $00,$20,$40,$60,$80,$A0,$C0,$E0
mirror_copymasks1bit = copymasks1bit+1
mirror_copymasks2bit = copymasks2bit+1
hgrlo3a = $6A00 ; $80 bytes
hgrlo3b = $6A80 ; $80 bytes
hgrlo3c = $6B00 ; $80 bytes
hgrhi3a = $6B80 ; $80 bytes
dither1_lo = $6880 ; $80 bytes
dither2_lo = $6900 ; $80 bytes
dither3_lo = $6980 ; $80 bytes
hgrhi3b = $6C00 ; $80 bytes
hgrhi3c = $BD01 ; $80 bytes
extra_cols = $BEF8 ; $08 bytes
; hgr.48boxes constants
HGR48StageDrawingRoutines = $7F00 ; $100 bytes
; 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 = $80
clear01 = $81
clear02 = $82
clear03 = $83
clear04 = $84
clear05 = $85
clear06 = $86
clear07 = $87
clear08 = $88
clear09 = $89
clear0A = $8A
clear0B = $8B
clear0C = $8C
clear0D = $8D
clear0E = $8E
clear0F = $8F
copy02 = $90
copy03 = $91
copy04 = $92
copy05 = $93
copy06 = $94
copy07 = $95
copy08 = $96
copy09 = $97
copy0A = $98
copy0B = $99
copy0C = $9A
copy0D = $9B
copy0E = $9C
copy0F = $9D
copy00 = $9E
copy01 = $9F
; dhgr.48boxes constants
DHGR48BoxStages = $10 ; $30 bytes, current stage for each box
DHGR48StageDrawingRoutines = $6F00 ; $100 bytes
; 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)
dhgr_clear00 = $70
dhgr_clear01 = $71
dhgr_clear02 = $72
dhgr_clear03 = $73
dhgr_clear04 = $74
dhgr_clear05 = $75
dhgr_clear06 = $76
dhgr_clear07 = $77
dhgr_clear08 = $78
dhgr_clear09 = $79
dhgr_clear0A = $7A
dhgr_clear0B = $7B
dhgr_clear0C = $7C
dhgr_clear0D = $7D
dhgr_clear0E = $7E
dhgr_clear0F = $7F
dhgr_copy02 = $80
dhgr_copy03 = $81
dhgr_copy04 = $82
dhgr_copy05 = $83
dhgr_copy06 = $84
dhgr_copy07 = $85
dhgr_copy08 = $86
dhgr_copy09 = $87
dhgr_copy0A = $88
dhgr_copy0B = $89
dhgr_copy0C = $8A
dhgr_copy0D = $8B
dhgr_copy0E = $8C
dhgr_copy0F = $8D
dhgr_copy00 = $8E
dhgr_copy01 = $8F
; LC RAM 1 & 2 addresses
; these are defined here because they are also called by other targets
; that are assembled separately, e.g. prelaunchers, demo launchers, and graphic effects
UnwaitForVBL = $FFEE
WaitForVBL = UnwaitForVBL-3
iLoadFileDirect = WaitForVBL-3 ; note: you really want LC RAM 2 banked in before calling this
iAddToPath = iLoadFileDirect-3
iLoadXSingle = iAddToPath-3
iLoadFXCODE = iLoadXSingle-3
iLoadFXDATA = iLoadFXCODE-3
;iBuildHGRTables = iLoadFXDATA-3
;iBuildHGRMirrorTables = iBuildHGRTables-3
;iBuildHGRMirrorCols = iBuildHGRMirrorTables-3
;iBuildDHGRMirrorCols = iBuildHGRMirrorCols-3
;iBuildHGRDitherMasks = iBuildDHGRMirrorCols-3
;iBuildDHGRDitherMasks = iBuildHGRDitherMasks-3
;iWaitForKeyWithTimeout = iBuildDHGRDitherMasks-3
;iReverseCoordinates1Bit = iWaitForKeyWithTimeout-3
;iRippleCoordinates1Bit = iReverseCoordinates1Bit-3
;iRippleCoordinates1Bit2 = iRippleCoordinates1Bit-3
;iRippleCoordinates1Bit3 = iRippleCoordinates1Bit2-3
;iRippleCoordinates1Bit4 = iRippleCoordinates1Bit3-3
;iBuildHGRSparseBitmasks1Bit = iRippleCoordinates1Bit4-3
;iBuildDHGRSparseBitmasks1Bit = iBuildHGRSparseBitmasks1Bit-3
;iBuildHGRSparseBitmasks2Bit = iBuildDHGRSparseBitmasks1Bit-3
;iBuildDHGRSparseBitmasks2Bit = iBuildHGRSparseBitmasks2Bit-3
;iReverseCoordinates2Bit = iBuildDHGRSparseBitmasks2Bit-3
;iRippleCoordinates2Bit = iReverseCoordinates2Bit-3
;iReverseCoordinates3Bit = iRippleCoordinates2Bit-3
;iRippleCoordinates3Bit = iReverseCoordinates3Bit-3
;iSetupPrecomputed3Bit = iRippleCoordinates3Bit-3
;iPrelaunchInit = iSetupPrecomputed3Bit-3
MockingboardStuff = $FFF8 ; bit 7 = 1 if SC-01 speech chip present (Speech I)
; bit 6 = 1 if SSI-263 speech chip present (Mockingboard "B"-"D")
; bit 5 = 1 if two AY-3-8910s present (Sound II / Mockingboard "A"-"D")
; bit 5 = 0 if only AY-3-8910 present (Sound I)
; bit 4 unused
; bits 0-3: slot number
MachineStatus = $FFF9
; LC RAM 2 addresses
DisableAccelerator = $DFB4
EnableAccelerator = DisableAccelerator+3
; application constants
gStackSize = 6 ; seems like only six are needed
PRELAUNCH_STANDARD_SIZE = 61 ; LoadStandardPrelaunch, eventually to be determined at build-time
; AND masks for MockingboardStuff
MOCKINGBOARD_SLOT = %00001111
HAS_STEREO = %00100000
HAS_SPEECH = %11000000
; AND masks for game info bitfield (after game display name in gSearchStore)
HAS_DHGR_TITLE = %10000000 ; this one is hard-coded via BMI instead of AND/BNE
IS_SINGLE_LOAD = %01000000
CHEAT_CATEGORY = %00001111
; ^^
; ++-- your bits here!
; 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
; AND masks for gMegaAttractModeFilter
ATTRACT_DEMO = %00000001
ATTRACT_HGR_TITLE = %00000010
ATTRACT_HGR_ACTION = %00000100
ATTRACT_DHGR_TITLE = %00001000
ATTRACT_DHGR_ACTION = %00010000
ATTRACT_SHR = %00100000
ATTRACT_GR = %01000000
ATTRACT_DGR = %10000000
; shared symbols for prelaunch and effects to call ProRWTS2 functions
iCurBlockLo = $D601 ; constant
iCurBlockHi = $D603 ; constant
launchpatch = $D85C ; glue.launch.a
itraverse = $DB4B ; Roger Rabbit, avoid, use Infiltrator 2 style instead
; also Columns (via file in disk image)
ldrlo = $55 ; constant
ldrhi = $56 ; constant
;namlo = $57 ; constant
;namhi = $58 ; constant
ldrlo2 = $64 ; constant
ldrhi2 = $65 ; constant
; Columns and Dangerous Dave also call (de)accelerator functions directly
_CONSTANTS_=*
;}
.endif

File diff suppressed because it is too large Load Diff

View File

@ -9,11 +9,33 @@
.include "fx.hgr.precomputed.1bit.s"
FX_INITONCE_1BIT FXCodeFile, CoordinatesFile, Start
; FX_INITONCE_1BIT FXCodeFile, CoordinatesFile, Start
InitOnce:
bit Start ; essentially a nop?
lda #$4C ; JMP?
sta InitOnce ; convert to a jump to start after first time
; LDADDR FXCodeFile ; load fx effect to $6200
; ldx #>FXCode
; jsr iLoadFXCODE
; LDADDR CoordinatesFile ; load co-ordinates file
; ldx #>Coordinates1Bit
; jsr iLoadFXDATA
sec
ror EndCoordinates1Bit ; ??
Start:
; jmp FXCode
FXCodeFile:
PSTRING "HGR1"
CoordinatesFile:
PSTRING "BUBBLES.DATA"
.include "code.hgr.precomputed.1bit.s"
;FXCodeFile:
; PSTRING "HGR1"
;CoordinatesFile:
; PSTRING "BUBBLES.DATA"

826
graphics/hgr/wipes/fx.lib.s Normal file
View File

@ -0,0 +1,826 @@
;license:MIT
;(c) 2024 by 4am
;
; common routines used by graphic effects
;
; Note: launcher code can call these routines directly. However,
; graphic effects are assembled as separate targets and must call
; these routines indirectly via the vectors defined in constants.a,
; e.g. iBuildHGRTables instead of BuildHGRTables.
;
; Public functions:
; - WaitForKeyWithTimeout
; - BuildHGRTables
; - BuildHGRMirrorTables
; - BuildHGRMirrorCols
; - BuildDHGRMirrorCols
; - BuildHGRDitherMasks
; - BuildDHGRDitherMasks
; - BuildHGRSparseBitmasks1Bit
; - BuildDHGRSparseBitmasks1Bit
; - ReverseCoordinates1Bit
; - RippleCoordinates1Bit
; - RippleCoordinates1Bit2
; - RippleCoordinates1Bit3
; - RippleCoordinates1Bit4
; - BuildHGRSparseBitmasks2Bit
; - BuildDHGRSparseBitmasks2Bit
; - ReverseCoordinates2Bit
; - RippleCoordinates2Bit
; - SetupPrecomputed3Bit
; - ReverseCoordinates3Bit
; - RippleCoordinates3Bit
; !source "src/fx/macros.a"
WaitForKeyWithTimeout:
; in: A = timeout length (like standard $FCA8 wait routine)
; out: A clobbered (not always 0 if key is pressed, but also not the key pressed)
; X/Y preserved
sec
@wait1: pha
@wait2: sbc #1
bne @wait2
pla
bit KBD
bmi @exit
sbc #1
bne @wait1
@exit: rts
; based on routine by John Brooks
; posted on comp.sys.apple2 on 2018-07-11
; https://groups.google.com/d/msg/comp.sys.apple2/v2HOfHOmeNQ/zD76fJg_BAAJ
BuildHGRTables:
; out: populates tables at $0201 (hgrlo) and $0301 (hgrhi)
; A clobbered
; X=$C0 (important! some callers rely on this)
; Z=1
; Y preserved
ldx #0
bht_m1: txa
and #$F8
bpl bht_p1
ora #5
bht_p1: asl
bpl bht_p2
ora #5
bht_p2: asl
asl
sta hgrlo, x
txa
and #7
rol
asl hgrlo, x
rol
ora #$20
sta hgrhi, x
inx
cpx #$C0
bne bht_m1
rts
BuildHGRMirrorTables:
ldx #$C0
ldy #0
bhm1_m1: tya
and #$F8
bpl bhm1_p1
ora #5
bhm1_p1: asl
bpl bhm1_p2
ora #5
bhm1_p2: asl
asl
sta hgrlomirror-1, x
tya
and #7
rol
asl hgrlomirror-1, x
rol
ora #$20
sta hgr1himirror-1, x
iny
dex
bne bhm1_m1
rts
BuildHGRMirrorCols:
; in: none
; out: mirror_cols populated with lookup table to get $27-y for y in $00..$27
; all registers and flags clobbered
ldx #$27
ldy #$00
bhmc_m1: tya
sta mirror_cols, x
iny
dex
bpl bhmc_m1
rts
.if 0
BuildDHGRMirrorCols:
; out: mirror_cols populated with lookup table to get $27-y for y in $00..$27
; duplicated in both mainmem and auxmem
; X=0
; Z=1
ldx #$28
ldy #$00
- tya
sta mirror_cols-1, x
sta $C005
sta mirror_cols-1, x
sta $C004
iny
dex
bne -
rts
BuildHGRDitherMasks:
ldy #40
- lda #%10110011
sta dithermasks, y
lda #%11100110
sta dithermasks+1, y
lda #%11001100
sta dithermasks+2, y
lda #%10011001
sta dithermasks+3, y
dey
dey
dey
dey
bpl -
ldy #43
lda #$FF
- sta no_masks, y
dey
bpl -
rts
BuildDHGRDitherMasks:
ldy #40
- lda #%10011110
sta dithermasks, y
lda #%11111000
sta dithermasks+1, y
lda #%11100001
sta dithermasks+2, y
lda #%10000111
sta dithermasks+3, y
dey
dey
dey
dey
bpl -
ldy #43
- lda #$FF
sta no_masks, y
dey
bpl -
sta $C005
ldy #40
- lda #%10001111
sta dithermasks, y
lda #%10111100
sta dithermasks+1, y
lda #%11110000
sta dithermasks+2, y
lda #%11000011
sta dithermasks+3, y
dey
dey
dey
dey
bpl -
ldy #43
- lda #$FF
sta no_masks, y
dey
bpl -
sta $C004
rts
.endif
BuildHGRSparseBitmasks1Bit:
lda #%10000001
sta copymasks1bit
sta mirror_copymasks1bit+$C0
lda #%10000010
sta copymasks1bit+$20
sta mirror_copymasks1bit+$A0
lda #%10000100
sta copymasks1bit+$40
sta mirror_copymasks1bit+$80
lda #%10001000
sta copymasks1bit+$60
sta mirror_copymasks1bit+$60
lda #%10010000
sta copymasks1bit+$80
sta mirror_copymasks1bit+$40
lda #%10100000
sta copymasks1bit+$A0
sta mirror_copymasks1bit+$20
lda #%11000000
sta copymasks1bit+$C0
sta mirror_copymasks1bit
rts
.if 0
BuildDHGRSparseBitmasks1Bit:
; out: X=0
ldx #$00
txa
- sta copymasks1bit, x
sta $C005
sta copymasks1bit, x
sta $C004
inx
bne -
; X=0
lda #%00000111
sta copymasks1bit+$80
sta mirror_copymasks1bit+$40
lda #%00011000
sta copymasks1bit+$A0
sta mirror_copymasks1bit+$20
lda #%01100000
sta copymasks1bit+$C0
sta mirror_copymasks1bit
sta $C005
lda #%10000011
sta copymasks1bit
sta mirror_copymasks1bit+$C0
lda #%10001100
sta copymasks1bit+$20
sta mirror_copymasks1bit+$A0
lda #%10110000
sta copymasks1bit+$40
sta mirror_copymasks1bit+$80
lda #%11000000
sta copymasks1bit+$60
sta mirror_copymasks1bit+$60
sta $C004
rts
ReverseCoordinates1Bit:
ldy #0 ; <Coordinates1Bit
sty $f0
lda #>Coordinates1Bit
sta $f1
lda #<(EndCoordinates1Bit - 2)
sta $f2
lda #>(EndCoordinates1Bit - 2)
sta $f3
clc
!byte $24
- sec
-- lda ($f0), y
pha
lda ($f2), y
sta ($f0), y
pla
sta ($f2), y
iny
bcc -
ldy #0
!byte $24
- clc
inc $f0
bne +
inc $f1
+ lda $f1
eor #>(Coordinates1Bit + $1A40)
bne +
lda $f0
eor #<(Coordinates1Bit + $1A40)
beq ++
+ lda $f2
bne +
dec $f3
+ dec $f2
bcs -
bcc -- ; always
++ rts
BuildHGRSparseBitmasks2Bit:
lda #%10000011
sta copymasks2bit
sta mirror_copymasks2bit+$E0
lda #%10001100
sta copymasks2bit+$20
sta mirror_copymasks2bit+$C0
lda #%10110000
sta copymasks2bit+$40
sta mirror_copymasks2bit+$A0
lda #%11000000
sta copymasks2bit+$60
sta mirror_copymasks2bit+$80
lda #%10000001
sta copymasks2bit+$80
sta mirror_copymasks2bit+$60
lda #%10000110
sta copymasks2bit+$A0
sta mirror_copymasks2bit+$40
lda #%10011000
sta copymasks2bit+$C0
sta mirror_copymasks2bit+$20
lda #%11100000
sta copymasks2bit+$E0
sta mirror_copymasks2bit
rts
BuildDHGRSparseBitmasks2Bit:
ldx #$00
txa
- sta copymasks2bit, x
sta $C005
sta copymasks2bit, x
sta $C004
inx
bne -
lda #%10011111
sta copymasks2bit+$40
sta mirror_copymasks2bit+$A0
lda #%11100000
sta copymasks2bit+$60
sta mirror_copymasks2bit+$80
lda #%10000111
sta copymasks2bit+$C0
sta mirror_copymasks2bit+$20
lda #%11111000
sta copymasks2bit+$E0
sta mirror_copymasks2bit
sta $C005
lda #%10001111
sta copymasks2bit
sta mirror_copymasks2bit+$E0
lda #%11110000
sta copymasks2bit+$20
sta mirror_copymasks2bit+$C0
lda #%10000011
sta copymasks2bit+$80
sta mirror_copymasks2bit+$60
lda #%11111100
sta copymasks2bit+$A0
sta mirror_copymasks2bit+$40
sta $C004
rts
ReverseCoordinates2Bit:
ldy #0 ; <Coordinates2Bit
sty $f0
lda #>Coordinates2Bit
sta $f1
lda #<(EndCoordinates2Bit - 2)
sta $f2
lda #>(EndCoordinates2Bit - 2)
sta $f3
ldx #$1E ; #$3C/2
clc
!byte $24
- sec
-- lda ($f0), y
pha
lda ($f2), y
sta ($f0), y
pla
sta ($f2), y
iny
bcc -
ldy #0
!byte $24
- clc
inc $f0
bne +
inc $f1
dex
beq ++
+ lda $f2
bne +
dec $f3
+ dec $f2
bcs -
bcc -- ; always branches
++ rts
RippleCoordinates2Bit:
ldy #0
ldx #$33
- lda @ptrtbl, x
sta $c0, x
dex
bpl -
lda #$9b
sta $fe
iny
sty $ff
ldx #6
- lda Coordinates2Bit + 1, x
sta $7f, x
lda Coordinates2Bit + 9, x
sta $85, x
lda Coordinates2Bit + 17, x
sta $8b, x
lda Coordinates2Bit + 65, x
sta $9b, x
dex
bne -
lda Coordinates2Bit + 28
sta $92
lda Coordinates2Bit + 29
sta $93
ldx #4
- lda Coordinates2Bit + 33, x
sta $93, x
lda Coordinates2Bit + 41, x
sta $97, x
lda Coordinates2Bit + 83, x
sta $a1, x
dex
bne -
ldx #2
- lda Coordinates2Bit + 125, x
sta $a5, x
lda Coordinates2Bit + 131, x
sta $a7, x
lda Coordinates2Bit + 139, x
sta $a9, x
lda Coordinates2Bit + 169, x
sta $ab, x
lda Coordinates2Bit + 237, x
sta $ad, x
lda Coordinates2Bit + 2193, x
sta $af, x
lda Coordinates2Bit + 6581, x
sta $b1, x
dex
bne -
--- ldx #$34
-- lda $be, x
tay
ora $bf, x
beq +
lda $bf, x
jsr @aslmod
sty $be, x
sta $bf, x
sty $fc
clc
adc #>Coordinates2Bit
sta $fd
ldy #0
!byte $24
- sec
lda ($fc), y
pha
lda $7e, x
sta ($fc), y
pla
sta $7e, x
inx
iny
bcc -
dex
dex
+ dex
dex
bne --
ldy #1
lda $fe
eor #<(411 - 2)
beq +
ldy #9
eor #<(411 - 2) xor <(411 - 136)
bne ++
+
- ldx @zerotbl, y
sta $0, x
sta $1, x
dey
bpl -
++ dec $fe
bne ---
dec $ff
bpl ---
bmi @exit ; always branches
@aslmod jsr +
+ cmp #$1E
bcc +
iny
+ pha
tya
asl
tay
pla
rol
cmp #$3C
bcc @exit
sbc #$3C
@exit rts
@ptrtbl !word 2, 4, 6, 10, 12, 14, 18, 20
!word 22, 28, 34, 36, 42, 44, 66, 68
!word 70, 84, 86, 126, 132, 140, 170, 238
!word 2194, 6582
@zerotbl !byte $f0, $f2, $ca, $d2, $d8, $e0, $e2, $e6, $ea, $ee
SetupPrecomputed3Bit:
; build regular HGR lookup tables, then split them
jsr BuildHGRTables
ldx #$BF
ldy #$3F
- lda hgrlo, x
sta hgrlo3c, y
sta hgrlo3c+$40, y
lda hgrhi, x
sta hgrhi3c, y
sta hgrhi3c+$40, y
dex
lda hgrlo, x
sta hgrlo3b, y
sta hgrlo3b+$40, y
lda hgrhi, x
sta hgrhi3b, y
sta hgrhi3b+$40, y
dex
lda hgrlo, x
sta hgrlo3a, y
sta hgrlo3a+$40, y
lda hgrhi, x
sta hgrhi3a, y
sta hgrhi3a+$40, y
dex
dey
bpl -
; build lookup table to get $20+y for y in $00..$07
ldx #$07
ldy #$27
- tya
sta extra_cols-$20, y
dey
dex
bpl -
; build sparse lookup tables for bitmasks
lda #%10000011
sta copymasks3bit
lda #%10001100
sta copymasks3bit+$20
lda #%10110000
sta copymasks3bit+$40
lda #%11000000
sta copymasks3bit+$60
lda #%10000001
sta copymasks3bit+$80
lda #%10000110
sta copymasks3bit+$A0
lda #%10011000
sta copymasks3bit+$C0
lda #%11100000
sta copymasks3bit+$E0
rts
ReverseCoordinates3Bit:
ldy #0 ; <Coordinates3Bit
sty $f0
lda #>Coordinates3Bit
sta $f1
lda #<(EndCoordinates3Bit - 2)
sta $f2
lda #>(EndCoordinates3Bit - 2)
sta $f3
ldx #$28 ; #$50/2
clc
!byte $24
- sec
-- lda ($f0), y
pha
lda ($f2), y
sta ($f0), y
pla
sta ($f2), y
iny
bcc -
ldy #0
!byte $24
- clc
inc $f0
bne +
inc $f1
dex
beq ++
+ lda $f2
bne +
dec $f3
+ dec $f2
bcs -
bcc -- ; always branches
++ rts
RippleCoordinates3Bit:
ldx #$1B
- lda @ripplezp, x
sta $e0, x
dex
bpl -
--- ldx #$0c
-- ldy $ee, x
lda $ef, x
jsr @aslmod
sty $ee, x
sta $ef, x
sty $ec
clc
adc #>Coordinates3Bit
sta $ed
ldy #0
!byte $24
- sec
lda ($ec), y
pha
lda $de, x
sta ($ec), y
pla
sta $de, x
inx
iny
bcc -
dex
dex
dex
dex
bne --
dec $ee
bne ---
dec $ef
bpl ---
bmi @exit ; always branches
@aslmod jsr +
+ cmp #$28
bcc +
iny
+ pha
tya
asl
tay
pla
rol
cmp #$50
bcc @exit
sbc #$50
@exit rts
@ripplezp
!byte $1F,$F3,$20,$F3,$20,$14,$20,$D3
!byte $1E,$F3,$1F,$54,$00,$00,$AA,$06
!byte $02,$00,$04,$00,$06,$00,$0C,$00
!byte $16,$00,$1A,$00
!zone {
RippleCoordinates1Bit4:
lda #<aslmod4
+HIDE_NEXT_2_BYTES
RippleCoordinates1Bit3
lda #<aslmod3
+HIDE_NEXT_2_BYTES
RippleCoordinates1Bit2
lda #<aslmod2
+HIDE_NEXT_2_BYTES
RippleCoordinates1Bit
lda #<aslmod
sta @jsr+1
lda #2 ; <(Coordinates1Bit + 2)
sta $f0
ldy #0
sty $f1
lda #$16 ; <(Coordinates1Bit + 22)
sta $f2
sty $f3
lda #$1f
sta $ee
lda #$0d
sta $ef
lda Coordinates1Bit + 2
sta $e0
lda Coordinates1Bit + 3
sta $e1
lda Coordinates1Bit + 22
sta $e2
lda Coordinates1Bit + 23
sta $e3
--- ldx #4
-- ldy $ee, x
lda $ef, x
@jsr jsr aslmod ; SMC on entry
sty $ee, x
sta $ef, x
sty $ec
clc
adc #>Coordinates1Bit
sta $ed
ldy #0
!byte $24
- sec
lda ($ec), y
pha
lda $de, x
sta ($ec), y
pla
sta $de, x
inx
iny
bcc -
dex
dex
dex
dex
bne --
dec $ee
bne ---
dec $ef
bpl ---
bmi exit ; always branches
aslmod4 jsr aslmod
aslmod3 jsr aslmod
aslmod2 jsr aslmod
aslmod cmp #$1A
!if (>aslmod != >aslmod4) {
!serious "aslmod entry points are not on the same page"
}
bcc +
bne ++
cpy #$40
bcc +
++ iny
+ pha
tya
asl
tay
pla
rol
cmp #$34
bcc exit
bne ++
cpy #$80
bcc exit
++ pha
tya
sbc #$80
tay
pla
sbc #$34
exit rts
}
.endif

View File

@ -1,4 +1,5 @@
5 HOME
10 PRINT "TESTING 4AM WIPE CODE FROM 4CADE"
40 PRINT CHR$(4)"MAXFILES 1"
60 PRINT:PRINT CHR$(4)"CATALOG"

View File

@ -0,0 +1,62 @@
;license:MIT
;(c) 2019-2022 by 4am
;
;!ifndef _FX_MACROS_COPYBIT_ {
.ifndef _FX_MACROS_COPYBIT_
;!macro COPY_BIT .src1, .dest1, .copymasks {
.macro COPY_BIT src1, dest1, copymasks
lda (src1),y
eor (dest1),y ; merge source and destination bits
and copymasks,x ; isolate the bits to replace, zero the rest
eor (dest1),y ; unmerge source and destination bits, leaves 'to keep' destination bits intact
sta (dest1),y ; write the result
;}
.endmacro
;!macro COPY_BIT_DITHER .src1, .dest1, .copymasks, .dithermaskptr {
.macro COPY_BIT_DITHER src1, dest1, copymasks, dithermaskptr
lda (src1),y
eor (dest1),y ; merge source and destination bits
and copymasks,x ; isolate the bits to replace, zero the rest
and (dithermaskptr),y ; apply dither mask (if any)
eor (dest1),y ; unmerge source and destination bits, leaves 'to keep' destination bits intact
sta (dest1),y ; write the result
;}
.endmacro
;!macro COPY_BIT_ZP .src1, .dest1, .zpcopymask {
.macro COPY_BIT_ZP src1, dest1, zpcopymask
lda (src1),y
eor (dest1),y ; merge source and destination bits
and <zpcopymask ; isolate the bits to replace, zero the rest
eor (dest1),y ; unmerge source and destination bits, leaves 'to keep' destination bits intact
sta (dest1),y ; write the result
;}
.endmacro
;!macro COPY_BIT_ZP_DITHER .src1, .dest1, .zpcopymask, .ditherptr {
.macro COPY_BIT_ZP_DITHER src1, dest1, zpcopymask, ditherptr
lda (src1),y
eor (dest1),y ; merge source and destination bits
and <zpcopymask ; isolate the bits to replace, zero the rest
and (ditherptr), y ; apply dither mask (if any)
eor (dest1),y ; unmerge source and destination bits, leaves 'to keep' destination bits intact
sta (dest1),y ; write the result
;}
.endmacro
;!macro COPY_BIT_IMMEDIATE .copymask {
.macro COPY_BIT_IMMEDIATE copymask
lda (src), y
eor (dst), y ; merge source and destination bits
and #copymask ; isolate the bits to replace, zero the rest
eor (dst), y ; unmerge source and destination bits, leaves 'to keep' destination bits intact
sta (dst), y ; write the result
;}
.endmacro
_FX_MACROS_COPYBIT_=*
;}
.endif

View File

@ -80,7 +80,7 @@
.endmacro
;!macro ROW_X_TO_BASE_ADDRESSES .src1, .src2, .dest1, .dest2 {
.macro ROW_X_TO_BAS_ADDRESSES src1, src2, dest1, dest2
.macro ROW_X_TO_BASE_ADDRESSES src1, src2, dest1, dest2
lda hgrlo, x
sta <dest1
sta <src1

View File

@ -0,0 +1,99 @@
;license:MIT
;(c) 2019-2022 by 4am
;
;!ifndef _FX_MACROS_MISC_ {
.ifndef _FX_MACROS_MISC_
;!macro HIGH_3_LOW_5 .input {
.macro HIGH_3_LOW_5 input
and #%11100000 ; second value: high 3 bits = index into tables to find bitmasks
tax
eor (<input), y ; second value: low 5 bits = byte offset within the row (implicitly "and #%00011111")
tay
;}
.endmacro
; must set N flag based on Y immediately before using these macros
; e.g. LDY, INY, DEY, TYA
;!macro IS_Y_OFFSCREEN {
;.macro IS_Y_OFFSCREEN
; bpl +
; sec
; bcs ++
;+ cpy #40
;++
;}
;.endmacro
;!macro BRANCH_IF_Y_IS_OFFSCREEN .target {
; cpy #40
; bcs .target
;}
;!macro LONG_BRANCH_IF_Y_IS_OFFSCREEN .target {
; cpy #40
; bcc +
; jmp .target
;+
;}
;!macro COPY_TO_0 .start, .end {
.macro COPY_TO_0 start, end
; out: X=0
; Z=1
.Local m1
ldx #(end-start)
m1: lda start-1, x
sta $FF, x
dex
bne m1
;}
.endmacro
;!macro OVERCOPY_TO_0 .start, .end {
; over-copy region to $00
; clobbers $FF
; out: X=0
; Y=last byte before start (e.g. 0 if the last instruction is JMP $0000)
; ldx #(.end-.start+1)
;- ldy .start-2, x
; sty $FE, x
; dex
; bne -
;}
;!macro INC_INPUT_AND_LOOP .input, .loop {
.macro INC_INPUT_AND_LOOP input, loop
.Local p1
.Local p2
inc <input
beq p1
jmp loop
p1:
bit KBD
bmi p2
inc <input+1
jmp loop
p2:
rts
;}
.endmacro
;!macro DEC_INPUT_AND_LOOP .input, .loop {
; lda .input
; php
; dec .input
; dec .input
; plp
; bne +
; dec .input+1
; bit KBD
; bpl .loop
; bmi ++
;+ jmp .loop
;++ rts
;}
_FX_MACROS_MISC_=*
;}
.endif

View File

@ -11,7 +11,10 @@
; !source "src/fx/macros.dhgr.a"
; !source "src/fx/macros.shr.a"
; !source "src/fx/macros.copybit.a"
.include "macros.copybit.s"
; !source "src/fx/macros.misc.a"
.include "macros.misc.s"
_FX_MACROS_=*
.endif

View File

@ -7,6 +7,7 @@
;!ifndef _MACROS_ {
.ifndef _MACROS_
; !source "src/constants.a"
.include "constants.s"
; appears to put string and length?

View File

@ -4,7 +4,20 @@
.include "hardware.inc"
wipe_test:
lda #0
jmp after
test_graphic:
.incbin "graphics/a2_dating.hgr.zx02"
.include "zx02_optim.s"
.include "fx.lib.s"
after:
jsr BuildHGRTables
jsr BuildHGRMirrorTables
jsr BuildHGRMirrorCols
jsr BuildHGRSparseBitmasks1Bit
bit SET_GR
bit HIRES
@ -22,6 +35,22 @@ wipe_test:
lda #$20
jsr zx02_full_decomp
; ldy #0
;fake_hgr2:
; lda #$0
; sta $4000,Y
; dey
; bne fake_hgr2
;
; inc fake_hgr2+2
; lda fake_hgr2+2
; cmp #$60
; bne fake_hgr2
jsr HGR2
bit PAGE1
jsr wait_until_keypress
;=================================
@ -29,17 +58,19 @@ wipe_test:
;=================================
test_loop:
jsr Start
jsr InitOnce
jsr wait_until_keypress
jmp test_loop
test_graphic:
.incbin "graphics/a2_dating.hgr.zx02"
.include "wait_keypress.s"
.include "zx02_optim.s"
.include "fx.hgr.bubbles.s"
; possibly some bytes before get chewed on with some effects?
.align $100
Coordinates1Bit:
.incbin "fx.hgr.bubbles.data"
EndCoordinates1Bit:

View File

@ -0,0 +1,12 @@
MEMORY {
ZP: start = $00, size = $1A, type = rw;
RAM: start = $5700, size = $6900, file = %O;
}
SEGMENTS {
CODE: load = RAM, type = ro, align=$100;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
}

View File

@ -0,0 +1,12 @@
MEMORY {
ZP: start = $00, size = $1A, type = rw;
RAM: start = $5800, size = $6800, file = %O;
}
SEGMENTS {
CODE: load = RAM, type = ro, align=$100;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
}

View File

@ -0,0 +1,12 @@
MEMORY {
ZP: start = $00, size = $1A, type = rw;
RAM: start = $8800, size = $3800, file = %O;
}
SEGMENTS {
CODE: load = RAM, type = ro, align=$100;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
}