Subversion Repositories ngs

Rev

Rev 115 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
35 savelij 1
 
181 savelij 2
; LAST UPDATE: 11.12.2024 savelij
35 savelij 3
 
115 savelij 4
                include ../macros.a80
5
                include ../ports_ngs.a80
6
                include ../sdcomand.a80
35 savelij 7
 
181 savelij 8
; адрес загрузки найденной прошивки
9
ADRLOAD         EQU 0x8000
35 savelij 10
 
181 savelij 11
RAMCOD          EQU 0x4080                      ; адрес работы основного кода
12
RAM8KB          EQU 0x6000                      ; адрес буфера для переброски кода
13
STRPAG          EQU 0x8000                      ; адрес куда загрузки
35 savelij 14
 
181 savelij 15
FREQUENCY       EQU C_20MHZ                     ; текущая частота для основной прошивки
112 savelij 16
 
69 savelij 17
                ORG 0
35 savelij 18
                DI
19
                LD SP,RAMCOD
20
                XOR A
21
                OUT (VOL1),A
22
                OUT (VOL2),A
23
                OUT (VOL3),A
24
                OUT (VOL4),A
25
                OUT (VOL5),A
26
                OUT (VOL6),A
27
                OUT (VOL7),A
181 savelij 28
                OUT (VOL8),A                    ; заглушили мод порты для использования буфера
35 savelij 29
 
181 savelij 30
;               JP RDBYT_DBG                    ; отладочная фигня
38 savelij 31
 
181 savelij 32
; ожидание загрузки прошивки со спека
33
                LD B,0                          ; читаем 256 порт статуса
34
.L1             IN A,(ZXSTAT)                   ; на предмет изменения состояния 
35 savelij 35
                RRA
36
                JR C,RDBYT01
181 savelij 37
                DJNZ .L1
38
                DEC B                           ; счетчик обнулился, состояние порта не изменилось
39
                JR RDBYT03                      ; грузим стандартную прошивку
35 savelij 40
 
181 savelij 41
RDBYT01         IN A,(ZXCMD)                    ; читем пришедший байт из порта команд
42
                LD C,A                          ; сохранили для проверки
43
                IN A,(ZXDATRD)                  ; читем байт из порта данных
44
                OUT (CLRCBIT),A                 ; сбросили команд бит
45
                CP C                            ; сравниваем пришедшие байты
46
                JR NZ,RDBYT03                   ; не совпали, грузим стандартную прошивку
47
                CP 0x55                         ; пришел байт 0x55?
48
                JR NZ,RDBYT03                   ; если нет, грузим стандартную прошивку
49
                LD B,0                          ; читаем 256 раз изменение порта команд
35 savelij 50
                IN A,(ZXSTAT)
51
                RRA
52
                JR C,RDBYT02
53
                DJNZ $-5
54
                DEC B
181 savelij 55
                JR RDBYT03                      ; не дождались, грузим стандартную прошивку
35 savelij 56
 
181 savelij 57
RDBYT02         IN A,(ZXCMD)                    ; забрали байт из порта команд
58
                LD C,A                          ; сохранили для проверки
59
                IN A,(ZXDATRD)                  ; забрали байт из порта данных
60
                CP C                            ; сравнили
61
                JR NZ,RDBYT03                   ; если не совпадают, грузим стандартную прошивку
62
RDBYT_DBG       CP 0xAA                         ; это 0xAA?
63
RDBYT03         EX AF,AF'                       ; временно спрятали флаги процессора
35 savelij 64
                LD HL,GRUZILA
65
                LD DE,RAMCOD
66
                LD BC,RAMCEND-VERLOAD
181 savelij 67
                LDIR                            ; перенесли основной код в адрес работы
68
                OUT (CLRCBIT),A                 ; сбросили команд бит
69
                EX AF,AF'                       ; вернули спрятанные флаги
70
                JP Z,GRUZIM2                    ; если все условия совпали, запускаем загрузчик
71
                JP GRUZIM0                      ; иначе грузим стандартную прошивку из пзу
35 savelij 72
 
73
GRUZILA
69 savelij 74
                PHASE RAMCOD
35 savelij 75
 
76
VERLOAD         DB "Loader"
105 savelij 77
                DW DATA_VERS
35 savelij 78
 
181 savelij 79
; путь до файла прошивки GS
69 savelij 80
F_PATH          DB "NEOGS.ROM",0
35 savelij 81
 
69 savelij 82
UPDATENAME      DB "NGS_ROM.UPD",0
83
 
35 savelij 84
TXT1            DB "not found",0
85
TXT1E
86
TXT2            DB "beta",0
87
TXT2E
69 savelij 88
TXT3            DB 0;"stable",0
35 savelij 89
TXT3E
90
 
181 savelij 91
GRUZIM0         CALL RROMSD                     ; загружаем и запускаем прошивку с SD карты, если она там есть
92
                JP GS105                        ; иначе загружаем прошивку из пзу и запускаем
35 savelij 93
 
181 savelij 94
GRUZIM2         LD A,0x11                       ; конфигурим НГС
112 savelij 95
                LD (NGS_MODES),A
181 savelij 96
                OUT (GSCFG0),A                  ; отрубаем пзу и врубаем частоту 12МГЦ
35 savelij 97
                XOR A
181 savelij 98
                OUT (MPAG),A                    ; включаем страницу 0
99
GRUZIM          IN A,(ZXSTAT)                   ; постоянно ждем команд от спека
35 savelij 100
                RRA
78 savelij 101
                JR NC,GRUZIM
181 savelij 102
                IN A,(ZXCMD)                    ; поймали команду
103
                CP 0x1D                         ; это команда проверки? 
35 savelij 104
                JR NZ,GRUZIM1
181 savelij 105
                LD A,0x76
106
                OUT (ZXDATWR),A                 ; отдаем байт идентификации загрузчика
35 savelij 107
                OUT (CLRCBIT),A
181 savelij 108
                JR GRUZIM                       ; и продолжаем ждать команд
35 savelij 109
 
181 savelij 110
GRUZIM1         CP 0xF3
111
                JP Z,GS105                      ; при поступлении команд 0xF3 и
112
                CP 0xF4
113
                JP Z,GS105                      ; 0xF4 загружаем и запускаем прошивку из пзу
35 savelij 114
                CP LOW (FLOADE-FLOADER)/2+1
181 savelij 115
                JP NC,GS105                     ; аналогично не команда загрузчика переходим на основное пзу
35 savelij 116
                ADD A,A
117
                LD L,A
118
                LD H,0
119
                LD DE,GRUZIM2
181 savelij 120
                PUSH DE                         ; на стеке адрес возврата после исполнения команды
35 savelij 121
                LD DE,FLOADER
122
                ADD HL,DE
123
                LD E,(HL)
124
                INC HL
181 savelij 125
                LD D,(HL)                       ; забрали адрес исполнения команды
35 savelij 126
                EX DE,HL
181 savelij 127
                JP (HL)                         ; поехали на исполнение
35 savelij 128
 
181 savelij 129
FLOADER         DW LOADROM                      ; 00 загрузка rom со спека вместо скопированной из ROM
130
                DW JPLDROM                      ; 01 запуск загруженной прошивки 
131
                DW GS105                        ; 02 копирование из ROM и запуск
132
                DW RROMSD                       ; 03 загрузка и запуск ROM с SD карты
133
                DW LOADCOD                      ; 04 загрузка кода со спека
134
                DW LDINSD                       ; 05 загрузка файла с SD карты
135
                DW RUNCOD                       ; 06 запуск кода с любого адреса и в любой странице
136
                DW STATSD                       ; 07 статус загруженного файла
137
                DW VERPAGE                      ; 08 версия в текстовом виде для указанной страницы
138
                DW GET_CRC                      ; 09 получить CRC16
139
                DW LOADUPDATE                   ; 0A загрузка файла с обновлением
140
                DW SET_FREQ                     ; 0B установка частоты процессора
35 savelij 141
FLOADE
142
 
181 savelij 143
SET_FREQ        IN A,(ZXDATRD)                  ; приняли номер частоты
112 savelij 144
                BIT 7,A
145
                JR NZ,SET_FREQ2
181 savelij 146
                OUT (CLRCBIT),A                 ; сбросили команд бит
112 savelij 147
                AND 3
181 savelij 148
                LD L,C_10MHZ                    ; установка частоты 10 МГЦ
112 savelij 149
                JR Z,SET_FREQ1
150
                DEC A
181 savelij 151
                LD L,C_12MHZ                    ; установка частоты 12 МГЦ
112 savelij 152
                JR Z,SET_FREQ1
153
                DEC A
181 savelij 154
                LD L,C_20MHZ                    ; установка частоты 20 МГЦ
112 savelij 155
                JR Z,SET_FREQ1
181 savelij 156
                LD L,C_24MHZ                    ; установка частоты 24 МГЦ
112 savelij 157
SET_FREQ1       LD A,(NGS_MODES)
158
                AND %11001111
159
                OR L
160
                LD (NGS_MODES),A
161
                OUT (GSCFG0),A
162
                RET
163
 
164
SET_FREQ2       LD A,(NGS_MODES)
181 savelij 165
                AND 0x30
112 savelij 166
                RRCA
167
                RRCA
168
                RRCA
169
                RRCA
170
                OUT (CLRCBIT),A
171
                OUT (ZXDATWR),A
172
                JP WDN
173
 
