Форум программистов, компьютерный форум, киберфорум
QBasic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/4: Рейтинг темы: голосов - 4, средняя оценка - 5.00
Кормпилятор
 Аватар для Quiet Snow
5044 / 1718 / 409
Регистрация: 25.04.2010
Сообщений: 4,827
Записей в блоге: 2

Мышь + Клавиатура + Таймер(мс) + Скан папки / [ "КАЛ АБСОЛЮТ" ]

16.01.2025, 13:23. Показов 2026. Ответов 3

Студворк — интернет-сервис помощи студентам
Подытоживая последние темы.



Нюансы
В QBasic CALL ABSOLUTE встроен, в QuickBASIC - его надо подключать ключом /L,
при этом QB.QLB - должeн быть в папке с QB.EXE.
Чтобы создать EXE-шник, в папке должны присутствовать ещё и
Для QB 4.0: BC.EXE, LINK.EXE, BCOM40.LIB, QB.LIB
Для QB 4.5: BC.EXE, LINK.EXE, BCOM45.LIB, QB.LIB
Для QBX - думаю то же самое.

Ещё раз, директива $DYNAMIC, для массивов инлайна - НУЖНА!
Почему не "стринги", потому что этими "труселями" невозможно адресовать параметры,
забитые перед процедурами.
Почему не стек, если хотите геморой на свою жопу - то отговаривать не буду.
Машинки лучше проверять в отладчике, асм иногда такое городит, что можно опупеть.




Код:
QBasic/QuickBASIC
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
 '
 '  Базовый код создан через: Hex2Abs - v 0.1.2
 '  >Quiet Snow<  2011-2025г.
 '
 
  ' Структура DTA для работы с диском
TYPE DataTransferArea
   DtaNoUse AS STRING * 21
   DtaAtrib AS STRING * 1
   DtaTime AS INTEGER
   DtaData AS INTEGER
   DtaFileSize AS LONG
   DtaFileName AS STRING * 13
END TYPE
 
      '  Загрузка кода
 
 DECLARE SUB CodeToMem (CodSeg AS LONG, CodPtr AS LONG, NumLines AS INTEGER)
 
      '  Инициализация кода
 
 DECLARE SUB InitRoutines ()
 
      '  Работа с векторами
 
 DECLARE SUB SetIntVec (IntNum AS INTEGER, CSegm&, COffs&)
 DECLARE SUB RestoreVec (IntNum AS INTEGER)
 
      '  Работа с клавиатурой
 
 DECLARE SUB KeybActivate ()
 DECLARE SUB KeybClose ()
 DECLARE FUNCTION KeyPress (KNum%)
 
      '  Работа с мышью
 
 DECLARE SUB MouUpdate ()
 
      '  Работа с таймером
 
 DECLARE SUB TimerActivate (Hertz AS LONG)
 DECLARE SUB TimerClose ()
 DECLARE SUB Delay (Ms AS LONG)
 
      '  Сканирование текущей директории (DTA)
 
 DECLARE SUB SetMask (Mask AS STRING)
 DECLARE SUB ScanDir ()
 DECLARE FUNCTION GetMinNames ()
 DECLARE FUNCTION GetMaxNames ()
 DECLARE FUNCTION GetNameByNum$ (Num AS INTEGER)
 DECLARE SUB PrintDirFixed (Num1 AS INTEGER, Num2 AS INTEGER, Sel AS INTEGER)
 
 
 REM $DYNAMIC
 DIM SHARED Code1(472) AS INTEGER  '  Код и данные подпрограмм прерываний
 DIM SHARED Code2(18) AS INTEGER   '  Код подпрограммы клавиатуры
 DIM SHARED Code3(23) AS INTEGER   '  Код подпрограммы мыши
 DIM SHARED Code4(20) AS LONG      '  Код подпрограммы таймера
 
 DIM SHARED Code5(13) AS INTEGER   '  Получение адреса DTA
 DIM SHARED Code6(14) AS INTEGER   '  Установка адреса DTA
 DIM SHARED Code7(25) AS INTEGER   '  Нахождение первого вхождения
 DIM SHARED Code8(24) AS INTEGER   '  Нахождение следующего файла
 
 '  Для работы пп векторов, мыши, клавиатуры и таймера
 DIM SHARED Kolic AS LONG          '  Кол-во байт в подпрограмме
 DIM SHARED MultiKey(127) AS INTEGER  '  Массив клавиш клавиатуры
 DIM SHARED OldK(127) AS INTEGER   '  Старые нажатия (форм сами)
 DIM SHARED CuMx AS LONG           '  Кастомные координаты курсора
 DIM SHARED CuMy AS LONG
 DIM SHARED BtnO AS INTEGER        '  Старое значение ЛКМ
 DIM SHARED Hz AS LONG             '  Герц
 
 DIM SHARED DTA AS DataTransferArea
 DIM SHARED MaskPath AS STRING * 64
 DIM SHARED InDirNames(30) AS STRING * 13
 DIM SHARED DirFNames AS STRING
 DIM SHARED QuaNames AS INTEGER
 
 '  Пользовательские массивы и переменные
 DIM FVib AS INTEGER, MinV AS INTEGER, MaxV AS INTEGER
 DIM Rdr AS INTEGER, Ferr AS INTEGER
 
 
 '  Инициализация
 
 InitRoutines
 
 '  Пользовательская программа
 
 CLS
 ScanDir                          '  Скан директории  [ INT 21h ]
 MinV = GetMinNames
 MaxV = GetMaxNames
 FVib = MinV: Rdr = -1
 
 KeybActivate                     '  Включаем обработчик  [ INT 9 ]
 
 TimerActivate (1000)             '  1000 прерываний в секунду  [ INT 8 ]
 
 '  Тестовые задержки
 FOR i = 160 TO 50 STEP -5
    Delay CLNG(i)
    PRINT "  Delay"; i; "ms"
 NEXT: LOCATE 1
 FOR i = 46 TO 2 STEP -2
    Delay CLNG(i): LOCATE , 40
    PRINT "  Delay"; i; "ms"
 NEXT
 
 Delay 1000
 
 CLS 2
 LOCATE 16, 40
 PrintDirFixed 1, 7, FVib
 
 
 
  DO
     MouUpdate                    '  Берём параметры мыши  [ INT 51 ]
    
     '   Мышь
     LOCATE 2, 1
     COLOR 15: PRINT "   Mouse": COLOR 7
     PRINT " Mx:"; Code3(3), "My:"; Code3(4), "  Delta", "dMx:"; Code3(0), "dMy:"; Code3(1)
     PRINT " Buttons:"; Code3(2)
     CuMx = CuMx + CLNG(Code3(0))
     CuMy = CuMy + CLNG(Code3(1))
 
     PRINT " Custom mouse position    Mx:"; CuMx, "My:"; CuMy
 
     '   Клавиатура
     LOCATE 7, 1
     COLOR 15: PRINT "   KeyBoard": COLOR 7
     FOR i = 0 TO 127
        PRINT MultiKey(i);
     NEXT
 
     '   Таймер
     LOCATE 14, 1
     COLOR 15: PRINT "   Timer": COLOR 7
     PRINT " Hertz: "; Hz
     PRINT " Incremental (Int 8): "; Code4(0)
     PRINT " QBasic Timer:"; TIMER
     PRINT " Time: "; TIME$
     PRINT
 
     '   Директории
     LOCATE 14, 37
     COLOR 15: PRINT "   Directories": COLOR 7
    
     IF Rdr AND -GetMinNames THEN
        LOCATE 16, 40
        PrintDirFixed FVib - 3, FVib + 3, FVib
        Rdr = 0
     END IF
    
     '  Кнопки:  Вверх \ Вниз
     IF KeyPress(72) AND FVib > MinV THEN
       FVib = FVib - 1: Rdr = -1
     END IF
     IF KeyPress(80) AND FVib < MaxV THEN
       FVib = FVib + 1: Rdr = -1
     END IF
    
     '  Кнопка ENTER
     IF KeyPress(28) THEN
       
       '  Выбор текущей директории через DOS SHELL
       ON ERROR GOTO DirErr: Ferr = 0
         CHDIR GetNameByNum$(FVib)
       ON ERROR GOTO 0
      
       '  Если нет ошибок(выбор произошёл)
       IF NOT Ferr THEN
         '  Сканируем заново
         ScanDir                          '  Скан директории  [ INT 21h ]
      
         '  Границы записей
         MinV = GetMinNames
         MaxV = GetMaxNames
         FVib = MinV
      
         '  Перерисовка
         LOCATE 16, 40
         PrintDirFixed 1, 7, FVib
         Rdr = -1
       END IF
     END IF
 
  BtnO = Code3(2)
  LOOP UNTIL MultiKey(1)
 
  TimerClose
  KeybClose
 
 
