Initial Revision

This is Manic Miner for the Apple 2 but the source code is in Orca/M format.
This commit is contained in:
StewBC 2021-08-18 18:38:06 -07:00
commit 0cfbcae376
28 changed files with 13440 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
.vscode/*
/src/*.mac
/obj/
/debug*
/mminer.po
/MMINER

79
Makefile Normal file
View File

@ -0,0 +1,79 @@
# Settings
PROGRAM := MMINER
SRCDIR := src
TARGETOBJDIR := obj
TEMPLATE := apple2/template.po
DISK := mminer.po
VOLUME := MANIC
CADIUS := $(CADIUS)
ORCA := $(ORACInclude)
SED := $(SED)
AWK := $(AWK)
EMUDIR := $(APPLEWIN_HOME)
EMU := applewin.exe -d1 $(DISK)
all: $(PROGRAM)
ifeq ($(shell echo),)
MKDIR = mkdir -p $1
RMDIR = rmdir $1
RMFILES = $(RM) $1
CP = cp $1
else
MKDIR = mkdir $(subst /,\,$1)
RMDIR = rmdir /S /Q $(subst /,\,$1)
RMFILES = $(if $1,del /f /q $(subst /,\,$1))
CP = copy $(subst /,\,$1)
endif
define NEWLINE
endef
SOURCES += $(wildcard $(SRCDIR)/*.asm)
SOURCES := $(filter-out $(SRCDIR)/mminer.asm,$(SOURCES))
SOURCES := $(SRCDIR)/mminer.asm $(SOURCES)
OBJECTS += $(subst .asm,.ROOT,$(subst $(SRCDIR),$(TARGETOBJDIR),$(SOURCES)))
vpath %.asm $(SRCDIR)
$(TARGETOBJDIR):
$(call MKDIR,$@)
$(TARGETOBJDIR)/%.ROOT: %.asm $(wildcard $(SRCDIR)/*.s) $(wildcard $(SRCDIR)/*.mac) | $(TARGETOBJDIR)
iix assemble $< keep=$(subst /,:,$(basename $@))
$(PROGRAM): $(OBJECTS)
-$(call RMFILES,$(PROGRAM))
iix link +S $(OBJECTS) keep=$@ > debug0.map
iix makebin $@
.PHONY: all dsk test macros
all: $(PROGRAM)
dsk: $(PROGRAM)
$(call CP,$(TEMPLATE) $(DISK))
$(CADIUS) ADDFILE $(DISK) /$(VOLUME) ./$(PROGRAM)
test: dsk
$(SED) '9{:a;N;$$!ba;s/\n/ /g; s/\(\w\+\) . .. .. \(\w\+\)\s*/0x\1 \2\n/g;}' debug0.map > temp.map
$(AWK) --non-decimal-data 'NR>8 {$$1 += 0x4000; printf "%x %s\n", $$1, $$2}' temp.map > debug.map
$(call RMFILES,temp.map)
$(call CP,debug.map $(EMUDIR)/A2_USER1.SYM)
$(EMUDIR)/$(EMU)
macros:
$(foreach FILE, $(SOURCES), iix macgen $(FILE) $(subst .asm,.mac,$(FILE)) $(ORACInclude)/m16= src/Macros/macros.s ${NEWLINE})
clean:
-$(call RMFILES,$(OBJECTS))
-$(call RMFILES,$(addsuffix .A,$(basename $(OBJECTS))))
-$(call RMFILES,debug*.map)
-$(call RMFILES,$(PROGRAM))
-$(call RMFILES,$(DISK))
zap: clean
-$(call RMDIR,$(TARGETOBJDIR))

40
README.md Normal file
View File

