Subversion Repositories Kolibri OS

Rev

Rev 2288 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2288 Rev 3598
1
; Copyright (c) 2008-2009, diamond
1
; Copyright (c) 2008-2009, diamond
2
; All rights reserved.
2
; All rights reserved.
3
;
3
;
4
; Redistribution and use in source and binary forms, with or without
4
; Redistribution and use in source and binary forms, with or without
5
; modification, are permitted provided that the following conditions are met:
5
; modification, are permitted provided that the following conditions are met:
6
;       * Redistributions of source code must retain the above copyright
6
;       * Redistributions of source code must retain the above copyright
7
;       notice, this list of conditions and the following disclaimer.
7
;       notice, this list of conditions and the following disclaimer.
8
;       * Redistributions in binary form must reproduce the above copyright
8
;       * Redistributions in binary form must reproduce the above copyright
9
;       notice, this list of conditions and the following disclaimer in the
9
;       notice, this list of conditions and the following disclaimer in the
10
;       documentation and/or other materials provided with the distribution.
10
;       documentation and/or other materials provided with the distribution.
11
;       * Neither the name of the  nor the
11
;       * Neither the name of the  nor the
12
;       names of its contributors may be used to endorse or promote products
12
;       names of its contributors may be used to endorse or promote products
13
;       derived from this software without specific prior written permission.
13
;       derived from this software without specific prior written permission.
14
;
14
;
15
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka  ''AS IS'' AND ANY
15
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka  ''AS IS'' AND ANY
16
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
; DISCLAIMED. IN NO EVENT SHALL  BE LIABLE FOR ANY
18
; DISCLAIMED. IN NO EVENT SHALL  BE LIABLE FOR ANY
19
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
;*****************************************************************************
25
;*****************************************************************************
26
 
26
 
27
        jmp     far 0:real_start
27
        jmp     far 0:real_start
28
; special text
28
; special text
29
org $+0x7C00
29
org $+0x7C00
30
real_start:
30
real_start:
31
; initialize
31
; initialize
32
        xor     ax, ax
32
        xor     ax, ax
33
        mov     ss, ax
33
        mov     ss, ax
34
        mov     sp, 0x7C00
34
        mov     sp, 0x7C00
35
        mov     ds, ax
35
        mov     ds, ax
36
        mov     es, ax
36
        mov     es, ax
37
        cld
37
        cld
38
        sti
38
        sti
39
        mov     [bootdrive], dl
39
        mov     [bootdrive], dl
40
; check LBA support
40
; check LBA support
41
        mov     ah, 41h
41
        mov     ah, 41h
42
        mov     bx, 55AAh
42
        mov     bx, 55AAh
43
        int     13h
43
        int     13h
44
        mov     si, aNoLBA
44
        mov     si, aNoLBA
45
        jc      err_
45
        jc      err_
46
        cmp     bx, 0AA55h
46
        cmp     bx, 0AA55h
47
        jnz     err_
47
        jnz     err_
48
        test    cl, 1
48
        test    cl, 1
49
        jz      err_
49
        jz      err_
50
; get file system information
50
; get file system information
51
; scan for Primary Volume Descriptor
51
; scan for Primary Volume Descriptor
52
        db      66h
52
        db      66h
53
        push    10h-1
53
        movi    eax, 10h-1
54
        pop     eax
-
 
55
pvd_scan_loop:
54
pvd_scan_loop:
56
        mov     cx, 1
55
        mov     cx, 1
57
        inc     eax
56
        inc     eax
58
        mov     bx, 0x1000
57
        mov     bx, 0x1000
59
        call    read_sectors
58
        call    read_sectors
60
        jnc     @f
59
        jnc     @f
61
fatal_read_err:
60
fatal_read_err:
62
        mov     si, aReadError
61
        mov     si, aReadError
63
err_:
62
err_:
64
        call    out_string
63
        call    out_string
65
        mov     si, aPressAnyKey
64
        mov     si, aPressAnyKey
66
        call    out_string
65
        call    out_string
67
        xor     ax, ax
66
        xor     ax, ax
68
        int     16h
67
        int     16h
69
        int     18h
68
        int     18h
70
        jmp     $
69
        jmp     $
71
@@:
70
@@:
72
        push    ds
71
        push    ds
73
        pop     es
72
        pop     es
74
        cmp     word [bx+1], 'CD'
73
        cmp     word [bx+1], 'CD'
75
        jnz     pvd_scan_loop
74
        jnz     pvd_scan_loop
76
        cmp     word [bx+3], '00'
75
        cmp     word [bx+3], '00'
77
        jnz     pvd_scan_loop
76
        jnz     pvd_scan_loop
78
        cmp     byte [bx+5], '1'
77
        cmp     byte [bx+5], '1'
79
        jnz     pvd_scan_loop
78
        jnz     pvd_scan_loop
80
; we have found ISO9660 descriptor, look for type
79
; we have found ISO9660 descriptor, look for type
81
        cmp     byte [bx], 1    ; Primary Volume Descriptor?
80
        cmp     byte [bx], 1    ; Primary Volume Descriptor?
82
        jz      pvd_found
81
        jz      pvd_found
83
        cmp     byte [bx], 0xFF ; Volume Descriptor Set Terminator?
82
        cmp     byte [bx], 0xFF ; Volume Descriptor Set Terminator?
84
        jnz     pvd_scan_loop
83
        jnz     pvd_scan_loop
85
; Volume Descriptor Set Terminator reached, no PVD found - fatal error
84
; Volume Descriptor Set Terminator reached, no PVD found - fatal error
86
        mov     si, no_pvd
85
        mov     si, no_pvd
87
        jmp     err_
86
        jmp     err_
88
pvd_found:
87
pvd_found:
89
        add     bx, 80h
88
        add     bx, 80h
90
        mov     ax, [bx]
89
        mov     ax, [bx]
91
        mov     [lb_size], ax
90
        mov     [lb_size], ax
92
; calculate number of logical blocks in one sector
91
; calculate number of logical blocks in one sector
93
        mov     ax, 800h
92
        mov     ax, 800h
94
        cwd
93
        cwd
95
        div     word [bx]
94
        div     word [bx]
96
        mov     [lb_per_sec], ax
95
        mov     [lb_per_sec], ax
97
; get location of root directory
96
; get location of root directory
98
        mov     di, root_location
97
        mov     di, root_location
99
        movzx   eax, byte [bx+1Dh]
98
        movzx   eax, byte [bx+1Dh]
100
        add     eax, [bx+1Eh]
99
        add     eax, [bx+1Eh]
101
        stosd
100
        stosd
102
; get memory size
101
; get memory size
103
        int     12h
102
        int     12h
104
        mov     si, nomem_str
103
        mov     si, nomem_str
105
        cmp     ax, 71000h / 400h
104
        cmp     ax, 71000h / 400h
106
        jb      err_
105
        jb      err_
107
        shr     ax, 1
106
        shr     ax, 1
108
        sub     ax, 60000h / 800h
107
        sub     ax, 60000h / 800h
109
        mov     [size_rest], ax
108
        mov     [size_rest], ax
110
        mov     [free_ptr], 60000h / 800h
109
        mov     [free_ptr], 60000h / 800h
111
; load path table
110
; load path table
112
; if size > 62K => it's very strange, avoid using it
111
; if size > 62K => it's very strange, avoid using it
113
; if size > (size of cache)/2 => avoid using it too
112
; if size > (size of cache)/2 => avoid using it too
114
        mov     ecx, [bx+4]
113
        mov     ecx, [bx+4]
115
        cmp     ecx, 0x10000 - 0x800
114
        cmp     ecx, 0x10000 - 0x800
116
        ja      nopathtable
115
        ja      nopathtable
117
        shr     ax, 1
116
        shr     ax, 1
118
        cmp     ax, 0x20
117
        cmp     ax, 0x20
119
        jae     @f
118
        jae     @f
120
        shl     ax, 11
119
        shl     ax, 11
121
        cmp     cx, ax
120
        cmp     cx, ax
