-
Notifications
You must be signed in to change notification settings - Fork 0
/
royale.asm
1546 lines (1151 loc) · 27.3 KB
/
royale.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
.486 ; omg trigo and stuff (80486 preprocessor)
IDEAL
MODEL compact
STACK 100h
jumps
SEGMENT data1
; --------------------------
; Your variables here
; --------------------------
SCREENWIDTH dw 320 ; screen width constant
; SCREENHEIGHT dw 200 ; screen height constant
HALFSCREENWIDTH dw 160 ; half of the screen width constant
; HALFSCREENHEIGHT dw 100 ; half of the screen height constant
HALFSCREENWIDTHd dd 160 ; half of the screen width constant
; HALFSCREENHEIGHTd dd 100 ; half of the screen height constant
playerX dd ? ; player X position on screen
playerY dd ? ; player Y position on screen
dirX dd ? ; player X direction vector
dirY dd ? ; player Y direction vector
Vx dd ? ; player X direction velocity
Vy dd ? ; player Y direction velocity
mapEditorMode db 0 ; 0 or 1- indicating if user is in map editing mode
; STRING db '0', '0', '0', '0', '$' ; DELETEEEEEEEEEEEEEEEEEEEEEEEE
playerColor db 5 ; the player's color (originally 2)
dirColor db 6 ; the player's direction color (originally 0Ch)
wallColor db 1 ; the wall's color in bmp file, for collision
backgroundColor db 0 ; the background's color in bmp file, for cheking for collision
playerWallColor db 7 ; player's placed walls color in bmp file, for collision
randomColor db 42
; sizeOfDir dw 20
; ----------- IMAGE LOAD -----------
filename db 'maze.bmp', 0 ;
filehandle dw ? ;
Header db 54 dup (0) ;
Palette db 256*4 dup (0) ;
ScrLine db 320 dup (0) ;
ErrorMsg db 'Error', 13, 10 ,'$';
; ----------- IMAGE LOAD -----------
; TRIGO
temp db ?
tempW dw ?
tempD dd ?
tempD2 dd ?
res dd 4 ; casting resolution (size of rects)
V dd 1 ; player velocity
FOV dd 60 ; player's field of view
alpha dd ? ; current ray's angle
rayX dd ? ; current ray's x direction
rayY dd ? ; current ray's y direction
rayTipX dd ? ; current ray's x tip
rayTipY dd ? ; current ray's y tip
distance dd ? ; current ray's tip distance from player
height dd ? ; current ray's rectangle's height
X dd 0 ; yuval's variable (POG)
R dd 10 ; rotation radius
angle dd 0 ; player direction angle
rotSen dd 1 ; rotation sensitivity
SCREENWIDTHd dd 320 ; screen width constant
SCREENHEIGHTd dd 200 ; screen height constant
degrad dd ? ; degree to radian: pi / 180 (1 degree in radians)
__1 dd -1
_0 dd 0
_1 dd 1
_2 dd 2
_100 dd 100
_160 dd 160
_180 dd 180
_360 dd 360
ENDS data1
SEGMENT boardSeg
board db 64000 dup (?)
ENDS boardSeg
CODESEG
assume ds:data1
; ================================================================================
; = IMAGE LOAD =
; ================================================================================
proc OpenFile
; Open file
mov ah, 3Dh
xor al, al
; mov dx, offset filename
int 21h
jc openerror
mov [filehandle], ax
ret
openerror:
mov dx, offset ErrorMsg
mov ah, 9h
int 21h
ret
endp OpenFile
proc ReadHeader
; Read BMP file header, 54 bytes
mov ah,3fh
mov bx, [filehandle]
mov cx,54
mov dx,offset Header
int 21h
ret
endp ReadHeader
proc ReadPalette
; Read BMP file color palette, 256 colors * 4 bytes (400h)
mov ah,3fh
mov cx,400h
mov dx,offset Palette
int 21h
ret
endp ReadPalette
proc CopyPal
; Copy the colors palette to the video memory
; The number of the first color should be sent to port 3C8h
; The palette is sent to port 3C9h
mov si,offset Palette
mov cx,256
mov dx,3C8h
mov al,0
; Copy starting color to port 3C8h
out dx,al
; Copy palette itself to port 3C9h
inc dx
PalLoop:
; Note: Colors in a BMP file are saved as BGR values rather than RGB .
mov al,[si+2] ; Get red value .
shr al,2 ; Max. is 255, but video palette maximal
; value is 63. Therefore dividing by 4.
out dx,al ; Send it .
mov al,[si+1] ; Get green value .
shr al,2
out dx,al ; Send it .
mov al,[si] ; Get blue value .
shr al,2
out dx,al ; Send it .
add si,4 ; Point to next color .
; (There is a null chr. after every color.)
loop PalLoop
ret
endp CopyPal
proc CopyBitmap
; BMP graphics are saved upside-down .
; Read the graphic line by line (200 lines in VGA format),
; displaying the lines from bottom to top.
push ds
mov ax, boardSeg
mov ds, ax
; mov ax, ds
mov es, ax
mov cx, 199
mov di, offset board
add di, 200*320
pop ds
PrintBMPLoop:
push cx
; di = offset board + cx*320, point to the correct board line
sub di, 320
; Read one line
mov ah, 3fh
mov cx, 320
mov dx, offset ScrLine
int 21h
; Copy one line into video memory
cld ; Clear direction flag, for movsb
mov cx, 320
mov si, offset ScrLine
push di
rep movsb ; Copy line to the screen
;rep movsb is same as the following code :
;mov es:di, ds:si
;inc si
;inc di
;dec cx
;loop until cx=0
pop di
pop cx
loop PrintBMPLoop
ret
endp CopyBitmap
proc loadImage
; Process BMP file, load it into [board]
; ds:dx = filename pointer
call OpenFile
call ReadHeader
call ReadPalette
call CopyPal
call CopyBitmap
ret
endp loadImage
proc drawBoard
pusha
; draw [board]
; copy [board] to video memory
push ds
mov ax, boardSeg
mov ds, ax
mov ax, 0A000h ; ex = video memory start
mov es, ax
mov di, 0
mov si, offset board
mov cx, 320*200
cld
rep movsb ; mov es:di, ds:si
pop ds
popa
ret
endp drawBoard
; ================================================================================
; = IMAGE LOAD =
; ================================================================================
proc rayCast
; omg literally raycasting in x86 assembly omg WOW.
; initiallize alpha, alpha = angle + (fov / 2)
fild [FOV]
fidiv [_2]
fiadd [angle]
; convert alpha to radians (alpha = pi/180 * alpha)
fmul [degrad]
fstp [alpha] ; store in alpha
; reset X (we spent about 6 hours figuring that out)
xor [X], [X]
; loop screenWidth / res times
fild [SCREENWIDTHd]
fidiv [res]
fistp [tempD]
; start ray casting loop! (omg so cool OwO)
mov cx, [word ptr tempD]
rayLoop:
push cx
; init ray direction tips
; rayTipX = playerX
fld [playerX]
fstp [rayTipX]
; rayTipY = playerY
fld [playerY]
fstp [rayTipY]
; init ray's direction
; rayX = sin(alpha)
fld [alpha]
fsin
fstp [rayX]
; rayY = cos(alpha)
fld [alpha]
fcos
fstp [rayY]
rayForwardLoop:
; move ray forward until collision
; move ray forward
fld [rayTipX]
fadd [rayX]
fstp [rayTipX]
fld [rayTipY]
fadd [rayY]
fstp [rayTipY]
; draw pixel (only if editor mode is enabled)
mov al, [mapEditorMode] ; if editor mode is disabled, dont draw pixels
cmp al, 0
je continueRayCast_
mov al, [dirColor] ; color
mov bh, 0
fld [rayTipX]
fistp [tempD]
mov cx, [word ptr tempD] ; X
fld [rayTipY]
fistp [tempD]
mov dx, [word ptr tempD] ; Y
mov ah, 0Ch ; DRAW PIXEL
int 10h
continueRayCast_:
; CHECK FOR COLLISION
fld [rayTipY] ; Y
fistp [tempD]
fild [tempD]
fimul [SCREENWIDTHd]
fadd [rayTipX] ; X
fistp [tempD]
mov bx, [word ptr tempD]
push ds
mov ax, boardSeg
mov ds, ax
mov di, offset board
mov al, [di + bx] ; al = color in board, in player's position
pop ds
cmp al, [backgroundColor]
je rayForwardLoop
; ray has hit wall!
; if editor mode is disabled, draw rect. if not, skip next code
mov al, [mapEditorMode] ; if editor mode is disabled, dont draw pixels
cmp al, 0
jne continueRayLoop
; calculate distance
; distance = sqrt((playerX - rayTipX)² + (playerY - PlayerTipY)²) * cos(alpha - angle)
fld [rayTipX]
fsub [playerX]
fst [tempD]
fmul [tempD]
fstp [distance] ; TEMPORARILY! Distance is not complete yet.
fld [rayTipY]
fsub [playerY]
fst [tempD]
fmul [tempD]
fadd [distance]
fsqrt
; fmul [rayY] ; rayY = cos(alpha)
fstp [distance]
fild [angle]
fmul [degrad]
fsub [alpha]
fcos
; fabs
fmul [distance]
fstp [distance]
; calculate height
; height = (some big num) / distance
fild [_180]
fimul [_2]
fimul [_2]
fimul [_2]
fdiv [distance]
fstp [height]
; limit height to screenHeight)
fld [height]
fimul [_2]
fistp [tempD]
mov cx, [word ptr tempD]
mov dx, [word ptr SCREENHEIGHTd]
cmp cx, dx ; compare height*2 and screen height.
jb continueRayCast ; if height*2 is lower, skip next code.
; if height*2 is higher than screen height, set height to be screen height / 2
fild [SCREENHEIGHTd]
fidiv [_2]
fstp [height]
continueRayCast:
; draw the rect on the screen! omg so exciting
call drawRect
continueRayLoop:
; decrease alpha by fov * res / screenwidth (in radians)
fild [fov]
fimul [res]
fidiv [SCREENWIDTHd]
fmul [degrad]
fimul [__1]
fadd [alpha]
fstp [alpha]
; fild [_2]
; fiadd [_2]
; fiadd [_2]
; fiadd [_2]
; fiadd [_2]
fild [res]
fiadd [X]
fistp [X]
pop cx
loop rayLoop
ret
endp rayCast
proc drawRect
; draws rect from (X, screenHeight / 2 - height) with width = [res] and height = [height]
mov ax, 0A000h ; load directly to video memory
mov es, ax
; calculate "breakpoints" (when to change rect color)
; bx = first index to draw rect color. (screenHeight / 2 - height ) * screenWidth + X
fild [SCREENHEIGHTd]
fidiv [_2]
fsub [height]
fistp [tempD]
fild [tempD]
fimul [SCREENWIDTHd]
fiadd [X]
fistp [tempD]
mov bx, [word ptr tempD]
; dx = first index to draw background color. bx + int(2 * height)
fild [SCREENHEIGHTd]
fidiv [_2]
fadd [height]
fistp [tempD]
fild [tempD]
fimul [SCREENWIDTHd]
fiadd [X]
fistp [tempD]
mov dx, [word ptr tempD]
mov al, 4 ; initialize color as SKY COLOR
mov di, [word ptr X] ; init index
mov cx, [word ptr SCREENHEIGHTd] ; loop screen height times
drawRectY:
push cx
cmp di, bx
je changeToColor
cmp di, dx
je changeToBackground
jmp continueYLoop
changeToColor:
; calculate color
; color index = 63 - distance * 63 / screenwidth + 10
mov [tempD], 0
mov [word ptr tempD], 63
fld [distance]
fimul [tempD]
fidiv [SCREENWIDTHd]
fimul [__1]
fiadd [tempD]
mov [word ptr tempD], 10
fiadd [tempD]
fistp [tempD]
mov al, [byte ptr tempD]
jmp continueYLoop
changeToBackground:
mov al, 5 ; GROUND COLOR
jmp continueYLoop
continueYLoop:
mov cx, [word ptr res]
drawRectX:
push cx
mov [byte ptr es:di], al
inc di
pop cx
loop drawRectX
; add Y to index (screenWidth - res)
add di, [SCREENWIDTH]
sub di, [word ptr res]
pop cx
loop drawRectY
ret
endp drawRect
; proc drawRect
; ; draws rect from (X, screenHeight / 2 - height) with width = [res] and height = [height]
; mov ax, 0A000h ; load directly to video memory
; mov es, ax
; ; calculate color
; ; color index = 63 - distance * 63 / screenwidth + 10
; mov [tempD], 0
; mov [word ptr tempD], 63
; fld [distance]
; fimul [tempD]
; fidiv [SCREENWIDTHd]
; fimul [__1]
; fiadd [tempD]
; ; mov [tempD], 0
; mov [word ptr tempD], 10
; fiadd [tempD]
; fistp [tempD]
; mov al, [byte ptr tempD]
; ; load initial index to bx (int(y) * screenWidth + x)
; fild [SCREENHEIGHTd]
; fidiv [_2]
; fsub [height]
; fistp [tempD]
; fild [tempD]
; fimul [SCREENWIDTHd]
; fiadd [X]
; fistp [tempD]
; mov bx, [word ptr tempD]
; fld [height]
; fimul [_2]
; fisub [_1]
; fistp [tempD]
; mov cx, [word ptr tempD]
; drawRectY:
; push cx
; mov cx, [word ptr res]
; drawRectX:
; push cx
; mov [byte ptr es:bx], al
; inc bx
; pop cx
; loop drawRectX
; ; add Y to index (screenWidth - res)
; add bx, [SCREENWIDTH]
; sub bx, [word ptr res]
; pop cx
; loop drawRectY
; ret
; endp drawRect
; proc printAx
; push ax
; mov ax, 2h ; text mode
; int 10h
; pop ax
; ; print ax
; mov di, offset STRING
; mov bx, 2
; mov cx, 3
; mov dl, 10
; fff:
; cmp ax, 0
; je printSTRING
; div dl ; al = ax / 10, ah = ax mod 10
; mov [byte ptr di+bx + 1], ah
; add [byte ptr di+bx + 1], '0'
; dec bx
; xor ah, ah
; loop fff
; printSTRING:
; lea dx, [STRING]
; mov ah, 9h
; int 21h
; mov [STRING + 1], ' '
; mov [STRING + 2], ' '
; mov [STRING + 3], '0'
; mov ah, 1h
; int 21h
; jmp exit
; ret
; endp printAx
; proc drawBackground
; ; draw background
; mov ax, 0013h ; enter graphic mode
; int 10h
; ret
; endp drawBackground
proc drawPlayer
pusha
; draw player
mov al, [playerColor] ; color
mov bh, 0
fld [playerX]
fistp [tempD]
mov cx, [word ptr tempD] ; X
fld [playerY]
fistp [tempD]
mov dx, [word ptr tempD] ; Y
mov ah, 0Ch ; DRAW PIXEL
int 10h
popa
ret
endp drawPlayer
; proc drawDir
; ; draw direction
; pusha
; ; store player color and position
; mov bl, [playerColor]
; fld [playerX] ; save player position in stack
; fld [playerY]
; ; replace player color with direction color
; mov al, [dirColor]
; mov [playerColor], al
; ; move player [sizeOfDir] times and draw
; mov cx, [sizeOfDir]
; drawDirLoop:
; fld [playerX]
; fadd [vX]
; fstp [playerX]
; fld [playerY]
; fadd [vY]
; fstp [playerY]
; call drawPlayer
; loop drawDirLoop
; ; restore player color
; mov [playerColor], bl
; ; restore player position
; fstp [playerY]
; fstp [playerX]
; popa
; ret
; endp drawDir
proc deleteTrail
; DELETE trail
; mov ax, 0A000h
; mov es, ax
; mov bx, 0
; mov cx, 320*200
; deleteTrailLoop:
; mov [byte ptr es:bx], 1 ; clear pixel
; inc bx
; loop deleteTrailLoop
call drawBoard
; mov bl, [playerColor]
; mov bh, [dirColor]
; mov [playerColor], 0
; mov [dirColor], 0
; call drawPlayer
; call drawDir
; mov [playerColor], bl
; mov [dirColor], bh
ret
endp deleteTrail
proc toggleEditorMode
; toggle editor mode
cmp [mapEditorMode], 0
jne disableEditorMode
enableEditorMode:
mov [mapEditorMode], 1
; show mouse cursor
mov ax, 1h
int 33h
jmp exitToggleEditorMode
disableEditorMode:
mov [mapEditorMode], 0
; hide mouse cursor (mouse reset)
mov ax, 0h
int 33h
jmp exitToggleEditorMode
exitToggleEditorMode:
call updateScreen
ret
endp toggleEditorMode
proc rotate
; update player rotation based on [angle]
call updateScreen
; if angle is bigger than 180, sub 360
mov ax, [word ptr angle]
cmp ax, 180
jge above180
; if angle is less than 180, add 360
cmp ax, -180
jle below180
jmp continueRot
above180:
fild [angle]
fisub [_360]
fistp [angle]
; sub [word ptr angle], 360
jmp continueRot
below180:
fild [angle]
fiadd [_360]
fistp [angle]
; add [word ptr angle], 360
jmp continueRot
continueRot:
fld [degrad]
fimul [angle]
fsin
fst [vX]
fimul [R]
fstp [dirX]
fld [degrad]
fimul [angle]
fcos
fst [vY]
fimul [R]
fstp [dirY]
ret
endp rotate
proc createShades
; changes the color pallete
; change colors 10-73 to be shades of grey (black to white)
mov ax, 1010h ; Video BIOS function to change palette color
mov bx, 10 ; color number 5
mov dh, 0 ; red color value (0-63, not 0-255!)
mov ch, 0 ; green color component (0-63)
mov cl, 0 ; blue color component (0-63)
loopColors:
int 10h ; Video BIOS interrupt
inc bx ; color number 5
inc dh ; red color value (0-63, not 0-255!)
inc ch ; green color component (0-63)
inc cl ; blue color component (0-63)
cmp cl, 64
jne loopColors
ret
endp createShades
proc handleMouse
mov ax, 03h ; GET MOUSE INFO
int 33h ; CX = X (0-639), DX = Y (0-199)
shr cx, 1 ; div cx by 2 so it is in range of (0-319)
; if map editor mode is enabled
cmp [mapEditorMode], 0
jne handleMouseMapEditor
; if map editor mode is disabled
jmp handleMouseRayCast
handleMouseMapEditor:
test bx, 1 ; check left mouse click
jz continueHandleMouse ; if not skip next code
; if left clicked, place a wall
push cx
push dx
call placeWall
; update screen
call updateScreen
; skip rotation
jmp exitHandleMouse
continueHandleMouse:
test bx, 2 ; check right mouse click
jz exitHandleMouse ; if not skip next code
; if right clicked, remove a wall
push cx
push dx
call removeWall
; update screen
call updateScreen
; skip rotation
jmp exitHandleMouse
handleMouseRayCast:
; if x is in the middle of the screen, return.
cmp cx, [HALFSCREENWIDTH]
je exitHandleMouse
; if x is not in the middle, rotate accordingly.
; load mouse pos to stack
mov [tempD], 0
mov [word ptr tempD], cx
fild [tempD]
; sub the half screen width to get the difference of mouse position
fisub [HALFSCREENWIDTHd]
; rotate by difference
; multiply by [rotSen]
fimul [rotSen]
; sub to angle and store
fimul [__1]
fiadd [angle]
fistp [angle]
; rotate
call rotate
; SET X to half of screen width
mov cx, [SCREENWIDTH]
mov ax, 4 ; SET MOUSE POSITION
int 33h
exitHandleMouse:
ret
endp handleMouse
proc handleInput
; check if a key is being pressed, if not, return.
mov ah, 1h
int 16h
jz exitHandleInput
; check which key is being pressed, put ascii value in al
mov ah, 0h
int 16h
; TESTING
cmp al, ' '
je space
; MOVE PLAYER
cmp al, 'w'
je forward
cmp al, 's'
je backward
cmp al, 'a'
je left
cmp al, 'd'
je right
cmp al, 'l' ; rotate right
je rotateRight
cmp al, 'j' ; rotate left
je rotateLeft
; if the key is ESC, exit
cmp al, 27 ; 27 = ESC
je exit
; if none of the above, return.
jmp exitHandleInput
space:
; toggle map editor mode
call toggleEditorMode
jmp exitHandleInput