/
piko.asm
2799 lines (2731 loc) · 54.2 KB
/
piko.asm
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
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
BITS 16
;***********
;BOOTLOADER
;***********
;constants instead of magic numbers
OS_SECTORS equ 0x20b ;size of OS in sectors, 2 is for int 13h (read)
RANDOM_BUFFER equ 0x1160
SEARCH_BUFFER equ 0x1161
REPLACE_BUFFER equ 0x1168
COPY_BUFFER equ 0x1170
jmp bootloader
;"help file" list of commands
db "Pikobrain v1.6", 0xd, 0xa
db "new, enter, back", 0xd, 0xa
db "time", 0xd, 0xa
db "memory [fi]", 0xd, 0xa
db "visible [fi][2h]", 0xd, 0xa
db "place [fi][4h][2h][]", 0xd, 0xa
db "write [fi]", 0xd, 0xa
db "edit [fi][2h]", 0xd, 0xa
db "delete [fi][2h]", 0xd, 0xa
db "link [fi][fi][2h]", 0xd, 0xa
db "copy [fi][2h]w[fo][fi]", 0xd, 0xa
db "jump [1h][fi][2h]w[fo][fi]", 0xd, 0xa
db "kalc [4h][4h][1h]", 0xd, 0xa
db "Kagain [4h][1h]", 0xd, 0xa
db "hex [4h]", 0xd, 0xa
db "xdex [5d]", 0xd, 0xa
db ".float [4h]", 0xd, 0xa
db "folder [fo]", 0xd, 0xa
db "search [str]", 0xd, 0xa
db "info", 0xd, 0xa
db "os", 0xd, 0xa
db "assembly [fi][2h]a[fi]", 0xd, 0xa
db "run [fi][2h]"
bootloader:
;set up registers
mov ax, 0x7c0
mov ds, ax ;data segment
mov ax, 0xa00
mov ss, ax ;stack segment
mov sp, 0x1000 ;stack pointer
;redirect ctrl+break handler
xor ax, ax
mov es, ax
mov bx, 0x6c ;location in Interrup Vector Table
mov word [es:bx], CTRL_BREAK ;location of handler in code
add bx, 2h
mov word [es:bx], 0x1000
;read OS files into RAM
mov ax, 0x1000
mov es, ax
xor bx, bx
mov ax, OS_SECTORS ;files to read
mov cx, 1h
mov dh, 0h ;dl set at boot
int 13h
cmp ah, 0h ;if error stop
jne $
;check if install has been made
mov bx, 0x1fd ;location of variable
cmp byte [es:bx], 0h ;if installed: jump to OS
jne jmppb
mov byte [es:bx], 1h ;else: mark as installed, and install
;set destination drive for install
shr dl, 7h
or dl, 0x80 ;0->80, 80->81 bitwise math
;write files to hard drive
xor bx, bx
mov ah, 3h ;use same values as previous int 13h
int 13h
cmp ah, 0h ;if error stop
jne $
jmppb:
jmp 0x1000:0x0200 ;jump to Pikobrain main
;fill up space
times 506-($-$$) db 0h
;folder number
db 0h ;upper 2 bits cl -- track
dw 0h ;0x1000:last_byte
db 0h ;0=installation=false, 1=installation=true
dw 0xaa55
;**********
;PIKOBRAIN
;**********
;setup copy buffer
mov ax, COPY_BUFFER
mov es, ax
xor bx, bx
mov byte [es:bx], 0h
callnew:
call new ;call function, jump to main loop
jmp input ;-->
new:
;clear screen
pusha
;set graphics mode
mov ax, 3h ;80x25 16 color text
int 10h
;popa ;UNCOMMENT
;ret ;FOR QEMU
;set color and clear screen
mov ax, 0x600
mov bh, 0x3e ;cyan-yellow <-- change this value to change colors in Pikobrain
xor cx, cx
mov dx, 0x184f ;size of screen 25x80
int 10h
popa
ret
;**********
;FUNCTIONS
;**********
;common functions
;some used as macros in pikoasm
callenter:
call enter
jmp input
enter:
;print enter char
mov ax, 0xe0d
int 10h
mov al, 0xa
int 10h
ret
readfile:
;reads one file
mov ax, 0x1200
mov es, ax
xor bx, bx
call filenum ;number of file
call setfolder
mov ax, 0x201 ;read one file
int 13h
ret
readfiles:
;read multiple files
mov ax, 0x1200
mov es, ax
xor bx, bx
readfiles2: ;used by link
push bx
call filenum ;first file
push cx ;store number
call filenum ;number of files
mov bl, cl ;store for al
pop cx
call setfolder
mov al, bl
mov ah, 2h
pop bx
int 13h ;read
ret
xtox:
;output ch as 2 digit hex number
mov al, ch
and al, 0xf ;clear upper nibble, to get second digit only
call xtoasc
mov ah, al ;store
mov al, ch
shr al, 4h ;get upper nibble, to get first digit only
call xtoasc
mov ch, ah ;store
;output two numbers
mov ah, 0xe
int 10h
mov al, ch
int 10h
ret
;the next two convert between ascii-chars and numerical values
;such as F=46h <-> 0xf
atohex:
;ascii-hex to hex
sub al, 30h
cmp al, 9h
jle athback
sub al, 7h ;if letter
athback:
ret
xtoasc:
;hex to ascii-hex
add al, 30h
cmp al, 39h
jle xtaback
add al, 7h ;if letter
xtaback:
ret
filenum:
;get 2 digit hex num input
;converts and into cl
mov ah, 0h
int 16h
cmp al, 0x8 ;backspace = cancel
je filenquit
mov ah, 0xe ;output
int 10h
call atohex
mov cl, al
shl cl, 4h ;*16, store in upper nibble
mov ah, 0h
int 16h
cmp al, 0x8 ;backspace = cancel
je filenquit
mov ah, 0xe
int 10h
call atohex
add cl, al ;lower nibble
ret
filenquit:
;exit writing, clear stack, go to input
mov sp, 0x1000
jmp input ;if a pikoasm program gets here it will terminate
setfolder:
;set folder to current folder number, for int 13h
;folder number stored in the end of the bootloader code
and cl, 0x3f ;clear upper bits, cl is file number
mov ax, 0x1000
mov fs, ax
mov si, 0x1fa ;folder number location
mov al, [fs:si]
shl al, 6h ;into right position
add cl, al
inc si
mov dh, [fs:si] ;set values
inc si
mov ch, [fs:si]
mov dl, 0x80
ret
callfolder:
call folder
jmp input
folder:
;change (head and track i.e.) folder number
;dh and ch (cl) for int 13h
mov ax, 0x1000
mov fs, ax
mov si, 0x1fc ;last number in folder number
call filenum
cmp cl, 0x69 ;double press tab to select current folder
je fsame
cmp cl, 0x44 ;double semi-colon to only enter last two digits
je flast
cmp cl, 0x41 ;double press h to select home folder (000000)
je fhome
and cl, 3h ;clear bits
push cx
call filenum
push cx
call filenum ;i.e. 6 digits total
;write values, to change folder number
mov [fs:si], cl
dec si
pop cx
mov [fs:si], cl
dec si
pop cx
mov [fs:si], cl
ret
fhome:
;set folder number to 000000
dec si
mov word [fs:si], 0h
dec si
mov byte [fs:si], 0h
ret
flast:
;only change last two digits of folder number
call filenum
mov [fs:si], cl
fsame: ;use current folder number
ret
random:
;random number generator
push cx ;store for assembly macros
push dx
mov ah, 0h ;get tick
int 1ah
mov ax, RANDOM_BUFFER
mov fs, ax
xor si, si
mov ax, [fs:si]
sub ah, dl ;update number = generate
sub al, ah ;al is random number returned
rol ax, 1h
mov [fs:si], ax ;store
pop dx
pop cx
ret
sget:
;get string input
mov ax, SEARCH_BUFFER
mov gs, ax
xor di, di ;gs:di search word
sword:
;get char
mov ah, 0h
int 16h
cmp ah, 0x3b ;f1, quit writing, for use of old string input
je ssend
cmp al, 8h ;backspace
jne swordcon
dec di
mov ah, 0xe ;print backspace
int 10h
mov ax, 0xa20 ;space
int 10h
jmp sword
swordcon:
mov [gs:di], al ;store char in buffer
;if enter: end
cmp al, 0xd ;if enter, end writing
je ssend
;output
mov ah, 0xe ;output char
int 10h
inc di
jmp sword
ssend:
xor di, di
ret
;******
;INPUT
;******
;main loop
input:
;get commands
mov ah, 0h
int 16h
mov bh, 0h ;graphics reason
cmp al, 0x6e ;n
je callnew
cmp al, 0xd ;enter
je callenter
cmp al, 0x62 ;b
je callback
cmp al, 0x74 ;t
je time
cmp al, 0x6d ;m
je memory
cmp al, 0x76 ;v
je visible
cmp al, 0x70 ;p
je place
cmp al, 0x77 ;w
je write
cmp al, 0x65 ;e
je edit
cmp al, 0x64 ;d
je delete
cmp al, 0x6c ;l
je link
cmp al, 0x63 ;c
je copystart
cmp al, 0x6a ;j
je jump
cmp al, 0x6b ;k
je kalc
cmp al, 0x4b ;K
je kagain
cmp al, 0x68 ;h
je hex
cmp al, 0x78 ;x
je xdec
cmp al, 0x2e ;.
je real
cmp al, 0x66 ;f
je callfolder
cmp al, 0x69 ;i
je info
cmp al, 0x73 ;s
je search
cmp al, 0x6f ;o
je os
cmp al, 0x61 ;a
je assembly
cmp al, 0x72 ;r
je run
;else check arrows
arrow:
mov al, ah
;get cursor location
mov ah, 3h
int 10h
cmp al, 0x48 ;up
je arrowup
cmp al, 0x50 ;down
je arrowdown
cmp al, 0x4b ;left
je arrowleft
cmp al, 0x4d ;right
je arrowright
jmp input
arrowup:
dec dh
jmp arrowend
arrowdown:
inc dh
jmp arrowend
arrowleft:
dec dl
jmp arrowend
arrowright:
inc dl
arrowend:
mov ah, 2h ;update cursor
int 10h
jmp input
callback:
call back
jmp input
back:
;move cursor to top left
mov ah, 2h
xor dx, dx
int 10h
ret
;*********
;COMMANDS
;*********
;'programs'
time:
;get date
;convert to decimal
mov ah, 4h
int 1ah
call xtox
mov ch, cl
call xtox
mov al, 0x2f ;/
int 10h
mov ch, dh
call xtox
mov al, 0x2f ;/
int 10h
mov ch, dl
call xtox
mov al, 0x20 ;space
int 10h
;get time
;convert to decimal
mov ah, 2h
int 1ah
call xtox
mov al, 0x3a ;:
int 10h
mov ch, cl
call xtox
mov al, 0x3a ;:
int 10h
mov ch, dh
call xtox
jmp input
memory:
;read file in hex and ascii
call readfile
mov dl, 0h ;due to visible, show that m command running, not v
menter:
mov dh, 0h ;column counter
call enter
mov ch, bl ;print row index
call xtox
mov al, 0x3a ;:
int 10h
mbyte:
mov ch, [es:bx] ;get content of byte
cmp ch, dl ;if value == <visible command value> or 0h when m command
je mvisible
call xtox ;else output as hex
mcon:
mov al, 0x20 ;space
int 10h
inc bx
inc dh
cmp dh, 0x10 ;width of content
jne mbyte
;output row as ascii
mov si, bx
sub bx, 0x10
mascii:
mov al, [es:bx]
;check if special char
cmp al, 0x1f
ja macon
mov al, 0x2a ;*
macon:
int 10h ;write char
inc bx
cmp bx, si ;end of row
jne mascii
cmp bx, 0x100 ;press key after half is shown; screen too small
je mhalf
cmp bx, 0x200 ;reading 512 bytes
je input
jmp menter
mhalf:
mov ah, 0h
int 16h
jmp menter
mvisible:
mov al, 0x2e ;.. to mark v command value
int 10h
int 10h
jmp mcon
visible:
;highlight opcode in memory
call readfile
call filenum ;get opcode
mov dl, cl ;store opcode
call menter
place:
;write byte to certain location(s)
call readfile
push cx ;save file number
;get two bytes for location
call filenum
mov bh, cl
call filenum
mov bl, cl ;store in bx
ploop:
call enter
mov ch, [es:bx] ;output current value
call xtox
call filenum ;get value to place
mov [es:bx], cl ;place
inc bx
mov ah, 0h
int 16h
cmp al, 0xd ;if enter: write more
je ploop
;else save updated file
xor bx, bx
pop cx
call setfolder
mov ax, 0x301
int 13h
jmp input
read:
;OK the text editor is a mess so I'll list what registers are used for
;ax = general purpose
;bx = general purpose if necessary; bh=0h (1st screen) whenever video interrupts are used
;cx = general purpose ;is pushed as it stores the file number
;dx = stores cursor location
;si = index of the character in top left, needed for scrolling
;di = index of current character the cursor is located on
;es:di holds the actual text
;fs: holds copy buffer
;gs: holds search buffer
;first the file is read and written to the screen
;when a char is typed:
;the screen is rewritten from the cursor forward
;when a special function is used:
;various levels of (if any) rewriting of the screen takes place
;read file as ASCII chars
;de facto part of text editor
call readfiles
rlink: ;used by wlink
mov bl, al ;al=number of files
shl bx, 9h ;*200h-> buffer size in bytes
mov byte [es:bx], 0h ;mark end of buffer, due to full files
rstart: ;used by wdel, wgoto
mov ax, RANDOM_BUFFER
mov gs, ax ;gs:di used as cmp buffer for wfind
mov di, 2h ;placing it somewhere else for now
mov byte [gs:di], 0h
readstart: ;used by wfind
xor bx, bx
xor si, si ;si always stores the index of the first char on the screen i.e. top left
call new ;due to text editor
readstart2: ;used by wfnext, doesn't clear screen
push cx ;store file number
nextread:
mov al, [es:bx] ;get char
cmp al, 0xd ;newline
je readsi
readcon:
cmp al, 0h ;end of file
je readend
mov ah, 0xe ;print char
int 10h
inc bx
cmp byte [gs:di], 0x2a ;* for text editor find any char (joker)
je readeq
cmp al, [gs:di] ;equal chars
je readeq
xor di, di
jmp nextread
readeq:
;for wfind
;chars are equal
inc di
cmp byte [gs:di], 0xd ;if string found
jne nextread
readend:
pop cx ;file number
ret
;si stuff for editor
readsi: ;si stores location of first char on screen (in text editor)
;si to next line
push ax
push bx
mov bh, 0h
mov ah, 3h ;get cusor position
int 10h
pop bx
pop ax
cmp dh, 0x18 ;bottom row
jne rsiend
call rsiloop
rsiend:
jmp readcon
rsiloop:
;move si to next line
inc si
cmp byte [es:si], 0xa ;newline
jne rsiloop
inc si
ret
rbacksi:
;si to previous line
sub si, 2h ;skip newline
rbsiloop:
dec si
cmp si, 1h
jle rbsiend
cmp byte [es:si], 0xa ;newline
jne rbsiloop
inc si
ret
rbsiend:
xor si, si
ret
;TEXT EDITOR
write:
mov ax, 0x1200
mov es, ax
call filenum ;get file number
push cx ;store for save
call new
xor si, si ;for scrolling
xor bx, bx ;pointer
wedit: ;for edit
mov byte [es:bx], 0h ;mark last char
mov di, bx ;index of cursor char
mov ax, COPY_BUFFER
mov fs, ax
typechar: ;main editor loop
call wtype
jmp wgetchar
wtype:
;update screen from location of cursor
push di
mov bh, 0h ;i hate that bh must be 0, else bugs
mov ah, 3h ;get cursor
int 10h
push dx
typeloop:
;write char or fill line if newline
mov ah, 0xe
mov al, [es:di]
cmp al, 0h ;end of file
je typend
cmp al, 0xd ;enter
je typelinestart
cmp al, 0xa ;don't output
je typecont
int 10h ;output char
typecont:
inc di
jmp typeloop
typend:
call typeline ;clear two lines
call typeline ;..due to backspace on newline
typend2: ;used by typelinestart
pop dx
mov ah, 2h ;reset cursor
int 10h
pop di
ret
typelinestart:
call typeline
cmp dh, 0x18
je typend2
jmp typecont
typeline:
;fill rest of line with spaces
mov ah, 3h
int 10h
mov cx, 0x50 ;width of screen (ch=0)
sub cl, dl ;number of spaces to fill line with
je typeret ;if cl=0 don't write
mov ax, 0xa20
int 10h
cmp dh, 0x18 ;if last line
je typeret
call enter
typeret:
ret
wgetchar:
mov bh, 0h
;get cursor location for dx, used by some special keys
mov ah, 3h
int 10h
;get char to write
mov ah, 0h
int 16h
;special keys
cmp al, 0x8 ;backspace
je backspace
cmp ah, 0x4b ;left arrow
je wleft
cmp ah, 0x4d ;right arrow
je wright
cmp ah, 0x50 ;down arrow
je wdown
cmp ah, 0x48 ;up arrow
je wup
cmp al, 0x9 ;tab (circle)
je wcallcopy
cmp ah, 0xf ;shifted tab (cut)
je wcallcopy
cmp al, 0x7c ;| paste
je wpaste
cmp ah, 0x49 ;page up
je wpgup
cmp ah, 0x51 ;page down
je wpgdown
cmp ah, 0x52 ;ins
je wins
cmp ah, 0x53 ;del
je wdel
cmp ah, 0x47 ;home
je whome
cmp ah, 0x4f ;end
je wend
cmp al, 0xd ;enter
je wenter
cmp ah, 0x3b ;f1
je wfind
cmp ah, 0x3c ;f2
je wfnext
cmp ah, 0x3d ;f3
je wreplace
cmp ah, 0x3e ;f4
je save
cmp ah, 0x3f ;f5
je wspace
cmp ah, 0x40 ;f6
je wgoto
cmp ah, 0x41 ;f7
je wlink
;output character typed
mov ah, 0xe
int 10h
cmp al, 0x60 ;` save
je save
cmp al, 0x1b ;esc cancel
je savend
cmp al, 0x5c ;\ special char
je wspecial
cmp al, 0x7e ;~ char count
je wchar
call wloopstart ;add char to buffer
jmp typechar
wloopstart:
mov bx, di ;pointer
wloop:
;add char to buffer
mov ah, [es:bx] ;get current char
mov [es:bx], al ;place new char (the typed one)
mov al, ah ;store the old char as the "new char"
inc bx
cmp al, 0h ;check if file end
jne wloop
wloopend:
inc di ;update di
mov byte [es:bx], 0h ;show end of file
ret
wleft:
;move cursor one step left
cmp dx, 0h ;if top left of screen do nothing
je wgetchar
dec di
cmp dl, 0h ;beginning of line
je wleftnl
mov ax, 0xe08 ;backspace
int 10h
jmp wgetchar
wleftnl:
;move cursor to previous line due to newline
mov ah, 2h
dec dh
mov dl, 0x4f ;end of line
int 10h
cmp byte [es:di], 0xa ;newline
jne wgetchar
dec di
jmp wbnloop
wright:
;move cursor one step right
cmp byte [es:di], 0h ;end of file
je wgetchar
call wright2
jmp wgetchar
wright2:
;get cursor location
mov ah, 3h ;due to wend
int 10h
cmp byte [es:di], 0xd ;if newline
je wrightnl
inc di
;else simply move cursor right
mov ah, 2h
inc dl
int 10h
ret
wrightnl:
cmp dh, 0x18 ;if last line do nothing; we don't want to scroll
je wrightend
add di, 2h ;go past 0xa
;move cursor to start of next line
mov ah, 2h
inc dh
mov dl, 0h
int 10h
wrightend:
ret
backspace:
cmp di, 0h ;if start of file: do nothing
je wgetchar
cmp dx, 0h ;if top left of screen: do nothing
je wgetchar
mov ax, 0xe08 ;backspace
int 10h
dec di
mov ch, [es:di] ;must store for cmp later
call wbloopstart ;remove char from buffer
cmp dl, 0h ;are we removing a newline?
je wbnl
wbauto:
;else just erase char
mov bh, 0h
mov cx, 1h ;only one char
mov ax, 0xa20 ;for backspace newline
int 10h
jmp typechar
wbnl:
;move cursor to previous line
mov bh, 0h
mov ah, 2h
dec dh
mov dl, 0x4f ;79 end of row
int 10h
cmp ch, 0xa ;was stored, check if newline
jne wbauto ;this causes a bug if removed
;remove newline
dec di
call wbloopstart
wbnloop:
;move left until we find text; due to this a line can not end with a space
;get cursor char
mov bh, 0h
mov ah, 8h
int 10h
cmp al, 0x20 ;space apparently
jne wbnlend
;get cursor position
mov ah, 3h
int 10h
cmp dl, 0h ;beginning of line
je typechar
;mov cursor left
dec ah ;2h
dec dl
int 10h
jmp wbnloop
wbnlend:
;cursor right
mov ah, 2h
inc dl
int 10h
jmp typechar
wbloopstart:
mov bx, di
wbloop:
;erase character from buffer
inc bx
mov al, [es:bx] ;get next character
dec bx
mov [es:bx], al ;move it to current byte
cmp al, 0h ;check if file end
je wbloopend
inc bx ;go to next byte
jmp wbloop
wbloopend:
ret
wup:
;arrow up, move to end of previous line
mov bl, dl ;bh = 0
sub di, bx ;move di to start of line
mov ah, 2h
mov dl, 0h ;move cursor to start of line
int 10h
jmp wleft
wdown:
;arrow down, move to end of next line
mov al, [es:di]
cmp al, 0xd ;search for newline
je wdown2
cmp al, 0h ;end of file
je wgetchar
call wright2
jmp wdown
wdown2:
;when newline found, go to end of that line
call wright2
mov al, [es:di]
cmp al, 0xd ;newline
je wgetchar
cmp al, 0h ;end of file
je wgetchar
jmp wdown2
wenter:
;handles the writing of enter
call wloopstart ;insert al=0xd into buffer
;di already increased
mov bh, 0h
call typeline
mov al, 0xa
call wloopstart
cmp dh, 0x18 ;bottom row
jne typechar
mov ax, 0xe0d ;print enter, else bug on last row
int 10h
mov al, 0xa
int 10h
call rsiloop ;si to next line
jmp typechar
wpgup:
;scroll page up
cmp si, 0h ;if already at top: do nothing
je wgetchar
call rbacksi ;si to previous line
call wpg
inc dh
int 10h ;update cursor
jmp wgetchar
wpgdown:
;scroll page down
call rsiloop ;si to next line
call wpg
dec dh
int 10h ;update cursor
jmp wgetchar