122
        ja      nopathtable
121
        ja      nopathtable
123
@@:
122
@@:
124
; size is ok, try to load it
123
; size is ok, try to load it
125
        mov     [pathtable_size], cx
124
        mov     [pathtable_size], cx
126
        mov     eax, [bx+12]
125
        mov     eax, [bx+12]
127
        xor     edx, edx
126
        xor     edx, edx
128
        div     dword [lb_per_sec]
127
        div     dword [lb_per_sec]
129
        imul    dx, [bx]
128
        imul    dx, [bx]
130
        mov     [pathtable_start], dx
129
        mov     [pathtable_start], dx
131
        add     cx, dx
130
        add     cx, dx
132
        call    cx_to_sectors
131
        call    cx_to_sectors
133
        xor     bx, bx
132
        xor     bx, bx
134
        push    6000h
133
        push    6000h
135
        pop     es
134
        pop     es
136
        call    read_sectors
135
        call    read_sectors
137
        jc      nopathtable
136
        jc      nopathtable
138
; path table has been loaded
137
; path table has been loaded
139
        inc     [use_path_table]
138
        inc     [use_path_table]
140
        sub     [size_rest], cx
139
        sub     [size_rest], cx
141
        add     [free_ptr], cx
140
        add     [free_ptr], cx
142
nopathtable:
141
nopathtable:
143
; init cache
142
; init cache
144
        mov     ax, [size_rest]
143
        mov     ax, [size_rest]
145
        mov     [cache_size], ax
144
        mov     [cache_size], ax
146
        mov     ax, [free_ptr]
145
        mov     ax, [free_ptr]
147
        mov     [cache_start], ax
146
        mov     [cache_start], ax
148
; load secondary loader
147
; load secondary loader
149
        mov     di, secondary_loader_info
148
        mov     di, secondary_loader_info
150
        call    load_file
149
        call    load_file
151
        test    bx, bx
150
        test    bx, bx
152
        jnz     noloader
151
        jnz     noloader
153
; set registers for secondary loader
152
; set registers for secondary loader
154
        mov     ah, [bootdrive]
153
        mov     ah, [bootdrive]
155
        mov     al, 'c'
154
        mov     al, 'c'
156
        mov     bx, 'is'
155
        mov     bx, 'is'
157
        mov     si, callback
156
        mov     si, callback
158
        jmp     far [si-callback+secondary_loader_info] ; jump to 1000:0000
157
        jmp     far [si-callback+secondary_loader_info] ; jump to 1000:0000
159
 
158
 
160
noloader:
159
noloader:
161
        mov     si, aKernelNotFound
160
        mov     si, aKernelNotFound
162
        jmp     err_
161
        jmp     err_
163
 
162
 
164
read_sectors:
163
read_sectors:
165
; es:bx = pointer to data
164
; es:bx = pointer to data
166
; eax = first sector
165
; eax = first sector
167
; cx = number of sectors
166
; cx = number of sectors
168
        pushad
167
        pushad
169
        push    ds
168
        push    ds
170
do_read_sectors:
169
do_read_sectors:
171
        push    ax
170
        push    ax
172
        push    cx
171
        push    cx
173
        cmp     cx, 0x7F
172
        cmp     cx, 0x7F
174
        jbe     @f
173
        jbe     @f
175
        mov     cx, 0x7F
174
        mov     cx, 0x7F
176
@@:
175
@@:
177
; create disk address packet on the stack
176
; create disk address packet on the stack
178
; dq starting LBA
177
; dq starting LBA
179
        db      66h
178
        db      66h
180
        push    0
179
        push    0
181
        push    eax
180
        push    eax
182
; dd buffer
181
; dd buffer
183
        push    es
182
        push    es
184
        push    bx
183
        push    bx
185
; dw number of blocks to transfer (no more than 0x7F)
184
; dw number of blocks to transfer (no more than 0x7F)
186
        push    cx
185
        push    cx
187
; dw packet size in bytes
186
; dw packet size in bytes
188
        push    10h
187
        push    10h
189
; issue BIOS call
188
; issue BIOS call
190
        push    ss
189
        push    ss
191
        pop     ds
190
        pop     ds
192
        mov     si, sp
191
        mov     si, sp
193
        mov     dl, [cs:bootdrive]
192
        mov     dl, [cs:bootdrive]
194
        mov     ah, 42h
193
        mov     ah, 42h
195
        int     13h
194
        int     13h
196
        jc      diskreaderr
195
        jc      diskreaderr
197
; restore stack
196
; restore stack
198
        add     sp, 10h
197
        add     sp, 10h
199
; increase current sector & buffer; decrease number of sectors
198
; increase current sector & buffer; decrease number of sectors
200
        movzx   esi, cx
199
        movzx   esi, cx
201
        mov     ax, es
200
        mov     ax, es
202
        shl     cx, 7
201
        shl     cx, 7
203
        add     ax, cx
202
        add     ax, cx
204
        mov     es, ax
203
        mov     es, ax
205
        pop     cx
204
        pop     cx
206
        pop     ax
205
        pop     ax
207
        add     eax, esi
206
        add     eax, esi
208
        sub     cx, si
207
        sub     cx, si
209
        jnz     do_read_sectors
208
        jnz     do_read_sectors
210
        pop     ds
209
        pop     ds
211
        popad
210
        popad
212
        ret
211
        ret
213
diskreaderr:
212
diskreaderr:
214
        add     sp, 10h + 2*2
213
        add     sp, 10h + 2*2
215
        pop     ds
214
        pop     ds
216
        popad
215
        popad
217
        stc
216
        stc
218
out_string.ret:
217
out_string.ret:
219
        ret
218
        ret
220
 
219
 
221
out_string:
220
out_string:
222
; in: ds:si -> ASCIIZ string
221
; in: ds:si -> ASCIIZ string
223
        lodsb
222
        lodsb
224
        test    al, al
223
        test    al, al
225
        jz      .ret
224
        jz      .ret
226
        mov     ah, 0Eh
225
        mov     ah, 0Eh
227
        mov     bx, 7
226
        mov     bx, 7
228
        int     10h
227
        int     10h
229
        jmp     out_string
228
        jmp     out_string
230
 
229
 
231
aNoLBA          db      'The drive does not support LBA!',0
230
aNoLBA          db      'The drive does not support LBA!',0
232
aReadError      db      'Read error',0
231
aReadError      db      'Read error',0
233
no_pvd          db      'Primary Volume Descriptor not found!',0
232
no_pvd          db      'Primary Volume Descriptor not found!',0
234
nomem_str       db      'No memory',0
233
nomem_str       db      'No memory',0
235
aPressAnyKey    db      13,10,'Press any key...',13,10,0
234
aPressAnyKey    db      13,10,'Press any key...',13,10,0
236
 
235
 
237
load_file:
236
load_file:
238
; in: ds:di -> information structure
237
; in: ds:di -> information structure
239
;       dw:dw   address
238
;       dw:dw   address
240
;       dw      limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
239
;       dw      limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
241
;       ASCIIZ  name
240
;       ASCIIZ  name
242
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found
241
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found
243
; out: dx:ax = file size (0xFFFFFFFF if file not found)
242
; out: dx:ax = file size (0xFFFFFFFF if file not found)
244
; parse path to the file
243
; parse path to the file
245
        lea     si, [di+6]
244
        lea     si, [di+6]
246
        mov     eax, [cs:root_location]
245
        mov     eax, [cs:root_location]
247
        cmp     [cs:use_path_table], 0
246
        cmp     [cs:use_path_table], 0
248
        jz      parse_dir
247
        jz      parse_dir
249
; scan for path in path table
248
; scan for path in path table
250
        push    di
249
        push    di
251
        push    6000h
250
        push    6000h
252
        pop     es
251
        pop     es
253
        mov     di, [cs:pathtable_start]        ; es:di = pointer to current entry in path table
252
        mov     di, [cs:pathtable_start]        ; es:di = pointer to current entry in path table
254
        mov     dx, 1   ; dx = number of current entry in path table, start from 1
