Initial commit
This commit is contained in:
commit
3049dc938c
38 changed files with 1191 additions and 0 deletions
17
.gitattributes
vendored
Normal file
17
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Auto detect text files and perform LF normalization
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
# Custom for Visual Studio
|
||||||
|
*.cs diff=csharp
|
||||||
|
|
||||||
|
# Standard to msysgit
|
||||||
|
*.doc diff=astextplain
|
||||||
|
*.DOC diff=astextplain
|
||||||
|
*.docx diff=astextplain
|
||||||
|
*.DOCX diff=astextplain
|
||||||
|
*.dot diff=astextplain
|
||||||
|
*.DOT diff=astextplain
|
||||||
|
*.pdf diff=astextplain
|
||||||
|
*.PDF diff=astextplain
|
||||||
|
*.rtf diff=astextplain
|
||||||
|
*.RTF diff=astextplain
|
||||||
23
.gitignore
vendored
Normal file
23
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
Desktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
# Project files
|
||||||
|
.vscode/tasks.json
|
||||||
|
work/
|
||||||
129
README.md
Normal file
129
README.md
Normal file
File diff suppressed because one or more lines are too long
71
build.sh
Executable file
71
build.sh
Executable file
|
|
@ -0,0 +1,71 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Set up program locations (change these if they are not aleady in the path)
|
||||||
|
beebasm="beebasm"
|
||||||
|
c1541="c1541"
|
||||||
|
python="python"
|
||||||
|
|
||||||
|
# Create an empty work folder
|
||||||
|
rm -fr work
|
||||||
|
mkdir work
|
||||||
|
|
||||||
|
# First, we build the NTSC version
|
||||||
|
cd work
|
||||||
|
|
||||||
|
# Extract the files from the original disk image
|
||||||
|
$c1541 -attach "../original-disks/elite[firebird_1986](ntsc)(v060186)(!).g64" \
|
||||||
|
-extract
|
||||||
|
|
||||||
|
# Assemble the additional code required for flicker-free ships
|
||||||
|
$beebasm -i ../src/elite-flicker-free.asm -v > compile.txt
|
||||||
|
|
||||||
|
# Modify the main game code
|
||||||
|
$python ../src/elite-modify.py ntsc
|
||||||
|
|
||||||
|
# Rebuild the game disk
|
||||||
|
$c1541 \
|
||||||
|
-format "no-flicker elite,1" \
|
||||||
|
d64 \
|
||||||
|
../flicker-free-disks/c64-elite-flicker-free-ntsc.d64 \
|
||||||
|
-attach ../flicker-free-disks/c64-elite-flicker-free-ntsc.d64 \
|
||||||
|
-write firebird \
|
||||||
|
-write gma1.modified gma1 \
|
||||||
|
-write gma3 \
|
||||||
|
-write gma4 \
|
||||||
|
-write gma5 \
|
||||||
|
-write gma6.encrypted gma6
|
||||||
|
|
||||||
|
# Report checksums
|
||||||
|
cd ..
|
||||||
|
$python src/crc32.py reference-binaries/ntsc work
|
||||||
|
|
||||||
|
# And now, we build the PAL version
|
||||||
|
cd work
|
||||||
|
|
||||||
|
# Extract the files from the original disk image
|
||||||
|
$c1541 -attach "../original-disks/elite[firebird_1986](pal)(v040486).g64" \
|
||||||
|
-extract
|
||||||
|
|
||||||
|
# Assemble the additional code required for flicker-free ships
|
||||||
|
$beebasm -i ../src/elite-flicker-free.asm -v >> compile.txt
|
||||||
|
|
||||||
|
# Modify the main game code
|
||||||
|
$python ../src/elite-modify.py pal
|
||||||
|
|
||||||
|
# Rebuild the game disk
|
||||||
|
$c1541 \
|
||||||
|
-format "no-flicker elite,1" \
|
||||||
|
d64 \
|
||||||
|
../flicker-free-disks/c64-elite-flicker-free-pal.d64 \
|
||||||
|
-attach ../flicker-free-disks/c64-elite-flicker-free-pal.d64 \
|
||||||
|
-write firebird \
|
||||||
|
-write byebyejulie \
|
||||||
|
-write gma1.modified gma1 \
|
||||||
|
-write gma3 \
|
||||||
|
-write gma4 \
|
||||||
|
-write gma5 \
|
||||||
|
-write gma6.encrypted gma6
|
||||||
|
|
||||||
|
# Report checksums
|
||||||
|
cd ..
|
||||||
|
$python src/crc32.py reference-binaries/pal work
|
||||||
BIN
flicker-free-disks/c64-elite-flicker-free-ntsc.d64
Normal file
BIN
flicker-free-disks/c64-elite-flicker-free-ntsc.d64
Normal file
Binary file not shown.
BIN
flicker-free-disks/c64-elite-flicker-free-pal.d64
Normal file
BIN
flicker-free-disks/c64-elite-flicker-free-pal.d64
Normal file
Binary file not shown.
BIN
original-disks/elite[firebird_1986](ntsc)(v060186)(!).g64
Normal file
BIN
original-disks/elite[firebird_1986](ntsc)(v060186)(!).g64
Normal file
Binary file not shown.
BIN
original-disks/elite[firebird_1986](pal)(v040486).g64
Normal file
BIN
original-disks/elite[firebird_1986](pal)(v040486).g64
Normal file
Binary file not shown.
BIN
reference-binaries/ntsc/extra.bin
Normal file
BIN
reference-binaries/ntsc/extra.bin
Normal file
Binary file not shown.
BIN
reference-binaries/ntsc/firebird
Normal file
BIN
reference-binaries/ntsc/firebird
Normal file
Binary file not shown.
BIN
reference-binaries/ntsc/gma1
Normal file
BIN
reference-binaries/ntsc/gma1
Normal file
Binary file not shown.
BIN
reference-binaries/ntsc/gma1.modified
Normal file
BIN
reference-binaries/ntsc/gma1.modified
Normal file
Binary file not shown.
BIN
reference-binaries/ntsc/gma3
Normal file
BIN
reference-binaries/ntsc/gma3
Normal file
Binary file not shown.
BIN
reference-binaries/ntsc/gma4
Normal file
BIN
reference-binaries/ntsc/gma4
Normal file
Binary file not shown.
BIN
reference-binaries/ntsc/gma5
Normal file
BIN
reference-binaries/ntsc/gma5
Normal file
Binary file not shown.
BIN
reference-binaries/ntsc/gma6
Normal file
BIN
reference-binaries/ntsc/gma6
Normal file
Binary file not shown.
BIN
reference-binaries/ntsc/gma6.decrypted
Normal file
BIN
reference-binaries/ntsc/gma6.decrypted
Normal file
Binary file not shown.
BIN
reference-binaries/ntsc/gma6.encrypted
Normal file
BIN
reference-binaries/ntsc/gma6.encrypted
Normal file
Binary file not shown.
BIN
reference-binaries/ntsc/gma6.modified
Normal file
BIN
reference-binaries/ntsc/gma6.modified
Normal file
Binary file not shown.
BIN
reference-binaries/ntsc/ll155.bin
Normal file
BIN
reference-binaries/ntsc/ll155.bin
Normal file
Binary file not shown.
1
reference-binaries/ntsc/shppt.bin
Normal file
1
reference-binaries/ntsc/shppt.bin
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
}6Ð¥CÉŽ° \™¥Ci \™©(…(Lx¡©÷%(…(Lx¡…l…n¥5…ki<03>©ÿ…mLàÌ
|
||||||
BIN
reference-binaries/pal/byebyejulie
Normal file
BIN
reference-binaries/pal/byebyejulie
Normal file
Binary file not shown.
BIN
reference-binaries/pal/extra.bin
Normal file
BIN
reference-binaries/pal/extra.bin
Normal file
Binary file not shown.
BIN
reference-binaries/pal/firebird
Normal file
BIN
reference-binaries/pal/firebird
Normal file
Binary file not shown.
BIN
reference-binaries/pal/gma1
Normal file
BIN
reference-binaries/pal/gma1
Normal file
Binary file not shown.
BIN
reference-binaries/pal/gma1.modified
Normal file
BIN
reference-binaries/pal/gma1.modified
Normal file
Binary file not shown.
BIN
reference-binaries/pal/gma3
Normal file
BIN
reference-binaries/pal/gma3
Normal file
Binary file not shown.
BIN
reference-binaries/pal/gma4
Normal file
BIN
reference-binaries/pal/gma4
Normal file
Binary file not shown.
BIN
reference-binaries/pal/gma5
Normal file
BIN
reference-binaries/pal/gma5
Normal file
Binary file not shown.
BIN
reference-binaries/pal/gma6
Normal file
BIN
reference-binaries/pal/gma6
Normal file
Binary file not shown.
BIN
reference-binaries/pal/gma6.decrypted
Normal file
BIN
reference-binaries/pal/gma6.decrypted
Normal file
Binary file not shown.
BIN
reference-binaries/pal/gma6.encrypted
Normal file
BIN
reference-binaries/pal/gma6.encrypted
Normal file
Binary file not shown.
BIN
reference-binaries/pal/gma6.modified
Normal file
BIN
reference-binaries/pal/gma6.modified
Normal file
Binary file not shown.
BIN
reference-binaries/pal/ll155.bin
Normal file
BIN
reference-binaries/pal/ll155.bin
Normal file
Binary file not shown.
1
reference-binaries/pal/shppt.bin
Normal file
1
reference-binaries/pal/shppt.bin
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
}6Ð¥CÉŽ° \™¥Ci \™©(…(Lx¡©÷%(…(Lx¡…l…n¥5…ki<03>©ÿ…mLàÌ
|
||||||
108
src/crc32.py
Normal file
108
src/crc32.py
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# ******************************************************************************
|
||||||
|
#
|
||||||
|
# ELITE VERIFICATION SCRIPT
|
||||||
|
#
|
||||||
|
# Written by Kieran Connell, extended by Mark Moxon
|
||||||
|
#
|
||||||
|
# This script performs checksums on the compiled files from the build process,
|
||||||
|
# and checks them against the extracted files from the original source disc
|
||||||
|
#
|
||||||
|
# ******************************************************************************
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import zlib
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) <= 2:
|
||||||
|
# Do CRC on single folder
|
||||||
|
folder = sys.argv[1] if len(sys.argv) == 2 else "."
|
||||||
|
names = sorted(os.listdir(folder))
|
||||||
|
|
||||||
|
print()
|
||||||
|
print('Checksum Size Filename')
|
||||||
|
print('------------------------------------------')
|
||||||
|
|
||||||
|
for name in names:
|
||||||
|
if not name.startswith("."):
|
||||||
|
full_name = os.path.join(folder, name)
|
||||||
|
if not os.path.isfile(full_name):
|
||||||
|
continue
|
||||||
|
with open(full_name, 'rb') as f:
|
||||||
|
data = f.read()
|
||||||
|
print('%08x %5d %s' % (
|
||||||
|
zlib.crc32(data) & 0xffffffff,
|
||||||
|
len(data),
|
||||||
|
full_name)
|
||||||
|
)
|
||||||
|
print()
|
||||||
|
else:
|
||||||
|
# Do CRC on two folders
|
||||||
|
folder1 = sys.argv[1]
|
||||||
|
names1 = sorted(os.listdir(folder1))
|
||||||
|
folder2 = sys.argv[2]
|
||||||
|
names2 = sorted(os.listdir(folder2))
|
||||||
|
names = list(names1)
|
||||||
|
names.extend(x for x in names2 if x not in names)
|
||||||
|
|
||||||
|
if 'reference-binaries' in folder1:
|
||||||
|
src = '[--originals--]'
|
||||||
|
elif 'output' in folder1:
|
||||||
|
src = '[---output----]'
|
||||||
|
else:
|
||||||
|
src = '[{0: ^13}]'.format(folder1[0:13]).replace(' ', '-')
|
||||||
|
|
||||||
|
if 'reference-binaries' in folder2:
|
||||||
|
dest = '[--originals--]'
|
||||||
|
elif 'output' in folder2:
|
||||||
|
dest = '[---output----]'
|
||||||
|
else:
|
||||||
|
dest = '[{0: ^13}]'.format(folder2[0:13]).replace(' ', '-')
|
||||||
|
|
||||||
|
print()
|
||||||
|
print(src + ' ' + dest)
|
||||||
|
print('Checksum Size Checksum Size Match Filename')
|
||||||
|
print('-----------------------------------------------------------')
|
||||||
|
|
||||||
|
for name in names:
|
||||||
|
if not name.startswith("."):
|
||||||
|
full_name1 = os.path.join(folder1, name)
|
||||||
|
full_name2 = os.path.join(folder2, name)
|
||||||
|
|
||||||
|
if name in names1 and name in names2 and os.path.isfile(full_name1) and os.path.isfile(full_name2):
|
||||||
|
with open(full_name1, 'rb') as f:
|
||||||
|
data1 = f.read()
|
||||||
|
with open(full_name2, 'rb') as f:
|
||||||
|
data2 = f.read()
|
||||||
|
crc1 = zlib.crc32(data1) & 0xffffffff
|
||||||
|
crc2 = zlib.crc32(data2) & 0xffffffff
|
||||||
|
match = ' Yes ' if crc1 == crc2 and len(data1) == len(data2) else ' No '
|
||||||
|
print('%08x %5d %08x %5d %s %s' % (
|
||||||
|
crc1,
|
||||||
|
len(data1),
|
||||||
|
crc2,
|
||||||
|
len(data2),
|
||||||
|
match,
|
||||||
|
name)
|
||||||
|
)
|
||||||
|
elif name in names1 and os.path.isfile(full_name1):
|
||||||
|
with open(full_name1, 'rb') as f:
|
||||||
|
data = f.read()
|
||||||
|
print('%08x %5d %s %s %s %s' % (
|
||||||
|
zlib.crc32(data) & 0xffffffff,
|
||||||
|
len(data),
|
||||||
|
'- ',
|
||||||
|
' -',
|
||||||
|
' - ',
|
||||||
|
name)
|
||||||
|
)
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
429
src/elite-flicker-free.asm
Normal file
429
src/elite-flicker-free.asm
Normal file
|
|
@ -0,0 +1,429 @@
|
||||||
|
\ ******************************************************************************
|
||||||
|
\
|
||||||
|
\ BBC MASTER ELITE GAME SOURCE (FLICKER-FREE ROUTINES)
|
||||||
|
\
|
||||||
|
\ BBC Master Elite was written by Ian Bell and David Braben and is copyright
|
||||||
|
\ Acornsoft 1986
|
||||||
|
\
|
||||||
|
\ The code on this site has been reconstructed from a disassembly of the version
|
||||||
|
\ released on Ian Bell's personal website at http://www.elitehomepage.org/
|
||||||
|
\
|
||||||
|
\ The commentary is copyright Mark Moxon, and any misunderstandings or mistakes
|
||||||
|
\ in the documentation are entirely my fault
|
||||||
|
\
|
||||||
|
\ The terminology and notations used in this commentary are explained at
|
||||||
|
\ https://www.bbcelite.com/about_site/terminology_used_in_this_commentary.html
|
||||||
|
\
|
||||||
|
\ The deep dive articles referred to in this commentary can be found at
|
||||||
|
\ https://www.bbcelite.com/deep_dives
|
||||||
|
\
|
||||||
|
\ ******************************************************************************
|
||||||
|
|
||||||
|
GUARD &CE00 \ Guard against assembling over memory used by game
|
||||||
|
|
||||||
|
\ ******************************************************************************
|
||||||
|
\
|
||||||
|
\ Configuration variables
|
||||||
|
\
|
||||||
|
\ The addresses in the following are from when the game binary is loaded into
|
||||||
|
\ memory. They were calculated by analysing a memory dump of the running game,
|
||||||
|
\ searching for patterns in the bytes to match them with the corrsponding code
|
||||||
|
\ from the BBC Micro version (which is very similar, if you ignore any different
|
||||||
|
\ addresses).
|
||||||
|
\
|
||||||
|
\ XX14 is an unused variable in BBC Micro Elite, and the corresponding address
|
||||||
|
\ in Commodore 64 Elite is used by something else. Luckily locations $FB to $FE
|
||||||
|
\ are unused by Elite and the OS, so we can sneak XX14 in there instead.
|
||||||
|
\
|
||||||
|
\ Also, the Y variable contains the height of the space view in pixels, divided
|
||||||
|
\ by 2. This is 96 on the BBC Micro, but the space view is 144 pixels on the
|
||||||
|
\ Commodore 64, so Y needs to be set to 72 instead.
|
||||||
|
\
|
||||||
|
\ ******************************************************************************
|
||||||
|
|
||||||
|
XX1 = $0009
|
||||||
|
INWK = $0009
|
||||||
|
XX19 = $002A
|
||||||
|
CNT = $0030
|
||||||
|
K3 = $0035
|
||||||
|
K4 = $0043
|
||||||
|
XX0 = $0057
|
||||||
|
V = $005B
|
||||||
|
XX15 = $006B
|
||||||
|
X1 = $006B
|
||||||
|
Y1 = $006C
|
||||||
|
X2 = $006D
|
||||||
|
Y2 = $006E
|
||||||
|
XX12 = $0071
|
||||||
|
XX17 = $009F
|
||||||
|
XX4 = $00AD
|
||||||
|
XX20 = $00AE
|
||||||
|
XX14 = $00FB
|
||||||
|
PROJ = $7D1F
|
||||||
|
LL75 = $9FB8
|
||||||
|
LL80 = $A13F
|
||||||
|
LL30 = $AB91
|
||||||
|
Y = 72
|
||||||
|
|
||||||
|
\ ******************************************************************************
|
||||||
|
\
|
||||||
|
\ Name: SHPPT
|
||||||
|
\ Type: Subroutine
|
||||||
|
\ Category: Drawing ships
|
||||||
|
\ Summary: Draw a distant ship as a point rather than a full wireframe
|
||||||
|
\
|
||||||
|
\ ******************************************************************************
|
||||||
|
|
||||||
|
ORG $9932
|
||||||
|
|
||||||
|
.SHPPT
|
||||||
|
|
||||||
|
JSR PROJ \ Project the ship onto the screen, returning:
|
||||||
|
\
|
||||||
|
\ * K3(1 0) = the screen x-coordinate
|
||||||
|
\ * K4(1 0) = the screen y-coordinate
|
||||||
|
\ * A = K4+1
|
||||||
|
|
||||||
|
ORA K3+1 \ If either of the high bytes of the screen coordinates
|
||||||
|
BNE nono \ are non-zero, jump to nono as the ship is off-screen
|
||||||
|
|
||||||
|
LDA K4 \ Set A = the y-coordinate of the dot
|
||||||
|
|
||||||
|
CMP #Y*2-2 \ If the y-coordinate is bigger than the y-coordinate of
|
||||||
|
BCS nono \ the bottom of the screen, jump to nono as the ship's
|
||||||
|
\ dot is off the bottom of the space view
|
||||||
|
|
||||||
|
JSR Shpt \ Call Shpt to draw a horizontal 4-pixel dash for the
|
||||||
|
\ first row of the dot (i.e. a four-pixel dash)
|
||||||
|
|
||||||
|
LDA K4 \ Set A = y-coordinate of dot + 1 (so this is the second
|
||||||
|
CLC \ row of the two-pixel-high dot)
|
||||||
|
ADC #1
|
||||||
|
|
||||||
|
JSR Shpt \ Call Shpt to draw a horizontal 4-pixel dash for the
|
||||||
|
\ first row of the dot (i.e. a four-pixel dash)
|
||||||
|
|
||||||
|
LDA #%00001000 \ Set bit 3 of the ship's byte #31 to record that we
|
||||||
|
ORA XX1+31 \ have now drawn something on-screen for this ship
|
||||||
|
STA XX1+31
|
||||||
|
|
||||||
|
JMP LL155 \ Jump to LL155 to draw any remaining lines that are
|
||||||
|
\ still in the ship line heap and return from the
|
||||||
|
\ subroutine using a tail call
|
||||||
|
|
||||||
|
.nono
|
||||||
|
|
||||||
|
LDA #%11110111 \ Clear bit 3 of the ship's byte #31 to record that
|
||||||
|
AND XX1+31 \ nothing is being drawn on-screen for this ship
|
||||||
|
STA XX1+31
|
||||||
|
|
||||||
|
JMP LL155 \ Jump to LL155 to draw any remaining lines that are
|
||||||
|
\ still in the ship line heap and return from the
|
||||||
|
\ subroutine using a tail call
|
||||||
|
|
||||||
|
.Shpt
|
||||||
|
|
||||||
|
\ This routine draws a horizontal 4-pixel dash, for
|
||||||
|
\ either the top or the bottom of the ship's dot
|
||||||
|
|
||||||
|
STA Y1 \ Store A in both y-coordinates, as this is a horizontal
|
||||||
|
STA Y2 \ dash at y-coordinate A
|
||||||
|
|
||||||
|
LDA K3 \ Set A = screen x-coordinate of the ship dot
|
||||||
|
|
||||||
|
STA X1 \ Store the x-coordinate of the ship dot in X1, as this
|
||||||
|
\ is where the dash starts
|
||||||
|
|
||||||
|
CLC \ Set A = screen x-coordinate of the ship dot + 3
|
||||||
|
ADC #3
|
||||||
|
|
||||||
|
BCC P%+4 \ If the addition overflowed, set A = 255, the
|
||||||
|
LDA #255 \ x-coordinate of the right edge of the screen
|
||||||
|
|
||||||
|
STA X2 \ Store the x-coordinate of the ship dot in X1, as this
|
||||||
|
\ is where the dash starts
|
||||||
|
|
||||||
|
JMP LLX30 \ Draw this edge using flicker-free animation, by first
|
||||||
|
\ drawing the ship's new line and then erasing the
|
||||||
|
\ corresponding old line from the screen, and return
|
||||||
|
\ from the subroutine using a tail call
|
||||||
|
|
||||||
|
SAVE "shppt.bin", SHPPT, P%
|
||||||
|
|
||||||
|
\ ******************************************************************************
|
||||||
|
\
|
||||||
|
\ Name: LL9 (Part 11 of 12)
|
||||||
|
\ Type: Subroutine
|
||||||
|
\ Category: Drawing ships
|
||||||
|
\ Summary: Draw ship: Loop back for the next edge
|
||||||
|
\ Deep dive: Drawing ships
|
||||||
|
\
|
||||||
|
\ ******************************************************************************
|
||||||
|
|
||||||
|
ORG $A15B
|
||||||
|
|
||||||
|
.LL78
|
||||||
|
|
||||||
|
LDA XX14 \ If XX14 >= CNT, skip to LL81 so we don't loop back for
|
||||||
|
CMP CNT \ the next edge (CNT was set to the maximum heap size
|
||||||
|
BCS LL81 \ for this ship in part 10, so this checks whether we
|
||||||
|
\ have just run out of space in the ship line heap, and
|
||||||
|
\ stops drawing edges if we have)
|
||||||
|
|
||||||
|
LDA V \ Increment V by 4 so V(1 0) points to the data for the
|
||||||
|
CLC \ next edge
|
||||||
|
ADC #4
|
||||||
|
STA V
|
||||||
|
|
||||||
|
BCC ll81 \ If the above addition didn't overflow, jump to ll81
|
||||||
|
|
||||||
|
INC V+1 \ Otherwise increment the high byte of V(1 0), as we
|
||||||
|
\ just moved the V(1 0) pointer past a page boundary
|
||||||
|
|
||||||
|
.ll81
|
||||||
|
|
||||||
|
INC XX17 \ Increment the edge counter to point to the next edge
|
||||||
|
|
||||||
|
LDY XX17 \ If Y >= XX20, which contains the number of edges in
|
||||||
|
CPY XX20 \ the blueprint, skip the following
|
||||||
|
BCS P%+5
|
||||||
|
|
||||||
|
JMP LL75-2 \ Loop back to LL75-2 to process the next edge (we jump
|
||||||
|
\ to LL75-2 as we have modified the code around LL75,
|
||||||
|
\ which moves the jump point back by two bytes)
|
||||||
|
|
||||||
|
.LL81
|
||||||
|
|
||||||
|
NOP
|
||||||
|
|
||||||
|
SAVE "ll78.bin", LL78, P%
|
||||||
|
|
||||||
|
\ ******************************************************************************
|
||||||
|
\
|
||||||
|
\ Name: LL9 (Part 12 of 12)
|
||||||
|
\ Type: Subroutine
|
||||||
|
\ Category: Drawing ships
|
||||||
|
\ Summary: Draw ship: Draw all the visible edges from the ship line heap
|
||||||
|
\ Deep dive: Drawing ships
|
||||||
|
\
|
||||||
|
\ ******************************************************************************
|
||||||
|
|
||||||
|
ORG $A178
|
||||||
|
|
||||||
|
.LL155
|
||||||
|
|
||||||
|
LDY XX14 \ Set Y to the offset in the line heap XX14
|
||||||
|
|
||||||
|
.LL27
|
||||||
|
|
||||||
|
CPY XX14+1 \ If Y >= XX14+1, jump to LLEX to return from the ship
|
||||||
|
BCS LLEX \ drawing routine, because the index in Y is greater
|
||||||
|
\ than the size of the existing ship line heap, which
|
||||||
|
\ means we have alrady erased all the old ships lines
|
||||||
|
\ when drawing the new ship
|
||||||
|
|
||||||
|
\ If we get here then Y < XX14+1, which means Y is
|
||||||
|
\ pointing to an on-screen line from the old ship that
|
||||||
|
\ we need to erase
|
||||||
|
|
||||||
|
LDA (XX19),Y \ Fetch the X1 line coordinate from the heap and store
|
||||||
|
STA XX15 \ it in XX15
|
||||||
|
|
||||||
|
INY \ Increment the heap pointer
|
||||||
|
|
||||||
|
LDA (XX19),Y \ Fetch the Y1 line coordinate from the heap and store
|
||||||
|
STA XX15+1 \ it in XX15+1
|
||||||
|
|
||||||
|
INY \ Increment the heap pointer
|
||||||
|
|
||||||
|
LDA (XX19),Y \ Fetch the X2 line coordinate from the heap and store
|
||||||
|
STA XX15+2 \ it in XX15+2
|
||||||
|
|
||||||
|
INY \ Increment the heap pointer
|
||||||
|
|
||||||
|
LDA (XX19),Y \ Fetch the Y2 line coordinate from the heap and store
|
||||||
|
STA XX15+3 \ it in XX15+3
|
||||||
|
|
||||||
|
JSR LL30 \ Draw a line from (X1, Y1) to (X2, Y2) to erase it from
|
||||||
|
\ the screen
|
||||||
|
|
||||||
|
INY \ Increment the heap pointer
|
||||||
|
|
||||||
|
JMP LL27 \ Loop back to LL27 to draw (i.e. erase) the next line
|
||||||
|
\ from the heap
|
||||||
|
|
||||||
|
.LLEX
|
||||||
|
|
||||||
|
LDA XX14 \ Store XX14 in the first byte of the ship line heap
|
||||||
|
LDY #0
|
||||||
|
STA (XX19),Y
|
||||||
|
|
||||||
|
.LL82
|
||||||
|
|
||||||
|
RTS \ Return from the subroutine
|
||||||
|
|
||||||
|
SAVE "ll155.bin", LL155, P%
|
||||||
|
|
||||||
|
ORG $CCE0
|
||||||
|
|
||||||
|
\ ******************************************************************************
|
||||||
|
\
|
||||||
|
\ Name: LLX30
|
||||||
|
\ Type: Subroutine
|
||||||
|
\ Category: Drawing lines
|
||||||
|
\ Summary: Draw a ship line using flicker-free animation
|
||||||
|
\
|
||||||
|
\ ******************************************************************************
|
||||||
|
|
||||||
|
.LLX30
|
||||||
|
|
||||||
|
LDY XX14 \ Set Y = XX14, to get the offset within the ship line
|
||||||
|
\ heap where we want to insert our new line
|
||||||
|
|
||||||
|
CPY XX14+1 \ Compare XX14 and XX14+1 and store the flags on the
|
||||||
|
PHP \ stack so we can retrieve them later
|
||||||
|
|
||||||
|
LDX #3 \ We now want to copy the line coordinates (X1, Y1) and
|
||||||
|
\ (X2, Y2) to XX12...XX12+3, so set a counter to copy
|
||||||
|
\ 4 bytes
|
||||||
|
|
||||||
|
.LLXL
|
||||||
|
|
||||||
|
LDA X1,X \ Copy the X-th byte of X1/Y1/X2/Y2 to the X-th byte of
|
||||||
|
STA XX12,X \ XX12
|
||||||
|
|
||||||
|
DEX \ Decrement the loop counter
|
||||||
|
|
||||||
|
BPL LLXL \ Loop back until we have copied all four bytes
|
||||||
|
|
||||||
|
JSR LL30 \ Draw a line from (X1, Y1) to (X2, Y2)
|
||||||
|
|
||||||
|
LDA (XX19),Y \ Set X1 to the Y-th coordinate on the ship line heap,
|
||||||
|
STA X1 \ i.e. one we are replacing in the heap
|
||||||
|
|
||||||
|
LDA XX12 \ Replace it with the X1 coordinate in XX12
|
||||||
|
STA (XX19),Y
|
||||||
|
|
||||||
|
INY \ Increment the index to point to the Y1 coordinate
|
||||||
|
|
||||||
|
LDA (XX19),Y \ Set Y1 to the Y-th coordinate on the ship line heap,
|
||||||
|
STA Y1 \ i.e. one we are replacing in the heap
|
||||||
|
|
||||||
|
LDA XX12+1 \ Replace it with the Y1 coordinate in XX12+1
|
||||||
|
STA (XX19),Y
|
||||||
|
|
||||||
|
INY \ Increment the index to point to the X2 coordinate
|
||||||
|
|
||||||
|
LDA (XX19),Y \ Set X1 to the Y-th coordinate on the ship line heap,
|
||||||
|
STA X2
|
||||||
|
|
||||||
|
LDA XX12+2 \ Replace it with the X2 coordinate in XX12+2
|
||||||
|
STA (XX19),Y
|
||||||
|
|
||||||
|
INY \ Increment the index to point to the Y2 coordinate
|
||||||
|
|
||||||
|
LDA (XX19),Y \ Set Y2 to the Y-th coordinate on the ship line heap,
|
||||||
|
STA Y2
|
||||||
|
|
||||||
|
LDA XX12+3 \ Replace it with the Y2 coordinate in XX12+3
|
||||||
|
STA (XX19),Y
|
||||||
|
|
||||||
|
INY \ Increment the index to point to the next coordinate
|
||||||
|
STY XX14 \ and store the updated index in XX14
|
||||||
|
|
||||||
|
PLP \ Restore the result of the comparison above, so if the
|
||||||
|
BCS LL82a \ original value of XX14 >= XX14+1, then we have already
|
||||||
|
\ redrawn all the lines from the old ship's line heap,
|
||||||
|
\ so return from the subroutine (as LL82 contains an
|
||||||
|
\ RTS)
|
||||||
|
|
||||||
|
JMP LL30 \ Otherwise there are still more lines to erase from the
|
||||||
|
\ old ship on-screen, so the coordinates in (X1, Y1) and
|
||||||
|
\ (X2, Y2) that we just pulled from the ship line heap
|
||||||
|
\ point to a line that is still on-screen, so call LL30
|
||||||
|
\ to draw this line and erase it from the screen,
|
||||||
|
\ returning from the subroutine using a tail call
|
||||||
|
|
||||||
|
.LL82a
|
||||||
|
|
||||||
|
RTS \ Return from the subroutine
|
||||||
|
|
||||||
|
\ ******************************************************************************
|
||||||
|
\
|
||||||
|
\ Name: LL9 (Part 1 of 12)
|
||||||
|
\ Type: Subroutine
|
||||||
|
\ Category: Drawing ships
|
||||||
|
\ Summary: Draw ship: Check if ship is exploding, check if ship is in front
|
||||||
|
\ Deep dive: Drawing ships
|
||||||
|
\
|
||||||
|
\ ******************************************************************************
|
||||||
|
|
||||||
|
.PATCH1
|
||||||
|
|
||||||
|
\ We replace the following two instructions in part 1 of
|
||||||
|
\ LL9 with JSR PATCH1, so we start with those two
|
||||||
|
\ instructions to ensure that they still get done
|
||||||
|
|
||||||
|
LDA #31 \ Set XX4 = 31 to store the ship's distance for later
|
||||||
|
STA XX4 \ comparison with the visibility distance. We will
|
||||||
|
\ update this value below with the actual ship's
|
||||||
|
\ distance if it turns out to be visible on-screen
|
||||||
|
|
||||||
|
\ We now set things up for flicker-free ship plotting,
|
||||||
|
\ by setting the following:
|
||||||
|
\
|
||||||
|
\ XX14 = offset to the first coordinate in the ship's
|
||||||
|
\ line heap
|
||||||
|
\
|
||||||
|
\ XX14+1 = the number of bytes in the heap for the
|
||||||
|
\ ship that's currently on-screen (or 0 if
|
||||||
|
\ there is no ship currently on-screen)
|
||||||
|
|
||||||
|
LDY #1 \ Set XX14 = 1, the offset of the first set of line
|
||||||
|
STY XX14 \ coordinates in the ship line heap
|
||||||
|
|
||||||
|
DEY \ Decrement Y to 0
|
||||||
|
|
||||||
|
LDA #%00001000 \ If bit 3 of the ship's byte #31 is set, then the ship
|
||||||
|
BIT INWK+31 \ is currently being drawn on-screen, so skip the
|
||||||
|
BNE P%+5 \ following two instructions
|
||||||
|
|
||||||
|
LDA #0 \ The ship is not being drawn on screen, so set A = 0
|
||||||
|
\ so that XX14+1 gets set to 0 below (as there are no
|
||||||
|
\ existing coordinates on the ship line heap for this
|
||||||
|
\ ship)
|
||||||
|
|
||||||
|
EQUB $2C \ Skip the next instruction by turning it into
|
||||||
|
\ $2C $B1 $BD, or BIT $BDB1 which does nothing apart
|
||||||
|
\ from affect the flags
|
||||||
|
|
||||||
|
LDA (XX19),Y \ Set XX14+1 to the first byte of the ship's line heap,
|
||||||
|
STA XX14+1 \ which contains the number of bytes in the heap
|
||||||
|
|
||||||
|
RTS
|
||||||
|
|
||||||
|
\ ******************************************************************************
|
||||||
|
\
|
||||||
|
\ Name: LL9 (Part 10 of 12)
|
||||||
|
\ Type: Subroutine
|
||||||
|
\ Category: Drawing ships
|
||||||
|
\ Summary: Draw ship: Check if ship is exploding, check if ship is in front
|
||||||
|
\ Deep dive: Drawing ships
|
||||||
|
\
|
||||||
|
\ ******************************************************************************
|
||||||
|
|
||||||
|
.PATCH2
|
||||||
|
|
||||||
|
\ We replace the JMP LL78 instruction at the end of part
|
||||||
|
\ 10 of LL9 with JSR PATCH2, so this effectively inserts
|
||||||
|
\ the call to LLX30 at the end of part 10, as required
|
||||||
|
|
||||||
|
JSR LLX30 \ Draw the laser line using flicker-free animation, by
|
||||||
|
\ first drawing the new laser line and then erasing the
|
||||||
|
\ corresponding old line from the screen
|
||||||
|
|
||||||
|
JMP LL78 \ Jump down to part 11
|
||||||
|
|
||||||
|
|
||||||
|
SAVE "extra.bin", LLX30, P%
|
||||||
|
|
||||||
412
src/elite-modify.py
Normal file
412
src/elite-modify.py
Normal file
|
|
@ -0,0 +1,412 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# ******************************************************************************
|
||||||
|
#
|
||||||
|
# COMMODORE 64 ELITE FLICKER-FREE MODIFICATION SCRIPT
|
||||||
|
#
|
||||||
|
# Written by Mark Moxon
|
||||||
|
#
|
||||||
|
# This script applies flicker-free ship-drawing to Commodore 64 Elite, as
|
||||||
|
# described here:
|
||||||
|
#
|
||||||
|
# https://www.bbcelite.com/deep_dives/flicker-free_ship_drawing.html
|
||||||
|
#
|
||||||
|
# It does the following:
|
||||||
|
#
|
||||||
|
# * Decrypt the gma6 file
|
||||||
|
# * Modify the gma6 file to draw flicker-free ships
|
||||||
|
# * Encrypt the gma6 file
|
||||||
|
# * Modify the gma1 file to remove disk protection
|
||||||
|
#
|
||||||
|
# Run this script by changing directory to the folder containing the disk files
|
||||||
|
# and running the script with "python elite-modify.py"
|
||||||
|
#
|
||||||
|
# This modification script works with the elite[firebird_1986](pal)(v040486).g64
|
||||||
|
# disk image
|
||||||
|
#
|
||||||
|
# ******************************************************************************
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
# Convert a C64 address into the corresponding offset within the gma6 file
|
||||||
|
|
||||||
|
def get_offset(addr):
|
||||||
|
return addr - load_address
|
||||||
|
|
||||||
|
|
||||||
|
# Insert a binary file into the game code, overwriting what's there
|
||||||
|
|
||||||
|
def insert_binary_file(data_block, addr, filename):
|
||||||
|
file = open(filename, "rb")
|
||||||
|
file_size = os.path.getsize(filename)
|
||||||
|
insert_from = get_offset(addr)
|
||||||
|
insert_to = insert_from + file_size
|
||||||
|
data_block[insert_from:insert_to] = file.read()
|
||||||
|
file.close()
|
||||||
|
print("[ Modify ] insert file {} at 0x{:02X}".format(filename, addr))
|
||||||
|
|
||||||
|
|
||||||
|
# Insert an array of bytes into the game code, overwriting what's there
|
||||||
|
|
||||||
|
def insert_bytes(data_block, addr, insert):
|
||||||
|
insert_from = get_offset(addr)
|
||||||
|
insert_to = insert_from + len(insert)
|
||||||
|
data_block[insert_from:insert_to] = insert
|
||||||
|
print("[ Modify ] insert {} bytes at 0x{:02X}".format(len(insert), addr))
|
||||||
|
|
||||||
|
|
||||||
|
# Insert a block of NOPs into the game code, overwriting what's there
|
||||||
|
|
||||||
|
def insert_nops(data_block, addr, count):
|
||||||
|
insert = [0xEA] * count
|
||||||
|
insert_bytes(data_block, addr, insert)
|
||||||
|
print("[ Modify ] insert {} NOPs at 0x{:02X}".format(count, addr))
|
||||||
|
|
||||||
|
|
||||||
|
# Fetch the platform (NTSC or PAL) from the command line arguments
|
||||||
|
|
||||||
|
if len(sys.argv) >= 2:
|
||||||
|
platform = sys.argv[1]
|
||||||
|
else:
|
||||||
|
platform = "pal"
|
||||||
|
|
||||||
|
# Print a progess message
|
||||||
|
|
||||||
|
print()
|
||||||
|
print("Modifying Commodore 64 Elite")
|
||||||
|
print("Platform: {}".format(platform.upper()))
|
||||||
|
|
||||||
|
# Configuration variables
|
||||||
|
|
||||||
|
load_address = 0x6A00 - 2
|
||||||
|
seed = 0x49
|
||||||
|
scramble_from = 0x6A00
|
||||||
|
scramble_to = 0x6A00 + 0x62D6
|
||||||
|
|
||||||
|
# Set up an array to hold the game binary, so we can modify it
|
||||||
|
|
||||||
|
data_block = bytearray()
|
||||||
|
|
||||||
|
# Load the main code file into data_block
|
||||||
|
|
||||||
|
elite_file = open("gma6", "rb")
|
||||||
|
data_block.extend(elite_file.read())
|
||||||
|
elite_file.close()
|
||||||
|
|
||||||
|
print()
|
||||||
|
print("[ Read ] gma6")
|
||||||
|
|
||||||
|
# Decrypt the main code file
|
||||||
|
|
||||||
|
updated_seed = seed
|
||||||
|
|
||||||
|
for n in range(scramble_to, scramble_from - 1, -1):
|
||||||
|
new = (data_block[n - load_address] - updated_seed) % 256
|
||||||
|
data_block[n - load_address] = new
|
||||||
|
updated_seed = new
|
||||||
|
|
||||||
|
print("[ Decrypt ] gma6")
|
||||||
|
|
||||||
|
# Write an output file containing the decrypted but unmodified game code, which
|
||||||
|
# we can use for debugging
|
||||||
|
|
||||||
|
output_file = open("gma6.decrypted", "wb")
|
||||||
|
output_file.write(data_block)
|
||||||
|
output_file.close()
|
||||||
|
|
||||||
|
print("[ Save ] gma6.decrypted")
|
||||||
|
|
||||||
|
# Set the addresses for the extra routines (LLX30, PATCH1, PATCH2) that we will
|
||||||
|
# append to the end of the main game code (where there is a bit of free space)
|
||||||
|
|
||||||
|
llx30 = 0xCCE0
|
||||||
|
patch1 = 0xCD1E
|
||||||
|
patch2 = 0xCD35
|
||||||
|
|
||||||
|
# We now modify the code to implement flicker-free ship drawing. The code
|
||||||
|
# changes are described here, which can be read alongside the following:
|
||||||
|
#
|
||||||
|
# https://www.bbcelite.com/deep_dives/backporting_the_flicker-free_algorithm.html
|
||||||
|
#
|
||||||
|
# The addresses in the following are from when the game binary is loaded into
|
||||||
|
# memory. They were calculated by analysing a memory dump of the running game,
|
||||||
|
# searching for patterns in the bytes to match them with the corrsponding code
|
||||||
|
# from the BBC Micro version (which is very similar, if you ignore any different
|
||||||
|
# addresses).
|
||||||
|
|
||||||
|
# SHPPT
|
||||||
|
#
|
||||||
|
# We start with the new version of SHPPT, which we have already assembled in
|
||||||
|
# BeebAsm and saved as the binary file shppt.bin, so we simply drop this over
|
||||||
|
# the top of the existing routine (which is slightly longer, so there is room).
|
||||||
|
|
||||||
|
insert_binary_file(data_block, 0x9932, "shppt.bin")
|
||||||
|
|
||||||
|
# LL9 (Part 1)
|
||||||
|
#
|
||||||
|
# This is the modification just after LL9. We insert the extra code with a call
|
||||||
|
# to the new PATCH1 routine, which implements the original instructions before
|
||||||
|
# moving on to the new code.
|
||||||
|
#
|
||||||
|
# From: LDA #31
|
||||||
|
# STA XX4
|
||||||
|
#
|
||||||
|
# To: JSR PATCH1
|
||||||
|
# NOP
|
||||||
|
|
||||||
|
insert_bytes(data_block, 0x9A8A, [
|
||||||
|
0x20, patch1 % 256, patch1 // 256 # JSR PATCH1
|
||||||
|
])
|
||||||
|
insert_nops(data_block, 0x9A8D, 1)
|
||||||
|
|
||||||
|
# LL9 (Part 9)
|
||||||
|
#
|
||||||
|
# This is the modification at EE31.
|
||||||
|
#
|
||||||
|
# From: LDA #%00001000
|
||||||
|
# BIT XX1+31
|
||||||
|
# BEQ LL74
|
||||||
|
# JSR LL155
|
||||||
|
#
|
||||||
|
# To: LDY #9
|
||||||
|
# LDA (XX0),Y
|
||||||
|
# STA XX20
|
||||||
|
# NOP
|
||||||
|
# NOP
|
||||||
|
# NOP
|
||||||
|
|
||||||
|
insert_bytes(data_block, 0x9F2A, [
|
||||||
|
0xA0, 0x09, # LDY #9
|
||||||
|
0xB1, 0x57, # LDA (XX0),Y
|
||||||
|
0x85, 0xAE # STA XX20
|
||||||
|
])
|
||||||
|
insert_nops(data_block, 0x9F30, 3)
|
||||||
|
|
||||||
|
# LL9 (Part 9)
|
||||||
|
#
|
||||||
|
# This is the modification just after LL74.
|
||||||
|
#
|
||||||
|
# From: LDY #9
|
||||||
|
# LDA (XX0),Y
|
||||||
|
# STA XX20
|
||||||
|
# LDY #0
|
||||||
|
# STY U
|
||||||
|
# STY XX17
|
||||||
|
# INC U
|
||||||
|
#
|
||||||
|
# To: LDY #0
|
||||||
|
# STY XX17
|
||||||
|
# NOP x10
|
||||||
|
|
||||||
|
insert_bytes(data_block, 0x9F39, [
|
||||||
|
0xA0, 0x00, # LDY #0
|
||||||
|
0x84, 0x9F # STY XX17
|
||||||
|
])
|
||||||
|
insert_nops(data_block, 0x9F3D, 10)
|
||||||
|
|
||||||
|
# LL9 (Part 9)
|
||||||
|
#
|
||||||
|
# This is the modification at the end of the routine.
|
||||||
|
#
|
||||||
|
# From: LDA XX15
|
||||||
|
# STA (XX19),Y
|
||||||
|
# INY
|
||||||
|
# LDA XX15+1
|
||||||
|
# STA (XX19),Y
|
||||||
|
# INY :
|
||||||
|
# LDA XX15+2
|
||||||
|
# STA (XX19),Y
|
||||||
|
# INY
|
||||||
|
# LDA XX15+3
|
||||||
|
# STA (XX19),Y
|
||||||
|
# INY
|
||||||
|
# STY U
|
||||||
|
#
|
||||||
|
# To: JSR LLX30
|
||||||
|
# NOP x21
|
||||||
|
|
||||||
|
insert_bytes(data_block, 0x9F87, [
|
||||||
|
0x20, llx30 % 256, llx30 // 256 # JSR LLX30
|
||||||
|
])
|
||||||
|
insert_nops(data_block, 0x9F8A, 21)
|
||||||
|
|
||||||
|
# LL9 (Part 10)
|
||||||
|
#
|
||||||
|
# This is the modification around LL75.
|
||||||
|
#
|
||||||
|
# From: STA T1
|
||||||
|
# LDY XX17
|
||||||
|
#
|
||||||
|
# To: STA CNT
|
||||||
|
# LDY #0
|
||||||
|
|
||||||
|
insert_bytes(data_block, 0x9FB4, [
|
||||||
|
0x85, 0x30, # STA CNT
|
||||||
|
0xA0, 0x00 # LDY #0
|
||||||
|
])
|
||||||
|
|
||||||
|
# LL9 (Part 10)
|
||||||
|
#
|
||||||
|
# This is the second INY after LL75.
|
||||||
|
#
|
||||||
|
# From: INY
|
||||||
|
#
|
||||||
|
# To: NOP
|
||||||
|
|
||||||
|
insert_nops(data_block, 0x9FC1, 1)
|
||||||
|
|
||||||
|
# LL9 (Part 10)
|
||||||
|
#
|
||||||
|
# This are the two modifications at LL79.
|
||||||
|
#
|
||||||
|
# From: LDA (V),Y
|
||||||
|
# TAX
|
||||||
|
# INY
|
||||||
|
# LDA (V),Y
|
||||||
|
# STA Q
|
||||||
|
# ... four lots of unchanged LDA/STA, 5 bytes each ...
|
||||||
|
# LDX Q
|
||||||
|
#
|
||||||
|
# To: INY
|
||||||
|
# LDA (V),Y
|
||||||
|
# TAX
|
||||||
|
# ... shuffle the LDA/STA block down by 4 bytes ...
|
||||||
|
# INY
|
||||||
|
# LDA (V),Y
|
||||||
|
# TAX
|
||||||
|
# NOP
|
||||||
|
# NOP
|
||||||
|
|
||||||
|
insert_bytes(data_block, 0x9FD9, [
|
||||||
|
0xC8, # INY
|
||||||
|
0xB1, 0x5B, # LDA (V),Y
|
||||||
|
0xAA # TAX
|
||||||
|
])
|
||||||
|
|
||||||
|
lda_sta_block = get_offset(0x9FDD)
|
||||||
|
for n in range(lda_sta_block, lda_sta_block + 4 * 5):
|
||||||
|
data_block[n] = data_block[n + 4]
|
||||||
|
|
||||||
|
insert_bytes(data_block, 0x9FF1, [
|
||||||
|
0xC8, # INY
|
||||||
|
0xB1, 0x5B, # LDA (V),Y
|
||||||
|
0xAA # TAX
|
||||||
|
])
|
||||||
|
insert_nops(data_block, 0x9FF5, 2)
|
||||||
|
|
||||||
|
# LL9 (Part 10)
|
||||||
|
#
|
||||||
|
# This is the modification at the end of the routine. The C64 version has an
|
||||||
|
# extra JMP LL80 instruction at this point that we can modify to jump to a
|
||||||
|
# new routine PATCH2, which lets us insert the extra JSR LLX30 without taking
|
||||||
|
# up any more bytes.
|
||||||
|
#
|
||||||
|
# From: JMP LL80
|
||||||
|
#
|
||||||
|
# To: JMP PATCH2
|
||||||
|
|
||||||
|
insert_bytes(data_block, 0xA010, [
|
||||||
|
0x4C, patch2 % 256, patch2 // 256 # JMP PATCH2
|
||||||
|
])
|
||||||
|
|
||||||
|
# LL9 (Part 11)
|
||||||
|
#
|
||||||
|
# This is the modification at LL80.
|
||||||
|
#
|
||||||
|
# We blank out the .LL80 section with 28 NOPs
|
||||||
|
|
||||||
|
insert_nops(data_block, 0xA13F, 28)
|
||||||
|
|
||||||
|
# LL9 (Part 11)
|
||||||
|
#
|
||||||
|
# We have already assembled the modified part 11 in BeebAsm and saved it as
|
||||||
|
# the binary file ll78.bin, so now we drop this over the top of the existing
|
||||||
|
# routine (which is exactly the same size).
|
||||||
|
|
||||||
|
insert_binary_file(data_block, 0xA15B, "ll78.bin")
|
||||||
|
|
||||||
|
# LL9 (Part 12)
|
||||||
|
#
|
||||||
|
# We have already assembled the modified part 11 in BeebAsm and saved it as
|
||||||
|
# the binary file ll115.bin, so now we drop this over the top of the existing
|
||||||
|
# routine (which is slightly longer, so there is room).
|
||||||
|
|
||||||
|
insert_binary_file(data_block, 0xA178, "ll155.bin")
|
||||||
|
|
||||||
|
# We now append the three extra routines required by the modifications to the
|
||||||
|
# end of the main binary (where there is enough free space for them):
|
||||||
|
#
|
||||||
|
# LLX30
|
||||||
|
# PATCH1
|
||||||
|
# PATCH2
|
||||||
|
#
|
||||||
|
# We have already assembled these in BeebAsm and saved them as the binary file
|
||||||
|
# extra.bin, so we simply append this file to the end.
|
||||||
|
|
||||||
|
elite_file = open("extra.bin", "rb")
|
||||||
|
data_block.extend(elite_file.read())
|
||||||
|
elite_file.close()
|
||||||
|
|
||||||
|
print("[ Modify ] append file extra.bin")
|
||||||
|
|
||||||
|
# All the modifications are done, so write the output file for gma6.modified,
|
||||||
|
# which we can use for debugging
|
||||||
|
|
||||||
|
output_file = open("gma6.modified", "wb")
|
||||||
|
output_file.write(data_block)
|
||||||
|
output_file.close()
|
||||||
|
|
||||||
|
print("[ Save ] gma6.modified")
|
||||||
|
|
||||||
|
# Encrypt the main code file
|
||||||
|
|
||||||
|
for n in range(scramble_from, scramble_to):
|
||||||
|
data_block[n - load_address] = (data_block[n - load_address] + data_block[n + 1 - load_address]) % 256
|
||||||
|
|
||||||
|
data_block[scramble_to - load_address] = (data_block[scramble_to - load_address] + seed) % 256
|
||||||
|
|
||||||
|
print("[ Encrypt ] gma6.modified")
|
||||||
|
|
||||||
|
# Write the output file for gma6.encrypted, which contains our modified game
|
||||||
|
# binary with the flicker-free code
|
||||||
|
|
||||||
|
output_file = open("gma6.encrypted", "wb")
|
||||||
|
output_file.write(data_block)
|
||||||
|
output_file.close()
|
||||||
|
|
||||||
|
print("[ Save ] gma6.encrypted")
|
||||||
|
|
||||||
|
# Finally, we need to remove the disk protection from gma1, as described here:
|
||||||
|
# https://www.lemon64.com/forum/viewtopic.php?t=67762&start=90
|
||||||
|
|
||||||
|
data_block = bytearray()
|
||||||
|
|
||||||
|
elite_file = open("gma1", "rb")
|
||||||
|
data_block.extend(elite_file.read())
|
||||||
|
elite_file.close()
|
||||||
|
|
||||||
|
print("[ Read ] gma1")
|
||||||
|
|
||||||
|
if platform == "pal":
|
||||||
|
# For elite[firebird_1986](pal)(v040486).g64
|
||||||
|
data_block[0x25] = 0xEA
|
||||||
|
data_block[0x26] = 0xEA
|
||||||
|
data_block[0x27] = 0xEA
|
||||||
|
data_block[0x2C] = 0xD0
|
||||||
|
else:
|
||||||
|
# For elite[firebird_1986](ntsc)(v060186)(!).g64
|
||||||
|
data_block[0x14] = 0xEA
|
||||||
|
data_block[0x16] = 0xEA
|
||||||
|
data_block[0x15] = 0xEA
|
||||||
|
|
||||||
|
print("[ Modify ] gma1")
|
||||||
|
|
||||||
|
output_file = open("gma1.modified", "wb")
|
||||||
|
output_file.write(data_block)
|
||||||
|
output_file.close()
|
||||||
|
|
||||||
|
print("[ Save ] gma1.modified")
|
||||||
|
print()
|
||||||
Loading…
Reference in a new issue