END
 
DirErr: Ferr = -1
RESUME NEXT
 
     '  INLINE КОДЫ
     '  код работы с векторами
Asm1:
DATA 11112222333306505352572E8B3E20032E
DATA 8B1E22032E8B0E240333C02E8A8580020A
DATA C00F857003B801002E88858002FA33C08E
DATA C0C1E702268B152E89950000268B55022E
DATA 8995020026890D26895D02FB5F5A5B5807
DATA CB065053572E8B3E200333C02E8A858002
DATA 0AC00F84AD0333C02E88858002FA33C08E
DATA C0C1E7022E8B9D000026891D2E8B9D0200
DATA 26895D02FB5F5B5807CB
 
     '  код клавиатуры
 
Asm2: DATA 505306B811118EC033DBE460A880
DATA 7803BBFFFF257F0093D1E3268987222207
DATA 5BB020E62058CF
 
     '  код мыши
 
Asm3: DATA 0000000000000000000060B80B00
DATA CD332E890E00002E89160200B80300CD33
DATA 2E891E04002E890E06002E8916080061CB
 
     '  код таймера
 
Asm4: DATA 0000000011111111222222226650
DATA 1E0E1F2E66FF0600002E66A108002E6601
DATA 0604002E66813E0400FFFF000077081FB0
DATA 20E6206658CF2E66812E0400FFFF00001F
DATA 6658EA33333333
    
     '  Получение адреса DTA
 
Asm5: DATA 221144339C5053B8002FCD218CC0
DATA 2EA300002E891E02005B589DCB
 
     '  Установка адреса DTA
 
Asm6: DATA 221144339C50521E2EA100008ED8
DATA B8001A2E8B160200CD211F5A589DCB
 
     '  Нахождение первого вхождения
 
Asm7: DATA 2211443366559C5051521E33C02E
DATA A300002EA102008ED82E8B160400B8004E
DATA B93500F8CD2172072EC706000001001F5A
DATA 59589DCB
 
     '  Нахождение следующего файла
 
Asm8: DATA 2211443366559C50521E33C02EA3
DATA 00002EA102008ED82E8B160400B8004FB9
DATA 3500F8CD2172072EC706000001001F5A58
DATA 9DCB
 
SUB CodeToMem (CodSeg AS LONG, CodPtr AS LONG, NumLines AS INTEGER)
DIM Lst AS INTEGER, Lba AS INTEGER
DIM Sc AS STRING, Pr AS INTEGER
DIM IntInMas AS LONG, LngInMas AS LONG
 Kolic = 0
    DEF SEG = CodSeg
 FOR Lst = 1 TO NumLines          'Грузим строки кода
     READ Sc
     FOR Lba = 1 TO LEN(Sc) STEP 2    'Преобразовываем в байты
       Pr = VAL("&H" + MID$(Sc, Lba, 2))
       POKE CodPtr + Kolic, Pr
       Kolic = Kolic + 1
     NEXT
 NEXT
 '  Рассчитать кол-во байт в массиве
 IntInMas = ((Kolic + (Kolic AND 1)) \ 2) - 1
 LngInMas = ((IntInMas + (IntInMas AND 1)) \ 2) - 1
 'PRINT "Integers upper bound in DIM:"; IntInMas
 'PRINT "Longs upper bound in DIM:"; LngInMas
    DEF SEG
END SUB
 
REM $STATIC
SUB Delay (Ms AS LONG)
   DIM TmStop AS LONG
   TmStop = Code4(0) + Ms
   WHILE Code4(0) < TmStop
   WEND
END SUB
 
FUNCTION GetMaxNames
  GetMaxNames = QuaNames
END FUNCTION
 
FUNCTION GetMinNames
  IF QuaNames > 0 THEN
    GetMinNames = 1
  ELSE : GetMinNames = 0
  END IF
END FUNCTION
 
FUNCTION GetNameByNum$ (Num AS INTEGER)
DIM TName AS STRING
DIM OldFi AS INTEGER, Fi AS INTEGER, NumName AS INTEGER
OldFi = 1: NumName = 1
 
 DO
    Fi = INSTR(OldFi, DirFNames, CHR$(0))
    IF Num = NumName THEN
       TName = MID$(DirFNames, OldFi, Fi - OldFi)
       GetNameByNum$ = TName
       EXIT FUNCTION
    END IF
    OldFi = Fi + 1
    NumName = NumName + 1
 LOOP UNTIL Fi = 0
 
END FUNCTION
 
REM $DYNAMIC
SUB InitRoutines
DIM p AS INTEGER
   '   Код работы с векторами прерываний
   RESTORE Asm1
   CodeToMem VARSEG(Code1(400)), VARPTR(Code1(400)), 9
 
   '   Код работы с клавиатурой
   RESTORE Asm2
   CodeToMem VARSEG(Code2(0)), VARPTR(Code2(0)), 3
 
   '   Вставим в код динамичски меняющиеся сегмент и смещение
   DEF SEG = VARSEG(Code2(0))
     POKE VARPTR(Code2(0)) + 4, ASC(MKL$(VARSEG(MultiKey(0))))
     POKE VARPTR(Code2(0)) + 5, ASC(MID$(MKL$(VARSEG(MultiKey(0))), 2, 1))
     POKE VARPTR(Code2(0)) + 28, ASC(MKL$(VARPTR(MultiKey(0))))
     POKE VARPTR(Code2(0)) + 29, ASC(MID$(MKL$(VARPTR(MultiKey(0))), 2, 1))
   DEF SEG
 
 '  Отладочная информация
 'FOR i = 0 TO Kolic - 1
 'PRINT HEX$(PEEK(VARPTR(Code2(0)) + i));
 'NEXT
 'PRINT
   
 
   '   Код работы с мышью
   RESTORE Asm3
   CodeToMem VARSEG(Code3(0)), VARPTR(Code3(0)), 3
 
   '   Код работы с таймером (полный перехват без компенсации)
   RESTORE Asm4
   CodeToMem VARSEG(Code4(0)), VARPTR(Code4(0)), 5
 
   DIM b1 AS INTEGER, b2 AS INTEGER, b3 AS INTEGER, b4 AS INTEGER
  
   DEF SEG = 0
     b1 = PEEK(4 * 8)            '  Смещение
     b2 = PEEK(4 * 8 + 1)        '  Смещение
     b3 = PEEK(4 * 8 + 2)        '  Сегмент
     b4 = PEEK(4 * 8 + 3)        '  Сегмент
   DEF SEG = VARSEG(Code4(0))
    '  Вставляем адрес старого вектора для JMP
    POKE VARPTR(Code4(0)) + Kolic - 4, b1
    POKE VARPTR(Code4(0)) + Kolic - 3, b2
    POKE VARPTR(Code4(0)) + Kolic - 2, b3
    POKE VARPTR(Code4(0)) + Kolic - 1, b4
    
    'PRINT HEX$(PEEK(VARPTR(Code4(0)) + Kolic - 4))
    'PRINT HEX$(PEEK(VARPTR(Code4(0)) + Kolic - 3))
    'PRINT HEX$(PEEK(VARPTR(Code4(0)) + Kolic - 2))
    'PRINT HEX$(PEEK(VARPTR(Code4(0)) + Kolic - 1))
   DEF SEG
 
   RESTORE Asm5
   CodeToMem VARSEG(Code5(0)), VARPTR(Code5(0)), 2
   RESTORE Asm6
   CodeToMem VARSEG(Code6(0)), VARPTR(Code6(0)), 2
   RESTORE Asm7
   CodeToMem VARSEG(Code7(0)), VARPTR(Code7(0)), 4
   RESTORE Asm8
   CodeToMem VARSEG(Code8(0)), VARPTR(Code8(0)), 4
 
 SetMask "*.*"
 