253
        mov     dx, 1   ; dx = number of current entry in path table, start from 1
255
        mov     cx, [cs:pathtable_size]
254
        mov     cx, [cs:pathtable_size]
256
pathtable_newparent:
255
pathtable_newparent:
257
        mov     bx, dx  ; bx = number of current parent in path table: root = 1
256
        mov     bx, dx  ; bx = number of current parent in path table: root = 1
258
scan_path_table_e:
257
scan_path_table_e:
259
        call    is_last_component
258
        call    is_last_component
260
        jnc     path_table_scanned
259
        jnc     path_table_scanned
261
scan_path_table_i:
260
scan_path_table_i:
262
        cmp     word [es:di+6], bx
261
        cmp     word [es:di+6], bx
263
        jb      .next
262
        jb      .next
264
        ja      path_table_notfound
263
        ja      path_table_notfound
265
        call    test_filename1
264
        call    test_filename1
266
        jc      .next
265
        jc      .next
267
@@:
266
@@:
268
        lodsb
267
        lodsb
269
        cmp     al, '/'
268
        cmp     al, '/'
270
        jnz     @b
269
        jnz     @b
271
        jmp     pathtable_newparent
270
        jmp     pathtable_newparent
272
.next:
271
.next:
273
; go to next entry
272
; go to next entry
274
        inc     dx
273
        inc     dx
275
        movzx   ax, byte [es:di]
274
        movzx   ax, byte [es:di]
276
        add     ax, 8+1
275
        add     ax, 8+1
277
        and     al, not 1
276
        and     al, not 1
278
        add     di, ax
277
        add     di, ax
279
        sub     cx, ax
278
        sub     cx, ax
280
        ja      scan_path_table_i
279
        ja      scan_path_table_i
281
path_table_notfound:
280
path_table_notfound:
282
        pop     di
281
        pop     di
283
        mov     ax, -1
282
        mov     ax, -1
284
        mov     dx, ax
283
        mov     dx, ax
285
        mov     bx, 2   ; file not found
284
        mov     bx, 2   ; file not found
286
        ret
285
        ret
287
path_table_scanned:
286
path_table_scanned:
288
        movzx   eax, byte [es:di+1]
287
        movzx   eax, byte [es:di+1]
289
        add     eax, [es:di+2]
288
        add     eax, [es:di+2]
290
        pop     di
289
        pop     di
291
parse_dir:
290
parse_dir:
292
; eax = logical block, ds:di -> information structure, ds:si -> file name
291
; eax = logical block, ds:di -> information structure, ds:si -> file name
293
; was the folder already read?
292
; was the folder already read?
294
        push    di ds
293
        push    di ds
295
        push    cs
294
        push    cs
296
        pop     ds
295
        pop     ds
297
        mov     [cur_desc_end], 2000h
296
        mov     [cur_desc_end], 2000h
298
        mov     bx, cachelist
297
        mov     bx, cachelist
299
.scan1:
298
.scan1:
300
        mov     bx, [bx+2]
299
        mov     bx, [bx+2]
301
        cmp     bx, cachelist
300
        cmp     bx, cachelist
302
        jz      .notfound
301
        jz      .notfound
303
        cmp     [bx+4], eax
302
        cmp     [bx+4], eax
304
        jnz     .scan1
303
        jnz     .scan1
305
.found:
304
.found:
306
; yes; delete this item from the list (the following code will append this item to the tail)
305
; yes; delete this item from the list (the following code will append this item to the tail)
307
        mov     di, [bx]
306
        mov     di, [bx]
308
        push    word [bx+2]
307
        push    word [bx+2]
309
        pop     word [di+2]
308
        pop     word [di+2]
310
        mov     di, [bx+2]
309
        mov     di, [bx+2]
311
        push    word [bx]
310
        push    word [bx]
312
        pop     word [di]
311
        pop     word [di]
313
        mov     di, bx
312
        mov     di, bx
314
        jmp     .scan
313
        jmp     .scan
315
.notfound:
314
.notfound:
316
; no; load first sector of the folder to get its size
315
; no; load first sector of the folder to get its size
317
        push    eax
316
        push    eax
318
        push    si
317
        push    si
319
        mov     si, 1
318
        mov     si, 1
320
        call    load_phys_sector_for_lb_force
319
        call    load_phys_sector_for_lb_force
321
        mov     bx, si
320
        mov     bx, si
322
        pop     si
321
        pop     si
323
        pop     eax
322
        pop     eax
324
        jnc     @f
323
        jnc     @f
325
; read error - return
324
; read error - return
326
.readerr:
325
.readerr:
327
        pop     ds
326
        pop     ds
328
.readerr2:
327
.readerr2:
329
        pop     di
328
        pop     di
330
        mov     ax, -1
329
        mov     ax, -1
331
        mov     dx, ax
330
        mov     dx, ax
332
        mov     bx, 3
331
        mov     bx, 3
333
        ret
332
        ret
334
@@:
333
@@:
335
; first item of the folder describes the folder itself
334
; first item of the folder describes the folder itself
336
; do not cache too big folders: size < 64K and size <= (total cache size)/2
335
; do not cache too big folders: size < 64K and size <= (total cache size)/2
337
        cmp     word [bx+12], 0
336
        cmp     word [bx+12], 0
338
        jnz     .nocache
337
        jnz     .nocache
339
        mov     cx, [cache_size]        ; cx = cache size in sectors
338
        mov     cx, [cache_size]        ; cx = cache size in sectors
340
        shr     cx, 1                   ; cx = (cache size)/2
339
        shr     cx, 1                   ; cx = (cache size)/2
341
        cmp     cx, 0x20
340
        cmp     cx, 0x20
342
        jae     @f
341
        jae     @f
343
        shl     cx, 11
342
        shl     cx, 11
344
        cmp     [bx+10], cx
343
        cmp     [bx+10], cx
345
        ja      .nocache
344
        ja      .nocache
346
@@:
345
@@:
347
; we want to cache this folder; get space for it
346
; we want to cache this folder; get space for it
348
        mov     cx, [bx+10]
347
        mov     cx, [bx+10]
349
        call    cx_to_sectors
348
        call    cx_to_sectors
350
        jnz     .yescache
349
        jnz     .yescache
351
.nocache:
350
.nocache:
352
        push    dword [bx+10]
351
        push    dword [bx+10]
353
        pop     dword [cur_nocache_len]
352
        pop     dword [cur_nocache_len]
354
        call    lb_to_sector
353
        call    lb_to_sector
355
        push    ds
354
        push    ds
356
        pop     es
355
        pop     es
357
        pop     ds
356
        pop     ds
358
.nocache_loop:
357
.nocache_loop:
359
        push    eax
358
        push    eax
360
        mov     dx, 1800h
359
        mov     dx, 1800h
361
        call    scan_for_filename_in_sector
360
        call    scan_for_filename_in_sector
362
        mov     cx, dx
361
        mov     cx, dx
363
        pop     eax
362
        pop     eax
364
        jnc     .j_scandone
363
        jnc     .j_scandone
365
        sub     cx, bx
364
        sub     cx, bx
366
        sub     word [es:cur_nocache_len], cx
365
        sub     word [es:cur_nocache_len], cx
367
        sbb     word [es:cur_nocache_len+2], 0
366
        sbb     word [es:cur_nocache_len+2], 0
368
        jb      .j_scandone
367
        jb      .j_scandone
369
        ja      @f
368
        ja      @f
370
        cmp     word [es:cur_nocache_len], 0
369
        cmp     word [es:cur_nocache_len], 0
371
        jz      .j_scandone
370
        jz      .j_scandone
372
@@:
371
@@:
373
        mov     cx, 1
372
        mov     cx, 1
374
        inc     eax
373
        inc     eax
375
        push    es
374
        push    es
376
        mov     bx, 1000h
375
        mov     bx, 1000h
377
        call    read_sectors
376
        call    read_sectors
378
        pop     es
377
        pop     es
379
        jc      .readerr2
378
        jc      .readerr2
380
        jmp     .nocache_loop