181 savelij 174
; передача на спек версии в текстовом виде
175
VERPAGE         IN A,(ZXDATRD)                  ; забрали байт номера запрошенной страницы пзу
176
                AND 7                           ; старшие 5 бит в игноре
177
                EX AF,AF'                       ; временно спрятали флаги проца
178
                LD A,0x30
179
                OUT (GSCFG0),A                  ; включили 10 МГЦ и вернули пзу
180
                EX AF,AF'                       ; вернули флаги
181
                ADD A,A                         ; нам нужна вторые 32К страницы пзу
182
;               AND A                           ; выбрана страница 0?
183
;               JR NZ,VERPAG1                   ; если нет, то идем на извлечение последних 8 байт
184
;               LD HL,VERLOAD                   ; для загрузчика берем из другого адреса
69 savelij 185
;               LD DE,RAMCEND
186
;               LD BC,8
187
;               PUSH DE
188
;               LDIR
189
;               POP DE
181 savelij 190
;               JR VERPAG2                      ; пошли на переводчик в текстовый вид
35 savelij 191
 
192
VERPAG1         INC A
181 savelij 193
                OUT (MPAG),A                    ; включили последние 16К выбранной страницы пзу
194
                LD HL,0xFFF8
35 savelij 195
                LD BC,8
196
                LD DE,RAMCEND
197
                PUSH DE
181 savelij 198
                LDIR                            ; перенесли 8 байт из хвоста пзу
35 savelij 199
                POP DE
181 savelij 200
VERPAG2         LD A,0x11
201
                OUT (GSCFG0),A                  ; отрубили пзу и вернули 12МГЦ
35 savelij 202
                XOR A
181 savelij 203
                OUT (MPAG),A                    ; вернули страницу 0 озу
204
                LD B,8                          ; проверям перенесенные 8 байт, а не 0xFF ли там?
35 savelij 205
                LD A,(DE)
206
                INC DE
207
                INC A
181 savelij 208
                JR NZ,VFPGA1                    ; не 0xFF, продолжаем
35 savelij 209
                DJNZ $-5
181 savelij 210
                DEC SP                          ; таки все 8 байт 0xFF, версии у пзу страницы нету
35 savelij 211
                DEC SP
212
                POP DE
213
                LD HL,TXT1
214
                LD BC,TXT1E-TXT1
181 savelij 215
                LDIR                            ; отдать текст об этом
35 savelij 216
                JR VFPGA0
217
 
218
VFPGA1          DEC SP
219
                DEC SP
220
                POP DE
181 savelij 221
                CALL UNVERS                     ; распаковка полученных 8 байт в текст
222
VFPGA0          OUT (CLRCBIT),A                 ; сбросили команд бит
35 savelij 223
                LD HL,RAMCEND
224
                LD BC,ZXDATWR
69 savelij 225
VFPGA2          LD A,(HL)
35 savelij 226
                OUTI
69 savelij 227
                EX AF,AF'
35 savelij 228
                CALL WDN
69 savelij 229
                EX AF,AF'
35 savelij 230
                AND A
181 savelij 231
                JR NZ,VFPGA2                    ; отдаем текст версии пока не встретится байт 0, который тоже отдаем
35 savelij 232
                RET
233
 
181 savelij 234
; распаковщик даты
35 savelij 235
UNVERS          LD HL,6
181 savelij 236
                ADD HL,DE                       ; пропустили 6 байт текста версии
237
                LD C,(HL)                       ; забрали младший байт версии
238
                LD (HL)," "                     ; на его место пробел
35 savelij 239
                INC HL
181 savelij 240
                LD B,(HL)                       ; забрали старший байт
241
                LD A,C                          ; взяли младший байт версии
242
                AND 0x1F                        ; нас интересуют младшие 5 бит (день месяца)
243
                JR NZ,.L1
244
                RES 7,B                         ; если получился 0, возможно это бета версия
245
.L1             CP 32
246
                JR C,.L2                        ; в месяце не может быть более 31 дня
247
                RES 7,B                         ; иначе это бета версия
248
.L2             CALL A2TXT                      ; переводим полученное число в текст
249
                SRL B                           ; сдинули версию на 1 бит влево чтобы номер месяца
250
                RR C                            ; оказался в одном байте
251
                LD A,C                          ; забрали этот байт
35 savelij 252
                RRCA
253
                RRCA
254
                RRCA
181 savelij 255
                RRCA                            ; сдвинули нужные биты в младшие разрады байта
256
                AND 0x0F                        ; оставили нужные 4 бита (номер месяца)
257
                JR NZ,.L3                       ; номер месяца неможет быть 0
258
                RES 6,B                         ; иначе это бета версия
259
.L3             CP 13                           ; и номер месяца не может быть больше 12
260
                JR C,.L4
261
                RES 6,B                         ; иначе бета версия
262
.L4             LD (HL),"."                     ; отделили номер дня месяца точкой
35 savelij 263
                INC HL
181 savelij 264
                CALL A2TXT                      ; конвертировали номер месяца
265
                LD (HL),"."                     ; так же отделили точкой
35 savelij 266
                INC HL
181 savelij 267
                LD A,B                          ; взяли оставшиеся биты
268
                AND 0x3F                        ; нам нужны 6 бит номера года
269
                CALL A2TXT                      ; конвертнули в текст
270
                BIT 6,B                         ; бета или стабл версия?
271
                JR NZ,.L5
272
                LD DE,TXT2                      ; все-таки бета, о чем и добавляем текст к версии
35 savelij 273
                LD BC,TXT2E-TXT2
181 savelij 274
                JR .L6
35 savelij 275
 
181 savelij 276
.L5             LD DE,TXT3                      ; версия стабл
35 savelij 277
                LD BC,TXT3E-TXT3
181 savelij 278
.L6             LD (HL)," "                     ; перед текстом (бета или стабл) вставляем пробел
35 savelij 279
                INC HL
280
                EX DE,HL
181 savelij 281
                LDIR                            ; перетащили текст
35 savelij 282
                EX DE,HL
181 savelij 283
                LD (HL),0                       ; завершили строку нулем
35 savelij 284
                RET
285
 
181 savelij 286
; перевод "A" в десятичный вид и в текст. для чисел от 0 до 99
287
A2TXT           PUSH HL                         ; сохранили адрес куда ложить сконверченное
35 savelij 288
                LD L,A
289
                LD H,0
290
                LD DE,10
291
                XOR A
292
                DEC A
181 savelij 293
.L1             INC A
35 savelij 294
                SBC HL,DE
181 savelij 295
                JR NC,.L1                       ; считаем количество десятков в числе
296
                ADD HL,DE                       ; вернули перебор вычитания
297
                ADD A,"0"                       ; перевели в тесктовый вид полученное число
298
                LD D,A                          ; пока сохранили
299
                LD A,L                          ; взяли оставшиеся единицы числа
300
                ADD A,"0"                       ; конвертули в текст
301
                POP HL                          ; вернули адрес куда ложить
302
                LD (HL),D                       ; положили десятки заданного числа
35 savelij 303
                INC HL
181 savelij 304
                LD (HL),A                       ; положили единицы того же числа
35 savelij 305
                INC HL
306
                RET
307
 
181 savelij 308
; загрузка с SD карты по указанному пути
309
; первый байт-номер страницы озу куда начинать грузить 
310
; далее байты текстовой строка пути и имени файла
311
; конец строки байт 0, он же стоп байт
312
LDINSD          LD BC,ZXDATRD                   ; адрес порта данных
313
                LD HL,RAMCEND                   ; адрес куда строку пути складировать
35 savelij 314
                PUSH HL
181 savelij 315
                IN A,(C)                        ; приняли номер страницы откуда начинать загрузку
316
                OUT (CLRCBIT),A                 ; сбросили команд бит
69 savelij 317
                EX AF,AF'
318
LDINSD1         CALL WDY
35 savelij 319
                IN A,(C)
320
                LD (HL),A
321
                INC HL
322
                AND A
181 savelij 323
                JR NZ,LDINSD1                   ; принимаем строку пока не встретится байт 0
69 savelij 324
                EX AF,AF'
35 savelij 325
                POP HL
181 savelij 326
                JP LOAD_SD                      ; далее запускаем загрузку с SD карты
35 savelij 327
 
181 savelij 328
; загрузка файла с обновлениями
329
LOADUPDATE      LD HL,UPDATENAME                ; имя файла обновления
330
                LD A,2                          ; грузить начиная со 2 страницы
69 savelij 331
                OUT (CLRCBIT),A
332
                JP LOAD_SD
333
 
181 savelij 334
; статус загрузки файла с SD карты
35 savelij 335
STATSD          LD A,(STATUS)
336
                OUT (ZXDATWR),A
337
                OUT (CLRCBIT),A
338
                RET
339
 
181 savelij 340
; загрузка и запуск прошивки с SD карты
341
; имя, путь и адрес фиксирован
342
RROMSD          LD HL,F_PATH                    ; адрес строки фиксированного пути для загрузки 
35 savelij 343
                XOR A
181 savelij 344
                CALL LOAD_SD                    ; загружаем
35 savelij 345
                AND A
181 savelij 346
                RET NZ                          ; если ошибка, то грузим из пзу
35 savelij 347
                JP JPLDROM
348
 
181 savelij 349
; запуск кода в любой странице
350
; 0 - номер страницы озу
351
; 1 - младший байт адреса запуска
352
; 2 - старший байт адреса запуска
353
RUNCOD          LD BC,ZXDATRD                   ; адрес порта данных
354
                IN A,(C)                        ; приняли номер страницы озу