END SUB
 
SUB KeybActivate
   SetIntVec 9, VARSEG(Code2(0)), VARPTR(Code2(0))
END SUB
 
SUB KeybClose
   RestoreVec 9
END SUB
 
REM $STATIC
FUNCTION KeyPress (KNum%)
  IF MultiKey(KNum%) <> OldK(KNum%) THEN
     IF MultiKey(KNum%) THEN
        KeyPress = -1
     ELSE
        KeyPress = 0
     END IF
  END IF
  OldK(KNum%) = MultiKey(KNum%)
END FUNCTION
 
REM $DYNAMIC
SUB MouUpdate
   DEF SEG = VARSEG(Code3(0))
      CALL ABSOLUTE(VARPTR(Code3(0)) + 10)
   DEF SEG
END SUB
 
REM $STATIC
SUB PrintDirFixed (Num1 AS INTEGER, Num2 AS INTEGER, Sel AS INTEGER)
DIM TName AS STRING
DIM OldFi AS INTEGER, Fi AS INTEGER, NumName AS INTEGER
DIM N1 AS INTEGER, N2 AS INTEGER
DIM CrPosX AS INTEGER, CrLinY AS INTEGER
N1 = Num1: N2 = Num2
IF N1 < GetMinNames THEN N1 = GetMinNames
IF N2 > GetMaxNames THEN N2 = GetMaxNames
OldFi = 1: NumName = 1
CrPosX = POS(0): CrLinY = CSRLIN
 
  DO
    Fi = INSTR(OldFi, DirFNames, CHR$(0))
    IF NumName >= N1 THEN
        IF Sel = NumName THEN COLOR 15, 1 ELSE COLOR 7, 0
              IF NumName > N2 THEN EXIT DO
        TName = MID$(DirFNames, OldFi, Fi - OldFi)
        CrLinY = CSRLIN
        LOCATE , CrPosX
        PRINT SPACE$(13)
        LOCATE CrLinY, CrPosX
        PRINT TName
    END IF
    OldFi = Fi + 1
    NumName = NumName + 1
  LOOP UNTIL Fi = 0
  WHILE N2 < Num2
    LOCATE , CrPosX
    PRINT SPACE$(13)
    N2 = N2 + 1
  WEND
END SUB
 
REM $DYNAMIC
SUB RestoreVec (IntNum AS INTEGER)
 
  IF IntNum > 159 OR IntNum < 0 THEN EXIT SUB
  Code1(400) = IntNum
 
  DEF SEG = VARSEG(Code1(0))
     CALL ABSOLUTE(VARPTR(Code1(0)) + 886)
  DEF SEG
 
END SUB
 
REM $STATIC
SUB ScanDir
 DIM DTAOLDSeg%, DTAOLDPtr%
 DIM AddName AS STRING
  '  Вызываем функцию получения адреса DTA
  DEF SEG = VARSEG(Code5(0))
     CALL ABSOLUTE(VARPTR(Code5(2)))
 
     DTAOLDSeg% = Code5(0)   ' Сохраним указатель на DTA
     DTAOLDPtr% = Code5(1)
 
  '  Вызываем функцию установки адреса DTA
     Code6(0) = VARSEG(DTA)  ' Новый адрес
     Code6(1) = VARPTR(DTA)
  DEF SEG = VARSEG(Code6(0))
     CALL ABSOLUTE(VARPTR(Code6(2)))
 
  '  Поиск 1-го вхождения
 
  Code7(1) = VARSEG(MaskPath)  ' Адрес шаблона
  Code7(2) = VARPTR(MaskPath)
  QuaNames = 0
  DirFNames = ""
 
  DEF SEG = VARSEG(Code7(0))
     CALL ABSOLUTE(VARPTR(Code7(3)))
     '  Если вхождение найдено
     IF Code7(0) THEN
        AddName = LEFT$(DTA.DtaFileName, INSTR(DTA.DtaFileName, CHR$(0)))
        IF AddName <> ("." + CHR$(0)) THEN
          DirFNames = DirFNames + AddName
          QuaNames = QuaNames + 1
        END IF
        DEF SEG = VARSEG(Code8(0))
        DO   '  Ищем всё последующие вхождения
          CALL ABSOLUTE(VARPTR(Code8(3)))
          IF Code8(0) THEN
            QuaNames = QuaNames + 1
            'PRINT LEFT$(DTA.DtaFileName, INSTR(DTA.DtaFileName, CHR$(0)) - 1)
            DirFNames = DirFNames + LEFT$(DTA.DtaFileName, INSTR(DTA.DtaFileName, CHR$(0)))
          END IF
        LOOP UNTIL Code8(0) = 0
     END IF
 
  '  Восстанавливаем адрес DTA
     Code6(0) = DTAOLDSeg%
     Code6(1) = DTAOLDPtr%
  DEF SEG = VARSEG(Code6(0))
     CALL ABSOLUTE(VARPTR(Code6(2)))
  DEF SEG
 
END SUB
 
REM $DYNAMIC
SUB SetIntVec (IntNum AS INTEGER, CSegm&, COffs&)
 
  IF IntNum > 159 OR IntNum < 0 THEN EXIT SUB
  Code1(400) = IntNum
 
  DEF SEG = VARSEG(Code1(0))
     POKE 802, ASC(MKL$(CSegm&))
     POKE 803, ASC(MID$(MKL$(CSegm&), 2, 1))
     POKE 804, ASC(MKL$(COffs&))
     POKE 805, ASC(MID$(MKL$(COffs&), 2, 1))
         CALL ABSOLUTE(VARPTR(Code1(0)) + 806)
  DEF SEG
 
END SUB
 
REM $STATIC
SUB SetMask (Mask AS STRING)
   MaskPath = Mask + CHR$(0)
END SUB
 
REM $DYNAMIC
SUB TimerActivate (Hertz AS LONG)
 
 DIM Divisor AS LONG
 Divisor = 1193182 / Hertz
 IF Divisor < 2 THEN Divisor = 2
 IF Divisor > 65535 THEN Divisor = 65535
 Hz = 1193182 / Divisor
 
 Code4(0) = 0: Code4(1) = 0
 
 DEF SEG = VARSEG(Code4(0))
    POKE VARPTR(Code4(0)) + 8, Divisor AND 255
    POKE VARPTR(Code4(0)) + 9, Divisor \ 256
    POKE VARPTR(Code4(0)) + 10, 0
    POKE VARPTR(Code4(0)) + 11, 0
 DEF SEG
 
     SetIntVec 8, VARSEG(Code4(0)), VARPTR(Code4(0)) + 12
 
 OUT &H43, &H36                     '  Управляющий регистр
 OUT &H40, ASC(MKL$(Divisor))              '  Младший байт
 OUT &H40, ASC(MID$(MKL$(Divisor), 2, 1))  '  Старший байт
 
