summaryrefslogtreecommitdiff
path: root/FFS.S
blob: 229f16f4dea158129da10644a839f3cd4d3b65ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
***************************************************************************
**                                                                       **
**   FFS.S  -  FastFileSystem-Laderoutine               (2. Generation)  **
**                                                                       **
***************************************************************************
**                                                                       **
**   Modification History                                                **
**   --------------------                                                **
**                                                                       **
**   Steinzeit  RS    Created this file!                                 **
**   01-Sep-89  CHW   Adaptiert für Exec (Packet-Interface)              **
**   ??-Nov-89  CHW   File-Size/512-Bytes-Guru-Bug fixed (GRRRR!)        **
**   18-Sep-90  CHW   74-Block-Bug gefunden, (2 Tage futsch! #@$*&!)     **
**                                                                       **
**   19-Sep-90  CHW   Neu programmiert, ist 200 Bytes kürzer worden :-)  **
**   29-Dec-90  CHW   Pure-Flag bedeutet File ist gecruncht              **
**                                                                       **
***************************************************************************

		OPT	OW6+

		IDNT	FastFileSystem
		SECTION	text,CODE

		INCLUDE	"MyExec.i"

CRUNCH
	IFD RAMVERSION


		XDEF	ProcessFFSPacket

***************************************************************************

BLOCKSIZE:	EQU	512		; Grösse eines Disk-Blocks in Bytes
ST.FILE:	EQU	-3		; SubTyp eines Files

   STRUCTURE FileHeaderBlock,0

	ULONG	fh_Type			;   0 T.SHORT
	ULONG	fh_OwnKey		;   1 Zeiger auf sich selbst
	ULONG	fh_HighSeq		;   2 Anzahl hier vermerkter Datenblöcke
	ULONG	fh_DataSize		;   3 Anzahl der benutzten Datenblöcke
	ULONG	fh_FirstData		;   4 Erster Datenblock
	ULONG	fh_CheckSum		;   5 Checksumme
	STRUCT	fh_BlockPtrs,4*72	;   6 Zeiger auf Datenblöcke (rückwärts!)
	LABEL	fh_BlockPtrEnd		;  78
	ULONG	fh_unused78		;  78
	ULONG	fh_unused79		;  79
	ULONG	fh_Protect		;  80 Protection-Bits
	ULONG	fh_FileSize		;  81 Grösse der Datei in Bytes
	STRUCT	fh_Comment,4*23		;  82 Kommentar als BCPL-String
	ULONG	fh_Days			; 105 Datum und Zeit der Erstellung
	ULONG	fh_Mins			; 106
	ULONG	fh_Ticks		; 107
	STRUCT	fh_Name,4*16		; 108 Dateiname als BCPL-String
	ULONG	fh_HashChain		; 124
	ULONG	fh_Parent		; 125 Zeiger auf Ursprungs-Directory
	ULONG	fh_Extension		; 126 Null oder Zeiger auf Extension
	ULONG	fh_SecondaryType	; 127 Sekundärtyp (ST.FILE)

	LABEL	fh_SIZEOF

	IFNE	fh_SIZEOF-BLOCKSIZE
	  FAIL	"Bad FileHeaderBlock structure!"
	ENDC

***************************************************************************
* CDisk-Packet (A0) abarbeiten (File aus der RAMDisk laden)

ProcessFFSPacket:
		movem.l	d0-d2/d7/a0-a3/a5,-(SP)
		movea.l	a0,a2			; A2 :  Packet
		move.l	#BLOCKSIZE,d7		; D7 :  BlockSize (immer)

		move.l	d7,d0			; 1 Block
		jsr	meb_AllocFastMem(a6)	; reservieren
		movea.l	d0,a5			; a5 :  Block-Buffer

		movea.l	dp_FileName(a2),a0
		bsr	FindFile		; Fileheader suchen
		bne.s	1$			; OK --->
		SMSG	<"FFS: File '%s' not found, packet=$%08lx">,a0,a2
		jmp	meb_ColdReboot(a6)
1$:
		bsr	GetBlock		; Fileheader laden
		moveq.l	#ST.FILE,d0
		cmp.l	fh_SecondaryType(a5),d0	; Ist's ein File ?
		beq.s	2$			; ja --->
		SMSG	<"FFS: '%'s is not a file, packet=$%08lx">,a0,a2
		jmp	meb_ColdReboot(a6)
2$:
		move.l	fh_FileSize(a5),d2	; D2 :  Datei-Größe in Bytes
		move.l	d2,dp_FileSize(a2)	; ins Packet eintragen

	IFD CRUNCH
		btst.b	#5,fh_Protect+3(a5)	; Pure-Bit gesetzt ?
		beq.s	.NotCrunched
		bset.b	#DPB_CRUNCHED,dp_Flags(a2)
		move.l	fh_FirstData(a5),d0	; 1. Datenblock
		bsr	GetBlock
		moveq.l	#PP_SAVEMARGIN,d2	; Sicherheitsabstand
		add.l	(a5),d2			; Plus ungecrunchte Länge
		movea.l	dp_FileName(a2),a0
		bsr	FindFile		; Fileheader suchen
		bsr	GetBlock		; Fileheader laden
.NotCrunched:
	ENDC
		btst.b	#DPB_ALLOCMEM,dp_Flags(a2) ; CHIP-Alloc gewünscht ?
		beq.s	.NoChipAlloc		; nein --->
		move.l	d2,d0			; File-Länge
		jsr	meb_AllocMem(a6)
		bra.s	.AllocCont		; --->
.NoChipAlloc:
		btst.b	#DPB_ALLOCFASTMEM,dp_Flags(a2) ; FAST-Alloc gewünscht?
		beq.s	.NoFastAlloc		; nein --->
		move.l	d2,d0			; File-Länge
		jsr	meb_AllocFastMem(a6)