355
                OUT (CLRCBIT),A                 ; сбросили команд бит
35 savelij 356
                OUT (MPAG),A
357
                CALL WDY
181 savelij 358
                IN L,(C)                        ; приняли младший байт адреса запуска
35 savelij 359
                CALL WDY
181 savelij 360
                IN H,(C)                        ; приняли старший байт адреса запуска
361
                JP (HL)                         ; запускаем
35 savelij 362
 
181 savelij 363
; 0 - номер страницы озу
364
; 1 - младший байт длины загрузки
365
; 2 - старший байт длины загрузки
366
; загрузка не более 32КБ
367
LOADCOD         LD BC,ZXDATRD                   ; адрес порта данных
368
                LD HL,0x8000                    ; адрес начала зaгрузки
369
                IN A,(C)                        ; приняли номер страницы озу
370
                OUT (CLRCBIT),A                 ; сбросили команд бит
371
                OUT (MPAG),A                    ; включили заданную страницу озу
35 savelij 372
                CALL WDY
181 savelij 373
                IN E,(C)                        ; приняли младший байт длины загрузки
35 savelij 374
                CALL WDY
181 savelij 375
                IN D,(C)                        ; приняли старший байт длины загрузки
35 savelij 376
LOADCO1         CALL WDY
377
                INI
378
                LD A,H
379
                AND A
181 savelij 380
                RET Z                           ; если озу кончилось, выходим
35 savelij 381
                DEC DE
382
                LD A,D
383
                OR E
181 savelij 384
                JR NZ,LOADCO1                   ; грузим скока указано
35 savelij 385
                RET
386
 
181 savelij 387
; загрузка прошивки 32КБ со спека
35 savelij 388
LOADROM         XOR A
181 savelij 389
                OUT (MPAG),A                    ; включаем страницу
390
                LD HL,0x8000                    ; адрес загрузки
391
                OUT (CLRCBIT),A                 ; сброс команд бита
392
                LD BC,ZXDATRD                   ; адрес порта данных
112 savelij 393
LOADROM1        CALL WDY
35 savelij 394
                INI
395
                LD A,H
396
                AND A
181 savelij 397
                JR NZ,LOADROM1                  ; грузим пока память не кончится
35 savelij 398
                RET
399
 
181 savelij 400
; грузилка стандартной прошивки из ROM
401
GS105           LD HL,STRPAG                    ; адрес куда переносить
402
                LD A,4                          ; переносить 4 куска по 8 килобайт
403
MOV1            EX AF,AF'                       ; прячем счетчик
404
                LD A,0x30
405
                OUT (GSCFG0),A                  ; включили пзу
35 savelij 406
                LD A,2
181 savelij 407
                OUT (MPAG),A                    ; страницу 2 со стандартной прошивкой
35 savelij 408
                PUSH HL
409
                LD DE,RAM8KB
181 savelij 410
                LD BC,0x2000
411
                LDIR                            ; перенесли в буфер 8 килобайт
412
                LD A,0x31
413
                OUT (GSCFG0),A                  ; переключили пзу
35 savelij 414
                XOR A
181 savelij 415
                OUT (MPAG),A                    ; включили страницу 0 озу
35 savelij 416
                POP DE
417
                LD HL,RAM8KB
181 savelij 418
                LD BC,0x2000
419
                LDIR                            ; перенесли из буфера 8 килобайт
35 savelij 420
                EX DE,HL
69 savelij 421
                EX AF,AF'
35 savelij 422
                DEC A
181 savelij 423
                JR NZ,MOV1                      ; и так 4 раза
35 savelij 424
 
181 savelij 425
; запуск загруженной прошивки
35 savelij 426
JPLDROM         XOR A
181 savelij 427
                OUT (MPAG),A                    ; включили страницу 0 озу
428
;               LD A,0x13                       ; включили частоту 12МГЦ, отключили пзу и защитили озу от записи
429
;               LD A,0x23                       ; включили частоту 20МГЦ, отключили пзу и защитили озу от записи
430
                LD A,3+FREQUENCY                ; включили указанную частоту, отключили пзу и защитили озу от записи
105 savelij 431
                OUT (GSCFG0),A
181 savelij 432
                JP 0                            ; стартуем стандартную прошивку
35 savelij 433
 
181 savelij 434
; ждем пока спек даст байт
35 savelij 435
WDY             IN A,(ZXSTAT)
436
                RLA
437
                JR NC,WDY
438
                RET
439
 
181 savelij 440
; ждем пока спек заберет байт из порта
35 savelij 441
WDN             IN A,(ZXSTAT)
442
                RLA
443
                JR C,WDN
444
                RET
445
 
181 savelij 446
; подсчет CRC16
35 savelij 447
GET_CRC         LD A,2
448
                OUT (MPAG),A
449
                DEC A
450
                OUT (GSCFG0),A
181 savelij 451
                LD HL,(0x8000)
35 savelij 452
                SRL H
453
                RR L
454
                SRL H
455
                RR L
456
                SRL H
457
                RR L
458
                SRL H
459
                RR L
69 savelij 460
                LD A,L
461
                LD IYH,A
181 savelij 462
;               LD IX,0x8000
69 savelij 463
;               LD C,(IX+0)
464
;               LD B,(IX+1)
465
;               CALL CRC16
466
;               LD C,(IX+0)
467
;               LD B,(IX+1)
181 savelij 468
;               LD A,0x81
69 savelij 469
;               AND A
470
;               SBC HL,BC
181 savelij 471
;               JR NZ,OUT_ERR                   ; CRC16 заголовка ERROR
472
                LD IX,0x8000+8-0x10
473
SCHET           LD DE,0x10
474
                ADD IX,DE                       ; в IX адрес выбранного блока
35 savelij 475
                LD C,(IX+4)
181 savelij 476
                LD B,(IX+5)                     ; в BC длина блока
35 savelij 477
                LD E,(IX+1)
478
                LD L,(IX+2)
479
                LD H,(IX+3)
480
                LD A,L
181 savelij 481
                AND 0x7F
482
                LD D,A                          ; в DE смещение в странице
35 savelij 483
                ADD HL,HL
484
                LD A,2
485
                ADD A,H
69 savelij 486
                LD IYL,A
181 savelij 487
                OUT (MPAG),A                    ; номер страницы
35 savelij 488
                PUSH IX
181 savelij 489
                LD IX,0x8000
490
                ADD IX,DE                       ; в IX адрес начала блока
35 savelij 491
                CALL CRC16
492
                POP IX
493
                LD C,(IX+6)
494
                LD B,(IX+7)
181 savelij 495
                LD A,0x82
35 savelij 496
                AND A
497
                SBC HL,BC
498
                JR NZ,OUT_ERR
69 savelij 499
                DEC IYH
500
                JR NZ,SCHET
181 savelij 501
ERR_OK          LD A,0x80
35 savelij 502
 
181 savelij 503
; CRC16 ERROR
504
; 0x80 - CRC16 блока ok
505
; 0x81 - CRC16 заголовка error
506
; 0x82 - CRC16 блока ERROR
35 savelij 507
OUT_ERR         OUT (CLRCBIT),A
508
                OUT (ZXDATWR),A
509
                CALL WDN
510
                LD A,L
511
                OUT (ZXDATWR),A
512
                CALL WDN
513
                LD A,H
514
                OUT (ZXDATWR),A
515
                RET
516
 
181 savelij 517
CRC16           LD HL,0xFFFF
518
                LD DE,0x1021
35 savelij 519
CRC_0           LD A,(IX)
520
                INC IX
69 savelij 521
                EX AF,AF'
522
                LD A,IXL
523
                OR IXH
35 savelij 524
                JR NZ,CRC_3
69 savelij 525
                INC IYL
526
                LD A,IYL
35 savelij 527
                OUT (MPAG),A
181 savelij 528
                LD IX,0x8000
69 savelij 529
CRC_3           EX AF,AF'
35 savelij 530
                XOR H
531
                LD H,A
532
                LD A,8
533
CRC_1           ADD HL,HL
534
                JR NC,CRC_2
69 savelij 535
                EX AF,AF'
35 savelij 536
                LD A,L
537
                XOR E
538
                LD L,A
539
                LD A,H
540
                XOR D
541
                LD H,A
69 savelij 542
                EX AF,AF'
35 savelij 543
CRC_2           DEC A
544
                JR NZ,CRC_1
545
                DEC BC
546
                LD A,B
547
                OR C
548
                JR NZ,CRC_0
69 savelij 549
                LD A,2
550
                OUT (MPAG),A
35 savelij 551
                RET
552
 
553
;---------------------------------
181 savelij 554
; грузилка файла по указанному пути
35 savelij 555
 
181 savelij 556
 INIT_VAR 0x5000
557
 SETVAR BUF_512,        0x200           ; буфер сектора
558
 SETVAR TDIRCLS,        0x400           ; буфер кластеров ROOT директории
559
 SETVAR CAL_FAT,        BYTE            ; калибр FAT
560
 SETVAR BYTSSEC,        BYTE            ; количество секторов в кластере
561
 SETVAR ROOTCLS,        DWORD           ; кластер начала ROOT директории
562
 SETVAR ROOTSEC,        WORD            ; размер в секторах ROOT директории
563
 SETVAR SEC_FAT,        DWORD           ; количество секторов одной FAT