END SUB
 
REM $STATIC
SUB TimerClose
   '  Сбрасываем делитель в дефолт
   OUT &H43, &H36           '  Управляющий регистр
   OUT &H40, 0              '  Младший байт
   OUT &H40, 0              '  Старший байт
   RestoreVec 8
END SUB
Дополнительно закрепляю немного обновлённый HEX2ABS в который впилил 2 функции(удаление байта
и вставку байта).

P.S: Классически предлагаю не гадить в топик, а постить исходники строго по теме хотя бы
не ниже этого уровня. Но кто меня когда слушал...
Вложения
Тип файла: zip HEX2ABS.zip (55.2 Кб, 8 просмотров)
1
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
16.01.2025, 13:23
Ответы с готовыми решениями:

Клавиатура и мышь
Здраствуйте. Вопрос: как сделать поддержку клавиатуры и мыши для своей программы, что бы потом можно было работать и в линуксе и в...

Клавиатура и мышь
Доброго времени суток... У меня есть клавиатура DEFENDER KD-2201 И есть мышь, SVEN OP-15 (usb) ОП windows 7 Проблема в...

Клавиатура и мышь
Добрый вечер Ребята у меня такая проблема не знаю куда уже обратиться Собрал в декабре новый компьютер радости нет предела, но докучает...

3
Кормпилятор
 Аватар для Quiet Snow
5044 / 1718 / 409
Регистрация: 25.04.2010
Сообщений: 4,827
Записей в блоге: 2
24.01.2025, 07:12  [ТС]
+Джойстик


Добавлен джойстик, получение имени диска + соотв фиксы кода,
пофикшен баг с KeyPress в EXE, исправлены комментарии(было много неточностей).
Примерно в таком виде стоило выкладывать первый пост. Необходимо тестирование.

По настройке джойстика(в DOSBox-е) видео инструкция ТУТ.

Основная идея - донести до комьюнити этот функционал в целях быстрой адаптации уже готовых
прог и ускоренного их портирования на FreeBASIC. На ближайшее время это последний фикс.



QBasic/QuickBASIC
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
 '
 '  Базовый код создан через: Hex2Abs - v 0.1.2
 '  >Quiet Snow<  2011-2025г.
 '
 '
 '  При запуске через QuickBasic запускать QB.EXE с ключом /L
 '
 '
 
 
  ' Структура DTA для работы с диском
TYPE DataTransferArea
   DtaNoUse AS STRING * 21
   DtaAtrib AS STRING * 1
   DtaTime AS INTEGER
   DtaData AS INTEGER
   DtaFileSize AS LONG
   DtaFileName AS STRING * 13