379
        jmp     .nocache_loop
381
.j_scandone:
380
.j_scandone:
382
        jmp     .scandone
381
        jmp     .scandone
383
.yescache:
382
.yescache:
384
        push    bx
383
        push    bx
385
        mov     bx, [cachelist.head]
384
        mov     bx, [cachelist.head]
386
.freeloop:
385
.freeloop:
387
        cmp     cx, [size_rest]
386
        cmp     cx, [size_rest]
388
        jbe     .sizeok
387
        jbe     .sizeok
389
@@:
388
@@:
390
; if we are here: there is not enough free space, so we must delete old folders' data
389
; if we are here: there is not enough free space, so we must delete old folders' data
391
; N.B. We know that after deleting some folders the space will be available (size <= (total cache size)/2).
390
; N.B. We know that after deleting some folders the space will be available (size <= (total cache size)/2).
392
; one loop iteration: delete data of one folder
391
; one loop iteration: delete data of one folder
393
        pusha
392
        pusha
394
        mov     dx, [bx+10]
393
        mov     dx, [bx+10]
395
        mov     es, dx          ; es = segment of folder data to be deleted
394
        mov     es, dx          ; es = segment of folder data to be deleted
396
        xor     di, di
395
        xor     di, di
397
        mov     ax, [bx+8]
396
        mov     ax, [bx+8]
398
        add     ax, 0x7FF
397
        add     ax, 0x7FF
399
        rcr     ax, 1
398
        rcr     ax, 1
400
        shr     ax, 10
399
        shr     ax, 10
401
        push    ax
400
        push    ax
402
        shl     ax, 11-4        ; get number of paragraphs in folder data to be deleted
401
        shl     ax, 11-4        ; get number of paragraphs in folder data to be deleted
403
        mov     cx, [cache_size]
402
        mov     cx, [cache_size]
404
        add     cx, [cache_start]
403
        add     cx, [cache_start]
405
        push    ds
404
        push    ds
406
        push    ax
405
        push    ax
407
        add     ax, dx
406
        add     ax, dx
408
        mov     ds, ax
407
        mov     ds, ax
409
        pop     ax
408
        pop     ax
410
        shl     cx, 11-4
409
        shl     cx, 11-4
411
        sub     cx, dx          ; cx = number of paragraphs to be moved
410
        sub     cx, dx          ; cx = number of paragraphs to be moved
412
        push    si
411
        push    si
413
        xor     si, si
412
        xor     si, si
414
; move cx paragraphs from ds:si to es:di to get free space in the end of cache
413
; move cx paragraphs from ds:si to es:di to get free space in the end of cache
415
@@:
414
@@:
416
        sub     cx, 1000h
415
        sub     cx, 1000h
417
        jbe     @f
416
        jbe     @f
418
        push    cx
417
        push    cx
419
        mov     cx, 8000h
418
        mov     cx, 8000h
420
        rep movsw
419
        rep movsw
421
        mov     cx, ds
420
        mov     cx, ds
422
        add     cx, 1000h
421
        add     cx, 1000h
423
        mov     ds, cx
422
        mov     ds, cx
424
        mov     cx, es
423
        mov     cx, es
425
        add     cx, 1000h
424
        add     cx, 1000h
426
        mov     es, cx
425
        mov     es, cx
427
        pop     cx
426
        pop     cx
428
        jmp     @b
427
        jmp     @b
429
@@:
428
@@:
430
        add     cx, 1000h
429
        add     cx, 1000h
431
        shl     cx, 3
430
        shl     cx, 3
432
        rep movsw
431
        rep movsw
433
        pop     si
432
        pop     si
434
        pop     ds
433
        pop     ds
435
; correct positions in cache for existing items
434
; correct positions in cache for existing items
436
        mov     cx, 80h
435
        mov     cx, 80h
437
        mov     di, 8400h
436
        mov     di, 8400h
438
.correct:
437
.correct:
439
        cmp     [di+10], dx
438
        cmp     [di+10], dx
440
        jbe     @f
439
        jbe     @f
441
        sub     [di+10], ax
440
        sub     [di+10], ax
442
@@:
441
@@:
443
        add     di, 12
442
        add     di, 12
444
        loop    .correct
443
        loop    .correct
445
; some additional space is free now
444
; some additional space is free now
446
        pop     ax
445
        pop     ax
447
        add     [size_rest], ax
446
        add     [size_rest], ax
448
        sub     [free_ptr], ax
447
        sub     [free_ptr], ax
449
; add cache item to the list of free items
448
; add cache item to the list of free items
450
        mov     dx, [bx]
449
        mov     dx, [bx]
451
        mov     ax, [free_cache_item]
450
        mov     ax, [free_cache_item]
452
        mov     [bx], ax
451
        mov     [bx], ax
453
        mov     [free_cache_item], bx
452
        mov     [free_cache_item], bx
454
        mov     bx, dx
453
        mov     bx, dx
455
; current iteration done
454
; current iteration done
456
        popa
455
        popa
457
        jmp     .freeloop
456
        jmp     .freeloop
458
.sizeok:
457
.sizeok:
459
        mov     [cachelist.head], bx
458
        mov     [cachelist.head], bx
460
        mov     word [bx+2], cachelist
459
        mov     word [bx+2], cachelist
461
; allocate new item in cache
460
; allocate new item in cache
462
        mov     di, [free_cache_item]
461
        mov     di, [free_cache_item]
463
        test    di, di
462
        test    di, di
464
        jz      .nofree
463
        jz      .nofree
465
        push    word [di]
464
        push    word [di]
466
        pop     [free_cache_item]
465
        pop     [free_cache_item]
467
        jmp     @f
466
        jmp     @f
468
.nofree:
467
.nofree:
469
        mov     di, [last_cache_item]
468
        mov     di, [last_cache_item]
470
        add     [last_cache_item], 12
469
        add     [last_cache_item], 12
471
@@:
470
@@:
472
        pop     bx
471
        pop     bx
473
        push    si di
472
        push    si di
474
;       mov     [di+4], eax     ; start of folder
473
;       mov     [di+4], eax     ; start of folder
475
        scasd
474
        scasd
476
        stosd
475
        stosd
477
        push    ax
476
        push    ax
478
        mov     ax, [free_ptr]
477
        mov     ax, [free_ptr]
479
        shl     ax, 11-4
478
        shl     ax, 11-4
480
        mov     [di+10-8], ax
479
        mov     [di+10-8], ax
481
        mov     es, ax
480
        mov     es, ax
482
        pop     ax
481
        pop     ax
483
        add     [free_ptr], cx
482
        add     [free_ptr], cx
484
        sub     [size_rest], cx
483
        sub     [size_rest], cx
485
; read folder data
484
; read folder data
486
; first sector is already in memory, 0000:bx
485
; first sector is already in memory, 0000:bx
487
        pusha
486
        pusha
488
        mov     cx, [bx+10]
487
        mov     cx, [bx+10]
489
        mov     [di+8-8], cx    ; folder size in bytes
488
        mov     [di+8-8], cx    ; folder size in bytes
490
        mov     si, bx
489
        mov     si, bx
491
        xor     di, di
490
        xor     di, di
492
        mov     cx, 0x1800
491
        mov     cx, 0x1800
493
        sub     cx, si
492
        sub     cx, si
494
        rep movsb
493
        rep movsb
495
        pop     ax
494
        pop     ax
496
        push    di
495
        push    di
497
        popa
496
        popa
498
; read rest of folder
497
; read rest of folder
499
        mov     esi, dword [lb_per_sec]
498
        mov     esi, dword [lb_per_sec]
500
        add     eax, esi
499
        add     eax, esi
501
        dec     si
500
        dec     si
502
        not     si
501
        not     si
503
        and     ax, si
502
        and     ax, si
504
        mov     si, word [bx+10]
503
        mov     si, word [bx+10]
505
        mov     bx, di
504
        mov     bx, di
506
        pop     di
505
        pop     di
507
        sub     si, bx
506
        sub     si, bx
508
        jbe     @f