564
 SETVAR RSVDSEC,        WORD            ; размер резервной области
565
 SETVAR STARTRZ,        DWORD           ; начало диска/раздела
566
 SETVAR FRSTDAT,        DWORD           ; адрес первого сектора данных от BPB
567
 SETVAR SEC_DSC,        DWORD           ; количество секторов на диске/разделе
568
 SETVAR CLS_DSC,        DWORD           ; количество кластеров на диске/разделе
569
 SETVAR FATSTR,         DWORD           ; начало первой FAT таблицы
570
 SETVAR ADRPATH,        WORD            ; адрес текста пути файла
571
 SETVAR STATUS,         BYTE            ; статус после вызова LOAD_SD
572
 SETVAR OLD_SP,         WORD            ; стек для выхода
573
 SETVAR FB_EXT,         0x0B            ; буфер 8.3 для поиска имени
574
 SETVAR LVL_DIR,        BYTE            ; номер уровня директории
575
 SETVAR LSTLOAD,        DWORD           ; номер сектора загруженного в буфер
576
 SETVAR NGS_MODES,      BYTE            ; текущий установленный режим
35 savelij 577
 
181 savelij 578
; SD карта не найдена
579
ZAW003          LD A,0xEE
35 savelij 580
WR_STAT         LD SP,(OLD_SP)
581
                LD (STATUS),A
582
                RET
583
 
181 savelij 584
; загрузка файла
585
; на входе: A - страница начала загрузки
586
; HL - адрес текстовой строки
587
; пути к файлу вместе с именем и расширением файла. путь полностью от ROOT 
588
; загружается файл по размеру дополненому до полных секторов (сектор 512 байт)
589
; пример: размер файла =0x80-после дополнения будет загружен 1 сектор
590
; =0x401 - будет загружено 3 сектора
591
; на выходе: A =
592
                ; 0x00 - файл загружен
593
                ; 0xAA - файл не найден
594
                ; 0xDD - FAT не обнаружен
595
                ; 0xEE - SD карта не обнаружена
596
LOAD_SD         LD IYL,A                        ; сохранили номер страницы куда грузить
597
                LD (ADRPATH),HL                 ; сохранили адрес строки пути
598
                LD (OLD_SP),SP                  ; сохранили стек
599
                LD A,0xFF
600
                LD (LSTLOAD+3),A                ; принудительная загрузка сектора без проверки
35 savelij 601
                LD A,1
181 savelij 602
                OUT (GSCFG0),A                  ; отключили пзу, все страница озу
603
                LD A,M_SDNCS+M_SNCLR;%10011011
604
                OUT (SCTRL),A                   ; сконфигурили нгс с CS=1 для SD карты          
605
                LD B,0x10
606
.L1             LD A,0xFF
607
                OUT (SD_SEND),A                 ; пишем 0x80 байт 0xFF в порт карточки
608
                DJNZ .L1
609
                XOR A                           ; 256 попыток найти SD карту
69 savelij 610
                EX AF,AF'
181 savelij 611
                LD A,M_SDNCS
612
                OUT (SCTRL),A                   ; выбрали SD карту CS=0
613
.L2             LD HL,CMD00
614
                CALL OUTCOM                     ; переводим карточку в режим SPI командой 0
615
                CALL IN_OOUT                    ; ждем ответа
69 savelij 616
                EX AF,AF'
35 savelij 617
                DEC A
181 savelij 618
                JR Z,ZAW003                     ; ждем по счептчику 256 раз
69 savelij 619
                EX AF,AF'
35 savelij 620
                DEC A
181 savelij 621
                JR NZ,.L2                       ; ждем пока карта ответит байтом 1
35 savelij 622
                LD BC,SD_RSTR
623
                LD HL,CMD08
181 savelij 624
                CALL OUTCOM                     ; определяем спецификацию карты
625
                CALL IN_OOUT                    ; в "A" ответ карты R1
35 savelij 626
                IN H,(C)
627
                NOP
628
                IN H,(C)       
629
                NOP
630
                IN H,(C)
631
                NOP
181 savelij 632
                IN H,(C)                        ; прочитали остальные байты в никуда
633
                BIT 2,A                         ; если ошибка, то
634
                LD HL,0                         ; карта спецификации 1.0
635
                JR NZ,.L3                       ; иначе
636
                LD H,0x40                       ; карта спецификации 2.0
637
.L3             LD A,CMD_55
638
                CALL OUT_COM                    ; запускаем внутреннюю инициализацию карты
35 savelij 639
                CALL IN_OOUT
181 savelij 640
                in (c) ;in f,(c)
641
                in (c) ;in f,(c)
35 savelij 642
                LD BC,SD_SEND
643
                LD A,ACMD_41
644
                OUT (C),A
645
                LD A,H
646
                OUT (C),A
647
                XOR A
648
                OUT (C),A
649
                NOP
650
                OUT (C),A
651
                NOP
652
                OUT (C),A
653
                DEC A
654
                OUT (C),A
655
                CALL IN_OOUT
656
                AND A
181 savelij 657
                JR NZ,.L3                       ; ждем пока карты перейдет в режим готовности
658
.L4             LD A,CMD_59
659
                CALL OUT_COM                    ; принудительно отключаем CRC16
35 savelij 660
                CALL IN_OOUT
661
                AND A
181 savelij 662
                JR NZ,.L4
663
.L5             LD HL,CMD16
664
                CALL OUTCOM                     ; принудительный размер сектора 512 байт
35 savelij 665
                CALL IN_OOUT
666
                AND A
181 savelij 667
                JR NZ,.L5
35 savelij 668
 
181 savelij 669
; инициализация переменных FAT
35 savelij 670
WC_FAT          LD DE,0
671
                LD B,D
672
                LD C,E
181 savelij 673
                CALL LOADLST                    ; читаем сектор 0 карточки
35 savelij 674
                PUSH HL
675
                POP IX
181 savelij 676
                LD DE,0x01BE
677
                ADD HL,DE                       ; переходим на смещение для проверок
678
                LD A,(HL)                       ; проверям чтобы был 0, карточки не могут быть загрузочными
35 savelij 679
                AND A
181 savelij 680
                JR NZ,.L2                       ; если не 0, проверить другое
35 savelij 681
                LD DE,4
181 savelij 682
                ADD HL,DE                       ; переходим к проверке типа раздела
35 savelij 683
                LD A,(HL)
684
                LD B,0
181 savelij 685
                CP 1                            ; FAT12?
686
                JR Z,.L1
35 savelij 687
                LD B,2
181 savelij 688
                CP 0x0B                         ; FAT32?
689
                JR Z,.L1
690
                CP 0x0C                         ; FAT32?
691
                JR Z,.L1
35 savelij 692
                LD B,1
181 savelij 693
                CP 6                            ; FAT16?
694
                JR Z,.L1
695
                CP 4                            ; FAT16?
696
                JR Z,.L1
697
                CP 0x0E                         ; FAT16?
698
                JR NZ,.L2              
699
.L1             LD A,B                          ; берем из "B" тип раздела
700
                LD (CAL_FAT),A                  ; сохранили
35 savelij 701
                ADD HL,DE
181 savelij 702
                CALL LOADZP                     ; берем номер сектора начала основного раздела
703
                JR .R1                          ; переходим к инициализации переменных для работы с фатом
35 savelij 704
 
181 savelij 705
; MBR не обнаружен, проверяем сектор 0 карты как описатель
706
.L2             LD C,(IX+0x0D)                  ; C = количество секторов в кластере
35 savelij 707
                XOR A
708
                LD E,A
709
                LD B,8
181 savelij 710
.L3             RR C
35 savelij 711
                ADC A,0
181 savelij 712
                DJNZ .L3                        ; количество секторов в кластере должно быть степенью 2
35 savelij 713
                DEC A
181 savelij 714
                JR NZ,.L4                       ; проверили количество бит
715
                INC E                           ; +1, есть такое
716
.L4             LD A,(IX+0x0E)
717
                OR (IX+0x0F)
718
                JR Z,.L5                        ; количество зарезервированных секторов должно быть >0
719
                INC E                           ; +1, есть такое
720
.L5             LD A,(IX+0x13)
721
                OR (IX+0x14)
722
                JR NZ,.L6                       ; количество секторов на разделе для ФАТ16?
35 savelij 723
                INC E
181 savelij 724
.L6             LD A,(IX+0x20)
725
                OR (IX+0x21)
726
                OR (IX+0x22)
727
                OR (IX+0x23)
728
                JR NZ,.L7                       ; количество секторов на разделе для ФАТ32?
729
                INC E                           ; од но из них должно быть =0, другое >0
730
.L7             LD A,(IX+0x15)
731
                AND 0xF0
732
                CP 0xF0
733
                JR NZ,.L8                       ; старшие биты должны быть в 1
35 savelij 734
                INC E
181 savelij 735
.L8             LD A,E
736
                CP 4                            ; условия совпали?
737
                LD A,0xDD                       ; FAT не найден
35 savelij 738
                JP NZ,WR_STAT
181 savelij 739
                LD A,0xFF
740
                LD (CAL_FAT),A                  ; тип фат пока не определен
35 savelij 741
                LD DE,0
742
                LD B,D
743
                LD C,E
744
 
181 savelij 745
.R1             LD (STARTRZ),DE
746
                LD (STARTRZ+2),BC               ; положили номер стартового сектора раздела
747
                CALL LOADLST                    ; загрузили его