END TYPE
 
 CONST CTMDbg = 0        '  Узнать кол-во данных для ABSOLUTE в CodeToMem
 
      '  Загрузка кода
 
 DECLARE SUB CodeToMem (CodSeg AS LONG, CodPtr AS LONG, NumLines AS INTEGER)
 
      '  Инициализация кода
 
 DECLARE SUB InitRoutines ()
 
      '  Работа с векторами
 
 DECLARE SUB SetIntVec (IntNum AS INTEGER, CSegm&, COffs&)
 DECLARE SUB RestoreVec (IntNum AS INTEGER)
 
      '  Работа с клавиатурой
 
 DECLARE SUB KeybActivate ()
 DECLARE SUB KeybClose ()
 DECLARE FUNCTION KeyPress% (KNum%)
 
      '  Работа с мышью
 
 DECLARE SUB MouUpdate ()
 DECLARE SUB MouBtCalc ()
 
      '  Работа с джойстиком
 
 DECLARE SUB GetJoy ()
 
      '  Работа с таймером
 
 DECLARE SUB TimerActivate (Hertz AS LONG)
 DECLARE SUB TimerClose ()
 DECLARE SUB Delay (Ms AS LONG)
 
      '  Сканирование текущей директории (DTA)
 
 DECLARE SUB SetMask (Mask AS STRING)
 DECLARE SUB ScanDir ()
 DECLARE FUNCTION GetMinNames ()
 DECLARE FUNCTION GetMaxNames ()
 DECLARE SUB GetCurDir ()
 DECLARE SUB GetCurDisk ()
 
 DECLARE FUNCTION GetNameByNum$ (Num AS INTEGER)
 DECLARE SUB PrintDirFixed (Num1 AS INTEGER, Num2 AS INTEGER, Sel AS INTEGER)
 
      '  Кастомный вывод символа
 
 DECLARE SUB Symb (x AS LONG, y AS LONG, s AS LONG, cv1 AS LONG, cv2 AS LONG)
 DECLARE SUB TWnd (x AS LONG, y AS LONG, x2 AS LONG, y2 AS LONG, Cv AS LONG)
 
 REM $DYNAMIC
 DIM SHARED Code1(472) AS INTEGER  '  Код и данные подпрограмм прерываний
 DIM SHARED Code2(18) AS INTEGER   '  Код подпрограммы клавиатуры
 DIM SHARED Code3(23) AS INTEGER   '  Код подпрограммы мыши
 DIM SHARED Code4(17) AS LONG      '  Код подпрограммы таймера
 
 DIM SHARED Code5(13) AS INTEGER   '  Получение адреса DTA
 DIM SHARED Code6(14) AS INTEGER   '  Установка адреса DTA
 DIM SHARED Code7(25) AS INTEGER   '  Нахождение первого вхождения
 DIM SHARED Code8(24) AS INTEGER   '  Нахождение следующего файла
 
 DIM SHARED Code9(10) AS INTEGER   '  Получить текущ. директорию
 
 DIM SHARED Code10(8) AS INTEGER   '  Получить текущ. диск
 
 '  Для работы пп векторов, мыши, клавиатуры и таймера
 DIM SHARED Kolic AS LONG          '  Кол-во байт в подпрограмме
 DIM SHARED MultiKey(127) AS INTEGER  '  Массив клавиш клавиатуры
 DIM SHARED OldK(127) AS INTEGER   '  Старые нажатия (форм сами)
 DIM SHARED CuMx AS LONG           '  Кастомные координаты курсора
 DIM SHARED CuMy AS LONG
 DIM SHARED MbO AS INTEGER         '  Старое значение кнопок мыши
 DIM SHARED Hz AS LONG             '  Герц
 
 '  Статус клика кн. мыши при отпускании
 DIM SHARED LClick AS INTEGER
 DIM SHARED CClick AS INTEGER
 DIM SHARED RClick AS INTEGER
 '  Статус клика кн. мыши при нажатии
 DIM SHARED LClickPr AS INTEGER
 DIM SHARED CClickPr AS INTEGER
 DIM SHARED RClickPr AS INTEGER
 
 
 DIM SHARED DTA AS DataTransferArea
 DIM SHARED MaskPath AS STRING * 64
 DIM SHARED InDirNames(30) AS STRING * 13
 DIM SHARED CurrDir AS STRING * 256
 DIM SHARED CurDir AS STRING       '  Текущая директория
 DIM SHARED OldDir AS STRING       '  Сохранить первоначальную папку
 DIM SHARED DirFNames AS STRING
 DIM SHARED QuaNames AS INTEGER
 
 '  Для джойстика
 DIM SHARED JUp AS INTEGER, JDn AS INTEGER
 DIM SHARED JLf AS INTEGER, JRg AS INTEGER
 DIM SHARED JTrian AS INTEGER, JSquar AS INTEGER
 DIM SHARED JRound AS INTEGER, JCross AS INTEGER
 DIM SHARED JL1 AS INTEGER, JL2 AS INTEGER
 DIM SHARED JR1 AS INTEGER, JR2 AS INTEGER
 
 
 '  Пользовательские массивы и переменные
 DIM FVib AS INTEGER, MinV AS INTEGER, MaxV AS INTEGER
 DIM Rdr AS INTEGER, Ferr AS INTEGER
 DIM i AS INTEGER
 DIM LClks AS INTEGER, CClks AS INTEGER, RClks AS INTEGER
 
 '  Инициализация
 
 InitRoutines
 
 '  Пользовательская программа
 CLS
 
 ScanDir                          '  Скан директории  [ INT 21h ]
 
 OldDir = CHR$(Code10(0)) + ":\" + CurDir
 MinV = GetMinNames
 MaxV = GetMaxNames
 FVib = MinV: Rdr = -1
 
 TWnd 0, 0, 79, 24, 1
 
 KeybActivate                     '  Включаем обработчик  [ INT 9 ]
 
 TimerActivate (1000)             '  1000 прерываний в секунду  [ INT 8 ]
 
 
 '  Тестовые задержки
 LOCATE 1
 FOR i = 112 TO 44 STEP -3
    Delay CLNG(i)
    LOCATE CSRLIN + 1, 2
    PRINT "  Delay"; i; "ms";
 NEXT: LOCATE 1
 FOR i = 46 TO 2 STEP -2
    Delay CLNG(i): LOCATE CSRLIN + 1, 40
    PRINT "  Delay"; i; "ms";
 NEXT
 
 Delay 800
 
 CLS
 
 LOCATE 16, 33
 TWnd 31, 14, 45, 22, 7
 PrintDirFixed 1, 7, FVib
 
 
  DO
     MouUpdate                    '  Берём параметры мыши  [ INT 51 ]
     MouBtCalc                    '  Калькуляция кликов
 
     GetJoy                       '  Опрашиваем джойстик
 
     '   Мышь
    
     LClks = LClks - LClickPr
     CClks = CClks - CClickPr
     RClks = RClks - RClickPr
    
     LOCATE 2, 1
     COLOR 15: PRINT "   Mouse": COLOR 7
     PRINT " Mx:"; Code3(3), "My:"; Code3(4), "  Delta", "dMx:"; Code3(0), "dMy:"; Code3(1)
     PRINT " Buttons:"; Code3(2); "  LClicks: "; LClks; "  CClicks: "; CClks; "  RClicks: "; RClks
     CuMx = CuMx + CLNG(Code3(0))
     CuMy = CuMy + CLNG(Code3(1))
 
     PRINT " Custom mouse position    Mx:"; CuMx, "My:"; CuMy
 
     '   Клавиатура
     LOCATE 7, 1
     COLOR 15: PRINT "   KeyBoard": COLOR 7
     FOR i = 0 TO 127
        PRINT MultiKey(i);
     NEXT
 
     '   Таймер
     LOCATE 14, 1
     COLOR 15: PRINT "   Timer": COLOR 7
     PRINT " Hertz:"; Hz;
     LOCATE , 17: PRINT "Time: "; TIME$
     PRINT " Incremental (Int 8):"; Code4(0)
     PRINT " QBasic Timer:"; TIMER
     PRINT
 
     '   Директории
 
     LOCATE 14, 30
     COLOR 15: PRINT "   Directories": COLOR 7
    
     IF Rdr AND -GetMinNames THEN
        LOCATE 16, 33
        PrintDirFixed FVib - 3, FVib + 3, FVib
       
        LOCATE 1, 1
        PRINT SPACE$(80);
        LOCATE 1, 1
        COLOR 8
        PRINT "DIR: "; CHR$(Code10(0)) + ":\" + CurDir
        COLOR 7
       
        Rdr = 0
     END IF
 
     '  Кнопки:  Вверх \ Вниз
     IF KeyPress(72) AND FVib > MinV THEN
       FVib = FVib - 1: Rdr = -1
     END IF
     IF KeyPress(80) AND FVib < MaxV THEN
       FVib = FVib + 1: Rdr = -1
     END IF
   
     '  Кнопка ENTER
     IF KeyPress(28) THEN
       
       '  Выбор текущей директории встроенной функцией
       ON ERROR GOTO DirErr: Ferr = 0
         CHDIR GetNameByNum$(FVib)
       ON ERROR GOTO 0
      
       '  Если нет ошибок(выбор произошёл)
       IF NOT Ferr THEN
         '  Сканируем заново
         ScanDir                          '  Скан директории  [ INT 21h ]
      
         '  Границы записей
         MinV = GetMinNames
         MaxV = GetMaxNames
         FVib = MinV
      
         '  Перерисовка
         LOCATE 16, 33
         PrintDirFixed 1, 7, FVib
         Rdr = -1
       END IF
     END IF
 
     '   Джойстик
 
     LOCATE 19, 1
     COLOR 15: PRINT "   Joystick": COLOR 7
 
     LOCATE 20, 2: IF JL1 THEN COLOR 10 ELSE COLOR 8
     PRINT "L1"
    
     LOCATE 20, 5: IF JL2 THEN COLOR 10 ELSE COLOR 8
     PRINT "L2"
    
     LOCATE 20, 11: IF JR1 THEN COLOR 10 ELSE COLOR 8
     PRINT "R1"
    
     LOCATE 20, 14: IF JR2 THEN COLOR 10 ELSE COLOR 8
     PRINT "R2"
    
     IF JLf THEN Symb 1, 21, 17, 10, 0 ELSE Symb 1, 21, 17, 8, 0
     IF JRg THEN Symb 5, 21, 16, 10, 0 ELSE Symb 5, 21, 16, 8, 0
     IF JUp THEN Symb 3, 20, 30, 10, 0 ELSE Symb 3, 20, 30, 8, 0
     IF JDn THEN Symb 3, 22, 31, 10, 0 ELSE Symb 3, 22, 31, 8, 0
    
     IF JSquar THEN Symb 10, 21, 254, 10, 0 ELSE Symb 10, 21, 254, 8, 0
     IF JRound THEN Symb 14, 21, 111, 10, 0 ELSE Symb 14, 21, 111, 8, 0
     IF JTrian THEN Symb 12, 20, 30, 10, 0 ELSE Symb 12, 20, 30, 8, 0
     IF JCross THEN Symb 12, 22, 120, 10, 0 ELSE Symb 12, 22, 120, 8, 0
 
 
  LOOP UNTIL MultiKey(1)
 
  TimerClose
  KeybClose
  CHDIR OldDir
 
END
 
DirErr: Ferr = -1
RESUME NEXT
 
     '  INLINE КОДЫ
     '  код работы с векторами
Asm1:
DATA 11112222333306505352572E8B3E20032E
DATA 8B1E22032E8B0E240333C02E8A8580020A
DATA C00F857003B801002E88858002FA33C08E
DATA C0C1E702268B152E89950000268B55022E
DATA 8995020026890D26895D02FB5F5A5B5807
DATA CB065053572E8B3E200333C02E8A858002
DATA 0AC00F84AD0333C02E88858002FA33C08E
DATA C0C1E7022E8B9D000026891D2E8B9D0200
DATA 26895D02FB5F5B5807CB
 
     '  код клавиатуры
 
Asm2: DATA 505306B811118EC033DBE460A880
DATA 7803BBFFFF257F0093D1E3268987222207
DATA 5BB020E62058CF
 
     '  код мыши
 
Asm3: DATA 0000000000000000000060B80B00
DATA CD332E890E00002E89160200B80300CD33
DATA 2E891E04002E890E06002E8916080061CB
 
     '  код таймера
 
Asm4: DATA 0000000011111111222222226650
DATA 1E0E1F2E66FF0600002E66A108002E6601
DATA 0604002E66813E0400FFFF000077081FB0
DATA 20E6206658CF2E66812E0400FFFF00001F
DATA 6658EA33333333
    
     '  Получение адреса DTA
 
