mminer-orca/src/ui.asm

450 lines
28 KiB
NASM

;-----------------------------------------------------------------------------
; 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