507
        jbe     @f
509
        mov     [cur_limit], esi
508
        mov     [cur_limit], esi
510
        call    read_many_bytes
509
        call    read_many_bytes
511
        pop     si
510
        pop     si
512
        jnc     .scan
511
        jnc     .scan
513
        jmp     .readerr
512
        jmp     .readerr
514
@@:
513
@@:
515
        pop     si
514
        pop     si
516
.scan:
515
.scan:
517
; now we have required cache item; append it to the end of list
516
; now we have required cache item; append it to the end of list
518
        mov     bx, [cachelist.tail]
517
        mov     bx, [cachelist.tail]
519
        mov     [cachelist.tail], di
518
        mov     [cachelist.tail], di
520
        mov     [di+2], bx
519
        mov     [di+2], bx
521
        mov     word [di], cachelist
520
        mov     word [di], cachelist
522
        mov     [bx], di
521
        mov     [bx], di
523
; scan for given filename
522
; scan for given filename
524
        mov     es, [di+10]
523
        mov     es, [di+10]
525
        mov     dx, [di+8]
524
        mov     dx, [di+8]
526
        pop     ds
525
        pop     ds
527
        xor     bx, bx
526
        xor     bx, bx
528
        call    scan_for_filename_in_sector
527
        call    scan_for_filename_in_sector
529
.scandone:
528
.scandone:
530
        push    cs
529
        push    cs
531
        pop     es
530
        pop     es
532
        mov     bx, 2000h
531
        mov     bx, 2000h
533
        cmp     bx, [es:cur_desc_end]
532
        cmp     bx, [es:cur_desc_end]
534
        jnz     filefound
533
        jnz     filefound
535
j_notfound:
534
j_notfound:
536
        jmp     path_table_notfound
535
        jmp     path_table_notfound
537
filefound:
536
filefound:
538
@@:
537
@@:
539
        lodsb
538
        lodsb
540
        test    al, al
539
        test    al, al
541
        jz      @f
540
        jz      @f
542
        cmp     al, '/'
541
        cmp     al, '/'
543
        jnz     @b
542
        jnz     @b
544
@@:
543
@@:
545
        mov     cl, [es:bx+8]
544
        mov     cl, [es:bx+8]
546
        test    al, al
545
        test    al, al
547
        jz      @f
546
        jz      @f
548
; parse next component of file name
547
; parse next component of file name
549
        test    cl, 2   ; directory?
548
        test    cl, 2   ; directory?
550
        jz      j_notfound
549
        jz      j_notfound
551
        mov     eax, [es:bx]
550
        mov     eax, [es:bx]
552
        pop     di
551
        pop     di
553
        jmp     parse_dir
552
        jmp     parse_dir
554
@@:
553
@@:
555
        test    cl, 2   ; directory?
554
        test    cl, 2   ; directory?
556
        jnz     j_notfound      ; do not allow read directories as regular files
555
        jnz     j_notfound      ; do not allow read directories as regular files
557
; ok, now load the file
556
; ok, now load the file
558
        pop     di
557
        pop     di
559
        les     bx, [di]
558
        les     bx, [di]
560
        call    normalize
559
        call    normalize
561
        movzx   esi, word [di+4]        ; esi = limit in 4K blocks
560
        movzx   esi, word [di+4]        ; esi = limit in 4K blocks
562
        shl     esi, 12         ; esi = limit in bytes
561
        shl     esi, 12         ; esi = limit in bytes
563
        push    cs
562
        push    cs
564
        pop     ds
563
        pop     ds
565
        mov     [cur_limit], esi
564
        mov     [cur_limit], esi
566
        mov     di, 2000h
565
        mov     di, 2000h
567
loadloop:
566
loadloop:
568
        and     [cur_start], 0
567
        and     [cur_start], 0
569
.loadnew:
568
.loadnew:
570
        mov     esi, [cur_limit]
569
        mov     esi, [cur_limit]
571
        mov     eax, [cur_start]
570
        mov     eax, [cur_start]
572
        add     esi, eax
571
        add     esi, eax
573
        mov     [overflow], 1
572
        mov     [overflow], 1
574
        sub     esi, [di+4]
573
        sub     esi, [di+4]
575
        jb      @f
574
        jb      @f
576
        xor     esi, esi
575
        xor     esi, esi
577
        dec     [overflow]
576
        dec     [overflow]
578
@@:
577
@@:
579
        add     esi, [di+4]     ; esi = number of bytes to read
578
        add     esi, [di+4]     ; esi = number of bytes to read
580
        mov     [cur_start], esi
579
        mov     [cur_start], esi
581
        sub     esi, eax
580
        sub     esi, eax
582
        jz      .loadcontinue
581
        jz      .loadcontinue
583
        xor     edx, edx
582
        xor     edx, edx
584
        div     dword [lb_size] ; eax = number of logical blocks to skip,
583
        div     dword [lb_size] ; eax = number of logical blocks to skip,
585
        mov     [first_byte], dx; [first_byte] = number of bytes to skip in 1st block
584
        mov     [first_byte], dx; [first_byte] = number of bytes to skip in 1st block
586
        cmp     byte [di+10], 0
585
        cmp     byte [di+10], 0
587
        jnz     .interleaved
586
        jnz     .interleaved
588
        add     eax, [di]
587
        add     eax, [di]
589
; read esi bytes from logical block eax to buffer es:bx
588
; read esi bytes from logical block eax to buffer es:bx
590
        call    read_many_bytes.with_first
589
        call    read_many_bytes.with_first
591
        jc      .readerr3
590
        jc      .readerr3
592
.loadcontinue:
591
.loadcontinue:
593
        mov     [cur_chunk], di
592
        mov     [cur_chunk], di
594
        add     di, 11
593
        add     di, 11
595
        cmp     di, [cur_desc_end]
594
        cmp     di, [cur_desc_end]
596
        jae     @f
595
        jae     @f
597
        cmp     [cur_limit], 0
596
        cmp     [cur_limit], 0
598
        jnz     loadloop
597
        jnz     loadloop
599
@@:
598
@@:
600
        mov     bx, [overflow]
599
        mov     bx, [overflow]
601
.calclen:
600
.calclen:
602
; calculate length of file
601
; calculate length of file
603
        xor     ax, ax
602
        xor     ax, ax
604
        xor     dx, dx
603
        xor     dx, dx
605
        mov     di, 2000h
604
        mov     di, 2000h
606
@@:
605
@@:
607
        add     ax, [di+4]
606
        add     ax, [di+4]
608
        adc     dx, [di+6]
607
        adc     dx, [di+6]
609
        add     di, 11
608
        add     di, 11
610
        cmp     di, [cur_desc_end]
609
        cmp     di, [cur_desc_end]
611
        jb      @b
610
        jb      @b
612
        ret
611
        ret
613
.interleaved:
612
.interleaved:
614
        mov     [cur_unit_limit], esi
613
        mov     [cur_unit_limit], esi
615
        push    esi
614
        push    esi
616
; skip first blocks
615
; skip first blocks
617
        movzx   ecx, byte [di+9]        ; Unit Size
616
        movzx   ecx, byte [di+9]        ; Unit Size
618
        movzx   esi, byte [di+10]       ; Interleave Gap
617
        movzx   esi, byte [di+10]       ; Interleave Gap
619
        add     si, cx
618
        add     si, cx
620
        mov     edx, [di]
619
        mov     edx, [di]
621
@@:
620
@@:
622
        sub     eax, ecx
621
        sub     eax, ecx
623
        jb      @f
622
        jb      @f
624
        add     edx, esi
623
        add     edx, esi
625
        jmp     @b
624
        jmp     @b
626
@@:
625
@@:
627
        add     ecx, eax        ; ecx = number of logical blocks to skip
626
        add     ecx, eax        ; ecx = number of logical blocks to skip
628
        lea     eax, [ecx+edx]  ; eax = first logical block
627
        lea     eax, [ecx+edx]  ; eax = first logical block
629
        pop     esi
628
        pop     esi
