Add flicker-free planets, temporarily using sights sprite space

This commit is contained in:
Mark Moxon 2023-02-28 11:49:58 +00:00
commit 1879df09ab
2 changed files with 692 additions and 9 deletions

View file

@ -41,10 +41,9 @@ GUARD &CE00 \ Guard against assembling over memory used by game
\
\ ******************************************************************************
XX1 = $0009
XX1 = $0009 \ Variables for flicker-free ships
INWK = $0009
XX19 = $002A
CNT = $0030
K3 = $0035
K4 = $0043
XX0 = $0057
@ -56,14 +55,35 @@ X2 = $006D
Y2 = $006E
XX12 = $0071
XX17 = $009F
CNT = $00AA
XX4 = $00AD
XX20 = $00AE
XX14 = $00FB
PROJ = $860F \ Note, this is not equal to $7D1F + $0900
PROJ = $7D1F + $08F0
LL75 = $9FB8 + $0900
LL30 = $B49D \ Note, this is not equal to $AB91 + $0900
LL30 = $AB91 + $090C
Y = 72
K = $0077 \ Variables for flicker-free planets
LSP = $007E
K5 = $0085
K6 = $0089
XX13 = $00A2
TYPE = $00A5
FLAG = $00A9
CNT2 = $00AB
STP = $00AC
T = $00BB
SWAP = $06F4
LSX2 = $26A4 - 3
LSY2 = $27A4 - 3
PL9_2 = $7DA4 + $08F0
PL26 = $7DE0 + $08F0
PLL4 = $7E5F + $08F0
CIRCLE = $8044 + $08F0
WP1 = $80F5 + $08F0
LL145 = $A013 + $0900
\ ******************************************************************************
\
\ Name: SHPPT
@ -263,7 +283,259 @@ ORG $A178 + $0900
SAVE "ll155-plus4.bin", LL155, P%
ORG $7240
\ ******************************************************************************
\
\ Name: BLINE
\ Type: Subroutine
\ Category: Drawing circles
\ Summary: Draw a circle segment and add it to the ball line heap
\
\ ******************************************************************************
ORG $2977 - 3
GUARD $2A12 - 3
.BLINE
TXA \ Set K6(3 2) = (T X) + K4(1 0)
ADC K4 \ = y-coord of centre + y-coord of new point
STA K6+2 \
LDA K4+1 \ so K6(3 2) now contains the y-coordinate of the new
ADC T \ point on the circle but as a screen coordinate, to go
STA K6+3 \ along with the screen y-coordinate in K6(1 0)
LDA FLAG \ If FLAG = 0, jump down to BL1
BEQ BL1
INC FLAG \ Flag is &FF so this is the first call to BLINE, so
\ increment FLAG to set it to 0, as then the next time
\ we call BLINE it can draw the first line, from this
\ point to the next
.BL5
JSR DrawPlanetLine \ Draw the current line from the old planet
\ The following inserts a &FF marker into the LSY2 line
\ heap to indicate that the next call to BLINE should
\ store both the (X1, Y1) and (X2, Y2) points. We do
\ this on the very first call to BLINE (when FLAG is
\ &FF), and on subsequent calls if the segment does not
\ fit on-screen, in which case we don't draw or store
\ that segment, and we start a new segment with the next
\ call to BLINE that does fit on-screen
LDY LSP \ If byte LSP-1 of LSY2 = &FF, jump to BL7 to tidy up
LDA #&FF \ and return from the subroutine, as the point that has
CMP LSY2-1,Y \ been passed to BLINE is the start of a segment, so all
BEQ BL7 \ we need to do is save the coordinate in K5, without
\ moving the pointer in LSP
STA LSY2,Y \ Otherwise we just tried to plot a segment but it
\ didn't fit on-screen, so put the &FF marker into the
\ heap for this point, so the next call to BLINE starts
\ a new segment
INC LSP \ Increment LSP to point to the next point in the heap
BNE BL7 \ Jump to BL7 to tidy up and return from the subroutine
\ (this BNE is effectively a JMP, as LSP will never be
\ zero)
.BL1
LDA K5 \ Set XX15 = K5 = x_lo of previous point
STA XX15
LDA K5+1 \ Set XX15+1 = K5+1 = x_hi of previous point
STA XX15+1
LDA K5+2 \ Set XX15+2 = K5+2 = y_lo of previous point
STA XX15+2
LDA K5+3 \ Set XX15+3 = K5+3 = y_hi of previous point
STA XX15+3
LDA K6 \ Set XX15+4 = x_lo of new point
STA XX15+4
LDA K6+1 \ Set XX15+5 = x_hi of new point
STA XX15+5
LDA K6+2 \ Set XX12 = y_lo of new point
STA XX12
LDA K6+3 \ Set XX12+1 = y_hi of new point
STA XX12+1
JSR LL145 \ Call LL145 to see if the new line segment needs to be
\ clipped to fit on-screen, returning the clipped line's
\ end-points in (X1, Y1) and (X2, Y2)
BCS BL5 \ If the C flag is set then the line is not visible on
\ screen anyway, so jump to BL5, to avoid drawing and
\ storing this line
LDA SWAP \ If SWAP = 0, then we didn't have to swap the line
BEQ BL9 \ coordinates around during the clipping process, so
\ jump to BL9 to skip the following swap
LDA X1 \ Otherwise the coordinates were swapped by the call to
LDY X2 \ LL145 above, so we swap (X1, Y1) and (X2, Y2) back
STA X2 \ again
STY X1
LDA Y1
LDY Y2
STA Y2
STY Y1
.BL9
LDY LSP \ Set Y = LSP
LDA LSY2-1,Y \ If byte LSP-1 of LSY2 is not &FF, jump down to BL8
CMP #&FF \ to skip the following (X1, Y1) code
BNE BL8
\ Byte LSP-1 of LSY2 is &FF, which indicates that we
\ need to store (X1, Y1) in the heap
JSR DrawPlanetLine \ Draw the current line from the old planet
LDA X1 \ Store X1 in the LSP-th byte of LSX2
STA LSX2,Y
LDA Y1 \ Store Y1 in the LSP-th byte of LSY2
STA LSY2,Y
INY \ Increment Y to point to the next byte in LSX2/LSY2
.BL8
LDA #&FF \ Set bit 7 of K3+8 so we do not draw the current line
STA K3+8 \ in the call to DrawPlanetLine, but store the
\ coordinates so we we can check them below
JSR DrawPlanetLine+4 \ Calculate the current line from the old heap, but do
\ not draw it, but store the coordinates (X1, Y1) and
\ (X2, Y2) in K3+4 to K3+7
LDA X2 \ Store X2 in the LSP-th byte of LSX2
STA LSX2,Y
LDA Y2 \ Store Y2 in the LSP-th byte of LSX2
STA LSY2,Y
INY \ Increment Y to point to the next byte in LSX2/LSY2
STY LSP \ Update LSP to point to the same as Y
JSR DrawNewPlanetLine \ Draw a line from (X1, Y1) to (X2, Y2), but only if it
\ is different to the old line in K3+4 to K3+7
LDA XX13 \ If XX13 is non-zero, jump up to BL5 to add a &FF
BNE BL5 \ marker to the end of the line heap. XX13 is non-zero
\ after the call to the clipping routine LL145 above if
\ the end of the line was clipped, meaning the next line
\ sent to BLINE can't join onto the end but has to start
\ a new segment, and that's what inserting the &FF
\ marker does
.BL7
LDA K6 \ Copy the data for this step point from K6(3 2 1 0)
STA K5 \ into K5(3 2 1 0), for use in the next call to BLINE:
LDA K6+1 \
STA K5+1 \ * K5(1 0) = screen x-coordinate of this point
\LDA K6+2 \
\STA K5+2 \ * K5(3 2) = screen y-coordinate of this point
\LDA K6+3 \
\STA K5+3 \ They now become the "previous point" in the next call
JMP PATCH3 \ Jump to patch to implement the commented out
\ instructions above, plus the rest of the routine
SAVE "bline-plus4.bin", BLINE, P%
\ ******************************************************************************
\
\ Name: PL9 (Part 1 of 3)
\ Type: Subroutine
\ Category: Drawing planets
\ Summary: Draw the planet, with either an equator and meridian, or a crater
\
\ ******************************************************************************
ORG $7D8C + $08F0
GUARD $7DA4 + $08F0
.PL9
JSR CIRCLE \ Call CIRCLE to draw the planet's new circle
BCS PL20A \ If the call to CIRCLE returned with the C flag set,
\ then the circle does not fit on-screen, so jump to
\ PL20A to remove the planet from the screen and return
\ from the subroutine
LDA K+1 \ If K+1 is zero, jump to PL25 as K(1 0) < 256, so the
BEQ PL25 \ planet fits on the screen and we can draw meridians or
\ craters
.PL20
JMP EraseRestOfPlanet \ We have drawn the new circle, so now we need to erase
\ any lines that are left in the ball line heap, before
\ returning from the subroutine using a tail call
.PL20A
JMP WPLS2 \ Call WPLS2 to remove the planet from the screen
.PL25
LDA $1D0F \ Skip craters and meridians if not configured
BEQ PL20
JMP PATCH6 \ Jump to PATCH6 for the rest of the routine
SAVE "pl9-plus4.bin", PL9, P%
\ ******************************************************************************
\
\ Name: WPLS2
\ Type: Subroutine
\ Category: Drawing planets
\ Summary: Remove the planet from the screen
\
\ ******************************************************************************
ORG $80BB + $08F0
GUARD $80F5 + $08F0
.WPLS2
LDY LSX2 \ If LSX2 is non-zero (which indicates the ball line
BNE WP1 \ heap is empty), jump to WP1 to reset the line heap
\ without redrawing the planet
STY XX14 \ Reset XX14 to the start of the ball line heap (we can
\ set this to 0 rather than 1 to take advantage of the
\ fact that Y is 0 - the effect is the same)
LDA LSP \ Set XX14+1 to the end of the ball line heap
STA XX14+1
JSR EraseRestOfPlanet \ Draw the contents of the ball line heap to erase the
\ old planet
JMP WP1 \ Reset the ball line heap and return from the
\ subroutine using a tail call
SAVE "wpls2-plus4.bin", WPLS2, P%
\ ******************************************************************************
\
@ -274,6 +546,10 @@ ORG $7240
\
\ ******************************************************************************
ORG $7100
GUARD $7300
.LLX30
LDY XX14 \ Set Y = XX14, to get the offset within the ship line
@ -423,6 +699,314 @@ ORG $7240
JMP LL78 \ Jump down to part 11
\ ******************************************************************************
\
\ Name: EraseRestOfPlanet
\ Type: Subroutine
\ Category: Drawing lines
\ Summary: Draw all remaining lines in the ball line heap to erase the rest
\ of the old planet
\
\ ******************************************************************************
.EraseRestOfPlanet
LDY XX14 \ Set Y to the offset in XX14, which points to the part
\ of the heap that we are overwriting with new points
CPY XX14+1 \ If XX14 >= XX14+1, then we have already redrawn all of
BCS eras1 \ the lines from the old circle's ball line heap, so
\ skip the following
JSR DrawPlanetLine \ Erase the next planet line from the ball line heap
JMP EraseRestOfPlanet \ Loop back for the next line in the ball line heap
.eras1
RTS \ Return from the subroutine
\ ******************************************************************************
\
\ Name: DrawPlanetLine
\ Type: Subroutine
\ Category: Drawing lines
\ Summary: Draw a segment of the old planet from the ball line heap
\
\ ------------------------------------------------------------------------------
\
\ Other entry points:
\
\ DrawPlanetLine+4 If bit 7 of K3+8 is set, store the line coordinates in
\ K3+4 to K3+7 (X1, Y1, X2, Y2) and do not draw the line
\
\ ******************************************************************************
.DrawPlanetLine
LDA #0 \ Clear bit 7 of K3+8 so we draw the current line below
STA K3+8
LDA #0 \ Clear bit 7 of K3+9 to indicate that there is no line
STA K3+9 \ to draw (we may change this below)
LDA XX14 \ If XX14 = 1, then this is the first point from the
CMP #2 \ heap, so jump to plin3 to set the previous coordinate
BCC plin3 \ and return from the subroutine
LDA X1 \ Save X1, X2, Y1, Y2 and Y on the stack
PHA
LDA Y1
PHA
LDA X2
PHA
LDA Y2
PHA
TYA
PHA
LDY XX14 \ Set Y to the offset in XX14, which points to the part
\ of the heap that we are overwriting with new points
CPY XX14+1 \ If XX14 >= XX14+1, then we have already redrawn all of
BCS plin1 \ the lines from the old circle's ball line heap, so
\ jump to plin1 to return from the subroutine
\ Otherwise we need to draw the line from the heap, to
\ erase it from the screen
LDA K3+2 \ Set X1 = K3+2 = screen x-coordinate of previous point
STA X1 \ from the old heap
LDA K3+3 \ Set Y1 = K3+3 = screen y-coordinate of previous point
STA Y1 \ from the old heap
LDA LSX2,Y \ Set X2 to the y-coordinate from the XX14-th point in
STA X2 \ the heap
STA K3+2 \ Store the x-coordinate of the point we are overwriting
\ in K3+2, so we can use it on the next iteration
LDA LSY2,Y \ Set Y2 to the y-coordinate from the XX14-th point in
STA Y2 \ the heap
STA K3+3 \ Store the y-coordinate of the point we are overwriting
\ in K3+3, so we can use it on the next iteration
INC XX14 \ Increment XX14 to point to the next coordinate, so we
\ work our way through the current heap
LDA Y1 \ If Y1 or Y2 = &FF then this indicates a break in the
CMP #&FF \ circle, so jump to plin1 to skip the following and
BEQ plin1 \ return from the subroutine, asthere is no line to
LDA Y2 \ erase
CMP #&FF
BEQ plin1
DEC K3+9 \ Decrement K3+9 to &FF to indicate that there is a line
\ to draw
BIT K3+8 \ If bit 7 of K3+8 is set, jump to plin2 to store the
BMI plin2 \ line coordinates rather than drawing the line
JSR LL30 \ The coordinates in (X1, Y1) and (X2, Y2) that we just
\ pulled from the ball line heap point to a line that is
\ still on-screen, so call LL30 to draw this line and
\ erase it from the screen
.plin1
PLA \ Restore Y, X1, X2, Y1 and Y2 from the stack
TAY
PLA
STA Y2
PLA
STA X2
PLA
STA Y1
PLA
STA X1
RTS \ Return from the subroutine
.plin2
LDA X1 \ Store X1, Y1, X2, Y2 in K3+4 to K3+7
STA K3+4
LDA Y1
STA K3+5
LDA X2
STA K3+6
LDA Y2
STA K3+7
JMP plin1 \ Jump to plin1 to return from the subroutine
.plin3
LDA LSX2+1 \ Store the heap's first coordinate in K3+2 and K3+3
STA K3+2
LDA LSY2+1
STA K3+3
INC XX14 \ Increment XX14 to point to the next coordinate, so we
\ work our way through the current heap
RTS \ Return from the subroutine
\ ******************************************************************************
\
\ Name: DrawNewPlanetLine
\ Type: Subroutine
\ Category: Drawing lines
\ Summary: Draw a ball line, but only if it is different to the old line
\
\ ------------------------------------------------------------------------------
\
\ Arguments:
\
\ K3+4 to K3+7 The (X1, Y1) and (X2, Y2) coordinates of the old line
\
\ ******************************************************************************
.DrawNewPlanetLine
BIT K3+9 \ If bit 7 of K3+9 is clear, then there is no old line
BPL nlin2 \ to draw, so jump to nlin2 to draw the new line only
LDA K3+4 \ If the old line equals the new line, jump to nlin3
CMP X1 \ to skip drawing both lines
BNE nlin1
LDA K3+5
CMP Y1
BNE nlin1
LDA K3+6
CMP X2
BNE nlin1
LDA K3+7
CMP Y2
BEQ nlin3
.nlin1
\ If we get here then the old line is differnt to the new
\ line, so we draw them both
JSR LL30 \ Draw the new line from (X1, Y1) to (X2, Y2)
LDA K3+4 \ Set up the old line's coordinates
STA X1
LDA K3+5
STA Y1
LDA K3+6
STA X2
LDA K3+7
STA Y2
.nlin2
JSR LL30 \ Draw the old line to erase it
.nlin3
RTS \ Return from the subroutine
\ ******************************************************************************
\
\ Name: BLINE
\ Type: Subroutine
\ Category: Drawing circles
\ Summary: Draw a circle segment and add it to the ball line heap
\
\ ******************************************************************************
.PATCH3
\ These are the instructions from the end of BLINE that
\ we move here so there's room for the patch
LDA K6+2 \
STA K5+2 \ * K5(3 2) = screen y-coordinate of this point
LDA K6+3 \
STA K5+3 \ They now become the "previous point" in the next call
LDA CNT \ Set CNT = CNT + STP
CLC
ADC STP
STA CNT
RTS \ Return from the subroutine
\ ******************************************************************************
\
\ Name: PLS22
\ Type: Subroutine
\ Category: Drawing planets
\ Summary: Draw an ellipse or half-ellipse
\
\ ******************************************************************************
.PATCH4
\ We replace the following instruction just before PL40
\ in PLS22 with JMP PATCH4, so we now do this
\ instruction to ensure that it still gets done
STA CNT2 \ Set CNT2 = (CNT2 + STP) mod 64
JMP PLL4 \ Jump back to PLL4 to draw the next segment
\ ******************************************************************************
\
\ Name: CIRCLE2
\ Type: Subroutine
\ Category: Drawing circles
\ Summary: Draw a circle (for the planet or chart)
\ Deep dive: Drawing circles
\
\ ******************************************************************************
.PATCH5
LDX #0 \ Set XX14 = 0, to point to the offset before the first
STX XX14 \ set of circle coordinates in the ball line heap
LDX LSP \ Set XX14+1 to the last byte of the ball line heap
STX XX14+1
LDX #1 \ Set LSP = 1 to reset the ball line heap pointer
STX LSP
\ We replace the following instructions at CIRCLE2 with
\ JSR PATCH5, so we now do those two instructions to
\ ensure that they still get done
LDX #&FF \ Set FLAG = &FF to reset the ball line heap in the call
STX FLAG \ to the BLINE routine below
RTS \ Return from the subroutine
\ ******************************************************************************
\
\ Name: PL9 (Part 1 of 3)
\ Type: Subroutine
\ Category: Drawing planets
\ Summary: Draw the planet, with either an equator and meridian, or a crater
\
\ ******************************************************************************
.PATCH6
LDA TYPE \ If the planet type is 128 then it has an equator and
CMP #128 \ a meridian, so this jumps to PL26 if this is not a
BNE P%+5 \ planet with an equator - in other words, if it is a
\ planet with a crater
JMP PL9_2 \ Otherwise this is a planet with an equator and
\ meridian, so jump to the equator routine in part 2 of
\ PL9
JMP PL26 \ Jump to the crater routine
SAVE "extra-plus4.bin", LLX30, P%

