passport/src/passport.a

820 lines
24 KiB
Plaintext
Raw Normal View History

2017-01-08 03:35:35 +00:00
!cpu 6502
*=$2000
;-------------------------------
; Passport
; a 4am hack
; (c) 2016-7 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.
;
;-------------------------------
; Supported languages
; (each has its own localized strings file
; and its own output filename)
ENGLISH = 1 ; src/strings/en, PASSPORT.SYSTEM
FRENCH = 2 ; src/strings/fr, PASSPORT.FR
SPANISH = 3 ; src/strings/es, PASSPORT.ES
ITALIAN = 4 ; src/strings/it, PASSPORT.IT
FINNISH = 5 ; src/strings/fi, PASSPORT.FI
; Current language for this assembly
LANG = ENGLISH
!if LANG=ENGLISH {
!to "../build/PASSPORT.SYSTEM",plain
}
!if LANG=FRENCH {
!to "../build/PASSPORT.FR",plain
}
!if LANG=SPANISH {
!to "../build/PASSPORT.SP",plain
}
!if LANG=ITALIAN {
!to "../build/PASSPORT.IT",plain
}
!if LANG=FINNISH {
!to "../build/PASSPORT.FI",plain
}
;-------------------------------
; Addresses we read/call
TEXTTOP = $22
VPOS = $25
MLI = $BF00
REBOOT = $FAA6
TEXT = $FB2F
MACHINEID = $FBB3
HOME = $FC58
WAIT = $FCA8
PRBYTE = $FDDA
COUT = $FDED
PR0 = $FE89
IN0 = $FE93
; Zero-page addresses we use for variables
2017-01-30 22:10:41 +00:00
!ifdef PASS2 {
} else {
2017-01-08 03:35:35 +00:00
nibsrcindex = $EC ; byte
nibdestindex = $ED ; byte
prbuf = $EE ; word
unform = $F0 ; word
nibcount = $F2 ; byte
modtmp = $F3 ; byte
modsrc = $F4 ; word
moddest = $F6 ; word
cmp1 = $F8 ; word
cmp2 = $FA ; word
counter = $FC ; byte
tmp = $FC ; byte
tmpa = $FC ; byte
tmpx = $FD ; byte
tmpy = $FE ; byte
flag = $FF ; byte
2017-01-30 22:10:41 +00:00
}
2017-01-08 03:35:35 +00:00
; Application constants (not zero addresses)
RELBASE = $6300 ; address to move Passport code
2017-01-30 22:10:41 +00:00
; so that it's out of the way
2017-02-13 21:20:24 +00:00
LOWPOINT = $4300 ; lowest available address for code
2017-01-08 03:35:35 +00:00
BASEPAGE = $10 ; Special Delivery tracer assumes
; this is $10, so don't change it!
TRUE = $00 ; Lots of code assumes this is $00
; so it can branch with BEQ, so
; don't change it either!
FALSE = $01
ldx #$00
2017-01-30 22:10:41 +00:00
FM lda FirstMover + ((255 + LastMover - FirstMover) & $FF00),x
sta $B500,x
2017-01-08 03:35:35 +00:00
inx
bne FM
2017-01-30 22:10:41 +00:00
dec FM+2
dec FM+5
lda FM+2
cmp #$1F
2017-01-08 03:35:35 +00:00
bne FM
jmp OneTimeSetup
2017-01-30 22:10:41 +00:00
FirstMover
!pseudopc RELBASE {
!zone
2017-01-08 03:35:35 +00:00
; use localized strings based on current language
!if LANG=ENGLISH {
!source "strings/en.a"
}
!if LANG=FRENCH {
!source "strings/fr.a"
}
!if LANG=SPANISH {
!source "strings/es.a"
}
!if LANG=ITALIAN {
!source "strings/it.a"
}
!if LANG=FINNISH {
!source "strings/fi.a"
}
!source "analyze.a"
!source "id/inspect0.a"
!source "id/dos33.a"
2017-05-04 14:54:59 +00:00
!source "id/trace.a"
!source "id/prodos.a"
!source "id/pascal.a"
2017-01-08 03:35:35 +00:00
!source "id/jsr8b3.a"
!source "id/trace8b3.a"
2017-01-08 03:35:35 +00:00
!source "id/mecc.a"
!source "id/datasoft.a"
!source "id/protecteddos.a"
!source "id/specdelivery.a"
!source "id/encode44.a"
!source "id/encode53.a"
2017-01-30 22:10:41 +00:00
!source "id/ea.a"
2017-04-05 01:20:05 +00:00
!source "id/milliken.a"
!source "id/daviddos.a"
!source "id/quickdos.a"
!source "id/diversidos.a"
!source "id/prontodos.a"
2017-01-08 03:35:35 +00:00
!source "print.a"
!source "compare.a"
!source "modify.a"
!source "memory.a"
!source "sectormap.a"
!source "mli.a"
!source "slots.a"
!source "prefs.a"
!source "keys.a"
!source "cffa.a"
2017-01-08 03:35:35 +00:00
!source "rwts.a"
OneTimeSetup
lda $C0E8
jsr SaveProDOS
ldx MACHINEID
cpx #$EA
bne .slotscan
2017-01-08 03:35:35 +00:00
lda #$DF
sta kForceLower
.slotscan
2017-01-08 03:35:35 +00:00
jsr ScanForDiskII
lda DiskIIArray+5
bne .founds6
2017-01-08 03:35:35 +00:00
jmp FatalNoSlot6
.founds6
2017-01-08 03:35:35 +00:00
jsr LoadPrefs ; load preferences (if available)
bcc ResetVector
jsr SavePrefs ; save preferences (if possible)
ResetVector
lda #<ResetVector
sta $03F2
lda #>ResetVector
sta $03F3
eor #$A5
sta $03F4
lda $C0E8
jsr PR0
jsr IN0
sta $C000
sta $C002
sta $C004
sta $C00C
sta $C00E
MainMenu
ldx #$FF
txs
jsr TEXT
jsr ClearScreen
lda #s_header
jsr PrintByID
lda #s_mainmenu
jsr PrintByID
.getkey
2017-01-08 03:35:35 +00:00
jsr WaitForKey
cmp #$80
bne +
jsr EnterCFFAIfAvailable
bcc ResetVector
bcs .getkey
+ cmp #$9B
beq .jmptoexit
2017-01-08 03:35:35 +00:00
cmp #k_quit
bne +
.jmptoexit
2017-01-08 03:35:35 +00:00
jmp CleanExit
+
cmp #k_slot
bne +
jsr NextSlot
lda #TRUE
sta gChangedPrefs
jmp MainMenu
+
cmp #k_verify
bne +
lda #%00000000
beq Action ; unconditional branch
+
cmp #k_demuffin
bne +
lda #%10000000
bne Action ; unconditional branch
+
cmp #k_crack
bne .getkey
2017-01-08 03:35:35 +00:00
lda #%11000000
; note: execution falls through here
Action
sta gMode
jsr ResetProgress
jsr InitSectorMap
jsr CopyUniversal
lda #FALSE
sta gTriedUniv
sta gSaidWriting
lda #$00
sta gTrack
sta gSector
sta gPatchCount
sta callrwts+1
lda #$08
sta gAddress+1
jsr ClearScreen
lda #s_header
jsr PrintByID
lda #s_progbar
jsr PrintByID
lda VPOS
sta TEXTTOP
lda #s_reading
jsr PrintByID
;
; For the initial T00,S00 check, we need to wait much longer
; than usual to find the address prologue, because sector 0
; might literally be the only standard sector on the track.
; This will get overridden as soon as we either trace the
; disk's RWTS or copy the universal RWTS again. (One of these
; is guaranteed to happen before we read the rest of the disk.)
;
lda #$E7
sta $B945
ldy #<gRWTSParams ; call universal RWTS to see
lda #>gRWTSParams ; if T00,S00 is readable
jsr $BD00 ; (only care about the return code)
bcs .fatalt00s00
jmp .checkt00s00
.fatalt00s00
2017-01-08 03:35:35 +00:00
lda #$F0
sta $B959
lda #$05
sta $B95A
ldy #<gRWTSParams
lda #>gRWTSParams
jsr $BD00
bcs .reallyfatal
2017-01-08 03:35:35 +00:00
;
; Bad emulator detected (disk controller presents nibbles
; immediately instead of based on cycle count). Patch the
; universal RWTS to compensate.
;
lda #$F0
sta _B959
lda #$05
sta _B95A
bne .checkt00s00 ; unconditional branch
.reallyfatal
2017-01-08 03:35:35 +00:00
lda #s_fail
jsr PrintByID
lda #s_fatal0000
jsr PrintByID
jmp TheEnd
.checkt00s00
jmp IDBootloader ; /src/id/inspect0
2017-01-08 03:35:35 +00:00
;
; We are now fairly confident that the RWTS in memory
; is normal enough to call, Advanced Demuffin style.
;
ADStyle
jsr IncProgress
lda #s_diskrwts
jsr PrintByID
;
; Check for protections in early boot that
; might indicate intentional bad sectors
; elsewhere in the disk that we should skip,
; or changes we need to make to the RWTS
; before we start.
;
jsr xHeredityDog
bcs .noDog
2017-01-08 03:35:35 +00:00
lda #s_bb00
jsr PrintByID
.noDog
2017-01-08 03:35:35 +00:00
jsr xSunburst
bcs .noSun
2017-01-08 03:35:35 +00:00
lda #s_sunburst
jsr PrintByID
.noSun
2017-01-08 03:35:35 +00:00
jsr xOptimumRes
bcs .noOptimum
2017-02-10 05:13:35 +00:00
lda #TRUE
sta gIsOptimum
2017-01-08 03:35:35 +00:00
lda #s_optimum
jsr PrintByID
.noOptimum
2017-01-08 03:35:35 +00:00
jsr xB660
jsr xB4BB
jmp ReadWithRWTS
UseUniversal
jsr IncProgress
jsr StartWithUniv
; note: execution falls through here
ReadWithRWTS
lda #$22
jsr ChangeTrackNW
lda #$0F
jsr ChangeSector
lda #<T22S0F
sta checksector+1
lda #>T22S0F
sta checksector+2
.read
2017-01-08 03:35:35 +00:00
lda KEY
bpl checksector
jmp Cancel
checksector
lda $FFFF ; current sector in sector map
pha
beq nextsector ; #$00 = skip this sector
cmp #$FE ; #$FE = switch to built-in RWTS
bne + ; to read this sector
lda gTriedUniv
beq +
jsr SwitchToUniv
+
jsr ReadSector
bcc nextsector
pla
pha
;
; Uh oh, we got a read error. But do we care?
; Maybe we marked this sector as optional based
; on markers in the bootloader.
;
cmp #$80
beq .optional
2017-01-08 03:35:35 +00:00
;
; If we're in the middle of a track, try switching to the
; universal RWTS and see if that helps. (Many disks contain
; an RWTS that can't read the early tracks or sectors that
; contain the RWTS code, since those are loaded by the
; disk controller firmware.)
;
lda gSector
cmp #$0F
bne .tryuniversal
2017-01-08 03:35:35 +00:00
;
; We just got to this track, so check for a variety
; of whole-track conditions that might indicate we should
; just skip the entire track
jsr SkipTrack
2017-01-30 22:10:41 +00:00
bcs .tryuniversal
2017-01-08 03:35:35 +00:00
; Skip this track (we already printed the reason)
lda #$00
2017-01-08 03:35:35 +00:00
jsr ChangeSector
lda checksector+1
sec
sbc #$0F
sta checksector+1
bcs .notrackdec
2017-01-08 03:35:35 +00:00
dec checksector+2
.notrackdec
2017-01-08 03:35:35 +00:00
jmp nextsector
.tryuniversal
2017-01-08 03:35:35 +00:00
lda gTriedUniv ; have we tried the universal RWTS?
beq .fatal ; yes, so read error is fatal
2017-01-08 03:35:35 +00:00
jsr SwitchToUniv ; no, switch it in now
jmp .read ; and re-read this sector
2017-01-08 03:35:35 +00:00
.fatal pla ; if we get to here, we've
2017-01-08 03:35:35 +00:00
jmp FatalError ; decided the read error is fatal
.optional
2017-01-08 03:35:35 +00:00
lda #s_optbad ; say we're skipping this
jsr PrintByID ; optional sector
; note: execution falls through here
nextsector
pla
dec checksector+1
lda checksector+1
cmp #$FF
bne .nodec
2017-01-08 03:35:35 +00:00
dec checksector+2
.nodec
2017-01-08 03:35:35 +00:00
lda gSector
sec
sbc #$01
jsr ChangeSector
lda gSector
bmi .prevtrack
jmp .read
.prevtrack
2017-01-08 03:35:35 +00:00
lda #$0F
jsr ChangeSector
lda gTrack
sec
sbc #$01
jsr ChangeTrack
jsr IncProgress
lda gTrack
bmi .pass
2017-01-08 03:35:35 +00:00
cmp gLastTrack
bcc .pass
jmp .read
.pass
2017-01-08 03:35:35 +00:00
bit gMode
bmi .passwrite
2017-01-08 03:35:35 +00:00
lda #s_pass
bne .passprint ; always branches
.passwrite
bvs .passcrack
2017-01-08 03:35:35 +00:00
lda #s_passdemuf
bne .passprint ; always branches
.passcrack
2017-01-08 03:35:35 +00:00
lda gPatchCount
beq .passcrack0
2017-01-08 03:35:35 +00:00
lda #s_passcrack
!byte $2C ; hide next LDA
.passcrack0
2017-01-08 03:35:35 +00:00
lda #s_passcrack0
.passprint
2017-01-08 03:35:35 +00:00
jsr PrintByID
jmp TheEnd
SwitchToUniv
lda #s_switch
!byte $2C ; hide next LDA
StartWithUniv
lda #s_builtin
jsr PrintByID
lda #TRUE
sta gTriedUniv
lda #FALSE
sta gIsProtDOS
; note: execution falls through here
CopyUniversal
lda #>universalrwts
ldx #$B8
ldy #$08
jsr CopyMemory
lda #$00
sta callrwts+1
lda #$BD
sta callrwts+2
rts
Cancel
lda #s_canceled
jsr PrintByID
jmp TheEnd
FatalError
lda #s_fail
jsr PrintByID
lda gTrack
cmp #$22
beq .failont22
2017-01-08 03:35:35 +00:00
jmp TheEnd
.failont22
2017-01-08 03:35:35 +00:00
lda gSector
cmp #$0F
beq .failont22s0f
2017-01-08 03:35:35 +00:00
jmp TheEnd
.failont22s0f
2017-01-08 03:35:35 +00:00
lda #s_fatal220f
jsr PrintByID
; note: execution falls through here
TheEnd
lda $C0E8
lda #s_done
jsr PrintByID
jsr WaitForKey
cmp #$9B
beq CleanExit
jmp MainMenu
CleanExit
jsr SwapProDOS
lda gChangedPrefs
bne .doquit
2017-01-08 03:35:35 +00:00
jsr SavePrefs
.doquit
2017-01-08 03:35:35 +00:00
jsr MLI
!byte $65
!word .quitparm
.quitparm
!byte $04,$00,$00,$00,$00,$00,$00
2017-01-08 03:35:35 +00:00
FatalNoSlot6
lda #s_noslot6
jsr PrintByID
jsr WaitForKey
jmp CleanExit
ResetProgress
lda #$82 ; reset progress indicator
sta progressind+1
lda #$05
sta progressind+2
rts
IncProgress
lda #$20 ; display minimal progress indicator
progressind
sta $FFFF ; set at runtime
inc progressind+1
rts
;-------------------------------
; WriteTrack
;-------------------------------
MLI_IOERR = $27
MLI_NODEV = $28
MLI_WRITEPROT = $2B
WriteTrack
jsr AnalyzeTrack
WriteTrackNA ; entry point used by Special Delivery tracer
; to write track with "N"o "A"nalysis
bit gMode
bpl .done ; verify mode -> no write
2017-01-08 03:35:35 +00:00
lda gSaidWriting
beq .write
2017-01-08 03:35:35 +00:00
lda #s_writing ; only print "writing to" message once
jsr PrintByID
lda #TRUE
sta gSaidWriting
.write
2017-01-08 03:35:35 +00:00
jsr WriteTrackMLI
bcc .done
2017-01-08 03:35:35 +00:00
sta gDisplayBytes ; for use in error messages, if any
cmp #MLI_IOERR
beq .ioerr
2017-01-08 03:35:35 +00:00
cmp #MLI_NODEV
beq .nodev
2017-01-08 03:35:35 +00:00
cmp #MLI_WRITEPROT
beq .writeprot
2017-01-08 03:35:35 +00:00
lda #s_othermli
!byte $2C ; hide next LDA
.ioerr
2017-01-08 03:35:35 +00:00
lda #s_writeioerr
!byte $2C ; hide next LDA
.nodev
2017-01-08 03:35:35 +00:00
lda #s_writenodev
!byte $2C ; hide next LDA
.writeprot
2017-01-08 03:35:35 +00:00
lda #s_writeprot
pha
lda #s_writeerr
jsr PrintByID
pla
jsr PrintByID
jmp TheEnd
.done
2017-01-08 03:35:35 +00:00
rts
;-------------------------------
; ChangeTrack
; in: A = new track
;-------------------------------
ChangeTrack
pha
jsr WriteTrack
pla
; note: execution falls through here
ChangeTrackNW ; "N"o "W"rite
sta gTrack
jsr ClearTSBuffer
rts
;-------------------------------
; ChangeSector
; in: A = new sector
;-------------------------------
ChangeSector
sta gSector
clc
adc #BASEPAGE
sta gAddress+1
rts
;-------------------------------
; 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 as it finds and makes
; modifications in memory only.
; in: $BASEPAGE page contains one track worth of data
; 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
beq _applyToT00
jmp _applyToAll
_applyToT00
jsr AnalyzeT00 ; /src/id/inspect0
2017-01-08 03:35:35 +00:00
!source "patchers/sunburst.a"
!source "patchers/jmpbcf0.a"
!source "patchers/jmpbeb1.a"
!source "patchers/jmpbeca.a"
!source "patchers/jmpb660.a"
!source "patchers/jmpb720.a"
!source "patchers/bademu.a"
!source "patchers/bademu2.a"
!source "patchers/rwts.a"
!source "patchers/mecc1.a"
!source "patchers/mecc2.a"
!source "patchers/mecc3.a"
!source "patchers/mecc4.a"
2017-01-08 03:35:35 +00:00
!source "patchers/rol1e.a"
!source "patchers/jmpb4bb.a"
!source "patchers/jmpb4bbhi.a"
!source "patchers/thunder.a"
!source "patchers/jsrbb03.a"
!source "patchers/davidbb03.a"
!source "patchers/rwtsswap.a"
!source "patchers/rwtsswap2.a"
!source "patchers/border.a"
2017-01-08 03:35:35 +00:00
!source "patchers/jmpae8e.a"
!source "patchers/jmpbbfe.a"
!source "patchers/datasoft.a"
!source "patchers/nibtable.a"
!source "patchers/diskvol.a"
!source "patchers/c9ff.a"
2017-04-05 01:20:05 +00:00
!source "patchers/milliken.a"
!source "patchers/methods.a"
!source "patchers/jsr8b3.a"
2017-01-08 03:35:35 +00:00
_applyToAll
!source "patchers/universale7.a"
!source "patchers/runhello.a"
!source "patchers/a6bc95.a"
!source "patchers/a5count.a"
2017-01-08 03:35:35 +00:00
!source "patchers/d5d5f7.a"
!source "patchers/prodosrwts.a"
!source "patchers/prodos6a.a"
2017-01-08 03:35:35 +00:00
!source "patchers/prodosmecc.a"
!source "patchers/rwtsswapmecc.a"
!source "patchers/protecteddos.a"
2017-01-24 04:37:16 +00:00
!source "patchers/fbff.a"
2017-01-25 22:43:50 +00:00
!source "patchers/sierra.a"
!source "patchers/corrupter.a"
2017-01-30 22:10:41 +00:00
!source "patchers/ea.a"
!source "patchers/gamco.a"
2017-02-10 05:13:35 +00:00
!source "patchers/optimum.a"
!source "patchers/bootcounter.a"
2017-01-08 03:35:35 +00:00
lda gPatchCount
beq .nopatches
2017-01-08 03:35:35 +00:00
clc
!byte $24 ; hide next SEC
.nopatches
2017-01-08 03:35:35 +00:00
sec ; set carry if nothing happened
rts
;
; Global variables
;
gTriedUniv
!byte FALSE ; 0=true, 1=false
; whether or not we've already tried the built-in RWTS
; (and therefore a read error is fatal)
; reset before each operation
2017-01-08 03:35:35 +00:00
gMode
!byte %00000000 ; bit 7 0=verify, 1=see bit 6
; bit 6 0=demuffin, 1=crack
; set based on main menu choice
gPatchCount
!byte 00 ; int
; number of patches we've applied to this disk
2017-01-08 03:35:35 +00:00
; reset before each operation
; incremented in modify()
2017-01-08 03:35:35 +00:00
gSaidWriting
!byte FALSE ; 0=true, 1=false
; reset before each operation
; set to #TRUE after we print WRITING TO S%s,D%d
2017-01-08 03:35:35 +00:00
gChangedPrefs
!byte FALSE ; 0=true, 1=false
; whether we should try to write the configuration file
; when the program exits
2017-01-08 03:35:35 +00:00
; set to #TRUE when changing slots
gLastTrack
!byte 00 ; int
; the last track that we should try to read
; (assuming reading from T22 down to T00)
; reset to 0 before each operation, but some
; disks (like DOS3.3P) will change it because
; they write out the first few DOS tracks
; manually before seeking up to T22 to convert
; the rest of the disk
2017-01-08 03:35:35 +00:00
gIsBoot0
!byte FALSE ; 0=true, 1=false
; reset before each operation
; set in IDBootloader() after reading T00,S00
2017-01-08 03:35:35 +00:00
gIsBoot1
!byte FALSE ; 0=true, 1=false
; reset before each operation
; set in AnalyzeT00() after reading T00
2017-01-08 03:35:35 +00:00
gIsMaster
!byte FALSE ; 0=true, 1=false
; reset before each operation
; set in AnalyzeT00() after reading T00
2017-01-08 03:35:35 +00:00
gIsRWTS
!byte FALSE ; 0=true, 1=false
; reset before each operation
; set in AnalyzeT00() after reading T00
2017-01-08 03:35:35 +00:00
gIsProDOS
!byte FALSE ; 0=true, 1=false
; reset before each operation
; set in IDBootloader() after reading T00,S00
2017-01-08 03:35:35 +00:00
gIsPascal
!byte FALSE ; 0=true, 1=false
; reset before each operation
; set in IDBootloader() after reading T00,S00
2017-01-08 03:35:35 +00:00
gIsProtDOS
!byte FALSE ; 0=true, 1=false
; reset before each operation
; set in IDBootloader() after reading T00,S00
2017-01-30 22:10:41 +00:00
gIsEA
!byte FALSE ; 0=true, 1=false
; reset before each operation
; set in IDBootloader() after reading T00,S00
gIsEEEF
!byte FALSE ; 0=true, 1=false
; reset before each operation
; set in IsEEEF() after reading T22
2017-02-10 05:13:35 +00:00
gIsOptimum
!byte FALSE ; 0=true, 1=false
; reset before each operation
; set in IDBootloader() after reading T00,S00
gOnAClearDayYouCanReadForever
!byte FALSE ; 0=true, 1=false
; retry reads with a captured RWTS forever,
; instead of falling back to built-in RWTS
; compile-time flag, no way to change at runtime
2017-01-08 03:35:35 +00:00
!source "universalrwts.a"
}
2017-01-30 22:10:41 +00:00
LastMover
!if ($B500 - ((255 + LastMover - FirstMover) & $FF00)) != RELBASE {
!serious "RELBASE requires adjustment to ", ($B500 - ((255 + LastMover - FirstMover) & $FF00))
}
2017-02-13 21:20:24 +00:00
!if ($B500 - ((255 + LastMover - FirstMover) & $FF00)) < LOWPOINT {
!serious "code is too large to fit in available space!"
}