diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..dfa5dc00b --- /dev/null +++ b/Makefile @@ -0,0 +1,46 @@ +# +# 4cade Makefile +# assembles source code, optionally builds a disk image and mounts it +# +# original by Quinn Dunki on 2014-08-15 +# One Girl, One Laptop Productions +# http://www.quinndunki.com/blondihacks +# +# adapted by 4am on 2018-08-19 +# + +DISK=4cade.2mg + +# third-party tools required to build +# https://sourceforge.net/projects/acme-crossass/ +ACME=acme +# https://www.brutaldeluxe.fr/products/crossdevtools/cadius/ +# https://github.com/mach-kernel/cadius +CADIUS=cadius + +asm: md + $(ACME) -r build/prorwts2.lst src/PRORWTS2.S + +dsk: md asm + cadius CREATEVOLUME build/"$(DISK)" "A.4AM.PACK" 32MB +# cp res/_FileInformation.txt build/ +# bin/fixFileInformation.sh build/_FileInformation.txt +# $(CADIUS) ADDFILE build/"$(DISK)" "/A.4AM.PACK/" "res/CREDITS.TXT" +# $(CADIUS) CREATEFOLDER build/"$(DISK)" "/A.4AM.PACK/LIB/" +# $(CADIUS) ADDFILE build/"$(DISK)" "/A.4AM.PACK/LIB/" "build/ONBEYONDZ1" + +artwork: dsk + $(CADIUS) ADDFOLDER build/"$(DISK)" "/A.4AM.PACK/ARTWORK" "res/artwork" +# $(CADIUS) ADDFILE build/"$(DISK)" "/A.4AM.PACK/ARTWORK/" "res/DHRSLIDE.SYSTEM" +# $(CADIUS) ADDFOLDER build/"$(DISK)" "/A.4AM.PACK/ARTWORKGS" "res/artworkgs" + +mount: dsk + osascript bin/V2Make.scpt "`pwd`" bin/4cade.vii build/"$(DISK)" + +md: + mkdir -p build + +clean: + rm -rf build/ + +all: clean asm dsk artwork mount diff --git a/bin/4cade.vii b/bin/4cade.vii new file mode 100644 index 000000000..cc4fcc627 Binary files /dev/null and b/bin/4cade.vii differ diff --git a/res/catalog4.txt b/res/catalog4.txt index e834d2099..ead61e386 100644 --- a/res/catalog4.txt +++ b/res/catalog4.txt @@ -1,30 +1,31 @@ /---------name--------\/--directory--\ABC (A=1 if requires joystick; B=1 if requires 128K; C=1 if has good attract mode, 0=none, -=marginal, ?=unknown) -Agent USA AGENTUSA 01 -Airheart AIRHEART 1? +Agent USA AGENTUSA 001 +Airheart AIRHEART 110 Alcazar ALCAZAR 000 Alien Downpour ALIENDOWNPOUR 001 -Alien Rain ALIENRAIN 01 -Ankh ANKH 00 -Apple Panic APPLEPANIC 0- -Aquatron AQUATRON 01 -Arkanoid ARKANOID 01 -Battlezone BATTLEZONE 00 -BC's Quest For Tires BCSQUESTFORTIRE 00 -Beer Run BEERRUN 0- +Alien Rain ALIENRAIN 001 +Ankh ANKH 000 +Apple Panic APPLEPANIC 00- +Aquatron AQUATRON 001 +Arkanoid ARKANOID 101 +Battlezone BATTLEZONE 000 +BC's Quest For Tires BCSQUESTFORTIRE100 +Beer Run BEERRUN 00- Bellhop BELLHOP 00- Bill Budge's Trilogy BUDGETRILOGY 000 Bolo BOLO 001 -Brainteaser Boulevard BRAINTEASERBLVD 00 +Brainteaser Boulevard BRAINTEASERBLVD000 BurgerTime BURGERTIME 001 -Cannonball Blitz CANNONBALLBLITZ 0- +Cannonball Blitz CANNONBALLBLITZ00- Canyon Climber CANYONCLIMBER 001 -Centipede CENTIPEDE 0- -Choplifter CHOPLIFTER 01 -Commando COMMANDO 00 +Centipede CENTIPEDE 00- +Choplifter CHOPLIFTER 101 +Commando COMMANDO 000 Conan CONAN 001 -Crisis Mountain CRISISMOUNTAIN 00 -Crossfire CROSSFIRE 00 -David's Midnight Magic DAVIDSMIDNIGHTM 0- +Crisis Mountain CRISISMOUNTAIN 100 +Crossfire CROSSFIRE 000 +D-Generation DGENERATION 010 +David's Midnight Magic DAVIDSMIDNIGHTM10- Defender DEFENDER 00 Dig Dug DIGDUG 000 Dino Eggs DINOEGGS 01 @@ -40,8 +41,9 @@ Frogger FROGGER 000 Galaxian GALAXIAN 01 The Goonies GOONIES 00 Gremlins GREMLINS 00 +H.E.R.O. HERO 10? Hard Hat Mack HARDHATMACK 01 -H.E.R.O HERO 0? +Head On HEADON ?0? High Rise HIGHRISE 01 Hungry Boy HUNGRYBOY 00 Impossible Mission IMPOSSIBLEMISSI 00 @@ -50,13 +52,16 @@ Jungle Hunt JUNGLEHUNT 001 Karateka KARATEKA 01 Lady Tut LADYTUT 01 Lost Tomb LOSTTOMB 01 +Mad Bomber MADBOMBER ?0? Mario Bros MARIOBROS 000 +Montezuma's Revenge MONTEZUMASREVEN000 Moon Patrol MOONPATROL 0- Mr. Cool MRCOOL 01 Mr. Do MRDO 101 Mr. Robot MRROBOT 00- Ms. Pacman MSPACMAN 000 Nibbler NIBBLER 001 +Night Stalker NIGHTSTALKER ?0? Nightmare Gallery NIGHTMAREGALLER 00 NORAD NORAD 000 O'Riley's Mine ORILEYSMINE 01 @@ -77,7 +82,9 @@ Repton REPTON 01 Ribbit RIBBIT 01 Robotron 2084 ROBOTRON2084 01 Sabotage SABOTAGE 000 +Serpentine SERPENTINE ?0? Shamus SHAMUS 0- +Snack Attack SNACKATTACK 00? Snake Byte SNAKEBYTE 01 Sneakers SNEAKERS 001 Snoggle SNOGGLE 01 diff --git a/res/dsk/blister ball 4k file PRODOS (san inc crack).dsk b/res/dsk/blister ball 4k file PRODOS (san inc crack).dsk new file mode 100644 index 000000000..c6ea7db69 Binary files /dev/null and b/res/dsk/blister ball 4k file PRODOS (san inc crack).dsk differ diff --git a/res/dsk/d-generation PRODOS (san inc crack).po b/res/dsk/d-generation PRODOS (san inc crack).po new file mode 100644 index 000000000..3437fc94a Binary files /dev/null and b/res/dsk/d-generation PRODOS (san inc crack).po differ diff --git a/res/dsk/head on 6k file PRODOS (san inc crack).dsk b/res/dsk/head on 6k file PRODOS (san inc crack).dsk new file mode 100644 index 000000000..82e186431 Binary files /dev/null and b/res/dsk/head on 6k file PRODOS (san inc crack).dsk differ diff --git a/res/dsk/mad bomber 3k file PRODOS (san inc crack).dsk b/res/dsk/mad bomber 3k file PRODOS (san inc crack).dsk new file mode 100644 index 000000000..496d3348d Binary files /dev/null and b/res/dsk/mad bomber 3k file PRODOS (san inc crack).dsk differ diff --git a/res/dsk/montezuma's revenge 22k file PRODOS (san inc crack).dsk b/res/dsk/montezuma's revenge 22k file PRODOS (san inc crack).dsk new file mode 100644 index 000000000..76654bd9e Binary files /dev/null and b/res/dsk/montezuma's revenge 22k file PRODOS (san inc crack).dsk differ diff --git a/res/dsk/night stalker 22k file PRODOS (san inc crack).dsk b/res/dsk/night stalker 22k file PRODOS (san inc crack).dsk new file mode 100644 index 000000000..88fdfe518 Binary files /dev/null and b/res/dsk/night stalker 22k file PRODOS (san inc crack).dsk differ diff --git a/res/dsk/serpentine 18k file PRODOS (san inc crack).po b/res/dsk/serpentine 18k file PRODOS (san inc crack).po new file mode 100644 index 000000000..1e0dd8974 Binary files /dev/null and b/res/dsk/serpentine 18k file PRODOS (san inc crack).po differ diff --git a/res/dsk/snack attack 15k file PRODOS (san inc crack).dsk b/res/dsk/snack attack 15k file PRODOS (san inc crack).dsk new file mode 100644 index 000000000..5ee4eb372 Binary files /dev/null and b/res/dsk/snack attack 15k file PRODOS (san inc crack).dsk differ diff --git a/res/wishlist.txt b/res/wishlist.txt index 4003774a5..ee1e0a8c2 100644 --- a/res/wishlist.txt +++ b/res/wishlist.txt @@ -18,9 +18,9 @@ Championship Baseball Championship Lode Runner Championship Wrestling Conquering Worlds +Crazy Mazey Crime Wave Cubit -D-Generation [DHGR] Deathsword [DHGR] Dive Bomber Dunzhin @@ -63,6 +63,7 @@ Shuttle Intercept Skyfox Soko-Ban [DHGR] Spindizzy +The Spy Strikes Back Station 5 Street Sports Basketball Street Sports Soccer @@ -81,7 +82,6 @@ Xevious //4am has unreleased crack Black Magic -Blisterball Bop N Wrestle County Fair Free Fall @@ -90,7 +90,6 @@ GBA Championship Basketball Ghostbusters International Gran Prix Karate Champ -Mad Bomber Microwave Pentapus Pipe Dream [DHGR] @@ -102,18 +101,26 @@ Ski Crazed Bandits Bruce Lee Captain Goodnight -D-Generation [DHGR] The Goonies Injured Engine Jawbreaker ][ Mating Zone -Night Stalker Randamn -Snack Attack Test Drive Tetris +//TODO(woz-imaged but uncracked) +The Dam Busters +Fight Night +Hardball +One on One +Saracen +Rescue Raiders +Thexder [DHGR] +Zaxxon + //TODO(flux-imaged but not woz) +The Bilestoad Borg Buzzard Bait Cyber Strike @@ -121,50 +128,32 @@ Flywars Gamma Goblins Gorgon Lode Runner +Night Mission Pinball Orbitron Phantoms Five +Phaser Fire Pulsar II Raster Blaster Space Eggs +Spare Change Twerps Warp Destroyer Wayout -//TODO(woz-imaged but uncracked) -The Dam Busters -Fight Night -Hardball -The Spy Strikes Back -Zaxxon - -//TODO(unimaged) -Firebird -Night Mission Pinball -Rescue Raiders -Serpentine -Spare Change -The Bilestoad -Thexder [DHGR] - //TODO(unacquired) Ceiling Zero Congo Copts and Robbers -Crazy Mazey Dung Beetles Eggs It +Firebird Horizon V Ice Hockey International Hockey Lemmings -One on One -Phaser Fire -Saracen Shuffleboard Super Zaxxon Tempest //TODO(unreleased) Crystal Castles -Mario Bros. -Montezuma's Revenge diff --git a/src/PRORWTS2.S b/src/PRORWTS2.S new file mode 100644 index 000000000..9627655c1 --- /dev/null +++ b/src/PRORWTS2.S @@ -0,0 +1,2860 @@ +;license:BSD-3-Clause +;extended open/read/write binary file in ProDOS filesystem, with random access +;copyright (c) Peter Ferrie 2013-18 + +ver_02 = 1 + +!if ver_02 = 1 { + !cpu 6502 +} else { ;ver_02 = 0 + !cpu 65c02 +} ;ver_02 +!to "build/prorwts2",plain +*=$800 + +;place no code before init label below. + + ;user-defined options + verbose_info = 1 ;set to 1 to enable display of memory usage + enable_floppy = 0 ;set to 1 to enable floppy drive support + poll_drive = 0 ;set to 1 to check if disk is in drive, recommended if allow_multi is enabled + override_adr = 0 ;set to 1 to require an explicit load address + aligned_read = 1 ;set to 1 if all reads can be a multiple of block size + enable_write = 1 ;set to 1 to enable write support + ;file must exist already and its size cannot be altered + ;writes occur in multiples of block size + enable_seek = 0 ;set to 1 to enable seek support + ;seeking with aligned_read=1 requires non-zero offset + allow_multi = 0 ;set to 1 to allow multiple floppies + check_chksum = 0 ;set to 1 to enforce checksum verification for floppies + allow_subdir = 0 ;set to 1 to allow opening subdirectories to access files + might_exist = 0 ;set to 1 if file is not known to always exist already + ;makes use of status to indicate success or failure + allow_aux = 0 ;set to 1 to allow read/write directly to/from aux memory + ;requires load_high to be set for arbitrary memory access + ;else driver must be running from same memory target + ;i.e. running from main if accessing main, running from aux if accessing aux + allow_saplings=0 ;enable support for saplings + allow_trees = 0 ;enable support for tree files, as opposed to only seedlings and saplings + fast_trees = 0 ;keep tree block in memory, requires an additional 512 bytes of RAM + always_trees = 0 ;set to 1 if the only file access involves tree files + ;not compatible with allow_subdir, allow_saplings + detect_treof = 0 ;detect EOF during read of tree files + allow_sparse = 0 ;enable support for reading sparse files + bounds_check = 0 ;set to 1 to prevent access beyond the end of the file + ;but limits file size to 64k-2 bytes. + no_interrupts= 0 ;set to 1 to disable interrupts across calls + detect_err = 0 ;set to 1 to to detect errors in no_interrupt mode + swap_zp = 0 ;set to 1 to include code to preserve zpage + ;used only by rwts_mode + rwts_mode = 0 ;set to 1 to enable emulation of DOS RWTS when running from hard disk + ;uses a one-time open of a tree file, no other file access allowed + ;use unique volume numbers to distinguish between images in the same file + ;requires override_adr, enable_seek, allow_trees, always_trees + ;not compatible with enable_floppy, aligned_read, allow_subdir, might_exist, bounds_check + load_high = 1 ;set to 1 to load to top of RAM (either main or banked, enables a himem check) + load_aux = 0 ;load to aux memory + load_banked = 1 ;set to 1 to load into banked RAM instead of main RAM (can be combined with load_aux for aux banked) + lc_bank = 1 ;load into specified bank (1 or 2) if load_banked=1 + one_page = 1 ;set to 1 if verbose mode says that you should (smaller code) + + ;user-defined driver load address +!if load_banked = 1 { + !if load_high = 1 { + !ifdef PASS2 { + } else { ;PASS2 not defined + reloc = $ff00 ;page-aligned, as high as possible, the ideal value will be shown on mismatch + } ;PASS2 + } else { ;load_high = 0 + reloc = $d000 ;page-aligned, but otherwise wherever you want + } ;load_high +} else { ;load_banked = 0 + !if load_high = 1 { + !ifdef PASS2 { + } else { ;PASS2 not defined + reloc = $bf00 ;page-aligned, as high as possible, the ideal value will be shown on mismatch + } ;PASS2 + } else { ;load_high = 0 + reloc = $bc00 ;page-aligned, but otherwise wherever you want ($BC00 is common for rwts_mode) + } ;load_high +} ;load_banked + + ;there are also buffers that can be moved if necessary: + ;dirbuf, encbuf, treebuf (and corresponding hdd* versions that load to the same place) + ;they are independent of each other so they can be placed separately + ;see near EOF for those + ;note that hddencbuf must be even-page-aligned in RWTS-mode + + ;zpage usage, arbitrary selection except for the "ProDOS constant" ones + ;feel free to move them around + +!if (might_exist + poll_drive) > 0 { + status = $50 ;returns non-zero on error +} ;might_exist or poll_drive +!if allow_aux = 1 { + auxreq = $51 ;set to 1 to read/write aux memory, else main memory is used +} ;allow_aux + sizelo = $52 ;set if enable_write=1 and writing, or reading, or if enable_seek=1 and seeking + sizehi = $53 ;set if enable_write=1 and writing, or reading, or if enable_seek=1 and seeking +!if (enable_write + enable_seek + allow_multi + rwts_mode) > 0 { + reqcmd = $54 ;set (read/write/seek) if enable_write=1 or enable_seek=1 + ;if allow_multi=1, bit 7 selects floppy drive in current slot (clear=drive 1, set=drive 2) during open call + ;bit 7 must be clear for read/write/seek on opened file +} ;enable_write or enable_seek or allow_multi + ldrlo = $55 ;set to load address if override_adr=1 + ldrhi = $56 ;set to load address if override_adr=1 + namlo = $57 ;name of file to access + namhi = $58 ;name of file to access + +!if enable_floppy = 1 { + tmpsec = $3c ;(internal) sector number read from disk + reqsec = $3d ;(internal) requested sector number + curtrk = $40 ;(internal) track number read from disk +} ;enable_floppy + + command = $42 ;ProDOS constant + unit = $43 ;ProDOS constant + adrlo = $44 ;ProDOS constant + adrhi = $45 ;ProDOS constant + bloklo = $46 ;ProDOS constant + blokhi = $47 ;ProDOS constant + + entries = $3f ;(internal) total number of entries in directory + +!if rwts_mode = 1 { + lasttree = $59 ;(internal) last used index in tree buffer + lastvol = $5a ;(internal) last used volume number +} ;rwts_mode +!if allow_trees = 1 { + treeidx = $5b ;(internal) index into tree block + !if always_trees = 0 { + istree = $5c ;(internal) flag to indicate tree file + } ;always_trees + !if fast_trees = 0 { + treeblklo = $5d + treeblkhi = $5e + } ;fast_trees +} ;allow_trees + blkidx = $5f ;(internal) index into sapling block list +!if rwts_mode = 1 { + lastblk = $60 ;(internal) previous index into sapling block list +} ;rwts_mode +!if bounds_check = 1 { + bleftlo = $61 ;(internal) bytes left in file + blefthi = $62 ;(internal) bytes left in file +} ;bounds_check +!if (aligned_read + rwts_mode) = 0 { + blkofflo = $63 ;(internal) offset within cache block + blkoffhi = $64 ;(internal) offset within cache block +} ;not aligned_read and not rwts_mode + +!if enable_floppy = 1 { + step = $65 ;(internal) state for stepper motor + tmptrk = $66 ;(internal) temporary copy of current track + phase = $67 ;(internal) current phase for seek +} ;enable_floppy + + ;constants + cmdseek = 0 ;requires enable_seek=1 + cmdread = 1 ;requires enable_write=1 + cmdwrite = 2 ;requires enable_write=1 + SETKBD = $fe89 + SETVID = $fe93 + DEVNUM = $bf30 + PHASEOFF = $c080 + MOTOROFF = $c088 + MOTORON = $c089 + DRV0EN = $c08a + Q6L = $c08c + Q6H = $c08d + Q7L = $c08e + Q7H = $c08f + MLI = $bf00 + NAME_LENGTH = $4 ;ProDOS constant + MASK_SUBDIR = $d0 ;ProDOS constant + MASK_ALL = $f0 ;ProDOS constant + KEY_POINTER = $11 ;ProDOS constant + EOF_LO = $15 ;ProDOS constant + EOF_HI = $16 ;ProDOS constant + AUX_TYPE = $1f ;ProDOS constant + ENTRY_SIZE = $27 ;ProDOS constant + NEXT_BLOCK_LO = $2 ;ProDOS constant + NEXT_BLOCK_HI = $3 ;ProDOS constant + SAPLING = $20 ;ProDOS constant + FILE_COUNT = $25 ;ProDOS constant + DEVADR01HI = $bf11 ;ProDOS constant + ROMIN = $c081 + LCBANK2 = $c089 + CLRAUXRD = $c002 + CLRAUXWR = $c004 + SETAUXWR = $c005 + CLRAUXZP = $c008 + SETAUXZP = $c009 + + first_zp = $40 ;lowest address to save if swap_zp enabled + last_zp = $60 ;highest address to save if swap_zp enabled (max 127 entries later) + + D1S1 = 1 ;disk 1 side 1 volume ID if rwts_mode enabled + +init jsr SETKBD + jsr SETVID + lda DEVNUM + sta x80_parms + 1 + sta unrunit + 1 + and #$70 +!if (enable_floppy + enable_write) > 1 { + sta unrslot1 + 1 + sta unrslot2 + 1 + sta unrslot3 + 1 + sta unrslot4 + 1 +} ;enable_floppy and enable_write + pha +!if enable_floppy = 1 { + ora # 0 { + sta unrdrvoff2 + 1 + } ;might_exist or poll_drive + sta unrdrvoff3 + 1 + tax + inx ;MOTORON + !if allow_multi = 1 { + stx unrdrvon1 + 1 + } ;allow_multi + stx unrdrvon2 + 1 + stx unrdrvon3 + 1 + stx unrdrvon4 + 1 + inx ;DRV0EN + !if allow_multi = 1 { + stx unrdrvsel2 + 1 + } ;allow_multi + inx + !if allow_multi = 1 { + stx unrdrvsel1 + 1 + } ;allow_multi + inx ;Q6L + stx unrread1 + 1 + !if (poll_drive + allow_multi) > 0 { + stx unrread2 + 1 + stx unrread3 + 1 + } ;poll_drive or allow_multi + stx unrread4 + 1 + stx unrread5 + 1 + !if check_chksum = 1 { + stx unrread6 + 1 + } ;check_chksum +} ;enable_floppy + ldx #1 + stx namlo + inx + stx namhi + + ;fetch path, if any + + jsr MLI + !byte $c7 + !word c7_parms + ldx $200 + dex + stx sizelo + bmi +++ + + ;find current directory name in directory + +readblock jsr MLI + !byte $80 + !word x80_parms + + lda #<(readbuff + NAME_LENGTH) + sta bloklo + lda #>(readbuff + NAME_LENGTH) + sta blokhi +inextent ldy #0 + lda (bloklo), y + pha + and #$0f + tax +-- iny + lda (bloklo), y + cmp (namlo), y + beq ifoundname + + ;match failed, move to next directory in this block, if possible + +- pla + clc + lda bloklo + adc #ENTRY_SIZE + sta bloklo + bcc + + + ;there can be only one page crossed, so we can increment instead of adc + + inc blokhi ++ cmp #<(readbuff + $1ff) ;4 + ($27 * $0d) + lda blokhi + sbc #>(readbuff + $1ff) + bcc inextent + + ;read next directory block when we reach the end of this block + + lda readbuff + NEXT_BLOCK_LO + ldx readbuff + NEXT_BLOCK_HI + bcs + + +ifoundname dex + bne -- + + ;parse path until last directory is seen + + iny + lda (namlo), y + cmp #'/' + bne - + tya + eor #$ff + adc sizelo + sta sizelo + clc + tya + adc namlo + sta namlo + pla + and #$20 ;Volume Directory Header XOR subdirectory + bne ++ + + ;cache block number of current directory + ;as starting position for subsequent searches + + ldy #(KEY_POINTER + 1) + lda (bloklo), y + tax + dey + lda (bloklo), y +!if enable_floppy = 1 { + sta unrblocklo + 1 + stx unrblockhi + 1 +} ;enable_floppy + sta unrhddblocklo + 1 + stx unrhddblockhi + 1 ++ sta x80_parms + 4 + stx x80_parms + 5 +++ lda sizelo + bne readblock + + ;unit to slot for SmartPort interface + ++++ pla + lsr + lsr + lsr + tay + ldx DEVADR01HI, y + cpx #$c8 + bcc set_slot + ldx #$c8 +- dex + stx blokhi + ldy #0 + sty bloklo + iny + lda (bloklo), y + cmp #$20 + bne - + iny + iny + lda (bloklo), y + bne - + iny + iny + lda (bloklo), y + cmp #3 + bne - + ldy #$ff + lda (bloklo), y + beq - + +set_slot stx slot + 2 + stx unrentry + 2 +!if load_banked = 1 { + lda LCBANK2 - ((lc_bank - 1) * 8) + lda LCBANK2 - ((lc_bank - 1) * 8) +} ;load_banked +!if load_aux = 1 { + sta SETAUXWR + (load_banked * 4) ;SETAUXWR or SETAUXZP +} ;load_aux +!if enable_floppy = 1 { + ldx #>unrelocdsk + ldy #unrelochdd + ldy #((codeend - rdwrpart) + $ff) + ldy #0 +- lda (bloklo), y +reladr sta reloc, y + iny + bne - + inc blokhi + inc reladr + 2 + dex + bne - + plp + bne ++ + + ;build 6-and-2 denibbilisation table + + ldx #$16 +-- stx bloklo + txa + asl + bit bloklo + beq + + ora bloklo + eor #$ff + and #$7e +- bcs + + lsr + bne - + tya + sta nibtbl - $16, x + !if enable_write = 1 { + ;and 6-and-2 nibbilisation table if writing + + txa + ora #$80 + sta xlattbl, y + } ;enable_write + iny ++ inx + bpl -- + +unrdrvon1 lda MOTORON + jsr readadr + lda curtrk + sta trackd1 + + !if allow_multi = 1 { +unrdrvsel1 lda DRV0EN + 1 + jsr spinup + jsr poll + bcs + + lda #$c8 ;iny + sta twodrives + inc driveind + 1 + jsr readadr + lda curtrk + sta trackd2 ++ + } ;allow_multi +unrdrvoff1 lda MOTOROFF +++ +} else { ;enable_floppy = 0 +slot lda $cfff + sta unrentry + 1 + ldy #0 +- lda unrelochdd, y + sta reloc, y + + !if one_page = 0 { + ;hack to avoid address overflow when load_high and load_banked + ;and code is less than two pages long (e.g. aligned_read, no write) + ;can't insert code during pass two because it breaks existing offsets + + !ifdef PASS2 { + !if >(hddcodeend - reloc) > 0 { + !set hack=$100 + } ;hddcodeend + } else { ;PASS2 not defined + !set hack=0 + } ;PASS2 + lda unrelochdd + hack, y + sta reloc + hack, y + } ;one_page + iny + bne - +} ;enable_floppy +!if load_aux = 1 { + sta CLRAUXWR + (load_banked * 4) ;CLRAUXWR or CLRAUXZP +} ;load_aux + +!if rwts_mode = 1 { + ;read volume directory key block + ;self-modified by init code + +hddopendir +unrhddblocklo = * + ldx #2 +unrhddblockhi = * + lda #0 +hddreaddir1 jsr hddreaddirsel + + ;include volume directory header in count + +hddreaddir +hddfirstent lda #NAME_LENGTH + sta bloklo + lda #>(hdddirbuf - 1) + sta blokhi + + ;there can be only one page crossed, so we can increment here + +hddnextent1 inc blokhi +hddnextent ldy #0 + + ;match name lengths before attempting to match names + + lda (bloklo), y + and #$0f + tax + inx +- cmp filename, y + beq hddfoundname + + ;match failed, move to next entry in this block, if possible + ++ clc + lda bloklo + adc #ENTRY_SIZE + sta bloklo + bcs hddnextent1 + cmp #$ff ;4 + ($27 * $0d) + bne hddnextent + + ;read next directory block when we reach the end of this block + + ldx hdddirbuf + NEXT_BLOCK_LO + lda hdddirbuf + NEXT_BLOCK_HI + bcs hddreaddir1 + +hddfoundname iny + lda (bloklo), y + dex + bne - + + !if swap_zp = 0 { + !if allow_trees = 1 { + stx treeidx + sty lasttree ;guarantee no match + } ;allow_trees + stx blkidx + sty lastblk ;guarantee no match + } else { ;swap_zp = 1 + !if allow_trees = 1 { + stx zp_array + treeidx - first_zp + sty zp_array + lasttree - first_zp ;guarantee no match + } ;allow_trees + stx zp_array + blkidx - first_zp + sty zp_array + lastblk - first_zp ;guarantee no match + } ;swap_zp + + ;fetch KEY_POINTER + + ldy #KEY_POINTER + lda (bloklo), y + tax + iny + lda (bloklo), y + jsr hddreaddirsect + ldx #2 + stx sizehi + dex + stx reqcmd + dex + stx sizelo + stx ldrlo + lda #$b6 + sta ldrhi + jsr hddrdfile + jmp $b700 + +filename !byte filename_e-filename_b +filename_b !text "diskimage.dsk" +filename_e +} else { ;rwts_mode = 0 + rts +} ;rwts_mode + +c7_parms !byte 1 + !word $200 + +x80_parms !byte 3, $d1 + !word readbuff, 2 + +!if enable_floppy = 1 { +unrelocdsk +!pseudopc reloc { +rdwrpart + !if (override_adr + allow_subdir) > 0 { + ;only available when load address is specified + + jmp rdwrfile + } ;override_adr or allow_subdir +opendir + !if no_interrupts = 1 { + !if detect_err = 1 { + clc + } ;detect_err + php + sei + jsr + + !if detect_err = 1 { + pla + adc #0 + pha + } ;detect_err + plp + rts ++ + } ;no_interrupts + + ;read volume directory key block + ;self-modified by init code + +unrblocklo = unrelocdsk + (* - reloc) + ldx #2 +unrblockhi = unrelocdsk + (* - reloc) + lda #0 + jsr readdirsel + + ;include volume directory header in count + +readdir + !if might_exist = 1 { + ldx dirbuf + FILE_COUNT ;assuming only 256 files per subdirectory + inx + stx entries + } ;might_exist + +firstent lda #NAME_LENGTH + sta bloklo + lda #>(dirbuf - 1) + sta blokhi + + ;there can be only one page crossed, so we can increment here + +nextent1 inc blokhi +nextent ldy #0 + !if (might_exist + allow_subdir + allow_saplings + (allow_trees and (always_trees xor 1))) > 0 { + lda (bloklo), y + !if might_exist = 1 { + sty status + + ;skip deleted entries without counting + + and #MASK_ALL + beq + + } ;might_exist + + !if (allow_subdir + allow_saplings + (allow_trees and (always_trees xor 1))) > 0 { + ;remember type + ;now bits 5-4 are represented by carry (subdirectory), sign (sapling) + + asl + asl + + !if allow_trees = 1 { + ;now bits 5-3 are represented by carry (subdirectory), sign (sapling), + ;overflow (seedling), and sign+overflow (tree) + + sta treeidx + bit treeidx + } ;allow_trees + php + } ;allow_subdir or allow_saplings or (allow_trees and not always_trees) + } ;might_exist or allow_subdir or allow_saplings or (allow_trees and not always_trees) + + ;match name lengths before attempting to match names + + lda (bloklo), y + and #$0f + tax + inx +- cmp (namlo), y + beq foundname + + ;match failed, check if any directory entries remain + + !if (allow_subdir + allow_saplings + (allow_trees and (always_trees xor 1))) > 0 { + plp + } ;allow_subdir or allow_saplings or (allow_trees and not always_trees) + !if might_exist = 1 { + dec entries + bne + + } ;might_exist + !if (might_exist + poll_drive) > 0 { +nodisk +unrdrvoff2 = unrelocdsk + (* - reloc) + lda MOTOROFF + inc status + rts + } ;might_exist or poll_drive + + ;move to next entry in this block, if possible + ++ clc + lda bloklo + adc #ENTRY_SIZE + sta bloklo + bcs nextent1 + cmp #$ff ;4 + ($27 * $0d) + bne nextent + + ;read next directory block when we reach the end of this block + + ldx dirbuf + NEXT_BLOCK_LO + lda dirbuf + NEXT_BLOCK_HI + jsr readdirsec + bne firstent + +foundname iny + lda (bloklo), y + dex + bne - + + ;initialise essential variables + + !if allow_trees = 1 { + stx treeidx + !if always_trees = 0 { + stx istree + } ;always_trees + } ;allow_trees + stx blkidx + !if aligned_read = 0 { + stx blkofflo + stx blkoffhi + } ;aligned_read + !if enable_write = 1 { + ldy reqcmd + cpy #cmdwrite ;control carry instead of zero + bne + + + ;round requested size up to nearest block if writing + + lda sizelo + adc #$fe + lda sizehi + adc #1 + and #$fe + sta sizehi + !if aligned_read = 0 { + stx sizelo + !if bounds_check = 1 { + sec + } ;bounds_check + } ;aligned_read ++ + } ;enable_write + + !if bounds_check = 1 { + ;cache EOF (file size, loaded backwards) + + ldy #EOF_HI + lda (bloklo), y + !if (enable_write + aligned_read) > 0 { + tax + dey ;EOF_LO + lda (bloklo), y + + ;round file size up to nearest block if writing without aligned reads + ;or always if using aligned reads + + !if aligned_read = 0 { + bcc + + } else { ;aligned_read = 1 + !if enable_write = 1 { + sec + } ;enable_write + } ;aligned_read + adc #$fe + txa + adc #1 + and #$fe + !if aligned_read = 0 { + tax + lda #0 ++ stx blefthi + sta bleftlo + } else { ;aligned_read = 1 + sta blefthi + } ;aligned_read + } else { ;enable_write = 0 and aligned_read = 0 + sta blefthi + dey ;EOF_LO + lda (bloklo), y + sta bleftlo + } ;enable_write or aligned_read + } ;bounds_check + ;cache AUX_TYPE (load offset for binary files) + + !if override_adr = 0 { + ldy #AUX_TYPE + lda (bloklo), y + !if (allow_subdir + allow_saplings + allow_trees + (aligned_read xor 1)) > 0 { + sta ldrlo + iny + lda (bloklo), y + sta ldrhi + } else { ;allow_subdir = 0 and allow_saplings = 0 and allow_trees = 0 and aligned_read = 1 + pha + iny + lda (bloklo), y + pha + } ;allow_subdir or allow_saplings or allow_trees or not aligned_read + } ;override_adr + + ;cache KEY_POINTER + + ldy #KEY_POINTER + lda (bloklo), y + tax + !if (allow_subdir + allow_saplings + allow_trees) > 0 { + sta dirbuf + !if fast_trees = 0 { + sta treeblklo + } ;fast_trees + iny + lda (bloklo), y + sta dirbuf + 256 + !if fast_trees = 0 { + sta treeblkhi + } ;fast_trees + !if (allow_trees and always_trees) = 0 { + plp + bpl ++ + !if allow_subdir = 1 { + php + } ;allow_subdir + !if allow_trees = 1 { + ldy #>dirbuf + bvc + + !if fast_trees = 1 { + ldy #>treebuf + } ;fast_trees + sty istree ++ + } ;allow_trees + } else { ;allow_trees = 0 or always_trees = 1 + !if (allow_trees + always_trees) > 1 { + ldy #>treebuf + } ;allow_trees and always_trees + } ;allow_trees or always_trees + } else { ;allow_subdir = 0 and allow_saplings = 0 and allow_trees = 0 + iny + lda (bloklo), y + } ;allow_subdir or allow_saplings or allow_trees + + ;read index block in case of sapling or tree + + jsr readdirsect + + !if allow_subdir = 1 { + plp + } ;allow_subdir +++ + ;skip some stuff + ;drive is on already + ;and interrupt control is in place + + jmp rdwrfilei + +rdwrfile +unrdrvon2 = unrelocdsk + (* - reloc) + lda MOTORON + + !if no_interrupts = 1 { + !if detect_err = 1 { + clc + } ;detect_err + php + sei + jsr + + !if detect_err = 1 { + pla + adc #0 + pha + } ;detect_err + plp + rts ++ + } ;no_interrupts + +rdwrfilei + !if (allow_subdir + allow_saplings + allow_trees + (aligned_read xor 1)) > 0 { + ;restore load offset + + ldx ldrhi + lda ldrlo + !if allow_subdir = 1 { + ;check file type and fake size and load address for subdirectories + + bcc + + ldy #2 + sty sizehi + ldx #>dirbuf + lda #0 + !if aligned_read = 0 { + sta sizelo + } ;aligned_read ++ + } ;allow_subdir + sta adrlo + stx adrhi + } else { ;allow_subdir = 0 and allow_saplings = 0 and allow_trees = 0 and aligned_read = 1 + pla + sta adrhi + pla + sta adrlo + } ;allow_subdir or allow_saplings or allow_trees + + ;set requested size to min(length, requested size) + + !if aligned_read = 0 { + !if bounds_check = 1 { + ldy bleftlo + cpy sizelo + lda blefthi + tax + sbc sizehi + bcs copyblock + sty sizelo + stx sizehi + } ;bounds_check + +copyblock + !if allow_aux = 1 { + ldx auxreq + jsr setaux + } ;allow_aux + !if enable_write = 1 { + lda reqcmd + lsr + bne rdwrloop + } ;enable_write + lda blkofflo + tax + ora blkoffhi + beq rdwrloop + lda sizehi + pha + lda sizelo + pha + lda adrhi + sta blokhi + lda adrlo + sta bloklo + stx adrlo + lda #>encbuf + clc + adc blkoffhi + sta adrhi + + ;determine bytes left in block + + lda #1 + sbc blkofflo + tay + lda #2 + sbc blkoffhi + tax + + ;set requested size to min(bytes left, requested size) + + cpy sizelo + sbc sizehi + bcs + + sty sizelo + stx sizehi ++ + !if enable_seek = 1 { + lda sizehi + } else { ;enable_seek = 0 + ldy sizehi + } ;enable_seek + jsr copycache +unrdrvon3 = unrelocdsk + (* - reloc) + lda MOTORON ;copycache turns it off + lda ldrlo + adc sizelo + sta ldrlo + lda ldrhi + adc sizehi + sta ldrhi + sec + pla + sbc sizelo + sta sizelo + pla + sbc sizehi + sta sizehi + ora sizelo + bne rdwrfilei + !if allow_aux = 0 { + rts + } else { ;allow_aux = 1 + beq rdwrdone + } ;allow_aux + } else { ;aligned_read = 1 + !if bounds_check = 1 { + lda blefthi + cmp sizehi + bcs + + sta sizehi ++ + } ;bounds_check + !if allow_aux = 1 { + ldx auxreq + jsr setaux + } ;allow_aux + } ;aligned_read + +rdwrloop + !if aligned_read = 0 { + !if (enable_write + enable_seek) > 0 { + ldx reqcmd + } ;enable_write or enable_seek + + ;set read/write size to min(length, $200) + + lda sizehi + cmp #2 + bcs + + pha + lda #2 + sta sizehi + + ;redirect read to private buffer for partial copy + + lda adrhi + pha + lda adrlo + pha + lda #>encbuf + sta adrhi + !if ver_02 = 1 { + ldx #0 + stx adrlo + !if (enable_write + enable_seek) > 0 { + inx ;ldx #cmdread + } ;enable_write or enable_seek + } else { ;ver_02 = 0 + stz adrlo + !if (enable_write + enable_seek) > 0 { + ldx #cmdread + } ;enable_write or enable_seek + } ;ver_02 ++ + } ;aligned_read + + !if allow_trees = 1 { + ;read tree data block only if tree and not read already + ;the indication of having read already is that at least one sapling/seed block entry has been read, too + + ldy blkidx + bne + + !if always_trees = 0 { + lda istree + beq + + } ;always_trees + lda adrhi + pha + lda adrlo + pha + !if ((aligned_read xor 1) + (enable_write or enable_seek)) > 1 { + !if ver_02 = 1 { + txa + pha + } else { ;ver_02 = 0 + phx + } ;ver_02 + } ;(not aligned_read) and (enable_write or enable_seek) + lda #>dirbuf + sta adrhi + sty adrlo + + ;fetch tree data block and read it + + ldy treeidx + inc treeidx + ldx treebuf, y + lda treebuf + 256, y + !if aligned_read = 0 { + php + } ;aligned_read + + jsr seekrd + + !if aligned_read = 0 { + plp + !if (enable_write + enable_seek) > 0 { + !if ver_02 = 1 { + pla + tax + } else { ;ver_02 = 0 + plx + } ;ver_02 + } ;enable_write or enable_seek + } ;aligned_read + pla + sta adrlo + pla + sta adrhi + } ;allow_trees + + ;fetch data block and read/write it + + ldy blkidx ++ inc blkidx + !if aligned_read = 0 { + !if enable_seek = 1 { + txa ;cpx #cmdseek, but that would require php at top + beq + + } ;enable_seek + !if enable_write = 1 { + stx command + } ;enable_write + } ;aligned_read + + ldx dirbuf, y + lda dirbuf + 256, y + !if allow_sparse = 1 { + pha + ora dirbuf, y + tay + pla + dey + iny ;don't affect carry + } ;allow_sparse + !if aligned_read = 0 { + php + } ;aligned_read + !if allow_sparse = 1 { + beq issparse + } ;allow_sparse + !if (aligned_read + (enable_write or enable_seek)) > 1 { + ldy reqcmd + !if enable_seek = 1 { + beq + + } ;enable_seek + } ;aligned_read and (enable_write or enable_seek) + !if enable_write = 1 { + jsr seekrdwr + } else { ;enable_write = 0 + jsr seekrd + } ;enable_write +resparse + !if aligned_read = 0 { + plp + !if bounds_check = 1 { ++ bcc + + dec blefthi + dec blefthi + } ;bounds_check + } ;aligned_read ++ dec sizehi + dec sizehi + bne rdwrloop + +unrdrvoff3 = unrelocdsk + (* - reloc) + lda MOTOROFF + !if aligned_read = 0 { + bcc + + lda sizelo + bne rdwrloop + } ;aligned_read +rdwrdone + !if allow_aux = 1 { + ldx #0 +setaux sta CLRAUXRD, x + sta CLRAUXWR, x + } ;allow_aux + rts + + !if allow_sparse = 1 { +issparse +- sta (adrlo), y + iny + bne - + inc adrhi +- sta (adrlo), y + iny + bne - + dec adrhi + bne resparse + } ;allow_sparse + + !if aligned_read = 0 { + ;cache partial block offset + ++ pla + sta bloklo + pla + sta blokhi + pla + sta sizehi + dec adrhi + dec adrhi + + !if enable_seek = 1 { +copycache + ldy reqcmd + ;cpy #cmdseek + beq ++ + tay + } else { ;enable_seek = 0 + tay +copycache + } ;enable_seek + beq + + dey +- lda (adrlo), y + sta (bloklo), y + iny + bne - + inc blokhi + inc adrhi + bne + +- lda (adrlo), y + sta (bloklo), y + iny ++ cpy sizelo + bne - +++ + !if bounds_check = 1 { + lda bleftlo + sec + sbc sizelo + sta bleftlo + lda blefthi + sbc sizehi + sta blefthi + } ;bounds_check + clc + !if enable_seek = 1 { + lda sizelo + } else { ;enable_seek = 0 + tya + } ;enable_seek + adc blkofflo + sta blkofflo + lda sizehi + adc blkoffhi + and #$fd + sta blkoffhi + bcc rdwrdone ;always + } ;aligned_read + +spinup ldy #6 +- jsr delay + dey + bpl - + +delay +-- ldx #$11 +- dex + bne - + sec + sbc #1 + bne -- + rts + + ;no tricks here, just the regular stuff + +seek ldy #0 + sty step + asl phase + txa + asl +copy_cur tax + sta tmptrk + sec + sbc phase + beq +++ + bcs + + !if ver_02 = 1 { + eor #$ff + } else { ;ver_02 = 0 + inc + } ;ver_02 + inx + bcc ++ ++ + !if ver_02 = 1 { + sbc #1 + } else { ;ver_02 = 0 + dec + } ;ver_02 + dex +++ cmp step + bcc + + lda step ++ cmp #8 + bcs + + tay + sec ++ + !if ver_02 = 1 { + txa + pha + } else { ;ver_02 = 0 + phx + } ;ver_02 + ldx step1, y ++++ php + bne + +--- clc + lda tmptrk + ldx step2, y ++ stx tmpsec + and #3 + rol + tax + lsr +unrseek = unrelocdsk + (* - reloc) + lda PHASEOFF, x +-- ldx #$12 +- dex + bpl - + dec tmpsec + bne -- + bcs --- + plp + beq seekret + pla + inc step + bne copy_cur + +step1 !byte 1, $30, $28, $24, $20, $1e, $1d, $1c +step2 !byte $70, $2c, $26, $22, $1f, $1e, $1d, $1c + +readadr +- jsr readd5aa + cmp #$96 + bne - + ldy #3 +- sta curtrk + jsr readnib + rol + sta tmpsec + jsr readnib + and tmpsec + dey + bne - +seekret rts + +readd5aa +-- jsr readnib +- cmp #$d5 + bne -- + jsr readnib + cmp #$aa + bne - + tay ;we need Y=#$AA later + +readnib +unrread1 = unrelocdsk + (* - reloc) +- lda Q6L + bpl - + rts + + !if (poll_drive + allow_multi) > 0 { +poll ldy #0 +unrread2 = unrelocdsk + (* - reloc) +- lda Q6L + jsr seekret + pha + pla +unrread3 = unrelocdsk + (* - reloc) + cmp Q6L + clc + bne + + dey + bne - + sec ++ rts + } ;poll_drive or allow_multi + +readdirsel + !if ver_02 = 1 { + pha + txa + pha + } else { ;ver_02 + pha + phx + } ;ver_02 + +unrdrvon4 = unrelocdsk + (* - reloc) + lda MOTORON + !if (ver_02 + allow_multi) > 0 { + ldy #0 + sty adrlo + !if poll_drive = 1 { + sty status + } ;poll_drive + } else { ;ver_02 = 0 and allow_multi = 0 + stz adrlo + !if poll_drive = 1 { + stz status + } ;poll_drive + } ;ver_02 or allow_multi + !if allow_multi = 1 { + asl reqcmd + bcc seldrive +twodrives nop ;replace with INY if drive exists +seldrive lsr reqcmd +unrdrvsel2 = unrelocdsk + (* - reloc) + lda DRV0EN, y + cpy driveind + 1 + sty driveind + 1 + beq nodelay + jsr spinup + +nodelay + } ;allow_multi + !if poll_drive = 1 { + jsr poll + bcc + + pla + pla + pla + pla + jmp nodisk ++ + } ;poll_drive + !if ver_02 = 1 { + pla + tax + pla + } else { ;ver_02 + plx + pla + } ;ver_02 + +readdirsec + !if allow_trees = 0 { +readdirsect ldy #>dirbuf + } else { ;allow_trees = 1 + ldy #>dirbuf +readdirsect + } ;allow_trees + sty adrhi +seekrd ldy #cmdread + !if (aligned_read + enable_write) > 1 { +seekrdwr sty command + } else { ;aligned_read = 0 or enable_write = 0 + sty command +seekrdwr + } ;aligned_read and enable_write + + ;convert block number to track/sector + + lsr + txa + ror + lsr + lsr + sta phase + txa + and #3 + php + asl + plp + rol + sta reqsec + +driveind ldy #0 + ldx trackd1, y + + ;if track does not match, then seek + + cpx phase + beq checksec + lda phase + sta trackd1, y + jsr seek + + ;match or read/write sector + +checksec jsr cmpsecrd + inc reqsec + inc reqsec + +cmpsecrd jsr readadr + + !if enable_write = 1 { + ldy command + cpy #cmdwrite ;we need Y=2 below + beq encsec + } ;enable_write + cmp reqsec + bne cmpsecrd + + ;read sector data + + jsr readd5aa + eor #$ad ;zero A if match +;; bne * ;lock if read failure +unrread4 = unrelocdsk + (* - reloc) +- ldx Q6L + bpl - + eor nibtbl - $96, x + sta bit2tbl - $aa, y + iny + bne - +unrread5 = unrelocdsk + (* - reloc) +- ldx Q6L + bpl - + eor nibtbl - $96, x + sta (adrlo), y ;the real address + iny + bne - + !if check_chksum = 1 { +unrread6 = unrelocdsk + (* - reloc) +- ldx Q6L + bpl - + eor nibtbl - $96, x + bne cmpsecrd + } ;check_chksum +-- ldx #$a9 +- inx + beq -- + lda (adrlo), y + lsr bit2tbl - $aa, x + rol + lsr bit2tbl - $aa, x + rol + sta (adrlo), y + iny + bne - + inc adrhi + rts + + !if enable_write = 1 { +encsec +-- ldx #$aa +- dey + lda (adrlo), y + lsr + rol bit2tbl - $aa, x + lsr + rol bit2tbl - $aa, x + sta encbuf, y + lda bit2tbl - $aa, x + and #$3f + sta bit2tbl - $aa, x + inx + bne - + tya + bne -- + +cmpsecwr jsr readadr + cmp reqsec + bne cmpsecwr + + ;skip tail #$DE #$AA #$EB some #$FFs ... + + ldy #$24 +- dey + bpl - + + ;write sector data + +unrslot1 = unrelocdsk + (* - reloc) + ldx #$d1 + lda Q6H, x ;prime drive + lda Q7L, x ;required by Unidisk + tya + sta Q7H, x + ora Q6L, x + + ;40 cycles + + ldy #4 ;2 cycles + cmp $ea ;3 cycles + cmp ($ea, x) ;6 cycles +- jsr writenib1 ;(29 cycles) + + ;+6 cycles + dey ;2 cycles + bne - ;3 cycles if taken, 2 if not + + ;36 cycles + ;+10 cycles + ldy #(prolog_e - prolog) + ;2 cycles + cmp $ea ;3 cycles +- lda prolog - 1, y ;4 cycles + jsr writenib2 ;(17 cycles) + + ;32 cycles if branch taken + ;+6 cycles + dey ;2 cycles + bne - ;3 cycles if taken, 2 if not + + ;36 cycles on first pass + ;+10 cycles + tya ;2 cycles + ldy #$56 ;2 cycles +- eor bit2tbl - 1, y ;5 cycles + tax ;2 cycles + lda xlattbl, x ;4 cycles +unrslot2 = unrelocdsk + (* - reloc) + ldx #$d1 ;2 cycles + sta Q6H, x ;5 cycles + lda Q6L, x ;4 cycles + + ;32 cycles if branch taken + + lda bit2tbl - 1, y ;5 cycles + dey ;2 cycles + bne - ;3 cycles if taken, 2 if not + + ;32 cycles + ;+9 cycles + clc ;2 cycles +-- eor encbuf, y ;4 cycles +- tax ;2 cycles + lda xlattbl, x ;4 cycles +unrslot3 = unrelocdsk + (* - reloc) + ldx #$d1 ;2 cycles + sta Q6H, x ;5 cycles + lda Q6L, x ;4 cycles + bcs + ;3 cycles if taken, 2 if not + + ;32 cycles if branch taken + + lda encbuf, y ;4 cycles + iny ;2 cycles + bne -- ;3 cycles if taken, 2 if not + + ;32 cycles + ;+10 cycles + sec ;2 cycles + bcs - ;3 cycles + + ;32 cycles + ;+3 cycles ++ ldy #(epilog_e - epilog) + ;2 cycles + cmp ($ea, x) ;6 cycles +- lda epilog - 1, y ;4 cycles + jsr writenib2 ;(17 cycles) + + ;32 cycles if branch taken + ;+6 cycles + dey ;2 cycles + bne - ;3 cycles if branch taken, 2 if not + + lda Q7L, x + lda Q6L, x ;flush final value + inc adrhi + rts + +writenib1 jsr writeret ;6 cycles +writenib2 +unrslot4=unrelocdsk+(*-reloc) + ldx #$d1 ;2 cycles + sta Q6H, x ;5 cycles + ora Q6L, x ;4 cycles +writeret rts ;6 cycles + +prolog !byte $ad, $aa, $d5 +prolog_e +epilog !byte $ff, $eb, $aa, $de +epilog_e + } ;enable_write +codeend +trackd1 !byte 0 +trackd2 !byte 0 + +bit2tbl = (* + 255) & -256 +nibtbl = bit2tbl + 86 + !if enable_write = 1 { +xlattbl = nibtbl + 106 +dataend = xlattbl + 64 + } else { ;enable_write = 0 +dataend = nibtbl + 106 + } ;enable_write +} ;enable_floppy +} ;reloc + +unrelochdd +!pseudopc reloc { +!if rwts_mode = 1 { + !if swap_zp = 1 { + jsr swap_zpg + } ;swap_zp + sta namhi + sty namlo + !if ver_02 = 1 { + ldx #0 + stx reqcmd ;seek + stx sizehi + stx adrhi + } else { ;ver_02 + stz reqcmd ;seek + stz sizehi + stz adrhi + } ;ver_02 + ldy #$0c ;command + lda (namlo),y + cmp #2 ;write (or format if greater) + php + bcc skipinit ;read + beq skipinit ;write + ldy #5 ;sector + !if ver_02 = 1 { + txa + } else { ;ver_02 + lda #0 + } ;ver_02 + sta (namlo),y + dey ;track + sta (namlo),y +skipinit ldy #3 ;volume + lda (namlo),y + bne + + lda lastvol ++ cmp lastvol + sta lastvol + bne + + ror adrhi ;bit 7 set if same volume ++ ldy #$0e ;returned volume + sta (namlo),y + ldx #vollist_e-vollist_b +- dex + cmp vollist_b,x + bne - + ldy #4 ;track + lda (namlo),y + asl + asl + asl + rol sizehi + asl + rol sizehi + iny ;sector + ora (namlo),y + ldy sizehi +- dex + bmi ++ + clc + adc #$30 + bcc + + iny ++ iny + iny + bne - +++ tax + tya + lsr + sta treeidx + tay + txa + ror + php + ++ bit adrhi + bpl newtree + cpy lasttree + beq newblock + + ;volume or tree changed, so tree changed + +newtree sty lasttree + tax + beq newblock ;block zero will automatically read tree + pha + lda #0 + jsr seek1 + pla + + ;block changed, read it + +newblock jsr seek1 + plp + bcc + + inc adrhi ++ ldy #9 ;adrhi + lda (namlo),y + sta blokhi + dey ;adrlo + lda (namlo),y + sta bloklo + ldy #0 + plp + bcs runinit + !if swap_zp = 0 { + jmp hddcopycache + } else { ;swap_zp + jsr hddcopycache + beq swap_zpg + } ;swap_zp + +runinit php + dec blkidx + bne + + dec treeidx ++ ldx #0 + plp + bne format +- lda (bloklo),y + sta (adrlo),y + iny + bne - + lda #1 + bne writesec +clrcarry clc + inc adrhi +format lda blanksec,x + sta (adrlo),y + inx + txa + and #7 + tax + iny + bne format + bcs clrcarry + dex + stx lasttree + iny + lda #$18 ;blocks + +writesec sta namlo + sty namhi + lda adrhi + and #$fe + sta adrhi +- lda #cmdwrite ;also size + sta sizehi + sta reqcmd + jsr hddrdwrloop + dec adrhi + dec adrhi + dec namlo + bne - + dec namhi + bpl - + clc + + !if swap_zp = 1 { +swap_zpg + pha + tya + pha + ldx #(last_zp - first_zp) +- lda first_zp,x + ldy hddcodeend,x + sta hddcodeend,x + sty first_zp,x + dex + bpl - + pla + tay + pla + } ;swap_zp + rts + +blanksec !text "SAN INC." + +seek1 sta blkidx + lda #1 + sta sizehi +} else { ;rwts_mode + !if (override_adr + allow_subdir) > 0 { +hddrdwrpart jmp hddrdwrfile + } ;override_adr or allow_subdir +hddopendir + !if no_interrupts = 1 { + !if detect_err = 1 { + clc + } ;detect_err + php + sei + jsr + + !if detect_err = 1 { + pla + adc #0 + pha + } ;detect_err + plp + rts ++ + } ;no_interrupts + + ;read volume directory key block + ;self-modified by init code + +unrhddblocklo = unrelochdd + (* - reloc) + ldx #2 +unrhddblockhi = unrelochdd + (* - reloc) + lda #0 +hddreaddir1 jsr hddreaddirsel + + !if enable_floppy = 1 { + !if (* - hddopendir) < (readdir - opendir) { + ;essential padding to match offset with floppy version + !fill (readdir - opendir) - (* - hddopendir), $ea + } + } ;enable_floppy + + ;include volume directory header in count + +hddreaddir + !if might_exist = 1 { + ldx hdddirbuf + FILE_COUNT ;assuming only 256 files per subdirectory + inx + stx entries + } ;might_exist + +hddfirstent lda #NAME_LENGTH + sta bloklo + lda #>(hdddirbuf - 1) + sta blokhi + + ;there can be only one page crossed, so we can increment here + +hddnextent1 inc blokhi +hddnextent ldy #0 + !if (might_exist + allow_subdir + allow_saplings + (allow_trees and (always_trees xor 1))) > 0 { + lda (bloklo), y + !if might_exist = 1 { + sty status + + ;skip deleted entries without counting + + and #MASK_ALL + beq + + } ;might_exist + + !if (allow_subdir + allow_saplings + (allow_trees and (always_trees xor 1))) > 0 { + ;remember type + ;now bits 5-4 are represented by carry (subdirectory), sign (sapling) + + asl + asl + + !if allow_trees = 1 { + ;now bits 5-3 are represented by carry (subdirectory), sign (sapling), + ;overflow (seedling), and sign+overflow (tree) + + sta treeidx + bit treeidx + } ;allow_trees + php + } ;allow_subdir or allow_saplings or allow_trees + } ;might_exist or allow_subdir or allow_saplings or allow_trees + + ;match name lengths before attempting to match names + + lda (bloklo), y + and #$0f + tax + inx +- cmp (namlo), y + beq hddfoundname + + ;match failed, check if any directory entries remain + + !if (allow_subdir + allow_saplings + (allow_trees and (always_trees xor 1))) > 0 { + plp + } ;allow_subdir or allow_saplings or (allow_trees and not always_trees) + !if might_exist = 1 { + dec entries + bne + + inc status + rts + } ;might_exist + + ;move to next entry in this block, if possible + ++ clc + lda bloklo + adc #ENTRY_SIZE + sta bloklo + bcs hddnextent1 + cmp #$ff ;4 + ($27 * $0d) + bne hddnextent + + ;read next directory block when we reach the end of this block + + ldx hdddirbuf + NEXT_BLOCK_LO + lda hdddirbuf + NEXT_BLOCK_HI + !if might_exist = 1 { + jsr hddreaddirsec + bcc hddfirstent + } else { ;might_exist = 0 + bcs hddreaddir1 + } ;might_exist + +hddfoundname iny + lda (bloklo), y + dex + bne - + + ;initialise essential variables + + !if allow_trees = 1 { + stx treeidx + !if always_trees = 0 { + stx istree + } ;always_trees + } ;allow_trees + stx blkidx + !if aligned_read = 0 { + stx blkofflo + stx blkoffhi + } ;aligned_read + !if enable_write = 1 { + ldy reqcmd + cpy #cmdwrite ;control carry instead of zero + bne + + + ;round requested size up to nearest block if writing + + lda sizelo + adc #$fe + lda sizehi + adc #1 + and #$fe + sta sizehi + !if aligned_read = 0 { + stx sizelo + !if bounds_check = 1 { + sec + } ;bounds_check + } ;aligned_read ++ + } ;enable_write + + !if bounds_check = 1 { + ;cache EOF (file size, loaded backwards) + + ldy #EOF_HI + lda (bloklo), y + !if (enable_write + aligned_read) > 0 { + tax + dey ;EOF_LO + lda (bloklo), y + + ;round file size up to nearest block if writing without aligned reads + ;or always if using aligned reads + + !if aligned_read = 0 { + bcc + + } else { ;aligned_read = 1 + !if enable_write = 1 { + sec + } ;enable_write + } ;aligned_read + adc #$fe + txa + adc #1 + and #$fe + !if aligned_read = 0 { + tax + lda #0 ++ stx blefthi + sta bleftlo + } else { ;aligned_read = 1 + sta blefthi + } ;aligned_read + } else { ;enable_write = 0 and aligned_read = 0 + sta blefthi + dey ;EOF_LO + lda (bloklo), y + sta bleftlo + } ;enable_write or aligned_read + } ;bounds_check + ;cache AUX_TYPE (load offset for binary files) + + !if override_adr = 0 { + ldy #AUX_TYPE + lda (bloklo), y + !if (allow_subdir + allow_saplings + allow_trees + (aligned_read xor 1)) > 0 { + sta ldrlo + iny + lda (bloklo), y + sta ldrhi + } else { ;allow_subdir = 0 and allow_saplings = 0 and allow_trees = 0 and aligned_read = 1 + pha + iny + lda (bloklo), y + pha + } ;allow_subdir or allow_saplings or allow_trees or not aligned_read + } ;override_adr + + ;cache KEY_POINTER + + ldy #KEY_POINTER + lda (bloklo), y + tax + !if (allow_subdir + allow_saplings + allow_trees) > 0 { + sta hdddirbuf + !if fast_trees = 0 { + sta treeblklo + } ;fast_trees + iny + lda (bloklo), y + sta hdddirbuf + 256 + !if fast_trees = 0 { + sta treeblkhi + } ;fast_trees + !if (allow_trees and always_trees) = 0 { + plp + bpl ++ + !if allow_subdir = 1 { + php + } ;allow_subdir + !if allow_trees = 1 { + ldy #>hdddirbuf + bvc + + !if fast_trees = 1 { + ldy #>hddtreebuf + } ;fast_trees + sty istree ++ + } ;allow_trees + } else { ;allow_trees = 0 or always_trees = 1 + !if (allow_trees + always_trees) > 1 { + ldy #>hddtreebuf + } ;allow_trees and always_trees + } ;allow_trees or always_trees + } else { ;allow_subdir = 0 and allow_saplings = 0 and allow_trees = 0 + iny + lda (bloklo), y + } ;allow_subdir or allow_saplings or allow_trees + + ;read index block in case of sapling + + jsr hddreaddirsect + + !if allow_subdir = 1 { + plp + } ;allow_subdir +++ +} ;rwts_mode + +hddrdfile +hddrdwrfile +!if no_interrupts = 1 { + !if detect_err = 1 { + clc + } ;detect_err + php + sei + jsr + + !if detect_err = 1 { + pla + adc #0 + pha + } ;detect_err + plp + rts ++ +} ;no_interrupts + +hddrdwrfilei +!if rwts_mode = 0 { + !if (allow_subdir + allow_saplings + allow_trees + (aligned_read xor 1)) > 0 { + ;restore load offset + + ldx ldrhi + lda ldrlo + !if allow_subdir = 1 { + ;check file type and fake size and load address for subdirectories + + bcc + + ldy #2 + sty sizehi + ldx #>hdddirbuf + lda #0 + !if aligned_read = 0 { + sta sizelo + } ;aligned_read ++ + } ;allow_subdir + sta adrlo + stx adrhi + } else { ;allow_subdir = 0 and allow_saplings = 0 and allow_trees = 0 and aligned_read = 1 + pla + sta adrhi + pla + sta adrlo + } ;allow_subdir or allow_saplings or allow_trees + + ;set requested size to min(length, requested size) + + !if aligned_read = 0 { + !if bounds_check = 1 { + ldy bleftlo + cpy sizelo + lda blefthi + tax + sbc sizehi + bcs hddcopyblock + sty sizelo + stx sizehi + } ;bounds_check + +hddcopyblock + !if allow_aux = 1 { + ldx auxreq + jsr hddsetaux + } ;allow_aux + !if enable_write = 1 { + lda reqcmd + lsr + bne hddrdwrloop + } ;enable_write + + ;if offset is non-zero then we return from cache + + lda blkofflo + tax + ora blkofflo + beq hddrdwrloop + lda sizehi + pha + lda sizelo + pha + lda adrhi + sta blokhi + lda adrlo + sta bloklo + stx adrlo + lda #>hddencbuf + clc + adc blkoffhi + sta adrhi + + ;determine bytes left in block + + lda #1 + sbc blkofflo + tay + lda #2 + sbc blkoffhi + tax + + ;set requested size to min(bytes left, requested size) + + cpy sizelo + sbc sizehi + bcs + + sty sizelo + stx sizehi ++ + !if enable_seek = 1 { + lda sizehi + } else { ;enable_seek = 0 + ldy sizehi + } ;enable_seek + jsr hddcopycache + + ;align to next block and resume read + + lda ldrlo + adc sizelo + sta ldrlo + lda ldrhi + adc sizehi + sta ldrhi + sec + pla + sbc sizelo + sta sizelo + pla + sbc sizehi + sta sizehi + ora sizelo + bne hddrdwrfilei + !if allow_aux = 0 { + rts + } else { ;allow_aux + beq hddrdwrdone + } ;allow_aux + } else { ;aligned_read = 1 + !if bounds_check = 1 { + lda blefthi + cmp sizehi + bcs + + sta sizehi ++ + } ;bounds_check + !if allow_aux = 1 { + ldx auxreq + jsr hddsetaux + } ;allow_aux + } ;aligned_read +} ;rwts_mode + +hddrdwrloop +!if aligned_read = 0 { + !if rwts_mode = 0 { + !if (enable_write + enable_seek) > 0 { + ldx reqcmd + } ;enable_write or enable_seek + + ;set read/write size to min(length, $200) + + lda sizehi + cmp #2 + bcs + + pha + + ;redirect read to private buffer for partial copy + + lda adrhi + pha + lda adrlo + pha + lda #2 + sta sizehi + } ;rwts_mode + lda #>hddencbuf + sta adrhi + !if ver_02 = 1 { + ldx #0 + stx adrlo + !if ((enable_write + enable_seek) and (rwts_mode - 1)) > 0 { + inx ;ldx #cmdread + } ;(enable_write or enable_seek) and not rwts_mode + } else { ;ver_02 = 0 + stz adrlo + !if ((enable_write + enable_seek) and (rwts_mode - 1)) > 0 { + ldx #cmdread + } ;(enable_write or enable_seek) and not rwts_mode + } ;ver_02 ++ +} ;aligned_read + +!if allow_trees = 1 { + ;read tree data block only if tree and not read already + ;the indication of having read already is that at least one sapling/seed block entry has been read, too + + !if rwts_mode = 0 { + ldy blkidx + bne + + !if always_trees = 0 { + lda istree + beq + + } ;always_trees + } else { ;rwts_mode = 1 + ldy istree + } ;rwts_mode + lda adrhi + pha + lda adrlo + pha + !if rwts_mode = 0 { + !if ((aligned_read xor 1) + (enable_write or enable_seek)) > 1 { + !if ver_02 = 1 { + txa + pha + } else { ;ver_02 = 0 + phx + } ;ver_02 + } ;(not aligned_read) and (enable_write or enable_seek) + !if aligned_read = 0 { + php + } ;aligned_read + lda #>hdddirbuf + sta adrhi + sty adrlo + } else { ;rwts_mode = 1 + ;or in this case, read whenever tree index changes + + sty adrhi + ldy treeidx + cpy lasttree + beq skiptree + sty lasttree + ldx blkidx + inx + stx lastblk + } ;rwts_mode + + ;fetch tree data block and read it + + !if fast_trees = 0 { + ldx treeblklo + lda treeblkhi + jsr hddseekrd + ldy treeidx + !if rwts_mode = 0 { + inc treeidx + } ;rwts_mode + ldx hdddirbuf, y + lda hdddirbuf + 256, y + } else { ;fast_trees = 1 + ldy treeidx + !if rwts_mode = 0 { + inc treeidx + } ;rwts_mode + ldx hddtreebuf, y + lda hddtreebuf + 256, y + } ;fast_trees + !if detect_treof = 1 { + bne noteof1 + tay + txa + bne fixy1 + pla + pla + sec + rts +fixy1 tya +noteof1 + } ;detect_treof + !if aligned_read = 0 { + php + } ;aligned_read + + jsr hddseekrd + +skiptree + !if rwts_mode = 0 { + !if aligned_read = 0 { + plp + } ;aligned_read + !if ((aligned_read xor 1) + (enable_write or enable_seek)) > 1 { + !if ver_02 = 1 { + pla + tax + } else { ;ver_02 = 0 + plx + } ;ver_02 + } ;(not aligned_read) and (enable_write or enable_seek) + } ;rwts_mode + pla + sta adrlo + pla + sta adrhi +} ;allow_trees + + ;fetch data block and read/write it + +!if rwts_mode = 1 { ++ +} ;rwts_mode + ldy blkidx +!if rwts_mode = 0 { ++ inc blkidx + !if aligned_read = 0 { + !if enable_seek = 1 { + txa ;cpx #cmdseek, but that would require php at top + beq + + } ;enable_seek + !if enable_write = 1 { + stx command + } ;enable_write + } ;aligned_read +} else { ;rwts_mode = 1 + ;read whenever block index changes + + cpy lastblk + beq skipblk + sty lastblk +} ;rwts_mode + + ldx hdddirbuf, y + lda hdddirbuf + 256, y +!if detect_treof = 1 { + bne noteof2 + tay + txa + bne fixy2 + sec + rts +fixy2 tya +noteof2 +} ;detect_treof +!if allow_sparse = 1 { + pha + ora hdddirbuf, y + tay + pla + dey + iny ;don't affect carry +} ;allow_sparse +!if (aligned_read + rwts_mode) = 0 { + php +} ;aligned_read or rwts_mode +!if allow_sparse = 1 { + !if rwts_mode = 0 { + beq hddissparse + } else { ;rwts_mode = 1 + bne hddseekrd + } ;rwts_mode +} ;allow_sparse +!if rwts_mode = 0 { + !if (aligned_read and (enable_write or enable_seek)) = 1 { + ldy reqcmd + !if enable_seek = 1 { + beq + + } ;enable_seek + } ;aligned_read and (enable_write or enable_seek) + !if enable_write = 1 { + jsr hddseekrdwr + } else { ;enable_write = 0 + jsr hddseekrd + } ;enable_write +hddresparse + !if aligned_read = 0 { + plp + !if bounds_check = 1 { ++ bcc + + dec blefthi + dec blefthi + } ;bounds_check + } ;aligned_read + inc adrhi + inc adrhi ++ dec sizehi + dec sizehi + bne hddrdwrloop + !if aligned_read = 0 { + !if bounds_check = 0 { + bcc + + } ;bounds_check + lda sizelo + bne hddrdwrloop + } ;aligned_read +hddrdwrdone + !if allow_aux = 1 { + ldx #0 +hddsetaux sta CLRAUXRD, x + sta CLRAUXWR, x + } ;allow_aux + rts +} ;rwts_mode + +!if allow_sparse = 1 { +hddissparse +- sta (adrlo), y + inc adrhi + sta (adrlo), y + dec adrhi + iny + bne - + !if rwts_mode = 0 { + beq hddresparse + } ;rwts_mode +} ;allow_sparse +!if rwts_mode = 1 { +skipblk rts +} ;rwts_mode + +!if aligned_read = 0 { + ;cache partial block offset + ++ pla + sta bloklo + pla + sta blokhi + pla + sta sizehi + !if bounds_check = 0 { + dec adrhi + dec adrhi + } ;bounds_check + + !if enable_seek = 1 { + !if rwts_mode = 0 { +hddcopycache + } ;rwts_mode + ldy reqcmd + ;cpy #cmdseek + !if rwts_mode = 0 { + beq ++ + tay + } else { ;rwts_mode + beq hddrdwrdone +hddcopycache + } ;rwts_mode + } else { ;enable_seek = 0 + tay +hddcopycache + } ;enable_seek + !if rwts_mode = 0 { + beq + + dey + } ;rwts_mode +- lda (adrlo), y + sta (bloklo), y + iny + bne - + !if rwts_mode = 0 { + inc blokhi + inc adrhi + bne + +- lda (adrlo), y + sta (bloklo), y + iny ++ cpy sizelo + bne - +++ + !if bounds_check = 1 { + lda bleftlo + sec + sbc sizelo + sta bleftlo + lda blefthi + sbc sizehi + sta blefthi + } ;bounds_check + clc + !if enable_seek = 1 { + lda sizelo + } else { ;enable_seek = 0 + tya + } ;enable_seek + adc blkofflo + sta blkofflo + lda sizehi + adc blkoffhi + and #$fd + sta blkoffhi + bcc hddrdwrdone ;always + } else { ;rwts_mode = 1 + rts + } ;rwts_mode +} ;aligned_read + +hddreaddirsel +!if ver_02 = 1 { + ldy #0 + sty adrlo + !if might_exist = 1 { + sty status + } ;might_exist +} else { ;ver_02 = 0 + stz adrlo + !if might_exist = 1 { + stz status + } ;might_exist +} ;ver_02 + +!if allow_multi = 1 { + asl reqcmd + lsr reqcmd +} ;allow_multi + +hddreaddirsec +!if allow_trees = 0 { +hddreaddirsect ldy #>hdddirbuf +} else { ;allow_trees = 1 + ldy #>hdddirbuf +hddreaddirsect +} ;allow_trees + sty adrhi +hddseekrd ldy #cmdread +!if (aligned_read + enable_write) > 1 { +hddseekrdwr sty command +} else { ;aligned_read = 0 or enable_write = 0 + sty command +hddseekrdwr +} ;aligned_read and enable_write + + stx bloklo + sta blokhi + +unrunit=unrelochdd+(*-reloc) + lda #$d1 + sta unit +unrentry=unrelochdd+(*-reloc) + jmp $d1d1 + +!if rwts_mode = 1 { +vollist_b +!byte D1S1 +vollist_e +} ;rwts_mode +hddcodeend +!if swap_zp = 1 { +zp_array !fill last_zp - first_zp +} ;swap_zp +hdddataend +} ;reloc + +;[music] you can't touch this [music] +;math magic to determine ideal loading address, and information dump +!ifdef PASS2 { +} else { ;PASS2 not defined + !set PASS2=1 + !if enable_floppy = 1 { + !if reloc < $c000 { + !if ((dataend + $ff) & -256) > $c000 { + !serious "initial reloc too high, adjust to ", $c000 - (((dataend + $ff) & -256) - reloc) + } ;dataend + !if load_high = 1 { + !if ((dataend + $ff) & -256) != $c000 { + !warn "initial reloc too low, adjust to ", $c000 - (((dataend + $ff) & -256) - reloc) + } ;dataend + dirbuf = reloc - $200 + encbuf = dirbuf - $200 + !if allow_trees = 1 { + treebuf = encbuf - $200 + } ;allow_trees + } else { ;load_high = 0 + !pseudopc ((dataend + $ff) & -256) { + dirbuf = * + } + encbuf=dirbuf + $200 + !if allow_trees = 1 { + treebuf = encbuf + $200 + } ;allow_trees + } ;load_high + } else { ;reloc > $c000 + !if ((dataend + $ff) & -256) < reloc { + !serious "initial reloc too high, adjust to ", (0 - (((dataend + $ff) & -256) - reloc)) & $ffff + } ;dataend + !if load_high = 1 { + !if (((dataend + $ff) & -256) & $ffff) != 0 { + !warn "initial reloc too low, adjust to ", (0 - (((dataend + $ff) & -256) - reloc)) & $ffff + } ;dataend + dirbuf = reloc - $200 + encbuf = dirbuf - $200 + !if allow_trees = 1 { + treebuf = encbuf - $200 + } ;allow_trees + } else { ;load_high = 0 + !pseudopc ((dataend + $ff) & -256) { + dirbuf = * + } + encbuf = dirbuf + $200 + !if allow_trees = 1 { + treebuf = encbuf + $200 + } ;allow_trees + } ;load_high + } ;reloc + !if verbose_info = 1 { + !warn "floppy code: ", reloc, "-", codeend - 1 + !warn "floppy data: ", bit2tbl, "-", dataend - 1 + !warn "floppy dirbuf: ", dirbuf, "-", dirbuf + $1ff + !if aligned_read = 0 { + !warn "floppy encbuf: ", encbuf, "-", encbuf + $1ff + } ;aligned_read + !if (allow_trees + fast_trees) > 1 { + !warn "floppy treebuf: ", treebuf, "-", treebuf + $1ff + } ;allow_trees and fast_trees + !warn "floppy driver start: ", unrelocdsk - init + } ;verbose_info + } ;enable_floppy + !if reloc < $c000 { + !if ((hdddataend + $ff) & -256) > $c000 { + !serious "initial reloc too high, adjust to ", $c000 - (((hdddataend + $ff) & -256) - reloc) + } ;hdddataend + !if load_high = 1 { + !if ((hdddataend + $ff) & -256) != $c000 { + !warn "initial reloc too low, adjust to ", $c000 - (((hdddataend + $ff) & -256) - reloc) + } ;hdddataend + hdddirbuf = reloc - $200 + !if aligned_read = 0 { + hddencbuf = hdddirbuf - $200 + } ;aligned_read + !if allow_trees = 1 { + !if aligned_read = 0 { + hddtreebuf = hddencbuf - $200 + } else { ;aligned_read = 1 + hddtreebuf = hdddirbuf - $200 + } ;aligned_read + } ;allow_trees + } else { ;load_high = 0 + !pseudopc ((hdddataend + $ff) & -256) { + hdddirbuf = * + } + !if aligned_read = 0 { + hddencbuf = hdddirbuf + $200 + !if hddencbuf >= $c000 { + !if hddencbuf < $d000 { + !set hddencbuf = reloc - $200 + } + } + } ;aligned_read + !if allow_trees = 1 { + !if aligned_read = 0 { + hddtreebuf = hddencbuf + $200 + !if hddtreebuf >= reloc { + !if hddencbuf < hddcodeend { + !set hddtreebuf = hddencbuf - $200 + } + } + } else { ;aligned_read = 1 + hddtreebuf = hdddirbuf + $200 + } ;aligned_read + } ;allow_trees + } ;load_high + } else { ;reloc > $c000 + !if ((hdddataend + $ff) & -256) < reloc { + !serious "initial reloc too high, adjust to ", (0 - (((hdddataend + $ff) & -256) - reloc)) & $ffff + } ;hdddataend + !if load_high = 1 { + !if enable_floppy = 0 { + !if (((hdddataend + $ff) & -256) & $ffff) != 0 { + !warn "initial reloc too low, adjust to ", (0 - (((hdddataend + $ff) & -256) - reloc)) & $ffff + } ;hdddataend + } ;enable_floppy + hdddirbuf = reloc - $200 + !if aligned_read = 0 { + hddencbuf = hdddirbuf - $200 + } ;aligned_read + !if allow_trees = 1 { + !if aligned_read = 0 { + hddtreebuf = hddencbuf - $200 + } else { ;aligned_read = 1 + hddtreebuf = hdddirbuf - $200 + } ;aligned_read + } ;allow_trees + } else { ;load_high = 0 + !pseudopc ((hdddataend + $ff) & -256) { + hdddirbuf = * + } + !if aligned_read = 0 { + hddencbuf = hdddirbuf + $200 + } ;aligned_read + !if allow_trees = 1 { + !if aligned_read = 0 { + hddtreebuf = hddencbuf + $200 + } else { ;aligned_read = 1 + hddtreebuf = hdddirbuf + $200 + } ;aligned_read + } ;allow_trees + } ;load_high + } ;reloc + !if verbose_info = 1 { + !warn "hdd code: ", reloc, "-", hddcodeend - 1 + !if hddcodeend != hdddataend { + !warn "hdd data: ", hddcodeend, "-", hdddataend - 1 + } + !warn "hdd dirbuf: ", hdddirbuf, "-", hdddirbuf + $1ff + !if aligned_read = 0 { + !warn "hdd encbuf: ", hddencbuf, "-", hddencbuf + $1ff + } ;aligned_read + !if (allow_trees + fast_trees) > 1 { + !warn "hdd treebuf: ", hddtreebuf, "-", hddtreebuf + $1ff + } ;allow_trees and fast_trees + !warn "hdd driver start: ", unrelochdd - init + !if (one_page + enable_floppy) = 0 { + !if ((hddcodeend - hddopendir) < $100) { + !warn "one_page can be enabled, code is small enough" + } ;hddcodeend + } ;not one_page and not enable_floppy + } ;verbose_info +} ;PASS2 + +readbuff +!byte $D3,$C1,$CE,$A0,$C9,$CE,$C3,$AE