passport/src/passport.a

511 lines
17 KiB
Plaintext
Executable File

;-------------------------------
; Passport
; a 4am hack
; (c) 2016-2021 by 4am
;
; Permission is hereby granted, free of charge, to any
; person obtaining a copy of this software and associated
; documentation files (the "Software"), to deal in the
; Software without restriction, including without limitation
; the rights to use, copy, modify, merge, publish,
; distribute, sublicense, and/or sell copies of the
; furnished to do so, subject to the following conditions:
;
; The above copyright notice and this permission notice
; shall be included in all copies or substantial portions of
; the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
; KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
; WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
; PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
; OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
; OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
; OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
;
;-------------------------------
!cpu 6502
!ifdef RELBASE {
*=RELBASE
} else {
*=$2000
}
!ifndef VERBOSE {
VERBOSE = $00 ; set to $01 to display API label addresses
}
!to "../build/PASSPORT.TMP",plain
!ct "lcase.ct"
Relocatable
!bin "../build/t00only.pak"
NonRelocatable
!source "apidefs.a"
!source "strings/en.a"
!source "id/inspect0.a"
!source "id/precheck.a"
!source "id/trace.a"
!source "id/trace33.a"
!source "id/trace32.a"
!source "id/trace8b3.a"
!source "id/trace33p.a"
!source "id/dos33.a"
!source "id/prodos.a"
!source "id/pascal.a"
!source "id/rdos.a"
!source "id/jsr8b3.a"
!source "id/mecc.a"
!source "id/datasoft.a"
!source "id/tsr.a"
!source "id/protecteddos.a"
!source "id/encode44.a"
!source "id/encode53.a"
!source "id/ea.a"
!source "id/milliken.a"
!source "id/daviddos.a"
!source "id/quickdos.a"
!source "id/diversidos.a"
!source "id/prontodos.a"
!source "id/d5d5f7.a"
!source "id/laureate.a"
!source "id/micrograms.a"
!source "id/volumename.a"
!source "id/dinkeydos.a"
!source "id/advent.a"
!source "id/panglosdos.a"
!source "id/davidson.a"
!source "id/holle.a"
!source "id/phoenix.a"
!source "id/555.a"
!source "id/bootfailure.a"
!source "print.a"
!source "compare.a"
!source "modify.a"
!source "memory.a"
!source "sectormap.a"
!source "write.a"
!source "mli.a"
!source "ramdisk.a"
!source "harddisk.a"
!source "slots.a"
!source "prefs.a"
!source "prefs.save.a"
!source "keys.a"
!source "cffa.a"
!source "progress.a"
!source "rwts.a"
!source "standarddelivery.a"
!source "wholetrack.a"
!source "adstyle.a"
!source "universalstyle.a"
!source "crackme.a"
MainMenu
jsr Cleanup ; RAM/HD files might be left open after Ctrl-Reset
jsr ClearScreen
jsr MoveT00PakLow
@refreshMainMenu
jsr PrintByID
!byte s_header
jsr PrintByID
!byte s_mainmenu
bit gTargetType
bmi @usingHardDisk
bvs @usingCFFA
lda #s_targetdisk
!byte $2C
@usingCFFA
lda #s_targetcffa
!byte $2C
@usingHardDisk
lda #s_targetfile
sta +
jsr PrintByID
+ !byte $FD ; SMC
@getkey
jsr WaitForKey
cmp #$80
bne +
jsr EnterCFFAIfAvailable
bcc MainMenu
bcs @getkey
+ cmp #$9B ; Esc quits
beq @jumpToExit
cmp #$91 ; Ctrl-Q quits
beq @jumpToExit
cmp #k_quit
bne +
@jumpToExit
jmp CleanExit
+ cmp #k_slot
bne +
jsr NextSlot
lda #0
sta HPOS
sta VPOS
jsr $FBC1
lda #TRUE
sta gChangedPrefs
beq @refreshMainMenu ; always branches
+ cmp #k_verify
bne +
lda #%00000000
beq Action ; always branches
+ cmp #k_crack
bne @getkey
lda #%11000000
; /!\ execution falls through here
Action
sta gMode
jsr InitSectorMap
Reaction
lda #FALSE
sta gTriedUniv
sta gSaidWriting
sta gIsProtDOS
sta gIsInfocom18
sta gIs13Sector
sta gIsRW18
lda #$00
sta gTrack
sta gSector
sta gPatchCount
sta jCallRWTS+1
sta CacheDst+1
lda #$08
sta gAddress+1
lda #$D4
sta CacheDst+2
jsr ShowInitialProgressScreen
lda gMode
bpl @printReading ; don't create RAM disk or hard disk file in verify mode
jsr LookupUnitNumberOfSelectedHardDisk
beq @notHardDrive
jsr SwapProDOS ; ProDOS out -> in (preserves flags)
jsr CreateFileOnHardDisk
jsr SwapProDOS ; ProDOS in -> out (preserves flags)
bcc @printReading
jmp FatalWriteError ; failed to create target file on hard disk
; this is fatal
@idBootloader
jmp IDBootloader ; /src/id/inspect0
@notHardDrive
lda RAMDiskImagePath
beq @printReading ; no RAM disk available
jsr SwapProDOS ; ProDOS out -> in (preserves flags)
jsr CreateFileOnRAMDisk
jsr SwapProDOS ; ProDOS in -> out (preserves flags)
bcc @printReading
lda #0 ; failed to create temporary file on RAM disk
sta RAMDiskImagePath ; this is not fatal, but we'll mark the RAM
; disk as unavailable so we don't bother with it
@printReading
jsr PrintByID
!byte s_reading
lda #$B2
ldx #$00
ldy #$0D
jsr ClearMemory
jsr CopyUniversal
jsr IgnoreAddressChecksum
jsr ReadSector
bcc @idBootloader
jsr IDBootFailure ; /src/id/bootfailure
bcc @idBootloader
jsr PrintByID
!byte s_fatal0000
; /!\ execution falls through here
TheEnd
jsr Cleanup
jsr PrintByID
!byte s_done
jsr WaitForKey
cmp #$9B
beq CleanExit
cmp #k_redo
beq HandleRedo
cmp #k_redo_with_ignore
beq HandleRedoWithIgnore
jsr CheckLogKeys
jmp MainMenu
HandleRedoWithIgnore
jsr InitSectorMapWithIgnore
jmp Reaction
HandleRedo
jsr ShowInitialProgressScreen
jsr PrintByID
!byte s_reading
; /!\ execution falls through here
;-------------------------------
; RestartScan
; Print 'Restarting scan...' then do exactly that.
; Used by several patchers that find evidence of a protection
; then activate an expensive search the second time around.
; Can be called from anywhere.
; Resets stack, never returns.
; Exits via ReadWithRWTS
;-------------------------------
RestartScan
jsr PrintByID
!byte s_restart
jsr RestartProgress
jsr IncProgress
ldx #$FF
txs
jmp ReadWithRWTS
;-------------------------------
; Cleanup
;
; Cleans up open files (if any)
; Also turns off slot 6 drive motor
;
; in: ProDOS is NOT in memory
; out: ProDOS is NOT in memory
; all registers and flags clobbered
;-------------------------------
Cleanup
lda $C0E8
lda gHardDiskRef
ora gRAMDiskRef
bne +
rts
jsr SwapProDOS ; ProDOS out -> in
jsr DeleteFileOnRAMDisk
+CloseFileOnHardDisk
jmp SwapProDOS ; ProDOS in -> out
;-------------------------------
; CleanExit
;
; Cleans up open files, saves preferences (if modified),
; and quits via ProDOS MLI
;
; in: ProDOS is NOT in memory
; out: does not return
;-------------------------------
CleanExit
jsr Cleanup
jsr SwapProDOS ; ProDOS out -> in
+SavePrefs
jsr PRODOSMLI ; does not return
!byte $65
!word +
+ !byte $04
;-------------------------------
; AnalyzeTrack routine
; Looks at buffer in memory to detect known
; copy protections and disable/revert/modify them
; to work on standard disks.
; Prints through COUT
; Makes modifications in memory only.
; in: @BASEPAGE contains one track worth of data ($1000 bytes)
; gTrack contains track number
; out: if C set, no known protections were found and
; no modifications were made
; if C clear, at least one modification was made
;-------------------------------
AnalyzeTrack
lda gTrack
bne @applyToAll
; Track 0 patchers are stored compressed in memory
; then decompressed into $2000 when needed
bit gMode
bpl @applyToAll ; only run track 0 modules in crack mode
lda T00PakPtr+1
sta _byte_hi
lda T00PakPtr
sta _byte_lo
jsr decrunch
jsr $2000
; /!\ execution falls through here
@applyToAll
; run these modules in verify and crack mode
!source "patchers/t11diskvol.a" ; T11 only
!source "patchers/t02volumename.a" ; T02 && gIsBoot0 only
bit gMode
bmi +
jmp _checkPatchCount
+
; only run these modules in crack mode
!source "patchers/universale7.a"
!source "patchers/c9ff.a"
!source "patchers/d5d5f7.a" ; gIsPascal || (gIsBoot0 && gPossibleD5D5F7) only
!source "patchers/rwtsswapmecc.a" ; gMECCFastloadType || gPossibleMECCSwapper only
!source "patchers/meccdqc.a" ; gMECCFastloadType==1 && gT07 only
!source "patchers/rwtsswappenguin.a" ; T01 only
!source "patchers/protecteddos.a" ; gIsProtDOS only
!source "patchers/fbff.a"
!source "patchers/corrupter.a" ; T13 only
!source "patchers/ea.a" ; gIsEA || gIsBoot0 only
!source "patchers/gamco.a" ; gPossibleGamco only
!source "patchers/optimum.a" ; gIsOptimum only
!source "patchers/bootcounter.a" ; T01 only
!source "patchers/jmp2012.a" ; T02 only
!source "patchers/advint.a" ; gAdventureInternational only
!source "patchers/jmpb4bb.a" ; T02 only
!source "patchers/dos32muse.a" ; T01 && gIsDOS32 only
!source "patchers/sra.a" ; gIsDOS32 || gIsBoot0 only
!source "patchers/sierra13.a" ; gIsDOS32 only
!source "patchers/ssprot.a" ; gIsF7F6 only
!source "patchers/f7f6.a" ; gIsF7F6 only
!source "patchers/trillium.a" ; gIsTrillium only
!source "patchers/trillium2.a" ; T17 only
!source "patchers/advent.a" ; gIsAdvent only
!source "patchers/davidsonforth.a" ; gIsDavidson only
!source "patchers/davidsonasm.a" ; gIsDavidson only
!source "patchers/ssi.a" ; gIsRDOS13 only
!source "patchers/rdosfmt.a" ; gIsRDOS13 only
!source "patchers/aacount.a"
!source "patchers/holle.a" ; gIsHolle only
!source "patchers/zoomgrafix.a" ; gIsPhoenix only
!source "patchers/e7everywhere.a" ; gIsBoot0 || gIsProDOS only
!source "patchers/choplifter.a" ; gIsChoplifter only
!source "patchers/tsr.a" ; T04 && gIsTSR only
!source "patchers/woodbury.a" ; gPossibleWoodbury only
!source "patchers/b4bbbasic.a" ; gPossibleB4BBBasic only
!source "patchers/errord51.a" ; gIsLowDOS only
!source "patchers/555.a" ; gIs555 only
;
; DOS 3.3-specific patchers
;
lda gIsBoot0
beq +
jmp _endDOS33Patchers
+
!source "patchers/hallabs.a" ; gIsBoot0 && T01 only
!source "patchers/harvey.a" ; gIsBoot0 && T01 only
!source "patchers/jmpb400.a" ; gIsBoot0 && T02 only
!source "patchers/jmpb412.a" ; gIsBoot0 && T02 only
!source "patchers/jsr8635.a" ; gIsBoot0 only
!source "patchers/sierra.a" ; gIsBoot0 only
_endDOS33Patchers
;
; Diversi-DOS-specific patchers
;
lda gIsDiversi
bne _endDiversiPatchers
!source "patchers/pdi.a" ; gIsDiversi only
!source "patchers/sigcheck.a" ; gIsDiversi only
_endDiversiPatchers
;
; ProDOS-specific patchers
;
lda gIsProDOS
beq +
jmp _endProDOSPatchers
+
!source "patchers/bbf9.a" ; gIsProDOS only
!source "patchers/fbffencrypted.a" ; gIsProDOS only
!source "patchers/leisure.a" ; gIsProDOS && T22 only
!source "patchers/memory.config.a" ; gIsProDOS only
!source "patchers/origin.a" ; gIsProDOS only
!source "patchers/polarware.a" ; gIsProDOS only
!source "patchers/prodos6a.a" ; gIsProDOS only
!source "patchers/prodosmecc.a" ; gIsProDOS only
!source "patchers/prodosrwts.a" ; gIsProDOS only
_endProDOSPatchers
;
; Pascal-specific patchers
;
lda gIsPascal
beq +
jmp _endPascalPatchers
+
!source "patchers/a5count.a" ; gIsPascal only
!source "patchers/a6bc95.a" ; gIsPascal only
!source "patchers/fbffpascal.a" ; gIsPascal only
_endPascalPatchers
_checkPatchCount
lda gPatchCount
beq @noPatches
clc
!byte $24 ; hide next SEC
@noPatches
sec ; set carry if nothing happened
rts
; utility functions used by several patchers
inx0F inx
inx0E inx
inx0D inx
inx0C inx
inx0B inx
inx0A inx
inx9 inx
inx8 inx
inx7 inx
inx6 inx
inx5 inx
inx4 inx
inx
inx
inx
rts
universalrwts
!bin "../build/universalrwts.pak"
!source "exodecrunch.s"
get_crunched_byte:
_byte_lo = * + 1
_byte_hi = * + 2
lda $1234 ; needs to be set correctly before
; decrunch_file is called.
inc _byte_lo
bne _byte_skip_hi
inc _byte_hi
_byte_skip_hi:
rts
!source "apicode.a" ; /!\ must be last
!if RELBASE = $2000 {
!ifdef PASS2 {
} else { ;PASS2
!set PASS2=1
!warn "RELBASE = ", HIGHPOINT - (* - Relocatable)
}
} else {
!if (HIGHPOINT - (* - NonRelocatable)) < LOWPOINT {
; code before NonRelocatable is moved and tracked, so it can be below LOWPOINT
!serious "My spoon is too big (", HIGHPOINT - (* - NonRelocatable), ") is below minimum (", LOWPOINT, ")!"
} else {
!warn "LowPoint=", NonRelocatable
}
!warn "ThisSlot=",ThisSlot
!warn "PrintByID=",PrintByID
!warn "WaitForKey=",WaitForKey
!warn "CleanExit=",CleanExit
!warn "OpenFile=",OpenFile
!warn "ReadFile=",ReadFile
!warn "CloseFile=",CloseFile
!warn "GetVolumeName=",GetVolumeName
!warn "GetVolumeInfo=",GetVolumeInfo
!warn "PREFSVER=",PREFSVER
!warn "PREFSFILE=",PREFSFILE
!warn "SLOT=",SLOT
!warn "DRIVE=",DRIVE
!warn "MainMenu=",MainMenu
!warn "CheckCache=",CheckCache
}