mminer-orca/src/tiles.asm

444 lines
23 KiB
NASM

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