@ -0,0 +1,40 @@
# Manic Miner - Orca/M version
This is the exact same version as the mminer-apple2 version (https://github.com/StewBC/mminer-apple2), except this has been changed to compile with the Orca/M assembler. Orca/M is an assembler that runs on Apple II hardware (I am using the Apple IIgs version, even though I am targeting the Apple II). I am also using this software on Windows - see below.
To learn more about Orca/M, see https://juiced.gs/store/opus-ii-software/
## Building
The Makefile is for GNU Make and I am using it on a Windows PC. It needs a few environment variables to be set. These are:
1. AWK and SED which turns the linker symbol output into a form usable with AppleWin. This can be commented out as it is not at all esential - it's only good for seeing the labels in the AppleWin debugger. If you use PowerShell on Windows, the below will set the AWK and SED environment variables:
$env:AWK="`"C:/Program Files/Git/usr/bin/gawk.exe`""
$env:SED="`"C:/Program Files/Git/usr/bin/sed.exe`""
(Notice the back-tick quoting of the inner quotes so PowerShell doesn't freak out)
2. I use Cadius (https://www.brutaldeluxe.fr/products/crossdevtools/cadius/) to add the executable to a disk image. I also formatted the code using Cadius. The following is where I have cadius installed:
$env:CADIUS="C:/Users/swessels/Apps/bin/Cadius.exe"
Cadius uses a hidden file called _FileInformation.txt to store meta information about the files it manipulates in the image. The most important bits are MMINER=Type(06),AuxType(4000) which says the file MMINER should be given the Binary type and Auxiliary data of $4000.
3. Lastly, I use Orca with GoldenGate to compile on a Windows PC. To learn more about GoldenGate, look at https://juiced.gs/store/golden-gate/
$env:ORACInclude="C:/ProgramData/GoldenGate/Libraries/ORCAInclude"
Once all is set to go, the first step is:
make macros
If this doesn't work, make sure the file src/Macros/macros.s has LF line endings. If it is CRLF then macgen is unhappy.
Then make will build or make dsk will build and generate mminer.po or make test which will make the disk and run it in an emulator (Configured for AppleWin).
make clean will delete intermediate files and make zap will delete intermediate files as well as remove the obj folder.
I think that's about it!
Stefan Wessels
swessels@email.com
18 August 2021

1
_FileInformation.txt Normal file
View File

@ -0,0 +1 @@
MMINER=Type(06),AuxType(4000),VersionCreate(00),MinVersion(80),Access(E3),FolderInfo1(000000000000000000000000000000000000),FolderInfo2(000000000000000000000000000000000000)

BIN
apple2/template.dsk Normal file

Binary file not shown.

BIN
apple2/template.po Normal file

Binary file not shown.

70
src/Macros/macros.s Normal file
View File

@ -0,0 +1,70 @@
;-----------------------------------------------------------------------------
; macro to take text address and split it into lo and hi (shorthand)
; macro
; printXY &xpos,&ypos,&text,&len,&colorMask,&inverse
; printXYlh &xpos,&ypos,#<&text,#>&text,&len,&colorMask,&inverse
; mend
;-----------------------------------------------------------------------------
; Macro that takes a lo and hi for the text with optional color and invert wanted
; sets up what's needed to call textShow which does the printing
macro
printXYlh &xpos,&ypos,&textL,&textH,&len,&colorMask,&inverse
aif C:&colorMask>0,.cmgiven
lda #$ff ; no color (white) is a mask of $ff left and right
sta dstPtrL
sta dstPtrL+1
ago .nocm
.cmgiven
ldx &colorMask ; this is an index into mask[Left|Right]
lda masksLeft,x
sta dstPtrL
lda masksRight,x
sta dstPtrL+1
.nocm
aif C:&inverse>0,.invgiven
lda #0 ; eor o is not inverse
ago .noinv
.invgiven
lda #$7f ; eor $7f inverts the color (leave MSB)
.noinv
sta eorMask+1 ; set the eor in the code
lda &textL ; set the string pointer in the code
sta read0+1
lda &textH
sta read0+2
ldx &len ; 0 based
stx sizeL
lda &xpos ; and x/y coords in x and y registers
asl a
tax
ldy &ypos
jsr textShowText ; print that string
mend
;-----------------------------------------------------------------------------
; Prep uiShowMMText internal variables with data relevant for the
; specific text the macro is called with
macro
uiShowMMTextXY &column,&row,&data,&widths,&colors
lda #<&data ; MANIC or MINER bit-arrays
sta dataLoc+1
lda #>&data
sta dataLoc+2
lda #<&widths
sta widthLoc+1 ; array of letter-widths in MANIC or MINER
lda #>&widths
sta widthLoc+2
lda #<&colors ; array of letter colors in the words
sta colorLoc+1
lda #>&colors
sta colorLoc+2
ldx &column ; screen location passed in x/y
ldy &row
jsr uiShowMMText ; show the word on-screen
mend

125
src/audio.asm Normal file
View File

@ -0,0 +1,125 @@
;-----------------------------------------------------------------------------
; audio.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
65816 OFF
copy src/defs.s
AUDIO start
;-----------------------------------------------------------------------------
audioPlayTitleNote entry
fixedDuration equ srcPtrL
noteDuration equ srcPtrH
freqTimer1 equ dstPtrL
freqTimer2 equ dstPtrH
ldy #0 ; load the duration
lda (musicL),y
beq reset ; on 0, the song is done
sta noteDuration
lda audioMask ; see if the note should be played or simply delayed
and #AUDIO_MUSIC
bne apt0 ; audio is on, go play
jsr uiDelay ; waste time as though a note was played
jmp leave ; and move the audio pointer along
apt0 iny ; load the 1st timer
lda (musicL),y
sta freqTimer1
iny ; load the second timer
lda (musicL),y
sta freqTimer2
preplay anop
lda #$8A ; repeat minimum this much
sta fixedDuration
tplay anop
lda SPEAKER ; toggle the speaker
dec freqTimer1 ; timer1 down
bne apt2 ; not zero, go to timer 2
ldy #1 ; reset timer 1
lda (musicL),y
sta freqTimer1
ldx #11 ; delay about 20 clock cycles
apt1 dex
bne apt1
apt2 dec freqTimer2 ; dec timer 2
bne apt4 ; not zero?
ldy #2 ; at zero, reset timer 2
lda (musicL),y
sta freqTimer2
ldx #11 ; and waste 20 clock cycles
apt3 dex
bne apt3
apt4 dec fixedDuration ; dec the fixed repeat count
bne tplay ; not zero, do another loop
dec noteDuration ; dec the note delay
bne preplay ; do more loops of at least fixedDuration
leave anop
clc
lda musicL ; add 3 to the music pointer
adc #3
sta musicL
bcc apt5
inc musicH
clc ; leave with carry clear
apt5 rts
reset anop
lda #<titleMusic ; played the whole tune
sta musicL ; reset to start of tune
lda #>titleMusic
sta musicH
sec ; and leave with carry set
rts
;-----------------------------------------------------------------------------
audioPlayNote entry
delayTime equ tmpBot+0
lda audioMask ; see if the music is on
and #AUDIO_MUSIC
beq done
nplay anop
ldx musicL ; get the index into the in-game music
inc musicL ; and advance that index
lda inGameMusic,x ; get the note at the index
bne apn0 ; if non-zero it's a valid note
sta musicL ; reset the index to the start of the song
beq nplay
apn0 ldy #$08 ; fixed number of iterations
freq entry ; external entry point for custom fixed iterations/delay
sta delayTime ; store it in a delay counter
lda audioMask ; see if
and #AUDIO_SOUND ; audio is enabled
beq done ; and play or ignore audio accordingly
loop anop
lda SPEAKER ; toggle the speaker
ldx delayTime ; and load the delay
apn1 dex ; count down
bne apn1 ; to zero
dey ; then repeat
bne loop ; for the fixed iterations
done anop
rts ; and return
end

283
src/defs.s Normal file
View File

@ -0,0 +1,283 @@
;-----------------------------------------------------------------------------
; defs.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
; These from apple2.inc for use with ca65
;-----------------------------------------------------------------------------
; Zero page
WNDLFT gequ $20 ; Text window left
WNDWDTH gequ $21 ; Text window width
WNDTOP gequ $22 ; Text window top
WNDBTM gequ $23 ; Text window bottom+1
CH gequ $24 ; Cursor horizontal position
CV gequ $25 ; Cursor vertical position
BASL gequ $28 ; Text base address low
BASH gequ $29 ; Text base address high
INVFLG gequ $32 ; Normal/inverse(/flash)
PROMPT gequ $33 ; Used by GETLN
RNDL gequ $4E ; Random counter low
RNDH gequ $4F ; Random counter high
HIMEM gequ $73 ; Highest available memory address+1
;-----------------------------------------------------------------------------
; Vectors
DOSWARM gequ $03D0 ; DOS warmstart vector
BRKVec gequ $03F0 ; Break vector
SOFTEV gequ $03F2 ; Vector for warm start
PWREDUP gequ $03F4 ; This must be = EOR #$A5 of SOFTEV+1
;-----------------------------------------------------------------------------
; Hardware
; Keyboard input
KBD gequ $C000 ; Read keyboard
KBDSTRB gequ $C010 ; Clear keyboard strobe
; 80 column video
CLR80COL gequ $C000 ; Disable 80 column store
SET80COL gequ $C001 ; Enable 80 column store
RD80COL gequ $C018 ; >127 if 80 column store enabled
RD80VID gequ $C01F ; >127 if 80 column video enabled
; Character set
CLRALTCHAR gequ $C00E ; Normal Apple II char set
SETALTCHAR gequ $C00F ; Norm/inv LC, no flash
ALTCHARSET gequ $C01E ; >127 if alt charset switched in
; Language card
RDLCBNK2 gequ $C011 ; >127 if LC bank 2 in use
RDLCRAM gequ $C012 ; >127 if LC is read enabled
ROMIN gequ $C081 ; Swap in D000-FFFF ROM
LCBANK2 gequ $C083 ; Swap in LC bank 2
LCBANK1 gequ $C08B ; Swap in LC bank 1
; Vertical blanking
RDVBLBAR gequ $C019 ; >127 if not vertical blanking
RDVBLMSK gequ $C041 ; >127 if VBL interrupts enabled
DISVBL gequ $C05A ; Disable VBL interrupts
ENVBL gequ $C05B ; Enable VBL interrupts
; Video mode
TXTCLR gequ $C050 ; Display graphics
TXTSET gequ $C051 ; Display text
MIXCLR gequ $C052 ; Disable 4 lines of text
MIXSET gequ $C053 ; Enable 4 lines of text
LOWSCR gequ $C054 ; Page 1
HISCR gequ $C055 ; Page 2
LORES gequ $C056 ; Lores graphics
HIRES gequ $C057 ; Hires graphics
DHIRESON gequ $C05E ; Enable double-width graphics
DHIRESOFF gequ $C05F ; Disable double-width graphics
; Game controller
TAPEIN gequ $C060 ; Read casette input / Switch input 3
BUTN0 gequ $C061 ; Switch input 0 / Open-Apple key
BUTN1 gequ $C062 ; Switch input 1 / Closed-Apple key
BUTN2 gequ $C063 ; Switch input 2 / Shift key
PADDL0 gequ $C064 ; Analog input 0
PADDL1 gequ $C065 ; Analog input 1
PADDL2 gequ $C066 ; Analog input 2
PADDL3 gequ $C067 ; Analog input 3
PTRIG gequ $C070 ; Analog input reset
; Input/Output Unit
IOUDISON gequ $C07E ; Disable IOU
IOUDISOFF gequ $C07F ; Enable IOU
; Control Your Apple
CYAREG gequ $C036 ; Bits 0-3=disk detect 4=shadow all banks 7=fast
;-----------------------------------------------------------------------------
; These are for mminer-apple2
;-----------------------------------------------------------------------------
HGRPage1 gequ $2000
HGRPage2 gequ $4000
MLI gequ $BF00
SPEAKER gequ $C030
PLACEHOLDER gequ $FFFF
;-----------------------------------------------------------------------------
; Cheat Key (binary 0-19 reverse) 12345
LEVEL_Central_Cavern gequ 0 ; 00000
LEVEL_The_Cold_Room gequ 1 ; 10000
LEVEL_The_Menagerie gequ 2 ; 01000
LEVEL_Abandoned_Uranium_Workings gequ 3 ; 11000
LEVEL_Eugenes_Lair gequ 4 ; 00100
LEVEL_Processing_Plant gequ 5 ; 10100
LEVEL_The_Vat gequ 6 ; 01100
LEVEL_Miner_Willy_meets_the_Kong gequ 7 ; 11100
LEVEL_Wacky_Amoebatrons gequ 8 ; 00010
LEVEL_The_Endorian_Forest gequ 9 ; 10010
LEVEL_Attack_of_the_Mutant_Telephones gequ 10 ; 01010
LEVEL_Return_of_the_Alien_Kong_Beast gequ 11 ; 11010
LEVEL_Ore_Refinery gequ 12 ; 00110
LEVEL_Skylab_Landing_Bay gequ 13 ; 10110
LEVEL_The_Bank gequ 14 ; 01110
LEVEL_The_Sixteenth_Cavern gequ 15 ; 11110
LEVEL_The_Warehouse gequ 16 ; 00001
LEVEL_Amoebatrons_Revenge gequ 17 ; 10001
LEVEL_Solar_Power_Generator gequ 18 ; 01001
LEVEL_The_Final_Barrier gequ 19 ; 11001
LEVEL_Game_Over gequ 20
;-----------------------------------------------------------------------------
DATA_BLANK gequ $00
DATA_FLOOR1 gequ $10
DATA_FLOOR2 gequ $20
DATA_CONVEYOR gequ $30
DATA_WALL gequ $40
DATA_BUSH gequ $50
DATA_ROCK gequ $60
DATA_COLLAPSE gequ $70
DATA_KEY gequ $80
DATA_SWITCH1 gequ $90
DATA_SWITCH1_OPEN gequ $A0
DATA_SWITCH2 gequ $B0
DATA_SWITCH2_OPEN gequ $C0
DATA_DOOR gequ $D0
;-----------------------------------------------------------------------------
START_LIVES gequ 2
MAX_LIVES gequ 5
PLAY_ROWS gequ 16
PLAY_COLS gequ 32
VISIBLE_COLS gequ 20
TILES_PER_LEVEL gequ 8
TILE_BYTES gequ 16
CONVEYOR_FRAMES gequ 7
KEYS_FRAMES gequ 4
MAX_SPRITES gequ 10
SPRITE_BYTES gequ 64
MAX_SPRITE_IFRAMES gequ 36
AIR_STR_LEN gequ 5
AIR_SPEED gequ 14
DEMO_TIMER_DURATION gequ 2
DEMO_TIMER_INITAL gequ 18
;-----------------------------------------------------------------------------
zero_base gequ $50
currPageH gequ $50 ; $02 or $04 - Hi for screen buffer to draw t0
backPage gequ $51 ; 0 or 1 - just used to toggle HISCR or LOSCR
monochrome gequ $52 ; 0 for color, 1 for black and white
leftEdge gequ $53 ; distance the screen has scrolled to the right
cameraMode gequ $54
tilesRendered gequ $55 ; count the number of tiles shown in a screen. Used to time music delay
willyXPos gequ $56 ; column for willy
willyYPos gequ $57 ; pixel-row for willy
willyYRow gequ $58 ; row (YPos / 8) for willy
willyFrame gequ $59 ; willy animation frame
willyDir gequ $5A ; direction willy is facing
willyJumpCounter gequ $5B ; what phase of a jump willy is in
willyFallFromJump gequ $5C ; 0 or 1. 1 when willy starts jumping. Affects falling death
numSprites gequ $5D ; how many sprites (excl. willy) to draw in a level (door is last)
spriteXPos gequ $5E ; MAX_SPRITES col position of the sprite
spriteYPos gequ $68 ; MAX_SPRITES pixel row
spriteDir gequ $72 ; MAX_SPRITES facing direction
spriteMin gequ $7C ; MAX_SPRITES min (turn/hold) point for path
spriteMax gequ $86 ; MAX_SPRITES max point for path
spriteSpeed gequ $90 ; MAX_SPRITES speed (frames/pixels) to move the sprite
spriteTick gequ $9A ; MAX_SPRITES counter how often a sprite animates (spritespeed as init)
spriteFramesIdx gequ $A4 ; MAX_SPRITES Index into
spriteFrame gequ $AE ; MAX_SPRITES which frame the sprite is on
spriteClass gequ $B8 ; MAX_SPRITES see CLASS_* in defs.inc for masks
spriteColor gequ $C2 ; MAX_SPRITES index into masks<Left|Right> in rosystem.inc
movementMask gequ $CC ; movement that happened in willyMove. See MASK_* in defs.inc
userKeyMask gequ $CD ; user desire to move based on keys pressed. See MASK_* in defs.inc
conveyorMask gequ $CE ; 0, willy not on conveyor, 2 for left, 1 for right
currLevel gequ $CF ; level that's active
lives gequ $D0 ; lives in reserve
airCols gequ $D1 ; screen columns that have an air bar in them
airTipGfx gequ $D2 ; the bit pattern for the tip of the air bar
airFlow gequ $D3 ; the "tick" till a unit of air is decreased
livesFrame gequ $D4 ; anim frame for the walking willy's at the bottom
keysFrameNum gequ $D5 ; animation frame for keys in the level (color)
conveyorFrameNum gequ $D6 ; animation frame for conveyor tile to be active
keysToCollect gequ $D7 ; number of keys that remain to be collected
eventState gequ $D8 ; see EVENT_* in defs.inc for bitmask values
updateUICount gequ $D9 ; updateUI is called when non-zero
uiComponent gequ $DA ; See UI_COMPONENT_* in defs.inc for mask values. What UI to update
fullScreenClearCount gequ $DB ; 0 - clear only top, non-zero all. Is counted down by gameAI
musicL gequ $DC ; pointer or index for playing music
musicH gequ $DD ; hi pointer for playing UI music
audioMask gequ $DE ; see AUDIO_* in defs.inc
demoMode gequ $DF ; 0 - not a demo, 1 when demo mode active
demoTimer gequ $E0 ; in demo mode, scroll when counter is 0
demoDirection gequ $E1 ; direction the demo scroll will move the screen
cheatIndex gequ $E2 ; count cheat code entry or when active, if 6 is down
cheatActive gequ $E3 ; non-zero when the cheat was successfully entered
srcPtrL gequ $E4 ; often a pointer Lo
srcPtrH gequ $E5 ; often a pointer Hi
dstPtrL gequ $E6 ; often a pointer Lo
dstPtrH gequ $E7 ; often a pointer Hi
sizeL gequ $E8 ; sometimes a size used in ptr operations
sizeH gequ $E9 ; sometimes a size used in ptr operations
tmpBot gequ $EA ; start of block of 7 zp values used randomly
bitMasks gequ $F1 ; constant - used mostly for bit instruction (see below)
bit0Mask gequ $F1 ; 1
bit1Mask gequ $F2 ; 2
bit2Mask gequ $F3 ; 4
bit3Mask gequ $F4 ; 8
bit4Mask gequ $F5 ; 16
bit5Mask gequ $F6 ; 32
bit6Mask gequ $F7 ; 64
bit7Mask gequ $F8 ; 128
CLASS_MOVE_Y gequ bit0Mask
CLASS_FOUR_FRAME gequ bit1Mask
CLASS_UNUSED gequ bit2Mask
CLASS_HOLDATEND gequ bit3Mask
CLASS_EUGENE gequ bit4Mask
CLASS_KONG gequ bit5Mask
CLASS_SKYLAB gequ bit6Mask
CLASS_DOOR gequ bit7Mask
;-----------------------------------------------------------------------------
CAMERA_MODE_3_ZONE gequ 0
CAMERA_MODE_SCROLL gequ 1
;-----------------------------------------------------------------------------
EVENT_OK gequ 0
EVENT_DIED gequ 1
EVENT_LEVEL_RESTART gequ 2
EVENT_NEXT_LEVEL gequ 4
EVENT_EXIT_GAME gequ 8
EVENT_CHEAT_JUMP gequ 16
;-----------------------------------------------------------------------------
UI_COMPONENT_NAME gequ 1
UI_COMPONENT_AIR_NAME gequ 2
UI_COMPONENT_AIR gequ 4
UI_COMPONENT_SCORE_NAME gequ 8
UI_COMPONENT_SCORE gequ 16
UI_COMPONENT_LIVES gequ 32
UI_COMPONENT_HIGHSCORE gequ 64
;-----------------------------------------------------------------------------
MASK_RIGHT gequ 1
MASK_LEFT gequ 2
MASK_AIR gequ 4
;-----------------------------------------------------------------------------
AUDIO_MUSIC gequ $80
AUDIO_SOUND gequ $40

859
src/game.asm Normal file
View File

@ -0,0 +1,859 @@
;-----------------------------------------------------------------------------
; game.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
65816 OFF
copy src/defs.s
GAME start
using ROSYSTEM
using DATA
using ROLEVELS
using ROTEXT
;-----------------------------------------------------------------------------
gameLoop entry
jsr gameNewGame ; init things that need 1-time game init
nextLevel anop
jsr tilesPrepForLevel ; move 8 tiles for this level to tilesInstances
restart anop
jsr gameInitStage ; init the stage, incl unpacking the level, tile prep etc
playLoop anop
jsr inputGet ; read the keyboard
lda demoMode ; check for demo mode
beq gl01 ; if not demo, move willy
jsr gameDemoTick ; demo mode so run demo
jmp ai ; skip moving willy
gl01 jsr willyMove ; move the main character based on user input (or conveyor or gravity)
ai anop
jsr gameAI ; run all the monster AI
ldx fullScreenClearCount ; get the flag for what level of screen clear is needed
jsr screenClear ; and clear the screen
jsr tilesAnimateKeys ; copy the 16 bytes for the next "key" frame into place
jsr tilesAnimateConveyor ; update the conveyor tile
jsr screenDrawSprites ; draw all the enemies
lda demoMode ; get the event state
beq gl02 ; 0 - not demo, full flow
jsr screenDrawLevel ; show all the tiles in demo mode
jmp ui0
gl02 lda #$ff ; Enable Collision detection
jsr screenDrawWilly ; not demo - draw willy with collision detection
bcc level ; carry set is a collision, clear is no problem
lda eventState ; on collision, set the die event
ora #EVENT_DIED
sta eventState
level anop
jsr screenDrawLevel ; show all the tiles
lda #0 ; No collision detection
jsr screenDrawWilly ; Now draw willy over self and level, no collision
ui0 anop
lda updateUICount ; see if the UI needs an update
beq gl03
jsr uiUpdate ; if needed, update the appropriate UI components
gl03 ldx numSprites ; The door's index
jsr screenDrawSprite ; render the door over everything else, no collision
jsr screenSwap ; swap to the newly rendered screen
jsr audioPlayNote ; play in-game music if needed
jsr gameDelay ; waste time to get all screens to run at same rate
lda eventState ; see if any events fired
beq playLoop ; keep looping while no events
jsr gameEvent ; process the event, return value in a
bit bit1Mask ; EVENT_LEVEL_RESTART
bne restart
bit bit2Mask ; EVENT_NEXT_LEVEL
bne nextLevel
lda demoMode ; no Game Over when the demo ends
bne gl04
jsr gameOver ; wasn't a demo, show Game Over
gl04 jsr textCheckHighScore ; game over - see if a new high score was set
rts
;-----------------------------------------------------------------------------
gameDelay entry
delayTime equ tmpBot+0
lda #$10
sta delayTime
delayCalc anop
sec
lda #$D0
sbc tilesRendered
bcc gddone
tax
gd01 ldy delayTime
gd02 dey
bne gd02
dex ; and do it for all tiles not rendered (<$80)
bne gd01
gddone anop
rts
;-----------------------------------------------------------------------------
gameNewGame entry
lda #START_LIVES ; init player number of lives
sta lives
lda #LEVEL_Central_Cavern ; Init these game vars to 0
sta currLevel
lda #0 ; audioPlayNote uses muiscL as well
sta musicL ; track progress through in-game song
ldx #5 ; six, zero-based score digits
lda #'0' ; load a with '0'
gng0 sta score,x ; set all 6 score digits to '0'
dex
bpl gng0
rts
;-----------------------------------------------------------------------------
gameInitStage entry
using LOWMEM
count equ tmpBot+0
spriteIdx equ tmpBot+1
instanceIdx equ tmpBot+2
ldy currLevel ; Skip some stuff for "Game Over" pseudo-level
cpy #20
bcs notDemo
jsr levelUnpack ; decompress a level to levelLayout
jsr levelPlaceKeys ; put the keys into the world
jsr textSetLevelText ; create the gfx cache for the name
ldy currLevel ; tables are indexed by level
lda demoMode ; see if this is demo mode
beq notDemo ; branch if game
lda willyx ; use willy screen 0 for willyXPos in demo (force leftEdge to 0)
bne gis1
notDemo anop
lda willyx,y ; set willy X up
gis1 sta willyXPos
ldx cameraMode
lda #CAMERA_MODE_SCROLL
sta cameraMode
jsr positionScreen ; set the screen position based on willy's X
stx cameraMode
lda willyy,y ; set willy's Y
sta willyYPos
lda willyStartDir,y ; and see what facing direction
sta willyDir
beq gis2 ; if right (0) then set that as the animFrame
lda #4 ; if left (1) set the anim frame to 4
gis2 sta willyFrame ; and save the anim frame
postWilly anop
lda #3 ; AI will count down and runs before clearScreen
sta fullScreenClearCount ; so set to 3 to get full clear on both buffers
lda #AIR_SPEED ; set counter for ticking down air
sta airFlow
lda #32 ; set how many air cols there are
sta airCols
lda #$7f ; the air "bar" tip is a character that draws less
sta airTipGfx ; bar over time, till it rolls to the prev column
lda #$ff ; match all masks
jsr uiUpdateComponent ; so force all UI elements to draw
lda level_sprites_count,y ; get how many enemy sprites the level has
sta count ; save for init
sta numSprites ; save for the game to use
dec numSprites ; make this count 0 based
lda level_sprites_offset,y ; see where in the sprite tables this sprite starts
tay ; move the offset into x - sprite tables indexed by this
ldx #0 ; y will be an enemy instance index
stx eventState ; init he event state
stx livesFrame ; but use this 0 to init some variables
stx movementMask ; current movement for willy
stx conveyorMask ; direction conveyor under willy is moving (0=no conveyor under willy)
stx userKeyMask ; keys the user has pressed to move willy
stx willyJumpCounter ; 0 means no jump, 1-18 is in a jump, beyond is a fall height
stx spriteFramesIdx
clc ; clear carry - will always enter below with carry clear
gisnext anop
sty spriteIdx ; save which sprite is being processed (x clobbered)
stx instanceIdx ; save y, also clobbered
lda #0
sta spriteFrame,x ; init the sprite specific frame counter to 0
lda sprites_x,y ; load the basic sprite variables and put into zero page
sta spriteXPos,x ; from 0 .. numSprites - 1
lda sprites_y,y ; the addressing is unfortunate - sta,x is zero-page 2 byte
sta spriteYPos,x ; but it's not worth swapping x and y for this bit of code
lda sprites_dir,y
sta spriteDir,x
lda sprites_min,y
sta spriteMin,x
lda sprites_max,y
sta spriteMax,x
lda sprites_speed,y
sta spriteSpeed,x
sta spriteTick,x
lda sprites_class,y
sta spriteClass,x
lda sprites_colors,y ; get the color
sta spriteColor,x
lda sprites_bitmaps,y ; get the index into the sprite data for this sprite's images
jsr spriteInstanceSpriteFrames
ldx instanceIdx ; restore y
cpx numSprites
beq prep
lda spriteClass,x
bit bit1Mask ; CLASS_FOUR_FRAME
beq gis3
lda #4
bne gis4
gis3 lda #8
gis4 adc spriteFramesIdx,x
sta spriteFramesIdx+1,x
ldy spriteIdx
iny ; next sprite in sprite table
inx ; next instance
dec count
beq prep
jmp gisnext
prep anop
ldx currLevel ; some levels need special handling
cpx #LEVEL_Eugenes_Lair ; eugene needs colored copies
bne gis5
jsr spriteEugeneSetup
jmp fixDoor
gis5 cpx #LEVEL_Miner_Willy_meets_the_Kong ; kong levels need switches
beq giskong
cpx #LEVEL_Return_of_the_Alien_Kong_Beast
bne gis6
giskong anop
lda #DATA_SWITCH1
sta levelLayout+6
lda #DATA_SWITCH2
sta levelLayout+18
jmp fixDoor
gis6 cpx #LEVEL_Skylab_Landing_Bay ; skylab needs satellites to get X values
bne gis7
ldx #2 ; init the falling satellites
skyLabPos anop
lda skylabXPos,x
sta spriteXPos,x
txa
sta spriteTick,x
dex
bpl skyLabPos
gis7 cpx #LEVEL_The_Final_Barrier
bne fixDoor
dec numSprites ; hide the victory door sprite
fixDoor anop
jmp spriteDoorSetup ; sprites are set up - door is special
;-----------------------------------------------------------------------------
gameAI entry
lda fullScreenClearCount ; get the state
beq ga01 ; if it's zero, move on
dec fullScreenClearCount ; count this down
ga01 dec airFlow ; deal with the air countdown. airFlow is "time" counter
bne airDone
jsr gameAirDecrease
airDone anop
inc livesFrame ; move the lives anim frame along
lda livesFrame ; through the first 4 frames only
cmp #16 ; by dividing by 4 (in essence) to get a slower animation
bcc ga02
lda #0 ; start at frame 0 when wrapping
ga02 sta livesFrame
and #3 ; only update every 4 frames (not & 3)
bne ga03
lda #UI_COMPONENT_LIVES ; tell ui to update lives
jsr uiUpdateComponent
ga03 ldx numSprites ; now set up all the sprites for this level
galoop anop
lda spriteClass,x ; start with the class
bit CLASS_DOOR ; and if it's a door, treat that separate
beq ga04
jmp door
ga04 bit CLASS_MOVE_Y ; see if it moves vertically
beq horizontal ; no - then it moves horizontally
jmp vertical ; yes - them move it vertically
horizontal anop
lda spriteSpeed,x ; get speed
bit bit0Mask ; Is the speed 1
beq rtick ; if not, advance this sprite
dec spriteTick,x ; dec the ticker
bpl ganext ; if ge 0 then ignore sprite
sta spriteTick,x ; reset ticker to speed and fall through to run
rtick anop
lda spriteDir,x ; get the direction
bne left ; 1 is left, 0 is right
right anop
inc spriteFrame,x ; move the frame
lda spriteFrame,x ; load it
cmp #4 ; see if it's 4
bcc ganext ; if 4+, done here
inc spriteXPos,x ; up the x position
lda spriteXPos,x ; load it
cmp spriteMax,x ; see if it's ge max
bcs rightEnd ; if yes, end of going right
lda #0 ; no, reset
sta spriteFrame,x ; frame to 0
beq ganext ; BRA. done with this sprite
rightEnd anop
dec spriteXPos,x ; set back to last valid x
lda #1 ; load left
sta spriteDir,x ; and set direction left
lda #7 ; 7 is most right position of sprite
sta spriteFrame,x ; and set the frame to that
fix4 anop
lda spriteClass,x ; get the class
bit CLASS_FOUR_FRAME ; see if it has the (only) 4 frames flag set
beq ganext ; if not, done with this sprite (frame 7 is good)
lda #3 ; drop the 7 to 3
sta spriteFrame,x ; set the frame
jmp ganext
left anop
dec spriteFrame,x ; move the frame
lda spriteFrame,x ; load it
cmp #$ff ; see if it is now lt 0 (3,2,1 -> 0 overflow)
beq stepLeft ; if it is, move the col left
cmp #3 ; if it's 3, (7,6,5,4 -> 3 overflow)
bne ganext ; if not, done with this sprite
stepLeft anop
dec spriteXPos,x ; move the column left
lda spriteXPos,x ; load it
cmp spriteMin,x ; compare to minimum
bcc leftEnd ; if less than minimum, too far, past the left edge
lda #7 ; keep going, load 7
sta spriteFrame,x ; set frame back to 7
bne fix4 ; BRA, and check for a 4-frame sprite
leftEnd anop
inc spriteXPos,x ; put the column back to in range
lda #0 ; load 0
sta spriteDir,x ; set as direction (right)
sta spriteFrame,x ; and frame (most left frame)
beq ganext ; BRA, done with this sprite
postVMove anop
lda spriteClass,x ; after a vertical update check these special cases
bit CLASS_EUGENE ; Eugene
bne eugene
bit CLASS_KONG ; Kong
beq ga05
jmp kong
ga05 bit CLASS_SKYLAB ; skylab
beq ga06
jmp skylab
ga06 inc spriteFrame,x ; otherwise go to next frame
lda spriteFrame,x
and #3
sta spriteFrame,x
ganext anop
dex ; get previous sprite
bpl goTop ; if ge 0 then still a sprite to process
rts ; all sprites done - exit
goTop anop
jmp galoop
vertical anop
lda spriteDir,x ; get direction 1 = UP, 0 equ DOWN
beq down
bmi postVMove ; if the spriteDir is lt $ff, stationary sprite
up anop
lda spriteYPos,x ; get the Y position
sec
sbc spriteSpeed,x ; move up by the speed
cmp spriteMin,x ; see if at top
bcc upEnd ; overshot top
sta spriteYPos,x ; update Y position
bcs postVMove ; BRA
upEnd anop
lda spriteClass,x ; get the class
bit CLASS_HOLDATEND ; should it stop or bounce
bne stop ; HOLDATEND means stop
lda #0 ; change direction
sta spriteDir,x ; to DOWN (0)
beq postVMove ; BRA
down anop
lda spriteYPos,x ; get the Y
clc
adc spriteSpeed,x ; add the speed
cmp spriteMax,x ; see of at end
bcs downEnd ; at or past end
sta spriteYPos,x ; still good, update Y position
bcc postVMove ; BRA
downEnd anop
lda spriteClass,x ; same as upEnd
bit CLASS_HOLDATEND
bne stop
lda #1 ; but mark for moving UP (1)
sta spriteDir,x
bne postVMove ; BRA maybe down?
stop anop
lda #$ff ; set the direction to -1 (lt 0)
sta spriteDir,x
bne postVMove ; BRA
door anop
lda keysToCollect ; check if all keys have been collected
bne ganext ; no - nothing more to do
frameToggle anop
dec spriteTick,x ; count down for animation
bpl ganext ; gt 0, nothing more
lda spriteFrame,x ; get the frame
eor #1 ; toggle between 1 and 0
sta spriteFrame,x ; update the frame
lda spriteSpeed,x ; get the anim speed
sta spriteTick,x ; save it to the tick
jmp ganext
eugene anop
lda keysToCollect ; eugene changes behavior when all keys collected
bne eugeneNormal ; not all keys, carry on
lda #0 ; all keys - force eugene down
sta spriteDir,x
inc spriteFrame,x ; cycle through the 5 colors
lda spriteFrame,x
cmp #4
bcc ga07
lda #0
ga07 sta spriteFrame,x ; save the new frame
eugeneNormal anop
jmp ganext
kong anop
lda spriteMax,x ; if kong's max is 0 he's still up
beq frameToggle
lda spriteDir,x ; if he's not up see what his direction is
bpl kongFall ; gt 0, then he's still falling
cmp #$FE ; $fe he's been erased so done with him
beq kongDone ; $ff he's just reached the bottom
dec spriteDir,x ; turn $ff into $fe
txa ; put the sprite index into a
pha ; and save it
lda spriteFramesIdx,x ; get the index to the 1st kong frame
tax ; put that in x
inx ; and skip the 2 frames where
inx ; kong is standing
ldy #2 ; want to clear 2 frames
jsr spriteClearFrames ; and make the falling frames blank
pla ; get the sprite index
tax ; and put it back in x
kongDone anop
jmp ganext
kongFall anop
ldx #3 ; digit 3 (100's)
lda #1 ; add 1
jsr textAddScore ; add to score
lda #UI_COMPONENT_SCORE ; show changes
jsr uiUpdateComponent
jmp frameToggle
skylab anop
lda spriteDir,x ; get the direction of the falling satellite
cmp #$ff ; see if it's reached its end
beq ga08 ; yes it has
jmp ganext
ga08 inc spriteFrame,x ; advance the collapsing frame
lda spriteFrame,x ; load that frame
cmp #8 ; see if it's the last
bcs ga09 ; yes
jmp ganext
ga09 lda spriteTick,x ; get the tick (hich is an index in this case)
clc
adc #3 ; advance by 3 (3 satellites at a time) so next index for this satellite
cmp #12 ; (3*4 is 12) - there are 4 stating locations per satellite
bcc ga10 ; not rolled over
and #3 ; reset this satellite to 1st starting location (index)
ga10 sta spriteTick,x ; save the tick
tay ; put into Y
lda skylabXPos,y ; get the actual start position, based on y, for this satellite
sta spriteXPos,x ; put that into the satellite
lda #0 ; reset the frame, position and direction all to 0
sta spriteFrame,x
sta spriteYPos,x
sta spriteDir,x
jmp ganext
;-----------------------------------------------------------------------------
gameDemoTick entry
dec demoTimer ; timer counts down
bne gdt0 ; if not yet zero, nothing to do
lda #DEMO_TIMER_DURATION ; reset the timer
sta demoTimer
lda #UI_COMPONENT_NAME ; mark the level name as needing an update
jsr uiUpdateComponent
lda leftEdge ; scroll the screen
clc
adc demoDirection ; based on the scrolling direction
sta leftEdge
beq nextDemoLevel ; if the edge is 0 then done with level
cmp #12 ; at 12, the level flips scroll direction
bne gdt0
lda #$ff ; at 12, the scroll direction becomes -1
sta demoDirection
gdt0 rts
nextDemoLevel anop
lda #DEMO_TIMER_INITAL ; set for a longer initial hold at a new level
sta demoTimer
lda #1 ; set the scroll direction to be right (1)
sta demoDirection
lda #0 ; set the edge to be the very left
sta leftEdge
lda #EVENT_NEXT_LEVEL ; fire a new level event
ora eventState
sta eventState
rts
;-----------------------------------------------------------------------------
gameEvent entry
bit bit0Mask ; EVENT_DIED
beq ge00 ; if not, must be end of level
dec lives ; died, so take a life
bmi died ; all lives lost ends the game
lda #0
sta tmpBot
jsr screenInvertVisibleScreen
lda #EVENT_LEVEL_RESTART ; still alive so restart the level
rts
ge00 bit bit4Mask ; EVENT_CHEAT_JUMP
bne gedone ; if jumping, just go
lda currLevel ; check the level
cmp #19 ; is this the last level
bcc ge01 ; if not, go to screen invert
lda cheatActive ; last level - got here by cheating?
bne ge01 ; yes - go screen invert
lda demoMode ; is this demo mode?
bne ge01 ; yes - go to screen invert
jsr gameVictory ; played properly through, get the victory
ge01 ldx #8 ; do an inverse screen effect
ge02 stx sizeL
txa
and #3
clc
adc #1
sta tmpBot
jsr screenInvertVisibleScreen
ldx sizeL
dex
bne ge02
lda demoMode ; is this demo mode
bne incLevel ; skip the air/score, just go to next level
jsr valueSwap ; do the air countdown/add score routine now, on front screen
airLoop entry
ldx #5 ; digit 5 (1's)
lda #7 ; add 7
jsr textAddScore ; add to score
ldx #4 ; digit 4 (10's)
lda #1 ; add 1 (so add 17 per tick)
jsr textAddScore ; add to score
jsr gameAirDecrease ; run the decrease air
lda airCols ; get the remaining bar length
asl a ; mult * 4
asl a
eor #$7f ; and reverse (ignore MSB which is 0) - this is the freq
ldy #6 ; duration for the freq
jsr freq ; make a sound of this freq and duration
jsr uiUpdate ; and show the updates
lda eventState ; get the event state
bit bit0Mask ; check for EVENT_DIED
beq airLoop ; not dead means more air left
jsr valueSwap ; go back to the back screen
incLevel anop
inc currLevel ; set the current level to the next
ldx currLevel
cpx #20 ; see if this is the last level+1
bcc gedone ; if not, all is well
lda demoMode ; check again for demo
beq ge03 ; if not, roll over to level 1 and keep playing
died anop
lda #EVENT_DIED ; demo also ends with a death event
rts
ge03 ldx #0 ; not demo, past last level, start at 1st level again
stx currLevel
gedone anop
lda #EVENT_NEXT_LEVEL ; return in a the action (next level)
rts
;-----------------------------------------------------------------------------
gameAirDecrease entry
lda #AIR_SPEED
sta airFlow
lda #UI_COMPONENT_AIR ; tick the air down, so update the UI
jsr uiUpdateComponent
ldx airCols ; see if it's an odd or even column
inx ; but the air draws from an odd column so the 1 bit is backwards
txa
and #1
tax ; x 0 is even,x 1 is odd
lda airTipGfx ; see what the tip looks like
cmp maskGreen,x ; if it's all green, time to drop another column
beq colDec
lsr a ; not all green, so adjust the tip by dropping 2 bits (1 white pixel)
lsr a
ora maskGreenHi,x ; and replace that with a green pixel (appropriate for odd/even column)
bne airOk
colDec anop
dec airCols ; one less bar
bpl gad0
lda eventState ; out of air causes death
ora #EVENT_DIED
sta eventState
lda #0
sta airCols ; lock airCols at 0
lda maskGreen,x ; lock to all green for the tip
bne airOk
gad0 lda maskNewTip,x ; start a new (mostly white) tip, appropriate for odd/even
airOk anop
sta airTipGfx
rts
;-----------------------------------------------------------------------------
gameOver entry
iter equ currLevel ; how many times to loop
bootPart anop
ldx #20 ; game over level is 20 (0 based)
stx currLevel
jsr gameInitStage
ldx #0 ; clear the top part of the screen
jsr screenClear
ldx #0 ; draw the boot
jsr screenDrawSprite
ldx #$60 ; start of boot-drop freq
stx iter
lda #1 ; pretend there's a key so Boot (EUGENE) doesn't animate
sta keysToCollect ; and the "door" doesn't switch to the second frame
tax ; also draw the pedestal (door)
jsr screenDrawSprite ; draw the boot
lda #2 ; set willy to frame 2
sta willyFrame
jsr screenDrawWilly ; show willy on the pedestal
jsr screenSwap ; make it all visible
jsr valueSwap ; fake the front as the back
bootLoop anop
jsr gameAI ; run the AI to move the boot down
dec iter ; raise freq
dec iter
lda audioMask ; see if the audio will play or skip
and #AUDIO_SOUND
beq otherDelay ; audio won't delay so "fake" an audio delay
lda iter ; get the freq
ldy #$80 ; duration for the freq (also slows the boot down)
jsr freq ; make a sound of this freq and duration
jmp go00
otherDelay anop
lda iter
lsr a
lsr a
tay
jsr ySet
go00 ldx #0 ; go draw the boot
jsr screenDrawSprite
lda spriteDir ; see if the boot has reached the pedestal
bpl bootLoop ; net yet, keep going
gameOverPart anop
color equ tmpBot+1 ; index into color masks arrays
xPos equ tmpBot+2 ; x for string
yPos equ tmpBot+3 ; y for string
textL equ tmpBot+4 ; string pointer
textH equ tmpBot+5
len equ tmpBot+6 ; how many characters (0 based)
lda #$20
sta iter ; how many times to loop
lda #(7*8) ; Y for string
sta yPos
lda #4 ; starting color
sta color
cycleLoop anop
lda #4 ; print GAME at x 4
sta xPos
lda #<roTextGame ; point at GAME text
sta textL
lda #>roTextGame
sta textH
lda #4 ; 0-3 characters
sta len
jsr textColorCycle ; show the text in color
lda #13 ; print OVER at x 13
sta xPos
lda #<roTextOver ; point at OVER text
sta textL
lda #>roTextOver
sta textH
lda #4 ; also 0-3 characters in length
sta len
jsr textColorCycle ; and show over with color
ldy #$30 ; delay the iteration of color
jsr ySet
dec iter ; one less iteration to do
bpl cycleLoop ; do all iterations
rts
;-----------------------------------------------------------------------------
gameVictory entry
lda #19 ; put willy above the door
sta willyXPos ; outside the caverns
lda #0
sta willyFrame
lda #2*8
sta willyYPos
ldx fullScreenClearCount ; get the flag for what level of screen clear is needed
jsr screenClear ; and clear the screen
jsr screenDrawSprites ; draw all the enemies
jsr screenDrawWilly ; not demo - draw willy with collision detection
jsr screenDrawLevel ; show all the tiles
ldx numSprites ; The door's index
inx
jsr screenDrawSprite ; render the door over everything else, no collision
jsr screenSwap ; swap to the newly rendered screen
audioPart anop
freqCntr equ tmpBot+0 ; freqCntr
duration equ tmpBot+1 ; duration
iteration equ tmpBot+2 ; iteration
lda #50 ; 50 iterations
sta iteration
lda #0 ; init freqCntr and duration
sta freqCntr
sta duration
gvloop anop
lda duration ; start with the duration
adc iteration ; add the iteration counter * 3
adc iteration
adc iteration
sta freqCntr ; save as the freqCntr
ldy duration ; put duration in Y
lda audioMask ; see if the audio will play or skip
and #AUDIO_SOUND
bne audioOn ; if on, use the freqCntr "API"
gv00 ldx freqCntr ; a bit ridiculous to redo playNote stuff here
gv01 dex ; but I want the audio code to all go through the
bne gv01 ; same "API" for consistency
dey
bne gv00
beq postfreq
audioOn anop
lda freqCntr
jsr freq ; make the sound if sound enabled
postFreq anop
dec iteration ; dec the iterations
bne gvloop ; loop till all iterations done
rts
end

228
src/input.asm Normal file
View File

@ -0,0 +1,228 @@
;-----------------------------------------------------------------------------
; input.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
65816 OFF
copy src/defs.s
mcopy src/input.mac
INPUT start
using ROSYSTEM
using ROTEXT
;-----------------------------------------------------------------------------
inputGet entry
lda KBD
bmi hasKey
lda cheatActive ; is the cheat code active
beq ig00 ; no - normal play
lda cheatIndex ; is the 6 down
beq ig00 ; no - normal play
jmp setJmpEvent ; cheat active and 6 down - keep resetting to this level
ig00 rts
hasKey anop
bit KBDSTRB
and #$5f ; strip MSB and upper/lower case (to upper)
tax
lda demoMode
beq ig01
jmp premusic
ig01 txa
bne right ; $5f clears space so a is 0 for jump
jump anop
lda userKeyMask
eor #MASK_AIR ; AIR marks the start of a jump
sta userKeyMask
rts
right anop
cmp #'W' ; go right with w (left handed) or P
beq ig02
cmp #'P'
bne left
ig02 lda userKeyMask
and #$FD ; <~MASK_LEFT ; clear left
eor #MASK_RIGHT ; activate right
sta userKeyMask
rts
left anop
cmp #'Q' ; go left with q (left handed) or o
beq ig03
cmp #'O'
bne camera
ig03 lda userKeyMask
and #$FE ; <~MASK_RIGHT ; clear right
eor #MASK_LEFT ; activate left
sta userKeyMask
rts
camera anop
cmp #'C' ; c toggles the scroll mode
bne cheat ; if not c maybe cheat?
lda #1 ; xor the camera mode with 1
eor cameraMode
sta cameraMode
rts ; done, can't be any other key
cheat anop
ora #%00100000 ; make "normal" characters
ldx cheatActive ; see if the cheat mode is on
bne checkJump ; if yes, see if a jump needs to happen
ldx cheatIndex ; active, not on
cmp roTextCheatCode,x ; is this the next cheat code character
bne resetCheat ; no, reset the cheat
inx ; yes
stx cheatIndex ; inc the index
cpx #7 ; all 7 typed
beq ig04 ; yes
rts ; not yet, so done here
ig04 ldx #1 ; make the cheat active
stx cheatActive
resetCheat anop
ldx #0 ; set the cheat index to 0
stx cheatIndex
jumpNotActive anop
and #%11011111 ; restore the acc to uppercase
bne music ; BRA
checkJump anop
cmp #'6' ; is this a 6
beq jumpToggle ; if yes, toggle the jump mode on/off
bcs jumpNotActive ; gt 6, then nothing to do with cheat
ldx cheatIndex ; is 6 down
beq jumpNotActive ; no, process as non-cheat key
cmp #'1'
bcc jumpNotActive ; less than 1, not cheat code
sec
sbc #'1' ; make key 0 based
tax ; and index in x
lda bitMasks,x ; get the appropriate bit
eor currLevel ; and toggle in the current level
cmp #20 ; if the level ge 20 then set to 0
bcc ig05
lda #0
ig05 sta currLevel
setJmpEvent anop
lda #EVENT_CHEAT_JUMP ; set the jump event active
ora eventState
sta eventState
rts
jumpToggle anop
lda #1 ; prep to toggle the jump state
eor cheatIndex
sta cheatIndex ; save it
beq ig06 ; is it off, just leave
lda #0 ; just turned on, reset
sta currLevel ; the level to level 0
ig06 rts
premusic anop
txa ; restore the read-key
music anop
cmp #'M' ; m toggles music on/off
bne ig07
LDA audioMask
eor #AUDIO_MUSIC
sta audioMask
rts
ig07 cmp #'B'
bne ig08
lda #1
eor monochrome
sta monochrome
jmp tilesPrepForLevel
ig08 cmp #'S' ; s toggles in-game sound on/off
bne ig09
LDA audioMask
eor #AUDIO_SOUND
sta audioMask
rts
ig09 cmp #$1B ; ESC
beq quit ; quit game or demo
lda demoMode ; see if this is demo
beq done ; if not, ignore all other keys, demo quit on any key
quit anop
lda #0 ; set lives to zero so this die event quits
sta lives
inc demoMode ; turn demo mode if not on, so there's no end-of-level stuff
lda eventState ; and make a death event
ora #EVENT_DIED
sta eventState
done anop
rts
;-----------------------------------------------------------------------------
inputUI entry
loop equ currLevel
lda KBD ; Get the keyboard
bpl okay ; and ignore no keys
bit KBDSTRB ; reset the keyboard
and #$5f ; strip MSB and case bit
cmp #'M' ; see if it's the music toggle
bne iu00
lda audioMask
eor #AUDIO_MUSIC
sta audioMask
okay anop
lda #0 ; no key or M or m returns 0
rts
iu00 cmp #'B' ; b in the UI toggles color/mono
bne iu01
lda #1
sta currLevel ; in UI so abuse currLevel as a counter
eor monochrome ; toggle mono/color
sta monochrome
beq showColor
showMono anop
printXYlh #7,#(17*8),#<roTextMono,#>roTextMono,#4 ; show Mono on screen CHECKCHECKCHECK
jsr valueSwap ; fake swap
dec currLevel ; and do twice so both buffers updated
bpl showMono
jmp doneB
showColor anop
printXYlh #7,#(17*8),#<roTextColor,#>roTextColor,#4 ; show Color on in both buffers
jsr valueSwap
dec currLevel
bpl showColor
doneB anop
lda #0 ; if all is well, return with 0 in a
rts
iu01 cmp #$1b ; non-music/color toggle key see if it's esc
beq exit ; exit if it is
stop anop
lda #1 ; non-M, B or ESC (non toggle) returns 1 (start game)
rts
exit anop
lda #$ff ; -1 on ESC (quit application)
rts
end

131
src/level.asm Normal file
View File

@ -0,0 +1,131 @@
;-----------------------------------------------------------------------------
; level.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
65816 OFF
copy src/defs.s
LEVEL start
using LOWMEM
using ROSYSTEM
using ROLEVELS
;-----------------------------------------------------------------------------
; "decompress" the stored level into a usable level in levelLayout
levelUnpack entry
value equ sizeL
len equ sizeH
ldx currLevel
lda #<levelLayout ; point at the level decode area
sta store+1
lda #>levelLayout
sta store+2
lda levelsL,x ; get the start of the level data intp srcPtr
sta srcPtrL
lda levelsH,x
sta srcPtrH
ldx #0 ; start at 0 in read and write area
ldy #0
loop anop
lda (srcPtrL),y ; read the first level byte (repeat counts)
beq done ; $00 ends level
pha ; save
iny ; point y at next byte
lsr a ; get high repeat nibble into low nibble
lsr a
lsr a
lsr a
tax ; but result in X
lda (srcPtrL),y ; read the next byte from level (values)
sta value ; save
iny ; advance y to next rep counts
lsr a ; get high value nibble into low nibble
lsr a
lsr a
lsr a
jsr lu00 ; store value repeat times into level decode area
pla ; restore the rep byte
and #$0f ; only the low nibble
tax ; put in x
lda value ; restore values
and #$0f ; only low nibble
jsr lu00 ; store value repeat times into level decode area
jmp loop ; repeat
lu00 stx len ; save the repeat count
tax ; value into x (value is a tile index)
lda mult16,x ; mult value by 16 as that's how wide a tile is
ldx len ; restore the repeat count
dex ; store index is 0+ but count is 1+ so pre-dec
store anop
sta PLACEHOLDER,x ; store the tile offset into the level decode area
dex ; from back to front and
bpl store ; repeat for all repetitions
lda len ; get the repeat length
clc
adc store+1 ; advance the stor pointer by the length
sta store+1
bcc done
inc store+2
done anop
rts ; return to self or caller
;-----------------------------------------------------------------------------
levelPlaceKeys entry
lda #0
sta keysToCollect ; init to 0 keys to collect
lda currLevel
asl a ; * 2
asl a ; * 4
adc currLevel ; * 5 - index into key table
tax ; keep index in x
lda #4 ; Need to do 5 keys, 0-4
sta sizeL ; save count in sizeL
ldy #0 ; keep offst from ptr at 0
lpk0 lda keyyH,x ; get the key Y hi (y=row*32 in key table)
bmi next ; if $ff then skip
inc keysToCollect ; count the key
sta dstPtrH ; save the hi
lda keyyL,x ; get the y lo
adc keyx,x ; and add the x (no carry still)
sta dstPtrL ; save as dst pointer
lda #>levelLayout ; get the scratch hi (the lo is 0 as it's aligned)
adc dstPtrH ; and add to the Y hi (and any carry)
sta dstPtrH ; and save as the dst Pointer Hi
lda #8*16 ; key tile offset * width of a tile
sta (dstPtrL),y ; poke into the unpacked level
next anop
inx ; next key
dec sizeL ; one less key to do
bpl lpk0 ; all keys done?
rts
end

527
src/logo.s Normal file
View File

@ -0,0 +1,527 @@
;-----------------------------------------------------------------------------
; logo.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
HGR data
dc h'25552a552a552a35552a552a552a552a'
dc h'552a552a552a552a552a552ad5aad5aa'
dc h'552a552a552a552aaad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a550000000000000000'
dc h'29552a552a552a35552a552a552a552a'
dc h'552a552a552a552a552a557a8f8080f8'
dc h'5f2a552a15552a2baad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a550000000000000000'
dc h'15552a1500552a2b552aa92d552a557a'
dc h'772f5f2a552a552a552a557a8f8080f8'
dc h'5f2a552a6552552caad5abd5abffafdd'
dc h'fad5ebd5aad5eaddabd7aefdead5badd'
dc h'aad5baf5feddeedfaff5eafdbbf5eadd'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'55541a15004d55d2da2aaab555d4562a'
dc h'552a552a553269326932697affffffff'
dc h'5f7b5d6f55525a2aaad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aadfaad5'
dc h'c081c3e1b0988ce0808683e0b0f88386'
dc h'c3e1b0988c86c3e180988c8683e0c0e1'
dc h'b0e0c0e1b0988c800000000000000000'
dc h'552a550a402a25d5aa2da92d25d5aa2b'
dc h'552a552a2a552a552a552a552a552a55'
dc h'2a552a552a552a55aad5aad5aaf5aff7'
dc h'aadfafddaed7bbf7eeddaadfeeddebf5'
dc h'aed5aefffed7aed5aad5aad5fedfaad5'
dc h'8080809880fef09fc3e1b0e0b080c0e1'
dc h'ff87fcffc0e1bff88ffe83e0bff88ffe'
dc h'c3e1bf808c8080800000000000000000'
dc h'552a550a402a552a55d2aad5562a552a'
dc h'2f552a552a552a552a552a552a552a55'
dc h'2a552a552a552a55aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'95552a0520502aadd5aaaaadd5aa9555'
dc h'ff5f2a552a552a552a552a552a552a55'
dc h'2a552a552a552a558ff8c087bc9eb0e0'
dc h'f3818ff8c0e78386bcfec081cf87bce0'
dc h'839e8f98f0f9c087bce0f381839e8f98'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a55bffef39fbffefcf9'
dc h'f3e7bffef3e7cf9fbffef3e7cf9ffff9'
dc h'cf9fbffefcf9f39ffff9f3e7cf9fbffe'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'25552a552a552a55552a552a552a552a'
dc h'552a552a552a552a552a552ad5aad5aa'
dc h'552a552a552a552aaad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a550000000000000000'
dc h'29552a552a552a55552a552a552a552a'
dc h'7f2a552a552a552a552a557a8f8080f8'
dc h'5f2a552a152b152baad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a550000000000000000'
dc h'25552a1500552a2b554aaad5552a55ff'
dc h'576f572a552a552a552a557acf9ffcf9'
dc h'5f7b5d6f652c562caad5abd5abd7aedd'
dc h'fad5ebd5abd5ead5abd7aefdead5bbdd'
dc h'bed5fafdbafdeed5bbf5eaf5baf5eadd'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'55525614002d55d2ea2aaab515d5da2a'
dc h'552a552a553269326932697affffffff'
dc h'5f7b5d6f45525a28aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5fadfaad5'
dc h'80fec0fff09f8ce0bffe83e0bfe080fe'
dc h'c3e1f39ffc87cfff80f88f868380bfe0'
dc h'f0e1c0e1bff88f800000000000000000'
dc h'552a550a402a55d4aa2da92da9d5ea2a'
dc h'552a55522a552a552a552a552a552a55'
dc h'2a552a552a552a55aad5aad5aaf5baf7'
dc h'aaf7eedfaed7bbffeeddaaf5eeddebf5'
dc h'aed5aef5aed7bad5aad5aad5fedfaad5'
dc h'808080e08398b098c3e1f09fb080c0e1'
dc h'b0988c86c3e1b0988c868080b0988c86'
dc h'c3e1b0808c8080800000000000000000'
dc h'552a550a402a592a55d2aad5da2a55f4'
dc h'3f552a552a552a552a552a552a552a55'
dc h'2a552a552a552a55aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'a5552a4528512a35d5aaa9d5d5aaa555'
dc h'ffff2a552a552a552a552a552a552a55'
dc h'2a552a552a552a558ff8c087bc9eb0e0'
dc h'f3818ff8c0e78386bcfec081cf87bce0'
dc h'839e8f98f0f9c087bce0f381839e8f98'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a55bffef39fbffefcf9'
dc h'f3e7bffef3e7cf9fbffef3e7cf9ffff9'
dc h'cf9fbffefcf9f39ffff9f3e7cf9fbffe'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'15552a552a552a2d552a552a552a552a'
dc h'552a552a552a552a552a552ad5aad5aa'
dc h'552a552a552a552aaad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a550000000000000000'
dc h'29552a552a552a35552a552a552a556a'
dc h'ff3f552a552a552a552a557acf9ffcf9'
dc h'5f2a552a154b162baaf5fff7aff5aadf'
dc h'faf7affdaad5ffd5efdfaffdfbfffedf'
dc h'aad5aad580c082858a94a0d4a88080c0'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a550000000000000000'
dc h'25552a1500555a2a554aaad5552a55ff'
dc h'ff2f7d2a5554aa55aa55aafdcf9ffcf9'
dc h'5f7b5d6f652c562ceaf5aad5abd7aedd'
dc h'ead5abf7abd5ead5abd7aef5eaf5baf5'
dc h'ead5baf7baddefd7aff5eef5baf5aad7'
dc h'80fe8080808080808080808080808080'
dc h'c0e180808c808380808080808080bfe0'
dc h'80e0c081809880800000000000000000'
dc h'55525614002b55d4ea2aaab515d5da2a'
dc h'552a552a553269326932697affffffff'
dc h'5f7b5d6f45525a28aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5fed7aad5'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'552a550a402a55d2aa2d552aa9d5da2a'
dc h'552a25552a552a552a552a552a552a55'
dc h'2a552a552a552a55aad5aad5aaf5baf7'
dc h'aaf7eeddaed7bbd7bedfaaf5eeddebf5'
dc h'aed5aeddaed7bad5aad5aad5bfffaad5'
dc h'808080808c98f09ff3e7b0e0b080c0e1'
dc h'b0988c86c3e1b0f88f8680e0bf988c86'
dc h'c3e1bf80838080800000000000000000'
dc h'552a550c402ca92b55d2aad5da2a25f5'
dc h'3f552a552a552a552a552a552a552a55'
dc h'2a552a552a552a55aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'a5552a552a552a35d5aaaab5d5aa2955'
dc h'7aff2a552a552a552a552a552a552a55'
dc h'2a552a552a552a558ff8c087bc9eb0e0'
dc h'f3818ff8c0e78386bcfec081cf87bce0'
dc h'839e8f98f0f9c087bce0f381839e8f98'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a55bffef39fbffefcf9'
dc h'f3e7bffef3e7cf9fbffef3e7cf9ffff9'
dc h'cf9fbffefcf9f39ffff9f3e7cf9fbffe'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'15552a552a552a35552a552a552a552a'
dc h'552a552a552a552a552a552ad5aad5aa'
dc h'552a552a552a552aaad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a550000000000000000'
dc h'29552a552a552a35552a552a552a557a'
dc h'ff2b552a552a552a552a557acf9ffcf9'
dc h'5f2a552a152b152baaf5eaf7abddabfd'
dc h'ead5abf7abf5ead5abd7bef5eaf5bafd'
dc h'aad5aa95aad1a8c488d1a8d088d5aad5'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a550000000000000000'
dc h'29552a1500555a2a554aaad5552a55ff'
dc h'ffff5d2e5f54aa55aa55aafdcf9ffcf9'
dc h'ffffffff29552a35eaddaaf5efdfbfff'
dc h'eaf7affdaad5fad5efdfbff5fbfffed5'
dc h'bbd5baf5baddeed5bbf5fbf5baf5aad7'
dc h'c0818380808080808080808080808080'
dc h'80e080808c8083808080808080e0c081'
dc h'b0e0c081809880800000000000000000'
dc h'552a550a002b55d4aa2baab515d5ea2a'
dc h'552a552a553269326932697affffffff'
dc h'5f7b5d6f45525a28aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5bad7aad5'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'552a550a402a554aaab5552aaad5552a'
dc h'552a2a552a552a552a552a552a552a55'
dc h'2a552a552a552a55aad5aad5aaf5badd'
dc h'aaf7eeddaed7bbf7bad7eaf5eeddebf5'
dc h'aed5aeddaef7bad5aad5aad5fffdaad5'
dc h'80808080b098b080b3e6b0e0b080b0e0'
dc h'b0988c86c3e1b0988086fce1b0988c86'
dc h'c3e180e0808080800000000000000000'
dc h'552a55140035a9b555d4aad5da2aaaf5'
dc h'3f552a552a552a552a552a552a552a55'
dc h'2a552a552a552a55aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'a5552a552a552a55e5aaa9d5d5aa2a55'
dc h'2a7f2a552a552a552a552a552a552a55'
dc h'2a552a552a552a558ff8c087bc9eb0e0'
dc h'f3818ff8c0e78386bcfec081cf87bce0'
dc h'839e8f98f0f9c087bce0f381839e8f98'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a55bffef39fbffefcf9'
dc h'f3e7bffef3e7cf9fbffef3e7cf9ffff9'
dc h'cf9fbffefcf9f39ffff9f3e7cf9fbffe'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'25552a552a552a35552a552a552a552a'
dc h'552a552a552a552a552a552ad5aad5aa'
dc h'552a552a552a552aaad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a550000000000000000'
dc h'25552a012a502a55552a552a552a553e'
dc h'757a572a552a552a552a557acf9ffcf9'
dc h'5f2a552a152b152baaddbbffabddabfd'
dc h'ead5ebd5abf5ead7abd7bef5ead5bbf5'
dc h'aad5aad5a0d1a8848ad4a8c488c1aad5'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a550000000000000000'
dc h'29552a150055562a552aaab5552a553e'
dc h'7d3f5f6f7f54aa55aa55aafdcf9ffcf9'
dc h'ffffffff29552a35aad7aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'afd5baf5feddeedfbbf5eafdfbf7afd7'
dc h'c081c0ffb098fce7bffe83e0bf868cfe'
dc h'c3e1f09ffc87c3ff80f88ffe83e080e0'
dc h'fce1c0e1b0f88f800000000000000000'
dc h'552a550a002b55d4aa2ba92d15d5ea2a'
dc h'552a552a553269326932697affffffff'
dc h'5f7b5d6f05500a28aad5aad5aaf5afd5'
dc h'aad7aed5aad5abd5aad5aadfaad5aaf5'
dc h'aad5affffed7bfd5aad5aad5fadfaad5'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'552a550a402a552aaab5252baab5552a'
dc h'554a2a552a552a552a552a552a552a55'
dc h'2a552a552a552a55aad5aad5aaf5afdd'
dc h'aad7eedfbedfbbffbad7aadfeeddebf7'
dc h'aed5aed7fed7bfd5aad5aad5fad7aad5'
dc h'80808098b098b0988c98b0e0b0e0b0e0'
dc h'b0988c86c3e1b0988c8680e0b0988c86'
dc h'c3e1b098808080800000000000000000'
dc h'552a25150035aad556d4aad5dad2aaf5'
dc h'ff552a552a552a552a552a552a552a55'
dc h'2a552a552a552a55aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'29552a552a552a552aaba9add5522a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a558ff8c087bc9eb0e0'
dc h'f3818ff8c0e78386bcfec081cf87bce0'
dc h'839e8f98f0f9c087bce0f381839e8f98'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a55bffef39fbffefcf9'
dc h'f3e7bffef3e7cf9fbffef3e7cf9ffff9'
dc h'cf9fbffefcf9f39ffff9f3e7cf9fbffe'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'25552a552a552a2d552a552a552a552a'
dc h'552a552a552a552a552a552ad5aad5aa'
dc h'552a552a552a552aaad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a550000000000000000'
dc h'15552a150a502a35552a552a552a553f'
dc h'572e572a552a552a552a557acf9ffcf9'
dc h'5f2a552a152b152baaddbbdfabd7aedd'
dc h'ebd5ebd5aaf5eaf7abd7eef5ead5baf5'
dc h'aad5aad58ad180c488d1a89488c5aad5'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a550000000000000000'
dc h'29552a150055552a592aaab5552c557a'
dc h'753f5f6f7f54aa55aa55aafdcf9ffcf9'
dc h'5f7b5d6f2a552a55bff5ffffffffffff'
dc h'ffffffffffffffffffffffffffffffdf'
dc h'eaffaad5aad5aad5aad5aad5aad5aad5'
dc h'809ec0e1b0988ce080868380b0868c80'
dc h'c3e180988c86c3e180988c8683e080e0'
dc h'b0e0ffe1b0988c800000000000000000'
dc h'552a550a402a15d5aa2ba92d25d5ea2a'
dc h'552a552a553269326932697affffffff'
dc h'5f7b5d6f45525a28aad5aad5aaf5bad5'
dc h'aad7aed5aed7abd5aad5eaf5aad5ebf5'
dc h'aaf5eef5aef7bad5aad5aad5fad7aad5'
dc h'80808080808080808080808080808098'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'552a550a402a552aa92daab5a92d552a'
dc h'55522a552a552a552a552a552a552a55'
dc h'2a552a552a552a55aad5aad5aad5aadd'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5bedfaad5'
dc h'808080e08ff8f09f8c98f09fc09f8ce0'
dc h'b0988c86c3e1b0f88f8680e0bff88ffe'
dc h'c3e7bff88f8080800000000000000000'
dc h'552a29150035aad5dad4aad5dad4aad5'
dc h'ff572a552a552a552a552a552a552a55'
dc h'2a552a552a552a55aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'2a552a552a552a552aadaaad95552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a558ff8c087bc9eb0e0'
dc h'f3818ff8c0e78386bcfec081cf87bce0'
dc h'839e8f98f0f9c087bce0f381839e8f98'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a55bffef39fbffefcf9'
dc h'f3e7bffef3e7cf9fbffef3e7cf9ffff9'
dc h'cf9fbffefcf9f39ffff9f3e7cf9fbffe'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'25552a552a552a35552a552a552a552a'
dc h'552a552a552a552a552a55aad5aad5aa'
dc h'd52a552a552a552aaad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a550000000000000000'
dc h'25552a0508502a55552a552a552a552f'
dc h'5f3f5f2a552a552a552a557acf9ffcf9'
dc h'5f2a552a152b152baaf5badfabd7aedd'
dc h'eed5ebd5aaf5eefdabd7aef7eadffadf'
dc h'aad58a80a0d1a8c48891a0d4a8d0aad5'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a550000000000000000'
dc h'25552a150055552ada2aaab555b4556a'
dc h'773f7d3f7d54aa55aa55aafd8f8080f8'
dc h'5f7b5d6f2a552a55aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'80e0c0e1b0988ce080fe83e0bf9883fe'
dc h'c3e1f09f8c86c3ff80988c8683e0f0e1'
dc h'b0e0c0e1b0988c800000000000000000'
dc h'552a550a402a15d5aa2ba92d25d5ea2a'
dc h'552a552a553269326932697affffffff'
dc h'5f7b5d6f454a5628aad5aad5aaf5bad5'
dc h'aad7aed5aed7abd5aad5ead5aad5eaf5'
dc h'aad5eef5aed7bad5aad5aad5ead5aad5'
dc h'808080e08f8080808080f09fc09f8086'
dc h'80808080c08180808080808080808080'
dc h'c08180f8838080800000000000000000'
dc h'552a550a402a552a25cdaad5a92b552a'
dc h'15552a552a552a552a552a552a552a55'
dc h'2a552a552a552a55aad5aad5aad5aad7'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5fedfaad5'
dc h'80808080808080808080808080808c80'
dc h'80808080808080808080808080988086'
dc h'80808080808080800000000000000000'
dc h'554a2a150035aad59ad5aad5ead4aad5'
dc h'ff572a552a552a552a552a552a552a55'
dc h'2a552a552a552a55aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'2a552a552a552a552aada9d595552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a558ff8c087bc9eb0e0'
dc h'f3818ff8c0e78386bcfec081cf87bce0'
dc h'839e8f98f0f9c087bce0f381839e8f98'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'2ad52ad52ad52ad52ad52ad52ad52ad5'
dc h'2ad52ad52ad52ad52ad52ad52ad52ad5'
dc h'2ad52ad52ad52ad5bffef39fbffefcf9'
dc h'f3e7bffef3e7cf9fbffef3e7cf9ffff9'
dc h'cf9fbffefcf9f39ffff9f3e7cf9fbffe'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'25552a552a552a55552a552a552a552a'
dc h'552a552a552a552a552a55aad5aad5aa'
dc h'd52a552a552a552aaad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a550000000000000000'
dc h'15552a1508552a35552a552a552a556b'
dc h'573f5f2a552a552a552a557a8f8080f8'
dc h'5f2a552a152b152baad5aed7abd7aedd'
dc h'eed5ebd5aad5ebddabd7aef7ead5bad7'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a550000000000000000'
dc h'25552a150055554ada2aaab555d4552a'
dc h'572f7dff5f54aa55aa55aafd8f8080f8'
dc h'5f7b5d6f2a552a55aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'8080c3e1b0988ce0808680e0b0988386'
dc h'c3e1b0988c86c38180988c8683e0c0e1'
dc h'b0e0c0e1b0988c800000000000000000'
dc h'552a550a402a25d5aa2da92d25d5aa2b'
dc h'552a552a2a3569326932697affffffff'
dc h'5f7b5d6f452a5528aad5aad5aaf5baf7'
dc h'aadfefdfffdfbfffeeddead5fedffbf7'
dc h'afd5eef5aed7bad5aad5aad5fad7aad5'
dc h'80808098b09880808080b0e0b0e08086'
dc h'80808080808080808080808080808080'
dc h'c08180988c8080800000000000000000'
dc h'552a550a402a552a154baad5652a552a'
dc h'29552a552a552a552a552a552a552a55'
dc h'2a552a552a552a55aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5beffaad5'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080988086'
dc h'80808080808080800000000000000000'
dc h'55522a150055aad59ad5aad5ead4aad5'
dc h'ff5f2a552a552a552a552a552a552a55'
dc h'2a552a552a552a55aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'aad5aad5aad5aad5aad5aad5aad5aad5'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'2a552a552a552a552a35a9ada5552a55'
dc h'2a552a552a552a552a552a552a552a55'
dc h'2a552a552a552a558ff8c087bc9eb0e0'
dc h'f3818ff8c0e78386bcfec081cf87bce0'
dc h'839e8f98f0f9c087bce0f381839e8f98'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
dc h'aa55aa55aa55aa55aa55aa55aa55aa55'
dc h'aa55aa55aa55aa55aa55aa55aa55aa55'
dc h'aa55aa55aa55aa55bffef39fbffefcf9'
dc h'f3e7bffef3e7cf9fbffef3e7cf9ffff9'
dc h'cf9fbffefcf9f39ffff9f3e7cf9fbffe'
dc h'80808080808080808080808080808080'
dc h'80808080808080808080808080808080'
dc h'80808080808080800000000000000000'
end

67
src/mminer.asm Normal file
View File

@ -0,0 +1,67 @@
;-----------------------------------------------------------------------------
; mminer.asm
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
65816 OFF
align $100
ORG $4000
copy src/logo.s
copy src/defs.s ; globally used defines (Incl. MLI)
MMINER start
;-----------------------------------------------------------------------------
main entry
jsr mainInit ; do some one-time global init
jsr uiWaitForIntroEnter ; color cycle ENTER and wait for key
loop anop
jsr uiTitleScreen ; go to the ui
and #EVENT_EXIT_GAME ; see if event to exit game is set
bne quit
jsr gameLoop ; not quit, so run the gameplay (or demo)
jmp loop ; go back to the ui
quit anop
jsr MLI ; quit using the prodos mli
dc h'65' ; ProDOS Quit request
dc s2'*+2'
dc h'04000000000000'
mainInit entry
lda #0 ; init some one-time globals
sta backPage
sta leftEdge
sta cameraMode
sta uiComponent
sta cheatActive
sta cheatIndex
sta monochrome
lda #AUDIO_MUSIC+AUDIO_SOUND ; turn the music and in-game sounds on
sta audioMask
lda #>HGRPage1 ; set the current hidden (back) page to page 1
sta currPageH ; (page 2 was made visible by the loader)
lda #$80 ; make a zero-page bit mask area for checking bits
ldx #7 ; from 1 to 128, set each bit (backwards)
mi00 sta bitMasks,x ; set the bits in the area called bitMasks
lsr a
dex
bpl mi00
rts
end

71
src/roaudio.asm Normal file
View File

@ -0,0 +1,71 @@
;-----------------------------------------------------------------------------
; roaudio.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
ROAUDIO start
;-----------------------------------------------------------------------------
titleMusic entry
dc h'5080815066675056'
dc h'5732565732ABCB32'
dc h'2B33322B3332ABCB'
dc h'32334032334032AB'
dc h'CB32808132808132'
dc h'6667325657326056'
dc h'32ABC0322B30322B'
dc h'3032ABC032304432'
dc h'304432ABC0328889'
dc h'328889327273324C'
dc h'4D324C4D32ABC032'
dc h'263032263032ABC0'
dc h'32304432304432AB'
dc h'C032888932888932'
dc h'7273324C4D324C4D'
dc h'32ABCB3226333226'
dc h'3332ABCB32334032'
dc h'334032ABCB328081'
dc h'3280813266673256'
dc h'573240413280AB32'
dc h'202B32202B3280AB'
dc h'322B33322B333280'
dc h'AB32808132808132'
dc h'6667325657324041'
dc h'3280983220263220'
dc h'2632809832263032'
dc h'2630320000327273'
dc h'327273326061324C'
dc h'4D324C99324C4D32'
dc h'4C4D324C99325B5C'
dc h'3256573233CD3233'
dc h'343233343233CD32'
dc h'4041326667646667'
dc h'327273644C4D3256'
dc h'573280CB19800019'
dc h'80813280CB00'
inGameMusic entry
dc h'E6CDB7AC9AB79A9A'
dc h'91AC91919AB79A9A'
dc h'E6CDB7AC9AB79A9A'
dc h'91AC91919A9A9A9A'
dc h'E6CDB7AC9AB79A9A'
dc h'91AC91919AB79A9A'
dc h'E6CDB7AC9AB79A73'
dc h'9AB7E6B79A9A9A9A'
dc h'00'
jumpFreq entry
dc h'4040383830302828'
dc h'2020282830303838'
dc h'4040'
fallFreq entry
dc h'F4FF4C5864707C88'
dc h'94A0ACB8C4D0DCE8'
end

974
src/rofont.asm Normal file
View File

@ -0,0 +1,974 @@
;-----------------------------------------------------------------------------
; rofont.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
ROFONT data
;-----------------------------------------------------------------------------
font anop
font00 anop
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
;font01:
; dc h'8080' ; -------------- = --------------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'8080' ; -------------- = --------------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'8080' ; -------------- = --------------
;
;font02:
; dc h'8080' ; -------------- = --------------
; dc h'8C86' ; ---XX------XX- = --XX----XX----
; dc h'8C86' ; ---XX------XX- = --XX----XX----
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
;
;font03:
; dc h'8080' ; -------------- = --------------
; dc h'8C86' ; ---XX------XX- = --XX----XX----
; dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
; dc h'8C86' ; ---XX------XX- = --XX----XX----
; dc h'8C86' ; ---XX------XX- = --XX----XX----
; dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
; dc h'8C86' ; ---XX------XX- = --XX----XX----
; dc h'8080' ; -------------- = --------------
;
;font04:
; dc h'8080' ; -------------- = --------------
; dc h'C081' ; X------------X = ------XX------
; dc h'F09F' ; XXX------XXXXX = ----XXXXXXXX--
; dc h'CC81' ; X--XX--------X = --XX--XX------
; dc h'F087' ; XXX--------XXX = ----XXXXXX----
; dc h'C099' ; X--------XX--X = ------XX--XX--
; dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
; dc h'C081' ; X------------X = ------XX------
;
;font05:
; dc h'8080' ; -------------- = --------------
; dc h'8F98' ; ---XXXX--XX--- = XXXX------XX--
; dc h'8F86' ; ---XXXX----XX- = XXXX----XX----
; dc h'C081' ; X------------X = ------XX------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'8C9E' ; ---XX----XXXX- = --XX----XXXX--
; dc h'839E' ; -----XX--XXXX- = XX------XXXX--
; dc h'8080' ; -------------- = --------------
;
font06 anop
dc h'8080' ; -------------- = --------------
dc h'B080' ; -XX----------- = ----XX--------
dc h'CC81' ; X--XX--------X = --XX--XX------
dc h'B080' ; -XX----------- = ----XX--------
dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
dc h'8386' ; -----XX----XX- = XX------XX----
dc h'FC99' ; XXXXX----XX--X = --XXXXXX--XX--
dc h'8080' ; -------------- = --------------
font07 anop
dc h'8080' ; -------------- = --------------
dc h'C081' ; X------------X = ------XX------
dc h'B080' ; -XX----------- = ----XX--------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
;font08:
; dc h'8080' ; -------------- = --------------
; dc h'8086' ; -----------XX- = --------XX----
; dc h'C081' ; X------------X = ------XX------
; dc h'C081' ; X------------X = ------XX------
; dc h'C081' ; X------------X = ------XX------
; dc h'C081' ; X------------X = ------XX------
; dc h'8086' ; -----------XX- = --------XX----
; dc h'8080' ; -------------- = --------------
;
;font09:
; dc h'8080' ; -------------- = --------------
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'8080' ; -------------- = --------------
;
;font0A:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'B086' ; -XX--------XX- = ----XX--XX----
; dc h'C081' ; X------------X = ------XX------
; dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
; dc h'C081' ; X------------X = ------XX------
; dc h'B086' ; -XX--------XX- = ----XX--XX----
; dc h'8080' ; -------------- = --------------
;
;font0B:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'C081' ; X------------X = ------XX------
; dc h'C081' ; X------------X = ------XX------
; dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
; dc h'C081' ; X------------X = ------XX------
; dc h'C081' ; X------------X = ------XX------
; dc h'8080' ; -------------- = --------------
;
font0C anop
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'B080' ; -XX----------- = ----XX--------
font0D anop
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
font0E anop
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'F081' ; XXX----------X = ----XXXX------
dc h'F081' ; XXX----------X = ----XXXX------
dc h'8080' ; -------------- = --------------
font0F anop
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8098' ; ---------XX--- = ----------XX--
dc h'8086' ; -----------XX- = --------XX----
dc h'C081' ; X------------X = ------XX------
dc h'B080' ; -XX----------- = ----XX--------
dc h'8C80' ; ---XX--------- = --XX----------
dc h'8080' ; -------------- = --------------
font10 anop
dc h'8080' ; -------------- = --------------
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'839E' ; -----XX--XXXX- = XX------XXXX--
dc h'C399' ; X----XX--XX--X = XX----XX--XX--
dc h'B398' ; -XX--XX--XX--- = XX--XX----XX--
dc h'8F98' ; ---XXXX--XX--- = XXXX------XX--
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8080' ; -------------- = --------------
font11 anop
dc h'8080' ; -------------- = --------------
dc h'F081' ; XXX----------X = ----XXXX------
dc h'CC81' ; X--XX--------X = --XX--XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
dc h'8080' ; -------------- = --------------
font12 anop
dc h'8080' ; -------------- = --------------
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8098' ; ---------XX--- = ----------XX--
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8380' ; -----XX------- = XX------------
dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
dc h'8080' ; -------------- = --------------
font13 anop
dc h'8080' ; -------------- = --------------
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'C087' ; X----------XXX = ------XXXX----
dc h'8098' ; ---------XX--- = ----------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8080' ; -------------- = --------------
font14 anop
dc h'8080' ; -------------- = --------------
dc h'C081' ; X------------X = ------XX------
dc h'F081' ; XXX----------X = ----XXXX------
dc h'CC81' ; X--XX--------X = --XX--XX------
dc h'C381' ; X----XX------X = XX----XX------
dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
dc h'C081' ; X------------X = ------XX------
dc h'8080' ; -------------- = --------------
font15 anop
dc h'8080' ; -------------- = --------------
dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
dc h'8380' ; -----XX------- = XX------------
dc h'FF87' ; XXXXXXX----XXX = XXXXXXXXXX----
dc h'8098' ; ---------XX--- = ----------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8080' ; -------------- = --------------
font16 anop
dc h'8080' ; -------------- = --------------
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8380' ; -----XX------- = XX------------
dc h'FF87' ; XXXXXXX----XXX = XXXXXXXXXX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8080' ; -------------- = --------------
font17 anop
dc h'8080' ; -------------- = --------------
dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
dc h'8098' ; ---------XX--- = ----------XX--
dc h'8086' ; -----------XX- = --------XX----
dc h'C081' ; X------------X = ------XX------
dc h'B080' ; -XX----------- = ----XX--------
dc h'B080' ; -XX----------- = ----XX--------
dc h'8080' ; -------------- = --------------
font18 anop
dc h'8080' ; -------------- = --------------
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8080' ; -------------- = --------------
font19 anop
dc h'8080' ; -------------- = --------------
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
dc h'8098' ; ---------XX--- = ----------XX--
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8080' ; -------------- = --------------
font1A anop
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'B080' ; -XX----------- = ----XX--------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'B080' ; -XX----------- = ----XX--------
dc h'8080' ; -------------- = --------------
font1B anop
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'B080' ; -XX----------- = ----XX--------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'B080' ; -XX----------- = ----XX--------
dc h'B080' ; -XX----------- = ----XX--------
dc h'8C80' ; ---XX--------- = --XX----------
font1C anop
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8086' ; -----------XX- = --------XX----
dc h'C081' ; X------------X = ------XX------
dc h'B080' ; -XX----------- = ----XX--------
dc h'C081' ; X------------X = ------XX------
dc h'8086' ; -----------XX- = --------XX----
dc h'8080' ; -------------- = --------------
font1D anop
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
dc h'8080' ; -------------- = --------------
dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
font1E anop
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'B080' ; -XX----------- = ----XX--------
dc h'C081' ; X------------X = ------XX------
dc h'8086' ; -----------XX- = --------XX----
dc h'C081' ; X------------X = ------XX------
dc h'B080' ; -XX----------- = ----XX--------
dc h'8080' ; -------------- = --------------
font1F anop
dc h'8080' ; -------------- = --------------
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8086' ; -----------XX- = --------XX----
dc h'C081' ; X------------X = ------XX------
dc h'8080' ; -------------- = --------------
dc h'C081' ; X------------X = ------XX------
dc h'8080' ; -------------- = --------------
font20 anop
dc h'8080' ; -------------- = --------------
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'C399' ; X----XX--XX--X = XX----XX--XX--
dc h'B39E' ; -XX--XX--XXXX- = XX--XX--XXXX--
dc h'F39F' ; XXX--XX--XXXXX = XX--XXXXXXXX--
dc h'8380' ; -----XX------- = XX------------
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8080' ; -------------- = --------------
font21 anop
dc h'8080' ; -------------- = --------------
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8080' ; -------------- = --------------
font22 anop
dc h'8080' ; -------------- = --------------
dc h'FF87' ; XXXXXXX----XXX = XXXXXXXXXX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FF87' ; XXXXXXX----XXX = XXXXXXXXXX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FF87' ; XXXXXXX----XXX = XXXXXXXXXX----
dc h'8080' ; -------------- = --------------
font23 anop
dc h'8080' ; -------------- = --------------
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8380' ; -----XX------- = XX------------
dc h'8380' ; -----XX------- = XX------------
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8080' ; -------------- = --------------
font24 anop
dc h'8080' ; -------------- = --------------
dc h'FF81' ; XXXXXXX------X = XXXXXXXX------
dc h'8386' ; -----XX----XX- = XX------XX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8386' ; -----XX----XX- = XX------XX----
dc h'FF81' ; XXXXXXX------X = XXXXXXXX------
dc h'8080' ; -------------- = --------------
font25 anop
dc h'8080' ; -------------- = --------------
dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
dc h'8380' ; -----XX------- = XX------------
dc h'FF87' ; XXXXXXX----XXX = XXXXXXXXXX----
dc h'8380' ; -----XX------- = XX------------
dc h'8380' ; -----XX------- = XX------------
dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
dc h'8080' ; -------------- = --------------
font26 anop
dc h'8080' ; -------------- = --------------
dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
dc h'8380' ; -----XX------- = XX------------
dc h'FF87' ; XXXXXXX----XXX = XXXXXXXXXX----
dc h'8380' ; -----XX------- = XX------------
dc h'8380' ; -----XX------- = XX------------
dc h'8380' ; -----XX------- = XX------------
dc h'8080' ; -------------- = --------------
font27 anop
dc h'8080' ; -------------- = --------------
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8380' ; -----XX------- = XX------------
dc h'C39F' ; X----XX--XXXXX = XX----XXXXXX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8080' ; -------------- = --------------
font28 anop
dc h'8080' ; -------------- = --------------
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8080' ; -------------- = --------------
font29 anop
dc h'8080' ; -------------- = --------------
dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
dc h'8080' ; -------------- = --------------
font2A anop
dc h'8080' ; -------------- = --------------
dc h'8098' ; ---------XX--- = ----------XX--
dc h'8098' ; ---------XX--- = ----------XX--
dc h'8098' ; ---------XX--- = ----------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8080' ; -------------- = --------------
font2B anop
dc h'8080' ; -------------- = --------------
dc h'8386' ; -----XX----XX- = XX------XX----
dc h'C381' ; X----XX------X = XX----XX------
dc h'BF80' ; -XXXXXX------- = XXXXXX--------
dc h'C381' ; X----XX------X = XX----XX------
dc h'8386' ; -----XX----XX- = XX------XX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8080' ; -------------- = --------------
font2C anop
dc h'8080' ; -------------- = --------------
dc h'8380' ; -----XX------- = XX------------
dc h'8380' ; -----XX------- = XX------------
dc h'8380' ; -----XX------- = XX------------
dc h'8380' ; -----XX------- = XX------------
dc h'8380' ; -----XX------- = XX------------
dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
dc h'8080' ; -------------- = --------------
font2D anop
dc h'8080' ; -------------- = --------------
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8F9E' ; ---XXXX--XXXX- = XXXX----XXXX--
dc h'F399' ; XXX--XX--XX--X = XX--XXXX--XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8080' ; -------------- = --------------
font2E anop
dc h'8080' ; -------------- = --------------
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8F98' ; ---XXXX--XX--- = XXXX------XX--
dc h'B398' ; -XX--XX--XX--- = XX--XX----XX--
dc h'C399' ; X----XX--XX--X = XX----XX--XX--
dc h'839E' ; -----XX--XXXX- = XX------XXXX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8080' ; -------------- = --------------
font2F anop
dc h'8080' ; -------------- = --------------
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8080' ; -------------- = --------------
font30 anop
dc h'8080' ; -------------- = --------------
dc h'FF87' ; XXXXXXX----XXX = XXXXXXXXXX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FF87' ; XXXXXXX----XXX = XXXXXXXXXX----
dc h'8380' ; -----XX------- = XX------------
dc h'8380' ; -----XX------- = XX------------
dc h'8080' ; -------------- = --------------
font31 anop
dc h'8080' ; -------------- = --------------
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'B398' ; -XX--XX--XX--- = XX--XX----XX--
dc h'C399' ; X----XX--XX--X = XX----XX--XX--
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8080' ; -------------- = --------------
font32 anop
dc h'8080' ; -------------- = --------------
dc h'FF87' ; XXXXXXX----XXX = XXXXXXXXXX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FF87' ; XXXXXXX----XXX = XXXXXXXXXX----
dc h'8386' ; -----XX----XX- = XX------XX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8080' ; -------------- = --------------
font33 anop
dc h'8080' ; -------------- = --------------
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8380' ; -----XX------- = XX------------
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8098' ; ---------XX--- = ----------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8080' ; -------------- = --------------
font34 anop
dc h'8080' ; -------------- = --------------
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'8080' ; -------------- = --------------
font35 anop
dc h'8080' ; -------------- = --------------
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'8080' ; -------------- = --------------
font36 anop
dc h'8080' ; -------------- = --------------
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8C86' ; ---XX------XX- = --XX----XX----
dc h'F081' ; XXX----------X = ----XXXX------
dc h'8080' ; -------------- = --------------
font37 anop
dc h'8080' ; -------------- = --------------
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'F399' ; XXX--XX--XX--X = XX--XXXX--XX--
dc h'8C86' ; ---XX------XX- = --XX----XX----
dc h'8080' ; -------------- = --------------
font38 anop
dc h'8080' ; -------------- = --------------
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8C86' ; ---XX------XX- = --XX----XX----
dc h'F081' ; XXX----------X = ----XXXX------
dc h'F081' ; XXX----------X = ----XXXX------
dc h'8C86' ; ---XX------XX- = --XX----XX----
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8080' ; -------------- = --------------
font39 anop
dc h'8080' ; -------------- = --------------
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'8C98' ; ---XX----XX--- = --XX------XX--
dc h'B086' ; -XX--------XX- = ----XX--XX----
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'8080' ; -------------- = --------------
font3A anop
dc h'8080' ; -------------- = --------------
dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
dc h'8086' ; -----------XX- = --------XX----
dc h'C081' ; X------------X = ------XX------
dc h'B080' ; -XX----------- = ----XX--------
dc h'8C80' ; ---XX--------- = --XX----------
dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
dc h'8080' ; -------------- = --------------
; font3B:
; dc h'8080' ; -------------- = --------------
; dc h'C09F' ; X--------XXXXX = ------XXXXXX--
; dc h'C081' ; X------------X = ------XX------
; dc h'C081' ; X------------X = ------XX------
; dc h'C081' ; X------------X = ------XX------
; dc h'C081' ; X------------X = ------XX------
; dc h'C09F' ; X--------XXXXX = ------XXXXXX--
; dc h'8080' ; -------------- = --------------
; font3C:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8380' ; -----XX------- = XX------------
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'C081' ; X------------X = ------XX------
; dc h'8086' ; -----------XX- = --------XX----
; dc h'8080' ; -------------- = --------------
; font3D:
; dc h'8080' ; -------------- = --------------
; dc h'BF80' ; -XXXXXX------- = XXXXXX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'BF80' ; -XXXXXX------- = XXXXXX--------
; dc h'8080' ; -------------- = --------------
; font3E:
; dc h'8080' ; -------------- = --------------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'FC81' ; XXXXX--------X = --XXXXXX------
; dc h'B386' ; -XX--XX----XX- = XX--XX--XX----
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'8080' ; -------------- = --------------
; font3F:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
; font40:
; dc h'8080' ; -------------- = --------------
; dc h'F087' ; XXX--------XXX = ----XXXXXX----
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'FF81' ; XXXXXXX------X = XXXXXXXX------
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
; dc h'8080' ; -------------- = --------------
; font41:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'F087' ; XXX--------XXX = ----XXXXXX----
; dc h'8098' ; ---------XX--- = ----------XX--
; dc h'F09F' ; XXX------XXXXX = ----XXXXXXXX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'F09F' ; XXX------XXXXX = ----XXXXXXXX--
; dc h'8080' ; -------------- = --------------
; font42:
; dc h'8080' ; -------------- = --------------
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
; dc h'8080' ; -------------- = --------------
; font43:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'F087' ; XXX--------XXX = ----XXXXXX----
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'F087' ; XXX--------XXX = ----XXXXXX----
; dc h'8080' ; -------------- = --------------
; font44:
; dc h'8080' ; -------------- = --------------
; dc h'8098' ; ---------XX--- = ----------XX--
; dc h'8098' ; ---------XX--- = ----------XX--
; dc h'F09F' ; XXX------XXXXX = ----XXXXXXXX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'F09F' ; XXX------XXXXX = ----XXXXXXXX--
; dc h'8080' ; -------------- = --------------
; font45:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'F087' ; XXX--------XXX = ----XXXXXX----
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'F087' ; XXX--------XXX = ----XXXXXX----
; dc h'8080' ; -------------- = --------------
; font46:
; dc h'8080' ; -------------- = --------------
; dc h'C087' ; X----------XXX = ------XXXX----
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'F081' ; XXX----------X = ----XXXX------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'8080' ; -------------- = --------------
; font47:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'F09F' ; XXX------XXXXX = ----XXXXXXXX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'F09F' ; XXX------XXXXX = ----XXXXXXXX--
; dc h'8098' ; ---------XX--- = ----------XX--
; dc h'F087' ; XXX--------XXX = ----XXXXXX----
; font48:
; dc h'8080' ; -------------- = --------------
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8080' ; -------------- = --------------
; font49:
; dc h'8080' ; -------------- = --------------
; dc h'C081' ; X------------X = ------XX------
; dc h'8080' ; -------------- = --------------
; dc h'F081' ; XXX----------X = ----XXXX------
; dc h'C081' ; X------------X = ------XX------
; dc h'C081' ; X------------X = ------XX------
; dc h'F087' ; XXX--------XXX = ----XXXXXX----
; dc h'8080' ; -------------- = --------------
; font4A:
; dc h'8080' ; -------------- = --------------
; dc h'8086' ; -----------XX- = --------XX----
; dc h'8080' ; -------------- = --------------
; dc h'8086' ; -----------XX- = --------XX----
; dc h'8086' ; -----------XX- = --------XX----
; dc h'8086' ; -----------XX- = --------XX----
; dc h'8C86' ; ---XX------XX- = --XX----XX----
; dc h'F081' ; XXX----------X = ----XXXX------
; font4B:
; dc h'8080' ; -------------- = --------------
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'CC81' ; X--XX--------X = --XX--XX------
; dc h'BC80' ; -XXXX--------- = --XXXX--------
; dc h'BC80' ; -XXXX--------- = --XXXX--------
; dc h'CC81' ; X--XX--------X = --XX--XX------
; dc h'8C86' ; ---XX------XX- = --XX----XX----
; dc h'8080' ; -------------- = --------------
; font4C:
; dc h'8080' ; -------------- = --------------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'C087' ; X----------XXX = ------XXXX----
; dc h'8080' ; -------------- = --------------
; font4D:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'BC86' ; -XXXX------XX- = --XXXX--XX----
; dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
; dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
; dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
; dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
; dc h'8080' ; -------------- = --------------
; font4E:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8080' ; -------------- = --------------
; font4F:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'F087' ; XXX--------XXX = ----XXXXXX----
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'F087' ; XXX--------XXX = ----XXXXXX----
; dc h'8080' ; -------------- = --------------
; font50:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'8C80' ; ---XX--------- = --XX----------
; font51:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
; dc h'8386' ; -----XX----XX- = XX------XX----
; dc h'8386' ; -----XX----XX- = XX------XX----
; dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
; dc h'8086' ; -----------XX- = --------XX----
; dc h'8098' ; ---------XX--- = ----------XX--
; font52:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'F087' ; XXX--------XXX = ----XXXXXX----
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'8080' ; -------------- = --------------
; font53:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'F087' ; XXX--------XXX = ----XXXXXX----
; dc h'8C80' ; ---XX--------- = --XX----------
; dc h'F087' ; XXX--------XXX = ----XXXXXX----
; dc h'8098' ; ---------XX--- = ----------XX--
; dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
; dc h'8080' ; -------------- = --------------
; font54:
; dc h'8080' ; -------------- = --------------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'FC81' ; XXXXX--------X = --XXXXXX------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'C087' ; X----------XXX = ------XXXX----
; dc h'8080' ; -------------- = --------------
; font55:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'F087' ; XXX--------XXX = ----XXXXXX----
; dc h'8080' ; -------------- = --------------
; font56:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'B086' ; -XX--------XX- = ----XX--XX----
; dc h'B086' ; -XX--------XX- = ----XX--XX----
; dc h'C081' ; X------------X = ------XX------
; dc h'8080' ; -------------- = --------------
; font57:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
; dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
; dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
; dc h'B086' ; -XX--------XX- = ----XX--XX----
; dc h'8080' ; -------------- = --------------
; font58:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'B086' ; -XX--------XX- = ----XX--XX----
; dc h'C081' ; X------------X = ------XX------
; dc h'B086' ; -XX--------XX- = ----XX--XX----
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8080' ; -------------- = --------------
; font59:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'8C98' ; ---XX----XX--- = --XX------XX--
; dc h'F09F' ; XXX------XXXXX = ----XXXXXXXX--
; dc h'8098' ; ---------XX--- = ----------XX--
; dc h'F087' ; XXX--------XXX = ----XXXXXX----
; font5A:
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
; dc h'8086' ; -----------XX- = --------XX----
; dc h'C081' ; X------------X = ------XX------
; dc h'B080' ; -XX----------- = ----XX--------
; dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
; dc h'8080' ; -------------- = --------------
; font5B:
; dc h'8080' ; -------------- = --------------
; dc h'809E' ; ---------XXXX- = --------XXXX--
; dc h'C081' ; X------------X = ------XX------
; dc h'BC80' ; -XXXX--------- = --XXXX--------
; dc h'C081' ; X------------X = ------XX------
; dc h'C081' ; X------------X = ------XX------
; dc h'809E' ; ---------XXXX- = --------XXXX--
; dc h'8080' ; -------------- = --------------
; font5C:
; dc h'8080' ; -------------- = --------------
; dc h'C081' ; X------------X = ------XX------
; dc h'C081' ; X------------X = ------XX------
; dc h'C081' ; X------------X = ------XX------
; dc h'C081' ; X------------X = ------XX------
; dc h'C081' ; X------------X = ------XX------
; dc h'C081' ; X------------X = ------XX------
; dc h'8080' ; -------------- = --------------
; font5D:
; dc h'8080' ; -------------- = --------------
; dc h'BC80' ; -XXXX--------- = --XXXX--------
; dc h'C081' ; X------------X = ------XX------
; dc h'809E' ; ---------XXXX- = --------XXXX--
; dc h'C081' ; X------------X = ------XX------
; dc h'C081' ; X------------X = ------XX------
; dc h'BC80' ; -XXXX--------- = --XXXX--------
; dc h'8080' ; -------------- = --------------
; font5E:
; dc h'8080' ; -------------- = --------------
; dc h'B086' ; -XX--------XX- = ----XX--XX----
; dc h'CC81' ; X--XX--------X = --XX--XX------
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
; dc h'8080' ; -------------- = --------------
font5F anop
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'8C98' ; ---XX----XX--- = --XX------XX--
dc h'C3E1' ; X----XXXX----X = XX----XX----XX
dc h'B3E0' ; -XX--XXXX----- = XX--XX------XX
dc h'B3E0' ; -XX--XXXX----- = XX--XX------XX
dc h'C3E1' ; X----XXXX----X = XX----XX----XX
dc h'8C98' ; ---XX----XX--- = --XX------XX--
dc h'F087' ; XXX--------XXX = ----XXXXXX----
end

585
src/rolevels.asm Normal file
View File

@ -0,0 +1,585 @@
;-----------------------------------------------------------------------------
; rolevels.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
ROLEVELS data
using LOWMEM
level_01 anop
dc h'1A4014601E602F40F204FF002F40F204'
dc h'F700135013502D41417148712F40F204'
dc h'3F10C204F1003140195024413F035330'
dc h'2F40D2012F40F204B105730453712440'
dc h'FB102F40F204FF110104'
dc h'00'
level_02 anop
dc h'1F403E04FE001264FF002F4053071610'
dc h'2F40F204F41181042204F50041142174'
dc h'22041517F300124012402F4091042174'
dc h'22048701910421742204F30042701247'
dc h'124022404F30310421742204D4017104'
dc h'217422047407F4002F40F204FF110104'
dc h'00'
level_03 anop
dc h'19401760182013602F402106C204FF00'
dc h'2F40F204FF002441FB772F40F2046F10'
dc h'54012142FE0021424603F4002142F800'
dc h'62141C605C1024406F105204F500A214'
dc h'FF002F41F114'
dc h'00'
level_04 anop
dc h'16401660F444FF002F40F204F3006610'
dc h'2F40B401214151019101D204B2017301'
dc h'72043F70C2046201F20032102F402301'
dc h'A2043F30B1012B403710361025402F10'
dc h'14603214F2002B102F40F204FF110104'
dc h'00'
level_05 anop
dc h'1F404106A204FF002F40F204FF002F40'
dc h'81056204D41046713204FD002214F500'
dc h'19502F402A0332043A01F2002F40F204'
dc h'2B714701510127401F40720425101540'
dc h'12401D40244012501540124072455204'
dc h'7F1417410104'
dc h'00'
level_06 anop
dc h'1F40F204FF002F40F204FF002F405106'
dc h'920473014201450152042201B104B301'
dc h'2F401E402F40750132042F10D2046901'
dc h'19415204F1041D6022401C501B403214'
dc h'2403F2017204FF002F41F114'
dc h'00'
level_07 anop
dc h'1D40F444FF002F40F204E2011C471204'
dc h'F1001D47264052303114A17622743D10'
dc h'12471A072F401104917032741F101547'
dc h'17672D403114D274B510114718071267'
dc h'2F401104C1702D404547176728403210'
dc h'1F401204D104F1002D41F344'
dc h'00'
level_08 anop
dc h'11401760166012401A402F4011042104'
dc h'A204E2011B402214F1001D402F401104'
dc h'D204351062101241B204F10013404510'
dc h'12141301C1049101320473016104D204'
dc h'F100154182041A103210194042148201'
dc h'6104D2043201B10445014204A3031240'
dc h'1241B204D104210451057204FF110104'
dc h'00'
level_09 anop
dc h'12401F40C204FF002F40F204FF002F40'
dc h'F204421032108210321022102F40F204'
dc h'FD002214220123012803B204F6003210'
dc h'22102241FD002F40F204220123012801'
dc h'230122012204FD002214FF002F41F114'
dc h'00'
level_10 anop
dc h'1A401160311411061106A214F1044106'
dc h'920469101A4042142106C104E204F104'
dc h'4A1027401717164082144B101E402F40'
dc h'174134702541A104E20417607114C201'
dc h'24412970174161062F40164013674204'
dc h'7A02D2043F1093012F40F104FF220202'
dc h'00'
level_11 anop
dc h'7C401B602F403105B204FF002441FB00'
dc h'2F40F2044601420172215204F8001460'
dc h'2214F800166022412203F20014602214'
dc h'A90141056204B1066106810122045307'
dc h'121016601B502B401F5032142F105301'
dc h'5204FF002F41F114'
dc h'00'
level_12 anop
dc h'114017601660134019402F40F204E207'
dc h'E204FF002F40F2043510517421046271'
dc h'5204D1042104C1012540261012401D40'
dc h'22401A10124017406214940112401D40'
dc h'25401A101341A204F100174024102641'
dc h'A104510541052204A30112401B432204'
dc h'D1042104D204D414D114'
dc h'00'
level_13 anop
dc h'FF4432401F20C2042102FC0022401320'
dc h'F311240122401F20C2042102FC002240'
dc h'1320221042105210421012142102FC00'
dc h'22401F20C20421023501230135012401'
dc h'22401F20C2042102FC00224013203210'
dc h'32104210421022142102FC0022401F20'
dc h'C2042F13B2310104'
dc h'00'
level_14 anop
dc h'1F40F204FF002F40F204FF002F40F204'
dc h'E1011E20224011126101162011126101'
dc h'122026401112E10116202F40F2044101'
dc h'162011126101162011122F40F2041112'
dc h'61011420643011124204FF0026401112'
dc h'F7002F40FF04F344'
dc h'00'
level_15 anop
dc h'1540FC44FD002224FD0022247F031531'
dc h'22247106F400126225412105F4001262'
dc h'2F4082012106222461074201E1062224'
dc h'2201D20181062224F900211012622241'
dc h'9201E1052224F200291022244301F201'
dc h'42022B402F102224FD002224FF110104'
dc h'00'
level_16 anop
dc h'1F40F204FF002F40F204FF002F40F204'
dc h'141014101240174036102A4012402F40'
dc h'23401610124038406214A1042404D204'
dc h'2F7394302F40F20492042C1014102941'
dc h'F6002F40410151014204F70035502F41'
dc h'F114'
dc h'00'
level_17 anop
dc h'1F40D404FF002F40F204FF0025401250'
dc h'13501250155011501650224172707270'
dc h'31702270221421766270727062702274'
dc h'92703170327051762207224725072207'
dc h'52306270227411072507270726072207'
dc h'22472507270712071467220722472407'
dc h'1260E370227422705270F2702274FF00'
dc h'2F40B4012F41F114'
dc h'00'
level_18 anop
dc h'1F40C1042204FF002F40F204FF002F40'
dc h'F204220123012801230124012F40F204'
dc h'2F10D204B80123012201220422012301'
dc h'F6002F40D2012F40F204220123012801'
dc h'2301220122042F10D204FF001F41F211'
dc h'00'
level_19 anop
dc h'3F40D204FF002F40F204FF002F40F204'
dc h'2201460197012F40F204F30039102241'
dc h'A30187012F40F204F3002A102441F400'
dc h'721464033501C204FF004F40D404F511'
dc h'17410104'
dc h'00'
level_20 anop
dc h'FF00FF00FF00FF00FB00EF4031042104'
dc h'9104F30012401940F54421049204FD00'
dc h'2214FF002F4373301470284012501450'
dc h'1350165012102241FD0024402F109204'
dc h'FF002F41F114'
dc h'00'
;-----------------------------------------------------------------------------
levelsL anop
dc i1<'level_01',i1<'level_02',i1<'level_03',i1<'level_04',i1<'level_05',i1<'level_06'
dc i1<'level_07',i1<'level_08',i1<'level_09',i1<'level_10',i1<'level_11',i1<'level_12'
dc i1<'level_13',i1<'level_14',i1<'level_15',i1<'level_16',i1<'level_17',i1<'level_18'
dc i1<'level_19',i1<'level_20'
levelsH anop
dc i1>'level_01',i1>'level_02',i1>'level_03',i1>'level_04',i1>'level_05',i1>'level_06'
dc i1>'level_07',i1>'level_08',i1>'level_09',i1>'level_10',i1>'level_11',i1>'level_12'
dc i1>'level_13',i1>'level_14',i1>'level_15',i1>'level_16',i1>'level_17',i1>'level_18'
dc i1>'level_19',i1>'level_20'
;-----------------------------------------------------------------------------
; This table maps tiles (1-8) to tile representations, per level.
; space is 00, floor1 is 1 and collapse is 7 & key is 8. Only 0 through 7
; encoded in the level data. Key, door and switch added programatically to
; the level. The switch looks the same in both kong levels (only place it
; is present) so it doesn't need/get an entry. The door "tile" isn't seen,
; so isn't rendered. It's below the door sprite for collision purposes only.
;
; floor1, floor2, conveyor, wall, bush, rock, collapse, key - door & switch not here
levelTiles anop
dc h'31001C1F0D282709' ; Level 1
dc h'31001C1F0D282710' ; Level 2
dc h'2E031E150D052D09' ; Level 3
dc h'31001C1F0D342709' ; Level 4
dc h'3100071F0D132708' ; Level 5
dc h'2F001C1F0D0B3109' ; Level 6
dc h'3100161F0D172609' ; Level 7
dc h'31351D1F0D132714' ; Level 8
dc h'310007180D132709' ; Level 9
dc h'12301C1B0D0F2001' ; Level 10
dc h'3133211A0403270A' ; Level 11
dc h'31351D1F0D132714' ; Level 12
dc h'292307180D133106' ; Level 13
dc h'2C2B072200003119' ; Level 14
dc h'322A211A04032711' ; Level 15
dc h'31311D1B0E132702' ; Level 16
dc h'31001C250D0C2609' ; Level 17
dc h'31001C240D132709' ; Level 18
dc h'31001C1F0D132709' ; Level 19
dc h'31001C1F04132709' ; Level 20
; This table says which color index to use, to color a
; tile (1-8), per level. The colors are:
; 00 White - 01 Green - 02 Orange - 03 Purple - 04 Blue
; The keys are done as a color animation so at inctance
; time they are left white.
;
; floor1, floor2, conveyor, wall, bush, rock, collapse, key - door & switch not here
levelMasks anop
dc h'0102030201020400' ; Level 1
dc h'0302030201020400' ; Level 2
dc h'0400030401030100' ; Level 3
dc h'0200030401000400' ; Level 4
dc h'0402020100020100' ; Level 5
dc h'0100040201000400' ; Level 6
dc h'0302010401000200' ; Level 7
dc h'0200010001020400' ; Level 8
dc h'0302010201020400' ; Level 9
dc h'0100010201010200' ; Level 10
dc h'0400030202000100' ; Level 11
dc h'0300000201020400' ; Level 12
dc h'0403010201020400' ; Level 13
dc h'0403000401020400' ; Level 14
dc h'0402000002000400' ; Level 15
dc h'0203000301020400' ; Level 16
dc h'0102010201000400' ; Level 17
dc h'0202030301020400' ; Level 18
dc h'0102000201020400' ; Level 19
dc h'0202040100020400' ; Level 20
; The number of bytes to skip when calling a tileDrawP*R* routine for a collapsing platform
collapseHeight anop
dc i1'12*0, 12*1, 12*2, 12*3, 12*4, 12*5, 12*6, 12*7'
conveyorDirections anop
dc h'0201020102020201010202010102'
dc h'020201020201'
skylabXPos anop
dc h'01150B091D131105'
dc h'1B190D03'
willyx anop
dc h'0202021D010F0202'
dc h'010103021D1D0202'
dc h'011D0E1B0F'
willyy anop
dc h'6868686818186868'
dc h'6820086868686868'
dc h'1868506858'
willyStartDir anop
dc h'0000000100010000000000000000'
dc h'00000101000100'
doorL anop
dc i1<'levelLayout+$1BE' ; level 0
dc i1<'levelLayout+$1DE' ; level 1
dc i1<'levelLayout+$17E' ; level 2
dc i1<'levelLayout+$03E' ; level 3
dc i1<'levelLayout+$1CF' ; level 4
dc i1<'levelLayout+$01E' ; level 5
dc i1<'levelLayout+$1CF' ; level 6
dc i1<'levelLayout+$1CF' ; level 7
dc i1<'levelLayout+$001' ; level 8
dc i1<'levelLayout+$1CC' ; level 9
dc i1<'levelLayout+$021' ; level 10
dc i1<'levelLayout+$1CF' ; level 11
dc i1<'levelLayout+$1C1' ; level 12
dc i1<'levelLayout+$010' ; level 13
dc i1<'levelLayout+$061' ; level 14
dc i1<'levelLayout+$0CC' ; level 15
dc i1<'levelLayout+$03E' ; level 16
dc i1<'levelLayout+$03E' ; level 17
dc i1<'levelLayout+$041' ; level 18
dc i1<'levelLayout+$0B3' ; level 19
doorH anop
dc i1>'levelLayout+$1BE' ; level 0
dc i1>'levelLayout+$1DE' ; level 1
dc i1>'levelLayout+$17E' ; level 2
dc i1>'levelLayout+$03E' ; level 3
dc i1>'levelLayout+$1CF' ; level 4
dc i1>'levelLayout+$01E' ; level 5
dc i1>'levelLayout+$1CF' ; level 6
dc i1>'levelLayout+$1CF' ; level 7
dc i1>'levelLayout+$001' ; level 8
dc i1>'levelLayout+$1CC' ; level 9
dc i1>'levelLayout+$021' ; level 10
dc i1>'levelLayout+$1CF' ; level 11
dc i1>'levelLayout+$1C1' ; level 12
dc i1>'levelLayout+$010' ; level 13
dc i1>'levelLayout+$061' ; level 14
dc i1>'levelLayout+$0CC' ; level 15
dc i1>'levelLayout+$03E' ; level 16
dc i1>'levelLayout+$03E' ; level 17
dc i1>'levelLayout+$041' ; level 18
dc i1>'levelLayout+$0B3' ; level 19
door_color1 anop
dc h'0103010203040102'
dc h'0304000101010101'
dc h'0101010101'
door_color2 anop
dc h'0204040302010102'
dc h'0304010202020202'
dc h'0202020202'
keyx anop
dc h'091D10181E'
dc h'07181A0313'
dc h'060F171E15'
dc h'010C19101E'
dc h'1E0A1D0709'
dc h'0F111E010D'
dc h'1E141B131E'
dc h'0D0E021DFF'
dc h'10FFFFFFFF'
dc h'150E0C121E'
dc h'181E01131E'
dc h'0F10021D1A'
dc h'1A0A131A0B'
dc h'17031B10FF'
dc h'190C1AFFFF'
dc h'1E0D0111FF'
dc h'180F01131A'
dc h'10FFFFFFFF'
dc h'1E011EFFFF'
dc h'171E0A0E13'
keyyL anop
dc h'00002080C0'
dc h'2020E02080'
dc h'000000C0C0'
dc h'002020C0C0'
dc h'20C0E08080'
dc h'C0C0E04060'
dc h'60C0E04060'
dc h'40C000A0E0'
dc h'20E0E0E0E0'
dc h'4020C00020'
dc h'002080C0A0'
dc h'60E0C0A0A0'
dc h'60C0202080'
dc h'4000E0E0E0'
dc h'40C0C0E0E0'
dc h'40E00040E0'
dc h'A0E0204060'
dc h'20E0E0E0E0'
dc h'20A080E0E0'
dc h'A0C0606060'
keyyH anop
dc h'0000000000'
dc h'0000000101'
dc h'0000000000'
dc h'0000000000'
dc h'0000000101'
dc h'0000000101'
dc h'0000000101'
dc h'00000101FF'
dc h'00FFFFFFFF'
dc h'0000000100'
dc h'0000000001'
dc h'0000000100'
dc h'0000010101'
dc h'00010000FF'
dc h'000001FFFF'
dc h'00000001FF'
dc h'0000010101'
dc h'00FFFFFFFF'
dc h'000001FFFF'
dc h'0000010101'
sprites_x anop
dc h'081D121D1D131012'
dc h'1D01071D0C040F0F'
dc h'060E08181D0F0A11'
dc h'0F090B120F0F0C10'
dc h'050A141901090C08'
dc h'120C0F0E0F0C0315'
dc h'1A01090B190F0F07'
dc h'1014120501000000'
dc h'0F11090F15010901'
dc h'121A0C050C030A13'
dc h'1B1D0C101010050A'
dc h'14191D181C1D1005'
dc h'0B1001071813130F'
dc h'0F'
sprites_y anop
dc h'3868186868681818'
dc h'5868680818380168'
dc h'4040686800084068'
dc h'6868583800681850'
dc h'0808080800385068'
dc h'2868183868082030'
dc h'3008685830006808'
dc h'2038500868000000'
dc h'0068284050186850'
dc h'3828286868404030'
dc h'0008185030680808'
dc h'0808001830486840'
dc h'3850086830282800'
dc h'68'
sprites_min anop
dc h'081D010C1D010112'
dc h'1D01061D0104010F'
dc h'060E08181D0F0211'
dc h'0F010B12000F0C0C'
dc h'0505050501090804'
dc h'110C0F0E05022030'
dc h'0401010B19000F07'
dc h'070A070801000000'
dc h'0F11242420010101'
dc h'12190C050C400301'
dc h'041D0C0C0C0C0505'
dc h'05051D1716170D02'
dc h'3004010728131300'
dc h'0F'
sprites_max anop
dc h'101E131E1E14111E'
dc h'1E0B101E0D0D5810'
dc h'0E16151E1E1E0B1E'
dc h'100A101600101313'
dc h'65656565020F0F1B'
dc h'160D191314396565'
dc h'65020A101D00101E'
dc h'1E1B1E6502493921'
dc h'1014676769021308'
dc h'181E0D091A676141'
dc h'611E131212136969'
dc h'69691E1E1E1E1E67'
dc h'6751021768141459'
dc h'10'
sprites_speed anop
dc h'0204020204020202'
dc h'0402020402020104'
dc h'0202020204020202'
dc h'0402010204040201'
dc h'0102010204020102'
dc h'0204020102020101'
dc h'0204020102040402'
dc h'0102010204030201'
dc h'0402020102040202'
dc h'0201040102020201'
dc h'0404010102020302'
dc h'0401040202010203'
dc h'0201040201040402'
dc h'04'
sprites_dir anop
dc h'0000010100010100'
dc h'0000000001000000'
dc h'0001010100000100'
dc h'0001000000000000'
dc h'0000000000000000'
dc h'0000000001000000'
dc h'0100010000000000'
dc h'0001000000000000'
dc h'0000000001000000'
dc h'0000000000000100'
dc h'0000000000010000'
dc h'0000000000010000'
dc h'0100000000000000'
dc h'00'
sprites_bitmaps anop
dc h'0093090994121212'
dc h'951A1A9623232297'
dc h'2B2B2B2B98333333'
dc h'993F3F3F3B9A4747'
dc h'434343439B4B4B4B'
dc h'4B9C575757535353'
dc h'539D3F3F3F3B9E5F'
dc h'5F5F5F5B9F636363'
dc h'A06F6B6B6BA17373'
dc h'7373A27F7F7B7B7B'
dc h'7BA3474747478383'
dc h'8383A48B8B8B8B87'
dc h'8787A58F5BA6A711'
dc h'08'
sprites_colors anop
dc h'0200020400010302'
dc h'0002010002000000'
dc h'0203040200040302'
dc h'0001030401000104'
dc h'0301040200020003'
dc h'0400020100030102'
dc h'0400010204010003'
dc h'0102040000000204'
dc h'0004020001000102'
dc h'0304000004040200'
dc h'0300010403020301'
dc h'0400000004030000'
dc h'0204000200000400'
dc h'00'
sprites_class anop
dc h'0082000082000000'
dc h'8200008200001382'
dc h'0000000082000000'
dc h'820206022B820202'
dc h'0303030382000000'
dc h'0082020202030303'
dc h'03820206022B8202'
dc h'0202020382494949'
dc h'8202030303820000'
dc h'0000820202030303'
dc h'0382020202020303'
dc h'0303820202020203'
dc h'0303820203820019'
dc h'82'
level_sprites_offset anop
dc h'000205090C101519'
dc h'1E252A32373D4146'
dc h'4B525B6367'
level_sprites_count anop
dc h'0203040304050405'
dc h'0705080506040505'
dc h'0709080402'
end

3212
src/rosprites.asm Normal file

File diff suppressed because it is too large Load Diff

304
src/rosystem.asm Normal file
View File

@ -0,0 +1,304 @@
;-----------------------------------------------------------------------------
; rosystem.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
ROSYSTEM data
;-----------------------------------------------------------------------------
; the lo byte for the memory at the start of every screen row
rowL anop
; .repeat $C0, Row
; .byte Row & $08 << 4 | Row & $C0 >> 1 | Row & $C0 >> 3
; .endrep
dc h'00000000'
dc h'00000000'
dc h'80808080'
dc h'80808080'
dc h'00000000'
dc h'00000000'
dc h'80808080'
dc h'80808080'
dc h'00000000'
dc h'00000000'
dc h'80808080'
dc h'80808080'
dc h'00000000'
dc h'00000000'
dc h'80808080'
dc h'80808080'
dc h'28282828'
dc h'28282828'
dc h'A8A8A8A8'
dc h'A8A8A8A8'
dc h'28282828'
dc h'28282828'
dc h'A8A8A8A8'
dc h'A8A8A8A8'
dc h'28282828'
dc h'28282828'
dc h'A8A8A8A8'
dc h'A8A8A8A8'
dc h'28282828'
dc h'28282828'
dc h'A8A8A8A8'
dc h'A8A8A8A8'
dc h'50505050'
dc h'50505050'
dc h'D0D0D0D0'
dc h'D0D0D0D0'
dc h'50505050'
dc h'50505050'
dc h'D0D0D0D0'
dc h'D0D0D0D0'
dc h'50505050'
dc h'50505050'
dc h'D0D0D0D0'
dc h'D0D0D0D0'
dc h'50505050'
dc h'50505050'
dc h'D0D0D0D0'
dc h'D0D0D0D0'
;-----------------------------------------------------------------------------
; the hi byte for the memory at the start of every screen row
rowH anop
; .repeat $C0, Row
; .byte >$0000 | Row & $07 << 2 | Row & $30 >> 4
; .endrep
dc h'0004080C'
dc h'1014181C'
dc h'0004080C'
dc h'1014181C'
dc h'0105090D'
dc h'1115191D'
dc h'0105090D'
dc h'1115191D'
dc h'02060A0E'
dc h'12161A1E'
dc h'02060A0E'
dc h'12161A1E'
dc h'03070B0F'
dc h'13171B1F'
dc h'03070B0F'
dc h'13171B1F'
dc h'0004080C'
dc h'1014181C'
dc h'0004080C'
dc h'1014181C'
dc h'0105090D'
dc h'1115191D'
dc h'0105090D'
dc h'1115191D'
dc h'02060A0E'
dc h'12161A1E'
dc h'02060A0E'
dc h'12161A1E'
dc h'03070B0F'
dc h'13171B1F'
dc h'03070B0F'
dc h'13171B1F'
dc h'0004080C'
dc h'1014181C'
dc h'0004080C'
dc h'1014181C'
dc h'0105090D'
dc h'1115191D'
dc h'0105090D'
dc h'1115191D'
dc h'02060A0E'
dc h'12161A1E'
dc h'02060A0E'
dc h'12161A1E'
dc h'03070B0F'
dc h'13171B1F'
dc h'03070B0F'
dc h'13171B1F'
;-----------------------------------------------------------------------------
; Jump table for screen tile rendering, per row - unrolled loops
rowDrawL anop
dc s1<'tileDrawP0R0'
dc s1<'tileDrawP0R1'
dc s1<'tileDrawP0R2'
dc s1<'tileDrawP0R3'
dc s1<'tileDrawP0R4'
dc s1<'tileDrawP0R5'
dc s1<'tileDrawP0R6'
dc s1<'tileDrawP0R7'
dc s1<'tileDrawP0R8'
dc s1<'tileDrawP0R9'
dc s1<'tileDrawP0RA'
dc s1<'tileDrawP0RB'
dc s1<'tileDrawP0RC'
dc s1<'tileDrawP0RD'
dc s1<'tileDrawP0RE'
dc s1<'tileDrawP0RF'
dc s1<'tileDrawP1R0' ; Page 1
dc s1<'tileDrawP1R1'
dc s1<'tileDrawP1R2'
dc s1<'tileDrawP1R3'
dc s1<'tileDrawP1R4'
dc s1<'tileDrawP1R5'
dc s1<'tileDrawP1R6'
dc s1<'tileDrawP1R7'
dc s1<'tileDrawP1R8'
dc s1<'tileDrawP1R9'
dc s1<'tileDrawP1RA'
dc s1<'tileDrawP1RB'
dc s1<'tileDrawP1RC'
dc s1<'tileDrawP1RD'
dc s1<'tileDrawP1RE'
dc s1<'tileDrawP1RF'
rowDrawH anop
dc s1>'tileDrawP0R0'
dc s1>'tileDrawP0R1'
dc s1>'tileDrawP0R2'
dc s1>'tileDrawP0R3'
dc s1>'tileDrawP0R4'
dc s1>'tileDrawP0R5'
dc s1>'tileDrawP0R6'
dc s1>'tileDrawP0R7'
dc s1>'tileDrawP0R8'
dc s1>'tileDrawP0R9'
dc s1>'tileDrawP0RA'
dc s1>'tileDrawP0RB'
dc s1>'tileDrawP0RC'
dc s1>'tileDrawP0RD'
dc s1>'tileDrawP0RE'
dc s1>'tileDrawP0RF'
dc s1>'tileDrawP1R0' ; Page 1
dc s1>'tileDrawP1R1'
dc s1>'tileDrawP1R2'
dc s1>'tileDrawP1R3'
dc s1>'tileDrawP1R4'
dc s1>'tileDrawP1R5'
dc s1>'tileDrawP1R6'
dc s1>'tileDrawP1R7'
dc s1>'tileDrawP1R8'
dc s1>'tileDrawP1R9'
dc s1>'tileDrawP1RA'
dc s1>'tileDrawP1RB'
dc s1>'tileDrawP1RC'
dc s1>'tileDrawP1RD'
dc s1>'tileDrawP1RE'
dc s1>'tileDrawP1RF'
;-----------------------------------------------------------------------------
mult64H anop
;.repeat MAX_SPRITE_IFRAMES, Row
; .byte >(Row * 64)
;.endrep
dc h'00000000'
dc h'01010101'
dc h'02020202'
dc h'03030303'
dc h'04040404'
dc h'05050505'
dc h'06060606'
dc h'07070707'
dc h'08080808'
mult64L anop
;.repeat MAX_SPRITE_IFRAMES, Row
; dc s1<'(Row * 64)
;.endrep
dc h'004080C0'
dc h'004080C0'
dc h'004080C0'
dc h'004080C0'
dc h'004080C0'
dc h'004080C0'
dc h'004080C0'
dc h'004080C0'
dc h'004080C0'
mult32H anop
;.repeat 15, Row
; .byte >(Row * 32)
;.endrep
dc h'00000000'
dc h'00000000'
dc h'01010101'
dc h'010101'
mult32L anop
;.repeat 15, Row
; dc s1<'(Row * 32)
;.endrep
dc h'00204060'
dc h'80A0C0E0'
dc h'00204060'
dc h'80A0C0'
mult16 anop
;.repeat 9, Row
; .byte Row * 16
;.endrep
dc h'00102030'
dc h'40506070'
dc h'80'
mult8 anop
;.repeat 24, Row
; .byte Row * 8
;.endrep
dc h'00081018'
dc h'20283038'
dc h'40485058'
dc h'60687078'
dc h'80889098'
dc h'A0A8B0B8'
;-----------------------------------------------------------------------------
; color masks
masksLeft anop
dc b'11111111' ; 00 MSB-BITS-11..1 White
dc b'00101010' ; 01 0-BITS-01..0 Green
dc b'10101010' ; 04 1-BITS-01..0 Orange
dc b'01010101' ; 01 0-BITS-10..1 Purple
dc b'11010101' ; 02 1-BITS-10..1 Blue
masksRight anop
dc b'11111111' ; 00 MSB-BITS-11 White
dc b'01010101' ; 01 0-BITS-10..1 Green
dc b'11010101' ; 04 1-BITS-10..1 Orange
dc b'00101010' ; 01 0-BITS-01..0 Purple
dc b'10101010' ; 02 1-BITS-01..0 Blue
maskGreen anop
dc b'00101010 01010101' ; Green
maskOrange anop
dc b'10101010 11010101' ; Orange
maskGreenHi anop
dc b'00100000 01000000' ; Green
maskNewTip anop
dc b'01011111 00111111' ; White air graph tip (reversed order)
;-----------------------------------------------------------------------------
; sprite 32 to 64 byte bit-double helper table
binDouble anop
dc b'00000000'
dc b'00000011'
dc b'00001100'
dc b'00001111'
dc b'00110000'
dc b'00110011'
dc b'00111100'
dc b'00111111'
dc b'11000000'
dc b'11000011'
dc b'11001100'
dc b'11001111'
dc b'11110000'
dc b'11110011'
dc b'11111100'
dc b'11111111'
end

64
src/rotext.asm Normal file
View File

@ -0,0 +1,64 @@
;-----------------------------------------------------------------------------
; rotext.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
ROTEXT data
roTextLevel anop
dc c' CENTRAL CAVERN '
dc c' THE COLD ROOM '
dc c' THE MENAGERIE '
dc c' ABANDONED URANIUM WORKINGS '
dc c' EUGENE+S LAIR '
dc c' PROCESSING PLANT '
dc c' THE VAT '
dc c'MINER WILLY MEETS THE KONG BEAST'
dc c' WACKY AMOEBATRONS '
dc c' THE ENDORIAN FOREST '
dc c'ATTACK OF THE MUTANT TELEPHONES '
dc c' RETURN OF THE ALIEN KONG BEAST '
dc c' ORE REFINERY '
dc c' SKYLAB LANDING BAY '
dc c' THE BANK '
dc c' THE SIXTEENTH CAVERN '
dc c' THE WAREHOUSE '
dc c' AMOEBATRONS+ REVENGE '
dc c' SOLAR POWER GENERATOR '
dc c' THE FINAL BARRIER '
roTextAir anop
dc c'AIR '
roTextScore anop
dc c'SCORE'
roTextHighScore anop
dc c'HIGH'
roTextGame anop
dc c'GAME'
roTextOver anop
dc c'OVER'
roTextPressEnter anop
dc c'PRESS '
roTextEnter anop
dc c'ENTER TO START'
roTextAppleIIVersion anop
dc c' APPLE II V1.1A BY '
roTextend anop
dc c'STEFAN WESSELS, 2020'
roTextIntro anop
dc c'. . . . . . . MANIC MINER . . [ BUG-BYTE LTD. 1983 . . BY '
dc c'MATTHEW SMITH . . . Q, O * W, P = LEFT * RIGHT . . SPACE = JUMP . . M = MUSIC '
dc c'ON/OFF . . S = IN GAME SOUND ON/OFF . . B = MONOCHROME/COLOR . . '
dc c'C = LEVEL SCROLL MODE . . ESC = QUIT . . . GUIDE MINER WILLY THROUGH 20 LETHAL '
dc c'CAVERNS . . . . . . ',h'00'
roTextMono anop
dc c' MONO'
roTextColor anop
dc c'COLOR'
roTextCheatCode anop
dc c'6031769'
end

566
src/rotiles.asm Normal file
View File

@ -0,0 +1,566 @@
;-----------------------------------------------------------------------------
; rotiles.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
align $10
;-----------------------------------------------------------------------------
ROTILES data
;tiledata anop
tile00 anop
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
tile01 anop
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
dc h'F3FF' ; XXX--XXXXXXXXX = XX--XXXXXXXXXX
dc h'F3FF' ; XXX--XXXXXXXXX = XX--XXXXXXXXXX
dc h'83FE' ; -----XXXXXXXX- = XX------XXXXXX
dc h'8FE0' ; ---XXXXXX----- = XXXX--------XX
dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
tile02 anop
dc h'C0FF' ; X------XXXXXXX = ------XXXXXXXX
dc h'C0E1' ; X------XX----X = ------XX----XX
dc h'FCE7' ; XXXXX--XX--XXX = --XXXXXXXX--XX
dc h'8CFE' ; ---XX--XXXXXX- = --XX----XXXXXX
dc h'BF86' ; -XXXXXX----XX- = XXXXXX--XX----
dc h'F387' ; XXX--XX----XXX = XX--XXXXXX----
dc h'C381' ; X----XX------X = XX----XX------
dc h'FF81' ; XXXXXXX------X = XXXXXXXX------
tile03 anop
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
tile04 anop
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'CFF9' ; X--XXXXXXXX--X = XXXX--XX--XXXX
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'CFF9' ; X--XXXXXXXX--X = XXXX--XX--XXXX
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
dc h'C3E1' ; X----XXXX----X = XX----XX----XX
tile05 anop
dc h'C081' ; X------------X = ------XX------
dc h'CFF9' ; X--XXXXXXXX--X = XXXX--XX--XXXX
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'CFF9' ; X--XXXXXXXX--X = XXXX--XX--XXXX
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'8C98' ; ---XX----XX--- = --XX------XX--
dc h'8FF8' ; ---XXXXXXXX--- = XXXX------XXXX
dc h'B086' ; -XX--------XX- = ----XX--XX----
tile06 anop
dc h'C081' ; X------------X = ------XX------
dc h'BC9E' ; -XXXX----XXXX- = --XXXX--XXXX--
dc h'8C98' ; ---XX----XX--- = --XX------XX--
dc h'CFF9' ; X--XXXXXXXX--X = XXXX--XX--XXXX
dc h'8FE6' ; ---XXXXXX--XX- = XXXX----XX--XX
dc h'BC98' ; -XXXX----XX--- = --XXXX----XX--
dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
dc h'C081' ; X------------X = ------XX------
tile07 anop
dc h'C0FF' ; X------XXXXXXX = ------XXXXXXXX
dc h'8F9E' ; ---XXXX--XXXX- = XXXX----XXXX--
dc h'C0FF' ; X------XXXXXXX = ------XXXXXXXX
dc h'8F9E' ; ---XXXX--XXXX- = XXXX----XXXX--
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
tile08 anop
dc h'C0FF' ; X------XXXXXXX = ------XXXXXXXX
dc h'B0F8' ; -XX----XXXX--- = ----XX----XXXX
dc h'8CFE' ; ---XX--XXXXXX- = --XX----XXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'C3FF' ; X----XXXXXXXXX = XX----XXXXXXXX
dc h'C39F' ; X----XX--XXXXX = XX----XXXXXX--
dc h'C387' ; X----XX----XXX = XX----XXXX----
dc h'FF81' ; XXXXXXX------X = XXXXXXXX------
tile09 anop
dc h'F081' ; XXX----------X = ----XXXX------
dc h'8C86' ; ---XX------XX- = --XX----XX----
dc h'8386' ; -----XX----XX- = XX------XX----
dc h'C381' ; X----XX------X = XX----XX------
dc h'BC86' ; -XXXX------XX- = --XXXX--XX----
dc h'8098' ; ---------XX--- = ----------XX--
dc h'80E6' ; -------XX--XX- = --------XX--XX
dc h'8098' ; ---------XX--- = ----------XX--
tile0A anop
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'FC99' ; XXXXX----XX--X = --XXXXXX--XX--
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'BFE6' ; -XXXXXXXX--XX- = XXXXXX--XX--XX
dc h'BFE6' ; -XXXXXXXX--XX- = XXXXXX--XX--XX
dc h'BFE6' ; -XXXXXXXX--XX- = XXXXXX--XX--XX
dc h'FC99' ; XXXXX----XX--X = --XXXXXX--XX--
dc h'F087' ; XXX--------XXX = ----XXXXXX----
tile0B anop
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'C081' ; X------------X = ------XX------
dc h'F3E7' ; XXX--XXXX--XXX = XX--XXXXXX--XX
dc h'BFFE' ; -XXXXXXXXXXXX- = XXXXXX--XXXXXX
dc h'BFFE' ; -XXXXXXXXXXXX- = XXXXXX--XXXXXX
dc h'F3E7' ; XXX--XXXX--XXX = XX--XXXXXX--XX
dc h'C081' ; X------------X = ------XX------
dc h'F087' ; XXX--------XXX = ----XXXXXX----
tile0C anop
dc h'8C98' ; ---XX----XX--- = --XX------XX--
dc h'8FFE' ; ---XXXXXXXXXX- = XXXX----XXXXXX
dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
dc h'BCE6' ; -XXXX--XX--XX- = --XXXX--XX--XX
dc h'B39E' ; -XX--XX--XXXX- = XX--XX--XXXX--
dc h'FCE7' ; XXXXX--XX--XXX = --XXXXXXXX--XX
dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
dc h'8FFE' ; ---XXXXXXXXXX- = XXXX----XXXXXX
tile0D anop
dc h'8C86' ; ---XX------XX- = --XX----XX----
dc h'C081' ; X------------X = ------XX------
dc h'B380' ; -XX--XX------- = XX--XX--------
dc h'BCE0' ; -XXXX--XX----- = --XXXX------XX
dc h'B0E6' ; -XX----XX--XX- = ----XX--XX--XX
dc h'BF9E' ; -XXXXXX--XXXX- = XXXXXX--XXXX--
dc h'FC81' ; XXXXX--------X = --XXXXXX------
dc h'B080' ; -XX----------- = ----XX--------
tile0E anop
dc h'8C98' ; ---XX----XX--- = --XX------XX--
dc h'8C98' ; ---XX----XX--- = --XX------XX--
dc h'8C98' ; ---XX----XX--- = --XX------XX--
dc h'8C98' ; ---XX----XX--- = --XX------XX--
dc h'BCF8' ; -XXXX--XXXX--- = --XXXX----XXXX
dc h'BFFE' ; -XXXXXXXXXXXX- = XXXXXX--XXXXXX
dc h'BFFE' ; -XXXXXXXXXXXX- = XXXXXX--XXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
tile0F anop
dc h'8C86' ; ---XX------XX- = --XX----XX----
dc h'F399' ; XXX--XX--XX--X = XX--XXXX--XX--
dc h'CCE7' ; X--XX--XX--XXX = --XX--XXXX--XX
dc h'C099' ; X--------XX--X = ------XX--XX--
dc h'FC81' ; XXXXX--------X = --XXXXXX------
dc h'B39E' ; -XX--XX--XXXX- = XX--XX--XXXX--
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'8CF8' ; ---XX--XXXX--- = --XX------XXXX
tile10 anop
dc h'BC80' ; -XXXX--------- = --XXXX--------
dc h'C381' ; X----XX------X = XX----XX------
dc h'BC86' ; -XXXX------XX- = --XXXX--XX----
dc h'C381' ; X----XX------X = XX----XX------
dc h'BC86' ; -XXXX------XX- = --XXXX--XX----
dc h'C087' ; X----------XXX = ------XXXX----
dc h'8098' ; ---------XX--- = ----------XX--
dc h'80E0' ; -------XX----- = ------------XX
tile11 anop
dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'BC98' ; -XXXX----XX--- = --XXXX----XX--
dc h'CFFF' ; X--XXXXXXXXXXX = XXXX--XXXXXXXX
dc h'83FE' ; -----XXXXXXXX- = XX------XXXXXX
dc h'CFFF' ; X--XXXXXXXXXXX = XXXX--XXXXXXXX
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
tile12 anop
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'CFFF' ; X--XXXXXXXXXXX = XXXX--XXXXXXXX
dc h'F09F' ; XXX------XXXXX = ----XXXXXXXX--
dc h'C087' ; X----------XXX = ------XXXX----
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
tile13 anop
dc h'FCFF' ; XXXXX--XXXXXXX = --XXXXXXXXXXXX
dc h'F09F' ; XXX------XXXXX = ----XXXXXXXX--
dc h'C09F' ; X--------XXXXX = ------XXXXXX--
dc h'C087' ; X----------XXX = ------XXXX----
dc h'C087' ; X----------XXX = ------XXXX----
dc h'8086' ; -----------XX- = --------XX----
dc h'8086' ; -----------XX- = --------XX----
dc h'8086' ; -----------XX- = --------XX----
tile14 anop
dc h'8380' ; -----XX------- = XX------------
dc h'8F80' ; ---XXXX------- = XXXX----------
dc h'BF9E' ; -XXXXXX--XXXX- = XXXXXX--XXXX--
dc h'FCE1' ; XXXXX--XX----X = --XXXXXX----XX
dc h'B086' ; -XX--------XX- = ----XX--XX----
dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
dc h'83E6' ; -----XXXX--XX- = XX------XX--XX
dc h'83F8' ; -----XXXXXX--- = XX--------XXXX
tile15 anop
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'8FF8' ; ---XXXXXXXX--- = XXXX------XXXX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'C3E1' ; X----XXXX----X = XX----XX----XX
dc h'C3E1' ; X----XXXX----X = XX----XX----XX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'8FF8' ; ---XXXXXXXX--- = XXXX------XXXX
dc h'83E0' ; -----XXXX----- = XX----------XX
tile16 anop
dc h'C3FF' ; X----XXXXXXXXX = XX----XXXXXXXX
dc h'8F9E' ; ---XXXX--XXXX- = XXXX----XXXX--
dc h'C3FF' ; X----XXXXXXXXX = XX----XXXXXXXX
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
tile17 anop
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'8C98' ; ---XX----XX--- = --XX------XX--
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'CFF9' ; X--XXXXXXXX--X = XXXX--XX--XXXX
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'B086' ; -XX--------XX- = ----XX--XX----
tile18 anop
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
tile19 anop
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
tile1A anop
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
tile1B anop
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'F3E7' ; XXX--XXXX--XXX = XX--XXXXXX--XX
dc h'F3F9' ; XXX--XXXXXX--X = XX--XXXX--XXXX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'8FE6' ; ---XXXXXX--XX- = XXXX----XX--XX
dc h'8FE6' ; ---XXXXXX--XX- = XXXX----XX--XX
tile1C anop
dc h'8FF8' ; ---XXXXXXXX--- = XXXX------XXXX
dc h'BC9E' ; -XXXX----XXXX- = --XXXX--XXXX--
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'BC9E' ; -XXXX----XXXX- = --XXXX--XXXX--
dc h'8080' ; -------------- = --------------
dc h'C3E1' ; X----XXXX----X = XX----XX----XX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'8080' ; -------------- = --------------
tile1D anop
dc h'8FF8' ; ---XXXXXXXX--- = XXXX------XXXX
dc h'BC9E' ; -XXXX----XXXX- = --XXXX--XXXX--
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
tile1E anop
dc h'8FF8' ; ---XXXXXXXX--- = XXXX------XXXX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'BC9E' ; -XXXX----XXXX- = --XXXX--XXXX--
dc h'BC9E' ; -XXXX----XXXX- = --XXXX--XXXX--
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
tile1F anop
dc h'CFE7' ; X--XXXXXX--XXX = XXXX--XXXX--XX
dc h'8080' ; -------------- = --------------
dc h'BCFE' ; -XXXX--XXXXXX- = --XXXX--XXXXXX
dc h'8080' ; -------------- = --------------
dc h'CFE7' ; X--XXXXXX--XXX = XXXX--XXXX--XX
dc h'8080' ; -------------- = --------------
dc h'BCFE' ; -XXXX--XXXXXX- = --XXXX--XXXXXX
dc h'8080' ; -------------- = --------------
tile20 anop
dc h'FF87' ; XXXXXXX----XXX = XXXXXXXXXX----
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'83FE' ; -----XXXXXXXX- = XX------XXXXXX
dc h'C087' ; X----------XXX = ------XXXX----
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
tile21 anop
dc h'FFE7' ; XXXXXXXXX--XXX = XXXXXXXXXX--XX
dc h'BCF8' ; -XXXX--XXXX--- = --XXXX----XXXX
dc h'F3FF' ; XXX--XXXXXXXXX = XX--XXXXXXXXXX
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
tile22 anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
dc h'F0E7' ; XXX----XX--XXX = ----XXXXXX--XX
dc h'C0F9' ; X------XXXX--X = ------XX--XXXX
dc h'C0FF' ; X------XXXXXXX = ------XXXXXXXX
dc h'B0FE' ; -XX----XXXXXX- = ----XX--XXXXXX
dc h'8CF8' ; ---XX--XXXX--- = --XX------XXXX
dc h'83E0' ; -----XXXX----- = XX----------XX
tile23 anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'83E0' ; -----XXXX----- = XX----------XX
tile24 anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
tile25 anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'C3E1' ; X----XXXX----X = XX----XX----XX
dc h'F3F9' ; XXX--XXXXXX--X = XX--XXXX--XXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'C3E1' ; X----XXXX----X = XX----XX----XX
dc h'F3F9' ; XXX--XXXXXX--X = XX--XXXX--XXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
tile26 anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
tile27 anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'CFE7' ; X--XXXXXX--XXX = XXXX--XXXX--XX
dc h'B3F8' ; -XX--XXXXXX--- = XX--XX----XXXX
dc h'B098' ; -XX------XX--- = ----XX----XX--
dc h'CCE1' ; X--XX--XX----X = --XX--XX----XX
dc h'B080' ; -XX----------- = ----XX--------
dc h'8086' ; -----------XX- = --------XX----
dc h'8080' ; -------------- = --------------
tile28 anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FF9F' ; XXXXXXX--XXXXX = XXXXXXXXXXXX--
dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
dc h'FC87' ; XXXXX------XXX = --XXXXXXXX----
dc h'CC87' ; X--XX------XXX = --XX--XXXX----
dc h'CC87' ; X--XX------XXX = --XX--XXXX----
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
tile29 anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'C0E1' ; X------XX----X = ------XX----XX
dc h'B098' ; -XX------XX--- = ----XX----XX--
dc h'8C86' ; ---XX------XX- = --XX----XX----
dc h'C381' ; X----XX------X = XX----XX------
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
tile2A anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
tile2B anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'8C9E' ; ---XX----XXXX- = --XX----XXXX--
dc h'B09E' ; -XX------XXXX- = ----XX--XXXX--
dc h'C09F' ; X--------XXXXX = ------XXXXXX--
dc h'809E' ; ---------XXXX- = --------XXXX--
dc h'809E' ; ---------XXXX- = --------XXXX--
dc h'809E' ; ---------XXXX- = --------XXXX--
tile2C anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'BC98' ; -XXXX----XX--- = --XXXX----XX--
dc h'BC86' ; -XXXX------XX- = --XXXX--XX----
dc h'FC81' ; XXXXX--------X = --XXXXXX------
dc h'BC80' ; -XXXX--------- = --XXXX--------
dc h'BC80' ; -XXXX--------- = --XXXX--------
dc h'BC80' ; -XXXX--------- = --XXXX--------
tile2D anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'BC9E' ; -XXXX----XXXX- = --XXXX--XXXX--
dc h'C3E1' ; X----XXXX----X = XX----XX----XX
dc h'8C98' ; ---XX----XX--- = --XX------XX--
dc h'C081' ; X------------X = ------XX------
dc h'FF99' ; XXXXXXX--XX--X = XXXXXXXX--XX--
dc h'8080' ; -------------- = --------------
tile2E anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'BC9E' ; -XXXX----XXXX- = --XXXX--XXXX--
dc h'C3E1' ; X----XXXX----X = XX----XX----XX
dc h'BC9E' ; -XXXX----XXXX- = --XXXX--XXXX--
dc h'C3E1' ; X----XXXX----X = XX----XX----XX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'8080' ; -------------- = --------------
tile2F anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'C3E1' ; X----XXXX----X = XX----XX----XX
dc h'C3E1' ; X----XXXX----X = XX----XX----XX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'C3E1' ; X----XXXX----X = XX----XX----XX
dc h'BC9E' ; -XXXX----XXXX- = --XXXX--XXXX--
dc h'8080' ; -------------- = --------------
tile30 anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'CF99' ; X--XXXX--XX--X = XXXX--XX--XX--
dc h'8CE6' ; ---XX--XX--XX- = --XX----XX--XX
dc h'B398' ; -XX--XX--XX--- = XX--XX----XX--
dc h'CC81' ; X--XX--------X = --XX--XX------
dc h'8398' ; -----XX--XX--- = XX--------XX--
dc h'8080' ; -------------- = --------------
tile31 anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'CFF9' ; X--XXXXXXXX--X = XXXX--XX--XXXX
dc h'FC9F' ; XXXXX----XXXXX = --XXXXXXXXXX--
dc h'8FE6' ; ---XXXXXX--XX- = XXXX----XX--XX
dc h'8C80' ; ---XX--------- = --XX----------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
tile32 anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'CFE7' ; X--XXXXXX--XXX = XXXX--XXXX--XX
dc h'FCFF' ; XXXXX--XXXXXXX = --XXXXXXXXXXXX
dc h'B39B' ; -XX--XX--XX-XX = XX--XX-XX-XX--
dc h'CCE4' ; X--XX--XX--X-- = --XX--X--X--XX
dc h'B098' ; -XX------XX--- = ----XX----XX--
dc h'8080' ; -------------- = --------------
tile33 anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'B3E6' ; -XX--XXXX--XX- = XX--XX--XX--XX
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
dc h'8080' ; -------------- = --------------
tile34 anop
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'C081' ; X------------X = ------XX------
dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'CFF9' ; X--XXXXXXXX--X = XXXX--XX--XXXX
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'CC99' ; X--XX----XX--X = --XX--XX--XX--
tile35 anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'8C98' ; ---XX----XX--- = --XX------XX--
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'C081' ; X------------X = ------XX------
dc h'BC80' ; -XXXX--------- = --XXXX--------
dc h'BC80' ; -XXXX--------- = --XXXX--------
tile36 anop
dc h'FFFF' ; XXXXXXXXXXXXXX = XXXXXXXXXXXXXX
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'83E0' ; -----XXXX----- = XX----------XX
dc h'8C98' ; ---XX----XX--- = --XX------XX--
dc h'F087' ; XXX--------XXX = ----XXXXXX----
dc h'C081' ; X------------X = ------XX------
dc h'809E' ; ---------XXXX- = --------XXXX--
dc h'809E' ; ---------XXXX- = --------XXXX--
end

3085
src/screen.asm Normal file

File diff suppressed because it is too large Load Diff

382
src/sprite.asm Normal file
View File

@ -0,0 +1,382 @@
;-----------------------------------------------------------------------------
; sprite.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
65816 OFF
copy src/defs.s
SPRITE start
using LOWMEM
using ROSYSTEM
using ROLEVELS
using ROSPRITES
;-----------------------------------------------------------------------------
; Copy bytes from srcPtr to dstPtr
; IN: - srcPtr - start of copy
; dstPtr - start of non-overlapping destination
; size - number of bytes to copy
; Clobbers: a,y
spriteCopyMemSrcToDst entry
ldy #0
hiCopy anop
dec sizeH
bmi lowCopy
scm0 lda (srcPtrL),y
sta (dstPtrL),y
dey
bne scm0
inc srcPtrH
inc dstPtrH
bne hiCopy
lowCopy anop
ldy sizeL
dey
bmi doneScm
scm1 lda (srcPtrL),y
sta (dstPtrL),y
dey
bpl scm1
doneScm anop
rts
;-----------------------------------------------------------------------------
; Look up the color, and apply those masks to the frames
; IN: x = start frame
; y = num frames
; a = color index
; Clobbers: a,y
spriteApplyMaskToFrames entry
;instanceIdx0 equ tmpBot+0
colMaskL0 equ tmpBot+1
colMaskR0 equ tmpBot+2
numFrames equ tmpBot+3
sty numFrames ; save y
tay ; put color index in y
lda masksLeft,y ; look up the masks for the color
sta colMaskL0
lda masksRight,y
sta colMaskR0
lda mult64L,x ; build a pointer to the frame
sta srcPtrL
lda mult64H,x
adc #>spriteInstances
sta srcPtrH
ldy numFrames ; convert frames to bytes
lda mult64H,y
sta sizeH
lda mult64L,y
sta sizeL
ldy #0 ; do blocks of 256
hiPass anop
dec sizeH ; see if there's a hi block to do
bmi lowPass ; if none (remain) to do, move on
sam0 lda (srcPtrL),y ; do a left hand byte
and colMaskL0
sta (srcPtrL),y
dey
lda (srcPtrL),y ; then a right hand byte
and colMaskR0
sta (srcPtrL),y
dey
bne sam0 ; for 256 bytes
inc dstPtrH ; advance the dest ptr Hi
bne hiPass ; BRA
lowPass anop
ldy sizeL ; do bytes remaining lt 256
dey
bmi doneSam ; keep going till all done
sam1 lda (srcPtrL),y
and colMaskL0
sta (srcPtrL),y
dey
lda (srcPtrL),y
and colMaskR0
sta (srcPtrL),y
dey
bpl sam1
doneSam anop
rts
;-----------------------------------------------------------------------------
; Copy one frame to another
; IN:
; originalFrame = tmpBot+4
; newFrame = tmpBot+5
; Clobbers: a,x,y
spriteCopyFrameToFrame entry
originalFrame0 equ tmpBot+4
newFrame0 equ tmpBot+5
clc
ldx originalFrame0 ; point srcPtr at the original frame
lda mult64L,x
sta srcPtrL
lda mult64H,x
adc #>spriteInstances
sta srcPtrH
ldx newFrame0 ; point dstPtr at the target frame
lda mult64L,x
sta dstPtrL
lda mult64H,x
adc #>spriteInstances
sta dstPtrH
lda #0 ; 256 or less bytes (no Hi)
sta sizeH
lda #64 ; just 64 bytes to copy
sta sizeL
jsr spriteCopyMemSrcToDst ; use copymem to copy a 64 byte frame
rts
;-----------------------------------------------------------------------------
; Invert the pixels of a frame
; IN:
; x = frame number
spriteInvertFrame entry
clc
lda mult64L,x ; make srcPtr point at the frame
sta srcPtrL
lda mult64H,x
adc #>spriteInstances
sta srcPtrH
ldy #SPRITE_BYTES-1 ; do for a whole frame (0 based)
sif0 lda (srcPtrL),y ; get the frame byte
eor #%01111111 ; invert except for the MSB
sta (srcPtrL),y ; and save the byte
dey ; one less byte to do
bpl sif0 ; do for all bytes
rts
;-----------------------------------------------------------------------------
; Clear all the pixels of a frame
; IN:
; x = frame number
; y = number of frames to clear
spriteClearFrames entry
count0 equ sizeL
lda mult64L,y ; turn the number of frames into num bytes
sta count0 ; save as a count
clc ; and clear carry
lda mult64L,x ; make srcPtr point at the
sta srcPtrL
lda mult64H,x
adc #>spriteInstances
sta srcPtrH
ldy count0 ; how many bytes to clear
dey ; make zero based
lda #0 ; value to write
scf0 sta (srcPtrL),y ; write 0 to frame
dey ; previous byte in frame
bpl scf0 ; do for all, incl. zero'th byte
rts
;-----------------------------------------------------------------------------
; Make an instance of the bitmap (index in a) into the spriteInstance buffer
; while expanding the bitmap from 32 byte 1bpp into 64 byte 2bpp and masking
; the instance for the required color.
; IN:
; a - bitmapIdx
; x - instanceIdx
spriteInstanceSpriteFrames entry
; count = tmpBot+0
; spriteIdx = tmpBot+1
instanceIdx1 equ tmpBot+2
srcIdx equ tmpBot+3
dstIdx equ tmpBot+4
colMaskL1 equ tmpBot+5
colMaskR1 equ tmpBot+6
ldy #0
sty srcPtrH
sty dstPtrH
ldy #5 ; mult * 32 (shl 5 times) since each src frame is 32 bytes
sis0 asl a ; shift the low
rol srcPtrH ; and the hi, and move carry into hi if needed
dey ; do for all 6 iterations
bne sis0
adc #<sprite08 ; add the memory offset off the non-willy src sprites
sta srcPtrL
lda #>sprite08
adc srcPtrH
sta srcPtrH ; src ptr now points at the 1st frame
lda spriteFramesIdx,x ; get the sprite dest frame
ldy #6 ; mult * 64 (shl 6 times) since each frame is 64 bytes
sis1 asl a ; shift the lo
rol dstPtrH ; and the hi, and move carry into hi if needed
dey ; do for all 6 iterations
bne sis1
sta dstPtrL ; save the lo
lda dstPtrH ; get the hi
adc #>spriteInstances ; and make relative to the buffer
sta dstPtrH ; and save the hi
lda #1 ; assume 4 frames equ 256 bytes
sta sizeH
lda spriteClass,x ; get the class
bit bit1Mask ; CLASS_FOUR_FRAME is it 4 frames
bne sis2 ; yes, all set
inc sizeH ; 8 frames = 512 bytes equ 2 Hi
sis2 ldy instanceIdx1 ; get the instance
lda spriteColor,y ; and get the color for the instance
tay ; put the color index in y
lda masksLeft,y ; get the color mask
sta colMaskL1
lda masksRight,y ; do the same for the right
sta colMaskR1 ; SQW - look at comments but save for second (inverse) buffer
ldy #0
sty dstIdx ; set the src and dst indices to start at 0
sty srcIdx ; srcIndex moves at 1/2 of dstIndex
copyFrames anop
ldy srcIdx ; get the source index
lda (srcPtrL),y ; get a (left) src byte at the source index
pha ; save so the right nibble can be expanded later
lsr a ; make the left nibble the low nibble
lsr a
lsr a
lsr a
tax ; put the value in x
lda binDouble,x ; look up the "pixel doubled" value
ora #$80 ; and set the color msb "on"
and colMaskL1 ; mask it with appropriate color
ldy dstIdx ; get the destination offset
sta (dstPtrL),y ; and save to instance destination
iny ; move the destination along one
pla ; get the source byte
and #$0f ; mask so only right nibble
tax ; put it in x
lda binDouble,x ; and look up the "doubled" pixel values
sec ; set carry so a rotate will be equiv to or #$80
ror a ; and rotate, making it a "right" byte
and colMaskR1 ; mask it with appropriate color
sta (dstPtrL),y ; and save to instance destination
iny ; move the dest index along again
sty dstIdx ; and save the index
bne sis3 ; if the index rolled over
inc dstPtrH ; move the hi byte along
dec sizeH ; check if moved all required 4 * 32 src byte blocks
beq doneSis
sis3 inc srcIdx ; move the src index along
bne copyFrames ; do max 256 bytes equ 8 * 32 byte src frames
doneSis anop
rts
;-----------------------------------------------------------------------------
; Copy the door frame, invert the copy, mask both and combine
spriteDoorSetup entry
originalFrame1 equ tmpBot+4
newFrame1 equ tmpBot+5
ldx numSprites ; numSprites is the door sprite index
lda spriteFramesIdx,x
tax
stx originalFrame1
inx
stx newFrame1
jsr spriteCopyFrameToFrame ; make a copy y = instanceIdx, a = srcFrame,x equ dstFrame
ldx newFrame1
jsr spriteInvertFrame ; invert the instance frame bits (leave msb alone)
ldx currLevel
lda door_color1,x
beq sds0
ldx originalFrame1
ldy #1
jsr spriteApplyMaskToFrames
ldx currLevel
lda door_color2,x
beq sds0
ldx newFrame1
ldy #1
jmp spriteApplyMaskToFrames
sds0 rts
;-----------------------------------------------------------------------------
; Make 4 copies of Eugene frame 0 into frames 1-4 and apply a different
; color mask to the additional frames
spriteEugeneSetup entry
originalFrame2 equ tmpBot+4
newFrame2 equ tmpBot+5
count1 equ tmpBot+6
ldx numSprites
dex ; eugene is sprite before the door
lda spriteFramesIdx,x ; get the frame where eugene is
tax ; put in x
stx originalFrame2 ; and call it the original
inx ; and go to the next frame
stx newFrame2 ; and call it the new frame
ldx #3 ; and set the loop count to 3
stx count1
ses0 jsr spriteCopyFrameToFrame ; make a copy of eugene,x = ori,y equ new
lda count1 ; get the count in a (as a color mask index)
ldx newFrame2 ; the frame in x
ldy #1 ; and the number of frames to process in Y
jsr spriteApplyMaskToFrames ; mask the new eugene to the "count" color
inc newFrame2 ; go up a frame
dec count1 ; and dec the loop counter
bne ses0 ; and do for the number of loops (3)
rts ; there are now 4 eugenes, White, Green, Orange & Purple
end

308
src/text.asm Normal file
View File

@ -0,0 +1,308 @@
;-----------------------------------------------------------------------------
; text.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
65816 OFF
copy src/defs.s
TEXT start
using LOWMEM
using ROSYSTEM
using ROFONT
using ROTEXT
using DATA
;-----------------------------------------------------------------------------
textShowText entry
xpos0 equ srcPtrL
ypos0 equ srcPtrH
rows equ sizeH
strIndex equ sizeL
color0 equ dstPtrL ; and H
fontL equ charGfx+1
fontH equ charGfx+2
stx xpos0
sty ypos0
loop0 anop
lda #0
sta fontH ; init the pointer hi to 0 for later mult rol's
ldx strIndex ; get the index into the string
read0 entry
lda PLACEHOLDER,x ; get the character in the string
sec
sbc #32 ; the font only starts at space (char 32 or $20)
beq tst0
sbc #9 ; gap after space
asl a ; mult by 16 as that's how wide a char is in bytes
asl a
rol fontH
asl a
rol fontH
asl a
rol fontH ; srcPtr now points at the char but $0000 based
tst0 adc #<font ; add the font start
sta fontL
lda fontH
adc #>font
sta fontH ; srcPtr now point at the actual character memory
lda #8 ; font is 8 rows high
sta rows
ldy ypos0 ; start each character on the same line
iLoop anop
lda strIndex ; strIndex is also col offset from xpos
asl a ; but font is 2 cols wide
adc xpos0 ; add the xpos to get screen col
adc rowL,y ; and add the row
sta write0+1 ; lo byte of where to write to screen buffer
lda currPageH ; get the hi page
adc rowH,y ; add the row
sta write0+2 ; and complete the screen buffer write address
ldx #1 ; set up for copying 2 font bytes (1 char)
charGfx anop
lda PLACEHOLDER,x ; get the font
eorMask entry
eor #$00 ; eor to invert if necessary
and color0,x ; and to get the color needed
write0 anop
sta PLACEHOLDER,x ; and write to screen memory
dex ; go left a byte
bpl charGfx ; and repeat to do 2 bytes
dec rows ; done one of the 8 rows needed
beq nextChar ; repeat for all 8 rows, then done
iny ; more rows - next row in y
lda fontL ; move along 2 in the font
adc #2
sta fontL
bcc iLoop
inc fontH
bcs iLoop ; BRA
nextChar anop
dec strIndex ; string done from the back, so move left in string
bpl loop0 ; if not all of string done, loop
;done0 anop
rts
;-----------------------------------------------------------------------------
; Build a memory cache of the level name since this is re-drawn much more -
; every time the level scrolls left or right and copying from a cache is
; much faster than doing a text print
textSetLevelText entry
lda #0
sta sizeL ; index into string
sta read1+2 ; hi byte of string address
lda currLevel ; start with the level
asl a ; multiply by 32
asl a
asl a
asl a
rol read1+2
asl a
rol read1+2
adc #<roTextLevel ; add the base address of the string
sta read1+1
lda #>roTextLevel
adc read1+2
sta read1+2 ; read+1 as a ptr now points at the string for this level
lda #<levelNameGfx0 ; start at the top of the name cache
sta write1+1 ; and make write+1 be a pointer to the cache
lda #>levelNameGfx0
sta write1+2
lda #32 ; These strings are 32 characters wide
sta dstPtrL
loop1 anop
lda #0
sta srcPtrH ; init the pointer hi to 0 for later mult rol's
ldx sizeL ; get the index into the string
read1 anop
lda PLACEHOLDER,x ; get the character in the string
sec
sbc #32 ; the font only starts at space (char 32 or $20)
beq tsl0 ; gap after space
sbc #9
asl a ; mult by 16 as that's how wide a char is in bytes
asl a
rol srcPtrH
asl a
rol srcPtrH
asl a
rol srcPtrH ; srcPtr now points at the char but $0000 based
tsl0 adc #<font ; add the font start
sta srcPtrL
lda srcPtrH
adc #>font
sta srcPtrH ; srcPtr now point at the actual character memory
lda #8 ; copy 8 rows / character
sta sizeH
ldy #1 ; start at the right hand side character
lrLoop anop
ldx #1 ; load x for the right hand side as well
copyLoop anop
lda (srcPtrL),y ; get the line pixel
eor #$7f ; invert
maskName anop
and maskGreen,x ; mask for color (always green but left vs right hand side)
write1 anop
sta PLACEHOLDER,x ; store to the cache
dey ; back up a byte
dex
bpl copyLoop ; do 2 bytes, right and left hand
lda write1+1 ; get the cache ptr low
clc
step anop
adc #64 ; step to the next line - 64 bytes along
sta write1+1 ; update the pointer
bcc tsl1
inc write1+2 ; if it wrapped, update the hi byte
tsl1 iny ; y is now at minus 1 the last byte written
iny ; so advance it by 4 to get to the next right hand side byte
iny
iny
dec sizeH ; done one line
bne lrLoop ; if any lines left, keep going
sec
lda write1+1
sbc #<((64*8)-2)
sta write1+1
lda write1+2
sbc #>((64*8)-2)
sta write1+2
clc
inc sizeL ; move to the next character in the string
dec dstPtrL ; see if 32 characters were done
bne loop1 ; if not, keep going
;done anop
rts
;-----------------------------------------------------------------------------
; x has digit (5 means 1's, 4 means 10's, etc)
; a is the number to add 0..9
textAddScore entry
clc
adc score,x ; get the current digit
cmp #'9'+1 ; has it rolled over
bcc okay ; then simply increment
sec
sbc #10
sta score,x ; and save over the 9
lda #1
dex ; previous digit
bmi over ; if it rolls over 999999
cpx #1 ; if the digit is now the 010000 (1)
bne textAddScore ; no, then work with this digit
ldy lives
cpy #9 ; max out at 9 lives (keeps cheat boot on-screen)
bcs textAddScore
inc lives ; yes, then add a life
bne textAddScore ; and then work with this digit
okay anop
sta score,x ; and store it
over anop
lda #UI_COMPONENT_SCORE ; mark the score texts as needing an update
jmp uiUpdateComponent
;done anop
rts
;-----------------------------------------------------------------------------
textCheckHighScore entry
ldx #0 ; start at the most significant digit
tch0 lda score,x ; get the score
cmp highScore,x ; compare to the high score
bcc done0 ; if smaller then highscore gt score
bne newHigh ; if ne then highscore gt score
inx ; digits equal so check next digit
cpx #6 ; compare x to max digits (+ 1)
bcc tch0 ; x is 5 or less, keep checking digits
done0 anop
rts
newHigh anop
ldx #5 ; copy the 6 score digits over the highscore digits
tch1 lda score,x
sta highScore,x
dex
bpl tch1
lda #UI_COMPONENT_HIGHSCORE
jmp uiUpdateComponent
;-----------------------------------------------------------------------------
textColorCycle entry
color1 equ tmpBot+1
xPos equ tmpBot+2
yPos equ tmpBot+3
textL equ tmpBot+4
textH equ tmpBot+5
len equ tmpBot+6
prntLoop anop
; printXYlh xPos,yPos,textL,textH,#0,color macro included here
ldx color1 ; this is an index into mask[Left|Right]
lda masksLeft,x
sta dstPtrL
lda masksRight,x
sta dstPtrL+1
lda #0 ; eor o is not inverse
sta eorMask+1 ; set the eor in the code
lda textL ; set the string pointer in the code
sta read0+1
lda textH
sta read0+2
ldx #0 ; 0 based
stx sizeL
lda xPos ; and x/y coords in x and y registers
asl a
tax
ldy yPos
jsr textShowText ; print that string
dec len ; one less character to color
beq done1 ; all characters done?
inc xPos ; move to the next character on screen
inc textL ; and move to the next character in the sting
bne tcc0 ; did the string wrap a buffer
inc textH ; yes, up the Hi
tcc0 dec color1 ; prev color
bpl tcc1 ; still ge 0
lda #4 ; no, wrap to index 4
sta color1 ; and save that as the color
tcc1 jmp prntLoop ;and print this character
done1 anop
rts
end

443
src/tiles.asm Normal file
View File

@ -0,0 +1,443 @@
;-----------------------------------------------------------------------------
; tiles.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
65816 OFF
copy src/defs.s
TILES start
using LOWMEM
using ROSYSTEM
using ROLEVELS
;-----------------------------------------------------------------------------
tilesPrepForLevel entry
jsr tilesMakeInstances ; copy tile data to instance area
lda monochrome ; see if the game should render for monochrome
beq color ; no, apply all masks
mono anop
ldy #(DATA_COLLAPSE/$10)-1 ; apply color mask only to the conveyor tile
ldx #((DATA_COLLAPSE/$10)-1) *
lda #1
bne mask
color anop
ldy #0
ldx #0
lda #TILES_PER_LEVEL
mask anop
jsr tilesColorInstances ; color instance tiles by applying appropriate color masks
jsr tilesPrepKeysTiles ; make animated keys from the key tile
jmp tilesPrepConveyorTiles ; Make rotated conveyor tiles into conveyorAnimTiles
;-----------------------------------------------------------------------------
tilesMakeInstances entry
numTiles equ sizeL
iLevelTile equ sizeH
iWrite equ dstPtrL
tileMemL equ srcPtrL
tileMemH equ srcPtrH
lda #TILES_PER_LEVEL ; for all tiles used in a level
sta numTiles
lda #TILE_BYTES-1 ; start at the end of tile memory
sta iWrite
ldx currLevel ; find index into tile table
lda mult8,x ; 8 tiles per level
sta iLevelTile ; gives entry for the 1st tile
loop0 anop
lda #0 ; set the hi for reading tile memory to 0
sta tileMemH
ldx iLevelTile ; get the index into the table
lda levelTiles,x ; and get the id for the tile from the table
asl a ; mult tile offset * 16 (width of a tile)
asl a
asl a
rol tileMemH
asl a
rol tileMemH ; offset of tile start (from background) now in tileMem ptr
adc #<ROTILES ; add tiles base address
sta tileMemL
lda #>ROTILES
adc tileMemH
sta tileMemH ; tileMem pointer now points at memory for the tile
ldy #TILE_BYTES-1 ; 0 based, copy all the bytes of the tile
ldx iWrite
tmi0 lda (tileMemL),y ; get the tile byte
sta tilesInstances,x ; and save it to instance 0
dex ; back up the tile write pointer
dey ; and completed one byte
bpl tmi0 ; do for all bytes of a tile
dec numTiles ; done a tile
beq copyDone ; see if all tiles done
lda iWrite ; more tiles to do, adjust the tile write ptr
clc
adc #TILE_BYTES ; by moving it to the end of the next tile
sta iWrite
inc iLevelTile ; and advance the index into the table to the next tile
bne loop0 ; BRA to do the next tile
copyDone anop
rts
;-----------------------------------------------------------------------------
; Color tile instances
; IN: a-number of tiles to color
; y-index of first tile to color
; x-write address of first tile data (16 * y)
tilesColorInstances entry
;numTiles equ sizeL
;iLevelTile equ sizeH
colMaskL equ dstPtrL+0
colMaskR equ dstPtrL+1
;tileMemL equ srcPtrL
;tileMemH equ srcPtrH
sta numTiles ; save the register parameters
sty iLevelTile
ldy currLevel ; get the offset of the tiles in the level tile table
lda mult8,y
clc
adc iLevelTile ; and add the parameter offset (0 for color and 3 for mono)
sta iLevelTile
loop1 anop
ldy iLevelTile ; get the index
lda levelMasks,y ; and extract the masks for this tile
tay
lda masksLeft,y
sta colMaskL
lda masksRight,y
sta colMaskR
ldy #(TILE_BYTES/2) ; 2 masks at one time, so bytes/2
tci0 lda colMaskL ; instance 0 mask the left side with a left mask
and tilesInstances,x
sta tilesInstances,x
inx ; next byte
lda colMaskR ; instance 0 mask the right side with a right mask
and tilesInstances,x
sta tilesInstances,x
inx ; next byte
dey ; one more column done
bne tci0 ; keep going till all columns done
inc iLevelTile ; go to the next table entry
dec numTiles ; done one more tile
bne loop1 ; keep going till all tiles done
rts
;-----------------------------------------------------------------------------
tilesPrepKeysTiles entry
keyByte equ tmpBot+0
lda #4 ; init the key animation to frame 4
sta keysFrameNum
ldy #0 ; start at the 1st key byte
maskLoop anop
lda tilesInstances+DATA_KEY-TILE_BYTES,y
sta keyByte ; get a byte and save it
clc
ldx #4 ; make 4 color variations
colorLoopLeft anop
lda keyByte ; start with the white key byte
and masksLeft,x ; mask it for left
sta keyAnimTiles,y ; and save it to the first key frame instance 0
tya ; move y along to the next key instance
adc #TILE_BYTES
tay
dex ; and do the next color for that instance
bne colorLoopLeft ; repeat for all 4 color frames
tya ; move Y back 63 bytes, to the next white key byte
sec
sbc #63
tay
lda tilesInstances+DATA_KEY-TILE_BYTES,y
sta keyByte ; get the second (right hand byte)
clc
ldx #4 ; repeat the above but swap color masks
colorLoopRight anop
lda keyByte
and masksRight,x
sta keyAnimTiles,y
tya
adc #TILE_BYTES
tay
dex
bne colorLoopRight
tya
sec
sbc #63
tay ; y is now pointing at the next left byte
cpy #TILE_BYTES ; see if the whole key has been processes
bne maskLoop
rts
;-----------------------------------------------------------------------------
; Makes animated copies of the conveyor tile. Instead of making full tile
; copies, this should really just do the two lines affected (so use 1 tile
; of memory, not 7 * TILE_BYTES)
tilesPrepConveyorTiles entry
frame equ sizeL
count equ sizeH
dir equ tmpBot+0
carry equ tmpBot+1
lda #6 ; init the conveyor frame counter
sta conveyorFrameNum
ldx currLevel
lda conveyorDirections,x ; get a local copy of the conveyor direction
sta dir
clc ; point srcPtr at the conveyor tile
lda #DATA_CONVEYOR-TILE_BYTES
sta srcPtrL
lda #>tilesInstances
sta srcPtrH
lda #<conveyorAnimTiles ; point dstPtr at the first animated tile
sta dstPtrL
lda #>conveyorAnimTiles
sta dstPtrH
ldy #TILE_BYTES-1 ; copy the tile to the animated tiles
tpc0 lda (srcPtrL),y
and #$7F ; clear the MSB, will be fixed later
sta (dstPtrL),y
dey
bpl tpc0
ldy #CONVEYOR_FRAMES-1 ; set a counter for how many frames to process
processTile anop
sty frame
clc ; move srcPtr to dstPtr (the new src)
lda dstPtrL ; and move dstPtr to the next frame to animate
sta srcPtrL
adc #TILE_BYTES
sta dstPtrL
lda dstPtrH
sta srcPtrH
bcc tpc1
inc dstPtrH
tpc1 ldy #TILE_BYTES-1 ; process a tile's bytes (0 based)
tpc2 lda (srcPtrL),y ; copy the source
sta (dstPtrL),y ; save to the dest
dey ; copy the whole tile
bpl tpc2
lda dir ; different algorithm for each direction
cmp #2
beq left
right anop
ldy #0 ; top row
jsr shiftLeft ; move "left" which is "wrong", the processing is going 0..CONVEYOR_FRAMES
ldy #4 ; 3rd row down, 0 based (2) * 2 byes/row is 4
jsr shiftRight ; but the animation plays back CONVEYOR_FRAMES..0
jmp nextFrame ; so this is all reversed
left anop
ldy #0
jsr shiftRight
ldy #4
jsr shiftLeft
nextFrame anop
ldy frame
dey ; another frame processed
bne processTile ; have all tiles been animated (0 is original the rest shifted)
jmp finalFix ; fix the MSB
shiftRight anop
lda (dstPtrL),y ; left byte scroll right (apple pixels are reversed, so asl a)
asl a ; shift msb away, bit 0 clear
asl a ; shift 1/2 a pixel, bit 1 and 0 clear
sta (dstPtrL),y ; save left shifted. carry has a pixel bit that needs to move
iny
lda (dstPtrL),y
rol a ; shift right byte once, carry goes in, MSB bit out in carry
asl a ; shift second time, bit 0 is now a zero, carry bit needs moving left
sta (dstPtrL),y
dey
lda #0 ; start fresh
rol a ; move carry into bit 0
asl a ; carry into bit 1, carry clear, bit 0 now 0
ora (dstPtrL),y ; add bit 1 to the left byte
sta (dstPtrL),y ; save the left byte
and #$80 ; extract bit 8 left that should be in right bit0
asl a ; put bit 8 in carry and acc now clear
rol a ; put bit 8 in bit 0
iny
ora (dstPtrL),y ; add it to the right byte
sta (dstPtrL),y ; store the right byte
and #$80 ; extract bit 8 right which should be bit 0 left
asl a ; move into carry
rol a ; move carry into bit 0, carry now clear
dey
ora (dstPtrL),y ; add to bit0 of left byte
sta (dstPtrL),y ; and save
rts
shiftLeft anop
ldx #1
lda (dstPtrL),y ; get left byte
tpc3 lsr a ; move bit out
sta (dstPtrL),y ; save byte
lda #0 ; move bit in for next byte to bit 6
ror a
lsr a
sta carry
iny
lda (dstPtrL),y
ror a ; move right byte one over (carry needs to go left now)
ora carry ; add bit from left
sta (dstPtrL),y ; save
lda #0 ; start fresh
ror a ; move carry to bit 6
lsr a
dey
ora (dstPtrL),y ; add to left byte
dex
bpl tpc3
sta (dstPtrL),y ; save
rts
finalFix anop
ldy #(CONVEYOR_FRAMES*TILE_BYTES)-1
lda tilesInstances+(DATA_CONVEYOR-TILE_BYTES)
and #$80 ; load a byte from original
beq clear ; and see if color bit is set
tpc4 lda #$80 ; if set, set color on for all frames
ora conveyorAnimTiles,y
sta conveyorAnimTiles,y
dey
bpl tpc4
bmi done
clear anop
lda #$7f ; if not set, make sure color isn't on for all
and conveyorAnimTiles,y
sta conveyorAnimTiles,y
dey
bpl clear
done anop
rts
;-----------------------------------------------------------------------------
; Copy a pre-animated key tile into the tilesInstances so it looks as
; though the key is animating
tilesAnimateKeys entry
ldx keysFrameNum ; get the frame
dex ; step
bpl tak0 ; underflow
ldx #3 ; reset-frames are 0 to 6, but go to render+1
tak0 stx keysFrameNum ; save the new frame
inx ; go one frame past
lda mult16,x ; get the byte offset to the frame
tax ; put it in x
dex ; and go to the last byte of the frame needed
ldy #TILE_BYTES-1 ; set y to copy a whole tile
tak1 lda keyAnimTiles,x ; read the frame and write to key tile
sta tilesInstances+DATA_KEY-TILE_BYTES,y
dex
dey
bpl tak1
rts
;-----------------------------------------------------------------------------
; Copy a pre-animated conveyor lines over the lines in the conveyor frame tile,
; in the tilesInstances area
tilesAnimateConveyor entry
ldx conveyorFrameNum ; get the frame
dex ; step
bpl tac0 ; underflow
ldx #6 ; reset-frames are 0 to 6, but go to render+1
tac0 stx conveyorFrameNum ; save the new frame
lda mult16,x ; get the byte offset to the frame
tax ; put it in x
lda conveyorAnimTiles,x ; copy the 4 animated bytes for
sta tilesInstances+DATA_CONVEYOR-TILE_BYTES
inx
lda conveyorAnimTiles,x ; instance 0 over
sta tilesInstances+DATA_CONVEYOR-TILE_BYTES+1
inx ; to the tile area 0
inx
inx
lda conveyorAnimTiles,x
sta tilesInstances+DATA_CONVEYOR-TILE_BYTES+4
inx
lda conveyorAnimTiles,x
sta tilesInstances+DATA_CONVEYOR-TILE_BYTES+5
rts
end

449
src/ui.asm Normal file
View File

@ -0,0 +1,449 @@
;-----------------------------------------------------------------------------
; ui.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
65816 OFF
copy src/defs.s
mcopy src/ui.mac
UI start
using ROSYSTEM
using RODATA
using ROTEXT
using DATA
;-----------------------------------------------------------------------------
uiUpdateComponent entry
ora uiComponent
sta uiComponent
lda #2
sta updateUICount
rts
;-----------------------------------------------------------------------------
uiUpdate entry
lda uiComponent
bit bit0Mask ; UI_COMPONENT_NAME
beq ud00
jsr screenDrawLevelName
lda uiComponent
ud00 bit bit1Mask ; UI_COMPONENT_AIR_NAME
beq ud01
printXYlh #0,#(17*8),#<roTextAir,#>roTextAir,#4,#2,1
jsr screenDrawAirFrame
lda uiComponent
ud01 bit bit2Mask ; UI_COMPONENT_AIR
beq ud02
jsr screenDrawAirRemaining
lda uiComponent
ud02 bit bit3Mask ; UI_COMPONENT_SCORE_NAME
beq ud03
printXYlh #4,#(19*8),#<roTextHighScore,#>roTextHighScore,#3
printXYlh #11,#(19*8),#<roTextScore,#>roTextScore,#4
lda uiComponent
ud03 bit bit4Mask ; UI_COMPONENT_SCORE
beq ud04
printXYlh #11,#(20*8),#<score,#>score,#5
lda uiComponent
ud04 bit bit5Mask ; UI_COMPONENT_LIVES
beq ud05
jsr screenDrawLives
lda uiComponent
ud05 bit bit6Mask ; UI_COMPONENT_HIGHSCORE
beq ud06
printXYlh #3,#(20*8),#<highScore,#>highScore,#5
ud06 dec updateUICount
bne ud07
lda #0
sta uiComponent
ud07 rts
;-----------------------------------------------------------------------------
; 28209 cycle delay from start till after rts
uiDelay entry
ldy #$80
ySet entry
ldx #0
udl0 dex
bne udl0
dey
bne udl0
rts
;-----------------------------------------------------------------------------
; This routine shows the MANIC and MINER text on screen.
; the macro uiShowMMTextXY puts specific values appropriate for each right
; into the routine (such as the address of the character width array)
; The Manic & Miner words are stored in a "compressed" form, this also decodes
; that. Each letter "pixel" is stored as a bit.
uiShowMMText entry
row equ srcPtrL
col equ srcPtrH
offset equ dstPtrL
index equ dstPtrH
colMaskL equ sizeL
colMaskR equ sizeH
width equ tmpBot+0
height equ tmpBot+1
dataByte equ tmpBot+2
dr equ tmpBot+3
dc equ tmpBot+4
dw equ tmpBot+5
pr equ tmpBot+6
sty row
stx col
lda #0
sta offset
sta index
strLoop anop
ldx index
colorLoc entry
lda PLACEHOLDER,x ; unpack the color masks
tay
lda masksLeft,y
sta colMaskL
lda masksRight,y
sta colMaskR
lda #6 ; the text is 6 rows high
sta height
lda row
sta dr ; set the working counter to the row
charLoop anop
lda col
sta dc ; set the working counter to the column
ldx index ; get the index to the character in the string
widthLoc entry
lda PLACEHOLDER,x ; get the width of the character
sta width ; save
sta dw ; and init the working width
ldx offset ; the offset is into the encoded data
dataLoc entry
lda PLACEHOLDER,x ; get the next encoded character
inc offset ; and move the index
sta dataByte ; save the character
colLoop anop
lda dataByte ; load the character
asl a ; shift out the MSB to get the bit
sta dataByte ; save the new shifted encoded character
bcc skipPlot ; if bit was 0, blank, nothing to do
lda #8 ; 1-bit to be drawn. "pixel" is 8 pixel-rows high
sta pr ; save row draw counter
lda dr ; load the screen draw row where drawing should happen
asl a ; * 8
asl a
asl a
tay ; store the row in Y
lda dc ; get the column
and #1 ; and see if the column is odd or even (for color mask)
tax
usm0 lda dc ; start with the column
adc rowL,y ; and calculate the hi-res row/col address
sta write+1
lda rowH,y
adc currPageH ; add the page to draw to
sta write+2
lda #$ff ; assume all bits on
and colMaskL,x ; but then mask to get appropriate color
write anop
sta PLACEHOLDER ; write to the screen
iny ; next hi-res pixel-row
dec pr ; and one less row to draw
bne usm0 ; do all 8 rows
skipPlot anop
inc dc ; go to the next column
dec dw ; one less to do in the width of the character
bpl colLoop ; if not done the whole character, keep going
inc dr ; move down to the next row of the character
dec height ; one less row to do
bpl charLoop ; keep going till the whole character height done
lda width ; move the draw col by the width of the character just drawn
clc
adc col
sta col
inc index ; and move the string index to the next character
lda index
cmp #6
bcc strLoop ; if not all 5 characters (MANIC or MINER) done, keep going
rts
;-----------------------------------------------------------------------------
uiTitleScreen entry
scrollPtrL equ 0 ;tmpBot+0
scrollPtrH equ 1 ;tmpBot+1
scrollLen equ 2 ;tmpBot+2
scrollIdx equ 3 ;tmpBot+3
titleState equ 4 ;currLevel
lda #0
sta leftEdge ; reset the left edge
lda #11*8 ; position willy for the UI
sta willyYPos
lda #0
sta willyFrame
lda #18
sta willyXPos
lda #<titleMusic ; init the music ptr
sta musicL
lda #>titleMusic
sta musicH
ldx #1 ; do a full screen clear of both buffers
jsr screenClear
jsr screenSwap
ldx #1
jsr screenClear
lda #0
sta titleState ; set to bounce manic miner / audio
sta uiComponent ; and init the ui update to nothing
lda #UI_COMPONENT_SCORE_NAME+UI_COMPONENT_SCORE+UI_COMPONENT_HIGHSCORE
jsr uiUpdateComponent ; add an update for bottom part of screen
jsr screenDrawWilly ; show willy on this screen
uiShowMMTextXY #6,#6,manicText,manicCharWidth,manicColors
printXYlh #0,#22*8,#<roTextAppleIIVersion,#>roTextAppleIIVersion,#19
printXYlh #0,#23*8,#<roTextend,#>roTextend,#19
jsr uiUpdate ; show the UI on the Manic screen
jsr screenSwap
jsr screenDrawWilly ; show willy on the other screen
uiShowMMTextXY #6,#6,minerText,minerCharWidth,minerColors
printXYlh #0,#22*8,#<roTextAppleIIVersion,#>roTextAppleIIVersion,#19
printXYlh #0,#23*8,#<roTextend,#>roTextend,#19
jsr uiUpdate ; show the UI on the Miner screen
lda KBDSTRB
mainLoop anop
jsr screenSwap ; swap screens (manic/miner) or scroll text
jsr inputUI ; read keys -1 - quit, 0 - no key, 1 - go to game
beq stayInUI ; no key
bpl playGame ; go to game
lda #EVENT_EXIT_GAME ; quit
bne exit
playGame anop
lda #EVENT_OK
exit anop
jmp done
stayInUI anop
lda titleState ; get the state (bounce vs scroll)
beq bounce
jmp introScroll ; 0 - bounce, 1 - scroll
bounce anop
jsr audioPlayTitleNote ; play the tune
bcc mainLoop ; tune done when carry is set, else bounce
lda #2
sta titleState ; use this as a temporary counter
uts0 ldx #0 ; clear the upper portion of the screen
jsr screenClear ; show both manic & miner
uiShowMMTextXY #6,#0,manicText,manicCharWidth,manicColors
uiShowMMTextXY #6,#8,minerText,minerCharWidth,minerColors
jsr screenDrawWilly ; show willy as well
jsr screenSwap
dec titleState ; do for both buffers
lda titleState
bne uts0
lda #1 ; set the state to the scrolling screen
sta titleState
lda #<roTextIntro ;init the scrolling message text
sta scrollPtrL
lda #>roTextIntro
sta scrollPtrH
lda #0
sta scrollLen
lda #19
sta scrollIdx
introScroll anop ; show the scrolling message
ldy willyYPos ; start by erasing willy so the eor draw works
lda #16 ; 16 rows from his Y
sta sizeL ; track rows in sizeL
uts1 clc
lda willyXPos ; start with his X
asl a ; * 2 for screen coordinates
adc rowL,y ; get the hires coordinates
sta writeZero+1
lda rowH,y
adc currPageH
sta writeZero+2
lda #0 ; write 4 zero-bytes to each row
ldx #3
writeZero anop
sta PLACEHOLDER,x
dex
bpl writeZero
iny ; next hi-res row
dec sizeL ; one more row done
bne uts1
lda willyFrame ; get the current frame
clc
adc #2 ; advance by 2
and #7 ; and keep in the frame range
sta willyFrame ; update the frame
jsr screenDrawWilly ; and draw willy in the new pose
;sqw printXYlh scrollIdx, #16*8, scrollPtrL, scrollPtrH, scrollLen
lda #$ff ; no color (white) is a mask of $ff left and right
sta dstPtrL
sta dstPtrL+1
lda #0 ; eor o is not inverse
sta eorMask+1 ; set the eor in the code
lda scrollPtrL ; set the string pointer in the code
sta read0+1
lda scrollPtrH
sta read0+2
ldx scrollLen ; 0 based
stx sizeL
lda scrollIdx ; and x/y coords in x and y registers
asl a
tax
ldy #16*8
jsr textShowText ; print that string
lda scrollIdx ; see if scrolled all the way into the screen
beq uts2 ; if printing at 0, then scrolled all the way in
dec scrollIdx ; not scrolled in all the way, so move the start left
inc scrollLen ; and increase the length to print by 1
bne uts3 ; and skip moving the start of the message
uts2 inc scrollPtrL ; move the scroller so the left disappears off
bne uts3 ; the left end of the screen
inc scrollPtrH
uts3 jsr uiDelay ; wait a bit so the message can be read
ldy scrollLen ; see if this is the end of the message
lda (scrollPtrL),y
bne uts4 ; if not a zero, still in message
dec scrollLen ; start printing less of the message so the tail scrolls across
bmi demoTime ; when completely done, go to demo mode
uts4 jmp mainLoop ; repeat till fully scrolled
demoTime anop
lda #DEMO_TIMER_INITAL ; set up the demo variables
sta demoTimer
lda #1
sta demoDirection
done anop
sta demoMode
rts
;-----------------------------------------------------------------------------
uiWaitForIntroEnter entry
iter equ tmpBot+0 ; how many times to loop
color equ tmpBot+1 ; the starting color for the string
xPos equ tmpBot+2 ; x for string
yPos equ tmpBot+3 ; y for string
textL equ tmpBot+4 ; string pointer
textH equ tmpBot+5
len equ tmpBot+6 ; how many characters (0 based)
lda KBDSTRB ; clear the keyboard
jsr valueSwap
printXYlh #0,#22*8,#<roTextPressEnter,#>roTextPressEnter,#19
lda #$28 ; intentionally outside the range
sta color ; it gives an interesting "materialize" effect
lda #22*8
sta yPos
cycleLoop anop
lda #6 ; print ENTER at x 4
sta xPos
lda #<roTextEnter ; point at ENTER text
sta textL
lda #>roTextEnter
sta textH
lda #5
sta len
jsr textColorCycle ; show the text in color
ldy #$40
jsr ySet
lda KBD ; hold the load screen graphic till a key is pressed
bpl cycleLoop
lda KBDSTRB ; clear the keyboard
jsr valueSwap
ldx #1 ; for clear-screen,x = 1 is all clear,x equ 0 is partial
jsr screenClear
jsr screenSwap ; swap to see page 1
ldx #1
jmp screenClear ; all clear page 2
end
;-----------------------------------------------------------------------------
RODATA data
manicText anop
dc h'88D8A888880000'
dc h'00708888F88800'
dc h'88C8A898880000'
dc h'0000E0404040E0'
dc h'00708880887000'
manicCharWidth anop
dc h'0606060405'
manicColors anop
dc h'0201000304'
;-----------------------------------------------------------------------------
minerText anop
dc h'000088D8A88888'
dc h'E0404040E00000'
dc h'0088C8A8988800'
dc h'F880F880F80000'
dc h'0000F088F0A098'
minerCharWidth anop
dc h'0604060605'
minerColors anop
dc h'0304020100'
end

48
src/variables.asm Normal file
View File

@ -0,0 +1,48 @@
;-----------------------------------------------------------------------------
; variables.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
;.segment "LOWMEM"
copy src/defs.s
; These are instance buffers for sprites / tiles. They are copied into this
; area and then masked for color from where they are rendered
LOWMEM data
levelLayout gequ $0800
levelLayoutEnd gequ levelLayout+PLAY_COLS*PLAY_ROWS ; Unpacked level (tile) info - keep 1st for alignment
; Instances for display
spriteInstances gequ levelLayoutEnd ; Instances of sprite data in a level
spriteInstancesEnd gequ spriteInstances+MAX_SPRITE_IFRAMES*SPRITE_BYTES
tilesInstances gequ spriteInstancesEnd ; instances of tiles in use bitmaps
tilesInstancesEnd gequ tilesInstances+TILES_PER_LEVEL*TILE_BYTES
keyAnimTiles gequ tilesInstancesEnd ; color instances of key tile
keyAnimTilesEnd gequ keyAnimTiles+KEYS_FRAMES*TILE_BYTES
conveyorAnimTiles gequ keyAnimTilesEnd ; instances of conveyor animated tiles
conveyorAnimTilesEnd gequ conveyorAnimTiles+CONVEYOR_FRAMES*TILE_BYTES
; cache of 8 pixel-rows for 32 double-byte characters. The level name is centered in here, and drawn from here
levelNameGfx0 gequ conveyorAnimTilesEnd
levelNameGfx0End gequ levelNameGfx0+PLAY_COLS*2*8
end
;-----------------------------------------------------------------------------
;.segment "DATA"
DATA data
; The scores are updated in these text strings directly
highScore dc c'000000'
score dc c'000000'
end

533
src/willy.asm Normal file
View File

@ -0,0 +1,533 @@
;-----------------------------------------------------------------------------
; willy.inc
; Part of manic miner, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2020
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
65816 OFF
copy src/defs.s
WILLY start
using LOWMEM
using ROSYSTEM
using ROLEVELS
;-----------------------------------------------------------------------------
; Moves willy. Incorporates user desire (userKeyMask) and conveyor direction
; in movement and does movement and collision resolution. This code was juggled a
; whole lot to make the outcome match that of the original game. It's quite
; possibly sub-optimal, but it does what it is meant to do.
willyMove entry
willyYPosBackup equ tmpBot+1
willyXPosBackup equ tmpBot+2
willyFrameBackup equ tmpBot+3
willyFloor equ tmpBot+4
lda movementMask
bit bit2Mask ; MASK_AIR
beq checkHorzKeys ; on ground - check horizontal keys
jmp selectDirection ; in air - check horizontal motion
checkHorzKeys anop
lda userKeyMask ; get the user Key
ldx conveyorMask ; and get the conveyor direction
beq notOnConveyor ; ignore conveyor code if not on a conveyor
and conveyorMask ; and user desire with conveyor
bne onConveyor ; if same, user conveyor direction for actual
lda userKeyMask ; get the user mask and
and #$FB ; <~MASK_AIR ; if it's got no horizontal component
beq onConveyor ; willy is following the conveyor
lda movementMask ; user key horiz and not same as conveyor
jmp selectDirection ; so simply keep the current movement going
onConveyor anop
lda movementMask ; actual is now conveyor direction
and #$FC ;<~(MASK_LEFT | MASK_RIGHT) ; clear current
ora conveyorMask ; add conveyor direction
sta movementMask ; store as actual
jmp selectDirection ; use the conveyor for sideways
notOnConveyor anop
and #$FB ; <~MASK_AIR ; clear the jump desire
sta movementMask ; make actual user desire
selectDirection anop
and #3 ;(MASK_LEFT | MASK_RIGHT) ; see if willy is moving horizontally
bne wm00 ; yes - handle horizontal movement
jmp vertical
wm00 and #MASK_RIGHT ; check MASK_RIGHT
bne right ; if set, move to the right
left anop
lda willyDir ; see if already heading left
bne moveLeft ; if so, keep moving left
lda #0 ; when turning, no direction
sta movementMask
lda #1 ; was facing right, so turn around
sta willyDir
lda willyFrame ; flip the facing frame to left
ora #4
sta willyFrame
bne vertical
moveLeft anop
ldx willyFrame ; get the frame
stx willyFrameBackup ; back it up
dex ; move one left
cpx #4 ; wrapped?
bcc wm01 ; yes, move to previous column
stx willyFrame ; not wrapped, save the frame
bcc wm01
jmp vertical
wm01 ldx #7 ; keep going, load right most frame
stx willyFrame ; set frame
ldx willyXPos ; get the column
stx willyXPosBackup ; save it
dex ; previous column
stx willyXPos ; make that current
ldy #0 ; check side (left) collisions column
beq hCollision ; BRA
right anop
lda willyDir ; see if willy's already facing right
beq moveRight ; if so, move
lda #0 ; turn willy to the right
sta willyDir
sta movementMask ; and clear the movement mask
lda willyFrame
and #3 ; set right facing frame
sta willyFrame
jmp vertical
moveRight anop
ldx willyFrame ; back up the animation frame
stx willyFrameBackup
inx ; next frame (to the right)
cpx #4 ; wrapped?
bcs wm02 ; yes, move to next (right) column
stx willyFrame ; save the frame
bcc vertical
wm02 ldx #0
stx willyFrame ; set frame 0
ldx willyXPos ; back up the column
stx willyXPosBackup
inx ; move right
stx willyXPos ; save this column
ldy #1 ; check the right-hand column for collisions
hCollision anop
jsr willySetWorldPtr ; set up the world pointer to check collisions
ldx #2 ; assume checking 2 rows
lda willyYPos ; get the height in pixels
and #7 ; see if willy is aligned
beq colLoop ; yes, go with 2 rows
inx ; if not aligned, willy crosses 3 rows
colLoop anop
lda (srcPtrL),y ; load the world byte
beq wm03 ; if air then no collision
jsr willyWorldCollision ; resolve the collision if needed
bcc wm03 ; if carry clear, can move (didn't hit a wall)
lda willyXPosBackup ; hit a wall, so restore position (column)
sta willyXPos
lda willyFrameBackup ; and also restore the frame
sta willyFrame
jmp vertical
wm03 tya ; Y is 0 or 1 (left or right), put in a
adc #32 ; move down a row
tay ; and put back in y
dex ; x has the number of rows remaining to check
bne colLoop ; do till all rows checked
vertical anop
lda movementMask
bit bit2Mask ; MASK_AIR
bne vertMove ; in the air already then move vertically
lda userKeyMask ; get the user desire
bit bit2Mask ; MASK_AIR see if user wants to jump
beq willyCollisionFeet ; if not then check feet
and #$FB ; <~MASK_AIR ; clear jump from desire
sta userKeyMask ; and save
lda movementMask ; update actual
ora #MASK_AIR ; by adding a jump
sta movementMask
lda #1 ; mark this as a fall starting
sta willyFallFromJump ; from a jump - willy dies easier
vertMove anop
lda willyYPos ; save the current Y position
sta willyYPosBackup
lda willyJumpCounter ; get the current jump counter for height calculation
cmp #18 ; see sbc #4 below for why 18 (up/down curve length)
bcs falling ; if jump counter gt 17 then falling (0-17 is jump)
lsr a ; / 2
sec
sbc #4 ; -4, so -4, -4, -3, -3, -2, -2, -1, -1, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4
clc
adc willyYPos ; adjust willy height
sta willyYPos
ldx willyJumpCounter ; get the current jump counter for height calculation
lda jumpFreq,x
ldy #$08 ; duration for the freq
jsr freq ; make a sound of this freq and duration
inc willyJumpCounter
lda willyJumpCounter
cmp #9
bcs willyCollisionFeet ; and move the jump counter along
willyCollisionTop anop
lda willyYPosBackup ; see where willy was
and #7 ; if aligned with a row, now entering a new row so check collision
bne willyCollisionFeet ; not aligned, no collision, go to feet check
jsr willySetWorldPtr ; set the srcPtr to point into the world
ldy #0 ; start with the head left
lda (srcPtrL),y ; read the world byte
beq wm04 ; if air then do nothing
jsr willyWorldCollision ; not air so handle the potential collision
bcs hitHead ; carry set means wall collision, so fall
wm04 ldy #1 ; check the right as well
lda (srcPtrL),y
beq willyCollisionFeet ; if air, ignore
jsr willyWorldCollision
bcc willyCollisionFeet ; carry clear means no collision
hitHead anop
lda willyYPosBackup
sta willyYPos
lda #18
sta willyJumpCounter
jmp willyCollisionFeet ; and check for landing immediately
falling anop
lda willyJumpCounter ; get the current jump counter for height calculation
and #$0f
tax
lda fallFreq,x
ldy #$08 ; duration for the freq
jsr freq ; make a sound of this freq and duration
inc willyJumpCounter ; and move the jump counter along
lda movementMask ; strip horizontal from actual
and #$FC ; <~(MASK_LEFT | MASK_RIGHT)
sta movementMask
lda willyYPos ; get willy's height
clc
adc #4 ; move him 4 down (fall speed)
sta willyYPos
willyCollisionFeet anop
lda #0 ; assume not on a conveyor
sta conveyorMask
lda willyYPos ; see if willy is level with a floor
and #7
bne positionScreen ; if not, don't check the feet
lda willyJumpCounter ; see if still going up in jump
beq wm05 ; if 0 then not jumping
cmp #10 ; if still going up in the jump, don't check the feet
bcc positionScreen
wm05 jsr willySetWorldPtr ; set up the world pointer
ldy #64 ; check the ground below willy, left
lda (srcPtrL),y
sta willyFloor ; store the byte
beq wm06 ; if air, don't resolve
jsr willyFloorCollision ; resolve the collision
wm06 ldy #65 ; check the floor right
lda (srcPtrL),y
beq checkFloor ; if air, done with feet
tax ; save the byte
ora willyFloor ; and update the floor
sta willyFloor
txa ; restore the world byte
jsr willyFloorCollision ; and resolve it
checkFloor anop
lda willyFloor ; was there something under willy's feet
bne positionScreen ; if yes, then position willy
lda willyJumpCounter ; see if willy is in a jump or fall
bne positionScreen ; yes, position screen
lda #18 ; willy was walking, so set him to fall
sta willyJumpCounter
lda movementMask ; strip horizontal from actual
and #$FC ; <~(MASK_LEFT | MASK_RIGHT) ; clear left and right
ora #MASK_AIR ; set the mask that he's now in the air (fall)
sta movementMask
positionScreen entry ; this is also called from gameInitStage
lda cameraMode ; see which "camera mode" is active
bne cameraScroll ; non zero is scroll mode
camera3Zone anop ; zone 1: 0-19, 2: 6-25, 3: 12-31
lda willyXPos ; see where Willy is
cmp #10 ; 10 divides zones 1 and 2
bcs zone2or3 ; ge 10 means zone 2 or 3
lda leftEdge ; zone 1 - see where the edge is
cmp #0 ; if it's at 0 all is well
beq done0
cameraLess anop
dec leftEdge ; edge is gt 0, so move it left
bpl moveName ; BRA
zone2or3 anop
cmp #20 ; 20 divides zones 2 and 3
bcs cameraRight ; ge 20 means zone 3
lda leftEdge ; see where the edge is (in zone 2)
cmp #6 ; zone 2 edge wants to be at 6
beq done0 ; if it's there, all is well
bcs cameraLess ; if it's gt 6, then move it left
inc leftEdge ; move the edge right
bne moveName ; BRA
cameraRight anop
lda leftEdge ; zone 3, see where the edge is
cmp #$0c ; if it's at 12
beq done0 ; then it's all good
inc leftEdge ; otherwise move it right towards 12
moveName anop ; if the edge moves the text needs to move as well
lda #UI_COMPONENT_NAME ; and mark the name as needing to scroll too
jsr uiUpdateComponent
rts
cameraScroll anop
lda willyXPos
sec ; col is in accumulator
sbc #$0a ; see if willy is past column 10
bcs wm07
lda #0 ; not, so set the left edge to the left
bne wm08 ; BRA
wm07 cmp #$0d ; see if the col is less than 13
bcc wm08
lda #$0c ; col is 13 or greater, so clamp to 12
wm08 cmp leftEdge ; see if the edge needs to move
beq done0 ; don't move
sta leftEdge ; set the new left edge
lda #UI_COMPONENT_NAME ; and mark the name as needing to scroll too
jsr uiUpdateComponent
done0 anop
rts ; done with willy's movement
;-----------------------------------------------------------------------------
; resolves collisions for willy. Used by feet but foot collision entry is
; from willyFloorCollision. on exit, carry set means wall collision
willyWorldCollision entry
clc
cmp #DATA_BUSH ; bushes kill willy
beq willyDies
cmp #DATA_ROCK ; rocks kill willy
bne wwc0
willyDies entry
lda #EVENT_DIED ; simply set the die event
ora eventState
sta eventState
rts
wwc0 cmp #DATA_WALL ; walls block willy
bne wwc1
rts ; carry was set by the cmp and equality. set means wall collision
wwc1 cmp #DATA_KEY ; key's need to be counted
bne wwc2
jmp willyHitKey ; clears carry
wwc2 cmp #DATA_DOOR ; added dynamically when last key found
bne wwc3
lda #EVENT_NEXT_LEVEL ; set event to move to next cavern/level
ora eventState
sta eventState
rts
wwc3 cmp #DATA_SWITCH1 ; added at level init for kong screens
bne wwc4
jmp willyHitSwitch1
wwc4 cmp #DATA_SWITCH2 ; added at level init for kong screens
bne done1
jmp willyHitSwitch2
done1 anop
clc ; for unhandled (floor tiles), just clear carry
rts
;-----------------------------------------------------------------------------
willyFloorCollision entry
cmp #DATA_FLOOR1 ; floors are landed on
beq landed
cmp #DATA_WALL ; walls can be walked on
beq landed
cmp #DATA_FLOOR2 ; special can be walked on
bne wfc0
landed anop
lda movementMask ; see landing from a jump/fall
and #MASK_AIR
beq notFromAir ; just a foot-fall from walking, no action
clc
lda willyFallFromJump ; see if a jump
adc willyJumpCounter ; and how far
cmp #18+9 ; compare to death height
bcc fellNotTooFar ; not too far
jmp willyDies ; fell to far, kill willy
fellNotTooFar anop
lda #0 ; reset the fall from jump
sta willyFallFromJump
sta willyJumpCounter ; and reset the willy jump counter
lda #$FB ; <~MASK_AIR ; clear the air bit
and movementMask
sta movementMask
notFromAir anop
rts
wfc0 cmp #DATA_CONVEYOR ; landed on a conveyor
bne wfc1
ldx currLevel ; get the level
lda conveyorDirections,x ; get the direction of the conveyor
sta conveyorMask ; set it as the conveyor mask (which is reset each frame)
bne landed ; and do landing code
wfc1 cmp #DATA_COLLAPSE ; check for collapsing tiles
bcc willyWorldCollision ; less than, not collapsing
cmp #DATA_COLLAPSE+9 ; in the collapse range
bcs willyWorldCollision ; no, check non-walk/floor tiles
jsr willyCollapse ; collapse a platform tile, returns with carry clear
bcc landed ; BRA to land code
;-----------------------------------------------------------------------------
willyHitSwitch1 entry
clc
adc #1 ; DATA_SWITCH1 becomes DATA_SWITCH1_OPEN
sta (srcPtrL),y ; make this switch draw open
lda #0
sta levelLayout+11*32+17 ; make a hole in the wall
sta levelLayout+12*32+17
ldx #1 ; sprite 1 barrel needs to go further
lda #19 ; this is the new max for return-kong
extend anop
sta spriteMax,x ; make the new max active
clc ; must leave with carry clear - not a wall collision
rts
;-----------------------------------------------------------------------------
willyHitSwitch2 entry
clc
adc #1 ; DATA_SWITCH2 becomes DATA_SWITCH2_OPEN
sta (srcPtrL),y ; make this switch draw open
lda #0
sta levelLayout+2*32+15 ; remove kong's platform
sta levelLayout+2*32+16
ldx #3 ; kong is at index 3
lda #14*8-5 ; put the fallen-down destination for kong in place
sta spriteMax,x
lda #2 ; turn kong upside down
sta spriteFrame,x
lda #0 ; set kong's direction to down
sta spriteDir,x
rts
;-----------------------------------------------------------------------------
willyCollapse entry
clc
adc #1 ; move the tile-top one down
cmp #DATA_COLLAPSE+7 ; is it all the way down
bcc wc00 ; not yet
lda #0 ; yes, so erase the tile
clc
wc00 sta (srcPtrL),y ; make the change in the level
rts
;-----------------------------------------------------------------------------
willyHitKey entry
tempX equ tmpBot+5
stx tempX ; save x - it may be an index in left/right col
lda #0 ; erase the key tile in the level
sta (srcPtrL),y
ldx #3 ; add 100 (digit 3 of 6, zero based 000100)
lda #1
jsr textAddScore
dec keysToCollect ; 1 less key to collect
bne done2 ; all keys collected?
ldx currLevel ; get the level
lda doorL,x ; get the door location in the level (lo)
sta putDoor+1
lda doorH,x ; and hi
sta putDoor+2
lda #DATA_DOOR ; get the door tile
putDoor anop
sta PLACEHOLDER ; and add the door tile to the level
done2 anop
ldx tempX ; restore the saved x
clc ; make sure carry is clear
rts
;-----------------------------------------------------------------------------
willySetWorldPtr entry
lda willyYPos ; get the height
lsr a ; divide by 8
lsr a
lsr a
sta willyYRow ; save the row willy's in
tax ; put the row in Y
clc
lda mult32L,x ; row * 32
adc willyXPos ; and add the X position (levelLayout is aligned so no need to add lo)
sta srcPtrL ; the low byte of the pos in the level
lda mult32H,x ; get the high byte
adc #>levelLayout ; and offset into the level
sta srcPtrH ; and now srcPtr points at willy in the level
rts
end