Asm5: DATA 221144339C5053B8002FCD218CC0
DATA 2EA300002E891E02005B589DCB
 
     '  Установка адреса DTA
 
Asm6: DATA 221144339C50521E2EA100008ED8
DATA B8001A2E8B160200CD211F5A589DCB
 
     '  Нахождение первого вхождения
 
Asm7: DATA 2211443366559C5051521E33C02E
DATA A300002EA102008ED82E8B160400B8004E
DATA B93500F8CD2172072EC706000001001F5A
DATA 59589DCB
 
     '  Нахождение следующего файла
 
Asm8: DATA 2211443366559C50521E33C02EA3
DATA 00002EA102008ED82E8B160400B8004FB9
DATA 3500F8CD2172072EC706000001001F5A58
DATA 9DCB
 
     '  Получение текущей директории
 
Asm9: DATA 11112222601E0E1FC536999933D2
DATA B447CD211F61CB
 
     '  Получение текущего диска
 
Asm10: DATA 000050B80019CD210441982EA300
 DATA 0058CB
 
SUB CodeToMem (CodSeg AS LONG, CodPtr AS LONG, NumLines AS INTEGER)
DIM Lst AS INTEGER, Lba AS INTEGER
DIM Sc AS STRING, Pr AS INTEGER
DIM IntInMas AS LONG, LngInMas AS LONG
 Kolic = 0
    DEF SEG = CodSeg
 FOR Lst = 1 TO NumLines          'Грузим строки кода
     READ Sc
     FOR Lba = 1 TO LEN(Sc) STEP 2    'Преобразовываем в байты
       Pr = VAL("&H" + MID$(Sc, Lba, 2))
       POKE CodPtr + Kolic, Pr
       Kolic = Kolic + 1
     NEXT
 NEXT
 '  Рассчитать кол-во байт в массиве
 IntInMas = ((Kolic + (Kolic AND 1)) \ 2) - 1
 LngInMas = ((Kolic + (Kolic AND 3)) \ 4) - 1
 IF CTMDbg THEN
   PRINT "Integers upper bound in DIM:"; IntInMas; STRING$(9, 196),
   PRINT " Longs UB in DIM:"; LngInMas;
 END IF
    DEF SEG
END SUB
 
REM $STATIC
SUB Delay (Ms AS LONG)
   DIM TmStop AS LONG
   TmStop = Code4(0) + Ms
   WHILE Code4(0) < TmStop
   WEND
END SUB
 
SUB GetCurDir
  CurrDir = SPACE$(255)
  DEF SEG = VARSEG(Code9(0))
     CALL ABSOLUTE(VARPTR(Code9(0)) + 4)
  DEF SEG
  CurDir = LEFT$(CurrDir, INSTR(CurrDir, CHR$(0)) - 1)
END SUB
 
SUB GetCurDisk
  'Code10(0) = 0
  DEF SEG = VARSEG(Code10(0))
     CALL ABSOLUTE(VARPTR(Code10(0)) + 2)
  DEF SEG
END SUB
 
SUB GetJoy
   JL1 = STRIG(1)
   JL2 = STRIG(5)
   JR1 = STRIG(3)
   JR2 = STRIG(7)
 
   IF STICK(0) > 192 THEN
     JRg = -1
     JLf = 0
   ELSE
     JRg = 0
     IF STICK(0) < 64 THEN JLf = -1 ELSE JLf = 0
   END IF
 
   IF STICK(1) > 192 THEN
     JDn = -1
     JUp = 0
   ELSE
     JDn = 0
     IF STICK(1) < 64 THEN JUp = -1 ELSE JUp = 0
   END IF
 
   IF STICK(2) > 192 THEN
     JRound = -1
     JSquar = 0
   ELSE
     JRound = 0
     IF STICK(2) < 64 THEN JSquar = -1 ELSE JSquar = 0
   END IF
 
   IF STICK(3) > 192 THEN
     JCross = -1
     JTrian = 0
   ELSE
     JCross = 0
     IF STICK(3) < 64 THEN JTrian = -1 ELSE JTrian = 0
   END IF
END SUB
 
FUNCTION GetMaxNames
  GetMaxNames = QuaNames
END FUNCTION
 
FUNCTION GetMinNames
  IF QuaNames > 0 THEN
    GetMinNames = 1
  ELSE : GetMinNames = 0
  END IF
END FUNCTION
 
FUNCTION GetNameByNum$ (Num AS INTEGER)
DIM TName AS STRING
DIM OldFi AS INTEGER, Fi AS INTEGER, NumName AS INTEGER
OldFi = 1: NumName = 1
 
 DO
    Fi = INSTR(OldFi, DirFNames, CHR$(0))
    IF Num = NumName THEN
       TName = MID$(DirFNames, OldFi, Fi - OldFi)
       GetNameByNum$ = TName
       EXIT FUNCTION
    END IF
    OldFi = Fi + 1
    NumName = NumName + 1
 LOOP UNTIL Fi = 0
 
END FUNCTION
 
REM $DYNAMIC
SUB InitRoutines
DIM p AS INTEGER
 
CLS
 
   '   Код работы с векторами прерываний
   RESTORE Asm1
   CodeToMem VARSEG(Code1(400)), VARPTR(Code1(400)), 9
 
   '   Код работы с клавиатурой
   RESTORE Asm2
   CodeToMem VARSEG(Code2(0)), VARPTR(Code2(0)), 3
 
   '   Вставим в код динамичски меняющиеся сегмент и смещение
   DEF SEG = VARSEG(Code2(0))
     POKE VARPTR(Code2(0)) + 4, ASC(MKL$(VARSEG(MultiKey(0))))
     POKE VARPTR(Code2(0)) + 5, ASC(MID$(MKL$(VARSEG(MultiKey(0))), 2, 1))
     POKE VARPTR(Code2(0)) + 28, ASC(MKL$(VARPTR(MultiKey(0))))
     POKE VARPTR(Code2(0)) + 29, ASC(MID$(MKL$(VARPTR(MultiKey(0))), 2, 1))
   DEF SEG
 
   '   Код работы с мышью
   RESTORE Asm3
   CodeToMem VARSEG(Code3(0)), VARPTR(Code3(0)), 3
 
   '   Код работы с таймером (перехват с компенсацией)
   RESTORE Asm4
   CodeToMem VARSEG(Code4(0)), VARPTR(Code4(0)), 5
 
   DIM b1 AS INTEGER, b2 AS INTEGER, b3 AS INTEGER, b4 AS INTEGER
  
   DEF SEG = 0
     b1 = PEEK(4 * 8)            '  Смещение
     b2 = PEEK(4 * 8 + 1)        '  Смещение
     b3 = PEEK(4 * 8 + 2)        '  Сегмент
     b4 = PEEK(4 * 8 + 3)        '  Сегмент
   DEF SEG = VARSEG(Code4(0))
    '  Вставляем адрес старого вектора для JMP
    POKE VARPTR(Code4(0)) + Kolic - 4, b1
    POKE VARPTR(Code4(0)) + Kolic - 3, b2
    POKE VARPTR(Code4(0)) + Kolic - 2, b3
    POKE VARPTR(Code4(0)) + Kolic - 1, b4
  
   DEF SEG
 
   '  Коды работы с DTA (поиск файлов в папке)
   RESTORE Asm5
   CodeToMem VARSEG(Code5(0)), VARPTR(Code5(0)), 2
   RESTORE Asm6
   CodeToMem VARSEG(Code6(0)), VARPTR(Code6(0)), 2
   RESTORE Asm7
   CodeToMem VARSEG(Code7(0)), VARPTR(Code7(0)), 4
   RESTORE Asm8
   CodeToMem VARSEG(Code8(0)), VARPTR(Code8(0)), 4
 
   '  Получение текущей директории
   RESTORE Asm9
   CodeToMem VARSEG(Code9(0)), VARPTR(Code9(0)), 2
   DIM SegStAsm AS LONG, PtrStAsm AS LONG
  
   '  Получим см и сег строки на 64 символа
   SegStAsm = VARSEG(CurrDir)
   PtrStAsm = VARPTR(CurrDir)
  
   '  Скопируем память переменных в маш код
   DEF SEG = VARSEG(SegStAsm)
     b1 = PEEK(VARPTR(SegStAsm))            '  Сегмент LB
     b2 = PEEK(VARPTR(SegStAsm) + 1)        '  Сегмент HB
   DEF SEG = VARSEG(PtrStAsm)
     b3 = PEEK(VARPTR(PtrStAsm))            '  Смещение LB
     b4 = PEEK(VARPTR(PtrStAsm) + 1)        '  Смещение HB
   DEF SEG = VARSEG(Code9(0))
     POKE VARPTR(Code9(0)), b3
     POKE VARPTR(Code9(0)) + 1, b4
     POKE VARPTR(Code9(0)) + 2, b1
     POKE VARPTR(Code9(0)) + 3, b2
   DEF SEG
   '  Получим смещение на начало кода
   PtrStAsm = VARPTR(Code9(0))
   '  Получим байты этого смещения
   DEF SEG = VARSEG(PtrStAsm)
     b1 = PEEK(VARPTR(PtrStAsm))            '  Смещение LB
     b2 = PEEK(VARPTR(PtrStAsm) + 1)        '  Смещение HB
   '  Забьём байты в память (в непоср смещение инструкции LDS)
   DEF SEG = VARSEG(Code9(0))
      POKE VARPTR(Code9(0)) + 10, b1        '  Смещение LB
      POKE VARPTR(Code9(0)) + 11, b2        '  Смещение HB
   DEF SEG
 
   '  Получение текущего диска
   RESTORE Asm10
   CodeToMem VARSEG(Code10(0)), VARPTR(Code10(0)), 2
 
 
 SetMask "*.*"
 
 IF CTMDbg THEN SLEEP: END
 
