-
Notifications
You must be signed in to change notification settings - Fork 26
/
update.pla
231 lines (219 loc) · 4.4 KB
/
update.pla
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
//
// HTTP Daemon
//
import cmdsys
predef syscall, call, getc, gets, putc, puts, putln
predef memset, memcpy, modaddr, modexec
predef isugt, isuge, isult, isule
predef heapmark, heapallocalign, heapalloc, heaprelease
byte MACHID
end
//
// Net object
//
import inet
word iNet
struc t_inet
word initIP
word serviceIP
word openUDP
word sendUDP
word closeUDP
word listenTCP
word connectTCP
word sendTCP
word closeTCP
word setInterfaceIP
word getInterfaceHA
word setDNS
word resolveIP
word setCallback
word setParam
end
end
const VERSION = 1
byte[4] serverIP
word serverPort
word updateList
word portUDP, timeout
byte response
byte perr
byte dlFile = "DOWNLOAD"
byte dlRef
byte rdreqpkt = $DA, $7E, VERSION, VERSION >> 8, $00, $00, $A2, 'F'
byte[17] filename = ""
word fileblock
word xferlen
asm reboot
BIT $C082 ; ENABLE ROM
DEC $03F4 ; INVALIDATE POWER-UP BYTE
JMP ($FFFC) ; RESET
end
//
// ProDOS routines
//
def getpfx(path)
byte params[3]
^path = 0
params.0 = 1
params:1 = path
perr = syscall($C7, @params)
return path
end
def setpfx(path)
byte params[3]
params.0 = 1
params:1 = path
perr = syscall($C6, @params)
return path
end
def open(path, buff)
byte params[6]
params.0 = 3
params:1 = path
params:3 = buff
params.5 = 0
perr = syscall($C8, @params)
return params.5
end
def close(refnum)
byte params[2]
params.0 = 1
params.1 = refnum
perr = syscall($CC, @params)
return perr
end
def read(refnum, buff, len)
byte params[8]
params.0 = 4
params.1 = refnum
params:2 = buff
params:4 = len
params:6 = 0
perr = syscall($CA, @params)
return params:6
end
def write(refnum, buff, len)
byte params[8]
params.0 = 4
params.1 = refnum
params:2 = buff
params:4 = len
params:6 = 0
perr = syscall($CB, @params)
return params:6
end
def create(path, access, type, aux)
byte params[12]
params.0 = 7
params:1 = path
params.3 = access
params.4 = type
params:5 = aux
params.7 = $1
params:8 = 0
params:10 = 0
perr = syscall($C0, @params)
return perr
end
def destroy(path)
byte params[3]
params.0 = 1
params:1 = path
perr = syscall($C1, @params)
return perr
end
def rename(path, newpath)
byte params[5]
params.0 = 2
params:1 = path
params:3 = newpath
perr = syscall($C2, @params)
return perr
end
//
// Restart
//
def restart
puts("Press any key to reboot...")
getc()
reboot()
end
//
// Error
//
def dl_error(errstr)
puts("Update Error: "); puts(errstr); putln
restart()
end
//
// Receive UDP packet
//
def recvUDP(ipsrc, portsrc, data, len, param)
when data->7
is 'F'
if data=>4 == rdreqpkt:4 // Sequence numbers match
xferlen = len - 8
if xferlen > 0
if write(dlRef, data + 8, xferlen) <> xferlen or perr
dl_error("Write download file")
fin
fin
response = 'F'
fin
break
is 'E'
dl_error("Server error")
break
otherwise
dl_error("Unexpected packet")
wend
end
//
// Main update loop
//
memcpy(@serverIP, $0300, 4) // Passed in IP
serverPort = *$0304 // Passed in port
updateList = *$0306 // Passed in update list
portUDP = iNet:openUDP($6500, @recvUDP, 0)
while ^updateList
puts("Updating: "); puts(updateList)
destroy(@dlFile)
if create(@dlFile, $C3, updateList->17, updateList=>18)
dl_error("Unable to create download file")
fin
dlRef = open(@dlFile, $0800) // Use system io_buffer
if not dlRef
dl_error("Unable to open download file")
fin
rdreqpkt:4 = 2 // Init sequence number
memcpy(@filename, updateList, 17)
fileblock = 0
repeat
iNet:sendUDP(portUDP, @serverIP, serverPort, @rdreqpkt, 27)
timeout = 1000
response = 0
while not response and timeout
iNet:serviceIP()
timeout = timeout - 1
loop
if not response
dl_error("No response from server")
fin
putc('.')
fileblock = fileblock + 1
rdreqpkt:4 = rdreqpkt:4 + 1 // Increment sequence
until xferlen <> 1024
close(dlRef)
destroy(updateList)
rename(@dlFile, updateList)
if perr
dl_error("Rename download file")
fin
updateList = updateList + 20
putln
loop
iNet:closeUDP(portUDP)
puts("Update complete.\n")
restart()
done