630
.interleaved_loop:
629
.interleaved_loop:
631
; get number of bytes in current file unit
630
; get number of bytes in current file unit
632
        push    eax
631
        push    eax
633
        movzx   eax, byte [di+9]
632
        movzx   eax, byte [di+9]
634
        sub     ax, cx
633
        sub     ax, cx
635
        imul    eax, dword [lb_size]
634
        imul    eax, dword [lb_size]
636
        cmp     eax, esi
635
        cmp     eax, esi
637
        ja      .i2
636
        ja      .i2
638
.i1:
637
.i1:
639
        xchg    esi, eax
638
        xchg    esi, eax
640
.i2:
639
.i2:
641
        pop     eax
640
        pop     eax
642
        sub     [cur_unit_limit], esi
641
        sub     [cur_unit_limit], esi
643
        push    eax
642
        push    eax
644
; read esi bytes from logical block eax to buffer es:bx
643
; read esi bytes from logical block eax to buffer es:bx
645
        call    read_many_bytes.with_first
644
        call    read_many_bytes.with_first
646
        pop     eax
645
        pop     eax
647
        jnc     @f
646
        jnc     @f
648
.readerr3:
647
.readerr3:
649
        mov     bx, 3
648
        mov     bx, 3
650
        jmp     .calclen
649
        jmp     .calclen
651
@@:
650
@@:
652
        mov     esi, [cur_unit_limit]
651
        mov     esi, [cur_unit_limit]
653
        test    esi, esi
652
        test    esi, esi
654
        jz      .loadcontinue
653
        jz      .loadcontinue
655
        movzx   ecx, byte [di+9]        ; add Unit Size
654
        movzx   ecx, byte [di+9]        ; add Unit Size
656
        add     cl, byte [di+10]        ; add Interleave Gap
655
        add     cl, byte [di+10]        ; add Interleave Gap
657
        adc     ch, 0
656
        adc     ch, 0
658
        add     eax, ecx
657
        add     eax, ecx
659
        xor     cx, cx
658
        xor     cx, cx
660
        mov     [first_byte], cx
659
        mov     [first_byte], cx
661
        jmp     .interleaved_loop
660
        jmp     .interleaved_loop
662
 
661
 
663
cx_to_sectors:
662
cx_to_sectors:
664
        add     cx, 7FFh
663
        add     cx, 7FFh
665
        rcr     cx, 1
664
        rcr     cx, 1
666
        shr     cx, 10
665
        shr     cx, 10
667
        ret
666
        ret
668
 
667
 
669
is_last_component:
668
is_last_component:
670
; in: ds:si -> name
669
; in: ds:si -> name
671
; out: CF set <=> current component is not last (=> folder)
670
; out: CF set <=> current component is not last (=> folder)
672
        push    si
671
        push    si
673
@@:
672
@@:
674
        lodsb
673
        lodsb
675
        test    al, al
674
        test    al, al
676
        jz      @f
675
        jz      @f
677
        cmp     al, '/'
676
        cmp     al, '/'
678
        jnz     @b
677
        jnz     @b
679
        stc
678
        stc
680
@@:
679
@@:
681
        pop     si
680
        pop     si
682
        ret
681
        ret
683
 
682
 
684
test_filename1:
683
test_filename1:
685
; in: ds:si -> filename, es:di -> path table item
684
; in: ds:si -> filename, es:di -> path table item
686
; out: CF set <=> no match
685
; out: CF set <=> no match
687
        pusha
686
        pusha
688
        mov     cl, [es:di]
687
        mov     cl, [es:di]
689
        add     di, 8
688
        add     di, 8
690
        jmp     test_filename2.start
689
        jmp     test_filename2.start
691
test_filename2:
690
test_filename2:
692
; in: ds:si -> filename, es:bx -> directory item
691
; in: ds:si -> filename, es:bx -> directory item
693
; out: CF set <=> no match
692
; out: CF set <=> no match
694
        pusha
693
        pusha
695
        mov     cl, [es:bx+32]
694
        mov     cl, [es:bx+32]
696
        lea     di, [bx+33]
695
        lea     di, [bx+33]
697
.start:
696
.start:
698
        mov     ch, 0
697
        mov     ch, 0
699
@@:
698
@@:
700
        lodsb
699
        lodsb
701
        test    al, al
700
        test    al, al
702
        jz      .test1
701
        jz      .test1
703
        cmp     al, '/'
702
        cmp     al, '/'
704
        jz      .test1
703
        jz      .test1
705
        call    toupper
704
        call    toupper
706
        mov     ah, al
705
        mov     ah, al
707
        mov     al, [es:di]
706
        mov     al, [es:di]
708
        call    toupper
707
        call    toupper
709
        inc     di
708
        inc     di
710
        cmp     al, ah
709
        cmp     al, ah
711
        loopz   @b
710
        loopz   @b
712
        jnz     .next1
711
        jnz     .next1
713
; if we have reached this point: current name is done
712
; if we have reached this point: current name is done
714
        lodsb
713
        lodsb
715
        test    al, al
714
        test    al, al
716
        jz      .ret
715
        jz      .ret
717
        cmp     al, '/'
716
        cmp     al, '/'
718
        jz      .ret
717
        jz      .ret
719
; if we have reached this point: current name is done, but input name continues
718
; if we have reached this point: current name is done, but input name continues
720
; so they do not match
719
; so they do not match
721
        jmp     .next1
720
        jmp     .next1
722
.test1:
721
.test1:
723
; if we have reached this point: input name is done, but current name continues
722
; if we have reached this point: input name is done, but current name continues
724
; "filename.ext;version" in ISO-9660 represents file "filename.ext"
723
; "filename.ext;version" in ISO-9660 represents file "filename.ext"
725
; "filename." and "filename.;version" are also possible for "filename"
724
; "filename." and "filename.;version" are also possible for "filename"
726
        cmp     byte [es:di], '.'
725
        cmp     byte [es:di], '.'
727
        jnz     @f
726
        jnz     @f
728
        inc     di
727
        inc     di
729
        dec     cx
728
        dec     cx
730
        jz      .ret
729
        jz      .ret
731
@@:
730
@@:
732
        cmp     byte [es:di], ';'
731
        cmp     byte [es:di], ';'
733
        jnz     .next1
732
        jnz     .next1
734
        jmp     .ret
733
        jmp     .ret
735
.next1:
734
.next1:
736
        stc
735
        stc
737
.ret:
736
.ret:
738
        popa
737
        popa
739
        ret
738
        ret
740
 
739
 
741
toupper:
740
toupper:
742
; in: al=symbol
741
; in: al=symbol
743
; out: al=symbol in uppercase
742
; out: al=symbol in uppercase
744
        cmp     al, 'a'
743
        cmp     al, 'a'
745
        jb      .ret
744
        jb      .ret
746
        cmp     al, 'z'
745
        cmp     al, 'z'
747
        ja      .ret
746
        ja      .ret
748
        sub     al, 'a'-'A'
747
        sub     al, 'a'-'A'
749
.ret:
748
.ret:
750
        ret
749
        ret
751
 
750
 
752
scan_for_filename_in_sector:
751
scan_for_filename_in_sector:
753
; in: ds:si->filename, es:bx->folder data, dx=limit
752
; in: ds:si->filename, es:bx->folder data, dx=limit
754
; out: CF=0 if found
753
; out: CF=0 if found
755
        push    bx
754
        push    bx
756
.loope:
755
.loope:
757
        push    bx
756
        push    bx
758
.loop:
757
.loop:
759
        cmp     bx, dx
758
        cmp     bx, dx
760
        jae     .notfound
759
        jae     .notfound
761
        cmp     byte [es:bx], 0
760
        cmp     byte [es:bx], 0
762
        jz      .loopd
761
        jz      .loopd
763
        test    byte [es:bx+25], 4      ; ignore files with Associated bit
762
        test    byte [es:bx+25], 4      ; ignore files with Associated bit
764
        jnz     .next
763
        jnz     .next
765
        call    test_filename2
764
        call    test_filename2
766
        jc      .next