35 savelij 748
                LD HL,0
181 savelij 749
                LD DE,(BUF_512+0x16)            ; BPB_FATSZ16
35 savelij 750
                LD A,D
751
                OR E
181 savelij 752
                JR NZ,.R2                       ; если не FAT12/16 (BPB_FATSZ16=0)
753
                LD DE,(BUF_512+0x24)
754
                LD HL,(BUF_512+0x26)            ; BPB_FATSZ32
755
                                                ; то берем из смещения +36
756
.R2             LD (SEC_FAT+2),HL
757
                LD (SEC_FAT),DE                 ; число секторов на FAT-таблицу
35 savelij 758
                LD HL,0
181 savelij 759
                LD DE,(BUF_512+0x13)            ; BPB_TOTSEC16
35 savelij 760
                LD A,D
761
                OR E
181 savelij 762
                JR NZ,.R3                       ; если не FAT12/16 (BPB_TOTSEC16=0)
763
                LD DE,(BUF_512+0x20)
764
                LD HL,(BUF_512+0x22)            ; BPB_TOTSEC32
765
                                                ; то берем из смещения +32
766
.R3             LD (SEC_DSC+2),HL
767
                LD (SEC_DSC),DE                 ; к-во секторов на диске/разделе
35 savelij 768
 
181 savelij 769
; вычисляем ROOTDIRSECTORS
770
                LD BC,(BUF_512+0x0B)            ; BPB_BYTSPERSEC
771
                LD DE,(BUF_512+0x11)            ; BPB_ROOTENTCNT
35 savelij 772
                LD HL,0
773
                LD A,D
774
                OR E
181 savelij 775
                JR Z,.R4
35 savelij 776
                LD B,H
777
                LD C,L
181 savelij 778
                LD A,0x10
35 savelij 779
                CALL BCDE_A
780
                EX DE,HL
781
 
181 savelij 782
; это реализована формула
783
; ROOTDIRSECTORS = ((BPB_ROOTENTCNT*32) + (BPB_BYTSPERSEC-1)) / BPB_BYTSPERSEC
784
; В HL=ROOTDIRSECTORS. если FAT32, то HL=0 всегда
35 savelij 785
 
181 savelij 786
.R4             PUSH HL                         ; ROOTDIRSECTORS
35 savelij 787
                LD (ROOTSEC),HL
181 savelij 788
                LD A,(BUF_512+0x10)
35 savelij 789
                LD DE,(SEC_FAT)
790
                LD HL,(SEC_FAT+2)
791
                DEC A
181 savelij 792
.R5             EX DE,HL
35 savelij 793
                ADD HL,HL
794
                EX DE,HL
795
                ADC HL,HL
796
                DEC A
181 savelij 797
                JR NZ,.R5
798
                POP BC                          ; полный размер FAT-области в секторах
799
                CALL HLDEPBC                    ; прибавили ROOTDIRSECTORS
800
                LD BC,(BUF_512+0x0E)            ; BPB_RSVDSECCNT
35 savelij 801
                LD (RSVDSEC),BC
181 savelij 802
                CALL HLDEPBC                    ; прибавили BPB_RESVDSECCNT
35 savelij 803
                LD (FRSTDAT),DE
181 savelij 804
                LD (FRSTDAT+2),HL               ; положили номер первого сектора данных
35 savelij 805
                LD B,H
806
                LD C,L
181 savelij 807
                LD HL,SEC_DSC                   ; BCDE + 32-ое число по адресу HL
808
                CALL BCDEHLM                    ; вычли из полного к-ва секторов раздела
809
                LD A,(BUF_512+0x0D)
35 savelij 810
                LD (BYTSSEC),A
181 savelij 811
                CALL BCDE_A                     ; разделили на к-во секторов в кластере
35 savelij 812
                LD (CLS_DSC),DE
181 savelij 813
                LD (CLS_DSC+2),BC               ; положили кол-во кластеров на разделе
35 savelij 814
 
112 savelij 815
                LD A,(CAL_FAT)
181 savelij 816
                CP 0xFF
817
                JR NZ,.R6
818
; определение типа FAT при отсуствии MBR
112 savelij 819
                LD DE,(SEC_FAT-1)
820
                LD BC,(SEC_FAT+1)
181 savelij 821
                LD E,0                          ; BCDE = количество секторов *0x100
112 savelij 822
                PUSH BC
181 savelij 823
                PUSH DE                         ; сохранили
112 savelij 824
                SRL B
825
                RR C
826
                RR D
181 savelij 827
                RR E                            ; BCDE = количество секторов *0x80
828
                LD HL,CLS_DSC                   ; количество кластеров на FAT
829
                PUSH HL                         ; сохранили
830
                CALL HLBCDEM                    ; количество кластеров-(количество секторов*0x80)
112 savelij 831
                LD A,E
181 savelij 832
                AND 0x80                        ; количество менее 128 кластеров в секторе для FAT32
112 savelij 833
                OR D
834
                OR C
835
                OR B
836
                LD A,2
837
                POP HL
838
                POP DE
839
                POP BC
181 savelij 840
                JR Z,.R6                        ; FAT32 если флаг Z=0
841
                CALL HLBCDEM                    ; количество кластеров-(количество секторов*0x100)
112 savelij 842
                LD A,D
843
                OR C
844
                OR B
35 savelij 845
                LD A,1
181 savelij 846
                JR Z,.R6                        ; FAT16 если флаг Z=0
847
                XOR A                           ; иначе FAT12
35 savelij 848
 
181 savelij 849
; для FAT12/16 вычисляем адрес первого сектора директории
850
; для FAT32 берем по смещемию +44, на выходе BCDE - сектор ROOTDIR
851
.R6             LD (CAL_FAT),A                  ; уточнили тип фата
112 savelij 852
                EX AF,AF'
35 savelij 853
                LD DE,(RSVDSEC)
854
                LD BC,0
855
                LD HL,STARTRZ
856
                CALL BCDEHLP
857
                LD (FATSTR),DE
181 savelij 858
                LD (FATSTR+2),BC                ; вычислили и положили номер сектора начала FAT-таблиц
112 savelij 859
                EX AF,AF'
35 savelij 860
                AND A
861
                LD DE,0
862
                LD B,D
863
                LD C,E
181 savelij 864
                JR Z,.F1                        ; FAT12 - none
35 savelij 865
                DEC A
181 savelij 866
                JR Z,.F1                        ; FAT16
867
                LD DE,(BUF_512+0x2C)
868
                LD BC,(BUF_512+0x2E)            ; FAT32
869
.F1             LD (ROOTCLS),DE
870
                LD (ROOTCLS+2),BC               ; положили номер кластер ROOT директории
35 savelij 871
 
112 savelij 872
                XOR A
181 savelij 873
                LD (LVL_DIR),A                  ; начинаем с ROOT директории
874
                LD HL,(ADRPATH)                 ; вернули адрес строки пути до файла
875
.F6             PUSH BC
876
                PUSH DE                         ; сохранили номер кластера
877
                CALL FNDBUF                     ; распаковка части текстовой строки для создания маски поиска
35 savelij 878
                POP DE
181 savelij 879
                POP BC                          ; восстановили номер кластера
880
                PUSH HL                         ; сохранили текущий адрес текстовой строки
35 savelij 881
 
181 savelij 882
                LD HL,TDIRCLS                   ; адрес таблицы кластеров текущей директории
35 savelij 883
                LD A,D
884
                OR E
885
                OR B
886
                OR C
181 savelij 887
                CALL SAVEZP                     ; сохранили в таблицу номер текущего кластера
888
                JR Z,.F3                        ; если номер кластера 0, то это ROOT дира (для ФАТ12/16)
889
.F2             PUSH HL
890
                CALL RDFATZP                    ; читаем следущий номер кластера из цепочки директории
891
                CALL LST_CLS                    ; проверяем на конец цепочки
35 savelij 892
                POP HL
181 savelij 893
                JR C,.F3
894
                CALL SAVEZP                     ; если непоследний сохраняем в таблицу
895
                JR .F2                          ; следующий номер кластера
35 savelij 896
 
181 savelij 897
.F3             LD BC,0xFFFF
898
                CALL SAVEZP                     ; кладем маркер конца цепочки
112 savelij 899
                EXX
900
                LD HL,LVL_DIR
181 savelij 901
                LD A,(HL)                       ; текущий уровень директории
902
                INC (HL)                        ; следующий уровень директории
112 savelij 903
                AND A
181 savelij 904
                LD BC,0                         ; количество записей ROOT директории
905
                JR NZ,.F4
112 savelij 906
                LD A,(CAL_FAT)
907
                CP 2
181 savelij 908
                JR NC,.F4
909
                LD HL,(ROOTSEC)                 ; уже не ROOT директория
112 savelij 910
                ADD HL,HL
911
                ADD HL,HL
912
                ADD HL,HL
913
                ADD HL,HL
914
                ADD HL,HL
915
                LD B,H
916
                LD C,L
181 savelij 917
.F4             EXX
35 savelij 918
 
181 savelij 919
.F5             INC BC                          ; ищем по заданной маске начиная с 0
920
                CALL RDDIRSC                    ; грузим по номеру описателя сектор директории
35 savelij 921
                LD A,C
181 savelij 922
                AND 0x0F                        ; в секторе максимум 16 описателей
35 savelij 923
                LD E,A
924
                LD D,0
925
                EX DE,HL
926
                ADD HL,HL
