summaryrefslogtreecommitdiff
path: root/builtin_video_mode.asm
blob: 571899ed5330aa7838d74ee1056f3d0ffcbbc590 (plain) (blame)
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
%ifndef _BUILTIN_VIDEO_MODE_ASM
%define _BUILTIN_VIDEO_MODE_ASM

builtin_video_mode:
	push bp
	mov bp, sp

	mov cx, [bp + 4]	; Load argc
	mov bx, [bp + 6]	; Load argv

	cmp cx, 1		; Not enough args?
	jl .no_args		; ... die
	jmp .main

	.no_args:
		push .error_arg
		call printf
		add sp, 2 * 1
		jmp .return

	; main program

	.main:
		mov bx, [bx]	; Load first element in argv array
		mov si, bx	; First element is source index

		push bx		; Get length of element
		call strlen
		add sp, 2
		mov cx, ax	; Store length
		mov bx, 0


		mov ax, 0
		mov dx, 0
		.chars:
			lodsb		; Load character from ES:SI
			cmp ax, '9'	; If value is greater than '9' it's likely hex, so
					; adjust AX to compensate
			jg .ishex

			sub ax, '0'	; Otherwise, the value is base-10
			jmp .nosub

		.tolower:
			sub ax, 20h
		.ishex:
			cmp ax, 'a'
			jge .tolower	; If we recieved a lowercase letter, convert it
					; to uppercase, then continue

			cmp ax, 'F'	; Is this a valid hexadecimal value? (0 ~ F)
			jg .invalid_input

			sub ax, 'A'	; Convert character to BCD
			add ax, 10

		.nosub:
			shl dx, 4	; Shift current BCD value 4-bits left
			or dx, ax	; Tack on the latest value
			dec cx		; Decrement counter
			jne .chars	; continue until no characters remain


		cmp dx, 13h		; Is the final value a valid video mode?
		jg .invalid_mode


		mov al, dl		; BIOS video services only operate on a byte value
					; ... oh well.

		mov ah, 00h
		int 10h			; Set video mode

	.return:
		mov sp, bp
		pop bp
		ret

	.invalid_input:
		push ax
		push .error_hex
		call printf
		add sp, 2 * 2
		jmp .return

	.invalid_mode:
		push dx
		push .error_mode
		call printf
		add sp, 2 * 2
		jmp .return

	.error_arg: db 'error: no graphics mode requested. (0..13)\n', 0
	.error_hex: db 'error: "%c" is an invalid hexadecimal value (0..F)\n', 0
	.error_mode: db 'error: %2x is an invalid video mode (0..13)\n', 0

%endif