765
        jc      .next
767
        push    ds es di
766
        push    ds es di
768
        push    es
767
        push    es
769
        pop     ds
768
        pop     ds
770
        push    cs
769
        push    cs
771
        pop     es
770
        pop     es
772
        mov     di, [es:cur_desc_end]
771
        mov     di, [es:cur_desc_end]
773
        movzx   eax, byte [bx+1]
772
        movzx   eax, byte [bx+1]
774
        add     eax, [bx+2]
773
        add     eax, [bx+2]
775
        stosd   ; first logical block
774
        stosd   ; first logical block
776
        mov     eax, [bx+10]
775
        mov     eax, [bx+10]
777
        stosd   ; length
776
        stosd   ; length
778
        mov     al, [bx+25]
777
        mov     al, [bx+25]
779
        stosb   ; flags
778
        stosb   ; flags
780
        mov     ax, [bx+26]
779
        mov     ax, [bx+26]
781
        stosw   ; File Unit size, Interleave Gap size
780
        stosw   ; File Unit size, Interleave Gap size
782
        mov     [es:cur_desc_end], di
781
        mov     [es:cur_desc_end], di
783
        cmp     di, 3000h
782
        cmp     di, 3000h
784
        pop     di es ds
783
        pop     di es ds
785
        jae     .done
784
        jae     .done
786
        test    byte [es:bx+25], 80h
785
        test    byte [es:bx+25], 80h
787
        jz      .done
786
        jz      .done
788
.next:
787
.next:
789
        add     bl, [es:bx]
788
        add     bl, [es:bx]
790
        adc     bh, 0
789
        adc     bh, 0
791
        jmp     .loop
790
        jmp     .loop
792
.loopd:
791
.loopd:
793
        mov     ax, bx
792
        mov     ax, bx
794
        pop     bx
793
        pop     bx
795
@@:
794
@@:
796
        add     bx, [cs:lb_size]
795
        add     bx, [cs:lb_size]
797
        jz      .done2
796
        jz      .done2
798
        cmp     bx, ax
797
        cmp     bx, ax
799
        jb      @b
798
        jb      @b
800
        jmp     .loope
799
        jmp     .loope
801
.notfound:
800
.notfound:
802
        stc
801
        stc
803
.done:
802
.done:
804
        pop     bx
803
        pop     bx
805
.done2:
804
.done2:
806
        pop     bx
805
        pop     bx
807
        ret
806
        ret
808
 
807
 
809
lb_to_sector:
808
lb_to_sector:
810
        xor     edx, edx
809
        xor     edx, edx
811
        div     dword [lb_per_sec]
810
        div     dword [lb_per_sec]
812
        ret
811
        ret
813
 
812
 
814
load_phys_sector_for_lb_force:
813
load_phys_sector_for_lb_force:
815
; in: eax = logical block, ds=0
814
; in: eax = logical block, ds=0
816
; in: si=0 - accept 0 logical blocks, otherwise force read at least 1
815
; in: si=0 - accept 0 logical blocks, otherwise force read at least 1
817
; out: 0000:1000 = physical sector data; si -> logical block
816
; out: 0000:1000 = physical sector data; si -> logical block
818
; out: eax = next physical sector
817
; out: eax = next physical sector
819
; out: CF=1 if read error
818
; out: CF=1 if read error
820
; destroys cx
819
; destroys cx
821
; this procedure reads 0-3 or 1-4 logical blocks, up to the end of physical sector
820
; this procedure reads 0-3 or 1-4 logical blocks, up to the end of physical sector
822
        call    lb_to_sector
821
        call    lb_to_sector
823
        or      si, dx
822
        or      si, dx
824
        jnz     @f
823
        jnz     @f
825
        mov     si, 1800h
824
        mov     si, 1800h
826
        jmp     .done
825
        jmp     .done
827
@@:
826
@@:
828
        mov     si, 1000h
827
        mov     si, 1000h
829
        imul    dx, [lb_size]
828
        imul    dx, [lb_size]
830
        add     si, dx
829
        add     si, dx
831
        mov     cx, 1
830
        mov     cx, 1
832
        push    es bx
831
        push    es bx
833
        push    ds
832
        push    ds
834
        pop     es
833
        pop     es
835
        mov     bx, 1000h
834
        mov     bx, 1000h
836
        call    read_sectors
835
        call    read_sectors
837
        pop     bx es
836
        pop     bx es
838
        inc     eax
837
        inc     eax
839
.done:
838
.done:
840
        ret
839
        ret
841
 
840
 
842
normalize:
841
normalize:
843
; in: es:bx = far pointer
842
; in: es:bx = far pointer
844
; out: es:bx = normalized pointer (i.e. 0 <= bx < 0x10)
843
; out: es:bx = normalized pointer (i.e. 0 <= bx < 0x10)
845
        push    ax bx
844
        push    ax bx
846
        mov     ax, es
845
        mov     ax, es
847
        shr     bx, 4
846
        shr     bx, 4
848
        add     ax, bx
847
        add     ax, bx
849
        mov     es, ax
848
        mov     es, ax
850
        pop     bx ax
849
        pop     bx ax
851
        and     bx, 0x0F
850
        and     bx, 0x0F
852
        ret
851
        ret
853
 
852
 
854
read_many_bytes:
853
read_many_bytes:
855
        and     [first_byte], 0
854
        and     [first_byte], 0
856
read_many_bytes.with_first:
855
read_many_bytes.with_first:
857
; read esi bytes from logical block dx:ax to buffer es:bx
856
; read esi bytes from logical block dx:ax to buffer es:bx
858
; out: CF=1 <=> disk error
857
; out: CF=1 <=> disk error
859
        push    di
858
        push    di
860
; load first physical sector
859
; load first physical sector
861
        push    bx si
860
        push    bx si
862
        mov     si, [first_byte]
861
        mov     si, [first_byte]
863
        call    load_phys_sector_for_lb_force
862
        call    load_phys_sector_for_lb_force
864
        jnc     @f
863
        jnc     @f
865
        pop     si bx
864
        pop     si bx
866
.ret:
865
.ret:
867
        pop     di
866
        pop     di
868
        ret
867
        ret
869
@@:
868
@@:
870
        add     si, [first_byte]
869
        add     si, [first_byte]
871
        mov     ecx, 1800h
870
        mov     ecx, 1800h
872
        sub     cx, si
871
        sub     cx, si
873
        mov     ebx, esi
872
        mov     ebx, esi
874
        pop     bx
873
        pop     bx
875
        sub     ebx, ecx
874
        sub     ebx, ecx
876
        jnc     @f
875
        jnc     @f
877
        add     cx, bx
876
        add     cx, bx
878
        xor     ebx, ebx
877
        xor     ebx, ebx
879
@@:
878
@@:
880
        pop     di
879
        pop     di
881
        sub     [cur_limit], ecx
880
        sub     [cur_limit], ecx
882
        rep movsb
881
        rep movsb
883
        mov     esi, ebx
882
        mov     esi, ebx
884
        mov     bx, di
883
        mov     bx, di
885
        call    normalize
884
        call    normalize
886
; load other physical sectors
885
; load other physical sectors
887
; read esi bytes from physical sector eax to buffer es:bx
886
; read esi bytes from physical sector eax to buffer es:bx
888
        test    esi, esi
887
        test    esi, esi
889
        jz      .ret
888
        jz      .ret
890
        push    esi
889
        push    esi
891
        add     esi, 0x7FF
890
        add     esi, 0x7FF
892
        and     si, not 0x7FF
891
        and     si, not 0x7FF
893
        cmp     esi, [cur_limit]
892
        cmp     esi, [cur_limit]
894
        jbe     .okplace
893
        jbe     .okplace
895
.noplace:
894
.noplace:
896
        sub     esi, 800h
895
        sub     esi, 800h
897
.okplace:
896
.okplace:
898
        shr     esi, 11 ; si = number of sectors
897
        shr     esi, 11 ; si = number of sectors
899
        mov     cx, si
898
        mov     cx, si
900
        jz      @f