END SUB
 
SUB KeybActivate
   SetIntVec 9, VARSEG(Code2(0)), VARPTR(Code2(0))
END SUB
 
SUB KeybClose
   RestoreVec 9
END SUB
 
REM $STATIC
FUNCTION KeyPress% (KNum%)
  IF MultiKey(KNum%) <> OldK(KNum%) THEN
     IF MultiKey(KNum%) THEN
        KeyPress% = -1
     ELSE
        KeyPress% = 0
     END IF
  END IF
  OldK(KNum%) = MultiKey(KNum%)
END FUNCTION
 
SUB MouBtCalc
   '  Клик отпускания
 IF ((MbO AND 1) IMP (Code3(2) AND 1)) = -2 THEN LClick = -1 ELSE LClick = 0
 IF ((MbO AND 2) IMP (Code3(2) AND 2)) = -3 THEN RClick = -1 ELSE RClick = 0
 IF ((MbO AND 4) IMP (Code3(2) AND 4)) = -5 THEN CClick = -1 ELSE CClick = 0
   '  Клик нажатия
 IF ((Code3(2) AND 1) IMP (MbO AND 1)) = -2 THEN LClickPr = -1 ELSE LClickPr = 0
 IF ((Code3(2) AND 2) IMP (MbO AND 2)) = -3 THEN RClickPr = -1 ELSE RClickPr = 0
 IF ((Code3(2) AND 4) IMP (MbO AND 4)) = -5 THEN CClickPr = -1 ELSE CClickPr = 0
END SUB
 
REM $DYNAMIC
SUB MouUpdate
   MbO = Code3(2)
   DEF SEG = VARSEG(Code3(0))
      CALL ABSOLUTE(VARPTR(Code3(0)) + 10)
   DEF SEG
END SUB
 
REM $STATIC
SUB PrintDirFixed (Num1 AS INTEGER, Num2 AS INTEGER, Sel AS INTEGER)
DIM TName AS STRING
DIM OldFi AS INTEGER, Fi AS INTEGER, NumName AS INTEGER
DIM N1 AS INTEGER, N2 AS INTEGER
DIM CrPosX AS INTEGER, CrLinY AS INTEGER
N1 = Num1: N2 = Num2
IF N1 < GetMinNames THEN N1 = GetMinNames
IF N2 > GetMaxNames THEN N2 = GetMaxNames
OldFi = 1: NumName = 1
CrPosX = POS(0): CrLinY = CSRLIN
 
  DO
    Fi = INSTR(OldFi, DirFNames, CHR$(0))
    IF NumName >= N1 THEN
        IF Sel = NumName THEN COLOR 15, 1 ELSE COLOR 7, 0
              IF NumName > N2 THEN EXIT DO
        TName = MID$(DirFNames, OldFi, Fi - OldFi)
        CrLinY = CSRLIN
        LOCATE , CrPosX
        PRINT SPACE$(13)
        LOCATE CrLinY, CrPosX
        PRINT TName
    END IF
    OldFi = Fi + 1
    NumName = NumName + 1
  LOOP UNTIL Fi = 0
  WHILE N2 < Num2
    LOCATE , CrPosX
    PRINT SPACE$(13)
    N2 = N2 + 1
  WEND
END SUB
 
REM $DYNAMIC
SUB RestoreVec (IntNum AS INTEGER)
 
  IF IntNum > 159 OR IntNum < 0 THEN EXIT SUB
  Code1(400) = IntNum
 
  DEF SEG = VARSEG(Code1(0))
     CALL ABSOLUTE(VARPTR(Code1(0)) + 886)
  DEF SEG
 
END SUB
 
REM $STATIC
SUB ScanDir
 DIM DTAOLDSeg%, DTAOLDPtr%
 DIM AddName AS STRING
 
  '  Узнаем текущий диск
  GetCurDisk
 
  '  Узнаем текущую директорию
  GetCurDir
 
  '  Вызываем функцию получения адреса DTA
  DEF SEG = VARSEG(Code5(0))
     CALL ABSOLUTE(VARPTR(Code5(2)))
 
     DTAOLDSeg% = Code5(0)   ' Сохраним указатель на DTA
     DTAOLDPtr% = Code5(1)
 
  '  Вызываем функцию установки адреса DTA
     Code6(0) = VARSEG(DTA)  ' Новый адрес
     Code6(1) = VARPTR(DTA)
  DEF SEG = VARSEG(Code6(0))
     CALL ABSOLUTE(VARPTR(Code6(2)))
 
  '  Поиск 1-го вхождения
 
  Code7(1) = VARSEG(MaskPath)  ' Адрес шаблона
  Code7(2) = VARPTR(MaskPath)
  QuaNames = 0
  DirFNames = ""
 
  DEF SEG = VARSEG(Code7(0))
     CALL ABSOLUTE(VARPTR(Code7(3)))
     '  Если вхождение найдено
     IF Code7(0) THEN
        AddName = LEFT$(DTA.DtaFileName, INSTR(DTA.DtaFileName, CHR$(0)))
        '  Если не 1 точка, тогда добавляем
        IF AddName <> ("." + CHR$(0)) THEN
          IF AddName = (".." + CHR$(0)) THEN
            IF CurDir <> "" THEN
              DirFNames = DirFNames + AddName
              QuaNames = QuaNames + 1
            END IF
          ELSE
            DirFNames = DirFNames + AddName
            QuaNames = QuaNames + 1
          END IF
        END IF
        DEF SEG = VARSEG(Code8(0))
        CALL ABSOLUTE(VARPTR(Code8(3)))
       
        IF Code8(0) THEN
          AddName = LEFT$(DTA.DtaFileName, INSTR(DTA.DtaFileName, CHR$(0)))
          IF AddName = (".." + CHR$(0)) THEN
            IF CurDir <> "" THEN
              DirFNames = DirFNames + AddName
              QuaNames = QuaNames + 1
            END IF
          ELSE
            DirFNames = DirFNames + AddName
            QuaNames = QuaNames + 1
          END IF
       
          DO   '  Ищем всё последующие вхождения
            CALL ABSOLUTE(VARPTR(Code8(3)))
            IF Code8(0) THEN
              QuaNames = QuaNames + 1
              'PRINT LEFT$(DTA.DtaFileName, INSTR(DTA.DtaFileName, CHR$(0)) - 1)
              DirFNames = DirFNames + LEFT$(DTA.DtaFileName, INSTR(DTA.DtaFileName, CHR$(0)))
            END IF
          LOOP UNTIL Code8(0) = 0
 
        END IF
       
     END IF
 
  '  Восстанавливаем адрес DTA
     Code6(0) = DTAOLDSeg%
     Code6(1) = DTAOLDPtr%
  DEF SEG = VARSEG(Code6(0))
     CALL ABSOLUTE(VARPTR(Code6(2)))
  DEF SEG
 