.AllocCont:	move.l	d0,dp_Address(a2)	; Adresse ins Packet
.NoFastAlloc:
	IFD CRUNCH
		move.l	fh_FileSize(a5),d2	; D2 :  Datei-Größe in Bytes
	ENDC
		movea.l	dp_Address(a2),a1	; A1 :  Ziel-Adresse
.ExtLoop:	move.l	fh_HighSeq(a5),d1	; D1 :  Datablock-Zähler
		lea	fh_BlockPtrEnd(a5),a3	; A3 :  Datenblockpointer-Zeiger
		bra.s	.BlockDBF		; Für DBF
.BlockLoop:	move.l	-(a3),d0
		cmp.l	d7,d2			; Weniger als ein Block übrig ?
		blo.s	.LastBlock		; ja ---> Spezialfall
		movea.l	a1,a0			; Destination
		bsr	ReadBlock		; Datenblock nach (A0) lesen
		adda.l	d7,a1			; destination += BLOCKSIZE
		sub.l	d7,d2			; file size   -= BLOCKSIZE
.BlockDBF	dbf	d1,.BlockLoop

		move.l	fh_Extension(a5),d0	; File-Extension vorhanden ?
		beq.s	.End			; nein ---> fertig
		bsr	GetBlock		; Extension-Block nach (a5)
		bra.s	.ExtLoop		; ---> Loop

.LastBlock	bsr	GetBlock		; letzten Block nach (a5)
		movea.l	a5,a0			; Source
		move.l	d2,d0			; Size
		jsr	meb_CopyMem(a6)		; Daten kopieren
.End:
		movea.l	a5,a1			; Hilfs-Block
		jsr	meb_FreeMem(a6)		; freigeben

		movem.l	(SP)+,d0-d2/d7/a0-a3/a5
		rts

***************************************************************************
* File mit Namen (A0) finden und Header-Blocknummer nach D0 / CCR

FindFile:	movem.l	d1-d3/a0-a2,-(SP)

		move.l	meb_RAMDiskSize(a6),d0	; Grösse der Disk
		lsr.l	#5,d0			; /BLOCKSIZE/2 gibt Mitte
		lsr.l	#5,d0
		bsr	GetBlock		; Rootblock einlesen

		bsr	CalcHash		; Hashwert von (A0) berechnen
		beq.s	.FileNotFound		; ungültig --->
		move.l	0(a5,d0.w),d0		; D0 :  FileHeader-Blocknummer

.BlockLoop:	beq.s	.FileNotFound		; Nummer ungültig --->
		bsr	GetBlock		; Fileheaderblock einlesen

		movea.l	a0,a1			; Filename
		lea	fh_Name(a5),a2		; Name im Fileheader
		moveq.l	#0,d3
		move.b	(a2)+,d3		; Stringlänge
		bra.s	.Dbf
.CmpLoop:	move.b	(a1)+,d1
		move.b	(a2)+,d2
		andi.b	#$df,d1			; ToUpper
		andi.b	#$df,d2			; ToUpper
		cmp.b	d2,d1
		bne.s	.NextHash		; Nicht gleich ---> weitersuchen
.Dbf:		dbf	d3,.CmpLoop

.FileNotFound:	tst.l	d0			; CCR richtig setzen
		movem.l	(SP)+,d1-d3/a0-a2
		rts

.NextHash:	move.l	fh_HashChain(a5),d0	; Liste durchackern
		bra.s	.BlockLoop		; ---> Loop

***************************************************************************
* Hashwert des C-Strings (A0) berechnen

CalcHash:	movem.l	d1/a0-a1,-(SP)
		moveq.l	#0,d0			; Hashwert resetten
		tst.b	(a0)
		beq	.End

                movea.l	a0,a1			; Hash := strlen(name)
1$:		tst.b	(a1)+
		beq.s	2$
		addq.l	#1,d0
		bra.s	1$
2$:
.Loop:		moveq.l	#0,d1
		move.b	(a0)+,d1		; Nächstes Zeichen
		beq.s	4$			; Null ---> fertig
		cmpi.w	#'a',d1
		blo.s	3$
		cmpi.w	#'z',d1
		bhi.s	3$
		andi.b	#$df,d1			; char = ToUpper(char)
3$:
		mulu.w	#13,d0                  ; Hash *= 13
		add.l	d1,d0                   ; Hash += char
		andi.l	#$7ff,d0		; Hash &= $7FF
		bra.s	.Loop
4$:
                divu.w	#72,d0			; Hash %= 72
		swap	d0
                ext.l	d0
		addq.l	#6,d0			; Hash += 6 (Tabellenanfang)

.End:		lsl.l	#2,d0			; Hash *= 4, affect Z bit
		movem.l	(SP)+,d1/a0-a1
		rts

***************************************************************************
* Einen Block (D0=Blocknummer) in Buffer (A5) einlesen

GetBlock:	move.l	a0,-(SP)
		movea.l	a5,a0
		bsr.s	ReadBlock
		movea.l	(SP)+,a0
		rts

***************************************************************************
* Einen Block (D0=Blocknummer) an Adresse (A0) einlesen

ReadBlock:	movem.l	d0/a0-a1,-(SP)
		lsl.l	#5,d0			; Blocknr *BLOCKSIZE = Offset
		lsl.l	#4,d0
		move.l	a0,a1			; Destination
		movea.l	d0,a0			; Offset
		add.l	meb_RAMDiskBase(a6),a0	; Plus Basis-Adresse
		move.l	d7,d0			; Länge: 1 Block
		jsr	meb_CopyMem(a6)
		movem.l	(SP)+,d0/a0-a1
		rts

	ENDC

***************************************************************************

		END