899
        jz      @f
901
        call    read_sectors
900
        call    read_sectors
902
@@:
901
@@:
903
        pop     esi
902
        pop     esi
904
        jc      .ret
903
        jc      .ret
905
        movzx   ecx, cx
904
        movzx   ecx, cx
906
        add     eax, ecx
905
        add     eax, ecx
907
        shl     ecx, 11
906
        shl     ecx, 11
908
        sub     [cur_limit], ecx
907
        sub     [cur_limit], ecx
909
        sub     esi, ecx
908
        sub     esi, ecx
910
        jc      .big
909
        jc      .big
911
        jz      .nopost
910
        jz      .nopost
912
        push    bx es
911
        push    bx es
913
        push    ds
912
        push    ds
914
        pop     es
913
        pop     es
915
        mov     bx, 1000h
914
        mov     bx, 1000h
916
        mov     cx, 1
915
        mov     cx, 1
917
        call    read_sectors
916
        call    read_sectors
918
        pop     es di
917
        pop     es di
919
        jc      .ret2
918
        jc      .ret2
920
        mov     cx, si
919
        mov     cx, si
921
        mov     si, 1000h
920
        mov     si, 1000h
922
        sub     word [cur_limit], cx
921
        sub     word [cur_limit], cx
923
        sbb     word [cur_limit+2], 0
922
        sbb     word [cur_limit+2], 0
924
        rep movsb
923
        rep movsb
925
        mov     bx, di
924
        mov     bx, di
926
        call    normalize
925
        call    normalize
927
.nopost:
926
.nopost:
928
        clc
927
        clc
929
.ret2:
928
.ret2:
930
        pop     di
929
        pop     di
931
        ret
930
        ret
932
.big:
931
.big:
933
        mov     ax, es
932
        mov     ax, es
934
        sub     ax, 80h
933
        sub     ax, 80h
935
        mov     es, ax
934
        mov     es, ax
936
        add     bx, 800h
935
        add     bx, 800h
937
        add     bx, si
936
        add     bx, si
938
        call    normalize
937
        call    normalize
939
        sub     [cur_limit], esi
938
        sub     [cur_limit], esi
940
        jmp     .nopost
939
        jmp     .nopost
941
 
940
 
942
; Callback function for secondary loader
941
; Callback function for secondary loader
943
callback:
942
callback:
944
; in: ax = function number; only function 1 is defined for now
943
; in: ax = function number; only function 1 is defined for now
945
        dec     ax
944
        dec     ax
946
        jz      callback_readfile
945
        jz      callback_readfile
947
        dec     ax
946
        dec     ax
948
        jz      callback_continueread
947
        jz      callback_continueread
949
        stc     ; unsupported function
948
        stc     ; unsupported function
950
        retf
949
        retf
951
 
950
 
952
callback_readfile:
951
callback_readfile:
953
; function 1: read file
952
; function 1: read file
954
; in: ds:di -> information structure
953
; in: ds:di -> information structure
955
;       dw:dw   address
954
;       dw:dw   address
956
;       dw      limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
955
;       dw      limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
957
;       ASCIIZ  name
956
;       ASCIIZ  name
958
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error
957
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error
959
; out: dx:ax = file size (0xFFFFFFFF if file was not found)
958
; out: dx:ax = file size (0xFFFFFFFF if file was not found)
960
        call    load_file
959
        call    load_file
961
        clc     ; function is supported
960
        clc     ; function is supported
962
        retf
961
        retf
963
 
962
 
964
callback_continueread:
963
callback_continueread:
965
; function 2: continue to read file
964
; function 2: continue to read file
966
; in: ds:di -> information structure
965
; in: ds:di -> information structure
967
;       dw:dw   address
966
;       dw:dw   address
968
;       dw      limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
967
;       dw      limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
969
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=3 - read error
968
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=3 - read error
970
; out: dx:ax = file size
969
; out: dx:ax = file size
971
        les     bx, [di]
970
        les     bx, [di]
972
        call    normalize
971
        call    normalize
973
        movzx   esi, word [di+4]        ; si = limit in 4K blocks
972
        movzx   esi, word [di+4]        ; si = limit in 4K blocks
974
        shl     esi, 12                 ; bp:si = limit in bytes
973
        shl     esi, 12                 ; bp:si = limit in bytes
975
        push    cs
974
        push    cs
976
        pop     ds
975
        pop     ds
977
        mov     [cur_limit], esi
976
        mov     [cur_limit], esi
978
        mov     di, [cur_chunk]
977
        mov     di, [cur_chunk]
979
        call    loadloop.loadnew
978
        call    loadloop.loadnew
980
        clc     ; function is supported
979
        clc     ; function is supported
981
        retf
980
        retf
982
 
981
 
983
secondary_loader_info:
982
secondary_loader_info:
984
        dw      0, 0x1000
983
        dw      0, 0x1000
985
        dw      0x30000 / 0x1000
984
        dw      0x30000 / 0x1000
986
        db      'kernel.mnt',0
985
        db      'kernel.mnt',0
987
aKernelNotFound db      'Fatal error: cannot load the kernel',0
986
aKernelNotFound db      'Fatal error: cannot load the kernel',0
988
 
987
 
989
align 2
988
align 2
990
cachelist:
989
cachelist:
991
.head           dw      cachelist
990
.head           dw      cachelist
992
.tail           dw      cachelist
991
.tail           dw      cachelist
993
free_cache_item dw      0
992
free_cache_item dw      0
994
last_cache_item dw      0x8400
993
last_cache_item dw      0x8400
995
 
994
 
996
use_path_table  db      0
995
use_path_table  db      0
997
bootdrive       db      ?
996
bootdrive       db      ?
998
align 2
997
align 2
999
lb_size         dw      ?       ; Logical Block size in bytes
998
lb_size         dw      ?       ; Logical Block size in bytes
1000
                dw      0       ; to allow access dword [lb_size]
999
                dw      0       ; to allow access dword [lb_size]
1001
lb_per_sec      dw      ?       ; Logical Blocks per physical sector
1000
lb_per_sec      dw      ?       ; Logical Blocks per physical sector
1002
                dw      0       ; to allow access dword [lb_per_sec]
1001
                dw      0       ; to allow access dword [lb_per_sec]
1003
free_ptr        dw      ?       ; first free block in cache (cache block = sector = 0x800 bytes)
1002
free_ptr        dw      ?       ; first free block in cache (cache block = sector = 0x800 bytes)
1004
size_rest       dw      ?       ; free space in cache (in blocks)
1003
size_rest       dw      ?       ; free space in cache (in blocks)
1005
cache_size      dw      ?
1004
cache_size      dw      ?
1006
cache_start     dw      ?
1005
cache_start     dw      ?
1007
pathtable_size  dw      ?
1006
pathtable_size  dw      ?
1008
pathtable_start dw      ?
1007
pathtable_start dw      ?
1009
root_location   dd      ?
1008
root_location   dd      ?
1010
cur_desc_end    dw      ?
1009
cur_desc_end    dw      ?
1011
cur_nocache_len dd      ?
1010
cur_nocache_len dd      ?
1012
cur_limit       dd      ?
1011
cur_limit       dd      ?
1013
cur_unit_limit  dd      ?
1012
cur_unit_limit  dd      ?
1014
overflow        dw      ?
1013
overflow        dw      ?
1015
cur_chunk       dw      ?
1014
cur_chunk       dw      ?
1016
first_byte      dw      ?
1015
first_byte      dw      ?
1017
cur_start       dd      ?
1016
cur_start       dd      ?
1018
 
1017
 
1019
times 83FCh-$  db      0
1018
times 83FCh-$  db      0
1020
        db      43h
1019
        db      43h
1021
; just to make file 2048 bytes long :)
1020
; just to make file 2048 bytes long :)
1022
        db      'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd'
1021
        db      'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd'
1023
 
1022
 
1024
        dw      0xAA55          ; this is not required for CD, but to be consistent...
1023
        dw      0xAA55          ; this is not required for CD, but to be consistent...