-
Notifications
You must be signed in to change notification settings - Fork 1
/
ink.asm
204 lines (167 loc) · 6.4 KB
/
ink.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
; Example of MOSlet
.assume adl=1
.org $0B0000 ; NOTE different assemble address for MOSlets
jp start ; We jump over the header
.align 64
.db "MOS"
.db 00h
.db 01h
app_name: .db "ink.bin", 0 ; The executable name, only used in arg1
max_args: EQU 16 ; Maximum number of arguments allowed in argv
arg_pointer: .blkb max_args * 3, 0 ; max 16 x 3 bytes each
num_args: .db 0 ; the number of arguments entered
; ---------------------------------------------
;
; INITIAL SETUP CODE HERE
;
; ---------------------------------------------
start:
push af ; Push all registers to the stack
push bc
push de
push ix
push iy
ld IX, arg_pointer ; The argv array pointer address
push IX
call PARSE_PARAMS ; Parse the parameters
ld a,c ; C contains the number of params entered
ld (num_args),a ; store number of arguments entered
pop IX ; IX: argv
cp 2
jr c, error ; if less than 2 args, then exit
ld de, (ix+3) ; address of first arg, is a 0 terminated string for the file
call STRING2INT ; turn string into a integer we can use
; hl = result, de = pointer to ASCII number
; no error checking, so watch out!
; lower byte L will contain the integer we want to use
ld a, 17
rst.lil $10 ; change ink colour to...
ld a, l
rst.lil $10 ; the value we got back in L
now_exit:
pop iy ; Pop all registers back from the stack
pop ix
pop de
pop bc
pop af
ld hl,0 ; Load the MOS API return code (0) for no errors.
ret ; Return MOS
error:
ld hl, errorString ; location of string
call printString
jp now_exit
printString: ; print zero terminated string
ld a,(hl)
or a
ret z
RST.LIL 10h
inc hl
jr printString
errorString:
.db "ERROR - no value entered\n\r",0
; ---------------------------------------------
;
; PARAM PARSING ROUTINE WRITTEN BY OTHERS
;
; ---------------------------------------------
; Parse the parameter string into a C style array
; Parameters
; - HL: Address of parameter string
; - IX: Address for array pointer storage
; Returns:
; - C: Number of parameters parsed
PARSE_PARAMS:
ld BC, app_name
ld (IX+0), BC ; ARGV[0] = the executable name
inc IX
inc IX
inc IX
call skip_spaces ; Skip HL past any leading spaces
ld BC, 1 ; C: ARGC = 1 - also clears out top 16 bits of BCU
ld B, max_args - 1 ; B: Maximum number of arg_pointer
parse_step_2:
push BC ; Stack ARGC
push HL ; Stack start address of token
call get_token ; Get the next token
ld A, C ; A: Length of the token in characters
pop DE ; Start address of token (was in HL)
pop BC ; ARGC
or A ; Check for A=0 (no token found) OR at end of string
ret Z
ld (IX+0), DE ; Store the pointer to the token
push HL ; DE=HL
pop DE
call skip_spaces ; And skip HL past any spaces onto the next character
Xor A
ld (DE), A ; Zero-terminate the token
inc IX
inc IX
inc IX ; Advance to next pointer position
inc C ; Increment ARGC
ld A, C ; Check for C >= A
cp B
jr C, parse_step_2 ; And loop
RET
; ---------------------------------------------
; Skip spaces in the parameter string
; Parameters:
; - HL: Address of parameter string
; Returns:
; - HL: Address of next none-space character
; F: Z if at end of string, otherwise NZ if there are more tokens to be parsed
skip_spaces:
ld A, (HL) ; Get the character from the parameter string
cp ' ' ; Exit if not space
ret NZ
inc HL ; Advance to next character
jr skip_spaces ; Increment length
; ---------------------------------------------
; Get the next token
; Parameters:
; - HL: Address of parameter string
; Returns:
; - HL: Address of first character after token
; - C: Length of token (in characters)
get_token:
ld C, 0 ; Initialise length
token_loop:
ld A, (HL) ; Get the character from the parameter string
or A ; Exit if 0 (end of parameter string in MOS)
ret Z
cp 13 ; Exit if CR (end of parameter string in BBC BASIC)
ret Z
cp ' ' ; Exit if space (end of token)
ret Z
inc HL ; Advance to next character
inc C ; Increment length
jr token_loop
; ---------------------------------------------
;
; STRING TO INTEGER ROUTINE WRITTEN BY OTHERS
;
; ---------------------------------------------
; Takes pointer to a string of ascii representing an integer and converts to 3 byte integer
; hl = result
; de = pointer to ASCII number
STRING2INT:
Ld hl,0
s2i_loop:
ld a,(de)
Sub 48
Jr c,s2i_done
Cp 10
Jr nc,s2i_done
Push hl
Pop bc
Add hl,hl ; x2
Add hl,hl ; x4
Add hl,bc ; x5
Add hl,hl ; x10
Ld bc,0
Ld c,a
Add hl,bc ; Add digit
Inc de ; go to next number
Jr s2i_loop
s2i_done:
ret
; ---------------------------------------------