927
                ADD HL,HL
928
                ADD HL,HL
929
                ADD HL,HL
930
                ADD HL,HL
181 savelij 931
                ADD HL,DE                       ; получили адрес нужного описателя
112 savelij 932
                EXX
933
                DEC BC
934
                LD A,B
935
                OR C
936
                EXX
181 savelij 937
                LD A,0xAA
112 savelij 938
                JP Z,WR_STAT
181 savelij 939
                LD A,(HL)                       ; проверяем первый байт имени описателя
35 savelij 940
                AND A
181 savelij 941
                LD A,0xAA                       ; если байт =0, то
942
                JP Z,WR_STAT                    ; переход по ошибке = файл не найден
35 savelij 943
                PUSH HL
944
                PUSH BC
181 savelij 945
                CALL COMPARE                    ; сравниваем с заданной маской
35 savelij 946
                POP BC
947
                POP DE
948
                PUSH DE
181 savelij 949
                POP IX                          ; содержимое IX = адрес описателя
950
                JR NZ,.F5                       ; не совпадает, переходим к следующему описателю
951
                CALL RD_CLAS                    ; забираем номер кластера из найденного описателя
952
                EX (SP),HL                      ; восстановили текущий адрес в строке пути до файла
35 savelij 953
                INC SP
181 savelij 954
                INC SP                          ; маскировка на стеке адреса размера в байтах текущего файла
35 savelij 955
                LD A,(HL)
181 savelij 956
                AND A                           ; текстовая строка кончилась?
957
                JR NZ,.F6                       ; если нет, то ищем дальше
958
                LD A,(IX+0x0B)                  ; проверяем это дира или файл?
959
                AND 0x10
960
                LD A,0xAA                       ; если дира, то ошибка
961
                JP NZ,WR_STAT                   ; текстовая строка должна указывать на файл
35 savelij 962
                DEC SP
963
                DEC SP
181 savelij 964
                POP HL                          ; восстановили в HL адрес откуда взять размер файла в байтах
35 savelij 965
                PUSH BC
966
                PUSH DE
181 savelij 967
                CALL LOADZP                     ; забираем размер файла (в байтах)
35 savelij 968
                LD A,E
969
                AND A
181 savelij 970
                JR Z,.F8                        ; младший байт размера файла =0?
971
                INC D                           ; увеличиваем размер на 256 байт без учета младшего байта
972
.F8             BIT 0,D                         ; проверяем чет/нечет
973
                JR Z,.F9                        ; если нечет, то
974
                INC D                           ; увеличиваем размер еще на 256 байт
975
.F9             CALL BCDE200                    ; делим на 512 (на размер сектор)
35 savelij 976
                PUSH DE
977
                EXX
978
                POP HL
979
                EXX
181 savelij 980
                LD A,(BYTSSEC)                  ; взяли размер кластера в секторах
981
                LD IXH,A                        ; сохранили
35 savelij 982
                POP DE
983
                POP BC
181 savelij 984
                LD HL,0x8000                    ; адрес загрузки
35 savelij 985
 
181 savelij 986
; HX - размер кластера
987
; HL' - кол-во секторов файла
988
; BCDE - номер стартового кластера
989
; LY - стартовая страница загрузки
35 savelij 990
 
181 savelij 991
                LD A,IYL                        ; восстановили страницу загрузки
35 savelij 992
                AND A
181 savelij 993
                JR NZ,CP_PAGE                   ; проверка для загрузки в страницу 0
994
                OUT (MPAG),A                    ; включаем страницу 0
35 savelij 995
                EXX
996
                LD A,L
181 savelij 997
                LD DE,0x41
35 savelij 998
                SBC HL,DE
181 savelij 999
                JR C,.F7                        ; если файл 0x41 и более секторов
1000
                LD A,0x40                       ; то грузим только 0x40 первых секторов
1001
.F7             EXX
1002
                JP LDMINI                       ; переходим на загрузку
35 savelij 1003
 
181 savelij 1004
; загрузка в страницу 1 запрещена
35 savelij 1005
CP_PAGE         DEC A
181 savelij 1006
                LD A,0xAA
35 savelij 1007
                JP Z,WR_STAT
112 savelij 1008
                LD A,IYL
35 savelij 1009
 
181 savelij 1010
; включаем страницу загрузки
1011
LDFILE0         OUT (MPAG),A                    ; включаем заданную страницу для загрузки
35 savelij 1012
 
181 savelij 1013
; загрузка в страницы 02...7F
35 savelij 1014
LD_FILE         EXX
112 savelij 1015
                LD E,IXH
181 savelij 1016
                LD D,0                          ; DE = размер кластера в секторах
35 savelij 1017
                AND A
181 savelij 1018
                SBC HL,DE                       ; сверяем с количеством секторов для загрузки
1019
                LD IXL,IXH                      ; LX = количество секторов для загрузки
35 savelij 1020
                EXX
181 savelij 1021
                JR NC,.L1
1022
                EXX                             ; секторов для загрузки меньше размера кластера
35 savelij 1023
                ADD HL,DE      
1024
                LD A,L
181 savelij 1025
                LD IXL,A                        ; LX = количество секторов для загрузки
35 savelij 1026
                EXX
1027
 
181 savelij 1028
.L1             PUSH BC
35 savelij 1029
                PUSH DE
1030
                PUSH HL
181 savelij 1031
                CALL REALSEC                    ; перевели номер кластера в номер реального сектора
112 savelij 1032
                LD A,IXL
181 savelij 1033
                CP 0x41                         ; количество секторов для загрузки больше 0x40?
1034
                JR C,.L2
1035
                LD A,0x40                       ; будем грузить 0x40 секторов
1036
.L2             POP HL
112 savelij 1037
                LD IYH,A
181 savelij 1038
                CALL RDMULTI                    ; загружаем сектора
112 savelij 1039
                LD A,IXH
181 savelij 1040
                AND 0x80
1041
                JR Z,.L5
112 savelij 1042
                LD A,IXL
1043
                SUB IYH
181 savelij 1044
                JR Z,.L3
1045
                JR C,.L3
1046
                LD HL,0x40
35 savelij 1047
                ADD HL,DE
1048
                EX DE,HL
1049
                LD HL,0
1050
                ADC HL,BC
1051
                LD B,H
1052
                LD C,L
1053
                LD L,A
112 savelij 1054
                INC IYL
1055
                LD A,IYL
181 savelij 1056
                CP 0x40
1057
                JR C,.L4
1058
.L3             INC SP
35 savelij 1059
                INC SP
1060
                INC SP
1061
                INC SP
1062
                JR LDEFILE
1063
 
181 savelij 1064
.L4             OUT (MPAG),A                    ; следующая страница
35 savelij 1065
                LD A,L
181 savelij 1066
                LD HL,0x8000
35 savelij 1067
                CALL RDMULTI
181 savelij 1068
.L5             POP DE
35 savelij 1069
                POP BC
1070
                PUSH HL
1071
                CALL RDFATZP
1072
                CALL LST_CLS
1073
                POP HL
38 savelij 1074
                JR C,LDEFILE
112 savelij 1075
                LD A,IXL
1076
                CP IXH
35 savelij 1077
                JR C,LDEFILE
1078
                LD A,H
1079
                AND A
1080
                JR NZ,LD_FILE
181 savelij 1081
                LD HL,0x8000
112 savelij 1082
                INC IYL
1083
                LD A,IYL
181 savelij 1084
                CP 0x40
35 savelij 1085
                JR C,LDFILE0
1086
LDEFILE         XOR A
1087
                JP WR_STAT
1088
 
1089
LDMINI          EXX
1090
                LD L,A
112 savelij 1091
                LD A,IXH
35 savelij 1092
                LD H,A
1093
                CP L
1094
                JR C,$+3
1095
                LD A,L
1096
                EXX
1097
                PUSH BC
1098
                PUSH DE
1099
                PUSH AF
1100
                PUSH HL
1101
                CALL REALSEC
1102
                POP HL
1103
                POP AF
1104
                CALL RDMULTI
1105
                POP DE
1106
                POP BC
1107
                LD A,H
1108
                AND A
1109
                RET Z
1110
                PUSH HL
1111
                CALL RDFATZP
1112
                CALL LST_CLS
1113
                POP HL
38 savelij 1114
                JR C,LDEFILE
35 savelij 1115
                EXX
1116
                LD A,L
1117
                SUB H
1118
                EXX
1119
                JR NC,LDMINI
1120
                JR LDEFILE
1121
 
1122
SAVEZP          LD (HL),E
1123
                INC HL
1124
                LD (HL),D
1125
                INC HL
1126
                LD (HL),C
1127
                INC HL
1128
                LD (HL),B
1129
                INC HL
1130
                RET
1131
 
1132
LOADZP          LD E,(HL)
1133
                INC HL
1134
                LD D,(HL)
1135
                INC HL
1136
                LD C,(HL)
1137
                INC HL
1138
                LD B,(HL)
1139
                INC HL
1140
                RET
1141
 
181 savelij 1142
; чтение сектора DIR по номеру BC
35 savelij 1143
RDDIRSC         PUSH BC
1144
                LD D,B
1145
                LD E,C
1146
                LD BC,0
181 savelij 1147
                LD A,0x10
35 savelij 1148
                CALL BCDE_A
1149
                LD A,E
1150
                PUSH AF
1151
                LD A,(BYTSSEC)
1152
                PUSH AF
1153
                CALL BCDE_A