END SUB
 
REM $DYNAMIC
SUB SetIntVec (IntNum AS INTEGER, CSegm&, COffs&)
 
  IF IntNum > 159 OR IntNum < 0 THEN EXIT SUB
  Code1(400) = IntNum
 
  DEF SEG = VARSEG(Code1(0))
     POKE 802, ASC(MKL$(CSegm&))
     POKE 803, ASC(MID$(MKL$(CSegm&), 2, 1))
     POKE 804, ASC(MKL$(COffs&))
     POKE 805, ASC(MID$(MKL$(COffs&), 2, 1))
         CALL ABSOLUTE(VARPTR(Code1(0)) + 806)
  DEF SEG
 
END SUB
 
REM $STATIC
SUB SetMask (Mask AS STRING)
   MaskPath = Mask + CHR$(0)
END SUB
 
SUB Symb (x AS LONG, y AS LONG, s AS LONG, cv1 AS LONG, cv2 AS LONG)
  DIM Adr AS LONG
  Adr = 160 * y + x + x
  DEF SEG = &HB800
     POKE Adr, s
     POKE Adr + 1, cv1 + cv2 * 16
  DEF SEG
END SUB
 
REM $DYNAMIC
SUB TimerActivate (Hertz AS LONG)
 
 DIM Divisor AS LONG
 Divisor = 1193182 / Hertz         '  Частота такт генератора дел на циклы
 IF Divisor < 2 THEN Divisor = 2   '  Ограничители делителя
 IF Divisor > 65535 THEN Divisor = 65535
 Hz = 1193182 / Divisor            '  Реальная частота
 
 Code4(0) = 0: Code4(1) = 0        '  Обнулить счётчики
 
 DEF SEG = VARSEG(Code4(0))        '  Делитель в подпрограмму побайтово
    POKE VARPTR(Code4(0)) + 8, Divisor AND 255
    POKE VARPTR(Code4(0)) + 9, Divisor \ 256
    POKE VARPTR(Code4(0)) + 10, 0
    POKE VARPTR(Code4(0)) + 11, 0
 DEF SEG
 
     '  Установка прерывания на таймер
     SetIntVec 8, VARSEG(Code4(0)), VARPTR(Code4(0)) + 12
 
 '  Меняем скорость таймера(0 канал) согласно делителю
 OUT &H43, &H36                     '  Управляющий регистр
 OUT &H40, ASC(MKL$(Divisor))              '  Младший байт
 OUT &H40, ASC(MID$(MKL$(Divisor), 2, 1))  '  Старший байт
 
END SUB
 
REM $STATIC
SUB TimerClose
   '  Сбрасываем делитель в дефолт
   OUT &H43, &H36           '  Управляющий регистр
   OUT &H40, 0              '  Младший байт
   OUT &H40, 0              '  Старший байт
   RestoreVec 8
END SUB
 
SUB TWnd (x AS LONG, y AS LONG, x2 AS LONG, y2 AS LONG, Cv AS LONG)
DIM i AS LONG
DIM C1 AS LONG, C2 AS LONG
C1 = Cv AND 15: C2 = Cv \ 16
  IF (x2 - x > 0) AND (y2 - y > 0) THEN
    FOR i = x + 1 TO x2 - 1
       Symb i, y, 196, C1, C2
       Symb i, y2, 196, C1, C2
    NEXT
    FOR i = y + 1 TO y2 - 1
       Symb x, i, 179, C1, C2
       Symb x2, i, 179, C1, C2
    NEXT
    Symb x, y, 218, C1, C2    ' Лев верх
    Symb x2, y, 191, C1, C2   ' Прав верх
    Symb x, y2, 192, C1, C2   ' Лев низ
    Symb x2, y2, 217, C1, C2  ' Прав низ
  END IF
END SUB
P.S: Хендлер клавиатуры можно доработать, т.к. идёт полный перехват Int 9.
В принципе, когда нужен INKEY$, - его можно вырубать. И тем не менее...
0
Эксперт по электронике
6814 / 3239 / 337
Регистрация: 28.10.2011
Сообщений: 12,652
Записей в блоге: 7
24.01.2025, 17:31
Цитата Сообщение от Quiet Snow Посмотреть сообщение
Добавлен джойстик
USB-джойстик тоже работает? Или этот код только под DOS?
0
Кормпилятор
 Аватар для Quiet Snow
5044 / 1718 / 409
Регистрация: 25.04.2010
Сообщений: 4,827
Записей в блоге: 2
25.01.2025, 11:30  [ТС]
Цитата Сообщение от locm Посмотреть сообщение
USB-джойстик тоже работает? Или этот код только под DOS?
Это код преимущественно для эмуляторов DOSBox и виртуалок, куда уходят параметры
любого USB джойстика. На реальном железе это скорее всего не заработает, хотя если W98-XP
и стоит драйвер для джойстика - то через NTVDM может быть и заработает(позже проверю).
Но тут есть жирное "НО", увеличение скорости таймера возможно только под чистым DOS,
поэтому при запуске из под старых винд функционал таймера стоит закомментировать.

Добавлено через 6 минут
По сути железо не даст возможность ремаппить оси\кнопки джойстиков и собрать один из двух
как собственно это и сделал. Но возможно весь функционал таки удастся задействовать,
если подобрать параметры Stick() и Strig(), функционал ремаппинга можно запилить самостоятельно.
По сути джойстик довольно интересное устройство в плане какой-либо автоматизации,
показанный стоит в пределах 500-700 рублей и имеет на борту кучу кнопок.
Вообще писал этот код больше чтобы размять мозги, т.к. с DOS давно ушёл. Некоторые детали
еле вспомнил, пришлось лопатить SWAG.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
25.01.2025, 11:30
Помогаю со студенческими работами здесь

Мышь и клавиатура
Добрый вечер. Решил попробывать сделать Авто асист для игры Archeage, но что то не выходит. Обращаюсь к вам. Вот сам код: ;...

Не работает мышь и клавиатура
Доброй ночи! Ситуация следующая, удалил (scp virtual bus driver) и (hidguardian) перестала работать клавиатура и мышь, в биосе и на экране...

Мышь и клавиатура не отвечают
Как давно не помню появился збой, начала отключатся мышка(издавая при етом сигнал отключения\подключеня устройста) было ето достаточно...

Не работает клавиатура и мышь
Не работает клавиатура и мышь. Пробовал зайти с live cd и режима устранение ошибок - всё ок. Но вот с безопасного режима не работает....

Не работает клавиатура и мышь
Доброго времени, всем! Помогите пожалуйста, у меня проблема: на компе 2 ОС ХР и 7, на ХР все норм. работает, а захажу на 7 не работает...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Новые блоги и статьи
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru