-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
b2_dsrutil.c
247 lines (203 loc) · 6.59 KB
/
b2_dsrutil.c
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
#include "banks.h"
#define MYBANK BANK(2)
#include "b0_globals.h"
#include "b0_main.h"
#include "b2_dsrutil.h"
#include "b2_mds_dsrlnk.h"
#include "b2_tifloat.h"
#include "b1_strutil.h"
#include "b8_terminal.h"
#include "b0_heap.h"
#include <vdp.h>
#include <string.h>
struct DeviceServiceRoutine* dsrList;
int matchesPrefix(char* basicstr, char* device_prefix) {
return basicstr[1] == device_prefix[0] &&
basicstr[2] == device_prefix[1] &&
basicstr[3] == device_prefix[2];
}
static int __attribute__((noinline)) isDrive(char* basicstr) {
// include IDE
if (basicstr[0] == 3 && matchesPrefix(basicstr, "IDE")) {
return 1;
}
// include CLOCK
if (basicstr[0] == 5 && matchesPrefix(basicstr, "CLO")) {
return 1;
}
// include PI
if (basicstr[0] == 2 && basicstr[1] == 'P' && basicstr[2] == 'I') {
return 1;
}
// include TIPI
if (basicstr[0] == 4 && matchesPrefix(basicstr, "TIP")) {
return 1;
}
// include MEXP-1 RD
if (basicstr[0] == 2 && basicstr[1] == 'R' && basicstr[2] == 'D') {
return 1;
}
if (basicstr[0] == 4) {
if (basicstr[4] >= '0' && basicstr[4] <= '9') {
return matchesPrefix(basicstr, "DSK") ||
matchesPrefix(basicstr, "IDE") ||
matchesPrefix(basicstr, "SCS") ||
matchesPrefix(basicstr, "WDS") ||
matchesPrefix(basicstr, "HDX") ||
matchesPrefix(basicstr, "URI");
} else if (basicstr[4] >= 'A' && basicstr[4] <= 'Z') {
return matchesPrefix(basicstr, "DSK");
}
}
return 0;
}
unsigned int existsDir(struct DeviceServiceRoutine* dsr, const char* pathname) {
struct PAB pab;
initPab(&pab);
unsigned int open_err = dsr_open(dsr, &pab, pathname, DSR_TYPE_INPUT | DSR_TYPE_FIXED | DSR_TYPE_INTERNAL | DSR_TYPE_RELATIVE, 0);
unsigned int read_err = 0;
if (!open_err) {
read_err = dsr_read(dsr, &pab, 0);
dsr_close(dsr, &pab);
}
return open_err || read_err;
}
unsigned int existsFile(struct DeviceServiceRoutine* dsr, const char* pathname) {
struct PAB pab;
initPab(&pab);
pab.pName = (unsigned char*) pathname;
return dsr_status(dsr, &pab) != 0x0080;
}
//---- the following are meant to be easy, not fast ----
void initPab(struct PAB* pab) {
pab->OpCode = DSR_OPEN;
pab->Status = DSR_TYPE_DISPLAY | DSR_TYPE_VARIABLE | DSR_TYPE_SEQUENTIAL | DSR_TYPE_INPUT;
pab->RecordLength = 0;
pab->RecordNumber = 0;
pab->ScreenOffset = 0;
pab->NameLength = 0;
pab->CharCount = 0;
pab->VDPBuffer = FBUF;
}
unsigned int dsr_prg_load(struct DeviceServiceRoutine* dsr, struct PAB* pab, const char* fname, int vdpaddr, int maxsize) {
initPab(pab);
pab->OpCode = DSR_LOAD;
pab->VDPBuffer = vdpaddr;
pab->pName = (unsigned char*)fname;
pab->RecordNumber = maxsize;
return mds_lvl3_dsrlnk(dsr->crubase, pab, VPAB);
}
unsigned int dsr_prg_save(struct DeviceServiceRoutine* dsr, struct PAB* pab, const char* fname, int vdpaddr, int count) {
initPab(pab);
pab->OpCode = DSR_SAVE;
pab->VDPBuffer = vdpaddr;
pab->pName = (unsigned char*)fname;
pab->RecordNumber = count;
return mds_lvl3_dsrlnk(dsr->crubase, pab, VPAB);
}
unsigned int dsr_open(struct DeviceServiceRoutine* dsr, struct PAB* pab, const char* fname, int flags, int reclen) {
initPab(pab);
pab->OpCode = DSR_OPEN;
if (flags) {
pab->Status = (unsigned char) flags;
}
if (reclen != 0) {
pab->RecordLength = reclen;
}
pab->pName = (unsigned char*)fname;
int res = mds_lvl3_dsrlnk(dsr->crubase, pab, VPAB);
vdpmemread(VPAB + 4, (char*) (&pab->RecordLength), 1);
return res;
}
unsigned int dsr_close(struct DeviceServiceRoutine* dsr, struct PAB* pab) {
pab->OpCode = DSR_CLOSE;
return mds_lvl3_dsrlnk(dsr->crubase, pab, VPAB);
}
unsigned int dsr_reset(struct DeviceServiceRoutine* dsr, struct PAB* pab, int record) {
pab->OpCode = DSR_REWIND;
pab->RecordNumber = record;
return mds_lvl3_dsrlnk(dsr->crubase, pab, VPAB);
}
// the data read is in FBUF, the length read in pab->CharCount
// typically passing 0 in for record number will let the controller
// auto-increment it.
unsigned int dsr_read(struct DeviceServiceRoutine* dsr, struct PAB* pab, int recordNumber) {
pab->OpCode = DSR_READ;
pab->RecordNumber = recordNumber;
pab->CharCount = 0;
unsigned char result = mds_lvl3_dsrlnk(dsr->crubase, pab, VPAB);
vdpmemread(VPAB + 5, (char*) (&pab->CharCount), 1);
if (! (pab->Status & DSR_TYPE_VARIABLE)) {
pab->CharCount = pab->RecordLength;
}
return result;
}
unsigned int dsr_write(struct DeviceServiceRoutine* dsr, struct PAB* pab, char* record, int reclen) {
pab->OpCode = DSR_WRITE;
pab->CharCount = reclen;
vdpmemcpy(pab->VDPBuffer, record, reclen);
unsigned char result = mds_lvl3_dsrlnk(dsr->crubase, pab, VPAB);
return result;
}
unsigned int dsr_status(struct DeviceServiceRoutine* dsr, struct PAB* pab) {
pab->OpCode = DSR_STATUS;
unsigned int result = (int)mds_lvl3_dsrlnk(dsr->crubase, pab, VPAB);
if (result) {
return result << 8;
} else {
return vdpreadchar(VPAB+8);
}
}
unsigned int dsr_delete(struct DeviceServiceRoutine* dsr, struct PAB* pab) {
pab->OpCode = DSR_DELETE;
unsigned char result = mds_lvl3_dsrlnk(dsr->crubase, pab, VPAB);
return result;
}
void loadDriveDSRs() {
dsrList = (struct DeviceServiceRoutine*) bk_alloc(sizeof(struct DeviceServiceRoutine));
struct DeviceServiceRoutine* listHead = dsrList;
int cruscan = 0x1000;
while(cruscan < 0x2000) {
enableROM(cruscan);
struct DeviceRomHeader* dsrrom = (struct DeviceRomHeader*) 0x4000;
if (dsrrom->flag == 0xAA) {
struct NameLink* dsrlinks = dsrrom->dsrlnk;
while(dsrlinks != 0) {
if (isDrive(dsrlinks->name)) {
bk_basicToCstr(dsrlinks->name, listHead->name);
listHead->crubase = cruscan;
listHead->addr = dsrlinks->routine;
listHead = (struct DeviceServiceRoutine*) bk_alloc(sizeof(struct DeviceServiceRoutine));
}
dsrlinks = dsrlinks->next;
}
}
disableROM(cruscan);
cruscan += 0x0100;
}
currentDsr = dsrList;
bk_strcpy(currentPath, currentDsr->name);
bk_strcat(currentPath, str2ram("."));
}
void enableROM(int crubase) {
__asm__("mov %0,r12\n\tsbo 0" : : "r"(crubase) : "r12");
}
void disableROM(int crubase) {
__asm__("mov %0,r12\n\tsbz 0" : : "r"(crubase) : "r12");
}
struct DeviceServiceRoutine* findDsr(char* devicename, int crubase) {
int i = 0;
while(dsrList[i].name[0] != 0) {
if (crubase != 0) {
if (dsrList[i].crubase == crubase && 0 == bk_strcmp(dsrList[i].name, devicename)) {
return &dsrList[i];
}
} else {
if (0 == bk_strcmp(dsrList[i].name, devicename)) {
return &dsrList[i];
}
}
i++;
}
return 0;
}