1154
                LD HL,TDIRCLS
1155
                EX DE,HL
1156
                ADD HL,HL
1157
                ADD HL,HL
1158
                ADD HL,DE
1159
                CALL LOADZP
1160
                CALL REALSEC
1161
                POP AF
1162
                DEC A
1163
                LD L,A
1164
                POP AF
1165
                AND L
1166
                LD L,A
1167
                LD H,0
1168
                ADD HL,DE
1169
                EX DE,HL
1170
                LD HL,0
1171
                ADC HL,BC
1172
                LD B,H
1173
                LD C,L
1174
                CALL LOADLST
1175
                POP BC
1176
                RET
1177
 
181 savelij 1178
; проверка на последний кластер в цепочке
1179
LST_CLS         LD A,(CAL_FAT)                  ; зависит от разрядности фата
35 savelij 1180
                AND A
1181
                JR NZ,LST_CL1
181 savelij 1182
                LD HL,0x0FF7                    ; проверка для ФАТ12
35 savelij 1183
                SBC HL,DE
1184
                RET
1185
 
1186
LST_CL1         DEC A
1187
                JR NZ,LST_CL2
181 savelij 1188
LST_CL3         LD HL,0xFFF7                    ; проверкам для ФАТ16 и младших бит ФАТ32
35 savelij 1189
                SBC HL,DE
1190
                RET
1191
 
181 savelij 1192
LST_CL2         LD HL,0x0FFF                    ; проверка для старших бит ФАТ32
35 savelij 1193
                SBC HL,BC
1194
                RET NZ
1195
                JR LST_CL3
1196
 
181 savelij 1197
; чтение следующего номера кластера в цепочке
1198
RDFATZP         LD A,(CAL_FAT)                  ; чтение зависит от разрадности фата
35 savelij 1199
                AND A
181 savelij 1200
                JR Z,RDFATS0                    ; переход вперед для ФАТ12
35 savelij 1201
                DEC A
181 savelij 1202
                JR Z,RDFATS1                    ; переход вперед для ФАТ16
1203
                EX DE,HL                        ; здесь чтение для ФАТ32
35 savelij 1204
                ADD HL,HL
1205
                EX DE,HL
1206
                LD HL,0
1207
                ADC HL,BC
181 savelij 1208
                ADC HL,BC                       ; умножили номер кластера на 2
35 savelij 1209
                LD A,E
1210
                LD E,D
1211
                LD D,L
1212
                LD C,H
181 savelij 1213
                LD B,0                          ; разделили номер кластера на 256
1214
                CALL RDFATS2                    ; читаем младшие 16 бит используя чтение для ФАТ16
35 savelij 1215
                INC HL
1216
                LD C,(HL)
1217
                INC HL
181 savelij 1218
                LD B,(HL)                       ; прочитали последующие старшие 16 бит
35 savelij 1219
                RET
1220
 
181 savelij 1221
; чтение 16 битного номера кластера из цепочки для ФАТ16
35 savelij 1222
RDFATS1         LD BC,0
1223
                LD A,E
1224
                LD E,D
181 savelij 1225
                LD D,C                          ; разделили номер кластера на 256, старшие 16 бит =0
1226
RDFATS2         PUSH AF                         ; общее чтение 16 битного номера кластера для ФАТ16/32
35 savelij 1227
                PUSH BC
1228
                LD HL,FATSTR
181 savelij 1229
                CALL BCDEHLP                    ; прибавили смещение от начала фат таблицы
1230
                CALL LOADLST                    ; загрузили вычисленный номер сектора
35 savelij 1231
                POP BC
1232
                POP AF
1233
                LD E,A
1234
                LD D,0
1235
                ADD HL,DE
181 savelij 1236
                ADD HL,DE                       ; вычислили смещение до нужного номера в загруженном секторе
35 savelij 1237
                LD E,(HL)
1238
                INC HL
181 savelij 1239
                LD D,(HL)                       ; получили 16 бит номера кластера
35 savelij 1240
                RET
1241
 
181 savelij 1242
; чтение 12 битного номера кластера из цепочки для ФАТ12
35 savelij 1243
RDFATS0         LD H,D
1244
                LD L,E
1245
                ADD HL,HL
181 savelij 1246
                ADD HL,DE                       ; HL = HL * 3
35 savelij 1247
                SRL H
181 savelij 1248
                RR L                            ; HL = HL / 2 - в итоге умножили номер кластера на 1,5
1249
                LD A,E                          ; A - нам интересен только бит номер старого номера кластера
35 savelij 1250
                LD E,H
1251
                LD D,0
1252
                LD B,D
181 savelij 1253
                LD C,D                          ; разделили номер кластера на 256
35 savelij 1254
                SRL E
1255
                PUSH AF
1256
                PUSH HL
1257
                LD HL,FATSTR
181 savelij 1258
                CALL BCDEHLP                    ; прибавили смещение от начала фат таблицы
1259
                CALL LOADLST                    ; загрузили вывчисленный сектор
35 savelij 1260
                POP BC
1261
                LD A,B
1262
                AND 1
181 savelij 1263
                LD B,A                          ; BC = смещение в загруженном секторе
1264
                ADD HL,BC                       ; HL = адрес откуда читать байты номера кластера
1265
                LD B,(HL)                       ; прочитали младшую часть номера кластера
1266
                INC HL                          ; адрес следующего байта
35 savelij 1267
                LD A,H
181 savelij 1268
                CP HIGH (BUF_512)+2             ; проверка на переход границы загруженного сектора
35 savelij 1269
                JR NZ,RDFATS4
181 savelij 1270
                PUSH BC                         ; выход за пределы текущего загруженного сектора
35 savelij 1271
                LD BC,0
1272
                INC DE
181 savelij 1273
                CALL LOADLST                    ; загружаем следующий сектор фат таблицы
35 savelij 1274
                POP BC
1275
RDFATS4         POP AF
181 savelij 1276
                LD D,(HL)                       ; читаем старшие биты номера кластера
1277
                LD E,B                          ; теперь DE = номер следующего кластера в цепочке
35 savelij 1278
                LD BC,0
181 savelij 1279
                RRA                             ; проверяем бит 0 старого номера кластера
35 savelij 1280
                JR NC,RDFATS3
181 savelij 1281
                SRL D                           ; сдвигаем номер прочитанного номера кластера в младшие 12 бит
35 savelij 1282
                RR E
1283
                SRL D
1284
                RR E
1285
                SRL D
1286
                RR E
1287
                SRL D
1288
                RR E
1289
RDFATS3         LD A,D
181 savelij 1290
                AND 0x0F
1291
                LD D,A                          ; сбросили незначащие старшие 4 бита у полученного номера кластера
35 savelij 1292
                RET
1293
 
181 savelij 1294
; вычисление реального сектора
1295
; на входе BCDE = номер кластера FAT
1296
; на выходе BCDE = номер реального сектора
35 savelij 1297
REALSEC         LD A,B
1298
                OR C
1299
                OR D
1300
                OR E
181 savelij 1301
                JR NZ,REALSE1                   ; BCDE = 0?
1302
                LD HL,SEC_FAT                   ; это root директория у ФАТ12/16
1303
                LD DE,(FATSTR)                  ; местоположение ROOT диры сразу после фат таблицы
35 savelij 1304
                LD BC,(FATSTR+2)
1305
                PUSH HL
181 savelij 1306
                CALL BCDEHLP                    ; прибавили к началу фат таблицы ее размер
35 savelij 1307
                POP HL
181 savelij 1308
                JP BCDEHLP                      ; прибавили еще раз и получили номер сектора начала ROOT диры
35 savelij 1309
 
181 savelij 1310
REALSE1         LD HL,0xFFFE
35 savelij 1311
                EX DE,HL
1312
                ADD HL,DE
1313
                EX DE,HL
1314
                INC HL
181 savelij 1315
                ADC HL,BC                       ; HLDE = номер кластера - 2
1316
                LD A,(BYTSSEC)                  ; нужно умножить на размер кластера
35 savelij 1317
                JR REALSE2
1318
 
1319
REALSE3         SLA E
1320
                RL D
1321
                RL L
1322
                RL H
1323
REALSE2         RRCA
181 savelij 1324
                JR NC,REALSE3                   ; умножили на размер кластера
35 savelij 1325
                LD B,H
1326
                LD C,L
1327
                LD HL,STARTRZ
181 savelij 1328
                CALL BCDEHLP                    ; прибавили смещение от начала диска
35 savelij 1329
                LD HL,FRSTDAT
181 savelij 1330
                JP BCDEHLP                      ; прибавили смещение от начала раздела
35 savelij 1331
 
181 savelij 1332
; BCDE = BCDE / 512
35 savelij 1333
BCDE200         LD E,D
1334
                LD D,C
1335
                LD C,B
1336
                LD B,0
1337
                LD A,2
1338
                JR BCDE_A
1339
 
181 savelij 1340
; BCDE = BCDE >> A
35 savelij 1341
BCDE_A1         SRL B
1342
                RR C
1343
                RR D
1344
                RR E
1345
BCDE_A          RRCA
1346
                JR NC,BCDE_A1
1347
                RET
1348
 
181 savelij 1349
; BCDE = (ADR) - BCDE
35 savelij 1350
BCDEHLM         LD A,(HL)
1351
                INC HL
1352
                SUB E
1353
                LD E,A
1354
                LD A,(HL)
1355
                INC HL
1356
                SBC A,D