View file

@ -89,9 +89,9 @@ print("[ Read ] elite_+4_unpacked.prg")
# Set the addresses for the extra routines (LLX30, PATCH1, PATCH2) that we will
# load into unused portiong of the main game code
llx30 = 0x7240
patch1 = 0x727E
patch2 = 0x7295
llx30 = 0x7100
patch1 = 0x713E
patch2 = 0x7155
# We now modify the code to implement flicker-free ship drawing. The code
# changes are described here, which can be read alongside the following:
@ -309,8 +309,107 @@ insert_binary_file(data_block, 0xA178 + 0x900, "ll155-plus4.bin")
# LLX30
# PATCH1
# PATCH2
#
# PATCH3
# PATCH4
# PATCH5
# PATCH6
insert_binary_file(data_block, 0x7240, "extra-plus4.bin")
insert_binary_file(data_block, 0x7100, "extra-plus4.bin")
# We now move on to the routines for drawing flicker-free planets
# Set the addresses for the extra routines (EraseRestOfPlanet, PATCH4, PATCH5)
# that we inserted above
erasep = 0x715B
patch4 = 0x7229
patch5 = 0x722E
# PL9 (Part 1 of 3)
#
# We have already assembled the modified part 1 of PL9 in BeebAsm and saved
# it as the binary file pl9.bin, so now we drop this over the top of the
# existing routine (the new routine is slightly bigger, so it ends by jumping
# to PATCH6, which contains the spill-over).
insert_binary_file(data_block, 0x7D8C + 0x8F0, "pl9-plus4.bin")
# PL9 (Part 2 of 3)
#
# The above modification moves PL20, so we need to modify the branch instruction
# at the start of part 2 of PL9.
insert_bytes(data_block, 0x7DA8 + 0x8F0, [
0x90, 0xEB # BCC PL20
])
# PL9 (Part 3 of 3)
#
# The above modification moves PL20, so we need to modify the branch instruction
# at the start of part 3 of PL9.
insert_bytes(data_block, 0x7DE2 + 0x8F0, [
0x30, 0xB1 # BMI PL20
])
# WPLS2
#
# We have already assembled the modified WPLS2 in BeebAsm and saved it as
# the binary file wpls2.bin, so now we drop this over the top of the
# existing routine (which is quite a bit longer, so there is room).
insert_binary_file(data_block, 0x80BB + 0x8F0, "wpls2-plus4.bin")
# PLS22
#
# This is the modification on either side of PL40, with the label moving two
# bytes backwards to accommodate the modified code.
#
# From: BCS PL40
# ...
# STA CNT2
# JMP PLL4
# .PL40
# RTS
#
# To: BCS PL40
# ...
# JMP PATCH4
# .PL40
# JMP EraseRestOfPlanet
insert_bytes(data_block, 0x7F04 + 0x8F0, [
0xB0, 0x0A # BCS PL40
])
insert_bytes(data_block, 0x7F0D + 0x8F0, [
0x4C, patch4 % 256, patch4 // 256, # JMP PATCH4
0x4C, erasep % 256, erasep // 256 # JMP EraseRestOfPlanet
])
# CIRCLE2
#
# This is the modification at the start of the routine.
#
# From: LDX #&FF
# STX FLAG
#
# To: JSR PATCH5
# NOP
insert_bytes(data_block, 0x805E + 0x8F0, [
0x20, patch5 % 256, patch5 // 256 # JSR PATCH5
])
insert_nops(data_block, 0x8061 + 0x8F0, 1)
# BLINE
#
# We have already assembled the modified BLINE in BeebAsm and saved it as the
# binary file bline.bin, so now we drop this over the top of the existing
# routine (the new routine is slightly bigger, so it ends by jumping to PATCH3,
# which contains the spill-over).
insert_binary_file(data_block, 0x2974, "bline-plus4.bin")
# All the modifications are done, so write the output file for the modified PRG