1357
                LD D,A
1358
                LD A,(HL)
1359
                INC HL
1360
                SBC A,C
1361
                LD C,A
1362
                LD A,(HL)
1363
                SBC A,B
1364
                LD B,A
1365
                RET
1366
 
181 savelij 1367
; BCDE = (ADR) + BCDE
35 savelij 1368
BCDEHLP         LD A,(HL)
1369
                INC HL
1370
                ADD A,E
1371
                LD E,A
1372
                LD A,(HL)
1373
                INC HL
1374
                ADC A,D
1375
                LD D,A
1376
                LD A,(HL)
1377
                INC HL
1378
                ADC A,C
1379
                LD C,A
1380
                LD A,(HL)
1381
                ADC A,B
1382
                LD B,A
1383
                RET
1384
 
181 savelij 1385
; HLDE = HLDE + BC
35 savelij 1386
HLDEPBC         EX DE,HL
1387
                ADD HL,BC
1388
                EX DE,HL
1389
                LD BC,0
1390
                ADC HL,BC
1391
                RET
1392
 
181 savelij 1393
; BCDE = BCDE - (ADR)
112 savelij 1394
HLBCDEM         LD A,E
1395
                SUB (HL)
1396
                INC HL
1397
                LD E,A
1398
                LD A,D
1399
                SBC A,(HL)
1400
                INC HL
1401
                LD D,A
1402
                LD A,C
1403
                SBC A,(HL)
1404
                INC HL
1405
                LD C,A
1406
                LD A,B
1407
                SBC A,(HL)
1408
                LD B,A
35 savelij 1409
                RET
1410
 
181 savelij 1411
; грузилка одного сектора
112 savelij 1412
LOADLST         CALL CPNUMSC
1413
                JR NZ,LOADLST1
1414
                LD HL,BUF_512
1415
                RET
1416
 
181 savelij 1417
LOADLST1        LD HL,BUF_512                   ; адрес буфера сектора
1418
                LD A,1                          ; грузить 1 сектор
35 savelij 1419
                PUSH HL
181 savelij 1420
                CALL RDMULTI                    ; загрузили сектор
1421
                POP HL                          ; на выходе HL=адрес начала буфера загруженного сектора
35 savelij 1422
                RET
1423
 
181 savelij 1424
; проверка на уже загруженный сектор
112 savelij 1425
CPNUMSC         LD HL,LSTLOAD
1426
                LD A,(HL)
1427
                INC HL
1428
                CP E
1429
                RET NZ
1430
                LD A,(HL)
1431
                INC HL
1432
                CP D
1433
                RET NZ
1434
                LD A,(HL)
1435
                INC HL
1436
                CP C
1437
                RET NZ
1438
                LD A,(HL)
1439
                CP B
1440
                RET
1441
 
181 savelij 1442
; подача команды в SD карту без параметров
35 savelij 1443
OUTCOM          PUSH BC
181 savelij 1444
                LD BC,0x0600+SD_SEND            ; выдать в порт 6 байт
35 savelij 1445
                OTIR
1446
                POP BC
1447
                RET
1448
 
181 savelij 1449
; выдача в порт SD карты команды с параметром 0
35 savelij 1450
OUT_COM         PUSH BC
1451
                LD BC,SD_SEND
181 savelij 1452
                in (c) ;in f,(c)
1453
                in (c) ;in f,(c)
1454
                OUT (C),A                       ; отправили код команды
35 savelij 1455
                XOR A
181 savelij 1456
                OUT (C),A                       ; биты 31-24 параметра
35 savelij 1457
                NOP
181 savelij 1458
                OUT (C),A                       ; биты 23-16 параметра
35 savelij 1459
                NOP
181 savelij 1460
                OUT (C),A                       ; биты 15-8 параметра
35 savelij 1461
                NOP
181 savelij 1462
                OUT (C),A                       ; биты 7-0 параметра
35 savelij 1463
                DEC A
181 savelij 1464
                OUT (C),A                       ; без CRC16
35 savelij 1465
                POP BC
1466
                RET
1467
 
1468
SECM200         PUSH HL
1469
                PUSH BC
1470
                LD A,CMD_58
181 savelij 1471
                LD BC,SD_RSTR
35 savelij 1472
                CALL OUT_COM
1473
                CALL IN_OOUT
1474
                IN H,(C)
1475
                NOP
1476
                IN A,(C)
1477
                NOP
1478
                IN A,(C)
1479
                NOP
1480
                IN A,(C)
1481
                BIT 6,H
1482
                POP HL
181 savelij 1483
                JR NZ,.L1
35 savelij 1484
                EX DE,HL
1485
                ADD HL,HL
1486
                EX DE,HL
1487
                ADC HL,HL
1488
                LD H,L
1489
                LD L,D
1490
                LD D,E
1491
                LD E,0
181 savelij 1492
.L1             LD A,CMD_18
35 savelij 1493
                LD C,SD_SEND
181 savelij 1494
                in (c) ;in f,(c)
1495
                in (c) ;in f,(c)
35 savelij 1496
                OUT (C),A
1497
                NOP
1498
                OUT (C),H
1499
                NOP
1500
                OUT (C),L
1501
                NOP
1502
                OUT (C),D
1503
                NOP
1504
                OUT (C),E
181 savelij 1505
                LD A,0xFF
35 savelij 1506
                OUT (C),A
1507
                POP HL
1508
                RET
1509
 
1510
IN_OOUT         EXX
181 savelij 1511
                LD DE,0x30FF
1512
.L1             IN A,(SD_RSTR)
35 savelij 1513
                CP E
181 savelij 1514
                JR NZ,.L2
1515
                DEC D
1516
                JR NZ,.L1
1517
.L2             EXX
35 savelij 1518
                RET
1519
 
181 savelij 1520
CMD00           DB 0x40,0x00,0x00,0x00,0x00,0x95;GO_IDLE_STATE
1521
CMD08           DB 0x48,0x00,0x00,0x01,0xAA,0x87;SEND_IF_COND
1522
CMD16           DB 0x50,0x00,0x00,0x02,0x00,0xFF;SET_BLOCKEN
35 savelij 1523
 
181 savelij 1524
; много секторное чтение с SD карты
69 savelij 1525
RDMULTI         EX AF,AF'
35 savelij 1526
                CALL SECM200
69 savelij 1527
                EX AF,AF'
35 savelij 1528
                LD BC,SD_RSTR
181 savelij 1529
.L1             EX AF,AF'
1530
.L2             CALL IN_OOUT
1531
                CP 0xFE
1532
                JR NZ,.L2
35 savelij 1533
                INIR
1534
                NOP
1535
                INIR
1536
                NOP
1537
                IN A,(C)
1538
                NOP
1539
                IN A,(C)
69 savelij 1540
                EX AF,AF'
35 savelij 1541
                DEC A
181 savelij 1542
                JR NZ,.L1
35 savelij 1543
                LD A,CMD_12
1544
                CALL OUT_COM
181 savelij 1545
.L3             CALL IN_OOUT
35 savelij 1546
                INC A
181 savelij 1547
                JR NZ,.L3
35 savelij 1548
                RET
1549
 
181 savelij 1550
; выборка номера кластера из файлового описателя
35 savelij 1551
RD_CLAS         EX DE,HL
181 savelij 1552
                LD DE,0x14                      ; старшие 16 бит читаем из смещения +20
35 savelij 1553
                ADD HL,DE
1554
                LD C,(HL)
1555
                INC HL
1556
                LD B,(HL)
181 savelij 1557
                LD E,5                          ; младшие 16 бит читаем из смещения +26
35 savelij 1558
                ADD HL,DE
1559
                LD E,(HL)
1560
                INC HL
1561
                LD D,(HL)
1562
                INC HL
1563
                RET
1564
 
181 savelij 1565
; проверка по маске
35 savelij 1566
COMPARE         LD DE,FB_EXT
181 savelij 1567
                LD B,0x0B
35 savelij 1568
                LD A,(DE)
1569
                CP (HL)
1570
                RET NZ
1571
                INC HL
1572
                INC DE
1573
                DJNZ $-5
1574
                RET
1575
 
181 savelij 1576
; распаковщик пути к файлу
1577
FNDBUF          LD BC,0x0802
35 savelij 1578
                LD DE,FB_EXT
1579
FNDBUF4         LD A,(HL)
1580
                INC HL
112 savelij 1581
                CP "."
35 savelij 1582
                JR Z,FNDBUF2
112 savelij 1583
                CP "/"
35 savelij 1584
                JR Z,FNDBUF5
1585
                LD (DE),A
1586
                INC DE
1587
                DJNZ FNDBUF4
1588
                LD A,(HL)
1589
                AND A
1590
                RET Z
1591
                INC HL
1592
                JR FNDBUF3
1593
 
1594
FNDBUF5         LD A,C
1595
                AND A
1596
                RET Z
1597
FNDBUF2         LD A,B
1598
                AND A
1599
                JR Z,FNDBUF3
112 savelij 1600
                LD A," "
35 savelij 1601
                LD (DE),A
1602
                INC DE
1603
                DJNZ $-2
1604
FNDBUF3         LD B,3
1605
                DEC C
1606
                DEC HL
1607
                LD A,(HL)
112 savelij 1608
                CP "/"
35 savelij 1609
                JR Z,FNDBUF4
1610
                INC HL
1611
                JR FNDBUF4
1612
RAMCEND
69 savelij 1613
                DEPHASE