BASIC compiler/interpreter for PIC32MX/MZ-80K
修訂 | 951d53848130aa0807175aecde0048c7e8ab33a6 (tree) |
---|---|
時間 | 2019-04-10 06:15:53 |
作者 | Katsumi <kmorimatsu@sour...> |
Commiter | Katsumi |
Start Protozoa Git repository
@@ -12,7 +12,7 @@ BAS | ||
12 | 12 | JavaのStringクラス様の文字列を扱うクラス。 |
13 | 13 | |
14 | 14 | <コンストラクター> |
15 | -第一引数は、文字列もしくはCSTRオブジェクト。 | |
15 | +第一引数は、文字列。 | |
16 | 16 | |
17 | 17 | <パブリックフィールド> |
18 | 18 | STR$ |
@@ -0,0 +1,794 @@ | ||
1 | +/* linker script for application of PIC32MX170F256B SD card bootloader */ | |
2 | + | |
3 | +/*-------------------------------------------------------------------------- | |
4 | + * MPLAB XC Compiler - PIC32MX170F256B linker script | |
5 | + * | |
6 | + * This software is developed by Microchip Technology Inc. and its | |
7 | + * subsidiaries ("Microchip"). | |
8 | + * | |
9 | + * Redistribution and use in source and binary forms, with or without | |
10 | + * modification, are permitted provided that the following conditions are | |
11 | + * met: | |
12 | + * | |
13 | + * 1. Redistributions of source code must retain the above copyright | |
14 | + * notice, this list of conditions and the following disclaimer. | |
15 | + * 2. Redistributions in binary form must reproduce the above | |
16 | + * copyright notice, this list of conditions and the following | |
17 | + * disclaimer in the documentation and/or other materials provided | |
18 | + * with the distribution. | |
19 | + * 3. Microchip's name may not be used to endorse or promote products | |
20 | + * derived from this software without specific prior written | |
21 | + * permission. | |
22 | + * | |
23 | + * THIS SOFTWARE IS PROVIDED BY MICROCHIP "AS IS" AND ANY EXPRESS OR IMPLIED | |
24 | + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
25 | + * MERCHANTABILITY AND FITNESS FOR PURPOSE ARE DISCLAIMED. IN NO EVENT | |
26 | + * SHALL MICROCHIP BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
27 | + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING BUT NOT LIMITED TO | |
28 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS; | |
29 | + * OR BUSINESS INTERRUPTION) HOWSOEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
30 | + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
31 | + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
32 | + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
33 | + * | |
34 | + *-------------------------------------------------------------------------*/ | |
35 | + | |
36 | +/* Default linker script, for normal executables */ | |
37 | + | |
38 | +/* IMPORTANT: PIC32MX MCUs use two files for the default linker script: | |
39 | + * 1) pic32mx/lib/ldscripts/elf32pic32.x (main linker script) | |
40 | + * 2) pic32mx/lib/proc/32MX170F256B/procdefs.ld (variant-specific fragment) | |
41 | + * | |
42 | + * This file is provided only as a convenience when adding a custom linker script | |
43 | + * to your application. | |
44 | + */ | |
45 | + | |
46 | +OUTPUT_FORMAT("elf32-tradlittlemips") | |
47 | +OUTPUT_ARCH(pic32mx) | |
48 | +ENTRY(_reset) | |
49 | +/* | |
50 | + * Provide for a minimum stack and heap size | |
51 | + * - _min_stack_size - represents the minimum space that must be made | |
52 | + * available for the stack. Can be overridden from | |
53 | + * the command line using the linker's --defsym option. | |
54 | + * - _min_heap_size - represents the minimum space that must be made | |
55 | + * available for the heap. Must be specified on | |
56 | + * the command line using the linker's --defsym option. | |
57 | + */ | |
58 | +EXTERN (_min_stack_size _min_heap_size) | |
59 | +PROVIDE(_min_stack_size = 0x400) ; | |
60 | + | |
61 | +/************************************************************************* | |
62 | + * Processor-specific object file. Contains SFR definitions. | |
63 | + *************************************************************************/ | |
64 | +INPUT("processor.o") | |
65 | + | |
66 | +/************************************************************************* | |
67 | + * Processor-specific peripheral libraries are optional | |
68 | + *************************************************************************/ | |
69 | +OPTIONAL("libmchp_peripheral.a") | |
70 | +OPTIONAL("libmchp_peripheral_32MX150F128B.a") | |
71 | + | |
72 | +/************************************************************************* | |
73 | + * For interrupt vector handling | |
74 | + *************************************************************************/ | |
75 | +PROVIDE(_vector_spacing = 0x00000001); | |
76 | +_ebase_address = 0x9D006000; | |
77 | + | |
78 | +/************************************************************************* | |
79 | + * Memory Address Equates | |
80 | + * _RESET_ADDR -- Reset Vector | |
81 | + * _BEV_EXCPT_ADDR -- Boot exception Vector | |
82 | + * _DBG_EXCPT_ADDR -- In-circuit Debugging Exception Vector | |
83 | + * _DBG_CODE_ADDR -- In-circuit Debug Executive address | |
84 | + * _DBG_CODE_SIZE -- In-circuit Debug Executive size | |
85 | + * _GEN_EXCPT_ADDR -- General Exception Vector | |
86 | + *************************************************************************/ | |
87 | +_RESET_ADDR = (0x9D006000 + 0x1000); | |
88 | +_BEV_EXCPT_ADDR = ((0x9D006000 + 0x1000) + 0x380); | |
89 | +_DBG_EXCPT_ADDR = ((0x9D006000 + 0x1000) + 0x480); | |
90 | +_DBG_CODE_ADDR = 0x9FC00490; | |
91 | +_DBG_CODE_SIZE = 0x760 ; | |
92 | +_GEN_EXCPT_ADDR = _ebase_address + 0x180; | |
93 | + | |
94 | +/************************************************************************* | |
95 | + * Memory Regions | |
96 | + * | |
97 | + * Memory regions without attributes cannot be used for orphaned sections. | |
98 | + * Only sections specifically assigned to these regions can be allocated | |
99 | + * into these regions. | |
100 | + * | |
101 | + * The Debug exception vector is located at 0x9FC00480. | |
102 | + * The config_<address> sections are used to locate the config words at | |
103 | + * their absolute addresses. | |
104 | + *************************************************************************/ | |
105 | +MEMORY | |
106 | +{ | |
107 | + kseg0_program_mem (rx) : ORIGIN = (0x9D006000 + 0x1000 + 0x490), LENGTH = 0x40000 - (0x6000 + 0x1000 + 0x490) /* All C Files will be located here */ | |
108 | + exception_mem : ORIGIN = 0x9D006000, LENGTH = 0x1000 /* Interrupt vector table */ | |
109 | + debug_exec_mem : ORIGIN = 0x9FC00490, LENGTH = 0x760 | |
110 | + kseg0_boot_mem : ORIGIN = 0x9D006000, LENGTH = 0x0 /* This memory region is dummy */ | |
111 | + kseg1_boot_mem : ORIGIN = (0x9D006000 + 0x1000), LENGTH = 0x490 /* C Startup code */ | |
112 | + config3 : ORIGIN = 0xBFC00BF0, LENGTH = 0x4 | |
113 | + config2 : ORIGIN = 0xBFC00BF4, LENGTH = 0x4 | |
114 | + config1 : ORIGIN = 0xBFC00BF8, LENGTH = 0x4 | |
115 | + config0 : ORIGIN = 0xBFC00BFC, LENGTH = 0x4 | |
116 | + kseg1_data_mem (w!x) : ORIGIN = 0xA0000000, LENGTH = 0x10000 | |
117 | + sfrs : ORIGIN = 0xBF800000, LENGTH = 0x100000 | |
118 | + configsfrs : ORIGIN = 0xBFC00BF0, LENGTH = 0x10 | |
119 | +} | |
120 | + | |
121 | +/************************************************************************* | |
122 | + * Configuration-word sections. Map the config-pragma input sections to | |
123 | + * absolute-address output sections. | |
124 | + *************************************************************************/ | |
125 | +SECTIONS | |
126 | +{ | |
127 | + .config_BFC00BF0 : { | |
128 | + KEEP(*(.config_BFC00BF0)) | |
129 | + } > config3 | |
130 | + .config_BFC00BF4 : { | |
131 | + KEEP(*(.config_BFC00BF4)) | |
132 | + } > config2 | |
133 | + .config_BFC00BF8 : { | |
134 | + KEEP(*(.config_BFC00BF8)) | |
135 | + } > config1 | |
136 | + .config_BFC00BFC : { | |
137 | + KEEP(*(.config_BFC00BFC)) | |
138 | + } > config0 | |
139 | +} | |
140 | +SECTIONS | |
141 | +{ | |
142 | + /* Boot Sections */ | |
143 | + .reset _RESET_ADDR : | |
144 | + { | |
145 | + KEEP(*(.reset)) | |
146 | + KEEP(*(.reset.startup)) | |
147 | + } > kseg1_boot_mem | |
148 | + .bev_excpt _BEV_EXCPT_ADDR : | |
149 | + { | |
150 | + KEEP(*(.bev_handler)) | |
151 | + } > kseg1_boot_mem | |
152 | + /* Debug exception vector */ | |
153 | + .dbg_excpt _DBG_EXCPT_ADDR (NOLOAD) : | |
154 | + { | |
155 | + . += (DEFINED (_DEBUGGER) ? 0x8 : 0x0); | |
156 | + } > kseg1_boot_mem | |
157 | + /* Space reserved for the debug executive */ | |
158 | + .dbg_code _DBG_CODE_ADDR (NOLOAD) : | |
159 | + { | |
160 | + . += (DEFINED (_DEBUGGER) ? _DBG_CODE_SIZE : 0x0); | |
161 | + } > debug_exec_mem | |
162 | + | |
163 | + .app_excpt _GEN_EXCPT_ADDR : | |
164 | + { | |
165 | + KEEP(*(.gen_handler)) | |
166 | + } > exception_mem | |
167 | + | |
168 | + .vector_0 _ebase_address + 0x200 + ((_vector_spacing << 5) * 0) : | |
169 | + { | |
170 | + KEEP(*(.vector_0)) | |
171 | + } > exception_mem | |
172 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_0) <= (_vector_spacing << 5), "function at exception vector 0 too large") | |
173 | + .vector_1 _ebase_address + 0x200 + ((_vector_spacing << 5) * 1) : | |
174 | + { | |
175 | + KEEP(*(.vector_1)) | |
176 | + } > exception_mem | |
177 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_1) <= (_vector_spacing << 5), "function at exception vector 1 too large") | |
178 | + .vector_2 _ebase_address + 0x200 + ((_vector_spacing << 5) * 2) : | |
179 | + { | |
180 | + KEEP(*(.vector_2)) | |
181 | + } > exception_mem | |
182 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_2) <= (_vector_spacing << 5), "function at exception vector 2 too large") | |
183 | + .vector_3 _ebase_address + 0x200 + ((_vector_spacing << 5) * 3) : | |
184 | + { | |
185 | + KEEP(*(.vector_3)) | |
186 | + } > exception_mem | |
187 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_3) <= (_vector_spacing << 5), "function at exception vector 3 too large") | |
188 | + .vector_4 _ebase_address + 0x200 + ((_vector_spacing << 5) * 4) : | |
189 | + { | |
190 | + KEEP(*(.vector_4)) | |
191 | + } > exception_mem | |
192 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_4) <= (_vector_spacing << 5), "function at exception vector 4 too large") | |
193 | + .vector_5 _ebase_address + 0x200 + ((_vector_spacing << 5) * 5) : | |
194 | + { | |
195 | + KEEP(*(.vector_5)) | |
196 | + } > exception_mem | |
197 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_5) <= (_vector_spacing << 5), "function at exception vector 5 too large") | |
198 | + .vector_6 _ebase_address + 0x200 + ((_vector_spacing << 5) * 6) : | |
199 | + { | |
200 | + KEEP(*(.vector_6)) | |
201 | + } > exception_mem | |
202 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_6) <= (_vector_spacing << 5), "function at exception vector 6 too large") | |
203 | + .vector_7 _ebase_address + 0x200 + ((_vector_spacing << 5) * 7) : | |
204 | + { | |
205 | + KEEP(*(.vector_7)) | |
206 | + } > exception_mem | |
207 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_7) <= (_vector_spacing << 5), "function at exception vector 7 too large") | |
208 | + .vector_8 _ebase_address + 0x200 + ((_vector_spacing << 5) * 8) : | |
209 | + { | |
210 | + KEEP(*(.vector_8)) | |
211 | + } > exception_mem | |
212 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_8) <= (_vector_spacing << 5), "function at exception vector 8 too large") | |
213 | + .vector_9 _ebase_address + 0x200 + ((_vector_spacing << 5) * 9) : | |
214 | + { | |
215 | + KEEP(*(.vector_9)) | |
216 | + } > exception_mem | |
217 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_9) <= (_vector_spacing << 5), "function at exception vector 9 too large") | |
218 | + .vector_10 _ebase_address + 0x200 + ((_vector_spacing << 5) * 10) : | |
219 | + { | |
220 | + KEEP(*(.vector_10)) | |
221 | + } > exception_mem | |
222 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_10) <= (_vector_spacing << 5), "function at exception vector 10 too large") | |
223 | + .vector_11 _ebase_address + 0x200 + ((_vector_spacing << 5) * 11) : | |
224 | + { | |
225 | + KEEP(*(.vector_11)) | |
226 | + } > exception_mem | |
227 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_11) <= (_vector_spacing << 5), "function at exception vector 11 too large") | |
228 | + .vector_12 _ebase_address + 0x200 + ((_vector_spacing << 5) * 12) : | |
229 | + { | |
230 | + KEEP(*(.vector_12)) | |
231 | + } > exception_mem | |
232 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_12) <= (_vector_spacing << 5), "function at exception vector 12 too large") | |
233 | + .vector_13 _ebase_address + 0x200 + ((_vector_spacing << 5) * 13) : | |
234 | + { | |
235 | + KEEP(*(.vector_13)) | |
236 | + } > exception_mem | |
237 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_13) <= (_vector_spacing << 5), "function at exception vector 13 too large") | |
238 | + .vector_14 _ebase_address + 0x200 + ((_vector_spacing << 5) * 14) : | |
239 | + { | |
240 | + KEEP(*(.vector_14)) | |
241 | + } > exception_mem | |
242 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_14) <= (_vector_spacing << 5), "function at exception vector 14 too large") | |
243 | + .vector_15 _ebase_address + 0x200 + ((_vector_spacing << 5) * 15) : | |
244 | + { | |
245 | + KEEP(*(.vector_15)) | |
246 | + } > exception_mem | |
247 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_15) <= (_vector_spacing << 5), "function at exception vector 15 too large") | |
248 | + .vector_16 _ebase_address + 0x200 + ((_vector_spacing << 5) * 16) : | |
249 | + { | |
250 | + KEEP(*(.vector_16)) | |
251 | + } > exception_mem | |
252 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_16) <= (_vector_spacing << 5), "function at exception vector 16 too large") | |
253 | + .vector_17 _ebase_address + 0x200 + ((_vector_spacing << 5) * 17) : | |
254 | + { | |
255 | + KEEP(*(.vector_17)) | |
256 | + } > exception_mem | |
257 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_17) <= (_vector_spacing << 5), "function at exception vector 17 too large") | |
258 | + .vector_18 _ebase_address + 0x200 + ((_vector_spacing << 5) * 18) : | |
259 | + { | |
260 | + KEEP(*(.vector_18)) | |
261 | + } > exception_mem | |
262 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_18) <= (_vector_spacing << 5), "function at exception vector 18 too large") | |
263 | + .vector_19 _ebase_address + 0x200 + ((_vector_spacing << 5) * 19) : | |
264 | + { | |
265 | + KEEP(*(.vector_19)) | |
266 | + } > exception_mem | |
267 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_19) <= (_vector_spacing << 5), "function at exception vector 19 too large") | |
268 | + .vector_20 _ebase_address + 0x200 + ((_vector_spacing << 5) * 20) : | |
269 | + { | |
270 | + KEEP(*(.vector_20)) | |
271 | + } > exception_mem | |
272 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_20) <= (_vector_spacing << 5), "function at exception vector 20 too large") | |
273 | + .vector_21 _ebase_address + 0x200 + ((_vector_spacing << 5) * 21) : | |
274 | + { | |
275 | + KEEP(*(.vector_21)) | |
276 | + } > exception_mem | |
277 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_21) <= (_vector_spacing << 5), "function at exception vector 21 too large") | |
278 | + .vector_22 _ebase_address + 0x200 + ((_vector_spacing << 5) * 22) : | |
279 | + { | |
280 | + KEEP(*(.vector_22)) | |
281 | + } > exception_mem | |
282 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_22) <= (_vector_spacing << 5), "function at exception vector 22 too large") | |
283 | + .vector_23 _ebase_address + 0x200 + ((_vector_spacing << 5) * 23) : | |
284 | + { | |
285 | + KEEP(*(.vector_23)) | |
286 | + } > exception_mem | |
287 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_23) <= (_vector_spacing << 5), "function at exception vector 23 too large") | |
288 | + .vector_24 _ebase_address + 0x200 + ((_vector_spacing << 5) * 24) : | |
289 | + { | |
290 | + KEEP(*(.vector_24)) | |
291 | + } > exception_mem | |
292 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_24) <= (_vector_spacing << 5), "function at exception vector 24 too large") | |
293 | + .vector_25 _ebase_address + 0x200 + ((_vector_spacing << 5) * 25) : | |
294 | + { | |
295 | + KEEP(*(.vector_25)) | |
296 | + } > exception_mem | |
297 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_25) <= (_vector_spacing << 5), "function at exception vector 25 too large") | |
298 | + .vector_26 _ebase_address + 0x200 + ((_vector_spacing << 5) * 26) : | |
299 | + { | |
300 | + KEEP(*(.vector_26)) | |
301 | + } > exception_mem | |
302 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_26) <= (_vector_spacing << 5), "function at exception vector 26 too large") | |
303 | + .vector_27 _ebase_address + 0x200 + ((_vector_spacing << 5) * 27) : | |
304 | + { | |
305 | + KEEP(*(.vector_27)) | |
306 | + } > exception_mem | |
307 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_27) <= (_vector_spacing << 5), "function at exception vector 27 too large") | |
308 | + .vector_28 _ebase_address + 0x200 + ((_vector_spacing << 5) * 28) : | |
309 | + { | |
310 | + KEEP(*(.vector_28)) | |
311 | + } > exception_mem | |
312 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_28) <= (_vector_spacing << 5), "function at exception vector 28 too large") | |
313 | + .vector_29 _ebase_address + 0x200 + ((_vector_spacing << 5) * 29) : | |
314 | + { | |
315 | + KEEP(*(.vector_29)) | |
316 | + } > exception_mem | |
317 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_29) <= (_vector_spacing << 5), "function at exception vector 29 too large") | |
318 | + .vector_30 _ebase_address + 0x200 + ((_vector_spacing << 5) * 30) : | |
319 | + { | |
320 | + KEEP(*(.vector_30)) | |
321 | + } > exception_mem | |
322 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_30) <= (_vector_spacing << 5), "function at exception vector 30 too large") | |
323 | + .vector_31 _ebase_address + 0x200 + ((_vector_spacing << 5) * 31) : | |
324 | + { | |
325 | + KEEP(*(.vector_31)) | |
326 | + } > exception_mem | |
327 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_31) <= (_vector_spacing << 5), "function at exception vector 31 too large") | |
328 | + .vector_32 _ebase_address + 0x200 + ((_vector_spacing << 5) * 32) : | |
329 | + { | |
330 | + KEEP(*(.vector_32)) | |
331 | + } > exception_mem | |
332 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_32) <= (_vector_spacing << 5), "function at exception vector 32 too large") | |
333 | + .vector_33 _ebase_address + 0x200 + ((_vector_spacing << 5) * 33) : | |
334 | + { | |
335 | + KEEP(*(.vector_33)) | |
336 | + } > exception_mem | |
337 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_33) <= (_vector_spacing << 5), "function at exception vector 33 too large") | |
338 | + .vector_34 _ebase_address + 0x200 + ((_vector_spacing << 5) * 34) : | |
339 | + { | |
340 | + KEEP(*(.vector_34)) | |
341 | + } > exception_mem | |
342 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_34) <= (_vector_spacing << 5), "function at exception vector 34 too large") | |
343 | + .vector_35 _ebase_address + 0x200 + ((_vector_spacing << 5) * 35) : | |
344 | + { | |
345 | + KEEP(*(.vector_35)) | |
346 | + } > exception_mem | |
347 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_35) <= (_vector_spacing << 5), "function at exception vector 35 too large") | |
348 | + .vector_36 _ebase_address + 0x200 + ((_vector_spacing << 5) * 36) : | |
349 | + { | |
350 | + KEEP(*(.vector_36)) | |
351 | + } > exception_mem | |
352 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_36) <= (_vector_spacing << 5), "function at exception vector 36 too large") | |
353 | + .vector_37 _ebase_address + 0x200 + ((_vector_spacing << 5) * 37) : | |
354 | + { | |
355 | + KEEP(*(.vector_37)) | |
356 | + } > exception_mem | |
357 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_37) <= (_vector_spacing << 5), "function at exception vector 37 too large") | |
358 | + .vector_38 _ebase_address + 0x200 + ((_vector_spacing << 5) * 38) : | |
359 | + { | |
360 | + KEEP(*(.vector_38)) | |
361 | + } > exception_mem | |
362 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_38) <= (_vector_spacing << 5), "function at exception vector 38 too large") | |
363 | + .vector_39 _ebase_address + 0x200 + ((_vector_spacing << 5) * 39) : | |
364 | + { | |
365 | + KEEP(*(.vector_39)) | |
366 | + } > exception_mem | |
367 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_39) <= (_vector_spacing << 5), "function at exception vector 39 too large") | |
368 | + .vector_40 _ebase_address + 0x200 + ((_vector_spacing << 5) * 40) : | |
369 | + { | |
370 | + KEEP(*(.vector_40)) | |
371 | + } > exception_mem | |
372 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_40) <= (_vector_spacing << 5), "function at exception vector 40 too large") | |
373 | + .vector_41 _ebase_address + 0x200 + ((_vector_spacing << 5) * 41) : | |
374 | + { | |
375 | + KEEP(*(.vector_41)) | |
376 | + } > exception_mem | |
377 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_41) <= (_vector_spacing << 5), "function at exception vector 41 too large") | |
378 | + .vector_42 _ebase_address + 0x200 + ((_vector_spacing << 5) * 42) : | |
379 | + { | |
380 | + KEEP(*(.vector_42)) | |
381 | + } > exception_mem | |
382 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_42) <= (_vector_spacing << 5), "function at exception vector 42 too large") | |
383 | + .vector_43 _ebase_address + 0x200 + ((_vector_spacing << 5) * 43) : | |
384 | + { | |
385 | + KEEP(*(.vector_43)) | |
386 | + } > exception_mem | |
387 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_43) <= (_vector_spacing << 5), "function at exception vector 43 too large") | |
388 | + .vector_44 _ebase_address + 0x200 + ((_vector_spacing << 5) * 44) : | |
389 | + { | |
390 | + KEEP(*(.vector_44)) | |
391 | + } > exception_mem | |
392 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_44) <= (_vector_spacing << 5), "function at exception vector 44 too large") | |
393 | + .vector_45 _ebase_address + 0x200 + ((_vector_spacing << 5) * 45) : | |
394 | + { | |
395 | + KEEP(*(.vector_45)) | |
396 | + } > exception_mem | |
397 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_45) <= (_vector_spacing << 5), "function at exception vector 45 too large") | |
398 | + .vector_46 _ebase_address + 0x200 + ((_vector_spacing << 5) * 46) : | |
399 | + { | |
400 | + KEEP(*(.vector_46)) | |
401 | + } > exception_mem | |
402 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_46) <= (_vector_spacing << 5), "function at exception vector 46 too large") | |
403 | + .vector_47 _ebase_address + 0x200 + ((_vector_spacing << 5) * 47) : | |
404 | + { | |
405 | + KEEP(*(.vector_47)) | |
406 | + } > exception_mem | |
407 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_47) <= (_vector_spacing << 5), "function at exception vector 47 too large") | |
408 | + .vector_48 _ebase_address + 0x200 + ((_vector_spacing << 5) * 48) : | |
409 | + { | |
410 | + KEEP(*(.vector_48)) | |
411 | + } > exception_mem | |
412 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_48) <= (_vector_spacing << 5), "function at exception vector 48 too large") | |
413 | + .vector_49 _ebase_address + 0x200 + ((_vector_spacing << 5) * 49) : | |
414 | + { | |
415 | + KEEP(*(.vector_49)) | |
416 | + } > exception_mem | |
417 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_49) <= (_vector_spacing << 5), "function at exception vector 49 too large") | |
418 | + .vector_50 _ebase_address + 0x200 + ((_vector_spacing << 5) * 50) : | |
419 | + { | |
420 | + KEEP(*(.vector_50)) | |
421 | + } > exception_mem | |
422 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_50) <= (_vector_spacing << 5), "function at exception vector 50 too large") | |
423 | + .vector_51 _ebase_address + 0x200 + ((_vector_spacing << 5) * 51) : | |
424 | + { | |
425 | + KEEP(*(.vector_51)) | |
426 | + } > exception_mem | |
427 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_51) <= (_vector_spacing << 5), "function at exception vector 51 too large") | |
428 | + .vector_52 _ebase_address + 0x200 + ((_vector_spacing << 5) * 52) : | |
429 | + { | |
430 | + KEEP(*(.vector_52)) | |
431 | + } > exception_mem | |
432 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_52) <= (_vector_spacing << 5), "function at exception vector 52 too large") | |
433 | + .vector_53 _ebase_address + 0x200 + ((_vector_spacing << 5) * 53) : | |
434 | + { | |
435 | + KEEP(*(.vector_53)) | |
436 | + } > exception_mem | |
437 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_53) <= (_vector_spacing << 5), "function at exception vector 53 too large") | |
438 | + .vector_54 _ebase_address + 0x200 + ((_vector_spacing << 5) * 54) : | |
439 | + { | |
440 | + KEEP(*(.vector_54)) | |
441 | + } > exception_mem | |
442 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_54) <= (_vector_spacing << 5), "function at exception vector 54 too large") | |
443 | + .vector_55 _ebase_address + 0x200 + ((_vector_spacing << 5) * 55) : | |
444 | + { | |
445 | + KEEP(*(.vector_55)) | |
446 | + } > exception_mem | |
447 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_55) <= (_vector_spacing << 5), "function at exception vector 55 too large") | |
448 | + .vector_56 _ebase_address + 0x200 + ((_vector_spacing << 5) * 56) : | |
449 | + { | |
450 | + KEEP(*(.vector_56)) | |
451 | + } > exception_mem | |
452 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_56) <= (_vector_spacing << 5), "function at exception vector 56 too large") | |
453 | + .vector_57 _ebase_address + 0x200 + ((_vector_spacing << 5) * 57) : | |
454 | + { | |
455 | + KEEP(*(.vector_57)) | |
456 | + } > exception_mem | |
457 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_57) <= (_vector_spacing << 5), "function at exception vector 57 too large") | |
458 | + .vector_58 _ebase_address + 0x200 + ((_vector_spacing << 5) * 58) : | |
459 | + { | |
460 | + KEEP(*(.vector_58)) | |
461 | + } > exception_mem | |
462 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_58) <= (_vector_spacing << 5), "function at exception vector 58 too large") | |
463 | + .vector_59 _ebase_address + 0x200 + ((_vector_spacing << 5) * 59) : | |
464 | + { | |
465 | + KEEP(*(.vector_59)) | |
466 | + } > exception_mem | |
467 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_59) <= (_vector_spacing << 5), "function at exception vector 59 too large") | |
468 | + .vector_60 _ebase_address + 0x200 + ((_vector_spacing << 5) * 60) : | |
469 | + { | |
470 | + KEEP(*(.vector_60)) | |
471 | + } > exception_mem | |
472 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_60) <= (_vector_spacing << 5), "function at exception vector 60 too large") | |
473 | + .vector_61 _ebase_address + 0x200 + ((_vector_spacing << 5) * 61) : | |
474 | + { | |
475 | + KEEP(*(.vector_61)) | |
476 | + } > exception_mem | |
477 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_61) <= (_vector_spacing << 5), "function at exception vector 61 too large") | |
478 | + .vector_62 _ebase_address + 0x200 + ((_vector_spacing << 5) * 62) : | |
479 | + { | |
480 | + KEEP(*(.vector_62)) | |
481 | + } > exception_mem | |
482 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_62) <= (_vector_spacing << 5), "function at exception vector 62 too large") | |
483 | + .vector_63 _ebase_address + 0x200 + ((_vector_spacing << 5) * 63) : | |
484 | + { | |
485 | + KEEP(*(.vector_63)) | |
486 | + } > exception_mem | |
487 | + ASSERT (_vector_spacing == 0 || SIZEOF(.vector_63) <= (_vector_spacing << 5), "function at exception vector 63 too large") | |
488 | + | |
489 | + /* The startup code is in the .reset.startup section. | |
490 | + * Keep this here for backwards compatibility with older | |
491 | + * C32 v1.xx releases. | |
492 | + */ | |
493 | + .startup ORIGIN(kseg0_boot_mem) : | |
494 | + { | |
495 | + KEEP(*(.startup)) | |
496 | + } > kseg0_boot_mem | |
497 | + /* Code Sections - Note that input sections *(.text) and *(.text.*) | |
498 | + ** are not mapped here. The best-fit allocator locates them, | |
499 | + ** so that .text may flow around absolute sections as needed. | |
500 | + */ | |
501 | + .text : | |
502 | + { | |
503 | + *(.stub .gnu.linkonce.t.*) | |
504 | + KEEP (*(.text.*personality*)) | |
505 | + *(.mips16.fn.*) | |
506 | + *(.mips16.call.*) | |
507 | + *(.gnu.warning) | |
508 | + . = ALIGN(4) ; | |
509 | + } >kseg0_program_mem | |
510 | + /* Global-namespace object initialization */ | |
511 | + .init : | |
512 | + { | |
513 | + KEEP (*crti.o(.init)) | |
514 | + KEEP (*crtbegin.o(.init)) | |
515 | + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o *crtn.o ).init)) | |
516 | + KEEP (*crtend.o(.init)) | |
517 | + KEEP (*crtn.o(.init)) | |
518 | + . = ALIGN(4) ; | |
519 | + } >kseg0_program_mem | |
520 | + .fini : | |
521 | + { | |
522 | + KEEP (*(.fini)) | |
523 | + . = ALIGN(4) ; | |
524 | + } >kseg0_program_mem | |
525 | + .preinit_array : | |
526 | + { | |
527 | + PROVIDE_HIDDEN (__preinit_array_start = .); | |
528 | + KEEP (*(.preinit_array)) | |
529 | + PROVIDE_HIDDEN (__preinit_array_end = .); | |
530 | + . = ALIGN(4) ; | |
531 | + } >kseg0_program_mem | |
532 | + .init_array : | |
533 | + { | |
534 | + PROVIDE_HIDDEN (__init_array_start = .); | |
535 | + KEEP (*(SORT(.init_array.*))) | |
536 | + KEEP (*(.init_array)) | |
537 | + PROVIDE_HIDDEN (__init_array_end = .); | |
538 | + . = ALIGN(4) ; | |
539 | + } >kseg0_program_mem | |
540 | + .fini_array : | |
541 | + { | |
542 | + PROVIDE_HIDDEN (__fini_array_start = .); | |
543 | + KEEP (*(SORT(.fini_array.*))) | |
544 | + KEEP (*(.fini_array)) | |
545 | + PROVIDE_HIDDEN (__fini_array_end = .); | |
546 | + . = ALIGN(4) ; | |
547 | + } >kseg0_program_mem | |
548 | + .ctors : | |
549 | + { | |
550 | + /* XC32 uses crtbegin.o to find the start of | |
551 | + the constructors, so we make sure it is | |
552 | + first. Because this is a wildcard, it | |
553 | + doesn't matter if the user does not | |
554 | + actually link against crtbegin.o; the | |
555 | + linker won't look for a file to match a | |
556 | + wildcard. The wildcard also means that it | |
557 | + doesn't matter which directory crtbegin.o | |
558 | + is in. */ | |
559 | + KEEP (*crtbegin.o(.ctors)) | |
560 | + KEEP (*crtbegin?.o(.ctors)) | |
561 | + /* We don't want to include the .ctor section from | |
562 | + the crtend.o file until after the sorted ctors. | |
563 | + The .ctor section from the crtend file contains the | |
564 | + end of ctors marker and it must be last */ | |
565 | + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) | |
566 | + KEEP (*(SORT(.ctors.*))) | |
567 | + KEEP (*(.ctors)) | |
568 | + . = ALIGN(4) ; | |
569 | + } >kseg0_program_mem | |
570 | + .dtors : | |
571 | + { | |
572 | + KEEP (*crtbegin.o(.dtors)) | |
573 | + KEEP (*crtbegin?.o(.dtors)) | |
574 | + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) | |
575 | + KEEP (*(SORT(.dtors.*))) | |
576 | + KEEP (*(.dtors)) | |
577 | + . = ALIGN(4) ; | |
578 | + } >kseg0_program_mem | |
579 | + /* Read-only sections */ | |
580 | + .rodata : | |
581 | + { | |
582 | + *( .gnu.linkonce.r.*) | |
583 | + *(.rodata1) | |
584 | + . = ALIGN(4) ; | |
585 | + } >kseg0_program_mem | |
586 | + /* | |
587 | + * Small initialized constant global and static data can be placed in the | |
588 | + * .sdata2 section. This is different from .sdata, which contains small | |
589 | + * initialized non-constant global and static data. | |
590 | + */ | |
591 | + .sdata2 ALIGN(4) : | |
592 | + { | |
593 | + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) | |
594 | + . = ALIGN(4) ; | |
595 | + } >kseg0_program_mem | |
596 | + /* | |
597 | + * Uninitialized constant global and static data (i.e., variables which will | |
598 | + * always be zero). Again, this is different from .sbss, which contains | |
599 | + * small non-initialized, non-constant global and static data. | |
600 | + */ | |
601 | + .sbss2 ALIGN(4) : | |
602 | + { | |
603 | + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) | |
604 | + . = ALIGN(4) ; | |
605 | + } >kseg0_program_mem | |
606 | + .eh_frame_hdr : | |
607 | + { | |
608 | + *(.eh_frame_hdr) | |
609 | + } >kseg0_program_mem | |
610 | + . = ALIGN(4) ; | |
611 | + .eh_frame : ONLY_IF_RO | |
612 | + { | |
613 | + KEEP (*(.eh_frame)) | |
614 | + } >kseg0_program_mem | |
615 | + . = ALIGN(4) ; | |
616 | + .gcc_except_table : ONLY_IF_RO | |
617 | + { | |
618 | + *(.gcc_except_table .gcc_except_table.*) | |
619 | + } >kseg0_program_mem | |
620 | + . = ALIGN(4) ; | |
621 | + .dbg_data (NOLOAD) : | |
622 | + { | |
623 | + . += (DEFINED (_DEBUGGER) ? 0x200 : 0x0); | |
624 | + } >kseg1_data_mem | |
625 | + .jcr : | |
626 | + { | |
627 | + KEEP (*(.jcr)) | |
628 | + . = ALIGN(4) ; | |
629 | + } >kseg1_data_mem | |
630 | + .eh_frame : ONLY_IF_RW | |
631 | + { | |
632 | + KEEP (*(.eh_frame)) | |
633 | + } >kseg1_data_mem | |
634 | + . = ALIGN(4) ; | |
635 | + .gcc_except_table : ONLY_IF_RW | |
636 | + { | |
637 | + *(.gcc_except_table .gcc_except_table.*) | |
638 | + } >kseg1_data_mem | |
639 | + . = ALIGN(4) ; | |
640 | + /* Persistent data - Use the new C 'persistent' attribute instead. */ | |
641 | + .persist : | |
642 | + { | |
643 | + _persist_begin = .; | |
644 | + *(.persist .persist.*) | |
645 | + *(.pbss .pbss.*) | |
646 | + . = ALIGN(4) ; | |
647 | + _persist_end = .; | |
648 | + } >kseg1_data_mem | |
649 | + /* | |
650 | + * Note that input sections named .data* are not mapped here. | |
651 | + * The best-fit allocator locates them, so that they may flow | |
652 | + * around absolute sections as needed. | |
653 | + */ | |
654 | + .data : | |
655 | + { | |
656 | + *( .gnu.linkonce.d.*) | |
657 | + SORT(CONSTRUCTORS) | |
658 | + *(.data1) | |
659 | + . = ALIGN(4) ; | |
660 | + } >kseg1_data_mem | |
661 | + . = .; | |
662 | + _gp = ALIGN(16) + 0x7ff0; | |
663 | + .got ALIGN(4) : | |
664 | + { | |
665 | + *(.got.plt) *(.got) | |
666 | + . = ALIGN(4) ; | |
667 | + } >kseg1_data_mem /* AT>kseg0_program_mem */ | |
668 | + /* | |
669 | + * Note that 'small' data sections are still mapped in the linker | |
670 | + * script. This ensures that they are grouped together for | |
671 | + * gp-relative addressing. Absolute sections are allocated after | |
672 | + * the 'small' data sections so small data cannot flow around them. | |
673 | + */ | |
674 | + /* | |
675 | + * We want the small data sections together, so single-instruction offsets | |
676 | + * can access them all, and initialized data all before uninitialized, so | |
677 | + * we can shorten the on-disk segment size. | |
678 | + */ | |
679 | + .sdata ALIGN(4) : | |
680 | + { | |
681 | + _sdata_begin = . ; | |
682 | + *(.sdata .sdata.* .gnu.linkonce.s.*) | |
683 | + . = ALIGN(4) ; | |
684 | + _sdata_end = . ; | |
685 | + } >kseg1_data_mem | |
686 | + .lit8 : | |
687 | + { | |
688 | + *(.lit8) | |
689 | + } >kseg1_data_mem | |
690 | + .lit4 : | |
691 | + { | |
692 | + *(.lit4) | |
693 | + } >kseg1_data_mem | |
694 | + . = ALIGN (4) ; | |
695 | + _data_end = . ; | |
696 | + _bss_begin = . ; | |
697 | + .sbss ALIGN(4) : | |
698 | + { | |
699 | + _sbss_begin = . ; | |
700 | + *(.dynsbss) | |
701 | + *(.sbss .sbss.* .gnu.linkonce.sb.*) | |
702 | + *(.scommon) | |
703 | + _sbss_end = . ; | |
704 | + . = ALIGN(4) ; | |
705 | + } >kseg1_data_mem | |
706 | + /* | |
707 | + * Align here to ensure that the .bss section occupies space up to | |
708 | + * _end. Align after .bss to ensure correct alignment even if the | |
709 | + * .bss section disappears because there are no input sections. | |
710 | + * | |
711 | + * Note that input sections named .bss* are no longer mapped here. | |
712 | + * The best-fit allocator locates them, so that they may flow | |
713 | + * around absolute sections as needed. | |
714 | + * | |
715 | + */ | |
716 | + .bss : | |
717 | + { | |
718 | + *(.dynbss) | |
719 | + *(COMMON) | |
720 | + /* Align here to ensure that the .bss section occupies space up to | |
721 | + _end. Align after .bss to ensure correct alignment even if the | |
722 | + .bss section disappears because there are no input sections. */ | |
723 | + . = ALIGN(. != 0 ? 4 : 1); | |
724 | + } >kseg1_data_mem | |
725 | + . = ALIGN(4) ; | |
726 | + _end = . ; | |
727 | + _bss_end = . ; | |
728 | + /* | |
729 | + * The heap and stack are best-fit allocated by the linker after other | |
730 | + * data and bss sections have been allocated. | |
731 | + */ | |
732 | + /* | |
733 | + * RAM functions go at the end of our stack and heap allocation. | |
734 | + * Alignment of 2K required by the boundary register (BMXDKPBA). | |
735 | + * | |
736 | + * RAM functions are now allocated by the linker. The linker generates | |
737 | + * _ramfunc_begin and _bmxdkpba_address symbols depending on the | |
738 | + * location of RAM functions. | |
739 | + */ | |
740 | + _bmxdudba_address = LENGTH(kseg1_data_mem) ; | |
741 | + _bmxdupba_address = LENGTH(kseg1_data_mem) ; | |
742 | + /* The .pdr section belongs in the absolute section */ | |
743 | + /DISCARD/ : { *(.pdr) } | |
744 | + .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } | |
745 | + .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } | |
746 | + .mdebug.abi32 : { KEEP(*(.mdebug.abi32)) } | |
747 | + .mdebug.abiN32 : { KEEP(*(.mdebug.abiN32)) } | |
748 | + .mdebug.abi64 : { KEEP(*(.mdebug.abi64)) } | |
749 | + .mdebug.abiO64 : { KEEP(*(.mdebug.abiO64)) } | |
750 | + .mdebug.eabi32 : { KEEP(*(.mdebug.eabi32)) } | |
751 | + .mdebug.eabi64 : { KEEP(*(.mdebug.eabi64)) } | |
752 | + .gcc_compiled_long32 : { KEEP(*(.gcc_compiled_long32)) } | |
753 | + .gcc_compiled_long64 : { KEEP(*(.gcc_compiled_long64)) } | |
754 | + /* Stabs debugging sections. */ | |
755 | + .stab 0 : { *(.stab) } | |
756 | + .stabstr 0 : { *(.stabstr) } | |
757 | + .stab.excl 0 : { *(.stab.excl) } | |
758 | + .stab.exclstr 0 : { *(.stab.exclstr) } | |
759 | + .stab.index 0 : { *(.stab.index) } | |
760 | + .stab.indexstr 0 : { *(.stab.indexstr) } | |
761 | + .comment 0 : { *(.comment) } | |
762 | + /* DWARF debug sections used by MPLAB X for source-level debugging. | |
763 | + Symbols in the DWARF debugging sections are relative to the beginning | |
764 | + of the section so we begin them at 0. */ | |
765 | + /* DWARF 1 */ | |
766 | + .debug 0 : { *(.debug) } | |
767 | + .line 0 : { *(.line) } | |
768 | + /* GNU DWARF 1 extensions */ | |
769 | + .debug_srcinfo 0 : { *(.debug_srcinfo) } | |
770 | + .debug_sfnames 0 : { *(.debug_sfnames) } | |
771 | + /* DWARF 1.1 and DWARF 2 */ | |
772 | + .debug_aranges 0 : { *(.debug_aranges) } | |
773 | + .debug_pubnames 0 : { *(.debug_pubnames) } | |
774 | + /* DWARF 2 */ | |
775 | + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } | |
776 | + .debug_abbrev 0 : { *(.debug_abbrev) } | |
777 | + .debug_line 0 : { *(.debug_line) } | |
778 | + .debug_frame 0 : { *(.debug_frame) } | |
779 | + .debug_str 0 : { *(.debug_str) } | |
780 | + .debug_loc 0 : { *(.debug_loc) } | |
781 | + .debug_macinfo 0 : { *(.debug_macinfo) } | |
782 | + /* SGI/MIPS DWARF 2 extensions */ | |
783 | + .debug_weaknames 0 : { *(.debug_weaknames) } | |
784 | + .debug_funcnames 0 : { *(.debug_funcnames) } | |
785 | + .debug_typenames 0 : { *(.debug_typenames) } | |
786 | + .debug_varnames 0 : { *(.debug_varnames) } | |
787 | + .debug_pubtypes 0 : { *(.debug_pubtypes) } | |
788 | + .debug_ranges 0 : { *(.debug_ranges) } | |
789 | + /DISCARD/ : { *(.rel.dyn) } | |
790 | + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } | |
791 | + /DISCARD/ : { *(.note.GNU-stack) } | |
792 | + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.discard) } | |
793 | +} | |
794 | + |
@@ -0,0 +1,39 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +#ifndef BOOL | |
9 | + typedef enum _BOOL { FALSE = 0, TRUE } BOOL; | |
10 | +#endif | |
11 | + | |
12 | +#ifndef BYTE | |
13 | + #define BYTE unsigned char | |
14 | +#endif | |
15 | + | |
16 | +#ifndef WORD | |
17 | + #define WORD unsigned short | |
18 | +#endif | |
19 | + | |
20 | +#ifndef DWORD | |
21 | + #define DWORD unsigned long | |
22 | +#endif | |
23 | + | |
24 | +#ifndef UINT16 | |
25 | + #define UINT16 unsigned short | |
26 | +#endif | |
27 | + | |
28 | +#ifndef size_t | |
29 | + #define size_t unsigned int | |
30 | +#endif | |
31 | + | |
32 | +// Used for asm("wait") | |
33 | +#define WAIT "wait" | |
34 | + | |
35 | +#include "interface/videoout.h" | |
36 | +#include "interface/SDFSIO.h" | |
37 | +#include "interface/ps2keyboard.h" | |
38 | +#include "interface/keyinput.h" | |
39 | +#include "debug.h" |
@@ -0,0 +1,106 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "compiler.h" | |
13 | + | |
14 | +const unsigned int g_initial_s5_stack[3]={ | |
15 | + 0, // -8($s5): no object | |
16 | + (unsigned int) &g_initial_s5_stack[2], // -4($s5): previous $s5 (recursive) | |
17 | + 0 // 0($s5): no parameter | |
18 | +}; | |
19 | + | |
20 | +static int g_args_stack; | |
21 | +/* | |
22 | + See ARGS_SP_XXXX and ARGS_S5_XXXX in compiler.h | |
23 | + At least 4 stacks are needed even without argument | |
24 | + 4($sp) = -12($s5): $sp | |
25 | + 8($sp) = -8($s5): $v0 - pointer to object or previous -8($s5) | |
26 | + 12($sp) = -4($s5): previous $s5 | |
27 | + 16($sp) = 0($s5): number of arguments | |
28 | + 20($sp) = 4($s5): first argument | |
29 | + $v0 must be the pointer to an object before comming to this code. | |
30 | + After this code, -12($s5) must be set to $sp: 0xAEBDFFF4 sw sp,-12(s5) | |
31 | +*/ | |
32 | +char* prepare_args_stack(char start_char){ | |
33 | + // start_char is either ',' or '(' | |
34 | + // When ',' mode, there must be a ',' if argument(s) exist(s). | |
35 | + // When '(' mode, there shouldn't be a '(', because this character has passed. | |
36 | + char* err; | |
37 | + int opos,stack; | |
38 | + stack=0; | |
39 | + opos=g_objpos; | |
40 | + check_obj_space(2); | |
41 | + g_object[g_objpos++]=0x27BD0000; // addiu sp,sp,-xx | |
42 | + // 8(sp) is for $v0, which is pointer to an object | |
43 | + g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp) | |
44 | + next_position(); | |
45 | + do { | |
46 | + if (!stack) { | |
47 | + // First parameter if exists | |
48 | + stack=16; | |
49 | + if (start_char==','){ | |
50 | + if (g_source[g_srcpos]!=',') break; | |
51 | + } else if (start_char=='('){ | |
52 | + next_position(); | |
53 | + if (g_source[g_srcpos]==')') break; | |
54 | + g_srcpos--; | |
55 | + } else { | |
56 | + return ERR_UNKNOWN; | |
57 | + } | |
58 | + } | |
59 | + g_srcpos++; | |
60 | + stack+=4; | |
61 | + err=get_stringFloatOrValue(); | |
62 | + if (err) return err; | |
63 | + check_obj_space(1); | |
64 | + g_object[g_objpos++]=0xAFA20000|stack; // sw v0,xx(sp) | |
65 | + next_position(); | |
66 | + } while (g_source[g_srcpos]==','); | |
67 | + // 12(sp) is for $s5, 16(sp) is for # of parameters | |
68 | + check_obj_space(5); | |
69 | + g_object[g_objpos++]=0xAFB5000C; // sw s5,12(sp) | |
70 | + g_object[g_objpos++]=0x34020000|(stack/4-4); // ori v0,zero,xx | |
71 | + g_object[g_objpos++]=0xAFA20010; // sw v0,16(sp) | |
72 | + g_object[g_objpos++]=0x27B50010; // addiu s5,sp,16 | |
73 | + g_object[opos]|=((0-stack)&0xFFFF); // addiu sp,sp,-xx (See above) | |
74 | + // All done. Register # of stacks to global var. | |
75 | + g_args_stack=stack; | |
76 | + return 0; | |
77 | +} | |
78 | + | |
79 | +char* remove_args_stack(void){ | |
80 | + // Remove stack | |
81 | + check_obj_space(2); | |
82 | + g_object[g_objpos++]=0x8FB5000C; // lw s5,12(sp) | |
83 | + g_object[g_objpos++]=0x27BD0000|g_args_stack; // addiu sp,sp,xx | |
84 | + return 0; | |
85 | +} | |
86 | + | |
87 | +char* args_function_main(void){ | |
88 | + char* err; | |
89 | + int i; | |
90 | + err=get_value(); | |
91 | + if (err) return err; | |
92 | + i=g_object[g_objpos-1]; | |
93 | + if ((i>>16)==0x3402) { | |
94 | + // Previous object is "ori v0,zero,xxxx". | |
95 | + i&=0xffff; | |
96 | + i=i<<2; | |
97 | + g_object[g_objpos-1]=0x8EA20000|i; // lw v0,xx(s5) | |
98 | + } else { | |
99 | + check_obj_space(3); | |
100 | + g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2 | |
101 | + g_object[g_objpos++]=0x02A21021; // addu v0,s5,v0 | |
102 | + g_object[g_objpos++]=0x8C420000; // lw v0,0(v0) | |
103 | + } | |
104 | + return 0; | |
105 | +} | |
106 | + |
@@ -0,0 +1,931 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by K.Tanaka & Katsumi | |
4 | + http://www.ze.em-net.ne.jp/~kenken/index.html | |
5 | + http://hp.vector.co.jp/authors/VA016157/ | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "compiler.h" | |
13 | + | |
14 | +static int* g_class_structure; | |
15 | + | |
16 | +/* | |
17 | + CMPDATA_CLASS structure | |
18 | + type: CMPDATA_CLASS (2) | |
19 | + len: 3 | |
20 | + data16: n/a (0) | |
21 | + record[1]: class name as integer | |
22 | + record[2]: pointer to class structure | |
23 | +*/ | |
24 | + | |
25 | +/* | |
26 | + CMPDATA_FIELD structure | |
27 | + type: CMPDATA_FIELD (3) | |
28 | + len: 2 or 3 (2: field; 3: method) | |
29 | + data16: field or method | |
30 | + CMPTYPE_PUBLIC_FIELD: 0 | |
31 | + CMPTYPE_PRIVATE_FIELD: 1 | |
32 | + CMPTYPE_PUBLIC_METHOD: 2 | |
33 | + record[1]: field/method name as integer | |
34 | + record[2]: pointer to method | |
35 | +*/ | |
36 | + | |
37 | +/* | |
38 | + CMPDATA_STATIC structure | |
39 | + type: CMPDATA_STATIC (4) | |
40 | + len: 3 | |
41 | + data16: variable number; add ALLOC_LNV_BLOCK when using | |
42 | + record[1]: class name as integer | |
43 | + record[2]: variable name as integer | |
44 | +*/ | |
45 | + | |
46 | +/* | |
47 | + CMPDATA_UNSOLVED structure | |
48 | + type: CMPDATA_UNSOLVED (5) | |
49 | + len: 4 | |
50 | + data16: CMPTYPE_NEW_FUNCTION (0) | |
51 | + record[1]: class name as integer | |
52 | + record[2]: address of code for pointer to class structure | |
53 | + record[3]: address of code for size definition | |
54 | + | |
55 | + type: CMPDATA_UNSOLVED (5) | |
56 | + len: 4 | |
57 | + data16: CMPTYPE_STATIC_METHOD (1) | |
58 | + record[1]: class name as integer | |
59 | + record[2]: method name as integer | |
60 | + record[3]: address of code for pointer to method | |
61 | + | |
62 | +*/ | |
63 | + | |
64 | +/* | |
65 | + Local prototyping | |
66 | +*/ | |
67 | +char* obj_method(int method); | |
68 | + | |
69 | +/* | |
70 | + Return code used for calling null method | |
71 | +*/ | |
72 | +static const unsigned int g_return_code[]={ | |
73 | + 0x8FA30004, // lw v1,4(sp) | |
74 | + 0x00600008, // jr v1 | |
75 | + 0x27BD0004, // addiu sp,sp,4 | |
76 | +}; | |
77 | + | |
78 | + | |
79 | + | |
80 | +char* begin_compiling_class(int class){ | |
81 | + // Initialize parameters | |
82 | + g_compiling_class=class; | |
83 | + g_class_structure=0; | |
84 | + // Register the class to cmpdata without class structure | |
85 | + return update_class_info(class); | |
86 | +} | |
87 | + | |
88 | +char* end_compiling_class(int class){ | |
89 | + char* err; | |
90 | + g_compiling_class=0; | |
91 | + // Construct class structure | |
92 | + err=construct_class_structure(class); | |
93 | + if (err) return err; | |
94 | + // Uppdate class information. | |
95 | + err=update_class_info(class); | |
96 | + if (err) return err; | |
97 | + // Resolve CMPDATA_UNSOLVED. | |
98 | + err=resolve_unresolved(class); | |
99 | + if (err) return err; | |
100 | + // Delete some cmpdata. | |
101 | + delete_cmpdata_for_class(class); | |
102 | + return 0; | |
103 | +} | |
104 | + | |
105 | +void* search_method(int* classdata,int method){ | |
106 | + int pos,i; | |
107 | + int nums=classdata[1]; | |
108 | + | |
109 | + classdata+=2; // exclude first 2 words | |
110 | + classdata+=2*(nums&0xff); // exclude public field | |
111 | + classdata+=2*((nums>>8)&0xff); // exclude private field | |
112 | + nums=(nums>>16)&0xff; // number of methods | |
113 | + for(i=0;i<nums;i++){ | |
114 | + if (classdata[0]==method) return (void*)classdata[1]; | |
115 | + classdata+=2; | |
116 | + } | |
117 | + return 0; // not found | |
118 | +} | |
119 | + | |
120 | +char* resolve_unresolved(int class){ | |
121 | + int* classdata; | |
122 | + int* record; | |
123 | + int* code; | |
124 | + int i; | |
125 | + // Get class structure | |
126 | + cmpdata_reset(); | |
127 | + while(record=cmpdata_find(CMPDATA_CLASS)){ | |
128 | + if (record[1]==class) break; | |
129 | + } | |
130 | + if (!record) return ERR_UNKNOWN; | |
131 | + classdata=(int*)record[2]; | |
132 | + // Explore CMPDATA_UNSOLVED | |
133 | + cmpdata_reset(); | |
134 | + while(record=cmpdata_find(CMPDATA_UNSOLVED)){ | |
135 | + // Note: don't use cmpdata_find() again in the loop. | |
136 | + // If used, the solved CMPDATA_UNSOLVED must be removed before. | |
137 | + if (record[1]!=class) continue; | |
138 | + switch (record[0]&0xffff) { | |
139 | + case CMPTYPE_NEW_FUNCTION: | |
140 | + // Resolve address of code for pointer to class structure | |
141 | + code=(int*)(record[2]); | |
142 | + code[0]=(code[0]&0xFFFF0000) | (((unsigned int)classdata)>>16); | |
143 | + code[1]=(code[1]&0xFFFF0000) | (((unsigned int)classdata) & 0x0000FFFF); | |
144 | + // Resolve size of object | |
145 | + code=(int*)(record[3]); | |
146 | + code[0]=(code[0]&0xFFFF0000) | (object_size(classdata) & 0x0000FFFF); | |
147 | + // All done | |
148 | + break; | |
149 | + case CMPTYPE_STATIC_METHOD: | |
150 | + // Resolve address of code for pointer to method | |
151 | + // Find method | |
152 | + i=(int)search_method(classdata,record[2]); | |
153 | + if (!i) return ERR_NOT_FIELD; | |
154 | + code=(int*)(record[3]); | |
155 | + code[0]=(code[0]&0xFC000000)|((i&0x0FFFFFFF)>>2); | |
156 | + // All done | |
157 | + break; | |
158 | + default: | |
159 | + return ERR_UNKNOWN; | |
160 | + } | |
161 | + } | |
162 | + return 0; | |
163 | +} | |
164 | + | |
165 | +char* update_class_info(int class){ | |
166 | + int* record; | |
167 | + int data[2]; | |
168 | + // Update record if exist. | |
169 | + cmpdata_reset(); | |
170 | + while(record=cmpdata_find(CMPDATA_CLASS)){ | |
171 | + if (record[1]==class) { | |
172 | + record[2]=(int)g_class_structure; | |
173 | + return 0; | |
174 | + } | |
175 | + } | |
176 | + // No record of this class yet. Insert a record. | |
177 | + data[0]=class; | |
178 | + data[1]=(int)g_class_structure; | |
179 | + return cmpdata_insert(CMPDATA_CLASS,0,&data[0],2); | |
180 | +} | |
181 | + | |
182 | +/* | |
183 | + Class structure: | |
184 | + cstruct[0]: class name as integer | |
185 | + cstruct[1]: number of fields and methods: | |
186 | + bit 0-7: # of public fields | |
187 | + bit 8-15: # of private fields | |
188 | + bit 16-23: # of public methods | |
189 | + bit 24-31: reserved | |
190 | + cstruct[x]: public field name | |
191 | + cstruct[x+1]: public field var number | |
192 | + cstruct[y]: private field name | |
193 | + cstruct[y+1]: private field var number | |
194 | + cstruct[z]: public method name | |
195 | + cstruct[z+1]: public method pointer | |
196 | +*/ | |
197 | + | |
198 | +/* | |
199 | + Object structure: | |
200 | + object[0]: pointer to class structure | |
201 | + object[1]: field value | |
202 | + ... | |
203 | + object[n]: field value | |
204 | + (according to class structure; public field(s) first, then private field(s)) | |
205 | +*/ | |
206 | + | |
207 | +char* construct_class_structure(int class){ | |
208 | + int* record; | |
209 | + int i; | |
210 | + int num=0; | |
211 | + // Register current address to global var | |
212 | + g_class_structure=&g_object[g_objpos]; | |
213 | + // Construct a class structure in object area in following lines | |
214 | + // Class name | |
215 | + check_obj_space(2); | |
216 | + g_object[g_objpos++]=class; // Class name | |
217 | + g_objpos++; // Number of fields/methods | |
218 | + // Public fields | |
219 | + cmpdata_reset(); | |
220 | + while(record=cmpdata_find(CMPDATA_FIELD)){ | |
221 | + if ((record[0]&0xffff)==CMPTYPE_PUBLIC_FIELD) { | |
222 | + num+=1<<0; | |
223 | + check_obj_space(2); | |
224 | + g_object[g_objpos++]=record[1]; // Field name | |
225 | + g_objpos++; // Var number (see below) | |
226 | + } | |
227 | + } | |
228 | + // Private fields | |
229 | + cmpdata_reset(); | |
230 | + while(record=cmpdata_find(CMPDATA_FIELD)){ | |
231 | + if ((record[0]&0xffff)==CMPTYPE_PRIVATE_FIELD) { | |
232 | + num+=1<<8; | |
233 | + check_obj_space(2); | |
234 | + g_object[g_objpos++]=record[1]; // Field name | |
235 | + g_objpos++; // Var number (see below) | |
236 | + } | |
237 | + } | |
238 | + // Public methods | |
239 | + cmpdata_reset(); | |
240 | + while(record=cmpdata_find(CMPDATA_FIELD)){ | |
241 | + if ((record[0]&0xffff)==CMPTYPE_PUBLIC_METHOD) { | |
242 | + num+=1<<16; | |
243 | + check_obj_space(2); | |
244 | + g_object[g_objpos++]=record[1]; // Method name | |
245 | + g_object[g_objpos++]=record[2]; // pointer | |
246 | + } | |
247 | + } | |
248 | + // Update number info | |
249 | + g_class_structure[1]=num; | |
250 | + // Update var numbers of fields | |
251 | + num=((num>>8)&0xff)+(num&0xff); | |
252 | + for(i=1;i<=num;i++){ | |
253 | + if (( | |
254 | + g_class_structure[i*2+1]=search_var_name(0x7FFFFFFF & g_class_structure[i*2])+ALLOC_LNV_BLOCK | |
255 | + )<ALLOC_LNV_BLOCK) return ERR_UNKNOWN; | |
256 | + } | |
257 | + return 0; | |
258 | +} | |
259 | + | |
260 | +void delete_cmpdata_for_class(int class){ | |
261 | + int* record; | |
262 | + // Delete field/method data | |
263 | + cmpdata_reset(); | |
264 | + while(record=cmpdata_find(CMPDATA_FIELD)){ | |
265 | + cmpdata_delete(record); | |
266 | + cmpdata_reset(); | |
267 | + } | |
268 | + // Delete longvar data | |
269 | + cmpdata_reset(); | |
270 | + while(record=cmpdata_find(CMPDATA_USEVAR)){ | |
271 | + cmpdata_delete(record); | |
272 | + cmpdata_reset(); | |
273 | + } | |
274 | + // Delete solved class codes | |
275 | + cmpdata_reset(); | |
276 | + while(record=cmpdata_find(CMPDATA_UNSOLVED)){ | |
277 | + if (record[1]!=class) continue; | |
278 | + cmpdata_delete(record); | |
279 | + cmpdata_reset(); | |
280 | + } | |
281 | +} | |
282 | + | |
283 | +int object_size(int* classdata){ | |
284 | + int nums=classdata[1]; | |
285 | + int size=nums&0xff; // public field | |
286 | + size+=(nums>>8)&0xff; // private | |
287 | + // Add 1 for pointer to class data. | |
288 | + return size+1; | |
289 | +} | |
290 | + | |
291 | +char* new_function(){ | |
292 | + char* err; | |
293 | + int class,size; | |
294 | + int i,stack, opos; | |
295 | + int* data; | |
296 | + int* classdata; | |
297 | + int record[3]; | |
298 | + void* init_method; | |
299 | + // Resolve class name | |
300 | + err=get_label(); | |
301 | + if (err) return err; | |
302 | + if (!g_label) return ERR_SYNTAX; | |
303 | + class=g_label; | |
304 | + record[0]=class; | |
305 | + next_position(); | |
306 | + // Get class data from cmpdata | |
307 | + // Note that the address of class structure can be resolved | |
308 | + // by using cmpdata when compiling NEW function but not running. | |
309 | + // Therefore, class table is not requred when running. | |
310 | + cmpdata_reset(); | |
311 | + while(data=cmpdata_find(CMPDATA_CLASS)){ | |
312 | + if (data[1]==class) break; | |
313 | + } | |
314 | + if (!data) return ERR_NO_CLASS; | |
315 | + classdata=(int*)data[2]; | |
316 | + if (classdata) { | |
317 | + size=object_size(classdata); | |
318 | + } else { | |
319 | + // Class structure is unsolved. | |
320 | + size=0; | |
321 | + } | |
322 | + // Create object | |
323 | + record[2]=(int)&g_object[g_objpos+3]; | |
324 | + call_quicklib_code(lib_calloc_memory,ASM_ORI_A0_ZERO_|size); | |
325 | + // First word of object is pointer to classdata | |
326 | + check_obj_space(3); | |
327 | + record[1]=(int)&g_object[g_objpos]; | |
328 | + g_object[g_objpos++]=0x3C080000|(((unsigned int)classdata)>>16); // lui t0,xxxx | |
329 | + g_object[g_objpos++]=0x35080000|(((unsigned int)classdata)&0x0000FFFF); // ori t0,t0,xxxx | |
330 | + g_object[g_objpos++]=0xAC480000; // sw t0,0(v0) | |
331 | + // Check if INIT method exists | |
332 | + if (classdata) { | |
333 | + init_method=search_method(classdata,LABEL_INIT); | |
334 | + } else { | |
335 | + // Class structure is unknown. Use null method. | |
336 | + init_method=(int*)&g_return_code[0]; | |
337 | + // Register CMPDATA | |
338 | + cmpdata_insert(CMPDATA_UNSOLVED,CMPTYPE_NEW_FUNCTION,(int*)&record[0],3); | |
339 | + g_allow_shift_obj=0; | |
340 | + } | |
341 | + if (!init_method) { | |
342 | + // All done | |
343 | + // Note that $v0 is address of object here. | |
344 | + // There should not be parameter(s). | |
345 | + if (g_source[g_srcpos]==',') return ERR_NO_INIT; | |
346 | + return 0; | |
347 | + } | |
348 | + // INIT method exists. Note that $v0 is address of object here. | |
349 | + if (g_source[g_srcpos]==',') g_srcpos++; | |
350 | + else if (g_source[g_srcpos]!=')') return ERR_SYNTAX; | |
351 | + check_obj_space(2); | |
352 | + g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 | |
353 | + g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp) | |
354 | + err=obj_method(LABEL_INIT); | |
355 | + if (err) return err; | |
356 | + g_srcpos--; // Leave ')' character for detecting end of "new" function | |
357 | + check_obj_space(2); | |
358 | + g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp) | |
359 | + g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4 | |
360 | + // All done | |
361 | + // Note that $v0 is address of object here. | |
362 | + return 0; | |
363 | +} | |
364 | + | |
365 | +char* field_statement(){ | |
366 | + char* err; | |
367 | + int i; | |
368 | + int data[1]; | |
369 | + int is_private=0; | |
370 | + // This statement is valid only in class file. | |
371 | + if (!g_compiling_class) return ERR_INVALID_NON_CLASS; | |
372 | + // Check which private or public | |
373 | + next_position(); | |
374 | + if (nextCodeIs("PRIVATE ")) { | |
375 | + is_private=1; | |
376 | + } else if (nextCodeIs("PUBLIC ")) { | |
377 | + is_private=0; | |
378 | + } | |
379 | + do { | |
380 | + next_position(); | |
381 | + i=check_var_name(); | |
382 | + if (i<65536) return ERR_SYNTAX; | |
383 | + // Register varname | |
384 | + err=register_var_name(i); | |
385 | + if (err) return err; | |
386 | + if (g_source[g_srcpos]=='#') { | |
387 | + g_srcpos++; | |
388 | + } else if (g_source[g_srcpos]=='$') { | |
389 | + // String field. Raise 31st bit. | |
390 | + g_srcpos++; | |
391 | + i|=0x80000000; | |
392 | + } else if (g_source[g_srcpos]=='(' && g_source[g_srcpos+1]==')' && is_private) { | |
393 | + // Dimension field (private only). Raise 31st bit. | |
394 | + g_srcpos++; | |
395 | + g_srcpos++; | |
396 | + i|=0x80000000; | |
397 | + } | |
398 | + // Register field | |
399 | + data[0]=i; | |
400 | + if (is_private) { | |
401 | + err=cmpdata_insert(CMPDATA_FIELD,CMPTYPE_PRIVATE_FIELD,(int*)&data[0],1); | |
402 | + } else { | |
403 | + err=cmpdata_insert(CMPDATA_FIELD,CMPTYPE_PUBLIC_FIELD,(int*)&data[0],1); | |
404 | + } | |
405 | + next_position(); | |
406 | + if (g_source[g_srcpos]==',') { | |
407 | + g_srcpos++; | |
408 | + } else { | |
409 | + break; | |
410 | + } | |
411 | + } while(1); | |
412 | + return 0; | |
413 | +} | |
414 | + | |
415 | +/* | |
416 | + char* obj_method(int method); | |
417 | + Implementation of access to method of object. | |
418 | +*/ | |
419 | +char* obj_method(int method){ | |
420 | + // $v0 contains the address of object. | |
421 | + // Note that '(' has been passed. | |
422 | + char* err; | |
423 | + int stack,opos; | |
424 | + // When method of an object is called from object, | |
425 | + // current variables must be saved to object fields | |
426 | + if (g_compiling_class) { | |
427 | + check_obj_space(1); | |
428 | + g_object[g_objpos++]=0x00402821; // addu a1,v0,zero | |
429 | + call_quicklib_code(lib_save_vars_to_fields,ASM_LW_A0_XXXX_S5|ARGS_S5_V0_OBJ); | |
430 | + } | |
431 | + // Parameters preparation (to $s5) here. | |
432 | + next_position(); | |
433 | + opos=g_objpos; | |
434 | + // Begin parameter(s) construction routine | |
435 | + err=prepare_args_stack('('); | |
436 | + if (err) return err; | |
437 | + if (g_source[g_srcpos]!=')') return ERR_SYNTAX; | |
438 | + g_srcpos++; | |
439 | + // Determine address of method and store fields to local variables. | |
440 | + check_obj_space(3); | |
441 | + g_object[g_objpos++]=0x8FA20000|ARGS_SP_V0_OBJ; // lw v0,8(sp) | |
442 | + g_object[g_objpos++]=0x3C050000|((method>>16)&0x0000FFFF); // lui a1,xxxx | |
443 | + g_object[g_objpos++]=0x34A50000|(method&0x0000FFFF); // ori a1,a1,xxxx | |
444 | + call_quicklib_code(lib_pre_method,ASM_ADDU_A0_V0_ZERO); | |
445 | + // Call method address here. Same routine for GOSUB statement with integer value is used. | |
446 | + check_obj_space(6); | |
447 | + g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 | |
448 | + g_object[g_objpos++]=0x04130003; // bgezall zero,label1 | |
449 | + g_object[g_objpos++]=0xAEBD0000|ARGS_S5_SP; // sw sp,-12(s5) | |
450 | + g_object[g_objpos++]=0x10000003; // beq zero,zero,label2 | |
451 | + g_object[g_objpos++]=0x00000000; // nop | |
452 | + // label1: | |
453 | + g_object[g_objpos++]=0x00400008; // jr v0 | |
454 | + g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp) // label2: | |
455 | + // Restore fields from local variables. | |
456 | + check_obj_space(3); | |
457 | + g_object[g_objpos++]=0x8FA40008; // lw a0,8(sp) | |
458 | + call_quicklib_code(lib_post_method,ASM_ADDU_A1_V0_ZERO); | |
459 | + // Remove stack | |
460 | + err=remove_args_stack(); | |
461 | + if (err) return err; | |
462 | + // When method of an object is called from object, | |
463 | + // current variables must be saved to object fields | |
464 | + if (g_compiling_class) { | |
465 | + check_obj_space(1); | |
466 | + g_object[g_objpos++]=0x00402821; // addu a1,v0,zero | |
467 | + call_quicklib_code(lib_load_vars_from_fields,ASM_LW_A0_XXXX_S5|ARGS_S5_V0_OBJ); | |
468 | + } | |
469 | + return 0; | |
470 | +} | |
471 | + | |
472 | +/* | |
473 | + char* integer_obj_field(); | |
474 | + char* string_obj_field(); | |
475 | + char* float_obj_field(); | |
476 | + Implementation of access to field of object. | |
477 | + This feature is recursive. When an object is applied to the field of another object, | |
478 | + following expression is possible (for example): | |
479 | + obj1.field1.field2 | |
480 | + | |
481 | +*/ | |
482 | + | |
483 | +#define OBJ_FIELD_INTEGER 0 | |
484 | +#define OBJ_FIELD_STRING '$' | |
485 | +#define OBJ_FIELD_FLOAT '#' | |
486 | + | |
487 | +char* _obj_field(char mode){ | |
488 | + // $v0 contains the address of object. | |
489 | + int i; | |
490 | + char* err; | |
491 | + do { | |
492 | + i=check_var_name(); | |
493 | + if (i<65536) return ERR_SYNTAX; | |
494 | + if (g_source[g_srcpos]=='(' && mode==OBJ_FIELD_INTEGER) { | |
495 | + // This is a method | |
496 | + g_srcpos++; | |
497 | + return obj_method(i); | |
498 | + } else if (g_source[g_srcpos+1]=='(') { | |
499 | + if (g_source[g_srcpos]==mode) { | |
500 | + // This is a string/float method | |
501 | + g_srcpos++; | |
502 | + g_srcpos++; | |
503 | + return obj_method(i); | |
504 | + } | |
505 | + } else if (g_source[g_srcpos]==mode && mode==OBJ_FIELD_STRING) { | |
506 | + // This is a string field. Raise 31st bit. | |
507 | + i|=0x80000000; | |
508 | + } | |
509 | + check_obj_space(2); | |
510 | + g_object[g_objpos++]=0x3C050000|((i>>16)&0x0000FFFF); // lui a1,xxxx | |
511 | + g_object[g_objpos++]=0x34A50000|(i&0x0000FFFF); // ori a1,a1,xxxx | |
512 | + // First and second arguments are address of object and field name, respectively. | |
513 | + call_quicklib_code(lib_obj_field,ASM_ADDU_A0_V0_ZERO); | |
514 | + // Check if "." follows | |
515 | + if (g_source[g_srcpos]=='.') { | |
516 | + // "." found. $v0 is adress of an object. See the field. | |
517 | + g_srcpos++; | |
518 | + continue; | |
519 | + } | |
520 | + } while(0); | |
521 | + // All done. Check variable type | |
522 | + if (mode==OBJ_FIELD_INTEGER) return 0; | |
523 | + else if (g_source[g_srcpos]==mode) { | |
524 | + g_srcpos++; | |
525 | + return 0; | |
526 | + } else return ERR_SYNTAX; | |
527 | +} | |
528 | + | |
529 | +char* integer_obj_field(){ | |
530 | + return _obj_field(OBJ_FIELD_INTEGER); | |
531 | +} | |
532 | + | |
533 | +char* string_obj_field(){ | |
534 | + return _obj_field(OBJ_FIELD_STRING); | |
535 | +} | |
536 | + | |
537 | +char* float_obj_field(){ | |
538 | + return _obj_field(OBJ_FIELD_FLOAT); | |
539 | +} | |
540 | + | |
541 | +int lib_obj_field(int* object, int fieldname){ | |
542 | + int* class; | |
543 | + int i,numfield; | |
544 | + // Check if this is an object (if within the RAM). | |
545 | + if (!withinRAM(object)) err_not_obj(); | |
546 | + class=(int*)object[0]; | |
547 | + if (!withinRAM(class)) err_not_obj(); | |
548 | + // Obtain # of public field | |
549 | + numfield=class[1]&0xff; | |
550 | + for(i=0;i<numfield;i++){ | |
551 | + if (class[2+i*2]==fieldname) break; | |
552 | + } | |
553 | + if (i==numfield) err_not_field(fieldname,class[0]); | |
554 | + // Got address of field. Return value as $v0 and address as $v1. | |
555 | + g_temp=(int)(&object[1+i]); | |
556 | + asm volatile("la $v1,%0"::"i"(&g_temp)); | |
557 | + asm volatile("lw $v1,0($v1)"); | |
558 | + return object[1+i]; | |
559 | +} | |
560 | + | |
561 | +/* | |
562 | + Library for letting string field | |
563 | +*/ | |
564 | + | |
565 | +void lib_let_str_field(char* prev_str, char* new_str){ | |
566 | + int var_num=get_permanent_var_num(); | |
567 | + free_perm_str(prev_str); | |
568 | + lib_let_str(new_str,var_num); | |
569 | + return; | |
570 | +} | |
571 | + | |
572 | +/* | |
573 | + Library for calling method statement | |
574 | +*/ | |
575 | + | |
576 | +int lib_load_vars_from_fields(int* object, int v0){ | |
577 | + // Do nothing if no object | |
578 | + if (object) lib_pre_method(object,LABEL_INIT); | |
579 | + return v0; | |
580 | +} | |
581 | + | |
582 | +int lib_pre_method(int* object, int methodname){ | |
583 | + int i,num,nums; | |
584 | + int* class; | |
585 | + // Check if this is an object (if within the RAM). | |
586 | + if (!withinRAM(object)) err_not_obj(); | |
587 | + class=(int*)object[0]; | |
588 | + if (!withinRAM(class)) err_not_obj(); | |
589 | + // Save object field values in local variables in class | |
590 | + nums=class[1]; | |
591 | + num=nums&0xff; | |
592 | + for(i=0;i<num;i++){ | |
593 | + // Public fields | |
594 | + class+=2; | |
595 | + g_var_mem[class[1]]=object[i+1]; | |
596 | + // When string, move from permanent block | |
597 | + if (0x80000000&class[0]) move_from_perm_block_if_exists(class[1]); | |
598 | + } | |
599 | + num+=(nums>>8)&0xff; | |
600 | + for(i=i;i<num;i++){ | |
601 | + // Private fields | |
602 | + class+=2; | |
603 | + g_var_mem[class[1]]=object[i+1]; | |
604 | + // When string/dimension, move from permanent block | |
605 | + if (0x80000000&class[0]) move_from_perm_block_if_exists(class[1]); | |
606 | + } | |
607 | + // Seek method | |
608 | + num+=(nums>>16)&0xff; | |
609 | + for(i=i;i<num;i++){ | |
610 | + class+=2; | |
611 | + if (class[0]==methodname) break; | |
612 | + } | |
613 | + if (i==num) { | |
614 | + // Method not found | |
615 | + if (methodname==LABEL_INIT) { | |
616 | + // INIT method not found | |
617 | + // Call null function | |
618 | + return (int)(&g_return_code[0]); | |
619 | + } else { | |
620 | + class=(int*)object[0]; | |
621 | + err_not_field(methodname,class[0]); | |
622 | + } | |
623 | + } | |
624 | + // Method found. return it. | |
625 | + return class[1]; | |
626 | +} | |
627 | + | |
628 | +int lib_save_vars_to_fields(int* object,int v0){ | |
629 | + int* class; | |
630 | + // Do nothing if no object | |
631 | + if (!object) return; | |
632 | + // Check if this is an object (if within the RAM). | |
633 | + if (!withinRAM(object)) err_not_obj(); | |
634 | + class=(int*)object[0]; | |
635 | + if (!withinRAM(class)) err_not_obj(); | |
636 | + // save vars | |
637 | + lib_post_method(object,0); | |
638 | + return v0; | |
639 | +} | |
640 | + | |
641 | +int lib_post_method(int* object, int v0){ | |
642 | + // Note that v0 (a1) contains the return value from a method. | |
643 | + int i,num,nums; | |
644 | + int* class; | |
645 | + // Restore local variables to object field values | |
646 | + class=(int*)object[0]; | |
647 | + nums=class[1]; | |
648 | + num=nums&0xff; | |
649 | + for(i=0;i<num;i++){ | |
650 | + // Public fields | |
651 | + class+=2; | |
652 | + object[i+1]=g_var_mem[class[1]]; | |
653 | + // When string, move to permanent block | |
654 | + if (0x80000000&class[0]) { | |
655 | + if (g_var_size[class[1]]) move_to_perm_block(class[1]); | |
656 | + } | |
657 | + } | |
658 | + num+=(nums>>8)&0xff; | |
659 | + for(i=i;i<num;i++){ | |
660 | + // Private fields | |
661 | + class+=2; | |
662 | + object[i+1]=g_var_mem[class[1]]; | |
663 | + // When string/dimension, move to permanent block | |
664 | + if (0x80000000&class[0]) { | |
665 | + if (g_var_size[class[1]]) move_to_perm_block(class[1]); | |
666 | + } | |
667 | + } | |
668 | + // all done | |
669 | + return v0; | |
670 | +} | |
671 | + | |
672 | +/* | |
673 | + Method statement | |
674 | +*/ | |
675 | + | |
676 | +char* method_statement(){ | |
677 | + char* err; | |
678 | + int data[2]; | |
679 | + int opos=g_objpos; | |
680 | + // This statement is valid only in class file. | |
681 | + if (!g_compiling_class) return ERR_INVALID_NON_CLASS; | |
682 | + // Insert label for setting $s6 | |
683 | + err=label_statement(); | |
684 | + if (err) return err; | |
685 | + // Register cmpdata | |
686 | + data[0]=g_label; | |
687 | + data[1]=(int)(&g_object[opos]); | |
688 | + return cmpdata_insert(CMPDATA_FIELD,CMPTYPE_PUBLIC_METHOD,(int*)&data[0],2); | |
689 | +} | |
690 | + | |
691 | +/* | |
692 | + Delete statement | |
693 | +*/ | |
694 | + | |
695 | +char* delete_statement(){ | |
696 | + char* err; | |
697 | + next_position(); | |
698 | + g_srcpos--; | |
699 | + do{ | |
700 | + g_srcpos++; | |
701 | + err=get_value(); | |
702 | + if (err) return err; | |
703 | + call_quicklib_code(lib_delete,ASM_ADDU_A0_V0_ZERO); | |
704 | + next_position(); | |
705 | + } while (g_source[g_srcpos]==','); | |
706 | + return 0; | |
707 | +} | |
708 | + | |
709 | +/* | |
710 | + Call statement | |
711 | +*/ | |
712 | + | |
713 | +char* call_statement(){ | |
714 | + // Just get an integer value. That is it. | |
715 | + return get_value(); | |
716 | +} | |
717 | + | |
718 | +/* | |
719 | + Static statement | |
720 | +*/ | |
721 | + | |
722 | +char* static_statement(){ | |
723 | + char* err; | |
724 | + int* record; | |
725 | + int data[2]; | |
726 | + int i; | |
727 | + int is_private=0; | |
728 | + // This statement is valid only in class file. | |
729 | + if (!g_compiling_class) return ERR_INVALID_NON_CLASS; | |
730 | + // Check which private or public | |
731 | + next_position(); | |
732 | + if (nextCodeIs("PRIVATE ")) { | |
733 | + is_private=1; | |
734 | + } else if (nextCodeIs("PUBLIC ")) { | |
735 | + is_private=0; | |
736 | + } | |
737 | + do { | |
738 | + next_position(); | |
739 | + i=check_var_name(); | |
740 | + if (i<65536) return ERR_SYNTAX; | |
741 | + if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') { | |
742 | + g_srcpos++; | |
743 | + } | |
744 | + // Register public static field | |
745 | + if (is_private) { | |
746 | + // This is the same as USEVAR | |
747 | + // Register varname | |
748 | + err=register_var_name(i); | |
749 | + if (err) return err; | |
750 | + } else { | |
751 | + // Check if there is already a CMPDATA record | |
752 | + cmpdata_reset(); | |
753 | + while(record=cmpdata_find(CMPDATA_STATIC)){ | |
754 | + if (record[1]!=g_compiling_class) continue; | |
755 | + if (record[2]!=i) continue; | |
756 | + break; | |
757 | + } | |
758 | + if (record) { | |
759 | + // There is already a record. | |
760 | + // Do not allocate new number but use the registered number; | |
761 | + i=record[0]&0xffff; | |
762 | + err=cmpdata_insert(CMPDATA_USEVAR,i,&record[2],1); | |
763 | + if (err) return err; | |
764 | + } else { | |
765 | + // Register varname | |
766 | + err=register_var_name(i); | |
767 | + if (err) return err; | |
768 | + // Insert a CMDATA_STATIC record | |
769 | + data[0]=g_compiling_class; // class name as integer | |
770 | + data[1]=i; // static var name as integer | |
771 | + i=search_var_name(i); // var number of this static field | |
772 | + if (i<0) return ERR_UNKNOWN; | |
773 | + err=cmpdata_insert(CMPDATA_STATIC,i,(int*)&data[0],2); | |
774 | + if (err) return err; | |
775 | + } | |
776 | + } | |
777 | + next_position(); | |
778 | + if (g_source[g_srcpos]==',') { | |
779 | + g_srcpos++; | |
780 | + } else { | |
781 | + break; | |
782 | + } | |
783 | + } while(1); | |
784 | + return 0; | |
785 | + | |
786 | +} | |
787 | + | |
788 | +/* | |
789 | + Static method | |
790 | + Type is either 0, '$', or '#', | |
791 | + for integer, string, or float | |
792 | +*/ | |
793 | + | |
794 | +char* static_method(char type){ | |
795 | + char* err; | |
796 | + int* data; | |
797 | + int record[3]; | |
798 | + int i,opos,method,stack; | |
799 | + next_position(); | |
800 | + // Check class name | |
801 | + i=check_var_name(); | |
802 | + if (i<65536) return ERR_SYNTAX; | |
803 | + record[0]=i; | |
804 | + // Check if the class exists | |
805 | + cmpdata_reset(); | |
806 | + while(data=cmpdata_find(CMPDATA_CLASS)){ | |
807 | + if (data[1]==i) { | |
808 | + // The class was already defined. | |
809 | + i=0; | |
810 | + break; | |
811 | + } | |
812 | + } | |
813 | + // Check '::' | |
814 | + if (g_source[g_srcpos]!=':') return ERR_SYNTAX; | |
815 | + g_srcpos++; | |
816 | + if (g_source[g_srcpos]!=':') return ERR_SYNTAX; | |
817 | + g_srcpos++; | |
818 | + if (i) return ERR_NO_CLASS; | |
819 | + data=(int*)data[2]; | |
820 | + // Check method | |
821 | + i=check_var_name(); | |
822 | + if (i<65536) return ERR_SYNTAX; | |
823 | + if (data) { | |
824 | + method=(int)search_method(data,i); | |
825 | + if (!method) return ERR_NOT_FIELD; | |
826 | + } else { | |
827 | + method=(int)&g_return_code[0]; | |
828 | + record[1]=i; | |
829 | + } | |
830 | + // Check type and '(' | |
831 | + if (type) {// Either 0, '$', or '#' | |
832 | + if (g_source[g_srcpos]!=type) return ERR_SYNTAX; | |
833 | + g_srcpos++; | |
834 | + | |
835 | + } | |
836 | + if (g_source[g_srcpos]!='(') return ERR_SYNTAX; | |
837 | + g_srcpos++; | |
838 | + // Begin parameter(s) construction routine | |
839 | + check_obj_space(1); | |
840 | + g_object[g_objpos++]=0x34020000; // ori v0,zero,0 | |
841 | + err=prepare_args_stack('('); | |
842 | + if (err) return err; | |
843 | + // Calling subroutine, which is static method of class | |
844 | + record[2]=(int)&g_object[g_objpos+5]; | |
845 | + check_obj_space(7); | |
846 | + g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 | |
847 | + g_object[g_objpos++]=0x04130003; // bgezall zero,label1 | |
848 | + g_object[g_objpos++]=0xAEBD0000|ARGS_S5_SP; // sw sp,-12(s5) | |
849 | + g_object[g_objpos++]=0x10000003; // beq zero,zero,label2 | |
850 | + g_object[g_objpos++]=0x00000000; // nop | |
851 | + // label1: | |
852 | + g_object[g_objpos++]=0x08000000|((method&0x0FFFFFFF)>>2); // j xxxx | |
853 | + g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp) | |
854 | + // label2: | |
855 | + // Register CMPDATA if required. | |
856 | + if (!data) { | |
857 | + cmpdata_insert(CMPDATA_UNSOLVED,CMPTYPE_STATIC_METHOD,(int*)&record[0],3); | |
858 | + g_allow_shift_obj=0; | |
859 | + } | |
860 | + // Remove stack | |
861 | + err=remove_args_stack(); | |
862 | + if (err) return err; | |
863 | + return 0; | |
864 | +} | |
865 | + | |
866 | +/* | |
867 | + Let object.field statement | |
868 | +*/ | |
869 | + | |
870 | +char* let_object_field(){ | |
871 | + char* err; | |
872 | + char b3; | |
873 | + int spos,opos; | |
874 | + // $v0 contains the pointer to object | |
875 | + spos=g_srcpos; | |
876 | + opos=g_objpos; | |
877 | + // Try string field, first | |
878 | + err=string_obj_field(); | |
879 | + if (err) { | |
880 | + // Integer or float field | |
881 | + g_srcpos=spos; | |
882 | + g_objpos=opos; | |
883 | + err=integer_obj_field(); | |
884 | + if (err) return err; | |
885 | + b3=g_source[g_srcpos]; | |
886 | + if (b3=='#') g_srcpos++; | |
887 | + } else { | |
888 | + // String field | |
889 | + b3='$'; | |
890 | + } | |
891 | + if (g_source[g_srcpos-1]==')') { | |
892 | + // This is a CALL statement | |
893 | + return 0; | |
894 | + } | |
895 | + // $v1 is address to store value. Save it in stack. | |
896 | + check_obj_space(1); | |
897 | + g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 | |
898 | + g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp) | |
899 | + if (b3=='$') { | |
900 | + // String field | |
901 | + // Get value | |
902 | + next_position(); | |
903 | + if (g_source[g_srcpos]!='=') return ERR_SYNTAX; | |
904 | + g_srcpos++; | |
905 | + err=get_string(); | |
906 | + } else if (b3=='#') { | |
907 | + // Float field | |
908 | + // Get value | |
909 | + next_position(); | |
910 | + if (g_source[g_srcpos]!='=') return ERR_SYNTAX; | |
911 | + g_srcpos++; | |
912 | + err=get_float(); | |
913 | + } else { | |
914 | + // Integer field | |
915 | + // Get value | |
916 | + next_position(); | |
917 | + if (g_source[g_srcpos]!='=') return ERR_SYNTAX; | |
918 | + g_srcpos++; | |
919 | + err=get_value(); | |
920 | + } | |
921 | + if (err) return err; | |
922 | + // Store in field of object | |
923 | + check_obj_space(4); | |
924 | + g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp) | |
925 | + g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4 | |
926 | + g_object[g_objpos++]=0x8C640000; // lw a0,0(v1) | |
927 | + g_object[g_objpos++]=0xAC620000; // sw v0,0(v1) | |
928 | + // Handle permanent block for string field | |
929 | + if (b3=='$') call_quicklib_code(lib_let_str_field,ASM_ADDU_A1_V0_ZERO); | |
930 | + return 0; | |
931 | +} | |
\ No newline at end of file |
@@ -0,0 +1,130 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "compiler.h" | |
13 | + | |
14 | +/* | |
15 | + This file provide functions for handling data used when compiling. | |
16 | + The data is inserted between g_objmax and file cache. | |
17 | + Data format (32 bit): | |
18 | + MSB LSB | |
19 | + +----+----+--------+ | |
20 | + |type|len | data16 | | |
21 | + +----+----+--------+ | |
22 | + where, | |
23 | + type: data type number (unsigned char) | |
24 | + len: length of data area in number of words (unsigned char) | |
25 | + data16: general 16 bit data (short) | |
26 | +*/ | |
27 | + | |
28 | +/* | |
29 | + CMPDATA_TEMP structure | |
30 | + type: CMPDATA_TEMP (6) | |
31 | + len: n+1 | |
32 | + data16: id | |
33 | + record[1]: any data | |
34 | + record[2]: any data | |
35 | + ... | |
36 | + record[n]: any data | |
37 | +*/ | |
38 | + | |
39 | +#define g_cmpdata g_objmax | |
40 | + | |
41 | +static int* g_cmpdata_end; | |
42 | +static int* g_cmpdata_point; | |
43 | +static unsigned short g_cmpdata_id; | |
44 | + | |
45 | +/* | |
46 | + Initialize routine must be called when starting compiler. | |
47 | +*/ | |
48 | +void cmpdata_init(){ | |
49 | + g_cmpdata_end=g_objmax; | |
50 | + g_cmpdata_point=g_objmax; | |
51 | + g_cmpdata_id=1; | |
52 | +} | |
53 | + | |
54 | +/* | |
55 | + Returns ID as 16 bit indivisual number | |
56 | +*/ | |
57 | +unsigned short cmpdata_get_id(){ | |
58 | + if ((++g_cmpdata_id)==0) printstr("CMPDATA: no more ID!\n"); | |
59 | + return g_cmpdata_id; | |
60 | +} | |
61 | + | |
62 | +/* | |
63 | + Function to insert a data. The data must be defined by a pointer to int array. | |
64 | + unsigned char type: Data type number (0-255) | |
65 | + short data16: 16 bit data. If not required, set 0. | |
66 | + int* data: Pointer to data array. If not requird, set 0. | |
67 | + unsigned char num: Length of above data array. If not required, set 0. | |
68 | +*/ | |
69 | +char* cmpdata_insert(unsigned char type, short data16, int* data, unsigned char num){ | |
70 | + unsigned char i; | |
71 | + g_cmpdata-=num+1; | |
72 | + if (g_cmpdata<g_object+g_objpos) return ERR_NE_BINARY; | |
73 | + g_cmpdata[0]=(type<<24)|(num+1)<<16|data16; | |
74 | + for(i=0;i<num;i++){ | |
75 | + g_cmpdata[i+1]=data[i]; | |
76 | + } | |
77 | + return 0; | |
78 | +} | |
79 | + | |
80 | +/* | |
81 | + Reset data point. Next search will be from the beginning. | |
82 | +*/ | |
83 | + | |
84 | +void cmpdata_reset(){ | |
85 | + g_cmpdata_point=g_cmpdata; | |
86 | +} | |
87 | + | |
88 | +/* | |
89 | + Find the next record with defined type. Return the pointer to the record. | |
90 | +*/ | |
91 | +int* cmpdata_find(unsigned char type){ | |
92 | + int* ret; | |
93 | + while(g_cmpdata_point<g_cmpdata_end){ | |
94 | + // Remember return value | |
95 | + ret=g_cmpdata_point; | |
96 | + // Move the point to next | |
97 | + g_cmpdata_point+=(ret[0]&0x00ff0000)>>16; | |
98 | + // Check if type is the same. If the same, return. | |
99 | + if ((ret[0]>>24)==type) return ret; | |
100 | + } | |
101 | + return 0; | |
102 | +} | |
103 | + | |
104 | +/* | |
105 | + Find the record from beginning. | |
106 | +*/ | |
107 | + | |
108 | +int* cmpdata_findfirst(unsigned char type){ | |
109 | + cmpdata_reset(); | |
110 | + return cmpdata_find(type); | |
111 | +} | |
112 | + | |
113 | +/* | |
114 | + Delete a record. | |
115 | +*/ | |
116 | +void cmpdata_delete(int* record){ | |
117 | + int delnum; | |
118 | + int* data; | |
119 | + // Ignore if invalid record. | |
120 | + if (record<g_cmpdata || g_cmpdata_end<record) return; | |
121 | + // Get number of word to delete. | |
122 | + delnum=(record[0]&0x00ff0000)>>16; | |
123 | + // Delete record by shifting data. | |
124 | + for(data=record-1;g_cmpdata<=data;data--){ | |
125 | + data[delnum]=data[0]; | |
126 | + } | |
127 | + g_cmpdata+=delnum; | |
128 | + // Reset | |
129 | + cmpdata_reset(); | |
130 | +} |
@@ -0,0 +1,183 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +/* | |
13 | + Usage of MIPS32 registors | |
14 | + $zero: always zero | |
15 | + $at: not used | |
16 | + $v0: return value or result of last calculation | |
17 | + $v1: for calculation (like $v0=$v1*$v0) | |
18 | + $a0-$a2: parameters for calling library ($a2=$v0) | |
19 | + $a3: function # for library | |
20 | + $t0-$t7: used as temporary registors | |
21 | + $s0-$s4: not used | |
22 | + $s5: pointer to parameters list | |
23 | + $s6: line or label number | |
24 | + $s7: address of call_library() | |
25 | + $t8-$t9: used as temporary registors | |
26 | + $k0-$k1: not used | |
27 | + $gp: for accessing global variables by C | |
28 | + $sp: stack pointer | |
29 | + $fp($s8) for accessing variables by BASIC | |
30 | + $ra: contains return address | |
31 | +*/ | |
32 | + | |
33 | +#include "compiler.h" | |
34 | + | |
35 | +void start_program(void* addr, void* memory){ | |
36 | + // Note that if usage of $s0-$s7, and $fp is changed, | |
37 | + // revice BasicInt() in timer.c, too. | |
38 | + static unsigned int stored_sp; | |
39 | + // Store s0-s7, fp, and ra in stacks | |
40 | + asm volatile("#":::"s0"); | |
41 | + asm volatile("#":::"s1"); | |
42 | + asm volatile("#":::"s2"); | |
43 | + asm volatile("#":::"s3"); | |
44 | + asm volatile("#":::"s4"); | |
45 | + asm volatile("#":::"s5"); | |
46 | + asm volatile("#":::"s6"); | |
47 | + asm volatile("#":::"s7"); | |
48 | + asm volatile("#":::"fp"); | |
49 | + asm volatile("#":::"ra"); | |
50 | + // Store sp in stored_sp | |
51 | + asm volatile("la $v0,%0"::"i"(&stored_sp)); | |
52 | + asm volatile("sw $sp,0($v0)"); | |
53 | + // Shift sp for safety | |
54 | + asm volatile("addiu $sp,$sp,-8"); | |
55 | + // Register vector for unexpected NEXT/RETURN | |
56 | + asm volatile("la $v0,%0"::"i"(&err_unexp_next)); | |
57 | + asm volatile("sw $v0,4($sp)"); | |
58 | + // Store end address in g_end_addr | |
59 | + asm volatile("la $v0,%0"::"i"(&g_end_addr)); | |
60 | + asm volatile("la $v1,label"); | |
61 | + asm volatile("sw $v1,0($v0)"); | |
62 | + // Set s5 for initial_s5_stack | |
63 | + asm volatile("la $s5,%0"::"i"(&g_initial_s5_stack[2])); | |
64 | + // Set s7 for easy calling call_library() | |
65 | + asm volatile("la $s7,%0"::"i"(&call_library)); | |
66 | + // Set fp and execute program | |
67 | + asm volatile("addu $fp,$zero,$a1"); | |
68 | + asm volatile("jr $a0"); | |
69 | + // Restore sp from stored_sp | |
70 | + asm volatile("label:"); | |
71 | + asm volatile("la $v0,%0"::"i"(&stored_sp)); | |
72 | + asm volatile("lw $sp,0($v0)"); | |
73 | + // Restore registers from stack and return | |
74 | + return; | |
75 | +} | |
76 | + | |
77 | +int get_gp(void){ | |
78 | + asm volatile("addu $v0,$gp,$zero"); | |
79 | +} | |
80 | + | |
81 | +int get_fp(void){ | |
82 | + asm volatile("addu $v0,$fp,$zero"); | |
83 | +} | |
84 | + | |
85 | + | |
86 | +void shift_obj(int* src, int* dst, int len){ | |
87 | + int i; | |
88 | + if (dst<src) { | |
89 | + for(i=0;i<len;i++){ | |
90 | + dst[i]=src[i]; | |
91 | + } | |
92 | + } else if (src<dst) { | |
93 | + for(i=len-1;0<=i;i--){ | |
94 | + dst[i]=src[i]; | |
95 | + } | |
96 | + } | |
97 | +} | |
98 | + | |
99 | +int strncmp(char* str1, char* str2, int len){ | |
100 | + int i; | |
101 | + for (i=0;i<len;i++) { | |
102 | + if (str1[i]>str2[i]) return 1; | |
103 | + if (str1[i]<str2[i]) return -1; | |
104 | + } | |
105 | + return 0; | |
106 | +} | |
107 | + | |
108 | +int nextCodeIs(char* str){ | |
109 | + int len; | |
110 | + next_position(); | |
111 | + for(len=0;str[len];len++); | |
112 | + if (!strncmp(g_source+g_srcpos,str,len)) { | |
113 | + if ('A'<=str[len-1] && str[len-1]<='Z') { | |
114 | + // When the last character of str is alphabet, | |
115 | + // the next character in source must be space, enter, ',', or ':'. | |
116 | + if (0x20<g_source[g_srcpos+len] && | |
117 | + g_source[g_srcpos+len]!=':' && g_source[g_srcpos+len]!=',') return 0; | |
118 | + } | |
119 | + // String matches in the current position in source. | |
120 | + g_srcpos+=len; | |
121 | + return len; | |
122 | + } else { | |
123 | + // String didn't match. | |
124 | + return 0; | |
125 | + } | |
126 | +} | |
127 | + | |
128 | +int endOfStatement(){ | |
129 | + unsigned char b; | |
130 | + next_position(); | |
131 | + b=g_source[g_srcpos]; | |
132 | + return (b<0x20 || b==':') ? 1:0; | |
133 | +} | |
134 | + | |
135 | +char* compile_line(void){ | |
136 | + char b1; | |
137 | + char* err; | |
138 | + g_line++; | |
139 | + g_fileline++; | |
140 | + // Check if line number exists | |
141 | + next_position(); | |
142 | + b1=g_source[g_srcpos]; | |
143 | + if (b1<0x20) { | |
144 | + // The end of line. | |
145 | + // Don't add $s6-setting command. | |
146 | + if (g_source[g_srcpos]==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++; | |
147 | + g_srcpos++; | |
148 | + return 0; | |
149 | + } else if ('0'<=b1 && b1<='9') { | |
150 | + // Line number exists | |
151 | + err=get_label(); | |
152 | + if (err) return err; | |
153 | + g_line=g_label; | |
154 | + } | |
155 | + // Store line number in $s6 | |
156 | + if (!(g_line&0xFFFF0000)) { | |
157 | + // Line number must be less than 65536. | |
158 | + // If not, it is invalid number. | |
159 | + // Check existing line with the same number here. | |
160 | + if (search_label(g_line)) { | |
161 | + // Error: duplicate lines | |
162 | + printstr("Line "); | |
163 | + printstr(resolve_label(g_line)); | |
164 | + return ERR_MULTIPLE_LABEL; | |
165 | + } | |
166 | + if (!g_nolinenum) { | |
167 | + check_obj_space(1); | |
168 | + g_object[g_objpos++]=0x34160000|g_line; //ori s6,zero,xxxx; | |
169 | + } | |
170 | + } | |
171 | + while(g_source[g_srcpos]!=0x0D && g_source[g_srcpos]!=0x0A){ | |
172 | + err=statement(); | |
173 | + if (err) return err; | |
174 | + next_position(); | |
175 | + if (g_source[g_srcpos]==':') { | |
176 | + g_srcpos++; | |
177 | + next_position(); | |
178 | + } | |
179 | + } | |
180 | + if (g_source[g_srcpos]==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++; | |
181 | + g_srcpos++; | |
182 | + return 0; | |
183 | +} | |
\ No newline at end of file |
@@ -0,0 +1,523 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +// Include envilonment specific configurations | |
13 | +#include "envspecific.h" | |
14 | + | |
15 | +/* Definitions */ | |
16 | +// Number of variables (including temporary ones) | |
17 | +#define ALLOC_VAR_NUM 36 | |
18 | +// Block # dedicated for PCG | |
19 | +#define ALLOC_PCG_BLOCK 36 | |
20 | +// Block # dedicated for GRAPHIC | |
21 | +#define ALLOC_GRAPHIC_BLOCK 37 | |
22 | +// Block # dedicated for PLAYWAVE | |
23 | +#define ALLOC_WAVE_BLOCK 38 | |
24 | +// Start # for long name variables | |
25 | +#define ALLOC_LNV_BLOCK 39 | |
26 | +// Number of long name variables | |
27 | +#define ALLOC_LNV_NUM 190 | |
28 | +// Start # of permanent blocks | |
29 | +#define ALLOC_PERM_BLOCK 229 | |
30 | +// Number of blocks that can be assigned for memory allocation (including all above) | |
31 | +#define ALLOC_BLOCK_NUM 329 | |
32 | + | |
33 | +// Persistent RAM bytes used for object, heap and exception data | |
34 | +#ifndef PERSISTENT_RAM_SIZE | |
35 | + // This must be defined in envspecific.h | |
36 | + #define PERSISTENT_RAM_SIZE (1024*53) | |
37 | +#endif | |
38 | +// Exception data area bytes | |
39 | +#define EXCEPTION_DATA_SIZE (64) | |
40 | +// RAM size used for object and heap | |
41 | +#define RAMSIZE (PERSISTENT_RAM_SIZE-EXCEPTION_DATA_SIZE) | |
42 | + | |
43 | +/* Enums */ | |
44 | +enum variable{ | |
45 | + VAR_INTEGER, | |
46 | + VAR_FLOAT, | |
47 | + VAR_STRING | |
48 | +}; | |
49 | + | |
50 | +#define OP_MASK 0x001F | |
51 | +enum operator{ | |
52 | + OP_VOID=0, | |
53 | + OP_OR =1, | |
54 | + OP_AND =2, | |
55 | + OP_XOR =3, | |
56 | + OP_EQ =4, | |
57 | + OP_NEQ =5, | |
58 | + OP_LT =6, | |
59 | + OP_LTE =7, | |
60 | + OP_MT =8, | |
61 | + OP_MTE =9, | |
62 | + OP_SHL =10, | |
63 | + OP_SHR =11, | |
64 | + OP_ADD =12, | |
65 | + OP_SUB =13, | |
66 | + OP_MUL =14, | |
67 | + OP_DIV =15, | |
68 | + OP_REM =16 | |
69 | +}; | |
70 | + | |
71 | +#define LIB_MASK 0xFE00 | |
72 | +#define LIB_STEP 0x0200 | |
73 | +enum libs{ | |
74 | + LIB_SOUND =LIB_STEP*0, | |
75 | + LIB_MUSICFUNC =LIB_STEP*1, | |
76 | + LIB_MUSIC =LIB_STEP*2, | |
77 | + LIB_SETDRAWCOUNT =LIB_STEP*3, | |
78 | + LIB_DRAWCOUNT =LIB_STEP*4, | |
79 | + LIB_PALETTE =LIB_STEP*5, | |
80 | + LIB_GPALETTE =LIB_STEP*6, | |
81 | + LIB_BGCOLOR =LIB_STEP*7, | |
82 | + LIB_CURSOR =LIB_STEP*8, | |
83 | + LIB_CLS =LIB_STEP*9, | |
84 | + LIB_GCLS =LIB_STEP*10, | |
85 | + LIB_COLOR =LIB_STEP*11, | |
86 | + LIB_GCOLOR =LIB_STEP*12, | |
87 | + LIB_KEYS =LIB_STEP*13, | |
88 | + LIB_RESTORE =LIB_STEP*14, | |
89 | + LIB_RESTORE2 =LIB_STEP*15, | |
90 | + LIB_READ =LIB_STEP*16, | |
91 | + LIB_MIDSTR =LIB_STEP*17, | |
92 | + LIB_CLEAR =LIB_STEP*18, | |
93 | + LIB_DIV0 =LIB_STEP*19, | |
94 | + LIB_LETSTR =LIB_STEP*20, | |
95 | + LIB_STRNCMP =LIB_STEP*21, | |
96 | + LIB_RND =LIB_STEP*22, | |
97 | + LIB_DEC =LIB_STEP*23, | |
98 | + LIB_HEX =LIB_STEP*24, | |
99 | + LIB_CHR =LIB_STEP*25, | |
100 | + LIB_CONNECT_STRING =LIB_STEP*26, | |
101 | + LIB_STRING =LIB_STEP*27, | |
102 | + LIB_PRINTSTR =LIB_STEP*28, | |
103 | + LIB_LABEL =LIB_STEP*29, | |
104 | + LIB_DIM =LIB_STEP*30, | |
105 | + LIB_VAL =LIB_STEP*31, | |
106 | + LIB_INPUT =LIB_STEP*32, | |
107 | + LIB_INKEY =LIB_STEP*33, | |
108 | + LIB_USEPCG =LIB_STEP*34, | |
109 | + LIB_PCG =LIB_STEP*35, | |
110 | + LIB_SCROLL =LIB_STEP*36, | |
111 | + LIB_WAIT =LIB_STEP*37, | |
112 | + LIB_VAR_PUSH =LIB_STEP*38, | |
113 | + LIB_VAR_POP =LIB_STEP*39, | |
114 | + LIB_SYSTEM =LIB_STEP*40, | |
115 | + LIB_SPRINTF =LIB_STEP*41, | |
116 | + LIB_FLOAT =LIB_STEP*42, | |
117 | + LIB_FLOATFUNCS =LIB_STEP*43, | |
118 | + LIB_CREAD =LIB_STEP*44, | |
119 | + LIB_USEGRAPHIC =LIB_STEP*45, | |
120 | + LIB_GRAPHIC =LIB_STEP*46, | |
121 | + LIB_WIDTH =LIB_STEP*47, | |
122 | + LIB_FILE =LIB_STEP*48, | |
123 | + LIB_PLAYWAVE =LIB_STEP*49, | |
124 | + LIB_PLAYWAVEFUNC =LIB_STEP*50, | |
125 | + LIB_SETDIR =LIB_STEP*51, | |
126 | + LIB_SETDIRFUNC =LIB_STEP*52, | |
127 | + LIB_GETDIR =LIB_STEP*53, | |
128 | + LIB_DEBUG =LIB_STEP*127, | |
129 | +}; | |
130 | + | |
131 | +// Note: OP_XXXX and FUNC_XXXX cannot be used simultaneously | |
132 | +#define FUNC_MASK 0x003F | |
133 | +#define FUNC_STEP 0x0001 | |
134 | +enum functions{ | |
135 | + FUNC_FLOAT =FUNC_STEP*0, | |
136 | + FUNC_INT =FUNC_STEP*1, | |
137 | + FUNC_VALSHARP =FUNC_STEP*2, | |
138 | + FUNC_SIN =FUNC_STEP*3, | |
139 | + FUNC_COS =FUNC_STEP*4, | |
140 | + FUNC_TAN =FUNC_STEP*5, | |
141 | + FUNC_ASIN =FUNC_STEP*6, | |
142 | + FUNC_ACOS =FUNC_STEP*7, | |
143 | + FUNC_ATAN =FUNC_STEP*8, | |
144 | + FUNC_ATAN2 =FUNC_STEP*9, | |
145 | + FUNC_SINH =FUNC_STEP*10, | |
146 | + FUNC_COSH =FUNC_STEP*11, | |
147 | + FUNC_TANH =FUNC_STEP*12, | |
148 | + FUNC_EXP =FUNC_STEP*13, | |
149 | + FUNC_LOG =FUNC_STEP*14, | |
150 | + FUNC_LOG10 =FUNC_STEP*15, | |
151 | + FUNC_POW =FUNC_STEP*16, | |
152 | + FUNC_SQRT =FUNC_STEP*17, | |
153 | + FUNC_CEIL =FUNC_STEP*18, | |
154 | + FUNC_FLOOR =FUNC_STEP*19, | |
155 | + FUNC_FABS =FUNC_STEP*20, | |
156 | + FUNC_MODF =FUNC_STEP*21, | |
157 | + FUNC_FMOD =FUNC_STEP*22, | |
158 | + FUNC_PSET =FUNC_STEP*23, | |
159 | + FUNC_LINE =FUNC_STEP*24, | |
160 | + FUNC_BOXFILL =FUNC_STEP*25, | |
161 | + FUNC_CIRCLE =FUNC_STEP*26, | |
162 | + FUNC_CIRCLEFILL =FUNC_STEP*27, | |
163 | + FUNC_GPRINT =FUNC_STEP*28, | |
164 | + FUNC_PUTBMP =FUNC_STEP*29, | |
165 | + FUNC_PUTBMP2 =FUNC_STEP*30, | |
166 | + FUNC_GCOLOR =FUNC_STEP*31, | |
167 | + FUNC_POINT =FUNC_STEP*32, | |
168 | + FUNC_FOPEN =FUNC_STEP*33, | |
169 | + FUNC_FOPENST =FUNC_STEP*34, | |
170 | + FUNC_FILE =FUNC_STEP*35, | |
171 | + FUNC_FCLOSE =FUNC_STEP*36, | |
172 | + FUNC_FINPUT =FUNC_STEP*37, | |
173 | + FUNC_FPRINTSTR =FUNC_STEP*38, | |
174 | + FUNC_FGET =FUNC_STEP*39, | |
175 | + FUNC_FPUT =FUNC_STEP*40, | |
176 | + FUNC_FSEEK =FUNC_STEP*41, | |
177 | + FUNC_FTELL =FUNC_STEP*42, | |
178 | + FUNC_FLEN =FUNC_STEP*43, | |
179 | + FUNC_FSTRING =FUNC_STEP*44, | |
180 | + FUNC_FGETC =FUNC_STEP*45, | |
181 | + FUNC_FPUTC =FUNC_STEP*46, | |
182 | + FUNC_FREMOVE =FUNC_STEP*47, | |
183 | + FUNC_FEOF =FUNC_STEP*48, | |
184 | + FUNC_FINIT =FUNC_STEP*49, | |
185 | + // MAX 63 | |
186 | +}; | |
187 | + | |
188 | +/* Global vars (see globalvers.c) */ | |
189 | +extern int g_intconst; | |
190 | +extern char g_valueisconst; | |
191 | +extern unsigned int g_rnd_seed; | |
192 | +extern unsigned int g_label; | |
193 | +extern int g_sdepth; | |
194 | +extern int g_maxsdepth; | |
195 | +extern char g_allow_shift_obj; | |
196 | +extern enum variable g_lastvar; | |
197 | +extern char* g_source; | |
198 | +extern int g_srcpos; | |
199 | +extern int g_line; | |
200 | +extern int g_fileline; | |
201 | +extern int* g_object; | |
202 | +extern int g_objpos; | |
203 | +extern int* g_objmax; | |
204 | +extern const char* g_err_str[]; | |
205 | +extern const unsigned char g_priority[]; | |
206 | +extern enum operator g_last_op; | |
207 | +extern int g_end_addr; | |
208 | +extern int g_gp; | |
209 | +extern int g_s6; | |
210 | +extern char RAM[RAMSIZE]; | |
211 | +extern unsigned int g_ex_data[EXCEPTION_DATA_SIZE/4]; | |
212 | +extern int g_var_mem[ALLOC_BLOCK_NUM]; | |
213 | +extern unsigned short g_var_pointer[ALLOC_BLOCK_NUM]; | |
214 | +extern unsigned short g_var_size[ALLOC_BLOCK_NUM]; | |
215 | +extern char g_temp_area_used; | |
216 | +extern char g_nolinenum; | |
217 | +extern int* g_heap_mem; | |
218 | +extern int g_max_mem; | |
219 | +extern char g_disable_break; | |
220 | +extern unsigned char* g_pcg_font; | |
221 | +extern char g_use_graphic; | |
222 | +extern unsigned short* g_graphic_area; | |
223 | +extern int* g_libparams; | |
224 | +extern int g_long_name_var_num; | |
225 | +extern char g_music_active; | |
226 | +extern int g_class; | |
227 | +extern int g_compiling_class; | |
228 | +extern int g_temp; | |
229 | + | |
230 | +/* Prototypes */ | |
231 | +int get_gp(void); | |
232 | +int get_fp(void); | |
233 | +void start_program(void* addr, void* memory); | |
234 | +void shift_obj(int* src, int* dst, int len); | |
235 | +char* compile_line(void); | |
236 | +int nextCodeIs(char* str); | |
237 | +int endOfStatement(); | |
238 | + | |
239 | +char* init_file(char* buff,char* appname); | |
240 | +void close_file(); | |
241 | +void read_file(int blocklen); | |
242 | +char* compile_file(); | |
243 | +int compile_and_link_file(char* buff,char* appname); | |
244 | +int compile_and_link_main_file(char* buff,char* appname); | |
245 | +int compile_and_link_class(char* buff,int class); | |
246 | + | |
247 | +void err_break(void); | |
248 | +void err_music(char* str); | |
249 | +void err_data_not_found(void); | |
250 | +void err_str_complex(void); | |
251 | +void err_label_not_found(void); | |
252 | +void err_no_mem(void); | |
253 | +void err_div_zero(void); | |
254 | +void err_unkonwn(void); | |
255 | +void err_unexp_next(void); | |
256 | +void err_no_block(void); | |
257 | +void err_invalid_param(void); | |
258 | +void err_file(void); | |
259 | +void err_wave(void); | |
260 | +void err_not_obj(void); | |
261 | +void err_not_field(int fieldname, int classname); | |
262 | +void err_str(char* str); | |
263 | +char* resolve_label(int s6); | |
264 | + | |
265 | +void musicint(); | |
266 | +void set_sound(unsigned long* data, int flagsLR); | |
267 | +int musicRemaining(int flagsLR); | |
268 | +int waveRemaining(int mode); | |
269 | +void set_music(char* str, int flagsLR); | |
270 | +void stop_music(void); | |
271 | +void init_music(void); | |
272 | +void play_wave(char* filename, int start); | |
273 | + | |
274 | +char* statement(void); | |
275 | +char* gosub_statement(); | |
276 | +char* graphic_statement(enum functions func); | |
277 | +char* fopen_statement_main(enum functions func); | |
278 | +char* fget_statement(); | |
279 | +char* fput_statement(); | |
280 | +char* fputc_statement(); | |
281 | +char* fremove_statement(); | |
282 | +char* label_statement(); | |
283 | + | |
284 | +char* function(void); | |
285 | +char* str_function(void); | |
286 | +char* float_function(void); | |
287 | + | |
288 | +void call_library(void); | |
289 | +void reset_dataread(); | |
290 | + | |
291 | +void free_temp_str(char* str); | |
292 | +void free_non_temp_str(char* str); | |
293 | +void free_perm_str(char* str); | |
294 | +void* alloc_memory(int size, int var_num); | |
295 | +void* calloc_memory(int size, int var_num); | |
296 | +void move_to_perm_block(int var_num); | |
297 | +void move_from_perm_block(int var_num); | |
298 | +int move_from_perm_block_if_exists(int var_num); | |
299 | +int get_permanent_var_num(void); | |
300 | +int get_varnum_from_address(void* address); | |
301 | +void* lib_calloc_memory(int size); | |
302 | +void lib_delete(int* object); | |
303 | + | |
304 | +char* link(void); | |
305 | +char* get_label(void); | |
306 | +void* search_label(unsigned int label); | |
307 | + | |
308 | +char* get_string(); | |
309 | +char* simple_string(void); | |
310 | + | |
311 | +char* get_operator(void); | |
312 | +char* get_floatOperator(void); | |
313 | +char* calculation(enum operator op); | |
314 | +char* calculation_float(enum operator op); | |
315 | +int lib_float(int ia0,int iv0, enum operator a1); | |
316 | + | |
317 | +int lib_file(enum functions func, int a0, int a1, int v0); | |
318 | + | |
319 | +char* get_dim_value(int i); | |
320 | +char* get_simple_value(void); | |
321 | +char* get_value(); | |
322 | +char* get_floatOrValue(); | |
323 | +char* get_stringFloatOrValue(); | |
324 | + | |
325 | +void blue_screen(void); | |
326 | + | |
327 | +char* get_float(); | |
328 | + | |
329 | +void cmpdata_init(); | |
330 | +unsigned short cmpdata_get_id(); | |
331 | +char* cmpdata_insert(unsigned char type, short data16, int* data, unsigned char num); | |
332 | +void cmpdata_reset(); | |
333 | +int* cmpdata_find(unsigned char type); | |
334 | +int* cmpdata_findfirst(unsigned char type); | |
335 | +void cmpdata_delete(int* record); | |
336 | + | |
337 | +int check_var_name(); | |
338 | +int get_var_number(); | |
339 | +int search_var_name(int nameint); | |
340 | +char* register_var_name(int nameint); | |
341 | + | |
342 | +char* update_class_info(int class); | |
343 | +char* construct_class_structure(int class); | |
344 | +void delete_cmpdata_for_class(int class); | |
345 | + | |
346 | +extern const unsigned int g_initial_s5_stack[3]; | |
347 | +char* prepare_args_stack(char start_char); | |
348 | +char* remove_args_stack(void); | |
349 | +char* args_function_main(void); | |
350 | + | |
351 | +char* begin_compiling_class(int class); | |
352 | +char* end_compiling_class(int class); | |
353 | +char* new_function(); | |
354 | +char* field_statement(); | |
355 | +char* integer_obj_field(); | |
356 | +char* string_obj_field(); | |
357 | +char* float_obj_field(); | |
358 | +int lib_obj_field(int* object, int fieldname); | |
359 | +int lib_pre_method(int* object, int methodname); | |
360 | +int lib_post_method(int* object, int v0); | |
361 | +int lib_save_vars_to_fields(int* object,int v0); | |
362 | +int lib_load_vars_from_fields(int* object, int v0); | |
363 | + | |
364 | +char* method_statement(); | |
365 | +char* delete_statement(); | |
366 | +char* call_statement(); | |
367 | +void lib_let_str_field(char* str, char* prev_str); | |
368 | +char* let_object_field(); | |
369 | +char* static_statement(); | |
370 | +char* static_method(char type); | |
371 | +char* resolve_unresolved(int class); | |
372 | + | |
373 | +void init_timer(); | |
374 | +void stop_timer(); | |
375 | +char* usetimer_statement(); | |
376 | +char* timer_statement(); | |
377 | +char* timer_function(); | |
378 | +char* interrupt_statement(); | |
379 | + | |
380 | +/* Error messages */ | |
381 | +#define ERR_SYNTAX (char*)(g_err_str[0]) | |
382 | +#define ERR_NE_BINARY (char*)(g_err_str[1]) | |
383 | +#define ERR_NE_MEMORY (char*)(g_err_str[2]) | |
384 | +#define ERR_DIV_0 (char*)(g_err_str[3]) | |
385 | +#define ERR_NY_I (char*)(g_err_str[4]) | |
386 | +#define ERR_LABEL_NF (char*)(g_err_str[5]) | |
387 | +#define ERR_LABEL_LONG (char*)(g_err_str[6]) | |
388 | +#define ERR_STR_COMPLEX (char*)(g_err_str[7]) | |
389 | +#define ERR_DATA_NF (char*)(g_err_str[8]) | |
390 | +#define ERR_UNKNOWN (char*)(g_err_str[9]) | |
391 | +#define ERR_MUSIC (char*)(g_err_str[10]) | |
392 | +#define ERR_MULTIPLE_LABEL (char*)(g_err_str[11]) | |
393 | +#define ERR_BREAK (char*)(g_err_str[12]) | |
394 | +#define ERR_UNEXP_NEXT (char*)(g_err_str[13]) | |
395 | +#define ERR_NO_BLOCK (char*)(g_err_str[14]) | |
396 | +#define ERR_GOSUB_ASH (char*)(g_err_str[15]) | |
397 | +#define ERR_INVALID_BREAK (char*)(g_err_str[16]) | |
398 | +#define ERR_INVALID_ELSEIF (char*)(g_err_str[17]) | |
399 | +#define ERR_INVALID_PARAM (char*)(g_err_str[18]) | |
400 | +#define ERR_FILE (char*)(g_err_str[19]) | |
401 | +#define ERR_INVALID_VAR_NAME (char*)(g_err_str[20]) | |
402 | +#define ERR_WAVE (char*)(g_err_str[21]) | |
403 | +#define ERR_COMPILE_CLASS (char*)(g_err_str[22]) | |
404 | +#define ERR_NO_CLASS (char*)(g_err_str[23]) | |
405 | +#define ERR_NOT_OBJ (char*)(g_err_str[24]) | |
406 | +#define ERR_NOT_FIELD (char*)(g_err_str[25]) | |
407 | +#define ERR_INVALID_NON_CLASS (char*)(g_err_str[26]) | |
408 | +#define ERR_INVALID_CLASS (char*)(g_err_str[27]) | |
409 | +#define ERR_NO_INIT (char*)(g_err_str[28]) | |
410 | + | |
411 | +/* compile data type numbers */ | |
412 | +#define CMPDATA_RESERVED 0 | |
413 | +#define CMPDATA_USEVAR 1 | |
414 | +#define CMPDATA_CLASS 2 | |
415 | +#define CMPDATA_FIELD 3 | |
416 | +#define CMPDATA_STATIC 4 | |
417 | +#define CMPDATA_UNSOLVED 5 | |
418 | +#define CMPDATA_TEMP 6 | |
419 | +// Sub types follow | |
420 | +#define CMPTYPE_PUBLIC_FIELD 0 | |
421 | +#define CMPTYPE_PRIVATE_FIELD 1 | |
422 | +#define CMPTYPE_PUBLIC_METHOD 2 | |
423 | +#define CMPTYPE_NEW_FUNCTION 0 | |
424 | +#define CMPTYPE_STATIC_METHOD 1 | |
425 | + | |
426 | + | |
427 | +/* Stack position for values in args.c */ | |
428 | +#define ARGS_SP_SP 4 | |
429 | +#define ARGS_SP_V0_OBJ 8 | |
430 | +#define ARGS_SP_PREV_S5 12 | |
431 | +#define ARGS_SP_NUM_ARGS 16 | |
432 | +#define ARGS_S5_SP (-12 & 0xFFFF) | |
433 | +#define ARGS_S5_V0_OBJ (-8 & 0xFFFF) | |
434 | +#define ARGS_S5_PREV_S5 (-4 & 0xFFFF) | |
435 | +#define ARGS_S5_NUM_ARGS (0 & 0xFFFF) | |
436 | + | |
437 | +/* | |
438 | + Hidden varname 31 bit values | |
439 | + Note that max number of 31 bit value is 0x61504BFF (for ZZZZZZ) | |
440 | +*/ | |
441 | +#define HIDDEN_VAR_THIS_OBJECT 0x7FFF0000 | |
442 | + | |
443 | +/* Macros */ | |
444 | + | |
445 | +// Lables as 31 bit integer | |
446 | +#define LABEL_INIT 0x0007df55 | |
447 | + | |
448 | +// Skip blanc(s) in source code | |
449 | +#define next_position() while(g_source[g_srcpos]==' ') {g_srcpos++;} | |
450 | + | |
451 | +// Check if object area is not full. | |
452 | +#define check_obj_space(x) if (g_objmax<g_object+g_objpos+(x)) return ERR_NE_BINARY | |
453 | + | |
454 | +// Returns priority of operator | |
455 | +#define priority(x) (int)g_priority[(int)(x)] | |
456 | + | |
457 | +// Insert code for calling library | |
458 | +//02E0F809 jalr ra,s7 | |
459 | +//24070000 addiu a3,zero,0000 | |
460 | +#define call_lib_code(x) \ | |
461 | + check_obj_space(2);\ | |
462 | + g_object[g_objpos++]=0x02E0F809;\ | |
463 | + g_object[g_objpos++]=0x24070000|((x)&0x0000FFFF) | |
464 | + | |
465 | +// Insert code for calling quick library | |
466 | +//3C081234 lui t0,0x1234 | |
467 | +//35085678 ori t0,t0,0x5678 | |
468 | +//0100F809 jalr ra,t0 | |
469 | +//00000000 nop | |
470 | +#define call_quicklib_code(x,y) do {\ | |
471 | + check_obj_space(4);\ | |
472 | + g_object[g_objpos++]=0x3C080000|(((unsigned int)(x))>>16);\ | |
473 | + g_object[g_objpos++]=0x35080000|(((unsigned int)(x))&0x0000FFFF);\ | |
474 | + g_object[g_objpos++]=0x0100F809;\ | |
475 | + g_object[g_objpos++]=(y);\ | |
476 | + } while (0) | |
477 | + | |
478 | +#define ASM_NOP 0x00000000 | |
479 | +#define ASM_ADDU_A0_V0_ZERO 0x00402021 | |
480 | +#define ASM_ADDU_A1_V0_ZERO 0x00402821 | |
481 | +#define ASM_ADDU_A2_V0_ZERO 0x00403021 | |
482 | +#define ASM_ADDU_A3_V0_ZERO 0x00403821 | |
483 | +#define ASM_ORI_A0_ZERO_ 0x34040000 | |
484 | +#define ASM_LW_A0_XXXX_S8 0x8FC40000 | |
485 | +#define ASM_LW_A0_XXXX_S5 0x8EA40000 | |
486 | + | |
487 | +// Interrupt macros | |
488 | +// 32 different type interruptions are possible | |
489 | +// See also envspecific.h for additional interruptions | |
490 | +#define INTERRUPT_TIMER 0 | |
491 | +#define INTERRUPT_DRAWCOUNT 1 | |
492 | +#define INTERRUPT_KEYS 2 | |
493 | +#define INTERRUPT_INKEY 3 | |
494 | +#define INTERRUPT_MUSIC 4 | |
495 | +#define INTERRUPT_WAVE 5 | |
496 | + | |
497 | +extern int g_interrupt_flags; | |
498 | +extern int g_int_vector[]; | |
499 | +#define raise_interrupt_flag(x) do {\ | |
500 | + if (g_int_vector[x]) {\ | |
501 | + IFS0bits.CS1IF=1;\ | |
502 | + g_interrupt_flags|=(1<<(x));\ | |
503 | + }\ | |
504 | +} while(0) | |
505 | + | |
506 | +// Division macro for unsigned long | |
507 | +// Valid for 31 bits for all cases and 32 bits for some cases | |
508 | +#define div32(x,y,z) ((((unsigned long long)((unsigned long)(x)))*((unsigned long long)((unsigned long)(y))))>>(z)) | |
509 | + | |
510 | +// Divide by 9 (valid for 32 bits) | |
511 | +#define div9_32(x) div32(x,0xe38e38e4,35) | |
512 | +#define rem9_32(x) ((x)-9*div9_32(x)) | |
513 | + | |
514 | +// Divide by 10 (valid for 32 bits) | |
515 | +#define div10_32(x) div32(x,0xcccccccd,35) | |
516 | +#define rem10_32(x) ((x)-10*div10_32(x)) | |
517 | + | |
518 | +// Divide by 36 (valid for 32 bits) | |
519 | +#define div36_32(x) div32(x,0xe38e38e4,37) | |
520 | +#define rem36_32(x) (x-36*div36_32(x)) | |
521 | + | |
522 | +// Check if within RAM | |
523 | +#define withinRAM(x) ((&RAM[0])<=((char*)(x)) && ((char*)(x))<(&RAM[RAMSIZE])) |
@@ -0,0 +1,302 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by K.Tanaka & Katsumi | |
4 | + http://www.ze.em-net.ne.jp/~kenken/index.html | |
5 | + http://hp.vector.co.jp/authors/VA016157/ | |
6 | +*/ | |
7 | + | |
8 | +#ifdef __DEBUG | |
9 | + | |
10 | +#include <xc.h> | |
11 | +#include "api.h" | |
12 | +#include "main.h" | |
13 | +#include "compiler.h" | |
14 | + | |
15 | +/* | |
16 | + Enable following line when debugging binary object. | |
17 | +*/ | |
18 | +//#include "debugdump.h" | |
19 | + | |
20 | + | |
21 | +// Pseudo reading config setting for debug mode | |
22 | +unsigned int g_DEVCFG1=0xFF7F4DDB; | |
23 | + | |
24 | +// Construct jump assembly in boot area. | |
25 | +const unsigned int _debug_boot[] __attribute__((address(0xBFC00000))) ={ | |
26 | + 0x0B401C00,// j 0x9d007000 | |
27 | + 0x00000000,// nop | |
28 | +}; | |
29 | + | |
30 | +// Use DEBUG.HEX as file name of this program. | |
31 | +const unsigned char _debug_filename[] __attribute__((address(FILENAME_FLASH_ADDRESS))) ="DEBUG.HEX"; | |
32 | + | |
33 | +static const char initext[]; | |
34 | +static const char bastext[]; | |
35 | +static const char class1text[]; | |
36 | +static const char class2text[]; | |
37 | + | |
38 | +static char* readtext; | |
39 | +static int filepos; | |
40 | + | |
41 | +/* | |
42 | + Debug dump | |
43 | + In debugdump.h: | |
44 | + __DEBUGDUMP is defined. | |
45 | + __DEBUGDUMP_FREEAREA is defined as start address of free area (1st argument of set_free_area() function) | |
46 | + const unsigned char dump[] is initialized. | |
47 | +*/ | |
48 | +#ifdef __DEBUGDUMP | |
49 | +int debugDump(){ | |
50 | + int i; | |
51 | + for(i=0;i<sizeof dump;i++){ | |
52 | + RAM[i]=dump[i]; | |
53 | + } | |
54 | + | |
55 | + g_objpos=(__DEBUGDUMP_FREEAREA-(unsigned int)g_object)/4; | |
56 | + | |
57 | + // Initialize parameters | |
58 | + g_pcg_font=0; | |
59 | + g_use_graphic=0; | |
60 | + g_graphic_area=0; | |
61 | + clearscreen(); | |
62 | + setcursor(0,0,7); | |
63 | + | |
64 | + printstr("BASIC "BASVER"\n"); | |
65 | + wait60thsec(15); | |
66 | + | |
67 | + printstr("Compiling..."); | |
68 | + | |
69 | + // Initialize the other parameters | |
70 | + // Random seed | |
71 | + g_rnd_seed=0x92D68CA2; //2463534242 | |
72 | + // Clear variables | |
73 | + for(i=0;i<ALLOC_BLOCK_NUM;i++){ | |
74 | + g_var_mem[i]=0; | |
75 | + g_var_size[i]=0; | |
76 | + } | |
77 | + // Clear key input buffer | |
78 | + for(i=0;i<256;i++){ | |
79 | + ps2keystatus[i]=0; | |
80 | + } | |
81 | + // Reset data/read. | |
82 | + reset_dataread(); | |
83 | + | |
84 | + // Assign memory | |
85 | + set_free_area((void*)(g_object+g_objpos),(void*)(&RAM[RAMSIZE])); | |
86 | + // Execute program | |
87 | + // Start program from the beginning of RAM. | |
88 | + // Work area (used for A-Z values) is next to the object code area. | |
89 | + start_program((void*)(&(RAM[0])),(void*)(&g_var_mem[0])); | |
90 | + printstr("\nOK\n"); | |
91 | + g_use_graphic=0; | |
92 | + | |
93 | + return 1; | |
94 | +} | |
95 | +#else | |
96 | +int debugDump(){ | |
97 | + return 0; | |
98 | +} | |
99 | +#endif | |
100 | + | |
101 | +/* | |
102 | + Override libsdfsio functions. | |
103 | + Here, don't use SD card, but the vertual files | |
104 | + (initext[] and bastext[]) are used. | |
105 | +*/ | |
106 | + | |
107 | +FSFILE fsfile; | |
108 | + | |
109 | +size_t FSfread(void *ptr, size_t size, size_t n, FSFILE *stream){ | |
110 | + char b; | |
111 | + size_t ret=0; | |
112 | + if (!readtext) return 0; | |
113 | + while(b=readtext[filepos]){ | |
114 | + filepos++; | |
115 | + ((char*)ptr)[ret]=b; | |
116 | + ret++; | |
117 | + if (n<=ret) break; | |
118 | + } | |
119 | + return ret; | |
120 | +} | |
121 | +FSFILE* FSfopen(const char * fileName, const char *mode){ | |
122 | + int i; | |
123 | + for(i=0;i<13;i++){ | |
124 | + if (fileName[i]=='.') break; | |
125 | + } | |
126 | + if (i==13) { | |
127 | + // Unknown file name | |
128 | + // Force BAS file | |
129 | + readtext=(char*)&bastext[0]; | |
130 | + } else if (fileName[i+1]=='I' && fileName[i+2]=='N' && fileName[i+3]=='I') { | |
131 | + // INI file | |
132 | + readtext=(char*)&initext[0]; | |
133 | + } else if (fileName[i+1]=='B' && fileName[i+2]=='A' && fileName[i+3]=='S') { | |
134 | + // Select BAS file | |
135 | + if (fileName[i-6]=='C' && fileName[i-5]=='L' && fileName[i-4]=='A' && | |
136 | + fileName[i-3]=='S' && fileName[i-2]=='S') { | |
137 | + if (fileName[i-1]=='1') readtext=(char*)&class1text[0]; | |
138 | + else if (fileName[i-1]=='2') readtext=(char*)&class2text[0]; | |
139 | + else readtext=(char*)&bastext[0]; | |
140 | + } else { | |
141 | + readtext=(char*)&bastext[0]; | |
142 | + } | |
143 | + // Try debugDump. | |
144 | + if (debugDump()) return 0; | |
145 | + } else { | |
146 | + readtext=0; | |
147 | + return 0; | |
148 | + } | |
149 | + filepos=0; | |
150 | + return &fsfile; | |
151 | +} | |
152 | +int FSfeof( FSFILE * stream ){ | |
153 | + return readtext[filepos]?1:0; | |
154 | +} | |
155 | +int FSfclose(FSFILE *fo){ | |
156 | + return 0; | |
157 | +} | |
158 | +int FSInit(void){ | |
159 | + return 1; | |
160 | +} | |
161 | +int FSremove (const char * fileName){ | |
162 | + return 0; | |
163 | +} | |
164 | +size_t FSfwrite(const void *ptr, size_t size, size_t n, FSFILE *stream){ | |
165 | + return 0; | |
166 | +} | |
167 | + | |
168 | +int FindFirst (const char * fileName, unsigned int attr, SearchRec * rec){ | |
169 | + return 0; | |
170 | +} | |
171 | +int FindNext (SearchRec * rec){ | |
172 | + return 0; | |
173 | +} | |
174 | +int FSmkdir (char * path){ | |
175 | + return 0; | |
176 | +} | |
177 | +char * FSgetcwd (char * path, int numchars){ | |
178 | + return 0; | |
179 | +} | |
180 | +int FSchdir (char * path){ | |
181 | + return 0; | |
182 | +} | |
183 | +long FSftell (FSFILE * fo){ | |
184 | + return 0; | |
185 | +} | |
186 | +int FSfseek(FSFILE *stream, long offset, int whence){ | |
187 | + return 0; | |
188 | +} | |
189 | +/* | |
190 | + ps2init() is not called. | |
191 | + Instead, not_ps2init_but_init_Timer1() is called. | |
192 | + Timer1 is used to update drawcount and drawing gloval variables. | |
193 | +*/ | |
194 | + | |
195 | +int not_ps2init_but_init_Timer1(){ | |
196 | + PR1=0x0FFF; | |
197 | + TMR1=0; | |
198 | + IFS0bits.T1IF=0; | |
199 | + T1CON=0x8000; | |
200 | + // Timer1 interrupt: priority 4 | |
201 | + IPC1bits.T1IP=4; | |
202 | + IPC1bits.T1IS=0; | |
203 | + IEC0bits.T1IE=1; | |
204 | + | |
205 | + return 0; | |
206 | +} | |
207 | + | |
208 | +#pragma interrupt timer1Int IPL4SOFT vector 4 | |
209 | + | |
210 | +void timer1Int(){ | |
211 | + IFS0bits.T1IF=0; | |
212 | + if (drawing) { | |
213 | + drawing=0; | |
214 | + drawcount++; | |
215 | + } else { | |
216 | + drawing=1; | |
217 | + } | |
218 | +} | |
219 | + | |
220 | +/* | |
221 | + initext[] and bastext[] are vertual files | |
222 | + as "MACHIKAN.INI" and "DEBUG.BAS". | |
223 | +*/ | |
224 | + | |
225 | + | |
226 | +static const char initext[]= | |
227 | +"#PRINT\n" | |
228 | +"#PRINT\n"; | |
229 | + | |
230 | +static const char bastext[]= | |
231 | +"I=1:WHILE I<=10\n" | |
232 | +"I=I+1:WEND\n" | |
233 | +"\n" | |
234 | +"I=1:DO\n" | |
235 | +"I=I+1:LOOP UNTIL I=11\n" | |
236 | +"\n" | |
237 | +"FOR I=1 TO 10\n" | |
238 | +"NEXT\n" | |
239 | +"\n" | |
240 | +"\n" | |
241 | +"\n"; | |
242 | + | |
243 | +static const char class1text[]= | |
244 | +"STATIC T1\n" | |
245 | +"useclass CLASS2\n" | |
246 | +"method T3\n" | |
247 | +" return CLASS2::T2\n" | |
248 | +"method T5\n" | |
249 | +" return T1\n" | |
250 | +"\n" | |
251 | +"\n"; | |
252 | + | |
253 | +static const char class2text[]= | |
254 | +"STATIC T2\n" | |
255 | +"useclass CLASS1\n" | |
256 | +"method T4\n" | |
257 | +" return CLASS1::T1\n" | |
258 | +"method T6\n" | |
259 | +" return T2\n" | |
260 | +"\n" | |
261 | +"\n" | |
262 | +"\n" | |
263 | +"\n"; | |
264 | + | |
265 | +/* | |
266 | + Test function for constructing assemblies from C codes. | |
267 | +*/ | |
268 | + | |
269 | +static const void* debugjumptable[]={ | |
270 | + FSfread, | |
271 | + FSfopen, | |
272 | +}; | |
273 | + | |
274 | +#define for2(x,y,z) for(x=y;x<=z;x++) | |
275 | + | |
276 | +int _debug_test(int a0, int a1, int a2, int a3, int param4, int param5){ | |
277 | + asm volatile(".set noreorder"); | |
278 | + asm volatile("addiu $v0,$zero,4772"); | |
279 | + asm volatile("loop:"); | |
280 | + asm volatile("bne $v0,$zero,loop"); | |
281 | + asm volatile("addi $v0,$v0,-1"); | |
282 | + asm volatile("wait"); | |
283 | + asm volatile("nop"); | |
284 | + asm volatile("nop"); | |
285 | + asm volatile("nop"); | |
286 | + asm volatile("nop"); | |
287 | + asm volatile("nop"); | |
288 | + asm volatile("nop"); | |
289 | + asm volatile("nop"); | |
290 | + asm volatile("nop"); | |
291 | + a2&=0xFFFFFFFC; | |
292 | + return a2+a3; | |
293 | +} | |
294 | + | |
295 | +/* | |
296 | + Break point used for debugging object code. | |
297 | + | |
298 | +g_object[g_objpos++]=0x0000000d;// break 0x0 | |
299 | + | |
300 | +*/ | |
301 | + | |
302 | +#endif // __DEBUG |
@@ -0,0 +1,34 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by K.Tanaka & Katsumi | |
4 | + http://www.ze.em-net.ne.jp/~kenken/index.html | |
5 | + http://hp.vector.co.jp/authors/VA016157/ | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#ifdef __DEBUG | |
13 | + | |
14 | +// Pseudo reading config setting for debug mode | |
15 | +extern unsigned int g_DEVCFG1; | |
16 | +#define DEVCFG1 g_DEVCFG1 | |
17 | + | |
18 | +// Do not use PS/2 keyboard | |
19 | +#define ps2init() not_ps2init_but_init_Timer1() | |
20 | +int not_ps2init_but_init_Timer1(); | |
21 | + | |
22 | +// Do not use asm("wait") but use asm("nop") | |
23 | +#undef WAIT | |
24 | +#define WAIT "nop" | |
25 | + | |
26 | +#endif // __DEBUG | |
27 | + | |
28 | +// key waiting macro | |
29 | + | |
30 | +#define debug_wait() lineinput((char*)&g_temp,3) | |
31 | +#define debug_wait_char(x) do {\ | |
32 | + printchar(x); \ | |
33 | + lineinput((char*)&g_temp,3);\ | |
34 | + } while(0) |
@@ -0,0 +1,20 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by K.Tanaka & Katsumi | |
4 | + http://www.ze.em-net.ne.jp/~kenken/index.html | |
5 | + http://hp.vector.co.jp/authors/VA016157/ | |
6 | +*/ | |
7 | + | |
8 | +#include <xc.h> | |
9 | +#include "api.h" | |
10 | +#include "editor.h" | |
11 | +#include "compiler.h" | |
12 | +#include "main.h" | |
13 | + | |
14 | +unsigned char currentfile[13],tempfile[13]; //編集中のファイル名、一時ファイル名 | |
15 | + | |
16 | +void wait60thsec(unsigned short n){ | |
17 | + // 60分のn秒ウェイト(ビデオ画面の最下行信号出力終了まで待つ) | |
18 | + n+=drawcount; | |
19 | + while(drawcount!=n) asm(WAIT); | |
20 | +} |
@@ -0,0 +1,41 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by K.Tanaka | |
4 | + http://www.ze.em-net.ne.jp/~kenken/index.html | |
5 | +*/ | |
6 | + | |
7 | +#define TBUFMAXLINE 201 //テキストバッファ数 | |
8 | + | |
9 | +#define TBUFSIZE 200 //テキストバッファ1つのサイズ | |
10 | +#define TBUFMAXSIZE (TBUFSIZE*(TBUFMAXLINE-1)) //最大バッファ容量(バッファ1行分空ける) | |
11 | +//#define EDITWIDTHX 30 //エディタ画面横幅 | |
12 | +#define EDITWIDTHY 29 //エディタ画面縦幅 | |
13 | +//#define EDITWIDTHY 39 //エディタ画面縦幅 | |
14 | +#define COLOR_NORMALTEXT 7 //通常テキスト色 | |
15 | +#define COLOR_ERRORTEXT 4 //エラーメッセージテキスト色 | |
16 | +#define COLOR_AREASELECTTEXT 4 //範囲選択テキスト色 | |
17 | +#define COLOR_BOTTOMLINE 5 //画面最下行の色 | |
18 | +#define COLOR_DIR 6 //ディレクトリ名表示の色 | |
19 | +#define FILEBUFSIZE 256 //ファイルアクセス用バッファサイズ | |
20 | +#define MAXFILENUM 200 //利用可能ファイル最大数 | |
21 | +#define PATHNAMEMAX 128 //ワーキングディレクトリパス名の最大値 | |
22 | +#define UNDOBUFSIZE 2048 //アンドゥ用バッファサイズ | |
23 | + | |
24 | +#define ERR_FILETOOBIG -1 | |
25 | +#define ERR_CANTFILEOPEN -2 | |
26 | +#define ERR_CANTWRITEFILE -3 | |
27 | + | |
28 | +#define TEMPFILENAME "~TEMP.BAS" //実行時ソース保存ファイル名 | |
29 | +#define WORKDIRFILE "~WORKDIR.TMP" //実行時パス保存ファイル名 | |
30 | + | |
31 | +#define UNDO_INSERT 1 | |
32 | +#define UNDO_OVERWRITE 2 | |
33 | +#define UNDO_DELETE 3 | |
34 | +#define UNDO_BACKSPACE 4 | |
35 | +#define UNDO_CONTINS 5 | |
36 | +#define UNDO_CONTDEL 6 | |
37 | + | |
38 | +void texteditor(void); //テキストエディタ本体 | |
39 | +int runbasic(char *s,int test); //コンパイルして実行 | |
40 | +extern unsigned char tempfile[13]; | |
41 | +void wait60thsec(unsigned short n); |
@@ -0,0 +1,268 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +#include <xc.h> | |
9 | +#include "main.h" | |
10 | +#include "compiler.h" | |
11 | +#include "api.h" | |
12 | + | |
13 | +/* | |
14 | + dymmy imprementations: | |
15 | + ps2keystatus | |
16 | + ps2init | |
17 | +*/ | |
18 | +volatile unsigned char ps2keystatus[256]; | |
19 | +void g_set_palette(unsigned char n,unsigned char b,unsigned char r,unsigned char g){ | |
20 | + set_palette(n,b,r,g); | |
21 | +} | |
22 | +void ps2init(void){} | |
23 | + | |
24 | + | |
25 | +void pre_run(){ | |
26 | + // Currently, do nothing. | |
27 | +} | |
28 | + | |
29 | +void post_run(){ | |
30 | + // Cool down | |
31 | +} | |
32 | + | |
33 | + | |
34 | +int readbuttons(){ | |
35 | + int keys; | |
36 | + LCD_CS_HI; | |
37 | + asm("nop"); | |
38 | + KEY_EN; | |
39 | + asm("nop"); | |
40 | + TRISBSET=KEYMASK; | |
41 | + asm("nop"); | |
42 | + keys=KEYPORT; | |
43 | +#if LCD_ALIGNMENT == VERTICAL | |
44 | + keys= | |
45 | + ((keys&KEYUP)? 0:1)| | |
46 | + ((keys&KEYDOWN)? 0:2)| | |
47 | + ((keys&KEYLEFT)? 0:4)| | |
48 | + ((keys&KEYRIGHT)? 0:8)| | |
49 | + ((keys&KEYSTART)? 0:16)| | |
50 | + ((keys&KEYFIRE)? 0:32); | |
51 | +#else | |
52 | + keys= | |
53 | + ((keys&KEYRIGHT)? 0:1)| | |
54 | + ((keys&KEYLEFT)? 0:2)| | |
55 | + ((keys&KEYUP)? 0:4)| | |
56 | + ((keys&KEYDOWN)? 0:8)| | |
57 | + ((keys&KEYSTART)? 0:16)| | |
58 | + ((keys&KEYFIRE)? 0:32); | |
59 | +#endif | |
60 | + KEY_DS; | |
61 | + asm("nop"); | |
62 | + TRISBCLR=KEYMASK; | |
63 | + asm("nop"); | |
64 | + LCD_CS_LO; | |
65 | + return keys; | |
66 | +} | |
67 | + | |
68 | +void scroll30(int x,int y){ | |
69 | + int i,j; | |
70 | + int vector=y*WIDTH_X1+x; | |
71 | + if (vector<0) { | |
72 | + // Copy data from upper address to lower address | |
73 | + for(i=0-vector;i<WIDTH_X1*WIDTH_Y;i++){ | |
74 | + TVRAM[i+vector]=TVRAM[i]; | |
75 | + TVRAM[WIDTH_X1*WIDTH_Y+i+vector]=TVRAM[WIDTH_X1*WIDTH_Y+i]; | |
76 | + } | |
77 | + } else if (0<vector) { | |
78 | + // Copy data from lower address to upper address | |
79 | + for(i=WIDTH_X1*WIDTH_Y-vector-1;0<=i;i--){ | |
80 | + TVRAM[i+vector]=TVRAM[i]; | |
81 | + TVRAM[WIDTH_X1*WIDTH_Y+i+vector]=TVRAM[WIDTH_X1*WIDTH_Y+i]; | |
82 | + } | |
83 | + } else { | |
84 | + return; | |
85 | + } | |
86 | + if (x<0) { | |
87 | + // Fill blanc at right | |
88 | + for(i=x;i<0;i++){ | |
89 | + for(j=WIDTH_X1+i;j<WIDTH_X1*WIDTH_Y;j+=WIDTH_X1){ | |
90 | + TVRAM[j]=0x00; | |
91 | + TVRAM[WIDTH_X1*WIDTH_Y+j]=cursorcolor; | |
92 | + } | |
93 | + } | |
94 | + } else if (0<x) { | |
95 | + // Fill blanc at left | |
96 | + for(i=0;i<x;i++){ | |
97 | + for(j=i;j<WIDTH_X1*WIDTH_Y;j+=WIDTH_X1){ | |
98 | + TVRAM[j]=0x00; | |
99 | + TVRAM[WIDTH_X1*WIDTH_Y+j]=cursorcolor; | |
100 | + } | |
101 | + } | |
102 | + } | |
103 | + if (y<0) { | |
104 | + // Fill blanc at bottom | |
105 | + for(i=WIDTH_X1*(WIDTH_Y+y);i<WIDTH_X1*WIDTH_Y;i++){ | |
106 | + TVRAM[i]=0x00; | |
107 | + TVRAM[WIDTH_X1*WIDTH_Y+i]=cursorcolor; | |
108 | + } | |
109 | + } else if (0<y) { | |
110 | + // Fill blanc at top | |
111 | + for(i=0;i<WIDTH_X1*y;i++){ | |
112 | + TVRAM[i]=0x00; | |
113 | + TVRAM[WIDTH_X1*WIDTH_Y+i]=cursorcolor; | |
114 | + } | |
115 | + } | |
116 | +} | |
117 | + | |
118 | +void scroll40(int x,int y){ | |
119 | + int i,j; | |
120 | + int vector=y*WIDTH_X2+x; | |
121 | + if (vector<0) { | |
122 | + // Copy data from upper address to lower address | |
123 | + for(i=0-vector;i<WIDTH_X2*WIDTH_Y;i++){ | |
124 | + TVRAM[i+vector]=TVRAM[i]; | |
125 | + TVRAM[WIDTH_X2*WIDTH_Y+i+vector]=TVRAM[WIDTH_X2*WIDTH_Y+i]; | |
126 | + } | |
127 | + } else if (0<vector) { | |
128 | + // Copy data from lower address to upper address | |
129 | + for(i=WIDTH_X2*WIDTH_Y-vector-1;0<=i;i--){ | |
130 | + TVRAM[i+vector]=TVRAM[i]; | |
131 | + TVRAM[WIDTH_X2*WIDTH_Y+i+vector]=TVRAM[WIDTH_X2*WIDTH_Y+i]; | |
132 | + } | |
133 | + } else { | |
134 | + return; | |
135 | + } | |
136 | + if (x<0) { | |
137 | + // Fill blanc at right | |
138 | + for(i=x;i<0;i++){ | |
139 | + for(j=WIDTH_X2+i;j<WIDTH_X2*WIDTH_Y;j+=WIDTH_X2){ | |
140 | + TVRAM[j]=0x00; | |
141 | + TVRAM[WIDTH_X2*WIDTH_Y+j]=cursorcolor; | |
142 | + } | |
143 | + } | |
144 | + } else if (0<x) { | |
145 | + // Fill blanc at left | |
146 | + for(i=0;i<x;i++){ | |
147 | + for(j=i;j<WIDTH_X2*WIDTH_Y;j+=WIDTH_X2){ | |
148 | + TVRAM[j]=0x00; | |
149 | + TVRAM[WIDTH_X2*WIDTH_Y+j]=cursorcolor; | |
150 | + } | |
151 | + } | |
152 | + } | |
153 | + if (y<0) { | |
154 | + // Fill blanc at bottom | |
155 | + for(i=WIDTH_X2*(WIDTH_Y+y);i<WIDTH_X2*WIDTH_Y;i++){ | |
156 | + TVRAM[i]=0x00; | |
157 | + TVRAM[WIDTH_X2*WIDTH_Y+i]=cursorcolor; | |
158 | + } | |
159 | + } else if (0<y) { | |
160 | + // Fill blanc at top | |
161 | + for(i=0;i<WIDTH_X2*y;i++){ | |
162 | + TVRAM[i]=0x00; | |
163 | + TVRAM[WIDTH_X2*WIDTH_Y+i]=cursorcolor; | |
164 | + } | |
165 | + } | |
166 | +} | |
167 | + | |
168 | +void scroll(int x, int y){ | |
169 | + if (twidth==40) scroll40(x,y); | |
170 | + else scroll30(x,y); | |
171 | +} | |
172 | + | |
173 | +void allocate_graphic_area(){ | |
174 | + if (!g_graphic_area) { | |
175 | + // Use this pointer like unsigned short GVRAM[G_H_WORD*G_Y_RES] __attribute__ ((aligned (4))); | |
176 | +// g_graphic_area=(unsigned short*)alloc_memory(G_H_WORD*G_Y_RES/2,ALLOC_GRAPHIC_BLOCK); | |
177 | + g_graphic_area=(void *)1; | |
178 | + // Start graphic and clear screen | |
179 | +// init_graphic(g_graphic_area); | |
180 | + init_graphic(); | |
181 | + // Move current point to (0,0) | |
182 | +// g_prev_x=g_prev_y=0; | |
183 | + } | |
184 | +} | |
185 | + | |
186 | +void usegraphic(int mode){ | |
187 | + // Modes; 0: stop GRAPHIC, 1: use GRAPHIC, 2: reset GRAPHIC and use it | |
188 | + switch(mode){ | |
189 | + case 0: | |
190 | + if (g_use_graphic){ | |
191 | + // Stop GRAPHIC if used | |
192 | + set_graphmode(0); | |
193 | + g_use_graphic=0; | |
194 | + // Set timer4 for tempo | |
195 | +// PR4=59473; // 3632*262/16-1 | |
196 | + } else { | |
197 | + // Prepare GRAPHIC area if not used and not allcated. | |
198 | + allocate_graphic_area(); | |
199 | + } | |
200 | + break; | |
201 | + case 2: | |
202 | + // Reset GRAPHIC and use it | |
203 | + g_graphic_area=0; | |
204 | + // Continue to case 1: | |
205 | + case 1: | |
206 | + case 3: | |
207 | + default: | |
208 | + // Use GRAPHIC | |
209 | + allocate_graphic_area(); | |
210 | + // Start showing GRAPHIC with mode 1, but not with mode 3 | |
211 | + if (mode !=3 && !g_use_graphic){ | |
212 | + set_graphmode(1); | |
213 | + g_use_graphic=1; | |
214 | + // Set timer4 for tempo | |
215 | +// PR4=55756; // ~=3405*262/16-1(55755.875) | |
216 | + } | |
217 | + break; | |
218 | + } | |
219 | +} | |
220 | + | |
221 | +void videowidth(int width){ | |
222 | + // Do nothing | |
223 | +} | |
224 | + | |
225 | +int lib_system(int a0, int a1 ,int v0, int a3, int g_gcolor, int g_prev_x, int g_prev_y){ | |
226 | + switch(a0){ | |
227 | + // Version info | |
228 | + case 0: return (int)SYSVER1; | |
229 | + case 1: return (int)SYSVER2; | |
230 | + case 2: return (int)BASVER; | |
231 | + case 3: return (int)FILENAME_FLASH_ADDRESS; | |
232 | + // Display info | |
233 | + case 20: return twidth; | |
234 | + case 21: return WIDTH_Y; | |
235 | + case 22: return G_X_RES; | |
236 | + case 23: return G_Y_RES; | |
237 | + case 24: return cursorcolor; | |
238 | + case 25: return g_gcolor; | |
239 | + case 26: return ((int)(cursor-TVRAM))%twidth; | |
240 | + case 27: return ((int)(cursor-TVRAM))/twidth; | |
241 | + case 28: return g_prev_x; | |
242 | + case 29: return g_prev_y; | |
243 | + // Keyboard info | |
244 | + case 40: return 0;//(int)inPS2MODE(); | |
245 | + case 41: return 0;//(int)vkey; | |
246 | + case 42: return 0;//(int)lockkey; | |
247 | + case 43: return 0;//(int)keytype; | |
248 | + // Pointers to gloval variables | |
249 | + case 100: return (int)&g_var_mem[0]; | |
250 | + case 101: return (int)&g_rnd_seed; | |
251 | + case 102: return (int)&TVRAM[0]; | |
252 | + case 103: return (int)&FontData[0]; | |
253 | + case 104: return (int)g_var_mem[ALLOC_PCG_BLOCK]; | |
254 | + case 105: return (int)g_var_mem[ALLOC_GRAPHIC_BLOCK]; | |
255 | + // Change system settings | |
256 | + case 200: | |
257 | + // ON/OFF monitor | |
258 | + if (v0) { | |
259 | +// start_composite(); | |
260 | + } else { | |
261 | +// stop_composite(); | |
262 | + } | |
263 | + break; | |
264 | + default: | |
265 | + break; | |
266 | + } | |
267 | + return 0; | |
268 | +} |
@@ -0,0 +1,37 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +#define CPU_CLOCK_HZ 48000000 | |
9 | +#define PERSISTENT_RAM_SIZE (1024*53) | |
10 | + | |
11 | +int readbuttons(); | |
12 | +void scroll(int x, int y); | |
13 | +void usegraphic(int mode); | |
14 | +void videowidth(int width); | |
15 | +int lib_system(int a0, int a1 ,int v0, int a3, int g_gcolor, int g_prev_x, int g_prev_y); | |
16 | + | |
17 | +// 30 or 40 characters per line for Zoea | |
18 | +#define printcomma() printstr(" "+rem10_32((unsigned int)(cursor-TVRAM))) | |
19 | + | |
20 | +// Check break key or buttons when executing BASIC code. | |
21 | +// In PS/2 mode, detect ctrl-break. | |
22 | +// In button mode, detect pushing four buttons are pushed simultaneously. | |
23 | +#define check_break() \ | |
24 | + if (g_disable_break==0) {\ | |
25 | + if (inPS2MODE()) {\ | |
26 | + if (ps2keystatus[0x03]) err_break();\ | |
27 | + } else {\ | |
28 | + if ((PORTB&0x4c80)==0) err_break();\ | |
29 | + }\ | |
30 | + } | |
31 | + | |
32 | +// Protozoa specific lists of statements and functions (none defined for Zoea) | |
33 | +#define ADDITIONAL_STATEMENTS | |
34 | +#define ADDITIONAL_INT_FUNCTIONS | |
35 | +#define ADDITIONAL_STR_FUNCTIONS | |
36 | +#define ADDITIONAL_RESERVED_VAR_NAMES | |
37 | +#define ADDITIONAL_INTERRUPT_FUNCTIONS |
@@ -0,0 +1,198 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "compiler.h" | |
13 | + | |
14 | +const char* g_err_str[]={ | |
15 | + "Syntax error", | |
16 | + "Not enough binary space", | |
17 | + "Not enough memory", | |
18 | + "Divided by zero", | |
19 | + "Not yet implemented", | |
20 | + "Label or line number not found: ", | |
21 | + "Label too long or too short", | |
22 | + "String too complexed", | |
23 | + "Data not found", | |
24 | + "Unknown error:", | |
25 | + "Music syntax error:'", | |
26 | + " found more than twice", | |
27 | + "Break", | |
28 | + "Unexpected NEXT or RETURN statement", | |
29 | + "Cannot assign temporary block", | |
30 | + "GOSUB fuction cannot be used after string-handling", | |
31 | + "Invalid BREAK statement in line ", | |
32 | + "Invalid ELSE/IF statement in line ", | |
33 | + "Invalid parameter(s)", | |
34 | + "File error", | |
35 | + "Invalid variable name", | |
36 | + "WAVE format error", | |
37 | + "ERR_COMPILE_CLASS", | |
38 | + "Class not found", | |
39 | + "Not an object", | |
40 | + " is not public field/method", | |
41 | + "Valid only in class file", | |
42 | + "Invalid in class file", | |
43 | + "INIT method does not exist", | |
44 | +}; | |
45 | + | |
46 | +char* resolve_label(int s6){ | |
47 | + static char str[7]; | |
48 | + int i,j; | |
49 | + if (s6<65536) { | |
50 | + // Line number | |
51 | + for(i=0;i<5;i++){ | |
52 | + str[5-i]='0'+rem10_32(s6); | |
53 | + s6=div10_32(s6); | |
54 | + } | |
55 | + str[6]=0x00; | |
56 | + for(j=1;j<5;j++){ | |
57 | + if (str[j]!='0') break; | |
58 | + } | |
59 | + return (char*)(str+j); | |
60 | + } else { | |
61 | + // Label | |
62 | + s6-=65536; | |
63 | + str[6]=0x00; | |
64 | + for(i=5;0<=i;i--){ | |
65 | + if (s6<36) { | |
66 | + // First character must be A-Z, corresponding to 1-26 but not 10-35. | |
67 | + // See get_label() for the detail. | |
68 | + str[i]=s6-1+'A'; | |
69 | + break; | |
70 | + } else { | |
71 | + // From second, 0-9 corresponds to 0-9 and A-Z corresponds to 10-35. | |
72 | + str[i]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[rem36_32(s6)]; | |
73 | + s6=div36_32(s6); | |
74 | + } | |
75 | + } | |
76 | + return (char*)(str+i); | |
77 | + } | |
78 | +} | |
79 | + | |
80 | +void pre_end_addr(int s6){ | |
81 | + int i,j; | |
82 | + char str[7]; | |
83 | + // Cool down the system | |
84 | + stop_music(); | |
85 | + // Resolve line and show it | |
86 | + if (s6<0) s6=s6&0x7fffffff; | |
87 | + g_label=s6; | |
88 | + if (s6<65536) { | |
89 | + // Line number | |
90 | + printstr("\nIn line "); | |
91 | + } else { | |
92 | + // Label | |
93 | + printstr("\nAfter label "); | |
94 | + } | |
95 | + printstr(resolve_label(s6)); | |
96 | + asm volatile("la $v0,%0"::"i"(&g_end_addr)); | |
97 | + asm volatile("lw $v0,0($v0)"); | |
98 | + asm volatile("nop"); | |
99 | + asm volatile("jr $v0"); | |
100 | +} | |
101 | + | |
102 | +#define end_exec() \ | |
103 | + asm volatile("addu $a0,$s6,$zero");\ | |
104 | + asm volatile("j pre_end_addr") | |
105 | + | |
106 | +void err_break(void){ | |
107 | + stop_music(); | |
108 | + printstr(ERR_BREAK); | |
109 | + end_exec(); | |
110 | +} | |
111 | + | |
112 | +void err_data_not_found(void){ | |
113 | + printstr(ERR_DATA_NF); | |
114 | + end_exec(); | |
115 | +} | |
116 | + | |
117 | +void err_label_not_found(void){ | |
118 | + printstr(ERR_LABEL_NF); | |
119 | + printstr(resolve_label(g_label)); | |
120 | + printstr("\n"); | |
121 | + end_exec(); | |
122 | +} | |
123 | + | |
124 | +void err_div_zero(void){ | |
125 | + printstr(ERR_DIV_0); | |
126 | + end_exec(); | |
127 | +} | |
128 | + | |
129 | +void err_no_mem(void){ | |
130 | + printstr(ERR_NE_MEMORY); | |
131 | + end_exec(); | |
132 | +} | |
133 | + | |
134 | +void err_str_complex(void){ | |
135 | + printstr(ERR_STR_COMPLEX); | |
136 | + end_exec(); | |
137 | +} | |
138 | + | |
139 | +void err_unknown(void){ | |
140 | + asm volatile("la $v0,%0"::"i"(&g_temp)); | |
141 | + asm volatile("sw $ra,0($v0)"); | |
142 | + printstr(ERR_UNKNOWN); | |
143 | + printhex32(g_temp); | |
144 | + end_exec(); | |
145 | +} | |
146 | + | |
147 | +void err_music(char* str){ | |
148 | + printstr(ERR_MUSIC); | |
149 | + printstr(str); | |
150 | + printstr("'\n"); | |
151 | + // Restore s6 from g_s6 | |
152 | + asm volatile("la $s6,%0"::"i"(&g_s6)); | |
153 | + asm volatile("lw $s6,0($s6)"); | |
154 | + end_exec(); | |
155 | +} | |
156 | + | |
157 | +void err_unexp_next(void){ | |
158 | + printstr(ERR_UNEXP_NEXT); | |
159 | + end_exec(); | |
160 | +} | |
161 | + | |
162 | +void err_no_block(void){ | |
163 | + printstr(ERR_NO_BLOCK); | |
164 | + end_exec(); | |
165 | +} | |
166 | + | |
167 | +void err_invalid_param(void){ | |
168 | + printstr(ERR_INVALID_PARAM); | |
169 | + end_exec(); | |
170 | +} | |
171 | + | |
172 | +void err_file(void){ | |
173 | + printstr(ERR_FILE); | |
174 | + end_exec(); | |
175 | +} | |
176 | + | |
177 | +void err_wave(void){ | |
178 | + printstr(ERR_WAVE); | |
179 | + end_exec(); | |
180 | +} | |
181 | + | |
182 | +void err_not_obj(void){ | |
183 | + printstr(ERR_NOT_OBJ); | |
184 | + end_exec(); | |
185 | +} | |
186 | + | |
187 | +void err_not_field(int fieldname, int classname){ | |
188 | + printstr(resolve_label(classname)); | |
189 | + printchar('.'); | |
190 | + printstr(resolve_label(fieldname & 0x7FFFFFFF)); | |
191 | + printstr(ERR_NOT_FIELD); | |
192 | + end_exec(); | |
193 | +} | |
194 | + | |
195 | +void err_str(char* str){ | |
196 | + printstr(str); | |
197 | + end_exec(); | |
198 | +} | |
\ No newline at end of file |
@@ -0,0 +1,170 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by K.Tanaka & Katsumi | |
4 | + http://www.ze.em-net.ne.jp/~kenken/index.html | |
5 | + http://hp.vector.co.jp/authors/VA016157/ | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include <xc.h> | |
13 | +#include "api.h" | |
14 | +#include "main.h" | |
15 | +#include "compiler.h" | |
16 | + | |
17 | +/* | |
18 | + Enable following line if memory dump is needed when exception occurs. | |
19 | +*/ | |
20 | + | |
21 | +//#define DUMPFILE "~~MEMORY.DMP" | |
22 | + | |
23 | +#ifdef DUMPFILE | |
24 | +void dumpMemory(){ | |
25 | + unsigned int i; | |
26 | + FSFILE *fp; | |
27 | + printstr("\n"DUMPFILE" "); | |
28 | + if(FSInit()==FALSE){ | |
29 | + printstr("cannot be created.\n"); | |
30 | + return; | |
31 | + } | |
32 | + fp=FSfopen(DUMPFILE,"w"); | |
33 | + if(fp==NULL) { | |
34 | + printstr("not saved.\n"); | |
35 | + return; | |
36 | + } | |
37 | + for(i=0;i<PERSISTENT_RAM_SIZE;i+=512){ | |
38 | + if (FSfwrite(&RAM[i],1,512,fp)<512) break; | |
39 | + } | |
40 | + FSfclose(fp); | |
41 | + printstr("saved.\n"); | |
42 | +} | |
43 | +#else | |
44 | +void dumpMemory(){} | |
45 | +#endif //ifdef DUMPFILE | |
46 | + | |
47 | +void _general_exception_handler_main (void); | |
48 | +void _general_exception_handler (void){ | |
49 | + asm volatile("la $sp,%0"::"i"(&RAM[RAMSIZE-4])); | |
50 | + asm volatile("j _general_exception_handler_main"); | |
51 | +} | |
52 | +void _general_exception_handler_main (void){ | |
53 | + int i; | |
54 | + // $v1 is g_ex_data | |
55 | + asm volatile("la $v1,%0"::"i"(&g_ex_data[0])); | |
56 | + // Prepare proper stack area before SoftReset | |
57 | + asm volatile("addiu $sp,$v1,0xfff0"); | |
58 | + // g_ex_data[2]=$s6 | |
59 | + asm volatile("sw $s6,8($v1)"); | |
60 | + // g_ex_data[3]=Cause | |
61 | + asm volatile("mfc0 $v0,$13"); | |
62 | + asm volatile("sw $v0,12($v1)"); | |
63 | + // g_ex_data[4]=EPC | |
64 | + asm volatile("mfc0 $v0,$14"); | |
65 | + asm volatile("sw $v0,16($v1)"); | |
66 | + // Exception occured | |
67 | + g_ex_data[0]=1; | |
68 | + // g_s6 | |
69 | + g_ex_data[1]=g_s6; | |
70 | + // Clear 2 MLB bits of EPC | |
71 | + g_ex_data[4]&=0xfffffffc; | |
72 | + // If EPC is within RAM, store data in exception area. | |
73 | + if ((int)(&RAM[0])<=g_ex_data[4] && g_ex_data[4] <(int)(&RAM[RAMSIZE])) { | |
74 | + // g_ex_data[5] - g_ex_data[12]: assembly | |
75 | + for(i=-3;i<=3;i++){ | |
76 | + g_ex_data[i+8]=((int*)g_ex_data[4])[i]; | |
77 | + } | |
78 | + } | |
79 | + // Wait until all buttons are released and reset MachiKania. | |
80 | + #ifdef __DEBUG | |
81 | + asm volatile("j 0xBFC00000"); | |
82 | + #else | |
83 | + for(i=0;i<100000;i++){ | |
84 | + if((readbuttons()&(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE)) | |
85 | + !=(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE)) i=0; | |
86 | + } | |
87 | + RCONbits.POR=0; | |
88 | + RCONbits.EXTR=0; | |
89 | + asm volatile("j 0x9FC00000"); | |
90 | + #endif | |
91 | +} | |
92 | + | |
93 | +void blue_screen(void){ | |
94 | + int i,j,s6,s6g; | |
95 | + unsigned int* opos; | |
96 | + if (RCONbits.POR || RCONbits.EXTR) { | |
97 | + // After power on or reset. Reset flags and return. | |
98 | + RCONbits.POR=0; | |
99 | + RCONbits.EXTR=0; | |
100 | + for(i=0;i<RAMSIZE;i++){ | |
101 | + // Reset all RAM area including g_ex_data[] | |
102 | + RAM[i]=0; | |
103 | + } | |
104 | + return; | |
105 | + } else if (g_ex_data[0]==0) { | |
106 | + // No exception found. | |
107 | + return; | |
108 | + } | |
109 | + // Exception occured before SoftReset(). | |
110 | + // Prepare data | |
111 | + s6=g_ex_data[2]; | |
112 | + s6g=g_ex_data[1]; | |
113 | + s6=s6&0x7fffffff; | |
114 | + s6g=s6g&0x7fffffff; | |
115 | + opos=(int*)g_ex_data[4]; | |
116 | + //set_bgcolor(255,0,0); | |
117 | + printstr("STOP"); | |
118 | + printstr("\nException at "); | |
119 | + printhex32(g_ex_data[4]); | |
120 | + printstr("\n Cause: "); | |
121 | + printhex32(g_ex_data[3]); | |
122 | + printstr("\n "); | |
123 | + switch((g_ex_data[3]>>2)&0x1f){ | |
124 | + case 0: printstr("(Interrupt)"); break; | |
125 | + case 1: printstr("(TLB modification)"); break; | |
126 | + case 2: printstr("(TLB load/fetch)"); break; | |
127 | + case 3: printstr("(TLB store)"); break; | |
128 | + case 4: printstr("(Address load/fetch error )"); break; | |
129 | + case 5: printstr("(Address store error)"); break; | |
130 | + case 6: printstr("(Bus fetch error)"); break; | |
131 | + case 7: printstr("(Bus load/store error)"); break; | |
132 | + case 8: printstr("(Syscall)"); break; | |
133 | + case 9: printstr("(Breakpoint)"); break; | |
134 | + case 10: printstr("(Reserved instruction)"); break; | |
135 | + case 11: printstr("(Coprocessor Unusable)"); break; | |
136 | + case 12: printstr("(Integer Overflow)"); break; | |
137 | + case 13: printstr("(Trap)"); break; | |
138 | + case 23: printstr("(Reference to Watch address)"); break; | |
139 | + case 24: printstr("(Machine check)"); break; | |
140 | + default: printstr("(Unknown)"); break; | |
141 | + } | |
142 | + printstr("\n s6: "); | |
143 | + printstr(resolve_label(s6)); | |
144 | + printstr("\n g_s6: "); | |
145 | + printstr(resolve_label(s6g)); | |
146 | + printstr("\n"); | |
147 | + printstr("Reset MachiKania to contine.\n\n"); | |
148 | + // Show code where the exception happened. | |
149 | + for(i=-3;i<=3;i++){ | |
150 | + printstr("\n "); | |
151 | + printhex32((unsigned int)&opos[i]); | |
152 | + printstr(" "); | |
153 | + if ((unsigned int)&RAM[0]<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<(unsigned int)&RAM[RAMSIZE]) { | |
154 | + // Exception in RAM[RAMSIZE] area | |
155 | + printhex32(g_ex_data[i+8]); | |
156 | + } else if ( 0xA0000000<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<0xA0000000+PIC32MX_RAMSIZE | |
157 | + || 0x9D000000<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<=0x9D000000+PIC32MX_FLASHSIZE) { | |
158 | + // Exception in outside RAM[RAMSIZE] or flash area | |
159 | + printhex32(opos[i]); | |
160 | + } else { | |
161 | + printstr("********"); | |
162 | + } | |
163 | + } | |
164 | + printstr("\n"); | |
165 | + | |
166 | +#ifndef __DEBUG | |
167 | + dumpMemory(); | |
168 | +#endif | |
169 | + while(1) asm("wait"); | |
170 | +} |
@@ -0,0 +1,275 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by K.Tanaka & Katsumi | |
4 | + http://www.ze.em-net.ne.jp/~kenken/index.html | |
5 | + http://hp.vector.co.jp/authors/VA016157/ | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include <xc.h> | |
13 | +#include "api.h" | |
14 | +#include "compiler.h" | |
15 | + | |
16 | +static FSFILE* g_fhandle; | |
17 | +static char* g_fbuff; | |
18 | +static int g_size; | |
19 | + | |
20 | +char* init_file(char* buff,char* appname){ | |
21 | + // Open file | |
22 | + g_fhandle=FSfopen(appname,"r"); | |
23 | + if (!g_fhandle) { | |
24 | + return ERR_UNKNOWN; | |
25 | + } | |
26 | + // Initialize parameters | |
27 | + g_fbuff=buff; | |
28 | + g_line=0; | |
29 | + g_fileline=0; | |
30 | + g_source=buff; | |
31 | + g_srcpos=0; | |
32 | + return 0; | |
33 | +} | |
34 | + | |
35 | +void close_file(){ | |
36 | + FSfclose(g_fhandle); | |
37 | +} | |
38 | + | |
39 | +void read_file(int blocklen){ | |
40 | + int i; | |
41 | + static char in_string, escape; | |
42 | + // blocklen is either 512 or 256. | |
43 | + if (blocklen==512) { | |
44 | + // This is first read. Initialize parameter(s). | |
45 | + in_string=0; | |
46 | + escape=0; | |
47 | + } else if (g_size<512) { | |
48 | + // Already reached the end of file. | |
49 | + return; | |
50 | + } else { | |
51 | + // Shift buffer and source position 256 bytes. | |
52 | + for(i=0;i<256;i++) g_fbuff[i]=g_fbuff[i+256]; | |
53 | + g_srcpos-=256; | |
54 | + } | |
55 | + // Read 512 or 256 bytes from SD card. | |
56 | + g_size=512-blocklen+FSfread((void*)&g_fbuff[512-blocklen],1,blocklen,g_fhandle); | |
57 | + // Some modifications of text for easy compiling. | |
58 | + for(i=512-blocklen;i<512;i++){ | |
59 | + if (in_string) { | |
60 | + if (g_fbuff[i]=='\\' && !escape) { | |
61 | + escape=1; | |
62 | + } else { | |
63 | + escape=0; | |
64 | + if (g_fbuff[i]=='"') in_string=0; | |
65 | + } | |
66 | + } else { | |
67 | + // If not in string, all upper cases. | |
68 | + if (g_fbuff[i]=='"') in_string=1; | |
69 | + else if ('a'<=g_fbuff[i] && g_fbuff[i]<='z') g_fbuff[i]+='A'-'a'; | |
70 | + // If not in string, tabs will be spaces. | |
71 | + else if ('\t'==g_fbuff[i]) g_fbuff[i]=' '; | |
72 | + } | |
73 | + if (g_fbuff[i]==0x0a || g_fbuff[i]==0x0d) in_string=escape=0; | |
74 | + } | |
75 | + return; | |
76 | +} | |
77 | + | |
78 | +char* compile_file(){ | |
79 | + int i; | |
80 | + char* err; | |
81 | + // Read first 512 bytes | |
82 | + read_file(512); | |
83 | + // Compile line by line | |
84 | + while (g_size==512) { | |
85 | + err=compile_line(); | |
86 | + if (err) return err; | |
87 | + // Maintain at least 256 characters in cache. | |
88 | + if (256<=g_srcpos) read_file(256); | |
89 | + } | |
90 | + // Return code at the end | |
91 | + g_source[g_size]=0x0d; | |
92 | + // Compile last few lines. | |
93 | + while(g_srcpos<g_size-1){ | |
94 | + err=compile_line(); | |
95 | + if (err) return err; | |
96 | + } | |
97 | + // Add "DATA 0" and "END" statements. | |
98 | + if (g_compiling_class) { | |
99 | + g_source="END\n"; | |
100 | + } else { | |
101 | + g_source="DATA 0:END\n"; | |
102 | + } | |
103 | + g_srcpos=0; | |
104 | + err=compile_line(); | |
105 | + if (err) return err; | |
106 | + g_srcpos=-1; | |
107 | + // No error occured | |
108 | + return 0; | |
109 | +} | |
110 | + | |
111 | +int compile_and_link_file(char* buff,char* appname){ | |
112 | + int i,j; | |
113 | + char* err; | |
114 | + | |
115 | + while(1){ | |
116 | + // Initialize SD card file system | |
117 | + err=init_file(buff,appname); | |
118 | + if (err) { | |
119 | + //setcursorcolor(COLOR_ERRORTEXT); | |
120 | + printstr("Can't Open "); | |
121 | + printstr(appname); | |
122 | + printchar('\n'); | |
123 | + return -1; | |
124 | + } | |
125 | + | |
126 | + // Option initialization(s) | |
127 | + g_nolinenum=0; | |
128 | + | |
129 | + // Compile the file | |
130 | + err=compile_file(); | |
131 | + close_file(); | |
132 | + | |
133 | + // If compiling a class file is required, do it. | |
134 | + if (err==ERR_COMPILE_CLASS) { | |
135 | + j=g_compiling_class; | |
136 | + i=compile_and_link_class(buff, g_class); | |
137 | + g_compiling_class=j; | |
138 | + if (i) return i; | |
139 | + // Continue compiling current file from the beginning. | |
140 | + continue; | |
141 | + } | |
142 | + break; | |
143 | + } | |
144 | + | |
145 | + if (err) { | |
146 | + // Compile error | |
147 | + printstr(err); | |
148 | + printstr("\nAround: '"); | |
149 | + for(i=0;i<5;i++){ | |
150 | + printchar(g_source[g_srcpos-2+i]); | |
151 | + } | |
152 | + printstr("' in line "); | |
153 | + printdec(g_line); | |
154 | + printstr("\n"); | |
155 | + for(i=g_srcpos;0x20<=g_source[i];i++); | |
156 | + g_source[i]=0x00; | |
157 | + for(i=g_srcpos;0x20<=g_source[i];i--); | |
158 | + printstr(g_source+i); | |
159 | + return g_fileline; | |
160 | + } | |
161 | + | |
162 | + // Link | |
163 | + err=link(); | |
164 | + if (err) { | |
165 | + // Link error | |
166 | + printstr(err); | |
167 | + printstr(resolve_label(g_label)); | |
168 | + return -2; | |
169 | + } | |
170 | + | |
171 | + // All done | |
172 | + return 0; | |
173 | +} | |
174 | + | |
175 | +int compile_and_link_class(char* buff,int class){ | |
176 | + int i,j; | |
177 | + char* err; | |
178 | + char* classname; | |
179 | + char classfile[13]; | |
180 | + char classdir[11]; | |
181 | + int data[2]; | |
182 | + unsigned short cwd_id; | |
183 | + int* record; | |
184 | + while(1){ | |
185 | + // Begin compiling class | |
186 | + err=begin_compiling_class(class); | |
187 | + if (err) break; | |
188 | + // Determine class file name | |
189 | + classname=resolve_label(class); | |
190 | + for(i=0;classfile[i]=classname[i];i++); | |
191 | + classfile[i++]='.'; | |
192 | + classfile[i++]='B'; | |
193 | + classfile[i++]='A'; | |
194 | + classfile[i++]='S'; | |
195 | + classfile[i]=0; | |
196 | + // Check if file exists in current directory | |
197 | + err=init_file(buff,&classfile[0]); | |
198 | + if (!err) { | |
199 | + // Class file found in current directory | |
200 | + close_file(); | |
201 | + // Compile it | |
202 | + i=compile_and_link_file(buff,&classfile[0]); | |
203 | + if (i) break; | |
204 | + } else { | |
205 | + // Class file not found in current directory. | |
206 | + // Try library directory, for example, \LIB\CLASS1\CLASS1.BAS | |
207 | + // Store current directory, first | |
208 | + if (!FSgetcwd(buff,256)) break; | |
209 | + for(i=0;buff[i];i++); | |
210 | + cwd_id=cmpdata_get_id(); | |
211 | + if (!cwd_id) break; | |
212 | + err=cmpdata_insert(CMPDATA_TEMP,cwd_id,(int*)(&buff[0]),(i+1+3)>>2); | |
213 | + if (err) break; | |
214 | + // Change current directory to class library directory | |
215 | + for(i=0;classdir[i]="\\LIB\\"[i];i++); | |
216 | + for(j=0;classdir[i++]=classname[j];j++); | |
217 | + classdir[i]=0; | |
218 | + FSchdir(classdir); | |
219 | + // Compile class file | |
220 | + i=compile_and_link_file(buff,&classfile[0]); | |
221 | + // Restore current dirctory | |
222 | + cmpdata_reset(); | |
223 | + while(record=cmpdata_find(CMPDATA_TEMP)){ | |
224 | + if (cwd_id=(record[0]&0xffff)) break; | |
225 | + } | |
226 | + if (!record) break; | |
227 | + FSchdir((char*)(&record[1])); | |
228 | + cmpdata_delete(record); | |
229 | + if (i) break; | |
230 | + } | |
231 | + // End compiling class | |
232 | + err=end_compiling_class(class); | |
233 | + if (err) break; | |
234 | + // Initial assembly is a jump statement to jump to the end of class file | |
235 | + // Note that there is at least a code (set line # to $s6) before reaching here | |
236 | + g_object[0]=0x08000000 | ((((int)(&g_object[g_objpos]))&0x0FFFFFFF)>>2); // j xxxxxxxx | |
237 | + // In the next link, current region of object is ignored. | |
238 | + g_object+=g_objpos; | |
239 | + g_objpos=0; | |
240 | + // All done | |
241 | + return 0; | |
242 | + } | |
243 | + // Error occured | |
244 | + printstr("/nError in class: "); | |
245 | + printstr((char*)&classfile[0]); | |
246 | + printchar('\n'); | |
247 | + if (err) printstr(err); | |
248 | + return -2; | |
249 | +} | |
250 | + | |
251 | +int compile_and_link_main_file(char* buff,char* appname){ | |
252 | + int i; | |
253 | + g_compiling_class=0; | |
254 | + i=compile_and_link_file(buff,appname); | |
255 | + if (i) return i; | |
256 | + return 0; | |
257 | + /* | |
258 | + After compiling class code, g_object is set to the beginning of next code. | |
259 | + Therefore, after the all, g_object is set toe the beginnig of main code, | |
260 | + and class code(s) is/are excluded. This will affect following features when running: | |
261 | + READ/DATA/RESTORE function/statements | |
262 | + The linker also works withing the g_object dimension. Therefore, the label only works withing the file, | |
263 | + but not in the other file. This feature allows using the same label name in different files without | |
264 | + causing error/misjumping | |
265 | + | |
266 | + After compiling class code, following cmpdata are destroyed (see delete_cmpdata_for_class() function): | |
267 | + CMPDATA_FIELD : object field and method information | |
268 | + CMPDATA_USEVAR : long var name information | |
269 | + but following cmpdata remains: | |
270 | + CMPDATA_CLASS : class name and address of class structure | |
271 | + This feature allows compiler to use class information (name and structure) for "NEW" function, | |
272 | + to use the same long var name in different files (note that g_long_name_var_num is not reseted after | |
273 | + compiling each class code). | |
274 | + */ | |
275 | +} | |
\ No newline at end of file |
@@ -0,0 +1,171 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "./compiler.h" | |
13 | +#include "stdlib.h" | |
14 | + | |
15 | +char* get_float_sub(int pr); | |
16 | + | |
17 | +char* get_simple_float(void){ | |
18 | + int i; | |
19 | + float f; | |
20 | + char* err; | |
21 | + char b1,b2,b3; | |
22 | + next_position(); | |
23 | + b1=g_source[g_srcpos]; | |
24 | + if (b1=='(') { | |
25 | + // (...) | |
26 | + // Parenthesis | |
27 | + g_srcpos++; | |
28 | + next_position(); | |
29 | + err=get_float_sub(priority(OP_VOID)); | |
30 | + if (err) return err; | |
31 | + next_position(); | |
32 | + if (g_source[g_srcpos]!=')') return ERR_SYNTAX; | |
33 | + g_srcpos++; | |
34 | + } else if (b1=='-') { | |
35 | + // Unary '-' operator | |
36 | + // Note that unary operators ( + and - ) have higher priority than the other operators | |
37 | + g_srcpos++; | |
38 | + err=get_simple_float(); | |
39 | + if (err) return err; | |
40 | + check_obj_space(1); | |
41 | + g_object[g_objpos++]=0x34040000; // ori a0,zero,0 | |
42 | + call_lib_code(LIB_FLOAT | OP_SUB); | |
43 | + } else { | |
44 | + // Main routine of getting float value here | |
45 | + if (b1=='+') g_srcpos++; // Ignore unary '+' operator | |
46 | + next_position(); | |
47 | + b1=g_source[g_srcpos]; | |
48 | + b2=g_source[g_srcpos+1]; | |
49 | + b3=g_source[g_srcpos+2]; | |
50 | + if ('0'<=b1 && b1<='9') { | |
51 | + f=strtof((const char*)&g_source[g_srcpos],&err); | |
52 | + if (&g_source[g_srcpos]==err) return ERR_SYNTAX; | |
53 | + g_srcpos=err-g_source; | |
54 | + i=((int*)(&f))[0]; | |
55 | + if (i&0xFFFF0000) { | |
56 | + // 32 bit | |
57 | + check_obj_space(2); | |
58 | + g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx | |
59 | + g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx | |
60 | + } else { | |
61 | + // 16 bit | |
62 | + check_obj_space(1); | |
63 | + g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx | |
64 | + } | |
65 | + } else { | |
66 | + i=get_var_number(); | |
67 | + if (i<0) { | |
68 | + // Must be a function. | |
69 | + return float_function(); | |
70 | + } | |
71 | + if (g_source[g_srcpos]=='.') { | |
72 | + // This is an object field or method to return string | |
73 | + check_obj_space(1); | |
74 | + g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8) | |
75 | + g_srcpos++; | |
76 | + return float_obj_field(); | |
77 | + } else if (g_source[g_srcpos]=='(') { | |
78 | + // An array element contains pointer to an object. | |
79 | + g_srcpos++; | |
80 | + err=get_dim_value(i); | |
81 | + if (err) return err; | |
82 | + if (g_source[g_srcpos]!='.') return ERR_SYNTAX; | |
83 | + g_srcpos++; | |
84 | + return float_obj_field(); | |
85 | + } | |
86 | + if (g_source[g_srcpos]!='#') return ERR_SYNTAX; | |
87 | + g_srcpos++; | |
88 | + if (g_source[g_srcpos]=='(') { | |
89 | + // Dimension | |
90 | + g_srcpos++; | |
91 | + return get_dim_value(i); | |
92 | + } | |
93 | + // Simple value | |
94 | + check_obj_space(1); | |
95 | + g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8) | |
96 | + } | |
97 | + } | |
98 | + // No error | |
99 | + return 0; | |
100 | +} | |
101 | + | |
102 | +char* get_float_sub(int pr){ | |
103 | + char* err; | |
104 | + enum operator op; | |
105 | + char b1,b2,b3; | |
106 | + int prevpos; | |
107 | + // Get a value in $v0. | |
108 | + err=get_simple_float(); | |
109 | + if (err) return err; | |
110 | + while(1){ | |
111 | + // Get the operator in op. If not valid operator, simply return without error. | |
112 | + prevpos=g_srcpos; | |
113 | + err=get_floatOperator(); | |
114 | + if (err) return 0; | |
115 | + op=g_last_op; | |
116 | + // Compair current and previous operators. | |
117 | + // If the previous operator has higher priolity, return. | |
118 | + if (pr>=priority(op)) { | |
119 | + g_srcpos=prevpos; | |
120 | + return 0; | |
121 | + } | |
122 | + // Store $v0 in stack | |
123 | + g_sdepth+=4; | |
124 | + if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth; | |
125 | + check_obj_space(1); | |
126 | + g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp) | |
127 | + // Get next value. | |
128 | + err=get_float_sub(priority(op)); | |
129 | + if (err) return err; | |
130 | + // Get value from stack to $a0. | |
131 | + check_obj_space(1); | |
132 | + g_object[g_objpos++]=0x8FA40000|g_sdepth; // lw a0,xx(sp) | |
133 | + g_sdepth-=4; | |
134 | + // Calculation. Result will be in $v0. | |
135 | + err=calculation_float(op); | |
136 | + if (err) return err; | |
137 | + } | |
138 | +} | |
139 | + | |
140 | +char* get_float(){ | |
141 | + // Note that this can be called recursively. | |
142 | + // Value may contain function with a parameter of another value. | |
143 | + char* err; | |
144 | + int prevpos; | |
145 | + if (g_sdepth==0) { | |
146 | + // Initialize stack handler | |
147 | + g_maxsdepth=0; | |
148 | + prevpos=g_objpos; | |
149 | + // Stack decrement command will be filled later | |
150 | + check_obj_space(1); | |
151 | + g_object[g_objpos++]=0x00000000; // nop (will be replaced by "addiu sp,sp,-xx") | |
152 | + } | |
153 | + err=get_float_sub(priority(OP_VOID)); | |
154 | + if (err) return err; | |
155 | + if (g_sdepth==0) { | |
156 | + if (g_maxsdepth==0) { | |
157 | + // Stack was not used. | |
158 | + if (g_allow_shift_obj) { | |
159 | + shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1); | |
160 | + g_objpos--; | |
161 | + } | |
162 | + } else { | |
163 | + // Stack was used. | |
164 | + check_obj_space(1); | |
165 | + g_object[prevpos]=0x27BD0000 | (0-g_maxsdepth) & 0x0000FFFF; // addiu sp,sp,-xx | |
166 | + g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx | |
167 | + } | |
168 | + } | |
169 | + g_lastvar=VAR_FLOAT; | |
170 | + return 0; | |
171 | +} | |
\ No newline at end of file |
@@ -0,0 +1,625 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "compiler.h" | |
13 | +#include "api.h" | |
14 | + | |
15 | +char* music_function(){ | |
16 | + char* err; | |
17 | + next_position(); | |
18 | + if (g_source[g_srcpos]==')') { | |
19 | + check_obj_space(1); | |
20 | + g_object[g_objpos++]=0x34020003; //ori v0,zero,0x03 | |
21 | + } else { | |
22 | + err=get_value(); | |
23 | + if (err) return err; | |
24 | + } | |
25 | + call_lib_code(LIB_MUSICFUNC); | |
26 | + return 0; | |
27 | +} | |
28 | + | |
29 | +char* read_function(){ | |
30 | + // This function is not valid in class file. | |
31 | + if (g_compiling_class) return ERR_INVALID_CLASS; | |
32 | + call_lib_code(LIB_READ); | |
33 | + return 0; | |
34 | +} | |
35 | + | |
36 | +char* cread_function(){ | |
37 | + call_lib_code(LIB_CREAD); | |
38 | + return 0; | |
39 | +} | |
40 | + | |
41 | +char* gosub_function(){ | |
42 | + // Check if garbage collection has been done. | |
43 | + // This check is required because the used temporary area would be changed | |
44 | + // in sub routine. | |
45 | + if (g_temp_area_used) return ERR_GOSUB_ASH; | |
46 | + return gosub_statement(); | |
47 | +} | |
48 | +char* strncmp_function(){ | |
49 | + char* err; | |
50 | + err=get_string(); | |
51 | + if (err) return err; | |
52 | + check_obj_space(2); | |
53 | + g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8 | |
54 | + g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp) | |
55 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
56 | + g_srcpos++; | |
57 | + err=get_string(); | |
58 | + if (err) return err; | |
59 | + check_obj_space(1); | |
60 | + g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp) | |
61 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
62 | + g_srcpos++; | |
63 | + err=get_value(); | |
64 | + if (err) return err; | |
65 | + call_lib_code(LIB_STRNCMP); | |
66 | + check_obj_space(1); | |
67 | + g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8 | |
68 | + return 0; | |
69 | +} | |
70 | +char* len_function(){ | |
71 | + char* err; | |
72 | + err=get_string(); | |
73 | + if (err) return err; | |
74 | + check_obj_space(5); | |
75 | + g_object[g_objpos++]=0x2443FFFF; // addiu v1,v0,-1 | |
76 | + // loop: | |
77 | + g_object[g_objpos++]=0x80640001; // lb a0,1(v1) | |
78 | + g_object[g_objpos++]=0x1480FFFE; // bne a0,zero,loop | |
79 | + g_object[g_objpos++]=0x24630001; // addiu v1,v1,1 | |
80 | + g_object[g_objpos++]=0x00621023; // subu v0,v1,v0 | |
81 | + return 0; | |
82 | +} | |
83 | + | |
84 | +char* asc_function(){ | |
85 | + char* err; | |
86 | + err=get_string(); | |
87 | + if (err) return err; | |
88 | + check_obj_space(1); | |
89 | + g_object[g_objpos++]=0x90420000; // lbu v0,0(v0) | |
90 | + return 0; | |
91 | +} | |
92 | + | |
93 | +char* val_function(){ | |
94 | + char* err; | |
95 | + err=get_string(); | |
96 | + if (err) return err; | |
97 | + call_lib_code(LIB_VAL); | |
98 | + return 0; | |
99 | +} | |
100 | + | |
101 | +char* peek_function_sub(int bits){ | |
102 | + char* err; | |
103 | + err=get_value(); | |
104 | + if (err) return err; | |
105 | + check_obj_space(1); | |
106 | + switch(bits){ | |
107 | + case 32: | |
108 | + g_object[g_objpos++]=0x8C420000; // lw v0,0(v0) | |
109 | + break; | |
110 | + case 16: | |
111 | + g_object[g_objpos++]=0x94420000; // lhu v0,0(v0) | |
112 | + break; | |
113 | + case 8: | |
114 | + default: | |
115 | + g_object[g_objpos++]=0x90420000; // lbu v0,0(v0) | |
116 | + break; | |
117 | + } | |
118 | + return 0; | |
119 | +} | |
120 | + | |
121 | +char* sgn_function(){ | |
122 | + char* err; | |
123 | + err=get_value(); | |
124 | + if (err) return err; | |
125 | + check_obj_space(5); | |
126 | + g_object[g_objpos++]=0x10400004; // beq v0,zero,end | |
127 | + g_object[g_objpos++]=0x24030001; // addiu v1,zero,1 | |
128 | + g_object[g_objpos++]=0x1C400002; // bgtz v0,end | |
129 | + g_object[g_objpos++]=0x00601021; // addu v0,v1,zero | |
130 | + g_object[g_objpos++]=0x00031023; // subu v0,zero,v1 | |
131 | + // end: | |
132 | + return 0; | |
133 | +} | |
134 | + | |
135 | +char* abs_function(){ | |
136 | + char* err; | |
137 | + err=get_value(); | |
138 | + if (err) return err; | |
139 | + check_obj_space(3); | |
140 | + g_object[g_objpos++]=0x00021FC3; //sra v1,v0,0x1f | |
141 | + g_object[g_objpos++]=0x00621026; //xor v0,v1,v0 | |
142 | + g_object[g_objpos++]=0x00431023; //subu v0,v0,v1 | |
143 | + return 0; | |
144 | +} | |
145 | + | |
146 | +char* not_function(){ | |
147 | + char* err; | |
148 | + err=get_value(); | |
149 | + if (err) return err; | |
150 | + check_obj_space(1); | |
151 | + g_object[g_objpos++]=0x2C420001; //sltiu v0,v0,1 | |
152 | + return 0; | |
153 | +} | |
154 | + | |
155 | +char* rnd_function(){ | |
156 | + call_lib_code(LIB_RND); | |
157 | + return 0; | |
158 | +} | |
159 | + | |
160 | +char* chr_function(void){ | |
161 | + char* err; | |
162 | + err=get_value(); | |
163 | + if (err) return err; | |
164 | + call_lib_code(LIB_CHR); | |
165 | + return 0; | |
166 | +} | |
167 | +char* hex_function(void){ | |
168 | + char* err; | |
169 | + err=get_value(); | |
170 | + if (err) return err; | |
171 | + if (g_source[g_srcpos]==',') { | |
172 | + // Second argument found. | |
173 | + // Get is as $a0. | |
174 | + g_srcpos++; | |
175 | + check_obj_space(2); | |
176 | + g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4 | |
177 | + g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp) | |
178 | + err=get_value(); | |
179 | + if (err) return err; | |
180 | + check_obj_space(3); | |
181 | + g_object[g_objpos++]=0x00022021; //a0,zero,v0 | |
182 | + g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp) | |
183 | + g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4 | |
184 | + } else { | |
185 | + // Second argument not found. | |
186 | + // Set $a0 to 0. | |
187 | + check_obj_space(1); | |
188 | + g_object[g_objpos++]=0x24040000; //addiu a0,zero,0 | |
189 | + } | |
190 | + call_lib_code(LIB_HEX); | |
191 | + return 0; | |
192 | +} | |
193 | + | |
194 | +char* dec_function(void){ | |
195 | + char* err; | |
196 | + err=get_value(); | |
197 | + if (err) return err; | |
198 | + call_lib_code(LIB_DEC); | |
199 | + return 0; | |
200 | +} | |
201 | + | |
202 | +char* keys_function(void){ | |
203 | + char* err; | |
204 | + next_position(); | |
205 | + if (g_source[g_srcpos]==')') { | |
206 | + check_obj_space(1); | |
207 | + g_object[g_objpos++]=0x3402003F; //ori v0,zero,0x3f | |
208 | + } else { | |
209 | + err=get_value(); | |
210 | + if (err) return err; | |
211 | + } | |
212 | + call_lib_code(LIB_KEYS); | |
213 | + return 0; | |
214 | +} | |
215 | + | |
216 | +char* tvram_function(void){ | |
217 | + char* err; | |
218 | + int i; | |
219 | + next_position(); | |
220 | + if (g_source[g_srcpos]==')') { | |
221 | + i=(int)(&TVRAM[0]); | |
222 | + i-=g_gp; | |
223 | + check_obj_space(1); | |
224 | + g_object[g_objpos++]=0x27820000|(i&0x0000FFFF); // addiu v0,gp,xxxx | |
225 | + } else { | |
226 | + err=get_value(); | |
227 | + if (err) return err; | |
228 | + i=(int)(&TVRAM[0]); | |
229 | + i-=g_gp; | |
230 | + check_obj_space(3); | |
231 | + g_object[g_objpos++]=0x27830000|(i&0x0000FFFF); // addiu v1,gp,xxxx | |
232 | + g_object[g_objpos++]=0x00621821; // addu v1,v1,v0 | |
233 | + g_object[g_objpos++]=0x90620000; // lbu v0,0(v1) | |
234 | + } | |
235 | + return 0; | |
236 | +} | |
237 | + | |
238 | +char* drawcount_function(void){ | |
239 | + call_lib_code(LIB_DRAWCOUNT); | |
240 | + return 0; | |
241 | +} | |
242 | + | |
243 | +char* input_function(void){ | |
244 | + call_lib_code(LIB_INPUT); | |
245 | + return 0; | |
246 | +} | |
247 | + | |
248 | +char* inkey_function(void){ | |
249 | + char* err; | |
250 | + next_position(); | |
251 | + if (g_source[g_srcpos]==')') { | |
252 | + check_obj_space(1); | |
253 | + g_object[g_objpos++]=0x34020000; //ori v0,zero,0x00 | |
254 | + } else { | |
255 | + err=get_value(); | |
256 | + if (err) return err; | |
257 | + } | |
258 | + call_lib_code(LIB_INKEY); | |
259 | + return 0; | |
260 | +} | |
261 | + | |
262 | +char* args_function(void){ | |
263 | + return args_function_main(); | |
264 | +} | |
265 | + | |
266 | +char* system_function(void){ | |
267 | + char* err; | |
268 | + err=get_value(); | |
269 | + if (err) return err; | |
270 | + g_object[g_objpos++]=0x00402021; // addu a0,v0,zero | |
271 | + call_lib_code(LIB_SYSTEM); | |
272 | + return 0; | |
273 | +} | |
274 | + | |
275 | +char* sprintf_function(void){ | |
276 | + char* err; | |
277 | + err=get_string(); | |
278 | + if (err) return err; | |
279 | + next_position(); | |
280 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
281 | + g_srcpos++; | |
282 | + check_obj_space(2); | |
283 | + g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4 | |
284 | + g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp) | |
285 | + err=get_float(); | |
286 | + if (err) return err; | |
287 | + check_obj_space(3); | |
288 | + g_object[g_objpos++]=0x00022021; //addu a0,zero,v0 | |
289 | + g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp) | |
290 | + g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4 | |
291 | + call_lib_code(LIB_SPRINTF); | |
292 | + return 0; | |
293 | +} | |
294 | + | |
295 | +char* floatstr_function(void){ | |
296 | + char* err; | |
297 | + err=get_float(); | |
298 | + if (err) return err; | |
299 | + check_obj_space(2); | |
300 | + g_object[g_objpos++]=0x00022021; //addu a0,zero,v0 | |
301 | + g_object[g_objpos++]=0x34020000; //ori v0,zero,0x0000 | |
302 | + call_lib_code(LIB_SPRINTF); | |
303 | + return 0; | |
304 | +} | |
305 | + | |
306 | +char* floatsharp_function(void){ | |
307 | + char* err; | |
308 | + err=get_value(); | |
309 | + if (err) return err; | |
310 | + call_lib_code(LIB_FLOATFUNCS | FUNC_FLOAT); | |
311 | + return 0; | |
312 | +} | |
313 | + | |
314 | +char* valsharp_function(void){ | |
315 | + char* err; | |
316 | + err=get_string(); | |
317 | + if (err) return err; | |
318 | + call_lib_code(LIB_FLOATFUNCS | FUNC_VALSHARP); | |
319 | + return 0; | |
320 | +} | |
321 | + | |
322 | +char* int_function(void){ | |
323 | + char* err; | |
324 | + err=get_float(); | |
325 | + if (err) return err; | |
326 | + call_lib_code(LIB_FLOATFUNCS | FUNC_INT); | |
327 | + return 0; | |
328 | +} | |
329 | + | |
330 | +char* fseek_function(){ | |
331 | + call_lib_code(LIB_FILE | FUNC_FTELL); | |
332 | + return 0; | |
333 | +} | |
334 | + | |
335 | +char* flen_function(){ | |
336 | + call_lib_code(LIB_FILE | FUNC_FLEN); | |
337 | + return 0; | |
338 | +} | |
339 | + | |
340 | +char* fgetc_function(){ | |
341 | + call_lib_code(LIB_FILE | FUNC_FGETC); | |
342 | + return 0; | |
343 | +} | |
344 | + | |
345 | +char* finput_function(){ | |
346 | + char* err; | |
347 | + next_position(); | |
348 | + if (g_source[g_srcpos]!=')') { | |
349 | + err=get_value(); | |
350 | + if (err) return err; | |
351 | + } else { | |
352 | + // Parameter will be zero if not defined | |
353 | + check_obj_space(1); | |
354 | + g_object[g_objpos++]=0x34020000; // ori v0,zero,0 | |
355 | + } | |
356 | + call_lib_code(LIB_FILE | FUNC_FINPUT); | |
357 | + return 0; | |
358 | +} | |
359 | + | |
360 | +char* feof_function(){ | |
361 | + call_lib_code(LIB_FILE | FUNC_FEOF); | |
362 | + return 0; | |
363 | +} | |
364 | + | |
365 | +char* playwave_function(){ | |
366 | + char* err; | |
367 | + next_position(); | |
368 | + if (g_source[g_srcpos]!=')') { | |
369 | + // Get param | |
370 | + err=get_value(); | |
371 | + if (err) return err; | |
372 | + } else { | |
373 | + // If parameter is omitted, use 0. | |
374 | + check_obj_space(1); | |
375 | + g_object[g_objpos++]=0x24020000; // addiu v0,zero,0 | |
376 | + } | |
377 | + call_lib_code(LIB_PLAYWAVEFUNC); | |
378 | + return 0; | |
379 | +} | |
380 | + | |
381 | +char* setdir_function(){ | |
382 | + char* err; | |
383 | + err=get_string(); | |
384 | + if (err) return err; | |
385 | + call_lib_code(LIB_SETDIRFUNC); | |
386 | + return 0; | |
387 | +} | |
388 | + | |
389 | +char* getdir_function(){ | |
390 | + call_lib_code(LIB_GETDIR); | |
391 | + return 0; | |
392 | +} | |
393 | + | |
394 | +char* float_constant(float val){ | |
395 | + volatile int i; | |
396 | + ((float*)(&i))[0]=val; | |
397 | + if (i&0xFFFF0000) { | |
398 | + // 32 bit | |
399 | + check_obj_space(2); | |
400 | + g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx | |
401 | + g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx | |
402 | + } else { | |
403 | + // 16 bit | |
404 | + check_obj_space(1); | |
405 | + g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx | |
406 | + } | |
407 | + return 0; | |
408 | +} | |
409 | + | |
410 | +char* float_1param_function(enum functions func){ | |
411 | + char* err; | |
412 | + err=get_float(); | |
413 | + if (err) return err; | |
414 | + call_lib_code(LIB_FLOATFUNCS | func); | |
415 | + return 0; | |
416 | +} | |
417 | + | |
418 | +char* float_2param_function(enum functions func){ | |
419 | + char* err; | |
420 | + err=get_float(); | |
421 | + if (err) return err; | |
422 | + next_position(); | |
423 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
424 | + g_srcpos++; | |
425 | + check_obj_space(2); | |
426 | + g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4 | |
427 | + g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp) | |
428 | + err=get_float(); | |
429 | + if (err) return err; | |
430 | + check_obj_space(3); | |
431 | + g_object[g_objpos++]=0x00022021; //addu a0,zero,v0 | |
432 | + g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp) | |
433 | + g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4 | |
434 | + call_lib_code(LIB_FLOATFUNCS | func); | |
435 | + return 0; | |
436 | +} | |
437 | + | |
438 | +char* float_function(void){ | |
439 | + char* err; | |
440 | + if (nextCodeIs("FLOAT#(")) { | |
441 | + err=floatsharp_function(); | |
442 | + } else if (nextCodeIs("VAL#(")) { | |
443 | + err=valsharp_function(); | |
444 | + } else if (nextCodeIs("SIN#(")) { | |
445 | + err=float_1param_function(FUNC_SIN); | |
446 | + } else if (nextCodeIs("COS#(")) { | |
447 | + err=float_1param_function(FUNC_COS); | |
448 | + } else if (nextCodeIs("TAN#(")) { | |
449 | + err=float_1param_function(FUNC_TAN); | |
450 | + } else if (nextCodeIs("ASIN#(")) { | |
451 | + err=float_1param_function(FUNC_ASIN); | |
452 | + } else if (nextCodeIs("ACOS#(")) { | |
453 | + err=float_1param_function(FUNC_ACOS); | |
454 | + } else if (nextCodeIs("ATAN#(")) { | |
455 | + err=float_1param_function(FUNC_ATAN); | |
456 | + } else if (nextCodeIs("ATAN2#(")) { | |
457 | + err=float_2param_function(FUNC_ATAN2); | |
458 | + } else if (nextCodeIs("SINH#(")) { | |
459 | + err=float_1param_function(FUNC_SINH); | |
460 | + } else if (nextCodeIs("COSH#(")) { | |
461 | + err=float_1param_function(FUNC_COSH); | |
462 | + } else if (nextCodeIs("TANH#(")) { | |
463 | + err=float_1param_function(FUNC_TANH); | |
464 | + } else if (nextCodeIs("EXP#(")) { | |
465 | + err=float_1param_function(FUNC_EXP); | |
466 | + } else if (nextCodeIs("LOG#(")) { | |
467 | + err=float_1param_function(FUNC_LOG); | |
468 | + } else if (nextCodeIs("LOG10#(")) { | |
469 | + err=float_1param_function(FUNC_LOG10); | |
470 | + } else if (nextCodeIs("POW#(")) { | |
471 | + err=float_2param_function(FUNC_POW); | |
472 | + } else if (nextCodeIs("SQRT#(")) { | |
473 | + err=float_1param_function(FUNC_SQRT); | |
474 | + } else if (nextCodeIs("CEIL#(")) { | |
475 | + err=float_1param_function(FUNC_CEIL); | |
476 | + } else if (nextCodeIs("FLOOR#(")) { | |
477 | + err=float_1param_function(FUNC_FLOOR); | |
478 | + } else if (nextCodeIs("FABS#(")) { | |
479 | + err=float_1param_function(FUNC_FABS); | |
480 | + } else if (nextCodeIs("MODF#(")) { | |
481 | + err=float_1param_function(FUNC_MODF); | |
482 | + } else if (nextCodeIs("FMOD#(")) { | |
483 | + err=float_2param_function(FUNC_FMOD); | |
484 | + } else if (nextCodeIs("GOSUB#(")) { | |
485 | + err=gosub_function(); | |
486 | + } else if (nextCodeIs("ARGS#(")) { | |
487 | + err=args_function(); | |
488 | + } else if (nextCodeIs("PI#")) { | |
489 | + return float_constant(3.141593); | |
490 | + } else { | |
491 | + // Check if static method of a class | |
492 | + err=static_method('#'); | |
493 | + //return ERR_SYNTAX; | |
494 | + } | |
495 | + if (err) return err; | |
496 | + if (g_source[g_srcpos]!=')') return ERR_SYNTAX; | |
497 | + g_srcpos++; | |
498 | + return 0; | |
499 | +} | |
500 | + | |
501 | +static const void* str_func_list[]={ | |
502 | + "CHR$(",chr_function, | |
503 | + "HEX$(",hex_function, | |
504 | + "DEC$(",dec_function, | |
505 | + "INPUT$(",input_function, | |
506 | + "GOSUB$(",gosub_function, | |
507 | + "ARGS$(",args_function, | |
508 | + "READ$(",read_function, | |
509 | + "SPRINTF$(",sprintf_function, | |
510 | + "FLOAT$(",floatstr_function, | |
511 | + "SYSTEM$(",system_function, | |
512 | + "FINPUT$(",finput_function, | |
513 | + "GETDIR$(",getdir_function, | |
514 | + // Additional functions follow | |
515 | + ADDITIONAL_STR_FUNCTIONS | |
516 | +}; | |
517 | + | |
518 | +char* str_function(void){ | |
519 | + char* err; | |
520 | + int i; | |
521 | + char* (*f)(); | |
522 | + // Seek the function | |
523 | + for (i=0;i<sizeof(str_func_list)/sizeof(str_func_list[0]);i+=2){ | |
524 | + if (nextCodeIs((char*)str_func_list[i])) break; | |
525 | + } | |
526 | + if (i<sizeof(str_func_list)/sizeof(str_func_list[0])) { | |
527 | + // Function found. Call it. | |
528 | + f=str_func_list[i+1]; | |
529 | + err=f(); | |
530 | + } else { | |
531 | + // Check if static method of a class | |
532 | + err=static_method('$'); | |
533 | + //return ERR_SYNTAX; | |
534 | + } | |
535 | + if (err) return err; | |
536 | + if (g_source[g_srcpos]!=')') return ERR_SYNTAX; | |
537 | + g_srcpos++; | |
538 | + return 0; | |
539 | +} | |
540 | + | |
541 | +// Aliases follow | |
542 | + | |
543 | +char* peek_function(){ | |
544 | + return peek_function_sub(8); | |
545 | +} | |
546 | + | |
547 | +char* peek16_function(){ | |
548 | + return peek_function_sub(16); | |
549 | +} | |
550 | + | |
551 | +char* peek32_function(){ | |
552 | + return peek_function_sub(32); | |
553 | +} | |
554 | + | |
555 | +char* gcolor_function(){ | |
556 | + return graphic_statement(FUNC_GCOLOR); | |
557 | +} | |
558 | + | |
559 | +char* fopen_function(){ | |
560 | + return fopen_statement_main(FUNC_FOPEN); | |
561 | +} | |
562 | + | |
563 | +static const void* int_func_list[]={ | |
564 | + "NOT(",not_function, | |
565 | + "DRAWCOUNT(",drawcount_function, | |
566 | + "MUSIC(",music_function, | |
567 | + "TVRAM(",tvram_function, | |
568 | + "KEYS(",keys_function, | |
569 | + "READ(",read_function, | |
570 | + "CREAD(",cread_function, | |
571 | + "GOSUB(",gosub_function, | |
572 | + "STRNCMP(",strncmp_function, | |
573 | + "PEEK(",peek_function, | |
574 | + "PEEK16(",peek16_function, | |
575 | + "PEEK32(",peek32_function, | |
576 | + "LEN(",len_function, | |
577 | + "ASC(",asc_function, | |
578 | + "SGN(",sgn_function, | |
579 | + "ABS(",abs_function, | |
580 | + "RND(",rnd_function, | |
581 | + "VAL(",val_function, | |
582 | + "INKEY(",inkey_function, | |
583 | + "ARGS(",args_function, | |
584 | + "SYSTEM(",system_function, | |
585 | + "INT(",int_function, | |
586 | + "GCOLOR(",gcolor_function, | |
587 | + "FOPEN(",fopen_function, | |
588 | + "FSEEK(",fseek_function, | |
589 | + "FLEN(",flen_function, | |
590 | + "FGET(",fget_statement, | |
591 | + "FPUT(",fput_statement, | |
592 | + "FGETC(",fgetc_function, | |
593 | + "FPUTC(",fputc_statement, | |
594 | + "FREMOVE(",fremove_statement, | |
595 | + "FEOF(",feof_function, | |
596 | + "PLAYWAVE(",playwave_function, | |
597 | + "NEW(",new_function, | |
598 | + "SETDIR(",setdir_function, | |
599 | + "TIMER(",timer_function, | |
600 | + // Additional functions follow | |
601 | + ADDITIONAL_INT_FUNCTIONS | |
602 | +}; | |
603 | + | |
604 | +char* function(void){ | |
605 | + char* err; | |
606 | + int i; | |
607 | + char* (*f)(); | |
608 | + // Seek the function | |
609 | + for (i=0;i<sizeof(int_func_list)/sizeof(int_func_list[0]);i+=2){ | |
610 | + if (nextCodeIs((char*)int_func_list[i])) break; | |
611 | + } | |
612 | + if (i<sizeof(int_func_list)/sizeof(int_func_list[0])) { | |
613 | + // Function found. Call it. | |
614 | + f=int_func_list[i+1]; | |
615 | + err=f(); | |
616 | + } else { | |
617 | + // Check if static method of a class | |
618 | + err=static_method(0); | |
619 | + //return ERR_SYNTAX; | |
620 | + } | |
621 | + if (err) return err; | |
622 | + if (g_source[g_srcpos]!=')') return ERR_SYNTAX; | |
623 | + g_srcpos++; | |
624 | + return 0; | |
625 | +} |
@@ -0,0 +1,95 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by K.Tanaka & Katsumi | |
4 | + http://www.ze.em-net.ne.jp/~kenken/index.html | |
5 | + http://hp.vector.co.jp/authors/VA016157/ | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "compiler.h" | |
13 | +#include "main.h" | |
14 | + | |
15 | +// Contain the valus of $gp and $s6 (GPR of MIPS32) | |
16 | +int g_gp; | |
17 | +int g_s6; | |
18 | + | |
19 | +// Line data when compiling | |
20 | +int g_line; | |
21 | +int g_fileline; | |
22 | + | |
23 | +// Contain the address to which return in "END" statement. | |
24 | +int g_end_addr; | |
25 | + | |
26 | +// Following vars are used in value.c and string.c. | |
27 | +// These define the depth of stack pointer used for | |
28 | +// handling values and strings. | |
29 | +int g_sdepth; | |
30 | +int g_maxsdepth; | |
31 | +char g_allow_shift_obj; | |
32 | + | |
33 | +// Following var shows what type of variable was defined | |
34 | +// in compiling the last code. | |
35 | +enum variable g_lastvar; | |
36 | + | |
37 | +// Vars used for handling constant integer | |
38 | +int g_intconst; | |
39 | +char g_valueisconst; | |
40 | + | |
41 | +// Global vars associated to RAM | |
42 | +char* g_source; | |
43 | +int g_srcpos; | |
44 | +int* g_object; | |
45 | +int g_objpos; | |
46 | +int* g_objmax; | |
47 | +char RAM[RAMSIZE] __attribute__((persistent,address(0xA0000000+PIC32MX_RAMSIZE-PERSISTENT_RAM_SIZE))); | |
48 | +unsigned int g_ex_data[EXCEPTION_DATA_SIZE/4] __attribute__((persistent,address(0xA0000000+PIC32MX_RAMSIZE-EXCEPTION_DATA_SIZE))); | |
49 | + | |
50 | +// Global area for vars A-Z and three temporary string pointers | |
51 | +int g_var_mem[ALLOC_BLOCK_NUM]; | |
52 | +unsigned short g_var_pointer[ALLOC_BLOCK_NUM]; | |
53 | +unsigned short g_var_size[ALLOC_BLOCK_NUM]; | |
54 | + | |
55 | +// Flag to use temporary area when compiling | |
56 | +char g_temp_area_used; | |
57 | + | |
58 | +// Flag to use option nolinenum | |
59 | +char g_nolinenum; | |
60 | + | |
61 | +// Heap area | |
62 | +int* g_heap_mem; | |
63 | +int g_max_mem; | |
64 | + | |
65 | +// Random seed | |
66 | +unsigned int g_rnd_seed; | |
67 | + | |
68 | +// Enable/disable Break keys | |
69 | +char g_disable_break; | |
70 | + | |
71 | +// Font data used for PCG | |
72 | +unsigned char* g_pcg_font; | |
73 | + | |
74 | +// Use or do not use graphic | |
75 | +char g_use_graphic; | |
76 | + | |
77 | +// Pointer to graphic RAM | |
78 | +unsigned short* g_graphic_area; | |
79 | + | |
80 | +// Parameter-containing block used for library | |
81 | +int* g_libparams; | |
82 | + | |
83 | +// Number of long name variables | |
84 | +int g_long_name_var_num; | |
85 | + | |
86 | +// Flag for active music/sound/wave function | |
87 | +char g_music_active; | |
88 | + | |
89 | +// Class name being compiled | |
90 | +int g_class; | |
91 | +// Flag to compile class file | |
92 | +int g_compiling_class; | |
93 | + | |
94 | +// General purpose integer used for asigning value with pointer | |
95 | +int g_temp; |
@@ -0,0 +1,176 @@ | ||
1 | +/* | |
2 | + * 液晶モジュールドライバ for PIC32MX1xx/2xx | |
3 | + * システムクロック48MHz、周辺クロック48MHz | |
4 | + * | |
5 | + * 液晶モジュールの初期化はブートローダ側で行うため不要 | |
6 | + * | |
7 | + * 8bit mode接続 | |
8 | + * D8 RB0 | |
9 | + * D9 RB1 | |
10 | + * D10 RB2 | |
11 | + * D11 RB3 | |
12 | + * D12 RB4 | |
13 | + * D13 RB5 | |
14 | + * D14 RB7 | |
15 | + * D15 RB8 | |
16 | + * RS RB9 | |
17 | + * WR RB10 | |
18 | + * CS RB11 | |
19 | + * RD RB13 | |
20 | + * RESET RB14 | |
21 | + */ | |
22 | + | |
23 | +#include <plib.h> | |
24 | +#include "LCDdriver.h" | |
25 | + | |
26 | +void inline LCD_set_dat(unsigned char c){ | |
27 | + LCD_DATCLR=LCD_DAT_MASK; | |
28 | + LCD_DATSET=((c<<1)&0x180)+(c&0x3f); | |
29 | +} | |
30 | +unsigned char LCD_get_dat(void){ | |
31 | + unsigned short d; | |
32 | + d=PORTB & LCD_DAT_MASK; | |
33 | + return ((d&0x180)>>1)+(d&0x3f); | |
34 | +} | |
35 | +void LCD_WriteIndex(unsigned char index){ | |
36 | +// Write Index | |
37 | + LCD_RS_LO; | |
38 | + LCD_set_dat(0); | |
39 | + LCD_WR_LO; | |
40 | + asm("nop"); | |
41 | + LCD_WR_HI; | |
42 | + LCD_set_dat(index); | |
43 | + LCD_WR_LO; | |
44 | + asm("nop"); | |
45 | + LCD_WR_HI; | |
46 | +} | |
47 | + | |
48 | +void LCD_WriteData(unsigned short data) | |
49 | +{ | |
50 | +// Write Data | |
51 | + LCD_RS_HI; | |
52 | + LCD_set_dat(data>>8); | |
53 | + LCD_WR_LO; | |
54 | + asm("nop"); | |
55 | + LCD_WR_HI; | |
56 | + LCD_set_dat((unsigned char)data); | |
57 | + LCD_WR_LO; | |
58 | + asm("nop"); | |
59 | + LCD_WR_HI; | |
60 | +} | |
61 | +unsigned short LCD_ReadData(void) | |
62 | +{ | |
63 | +// Read Data | |
64 | + unsigned short d; | |
65 | + TRISBSET=LCD_DAT_MASK; | |
66 | + LCD_RS_HI; | |
67 | + LCD_RD_LO; | |
68 | + asm("nop");asm("nop");asm("nop");asm("nop");asm("nop"); | |
69 | + asm("nop");asm("nop");asm("nop");asm("nop");asm("nop"); | |
70 | + asm("nop");asm("nop");asm("nop");asm("nop");asm("nop"); | |
71 | + d=LCD_get_dat(); | |
72 | + LCD_RD_HI; | |
73 | + asm("nop");asm("nop");asm("nop");asm("nop");asm("nop"); | |
74 | + asm("nop");asm("nop");asm("nop");asm("nop");asm("nop"); | |
75 | + LCD_RD_LO; | |
76 | + asm("nop");asm("nop");asm("nop");asm("nop");asm("nop"); | |
77 | + asm("nop");asm("nop");asm("nop");asm("nop");asm("nop"); | |
78 | + asm("nop");asm("nop");asm("nop");asm("nop");asm("nop"); | |
79 | + d=(d<<8)+LCD_get_dat(); | |
80 | + LCD_RD_HI; | |
81 | + asm("nop");asm("nop");asm("nop");asm("nop");asm("nop"); | |
82 | + TRISBCLR=LCD_DAT_MASK; | |
83 | + return d; | |
84 | +} | |
85 | +void LCD_WriteReg(unsigned char index, unsigned short data) | |
86 | +{ | |
87 | +// Write Index | |
88 | + LCD_WriteIndex(index); | |
89 | + | |
90 | +// Write Data | |
91 | + LCD_WriteData(data); | |
92 | +} | |
93 | +unsigned short LCD_ReadReg(unsigned char index) | |
94 | +{ | |
95 | +// Write Index | |
96 | + LCD_WriteIndex(index); | |
97 | + | |
98 | +// Read Data | |
99 | + return LCD_ReadData(); | |
100 | +} | |
101 | + | |
102 | +void LCD_SetCursor(unsigned short x, unsigned short y) | |
103 | +{ | |
104 | +#if LCD_ALIGNMENT == VERTICAL | |
105 | + LCD_WriteReg(0x20, x); | |
106 | + LCD_WriteReg(0x21, y); | |
107 | +#elif LCD_ALIGNMENT == HORIZONTAL | |
108 | + LCD_WriteReg(0x20, y); | |
109 | + LCD_WriteReg(0x21, x); | |
110 | +#endif | |
111 | +} | |
112 | + | |
113 | +void LCD_continuous_output(unsigned short x,unsigned short y,unsigned short color,int n) | |
114 | +{ | |
115 | + //High speed continuous output | |
116 | + int i; | |
117 | + unsigned char d1,d2; | |
118 | + LCD_SetCursor(x,y); | |
119 | + LCD_WriteIndex(0x22); | |
120 | + LCD_RS_HI; | |
121 | + d1=color>>8; | |
122 | + d2=(unsigned char)color; | |
123 | + for (i=0; i < n ; i++){ | |
124 | + LCD_set_dat(d1); | |
125 | + LCD_WR_LO; | |
126 | + asm("nop"); | |
127 | + LCD_WR_HI; | |
128 | + LCD_set_dat(d2); | |
129 | + LCD_WR_LO; | |
130 | + asm("nop"); | |
131 | + LCD_WR_HI; | |
132 | + } | |
133 | +} | |
134 | +void LCD_Clear(unsigned short color) | |
135 | +{ | |
136 | + LCD_continuous_output(0,0,color,X_RES*Y_RES); | |
137 | +} | |
138 | + | |
139 | +void drawPixel(unsigned short x, unsigned short y, unsigned short color) | |
140 | +{ | |
141 | + LCD_SetCursor(x,y); | |
142 | + LCD_WriteIndex(0x22); | |
143 | + LCD_WriteData(color); | |
144 | +} | |
145 | + | |
146 | +unsigned short getColor(unsigned short x, unsigned short y) | |
147 | +{ | |
148 | + unsigned short d; | |
149 | + LCD_SetCursor(x,y); | |
150 | + LCD_WriteIndex(0x22); | |
151 | + LCD_ReadData(); //dummy read | |
152 | + d=LCD_ReadData(); | |
153 | + return (d>>11)+(d&0x7e0)+((d&0x1f)<<11); //swap R and B | |
154 | +} | |
155 | + | |
156 | +void LCD_set_Vertical(void){ | |
157 | + if(LCD_ReadReg(0)==0x0129){ | |
158 | + LCD_WriteReg(0x01, 0x0127); | |
159 | + LCD_WriteReg(0x03, 0x1030); | |
160 | + } | |
161 | + else{ | |
162 | + LCD_WriteReg(0x01, 0x0100); | |
163 | + LCD_WriteReg(0x03, 0x1030); | |
164 | + } | |
165 | +} | |
166 | + | |
167 | +void LCD_set_Horizontal(void){ | |
168 | + if(LCD_ReadReg(0)==0x0129){ | |
169 | + LCD_WriteReg(0x01, 0x0027); | |
170 | + LCD_WriteReg(0x03, 0x1028); | |
171 | + } | |
172 | + else{ | |
173 | + LCD_WriteReg(0x01, 0x0000); | |
174 | + LCD_WriteReg(0x03, 0x1028); | |
175 | + } | |
176 | +} |
@@ -0,0 +1,36 @@ | ||
1 | +#define VERTICAL 0 | |
2 | +#define HORIZONTAL 1 | |
3 | +//#define LCD_ALIGNMENT VERTICAL | |
4 | +#define LCD_ALIGNMENT HORIZONTAL | |
5 | + | |
6 | +#if LCD_ALIGNMENT == VERTICAL | |
7 | + #define X_RES 240 // 横方向解像度 | |
8 | + #define Y_RES 320 // 縦方向解像度 | |
9 | +#else | |
10 | + #define X_RES 320 // 横方向解像度 | |
11 | + #define Y_RES 240 // 縦方向解像度 | |
12 | +#endif | |
13 | + | |
14 | +#define LCD_DAT_MASK 0x01bf | |
15 | +#define LCD_DATCLR LATBCLR | |
16 | +#define LCD_DATSET LATBSET | |
17 | +#define LCD_RS_LO LATBCLR=0x200 | |
18 | +#define LCD_RS_HI LATBSET=0x200 | |
19 | +#define LCD_CS_LO LATBCLR=0x800 | |
20 | +#define LCD_CS_HI LATBSET=0x800 | |
21 | +#define LCD_WR_LO LATBCLR=0x400 | |
22 | +#define LCD_WR_HI LATBSET=0x400 | |
23 | +#define LCD_RD_LO LATBCLR=0x2000 | |
24 | +#define LCD_RD_HI LATBSET=0x2000 | |
25 | +#define LCD_RESET_LO LATBCLR=0x4000 | |
26 | +#define LCD_RESET_HI LATBSET=0x4000 | |
27 | + | |
28 | +void LCD_WriteIndex(unsigned char index); | |
29 | +void LCD_WriteData(unsigned short data); | |
30 | +unsigned short LCD_ReadData(void); | |
31 | +void LCD_Init(void); | |
32 | +void LCD_SetCursor(unsigned short x, unsigned short y); | |
33 | +void LCD_Clear(unsigned short color); | |
34 | +void drawPixel(unsigned short x, unsigned short y, unsigned short color); | |
35 | +void LCD_set_Vertical(void); | |
36 | +void LCD_set_Horizontal(void); |
@@ -0,0 +1,2344 @@ | ||
1 | +/****************************************************************************** | |
2 | + * | |
3 | + * Microchip Memory Disk Drive File System | |
4 | + * | |
5 | + ****************************************************************************** | |
6 | + * FileName: FSIO.h | |
7 | + * Dependencies: GenericTypeDefs.h | |
8 | + * FSconfig.h | |
9 | + * FSDefs.h | |
10 | + * stddef.h | |
11 | + * Processor: PIC18/PIC24/dsPIC30/dsPIC33/PIC32 | |
12 | + * Compiler: C18/C30/C32 | |
13 | + * Company: Microchip Technology, Inc. | |
14 | + * Version: 1.3.0 | |
15 | + * | |
16 | + * Software License Agreement | |
17 | + * | |
18 | + * The software supplied herewith by Microchip Technology Incorporated | |
19 | + * (the 鼎ompany・ for its PICmicroョ Microcontroller is intended and | |
20 | + * supplied to you, the Company痴 customer, for use solely and | |
21 | + * exclusively on Microchip PICmicro Microcontroller products. The | |
22 | + * software is owned by the Company and/or its supplier, and is | |
23 | + * protected under applicable copyright laws. All rights are reserved. | |
24 | + * Any use in violation of the foregoing restrictions may subject the | |
25 | + * user to criminal sanctions under applicable laws, as well as to | |
26 | + * civil liability for the breach of the terms and conditions of this | |
27 | + * license. | |
28 | + * | |
29 | + * THIS SOFTWARE IS PROVIDED IN AN 鄭S IS・CONDITION. NO WARRANTIES, | |
30 | + * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED | |
31 | + * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |
32 | + * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, | |
33 | + * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR | |
34 | + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. | |
35 | + * | |
36 | +*****************************************************************************/ | |
37 | + | |
38 | +#ifndef FS_DOT_H | |
39 | +#define FS_DOT_H | |
40 | + | |
41 | +#define ALLOW_FILESEARCH | |
42 | +#define ALLOW_WRITES | |
43 | +#define ALLOW_DIRS | |
44 | +#define SUPPORT_FAT32 | |
45 | + | |
46 | +#define MDD_MediaInitialize MDD_SDSPI_MediaInitialize | |
47 | +#define MDD_MediaDetect MDD_SDSPI_MediaDetect | |
48 | +#define MDD_SectorRead MDD_SDSPI_SectorRead | |
49 | +#define MDD_SectorWrite MDD_SDSPI_SectorWrite | |
50 | +#define MDD_InitIO MDD_SDSPI_InitIO | |
51 | +#define MDD_ShutdownMedia MDD_SDSPI_ShutdownMedia | |
52 | +#define MDD_WriteProtectState MDD_SDSPI_WriteProtectState | |
53 | + | |
54 | +// Summary: An enumeration used for various error codes. | |
55 | +// Description: The CETYPE enumeration is used to indicate different error conditions during device operation. | |
56 | +typedef enum _CETYPE | |
57 | +{ | |
58 | + CE_GOOD = 0, // No error | |
59 | + CE_ERASE_FAIL, // An erase failed | |
60 | + CE_NOT_PRESENT, // No device was present | |
61 | + CE_NOT_FORMATTED, // The disk is of an unsupported format | |
62 | + CE_BAD_PARTITION, // The boot record is bad | |
63 | + CE_UNSUPPORTED_FS, // The file system type is unsupported | |
64 | + CE_INIT_ERROR, // An initialization error has occured | |
65 | + CE_NOT_INIT, // An operation was performed on an uninitialized device | |
66 | + CE_BAD_SECTOR_READ, // A bad read of a sector occured | |
67 | + CE_WRITE_ERROR, // Could not write to a sector | |
68 | + CE_INVALID_CLUSTER, // Invalid cluster value > maxcls | |
69 | + CE_FILE_NOT_FOUND, // Could not find the file on the device | |
70 | + CE_DIR_NOT_FOUND, // Could not find the directory | |
71 | + CE_BAD_FILE, // File is corrupted | |
72 | + CE_DONE, // No more files in this directory | |
73 | + CE_COULD_NOT_GET_CLUSTER, // Could not load/allocate next cluster in file | |
74 | + CE_FILENAME_2_LONG, // A specified file name is too long to use | |
75 | + CE_FILENAME_EXISTS, // A specified filename already exists on the device | |
76 | + CE_INVALID_FILENAME, // Invalid file name | |
77 | + CE_DELETE_DIR, // The user tried to delete a directory with FSremove | |
78 | + CE_DIR_FULL, // All root dir entry are taken | |
79 | + CE_DISK_FULL, // All clusters in partition are taken | |
80 | + CE_DIR_NOT_EMPTY, // This directory is not empty yet, remove files before deleting | |
81 | + CE_NONSUPPORTED_SIZE, // The disk is too big to format as FAT16 | |
82 | + CE_WRITE_PROTECTED, // Card is write protected | |
83 | + CE_FILENOTOPENED, // File not opened for the write | |
84 | + CE_SEEK_ERROR, // File location could not be changed successfully | |
85 | + CE_BADCACHEREAD, // Bad cache read | |
86 | + CE_CARDFAT32, // FAT 32 - card not supported | |
87 | + CE_READONLY, // The file is read-only | |
88 | + CE_WRITEONLY, // The file is write-only | |
89 | + CE_INVALID_ARGUMENT, // Invalid argument | |
90 | + CE_TOO_MANY_FILES_OPEN, // Too many files are already open | |
91 | + CE_UNSUPPORTED_SECTOR_SIZE // Unsupported sector size | |
92 | +} CETYPE; | |
93 | + | |
94 | + | |
95 | +// Summary: A macro indicating a dir entry was found | |
96 | +// Description: The FOUND macro indicates that a directory entry was found in the specified position | |
97 | +#define FOUND 0 | |
98 | + | |
99 | +// Summary: A macro indicating no dir entry was found | |
100 | +// Description: The NOT_FOUND macro indicates that the specified directory entry to load was deleted | |
101 | +#define NOT_FOUND 1 | |
102 | + | |
103 | +// Summary: A macro indicating that no more files were found | |
104 | +// Description: The NO_MORE macro indicates that there are no more directory entries to search for | |
105 | +#define NO_MORE 2 | |
106 | + | |
107 | + | |
108 | + | |
109 | +// Summary: A macro indicating the device is formatted with FAT12 | |
110 | +// Description: The FAT12 macro is used to indicate that the file system on the device being accessed is a FAT12 file system. | |
111 | +#define FAT12 1 | |
112 | + | |
113 | +// Summary: A macro indicating the device is formatted with FAT16 | |
114 | +// Description: The FAT16 macro is used to indicate that the file system on the device being accessed is a FAT16 file system. | |
115 | +#define FAT16 2 | |
116 | + | |
117 | +// Summary: A macro indicating the device is formatted with FAT32 | |
118 | +// Description: The FAT32 macro is used to indicate that the file system on the device being accessed is a FAT32 file system. | |
119 | +#define FAT32 3 | |
120 | + | |
121 | + | |
122 | + | |
123 | +// Summary: A read-only attribute macro | |
124 | +// Description: A macro for the read-only attribute. A file with this attribute should not be written to. Note that this | |
125 | +// attribute will not actually prevent a write to the file; that functionality is operating-system dependant. The | |
126 | +// user should take care not to write to a read-only file. | |
127 | +#define ATTR_READ_ONLY 0x01 | |
128 | + | |
129 | +// Summary: A hidden attribute macro | |
130 | +// Description: A macro for the hidden attribute. A file with this attribute may be hidden from the user, depending on the | |
131 | +// implementation of the operating system. | |
132 | +#define ATTR_HIDDEN 0x02 | |
133 | + | |
134 | +// Summary: A system attribute macro | |
135 | +// Description: A macro for the system attribute. A file with this attribute is used by the operating system, and should not be | |
136 | +// modified. Note that this attribute will not actually prevent a write to the file. | |
137 | +#define ATTR_SYSTEM 0x04 | |
138 | + | |
139 | +// Summary: A volume attribute macro | |
140 | +// Description: A macro for the volume attribute. If the first directory entry in the root directory has the volume attribute set, | |
141 | +// the device will use the name in that directory entry as the volume name. | |
142 | +#define ATTR_VOLUME 0x08 | |
143 | + | |
144 | +// Summary: A macro for the attributes for a long-file name entry | |
145 | +// Description: A macro for the long-name attributes. If a directory entry is used in a long-file name implementation, it will have | |
146 | +// all four lower bits set. This indicates that any software that does not support long file names should ignore that | |
147 | +// entry. | |
148 | +#define ATTR_LONG_NAME 0x0f | |
149 | + | |
150 | +// Summary: A directory attribute macro | |
151 | +// Description: A macro for the directory attribute. If a directory entry has this attribute set, the file it points to is a directory- | |
152 | +// type file, and will contain directory entries that point to additional directories or files. | |
153 | +#define ATTR_DIRECTORY 0x10 | |
154 | + | |
155 | +// Summary: An archive attribute macro | |
156 | +// Description: A macro for the archive attribute. This attribute will indicate to some archiving programs that the file with this | |
157 | +// attribute needs to be backed up. Most operating systems create files with the archive attribute set. | |
158 | +#define ATTR_ARCHIVE 0x20 | |
159 | + | |
160 | +// Summary: A macro for all attributes | |
161 | +// Description: A macro for all attributes. The search functions in this library require an argument that determines which attributes | |
162 | +// a file is allowed to have in order to be found. If ATTR_MASK is specified as this argument, any file may be found, regardless | |
163 | +// of its attributes. | |
164 | +#define ATTR_MASK 0x3f | |
165 | + | |
166 | + | |
167 | + | |
168 | +// Summary: A macro to indicate an empty FAT entry | |
169 | +// Description: The CLUSTER_EMPTY value is used to indicate that a FAT entry and it's corresponding cluster are available. | |
170 | +#define CLUSTER_EMPTY 0x0000 | |
171 | + | |
172 | +// Summary: A macro to indicate the last cluster value for FAT12 | |
173 | +// Description: The LAST_CLUSTER_FAT12 macro is used when reading the FAT to indicate that the next FAT12 entry for a file contains | |
174 | +// the end-of-file value. | |
175 | +#define LAST_CLUSTER_FAT12 0xff8 | |
176 | + | |
177 | +// Summary: A macro to indicate the last cluster value for FAT16 | |
178 | +// Description: The LAST_CLUSTER_FAT16 macro is used when reading the FAT to indicate that the next FAT16 entry for a file contains | |
179 | +// the end-of-file value. | |
180 | +#define LAST_CLUSTER_FAT16 0xfff8 | |
181 | + | |
182 | +// Summary: A macro to indicate the last allocatable cluster for FAT12 | |
183 | +// Description: The END_CLUSTER_FAT12 value is used as a comparison in FAT12 to determine that the firmware has reached the end of | |
184 | +// the range of allowed allocatable clusters. | |
185 | +#define END_CLUSTER_FAT12 0xFF7 | |
186 | + | |
187 | +// Summary: A macro to indicate the last allocatable cluster for FAT16 | |
188 | +// Description: The END_CLUSTER_FAT16 value is used as a comparison in FAT16 to determine that the firmware has reached the end of | |
189 | +// the range of allowed allocatable clusters. | |
190 | +#define END_CLUSTER_FAT16 0xFFF7 | |
191 | + | |
192 | +// Summary: A macro to indicate the failure of the ReadFAT function | |
193 | +// Description: The CLUSTER_FAIL_FAT16 macro is used by the ReadFAT function to indicate that an error occured reading a FAT12 or FAT16 | |
194 | +// file allocation table. Note that since '0xFFF8' is used for the last cluster return value in the FAT16 implementation | |
195 | +// the end-of-file value '0xFFFF' can be used to indicate an error condition. | |
196 | +#define CLUSTER_FAIL_FAT16 0xFFFF | |
197 | + | |
198 | + | |
199 | + | |
200 | +#ifdef SUPPORT_FAT32 | |
201 | + // Summary: A macro to indicate the last cluster value for FAT32 | |
202 | + // Description: The LAST_CLUSTER_FAT32 macro is used when reading the FAT to indicate that the next FAT32 entry for a file contains | |
203 | + // the end-of-file value. | |
204 | + #define LAST_CLUSTER_FAT32 0x0FFFFFF8 | |
205 | + | |
206 | + // Summary: A macro to indicate the last allocatable cluster for FAT32 | |
207 | + // Description: The END_CLUSTER_FAT32 value is used as a comparison in FAT32 to determine that the firmware has reached the end of | |
208 | + // the range of allowed allocatable clusters. | |
209 | + #define END_CLUSTER_FAT32 0x0FFFFFF7 | |
210 | + | |
211 | + // Summary: A macro to indicate the failure of the ReadFAT function | |
212 | + // Description: The CLUSTER_FAIL_FAT32 macro is used by the ReadFAT function to indicate that an error occured reading a FAT32 | |
213 | + // file allocation able. | |
214 | + #define CLUSTER_FAIL_FAT32 0x0FFFFFFF | |
215 | + | |
216 | +#endif | |
217 | + | |
218 | +// Summary: A macro indicating the number of bytes in a directory entry. | |
219 | +// Description: The NUMBER_OF_BYTES_IN_DIR_ENTRY macro represents the number of bytes in one directory entry. It is used to calculate | |
220 | +// the number of sectors in the root directory based on information in the boot sector. | |
221 | +#define NUMBER_OF_BYTES_IN_DIR_ENTRY 32 | |
222 | + | |
223 | + | |
224 | + | |
225 | +// Summary: A macro for a deleted dir entry marker. | |
226 | +// Description: The DIR_DEL macro is used to mark a directory entry as deleted. When a file is deleted, this value will replace the | |
227 | +// first character in the file name, and will indicate that the file the entry points to was deleted. | |
228 | +#define DIR_DEL 0xE5 | |
229 | + | |
230 | +// Summary: A macro for the last dir entry marker. | |
231 | +// Description: The DIR_EMPTY macro is used to indicate the last entry in a directory. Since entries in use cannot start with a 0 and | |
232 | +// deleted entries start with the DIR_DEL character, a 0 will mark the end of the in-use or previously used group of | |
233 | +// entries in a directory | |
234 | +#define DIR_EMPTY 0 | |
235 | + | |
236 | + | |
237 | + | |
238 | +// Summary: A macro used to indicate the length of an 8.3 file name | |
239 | +// Description: The DIR_NAMESIZE macro is used when validing the name portion of 8.3 filenames | |
240 | +#define DIR_NAMESIZE 8 | |
241 | + | |
242 | +// Summary: A macro used to indicate the length of an 8.3 file extension | |
243 | +// Description: The DIR_EXTENSION macro is used when validating the extension portion of 8.3 filenames | |
244 | +#define DIR_EXTENSION 3 | |
245 | + | |
246 | +// Summary: A macro used to indicate the length of an 8.3 file name and extension | |
247 | +// Description: The DIR_NAMECOMP macro is used when validating 8.3 filenames | |
248 | +#define DIR_NAMECOMP (DIR_NAMESIZE+DIR_EXTENSION) | |
249 | + | |
250 | + | |
251 | + | |
252 | +// Summary: A macro to write a byte to RAM | |
253 | +// Description: The RAMwrite macro is used to write a byte of data to a RAM array | |
254 | +#define RAMwrite( a, f, d) *(a+f) = d | |
255 | + | |
256 | +// Summary: A macro to read a byte from RAM | |
257 | +// Description: The RAMread macro is used to read a byte of data from a RAM array | |
258 | +#define RAMread( a, f) *(a+f) | |
259 | + | |
260 | +// Summary: A macro to read a 16-bit word from RAM | |
261 | +// Description: The RAMreadW macro is used to read two bytes of data from a RAM array | |
262 | +#define RAMreadW( a, f) *(WORD *)(a+f) | |
263 | + | |
264 | +// Summary: A macro to read a 32-bit word from RAM | |
265 | +// Description: The RAMreadD macro is used to read four bytes of data from a RAM array | |
266 | +#define RAMreadD( a, f) *(DWORD *)(a+f) | |
267 | + | |
268 | + | |
269 | + | |
270 | +#ifndef EOF | |
271 | + // Summary: Indicates error conditions or end-of-file conditions | |
272 | + // Description: The EOF macro is used to indicate error conditions in some function calls. It is also used to indicate | |
273 | + // that the end-of-file has been reached. | |
274 | + #define EOF ((int)-1) | |
275 | +#endif | |
276 | + | |
277 | + | |
278 | + | |
279 | +// Summary: A structure containing information about the device. | |
280 | +// Description: The DISK structure contains information about the device being accessed. | |
281 | +typedef struct | |
282 | +{ | |
283 | + BYTE * buffer; // Address of the global data buffer used to read and write file information | |
284 | + DWORD firsts; // Logical block address of the first sector of the FAT partition on the device | |
285 | + DWORD fat; // Logical block address of the FAT | |
286 | + DWORD root; // Logical block address of the root directory | |
287 | + DWORD data; // Logical block address of the data section of the device. | |
288 | + WORD maxroot; // The maximum number of entries in the root directory. | |
289 | + DWORD maxcls; // The maximum number of clusters in the partition. | |
290 | + DWORD sectorSize; // The size of a sector in bytes | |
291 | + DWORD fatsize; // The number of sectors in the FAT | |
292 | + BYTE fatcopy; // The number of copies of the FAT in the partition | |
293 | + BYTE SecPerClus; // The number of sectors per cluster in the data region | |
294 | + BYTE type; // The file system type of the partition (FAT12, FAT16 or FAT32) | |
295 | + BYTE mount; // Device mount flag (TRUE if disk was mounted successfully, FALSE otherwise) | |
296 | +#if defined __PIC32MX__ || defined __C30__ | |
297 | +} __attribute__ ((packed)) DISK; | |
298 | +#else | |
299 | +} DISK; | |
300 | +#endif | |
301 | + | |
302 | + | |
303 | +#ifdef __18CXX | |
304 | + // Summary: A 24-bit data type | |
305 | + // Description: The SWORD macro is used to defined a 24-bit data type. For 16+ bit architectures, this must be represented as | |
306 | + // an array of three bytes. | |
307 | + typedef unsigned short long SWORD; | |
308 | +#else | |
309 | + // Summary: A 24-bit data type | |
310 | + // Description: The SWORD macro is used to defined a 24-bit data type. For 16+ bit architectures, this must be represented as | |
311 | + // an array of three bytes. | |
312 | + typedef struct | |
313 | + { | |
314 | + unsigned char array[3]; | |
315 | +#if defined __PIC32MX__ || defined __C30__ | |
316 | + } __attribute__ ((packed)) SWORD; | |
317 | +#else | |
318 | + } SWORD; | |
319 | +#endif | |
320 | +#endif | |
321 | + | |
322 | + | |
323 | + | |
324 | +// Summary: A structure containing the bios parameter block for a FAT12 file system (in the boot sector) | |
325 | +// Description: The _BPB_FAT12 structure provides a layout of the "bios parameter block" in the boot sector of a FAT12 partition. | |
326 | +typedef struct { | |
327 | + SWORD BootSec_JumpCmd; // Jump Command | |
328 | + BYTE BootSec_OEMName[8]; // OEM name | |
329 | + WORD BootSec_BPS; // Number of bytes per sector | |
330 | + BYTE BootSec_SPC; // Number of sectors per cluster | |
331 | + WORD BootSec_ResrvSec; // Number of reserved sectors at the beginning of the partition | |
332 | + BYTE BootSec_FATCount; // Number of FATs on the partition | |
333 | + WORD BootSec_RootDirEnts; // Number of root directory entries | |
334 | + WORD BootSec_TotSec16; // Total number of sectors | |
335 | + BYTE BootSec_MDesc; // Media descriptor | |
336 | + WORD BootSec_SPF; // Number of sectors per FAT | |
337 | + WORD BootSec_SPT; // Number of sectors per track | |
338 | + WORD BootSec_HeadCnt; // Number of heads | |
339 | + DWORD BootSec_HiddenSecCnt; // Number of hidden sectors | |
340 | + DWORD BootSec_Reserved; // Reserved space | |
341 | + BYTE BootSec_DriveNum; // Drive number | |
342 | + BYTE BootSec_Reserved2; // Reserved space | |
343 | + BYTE BootSec_BootSig; // Boot signature - equal to 0x29 | |
344 | + BYTE BootSec_VolID[4]; // Volume ID | |
345 | + BYTE BootSec_VolLabel[11]; // Volume Label | |
346 | + BYTE BootSec_FSType[8]; // File system type in ASCII. Not used for determination | |
347 | +#if defined __PIC32MX__ || defined __C30__ | |
348 | + } __attribute__ ((packed)) _BPB_FAT12; | |
349 | +#else | |
350 | + } _BPB_FAT12; | |
351 | +#endif | |
352 | + | |
353 | +// Summary: A structure containing the bios parameter block for a FAT16 file system (in the boot sector) | |
354 | +// Description: The _BPB_FAT16 structure provides a layout of the "bios parameter block" in the boot sector of a FAT16 partition. | |
355 | +typedef struct { | |
356 | + SWORD BootSec_JumpCmd; // Jump Command | |
357 | + BYTE BootSec_OEMName[8]; // OEM name | |
358 | + WORD BootSec_BPS; // Number of bytes per sector | |
359 | + BYTE BootSec_SPC; // Number of sectors per cluster | |
360 | + WORD BootSec_ResrvSec; // Number of reserved sectors at the beginning of the partition | |
361 | + BYTE BootSec_FATCount; // Number of FATs on the partition | |
362 | + WORD BootSec_RootDirEnts; // Number of root directory entries | |
363 | + WORD BootSec_TotSec16; // Total number of sectors | |
364 | + BYTE BootSec_MDesc; // Media descriptor | |
365 | + WORD BootSec_SPF; // Number of sectors per FAT | |
366 | + WORD BootSec_SPT; // Number of sectors per track | |
367 | + WORD BootSec_HeadCnt; // Number of heads | |
368 | + DWORD BootSec_HiddenSecCnt; // Number of hidden sectors | |
369 | + DWORD BootSec_TotSec32; // Total sector count (32 bits) | |
370 | + BYTE BootSec_DriveNum; // Drive number | |
371 | + BYTE BootSec_Reserved; // Reserved space | |
372 | + BYTE BootSec_BootSig; // Boot signature - equal to 0x29 | |
373 | + BYTE BootSec_VolID[4]; // Volume ID | |
374 | + BYTE BootSec_VolLabel[11]; // Volume Label | |
375 | + BYTE BootSec_FSType[8]; // File system type in ASCII. Not used for determination | |
376 | +#if defined __PIC32MX__ || defined __C30__ | |
377 | + } __attribute__ ((packed)) _BPB_FAT16; | |
378 | +#else | |
379 | + } _BPB_FAT16; | |
380 | +#endif | |
381 | + | |
382 | +// Summary: A structure containing the bios parameter block for a FAT32 file system (in the boot sector) | |
383 | +// Description: The _BPB_FAT32 structure provides a layout of the "bios parameter block" in the boot sector of a FAT32 partition. | |
384 | +typedef struct { | |
385 | + SWORD BootSec_jmpBoot; // Jump Command | |
386 | + BYTE BootSec_OEMName[8]; // OEM name | |
387 | + WORD BootSec_BytsPerSec; // Number of bytes per sector | |
388 | + BYTE BootSec_SecPerClus; // Number of sectors per cluster | |
389 | + WORD BootSec_RsvdSecCnt; // Number of reserved sectors at the beginning of the partition | |
390 | + BYTE BootSec_NumFATs; // Number of FATs on the partition | |
391 | + WORD BootSec_RootEntCnt; // Number of root directory entries | |
392 | + WORD BootSec_TotSec16; // Total number of sectors | |
393 | + BYTE BootSec_Media; // Media descriptor | |
394 | + WORD BootSec_FATSz16; // Number of sectors per FAT | |
395 | + WORD BootSec_SecPerTrk; // Number of sectors per track | |
396 | + WORD BootSec_NumHeads; // Number of heads | |
397 | + DWORD BootSec_HiddSec; // Number of hidden sectors | |
398 | + DWORD BootSec_TotSec32; // Total sector count (32 bits) | |
399 | + DWORD BootSec_FATSz32; // Sectors per FAT (32 bits) | |
400 | + WORD BootSec_ExtFlags; // Presently active FAT. Defined by bits 0-3 if bit 7 is 1. | |
401 | + WORD BootSec_FSVers; // FAT32 filesystem version. Should be 0:0 | |
402 | + DWORD BootSec_RootClus; // Start cluster of the root directory (should be 2) | |
403 | + WORD BootSec_FSInfo; // File system information | |
404 | + WORD BootSec_BkBootSec; // Backup boot sector address. | |
405 | + BYTE BootSec_Reserved[12]; // Reserved space | |
406 | + BYTE BootSec_DrvNum; // Drive number | |
407 | + BYTE BootSec_Reserved1; // Reserved space | |
408 | + BYTE BootSec_BootSig; // Boot signature - 0x29 | |
409 | + BYTE BootSec_VolID[4]; // Volume ID | |
410 | + BYTE BootSec_VolLab[11]; // Volume Label | |
411 | + BYTE BootSec_FilSysType[8]; // File system type in ASCII. Not used for determination | |
412 | +#if defined __PIC32MX__ || defined __C30__ | |
413 | + } __attribute__ ((packed)) _BPB_FAT32; | |
414 | +#else | |
415 | + } _BPB_FAT32; | |
416 | +#endif | |
417 | + | |
418 | + | |
419 | +// Description: A macro for the boot sector bytes per sector value offset | |
420 | +#define BSI_BPS 11 | |
421 | + | |
422 | +// Description: A macro for the boot sector sector per cluster value offset | |
423 | +#define BSI_SPC 13 | |
424 | + | |
425 | +// Description: A macro for the boot sector reserved sector count value offset | |
426 | +#define BSI_RESRVSEC 14 | |
427 | + | |
428 | +// Description: A macro for the boot sector FAT count value offset | |
429 | +#define BSI_FATCOUNT 16 | |
430 | + | |
431 | +// Description: A macro for the boot sector root directory entry count value offset | |
432 | +#define BSI_ROOTDIRENTS 17 | |
433 | + | |
434 | +// Description: A macro for the boot sector 16-bit total sector count value offset | |
435 | +#define BSI_TOTSEC16 19 | |
436 | + | |
437 | +// Description: A macro for the boot sector sectors per FAT value offset | |
438 | +#define BSI_SPF 22 | |
439 | + | |
440 | +// Description: A macro for the boot sector 32-bit total sector count value offset | |
441 | +#define BSI_TOTSEC32 32 | |
442 | + | |
443 | +// Description: A macro for the boot sector boot signature offset | |
444 | +#define BSI_BOOTSIG 38 | |
445 | + | |
446 | +// Description: A macro for the boot sector file system type string offset | |
447 | +#define BSI_FSTYPE 54 | |
448 | + | |
449 | +// Description: A macro for the boot sector 32-bit sector per FAT value offset | |
450 | +#define BSI_FATSZ32 36 | |
451 | + | |
452 | +// Description: A macro for the boot sector start cluster of root directory value offset | |
453 | +#define BSI_ROOTCLUS 44 | |
454 | + | |
455 | +// Description: A macro for the FAT32 boot sector boot signature offset | |
456 | +#define BSI_FAT32_BOOTSIG 66 | |
457 | + | |
458 | +// Description: A macro for the FAT32 boot sector file system type string offset | |
459 | +#define BSI_FAT32_FSTYPE 82 | |
460 | + | |
461 | + | |
462 | + | |
463 | +// Summary: A partition table entry structure. | |
464 | +// Description: The PTE_MBR structure contains values found in a partition table entry in the MBR of a device. | |
465 | +typedef struct | |
466 | +{ | |
467 | + BYTE PTE_BootDes; // The boot descriptor (should be 0x00 in a non-bootable device) | |
468 | + SWORD PTE_FrstPartSect; // The cylinder-head-sector address of the first sector of the partition | |
469 | + BYTE PTE_FSDesc; // The file system descriptor | |
470 | + SWORD PTE_LstPartSect; // The cylinder-head-sector address of the last sector of the partition | |
471 | + DWORD PTE_FrstSect; // The logical block address of the first sector of the partition | |
472 | + DWORD PTE_NumSect; // The number of sectors in a partition | |
473 | +#if defined __PIC32MX__ || defined __C30__ | |
474 | + } __attribute__ ((packed)) PTE_MBR; | |
475 | +#else | |
476 | + } PTE_MBR; | |
477 | +#endif | |
478 | + | |
479 | + | |
480 | +// Summary: A structure of the organization of a master boot record. | |
481 | +// Description: The _PT_MBR structure has the same form as a master boot record. When the MBR is loaded from the device, it will | |
482 | +// be cast as a _PT_MBR structure so the MBR elements can be accessed. | |
483 | +typedef struct | |
484 | +{ | |
485 | + BYTE ConsChkRtn[446]; // Boot code | |
486 | + PTE_MBR Partition0; // The first partition table entry | |
487 | + PTE_MBR Partition1; // The second partition table entry | |
488 | + PTE_MBR Partition2; // The third partition table entry | |
489 | + PTE_MBR Partition3; // The fourth partition table entry | |
490 | + BYTE Signature0; // MBR signature code - equal to 0x55 | |
491 | + BYTE Signature1; // MBR signature code - equal to 0xAA | |
492 | +#if defined __PIC32MX__ || defined __C30__ | |
493 | +}__attribute__((packed)) _PT_MBR; | |
494 | +#else | |
495 | +}_PT_MBR; | |
496 | +#endif | |
497 | + | |
498 | +// Summary: A pointer to a _PT_MBR structure | |
499 | +// Description: The PT_MBR pointer points to a _PT_MBR structure. | |
500 | +typedef _PT_MBR * PT_MBR; | |
501 | + | |
502 | + | |
503 | + | |
504 | +// Summary: A structure of the organization of a boot sector. | |
505 | +// Description: The _BootSec structure has the same form as a boot sector. When the boot sector is loaded from the device, it will | |
506 | +// be cast as a _BootSec structure so the boot sector elements can be accessed. | |
507 | +typedef struct | |
508 | +{ | |
509 | + // A union of different bios parameter blocks | |
510 | + union | |
511 | + { | |
512 | + _BPB_FAT32 FAT_32; | |
513 | + _BPB_FAT16 FAT_16; | |
514 | + _BPB_FAT12 FAT_12; | |
515 | + }FAT; | |
516 | + BYTE Reserved[512-sizeof(_BPB_FAT32)-2]; // Reserved space | |
517 | + BYTE Signature0; // Boot sector signature code - equal to 0x55 | |
518 | + BYTE Signature1; // Boot sector signature code - equal to 0xAA | |
519 | +#if defined __PIC32MX__ || defined __C30__ | |
520 | + } __attribute__ ((packed)) _BootSec; | |
521 | +#else | |
522 | + } _BootSec; | |
523 | +#endif | |
524 | + | |
525 | +// Summary: A pointer to a _BootSec structure | |
526 | +// Description: The BootSec pointer points to a _BootSec structure. | |
527 | +typedef _BootSec * BootSec; | |
528 | + | |
529 | + | |
530 | + | |
531 | +// Summary: A macro indicating the offset for the master boot record | |
532 | +// Description: FO_MBR is a macro that indicates the addresss of the master boot record on the device. When the device is initialized | |
533 | +// this sector will be read | |
534 | +#define FO_MBR 0L | |
535 | + | |
536 | + | |
537 | + | |
538 | +// Summary: A macro for the first boot sector/MBR signature byte | |
539 | +// Description: The FAT_GOOD_SIGN_0 macro is used to determine that the first byte of the MBR or boot sector signature code is correct | |
540 | +#define FAT_GOOD_SIGN_0 0x55 | |
541 | + | |
542 | +// Summary: A macro for the second boot sector/MBR signature byte | |
543 | +// Description: The FAT_GOOD_SIGN_1 macro is used to determine that the second byte of the MBR or boot sector signature code is correct | |
544 | +#define FAT_GOOD_SIGN_1 0xAA | |
545 | + | |
546 | + | |
547 | +typedef struct | |
548 | +{ | |
549 | + BYTE errorCode; | |
550 | + union | |
551 | + { | |
552 | + BYTE value; | |
553 | + struct | |
554 | + { | |
555 | + BYTE sectorSize : 1; | |
556 | + BYTE maxLUN : 1; | |
557 | + } bits; | |
558 | + } validityFlags; | |
559 | + | |
560 | + WORD sectorSize; | |
561 | + BYTE maxLUN; | |
562 | +} MEDIA_INFORMATION; | |
563 | + | |
564 | +typedef enum | |
565 | +{ | |
566 | + MEDIA_NO_ERROR, // No errors | |
567 | + MEDIA_DEVICE_NOT_PRESENT, // The requested device is not present | |
568 | + MEDIA_CANNOT_INITIALIZE // Cannot initialize media | |
569 | +} MEDIA_ERRORS; | |
570 | + | |
571 | + | |
572 | +/*******************************************************************/ | |
573 | +/* Strunctures and defines */ | |
574 | +/*******************************************************************/ | |
575 | + | |
576 | +#ifndef FALSE | |
577 | + // Summary: False value | |
578 | + // Description: This macro will indicate that a condition is false. | |
579 | + #define FALSE 0 | |
580 | +#endif | |
581 | +#ifndef TRUE | |
582 | + // Summary: True value | |
583 | + // Description: This macro will indicate that a condition is true. | |
584 | + #define TRUE !FALSE // True value | |
585 | +#endif | |
586 | + | |
587 | + | |
588 | + | |
589 | + | |
590 | +#ifndef SEEK_SET | |
591 | + // Summary: Macro for the FSfseek SEEK_SET base location. | |
592 | + // Description: Functions as an input for FSfseek that specifies that the position in the file will be changed | |
593 | + // relative to the beginning of the file. | |
594 | + #define SEEK_SET 0 | |
595 | + | |
596 | +#endif | |
597 | +#ifndef SEEK_CUR | |
598 | + | |
599 | + // Summary: Macro for the FSfseek SEEK_CUR base location. | |
600 | + // Description: Functions as an input for FSfseek that specifies that the position in the file will be changed | |
601 | + // relative to the current location of the file | |
602 | + #define SEEK_CUR 1 | |
603 | + | |
604 | +#endif | |
605 | +#ifndef SEEK_END | |
606 | + | |
607 | + // Summary: Macro for the FSfseek SEEK_END base location | |
608 | + // Description: Functions as an input for FSfseek that specifies that the position in the file will be changed | |
609 | + // relative to the end of the file. For this macro, the offset value will be subtracted from | |
610 | + // the end location of the file by default. | |
611 | + #define SEEK_END 2 | |
612 | + | |
613 | +#endif | |
614 | + | |
615 | + | |
616 | + | |
617 | + | |
618 | +// Summary: Macro for the FSfopen FS_APPEND mode | |
619 | +// Description: If this macro is specified as the mode argument in a call of FSfopen, the file being opened will | |
620 | +// be created if it doesn't exist. If it does exist, it's file information will be loaded and the | |
621 | +// current location in the file will be set to the end. The user will then be able to write to the file. | |
622 | +#define FS_APPEND "a" | |
623 | +#define APPEND "a" //deprecated | |
624 | + | |
625 | +// Summary: Macro for the FSfopen FS_WRITE mode | |
626 | +// Description: If this macro is specified as the mode argument in a call of FSfopen, the file being opened will | |
627 | +// be created if it doesn't exist. If it does exist, it will be erased and replaced by an empty file | |
628 | +// of the same name. The user will then be able to write to the file. | |
629 | +#define FS_WRITE "w" | |
630 | +#define WRITE "w" //deprecated | |
631 | + | |
632 | +// Summary: Macro for the FSfopen FS_READ mode | |
633 | +// Description: If this macro is specified as the mode argument in a call of FSfopen, the file information for the | |
634 | +// specified file will be loaded. If the file does not exist, the FSfopen function will fail. The user | |
635 | +// will then be able to read from the file. | |
636 | +#define FS_READ "r" | |
637 | +#if defined(__32MX795F512L__) | |
638 | +// #warning FSfopen must use "r" and not READ as input on this device | |
639 | +#else | |
640 | + #define READ "r" //deprecated | |
641 | +#endif | |
642 | + | |
643 | +// Summary: Macro for the FSfopen FS_APPEND+ mode | |
644 | +// Description: If this macro is specified as the mode argument in a call of FSfopen, the file being opened will | |
645 | +// be created if it doesn't exist. If it does exist, it's file information will be loaded and the | |
646 | +// current location in the file will be set to the end. The user will then be able to write to the file | |
647 | +// or read from the file. | |
648 | +#define FS_APPENDPLUS "a+" | |
649 | +#define APPENDPLUS "a+" //deprecated | |
650 | + | |
651 | +// Summary: Macro for the FSfopen FS_WRITE+ mode | |
652 | +// Description: If this macro is specified as the mode argument in a call of FSfopen, the file being opened will | |
653 | +// be created if it doesn't exist. If it does exist, it will be erased and replaced by an empty file | |
654 | +// of the same name. The user will then be able to write to the file or read from the file. | |
655 | +#define FS_WRITEPLUS "w+" | |
656 | +#define WRITEPLUS "w+" //deprecated | |
657 | + | |
658 | +// Summary: Macro for the FSfopen FS_READ+ mode | |
659 | +// Description: If this macro is specified as the mode argument in a call of FSfopen, the file information for the | |
660 | +// specified file will be loaded. If the file does not exist, the FSfopen function will fail. The user | |
661 | +// will then be able to read from the file or write to the file. | |
662 | +#define FS_READPLUS "r+" | |
663 | +#define READPLUS "r+" //deprecated | |
664 | + | |
665 | + | |
666 | + | |
667 | +#ifndef intmax_t | |
668 | + #ifdef __PIC24F__ | |
669 | + // Summary: A data type indicating the maximum integer size in an architecture | |
670 | + // Description: The intmax_t data type refers to the maximum-sized data type on any given architecture. This | |
671 | + // data type can be specified as a format specifier size specification for the FSfprintf function. | |
672 | + #define intmax_t long long | |
673 | + #elif defined __PIC24H__ | |
674 | + #define intmax_t long long | |
675 | + #elif defined __dsPIC30F__ | |
676 | + #define intmax_t long long | |
677 | + #elif defined __dsPIC33F__ | |
678 | + #define intmax_t long long | |
679 | + #endif | |
680 | +#endif | |
681 | + | |
682 | + | |
683 | + | |
684 | +// Summary: Indicates flag conditions for a file object | |
685 | +// Description: The FILEFLAGS structure is used to indicate conditions in a file. It contains three flags: 'write' indicates | |
686 | +// that the file was opened in a mode that allows writes, 'read' indicates that the file was opened in a mode | |
687 | +// that allows reads, and 'FileWriteEOF' indicates that additional data that is written to the file will increase | |
688 | +// the file size. | |
689 | +typedef struct | |
690 | +{ | |
691 | + unsigned write :1; // Indicates a file was opened in a mode that allows writes | |
692 | + unsigned read :1; // Indicates a file was opened in a mode that allows reads | |
693 | + unsigned FileWriteEOF :1; // Indicates the current position in a file is at the end of the file | |
694 | +}FILEFLAGS; | |
695 | + | |
696 | + | |
697 | + | |
698 | +// Summary: Indicates how to search for file entries in the FILEfind function | |
699 | +// Description: The values in the SEARCH_TYPE enumeration are used internally by the library to indicate how the FILEfind function | |
700 | +// how to perform a search. The 'LOOK_FOR_EMPTY_ENTRY' value indicates that FILEfind should search for an empty file entry. | |
701 | +// The 'LOOK_FOR_MATCHING_ENTRY' value indicates that FILEfind should search for an entry that matches the FSFILE object | |
702 | +// that was passed into the FILEfind function. | |
703 | +typedef enum{ | |
704 | + LOOK_FOR_EMPTY_ENTRY = 0, | |
705 | + LOOK_FOR_MATCHING_ENTRY | |
706 | +} SEARCH_TYPE; | |
707 | + | |
708 | + | |
709 | + | |
710 | +// Summary: Macro indicating the length of a 8.3 file name | |
711 | +// Description: The TOTAL_FILE_SIZE_8P3 macro indicates the maximum number of characters in an 8.3 file name. This value includes | |
712 | +// 8 characters for the name, three for the extentsion, and 1 for the radix ('.') | |
713 | +#define TOTAL_FILE_SIZE_8P3 (8+3+1) | |
714 | +#define TOTAL_FILE_SIZE TOTAL_FILE_SIZE_8P3 | |
715 | + | |
716 | +// Summary: Macro indicating the max length of a LFN file name | |
717 | +// Description: The MAX_FILE_NAME_LENGTH_LFN macro indicates the maximum number of characters in an LFN file name. | |
718 | +#define MAX_FILE_NAME_LENGTH_LFN 256 | |
719 | + | |
720 | +// Summary: A mask that indicates the limit of directory entries in a sector | |
721 | +// Description: The MASK_MAX_FILE_ENTRY_LIMIT_BITS is used to indicate to the Cache_File_Entry function that a new sector needs to | |
722 | +// be loaded. | |
723 | +#define MASK_MAX_FILE_ENTRY_LIMIT_BITS 0x0f | |
724 | + | |
725 | +// Summary: Value used for shift operations to calculate the sector offset in a directory | |
726 | +// Description: The VALUE_BASED_ON_ENTRIES_PER_CLUSTER macro is used to calculate sector offsets for directories. The position of the | |
727 | +// entry is shifted by 4 bits (divided by 16, since there are 16 entries in a sector) to calculate how many sectors a | |
728 | +// specified entry is offset from the beginning of the directory. | |
729 | +#define VALUE_BASED_ON_ENTRIES_PER_CLUSTER 4 | |
730 | + | |
731 | +// Summary: A value that will indicate that a dotdot directory entry points to the root. | |
732 | +// Description: The VALUE_DOTDOT_CLUSTER_VALUE_FOR_ROOT macro is used as an absolute address when writing information to a dotdot entry | |
733 | +// in a newly created directory. If a dotdot entry points to the root directory, it's cluster value must be set to 0, | |
734 | +// regardless of the actual cluster number of the root directory. | |
735 | +#define VALUE_DOTDOT_CLUSTER_VALUE_FOR_ROOT 0 | |
736 | + | |
737 | +// Summary: MAcro indicating the length of an 8.3 file name in a directory entry | |
738 | +// Description: The FILE_NAME_SIZE_8P3 macro indicates the number of characters that an 8.3 file name will take up when packed in | |
739 | +// a directory entry. This value includes 8 characters for the name and 3 for the extension. Note that the radix is not | |
740 | +// stored in the directory entry. | |
741 | +#define FILE_NAME_SIZE_8P3 11 | |
742 | +#define FILE_NAME_SIZE FILE_NAME_SIZE_8P3 | |
743 | + | |
744 | + | |
745 | +// Summary: Contains file information and is used to indicate which file to access. | |
746 | +// Description: The FSFILE structure is used to hold file information for an open file as it's being modified or accessed. A pointer to | |
747 | +// an open file's FSFILE structure will be passeed to any library function that will modify that file. | |
748 | +typedef struct | |
749 | +{ | |
750 | + DISK * dsk; // Pointer to a DISK structure | |
751 | + DWORD cluster; // The first cluster of the file | |
752 | + DWORD ccls; // The current cluster of the file | |
753 | + WORD sec; // The current sector in the current cluster of the file | |
754 | + WORD pos; // The position in the current sector | |
755 | + DWORD seek; // The absolute position in the file | |
756 | + DWORD size; // The size of the file | |
757 | + FILEFLAGS flags; // A structure containing file flags | |
758 | + WORD time; // The file's last update time | |
759 | + WORD date; // The file's last update date | |
760 | + char name[FILE_NAME_SIZE_8P3]; // The short name of the file | |
761 | + #ifdef SUPPORT_LFN | |
762 | + BOOL AsciiEncodingType; // Ascii file name or Non-Ascii file name indicator | |
763 | + unsigned short int *utf16LFNptr; // Pointer to long file name in UTF16 format | |
764 | + unsigned short int utf16LFNlength; // LFN length in terms of words including the NULL word at the last. | |
765 | + #endif | |
766 | + WORD entry; // The position of the file's directory entry in it's directory | |
767 | + WORD chk; // File structure checksum | |
768 | + WORD attributes; // The file attributes | |
769 | + DWORD dirclus; // The base cluster of the file's directory | |
770 | + DWORD dirccls; // The current cluster of the file's directory | |
771 | +} FSFILE; | |
772 | + | |
773 | +/* Summary: Possible results of the FSGetDiskProperties() function. | |
774 | +** Description: See the FSGetDiskProperties() function for more information. | |
775 | +*/ | |
776 | +typedef enum | |
777 | +{ | |
778 | + FS_GET_PROPERTIES_NO_ERRORS = 0, | |
779 | + FS_GET_PROPERTIES_DISK_NOT_MOUNTED, | |
780 | + FS_GET_PROPERTIES_CLUSTER_FAILURE, | |
781 | + FS_GET_PROPERTIES_STILL_WORKING = 0xFF | |
782 | +} FS_DISK_ERRORS; | |
783 | + | |
784 | + | |
785 | +/* Summary: Contains the disk search information, intermediate values, and results | |
786 | +** Description: This structure is used in conjunction with the FSGetDiskProperties() | |
787 | +** function. See that function for more information about the usage. | |
788 | +*/ | |
789 | +typedef struct | |
790 | +{ | |
791 | + DISK * disk; /* pointer to the disk we are searching */ | |
792 | + BOOL new_request; /* is this a new request or a continued request */ | |
793 | + FS_DISK_ERRORS properties_status; /* status of the last call of the function */ | |
794 | + | |
795 | + struct | |
796 | + { | |
797 | + BYTE disk_format; /* disk format: FAT12, FAT16, FAT32 */ | |
798 | + WORD sector_size; /* sector size of the drive */ | |
799 | + BYTE sectors_per_cluster; /* number of sectors per cluster */ | |
800 | + DWORD total_clusters; /* the number of total clusters on the drive */ | |
801 | + DWORD free_clusters; /* the number of free (unused) clusters on drive */ | |
802 | + } results; /* the results of the current search */ | |
803 | + | |
804 | + struct | |
805 | + { | |
806 | + DWORD c; | |
807 | + DWORD curcls; | |
808 | + DWORD EndClusterLimit; | |
809 | + DWORD ClusterFailValue; | |
810 | + } private; /* intermediate values used to continue searches. This | |
811 | + member should be used only by the FSGetDiskProperties() | |
812 | + function */ | |
813 | + | |
814 | +} FS_DISK_PROPERTIES; | |
815 | + | |
816 | +// Summary: A structure used for searching for files on a device. | |
817 | +// Description: The SearchRec structure is used when searching for file on a device. It contains parameters that will be loaded with | |
818 | +// file information when a file is found. It also contains the parameters that the user searched for, allowing further | |
819 | +// searches to be perfomed in the same directory for additional files that meet the specified criteria. | |
820 | +typedef struct | |
821 | +{ | |
822 | + char filename[FILE_NAME_SIZE_8P3 + 2]; // The name of the file that has been found | |
823 | + unsigned char attributes; // The attributes of the file that has been found | |
824 | + unsigned long filesize; // The size of the file that has been found | |
825 | + unsigned long timestamp; // The last modified time of the file that has been found (create time for directories) | |
826 | + #ifdef SUPPORT_LFN | |
827 | + BOOL AsciiEncodingType; // Ascii file name or Non-Ascii file name indicator | |
828 | + unsigned short int *utf16LFNfound; // Pointer to long file name found in UTF16 format | |
829 | + unsigned short int utf16LFNfoundLength; // LFN Found length in terms of words including the NULL word at the last. | |
830 | + #endif | |
831 | + unsigned int entry; // The directory entry of the last file found that matches the specified attributes. (Internal use only) | |
832 | + char searchname[FILE_NAME_SIZE_8P3 + 2]; // The 8.3 format name specified when the user began the search. (Internal use only) | |
833 | + unsigned char searchattr; // The attributes specified when the user began the search. (Internal use only) | |
834 | + unsigned long cwdclus; // The directory that this search was performed in. (Internal use only) | |
835 | + unsigned char initialized; // Check to determine if the structure was initialized by FindFirst (Internal use only) | |
836 | +} SearchRec; | |
837 | + | |
838 | + | |
839 | +/*************************************************************************** | |
840 | +* Prototypes * | |
841 | +***************************************************************************/ | |
842 | + | |
843 | + | |
844 | + | |
845 | + | |
846 | +/************************************************************************* | |
847 | + Function: | |
848 | + int FSInit(void) | |
849 | + Summary: | |
850 | + Function to initialize the device. | |
851 | + Conditions: | |
852 | + The physical device should be connected to the microcontroller. | |
853 | + Input: | |
854 | + None | |
855 | + Return Values: | |
856 | + TRUE - Initialization successful | |
857 | + FALSE - Initialization unsuccessful | |
858 | + Side Effects: | |
859 | + The FSerrno variable will be changed. | |
860 | + Description: | |
861 | + Initializes the static or dynamic memory slots for holding file | |
862 | + structures. Initializes the device with the DISKmount function. Loads | |
863 | + MBR and boot sector information. Initializes the current working | |
864 | + directory to the root directory for the device if directory support | |
865 | + is enabled. | |
866 | + Remarks: | |
867 | + None | |
868 | + *************************************************************************/ | |
869 | + | |
870 | +int FSInit(void); | |
871 | + | |
872 | + | |
873 | +/********************************************************************* | |
874 | + Function: | |
875 | + FSFILE * FSfopen (const char * fileName, const char *mode) | |
876 | + Summary: | |
877 | + Open a Ascii file | |
878 | + Conditions: | |
879 | + For read modes, file exists; FSInit performed | |
880 | + Input: | |
881 | + fileName - The name of the file to open | |
882 | + mode - | |
883 | + - WRITE - Create a new file or replace an existing file | |
884 | + - READ - Read data from an existing file | |
885 | + - APPEND - Append data to an existing file | |
886 | + - WRITEPLUS - Create a new file or replace an existing file (reads also enabled) | |
887 | + - READPLUS - Read data from an existing file (writes also enabled) | |
888 | + - APPENDPLUS - Append data to an existing file (reads also enabled) | |
889 | + Return Values: | |
890 | + FSFILE * - The pointer to the file object | |
891 | + NULL - The file could not be opened | |
892 | + Side Effects: | |
893 | + The FSerrno variable will be changed. | |
894 | + Description: | |
895 | + This function will open a file or directory. First, RAM in the | |
896 | + dynamic heap or static array will be allocated to a new FSFILE object. | |
897 | + Then, the specified file name will be formatted to ensure that it's | |
898 | + in 8.3 format or LFN format. Next, the FILEfind function will be used | |
899 | + to search for the specified file name. If the name is found, one of three | |
900 | + things will happen: if the file was opened in read mode, its file | |
901 | + info will be loaded using the FILEopen function; if it was opened in | |
902 | + write mode, it will be erased, and a new file will be constructed in | |
903 | + its place; if it was opened in append mode, its file info will be | |
904 | + loaded with FILEopen and the current location will be moved to the | |
905 | + end of the file using the FSfseek function. If the file was not | |
906 | + found by FILEfind, a new file will be created if the mode was specified as | |
907 | + a write or append mode. In these cases, a pointer to the heap or | |
908 | + static FSFILE object array will be returned. If the file was not | |
909 | + found and the mode was specified as a read mode, the memory | |
910 | + allocated to the file will be freed and the NULL pointer value | |
911 | + will be returned. | |
912 | + Remarks: | |
913 | + None. | |
914 | + *********************************************************************/ | |
915 | + | |
916 | +FSFILE * FSfopen(const char * fileName, const char *mode); | |
917 | + | |
918 | +#ifdef SUPPORT_LFN | |
919 | +/********************************************************************* | |
920 | + Function: | |
921 | + FSFILE * wFSfopen (const unsigned short int * fileName, const char *mode) | |
922 | + Summary: | |
923 | + Open a UTF16 file. | |
924 | + Conditions: | |
925 | + For read modes, file exists; FSInit performed | |
926 | + Input: | |
927 | + fileName - The name of the file to open | |
928 | + mode - | |
929 | + - WRITE - Create a new file or replace an existing file | |
930 | + - READ - Read data from an existing file | |
931 | + - APPEND - Append data to an existing file | |
932 | + - WRITEPLUS - Create a new file or replace an existing file (reads also enabled) | |
933 | + - READPLUS - Read data from an existing file (writes also enabled) | |
934 | + - APPENDPLUS - Append data to an existing file (reads also enabled) | |
935 | + Return Values: | |
936 | + FSFILE * - The pointer to the file object | |
937 | + NULL - The file could not be opened | |
938 | + Side Effects: | |
939 | + The FSerrno variable will be changed. | |
940 | + Description: | |
941 | + This function will open a file or directory. First, RAM in the | |
942 | + dynamic heap or static array will be allocated to a new FSFILE object. | |
943 | + Then, the specified file name will be formatted to ensure that it's | |
944 | + in 8.3 format or LFN format. Next, the FILEfind function will be used | |
945 | + to search for the specified file name. If the name is found, one of three | |
946 | + things will happen: if the file was opened in read mode, its file | |
947 | + info will be loaded using the FILEopen function; if it was opened in | |
948 | + write mode, it will be erased, and a new file will be constructed in | |
949 | + its place; if it was opened in append mode, its file info will be | |
950 | + loaded with FILEopen and the current location will be moved to the | |
951 | + end of the file using the FSfseek function. If the file was not | |
952 | + found by FILEfind, a new file will be created if the mode was specified as | |
953 | + a write or append mode. In these cases, a pointer to the heap or | |
954 | + static FSFILE object array will be returned. If the file was not | |
955 | + found and the mode was specified as a read mode, the memory | |
956 | + allocated to the file will be freed and the NULL pointer value | |
957 | + will be returned. | |
958 | + Remarks: | |
959 | + None. | |
960 | + *********************************************************************/ | |
961 | + | |
962 | +FSFILE * wFSfopen(const unsigned short int * fileName, const char *mode); | |
963 | +#endif | |
964 | + | |
965 | +#ifdef ALLOW_PGMFUNCTIONS | |
966 | + | |
967 | +/****************************************************************************** | |
968 | + Function: | |
969 | + FSFILE * FSfopenpgm(const rom char * fileName, const rom char *mode) | |
970 | + Summary: | |
971 | + Open a Ascii file named with a ROM string on PIC18 | |
972 | + Conditions: | |
973 | + For read modes, file exists; FSInit performed | |
974 | + Input: | |
975 | + fileName - The name of the file to be opened (ROM) | |
976 | + mode - The mode the file will be opened in (ROM) | |
977 | + Return Values: | |
978 | + FSFILE * - A pointer to the file object | |
979 | + NULL - File could not be opened | |
980 | + Side Effects: | |
981 | + The FSerrno variable will be changed. | |
982 | + Description: | |
983 | + The FSfopenpgm function will copy a PIC18 ROM fileName and mode argument | |
984 | + into RAM arrays, and then pass those arrays to the FSfopen function. | |
985 | + Remarks: | |
986 | + This function is for use with PIC18 when passing arguments in ROM. | |
987 | + ******************************************************************************/ | |
988 | + | |
989 | + FSFILE * FSfopenpgm(const rom char * fileName, const rom char *mode); | |
990 | + | |
991 | + | |
992 | +/************************************************************************************** | |
993 | + Function: | |
994 | + int FindFirstpgm (const char * fileName, unsigned int attr, SearchRec * rec) | |
995 | + Summary: | |
996 | + Find a file named with a ROM string on PIC18 | |
997 | + Conditions: | |
998 | + None | |
999 | + Input: | |
1000 | + fileName - The name of the file to be found (ROM) | |
1001 | + attr - The attributes of the file to be found | |
1002 | + rec - Pointer to a search record to store the file info in | |
1003 | + Return Values: | |
1004 | + 0 - File was found | |
1005 | + -1 - No file matching the given parameters was found | |
1006 | + Side Effects: | |
1007 | + Search criteria from previous FindFirstpgm call on passed SearchRec object | |
1008 | + will be lost.The FSerrno variable will be changed. | |
1009 | + Description: | |
1010 | + The FindFirstpgm function will copy a PIC18 ROM fileName argument | |
1011 | + into a RAM array, and then pass that array to the FindFirst function. | |
1012 | + Remarks: | |
1013 | + Call FindFirstpgm or FindFirst before calling FindNext. | |
1014 | + This function is for use with PIC18 when passing arguments in ROM. | |
1015 | + **************************************************************************************/ | |
1016 | + | |
1017 | + int FindFirstpgm (const rom char * fileName, unsigned int attr, SearchRec * rec); | |
1018 | + | |
1019 | + | |
1020 | +/************************************************************************** | |
1021 | + Function: | |
1022 | + int FSchdirpgm (const rom char * path) | |
1023 | + Summary: | |
1024 | + Changed the CWD with a path in ROM on PIC18 | |
1025 | + Conditions: | |
1026 | + None | |
1027 | + Input: | |
1028 | + path - The path of the directory to change to (ROM) | |
1029 | + Return Values: | |
1030 | + 0 - The current working directory was changed successfully | |
1031 | + EOF - The current working directory could not be changed | |
1032 | + Side Effects: | |
1033 | + The current working directory may be changed. The FSerrno variable will | |
1034 | + be changed. | |
1035 | + Description: | |
1036 | + The FSchdirpgm function passes a PIC18 ROM path pointer to the | |
1037 | + chdirhelper function. | |
1038 | + Remarks: | |
1039 | + This function is for use with PIC18 when passing arguments in ROM | |
1040 | + **************************************************************************/ | |
1041 | + | |
1042 | + int FSchdirpgm (const rom char * path); | |
1043 | + | |
1044 | + #ifdef ALLOW_WRITES | |
1045 | + | |
1046 | + | |
1047 | +/************************************************************* | |
1048 | + Function: | |
1049 | + int FSremovepgm (const rom char * fileName) | |
1050 | + Summary: | |
1051 | + Delete a file named with a ROM string on PIC18 | |
1052 | + Conditions: | |
1053 | + File not opened; file exists | |
1054 | + Input: | |
1055 | + fileName - The name of the file to be deleted (ROM) | |
1056 | + Return Values: | |
1057 | + 0 - File was removed successfully | |
1058 | + -1 - File could not be removed | |
1059 | + Side Effects: | |
1060 | + The FSerrno variable will be changed. | |
1061 | + Description: | |
1062 | + The FSremovepgm function will copy a PIC18 ROM fileName argument | |
1063 | + into a RAM array, and then pass that array to the FSremove function. | |
1064 | + Remarks: | |
1065 | + This function is for use with PIC18 when passing arguments in ROM. | |
1066 | + *************************************************************/ | |
1067 | + | |
1068 | + int FSremovepgm (const rom char * fileName); | |
1069 | + | |
1070 | + | |
1071 | +/************************************************************************** | |
1072 | + Function: | |
1073 | + int FSmkdirpgm (const rom char * path) | |
1074 | + Summary: | |
1075 | + Create a directory with a path in ROM on PIC18 | |
1076 | + Conditions: | |
1077 | + None | |
1078 | + Input: | |
1079 | + path - The path of directories to create (ROM) | |
1080 | + Return Values: | |
1081 | + 0 - The specified directory was created successfully | |
1082 | + EOF - The specified directory could not be created | |
1083 | + Side Effects: | |
1084 | + Will create all non-existent directories in the path. The FSerrno | |
1085 | + variable will be changed. | |
1086 | + Description: | |
1087 | + The FSmkdirpgm function passes a PIC18 ROM path pointer to the | |
1088 | + mkdirhelper function. | |
1089 | + Remarks: | |
1090 | + This function is for use with PIC18 when passing arugments in ROM | |
1091 | + **************************************************************************/ | |
1092 | + | |
1093 | + int FSmkdirpgm (const rom char * path); | |
1094 | + | |
1095 | + | |
1096 | +/************************************************************************** | |
1097 | + Function: | |
1098 | + int FSrmdirpgm (const rom char * path) | |
1099 | + Summary: | |
1100 | + Delete a directory with a path in ROM on PIC18 | |
1101 | + Conditions: | |
1102 | + None. | |
1103 | + Input: | |
1104 | + path - The path of the directory to remove (ROM) | |
1105 | + rmsubdirs - | |
1106 | + - TRUE - All sub-dirs and files in the target dir will be removed | |
1107 | + - FALSE - FSrmdir will not remove non-empty directories | |
1108 | + Return Values: | |
1109 | + 0 - The specified directory was deleted successfully | |
1110 | + EOF - The specified directory could not be deleted | |
1111 | + Side Effects: | |
1112 | + The FSerrno variable will be changed. | |
1113 | + Description: | |
1114 | + The FSrmdirpgm function passes a PIC18 ROM path pointer to the | |
1115 | + rmdirhelper function. | |
1116 | + Remarks: | |
1117 | + This function is for use with PIC18 when passing arguments in ROM. | |
1118 | + **************************************************************************/ | |
1119 | + | |
1120 | + int FSrmdirpgm (const rom char * path, unsigned char rmsubdirs); | |
1121 | + | |
1122 | + | |
1123 | +/***************************************************************** | |
1124 | + Function: | |
1125 | + int FSrenamepgm(const rom char * fileName, FSFILE * fo) | |
1126 | + Summary: | |
1127 | + Rename a file named with a ROM string on PIC18 | |
1128 | + Conditions: | |
1129 | + File opened. | |
1130 | + Input: | |
1131 | + fileName - The new name of the file (in ROM) | |
1132 | + fo - The file to rename | |
1133 | + Return Values: | |
1134 | + 0 - File renamed successfully | |
1135 | + -1 - File could not be renamed | |
1136 | + Side Effects: | |
1137 | + The FSerrno variable will be changed. | |
1138 | + Description: | |
1139 | + The Fsrenamepgm function will copy the rom fileName specified | |
1140 | + by the user into a RAM array and pass that array into the | |
1141 | + FSrename function. | |
1142 | + Remarks: | |
1143 | + This function is for use with PIC18 when passing arguments in ROM. | |
1144 | + *****************************************************************/ | |
1145 | + | |
1146 | + int FSrenamepgm (const rom char * fileName, FSFILE * fo); | |
1147 | + #endif | |
1148 | +#endif | |
1149 | + | |
1150 | + | |
1151 | +/************************************************************ | |
1152 | + Function: | |
1153 | + int FSfclose(FSFILE *fo) | |
1154 | + Summary: | |
1155 | + Update file information and free FSFILE objects | |
1156 | + Conditions: | |
1157 | + File opened | |
1158 | + Input: | |
1159 | + fo - Pointer to the file to close | |
1160 | + Return Values: | |
1161 | + 0 - File closed successfully | |
1162 | + EOF - Error closing the file | |
1163 | + Side Effects: | |
1164 | + The FSerrno variable will be changed. | |
1165 | + Description: | |
1166 | + This function will update the directory entry for the | |
1167 | + file pointed to by 'fo' with the information contained | |
1168 | + in 'fo,' including the new file size and attributes. | |
1169 | + Timestamp information will also be loaded based on the | |
1170 | + method selected by the user and written to the entry | |
1171 | + as the last modified time and date. The file entry will | |
1172 | + then be written to the device. Finally, the memory | |
1173 | + used for the specified file object will be freed from | |
1174 | + the dynamic heap or the array of FSFILE objects. | |
1175 | + Remarks: | |
1176 | + A function to flush data to the device without closing the | |
1177 | + file can be created by removing the portion of this | |
1178 | + function that frees the memory and the line that clears | |
1179 | + the write flag. | |
1180 | + ************************************************************/ | |
1181 | + | |
1182 | +int FSfclose(FSFILE *fo); | |
1183 | + | |
1184 | + | |
1185 | +/********************************************************* | |
1186 | + Function: | |
1187 | + void FSrewind (FSFILE * fo) | |
1188 | + Summary: | |
1189 | + Set the current position in a file to the beginning | |
1190 | + Conditions: | |
1191 | + File opened. | |
1192 | + Input: | |
1193 | + fo - Pointer to file structure | |
1194 | + Return Values: | |
1195 | + None | |
1196 | + Side Effects: | |
1197 | + None. | |
1198 | + Description: | |
1199 | + The FSrewind funciton will reset the position of the | |
1200 | + specified file to the beginning of the file. This | |
1201 | + functionality is faster than using FSfseek to reset | |
1202 | + the position in the file. | |
1203 | + Remarks: | |
1204 | + None. | |
1205 | + *********************************************************/ | |
1206 | + | |
1207 | +void FSrewind (FSFILE *fo); | |
1208 | + | |
1209 | + | |
1210 | +/************************************************************************** | |
1211 | + Function: | |
1212 | + size_t FSfread(void *ptr, size_t size, size_t n, FSFILE *stream) | |
1213 | + Summary: | |
1214 | + Read data from a file | |
1215 | + Conditions: | |
1216 | + File is opened in a read mode | |
1217 | + Input: | |
1218 | + ptr - Destination buffer for read bytes | |
1219 | + size - Size of units in bytes | |
1220 | + n - Number of units to be read | |
1221 | + stream - File to be read from | |
1222 | + Return: | |
1223 | + size_t - number of units read | |
1224 | + Side Effects: | |
1225 | + The FSerrno variable will be changed. | |
1226 | + Description: | |
1227 | + The FSfread function will read data from the specified file. First, | |
1228 | + the appropriate sector of the file is loaded. Then, data is read into | |
1229 | + the specified buffer until the specified number of bytes have been read. | |
1230 | + When a cluster boundary is reached, a new cluster will be loaded. The | |
1231 | + parameters 'size' and 'n' indicate how much data to read. 'Size' | |
1232 | + refers to the size of one object to read (in bytes), and 'n' will refer | |
1233 | + to the number of these objects to read. The value returned will be equal | |
1234 | + to 'n' unless an error occured or the user tried to read beyond the end | |
1235 | + of the file. | |
1236 | + Remarks: | |
1237 | + None. | |
1238 | + **************************************************************************/ | |
1239 | + | |
1240 | +size_t FSfread(void *ptr, size_t size, size_t n, FSFILE *stream); | |
1241 | + | |
1242 | + | |
1243 | +/********************************************************************** | |
1244 | + Function: | |
1245 | + int FSfseek(FSFILE *stream, long offset, int whence) | |
1246 | + Summary: | |
1247 | + Change the current position in a file | |
1248 | + Conditions: | |
1249 | + File opened | |
1250 | + Input: | |
1251 | + stream - Pointer to file structure | |
1252 | + offset - Offset from base location | |
1253 | + whence - | |
1254 | + - SEEK_SET - Seek from start of file | |
1255 | + - SEEK_CUR - Seek from current location | |
1256 | + - SEEK_END - Seek from end of file (subtract offset) | |
1257 | + Return Values: | |
1258 | + 0 - Operation successful | |
1259 | + -1 - Operation unsuccesful | |
1260 | + Side Effects: | |
1261 | + The FSerrno variable will be changed. | |
1262 | + Description: | |
1263 | + The FSfseek function will change the current position in the file to | |
1264 | + one specified by the user. First, an absolute offset is calculated | |
1265 | + using the offset and base location passed in by the user. Then, the | |
1266 | + position variables are updated, and the sector number that corresponds | |
1267 | + to the new location. That sector is then loaded. If the offset | |
1268 | + falls exactly on a cluster boundary, a new cluster will be allocated | |
1269 | + to the file and the position will be set to the first byte of that | |
1270 | + cluster. | |
1271 | + Remarks: | |
1272 | + None | |
1273 | + **********************************************************************/ | |
1274 | + | |
1275 | +int FSfseek(FSFILE *stream, long offset, int whence); | |
1276 | + | |
1277 | + | |
1278 | +/******************************************************************* | |
1279 | + Function: | |
1280 | + long FSftell (FSFILE * fo) | |
1281 | + Summary: | |
1282 | + Determine the current location in a file | |
1283 | + Conditions: | |
1284 | + File opened | |
1285 | + Input: | |
1286 | + fo - Pointer to file structure | |
1287 | + Return: Current location in the file | |
1288 | + Side Effects: | |
1289 | + The FSerrno variable will be changed | |
1290 | + Description: | |
1291 | + The FSftell function will return the current position in the | |
1292 | + file pointed to by 'fo' by returning the 'seek' variable in the | |
1293 | + FSFILE object, which is used to keep track of the absolute | |
1294 | + location of the current position in the file. | |
1295 | + Remarks: | |
1296 | + None | |
1297 | + *******************************************************************/ | |
1298 | + | |
1299 | +long FSftell(FSFILE *fo); | |
1300 | + | |
1301 | + | |
1302 | +/**************************************************** | |
1303 | + Function: | |
1304 | + int FSfeof( FSFILE * stream ) | |
1305 | + Summary: | |
1306 | + Indicate whether the current file position is at the end | |
1307 | + Conditions: | |
1308 | + File is open in a read mode | |
1309 | + Input: | |
1310 | + stream - Pointer to the target file | |
1311 | + Return Values: | |
1312 | + Non-Zero - EOF reached | |
1313 | + 0 - Not at end of File | |
1314 | + Side Effects: | |
1315 | + The FSerrno variable will be changed. | |
1316 | + Description: | |
1317 | + The FSfeof function will indicate that the end-of- | |
1318 | + file has been reached for the specified file by | |
1319 | + comparing the absolute location in the file to the | |
1320 | + size of the file. | |
1321 | + Remarks: | |
1322 | + None. | |
1323 | + ****************************************************/ | |
1324 | + | |
1325 | +int FSfeof( FSFILE * stream ); | |
1326 | + | |
1327 | + | |
1328 | +#ifdef ALLOW_FORMATS | |
1329 | +/******************************************************************* | |
1330 | + Function: | |
1331 | + int FSformat (char mode, long int serialNumber, char * volumeID) | |
1332 | + Summary: | |
1333 | + Formats a device | |
1334 | + Conditions: | |
1335 | + The device must possess a valid master boot record. | |
1336 | + Input: | |
1337 | + mode - - 0 - Just erase the FAT and root | |
1338 | + - 1 - Create a new boot sector | |
1339 | + serialNumber - Serial number to write to the card | |
1340 | + volumeID - Name of the card | |
1341 | + Return Values: | |
1342 | + 0 - Format was successful | |
1343 | + EOF - Format was unsuccessful | |
1344 | + Side Effects: | |
1345 | + The FSerrno variable will be changed. | |
1346 | + Description: | |
1347 | + The FSformat function can be used to create a new boot sector | |
1348 | + on a device, based on the information in the master boot record. | |
1349 | + This function will first initialize the I/O pins and the device, | |
1350 | + and then attempts to read the master boot record. If the MBR | |
1351 | + cannot be loaded successfully, the function will fail. Next, if | |
1352 | + the 'mode' argument is specified as '0' the existing boot sector | |
1353 | + information will be loaded. If the 'mode' argument is '1' an | |
1354 | + entirely new boot sector will be constructed using the disk | |
1355 | + values from the master boot record. Once the boot sector has | |
1356 | + been successfully loaded/created, the locations of the FAT and | |
1357 | + root will be loaded from it, and they will be completely | |
1358 | + erased. If the user has specified a volumeID parameter, a | |
1359 | + VOLUME attribute entry will be created in the root directory | |
1360 | + to name the device. | |
1361 | + | |
1362 | + FAT12, FAT16 and FAT32 formatting are supported. | |
1363 | + | |
1364 | + Based on the number of sectors, the format function automatically | |
1365 | + compute the smallest possible value for the cluster size in order to | |
1366 | + accommodate the physical size of the media. In this case, if a media | |
1367 | + with a big capacity is formatted, the format function may take a very | |
1368 | + long time to write all the FAT tables. | |
1369 | + | |
1370 | + Therefore, the FORMAT_SECTORS_PER_CLUSTER macro may be used to | |
1371 | + specify the exact cluster size (in multiples of sector size). This | |
1372 | + macro can be defined in FSconfig.h | |
1373 | + | |
1374 | + Remarks: | |
1375 | + Only devices with a sector size of 512 bytes are supported by the | |
1376 | + format function | |
1377 | + *******************************************************************/ | |
1378 | + | |
1379 | +int FSformat (char mode, long int serialNumber, char * volumeID); | |
1380 | +#endif | |
1381 | + | |
1382 | + | |
1383 | +#ifdef ALLOW_WRITES | |
1384 | +/*************************************************************************** | |
1385 | + Function: | |
1386 | + int FSattrib (FSFILE * file, unsigned char attributes) | |
1387 | + Summary: | |
1388 | + Change the attributes of a file | |
1389 | + Conditions: | |
1390 | + File opened | |
1391 | + Input: | |
1392 | + file - Pointer to file structure | |
1393 | + attributes - The attributes to set for the file | |
1394 | + - Attribute - Value - Indications | |
1395 | + - ATTR_READ_ONLY - 0x01 - The read-only attribute | |
1396 | + - ATTR_HIDDEN - 0x02 - The hidden attribute | |
1397 | + - ATTR_SYSTEM - 0x04 - The system attribute | |
1398 | + - ATTR_ARCHIVE - 0x20 - The archive attribute | |
1399 | + Return Values: | |
1400 | + 0 - Attribute change was successful | |
1401 | + -1 - Attribute change was unsuccessful | |
1402 | + Side Effects: | |
1403 | + The FSerrno variable will be changed. | |
1404 | + Description: | |
1405 | + The FSattrib funciton will set the attributes of the specified file | |
1406 | + to the attributes passed in by the user. This function will load the | |
1407 | + file entry, replace the attributes with the ones specified, and write | |
1408 | + the attributes back. If the specified file is a directory, the | |
1409 | + directory attribute will be preserved. | |
1410 | + Remarks: | |
1411 | + None | |
1412 | + ***************************************************************************/ | |
1413 | + | |
1414 | +int FSattrib (FSFILE * file, unsigned char attributes); | |
1415 | + | |
1416 | + | |
1417 | +/*************************************************************** | |
1418 | + Function: | |
1419 | + int FSrename (const rom char * fileName, FSFILE * fo) | |
1420 | + Summary: | |
1421 | + Change the Ascii name of a file or directory | |
1422 | + Conditions: | |
1423 | + File opened. | |
1424 | + Input: | |
1425 | + fileName - The new name of the file | |
1426 | + fo - The file to rename | |
1427 | + Return Values: | |
1428 | + 0 - File was renamed successfully | |
1429 | + EOF - File was not renamed | |
1430 | + Side Effects: | |
1431 | + The FSerrno variable will be changed. | |
1432 | + Description: | |
1433 | + The FSrename function will rename a file. First, it will | |
1434 | + search through the current working directory to ensure the | |
1435 | + specified new filename is not already in use. If it isn't, | |
1436 | + the new filename will be written to the file entry of the | |
1437 | + file pointed to by 'fo.' | |
1438 | + Remarks: | |
1439 | + None | |
1440 | + ***************************************************************/ | |
1441 | + | |
1442 | +int FSrename (const char * fileName, FSFILE * fo); | |
1443 | + | |
1444 | +#ifdef SUPPORT_LFN | |
1445 | +/*************************************************************** | |
1446 | + Function: | |
1447 | + int wFSrename (const rom unsigned short int * fileName, FSFILE * fo) | |
1448 | + Summary: | |
1449 | + Change the name of a file or directory to the UTF16 input fileName | |
1450 | + Conditions: | |
1451 | + File opened. | |
1452 | + Input: | |
1453 | + fileName - The new name of the file | |
1454 | + fo - The file to rename | |
1455 | + Return Values: | |
1456 | + 0 - File was renamed successfully | |
1457 | + EOF - File was not renamed | |
1458 | + Side Effects: | |
1459 | + The FSerrno variable will be changed. | |
1460 | + Description: | |
1461 | + The wFSrename function will rename a file. First, it will | |
1462 | + search through the current working directory to ensure the | |
1463 | + specified new UTF16 filename is not already in use. If it isn't, | |
1464 | + the new filename will be written to the file entry of the | |
1465 | + file pointed to by 'fo.' | |
1466 | + Remarks: | |
1467 | + None | |
1468 | + ***************************************************************/ | |
1469 | + | |
1470 | +int wFSrename (const unsigned short int * fileName, FSFILE * fo); | |
1471 | +#endif | |
1472 | + | |
1473 | +/********************************************************************* | |
1474 | + Function: | |
1475 | + int FSremove (const char * fileName) | |
1476 | + Summary: | |
1477 | + Delete a Ascii file | |
1478 | + Conditions: | |
1479 | + File not opened, file exists | |
1480 | + Input: | |
1481 | + fileName - Name of the file to erase | |
1482 | + Return Values: | |
1483 | + 0 - File removed | |
1484 | + EOF - File was not removed | |
1485 | + Side Effects: | |
1486 | + The FSerrno variable will be changed. | |
1487 | + Description: | |
1488 | + The FSremove function will attempt to find the specified file with | |
1489 | + the FILEfind function. If the file is found, it will be erased | |
1490 | + using the FILEerase function.The user can also provide ascii alias name | |
1491 | + of the ascii long file name as the input to this function to get it erased | |
1492 | + from the memory. | |
1493 | + Remarks: | |
1494 | + None | |
1495 | + **********************************************************************/ | |
1496 | + | |
1497 | +int FSremove (const char * fileName); | |
1498 | + | |
1499 | +#ifdef SUPPORT_LFN | |
1500 | +/********************************************************************* | |
1501 | + Function: | |
1502 | + int wFSremove (const unsigned short int * fileName) | |
1503 | + Summary: | |
1504 | + Delete a UTF16 file | |
1505 | + Conditions: | |
1506 | + File not opened, file exists | |
1507 | + Input: | |
1508 | + fileName - Name of the file to erase | |
1509 | + Return Values: | |
1510 | + 0 - File removed | |
1511 | + EOF - File was not removed | |
1512 | + Side Effects: | |
1513 | + The FSerrno variable will be changed. | |
1514 | + Description: | |
1515 | + The wFSremove function will attempt to find the specified UTF16 file | |
1516 | + name with the FILEfind function. If the file is found, it will be erased | |
1517 | + using the FILEerase function. | |
1518 | + Remarks: | |
1519 | + None | |
1520 | + **********************************************************************/ | |
1521 | + | |
1522 | +int wFSremove (const unsigned short int * fileName); | |
1523 | +#endif | |
1524 | + | |
1525 | +/********************************************************************************* | |
1526 | + Function: | |
1527 | + size_t FSfwrite(const void *ptr, size_t size, size_t n, FSFILE *stream) | |
1528 | + Summary: | |
1529 | + Write data to a file | |
1530 | + Conditions: | |
1531 | + File opened in WRITE, APPEND, WRITE+, APPEND+, READ+ mode | |
1532 | + Input: | |
1533 | + ptr - Pointer to source buffer | |
1534 | + size - Size of units in bytes | |
1535 | + n - Number of units to transfer | |
1536 | + stream - Pointer to file structure | |
1537 | + Return: | |
1538 | + size_t - number of units written | |
1539 | + Side Effects: | |
1540 | + The FSerrno variable will be changed. | |
1541 | + Description: | |
1542 | + The FSfwrite function will write data to a file. First, the sector that | |
1543 | + corresponds to the current position in the file will be loaded (if it hasn't | |
1544 | + already been cached in the global data buffer). Data will then be written to | |
1545 | + the device from the specified buffer until the specified amount has been written. | |
1546 | + If the end of a cluster is reached, the next cluster will be loaded, unless | |
1547 | + the end-of-file flag for the specified file has been set. If it has, a new | |
1548 | + cluster will be allocated to the file. Finally, the new position and filesize | |
1549 | + will be stored in the FSFILE object. The parameters 'size' and 'n' indicate how | |
1550 | + much data to write. 'Size' refers to the size of one object to write (in bytes), | |
1551 | + and 'n' will refer to the number of these objects to write. The value returned | |
1552 | + will be equal to 'n' unless an error occured. | |
1553 | + Remarks: | |
1554 | + None. | |
1555 | + *********************************************************************************/ | |
1556 | + | |
1557 | +size_t FSfwrite(const void *ptr, size_t size, size_t n, FSFILE *stream); | |
1558 | + | |
1559 | +#endif | |
1560 | + | |
1561 | +#ifdef ALLOW_DIRS | |
1562 | + | |
1563 | + | |
1564 | +/************************************************************************** | |
1565 | + Function: | |
1566 | + int FSchdir (char * path) | |
1567 | + Summary: | |
1568 | + Change the current working directory as per the path specified in Ascii format | |
1569 | + Conditions: | |
1570 | + None | |
1571 | + Input: | |
1572 | + path - The path of the directory to change to. | |
1573 | + Return Values: | |
1574 | + 0 - The current working directory was changed successfully | |
1575 | + EOF - The current working directory could not be changed | |
1576 | + Side Effects: | |
1577 | + The current working directory may be changed. The FSerrno variable will | |
1578 | + be changed. | |
1579 | + Description: | |
1580 | + The FSchdir function passes a RAM pointer to the path to the | |
1581 | + chdirhelper function. | |
1582 | + Remarks: | |
1583 | + None | |
1584 | + **************************************************************************/ | |
1585 | + | |
1586 | +int FSchdir (char * path); | |
1587 | + | |
1588 | +#ifdef SUPPORT_LFN | |
1589 | +/************************************************************************** | |
1590 | + Function: | |
1591 | + int wFSchdir (unsigned short int * path) | |
1592 | + Summary: | |
1593 | + Change the current working directory as per the path specified in UTF16 format | |
1594 | + Conditions: | |
1595 | + None | |
1596 | + Input: | |
1597 | + path - The path of the directory to change to. | |
1598 | + Return Values: | |
1599 | + 0 - The current working directory was changed successfully | |
1600 | + EOF - The current working directory could not be changed | |
1601 | + Side Effects: | |
1602 | + The current working directory may be changed. The FSerrno variable will | |
1603 | + be changed. | |
1604 | + Description: | |
1605 | + The FSchdir function passes a RAM pointer to the path to the | |
1606 | + chdirhelper function. | |
1607 | + Remarks: | |
1608 | + None | |
1609 | + **************************************************************************/ | |
1610 | + | |
1611 | +int wFSchdir (unsigned short int * path); | |
1612 | +#endif | |
1613 | + | |
1614 | +/************************************************************** | |
1615 | + Function: | |
1616 | + char * FSgetcwd (char * path, int numchars) | |
1617 | + Summary: | |
1618 | + Get the current working directory path in Ascii format | |
1619 | + Conditions: | |
1620 | + None | |
1621 | + Input: | |
1622 | + path - Pointer to the array to return the cwd name in | |
1623 | + numchars - Number of chars in the path | |
1624 | + Return Values: | |
1625 | + char * - The cwd name string pointer (path or defaultArray) | |
1626 | + NULL - The current working directory name could not be loaded. | |
1627 | + Side Effects: | |
1628 | + The FSerrno variable will be changed | |
1629 | + Description: | |
1630 | + The FSgetcwd function will get the name of the current | |
1631 | + working directory and return it to the user. The name | |
1632 | + will be copied into the buffer pointed to by 'path,' | |
1633 | + starting at the root directory and copying as many chars | |
1634 | + as possible before the end of the buffer. The buffer | |
1635 | + size is indicated by the 'numchars' argument. The first | |
1636 | + thing this function will do is load the name of the current | |
1637 | + working directory, if it isn't already present. This could | |
1638 | + occur if the user switched to the dotdot entry of a | |
1639 | + subdirectory immediately before calling this function. The | |
1640 | + function will then copy the current working directory name | |
1641 | + into the buffer backwards, and insert a backslash character. | |
1642 | + Next, the function will continuously switch to the previous | |
1643 | + directories and copy their names backwards into the buffer | |
1644 | + until it reaches the root. If the buffer overflows, it | |
1645 | + will be treated as a circular buffer, and data will be | |
1646 | + copied over existing characters, starting at the beginning. | |
1647 | + Once the root directory is reached, the text in the buffer | |
1648 | + will be swapped, so that the buffer contains as much of the | |
1649 | + current working directory name as possible, starting at the | |
1650 | + root. | |
1651 | + Remarks: | |
1652 | + None | |
1653 | + **************************************************************/ | |
1654 | + | |
1655 | +char * FSgetcwd (char * path, int numbchars); | |
1656 | + | |
1657 | +#ifdef SUPPORT_LFN | |
1658 | +/************************************************************** | |
1659 | + Function: | |
1660 | + char * wFSgetcwd (unsigned short int * path, int numchars) | |
1661 | + Summary: | |
1662 | + Get the current working directory path in UTF16 format | |
1663 | + Conditions: | |
1664 | + None | |
1665 | + Input: | |
1666 | + path - Pointer to the array to return the cwd name in | |
1667 | + numchars - Number of chars in the path | |
1668 | + Return Values: | |
1669 | + char * - The cwd name string pointer (path or defaultArray) | |
1670 | + NULL - The current working directory name could not be loaded. | |
1671 | + Side Effects: | |
1672 | + The FSerrno variable will be changed | |
1673 | + Description: | |
1674 | + The FSgetcwd function will get the name of the current | |
1675 | + working directory and return it to the user. The name | |
1676 | + will be copied into the buffer pointed to by 'path,' | |
1677 | + starting at the root directory and copying as many chars | |
1678 | + as possible before the end of the buffer. The buffer | |
1679 | + size is indicated by the 'numchars' argument. The first | |
1680 | + thing this function will do is load the name of the current | |
1681 | + working directory, if it isn't already present. This could | |
1682 | + occur if the user switched to the dotdot entry of a | |
1683 | + subdirectory immediately before calling this function. The | |
1684 | + function will then copy the current working directory name | |
1685 | + into the buffer backwards, and insert a backslash character. | |
1686 | + Next, the function will continuously switch to the previous | |
1687 | + directories and copy their names backwards into the buffer | |
1688 | + until it reaches the root. If the buffer overflows, it | |
1689 | + will be treated as a circular buffer, and data will be | |
1690 | + copied over existing characters, starting at the beginning. | |
1691 | + Once the root directory is reached, the text in the buffer | |
1692 | + will be swapped, so that the buffer contains as much of the | |
1693 | + current working directory name as possible, starting at the | |
1694 | + root. | |
1695 | + Remarks: | |
1696 | + None | |
1697 | + **************************************************************/ | |
1698 | + | |
1699 | +char * wFSgetcwd (unsigned short int * path, int numbchars); | |
1700 | +#endif | |
1701 | + | |
1702 | +#ifdef ALLOW_WRITES | |
1703 | + | |
1704 | +/************************************************************************** | |
1705 | + Function: | |
1706 | + int FSmkdir (char * path) | |
1707 | + Summary: | |
1708 | + Create a directory as per the Ascii input path | |
1709 | + Conditions: | |
1710 | + None | |
1711 | + Input: | |
1712 | + path - The path of directories to create. | |
1713 | + Return Values: | |
1714 | + 0 - The specified directory was created successfully | |
1715 | + EOF - The specified directory could not be created | |
1716 | + Side Effects: | |
1717 | + Will create all non-existent directories in the path. The FSerrno | |
1718 | + variable will be changed. | |
1719 | + Description: | |
1720 | + The FSmkdir function passes a RAM pointer to the path to the | |
1721 | + mkdirhelper function. | |
1722 | + Remarks: | |
1723 | + None | |
1724 | + **************************************************************************/ | |
1725 | + | |
1726 | +int FSmkdir (char * path); | |
1727 | + | |
1728 | +#ifdef SUPPORT_LFN | |
1729 | +/************************************************************************** | |
1730 | + Function: | |
1731 | + int wFSmkdir (unsigned short int * path) | |
1732 | + Summary: | |
1733 | + Create a directory as per the UTF16 input path | |
1734 | + Conditions: | |
1735 | + None | |
1736 | + Input: | |
1737 | + path - The path of directories to create. | |
1738 | + Return Values: | |
1739 | + 0 - The specified directory was created successfully | |
1740 | + EOF - The specified directory could not be created | |
1741 | + Side Effects: | |
1742 | + Will create all non-existent directories in the path. The FSerrno | |
1743 | + variable will be changed. | |
1744 | + Description: | |
1745 | + The wFSmkdir function passes a RAM pointer to the path to the | |
1746 | + mkdirhelper function. | |
1747 | + Remarks: | |
1748 | + None | |
1749 | + **************************************************************************/ | |
1750 | + | |
1751 | +int wFSmkdir (unsigned short int * path); | |
1752 | +#endif | |
1753 | + | |
1754 | +/************************************************************************** | |
1755 | + Function: | |
1756 | + int FSrmdir (char * path) | |
1757 | + Summary: | |
1758 | + Delete a directory as per the Ascii input path | |
1759 | + Conditions: | |
1760 | + None | |
1761 | + Input: | |
1762 | + path - The path of the directory to remove | |
1763 | + rmsubdirs - | |
1764 | + - TRUE - All sub-dirs and files in the target dir will be removed | |
1765 | + - FALSE - FSrmdir will not remove non-empty directories | |
1766 | + Return Values: | |
1767 | + 0 - The specified directory was deleted successfully | |
1768 | + EOF - The specified directory could not be deleted | |
1769 | + Side Effects: | |
1770 | + The FSerrno variable will be changed. | |
1771 | + Description: | |
1772 | + The FSrmdir function passes a RAM pointer to the path to the | |
1773 | + rmdirhelper function. | |
1774 | + Remarks: | |
1775 | + None. | |
1776 | + **************************************************************************/ | |
1777 | + | |
1778 | +int FSrmdir (char * path, unsigned char rmsubdirs); | |
1779 | + | |
1780 | +#ifdef SUPPORT_LFN | |
1781 | +/************************************************************************** | |
1782 | + Function: | |
1783 | + int wFSrmdir (unsigned short int * path, unsigned char rmsubdirs) | |
1784 | + Summary: | |
1785 | + Delete a directory as per the UTF16 input path | |
1786 | + Conditions: | |
1787 | + None | |
1788 | + Input: | |
1789 | + path - The path of the directory to remove | |
1790 | + rmsubdirs - | |
1791 | + - TRUE - All sub-dirs and files in the target dir will be removed | |
1792 | + - FALSE - FSrmdir will not remove non-empty directories | |
1793 | + Return Values: | |
1794 | + 0 - The specified directory was deleted successfully | |
1795 | + EOF - The specified directory could not be deleted | |
1796 | + Side Effects: | |
1797 | + The FSerrno variable will be changed. | |
1798 | + Description: | |
1799 | + The wFSrmdir function passes a RAM pointer to the path to the | |
1800 | + rmdirhelper function. | |
1801 | + Remarks: | |
1802 | + None. | |
1803 | + **************************************************************************/ | |
1804 | + | |
1805 | +int wFSrmdir (unsigned short int * path, unsigned char rmsubdirs); | |
1806 | +#endif | |
1807 | + | |
1808 | +#endif | |
1809 | + | |
1810 | +#endif | |
1811 | + | |
1812 | +#ifdef USERDEFINEDCLOCK | |
1813 | + | |
1814 | + | |
1815 | +/*********************************************************************************************************** | |
1816 | + Function: | |
1817 | + int SetClockVars (unsigned int year, unsigned char month, unsigned char day, unsigned char hour, unsigned char minute, unsigned char second) | |
1818 | + Summary: | |
1819 | + Manually set timestamp variables | |
1820 | + Conditions: | |
1821 | + USERDEFINEDCLOCK macro defined in FSconfig.h. | |
1822 | + Input: | |
1823 | + year - The year (1980\-2107) | |
1824 | + month - The month (1\-12) | |
1825 | + day - The day of the month (1\-31) | |
1826 | + hour - The hour (0\-23) | |
1827 | + minute - The minute (0\-59) | |
1828 | + second - The second (0\-59) | |
1829 | + Return Values: | |
1830 | + None | |
1831 | + Side Effects: | |
1832 | + Modifies global timing variables | |
1833 | + Description: | |
1834 | + Lets the user manually set the timing variables. The values passed in will be converted to the format | |
1835 | + used by the FAT timestamps. | |
1836 | + Remarks: | |
1837 | + Call this before creating a file or directory (set create time) and | |
1838 | + before closing a file (set last access time, last modified time) | |
1839 | + ***********************************************************************************************************/ | |
1840 | + | |
1841 | +int SetClockVars (unsigned int year, unsigned char month, unsigned char day, unsigned char hour, unsigned char minute, unsigned char second); | |
1842 | +#endif | |
1843 | + | |
1844 | + | |
1845 | +#ifdef ALLOW_FILESEARCH | |
1846 | + | |
1847 | +/*********************************************************************************** | |
1848 | + Function: | |
1849 | + int FindFirst (const char * fileName, unsigned int attr, SearchRec * rec) | |
1850 | + Summary: | |
1851 | + Initial search function for the input Ascii fileName | |
1852 | + Conditions: | |
1853 | + None | |
1854 | + Input: | |
1855 | + fileName - The name to search for | |
1856 | + - Parital string search characters | |
1857 | + - * - Indicates the rest of the filename or extension can vary (e.g. FILE.*) | |
1858 | + - ? - Indicates that one character in a filename can vary (e.g. F?LE.T?T) | |
1859 | + attr - The attributes that a found file may have | |
1860 | + - ATTR_READ_ONLY - File may be read only | |
1861 | + - ATTR_HIDDEN - File may be a hidden file | |
1862 | + - ATTR_SYSTEM - File may be a system file | |
1863 | + - ATTR_VOLUME - Entry may be a volume label | |
1864 | + - ATTR_DIRECTORY - File may be a directory | |
1865 | + - ATTR_ARCHIVE - File may have archive attribute | |
1866 | + - ATTR_MASK - All attributes | |
1867 | + rec - pointer to a structure to put the file information in | |
1868 | + Return Values: | |
1869 | + 0 - File was found | |
1870 | + -1 - No file matching the specified criteria was found | |
1871 | + Side Effects: | |
1872 | + Search criteria from previous FindFirst call on passed SearchRec object | |
1873 | + will be lost. "utf16LFNfound" is overwritten after subsequent FindFirst/FindNext | |
1874 | + operations.It is the responsibility of the application to read the "utf16LFNfound" | |
1875 | + before it is lost.The FSerrno variable will be changed. | |
1876 | + Description: | |
1877 | + The FindFirst function will search for a file based on parameters passed in | |
1878 | + by the user. This function will use the FILEfind function to parse through | |
1879 | + the current working directory searching for entries that match the specified | |
1880 | + parameters. If a file is found, its parameters are copied into the SearchRec | |
1881 | + structure, as are the initial parameters passed in by the user and the position | |
1882 | + of the file entry in the current working directory.If the return value of the | |
1883 | + function is 0 then "utf16LFNfoundLength" indicates whether the file found was | |
1884 | + long file name or short file name(8P3 format). The "utf16LFNfoundLength" is non-zero | |
1885 | + for long file name and is zero for 8P3 format."utf16LFNfound" points to the | |
1886 | + address of long file name if found during the operation. | |
1887 | + Remarks: | |
1888 | + Call FindFirst or FindFirstpgm before calling FindNext | |
1889 | + ***********************************************************************************/ | |
1890 | + | |
1891 | +int FindFirst (const char * fileName, unsigned int attr, SearchRec * rec); | |
1892 | + | |
1893 | +#ifdef SUPPORT_LFN | |
1894 | +/*********************************************************************************** | |
1895 | + Function: | |
1896 | + int wFindFirst (const unsigned short int * fileName, unsigned int attr, SearchRec * rec) | |
1897 | + Summary: | |
1898 | + Initial search function for the input UTF16 fileName | |
1899 | + Conditions: | |
1900 | + None | |
1901 | + Input: | |
1902 | + fileName - The name to search for | |
1903 | + - Parital string search characters | |
1904 | + - * - Indicates the rest of the filename or extension can vary (e.g. FILE.*) | |
1905 | + - ? - Indicates that one character in a filename can vary (e.g. F?LE.T?T) | |
1906 | + attr - The attributes that a found file may have | |
1907 | + - ATTR_READ_ONLY - File may be read only | |
1908 | + - ATTR_HIDDEN - File may be a hidden file | |
1909 | + - ATTR_SYSTEM - File may be a system file | |
1910 | + - ATTR_VOLUME - Entry may be a volume label | |
1911 | + - ATTR_DIRECTORY - File may be a directory | |
1912 | + - ATTR_ARCHIVE - File may have archive attribute | |
1913 | + - ATTR_MASK - All attributes | |
1914 | + rec - pointer to a structure to put the file information in | |
1915 | + Return Values: | |
1916 | + 0 - File was found | |
1917 | + -1 - No file matching the specified criteria was found | |
1918 | + Side Effects: | |
1919 | + Search criteria from previous wFindFirst call on passed SearchRec object | |
1920 | + will be lost. "utf16LFNfound" is overwritten after subsequent wFindFirst/FindNext | |
1921 | + operations.It is the responsibility of the application to read the "utf16LFNfound" | |
1922 | + before it is lost.The FSerrno variable will be changed. | |
1923 | + Description: | |
1924 | + The wFindFirst function will search for a file based on parameters passed in | |
1925 | + by the user. This function will use the FILEfind function to parse through | |
1926 | + the current working directory searching for entries that match the specified | |
1927 | + parameters. If a file is found, its parameters are copied into the SearchRec | |
1928 | + structure, as are the initial parameters passed in by the user and the position | |
1929 | + of the file entry in the current working directory.If the return value of the | |
1930 | + function is 0 then "utf16LFNfoundLength" indicates whether the file found was | |
1931 | + long file name or short file name(8P3 format). The "utf16LFNfoundLength" is non-zero | |
1932 | + for long file name and is zero for 8P3 format."utf16LFNfound" points to the | |
1933 | + address of long file name if found during the operation. | |
1934 | + Remarks: | |
1935 | + Call FindFirst or FindFirstpgm before calling FindNext | |
1936 | + ***********************************************************************************/ | |
1937 | + | |
1938 | +int wFindFirst (const unsigned short int * fileName, unsigned int attr, SearchRec * rec); | |
1939 | +#endif | |
1940 | + | |
1941 | +/********************************************************************** | |
1942 | + Function: | |
1943 | + int FindNext (SearchRec * rec) | |
1944 | + Summary: | |
1945 | + Sequential search function | |
1946 | + Conditions: | |
1947 | + None | |
1948 | + Input: | |
1949 | + rec - The structure to store the file information in | |
1950 | + Return Values: | |
1951 | + 0 - File was found | |
1952 | + -1 - No additional files matching the specified criteria were found | |
1953 | + Side Effects: | |
1954 | + Search criteria from previous FindNext call on passed SearchRec object | |
1955 | + will be lost. "utf16LFNfound" is overwritten after subsequent FindFirst/FindNext | |
1956 | + operations.It is the responsibility of the application to read the "utf16LFNfound" | |
1957 | + before it is lost.The FSerrno variable will be changed. | |
1958 | + Description: | |
1959 | + The FindNext function performs the same function as the FindFirst | |
1960 | + funciton, except it does not copy any search parameters into the | |
1961 | + SearchRec structure (only info about found files) and it begins | |
1962 | + searching at the last directory entry offset at which a file was | |
1963 | + found, rather than at the beginning of the current working | |
1964 | + directory.If the return value of the function is 0 then "utf16LFNfoundLength" | |
1965 | + indicates whether the file found was long file name or short file | |
1966 | + name(8P3 format). The "utf16LFNfoundLength" is non-zero for long file name | |
1967 | + and is zero for 8P3 format."utf16LFNfound" points to the address of long | |
1968 | + file name if found during the operation. | |
1969 | + Remarks: | |
1970 | + Call FindFirst or FindFirstpgm before calling this function | |
1971 | + **********************************************************************/ | |
1972 | + | |
1973 | +int FindNext (SearchRec * rec); | |
1974 | +#endif | |
1975 | + | |
1976 | + | |
1977 | +/********************************************************************** | |
1978 | + Function: | |
1979 | + // PIC24/30/33/32 | |
1980 | + int FSfprintf (FSFILE * fptr, const char * fmt, ...) | |
1981 | + // PIC18 | |
1982 | + int FSfpritnf (FSFILE * fptr, const rom char * fmt, ...) | |
1983 | + Summary: | |
1984 | + Function to write formatted strings to a file | |
1985 | + Conditions: | |
1986 | + For PIC18, integer promotion must be enabled in the project build | |
1987 | + options menu. File opened in a write mode. | |
1988 | + Input: | |
1989 | + fptr - A pointer to the file to write to. | |
1990 | + fmt - A string of characters and format specifiers to write to | |
1991 | + the file | |
1992 | + ... - Additional arguments inserted in the string by format | |
1993 | + specifiers | |
1994 | + Returns: | |
1995 | + The number of characters written to the file | |
1996 | + Side Effects: | |
1997 | + The FSerrno variable will be changed. | |
1998 | + Description: | |
1999 | + Writes a specially formatted string to a file. | |
2000 | + Remarks: | |
2001 | + Consult AN1045 for a full description of how to use format | |
2002 | + specifiers. | |
2003 | + **********************************************************************/ | |
2004 | + | |
2005 | +#ifdef ALLOW_FSFPRINTF | |
2006 | + #ifdef __18CXX | |
2007 | + int FSfprintf (FSFILE *fptr, const rom char *fmt, ...); | |
2008 | + #else | |
2009 | + int FSfprintf (FSFILE *fptr, const char * fmt, ...); | |
2010 | + #endif | |
2011 | +#endif | |
2012 | + | |
2013 | + | |
2014 | +/************************************************************************** | |
2015 | + Function: | |
2016 | + int FSerror (void) | |
2017 | + Summary: | |
2018 | + Return an error code for the last function call | |
2019 | + Conditions: | |
2020 | + The return value depends on the last function called. | |
2021 | + Input: | |
2022 | + None | |
2023 | + Side Effects: | |
2024 | + None. | |
2025 | + Return Values: | |
2026 | + FSInit - | |
2027 | + - CE_GOOD ・ No Error | |
2028 | + - CE_INIT_ERROR ・ The physical media could not be initialized | |
2029 | + - CE_BAD_SECTOR_READ ・ The MBR or the boot sector could not be | |
2030 | + read correctly | |
2031 | + - CE_BAD_PARITION ・ The MBR signature code was incorrect. | |
2032 | + - CE_NOT_FORMATTED ・ The boot sector signature code was incorrect or | |
2033 | + indicates an invalid number of bytes per sector. | |
2034 | + - CE_CARDFAT32 ・ The physical media is FAT32 type (only an error | |
2035 | + when FAT32 support is disabled). | |
2036 | + - CE_UNSUPPORTED_FS ・ The device is formatted with an unsupported file | |
2037 | + system (not FAT12 or 16). | |
2038 | + FSfopen - | |
2039 | + - CE_GOOD ・ No Error | |
2040 | + - CE_NOT_INIT ・ The device has not been initialized. | |
2041 | + - CE_TOO_MANY_FILES_OPEN ・ The function could not allocate any | |
2042 | + additional file information to the array | |
2043 | + of FSFILE structures or the heap. | |
2044 | + - CE_INVALID_FILENAME ・ The file name argument was invalid. | |
2045 | + - CE_INVALID_ARGUMENT ・ The user attempted to open a directory in a | |
2046 | + write mode or specified an invalid mode argument. | |
2047 | + - CE_FILE_NOT_FOUND ・ The specified file (which was to be opened in read | |
2048 | + mode) does not exist on the device. | |
2049 | + - CE_BADCACHEREAD ・ A read from the device failed. | |
2050 | + - CE_ERASE_FAIL ・ The existing file could not be erased (when opening | |
2051 | + a file in WRITE mode). | |
2052 | + - CE_DIR_FULL ・ The directory is full. | |
2053 | + - CE_DISK_FULL・ The data memory section is full. | |
2054 | + - CE_WRITE_ERROR ・ A write to the device failed. | |
2055 | + - CE_SEEK_ERROR ・ The current position in the file could not be set to | |
2056 | + the end (when the file was opened in APPEND mode). | |
2057 | + FSfclose - | |
2058 | + - CE_GOOD ・ No Error | |
2059 | + - CE_WRITE_ERROR ・ The existing data in the data buffer or the new file | |
2060 | + entry information could not be written to the device. | |
2061 | + - CE_BADCACHEREAD ・ The file entry information could not be cached | |
2062 | + FSfread - | |
2063 | + - CE_GOOD ・ No Error | |
2064 | + - CE_WRITEONLY ・ The file was opened in a write-only mode. | |
2065 | + - CE_WRITE_ERROR ・ The existing data in the data buffer could not be | |
2066 | + written to the device. | |
2067 | + - CE_BAD_SECTOR_READ ・ The data sector could not be read. | |
2068 | + - CE_EOF ・ The end of the file was reached. | |
2069 | + - CE_COULD_NOT_GET_CLUSTER ・Additional clusters in the file could not be loaded. | |
2070 | + FSfwrite - | |
2071 | + - CE_GOOD ・ No Error | |
2072 | + - CE_READONLY ・ The file was opened in a read-only mode. | |
2073 | + - CE_WRITE_PROTECTED ・ The device write-protect check function indicated | |
2074 | + that the device has been write-protected. | |
2075 | + - CE_WRITE_ERROR ・ There was an error writing data to the device. | |
2076 | + - CE_BADCACHEREAD ・ The data sector to be modified could not be read from | |
2077 | + the device. | |
2078 | + - CE_DISK_FULL ・ All data clusters on the device are in use. | |
2079 | + FSfseek - | |
2080 | + - CE_GOOD ・ No Error | |
2081 | + - CE_WRITE_ERROR ・ The existing data in the data buffer could not be | |
2082 | + written to the device. | |
2083 | + - CE_INVALID_ARGUMENT ・ The specified offset exceeds the size of the file. | |
2084 | + - CE_BADCACHEREAD ・ The sector that contains the new current position | |
2085 | + could not be loaded. | |
2086 | + - CE_COULD_NOT_GET_CLUSTER ・Additional clusters in the file could not be | |
2087 | + loaded/allocated. | |
2088 | + FSftell - | |
2089 | + - CE_GOOD ・ No Error | |
2090 | + FSattrib - | |
2091 | + - CE_GOOD ・ No Error | |
2092 | + - CE_INVALID_ARGUMENT ・ The attribute argument was invalid. | |
2093 | + - CE_BADCACHEREAD ・ The existing file entry information could not be | |
2094 | + loaded. | |
2095 | + - CE_WRITE_ERROR ・ The file entry information could not be written to | |
2096 | + the device. | |
2097 | + FSrename - | |
2098 | + - CE_GOOD ・ No Error | |
2099 | + - CE_FILENOTOPENED ・ A null file pointer was passed into the function. | |
2100 | + - CE_INVALID_FILENAME ・ The file name passed into the function was invalid. | |
2101 | + - CE_BADCACHEREAD ・ A read from the device failed. | |
2102 | + - CE_FILENAME_EXISTS ・ A file with the specified name already exists. | |
2103 | + - CE_WRITE_ERROR ・ The new file entry data could not be written to the | |
2104 | + device. | |
2105 | + FSfeof - | |
2106 | + - CE_GOOD ・ No Error | |
2107 | + FSformat - | |
2108 | + - CE_GOOD ・ No Error | |
2109 | + - CE_INIT_ERROR ・ The device could not be initialized. | |
2110 | + - CE_BADCACHEREAD ・ The master boot record or boot sector could not be | |
2111 | + loaded successfully. | |
2112 | + - CE_INVALID_ARGUMENT ・ The user selected to create their own boot sector on | |
2113 | + a device that has no master boot record, or the mode | |
2114 | + argument was invalid. | |
2115 | + - CE_WRITE_ERROR ・ The updated MBR/Boot sector could not be written to | |
2116 | + the device. | |
2117 | + - CE_BAD_PARTITION ・ The calculated number of sectors per clusters was | |
2118 | + invalid. | |
2119 | + - CE_NONSUPPORTED_SIZE ・ The card has too many sectors to be formatted as | |
2120 | + FAT12 or FAT16. | |
2121 | + FSremove - | |
2122 | + - CE_GOOD ・ No Error | |
2123 | + - CE_WRITE_PROTECTED ・ The device write-protect check function indicated | |
2124 | + that the device has been write-protected. | |
2125 | + - CE_INVALID_FILENAME ・ The specified filename was invalid. | |
2126 | + - CE_FILE_NOT_FOUND ・ The specified file could not be found. | |
2127 | + - CE_ERASE_FAIL ・ The file could not be erased. | |
2128 | + FSchdir - | |
2129 | + - CE_GOOD ・ No Error | |
2130 | + - CE_INVALID_ARGUMENT ・ The path string was mis-formed or the user tried to | |
2131 | + change to a non-directory file. | |
2132 | + - CE_BADCACHEREAD ・ A directory entry could not be cached. | |
2133 | + - CE_DIR_NOT_FOUND ・ Could not find a directory in the path. | |
2134 | + FSgetcwd - | |
2135 | + - CE_GOOD ・ No Error | |
2136 | + - CE_INVALID_ARGUMENT ・ The user passed a 0-length buffer into the function. | |
2137 | + - CE_BADCACHEREAD ・ A directory entry could not be cached. | |
2138 | + - CE_BAD_SECTOR_READ ・ The function could not determine a previous directory | |
2139 | + of the current working directory. | |
2140 | + FSmkdir - | |
2141 | + - CE_GOOD ・ No Error | |
2142 | + - CE_WRITE_PROTECTED ・ The device write-protect check function indicated | |
2143 | + that the device has been write-protected. | |
2144 | + - CE_INVALID_ARGUMENT ・ The path string was mis-formed. | |
2145 | + - CE_BADCACHEREAD ・ Could not successfully change to a recently created | |
2146 | + directory to store its dir entry information, or | |
2147 | + could not cache directory entry information. | |
2148 | + - CE_INVALID_FILENAME ・ One or more of the directory names has an invalid | |
2149 | + format. | |
2150 | + - CE_WRITE_ERROR ・ The existing data in the data buffer could not be | |
2151 | + written to the device or the dot/dotdot entries could | |
2152 | + not be written to a newly created directory. | |
2153 | + - CE_DIR_FULL ・ There are no available dir entries in the CWD. | |
2154 | + - CE_DISK_FULL ・ There are no available clusters in the data region of | |
2155 | + the device. | |
2156 | + FSrmdir - | |
2157 | + - CE_GOOD ・ No Error | |
2158 | + - CE_DIR_NOT_FOUND ・ The directory specified could not be found or the | |
2159 | + function could not change to a subdirectory within | |
2160 | + the directory to be deleted (when recursive delete is | |
2161 | + enabled). | |
2162 | + - CE_INVALID_ARGUMENT ・ The user tried to remove the CWD or root directory. | |
2163 | + - CE_BADCACHEREAD ・ A directory entry could not be cached. | |
2164 | + - CE_DIR_NOT_EMPTY ・ The directory to be deleted was not empty and | |
2165 | + recursive subdirectory removal was disabled. | |
2166 | + - CE_ERASE_FAIL ・ The directory or one of the directories or files | |
2167 | + within it could not be deleted. | |
2168 | + - CE_BAD_SECTOR_READ ・ The function could not determine a previous directory | |
2169 | + of the CWD. | |
2170 | + SetClockVars - | |
2171 | + - CE_GOOD ・ No Error | |
2172 | + - CE_INVALID_ARGUMENT ・ The time values passed into the function were | |
2173 | + invalid. | |
2174 | + FindFirst - | |
2175 | + - CE_GOOD ・ No Error | |
2176 | + - CE_INVALID_FILENAME ・ The specified filename was invalid. | |
2177 | + - CE_FILE_NOT_FOUND ・ No file matching the specified criteria was found. | |
2178 | + - CE_BADCACHEREAD ・ The file information for the file that was found | |
2179 | + could not be cached. | |
2180 | + FindNext - | |
2181 | + - CE_GOOD ・ No Error | |
2182 | + - CE_NOT_INIT ・ The SearchRec object was not initialized by a call to | |
2183 | + FindFirst. | |
2184 | + - CE_INVALID_ARGUMENT ・ The SearchRec object was initialized in a different | |
2185 | + directory from the CWD. | |
2186 | + - CE_INVALID_FILENAME ・ The filename is invalid. | |
2187 | + - CE_FILE_NOT_FOUND ・ No file matching the specified criteria was found. | |
2188 | + FSfprintf - | |
2189 | + - CE_GOOD ・ No Error | |
2190 | + - CE_WRITE_ERROR ・ Characters could not be written to the file. | |
2191 | + Description: | |
2192 | + The FSerror function will return the FSerrno variable. This global | |
2193 | + variable will have been set to an error value during the last call of a | |
2194 | + library function. | |
2195 | + Remarks: | |
2196 | + None | |
2197 | + **************************************************************************/ | |
2198 | + | |
2199 | +int FSerror (void); | |
2200 | + | |
2201 | + | |
2202 | +/********************************************************************************* | |
2203 | + Function: | |
2204 | + int FSCreateMBR (unsigned long firstSector, unsigned long numSectors) | |
2205 | + Summary: | |
2206 | + Creates a master boot record | |
2207 | + Conditions: | |
2208 | + The I/O pins for the device have been initialized by the InitIO function. | |
2209 | + Input: | |
2210 | + firstSector - The first sector of the partition on the device (cannot | |
2211 | + be 0; that's the MBR) | |
2212 | + numSectors - The number of sectors available in memory (including the | |
2213 | + MBR) | |
2214 | + Return Values: | |
2215 | + 0 - MBR was created successfully | |
2216 | + EOF - MBR could not be created | |
2217 | + Side Effects: | |
2218 | + None | |
2219 | + Description: | |
2220 | + This function can be used to create a master boot record for a device. Note | |
2221 | + that this function should not be used on a device that is already formatted | |
2222 | + with a master boot record (i.e. most SD cards, CF cards, USB keys). This | |
2223 | + function will fill the global data buffer with appropriate partition information | |
2224 | + for a FAT partition with a type determined by the number of sectors available | |
2225 | + to the partition. It will then write the MBR information to the first sector | |
2226 | + on the device. This function should be followed by a call to FSformat, which | |
2227 | + will create a boot sector, root dir, and FAT appropriate the the information | |
2228 | + contained in the new master boot record. Note that FSformat only supports | |
2229 | + FAT12 and FAT16 formatting at this time, and so cannot be used to format a | |
2230 | + device with more than 0x3FFD5F sectors. | |
2231 | + Remarks: | |
2232 | + This function can damage the device being used, and should not be called | |
2233 | + unless the user is sure about the size of the device and the first sector value. | |
2234 | + *********************************************************************************/ | |
2235 | + | |
2236 | +int FSCreateMBR (unsigned long firstSector, unsigned long numSectors); | |
2237 | + | |
2238 | + | |
2239 | +#ifdef ALLOW_GET_DISK_PROPERTIES | |
2240 | +/********************************************************************************* | |
2241 | + Function: | |
2242 | + void FSGetDiskProperties(FS_DISK_PROPERTIES* properties) | |
2243 | + Summary: | |
2244 | + Allows user to get the disk properties (size of disk, free space, etc) | |
2245 | + Conditions: | |
2246 | + 1) ALLOW_GET_DISK_PROPERTIES must be defined in FSconfig.h | |
2247 | + 2) a FS_DISK_PROPERTIES object must be created before the function is called | |
2248 | + 3) the new_request member of the FS_DISK_PROPERTIES object must be set before | |
2249 | + calling the function for the first time. This will start a new search. | |
2250 | + 4) this function should not be called while there is a file open. Close all | |
2251 | + files before calling this function. | |
2252 | + Input: | |
2253 | + properties - a pointer to a FS_DISK_PROPERTIES object where the results should | |
2254 | + be stored. | |
2255 | + Return Values: | |
2256 | + This function returns void. The properties_status of the previous call of | |
2257 | + this function is located in the properties.status field. This field has | |
2258 | + the following possible values: | |
2259 | + | |
2260 | + FS_GET_PROPERTIES_NO_ERRORS - operation completed without error. Results | |
2261 | + are in the properties object passed into the function. | |
2262 | + FS_GET_PROPERTIES_DISK_NOT_MOUNTED - there is no mounted disk. Results in | |
2263 | + properties object is not valid | |
2264 | + FS_GET_PROPERTIES_CLUSTER_FAILURE - there was a failure trying to read a | |
2265 | + cluster from the drive. The results in the properties object is a partial | |
2266 | + result up until the point of the failure. | |
2267 | + FS_GET_PROPERTIES_STILL_WORKING - the search for free sectors is still in | |
2268 | + process. Continue calling this function with the same properties pointer | |
2269 | + until either the function completes or until the partial results meets the | |
2270 | + application needs. The properties object contains the partial results of | |
2271 | + the search and can be used by the application. | |
2272 | + Side Effects: | |
2273 | + Can cause errors if called when files are open. Close all files before | |
2274 | + calling this function. | |
2275 | + | |
2276 | + Calling this function without setting the new_request member on the first | |
2277 | + call can result in undefined behavior and results. | |
2278 | + | |
2279 | + Calling this function after a result is returned other than | |
2280 | + FS_GET_PROPERTIES_STILL_WORKING can result in undefined behavior and results. | |
2281 | + Description: | |
2282 | + This function returns the information about the mounted drive. The results | |
2283 | + member of the properties object passed into the function is populated with | |
2284 | + the information about the drive. | |
2285 | + | |
2286 | + Before starting a new request, the new_request member of the properties | |
2287 | + input parameter should be set to TRUE. This will initiate a new search | |
2288 | + request. | |
2289 | + | |
2290 | + This function will return before the search is complete with partial results. | |
2291 | + All of the results except the free_clusters will be correct after the first | |
2292 | + call. The free_clusters will contain the number of free clusters found up | |
2293 | + until that point, thus the free_clusters result will continue to grow until | |
2294 | + the entire drive is searched. If an application only needs to know that a | |
2295 | + certain number of bytes is available and doesn't need to know the total free | |
2296 | + size, then this function can be called until the required free size is | |
2297 | + verified. To continue a search, pass a pointer to the same FS_DISK_PROPERTIES | |
2298 | + object that was passed in to create the search. | |
2299 | + | |
2300 | + A new search request sould be made once this function has returned a value | |
2301 | + other than FS_GET_PROPERTIES_STILL_WORKING. Continuing a completed search | |
2302 | + can result in undefined behavior or results. | |
2303 | + | |
2304 | + Typical Usage: | |
2305 | + <code> | |
2306 | + FS_DISK_PROPERTIES disk_properties; | |
2307 | + | |
2308 | + disk_properties.new_request = TRUE; | |
2309 | + | |
2310 | + do | |
2311 | + { | |
2312 | + FSGetDiskProperties(&disk_properties); | |
2313 | + } while (disk_properties.properties_status == FS_GET_PROPERTIES_STILL_WORKING); | |
2314 | + </code> | |
2315 | + | |
2316 | + results.disk_format - contains the format of the drive. Valid results are | |
2317 | + FAT12(1), FAT16(2), or FAT32(3). | |
2318 | + | |
2319 | + results.sector_size - the sector size of the mounted drive. Valid values are | |
2320 | + 512, 1024, 2048, and 4096. | |
2321 | + | |
2322 | + results.sectors_per_cluster - the number sectors per cluster. | |
2323 | + | |
2324 | + results.total_clusters - the number of total clusters on the drive. This | |
2325 | + can be used to calculate the total disk size (total_clusters * | |
2326 | + sectors_per_cluster * sector_size = total size of drive in bytes) | |
2327 | + | |
2328 | + results.free_clusters - the number of free (unallocated) clusters on the drive. | |
2329 | + This can be used to calculate the total free disk size (free_clusters * | |
2330 | + sectors_per_cluster * sector_size = total size of drive in bytes) | |
2331 | + | |
2332 | + Remarks: | |
2333 | + PIC24F size estimates: | |
2334 | + Flash - 400 bytes (-Os setting) | |
2335 | + | |
2336 | + PIC24F speed estimates: | |
2337 | + Search takes approximately 7 seconds per Gigabyte of drive space. Speed | |
2338 | + will vary based on the number of sectors per cluster and the sector size. | |
2339 | + *********************************************************************************/ | |
2340 | +void FSGetDiskProperties(FS_DISK_PROPERTIES* properties); | |
2341 | +#endif | |
2342 | + | |
2343 | + | |
2344 | +#endif |
@@ -0,0 +1,894 @@ | ||
1 | +//カラーグラフィックライブラリ | |
2 | + | |
3 | +#include <plib.h> | |
4 | +#include "videoout.h" | |
5 | +#include "LCDdriver.h" | |
6 | + | |
7 | +//unsigned char TVRAM[WIDTH_X*WIDTH_Y*2+1] __attribute__ ((aligned (4))); | |
8 | +unsigned char TVRAM[WIDTH_X2*WIDTH_Y*2+1] __attribute__ ((aligned (4))); | |
9 | +unsigned char *fontp; //フォント格納アドレス、初期化時はFontData、RAM指定することでPCGを実現 | |
10 | +unsigned int bgcolor; // バックグランドカラー | |
11 | +unsigned char twidth; //テキスト1行文字数(30 or 40) | |
12 | +unsigned char graphmode; //テキストモード時 0、グラフィックモード時 0以外 | |
13 | + | |
14 | +unsigned short palette[256]; | |
15 | +const unsigned char __attribute__((weak)) FontData[256*8]={ | |
16 | +//フォントデータ、キャラクタコード順に8バイトずつ、上位ビットが左 | |
17 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
18 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
19 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
20 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
21 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
22 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
23 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
24 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
25 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
26 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
27 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
28 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
29 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
30 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
31 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
32 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
33 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
34 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
35 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
36 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
37 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
38 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
39 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
40 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
41 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
42 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
43 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
44 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
45 | + 0x00,0x08,0x0C,0xFE,0xFE,0x0C,0x08,0x00, | |
46 | + 0x00,0x20,0x60,0xFE,0xFE,0x60,0x20,0x00, | |
47 | + 0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x00, | |
48 | + 0x00,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18, | |
49 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
50 | + 0x30,0x30,0x30,0x30,0x00,0x00,0x30,0x00, | |
51 | + 0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00, | |
52 | + 0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00, | |
53 | + 0x18,0x7E,0xD8,0x7E,0x1A,0xFE,0x18,0x00, | |
54 | + 0xE0,0xE6,0x0C,0x18,0x30,0x6E,0xCE,0x00, | |
55 | + 0x78,0xCC,0xD8,0x70,0xDE,0xCC,0x76,0x00, | |
56 | + 0x0C,0x18,0x30,0x00,0x00,0x00,0x00,0x00, | |
57 | + 0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00, | |
58 | + 0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00, | |
59 | + 0xD6,0x7C,0x38,0xFE,0x38,0x7C,0xD6,0x00, | |
60 | + 0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00, | |
61 | + 0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60, | |
62 | + 0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00, | |
63 | + 0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x00, | |
64 | + 0x00,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00, | |
65 | + 0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, | |
66 | + 0x18,0x38,0x78,0x18,0x18,0x18,0x7E,0x00, | |
67 | + 0x7C,0xC6,0x06,0x1C,0x70,0xC0,0xFE,0x00, | |
68 | + 0x7C,0xC6,0x06,0x3C,0x06,0xC6,0x7C,0x00, | |
69 | + 0x0C,0x1C,0x3C,0x6C,0xFE,0x0C,0x0C,0x00, | |
70 | + 0xFE,0xC0,0xF8,0x0C,0x06,0xCC,0x78,0x00, | |
71 | + 0x3C,0x60,0xC0,0xFC,0xC6,0xC6,0x7C,0x00, | |
72 | + 0xFE,0xC6,0x0C,0x18,0x30,0x30,0x30,0x00, | |
73 | + 0x7C,0xC6,0xC6,0x7C,0xC6,0xC6,0x7C,0x00, | |
74 | + 0x7C,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00, | |
75 | + 0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00, | |
76 | + 0x00,0x30,0x00,0x00,0x00,0x30,0x30,0x60, | |
77 | + 0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00, | |
78 | + 0x00,0x00,0xFE,0x00,0xFE,0x00,0x00,0x00, | |
79 | + 0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00, | |
80 | + 0x7C,0xC6,0x06,0x1C,0x30,0x00,0x30,0x00, | |
81 | + 0x3C,0x66,0xDE,0xF6,0xDC,0x60,0x3E,0x00, | |
82 | + 0x38,0x6C,0xC6,0xFE,0xC6,0xC6,0xC6,0x00, | |
83 | + 0xFC,0x66,0x66,0x7C,0x66,0x66,0xFC,0x00, | |
84 | + 0x3C,0x66,0xC0,0xC0,0xC0,0x66,0x3C,0x00, | |
85 | + 0xF8,0x6C,0x66,0x66,0x66,0x6C,0xF8,0x00, | |
86 | + 0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xFE,0x00, | |
87 | + 0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xC0,0x00, | |
88 | + 0x3C,0x66,0xC0,0xCE,0xC6,0x66,0x3C,0x00, | |
89 | + 0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00, | |
90 | + 0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, | |
91 | + 0x1E,0x0C,0x0C,0x0C,0x0C,0xCC,0x78,0x00, | |
92 | + 0xC6,0xCC,0xD8,0xF0,0xD8,0xCC,0xC6,0x00, | |
93 | + 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFE,0x00, | |
94 | + 0xC6,0xEE,0xFE,0xD6,0xC6,0xC6,0xC6,0x00, | |
95 | + 0xC6,0xE6,0xF6,0xDE,0xCE,0xC6,0xC6,0x00, | |
96 | + 0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x38,0x00, | |
97 | + 0xFC,0xC6,0xC6,0xFC,0xC0,0xC0,0xC0,0x00, | |
98 | + 0x38,0x6C,0xC6,0xC6,0xDE,0x6C,0x3E,0x00, | |
99 | + 0xFC,0xC6,0xC6,0xFC,0xD8,0xCC,0xC6,0x00, | |
100 | + 0x7C,0xC6,0xC0,0x7C,0x06,0xC6,0x7C,0x00, | |
101 | + 0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00, | |
102 | + 0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, | |
103 | + 0xC6,0xC6,0xC6,0x6C,0x6C,0x38,0x38,0x00, | |
104 | + 0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00, | |
105 | + 0xC6,0xC6,0x6C,0x38,0x6C,0xC6,0xC6,0x00, | |
106 | + 0xCC,0xCC,0xCC,0x78,0x30,0x30,0x30,0x00, | |
107 | + 0xFE,0x06,0x0C,0x38,0x60,0xC0,0xFE,0x00, | |
108 | + 0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00, | |
109 | + 0xCC,0xCC,0x78,0xFC,0x30,0xFC,0x30,0x00, | |
110 | + 0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00, | |
111 | + 0x30,0x78,0xCC,0x00,0x00,0x00,0x00,0x00, | |
112 | + 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00, | |
113 | + 0x30,0x18,0x0C,0x00,0x00,0x00,0x00,0x00, | |
114 | + 0x00,0x00,0x7C,0x0C,0x7C,0xCC,0x7E,0x00, | |
115 | + 0xC0,0xC0,0xFC,0xE6,0xC6,0xE6,0xFC,0x00, | |
116 | + 0x00,0x00,0x7C,0xC6,0xC0,0xC6,0x7C,0x00, | |
117 | + 0x06,0x06,0x7E,0xCE,0xC6,0xCE,0x7E,0x00, | |
118 | + 0x00,0x00,0x7C,0xC6,0xFE,0xC0,0x7C,0x00, | |
119 | + 0x1C,0x36,0x30,0xFC,0x30,0x30,0x30,0x00, | |
120 | + 0x00,0x00,0x7E,0xCE,0xCE,0x7E,0x06,0x7C, | |
121 | + 0xC0,0xC0,0xFC,0xE6,0xC6,0xC6,0xC6,0x00, | |
122 | + 0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00, | |
123 | + 0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0xCC,0x78, | |
124 | + 0xC0,0xC0,0xCC,0xD8,0xF0,0xF8,0xCC,0x00, | |
125 | + 0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, | |
126 | + 0x00,0x00,0xFC,0xB6,0xB6,0xB6,0xB6,0x00, | |
127 | + 0x00,0x00,0xFC,0xE6,0xC6,0xC6,0xC6,0x00, | |
128 | + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0x00, | |
129 | + 0x00,0x00,0xFC,0xE6,0xE6,0xFC,0xC0,0xC0, | |
130 | + 0x00,0x00,0x7E,0xCE,0xCE,0x7E,0x06,0x06, | |
131 | + 0x00,0x00,0xDC,0xE6,0xC0,0xC0,0xC0,0x00, | |
132 | + 0x00,0x00,0x7E,0xC0,0x7C,0x06,0xFC,0x00, | |
133 | + 0x30,0x30,0xFC,0x30,0x30,0x36,0x1C,0x00, | |
134 | + 0x00,0x00,0xC6,0xC6,0xC6,0xCE,0x76,0x00, | |
135 | + 0x00,0x00,0xC6,0xC6,0xC6,0x6C,0x38,0x00, | |
136 | + 0x00,0x00,0x86,0xB6,0xB6,0xB6,0xFC,0x00, | |
137 | + 0x00,0x00,0xC6,0x6C,0x38,0x6C,0xC6,0x00, | |
138 | + 0x00,0x00,0xC6,0xC6,0xCE,0x7E,0x06,0x7C, | |
139 | + 0x00,0x00,0xFE,0x0C,0x38,0x60,0xFE,0x00, | |
140 | + 0x3C,0x60,0x60,0xC0,0x60,0x60,0x3C,0x00, | |
141 | + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00, | |
142 | + 0xF0,0x18,0x18,0x0C,0x18,0x18,0xF0,0x00, | |
143 | + 0x60,0xB6,0x1C,0x00,0x00,0x00,0x00,0x00, | |
144 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
145 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, | |
146 | + 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF, | |
147 | + 0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF, | |
148 | + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, | |
149 | + 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF, | |
150 | + 0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | |
151 | + 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | |
152 | + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | |
153 | + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, | |
154 | + 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0, | |
155 | + 0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0, | |
156 | + 0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, | |
157 | + 0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8, | |
158 | + 0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC, | |
159 | + 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, | |
160 | + 0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18, | |
161 | + 0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00, | |
162 | + 0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18, | |
163 | + 0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18, | |
164 | + 0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18, | |
165 | + 0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
166 | + 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00, | |
167 | + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, | |
168 | + 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, | |
169 | + 0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18, | |
170 | + 0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18, | |
171 | + 0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00, | |
172 | + 0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00, | |
173 | + 0x00,0x00,0x00,0x00,0x07,0x0C,0x18,0x18, | |
174 | + 0x00,0x00,0x00,0x00,0xE0,0x30,0x18,0x18, | |
175 | + 0x18,0x18,0x18,0x0C,0x07,0x00,0x00,0x00, | |
176 | + 0x18,0x18,0x18,0x30,0xE0,0x00,0x00,0x00, | |
177 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
178 | + 0x00,0x00,0x00,0x00,0x78,0x68,0x78,0x00, | |
179 | + 0x78,0x60,0x60,0x60,0x00,0x00,0x00,0x00, | |
180 | + 0x00,0x00,0x00,0x18,0x18,0x18,0x78,0x00, | |
181 | + 0x00,0x00,0x00,0x00,0x60,0x30,0x18,0x00, | |
182 | + 0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00, | |
183 | + 0xFE,0x06,0x06,0xFE,0x06,0x0C,0x78,0x00, | |
184 | + 0x00,0x00,0xFC,0x0C,0x38,0x30,0x60,0x00, | |
185 | + 0x00,0x00,0x0C,0x18,0x38,0x78,0x18,0x00, | |
186 | + 0x00,0x00,0x30,0xFC,0xCC,0x0C,0x38,0x00, | |
187 | + 0x00,0x00,0x00,0xFC,0x30,0x30,0xFC,0x00, | |
188 | + 0x00,0x00,0x18,0xFC,0x38,0x78,0xD8,0x00, | |
189 | + 0x00,0x00,0x60,0xFC,0x6C,0x68,0x60,0x00, | |
190 | + 0x00,0x00,0x00,0x78,0x18,0x18,0xFC,0x00, | |
191 | + 0x00,0x00,0x7C,0x0C,0x7C,0x0C,0x7C,0x00, | |
192 | + 0x00,0x00,0x00,0xAC,0xAC,0x0C,0x38,0x00, | |
193 | + 0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00, | |
194 | + 0xFE,0x06,0x06,0x34,0x38,0x30,0x60,0x00, | |
195 | + 0x06,0x0C,0x18,0x38,0x78,0xD8,0x18,0x00, | |
196 | + 0x18,0xFE,0xC6,0xC6,0x06,0x0C,0x38,0x00, | |
197 | + 0x00,0x7E,0x18,0x18,0x18,0x18,0x7E,0x00, | |
198 | + 0x18,0xFE,0x18,0x38,0x78,0xD8,0x18,0x00, | |
199 | + 0x30,0xFE,0x36,0x36,0x36,0x36,0x6C,0x00, | |
200 | + 0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00, | |
201 | + 0x3E,0x66,0xC6,0x0C,0x18,0x30,0xE0,0x00, | |
202 | + 0x60,0x7E,0xD8,0x18,0x18,0x18,0x30,0x00, | |
203 | + 0x00,0xFE,0x06,0x06,0x06,0x06,0xFE,0x00, | |
204 | + 0x6C,0xFE,0x6C,0x0C,0x0C,0x18,0x30,0x00, | |
205 | + 0x00,0xF0,0x00,0xF6,0x06,0x0C,0xF8,0x00, | |
206 | + 0xFE,0x06,0x0C,0x18,0x38,0x6C,0xC6,0x00, | |
207 | + 0x60,0xFE,0x66,0x6C,0x60,0x60,0x3E,0x00, | |
208 | + 0xC6,0xC6,0x66,0x06,0x0C,0x18,0xF0,0x00, | |
209 | + 0x3E,0x66,0xE6,0x3C,0x18,0x30,0xE0,0x00, | |
210 | + 0x0C,0x78,0x18,0xFE,0x18,0x18,0xF0,0x00, | |
211 | + 0x00,0xD6,0xD6,0xD6,0x0C,0x18,0xF0,0x00, | |
212 | + 0x7C,0x00,0xFE,0x18,0x18,0x30,0x60,0x00, | |
213 | + 0x30,0x30,0x38,0x3C,0x36,0x30,0x30,0x00, | |
214 | + 0x18,0x18,0xFE,0x18,0x18,0x30,0x60,0x00, | |
215 | + 0x00,0x7C,0x00,0x00,0x00,0x00,0xFE,0x00, | |
216 | + 0x00,0x7E,0x06,0x6C,0x18,0x36,0x60,0x00, | |
217 | + 0x18,0x7E,0x0C,0x18,0x3C,0x7E,0x18,0x00, | |
218 | + 0x06,0x06,0x06,0x0C,0x18,0x30,0x60,0x00, | |
219 | + 0x30,0x18,0x0C,0xC6,0xC6,0xC6,0xC6,0x00, | |
220 | + 0xC0,0xC0,0xFE,0xC0,0xC0,0xC0,0x7E,0x00, | |
221 | + 0x00,0xFE,0x06,0x06,0x0C,0x18,0x70,0x00, | |
222 | + 0x00,0x30,0x78,0xCC,0x06,0x06,0x00,0x00, | |
223 | + 0x18,0x18,0xFE,0x18,0xDB,0xDB,0x18,0x00, | |
224 | + 0xFE,0x06,0x06,0x6C,0x38,0x30,0x18,0x00, | |
225 | + 0x00,0x3C,0x00,0x3C,0x00,0x7C,0x06,0x00, | |
226 | + 0x0C,0x18,0x30,0x60,0xCC,0xFC,0x06,0x00, | |
227 | + 0x02,0x36,0x3C,0x18,0x3C,0x6C,0xC0,0x00, | |
228 | + 0x00,0xFE,0x30,0xFE,0x30,0x30,0x3E,0x00, | |
229 | + 0x30,0x30,0xFE,0x36,0x3C,0x30,0x30,0x00, | |
230 | + 0x00,0x78,0x18,0x18,0x18,0x18,0xFE,0x00, | |
231 | + 0xFE,0x06,0x06,0xFE,0x06,0x06,0xFE,0x00, | |
232 | + 0x7C,0x00,0xFE,0x06,0x0C,0x18,0x30,0x00, | |
233 | + 0xC6,0xC6,0xC6,0x06,0x06,0x0C,0x38,0x00, | |
234 | + 0x6C,0x6C,0x6C,0x6E,0x6E,0x6C,0xC8,0x00, | |
235 | + 0x60,0x60,0x60,0x66,0x6C,0x78,0x70,0x00, | |
236 | + 0x00,0xFE,0xC6,0xC6,0xC6,0xC6,0xFE,0x00, | |
237 | + 0x00,0xFE,0xC6,0xC6,0x06,0x0C,0x38,0x00, | |
238 | + 0x00,0xF0,0x06,0x06,0x0C,0x18,0xF0,0x00, | |
239 | + 0x18,0xCC,0x60,0x00,0x00,0x00,0x00,0x00, | |
240 | + 0x70,0xD8,0x70,0x00,0x00,0x00,0x00,0x00, | |
241 | + 0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00, | |
242 | + 0x18,0x18,0x1F,0x18,0x18,0x1F,0x18,0x18, | |
243 | + 0x18,0x18,0xFF,0x18,0x18,0xFF,0x18,0x18, | |
244 | + 0x18,0x18,0xF8,0x18,0x18,0xF8,0x18,0x18, | |
245 | + 0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF, | |
246 | + 0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF, | |
247 | + 0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01, | |
248 | + 0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80, | |
249 | + 0x10,0x38,0x7C,0xFE,0xFE,0x38,0x7C,0x00, | |
250 | + 0x6C,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00, | |
251 | + 0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00, | |
252 | + 0x38,0x38,0xFE,0xFE,0xD6,0x10,0x7C,0x00, | |
253 | + 0x00,0x3C,0x7E,0x7E,0x7E,0x7E,0x3C,0x00, | |
254 | + 0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, | |
255 | + 0x03,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80, | |
256 | + 0x80,0xC0,0x60,0x30,0x18,0x0C,0x06,0x03, | |
257 | + 0x83,0xC6,0x6C,0x38,0x38,0x6C,0xC6,0x83, | |
258 | + 0xFE,0xB6,0xB6,0xFE,0x86,0x86,0x86,0x00, | |
259 | + 0xC0,0xFE,0xD8,0x7E,0x58,0xFE,0x18,0x00, | |
260 | + 0x7E,0x66,0x7E,0x66,0x7E,0x66,0xC6,0x00, | |
261 | + 0xFE,0xC6,0xC6,0xFE,0xC6,0xC6,0xFE,0x00, | |
262 | + 0x06,0xEF,0xA6,0xFF,0xA2,0xFF,0x0A,0x06, | |
263 | + 0x00,0x38,0x6C,0xC6,0x7C,0x34,0x6C,0x00, | |
264 | + 0xFC,0x6C,0xFE,0x6E,0xF6,0xEC,0x6C,0x78, | |
265 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
266 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
267 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
268 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
269 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
270 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
271 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
272 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 | |
273 | +}; | |
274 | + | |
275 | +void set_palette(unsigned char n,unsigned char b,unsigned char r,unsigned char g){ | |
276 | +//テキスト、グラフィック共用カラーパレット設定 | |
277 | + palette[n]=((r>>3)<<11)+((g>>2)<<5)+(b>>3); | |
278 | +} | |
279 | + | |
280 | +void g_pset(int x,int y,unsigned int c) | |
281 | +// (x,y)の位置にカラーパレット番号cで点を描画 | |
282 | +{ | |
283 | + if(x>=0 && x<X_RES && y>=0 && y<Y_RES) | |
284 | + drawPixel(x,y,palette[c]); | |
285 | +} | |
286 | + | |
287 | +void g_putbmpmn(int x,int y,char m,char n,const unsigned char bmp[]) | |
288 | +// 横m*縦nドットのキャラクターを座標x,yに表示 | |
289 | +// unsigned char bmp[m*n]配列に、単純にカラー番号を並べる | |
290 | +// カラー番号が0の部分は透明色として扱う | |
291 | +{ | |
292 | + int i,j; | |
293 | + int skip; | |
294 | + const unsigned char *p; | |
295 | + if(x<=-m || x>X_RES || y<=-n || y>=Y_RES) return; //画面外 | |
296 | + if(y<0){ //画面上部に切れる場合 | |
297 | + i=0; | |
298 | + p=bmp-y*m; | |
299 | + } | |
300 | + else{ | |
301 | + i=y; | |
302 | + p=bmp; | |
303 | + } | |
304 | + for(;i<y+n;i++){ | |
305 | + if(i>=Y_RES) return; //画面下部に切れる場合 | |
306 | + if(x<0){ //画面左に切れる場合は残る部分のみ描画 | |
307 | + j=0; | |
308 | + p+=-x; | |
309 | + } | |
310 | + else{ | |
311 | + j=x; | |
312 | + } | |
313 | + skip=1; | |
314 | + for(;j<x+m;j++){ | |
315 | + if(j>=X_RES){ //画面右に切れる場合 | |
316 | + p+=x+m-j; | |
317 | + break; | |
318 | + } | |
319 | + if(*p!=0){ //カラー番号が0の場合、透明として処理 | |
320 | + if(skip){ | |
321 | + LCD_SetCursor(j,i); | |
322 | + LCD_WriteIndex(0x22); | |
323 | + skip=0; | |
324 | + } | |
325 | + LCD_WriteData(palette[*p]); | |
326 | + } | |
327 | + else skip=1; | |
328 | + p++; | |
329 | + } | |
330 | + } | |
331 | +} | |
332 | + | |
333 | + | |
334 | +// 縦m*横nドットのキャラクター消去 | |
335 | +// カラー0で塗りつぶし | |
336 | +void g_clrbmpmn(int x,int y,char m,char n) | |
337 | +{ | |
338 | + int i,j,k; | |
339 | + if(x<=-m || x>X_RES || y<=-n || y>=Y_RES) return; //画面外 | |
340 | + if(y<0) i=0; //画面上部に切れる場合 | |
341 | + else i=y; | |
342 | + if(x<0) j=0; //画面左に切れる場合は残る部分のみ描画 | |
343 | + else j=x; | |
344 | + if(x+m>=X_RES) k=X_RES-j; //画面右に切れる場合 | |
345 | + else k=x+m-j; | |
346 | + for(;i<y+n;i++){ | |
347 | + if(i>=Y_RES) return; //画面下部に切れる場合 | |
348 | + LCD_continuous_output(j,i,0,k); | |
349 | + } | |
350 | +} | |
351 | + | |
352 | +void g_gline(int x1,int y1,int x2,int y2,unsigned int c) | |
353 | +// (x1,y1)-(x2,y2)にカラーパレット番号cで線分を描画 | |
354 | +{ | |
355 | + int sx,sy,dx,dy,i; | |
356 | + int e; | |
357 | + | |
358 | + if(x2>x1){ | |
359 | + dx=x2-x1; | |
360 | + sx=1; | |
361 | + } | |
362 | + else{ | |
363 | + dx=x1-x2; | |
364 | + sx=-1; | |
365 | + } | |
366 | + if(y2>y1){ | |
367 | + dy=y2-y1; | |
368 | + sy=1; | |
369 | + } | |
370 | + else{ | |
371 | + dy=y1-y2; | |
372 | + sy=-1; | |
373 | + } | |
374 | + if(dx>=dy){ | |
375 | + e=-dx; | |
376 | + for(i=0;i<=dx;i++){ | |
377 | + g_pset(x1,y1,c); | |
378 | + x1+=sx; | |
379 | + e+=dy*2; | |
380 | + if(e>=0){ | |
381 | + y1+=sy; | |
382 | + e-=dx*2; | |
383 | + } | |
384 | + } | |
385 | + } | |
386 | + else{ | |
387 | + e=-dy; | |
388 | + for(i=0;i<=dy;i++){ | |
389 | + g_pset(x1,y1,c); | |
390 | + y1+=sy; | |
391 | + e+=dx*2; | |
392 | + if(e>=0){ | |
393 | + x1+=sx; | |
394 | + e-=dy*2; | |
395 | + } | |
396 | + } | |
397 | + } | |
398 | +} | |
399 | +void g_hline(int x1,int x2,int y,unsigned int c) | |
400 | +// (x1,y)-(x2,y)への水平ラインを高速描画 | |
401 | +{ | |
402 | + int temp; | |
403 | + unsigned short d,*ad; | |
404 | + | |
405 | + if(y<0 || y>=Y_RES) return; | |
406 | + if(x1>x2){ | |
407 | + temp=x1; | |
408 | + x1=x2; | |
409 | + x2=temp; | |
410 | + } | |
411 | + if(x2<0 || x1>=X_RES) return; | |
412 | + if(x1<0) x1=0; | |
413 | + if(x2>=X_RES) x2=X_RES-1; | |
414 | + LCD_continuous_output(x1,y,palette[c],x2-x1+1); | |
415 | +} | |
416 | + | |
417 | +void g_circle(int x0,int y0,unsigned int r,unsigned int c) | |
418 | +// (x0,y0)を中心に、半径r、カラーパレット番号cの円を描画 | |
419 | +{ | |
420 | + int x,y,f; | |
421 | + x=r; | |
422 | + y=0; | |
423 | + f=-2*r+3; | |
424 | + while(x>=y){ | |
425 | + g_pset(x0-x,y0-y,c); | |
426 | + g_pset(x0-x,y0+y,c); | |
427 | + g_pset(x0+x,y0-y,c); | |
428 | + g_pset(x0+x,y0+y,c); | |
429 | + g_pset(x0-y,y0-x,c); | |
430 | + g_pset(x0-y,y0+x,c); | |
431 | + g_pset(x0+y,y0-x,c); | |
432 | + g_pset(x0+y,y0+x,c); | |
433 | + if(f>=0){ | |
434 | + x--; | |
435 | + f-=x*4; | |
436 | + } | |
437 | + y++; | |
438 | + f+=y*4+2; | |
439 | + } | |
440 | +} | |
441 | +void g_boxfill(int x1,int y1,int x2,int y2,unsigned int c) | |
442 | +// (x1,y1),(x2,y2)を対角線とするカラーパレット番号cで塗られた長方形を描画 | |
443 | +{ | |
444 | + int temp; | |
445 | + if(x1>x2){ | |
446 | + temp=x1; | |
447 | + x1=x2; | |
448 | + x2=temp; | |
449 | + } | |
450 | + if(x2<0 || x1>=X_RES) return; | |
451 | + if(y1>y2){ | |
452 | + temp=y1; | |
453 | + y1=y2; | |
454 | + y2=temp; | |
455 | + } | |
456 | + if(y2<0 || y1>=Y_RES) return; | |
457 | + if(y1<0) y1=0; | |
458 | + if(y2>=Y_RES) y2=Y_RES-1; | |
459 | + while(y1<=y2){ | |
460 | + g_hline(x1,x2,y1++,c); | |
461 | + } | |
462 | +} | |
463 | +void g_circlefill(int x0,int y0,unsigned int r,unsigned int c) | |
464 | +// (x0,y0)を中心に、半径r、カラーパレット番号cで塗られた円を描画 | |
465 | +{ | |
466 | + int x,y,f; | |
467 | + x=r; | |
468 | + y=0; | |
469 | + f=-2*r+3; | |
470 | + while(x>=y){ | |
471 | + g_hline(x0-x,x0+x,y0-y,c); | |
472 | + g_hline(x0-x,x0+x,y0+y,c); | |
473 | + g_hline(x0-y,x0+y,y0-x,c); | |
474 | + g_hline(x0-y,x0+y,y0+x,c); | |
475 | + if(f>=0){ | |
476 | + x--; | |
477 | + f-=x*4; | |
478 | + } | |
479 | + y++; | |
480 | + f+=y*4+2; | |
481 | + } | |
482 | +} | |
483 | + | |
484 | +void g_putfont(int x,int y,unsigned int c,int bc,unsigned char n) | |
485 | +//8*8ドットのアルファベットフォント表示 | |
486 | +//座標(x,y)、カラーパレット番号c | |
487 | +//bc:バックグランドカラー、負数の場合無視 | |
488 | +//n:文字番号 | |
489 | +{ | |
490 | + int i,j; | |
491 | + unsigned char d; | |
492 | + int skip; | |
493 | + unsigned short c1; | |
494 | + const unsigned char *p; | |
495 | + if(x<=-8 || x>=X_RES || y<=-8 || y>=Y_RES) return; //画面外 | |
496 | + if(y<0){ //画面上部に切れる場合 | |
497 | + i=0; | |
498 | + p=fontp+n*8-y; | |
499 | + } | |
500 | + else{ | |
501 | + i=y; | |
502 | + p=fontp+n*8; | |
503 | + } | |
504 | + c1=palette[c]; | |
505 | + if(bc>=0) bc=palette[bc]; | |
506 | + for(;i<y+8;i++){ | |
507 | + if(i>=Y_RES) return; //画面下部に切れる場合 | |
508 | + d=*p++; | |
509 | + if(x<0){ //画面左に切れる場合は残る部分のみ描画 | |
510 | + j=0; | |
511 | + d<<=-x; | |
512 | + } | |
513 | + else{ | |
514 | + j=x; | |
515 | + } | |
516 | + if(bc<0){ | |
517 | + skip=1; | |
518 | + for(;j<x+8;j++){ | |
519 | + if(j>=X_RES){ //画面右に切れる場合 | |
520 | + break; | |
521 | + } | |
522 | + if(d&0x80){ | |
523 | + if(skip){ | |
524 | + LCD_SetCursor(j,i); | |
525 | + LCD_WriteIndex(0x22); | |
526 | + skip=0; | |
527 | + } | |
528 | + LCD_WriteData(c1); | |
529 | + } | |
530 | + else skip=1; | |
531 | + d<<=1; | |
532 | + } | |
533 | + } | |
534 | + else{ | |
535 | + LCD_SetCursor(j,i); | |
536 | + LCD_WriteIndex(0x22); | |
537 | + for(;j<x+8;j++){ | |
538 | + if(j>=X_RES){ //画面右に切れる場合 | |
539 | + break; | |
540 | + } | |
541 | + if(d&0x80){ | |
542 | + LCD_WriteData(c1); | |
543 | + } | |
544 | + else{ | |
545 | + LCD_WriteData(bc); | |
546 | + } | |
547 | + d<<=1; | |
548 | + } | |
549 | + } | |
550 | + } | |
551 | +} | |
552 | + | |
553 | +void g_printstr(int x,int y,unsigned int c,unsigned int bc,unsigned char *s){ | |
554 | + //座標(x,y)からカラーパレット番号cで文字列sを表示、bc:バックグランドカラー | |
555 | + //bcが負の場合は無視 | |
556 | + while(*s){ | |
557 | + g_putfont(x,y,c,bc,*s++); | |
558 | + x+=8; | |
559 | + } | |
560 | +} | |
561 | +void g_printnum(int x,int y,unsigned int c,unsigned int bc,unsigned int n){ | |
562 | + //座標(x,y)にカラー番号cで数値nを表示、bc:バックグランドカラー | |
563 | + unsigned int d,e; | |
564 | + d=10; | |
565 | + e=0; | |
566 | + while(n>=d){ | |
567 | + e++; | |
568 | + if(e==9) break; | |
569 | + d*=10; | |
570 | + } | |
571 | + x+=e*8; | |
572 | + do{ | |
573 | + g_putfont(x,y,c,bc,'0'+n%10); | |
574 | + n/=10; | |
575 | + x-=8; | |
576 | + }while(n!=0); | |
577 | +} | |
578 | +void g_printnum2(int x,int y,unsigned int c,unsigned int bc,unsigned int n,unsigned char e){ | |
579 | + //座標(x,y)にカラー番号cで数値nを表示、bc:バックグランドカラー、e桁で表示 | |
580 | + if(e==0) return; | |
581 | + x+=(e-1)*8; | |
582 | + do{ | |
583 | + g_putfont(x,y,c,bc,'0'+n%10); | |
584 | + e--; | |
585 | + n/=10; | |
586 | + x-=8; | |
587 | + }while(e!=0 && n!=0); | |
588 | + while(e!=0){ | |
589 | + g_putfont(x,y,c,bc,' '); | |
590 | + x-=8; | |
591 | + e--; | |
592 | + } | |
593 | +} | |
594 | +unsigned int g_color(int x,int y){ | |
595 | +//座標(x,y)の色情報を返す、画面外は0を返す | |
596 | +//パレット番号ではないことに注意 | |
597 | + if(x<0 || x>=X_RES || y<0 || y>=Y_RES) return 0; | |
598 | + return getColor(x,y); | |
599 | +} | |
600 | + | |
601 | +// テキスト画面クリア | |
602 | +void clearscreen(void) | |
603 | +{ | |
604 | + unsigned int *vp; | |
605 | + int i; | |
606 | + vp=(unsigned int *)TVRAM; | |
607 | + for(i=0;i<WIDTH_X2*WIDTH_Y*2/4;i++) *vp++=0; | |
608 | + cursor=TVRAM; | |
609 | + LCD_Clear(bgcolor); | |
610 | +} | |
611 | + | |
612 | +// グラフィック画面クリア | |
613 | +void g_clearscreen(void) | |
614 | +{ | |
615 | + LCD_Clear(0); | |
616 | +} | |
617 | +unsigned char *cursor; | |
618 | +unsigned char cursorcolor; | |
619 | + | |
620 | +void textredraw(void){ | |
621 | +// テキスト画面再描画 | |
622 | +// テキストVRAMの内容にしたがって液晶に出力 | |
623 | + unsigned char *p; | |
624 | + int i,j; | |
625 | + | |
626 | + p=TVRAM; | |
627 | + for(i=0;i<WIDTH_Y;i++){ | |
628 | + if(twidth==WIDTH_X1){ | |
629 | + for(j=0;j<WIDTH_X1;j++){ | |
630 | + g_putfont(j*8,i*8,*(p+ATTROFFSET1),bgcolor,*p); | |
631 | + p++; | |
632 | + } | |
633 | + } | |
634 | + else{ | |
635 | + for(j=0;j<WIDTH_X2;j++){ | |
636 | + g_putfont(j*6,i*8,*(p+ATTROFFSET2),bgcolor,*p); | |
637 | + p++; | |
638 | + } | |
639 | + } | |
640 | + } | |
641 | +} | |
642 | +void vramscroll(void){ | |
643 | + unsigned short *p1,*p2; | |
644 | + | |
645 | + p1=(unsigned short *)TVRAM; | |
646 | + if(twidth==WIDTH_X1){ | |
647 | + p2=(unsigned short *)(TVRAM+WIDTH_X1); | |
648 | + while(p2<(unsigned short *)(TVRAM+ATTROFFSET1)){ | |
649 | + *(p1+ATTROFFSET1/2)=*(p2+ATTROFFSET1/2); | |
650 | + *p1++=*p2++; | |
651 | + } | |
652 | + while(p1<(unsigned short *)(TVRAM+ATTROFFSET1)){ | |
653 | + *(p1+ATTROFFSET1/2)=0; | |
654 | + *p1++=0; | |
655 | + } | |
656 | + } | |
657 | + else{ | |
658 | + p2=(unsigned short *)(TVRAM+WIDTH_X2); | |
659 | + while(p2<(unsigned short *)(TVRAM+ATTROFFSET2)){ | |
660 | + *(p1+ATTROFFSET2/2)=*(p2+ATTROFFSET2/2); | |
661 | + *p1++=*p2++; | |
662 | + } | |
663 | + while(p1<(unsigned short *)(TVRAM+ATTROFFSET2)){ | |
664 | + *(p1+ATTROFFSET2/2)=0; | |
665 | + *p1++=0; | |
666 | + } | |
667 | + } | |
668 | + textredraw(); | |
669 | +} | |
670 | +void vramscrolldown(void){ | |
671 | + unsigned short *p1,*p2; | |
672 | + | |
673 | + if(twidth==WIDTH_X1){ | |
674 | + p1=(unsigned short *)(TVRAM+ATTROFFSET1)-1; | |
675 | + p2=(unsigned short *)(TVRAM+ATTROFFSET1-WIDTH_X1)-1; | |
676 | + while(p2>=(unsigned short *)(TVRAM)){ | |
677 | + *(p1+ATTROFFSET1/2)=*(p2+ATTROFFSET1/2); | |
678 | + *p1++=*p2++; | |
679 | + } | |
680 | + while(p1>=(unsigned short *)(TVRAM)){ | |
681 | + *(p1+ATTROFFSET1/2)=0; | |
682 | + *p1++=0; | |
683 | + } | |
684 | + } | |
685 | + else{ | |
686 | + p1=(unsigned short *)(TVRAM+ATTROFFSET2)-1; | |
687 | + p2=(unsigned short *)(TVRAM+ATTROFFSET2-WIDTH_X2)-1; | |
688 | + while(p2>=(unsigned short *)(TVRAM)){ | |
689 | + *(p1+ATTROFFSET2/2)=*(p2+ATTROFFSET2/2); | |
690 | + *p1++=*p2++; | |
691 | + } | |
692 | + while(p1>=(unsigned short *)(TVRAM)){ | |
693 | + *(p1+ATTROFFSET2/2)=0; | |
694 | + *p1++=0; | |
695 | + } | |
696 | + } | |
697 | + textredraw(); | |
698 | +} | |
699 | +void setcursor(unsigned char x,unsigned char y,unsigned char c){ | |
700 | + //カーソルを座標(x,y)にカラー番号cに設定 | |
701 | + if(x>=twidth || y>=WIDTH_Y) return; | |
702 | + cursor=TVRAM+y*twidth+x; | |
703 | + cursorcolor=c; | |
704 | +} | |
705 | +void setcursorcolor(unsigned char c){ | |
706 | + //カーソル位置そのままでカラー番号をcに設定 | |
707 | + cursorcolor=c; | |
708 | +} | |
709 | +void printchar(unsigned char n){ | |
710 | + //カーソル位置にテキストコードnを1文字表示し、カーソルを1文字進める | |
711 | + //画面最終文字表示してもスクロールせず、次の文字表示時にスクロールする | |
712 | + if(cursor<TVRAM || cursor>TVRAM+twidth*WIDTH_Y) return; | |
713 | + if(cursor==TVRAM+twidth*WIDTH_Y){ | |
714 | + vramscroll(); | |
715 | + cursor-=twidth; | |
716 | + } | |
717 | + if(n=='\n'){ | |
718 | + //改行 | |
719 | + cursor+=twidth-((cursor-TVRAM)%twidth); | |
720 | + } else{ | |
721 | + *cursor=n; | |
722 | + if(twidth==WIDTH_X1){ | |
723 | + *(cursor+ATTROFFSET1)=cursorcolor; | |
724 | + g_putfont(((cursor-TVRAM)%WIDTH_X1)*8,((cursor-TVRAM)/WIDTH_X1)*8,cursorcolor,bgcolor,n); | |
725 | + } | |
726 | + else{ | |
727 | + *(cursor+ATTROFFSET2)=cursorcolor; | |
728 | + g_putfont(((cursor-TVRAM)%WIDTH_X2)*6,((cursor-TVRAM)/WIDTH_X2)*8,cursorcolor,bgcolor,n); | |
729 | + } | |
730 | + cursor++; | |
731 | + } | |
732 | +} | |
733 | +void printstr(unsigned char *s){ | |
734 | + //カーソル位置に文字列sを表示 | |
735 | + while(*s){ | |
736 | + printchar(*s++); | |
737 | + } | |
738 | +} | |
739 | +void printnum(unsigned int n){ | |
740 | + //カーソル位置に符号なし整数nを10進数表示 | |
741 | + unsigned int d,n1; | |
742 | + n1=n/10; | |
743 | + d=1; | |
744 | + while(n1>=d){ | |
745 | + d*=10; | |
746 | + } | |
747 | + while(d!=0){ | |
748 | + printchar('0'+n/d); | |
749 | + n%=d; | |
750 | + d/=10; | |
751 | + } | |
752 | +} | |
753 | +void printnum2(unsigned int n,unsigned char e){ | |
754 | + //カーソル位置に符号なし整数nをe桁の10進数表示(前の空き桁部分はスペースで埋める) | |
755 | + unsigned int d,n1; | |
756 | + if(e==0) return; | |
757 | + n1=n/10; | |
758 | + d=1; | |
759 | + e--; | |
760 | + while(e>0 && n1>=d){ | |
761 | + d*=10; | |
762 | + e--; | |
763 | + } | |
764 | + if(e==0 && n1>d) n%=d*10; | |
765 | + for(;e>0;e--) printchar(' '); | |
766 | + while(d!=0){ | |
767 | + printchar('0'+n/d); | |
768 | + n%=d; | |
769 | + d/=10; | |
770 | + } | |
771 | +} | |
772 | +void cls(void){ | |
773 | + //画面消去しカーソルを先頭に移動 | |
774 | + clearscreen(); | |
775 | +} | |
776 | +void startPCG(unsigned char *p,int a){ | |
777 | +// RAMフォント(PCG)の利用開始 | |
778 | +// p:RAMフォントの格納アドレス(8*256=2048バイト) | |
779 | +// a: システムフォントからのコピー指定。0の場合コピーなし、0以外でコピー | |
780 | + int i; | |
781 | + if(a){ | |
782 | + if(twidth==WIDTH_X1) | |
783 | + for(i=0;i<8*256;i++) *p++=FontData[i]; | |
784 | +// else | |
785 | +// for(i=0;i<8*256;i++) *p++=FontData2[i]; | |
786 | + fontp=p-8*256; | |
787 | + } | |
788 | + else fontp=p; | |
789 | +} | |
790 | +void stopPCG(void){ | |
791 | +// RAMフォント(PCG)の利用停止 | |
792 | + if(twidth==WIDTH_X1) fontp=(unsigned char *)FontData; | |
793 | +// else fontp=(unsigned char *)FontData2; | |
794 | +} | |
795 | +void set_bgcolor(unsigned char b,unsigned char r,unsigned char g) | |
796 | +{ | |
797 | + bgcolor=((r>>3)<<11)+((g>>2)<<5)+(b>>3); | |
798 | + | |
799 | +} | |
800 | +void init_textgraph(void){ | |
801 | + //テキストモードでのグラフィックLCDライブラリの使用開始 | |
802 | + //パレット設定 | |
803 | + //LCD縦横設定 | |
804 | + | |
805 | + int i; | |
806 | + graphmode=0;//テキストモード | |
807 | + fontp=(unsigned char *)FontData; | |
808 | + twidth=WIDTH_X1;//30文字モード | |
809 | + set_bgcolor(0,0,0); //バックグランドカラーは黒 | |
810 | + clearscreen(); | |
811 | + //カラーパレット初期化 | |
812 | + for(i=0;i<8;i++){ | |
813 | + set_palette(i,255*(i&1),255*((i>>1)&1),255*(i>>2)); | |
814 | + } | |
815 | + for(i=0;i<8;i++){ | |
816 | + set_palette(i+8,128*(i&1),128*((i>>1)&1),128*(i>>2)); | |
817 | + } | |
818 | + for(i=16;i<256;i++){ | |
819 | + set_palette(i,255,255,255); | |
820 | + } | |
821 | + setcursorcolor(7); | |
822 | + | |
823 | +// LCD_Init(); //ブートローダで初期化するため、アプリ側では初期化しない | |
824 | + | |
825 | +#if LCD_ALIGNMENT == HORIZONTAL | |
826 | + LCD_set_Horizontal(); | |
827 | +#endif | |
828 | +} | |
829 | + | |
830 | +void init_graphic(void){ | |
831 | + //グラフィックLCDライブラリの使用開始 | |
832 | + //パレット設定 | |
833 | + //LCD縦横設定 | |
834 | + | |
835 | + int i; | |
836 | + //カラーパレット初期化 | |
837 | + for(i=0;i<8;i++){ | |
838 | + set_palette(i,255*(i&1),255*((i>>1)&1),255*(i>>2)); | |
839 | + } | |
840 | + for(i=0;i<8;i++){ | |
841 | + set_palette(i+8,128*(i&1),128*((i>>1)&1),128*(i>>2)); | |
842 | + } | |
843 | + for(i=16;i<256;i++){ | |
844 | + set_palette(i,255,255,255); | |
845 | + } | |
846 | + | |
847 | +// LCD_Init(); //ブートローダで初期化するため、アプリ側では初期化しない | |
848 | + | |
849 | +#if LCD_ALIGNMENT == HORIZONTAL | |
850 | + LCD_set_Horizontal(); | |
851 | +#endif | |
852 | + LCD_Clear(0); | |
853 | +} | |
854 | +volatile unsigned short drawcount; | |
855 | +/********************** | |
856 | +* Timer2 割り込み処理関数 | |
857 | +***********************/ | |
858 | +void __ISR(8, ipl4) T2Handler(void) | |
859 | +{ | |
860 | + drawcount++; | |
861 | + IFS0bits.T2IF = 0; // T2割り込みフラグクリア | |
862 | + IFS0bits.CS0IF= 1; // CS0割り込み | |
863 | +} | |
864 | + | |
865 | +//30文字モード(8ドットフォント)と40文字モード(6ドットフォント)の切り替え | |
866 | +void set_width(unsigned char m){ | |
867 | +// m:0 30文字モード、1 40文字モード | |
868 | +// グラフモード時は無効 | |
869 | +// PCG使用中はフォント変更しない | |
870 | + if(graphmode) return; | |
871 | + clearscreen(); | |
872 | + if(m){ | |
873 | +// if(fontp<(unsigned char *)0xa0000000) fontp=(unsigned char *)FontData2; | |
874 | + twidth=WIDTH_X2; | |
875 | + } | |
876 | + else{ | |
877 | + if(fontp<(unsigned char *)0xa0000000) fontp=(unsigned char *)FontData; | |
878 | + twidth=WIDTH_X1; | |
879 | + } | |
880 | + return; | |
881 | +} | |
882 | + | |
883 | +//テキストモードとグラフィックモードの切り替え | |
884 | +void set_graphmode(unsigned char m){ | |
885 | +// m:0 テキストモード、0以外 グラフィックモード | |
886 | + if(m){ | |
887 | + //グラフィックモード開始 | |
888 | + graphmode=1; | |
889 | + } | |
890 | + else{ | |
891 | + //テキストーモード開始 | |
892 | + graphmode=0; | |
893 | + } | |
894 | +} |
@@ -0,0 +1,41 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by K.Tanaka & Katsumi | |
4 | + http://www.ze.em-net.ne.jp/~kenken/index.html | |
5 | + http://hp.vector.co.jp/authors/VA016157/ | |
6 | +*/ | |
7 | +// キー入力、カーソル表示関連機能 by K.Tanaka | |
8 | +// PS/2キーボード入力システム、カラーテキスト出力システム利用 | |
9 | + | |
10 | +#include "videoout.h" | |
11 | +#include "ps2keyboard.h" | |
12 | +#include "keyinput.h" | |
13 | +#include "plib.h" | |
14 | + | |
15 | +volatile unsigned short vkey; //仮想キーコード | |
16 | +unsigned short keystatus,keystatus2,oldkey; //最新のボタン状態と前回のボタン状態 | |
17 | + | |
18 | +int lineinput(char *s,int n){ | |
19 | + return 0; | |
20 | +} | |
21 | + | |
22 | +unsigned short readButton(void){ | |
23 | + unsigned short k; | |
24 | + LCD_CS_HI; | |
25 | + asm("nop"); | |
26 | + KEY_EN; | |
27 | + asm("nop"); | |
28 | + TRISBSET=KEYMASK; | |
29 | + asm("nop"); | |
30 | + k=~KEYPORT & KEYMASK; | |
31 | + KEY_DS; | |
32 | + asm("nop"); | |
33 | + TRISBCLR=KEYMASK; | |
34 | + asm("nop"); | |
35 | + LCD_CS_LO; | |
36 | + return k; | |
37 | +} | |
38 | + | |
39 | +unsigned char ps2readkey(){ | |
40 | + return 0; | |
41 | +} | |
\ No newline at end of file |
@@ -0,0 +1,48 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by K.Tanaka | |
4 | + http://www.ze.em-net.ne.jp/~kenken/index.html | |
5 | +*/ | |
6 | + | |
7 | +#define BLINKTIME 15 | |
8 | +#define CURSORCHAR 0x87 | |
9 | +#define CURSORCHAR2 0x80 | |
10 | +#define CURSORCOLOR 7 | |
11 | + | |
12 | +void getcursorchar(); | |
13 | +// カーソル点滅用に元の文字コードを退避 | |
14 | + | |
15 | +void resetcursorchar(); | |
16 | +// カーソルを元の文字に戻す | |
17 | + | |
18 | +void blinkcursorchar(); | |
19 | +// 定期的に呼び出すことでカーソルを点滅表示させる | |
20 | +// BLINKTIMEで点滅間隔を設定 | |
21 | +// 事前にgetcursorchar()を呼び出しておく | |
22 | + | |
23 | +int lineinput(char *s,int n); | |
24 | +// キー入力して文字列配列sに格納 | |
25 | +// sに初期文字列を入れておくと最初に表示して文字列の最後にカーソル移動する | |
26 | +// 初期文字列を使用しない場合は*s=0としておく | |
27 | +// カーソル位置はsetcursor関数で指定しておく | |
28 | +// 最大文字数n、最後に0を格納するのでn+1バイトの領域必要、ただしnの最大値は255 | |
29 | +// 戻り値 Enterで終了した場合0、ESCで終了時は-1(sは壊さない) | |
30 | + | |
31 | +unsigned char inputchar(void); | |
32 | +// キーボードから1キー入力待ち | |
33 | +// 戻り値 通常文字の場合ASCIIコード、その他は0、グローバル変数vkeyに仮想キーコード | |
34 | + | |
35 | +unsigned char printinputchar(void); | |
36 | +// カーソル表示しながらキーボードから通常文字キー入力待ちし、入力された文字を表示 | |
37 | +// 戻り値 入力された文字のASCIIコード、グローバル変数vkeyに最後に押されたキーの仮想キーコード | |
38 | + | |
39 | +unsigned char cursorinputchar(void); | |
40 | +// カーソル表示しながらキーボードから1キー入力待ち | |
41 | +// 戻り値 通常文字の場合ASCIIコード、その他は0、グローバル変数vkeyに仮想キーコード | |
42 | + | |
43 | +unsigned short readButton(void); | |
44 | + | |
45 | +extern unsigned char blinkchar,blinkcolor; | |
46 | +extern int blinktimer; | |
47 | +extern int insertmode; //挿入モード:1、上書きモード:0 | |
48 | +extern unsigned short keystatus,keystatus2,oldkey; //最新のボタン状態と前回のボタン状態 |
@@ -0,0 +1,178 @@ | ||
1 | +#define CHK_SHIFT 0x01 | |
2 | +#define CHK_CTRL 0x02 | |
3 | +#define CHK_ALT 0x04 | |
4 | +#define CHK_WIN 0x08 | |
5 | +#define CHK_SCRLK 0x10 | |
6 | +#define CHK_NUMLK 0x20 | |
7 | +#define CHK_CAPSLK 0x40 | |
8 | +#define CHK_SHIFT_L 0x01 | |
9 | +#define CHK_SHIFT_R 0x02 | |
10 | +#define CHK_CTRL_L 0x04 | |
11 | +#define CHK_CTRL_R 0x08 | |
12 | +#define CHK_ALT_L 0x10 | |
13 | +#define CHK_ALT_R 0x20 | |
14 | +#define CHK_WIN_L 0x40 | |
15 | +#define CHK_WIN_R 0x80 | |
16 | +#define CHK_SCRLK_A 0x100 | |
17 | +#define CHK_NUMLK_A 0x200 | |
18 | +#define CHK_CAPSLK_A 0x400 | |
19 | + | |
20 | +#define VK_LBUTTON 0x01 | |
21 | +#define VK_RBUTTON 0x02 | |
22 | +#define VK_CANCEL 0x03 | |
23 | +#define VK_MBUTTON 0x04 | |
24 | +#define VK_XBUTTON1 0x05 | |
25 | +#define VK_XBUTTON2 0x06 | |
26 | +#define VK_BACK 0x08 | |
27 | +#define VK_TAB 0x09 | |
28 | +#define VK_CLEAR 0x0C | |
29 | +#define VK_RETURN 0x0D | |
30 | +#define VK_SHIFT 0x10 | |
31 | +#define VK_CONTROL 0x11 | |
32 | +#define VK_MENU 0x12 | |
33 | +#define VK_PAUSE 0x13 | |
34 | +#define VK_CAPITAL 0x14 | |
35 | +#define VK_KANA 0x15 | |
36 | +#define VK_HANGUEL 0x15 | |
37 | +#define VK_HANGUL 0x15 | |
38 | +#define VK_JUNJA 0x17 | |
39 | +#define VK_FINAL 0x18 | |
40 | +#define VK_HANJA 0x19 | |
41 | +#define VK_KANJI 0x19 | |
42 | +#define VK_ESCAPE 0x1B | |
43 | +#define VK_CONVERT 0x1C | |
44 | +#define VK_NONCONVERT 0x1D | |
45 | +#define VK_ACCEPT 0x1E | |
46 | +#define VK_MODECHANGE 0x1F | |
47 | +#define VK_SPACE 0x20 | |
48 | +#define VK_PRIOR 0x21 | |
49 | +#define VK_NEXT 0x22 | |
50 | +#define VK_END 0x23 | |
51 | +#define VK_HOME 0x24 | |
52 | +#define VK_LEFT 0x25 | |
53 | +#define VK_UP 0x26 | |
54 | +#define VK_RIGHT 0x27 | |
55 | +#define VK_DOWN 0x28 | |
56 | +#define VK_SELECT 0x29 | |
57 | +#define VK_PRINT 0x2A | |
58 | +#define VK_EXECUTE 0x2B | |
59 | +#define VK_SNAPSHOT 0x2C | |
60 | +#define VK_INSERT 0x2D | |
61 | +#define VK_DELETE 0x2E | |
62 | +#define VK_HELP 0x2F | |
63 | +#define VK_LWIN 0x5B | |
64 | +#define VK_RWIN 0x5C | |
65 | +#define VK_APPS 0x5D | |
66 | +#define VK_SLEEP 0x5F | |
67 | +#define VK_NUMPAD0 0x60 | |
68 | +#define VK_NUMPAD1 0x61 | |
69 | +#define VK_NUMPAD2 0x62 | |
70 | +#define VK_NUMPAD3 0x63 | |
71 | +#define VK_NUMPAD4 0x64 | |
72 | +#define VK_NUMPAD5 0x65 | |
73 | +#define VK_NUMPAD6 0x66 | |
74 | +#define VK_NUMPAD7 0x67 | |
75 | +#define VK_NUMPAD8 0x68 | |
76 | +#define VK_NUMPAD9 0x69 | |
77 | +#define VK_MULTIPLY 0x6A | |
78 | +#define VK_ADD 0x6B | |
79 | +#define VK_SEPARATOR 0x6C | |
80 | +#define VK_SUBTRACT 0x6D | |
81 | +#define VK_DECIMAL 0x6E | |
82 | +#define VK_DIVIDE 0x6F | |
83 | +#define VK_F1 0x70 | |
84 | +#define VK_F2 0x71 | |
85 | +#define VK_F3 0x72 | |
86 | +#define VK_F4 0x73 | |
87 | +#define VK_F5 0x74 | |
88 | +#define VK_F6 0x75 | |
89 | +#define VK_F7 0x76 | |
90 | +#define VK_F8 0x77 | |
91 | +#define VK_F9 0x78 | |
92 | +#define VK_F10 0x79 | |
93 | +#define VK_F11 0x7A | |
94 | +#define VK_F12 0x7B | |
95 | +#define VK_F13 0x7C | |
96 | +#define VK_F14 0x7D | |
97 | +#define VK_F15 0x7E | |
98 | +#define VK_F16 0x7F | |
99 | +#define VK_F17 0x80 | |
100 | +#define VK_F18 0x81 | |
101 | +#define VK_F19 0x82 | |
102 | +#define VK_F20 0x83 | |
103 | +#define VK_F21 0x84 | |
104 | +#define VK_F22 0x85 | |
105 | +#define VK_F23 0x86 | |
106 | +#define VK_F24 0x87 | |
107 | +#define VK_NUMLOCK 0x90 | |
108 | +#define VK_SCROLL 0x91 | |
109 | +#define VK_LSHIFT 0xA0 | |
110 | +#define VK_RSHIFT 0xA1 | |
111 | +#define VK_LCONTROL 0xA2 | |
112 | +#define VK_RCONTROL 0xA3 | |
113 | +#define VK_LMENU 0xA4 | |
114 | +#define VK_RMENU 0xA5 | |
115 | +#define VK_BROWSER_BACK 0xA6 | |
116 | +#define VK_BROWSER_FORWARD 0xA7 | |
117 | +#define VK_BROWSER_REFRESH 0xA8 | |
118 | +#define VK_BROWSER_STOP 0xA9 | |
119 | +#define VK_BROWSER_SEARCH 0xAA | |
120 | +#define VK_BROWSER_FAVORITES 0xAB | |
121 | +#define VK_BROWSER_HOME 0xAC | |
122 | +#define VK_VOLUME_MUTE 0xAD | |
123 | +#define VK_VOLUME_DOWN 0xAE | |
124 | +#define VK_VOLUME_UP 0xAF | |
125 | +#define VK_MEDIA_NEXT_TRACK 0xB0 | |
126 | +#define VK_MEDIA_PREV_TRACK 0xB1 | |
127 | +#define VK_MEDIA_STOP 0xB2 | |
128 | +#define VK_MEDIA_PLAY_PAUSE 0xB3 | |
129 | +#define VK_LAUNCH_MAIL 0xB4 | |
130 | +#define VK_LAUNCH_MEDIA_SELECT 0xB5 | |
131 | +#define VK_LAUNCH_APP1 0xB6 | |
132 | +#define VK_LAUNCH_APP2 0xB7 | |
133 | +#define VK_OEM_1 0xBA | |
134 | +#define VK_OEM_PLUS 0xBB | |
135 | +#define VK_OEM_COMMA 0xBC | |
136 | +#define VK_OEM_MINUS 0xBD | |
137 | +#define VK_OEM_PERIOD 0xBE | |
138 | +#define VK_OEM_2 0xBF | |
139 | +#define VK_OEM_3 0xC0 | |
140 | +#define VK_OEM_4 0xDB | |
141 | +#define VK_OEM_5 0xDC | |
142 | +#define VK_OEM_6 0xDD | |
143 | +#define VK_OEM_7 0xDE | |
144 | +#define VK_OEM_8 0xDF | |
145 | +#define VK_OEM_102 0xE2 | |
146 | +#define VK_PROCESSKEY 0xE5 | |
147 | +#define VK_PACKE 0xE7 | |
148 | +#define VK_ATTN 0xF6 | |
149 | +#define VK_CRSEL 0xF7 | |
150 | +#define VK_EXSEL 0xF8 | |
151 | +#define VK_EREOF 0xF9 | |
152 | +#define VK_PLAY 0xFA | |
153 | +#define VK_ZOOM 0xFB | |
154 | +#define VK_NONAME 0xFC | |
155 | +#define VK_PA1 0xFD | |
156 | +#define VK_OEM_CLEAR 0xFE | |
157 | + | |
158 | +extern volatile unsigned char ps2keystatus[256]; // 仮想コードに相当するキーの状態(Onの時1) | |
159 | +extern volatile unsigned short vkey; //仮想キーコード | |
160 | +extern unsigned char lockkey; // 初期化時にLockキーの状態指定。下位3ビットが<CAPSLK><NUMLK><SCRLK> | |
161 | +extern unsigned char keytype; // キーボードの種類。0:日本語109キー、1:英語104キー | |
162 | + | |
163 | +//int ps2init(); // PS/2ライブラリ関連初期化。正常終了0、エラーで-1を返す | |
164 | +//unsigned char shiftkeys(); // SHIFT関連キーの押下状態を返す | |
165 | +#define shiftkeys() 0 // SHIFT関連キーの押下状態を返す | |
166 | +unsigned char ps2readkey(); | |
167 | +// 入力された1つのキーのキーコードをグローバル変数vkeyに格納(押されていなければ0を返す) | |
168 | +// 下位8ビット:キーコード | |
169 | +// 上位8ビット:シフト状態(押下:1)、上位から<0><CAPSLK><NUMLK><SCRLK><Win><ALT><CTRL><SHIFT> | |
170 | +// 英数・記号文字の場合、戻り値としてASCIIコード(それ以外は0を返す) | |
171 | + | |
172 | +// PIC32MX1xx/2xx版のキーボードとボタンの排他利用システムで使用する関数、マクロ | |
173 | +//void ps2mode(); // PS/2を有効にする | |
174 | +#define ps2mode() (0) | |
175 | +//void buttonmode(); // ボタンを有効にする | |
176 | +#define buttonmode() (0) | |
177 | +//#define inPS2MODE() ((LATA&2)>>1) // モード確認用マクロ。PS/2モードの場合1、ボタンモードの場合0を返す | |
178 | +#define inPS2MODE() (0) |
@@ -0,0 +1,130 @@ | ||
1 | +#include "LCDdriver.h" | |
2 | + | |
3 | +#if LCD_ALIGNMENT == VERTICAL | |
4 | +#define WIDTH_X1 30 // 横方向文字数1 | |
5 | +#define WIDTH_X2 40 // 横方向文字数2(6ドットフォント利用時) | |
6 | +#define WIDTH_Y 40 // 縦方向文字数 | |
7 | +#define ATTROFFSET1 (WIDTH_X1*WIDTH_Y) // VRAM上のカラーパレット格納位置1 | |
8 | +#define ATTROFFSET2 (WIDTH_X2*WIDTH_Y) // VRAM上のカラーパレット格納位置2 | |
9 | +#define G_X_RES 240 // 横方向解像度 | |
10 | +#define G_Y_RES 320 // 縦方向解像度 | |
11 | +#else | |
12 | +#define WIDTH_X1 40 // 横方向文字数1 | |
13 | +#define WIDTH_X2 52 // 横方向文字数2(6ドットフォント利用時) | |
14 | +#define WIDTH_Y 30 // 縦方向文字数 | |
15 | +#define ATTROFFSET1 (WIDTH_X1*WIDTH_Y) // VRAM上のカラーパレット格納位置1 | |
16 | +#define ATTROFFSET2 (WIDTH_X2*WIDTH_Y) // VRAM上のカラーパレット格納位置2 | |
17 | +#define G_X_RES 320 // 横方向解像度 | |
18 | +#define G_Y_RES 240 // 縦方向解像度 | |
19 | +#endif | |
20 | + | |
21 | +// 入力ボタンのポート、ビット定義 | |
22 | +#define KEYPORT PORTB | |
23 | +#define KEYDOWN 0x0004 | |
24 | +#define KEYLEFT 0x0008 | |
25 | +#define KEYRIGHT 0x0010 | |
26 | +#define KEYUP 0x0020 | |
27 | +#define KEYSTART 0x0080 | |
28 | +#define KEYFIRE 0x0100 | |
29 | +#define KEYMASK (KEYSTART | KEYFIRE | KEYUP | KEYDOWN | KEYLEFT | KEYRIGHT) | |
30 | +#define KEY_DS LATASET=0x0008 | |
31 | +#define KEY_EN LATACLR=0x0008 | |
32 | + | |
33 | +//extern volatile char drawing; // 表示期間中は-1 | |
34 | +extern volatile unsigned short drawcount; // 1画面表示終了ごとに1足す。アプリ側で0にする。 | |
35 | + // 最低1回は画面表示したことのチェックと、アプリの処理が何画面期間必要かの確認に利用。 | |
36 | +extern unsigned char TVRAM[]; //テキストビデオメモリ | |
37 | +//extern unsigned short *gVRAM; //グラフィックVRAM開始位置のポインタ | |
38 | + | |
39 | +extern const unsigned char FontData[]; //フォントパターン定義 | |
40 | +//extern const unsigned char FontData[],FontData2[]; //フォントパターン定義 | |
41 | +extern unsigned char *cursor; | |
42 | +extern unsigned char cursorcolor; | |
43 | +extern unsigned char *fontp; | |
44 | +extern unsigned char twidth; //テキスト1行文字数(30 or 40) | |
45 | +extern unsigned int bgcolor; // バックグランドカラー | |
46 | + | |
47 | +//void start_composite(void); //カラーコンポジット出力開始 | |
48 | +//void stop_composite(void); //カラーコンポジット出力停止 | |
49 | +//void init_composite(void); //カラーコンポジット出力初期化 | |
50 | +void clearscreen(void); //テキスト画面クリア | |
51 | +void set_palette(unsigned char n,unsigned char b,unsigned char r,unsigned char g); //テキストパレット設定 | |
52 | +void set_bgcolor(unsigned char b,unsigned char r,unsigned char g); //バックグランドカラー設定 | |
53 | +void set_graphmode(unsigned char m); //グラフィックモード変更 | |
54 | +void init_textgraph(void); //テキスト機能利用準備 | |
55 | +void init_graphic(void); //グラフィック機能利用準備 | |
56 | +void set_width(unsigned char m); //30文字モード(8ドットフォント)と40文字モード(6ドットフォント)の切り替え | |
57 | +void textredraw(void); | |
58 | + // テキスト画面再描画、テキストVRAMの内容にしたがって液晶に出力 | |
59 | +void vramscroll(void); | |
60 | + //1行スクロール | |
61 | +void vramscrolldown(void); | |
62 | + //1行逆スクロール | |
63 | +void setcursor(unsigned char x,unsigned char y,unsigned char c); | |
64 | + //カーソル位置とカラーを設定 | |
65 | +void setcursorcolor(unsigned char c); | |
66 | + //カーソル位置そのままでカラー番号をcに設定 | |
67 | +void printchar(unsigned char n); | |
68 | + //カーソル位置にテキストコードnを1文字表示し、カーソルを1文字進める | |
69 | +void printstr(unsigned char *s); | |
70 | + //カーソル位置に文字列sを表示 | |
71 | +void printnum(unsigned int n); | |
72 | + //カーソル位置に符号なし整数nを10進数表示 | |
73 | +void printnum2(unsigned int n,unsigned char e); | |
74 | + //カーソル位置に符号なし整数nをe桁の10進数表示(前の空き桁部分はスペースで埋める) | |
75 | +void cls(void); | |
76 | + //テキスト画面消去し、カーソルを先頭に移動 | |
77 | +void startPCG(unsigned char *p,int a); | |
78 | + // RAMフォント(PCG)の利用開始、pがフォント格納場所、aが0以外でシステムフォントをコピー | |
79 | +void stopPCG(void); | |
80 | + // RAMフォント(PCG)の利用停止 | |
81 | + | |
82 | +void g_clearscreen(void); | |
83 | +//グラフィック画面クリア | |
84 | +void g_set_palette(unsigned char n,unsigned char b,unsigned char r,unsigned char g); | |
85 | +//グラフィック用カラーパレット設定 | |
86 | + | |
87 | +void g_pset(int x,int y,unsigned int c); | |
88 | +// (x,y)の位置にカラーcで点を描画 | |
89 | + | |
90 | +void g_putbmpmn(int x,int y,char m,char n,const unsigned char bmp[]); | |
91 | +// 横m*縦nドットのキャラクターを座標x,yに表示 | |
92 | +// unsigned char bmp[m*n]配列に、単純にカラー番号を並べる | |
93 | +// カラー番号が0の部分は透明色として扱う | |
94 | + | |
95 | +void g_clrbmpmn(int x,int y,char m,char n); | |
96 | +// 縦m*横nドットのキャラクター消去 | |
97 | +// カラー0で塗りつぶし | |
98 | + | |
99 | +void g_gline(int x1,int y1,int x2,int y2,unsigned int c); | |
100 | +// (x1,y1)-(x2,y2)にカラーcで線分を描画 | |
101 | + | |
102 | +void g_hline(int x1,int x2,int y,unsigned int c); | |
103 | +// (x1,y)-(x2,y)への水平ラインを高速描画 | |
104 | + | |
105 | +void g_circle(int x0,int y0,unsigned int r,unsigned int c); | |
106 | +// (x0,y0)を中心に、半径r、カラーcの円を描画 | |
107 | + | |
108 | +void g_boxfill(int x1,int y1,int x2,int y2,unsigned int c); | |
109 | +// (x1,y1),(x2,y2)を対角線とするカラーcで塗られた長方形を描画 | |
110 | + | |
111 | +void g_circlefill(int x0,int y0,unsigned int r,unsigned int c); | |
112 | +// (x0,y0)を中心に、半径r、カラーcで塗られた円を描画 | |
113 | + | |
114 | +void g_putfont(int x,int y,unsigned int c,int bc,unsigned char n); | |
115 | +//8*8ドットのアルファベットフォント表示 | |
116 | +//座標(x,y)、カラー番号c | |
117 | +//bc:バックグランドカラー、負数の場合無視 | |
118 | +//n:文字番号 | |
119 | + | |
120 | +void g_printstr(int x,int y,unsigned int c,unsigned int bc,unsigned char *s); | |
121 | +//座標(x,y)からカラー番号cで文字列sを表示、bc:バックグランドカラー | |
122 | + | |
123 | +void g_printnum(int x,int y,unsigned int c,unsigned int bc,unsigned int n); | |
124 | +//座標(x,y)にカラー番号cで数値nを表示、bc:バックグランドカラー | |
125 | + | |
126 | +void g_printnum2(int x,int y,unsigned int c,unsigned int bc,unsigned int n,unsigned char e); | |
127 | +//座標(x,y)にカラー番号cで数値nを表示、bc:バックグランドカラー、e桁で表示 | |
128 | + | |
129 | +unsigned int g_color(int x,int y); | |
130 | +//座標(x,y)のVRAM上の現在のパレット番号を返す、画面外は0を返す |
@@ -0,0 +1,1108 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include <xc.h> | |
13 | +#include "main.h" | |
14 | +#include "compiler.h" | |
15 | +#include "api.h" | |
16 | +#include "interface/keyinput.h" | |
17 | +#include "stdlib.h" | |
18 | +#include "math.h" | |
19 | + | |
20 | +/* | |
21 | + Local global variables used for graphic | |
22 | + */ | |
23 | + | |
24 | +static int g_gcolor=7; | |
25 | +static int g_prev_x=0; | |
26 | +static int g_prev_y=0; | |
27 | + | |
28 | +int lib_setdir(int mode,char* path){ | |
29 | + int ret; | |
30 | + ret=FSchdir(path); | |
31 | + if (mode==LIB_SETDIR && ret) err_file(); | |
32 | + return ret; | |
33 | +} | |
34 | + | |
35 | +int lib_getdir(){ | |
36 | + char* path; | |
37 | + path=calloc_memory(32,-1); | |
38 | + FSgetcwd (path,128); | |
39 | + return (int)path; | |
40 | +} | |
41 | + | |
42 | +int lib_read(int mode, unsigned int label){ | |
43 | + unsigned int i,code,code2; | |
44 | + static unsigned int pos=0; | |
45 | + static unsigned int in_data=0; | |
46 | + static unsigned char skip=0; | |
47 | + if (label) { | |
48 | + // RESTORE function | |
49 | + switch(mode){ | |
50 | + case 0: | |
51 | + // label is label data | |
52 | + i=(int)search_label(label); | |
53 | + if (!i) { | |
54 | + err_data_not_found(); | |
55 | + return 0; | |
56 | + } | |
57 | + break; | |
58 | + case 1: | |
59 | + // label is pointer | |
60 | + i=label; | |
61 | + break; | |
62 | + case 2: | |
63 | + default: | |
64 | + // Reset data/read | |
65 | + pos=0; | |
66 | + in_data=0; | |
67 | + skip=0; | |
68 | + return 0; | |
69 | + } | |
70 | + i-=(int)(&g_object[0]); | |
71 | + pos=i/4; | |
72 | + in_data=0; | |
73 | + } | |
74 | + // Get data | |
75 | + if (in_data==0) { | |
76 | + for(i=pos;i<g_objpos;i++){ | |
77 | + code=g_object[i]; | |
78 | + code2=g_object[i+1]; | |
79 | + if ((code&0xFFFF0000)!=0x04110000) continue; | |
80 | + // "bgezal zero," assembly found. | |
81 | + // Check if 0x00000020,0x00000021,0x00000022, or 0x00000023 follows | |
82 | + if ((code2&0xfffffffc)!=0x00000020) {// add/addu/sub/subu zero,zero,zero | |
83 | + // If not, skip following block (it's strig). | |
84 | + i+=code&0x0000FFFF; | |
85 | + continue; | |
86 | + } | |
87 | + // DATA region found. | |
88 | + in_data=(code&0x0000FFFF)-1; | |
89 | + pos=i+2; | |
90 | + skip=code2&0x03; | |
91 | + break; | |
92 | + } | |
93 | + if (g_objpos<=i) { | |
94 | + err_data_not_found(); | |
95 | + return 0; | |
96 | + } | |
97 | + } | |
98 | + if (label) { | |
99 | + // RESTORE function. Return pointer. | |
100 | + return ((int)&g_object[pos])+skip; | |
101 | + } else { | |
102 | + switch(mode){ | |
103 | + case 0: | |
104 | + // READ() function | |
105 | + in_data--; | |
106 | + return g_object[pos++]; | |
107 | + case 1: | |
108 | + default: | |
109 | + // CREAD() function | |
110 | + i=g_object[pos]; | |
111 | + i>>=skip*8; | |
112 | + i&=0xff; | |
113 | + if ((++skip)==4) { | |
114 | + skip=0; | |
115 | + in_data--; | |
116 | + pos++; | |
117 | + } | |
118 | + return i; | |
119 | + } | |
120 | + } | |
121 | +} | |
122 | + | |
123 | +void reset_dataread(){ | |
124 | + lib_read(2,1); | |
125 | +} | |
126 | + | |
127 | +char* lib_midstr(int var_num, int pos, int len){ | |
128 | + int i; | |
129 | + char* str; | |
130 | + char* ret; | |
131 | + if (0<=pos) { | |
132 | + // String after "pos" position. | |
133 | + str=(char*)(g_var_mem[var_num]+pos); | |
134 | + } else { | |
135 | + // String right "pos" characters. | |
136 | + // Determine length | |
137 | + str=(char*)g_var_mem[var_num]; | |
138 | + for(i=0;str[i];i++); | |
139 | + if (0<=(i+pos)) { | |
140 | + str=(char*)(g_var_mem[var_num]+i+pos); | |
141 | + } | |
142 | + } | |
143 | + if (len<0) { | |
144 | + // Length is not specified. | |
145 | + // Return the string to the end. | |
146 | + return str; | |
147 | + } | |
148 | + // Length is specified. | |
149 | + // Construct temporary string containing specified number of characters. | |
150 | + ret=alloc_memory((len+1+3)/4,-1); | |
151 | + // Copy string. | |
152 | + for(i=0;(ret[i]=str[i])&&(i<len);i++); | |
153 | + ret[len]=0x00; | |
154 | + return ret; | |
155 | +} | |
156 | + | |
157 | +void lib_clear(void){ | |
158 | + int i; | |
159 | + // All variables (including temporary and permanent ones) will be integer 0 | |
160 | + for(i=0;i<ALLOC_BLOCK_NUM;i++){ | |
161 | + g_var_mem[i]=0; | |
162 | + } | |
163 | + // Clear memory allocation area | |
164 | + for(i=0;i<ALLOC_BLOCK_NUM;i++){ | |
165 | + g_var_size[i]=0; | |
166 | + } | |
167 | + // Cancel PCG | |
168 | + stopPCG(); | |
169 | + g_pcg_font=0; | |
170 | + // Stop using graphic | |
171 | + g_use_graphic=1; // Force set_graphmode(0) (see usegraphic() function) | |
172 | + usegraphic(0); | |
173 | +} | |
174 | + | |
175 | +void lib_let_str(char* str, int var_num){ | |
176 | + int begin,end,size; | |
177 | + // Save pointer | |
178 | + g_var_mem[var_num]=(int)str; | |
179 | + // Determine size | |
180 | + for(size=0;str[size];size++); | |
181 | + // Check if str is in heap area. | |
182 | + begin=(int)str; | |
183 | + end=(int)(&str[size]); | |
184 | + if (begin<(int)(&g_heap_mem[0]) || (int)(&g_heap_mem[g_max_mem])<=end) { | |
185 | + // String is not within allcated block | |
186 | + return; | |
187 | + } | |
188 | + // Str is in heap area. Calculate values stored in heap data dimension | |
189 | + begin-=(int)(&g_heap_mem[0]); | |
190 | + begin>>=2; | |
191 | + end-=(int)(&g_heap_mem[0]); | |
192 | + end>>=2; | |
193 | + size=end-begin+1; | |
194 | + g_var_pointer[var_num]=begin; | |
195 | + g_var_size[var_num]=size; | |
196 | +} | |
197 | + | |
198 | +int lib_rnd(){ | |
199 | + int y; | |
200 | + y=g_rnd_seed; | |
201 | + y = y ^ (y << 13); | |
202 | + y = y ^ (y >> 17); | |
203 | + y = y ^ (y << 5); | |
204 | + g_rnd_seed=y; | |
205 | + return y&0x7fff; | |
206 | +} | |
207 | + | |
208 | +char* lib_chr(int num){ | |
209 | + char* str; | |
210 | + str=alloc_memory(1,-1); | |
211 | + str[0]=num&0x000000FF; | |
212 | + str[1]=0x00; | |
213 | + return str; | |
214 | +} | |
215 | + | |
216 | +char* lib_dec(int num){ | |
217 | + char* str; | |
218 | + int i,j,minus; | |
219 | + char b[12]; | |
220 | + b[11]=0x00; | |
221 | + if (num<0) { | |
222 | + minus=1; | |
223 | + num=0-num; | |
224 | + } else { | |
225 | + minus=0; | |
226 | + } | |
227 | + for (i=10;0<i;i--) { | |
228 | + if (num==0 && i<10) break; | |
229 | + b[i]='0'+rem10_32(num); | |
230 | + num=div10_32(num); | |
231 | + } | |
232 | + if (minus) { | |
233 | + b[i]='-'; | |
234 | + } else { | |
235 | + i++; | |
236 | + } | |
237 | + str=alloc_memory(3,-1); | |
238 | + for(j=0;str[j]=b[i++];j++); | |
239 | + return str; | |
240 | +} | |
241 | + | |
242 | +char* lib_hex(int num, int width){ | |
243 | + char* str; | |
244 | + int i,j,minus; | |
245 | + char b[8]; | |
246 | + str=alloc_memory(3,-1); | |
247 | + for(i=0;i<8;i++){ | |
248 | + b[i]="0123456789ABCDEF"[(num>>(i<<2))&0x0F]; | |
249 | + } | |
250 | + // Width must be between 0 and 8; | |
251 | + if (width<0||8<width) width=8; | |
252 | + if (width==0) { | |
253 | + // Width not asigned. Use minimum width. | |
254 | + for(i=7;0<i;i--){ | |
255 | + if ('0'<b[i]) break; | |
256 | + } | |
257 | + } else { | |
258 | + // Constant width | |
259 | + i=width-1; | |
260 | + } | |
261 | + // Copy string to allocated block. | |
262 | + for(j=0;0<=i;i--){ | |
263 | + str[j++]=b[i]; | |
264 | + } | |
265 | + str[j]=0x00; | |
266 | + return str; | |
267 | +} | |
268 | + | |
269 | +char* lib_connect_string(char* str1, char* str2){ | |
270 | + int i,j; | |
271 | + char b; | |
272 | + char* result; | |
273 | + // Determine total length | |
274 | + for(i=0;str1[i];i++); | |
275 | + for(j=0;str2[j];j++); | |
276 | + // Allocate a block for new string | |
277 | + result=alloc_memory((i+j+1+3)/4,-1); | |
278 | + // Create connected strings | |
279 | + for(i=0;b=str1[i];i++) result[i]=b; | |
280 | + for(j=0;b=str2[j];j++) result[i+j]=b; | |
281 | + result[i+j]=0x00; | |
282 | + free_temp_str(str1); | |
283 | + free_temp_str(str2); | |
284 | + return result; | |
285 | +} | |
286 | + | |
287 | +void lib_string(int mode){ | |
288 | + int i; | |
289 | + switch(mode){ | |
290 | + case 0: | |
291 | + // CR | |
292 | + printchar('\n'); | |
293 | + return; | |
294 | + case 1: | |
295 | + // , | |
296 | + printcomma(); | |
297 | + return; | |
298 | + default: | |
299 | + return; | |
300 | + } | |
301 | +} | |
302 | + | |
303 | +void* lib_label(unsigned int label){ | |
304 | + // This routine is used to jump to address dynamically determined | |
305 | + // in the code; for example: "GOTO 100+I" | |
306 | + unsigned int i,code,search; | |
307 | + void* ret; | |
308 | + if (label&0xFFFF0000) { | |
309 | + // Label is not supported. | |
310 | + // Line number must bs less than 65536. | |
311 | + err_label_not_found(); | |
312 | + } else { | |
313 | + // Line number | |
314 | + ret=search_label(label); | |
315 | + if (ret) return ret; | |
316 | + // Line number not found. | |
317 | + err_label_not_found(); | |
318 | + } | |
319 | +} | |
320 | + | |
321 | +int lib_keys(int mask){ | |
322 | + int keys; | |
323 | + keys=readbuttons(); | |
324 | + keys= | |
325 | + ((keys&KEYUP)? 0:1)| | |
326 | + ((keys&KEYDOWN)? 0:2)| | |
327 | + ((keys&KEYLEFT)? 0:4)| | |
328 | + ((keys&KEYRIGHT)? 0:8)| | |
329 | + ((keys&KEYSTART)? 0:16)| | |
330 | + ((keys&KEYFIRE)? 0:32); | |
331 | + return mask&keys; | |
332 | +} | |
333 | + | |
334 | +int lib_val(char* str){ | |
335 | + int i; | |
336 | + int val=0; | |
337 | + int sign=1; | |
338 | + char b; | |
339 | + // Skip blanc | |
340 | + for(i=0;0<=str[i] && str[i]<0x21;i++); | |
341 | + // Skip '+' | |
342 | + if (str[i]=='+') i++; | |
343 | + // Check '-' | |
344 | + if (str[i]=='-') { | |
345 | + sign=-1; | |
346 | + i++; | |
347 | + } | |
348 | + // Check '0x' or '$' | |
349 | + if (str[i]=='$' || str[i]=='0' && (str[i+1]=='x' || str[i+1]=='X')) { | |
350 | + // Hexadecimal | |
351 | + if (str[i++]=='0') i++; | |
352 | + while(1) { | |
353 | + b=str[i++]; | |
354 | + if ('0'<=b && b<='9') { | |
355 | + val<<=4; | |
356 | + val+=b-'0'; | |
357 | + } else if ('a'<=b && b<='f') { | |
358 | + val<<=4; | |
359 | + val+=b-'a'+10; | |
360 | + } else if ('A'<=b && b<='F') { | |
361 | + val<<=4; | |
362 | + val+=b-'A'+10; | |
363 | + } else { | |
364 | + break; | |
365 | + } | |
366 | + } | |
367 | + } else { | |
368 | + // Decimal | |
369 | + while(1) { | |
370 | + b=str[i++]; | |
371 | + if ('0'<=b && b<='9') { | |
372 | + val*=10; | |
373 | + val+=b-'0'; | |
374 | + } else { | |
375 | + break; | |
376 | + } | |
377 | + } | |
378 | + } | |
379 | + return val*sign; | |
380 | +} | |
381 | + | |
382 | +char* lib_input(){ | |
383 | + // Allocate memory for strings with 63 characters | |
384 | + char *str=calloc_memory((63+1)/4,-1); | |
385 | + // Enable PS/2 keyboard | |
386 | + if (!inPS2MODE()) { | |
387 | + ps2mode(); | |
388 | + ps2init(); | |
389 | + } | |
390 | + // Clear key buffer | |
391 | + do ps2readkey(); | |
392 | + while(vkey!=0); | |
393 | + // Get string as a line | |
394 | + lineinput(str,63); | |
395 | + check_break(); | |
396 | + return str; | |
397 | +} | |
398 | + | |
399 | +unsigned char lib_inkey(int key){ | |
400 | + int i; | |
401 | + // Enable PS/2 keyboard | |
402 | + if (!inPS2MODE()) { | |
403 | + ps2mode(); | |
404 | + ps2init(); | |
405 | + } | |
406 | + if (key) { | |
407 | + return ps2keystatus[key&0xff]; | |
408 | + } else { | |
409 | + for(i=0;i<256;i++){ | |
410 | + if (ps2keystatus[i]) return i; | |
411 | + } | |
412 | + return 0; | |
413 | + } | |
414 | +} | |
415 | + | |
416 | +void lib_usepcg(int mode){ | |
417 | + // Modes; 0: stop PCG, 1: use PCG, 2: reset PCG and use it | |
418 | + switch(mode){ | |
419 | + case 0: | |
420 | + // Stop PCG | |
421 | + stopPCG(); | |
422 | + break; | |
423 | + case 2: | |
424 | + // Reset PCG and use it | |
425 | + if (g_pcg_font) { | |
426 | + free_non_temp_str(g_pcg_font); | |
427 | + g_pcg_font=0; | |
428 | + } | |
429 | + // Continue to case 1: | |
430 | + case 1: | |
431 | + default: | |
432 | + // Use PCG | |
433 | + if (g_pcg_font) { | |
434 | + startPCG(g_pcg_font,0); | |
435 | + } else { | |
436 | + g_pcg_font=alloc_memory(256*8/4,ALLOC_PCG_BLOCK); | |
437 | + startPCG(g_pcg_font,1); | |
438 | + } | |
439 | + break; | |
440 | + } | |
441 | +} | |
442 | + | |
443 | +void lib_pcg(unsigned int ascii,unsigned int fontdata1,unsigned int fontdata2){ | |
444 | + unsigned int* pcg; | |
445 | + // If USEPCG has not yet executed, do now. | |
446 | + if (!g_pcg_font) lib_usepcg(1); | |
447 | + pcg=(unsigned int*)g_pcg_font; | |
448 | + // 0 <= ascii <= 0xff | |
449 | + ascii&=0xff; | |
450 | + // Update font data | |
451 | + ascii<<=1; | |
452 | + pcg[ascii]=(fontdata1>>24)|((fontdata1&0xff0000)>>8)|((fontdata1&0xff00)<<8)|(fontdata1<<24); | |
453 | + pcg[ascii+1]=(fontdata2>>24)|((fontdata2&0xff0000)>>8)|((fontdata2&0xff00)<<8)|(fontdata2<<24); | |
454 | +} | |
455 | + | |
456 | +void lib_usegraphic(int mode){ | |
457 | + usegraphic(mode); | |
458 | + // Move current point to (0,0) | |
459 | + g_prev_x=g_prev_y=0; | |
460 | +} | |
461 | +void lib_wait(int period){ | |
462 | + int i; | |
463 | + unsigned short dcount; | |
464 | + for(i=0;i<period;i++){ | |
465 | + dcount=drawcount; | |
466 | + while(dcount==drawcount){ | |
467 | + asm (WAIT); | |
468 | + check_break(); | |
469 | + } | |
470 | + } | |
471 | +} | |
472 | + | |
473 | +int lib_graphic(int v0,enum functions func){ | |
474 | + unsigned char b; | |
475 | + int x1=g_libparams[1]; | |
476 | + int y1=g_libparams[2]; | |
477 | + int x2=g_libparams[3]; | |
478 | + int y2=g_libparams[4]; | |
479 | + // Disable if graphic area is not defined. | |
480 | + if (!g_graphic_area) return; | |
481 | + // If C is omitted in parameters, use current color. | |
482 | + if (v0==-1) { | |
483 | + v0=g_gcolor; | |
484 | + } | |
485 | + // If X1 or Y1 is 0x80000000, use the previous values. | |
486 | + if (x1==0x80000000) x1=g_prev_x; | |
487 | + if (y1==0x80000000) y1=g_prev_y; | |
488 | + switch(func){ | |
489 | + case FUNC_POINT:// X1,Y1 | |
490 | + g_prev_x=x1; | |
491 | + g_prev_y=y1; | |
492 | + break; | |
493 | + case FUNC_PSET:// X1,Y1[,C] | |
494 | + g_pset(x1,y1,v0); | |
495 | + g_prev_x=x1; | |
496 | + g_prev_y=y1; | |
497 | + break; | |
498 | + case FUNC_LINE:// X1,Y1,X2,Y2[,C] | |
499 | + if (y1==y2) g_hline(x1,x2,y1,v0); | |
500 | + else g_gline(x1,y1,x2,y2,v0); | |
501 | + g_prev_x=x2; | |
502 | + g_prev_y=y2; | |
503 | + break; | |
504 | + case FUNC_BOXFILL:// X1,Y1,X2,Y2[,C] | |
505 | + g_boxfill(x1,y1,x2,y2,v0); | |
506 | + g_prev_x=x2; | |
507 | + g_prev_y=y2; | |
508 | + break; | |
509 | + case FUNC_CIRCLE:// X1,Y1,R[,C] | |
510 | + g_circle(x1,y1,x2,v0); | |
511 | + g_prev_x=x1; | |
512 | + g_prev_y=y1; | |
513 | + break; | |
514 | + case FUNC_CIRCLEFILL:// X1,Y1,R[,C] | |
515 | + g_circlefill(x1,y1,x2,v0); | |
516 | + g_prev_x=x1; | |
517 | + g_prev_y=y1; | |
518 | + break; | |
519 | + case FUNC_GPRINT:// X1,Y1,C,BC,S$ | |
520 | + g_printstr(x1,y1,x2,y2,(unsigned char*)v0); | |
521 | + // Move current X,Y according to the string | |
522 | + while(b=((unsigned char*)v0)[0]){ | |
523 | + v0++; | |
524 | + if (b==0x0d) { | |
525 | + x1=0; | |
526 | + y1+=8; | |
527 | + } else { | |
528 | + x1+=8; | |
529 | + } | |
530 | + } | |
531 | + g_prev_x=x1; | |
532 | + g_prev_y=y1; | |
533 | + break; | |
534 | + case FUNC_PUTBMP2:// X1,Y1,M,N,BMP(label) | |
535 | + // Search CDATA | |
536 | + // It starts from either 0x00000020,0x00000021,0x00000022, or 0x00000023. | |
537 | + while((((unsigned int*)v0)[0]&0xfffffffc)!=0x00000020) v0+=4; | |
538 | + // CDATA starts from next word. | |
539 | + // MLB 3 bytes show skip byte(s). | |
540 | + v0+=4+(((unsigned int*)v0)[0]&0x03); | |
541 | + // Contunue to FUNC_PUTBMP. | |
542 | + case FUNC_PUTBMP:// X1,Y1,M,N,BMP(pointer) | |
543 | + g_putbmpmn(x1,y1,x2,y2,(const unsigned char*)v0); | |
544 | + g_prev_x=x1; | |
545 | + g_prev_y=y1; | |
546 | + break; | |
547 | + case FUNC_GCOLOR:// (X1,Y1) | |
548 | + v0=g_color(x1,y1); | |
549 | + break; | |
550 | + default: | |
551 | + break; | |
552 | + } | |
553 | + return v0; | |
554 | +} | |
555 | + | |
556 | +void lib_var_push(int a0, int a1, int* sp){ | |
557 | + // Note that sp[1] is used for string return address | |
558 | + // sp[2] can be used to store flags | |
559 | + // sp[3] etc can be used to store variable values | |
560 | + int i,params; | |
561 | + unsigned char varnum; | |
562 | + unsigned int strflags=0; | |
563 | + int stack=3; | |
564 | + for(i=0;i<8;i++){ | |
565 | + // Prepare parameter | |
566 | + switch(i){ | |
567 | + case 0: | |
568 | + params=a0; | |
569 | + break; | |
570 | + case 4: | |
571 | + params=a1; | |
572 | + break; | |
573 | + default: | |
574 | + break; | |
575 | + } | |
576 | + // Get variable number | |
577 | + varnum=params&0xff; | |
578 | + params>>=8; | |
579 | + if (varnum==0) break; // No more variable. End the loop. | |
580 | + varnum--; | |
581 | + sp[stack++]=g_var_mem[varnum]; | |
582 | + if (g_var_size[varnum] && g_var_mem[varnum]==(int)(&g_var_pointer[varnum])) { | |
583 | + // strflags change using varnum | |
584 | + strflags|=1<<i; | |
585 | + // Copy to VAR_BLOCK | |
586 | + move_to_perm_block(varnum); | |
587 | + } | |
588 | + // Clear variable | |
589 | + g_var_mem[varnum]=0; | |
590 | + } | |
591 | + // Store string flags | |
592 | + sp[2]=strflags; | |
593 | +} | |
594 | + | |
595 | +void lib_var_pop(int a0, int a1, int* sp){ | |
596 | + // Note that sp is 4 bytes larger than that in lib_var_push | |
597 | + // sp[1] was used to store flags | |
598 | + // sp[2] etc can be used to store variable values | |
599 | + int i,params; | |
600 | + unsigned char varnum; | |
601 | + int stack=2; | |
602 | + unsigned int strflags=sp[1]; | |
603 | + for(i=0;i<8;i++){ | |
604 | + // Prepare parameter | |
605 | + switch(i){ | |
606 | + case 0: | |
607 | + params=a0; | |
608 | + break; | |
609 | + case 4: | |
610 | + params=a1; | |
611 | + break; | |
612 | + default: | |
613 | + break; | |
614 | + } | |
615 | + // Get variable number | |
616 | + varnum=params&0xff; | |
617 | + params>>=8; | |
618 | + if (varnum==0) break; // No more variable. End the loop. | |
619 | + varnum--; | |
620 | + g_var_mem[varnum]=sp[stack++]; | |
621 | + if (strflags&(1<<i)) { | |
622 | + // Restore from VAR_BLOCK | |
623 | + move_from_perm_block(varnum); | |
624 | + } | |
625 | + } | |
626 | +} | |
627 | + | |
628 | + | |
629 | +char* lib_sprintf(char* format, int data){ | |
630 | + char* str; | |
631 | + int i; | |
632 | + char temp[4]; | |
633 | + if (!format) format="%g"; | |
634 | + i=snprintf((char*)(&temp[0]),4,format,data)+1; | |
635 | + str=alloc_memory((i+3)/4,-1); | |
636 | + snprintf(str,i,format,data); | |
637 | + return str; | |
638 | +} | |
639 | + | |
640 | +int lib_floatfuncs(int ia0,int iv0,enum functions a1){ | |
641 | + volatile float a0,v0; | |
642 | + ((int*)(&a0))[0]=ia0; | |
643 | + ((int*)(&v0))[0]=iv0; | |
644 | + switch(a1){ | |
645 | + case FUNC_FLOAT: | |
646 | + v0=(float)iv0; | |
647 | + break; | |
648 | + case FUNC_INT: | |
649 | + return (int)v0; | |
650 | + case FUNC_VALSHARP: | |
651 | + v0=strtof((const char*)iv0,0); | |
652 | + break; | |
653 | + case FUNC_SIN: | |
654 | + v0=sinf(v0); | |
655 | + break; | |
656 | + case FUNC_COS: | |
657 | + v0=cosf(v0); | |
658 | + break; | |
659 | + case FUNC_TAN: | |
660 | + v0=tanf(v0); | |
661 | + break; | |
662 | + case FUNC_ASIN: | |
663 | + v0=asinf(v0); | |
664 | + break; | |
665 | + case FUNC_ACOS: | |
666 | + v0=acosf(v0); | |
667 | + break; | |
668 | + case FUNC_ATAN: | |
669 | + v0=atanf(v0); | |
670 | + break; | |
671 | + case FUNC_ATAN2: | |
672 | + v0=atan2f(v0,a0); | |
673 | + break; | |
674 | + case FUNC_SINH: | |
675 | + v0=sinhf(v0); | |
676 | + break; | |
677 | + case FUNC_COSH: | |
678 | + v0=coshf(v0); | |
679 | + break; | |
680 | + case FUNC_TANH: | |
681 | + v0=tanhf(v0); | |
682 | + break; | |
683 | + case FUNC_EXP: | |
684 | + v0=expf(v0); | |
685 | + break; | |
686 | + case FUNC_LOG: | |
687 | + v0=logf(v0); | |
688 | + break; | |
689 | + case FUNC_LOG10: | |
690 | + v0=log10f(v0); | |
691 | + break; | |
692 | + case FUNC_POW: | |
693 | + v0=powf(v0,a0); | |
694 | + break; | |
695 | + case FUNC_SQRT: | |
696 | + v0=sqrtf(v0); | |
697 | + break; | |
698 | + case FUNC_CEIL: | |
699 | + v0=ceilf(v0); | |
700 | + break; | |
701 | + case FUNC_FLOOR: | |
702 | + v0=floorf(v0); | |
703 | + break; | |
704 | + case FUNC_FABS: | |
705 | + v0=fabsf(v0); | |
706 | + break; | |
707 | + case FUNC_MODF: | |
708 | + v0=modff(v0,(void*)&a0); | |
709 | + break; | |
710 | + case FUNC_FMOD: | |
711 | + v0=fmodf(v0,a0); | |
712 | + break; | |
713 | + default: | |
714 | + err_unknown(); | |
715 | + break; | |
716 | + } | |
717 | + return ((int*)(&v0))[0]; | |
718 | +}; | |
719 | + | |
720 | +int* lib_dim(int varnum, int argsnum, int* sp){ | |
721 | + int i,j; | |
722 | + static int* heap; | |
723 | + // Calculate total length. | |
724 | + int len=0; // Total length | |
725 | + int size=1; // Size of current block | |
726 | + for(i=1;i<=argsnum;i++){ | |
727 | + size*=sp[i]+1; | |
728 | + len+=size; | |
729 | + } | |
730 | + // Allocate memory | |
731 | + heap=calloc_memory(len,varnum); | |
732 | + // Construct pointers | |
733 | + len=0; | |
734 | + size=1; | |
735 | + for(i=1;i<argsnum;i++){ | |
736 | + size*=sp[i]+1; | |
737 | + for(j=0;j<size;j++){ | |
738 | + heap[len+j]=(int)&heap[len+size+(sp[i+1]+1)*j]; | |
739 | + } | |
740 | + len+=size; | |
741 | + } | |
742 | + return heap; | |
743 | +}; | |
744 | + | |
745 | +int lib_file_textlen(FSFILE* fhandle){ | |
746 | + char buff[128]; | |
747 | + int i,textlen,len,seek; | |
748 | + seek=FSftell(fhandle); | |
749 | + len=FSfread(&buff[0],1,128,fhandle); | |
750 | + textlen=0; | |
751 | + for(i=0;i<len-1;i++){ // Read 127 bytes for supporting CRLF | |
752 | + if (buff[i]==0x0d) { | |
753 | + if (i<len && buff[i+1]==0x0a) i++; | |
754 | + break; | |
755 | + } else if (buff[i]==0x0a) { | |
756 | + break; | |
757 | + } | |
758 | + if (i==len-2) { | |
759 | + // reached the end of buffer. Read next 127 bytes | |
760 | + textlen+=127; | |
761 | + buff[0]=buff[127]; | |
762 | + len=FSfread(&buff[1],1,127,fhandle); | |
763 | + // Continue with i=0 | |
764 | + i=-1; | |
765 | + } | |
766 | + } | |
767 | + // The last return code must be included to caluclate total length. | |
768 | + textlen+=i+1; | |
769 | + // Return to original position | |
770 | + FSfseek(fhandle,seek,SEEK_SET); | |
771 | + return textlen; | |
772 | +} | |
773 | + | |
774 | +int lib_file(enum functions func, int a0, int a1, int v0){ | |
775 | + static FSFILE* s_fhandle[2]={0,0}; | |
776 | + static char activefhandle=0; | |
777 | + static int numinline=0; | |
778 | + FSFILE* fhandle=0; | |
779 | + int i; | |
780 | + int buff[1]; | |
781 | + char* str; | |
782 | + if (activefhandle) fhandle=s_fhandle[activefhandle-1]; | |
783 | + switch(func){ | |
784 | + case FUNC_FINIT: | |
785 | + // This function is not BASIC statement/function but used from | |
786 | + // running routine. | |
787 | + for(i=0;i<2;i++){ | |
788 | + if (s_fhandle[i]) FSfclose(s_fhandle[i]); | |
789 | + s_fhandle[i]=0; | |
790 | + } | |
791 | + activefhandle=0; | |
792 | + numinline=0; | |
793 | + break; | |
794 | + case FUNC_FOPEN: // Return 0 when called as a function. | |
795 | + case FUNC_FOPENST: // Stop with error when called as a statement. | |
796 | + activefhandle=0; | |
797 | + // Check if file handle is free to use, first. | |
798 | + switch(v0){ | |
799 | + case 0: | |
800 | + // File handle was not designated | |
801 | + // Force handle=1 and continue to following cases. | |
802 | + v0=1; | |
803 | + case 1: | |
804 | + case 2: | |
805 | + // File handle was designated | |
806 | + // Check if not used yet. | |
807 | + if (s_fhandle[v0-1]) { | |
808 | + // This file handle has been occupied. | |
809 | + err_file(); | |
810 | + return 0; | |
811 | + } | |
812 | + // OK. This file handle can be asigned for new file opened. | |
813 | + break; | |
814 | + default: | |
815 | + err_invalid_param(); | |
816 | + return 0; | |
817 | + } | |
818 | + // Open a file | |
819 | + fhandle=FSfopen ((const char*) a0, (const char*) a1); | |
820 | + if (!fhandle) { | |
821 | + if (func==FUNC_FOPENST) err_file(); | |
822 | + return 0; | |
823 | + } | |
824 | + // The file is succesfully opened. Asign file handle. | |
825 | + s_fhandle[v0-1]=fhandle; | |
826 | + activefhandle=v0; | |
827 | + return v0; | |
828 | + case FUNC_FILE: | |
829 | + switch(v0){ | |
830 | + case 1: | |
831 | + case 2: | |
832 | + if (s_fhandle[v0]) { | |
833 | + activefhandle=v0; | |
834 | + break; | |
835 | + } | |
836 | + default: | |
837 | + err_invalid_param(); | |
838 | + } | |
839 | + break; | |
840 | + case FUNC_FCLOSE: | |
841 | + switch(v0){ | |
842 | + case 0: | |
843 | + break; | |
844 | + case 1: | |
845 | + case 2: | |
846 | + if (s_fhandle[v0-1]) activefhandle=v0; | |
847 | + if (activefhandle) fhandle=s_fhandle[activefhandle-1]; | |
848 | + break; | |
849 | + default: | |
850 | + err_invalid_param(); | |
851 | + } | |
852 | + if (fhandle) { | |
853 | + FSfclose(fhandle); | |
854 | + s_fhandle[activefhandle-1]=0; | |
855 | + } | |
856 | + activefhandle=0; | |
857 | + break; | |
858 | + case FUNC_FINPUT: | |
859 | + if (fhandle) { | |
860 | + // Determine text length if called without parameter | |
861 | + if (v0==0) v0=lib_file_textlen(fhandle); | |
862 | + // Allocate temporary area for string | |
863 | + str=alloc_memory((v0+1+3)/4,-1); | |
864 | + // Read from SD card | |
865 | + v0=FSfread(str,1,v0,fhandle); | |
866 | + // Null string at the end. | |
867 | + str[v0]=0; | |
868 | + return (int)str; | |
869 | + } else { | |
870 | + err_file(); | |
871 | + return (int)""; | |
872 | + } | |
873 | + case FUNC_FPRINTSTR: | |
874 | + // Like lib_printstr() | |
875 | + for(i=0;((char*)v0)[i];i++); | |
876 | + if (fhandle) { | |
877 | + if (!FSfwrite((char*)v0,1,i,fhandle)) err_file(); | |
878 | + } else err_file(); | |
879 | + numinline+=i; | |
880 | + break; | |
881 | + case FUNC_FSTRING: | |
882 | + // Like lib_string() | |
883 | + switch(v0){ | |
884 | + case 0: | |
885 | + // CR | |
886 | + lib_file(FUNC_FPRINTSTR,a0,a1,(int)"\r\n"); | |
887 | + numinline=0; | |
888 | + break; | |
889 | + case 1: | |
890 | + // , | |
891 | + i=rem10_32(numinline); | |
892 | + lib_file(FUNC_FPRINTSTR,a0,a1,(int)(" "+i)); | |
893 | + break; | |
894 | + default: | |
895 | + break; | |
896 | + } | |
897 | + break; | |
898 | + case FUNC_FGET: | |
899 | + if (fhandle) return FSfread((void*)a0,1,v0,fhandle); | |
900 | + err_file(); | |
901 | + break; | |
902 | + case FUNC_FPUT: | |
903 | + if (fhandle) return FSfwrite((void*)a0,1,v0,fhandle); | |
904 | + err_file(); | |
905 | + break; | |
906 | + case FUNC_FGETC: | |
907 | + if (fhandle) { | |
908 | + // Note: Little endian. | |
909 | + if (FSfread((void*)&buff[0],1,1,fhandle)) return buff[0]&0xff; | |
910 | + else return -1; | |
911 | + } | |
912 | + err_file(); | |
913 | + break; | |
914 | + case FUNC_FPUTC: | |
915 | + if (fhandle) { | |
916 | + // Note: Little endian. | |
917 | + buff[0]=v0; | |
918 | + return FSfwrite((void*)&buff[0],1,1,fhandle); | |
919 | + } | |
920 | + err_file(); | |
921 | + break; | |
922 | + case FUNC_FSEEK: | |
923 | + if (fhandle) return FSfseek(fhandle,v0,SEEK_SET); | |
924 | + err_file(); | |
925 | + break; | |
926 | + case FUNC_FTELL: | |
927 | + if (fhandle) return FSftell(fhandle); | |
928 | + err_file(); | |
929 | + break; | |
930 | + case FUNC_FLEN: | |
931 | + if (fhandle) return fhandle->size; | |
932 | + err_file(); | |
933 | + break; | |
934 | + case FUNC_FEOF: | |
935 | + if (fhandle) return (fhandle->size<=FSftell(fhandle)) ? 1:0; | |
936 | + err_file(); | |
937 | + break; | |
938 | + case FUNC_FREMOVE: | |
939 | + return FSremove((const char *)v0); | |
940 | + default: | |
941 | + err_unknown(); | |
942 | + } | |
943 | + return v0; | |
944 | +} | |
945 | + | |
946 | +int _call_library(int a0,int a1,int a2,enum libs a3); | |
947 | + | |
948 | +void call_library(void){ | |
949 | + // Store s6 in g_s6 | |
950 | + asm volatile("la $a2,%0"::"i"(&g_s6)); | |
951 | + asm volatile("sw $s6,0($a2)"); | |
952 | + // Copy $v0 to $a2 as 3rd argument of function | |
953 | + asm volatile("addu $a2,$v0,$zero"); | |
954 | + // Store sp in g_libparams | |
955 | + asm volatile("la $v0,%0"::"i"(&g_libparams)); | |
956 | + asm volatile("sw $sp,0($v0)"); | |
957 | + // Jump to main routine | |
958 | + asm volatile("j _call_library"); | |
959 | +} | |
960 | + | |
961 | +int _call_library(int a0,int a1,int v0,enum libs a3){ | |
962 | + // usage: call_lib_code(LIB_XXXX); | |
963 | + // Above code takes 2 words. | |
964 | + check_break(); | |
965 | + switch(a3 & LIB_MASK){ | |
966 | + case LIB_FLOAT: | |
967 | + return lib_float(a0,v0,(enum operator)(a3 & OP_MASK)); // see operator.c | |
968 | + case LIB_FLOATFUNCS: | |
969 | + return lib_floatfuncs(a0,v0,(enum functions)(a3 & FUNC_MASK)); | |
970 | + case LIB_STRNCMP: | |
971 | + return strncmp((char*)g_libparams[1],(char*)g_libparams[2],v0); | |
972 | + case LIB_MIDSTR: | |
973 | + return (int)lib_midstr(a1,v0,a0); | |
974 | + case LIB_RND: | |
975 | + return (int)lib_rnd(); | |
976 | + case LIB_DEC: | |
977 | + return (int)lib_dec(v0); | |
978 | + case LIB_HEX: | |
979 | + return (int)lib_hex(v0,a0); | |
980 | + case LIB_CHR: | |
981 | + return (int)lib_chr(v0); | |
982 | + case LIB_VAL: | |
983 | + return lib_val((char*)v0); | |
984 | + case LIB_LETSTR: | |
985 | + lib_let_str((char*)v0,a0); | |
986 | + return; | |
987 | + case LIB_CONNECT_STRING: | |
988 | + return (int)lib_connect_string((char*)a0, (char*)v0); | |
989 | + case LIB_STRING: | |
990 | + lib_string(v0); | |
991 | + return v0; | |
992 | + case LIB_PRINTSTR: | |
993 | + printstr((char*)v0); | |
994 | + return v0; | |
995 | + case LIB_GRAPHIC: | |
996 | + return lib_graphic(v0, (enum functions)(a3 & FUNC_MASK)); | |
997 | + case LIB_SPRINTF: | |
998 | + return (int)lib_sprintf((char*)v0,a0); | |
999 | + case LIB_VAR_PUSH: | |
1000 | + lib_var_push(a0,a1,g_libparams); | |
1001 | + return v0; | |
1002 | + case LIB_VAR_POP: | |
1003 | + lib_var_pop(a0,a1,g_libparams); | |
1004 | + return v0; | |
1005 | + case LIB_SCROLL: | |
1006 | + scroll(g_libparams[1],v0); | |
1007 | + return v0; | |
1008 | + case LIB_FILE: | |
1009 | + return lib_file((enum functions)(a3 & FUNC_MASK),g_libparams[1],g_libparams[2],v0); | |
1010 | + case LIB_KEYS: | |
1011 | + return lib_keys(v0); | |
1012 | + case LIB_INKEY: | |
1013 | + return (int)lib_inkey(v0); | |
1014 | + case LIB_CURSOR: | |
1015 | + setcursor(g_libparams[1],v0,cursorcolor); | |
1016 | + return v0; | |
1017 | + case LIB_SOUND: | |
1018 | + set_sound((unsigned long*)v0,a0); | |
1019 | + return v0; | |
1020 | + case LIB_MUSICFUNC: | |
1021 | + return musicRemaining(a0); | |
1022 | + case LIB_MUSIC: | |
1023 | + set_music((char*)v0,a0); | |
1024 | + return v0; | |
1025 | + case LIB_PLAYWAVE: | |
1026 | + play_wave((char*)g_libparams[1],v0); | |
1027 | + return v0; | |
1028 | + case LIB_PLAYWAVEFUNC: | |
1029 | + return waveRemaining(v0); | |
1030 | + case LIB_SETDRAWCOUNT: | |
1031 | + drawcount=(v0&0x0000FFFF); | |
1032 | + return v0; | |
1033 | + case LIB_GETDIR: | |
1034 | + return lib_getdir(); | |
1035 | + case LIB_SETDIRFUNC: | |
1036 | + case LIB_SETDIR: | |
1037 | + return lib_setdir(a3,(char*)v0); | |
1038 | + case LIB_DRAWCOUNT: | |
1039 | + return drawcount; | |
1040 | + case LIB_SYSTEM: | |
1041 | + return lib_system(a0, a1 ,v0, a3, g_gcolor, g_prev_x, g_prev_y); | |
1042 | + case LIB_RESTORE: | |
1043 | + return lib_read(0,v0); | |
1044 | + case LIB_RESTORE2: | |
1045 | + return lib_read(1,v0); | |
1046 | + case LIB_READ: | |
1047 | + return lib_read(0,0); | |
1048 | + case LIB_CREAD: | |
1049 | + return lib_read(1,0); | |
1050 | + case LIB_LABEL: | |
1051 | + return (int)lib_label(v0); | |
1052 | + case LIB_INPUT: | |
1053 | + return (int)lib_input(); | |
1054 | + case LIB_USEGRAPHIC: | |
1055 | + lib_usegraphic(v0); | |
1056 | + return v0; | |
1057 | + case LIB_USEPCG: | |
1058 | + lib_usepcg(v0); | |
1059 | + return v0; | |
1060 | + case LIB_PCG: | |
1061 | + lib_pcg(g_libparams[1],g_libparams[2],v0); | |
1062 | + return v0; | |
1063 | + case LIB_BGCOLOR: // BGCOLOR R,G,B | |
1064 | + set_bgcolor(v0,g_libparams[1],g_libparams[2]); //set_bgcolor(b,r,g); | |
1065 | + return v0; | |
1066 | + case LIB_PALETTE: // PALETTE N,R,G,B | |
1067 | + set_palette(g_libparams[1],v0,g_libparams[2],g_libparams[3]); // set_palette(n,b,r,g); | |
1068 | + return v0; | |
1069 | + case LIB_GPALETTE:// GPALETTE N,R,G,B | |
1070 | + if (g_graphic_area) g_set_palette(g_libparams[1],v0,g_libparams[2],g_libparams[3]); // g_set_palette(n,b,r,g); | |
1071 | + return v0; | |
1072 | + case LIB_CLS: | |
1073 | + clearscreen(); | |
1074 | + return v0; | |
1075 | + case LIB_GCLS: | |
1076 | + if (g_graphic_area) g_clearscreen(); | |
1077 | + g_prev_x=g_prev_y=0; | |
1078 | + return v0; | |
1079 | + case LIB_WIDTH: | |
1080 | + videowidth(v0); | |
1081 | + return v0; | |
1082 | + case LIB_COLOR: | |
1083 | + setcursorcolor(v0); | |
1084 | + return v0; | |
1085 | + case LIB_GCOLOR: | |
1086 | + g_gcolor=v0; | |
1087 | + return v0; | |
1088 | + case LIB_WAIT: | |
1089 | + lib_wait(v0); | |
1090 | + return v0; | |
1091 | + case LIB_CLEAR: | |
1092 | + lib_clear(); | |
1093 | + return v0; | |
1094 | + case LIB_DIM: | |
1095 | + return (int)lib_dim(a0,a1,(int*)v0); | |
1096 | +#ifdef __DEBUG | |
1097 | + case LIB_DEBUG: | |
1098 | + asm volatile("nop"); | |
1099 | + return v0; | |
1100 | +#endif | |
1101 | + case LIB_DIV0: | |
1102 | + err_div_zero(); | |
1103 | + return v0; | |
1104 | + default: | |
1105 | + err_unknown(); | |
1106 | + return v0; | |
1107 | + } | |
1108 | +} | |
\ No newline at end of file |
@@ -0,0 +1,394 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "compiler.h" | |
13 | + | |
14 | +unsigned int g_label; | |
15 | + | |
16 | +char* get_label(void){ | |
17 | + unsigned int i; | |
18 | + char b1; | |
19 | + int prevpos; | |
20 | + next_position(); | |
21 | + prevpos=g_srcpos; | |
22 | + i=0; | |
23 | + b1=g_source[g_srcpos]; | |
24 | + if ('0'<= b1 && b1<='9') { | |
25 | + // May be line number | |
26 | + do { | |
27 | + i*=10; | |
28 | + i+=b1-'0'; | |
29 | + g_srcpos++; | |
30 | + b1=g_source[g_srcpos]; | |
31 | + } while ('0'<= b1 && b1<='9'); | |
32 | + // Check if end of the statement. | |
33 | + if (i==0 || 65535<i) { | |
34 | + // Line number 0 or more than 65535 is not available | |
35 | + g_srcpos=prevpos; | |
36 | + return ERR_SYNTAX; | |
37 | + } else if (get_operator()) { | |
38 | + // Oparator not found. | |
39 | + g_label=i; | |
40 | + return 0; | |
41 | + } else { | |
42 | + // This is not constant line number. | |
43 | + g_srcpos=prevpos; | |
44 | + g_label=0; | |
45 | + return 0; | |
46 | + } | |
47 | + } else if ('A'<=b1 && b1<='Z') { | |
48 | + // May be label | |
49 | + do { | |
50 | + // First character must be A-Z | |
51 | + // From second, A-Z and 0-9 can be used. | |
52 | + i*=36; | |
53 | + if ('0'<=b1 && b1<='9') { | |
54 | + i+=b1-'0'; | |
55 | + } else if (g_srcpos==prevpos) { | |
56 | + // First character must be A-Z. | |
57 | + // Subtract 9, resulting 1-26 but not 10-35. | |
58 | + // This subtraction is required to maintain | |
59 | + // final number being <0x80000000. | |
60 | + i+=b1-'A'+1; | |
61 | + } else { | |
62 | + i+=b1-'A'+10; | |
63 | + } | |
64 | + g_srcpos++; | |
65 | + b1=g_source[g_srcpos]; | |
66 | + } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z'); | |
67 | + // Length of the label must be between 2 and 6. | |
68 | + if (g_srcpos-prevpos<2 || 6<g_srcpos-prevpos) { | |
69 | + g_srcpos=prevpos; | |
70 | + return ERR_LABEL_LONG; | |
71 | + } | |
72 | + // Must not be a function | |
73 | + next_position(); | |
74 | + if (g_source[g_srcpos]=='(') { | |
75 | + g_srcpos=prevpos; | |
76 | + g_label=0; | |
77 | + return 0; | |
78 | + } | |
79 | + g_label=i+65536; | |
80 | + return 0; | |
81 | + } else { | |
82 | + g_label=0; | |
83 | + return 0; | |
84 | + } | |
85 | +} | |
86 | + | |
87 | +void* search_label(unsigned int label){ | |
88 | + unsigned int i,code,search1,search2; | |
89 | + if (label&0xFFFF0000) { | |
90 | + // Label | |
91 | + search1=0x3C160000|((label>>16)&0x0000FFFF); //lui s6,yyyy; | |
92 | + search2=0x36D60000|(label&0x0000FFFF); //ori s6,s6,zzzz; | |
93 | + for(i=0;i<g_objpos;i++){ | |
94 | + code=g_object[i]; | |
95 | + if (code==search1) { | |
96 | + if (g_object[i+1]==search2) { | |
97 | + // Label number found | |
98 | + return &(g_object[i]); | |
99 | + } | |
100 | + } | |
101 | + if (code&0xFFFF0000==0x04110000) { | |
102 | + // "bgezal zero," assembly found. Skip following block (strig). | |
103 | + i+=code&0x0000FFFF; | |
104 | + } | |
105 | + } | |
106 | + // Line number not found. | |
107 | + return 0; | |
108 | + } else { | |
109 | + // Line number | |
110 | + search1=0x34160000|label; //ori s6,zero,xxxx; | |
111 | + for(i=0;i<g_objpos;i++){ | |
112 | + code=g_object[i]; | |
113 | + if (code==search1) { | |
114 | + // Line number found | |
115 | + return &(g_object[i]); | |
116 | + } | |
117 | + if (code&0xFFFF0000==0x04110000) { | |
118 | + // "bgezal zero," assembly found. Skip following block (strig). | |
119 | + i+=code&0x0000FFFF; | |
120 | + } | |
121 | + } | |
122 | + // Line number not found. | |
123 | + return 0; | |
124 | + } | |
125 | +} | |
126 | + | |
127 | +void* search_breakout(unsigned int start, int* prevcode){ | |
128 | + unsigned int pos,code1,depth; | |
129 | + // Start search from start point where BREAK statement is used. | |
130 | + depth=0; | |
131 | + for(pos=start;pos<g_objpos;pos++){ | |
132 | + code1=g_object[pos]; | |
133 | + switch(code1>>16){ | |
134 | + case 0x0411: | |
135 | + // "bgezal zero," assembly found. Skip following block (strig). | |
136 | + pos+=code1&0x0000FFFF; | |
137 | + break; | |
138 | + case 0x0820: // FOR | |
139 | + case 0x0821: // WHILE | |
140 | + case 0x0822: // DO | |
141 | + depth++; | |
142 | + break; | |
143 | + case 0x0830: // NEXT | |
144 | + case 0x0831: // WEND | |
145 | + case 0x0832: // LOOP | |
146 | + if (0<depth) { | |
147 | + depth--; | |
148 | + break; | |
149 | + } | |
150 | + // Destination found. | |
151 | + // Previous code will be also set if required for CONTINUE statement. | |
152 | + if (prevcode) prevcode[0]=g_object[pos-1]; | |
153 | + return (void*)&g_object[pos]; | |
154 | + default: | |
155 | + break; | |
156 | + } | |
157 | + } | |
158 | + return 0; | |
159 | +} | |
160 | + | |
161 | +void* search_ifout(unsigned int start){ | |
162 | + unsigned int pos,code1,depth; | |
163 | + // Start search from start point where BREAK statement is used. | |
164 | + depth=0; | |
165 | + for(pos=start;pos<g_objpos;pos++){ | |
166 | + code1=g_object[pos]; | |
167 | + switch(code1>>16){ | |
168 | + case 0x0411: | |
169 | + // "bgezal zero," assembly found. Skip following block (strig). | |
170 | + pos+=code1&0x0000FFFF; | |
171 | + break; | |
172 | + case 0x3000: // Block marker | |
173 | + if (code1==0x30008000) { | |
174 | + // end block | |
175 | + if (0<depth) { | |
176 | + depth--; | |
177 | + break; | |
178 | + } | |
179 | + // Destination found. | |
180 | + return (void*)&g_object[pos]; | |
181 | + } else if (code1==0x30000000) { | |
182 | + // begin block | |
183 | + depth++; | |
184 | + break; | |
185 | + } else { | |
186 | + break; | |
187 | + } | |
188 | + default: | |
189 | + break; | |
190 | + } | |
191 | + } | |
192 | + return 0; | |
193 | +} | |
194 | + | |
195 | +/* | |
196 | + Following codes are dedicated to specific use: | |
197 | + 0x0411xxxx: String/data block | |
198 | + Use 0x0413xxxx (bzegall zero,xxxx) for other cases to get PC to $ra | |
199 | + 0x0810xxxx, 0x0811xxxx: GOTO statement | |
200 | + 0x0812xxxx, 0x0813xxxx: GOSUB statement | |
201 | + 0x0814xxxx, 0x0815xxxx: SOUND etc, for setting v0 as pointer to DATA array. | |
202 | + 0x0816xxxx: BREAK statemant and relatives | |
203 | + 0x08160000: BREAK | |
204 | + 0x08160008: CONTINUE | |
205 | + 0x08160100: Jump to next ELSE, ELSEIF or ENDIF | |
206 | + 0x082xyyyy: Begin block (FOR/DO/WHILE) | |
207 | + 0x083xyyyy: End block (NEXT/LOOP/WEND) | |
208 | + 0x00000020, 0x00000021, | |
209 | + 0x00000022, 0x00000023: Marker for begining the DATA region. | |
210 | + MLB 2 bits show skip byte length in DATA. | |
211 | + 0x30000000: Begin block (IF-THEN-ELSEIF-ELSE-ENDIF) | |
212 | + 0x30008000: End block (IF-THEN-ELSEIF-ELSE-ENDIF) | |
213 | + 0x3000Fxxx: General purpose NOP with value 0x0000-0x0FFF. | |
214 | + | |
215 | + IF-THEN-ELSEIF-ELSE-ENDIF is written as follows: | |
216 | + IF-THEN: 0x30000000 0x10400000 0x30000000 | |
217 | + ELSEIF-THEN: 0x08160100 0x30008000 (conditional expression) 0x10400000 0x30000000 | |
218 | + ELSE: 0x08160100 0x30008000 0x30000000 | |
219 | + ENDIF: 0x30008000 0x30008000 | |
220 | + , where "0x10400000 0x30000000" and "0x08160100 0x30008000" will be replaced by | |
221 | + codes jumping to next 0x30008000. The 0x30000000 - 0x30008000 blocks will be skipped. | |
222 | +*/ | |
223 | + | |
224 | +char* link(void){ | |
225 | + int pos; | |
226 | + unsigned int code1,code2,label; | |
227 | + g_fileline=0; | |
228 | + for(pos=0;pos<g_objpos;pos++){ | |
229 | + code1=g_object[pos]; | |
230 | + switch(code1>>16){ | |
231 | + case 0x0411: | |
232 | + // "bgezal zero," assembly found. Skip following block (strig). | |
233 | + pos+=code1&0x0000FFFF; | |
234 | + break; | |
235 | + case 0x3416: | |
236 | + // "ori s6,zero,xxxx" found this is the first word in a line. | |
237 | + g_fileline++; | |
238 | + g_line=code1&0x0000FFFF; | |
239 | + break; | |
240 | + case 0x0810: | |
241 | + // GOTO | |
242 | + code2=g_object[pos+1]; | |
243 | + if ((code2&0xFFFF0000)!=0x08110000) continue; | |
244 | + code1&=0x0000FFFF; | |
245 | + code2&=0x0000FFFF; | |
246 | + label=(code1<<16)|code2; | |
247 | + code1=(int)search_label(label); | |
248 | + g_label=label; | |
249 | + if (!code1) return ERR_LABEL_NF; | |
250 | + code1&=0x0FFFFFFF; | |
251 | + code1>>=2; | |
252 | + code1|=0x08000000; // j xxxx | |
253 | + g_object[pos++]=code1; | |
254 | + g_object[pos]=0x00000000; // nop | |
255 | + break; | |
256 | + case 0x0812: | |
257 | + // GOSUB | |
258 | + code2=g_object[pos+1]; | |
259 | + if ((code2&0xFFFF0000)!=0x08130000) continue; | |
260 | + code1&=0x0000FFFF; | |
261 | + code2&=0x0000FFFF; | |
262 | + label=(code1<<16)|code2; | |
263 | + code2=(int)search_label(label); | |
264 | + g_label=label; | |
265 | + if (!code2) return ERR_LABEL_NF; | |
266 | + code2&=0x0FFFFFFF; | |
267 | + code2>>=2; | |
268 | + code2|=0x08000000; // j xxxx | |
269 | + g_object[pos++]=0x00000000; // nop | |
270 | + g_object[pos]=code2; | |
271 | + break; | |
272 | + case 0x0814: | |
273 | + // SOUND etc, for setting v0 as pointer to label/line | |
274 | + code2=g_object[pos+1]; | |
275 | + if ((code2&0xFFFF0000)!=0x08150000) continue; | |
276 | + code1&=0x0000FFFF; | |
277 | + code2&=0x0000FFFF; | |
278 | + label=(code1<<16)|code2; | |
279 | + code1=(int)search_label(label); | |
280 | + g_label=label; | |
281 | + if (!code1) return ERR_LABEL_NF; | |
282 | + g_object[pos++]=0x3C020000|((code1>>16)&0x0000FFFF); // lui v0,xxxx | |
283 | + g_object[pos] =0x34420000|(code1&0x0000FFFF); // ori v0,v0,xxxx | |
284 | + break; | |
285 | + case 0x0816: | |
286 | + switch(code1&0xFFFF) { | |
287 | + case 0x0000: | |
288 | + // BREAK statement | |
289 | + // Find next the NEXT or WHILE statement and insert jump code after this. | |
290 | + g_label=g_line; | |
291 | + code1=(int)search_breakout(pos,0); | |
292 | + if (!code1) return ERR_INVALID_BREAK; | |
293 | + code1&=0x0FFFFFFF; | |
294 | + code1>>=2; | |
295 | + code1|=0x08000000; // j xxxx | |
296 | + g_object[pos]=code1; | |
297 | + break; | |
298 | + case 0x0008: | |
299 | + // CONTINUE statement | |
300 | + // Find next the NEXT or WHILE statement and insert jump code after this. | |
301 | + g_label=g_line; | |
302 | + code1=(int)search_breakout(pos,&g_temp); | |
303 | + if (!code1) return ERR_INVALID_BREAK; | |
304 | + if (0x3000F000 == (g_temp&0xFFFFF000)) { | |
305 | + // WEND or LOOP statement found | |
306 | + code1-=(g_temp&0x0FFF)<<2; | |
307 | + } else { | |
308 | + // NEXT statement found | |
309 | + code1-=3<<2; | |
310 | + } | |
311 | + code1&=0x0FFFFFFF; | |
312 | + code1>>=2; | |
313 | + code1|=0x08000000; // j xxxx | |
314 | + g_object[pos]=code1; | |
315 | + break; | |
316 | + case 0x0100: | |
317 | + // Jump to next ENDIF | |
318 | + g_label=g_line; | |
319 | + // "pos+2" is for skipping next code (must be 0x30008000) | |
320 | + code1=(int)search_ifout(pos+2); | |
321 | + if (!code1) return ERR_INVALID_ELSEIF; | |
322 | + code1&=0x0FFFFFFF; | |
323 | + code1>>=2; | |
324 | + code1|=0x08000000; // j xxxx | |
325 | + g_object[pos]=code1; | |
326 | + break; | |
327 | + default: | |
328 | + break; | |
329 | + } | |
330 | + break; | |
331 | + case 0x3000: | |
332 | + // Block marker | |
333 | + switch(code1&0xFFFF) { | |
334 | + case 0x0000: | |
335 | + // Begin if block | |
336 | + if (g_object[pos-1]==0x10400000) { // beq v0,zero,xxxx | |
337 | + // IF-THEN or ELSEIF-THEN | |
338 | + // Jump to next ELSE, ELSEIF or ENDIF | |
339 | + g_label=g_line; | |
340 | + // "pos+1" is for skipping current code (0x30000000) | |
341 | + code1=(int)search_ifout(pos+1); | |
342 | + if (!code1) return ERR_INVALID_ELSEIF; | |
343 | + code1-=(int)(&g_object[pos]); | |
344 | + code1>>=2; | |
345 | + code1&=0x0000FFFF; | |
346 | + code1|=0x10400000; // beq v0,zero,xxxx | |
347 | + g_object[pos-1]=code1; | |
348 | + break; | |
349 | + } | |
350 | + break; | |
351 | + default: | |
352 | + break; | |
353 | + } | |
354 | + break; | |
355 | + case 0x0820: // FOR | |
356 | + case 0x0830: // NEXT | |
357 | + case 0x0821: // WHILE | |
358 | + case 0x0831: // WEND | |
359 | + case 0x0822: // DO | |
360 | + case 0x0832: // WHILE | |
361 | + // These are used for detecing the depth of structures. | |
362 | + // Change them to stack increase/decrease commands. | |
363 | + g_object[pos]=0x27BD0000|(code1&0x0000FFFF); //// addiu sp,sp,xx | |
364 | + break; | |
365 | + case 0x2407: // addiu a3,zero,xxxx | |
366 | + if (g_object[pos-1]!=0x02E0F809) break; // jalr ra,s7 | |
367 | + // call_lib_code(x) | |
368 | + switch(code1&0x0000FFFF){ | |
369 | + case LIB_RESTORE: | |
370 | + // Convert label data to pointer if not dynamic | |
371 | + code1=g_object[pos-3]; | |
372 | + code2=g_object[pos-2]; | |
373 | + if ((code1>>16)!=0x3C02) break; // lui v0,xxxx | |
374 | + if ((code2>>16)!=0x3442) break; // ori v0,v0,xxxx | |
375 | + label=(code1<<16)|(code2&0x0000FFFF); | |
376 | + code1=(int)search_label(label); | |
377 | + g_label=label; | |
378 | + if (!code1) return ERR_LABEL_NF; | |
379 | + code2=code1&0x0000FFFF; | |
380 | + code1=code1>>16; | |
381 | + g_object[pos-3]=0x3C020000|code1; // lui v0,xxxx | |
382 | + g_object[pos-2]=0x34420000|code2; // ori v0,v0,xxxx | |
383 | + g_object[pos]=0x24070000|LIB_RESTORE2; // addiu a3,zero,xxxx | |
384 | + break; | |
385 | + default: | |
386 | + break; | |
387 | + } | |
388 | + break; | |
389 | + default: | |
390 | + break; | |
391 | + } | |
392 | + } | |
393 | + return 0; | |
394 | +} | |
\ No newline at end of file |
@@ -0,0 +1,272 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by K.Tanaka & Katsumi | |
4 | + http://www.ze.em-net.ne.jp/~kenken/index.html | |
5 | + http://hp.vector.co.jp/authors/VA016157/ | |
6 | +*/ | |
7 | + | |
8 | +// main.c | |
9 | +// MachiKania BASIC System Ver Zoea | |
10 | +// KM-BASIC 統合開発実行環境 for PIC32MX170F256B / PIC32MX270F256B by K.Tanaka | |
11 | +// LCD出力バージョン(テスト) by K.Tanaka | |
12 | + | |
13 | +// 利用システム | |
14 | +// libsdfsio.a : SDカードアクセス用ライブラリ | |
15 | + | |
16 | +// System clock :48MHz FRC with PLL (8/2*24/2) | |
17 | +// Peripheral clock :48MHz | |
18 | + | |
19 | +/* | |
20 | + PIC32MX ペリフェラル使用状況 | |
21 | + | |
22 | + 割り込み | |
23 | + NTSC, Timer2, vector 8, priority 5 | |
24 | + MUSIC, CS0, vector 1, priority 2 | |
25 | + TIMER, Timer1, vector 4, priority 3 | |
26 | + INT, CS1, vector 2, priority 1 | |
27 | + | |
28 | + タイマー | |
29 | + Timer1 BASIC用タイマー | |
30 | + Timer2 NTSC | |
31 | + Timer3 MUSIC/PWM | |
32 | + Timer4 MUSIC | |
33 | + Timer5 未使用 | |
34 | + | |
35 | + DMA | |
36 | + DMA0 未使用 | |
37 | + DMA1 未使用 | |
38 | + DMA2 MUSIC | |
39 | + DMA3 未使用 | |
40 | + | |
41 | + Output compair | |
42 | + OC1 未使用 | |
43 | + OC2 未使用 | |
44 | + OC3 未使用 | |
45 | + OC4 MUSIC/PWM | |
46 | + OC5 未使用 | |
47 | + | |
48 | + SPI | |
49 | + SPI1 未使用 | |
50 | + SPI2 マルチメディアカード | |
51 | + | |
52 | + I2C | |
53 | + I2C1 未使用 | |
54 | + I2C2 未使用 | |
55 | + | |
56 | + ポート使用 | |
57 | + A0 MMC | |
58 | + A1 MMC | |
59 | + A2 Audio | |
60 | + A3 LCD/button切換え | |
61 | + A4 MMC | |
62 | + B0 LCD | |
63 | + B1 LCD | |
64 | + B2 LCD/button | |
65 | + B3 LCD/button | |
66 | + B4 LCD/button | |
67 | + B5 LCD/button | |
68 | + B6 未使用 | |
69 | + B7 LCD/button | |
70 | + B8 LCD/button | |
71 | + B9 PS2/button | |
72 | + B10 LCD | |
73 | + B11 LCD | |
74 | + B12 未使用 | |
75 | + B13 LCD | |
76 | + B14 LCD | |
77 | + B15 MMC | |
78 | +*/ | |
79 | + | |
80 | +#include <xc.h> | |
81 | +#include "api.h" | |
82 | +#include "compiler.h" | |
83 | +#include "editor.h" | |
84 | +#include "main.h" | |
85 | + | |
86 | +#define mBMXSetRAMKernProgOffset(offset) (BMXDKPBA = (offset)) | |
87 | +#define mBMXSetRAMUserDataOffset(offset) (BMXDUDBA = (offset)) | |
88 | +#define mBMXSetRAMUserProgOffset(offset) (BMXDUPBA = (offset)) | |
89 | + | |
90 | +// INIファイル指定キーワード(8文字以内) | |
91 | +const char InitKeywords[][9]={ | |
92 | + "106KEY","101KEY","NUMLOCK","CAPSLOCK","SCRLLOCK" | |
93 | +}; | |
94 | + | |
95 | +void freadline(char *s,FSFILE *fp){ | |
96 | +// ファイルから1行読み込み、配列sに返す | |
97 | +// 最大8文字まで。9文字以上の場合無効 | |
98 | +// #または0x20以下のコードを見つけた場合、以降は無視 | |
99 | +// s:9バイト以上の配列 | |
100 | +// fp:ファイルポインタ | |
101 | + int n; | |
102 | + char c,*p; | |
103 | + n=0; | |
104 | + p=s; | |
105 | + *p=0; | |
106 | + while(n<=8){ | |
107 | + if(FSfread(p,1,1,fp)==0 || *p=='\n'){ | |
108 | + *p=0; | |
109 | + return; | |
110 | + } | |
111 | + if(*p=='#'){ | |
112 | + *p=0; | |
113 | + break; | |
114 | + } | |
115 | + if(*p<=' '){ | |
116 | + if(n>0){ | |
117 | + *p=0; | |
118 | + break; | |
119 | + } | |
120 | + continue; | |
121 | + } | |
122 | + p++; | |
123 | + n++; | |
124 | + } | |
125 | + if(n>8) *s=0; //9文字以上の文字列の場合は無効 | |
126 | + //以降の文字は無視 | |
127 | + while(FSfread(&c,1,1,fp) && c!='\n') ; | |
128 | +} | |
129 | +int searchinittext(char *s){ | |
130 | +// InitKeywords配列の中から文字列sを探し、位置した場合何番目かを返す | |
131 | +// 見つからなかった場合-1を返す | |
132 | + int i; | |
133 | + char *p1; | |
134 | + const char *p2; | |
135 | + for(i=0;i<sizeof(InitKeywords)/sizeof(InitKeywords[0]);i++){ | |
136 | + p1=s; | |
137 | + p2=InitKeywords[i]; | |
138 | + while(*p1==*p2){ | |
139 | + if(*p1==0) return i; | |
140 | + p1++; | |
141 | + p2++; | |
142 | + } | |
143 | + } | |
144 | + return -1; | |
145 | +} | |
146 | +void readinifile(void){ | |
147 | + FSFILE *fp; | |
148 | + char inittext[9]; | |
149 | + | |
150 | + fp=FSfopen(INIFILE,"r"); | |
151 | + if(fp==NULL) return; | |
152 | + printstr("Initialization File Found\n"); | |
153 | +// lockkey=0; //INIファイルが存在する場合、Lock関連キーはINIファイルに従う | |
154 | + while(1){ | |
155 | + if(FSfeof(fp)) break; | |
156 | + freadline(inittext,fp); | |
157 | + switch(searchinittext(inittext)){ | |
158 | + case 0: | |
159 | +// keytype=0;//日本語キーボード | |
160 | + break; | |
161 | + case 1: | |
162 | +// keytype=1;//英語キーボード | |
163 | + break; | |
164 | + case 2: | |
165 | +// lockkey|=2;//Num Lock | |
166 | + break; | |
167 | + case 3: | |
168 | +// lockkey|=4;//CAPS Lock | |
169 | + break; | |
170 | + case 4: | |
171 | +// lockkey|=1;//Scroll Lock | |
172 | + break; | |
173 | + } | |
174 | + } | |
175 | + FSfclose(fp); | |
176 | +} | |
177 | + | |
178 | +void printhex8(unsigned char d){ | |
179 | + printchar("0123456789ABCDEF"[d>>4]); | |
180 | + printchar("0123456789ABCDEF"[d&0x0f]); | |
181 | +} | |
182 | + | |
183 | +void printhex16(unsigned short d){ | |
184 | + printhex8(d>>8); | |
185 | + printhex8(d&0x00ff); | |
186 | +} | |
187 | + | |
188 | +void printhex32(unsigned int d){ | |
189 | + printhex16(d>>16); | |
190 | + printhex16(d&0x0000ffff); | |
191 | +} | |
192 | + | |
193 | +int main(void){ | |
194 | + char *appname,*s; | |
195 | + | |
196 | + if(DEVCFG1 & 0x8000){ | |
197 | + // Set Clock switching enabled and reset | |
198 | + NVMWriteWord(&DEVCFG1,DEVCFG1 & 0xffff7fff); | |
199 | + SoftReset(); | |
200 | + } | |
201 | + | |
202 | + /* ポートの初期設定 */ | |
203 | + TRISA = 0x0000; // PORTA全て出力 | |
204 | + ANSELA = 0x0000; // 全てデジタル | |
205 | + TRISB = 0x0000; // PORTB全て出力(ボタン読み込み時のみ入力に切り替える) | |
206 | + ANSELB = 0x0000; // 全てデジタル | |
207 | + KEY_DS; | |
208 | + LCD_CS_LO; | |
209 | + | |
210 | + // 周辺機能ピン割り当て | |
211 | + SDI2R=2; //RPA4:SDI2 | |
212 | + RPA1R=4; //RPA1:SDO2 | |
213 | + | |
214 | + // Make RAM executable. See also "char RAM[RAMSIZE]" in globalvars.c | |
215 | + mBMXSetRAMKernProgOffset(PIC32MX_RAMSIZE-RAMSIZE); | |
216 | + mBMXSetRAMUserDataOffset(PIC32MX_RAMSIZE); | |
217 | + mBMXSetRAMUserProgOffset(PIC32MX_RAMSIZE); | |
218 | + | |
219 | + INTEnableSystemMultiVectoredInt(); | |
220 | + IPC2bits.T2IP = 4; // 割り込みレベル4 | |
221 | + IFS0bits.T2IF = 0; | |
222 | + IEC0bits.T2IE = 1; // タイマ2割り込み有効化 | |
223 | + PR2=3125; // 60分の1秒 | |
224 | + T2CON = 0x8070; // プリスケーラ1:256、タイマ2開始 | |
225 | + | |
226 | + init_textgraph();// パレット設定、LCDクリア | |
227 | + setcursor(0,0,COLOR_NORMALTEXT); | |
228 | + keystatus=0; | |
229 | + | |
230 | + // Show blue screen if exception before soft reset. | |
231 | + blue_screen(); | |
232 | + | |
233 | + printstr("MachiKania BASIC System\n"); | |
234 | + printstr(" Ver "SYSVER1" "SYSVER2" by KENKEN\n"); | |
235 | + printstr("BASIC Compiler "BASVER"\n"); | |
236 | + printstr(" by Katsumi\n\n"); | |
237 | + //SDカードファイルシステム初期化 | |
238 | + setcursorcolor(COLOR_NORMALTEXT); | |
239 | + printstr("Init File System..."); | |
240 | + // Initialize the File System | |
241 | + if(FSInit()==FALSE){ //ファイルシステム初期化 | |
242 | + //エラーの場合停止 | |
243 | + setcursorcolor(COLOR_ERRORTEXT); | |
244 | + printstr("\nFile System Error\n"); | |
245 | + printstr("Insert Correct Card\n"); | |
246 | + printstr("And Reset\n"); | |
247 | + while(1) asm("wait"); | |
248 | + } | |
249 | + printstr("OK\n"); | |
250 | + readinifile(); //INIファイル読み込み | |
251 | + | |
252 | + wait60thsec(60); //1秒待ち | |
253 | + | |
254 | +/* | |
255 | + // 実行中HEXファイル名がHEXFILEと一致した場合はエディタ起動 | |
256 | + appname=(char*)FILENAME_FLASH_ADDRESS; | |
257 | + s=HEXFILE; | |
258 | + while(*s++==*appname++) if(*s==0) texteditor(); //テキストエディター呼び出し | |
259 | +*/ | |
260 | + | |
261 | + // 実行中HEXファイル名の「.HEX」を「.BAS」に置き換えてBASファイルを実行 | |
262 | + appname=(char*)FILENAME_FLASH_ADDRESS; | |
263 | + s=tempfile; | |
264 | + while(*appname!='.') *s++=*appname++; | |
265 | + appname=".BAS"; | |
266 | + while(*appname!=0) *s++=*appname++; | |
267 | + *s=0; | |
268 | + // buttonmode(); //ボタン有効化 | |
269 | + g_disable_break=1; // Breakキー無効化 | |
270 | + runbasic(tempfile,0); | |
271 | + while(1) asm(WAIT); | |
272 | +} |
@@ -0,0 +1,21 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by K.Tanaka & Katsumi | |
4 | + http://www.ze.em-net.ne.jp/~kenken/index.html | |
5 | + http://hp.vector.co.jp/authors/VA016157/ | |
6 | +*/ | |
7 | + | |
8 | +#define SYSVER1 "Protozoa" | |
9 | +#define SYSVER2 "1.3" | |
10 | +#define BASVER "KM-1208" | |
11 | + | |
12 | +#define INIFILE "MACHILCD.INI" // 初期設定ファイル | |
13 | +#define HEXFILE "MACHILCD.HEX" // 実行中HEXファイル名がこれと一致した場合はエディタ起動 | |
14 | + | |
15 | +#define FILENAME_FLASH_ADDRESS 0x9D005800 | |
16 | +#define PIC32MX_RAMSIZE 0x10000 | |
17 | +#define PIC32MX_FLASHSIZE 0x40000 | |
18 | + | |
19 | +void printhex8(unsigned char d); | |
20 | +void printhex16(unsigned short d); | |
21 | +void printhex32(unsigned int d); |
@@ -0,0 +1,327 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "compiler.h" | |
13 | + | |
14 | +/* | |
15 | + ALLOC_VAR_NUM: # of variables used for allocation of memory (string/dimension). | |
16 | + 0 is for A, 1 is for B, ... , and 25 is for Z. | |
17 | + This number also includes temporary area used for string construction etc. | |
18 | + Temporary area is cleared every line of BASIC code in alloc_memory(). | |
19 | + ALLOC_BLOCK_NUM: # of blocks that can be used for memory allocation. | |
20 | + This # includes the ones for ALLOC_VAR_NUM, ALLOC_PCG_BLOCK etc, ALLOC_LNV_BLOCK, | |
21 | + ALLOC_PERM_BLOCK. | |
22 | + After ALLOC_VAR_NUM area, dedicated memory area and permanent area follows. | |
23 | + ALLOC_PERM_BLOCK: Start # of permanent blocks. | |
24 | + The blocks after this number is permanently stored. | |
25 | + Therefore, it must be released when it's not used any more. | |
26 | +*/ | |
27 | + | |
28 | +static int g_temp_var_num_candidate=ALLOC_PERM_BLOCK; | |
29 | + | |
30 | +#define DELETE_LIST_SIZE 10 | |
31 | +static int g_deleted_num; | |
32 | +static int g_deleted_pointer[DELETE_LIST_SIZE]; | |
33 | +static int g_deleted_size[DELETE_LIST_SIZE]; | |
34 | + | |
35 | +void register_deleted_block(int pointer, int size){ | |
36 | + // There is maximum | |
37 | + if (DELETE_LIST_SIZE<=g_deleted_num) return; | |
38 | + if (g_deleted_num) { | |
39 | + // Avoid duplication | |
40 | + if (g_deleted_pointer[g_deleted_num-1]==pointer) return; | |
41 | + } | |
42 | + g_deleted_pointer[g_deleted_num]=pointer; | |
43 | + g_deleted_size[g_deleted_num]=size; | |
44 | + g_deleted_num++; | |
45 | +} | |
46 | + | |
47 | +void set_free_area(void* begin, void* end){ | |
48 | + // Initialize heap area | |
49 | + int i; | |
50 | + for(i=0;i<ALLOC_BLOCK_NUM;i++){ | |
51 | + g_var_size[i]=0; | |
52 | + } | |
53 | + g_heap_mem=(int*)begin; | |
54 | + g_max_mem=(int)((end-begin)/4); | |
55 | + g_deleted_num=0; | |
56 | +} | |
57 | + | |
58 | +void* calloc_memory(int size, int var_num){ | |
59 | + int i; | |
60 | + void* ret; | |
61 | + // Allocate memory | |
62 | + ret=alloc_memory(size,var_num); | |
63 | + // Fill zero in allocated memory | |
64 | + for(i=0;i<size;i++){ | |
65 | + ((int*)ret)[i]=0; | |
66 | + } | |
67 | + // return pointer to allocated memory | |
68 | + return ret; | |
69 | +} | |
70 | +void* alloc_memory(int size, int var_num){ | |
71 | + // Remove temporary blocks once a line. | |
72 | + asm volatile("nop"); | |
73 | + asm volatile("bltz $s6,_alloc_memory_main"); // Skip if $s6<0 | |
74 | + // Following code will be activated after setting $s6 register | |
75 | + // every line and after label statement. | |
76 | + asm volatile("lui $v0,0x8000"); | |
77 | + asm volatile("or $s6,$v0,$s6"); // $s6=0x80000000|$s6; | |
78 | + // Remove all temporary blocks | |
79 | + // Note that g_var_size is short integer. | |
80 | + // Note that ALLOC_VAR_NUM is used here (but not ALLOC_BLOC_NUM) | |
81 | + // for(i=26;i<ALLOC_VAR_NUM;i++)g_var_size[i]=0; | |
82 | + asm volatile("addiu $v0,$zero,%0"::"n"((ALLOC_VAR_NUM-26)/2)); // $v0=(ALLOC_VAR_NUM-26)/2 | |
83 | + asm volatile("la $v1,%0"::"i"(&g_var_size[0])); // $v1=g_var_size | |
84 | + asm volatile("loop:"); | |
85 | + asm volatile("sw $zero,(26*2)($v1)"); // $v1[26]=0, $v1[27]=0 | |
86 | + asm volatile("addiu $v0,$v0,-1"); // $v0-- | |
87 | + asm volatile("addiu $v1,$v1,4"); // $v1+=2 | |
88 | + asm volatile("bne $v0,$zero,loop"); // loop if 0<$v0 | |
89 | + asm volatile("b _alloc_memory_main"); | |
90 | +} | |
91 | +void* _alloc_memory_main(int size, int var_num){ | |
92 | + int i,j,candidate; | |
93 | + // Assign temp var number | |
94 | + if (var_num<0) { | |
95 | + // Use ALLOC_VAR_NUM here but not ALLOC_BLOCK_NUM | |
96 | + for(i=26;i<ALLOC_VAR_NUM;i++){ | |
97 | + if (g_var_size[i]==0) { | |
98 | + var_num=i; | |
99 | + break; | |
100 | + } | |
101 | + } | |
102 | + if (var_num<0) { | |
103 | + err_str_complex(); | |
104 | + return 0; | |
105 | + } | |
106 | + } | |
107 | + // Clear var to be assigned. | |
108 | + g_var_size[var_num]=0; | |
109 | + g_var_pointer[var_num]=0; | |
110 | + while(1){ | |
111 | + // Try the block previously deleted, not for temporary block. | |
112 | + // This is for fast allocation of memory for class object. | |
113 | + if (var_num<26 || ALLOC_VAR_NUM<=var_num) { | |
114 | + candidate=0; | |
115 | + while(g_deleted_num){ | |
116 | + // Check if the last deleted block fits | |
117 | + // If not, these cannot be used anymore | |
118 | + g_deleted_num--; | |
119 | + if (size<=g_deleted_size[g_deleted_num]) { | |
120 | + candidate=g_deleted_pointer[g_deleted_num]; | |
121 | + break; | |
122 | + } | |
123 | + } | |
124 | + if (candidate || g_deleted_num) { | |
125 | + // Candidate found | |
126 | + break; | |
127 | + } | |
128 | + } | |
129 | + // Try the block after last block | |
130 | + candidate=0; | |
131 | + for(i=0;i<ALLOC_BLOCK_NUM;i++){ | |
132 | + if (g_var_size[i]==0) continue; | |
133 | + if (candidate<=g_var_pointer[i]) { | |
134 | + candidate=g_var_pointer[i]+g_var_size[i]; | |
135 | + } | |
136 | + } | |
137 | + if (candidate+size<=g_max_mem) { | |
138 | + // Check after deleted block | |
139 | + j=candidate; | |
140 | + for(i=0;i<g_deleted_num;i++){ | |
141 | + if (j<g_deleted_pointer[i]+g_deleted_size[i]) { | |
142 | + j=g_deleted_pointer[i]+g_deleted_size[i]; | |
143 | + } | |
144 | + } | |
145 | + if (j+size<=g_max_mem) { | |
146 | + // Candidate block found after previously deleted blokcs | |
147 | + candidate=j; | |
148 | + break; | |
149 | + } else { | |
150 | + // Candidate is before previously deleted blocks, | |
151 | + // and there is no candidate block after previously deleted blocks. | |
152 | + // Therefore, use the current candidate, which may invade previously | |
153 | + // deleted blocks. Therefore, erase the previously deleted blocks list. | |
154 | + g_deleted_num=0; | |
155 | + break; | |
156 | + } | |
157 | + } | |
158 | + // Peviously deleted blocks cannot be used any more | |
159 | + g_deleted_num=0; | |
160 | + // Check between blocks | |
161 | + // Note that there is at least one block with zero pointer and zero size (see above). | |
162 | + for(i=0;i<ALLOC_BLOCK_NUM;i++){ | |
163 | + // Candidate is after this block. | |
164 | + candidate=g_var_pointer[i]+g_var_size[i]; | |
165 | + // Check if there is an overlap. | |
166 | + for(j=0;j<ALLOC_BLOCK_NUM;j++){ | |
167 | + if (g_var_size[j]==0) continue; | |
168 | + if (candidate+size<=g_var_pointer[j]) continue; | |
169 | + if (g_var_pointer[j]+g_var_size[j]<=candidate) continue; | |
170 | + // This block overlaps with the candidate | |
171 | + candidate=-1; | |
172 | + break; | |
173 | + } | |
174 | + if (0<=candidate && candidate+size<=g_max_mem) { | |
175 | + // Available block found | |
176 | + break; | |
177 | + } else { | |
178 | + candidate=-1; | |
179 | + } | |
180 | + } | |
181 | + if (0<=candidate) break; | |
182 | + // New memory block cannot be allocated. | |
183 | + err_no_mem(); | |
184 | + return 0; | |
185 | + } | |
186 | + // Available block found. | |
187 | + g_var_pointer[var_num]=candidate; | |
188 | + g_var_size[var_num]=size; | |
189 | + g_var_mem[var_num]=(int)(&(g_heap_mem[candidate])); | |
190 | + return (void*)g_var_mem[var_num]; | |
191 | +} | |
192 | + | |
193 | +void free_temp_str(char* str){ | |
194 | + int i,pointer; | |
195 | + if (!str) return; | |
196 | + pointer=(int)str-(int)g_heap_mem; | |
197 | + pointer>>=2; | |
198 | + for(i=26;i<ALLOC_VAR_NUM;i++){ | |
199 | + if (g_var_pointer[i]==pointer) { | |
200 | + if (g_var_size[i] && g_var_mem[i]==(int)str) { | |
201 | + register_deleted_block(pointer,g_var_size[i]); | |
202 | + g_var_size[i]=0; | |
203 | + } | |
204 | + } | |
205 | + } | |
206 | +} | |
207 | + | |
208 | +void free_non_temp_str(char* str){ | |
209 | + int i,pointer; | |
210 | + if (!str) return; | |
211 | + pointer=(int)str-(int)g_heap_mem; | |
212 | + pointer>>=2; | |
213 | + for(i=0;i<26;i++){ | |
214 | + if (g_var_pointer[i]==pointer) { | |
215 | + if (g_var_size[i] && g_var_mem[i]==(int)str) { | |
216 | + register_deleted_block(pointer,g_var_size[i]); | |
217 | + g_var_size[i]=0; | |
218 | + g_var_mem[i]=0; | |
219 | + } | |
220 | + } | |
221 | + } | |
222 | + for(i=ALLOC_VAR_NUM;i<ALLOC_BLOCK_NUM;i++){ | |
223 | + if (g_var_pointer[i]==pointer) { | |
224 | + if (g_var_size[i] && g_var_mem[i]==(int)str) { | |
225 | + register_deleted_block(pointer,g_var_size[i]); | |
226 | + g_var_size[i]=0; | |
227 | + g_var_mem[i]=0; | |
228 | + if (ALLOC_PERM_BLOCK<=i) g_temp_var_num_candidate=i; | |
229 | + } | |
230 | + } | |
231 | + } | |
232 | +} | |
233 | + | |
234 | +void free_perm_str(char* str){ | |
235 | + int i,pointer; | |
236 | + if (!str) return; | |
237 | + pointer=(int)str-(int)g_heap_mem; | |
238 | + pointer>>=2; | |
239 | + // Search permanent block and delete a block if found. | |
240 | + for(i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){ | |
241 | + if (g_var_pointer[i]==pointer) { | |
242 | + if (g_var_size[i] && g_var_mem[i]==(int)str) { | |
243 | + register_deleted_block(pointer,g_var_size[i]); | |
244 | + g_var_size[i]=0; | |
245 | + g_temp_var_num_candidate=i; | |
246 | + break; | |
247 | + } | |
248 | + } | |
249 | + } | |
250 | +} | |
251 | + | |
252 | +void move_to_perm_block(int var_num){ | |
253 | + int i; | |
254 | + // Find available permanent block | |
255 | + i=get_permanent_var_num(); | |
256 | + // Available block found. | |
257 | + // Copy value from variable. | |
258 | + g_var_size[i]=g_var_size[var_num]; | |
259 | + g_var_pointer[i]=g_var_pointer[var_num]; | |
260 | + g_var_mem[i]=g_var_mem[var_num]; | |
261 | + // Clear variable | |
262 | + g_var_size[var_num]=0; | |
263 | + g_var_mem[var_num]=0; | |
264 | +} | |
265 | + | |
266 | +int move_from_perm_block_if_exists(int var_num){ | |
267 | + int i,pointer; | |
268 | + pointer=(int)g_var_mem[var_num]-(int)g_heap_mem; | |
269 | + pointer>>=2; | |
270 | + // Find stored block | |
271 | + for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){ | |
272 | + if (0<g_var_size[i] && g_var_pointer[i]==pointer) break; | |
273 | + } | |
274 | + if (ALLOC_BLOCK_NUM<=i) return 0; // Not found | |
275 | + // Stored block found. | |
276 | + // Replace pointer | |
277 | + g_var_size[var_num]=g_var_size[i]; | |
278 | + g_var_pointer[var_num]=g_var_pointer[i]; | |
279 | + // Clear block | |
280 | + g_var_size[i]=0; | |
281 | + g_temp_var_num_candidate=i; | |
282 | + return 1; | |
283 | +} | |
284 | + | |
285 | +void move_from_perm_block(int var_num){ | |
286 | + if (move_from_perm_block_if_exists(var_num)) return; // Found | |
287 | + err_unknown(); // Not found | |
288 | +} | |
289 | + | |
290 | +int get_permanent_var_num(){ | |
291 | + int i; | |
292 | + // Try candidate first | |
293 | + if (!g_var_size[g_temp_var_num_candidate]) { | |
294 | + if (ALLOC_PERM_BLOCK<g_temp_var_num_candidate && | |
295 | + g_temp_var_num_candidate<ALLOC_BLOCK_NUM) { | |
296 | + return g_temp_var_num_candidate++; | |
297 | + } | |
298 | + } | |
299 | + // Candidate is not available. Seek all. | |
300 | + for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++) { | |
301 | + if (g_var_size[i]==0) { | |
302 | + g_temp_var_num_candidate=i+1; | |
303 | + return i; | |
304 | + } | |
305 | + } | |
306 | + err_no_block(); | |
307 | + return 0; | |
308 | +} | |
309 | + | |
310 | +int get_varnum_from_address(void* address){ | |
311 | + int i; | |
312 | + for (i=0;i<ALLOC_BLOCK_NUM;i++){ | |
313 | + if (g_var_mem[i]==(int)address) return i; | |
314 | + } | |
315 | + // not found | |
316 | + return -1; | |
317 | +} | |
318 | + | |
319 | +void* lib_calloc_memory(int size){ | |
320 | + // Allocate memory and return address | |
321 | + return calloc_memory(size,get_permanent_var_num()); | |
322 | +} | |
323 | + | |
324 | +void lib_delete(int* object){ | |
325 | + // Remove region that fit to object | |
326 | + free_non_temp_str((char*)object); | |
327 | +} |
@@ -0,0 +1,644 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +#include <xc.h> | |
9 | +#include "compiler.h" | |
10 | +#include "api.h" | |
11 | + | |
12 | +/* | |
13 | + Timer3: 1/32 prescaler, toggle mode :750000 Hz | |
14 | + PR3=1704 <-> 440 Hz | |
15 | + Shift tone for 2048 <--> ~440 Hz. | |
16 | + x 1705 / 2048 = 213 / 256 + 1 / 2048 | |
17 | + | |
18 | +*/ | |
19 | + | |
20 | +/* | |
21 | + c: 1434 | |
22 | + B: 1519 | |
23 | + A#: 1609 | |
24 | + A: 1705 | |
25 | + G#: 1806 | |
26 | + G: 1914 | |
27 | + F#: 2028 | |
28 | + F: 2148 | |
29 | + E: 2276 | |
30 | + D#: 2411 | |
31 | + D: 2555 | |
32 | + C#: 2707 | |
33 | + C: 2867 | |
34 | + Cb: 3038 | |
35 | +*/ | |
36 | + | |
37 | +const static int g_keys[]={ | |
38 | + 1609,1434,2707,2411,2148,2028,1806,// 0 7# C# A#m | |
39 | + 1609,1519,2707,2411,2148,2028,1806,// 7 6# F# D#m | |
40 | + 1609,1519,2707,2411,2276,2028,1806,// 14 5# B G#m | |
41 | + 1705,1519,2707,2411,2276,2028,1806,// 21 4# E C#m | |
42 | + 1705,1519,2707,2555,2276,2028,1806,// 28 3# A F#m | |
43 | + 1705,1519,2707,2555,2276,2028,1914,// 35 2# D Bm | |
44 | + 1705,1519,2867,2555,2276,2028,1914,// 42 1# G Em | |
45 | + 1705,1519,2867,2555,2276,2148,1914,// 49 0 C Am | |
46 | + 1705,1609,2867,2555,2276,2148,1914,// 56 1b F Dm | |
47 | + 1705,1609,2867,2555,2411,2148,1914,// 63 2b Bb Gm | |
48 | + 1806,1609,2867,2555,2411,2148,1914,// 70 3b Eb Cm | |
49 | + 1806,1609,2867,2707,2411,2148,1914,// 77 4b Ab Fm | |
50 | + 1806,1609,2867,2707,2411,2148,2028,// 84 5b Db Bbm | |
51 | + 1806,1609,3038,2707,2411,2148,2028,// 91 6b Gb Ebm | |
52 | + 1806,1609,3038,2707,2411,2276,2028 // 98 7b Cb Abm | |
53 | +}; | |
54 | + | |
55 | +/* | |
56 | + 2^(1/12) ~= 69433/(2^16) | |
57 | + 1/(2^(1/12) ~= 1933/(2^11) | |
58 | +*/ | |
59 | + | |
60 | +#define toneFlat(x) ((((unsigned long)(x))*69433)>>16) | |
61 | +#define toneSharp(x) ((((unsigned long)(x))*1933)>>11) | |
62 | + | |
63 | +/* local global vars */ | |
64 | +static int* g_tones; | |
65 | +static int g_qvalue; | |
66 | +static int g_lvalue; | |
67 | +static int g_mpoint; | |
68 | +static char* g_mstr; | |
69 | +static int g_mspos; | |
70 | +static unsigned short g_music[32]; | |
71 | +static unsigned short g_sound[32]; | |
72 | +static unsigned short g_musiclen[32]; | |
73 | +static unsigned char g_soundlen[32]; | |
74 | +static int g_musicstart; | |
75 | +static int g_musicend; | |
76 | +static int g_musicwait; | |
77 | +static int g_soundstart; | |
78 | +static int g_soundend; | |
79 | +static int g_soundwait; | |
80 | +static int g_soundrepeat; | |
81 | + | |
82 | +static char g_sound_mode=0; | |
83 | +static FSFILE* g_fhandle=0; | |
84 | +static char* g_wavtable=0; | |
85 | + | |
86 | +#define SOUND_MODE_MUSIC 1 | |
87 | +#define SOUND_MODE_WAVE 2 | |
88 | + | |
89 | +#define start_dma() T4CONSET=0x8000; DCH2CONSET=0x00000080; g_sound_mode=SOUND_MODE_WAVE | |
90 | +#define stop_dma() T4CONCLR=0x8000; DCH2CONCLR=0x00000080; g_sound_mode=SOUND_MODE_MUSIC | |
91 | + | |
92 | +int waveRemaining(int mode){ | |
93 | + if (!g_fhandle) return 0; | |
94 | + switch(mode){ | |
95 | + case 1: // current position (header excluded) | |
96 | + return g_fhandle->seek-0x2c; | |
97 | + break; | |
98 | + case 2: // file size (header excluded) | |
99 | + return g_fhandle->size-0x2c; | |
100 | + break; | |
101 | + case 0: // remaining | |
102 | + default: | |
103 | + return g_fhandle->size-g_fhandle->seek; | |
104 | + break; | |
105 | + } | |
106 | +} | |
107 | +int musicRemaining(int flagsLR){ | |
108 | + // flagsLR is ignored | |
109 | + return (g_musicend-g_musicstart)&31; | |
110 | +} | |
111 | + | |
112 | +void musicint(){ | |
113 | + unsigned int i; | |
114 | + static unsigned short wavtable_pos; | |
115 | + // This function is called every 1/60 sec. | |
116 | + switch(g_sound_mode){ | |
117 | + case SOUND_MODE_MUSIC: | |
118 | + if (g_soundstart!=g_soundend){ | |
119 | + // Start timer & OC4 | |
120 | + i=g_sound[g_soundstart]; | |
121 | + if (i<0xffff) { | |
122 | + T3CONSET=0x8000; | |
123 | + PR3=i; | |
124 | + if (i<TMR3) TMR3=0; | |
125 | + } else { | |
126 | + T3CONCLR=0x8000; | |
127 | + } | |
128 | + if ((--g_soundwait)<=0) { | |
129 | + g_soundstart++; | |
130 | + if (g_soundstart==g_soundend || 31<g_soundstart) { | |
131 | + g_soundstart=0; | |
132 | + g_soundrepeat--; | |
133 | + if (0<g_soundrepeat) { | |
134 | + g_soundwait=g_soundlen[g_soundstart]; | |
135 | + } else { | |
136 | + g_soundend=g_soundrepeat=g_soundwait=0; | |
137 | + } | |
138 | + } else { | |
139 | + g_soundwait=g_soundlen[g_soundstart]; | |
140 | + } | |
141 | + } | |
142 | + // Shift music data even though without output. | |
143 | + if (g_musicstart!=g_musicend) { | |
144 | + if ((--g_musicwait)<=0) { | |
145 | + g_musicstart++; | |
146 | + g_musicstart&=31; | |
147 | + g_musicwait=g_musiclen[g_musicstart]; | |
148 | + } | |
149 | + } | |
150 | + } else if (g_musicstart!=g_musicend) { | |
151 | + // Start timer & OC4 | |
152 | + i=g_music[g_musicstart]; | |
153 | + if (i<0xffff) { | |
154 | + T3CONSET=0x8000; | |
155 | + PR3=i; | |
156 | + if (i<TMR3) TMR3=0; | |
157 | + } else { | |
158 | + T3CONCLR=0x8000; | |
159 | + } | |
160 | + if ((--g_musicwait)<=0) { | |
161 | + g_musicstart++; | |
162 | + g_musicstart&=31; | |
163 | + g_musicwait=g_musiclen[g_musicstart]; | |
164 | + if (((g_musicstart+1)&31)==g_musicend) { | |
165 | + // Raise MUSIC interrupt flag | |
166 | + raise_interrupt_flag(INTERRUPT_MUSIC); | |
167 | + } | |
168 | + } | |
169 | + } else { | |
170 | + // Stop timer | |
171 | + T3CONCLR=0x8000; | |
172 | + } | |
173 | + break; | |
174 | + case SOUND_MODE_WAVE: | |
175 | + // Initialize parameters | |
176 | + if (!T4CONbits.ON){ | |
177 | + start_dma(); | |
178 | + wavtable_pos=0; | |
179 | + } | |
180 | + wavtable_pos=262-wavtable_pos; | |
181 | + // Read from file | |
182 | + if (0 == FSfread((void*)&g_wavtable[wavtable_pos],1,262,g_fhandle)) { | |
183 | + // End of file. | |
184 | + stop_dma(); | |
185 | + FSfclose(g_fhandle); | |
186 | + g_fhandle=0; | |
187 | + g_sound_mode=SOUND_MODE_MUSIC; | |
188 | + stop_music(); | |
189 | + // Raise WAVE interrupt flag | |
190 | + raise_interrupt_flag(INTERRUPT_WAVE); | |
191 | + break; | |
192 | + } | |
193 | + break; | |
194 | + default: | |
195 | + break; | |
196 | + } | |
197 | +} | |
198 | + | |
199 | +int musicGetNum(){ | |
200 | + int i, ret; | |
201 | + char b; | |
202 | + // Skip non number character | |
203 | + for(i=0;(b=g_mstr[g_mspos+i])<'0' && '9'<g_mstr[g_mspos+i];i++); | |
204 | + // Determine the number | |
205 | + ret=0; | |
206 | + while('0'<=b && b<='9'){ | |
207 | + ret*=10; | |
208 | + ret+=b-'0'; | |
209 | + i++; | |
210 | + b=g_mstr[g_mspos+i]; | |
211 | + } | |
212 | + g_mspos+=i; | |
213 | + return ret; | |
214 | +} | |
215 | + | |
216 | +void stop_music(){ | |
217 | + // Initialize normal music mode. | |
218 | + | |
219 | + // Use Timer3 and OC4 for sound. | |
220 | + RPA2R=5; //Use RPA2 for OC4 | |
221 | + OC4R=0; | |
222 | + OC4CON=0x000b; // Timer3, toggle mode | |
223 | + OC4CONSET=0x8000;// Start OC4 | |
224 | + T3CON=0x0050; // Prescaller: 1:32 (1.5 MHz), not yet started | |
225 | + | |
226 | + // Initializations for music/sound. | |
227 | + g_musicstart=g_musicend=g_musicwait=g_soundstart=g_soundend=g_soundwait=g_soundrepeat=0; | |
228 | + g_sound_mode=SOUND_MODE_MUSIC; | |
229 | + | |
230 | + // Initialize DMA (see also init_dma_music()) | |
231 | + | |
232 | + // Stop Timer4 | |
233 | + T4CON=0x0000; // Not start yet | |
234 | + | |
235 | + // Enable DMA, stop DMA2 | |
236 | + DMACONSET=0x8000; | |
237 | + DCH2CONCLR=0x0080; | |
238 | + | |
239 | + // Close handle if open. | |
240 | + if (g_fhandle) FSfclose(g_fhandle); | |
241 | + g_fhandle=0; | |
242 | + | |
243 | + // Inactive music first | |
244 | + g_music_active=0; | |
245 | +} | |
246 | + | |
247 | +void init_music(){ | |
248 | + // Initilize music system | |
249 | + stop_music(); | |
250 | + | |
251 | + // Initializations for music/sound. | |
252 | + g_qvalue=160; // Q: 1/4=90 | |
253 | + g_lvalue=20; // L: 1/8 | |
254 | + g_tones=(int*)&(g_keys[49]); // C major | |
255 | +} | |
256 | + | |
257 | +void musicSetL(){ | |
258 | + // Set length of a character. | |
259 | + // Syntax: L:n/m, where n and m are numbers. | |
260 | + int n,m; | |
261 | + n=musicGetNum(); | |
262 | + g_mspos++; | |
263 | + m=musicGetNum(); | |
264 | + g_lvalue=g_qvalue*n/m; | |
265 | +} | |
266 | + | |
267 | +void musicSetQ(){ | |
268 | + int i; | |
269 | + // Syntax: Q:1/4=n, where n is number. | |
270 | + // Skip "1/4=" | |
271 | + for(i=0;g_mstr[g_mspos+i]!='=';i++); | |
272 | + g_mspos+=i+1; | |
273 | + i=musicGetNum(); | |
274 | + if (i<48) { g_qvalue=320; /* 1/4=45 */ } | |
275 | + else if (i<53) { g_qvalue=288; /* 1/4=50 */ } | |
276 | + else if (i<60) { g_qvalue=256; /* 1/4=56 */ } | |
277 | + else if (i<70) { g_qvalue=224; /* 1/4=64 */ } | |
278 | + else if (i<83) { g_qvalue=192; /* 1/4=75 */ } | |
279 | + else if (i<102) { g_qvalue=160; /* 1/4=90 */ } | |
280 | + else if (i<132) { g_qvalue=128; /* 1/4=113 */ } | |
281 | + else if (i<188) { g_qvalue=96; /* 1/4=150 */ } | |
282 | + else { g_qvalue=64; /* 1/4=225 */ } | |
283 | + g_lvalue=g_qvalue>>3; | |
284 | +} | |
285 | + | |
286 | +void musicSetK(){ | |
287 | + // Syntax: K:xxx | |
288 | + if (!strncmp((char*)&(g_mstr[g_mspos]),"A#m",3)) { | |
289 | + g_mspos+=3; | |
290 | + g_tones=(int*)&(g_keys[0]); | |
291 | + return; | |
292 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"D#m",3)) { | |
293 | + g_mspos+=3; | |
294 | + g_tones=(int*)&(g_keys[7]); | |
295 | + return; | |
296 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"G#m",3)) { | |
297 | + g_mspos+=3; | |
298 | + g_tones=(int*)&(g_keys[14]); | |
299 | + return; | |
300 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"C#m",3)) { | |
301 | + g_mspos+=3; | |
302 | + g_tones=(int*)&(g_keys[21]); | |
303 | + return; | |
304 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"F#m",3)) { | |
305 | + g_mspos+=3; | |
306 | + g_tones=(int*)&(g_keys[28]); | |
307 | + return; | |
308 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Bbm",3)) { | |
309 | + g_mspos+=3; | |
310 | + g_tones=(int*)&(g_keys[84]); | |
311 | + return; | |
312 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Ebm",3)) { | |
313 | + g_mspos+=3; | |
314 | + g_tones=(int*)&(g_keys[91]); | |
315 | + return; | |
316 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Abm",3)) { | |
317 | + g_mspos+=3; | |
318 | + g_tones=(int*)&(g_keys[98]); | |
319 | + return; | |
320 | + } | |
321 | + if (!strncmp((char*)&(g_mstr[g_mspos]),"C#",2)) { | |
322 | + g_mspos+=2; | |
323 | + g_tones=(int*)&(g_keys[0]); | |
324 | + return; | |
325 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"F#",2)) { | |
326 | + g_mspos+=2; | |
327 | + g_tones=(int*)&(g_keys[7]); | |
328 | + return; | |
329 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Bm",2)) { | |
330 | + g_mspos+=2; | |
331 | + g_tones=(int*)&(g_keys[35]); | |
332 | + return; | |
333 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Em",2)) { | |
334 | + g_mspos+=2; | |
335 | + g_tones=(int*)&(g_keys[42]); | |
336 | + return; | |
337 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Am",2)) { | |
338 | + g_mspos+=2; | |
339 | + g_tones=(int*)&(g_keys[49]); | |
340 | + return; | |
341 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Dm",2)) { | |
342 | + g_mspos+=2; | |
343 | + g_tones=(int*)&(g_keys[56]); | |
344 | + return; | |
345 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Gm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Bb",2)) { | |
346 | + g_mspos+=2; | |
347 | + g_tones=(int*)&(g_keys[63]); | |
348 | + return; | |
349 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Cm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Eb",2)) { | |
350 | + g_mspos+=2; | |
351 | + g_tones=(int*)&(g_keys[70]); | |
352 | + return; | |
353 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Fm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Ab",2)) { | |
354 | + g_mspos+=2; | |
355 | + g_tones=(int*)&(g_keys[77]); | |
356 | + return; | |
357 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Db",2)) { | |
358 | + g_mspos+=2; | |
359 | + g_tones=(int*)&(g_keys[84]); | |
360 | + return; | |
361 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Gb",2)) { | |
362 | + g_mspos+=2; | |
363 | + g_tones=(int*)&(g_keys[91]); | |
364 | + return; | |
365 | + } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Cb",2)) { | |
366 | + g_mspos+=2; | |
367 | + g_tones=(int*)&(g_keys[98]); | |
368 | + return; | |
369 | + } | |
370 | + switch(g_mstr[g_mspos]){ | |
371 | + case 'B': | |
372 | + g_mspos++; | |
373 | + g_tones=(int*)&(g_keys[14]); | |
374 | + return; | |
375 | + case 'E': | |
376 | + g_mspos++; | |
377 | + g_tones=(int*)&(g_keys[21]); | |
378 | + return; | |
379 | + case 'A': | |
380 | + g_mspos++; | |
381 | + g_tones=(int*)&(g_keys[28]); | |
382 | + return; | |
383 | + case 'D': | |
384 | + g_mspos++; | |
385 | + g_tones=(int*)&(g_keys[35]); | |
386 | + return; | |
387 | + case 'G': | |
388 | + g_mspos++; | |
389 | + g_tones=(int*)&(g_keys[42]); | |
390 | + return; | |
391 | + case 'C': | |
392 | + g_mspos++; | |
393 | + g_tones=(int*)&(g_keys[49]); | |
394 | + return; | |
395 | + case 'F': | |
396 | + g_mspos++; | |
397 | + g_tones=(int*)&(g_keys[56]); | |
398 | + return; | |
399 | + default: | |
400 | + err_music(g_mstr); | |
401 | + break; | |
402 | + } | |
403 | +} | |
404 | +void musicSetM(){ | |
405 | + // Currently do nothing | |
406 | + musicGetNum(); | |
407 | + musicGetNum(); | |
408 | +} | |
409 | + | |
410 | +void set_sound(unsigned long* data, int flagsLR){ | |
411 | + // flagsLR is ignored | |
412 | + int sound; | |
413 | + int len; | |
414 | + int pos; | |
415 | + int datalen; | |
416 | + IEC0bits.T4IE=0; // Stop interruption, first. | |
417 | + // Initialize | |
418 | + g_soundrepeat=g_soundstart=g_soundend=0; | |
419 | + pos=0; | |
420 | + do { | |
421 | + while(data[1]!=0x00000020) data++; // Seek DATA statement | |
422 | + datalen=(data[0]&0x00007FFF)-1; // Use bgezal statement containing data length. | |
423 | + data+=2; | |
424 | + while(0<datalen){ | |
425 | + datalen--; | |
426 | + len=data[0]>>16; | |
427 | + sound=data[0]&0x0000FFFF; | |
428 | + data++; | |
429 | + if (len) { | |
430 | + // Shift tone for 2048 <--> ~440 Hz. | |
431 | + // 2048 must be changed to 1705 | |
432 | + // x 1705 / 2048 = 213 / 256 + 1 / 2048 | |
433 | + sound=213*(sound>>8)+(sound>>11); | |
434 | + g_sound[pos]=sound-1; | |
435 | + g_soundlen[pos]=len; | |
436 | + pos++; | |
437 | + if (32<pos) { | |
438 | + err_music("Sound data too long."); | |
439 | + return; | |
440 | + } | |
441 | + } else { | |
442 | + g_soundrepeat=sound; | |
443 | + break; | |
444 | + } | |
445 | + } | |
446 | + } while(len); | |
447 | + g_soundend=pos; | |
448 | + g_soundwait=g_soundlen[0]; | |
449 | + IEC0bits.T4IE=1; // Restart interrupt. | |
450 | + g_music_active=1;// Activate music system | |
451 | +} | |
452 | + | |
453 | +void set_music(char* str, int flagsLR){ | |
454 | + // flagsLR is ignored | |
455 | + char b; | |
456 | + unsigned long tone,tonenatural; | |
457 | + int len; | |
458 | + g_mstr=str; | |
459 | + g_mspos=0; | |
460 | + while(0<(b=g_mstr[g_mspos])){ | |
461 | + if (g_mstr[g_mspos+1]==':') { | |
462 | + // Set property | |
463 | + g_mspos+=2; | |
464 | + switch(b){ | |
465 | + case 'L': | |
466 | + musicSetL(); | |
467 | + break; | |
468 | + case 'Q': | |
469 | + musicSetQ(); | |
470 | + break; | |
471 | + case 'K': | |
472 | + musicSetK(); | |
473 | + break; | |
474 | + case 'M': | |
475 | + musicSetM(); | |
476 | + break; | |
477 | + default: | |
478 | + err_music(str); | |
479 | + break; | |
480 | + } | |
481 | + } else if ('A'<=b && b<='G' || 'a'<=b && b<='g' || b=='z') { | |
482 | + g_mspos++; | |
483 | + if (b=='z') { | |
484 | + tone=0; | |
485 | + } else if (b<='G') { | |
486 | + tone=g_tones[b-'A']; | |
487 | + tonenatural=g_keys[b-'A'+49]; | |
488 | + } else { | |
489 | + tone=g_tones[b-'a']>>1; | |
490 | + tonenatural=g_keys[b-'a'+49]>>1; | |
491 | + } | |
492 | + // Check "'"s | |
493 | + while(g_mstr[g_mspos]=='\''){ | |
494 | + g_mspos++; | |
495 | + tone>>=1; | |
496 | + } | |
497 | + // Check ","s | |
498 | + while(g_mstr[g_mspos]==','){ | |
499 | + g_mspos++; | |
500 | + tone<<=1; | |
501 | + tonenatural<<=1; | |
502 | + } | |
503 | + // Check "^","=","_" | |
504 | + switch(g_mstr[g_mspos]){ | |
505 | + case '^': | |
506 | + g_mspos++; | |
507 | + tone=toneSharp(tone); | |
508 | + break; | |
509 | + case '_': | |
510 | + g_mspos++; | |
511 | + tone=toneFlat(tone); | |
512 | + break; | |
513 | + case '=': | |
514 | + g_mspos++; | |
515 | + tone=tonenatural; | |
516 | + break; | |
517 | + default: | |
518 | + break; | |
519 | + } | |
520 | + // Check number for length | |
521 | + b=g_mstr[g_mspos]; | |
522 | + if ('0'<=b && b<='9') { | |
523 | + len=g_lvalue*musicGetNum(); | |
524 | + } else { | |
525 | + len=g_lvalue; | |
526 | + } | |
527 | + if (g_mstr[g_mspos]=='/') { | |
528 | + g_mspos++; | |
529 | + len=len/musicGetNum(); | |
530 | + } | |
531 | + // Shift tone if graphic is used | |
532 | + if (g_use_graphic) { | |
533 | + // MUL_15 instead of MUL_16 for CPU clock. | |
534 | + // tone=tone*15/16 | |
535 | + tone-=(tone+7)>>4; | |
536 | + } | |
537 | + // Update music value array | |
538 | + IEC0bits.T4IE=0; // Stop interruption, first. | |
539 | + if (g_musicstart==g_musicend) { | |
540 | + g_musicwait=len; | |
541 | + } | |
542 | + g_music[g_musicend]=(tone-1)&0x0000FFFF; | |
543 | + g_musiclen[g_musicend]=len; | |
544 | + g_musicend++; | |
545 | + g_musicend&=31; | |
546 | + IEC0bits.T4IE=1; // Restart interruption. | |
547 | + } else { | |
548 | + err_music(str); | |
549 | + } | |
550 | + // Go to next character | |
551 | + while(0<g_mstr[g_mspos] && g_mstr[g_mspos]<=0x20 || g_mstr[g_mspos]=='|') g_mspos++; | |
552 | + } | |
553 | + g_music_active=1;// Activate music system | |
554 | +} | |
555 | + | |
556 | +/* | |
557 | + PLAYWAVE routines follow | |
558 | +*/ | |
559 | + | |
560 | +int checkChars(char* str1, char* str2, int num){ | |
561 | + int i; | |
562 | + for(i=0;i<num;i++){ | |
563 | + if (str1[i]!=str2[i]) return 1; | |
564 | + } | |
565 | + return 0; | |
566 | +} | |
567 | + | |
568 | +void init_dma_music(){ | |
569 | + // Timer4 for 15700 Hz | |
570 | + T4CON=0x0000; // Not start yet | |
571 | + if (g_use_graphic) { | |
572 | + PR4=3405-1; | |
573 | + } else { | |
574 | + PR4=3632-1; | |
575 | + } | |
576 | + TMR4=PR4-1; | |
577 | + | |
578 | + // Timer3 for PWM | |
579 | + TMR3=0; | |
580 | + PR3=0x100; | |
581 | + T3CON=0x8000; | |
582 | + | |
583 | + // OC4 setting | |
584 | + RPA2R=5; //Use RPA2 for OC4 | |
585 | + OC4RS=0x80; | |
586 | + OC4CON=0x000e; | |
587 | + OC4CONSET=0x8000; | |
588 | + | |
589 | + //DMA2 settings for OC4 | |
590 | + DMACONSET=0x8000; | |
591 | + DCH2CON=0x00000012; // CHBUSY=0, CHCHNS=0, CHEN=0, CHAED=0, CHCHN=0, CHAEN=1, CHEDET=0, CHPRI=b10 | |
592 | + DCH2ECON=0x1310; // CHAIRQ=0, CHSIRQ=19, CFORCE=0, CABRT=0, PATEN=0, SIRQEN=1, AIRQEN=0 | |
593 | + // CHSIRQ=19: Timer4 interrupt | |
594 | + DCH2SSA=((unsigned int)&(g_wavtable[0]))&0x1fffffff; | |
595 | + DCH2DSA=0x1F803620; // OC4RS | |
596 | + DCH2SSIZ=524; | |
597 | + DCH2DSIZ=1; | |
598 | + DCH2CSIZ=1; | |
599 | + DCH2INTCLR=0x00FF00FF; | |
600 | + DCH2CONSET=0x00000080; | |
601 | +} | |
602 | + | |
603 | +void play_wave(char* filename, int start){ | |
604 | + int i; | |
605 | + // Stop the previous play | |
606 | + stop_music(); | |
607 | + // Exit function if null filename | |
608 | + if (filename[0]==0x00) { | |
609 | + return; | |
610 | + } | |
611 | + // Alocate 524 byte buffer if not assigned | |
612 | + if (g_var_size[ALLOC_WAVE_BLOCK]==0) { | |
613 | + g_wavtable=(char*)alloc_memory(524/4,ALLOC_WAVE_BLOCK); | |
614 | + } | |
615 | + // Open file | |
616 | + if (g_fhandle) FSfclose(g_fhandle); | |
617 | + g_fhandle=FSfopen(filename,"r"); | |
618 | + if (!g_fhandle) err_file(); | |
619 | + // Read header and check if monaural 8 bit 16000 Hz. | |
620 | + if (0x2c != FSfread((void*)&g_wavtable[0],1,0x2c,g_fhandle)) err_file(); | |
621 | + i=0; | |
622 | + i+=checkChars((char*)&g_wavtable[0],"RIFF",4); // Check RIFF | |
623 | + i+=checkChars((char*)&g_wavtable[8],"WAVEfmt ",8); // Check WAVE and fmt | |
624 | + i+=checkChars((char*)&g_wavtable[16],"\x10\x00\x00\x00\x01\x00",6); // Check if liear PCM | |
625 | + if (!checkChars((char*)&g_wavtable[22],"\x01\x00\x80\x3e\x00\x00\x80\x3e\x00\x00\x01\x00",12)) { | |
626 | + // Monaural 16000 Hz | |
627 | + } else if (!checkChars((char*)&g_wavtable[22],"\x01\x00\x54\x3d\x00\x00\x54\x3d\x00\x00\x01\x00",12)) { | |
628 | + // Monaural 15700 Hz | |
629 | + } else { | |
630 | + i=1; | |
631 | + } | |
632 | + i+=checkChars((char*)&g_wavtable[34],"\x08\x00\x64\x61\x74\x61",6); // Check bit # and data | |
633 | + if (i) err_wave(); | |
634 | + // Support defined start position here to skip file pointer here. | |
635 | + FSfseek(g_fhandle, start, SEEK_CUR); | |
636 | + // Read first 262 bytes. | |
637 | + if (262 != FSfread((void*)&g_wavtable[0],1,262,g_fhandle)) err_file(); | |
638 | + | |
639 | + // Initialize DMA | |
640 | + init_dma_music(); | |
641 | + g_sound_mode=SOUND_MODE_WAVE; | |
642 | + | |
643 | + g_music_active=1;// Activate music system | |
644 | +} |
@@ -0,0 +1,277 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "compiler.h" | |
13 | + | |
14 | +/* | |
15 | +Operators: (upper ones have higher priority | |
16 | +() | |
17 | +* / % | |
18 | ++ - | |
19 | +<< >> | |
20 | +< <= > >= | |
21 | += != | |
22 | +XOR | |
23 | +AND | |
24 | +OR | |
25 | +*/ | |
26 | + | |
27 | + | |
28 | +const unsigned char g_priority[]={ | |
29 | + 0, // OP_VOID | |
30 | + 1, // OP_OR | |
31 | + 2, // OP_AND | |
32 | + 3, // OP_XOR | |
33 | + 4,4, // OP_EQ, OP_NEQ | |
34 | + 5,5,5,5, // OP_LT, OP_LTE, OP_MT, OP_MTE | |
35 | + 6,6, // OP_SHL, OP_SHR | |
36 | + 7,7, // OP_ADD, OP_SUB | |
37 | + 8,8,8 // OP_MUL, OP_DIV, OP_REM | |
38 | +}; | |
39 | + | |
40 | +enum operator g_last_op; | |
41 | + | |
42 | +char* get_operator(void){ | |
43 | + char b1,b2,b3; | |
44 | + next_position(); | |
45 | + b1=g_source[g_srcpos]; | |
46 | + b2=g_source[g_srcpos+1]; | |
47 | + b3=g_source[g_srcpos+2]; | |
48 | + switch(b1){ | |
49 | + case '%': g_last_op=OP_REM; break; | |
50 | + case '/': g_last_op=OP_DIV; break; | |
51 | + case '*': g_last_op=OP_MUL; break; | |
52 | + case '-': g_last_op=OP_SUB; break; | |
53 | + case '+': g_last_op=OP_ADD; break; | |
54 | + case '>': | |
55 | + if (b2=='>') { | |
56 | + g_srcpos++; | |
57 | + g_last_op=OP_SHR; | |
58 | + } else if (b2=='=') { | |
59 | + g_srcpos++; | |
60 | + g_last_op=OP_MTE; | |
61 | + } else { | |
62 | + g_last_op=OP_MT; | |
63 | + } | |
64 | + break; | |
65 | + case '<': | |
66 | + if (b2=='<') { | |
67 | + g_srcpos++; | |
68 | + g_last_op=OP_SHL; | |
69 | + } else if (b2=='=') { | |
70 | + g_srcpos++; | |
71 | + g_last_op=OP_LTE; | |
72 | + } else { | |
73 | + g_last_op=OP_LT; | |
74 | + } | |
75 | + break; | |
76 | + case '!': | |
77 | + if (b2!='=') return ERR_SYNTAX; | |
78 | + g_srcpos++; | |
79 | + g_last_op=OP_NEQ; | |
80 | + break; | |
81 | + case '=': | |
82 | + if (b2=='=') g_srcpos++; | |
83 | + g_last_op=OP_EQ; | |
84 | + break; | |
85 | + case 'X': | |
86 | + if (b2!='O') return ERR_SYNTAX; | |
87 | + if (b3!='R') return ERR_SYNTAX; | |
88 | + g_srcpos++; | |
89 | + g_srcpos++; | |
90 | + g_last_op=OP_XOR; | |
91 | + break; | |
92 | + case 'O': | |
93 | + if (b2!='R') return ERR_SYNTAX; | |
94 | + g_srcpos++; | |
95 | + g_last_op=OP_OR; | |
96 | + break; | |
97 | + case 'A': | |
98 | + if (b2!='N') return ERR_SYNTAX; | |
99 | + if (b3!='D') return ERR_SYNTAX; | |
100 | + g_srcpos++; | |
101 | + g_srcpos++; | |
102 | + g_last_op=OP_AND; | |
103 | + break; | |
104 | + default: | |
105 | + return ERR_SYNTAX; | |
106 | + } | |
107 | + g_srcpos++; | |
108 | + return 0; | |
109 | +} | |
110 | + | |
111 | +char* get_floatOperator(void){ | |
112 | + char* err; | |
113 | + int spos; | |
114 | + next_position(); | |
115 | + spos=g_srcpos; | |
116 | + err=get_operator(); | |
117 | + if (err) return err; | |
118 | + switch(g_last_op){ | |
119 | + // Following operators cannot be used for float values. | |
120 | + case OP_XOR: | |
121 | + case OP_REM: | |
122 | + case OP_SHR: | |
123 | + case OP_SHL: | |
124 | + g_srcpos=spos; | |
125 | + return ERR_SYNTAX; | |
126 | + default: | |
127 | + return 0; | |
128 | + } | |
129 | +} | |
130 | + | |
131 | +char* calculation(enum operator op){ | |
132 | + // $v0 = $v1 <op> $v0; | |
133 | + switch(op){ | |
134 | + case OP_OR: | |
135 | + check_obj_space(1); | |
136 | + g_object[g_objpos++]=0x00621025; // or v0,v1,v0 | |
137 | + break; | |
138 | + case OP_AND: | |
139 | + check_obj_space(1); | |
140 | + g_object[g_objpos++]=0x00621024; // and v0,v1,v0 | |
141 | + break; | |
142 | + case OP_XOR: | |
143 | + check_obj_space(1); | |
144 | + g_object[g_objpos++]=0x00621026; // xor v0,v1,v0 | |
145 | + break; | |
146 | + case OP_EQ: | |
147 | + check_obj_space(2); | |
148 | + g_object[g_objpos++]=0x00621026; // xor v0,v1,v0 | |
149 | + g_object[g_objpos++]=0x2C420001; // sltiu v0,v0,1 | |
150 | + break; | |
151 | + case OP_NEQ: | |
152 | + check_obj_space(2); | |
153 | + g_object[g_objpos++]=0x00621026; // xor v0,v1,v0 | |
154 | + g_object[g_objpos++]=0x0002102B; // sltu v0,zero,v0 | |
155 | + break; | |
156 | + case OP_LT: | |
157 | + check_obj_space(1); | |
158 | + g_object[g_objpos++]=0x0062102A; // slt v0,v1,v0 | |
159 | + break; | |
160 | + case OP_LTE: | |
161 | + check_obj_space(2); | |
162 | + g_object[g_objpos++]=0x0043102A; // slt v0,v0,v1 | |
163 | + g_object[g_objpos++]=0x38420001; // xori v0,v0,0x1 | |
164 | + break; | |
165 | + case OP_MT: | |
166 | + check_obj_space(1); | |
167 | + g_object[g_objpos++]=0x0043102A; // slt v0,v0,v1 | |
168 | + break; | |
169 | + case OP_MTE: | |
170 | + check_obj_space(2); | |
171 | + g_object[g_objpos++]=0x0062102A; // slt v0,v1,v0 | |
172 | + g_object[g_objpos++]=0x38420001; // xori v0,v0,0x1 | |
173 | + break; | |
174 | + case OP_SHR: | |
175 | + check_obj_space(1); | |
176 | + g_object[g_objpos++]=0x00431006; // srlv v0,v1,v0 | |
177 | + break; | |
178 | + case OP_SHL: | |
179 | + check_obj_space(1); | |
180 | + g_object[g_objpos++]=0x00431004; // sllv v0,v1,v0 | |
181 | + break; | |
182 | + case OP_ADD: | |
183 | + check_obj_space(1); | |
184 | + g_object[g_objpos++]=0x00621021; // addu v0,v1,v0 | |
185 | + break; | |
186 | + case OP_SUB: | |
187 | + check_obj_space(1); | |
188 | + g_object[g_objpos++]=0x00621023; // subu v0,v1,v0 | |
189 | + break; | |
190 | + case OP_MUL: | |
191 | + check_obj_space(1); | |
192 | + g_object[g_objpos++]=0x70621002; // mul v0,v1,v0 | |
193 | + break; | |
194 | + case OP_DIV: | |
195 | + // Note that intterupt functions do not use mflo and mfhi. | |
196 | + // Probably using div does not cause delay of interrupt. | |
197 | + check_obj_space(5); | |
198 | + g_object[g_objpos++]=0x14400003; // bne v0,zero,label | |
199 | + g_object[g_objpos++]=0x0062001A; // div v1,v0 | |
200 | + call_lib_code(LIB_DIV0); // 2 words | |
201 | + // label: | |
202 | + g_object[g_objpos++]=0x00001012; // mflo v0 | |
203 | + break; | |
204 | + case OP_REM: | |
205 | + check_obj_space(5); | |
206 | + g_object[g_objpos++]=0x14400003; // bne v0,zero,label | |
207 | + g_object[g_objpos++]=0x0062001A; // div v1,v0 | |
208 | + call_lib_code(LIB_DIV0); // 2 words | |
209 | + // label: | |
210 | + g_object[g_objpos++]=0x00001010; // mfhi v0 | |
211 | + break; | |
212 | + default: | |
213 | + return ERR_SYNTAX; | |
214 | + } | |
215 | + return 0; | |
216 | +} | |
217 | + | |
218 | +char* calculation_float(enum operator op){ | |
219 | + // $v0 = $a0 <op> $v0; | |
220 | + // All the calculations will be done in library code, lib_float function (see below). | |
221 | + call_lib_code(LIB_FLOAT | op); | |
222 | + return 0; | |
223 | +} | |
224 | + | |
225 | +int lib_float(int ia0,int iv0, enum operator a1){ | |
226 | + // This function was called from _call_library(). | |
227 | + // Variable types must be all int. | |
228 | + // Casting cannot be used. | |
229 | + // Instead, by using pointer, put as int value, get as float value, | |
230 | + // calculate, put as float value, then get as int value for returning. | |
231 | + volatile float a0,v0; | |
232 | + ((int*)(&a0))[0]=ia0; | |
233 | + ((int*)(&v0))[0]=iv0; | |
234 | + switch(a1){ | |
235 | + case OP_EQ: | |
236 | + v0= a0==v0?1:0; | |
237 | + break; | |
238 | + case OP_NEQ: | |
239 | + v0= a0!=v0?1:0; | |
240 | + break; | |
241 | + case OP_LT: | |
242 | + v0= a0<v0?1:0; | |
243 | + break; | |
244 | + case OP_LTE: | |
245 | + v0= a0<=v0?1:0; | |
246 | + break; | |
247 | + case OP_MT: | |
248 | + v0= a0>v0?1:0; | |
249 | + break; | |
250 | + case OP_MTE: | |
251 | + v0= a0>=v0?1:0; | |
252 | + break; | |
253 | + case OP_ADD: | |
254 | + v0= a0+v0; | |
255 | + break; | |
256 | + case OP_SUB: | |
257 | + v0= a0-v0; | |
258 | + break; | |
259 | + case OP_MUL: | |
260 | + v0= a0*v0; | |
261 | + break; | |
262 | + case OP_DIV: | |
263 | + if (v0==0) err_div_zero(); | |
264 | + v0= a0/v0; | |
265 | + break; | |
266 | + case OP_OR: | |
267 | + v0= a0||v0?1:0; | |
268 | + break; | |
269 | + case OP_AND: | |
270 | + v0= a0&&v0?1:0; | |
271 | + break; | |
272 | + default: | |
273 | + err_unknown(); | |
274 | + return 0; | |
275 | + } | |
276 | + return ((int*)(&v0))[0]; | |
277 | +}; | |
\ No newline at end of file |
@@ -0,0 +1,210 @@ | ||
1 | +[HEADER] | |
2 | +magic_cookie={66E99B07-E706-4689-9E80-9B2582898A13} | |
3 | +file_version=1.0 | |
4 | +device=PIC32MX150F128B | |
5 | +[PATH_INFO] | |
6 | +BuildDirPolicy=BuildDirIsProjectDir | |
7 | +dir_src= | |
8 | +dir_bin= | |
9 | +dir_tmp= | |
10 | +dir_sin= | |
11 | +dir_inc= | |
12 | +dir_lib=C:\Program Files\Microchip\xc32\v1.42\pic32mx\lib | |
13 | +dir_lkr= | |
14 | +[CAT_FILTERS] | |
15 | +filter_src=*.s;*.c | |
16 | +filter_inc=*.h;*.inc | |
17 | +filter_obj=*.o | |
18 | +filter_lib=*.a | |
19 | +filter_lkr=*.ld | |
20 | +[CAT_SUBFOLDERS] | |
21 | +subfolder_src= | |
22 | +subfolder_inc= | |
23 | +subfolder_obj= | |
24 | +subfolder_lib= | |
25 | +subfolder_lkr= | |
26 | +[FILE_SUBFOLDERS] | |
27 | +file_000=. | |
28 | +file_001=. | |
29 | +file_002=. | |
30 | +file_003=. | |
31 | +file_004=. | |
32 | +file_005=. | |
33 | +file_006=. | |
34 | +file_007=. | |
35 | +file_008=. | |
36 | +file_009=. | |
37 | +file_010=. | |
38 | +file_011=. | |
39 | +file_012=. | |
40 | +file_013=. | |
41 | +file_014=. | |
42 | +file_015=. | |
43 | +file_016=. | |
44 | +file_017=. | |
45 | +file_018=. | |
46 | +file_019=. | |
47 | +file_020=. | |
48 | +file_021=. | |
49 | +file_022=. | |
50 | +file_023=. | |
51 | +file_024=. | |
52 | +file_025=. | |
53 | +file_026=. | |
54 | +file_027=. | |
55 | +file_028=. | |
56 | +file_029=. | |
57 | +file_030=. | |
58 | +file_031=. | |
59 | +file_032=. | |
60 | +file_033=. | |
61 | +file_034=. | |
62 | +file_035=. | |
63 | +file_036=. | |
64 | +file_037=. | |
65 | +file_038=. | |
66 | +file_039=. | |
67 | +file_040=. | |
68 | +[GENERATED_FILES] | |
69 | +file_000=no | |
70 | +file_001=no | |
71 | +file_002=no | |
72 | +file_003=no | |
73 | +file_004=no | |
74 | +file_005=no | |
75 | +file_006=no | |
76 | +file_007=no | |
77 | +file_008=no | |
78 | +file_009=no | |
79 | +file_010=no | |
80 | +file_011=no | |
81 | +file_012=no | |
82 | +file_013=no | |
83 | +file_014=no | |
84 | +file_015=no | |
85 | +file_016=no | |
86 | +file_017=no | |
87 | +file_018=no | |
88 | +file_019=no | |
89 | +file_020=no | |
90 | +file_021=no | |
91 | +file_022=no | |
92 | +file_023=no | |
93 | +file_024=no | |
94 | +file_025=no | |
95 | +file_026=no | |
96 | +file_027=no | |
97 | +file_028=no | |
98 | +file_029=no | |
99 | +file_030=no | |
100 | +file_031=no | |
101 | +file_032=no | |
102 | +file_033=no | |
103 | +file_034=no | |
104 | +file_035=no | |
105 | +file_036=no | |
106 | +file_037=no | |
107 | +file_038=no | |
108 | +file_039=no | |
109 | +file_040=no | |
110 | +[OTHER_FILES] | |
111 | +file_000=no | |
112 | +file_001=no | |
113 | +file_002=no | |
114 | +file_003=no | |
115 | +file_004=no | |
116 | +file_005=no | |
117 | +file_006=no | |
118 | +file_007=no | |
119 | +file_008=no | |
120 | +file_009=no | |
121 | +file_010=no | |
122 | +file_011=no | |
123 | +file_012=no | |
124 | +file_013=no | |
125 | +file_014=no | |
126 | +file_015=no | |
127 | +file_016=no | |
128 | +file_017=no | |
129 | +file_018=no | |
130 | +file_019=no | |
131 | +file_020=no | |
132 | +file_021=no | |
133 | +file_022=no | |
134 | +file_023=no | |
135 | +file_024=no | |
136 | +file_025=no | |
137 | +file_026=no | |
138 | +file_027=no | |
139 | +file_028=no | |
140 | +file_029=no | |
141 | +file_030=no | |
142 | +file_031=no | |
143 | +file_032=no | |
144 | +file_033=no | |
145 | +file_034=no | |
146 | +file_035=no | |
147 | +file_036=no | |
148 | +file_037=no | |
149 | +file_038=no | |
150 | +file_039=no | |
151 | +file_040=no | |
152 | +[FILE_INFO] | |
153 | +file_000=args.c | |
154 | +file_001=class.c | |
155 | +file_002=cmpdata.c | |
156 | +file_003=compiler.c | |
157 | +file_004=debug.c | |
158 | +file_005=editor.c | |
159 | +file_006=envspecific.c | |
160 | +file_007=error.c | |
161 | +file_008=exception.c | |
162 | +file_009=file.c | |
163 | +file_010=float.c | |
164 | +file_011=function.c | |
165 | +file_012=globalvars.c | |
166 | +file_013=library.c | |
167 | +file_014=linker.c | |
168 | +file_015=main.c | |
169 | +file_016=memory.c | |
170 | +file_017=music.c | |
171 | +file_018=operator.c | |
172 | +file_019=run.c | |
173 | +file_020=statement.c | |
174 | +file_021=string.c | |
175 | +file_022=timer.c | |
176 | +file_023=value.c | |
177 | +file_024=varname.c | |
178 | +file_025=interface\graphlib.c | |
179 | +file_026=interface\keyinput.c | |
180 | +file_027=interface\LCDdriver.c | |
181 | +file_028=api.h | |
182 | +file_029=compiler.h | |
183 | +file_030=debug.h | |
184 | +file_031=editor.h | |
185 | +file_032=envspecific.h | |
186 | +file_033=main.h | |
187 | +file_034=interface\keyinput.h | |
188 | +file_035=interface\LCDdriver.h | |
189 | +file_036=interface\ps2keyboard.h | |
190 | +file_037=interface\SDFSIO.h | |
191 | +file_038=interface\videoout.h | |
192 | +file_039=interface\libsdfsio.a | |
193 | +file_040=App_32MX170F256B.ld | |
194 | +[SUITE_INFO] | |
195 | +suite_guid={62D235D8-2DB2-49CD-AF24-5489A6015337} | |
196 | +suite_state= | |
197 | +[TOOL_SETTINGS] | |
198 | +TS{6F324298-6323-4781-8C43-43FA5E6F3646}=-gdwarf-2 | |
199 | +TS{1F324EFA-C0BA-4A8F-A85A-B21644939CAD}=-g -D_SUPPRESS_PLIB_WARNING -O1 | |
200 | +TS{29D3B6CC-DCAB-4659-8011-FFF75BB7F8D7}=-o"$(BINDIR_)$(TARGETBASE).$(TARGETSUFFIX)" -Map="$(BINDIR_)$(TARGETBASE).map" | |
201 | +TS{AD4C3FBD-B6BB-4F50-AB4E-35BF132D4D60}= | |
202 | +[INSTRUMENTED_TRACE] | |
203 | +enable=0 | |
204 | +transport=0 | |
205 | +format=0 | |
206 | +[CUSTOM_BUILD] | |
207 | +Pre-Build= | |
208 | +Pre-BuildEnabled=1 | |
209 | +Post-Build= | |
210 | +Post-BuildEnabled=1 |
@@ -0,0 +1,133 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by K.Tanaka & Katsumi | |
4 | + http://www.ze.em-net.ne.jp/~kenken/index.html | |
5 | + http://hp.vector.co.jp/authors/VA016157/ | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include <xc.h> | |
13 | +#include "api.h" | |
14 | +#include "compiler.h" | |
15 | +#include "editor.h" | |
16 | +#include "main.h" | |
17 | + | |
18 | +char* printdec(int num){ | |
19 | + char str[11]; | |
20 | + int i; | |
21 | + if (num<0) { | |
22 | + printchar('-'); | |
23 | + num=0-num; | |
24 | + } | |
25 | + for(i=10;0<i;i--){ | |
26 | + if (num==0 && i<10) break; | |
27 | + str[i]='0'+rem10_32(num); | |
28 | + num=div10_32(num); | |
29 | + } | |
30 | + for(i++;i<11;i++) { | |
31 | + printchar(str[i]); | |
32 | + } | |
33 | +} | |
34 | + | |
35 | +int runbasic(char *appname,int test){ | |
36 | +// BASICソースのコンパイルと実行 | |
37 | +// appname 実行するBASICソースファイル | |
38 | +// test 0:コンパイルと実行、0以外:コンパイルのみで終了 | |
39 | +// | |
40 | +// 戻り値 | |
41 | +// 0:正常終了 | |
42 | +// -1:ファイルエラー | |
43 | +// -2:リンクエラー | |
44 | +// 1以上:コンパイルエラーの発生行(行番号ではなくファイル上の何行目か) | |
45 | + int i; | |
46 | + char* buff; | |
47 | + char* err; | |
48 | + | |
49 | + // Set grobal pointer | |
50 | + g_gp=get_gp(); | |
51 | + // Set buffer positions | |
52 | + buff=(char*)&(RAM[RAMSIZE-512]); | |
53 | + // Set object positions | |
54 | + g_object=(int*)(&RAM[0]); | |
55 | + g_objpos=0; | |
56 | + g_objmax=g_object+(RAMSIZE-512)/4; // Buffer area excluded. | |
57 | + // Clear object area | |
58 | + for(i=0;i<RAMSIZE/4;i++) g_object[i]=0x00000000; | |
59 | + | |
60 | + // Check file error | |
61 | + err=init_file(buff,appname); | |
62 | + if (err) { | |
63 | + setcursorcolor(COLOR_ERRORTEXT); | |
64 | + printstr("Can't Open "); | |
65 | + printstr(appname); | |
66 | + printchar('\n'); | |
67 | + return -1; | |
68 | + } | |
69 | + close_file(); | |
70 | + | |
71 | + // Initialize parameters | |
72 | + g_pcg_font=0; | |
73 | + g_use_graphic=0; | |
74 | + g_graphic_area=0; | |
75 | + clearscreen(); | |
76 | + setcursor(0,0,7); | |
77 | + g_long_name_var_num=0; | |
78 | + cmpdata_init(); | |
79 | + | |
80 | + // Initialize music system | |
81 | + init_music(); | |
82 | + | |
83 | + printstr("BASIC "BASVER"\n"); | |
84 | + wait60thsec(15); | |
85 | + | |
86 | + printstr("Compiling..."); | |
87 | + | |
88 | + // Compile the file | |
89 | + i=compile_and_link_main_file(buff,appname); | |
90 | + if (i) return i; | |
91 | + | |
92 | + // All done | |
93 | + printstr("done\n"); | |
94 | + if(test) return 0; //コンパイルのみの場合 | |
95 | + wait60thsec(15); | |
96 | + | |
97 | + // Initialize the other parameters | |
98 | + // Random seed | |
99 | + g_rnd_seed=0x92D68CA2; //2463534242 | |
100 | + // Clear variables | |
101 | + for(i=0;i<ALLOC_BLOCK_NUM;i++){ | |
102 | + g_var_mem[i]=0; | |
103 | + g_var_size[i]=0; | |
104 | + } | |
105 | + // Clear key input buffer | |
106 | + for(i=0;i<256;i++){ | |
107 | + ps2keystatus[i]=0; | |
108 | + } | |
109 | + // Reset data/read. | |
110 | + reset_dataread(); | |
111 | + // Initialize file system | |
112 | + lib_file(FUNC_FINIT,0,0,0); | |
113 | + | |
114 | + // Assign memory | |
115 | + set_free_area((void*)(g_object+g_objpos),(void*)(&RAM[RAMSIZE])); | |
116 | + | |
117 | + // Warm up environment | |
118 | + pre_run(); | |
119 | + init_timer(); | |
120 | + | |
121 | + // Execute program | |
122 | + // Start program from the beginning of RAM. | |
123 | + // Work area (used for A-Z values) is next to the object code area. | |
124 | + start_program((void*)(&(RAM[0])),(void*)(&g_var_mem[0])); | |
125 | + printstr("\nOK\n"); | |
126 | + | |
127 | + // Cool down environment | |
128 | + post_run(); | |
129 | + lib_file(FUNC_FINIT,0,0,0); | |
130 | + stop_timer(); | |
131 | + | |
132 | + return 0; | |
133 | +} |
@@ -0,0 +1,1771 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "api.h" | |
13 | +#include "compiler.h" | |
14 | + | |
15 | +char* rem_statement(){ | |
16 | + if (g_source[g_srcpos-4]<0x20) { | |
17 | + // This line contains only "REM" statement | |
18 | + // Delete $s6-setting command if exists. | |
19 | + if ((g_object[g_objpos-1]&0xffff0000)==0x34160000) g_objpos--; | |
20 | + } | |
21 | + while(0xE0 & g_source[g_srcpos]){ | |
22 | + g_srcpos++; | |
23 | + } | |
24 | + return 0; | |
25 | +} | |
26 | + | |
27 | +char* sound_statement(){ | |
28 | + char *err; | |
29 | + err=get_label(); | |
30 | + if (err) return err; | |
31 | + if (g_label) { | |
32 | + // Label/number is constant. | |
33 | + // Linker will change following codes later. | |
34 | + // Note that 0x0814xxxx and 0x0815xxxx are specific codes for these. | |
35 | + check_obj_space(2); | |
36 | + g_object[g_objpos++]=0x08140000|((g_label>>16)&0x0000FFFF); // lui v0,xxxx | |
37 | + g_object[g_objpos++]=0x08150000|(g_label&0x0000FFFF); // ori v0,v0,xxxx | |
38 | + } else { | |
39 | + // Label/number will be dynamically set when executing code. | |
40 | + err=get_value(); | |
41 | + if (err) return err; | |
42 | + call_lib_code(LIB_LABEL); | |
43 | + } | |
44 | + // 2nd param is optional | |
45 | + next_position(); | |
46 | + if (g_source[g_srcpos]==',') { | |
47 | + g_srcpos++; | |
48 | + check_obj_space(2); | |
49 | + g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 | |
50 | + g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp) | |
51 | + err=get_value(); | |
52 | + if (err) return err; | |
53 | + check_obj_space(3); | |
54 | + g_object[g_objpos++]=0x00402021; // addu a0,v0,zero | |
55 | + g_object[g_objpos++]=0x8FA20004; // lw v0,4(sp) | |
56 | + g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4 | |
57 | + } else { | |
58 | + // Set 3 if omitted | |
59 | + check_obj_space(1); | |
60 | + g_object[g_objpos++]=0x24040003; // addiu a0,zero,xx | |
61 | + } | |
62 | + call_lib_code(LIB_SOUND); | |
63 | + return 0; | |
64 | +} | |
65 | +char* music_statement(){ | |
66 | + char *err; | |
67 | + err=get_string(); | |
68 | + if (err) return err; | |
69 | + // 2nd param is optional | |
70 | + next_position(); | |
71 | + if (g_source[g_srcpos]==',') { | |
72 | + g_srcpos++; | |
73 | + check_obj_space(2); | |
74 | + g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 | |
75 | + g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp) | |
76 | + err=get_value(); | |
77 | + if (err) return err; | |
78 | + check_obj_space(3); | |
79 | + g_object[g_objpos++]=0x00402021; // addu a0,v0,zero | |
80 | + g_object[g_objpos++]=0x8FA20004; // lw v0,4(sp) | |
81 | + g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4 | |
82 | + } else { | |
83 | + // Set 3 if omitted | |
84 | + check_obj_space(1); | |
85 | + g_object[g_objpos++]=0x24040003; // addiu a0,zero,xx | |
86 | + } | |
87 | + call_lib_code(LIB_MUSIC); | |
88 | + return 0; | |
89 | +} | |
90 | + | |
91 | +char* exec_statement(){ | |
92 | + char *err; | |
93 | + char b1; | |
94 | + int i,prevpos; | |
95 | + b1=g_source[g_srcpos]; | |
96 | + while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){ | |
97 | + prevpos=g_objpos; | |
98 | + g_valueisconst=1; | |
99 | + err=get_simple_value(); | |
100 | + if (!g_valueisconst) err=ERR_SYNTAX; | |
101 | + if (err) return err; | |
102 | + check_obj_space(1); | |
103 | + g_objpos=prevpos; | |
104 | + g_object[g_objpos++]=g_intconst; | |
105 | + next_position(); | |
106 | + b1=g_source[g_srcpos]; | |
107 | + if (b1!=',') break; | |
108 | + g_srcpos++; | |
109 | + next_position(); | |
110 | + b1=g_source[g_srcpos]; | |
111 | + if (b1==0x0d || b1==0x0a) { | |
112 | + // Multiline DATA/EXEC statement | |
113 | + g_line++; | |
114 | + g_fileline++; | |
115 | + if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++; | |
116 | + g_srcpos++; | |
117 | + // Maintain at least 256 characters in cache. | |
118 | + if (256<=g_srcpos) read_file(256); | |
119 | + next_position(); | |
120 | + b1=g_source[g_srcpos]; | |
121 | + } | |
122 | + } | |
123 | + return 0; | |
124 | +} | |
125 | + | |
126 | +char* cdata_statement(){ | |
127 | + // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero) | |
128 | + // are the sign of data region | |
129 | + int beginpos,prevpos; | |
130 | + char* err; | |
131 | + char b1; | |
132 | + char* cpy; | |
133 | + int shift=0; | |
134 | + int i=0; | |
135 | + // This statement is not valid in class file. | |
136 | + if (g_compiling_class) return ERR_INVALID_CLASS; | |
137 | + beginpos=g_objpos; | |
138 | + check_obj_space(2); | |
139 | + g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx | |
140 | + g_object[g_objpos++]=0x00000020; // add zero,zero,zero | |
141 | + next_position(); | |
142 | + b1=g_source[g_srcpos]; | |
143 | + while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){ | |
144 | + prevpos=g_objpos; | |
145 | + g_valueisconst=1; | |
146 | + err=get_simple_value(); | |
147 | + if (!g_valueisconst) err=ERR_SYNTAX; | |
148 | + if (g_intconst<0x00 || 0xff<g_intconst) err=ERR_SYNTAX; | |
149 | + if (err) return err; | |
150 | + g_objpos=prevpos; | |
151 | + i|=g_intconst<<shift; | |
152 | + shift+=8; | |
153 | + if (32<=shift) { | |
154 | + check_obj_space(1); | |
155 | + g_object[g_objpos++]=i; | |
156 | + shift=0; | |
157 | + i=0; | |
158 | + } | |
159 | + next_position(); | |
160 | + b1=g_source[g_srcpos]; | |
161 | + if (b1!=',') break; | |
162 | + g_srcpos++; | |
163 | + next_position(); | |
164 | + b1=g_source[g_srcpos]; | |
165 | + if (b1==0x0d || b1==0x0a) { | |
166 | + // Multiline CDATA statement | |
167 | + g_line++; | |
168 | + g_fileline++; | |
169 | + if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++; | |
170 | + g_srcpos++; | |
171 | + // Maintain at least 256 characters in cache. | |
172 | + if (256<=g_srcpos) read_file(256); | |
173 | + next_position(); | |
174 | + b1=g_source[g_srcpos]; | |
175 | + } | |
176 | + } | |
177 | + // Write the last 1-3 bytes and shift data if total # is not multipes of 4. | |
178 | + if (0<shift) { | |
179 | + // Convert shift value from bit-shift to data byte-shift. | |
180 | + shift=4-shift/8; | |
181 | + check_obj_space(1); | |
182 | + g_object[g_objpos++]=i; | |
183 | + for(cpy=(char*)&g_object[g_objpos]-1;(char*)&g_object[beginpos+2]<cpy;cpy--){ | |
184 | + cpy[0]=cpy[0-shift]; | |
185 | + } | |
186 | + } | |
187 | + // Determine the size of data | |
188 | + i=g_objpos-beginpos-1; | |
189 | + g_object[beginpos] =0x04110000|i; // bgezal zero,xxxx | |
190 | + g_object[beginpos+1]=0x00000020|shift; // add zero,zero,zero | |
191 | + return 0; | |
192 | +} | |
193 | + | |
194 | +char* data_statement(){ | |
195 | + // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero) | |
196 | + // are the sign of data region | |
197 | + int i,prevpos; | |
198 | + char* err; | |
199 | + // This statement is not valid in class file. | |
200 | + if (g_compiling_class) return ERR_INVALID_CLASS; | |
201 | + while(1){ | |
202 | + prevpos=g_objpos; | |
203 | + check_obj_space(2); | |
204 | + g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx | |
205 | + g_object[g_objpos++]=0x00000020; // add zero,zero,zero | |
206 | + next_position(); | |
207 | + if (g_source[g_srcpos]=='"') { | |
208 | + // Constant string | |
209 | + // Store pointer to string. This is 3 words bellow of current position | |
210 | + g_object[g_objpos]=(int)(&g_object[g_objpos+3]); | |
211 | + g_objpos++; | |
212 | + g_object[prevpos]=0x04110002; // bgezal zero,xxxx | |
213 | + err=simple_string(); | |
214 | + if (err) return err; | |
215 | + next_position(); | |
216 | + if (g_source[g_srcpos]==',') { | |
217 | + g_srcpos++; | |
218 | + continue; | |
219 | + } | |
220 | + return 0; | |
221 | + } | |
222 | + err=exec_statement(); | |
223 | + if (err) return err; | |
224 | + // Determine the size of data | |
225 | + i=g_objpos-prevpos-1; | |
226 | + g_object[prevpos]=0x04110000|i; // bgezal zero,xxxx | |
227 | + if (g_source[g_srcpos]=='"') { | |
228 | + // Constant string | |
229 | + continue; | |
230 | + } | |
231 | + return 0; | |
232 | + } | |
233 | +} | |
234 | + | |
235 | +char* clear_statement(){ | |
236 | + call_lib_code(LIB_CLEAR); | |
237 | + return 0; | |
238 | +} | |
239 | + | |
240 | +char* poke_statement_sub(int bits){ | |
241 | + char* err; | |
242 | + err=get_value(); | |
243 | + if (err) return err; | |
244 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
245 | + g_srcpos++; | |
246 | + check_obj_space(2); | |
247 | + g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 | |
248 | + g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp) | |
249 | + err=get_value(); | |
250 | + if (err) return err; | |
251 | + check_obj_space(3); | |
252 | + g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp) | |
253 | + g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4 | |
254 | + switch(bits){ | |
255 | + case 32: | |
256 | + g_object[g_objpos++]=0xAC620000; // sw v0,0(v1) | |
257 | + break; | |
258 | + case 16: | |
259 | + g_object[g_objpos++]=0xA4620000; // sh v0,0(v1) | |
260 | + break; | |
261 | + case 8: | |
262 | + default: | |
263 | + g_object[g_objpos++]=0xA0620000; // sb v0,0(v1) | |
264 | + break; | |
265 | + } | |
266 | + return 0; | |
267 | +} | |
268 | + | |
269 | +char* dim_statement(){ | |
270 | + char* err; | |
271 | + char b1; | |
272 | + int i; | |
273 | + int spos; | |
274 | + int stack; | |
275 | + while(1){ | |
276 | + stack=0; | |
277 | + next_position(); | |
278 | + i=get_var_number(); | |
279 | + if (i<0) return ERR_SYNTAX; | |
280 | + if (g_source[g_srcpos]=='#') g_srcpos++; | |
281 | + next_position(); | |
282 | + if (g_source[g_srcpos]!='(') return ERR_SYNTAX; | |
283 | + check_obj_space(1); | |
284 | + spos=g_objpos++; // addiu sp,sp,xxxx | |
285 | + do { | |
286 | + g_srcpos++; | |
287 | + err=get_value(); | |
288 | + if (err) return err; | |
289 | + stack+=4; | |
290 | + check_obj_space(1); | |
291 | + g_object[g_objpos++]=0xAFA20000|stack; // sw v0,8(sp) | |
292 | + } while (g_source[g_srcpos]==','); | |
293 | + if (g_source[g_srcpos]!=')') return ERR_SYNTAX; | |
294 | + g_srcpos++; | |
295 | + check_obj_space(3); | |
296 | + g_object[g_objpos++]=0x24040000|(i); // addiu a0,zero,xx | |
297 | + g_object[g_objpos++]=0x24050000|(stack/4); // addiu a1,zero,xxxx | |
298 | + g_object[g_objpos++]=0x03A01025; // or v0,sp,zero | |
299 | + call_lib_code(LIB_DIM); | |
300 | + // Stack -/+ | |
301 | + check_obj_space(1); | |
302 | + g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xxxx | |
303 | + stack=(0-stack)&0x0000FFFF; | |
304 | + g_object[spos]=0x27BD0000|stack; // addiu sp,sp,xxxx | |
305 | + next_position(); | |
306 | + if (g_source[g_srcpos]!=',') break; | |
307 | + g_srcpos++; | |
308 | + } | |
309 | + return 0; | |
310 | +} | |
311 | + | |
312 | +char* label_statement(){ | |
313 | + char* err; | |
314 | + char b1; | |
315 | + b1=g_source[g_srcpos]; | |
316 | + if (b1<'A' || 'Z'<b1) return ERR_SYNTAX; // Number is not allowed here. | |
317 | + err=get_label(); | |
318 | + if (err) return err; | |
319 | + // Check existing label with the same name here. | |
320 | + if (search_label(g_label)) { | |
321 | + // Error: duplicate labels | |
322 | + printstr("Label "); | |
323 | + printstr(resolve_label(g_label)); | |
324 | + return ERR_MULTIPLE_LABEL; | |
325 | + } | |
326 | + check_obj_space(2); | |
327 | + g_object[g_objpos++]=0x3C160000|((g_label>>16)&0x0000FFFF); //lui s6,yyyy; | |
328 | + g_object[g_objpos++]=0x36D60000|(g_label&0x0000FFFF); //ori s6,s6,zzzz; | |
329 | + return 0; | |
330 | +} | |
331 | + | |
332 | +char* restore_statement(){ | |
333 | + char* err; | |
334 | + // This statement is not valid in class file. | |
335 | + if (g_compiling_class) return ERR_INVALID_CLASS; | |
336 | + err=get_label(); | |
337 | + if (err) return err; | |
338 | + if (g_label) { | |
339 | + // Constant label/number | |
340 | + // Use 32 bit mode also for values<65536 | |
341 | + // This code will be replaced to code for v0 for pointer in linker. | |
342 | + check_obj_space(2); | |
343 | + g_object[g_objpos++]=0x3C020000|(g_label>>16); // lui v0,xxxx | |
344 | + g_object[g_objpos++]=0x34420000|(g_label&0x0000FFFF); // ori v0,v0,xxxx | |
345 | + } else { | |
346 | + // Dynamic number | |
347 | + err=get_value(); | |
348 | + if (err) return err; | |
349 | + } | |
350 | + call_lib_code(LIB_RESTORE); | |
351 | + return 0; | |
352 | +} | |
353 | + | |
354 | +char* gosub_statement_sub(){ | |
355 | + char* err; | |
356 | + err=get_label(); | |
357 | + if (err) return err; | |
358 | + if (g_label) { | |
359 | + // Label/number is constant. | |
360 | + // Linker will change following codes later. | |
361 | + // Note that 0x0812xxxx and 0x0813xxxx are specific codes for these. | |
362 | + check_obj_space(7); | |
363 | + g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 | |
364 | + g_object[g_objpos++]=0x04130003; // bgezall zero,label1 | |
365 | + g_object[g_objpos++]=0xAEBD0000|ARGS_S5_SP; // sw sp,-12(s5) | |
366 | + g_object[g_objpos++]=0x10000003; // beq zero,zero,label2 | |
367 | + g_object[g_objpos++]=0x08120000|((g_label>>16)&0x0000FFFF); // nop | |
368 | + // label1: | |
369 | + g_object[g_objpos++]=0x08130000|(g_label&0x0000FFFF); // j xxxx | |
370 | + g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp) | |
371 | + // label2: | |
372 | + } else { | |
373 | + // Label/number will be dynamically set when executing code. | |
374 | + err=get_value(); | |
375 | + if (err) return err; | |
376 | + call_lib_code(LIB_LABEL); | |
377 | + check_obj_space(7); | |
378 | + g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 | |
379 | + g_object[g_objpos++]=0x04130003; // bgezall zero,label1 | |
380 | + g_object[g_objpos++]=0xAEBD0000|ARGS_S5_SP; // sw sp,-12(s5) | |
381 | + g_object[g_objpos++]=0x10000003; // beq zero,zero,label2 | |
382 | + g_object[g_objpos++]=0x00000000; // nop | |
383 | + // label1: | |
384 | + g_object[g_objpos++]=0x00400008; // jr v0 | |
385 | + g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp) | |
386 | + // label2: | |
387 | + } | |
388 | + return 0; | |
389 | +} | |
390 | + | |
391 | +char* gosub_statement(){ | |
392 | + char* err; | |
393 | + int opos,spos,stack; | |
394 | + // Skip label first (see below) | |
395 | + opos=g_objpos; | |
396 | + spos=g_srcpos; | |
397 | + err=gosub_statement_sub(); | |
398 | + if (err) return err; | |
399 | + next_position(); | |
400 | + // Rewind object and construct argument-creating routine. | |
401 | + g_objpos=opos; | |
402 | + // Begin parameter(s) construction routine | |
403 | + g_object[g_objpos++]=0x8EA20000|ARGS_S5_V0_OBJ; // lw v0,-8(s5) | |
404 | + err=prepare_args_stack(','); | |
405 | + if (err) return err; | |
406 | + // Rewind source and construct GOSUB routine again. | |
407 | + opos=spos; | |
408 | + spos=g_srcpos; | |
409 | + g_srcpos=opos; | |
410 | + err=gosub_statement_sub(); | |
411 | + if (err) return err; | |
412 | + // Remove stack | |
413 | + err=remove_args_stack(); | |
414 | + if (err) return err; | |
415 | + // All done, go back to right source position | |
416 | + g_srcpos=spos; | |
417 | + return 0; | |
418 | +} | |
419 | + | |
420 | +char* return_statement(){ | |
421 | + char* err; | |
422 | + char b1; | |
423 | + next_position(); | |
424 | + b1=g_source[g_srcpos]; | |
425 | + if (0x20<b1 && b1!=':') { | |
426 | + // There is a return value. | |
427 | + err=get_stringFloatOrValue(); | |
428 | + if (err) return err; | |
429 | + } | |
430 | + check_obj_space(4); | |
431 | + g_object[g_objpos++]=0x8EBD0000|ARGS_S5_SP; // lw sp,-12(s5) | |
432 | + g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp) | |
433 | + g_object[g_objpos++]=0x00600008; // jr v1 | |
434 | + g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4 | |
435 | + return 0; | |
436 | +} | |
437 | + | |
438 | +char* goto_statement(){ | |
439 | + char* err; | |
440 | + err=get_label(); | |
441 | + if (err) return err; | |
442 | + if (g_label) { | |
443 | + // Label/number is constant. | |
444 | + // Linker will change following codes later. | |
445 | + // Note that 0x0810xxxx and 0x0811xxxx are specific codes for these. | |
446 | + check_obj_space(2); | |
447 | + g_object[g_objpos++]=0x08100000|((g_label>>16)&0x0000FFFF); // j xxxx | |
448 | + g_object[g_objpos++]=0x08110000|(g_label&0x0000FFFF); // nop | |
449 | + } else { | |
450 | + // Label/number will be dynamically set when executing code. | |
451 | + err=get_value(); | |
452 | + if (err) return err; | |
453 | + call_lib_code(LIB_LABEL); | |
454 | + check_obj_space(2); | |
455 | + g_object[g_objpos++]=0x00400008; // jr v0 | |
456 | + g_object[g_objpos++]=0x00000000; // nop | |
457 | + } | |
458 | + return 0; | |
459 | +} | |
460 | + | |
461 | +char* if_statement(){ | |
462 | + char* err; | |
463 | + int prevpos,bpos; | |
464 | + // Get value. | |
465 | + err=get_floatOrValue(); | |
466 | + if (err) return err; | |
467 | + // Check "THEN" | |
468 | + if (!nextCodeIs("THEN")) return ERR_SYNTAX; | |
469 | + // Check if statement follows after THEN statement | |
470 | + next_position(); | |
471 | + if (nextCodeIs("REM")) { | |
472 | + // If REM statement follows, skip comment words. | |
473 | + rem_statement(); | |
474 | + } | |
475 | + if (g_source[g_srcpos]<0x20) { | |
476 | + // End of line. | |
477 | + // Use IF-THEN-ENDIF mode (multiple line mode) | |
478 | + check_obj_space(3); | |
479 | + g_object[g_objpos++]=0x30000000; // nop (see linker) | |
480 | + g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx | |
481 | + g_object[g_objpos++]=0x30000000; // nop (see linker) | |
482 | + return 0; | |
483 | + } | |
484 | + // One line mode | |
485 | + // If $v0=0 then skip. | |
486 | + bpos=g_objpos; | |
487 | + check_obj_space(2); | |
488 | + g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx | |
489 | + g_object[g_objpos++]=0x00000000; // nop | |
490 | + prevpos=g_srcpos; | |
491 | + if (statement()) { | |
492 | + // May be label | |
493 | + g_srcpos=prevpos; | |
494 | + err=goto_statement(); | |
495 | + if (err) return err; | |
496 | + } else { | |
497 | + // Must be statement(s) | |
498 | + while(1) { | |
499 | + if (g_source[g_srcpos]!=':') break; | |
500 | + g_srcpos++; | |
501 | + err=statement(); | |
502 | + if (err) return err; | |
503 | + } | |
504 | + } | |
505 | + // Check if "ELSE" exists. | |
506 | + if (!nextCodeIs("ELSE ")) { | |
507 | + // "ELSE" not found. This is the end of "IF" statement. | |
508 | + // Previous branch command must jump to this position. | |
509 | + g_object[bpos]=0x10400000|(g_objpos-bpos-1); // beq v0,zero,xxxx | |
510 | + return 0; | |
511 | + } | |
512 | + // Skip after ELSE if required. | |
513 | + check_obj_space(2); | |
514 | + g_object[g_objpos++]=0x10000000; // beq zero,zero,xxxx | |
515 | + g_object[g_objpos++]=0x00000000; // nop | |
516 | + // Previous branch command must jump to this position. | |
517 | + g_object[bpos]=0x10400000|(g_objpos-bpos-1); // beq v0,zero,xxxx | |
518 | + bpos=g_objpos-2; | |
519 | + // Next statement is either label or general statement | |
520 | + prevpos=g_srcpos; | |
521 | + if (statement()) { | |
522 | + // May be label | |
523 | + g_srcpos=prevpos; | |
524 | + err=goto_statement(); | |
525 | + if (err) return err; | |
526 | + } else { | |
527 | + // Must be statement(s) | |
528 | + while(1) { | |
529 | + if (g_source[g_srcpos]!=':') break; | |
530 | + g_srcpos++; | |
531 | + err=statement(); | |
532 | + if (err) return err; | |
533 | + } | |
534 | + } | |
535 | + // Previous branch command must jump to this position. | |
536 | + g_object[bpos]=0x10000000|(g_objpos-bpos-1); // beq zero,zero,xxxx | |
537 | + return 0; | |
538 | +} | |
539 | + | |
540 | +char* elseif_statement(void){ | |
541 | + // Multiple line mode | |
542 | + char* err; | |
543 | + g_object[g_objpos++]=0x08160100; // breakif (see linker) | |
544 | + g_object[g_objpos++]=0x30008000; // nop (see linker) | |
545 | + // Get value. | |
546 | + err=get_floatOrValue(); | |
547 | + if (err) return err; | |
548 | + // Check "THEN" | |
549 | + if (!nextCodeIs("THEN")) return ERR_SYNTAX; | |
550 | + // Check if statement follows after THEN statement | |
551 | + if (nextCodeIs("REM")) { | |
552 | + // If REM statement follows, skip comment words. | |
553 | + rem_statement(); | |
554 | + } | |
555 | + if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX; | |
556 | + // Statement didn't follow after THEM statement (that is correct). | |
557 | + g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx | |
558 | + g_object[g_objpos++]=0x30000000; // nop (see linker) | |
559 | + return 0; | |
560 | + | |
561 | +} | |
562 | + | |
563 | +char* else_statement(void){ | |
564 | + // Multiple line mode | |
565 | + g_object[g_objpos++]=0x08160100; // breakif (see linker) | |
566 | + g_object[g_objpos++]=0x30008000; // nop (see linker) | |
567 | + g_object[g_objpos++]=0x30000000; // nop (see linker) | |
568 | + // Check if statement follows after THEN statement | |
569 | + if (nextCodeIs("REM")) { | |
570 | + // If REM statement follows, skip comment words. | |
571 | + rem_statement(); | |
572 | + } | |
573 | + if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX; | |
574 | + // Statement didn't follow after THEM statement (that is correct). | |
575 | + return 0; | |
576 | +} | |
577 | + | |
578 | +char* endif_statement(void){ | |
579 | + // Multiple line mode | |
580 | + g_object[g_objpos++]=0x30008000; // nop (see linker) | |
581 | + g_object[g_objpos++]=0x30008000; // nop (see linker) | |
582 | + // Check if statement follows after THEN statement | |
583 | + if (nextCodeIs("REM")) { | |
584 | + // If REM statement follows, skip comment words. | |
585 | + rem_statement(); | |
586 | + } | |
587 | + if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX; | |
588 | + // Statement didn't follow after THEM statement (that is correct). | |
589 | + return 0; | |
590 | +} | |
591 | + | |
592 | +char* end_statement(void){ | |
593 | + int i; | |
594 | + i=(int)&g_end_addr; | |
595 | + i-=g_gp; | |
596 | + check_obj_space(3); | |
597 | + g_object[g_objpos++]=0x8F820000|(i&0x0000FFFF); // lw v0,xxxx(gp) | |
598 | + g_object[g_objpos++]=0x00400008; // jr v0 | |
599 | + g_object[g_objpos++]=0x00000000; // nop | |
600 | + return 0; | |
601 | +} | |
602 | + | |
603 | +char* let_dim_sub(int i){ | |
604 | + char* err; | |
605 | + g_srcpos++; | |
606 | + err=get_value(); | |
607 | + if (err) return err; | |
608 | + check_obj_space(4); | |
609 | + g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2 | |
610 | + g_object[g_objpos++]=0x8FC30000|(i*4); // lw v1,xx(s8) | |
611 | + g_object[g_objpos++]=0x00621821; // addu v1,v1,v0 | |
612 | + g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp) | |
613 | + while(g_source[g_srcpos]==','){ | |
614 | + g_srcpos++; | |
615 | + err=get_value(); | |
616 | + if (err) return err; | |
617 | + check_obj_space(4); | |
618 | + g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2 | |
619 | + g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp) | |
620 | + g_object[g_objpos++]=0x8C630000; // lw v1,0(v1) | |
621 | + g_object[g_objpos++]=0x00621821; // addu v1,v1,v0 | |
622 | + g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp) | |
623 | + } | |
624 | + if (g_source[g_srcpos]!=')') return ERR_SYNTAX; | |
625 | + g_srcpos++; | |
626 | + return 0; | |
627 | +}; | |
628 | + | |
629 | +char* let_statement(){ | |
630 | + char* err; | |
631 | + char b2,b3; | |
632 | + int i,spos,opos; | |
633 | + next_position(); | |
634 | + i=get_var_number(); | |
635 | + if (i<0) return ERR_SYNTAX; | |
636 | + b2=g_source[g_srcpos]; | |
637 | + b3=g_source[g_srcpos+1]; | |
638 | + if (b2=='#' && b3=='(') { | |
639 | + // Float dimension | |
640 | + g_srcpos++; | |
641 | + check_obj_space(1); | |
642 | + g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 | |
643 | + let_dim_sub(i); | |
644 | + next_position(); | |
645 | + if (g_source[g_srcpos]!='=') return ERR_SYNTAX; | |
646 | + g_srcpos++; | |
647 | + err=get_float(); | |
648 | + if (err) return err; | |
649 | + check_obj_space(3); | |
650 | + g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp) | |
651 | + g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4 | |
652 | + g_object[g_objpos++]=0xAC620000; // sw v0,0(v1) | |
653 | + return 0; | |
654 | + } else if (b2=='#') { | |
655 | + // Float A-Z | |
656 | + g_srcpos++; | |
657 | + next_position(); | |
658 | + if (g_source[g_srcpos]!='=') return ERR_SYNTAX; | |
659 | + g_srcpos++; | |
660 | + err=get_float(); | |
661 | + if (err) return err; | |
662 | + check_obj_space(1); | |
663 | + g_object[g_objpos++]=0xAFC20000|(i*4); // sw v0,xxx(s8) | |
664 | + return 0; | |
665 | + } else if (b2=='$') { | |
666 | + // String | |
667 | + g_srcpos++; | |
668 | + next_position(); | |
669 | + if (g_source[g_srcpos]!='=') return ERR_SYNTAX; | |
670 | + g_srcpos++; | |
671 | + err=get_string(); | |
672 | + if (err) return err; | |
673 | + check_obj_space(1); | |
674 | + g_object[g_objpos++]=0x24040000|(i); //addiu a0,zero,xx | |
675 | + call_lib_code(LIB_LETSTR); | |
676 | + return 0; | |
677 | + } else if (b2=='(') { | |
678 | + // Dimension | |
679 | + check_obj_space(1); | |
680 | + g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 | |
681 | + let_dim_sub(i); | |
682 | + if (g_source[g_srcpos]=='.') { | |
683 | + // This is an object. Determine the filed of this object. | |
684 | + // 4(sp) contains the address of dimension value | |
685 | + // The dimension value is the pointer to object | |
686 | + g_srcpos++; | |
687 | + check_obj_space(3); | |
688 | + g_object[g_objpos++]=0x8FA20004; // lw v0,4(sp) | |
689 | + g_object[g_objpos++]=0x8C420000; // lw v0,0(v0) g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4 | |
690 | + return let_object_field(); | |
691 | + } | |
692 | + next_position(); | |
693 | + if (g_source[g_srcpos]!='=') return ERR_SYNTAX; | |
694 | + g_srcpos++; | |
695 | + err=get_value(); | |
696 | + if (err) return err; | |
697 | + check_obj_space(3); | |
698 | + g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp) | |
699 | + g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4 | |
700 | + g_object[g_objpos++]=0xAC620000; // sw v0,0(v1) | |
701 | + return 0; | |
702 | + } else if (b2=='.') { | |
703 | + // Field of object | |
704 | + g_srcpos++; | |
705 | + check_obj_space(1); | |
706 | + g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8) | |
707 | + return let_object_field(); | |
708 | + } else { | |
709 | + // Integer A-Z | |
710 | + next_position(); | |
711 | + if (g_source[g_srcpos]!='=') return ERR_SYNTAX; | |
712 | + g_srcpos++; | |
713 | + err=get_value(); | |
714 | + if (err) return err; | |
715 | + check_obj_space(1); | |
716 | + g_object[g_objpos++]=0xAFC20000|(i*4); // sw v0,xxx(s8) | |
717 | + } | |
718 | + return 0; | |
719 | +} | |
720 | + | |
721 | +char* print_statement_main(enum libs lib_printstr, enum libs lib_string){ | |
722 | + char* err; | |
723 | + char b1; | |
724 | + int i; | |
725 | + int status=0;// 1:',' 2:';' 0:none | |
726 | + while(1){ | |
727 | + next_position(); | |
728 | + if (endOfStatement()) break; | |
729 | + if (!strncmp(g_source+g_srcpos,"ELSE " ,5)) break; | |
730 | + err=get_stringFloatOrValue(); | |
731 | + if (err) return err; | |
732 | + switch(g_lastvar){ | |
733 | + case VAR_INTEGER: | |
734 | + // Use DEC$() function. | |
735 | + call_lib_code(LIB_DEC); | |
736 | + break; | |
737 | + case VAR_FLOAT: | |
738 | + // Use FLOAT$() function. | |
739 | + check_obj_space(2); | |
740 | + g_object[g_objpos++]=0x00022021; //addu a0,zero,v0 | |
741 | + g_object[g_objpos++]=0x34020000; //ori v0,zero,0x0000 | |
742 | + call_lib_code(LIB_SPRINTF); | |
743 | + break; | |
744 | + case VAR_STRING: | |
745 | + default: | |
746 | + break; | |
747 | + } | |
748 | + // Call printstr() function | |
749 | + // First argument is the pointer to string | |
750 | + call_lib_code(lib_printstr); | |
751 | + next_position(); | |
752 | + b1=g_source[g_srcpos]; | |
753 | + if (b1==',') { | |
754 | + status=1; | |
755 | + g_srcpos++; | |
756 | + // Call lib_string() function for comma (,) | |
757 | + check_obj_space(1); | |
758 | + g_object[g_objpos++]=0x34020001; // ori v0,zero,1 | |
759 | + call_lib_code(lib_string); | |
760 | + } else if (b1==';') { | |
761 | + status=2; | |
762 | + g_srcpos++; | |
763 | + } else { | |
764 | + status=0; | |
765 | + } | |
766 | + } | |
767 | + if (status==0) { | |
768 | + // Call lib_string() function for CR (\n) | |
769 | + check_obj_space(1); | |
770 | + g_object[g_objpos++]=0x34020000; // ori v0,zero,0 | |
771 | + call_lib_code(lib_string); | |
772 | + } | |
773 | + return 0; | |
774 | +} | |
775 | + | |
776 | +char* break_statement(){ | |
777 | + check_obj_space(2); | |
778 | + g_object[g_objpos++]=0x08160000; // j xxxx (See link() function) | |
779 | + g_object[g_objpos++]=0x00000000; // nop | |
780 | + return 0; | |
781 | +} | |
782 | + | |
783 | +char* continue_statement(){ | |
784 | + check_obj_space(2); | |
785 | + g_object[g_objpos++]=0x08160008; // j xxxx (See link() function) | |
786 | + g_object[g_objpos++]=0x00000000; // nop | |
787 | + return 0; | |
788 | +} | |
789 | + | |
790 | +char* for_statement(){ | |
791 | + char* err; | |
792 | +// char b1; | |
793 | + int i; | |
794 | + int prepos=g_srcpos; | |
795 | + // Initialization of variable | |
796 | +// next_position(); | |
797 | +// b1=g_source[g_srcpos]; | |
798 | + i=get_var_number(); | |
799 | +// if (b1<'A' || 'Z'<b1) return ERR_SYNTAX; | |
800 | + if (i<0) return ERR_SYNTAX; | |
801 | + g_srcpos=prepos; | |
802 | + err=let_statement(); | |
803 | + if (err) return err; | |
804 | + // Check if "TO" exists | |
805 | + if (!nextCodeIs("TO ")) return ERR_SYNTAX; | |
806 | + err=get_value(); | |
807 | + if (err) return err; | |
808 | + // Usage of stack: | |
809 | + // 12(sp): "TO" value | |
810 | + // 8(sp): "STEP" value | |
811 | + // 4(sp): Address to return to in "NEXT" statement. | |
812 | + // Store "TO" value in stack | |
813 | + check_obj_space(2); | |
814 | + g_object[g_objpos++]=0x0820FFF4; // addiu sp,sp,-12 (see linker) | |
815 | + g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp) | |
816 | + // Check if "STEP" exists | |
817 | + g_valueisconst=1; | |
818 | + if (nextCodeIs("STEP ")) { | |
819 | + // "STEP" exists. Get value | |
820 | + err=get_value(); | |
821 | + if (err) return err; | |
822 | + } else { | |
823 | + // "STEP" not exist. Use "1". | |
824 | + check_obj_space(1); | |
825 | + g_object[g_objpos++]=0x24020001; // addiu v0,zero,1 | |
826 | + g_intconst=1; | |
827 | + } | |
828 | + check_obj_space(14); | |
829 | + g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp) (STEP value) | |
830 | + g_object[g_objpos++]=0x04130004; // bgezall zero,check | |
831 | +// g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value) | |
832 | + g_object[g_objpos++]=0x8FC40000|(i*4); // lw a0,xx(s8) (current var value) | |
833 | + // After executing "NEXT" statement, process reaches following line. | |
834 | + // Update variable value by adding STEP value | |
835 | + // Note that STEP value is loaded onto $v0 in NEXT statement | |
836 | +// g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value) | |
837 | + g_object[g_objpos++]=0x8FC40000|(i*4); // lw a0,xx(s8) (current var value) | |
838 | + g_object[g_objpos++]=0x00822021; // addu a0,a0,v0 | |
839 | +// g_object[g_objpos++]=0xAFC40000|((b1-'A')*4); // sw a0,xx(s8) (new var value) | |
840 | + g_object[g_objpos++]=0xAFC40000|(i*4); // sw a0,xx(s8) (new var value) | |
841 | + // Value-checking routine and storing ra in stack | |
842 | + // check: | |
843 | + g_object[g_objpos++]=0x8FA3000C; // lw v1,12(sp) (TO value) | |
844 | + g_object[g_objpos++]=0x00641823; // subu v1,v1,a0 | |
845 | + g_object[g_objpos++]=0x04420001; // bltzl v0,negative | |
846 | + g_object[g_objpos++]=0x00031823; // subu v1,zero,v1 | |
847 | + // negative: | |
848 | + g_object[g_objpos++]=0x04610003; // bgez v1,continue | |
849 | + g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp) | |
850 | + break_statement(); // (2 words) | |
851 | + // continue: | |
852 | + return 0; | |
853 | +} | |
854 | + | |
855 | +char* next_statement(){ | |
856 | + // Return to address stored in 4($sp) | |
857 | + // while set $v0 to 8($sp) (see for_statement) | |
858 | + // Following assembly must be 4 words. | |
859 | + // If the number of words will be changed, link.c must be reviced for CONTINUE statement. | |
860 | + check_obj_space(4); | |
861 | + g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp) | |
862 | + g_object[g_objpos++]=0x03E00008; // jr ra | |
863 | + g_object[g_objpos++]=0x8FA20008; // lw v0,8(sp) (STEP value) | |
864 | + g_object[g_objpos++]=0x0830000C; // addiu sp,sp,12 (see linker) | |
865 | + return 0; | |
866 | +} | |
867 | + | |
868 | +char* do_statement(){ | |
869 | + char* err; | |
870 | + // Usage of stack: | |
871 | + // 4(sp): Address to return to in "DO" statement. | |
872 | + check_obj_space(3); | |
873 | + g_object[g_objpos++]=0x04130001;// bgezall zero,label1: | |
874 | + g_object[g_objpos++]=0x0822FFFC;// addiu sp,sp,-4 (see linker) | |
875 | + // label1: | |
876 | + g_object[g_objpos++]=0xAFBF0004;// sw ra,4(sp) | |
877 | + if (nextCodeIs("WHILE ")) { | |
878 | + // DO WHILE | |
879 | + err=get_floatOrValue(); | |
880 | + if (err) return err; | |
881 | + check_obj_space(2); | |
882 | + g_object[g_objpos++]=0x14400003; // bne v0,zero,labe2 | |
883 | + g_object[g_objpos++]=0x00000000; // nop | |
884 | + return break_statement(); // (2 words) | |
885 | + // label2: | |
886 | + | |
887 | + } else if (nextCodeIs("UNTIL ")) { | |
888 | + // DO UNTIL | |
889 | + err=get_floatOrValue(); | |
890 | + if (err) return err; | |
891 | + check_obj_space(2); | |
892 | + g_object[g_objpos++]=0x10400003; // beq v0,zero,label2 | |
893 | + g_object[g_objpos++]=0x00000000; // nop | |
894 | + return break_statement(); // (2 words) | |
895 | + // label2: | |
896 | + } else { | |
897 | + // DO statement without WHILE/UNTIL | |
898 | + return 0; | |
899 | + } | |
900 | +} | |
901 | + | |
902 | +char* loop_statement(){ | |
903 | + char* err; | |
904 | + int opos; | |
905 | + opos=g_objpos; | |
906 | + if (nextCodeIs("WHILE ")) { | |
907 | + // LOOP WHILE | |
908 | + err=get_floatOrValue(); | |
909 | + if (err) return err; | |
910 | + check_obj_space(1); | |
911 | + g_object[g_objpos++]=0x10400003; // beq v0,zero,label1 | |
912 | + } else if (nextCodeIs("UNTIL ")) { | |
913 | + // LOOP UNTIL | |
914 | + err=get_floatOrValue(); | |
915 | + if (err) return err; | |
916 | + check_obj_space(1); | |
917 | + g_object[g_objpos++]=0x14400003; // bne v0,zero,label | |
918 | + } else { | |
919 | + // LOOP statement without WHILE/UNTIL | |
920 | + } | |
921 | + check_obj_space(4); | |
922 | + g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp) | |
923 | + g_object[g_objpos++]=0x03E00008; // jr ra | |
924 | + opos=g_objpos+1-opos; | |
925 | + g_object[g_objpos++]=0x3000F000|opos; // nop (See linker, used for CONTINUE statement) | |
926 | + // label1: | |
927 | + g_object[g_objpos++]=0x08320004; // addiu sp,sp,4 (See link() function) | |
928 | + return 0; | |
929 | +} | |
930 | + | |
931 | +char* while_statement(){ | |
932 | + char* err; | |
933 | + check_obj_space(3); | |
934 | + g_object[g_objpos++]=0x04130001; // bgezall zero,label1: | |
935 | + g_object[g_objpos++]=0x0821FFFC; // addiu sp,sp,-4 (see linker) | |
936 | + // label1: | |
937 | + g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp) | |
938 | + err=get_floatOrValue(); | |
939 | + if (err) return err; | |
940 | + check_obj_space(2); | |
941 | + g_object[g_objpos++]=0x14400003; // bne v0,zero,label2 | |
942 | + g_object[g_objpos++]=0x00000000; // nop | |
943 | + return break_statement(); // (2 words) | |
944 | + // label2: | |
945 | +} | |
946 | + | |
947 | +char* wend_statement(){ | |
948 | + check_obj_space(4); | |
949 | + g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp) | |
950 | + g_object[g_objpos++]=0x03E00008; // jr ra | |
951 | + g_object[g_objpos++]=0x3000F003; // nop (See linker, used for CONTINUE statement) | |
952 | + // label1: | |
953 | + g_object[g_objpos++]=0x08310004; // addiu sp,sp,4 (See link() function) | |
954 | + return 0; | |
955 | +} | |
956 | + | |
957 | +char* param4_statement(enum libs lib){ | |
958 | + // lib is either LIB_PALETTE or LIB_GPALETTE | |
959 | + // PALETTE N,R,G,B | |
960 | + char* err; | |
961 | + // Get N | |
962 | + err=get_value(); | |
963 | + if (err) return err; | |
964 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
965 | + g_srcpos++; | |
966 | + check_obj_space(2); | |
967 | + g_object[g_objpos++]=0x27BDFFF4; // addiu sp,sp,-12 | |
968 | + g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp) | |
969 | + // Get R | |
970 | + err=get_value(); | |
971 | + if (err) return err; | |
972 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
973 | + g_srcpos++; | |
974 | + check_obj_space(1); | |
975 | + g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp) | |
976 | + // Get G | |
977 | + err=get_value(); | |
978 | + if (err) return err; | |
979 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
980 | + g_srcpos++; | |
981 | + check_obj_space(1); | |
982 | + g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp) | |
983 | + // Get B | |
984 | + err=get_value(); | |
985 | + if (err) return err; | |
986 | + call_lib_code(lib); | |
987 | + check_obj_space(1); | |
988 | + g_object[g_objpos++]=0x27BD000C; // addiu sp,sp,12 | |
989 | + return 0; | |
990 | +} | |
991 | + | |
992 | +char* param3_statement(enum libs lib){ | |
993 | + char* err; | |
994 | + // Get 1st parameter | |
995 | + err=get_value(); | |
996 | + if (err) return err; | |
997 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
998 | + g_srcpos++; | |
999 | + check_obj_space(2); | |
1000 | + g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8 | |
1001 | + g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp) | |
1002 | + // Get 2nd parameter | |
1003 | + err=get_value(); | |
1004 | + if (err) return err; | |
1005 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
1006 | + g_srcpos++; | |
1007 | + check_obj_space(1); | |
1008 | + g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp) | |
1009 | + // Get 3rd parameter | |
1010 | + err=get_value(); | |
1011 | + if (err) return err; | |
1012 | + call_lib_code(lib); | |
1013 | + check_obj_space(1); | |
1014 | + g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8 | |
1015 | + return 0; | |
1016 | +} | |
1017 | + | |
1018 | +char* bgcolor_statement(){ | |
1019 | + // BGCOLOR R,G,B | |
1020 | + return param3_statement(LIB_BGCOLOR); | |
1021 | +} | |
1022 | + | |
1023 | +char* pcg_statement(){ | |
1024 | + // PCG ASCII,D1,D2 | |
1025 | + return param3_statement(LIB_PCG); | |
1026 | +} | |
1027 | + | |
1028 | +char* usepcg_statement(){ | |
1029 | + int objpos=g_objpos; | |
1030 | + if (get_value()) { | |
1031 | + // Getting integer failed. | |
1032 | + // It supporsed to be not parameter | |
1033 | + // and same as parameter=1. | |
1034 | + g_objpos=objpos; | |
1035 | + check_obj_space(1); | |
1036 | + g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01 | |
1037 | + } | |
1038 | + call_lib_code(LIB_USEPCG); | |
1039 | + return 0; | |
1040 | +} | |
1041 | + | |
1042 | +char* usegraphic_statement(){ | |
1043 | + int objpos=g_objpos; | |
1044 | + if (get_value()) { | |
1045 | + // Getting integer failed. | |
1046 | + // It supporsed to be not parameter | |
1047 | + // and same as parameter=1. | |
1048 | + g_objpos=objpos; | |
1049 | + check_obj_space(1); | |
1050 | + g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01 | |
1051 | + } | |
1052 | + call_lib_code(LIB_USEGRAPHIC); | |
1053 | + return 0; | |
1054 | +} | |
1055 | + | |
1056 | +char* cls_statement(){ | |
1057 | + call_lib_code(LIB_CLS); | |
1058 | + return 0; | |
1059 | +} | |
1060 | + | |
1061 | +char* gcls_statement(){ | |
1062 | + call_lib_code(LIB_GCLS); | |
1063 | + return 0; | |
1064 | +} | |
1065 | + | |
1066 | +char* color_statement(){ | |
1067 | + char* err; | |
1068 | + err=get_value(); | |
1069 | + if (err) return err; | |
1070 | + call_lib_code(LIB_COLOR); | |
1071 | + return 0; | |
1072 | +} | |
1073 | + | |
1074 | +char* gcolor_statement(){ | |
1075 | + char* err; | |
1076 | + err=get_value(); | |
1077 | + if (err) return err; | |
1078 | + call_lib_code(LIB_GCOLOR); | |
1079 | + return 0; | |
1080 | +} | |
1081 | + | |
1082 | +char* param2_statement(enum libs lib){ | |
1083 | + char* err; | |
1084 | + // Get 1st | |
1085 | + err=get_value(); | |
1086 | + if (err) return err; | |
1087 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
1088 | + g_srcpos++; | |
1089 | + check_obj_space(2); | |
1090 | + g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 | |
1091 | + g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp) | |
1092 | + // Get 2nd | |
1093 | + err=get_value(); | |
1094 | + if (err) return err; | |
1095 | + call_lib_code(lib); | |
1096 | + check_obj_space(1); | |
1097 | + g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4 | |
1098 | + return 0; | |
1099 | +} | |
1100 | + | |
1101 | +char* system_statement(){ | |
1102 | + // SYSTEM X,Y | |
1103 | + char* err; | |
1104 | + // Get 1st | |
1105 | + err=get_value(); | |
1106 | + if (err) return err; | |
1107 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
1108 | + g_srcpos++; | |
1109 | + check_obj_space(2); | |
1110 | + g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 | |
1111 | + g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp) | |
1112 | + // Get 2nd | |
1113 | + err=get_value(); | |
1114 | + if (err) return err; | |
1115 | + check_obj_space(2); | |
1116 | + g_object[g_objpos++]=0x8FA40004; // lw a0,4(sp) | |
1117 | + g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4 | |
1118 | + call_lib_code(LIB_SYSTEM); | |
1119 | + return 0; | |
1120 | +} | |
1121 | + | |
1122 | +char* cursor_statement(){ | |
1123 | + // CURSOR X,Y | |
1124 | + return param2_statement(LIB_CURSOR); | |
1125 | +} | |
1126 | + | |
1127 | +char* scroll_statement(){ | |
1128 | + // SCROLL X,Y | |
1129 | + return param2_statement(LIB_SCROLL); | |
1130 | +} | |
1131 | + | |
1132 | +char* drawcount_statement(){ | |
1133 | + char* err; | |
1134 | + err=get_value(); | |
1135 | + if (err) return err; | |
1136 | + call_lib_code(LIB_SETDRAWCOUNT); | |
1137 | + return 0; | |
1138 | +} | |
1139 | + | |
1140 | +char* wait_statement(){ | |
1141 | + char* err; | |
1142 | + err=get_value(); | |
1143 | + if (err) return err; | |
1144 | + call_lib_code(LIB_WAIT); | |
1145 | + return 0; | |
1146 | +} | |
1147 | + | |
1148 | +char* width_statement(){ | |
1149 | + char* err; | |
1150 | + err=get_value(); | |
1151 | + if (err) return err; | |
1152 | + call_lib_code(LIB_WIDTH); | |
1153 | + return 0; | |
1154 | +} | |
1155 | + | |
1156 | +char* var_statement_sub(int a0, int a1){ | |
1157 | + // Construct parameter-setting scripts | |
1158 | + if (a0&0xffff0000) { | |
1159 | + check_obj_space(1); | |
1160 | + g_object[g_objpos++]=0x3C040000|(a0>>16); // lui a0,XXXX | |
1161 | + if (a0&0x0000ffff) { | |
1162 | + check_obj_space(1); | |
1163 | + g_object[g_objpos++]=0x34840000|(a0&0xffff); // ori a0,a0,XXXX | |
1164 | + } | |
1165 | + } else if (a0&0x0000ffff) { | |
1166 | + check_obj_space(1); | |
1167 | + g_object[g_objpos++]=0x34040000|(a0&0xffff); // ori a0,zero,xxxx | |
1168 | + } | |
1169 | + if (a1&0xffff0000) { | |
1170 | + check_obj_space(1); | |
1171 | + g_object[g_objpos++]=0x3C050000|(a1>>16); // lui a1,XXXX | |
1172 | + if (a1&0x0000ffff) { | |
1173 | + check_obj_space(1); | |
1174 | + g_object[g_objpos++]=0x34A50000|(a1&0xffff); // ori a1,a1,XXXX | |
1175 | + } | |
1176 | + } else if (a1&0x0000ffff) { | |
1177 | + check_obj_space(1); | |
1178 | + g_object[g_objpos++]=0x34050000|(a1&0xffff); // ori a1,zero,xxxx | |
1179 | + } else if (a0&0xff000000) { | |
1180 | + // # of variables is 4. Reset $a1 to let lib_var() know that there is no more variables to store. | |
1181 | + check_obj_space(1); | |
1182 | + g_object[g_objpos++]=0x34050000; // ori a1,zero,0 | |
1183 | + } | |
1184 | + return 0; | |
1185 | +} | |
1186 | + | |
1187 | +char* var_statement(){ | |
1188 | + char* err; | |
1189 | + int i,j,a0,a1; | |
1190 | + static int prevpos; | |
1191 | + short stack; | |
1192 | + do { | |
1193 | + // For stack, 4 bytes are used for return address, | |
1194 | + // 4 bytes are used in lib_var(), | |
1195 | + // and additinal bytes are used for storing variable values. | |
1196 | + stack=8; | |
1197 | + a0=a1=0; | |
1198 | + for (i=0;i<8;i++){ | |
1199 | + // Determine the variable number from source code | |
1200 | + j=get_var_number(); | |
1201 | + if (j<0) return ERR_SYNTAX; | |
1202 | + stack+=4; | |
1203 | + // Create parameters in $a0, or $a1 | |
1204 | + if (i<4) { | |
1205 | + a0=(a0<<8)|(j+1); | |
1206 | + } else { | |
1207 | + a1=(a1<<8)|(j+1); | |
1208 | + } | |
1209 | + // Check remaining variable(s) | |
1210 | + if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') g_srcpos++; | |
1211 | + next_position(); | |
1212 | + if (g_source[g_srcpos]!=',') break; | |
1213 | + g_srcpos++; | |
1214 | + } | |
1215 | + // Jump to push routine, first | |
1216 | + check_obj_space(2); | |
1217 | + prevpos=g_objpos; | |
1218 | + g_object[g_objpos++]=0x04130000; // bgezall zero,label1 | |
1219 | + g_object[g_objpos++]=0x27BD0000|((0-stack)&0xffff); // addiu sp,sp,-xx | |
1220 | + // Process will be here after RETURN statement | |
1221 | + // Pop routine | |
1222 | + err=var_statement_sub(a0,a1); // Prepare a0, and a1 | |
1223 | + if (err) return err; | |
1224 | + call_lib_code(LIB_VAR_POP); | |
1225 | + // Restore stack and return | |
1226 | + check_obj_space(3); | |
1227 | + g_object[g_objpos++]=0x8FA30000|stack; // lw v1,xx(sp) | |
1228 | + g_object[g_objpos++]=0x00600008; // jr v1 | |
1229 | + g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xx | |
1230 | + // Push rotine | |
1231 | + g_object[prevpos]|=g_objpos-prevpos-1; // label1: | |
1232 | + check_obj_space(1); | |
1233 | + g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp) | |
1234 | + err=var_statement_sub(a0,a1); // Prepare a0, and a1 | |
1235 | + if (err) return err; | |
1236 | + call_lib_code(LIB_VAR_PUSH); | |
1237 | + | |
1238 | + } while (g_source[g_srcpos-1]==','); | |
1239 | + // Renew sp stored in s5 stack. | |
1240 | + check_obj_space(1); | |
1241 | + g_object[g_objpos++]=0xAEBD0000|ARGS_S5_SP; // sw sp,-12(s5) | |
1242 | + return 0; | |
1243 | +} | |
1244 | + | |
1245 | + | |
1246 | +char* graphic_statement(enum functions func){ | |
1247 | + /* | |
1248 | + PSET X1,Y1[,C] | |
1249 | + LINE X1,Y1,X2,Y2[,C] | |
1250 | + BOXFILL X1,Y1,X2,Y2[,C] | |
1251 | + CIRCLE X1,Y1,R[,C] | |
1252 | + CIRCLEFILL X1,Y1,R[,C] | |
1253 | + GPRINT X1,Y1,C,BC,S$ | |
1254 | + PUTBMP X1,Y1,M,N,BMP | |
1255 | + 4(sp): X1 | |
1256 | + 8(sp): Y1 | |
1257 | + 12(sp): X2/R/M | |
1258 | + 16(sp): Y2/N | |
1259 | + v0: C/S$/BMP | |
1260 | + */ | |
1261 | + char* err; | |
1262 | + int spos; | |
1263 | + int paramnum; | |
1264 | + switch(func){ | |
1265 | + case FUNC_PSET:// X1,Y1[,C] | |
1266 | + case FUNC_GCOLOR:// X1,Y1 | |
1267 | + case FUNC_POINT:// X1,Y1 | |
1268 | + paramnum=2; | |
1269 | + break; | |
1270 | + case FUNC_CIRCLE:// X1,Y1,R[,C] | |
1271 | + case FUNC_CIRCLEFILL:// X1,Y1,R[,C] | |
1272 | + paramnum=3; | |
1273 | + break; | |
1274 | + case FUNC_LINE:// X1,Y1,X2,Y2[,C] | |
1275 | + case FUNC_BOXFILL:// X1,Y1,X2,Y2[,C] | |
1276 | + paramnum=4; | |
1277 | + break; | |
1278 | + case FUNC_GPRINT:// X1,Y1,C,BC,S$ | |
1279 | + case FUNC_PUTBMP:// X1,Y1,M,N,BMP | |
1280 | + paramnum=5; | |
1281 | + break; | |
1282 | + default: | |
1283 | + return ERR_UNKNOWN; | |
1284 | + } | |
1285 | + | |
1286 | + next_position(); | |
1287 | + if (g_source[g_srcpos]==',') { | |
1288 | + // X1 and Y1 is omitted. Set 0x80000000 for both. | |
1289 | + check_obj_space(4); | |
1290 | + g_object[g_objpos++]=0x27BDFFF0; // addiu sp,sp,-16 | |
1291 | + g_object[g_objpos++]=0x3C028000; // lui v0,0x0080 | |
1292 | + g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp) | |
1293 | + g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp) | |
1294 | + } else { | |
1295 | + // X1 | |
1296 | + err=get_value(); | |
1297 | + if (err) return err; | |
1298 | + check_obj_space(2); | |
1299 | + g_object[g_objpos++]=0x27BDFFF0; // addiu sp,sp,-16 | |
1300 | + g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp) | |
1301 | + // Y1 | |
1302 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
1303 | + g_srcpos++; | |
1304 | + err=get_value(); | |
1305 | + if (err) return err; | |
1306 | + check_obj_space(1); | |
1307 | + g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp) | |
1308 | + } | |
1309 | + if (2<paramnum) { | |
1310 | + // X2, R, or M | |
1311 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
1312 | + g_srcpos++; | |
1313 | + err=get_value(); | |
1314 | + if (err) return err; | |
1315 | + check_obj_space(1); | |
1316 | + g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp) | |
1317 | + if (3<paramnum) { | |
1318 | + // Y2, BC, or N | |
1319 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
1320 | + g_srcpos++; | |
1321 | + err=get_value(); | |
1322 | + if (err) return err; | |
1323 | + check_obj_space(1); | |
1324 | + g_object[g_objpos++]=0xAFA20010; // sw v0,16(sp) | |
1325 | + } | |
1326 | + } | |
1327 | + if (func==FUNC_GPRINT) { | |
1328 | + // S$ | |
1329 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
1330 | + g_srcpos++; | |
1331 | + err=get_string(); | |
1332 | + if (err) return err; | |
1333 | + } else if (func==FUNC_PUTBMP) { | |
1334 | + // BMP | |
1335 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
1336 | + g_srcpos++; | |
1337 | + spos=g_srcpos; | |
1338 | + err=get_label(); | |
1339 | + if (g_label && !err) { | |
1340 | + if (search_var_name(g_label)!=-1) { | |
1341 | + // This is a long var name. | |
1342 | + g_label=0; | |
1343 | + g_srcpos=spos; | |
1344 | + } | |
1345 | + } | |
1346 | + if (g_label && !err) { | |
1347 | + // Label/number is constant. | |
1348 | + // Linker will change following codes later. | |
1349 | + // Note that 0x0814xxxx and 0x0815xxxx are specific codes for these. | |
1350 | + check_obj_space(2); | |
1351 | + g_object[g_objpos++]=0x08140000|((g_label>>16)&0x0000FFFF); // lui v0,xxxx | |
1352 | + g_object[g_objpos++]=0x08150000|(g_label&0x0000FFFF); // ori v0,v0,xxxx | |
1353 | + // Change func to FUNC_PUTBMP2 (label mode). | |
1354 | + func=FUNC_PUTBMP2; | |
1355 | + } else { | |
1356 | + err=get_value(); | |
1357 | + if (err) return err; | |
1358 | + } | |
1359 | + } else { | |
1360 | + // [,C] | |
1361 | + if (g_source[g_srcpos]==',') { | |
1362 | + g_srcpos++; | |
1363 | + err=get_value(); | |
1364 | + if (err) return err; | |
1365 | + } else { | |
1366 | + // If C is omitted, use -1. | |
1367 | + check_obj_space(1); | |
1368 | + g_object[g_objpos++]=0x2402FFFF; // addiu v0,zero,-1 | |
1369 | + } | |
1370 | + } | |
1371 | + // Call library | |
1372 | + call_lib_code(LIB_GRAPHIC | func); | |
1373 | + // Restore stack pointer | |
1374 | + check_obj_space(1); | |
1375 | + g_object[g_objpos++]=0x27BD0010; // addiu sp,sp,16 | |
1376 | + return 0; | |
1377 | +} | |
1378 | + | |
1379 | +char* fopen_statement_main(enum functions func){ | |
1380 | + // func is either FUNC_FOPENST or FUNC_FOPEN | |
1381 | + char* err; | |
1382 | + // Get 1st | |
1383 | + err=get_string(); | |
1384 | + if (err) return err; | |
1385 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
1386 | + g_srcpos++; | |
1387 | + check_obj_space(2); | |
1388 | + g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8 | |
1389 | + g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp) | |
1390 | + // Get 2nd | |
1391 | + err=get_string(); | |
1392 | + if (err) return err; | |
1393 | + check_obj_space(1); | |
1394 | + g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp) | |
1395 | + // Get 3rd | |
1396 | + if (g_source[g_srcpos]==',') { | |
1397 | + g_srcpos++; | |
1398 | + err=get_value(); | |
1399 | + if (err) return err; | |
1400 | + } else { | |
1401 | + // If 3rd parameter is omitted, use 0. | |
1402 | + check_obj_space(1); | |
1403 | + g_object[g_objpos++]=0x24020000; // addiu v0,zero,0 | |
1404 | + } | |
1405 | + call_lib_code(LIB_FILE | func); | |
1406 | + check_obj_space(1); | |
1407 | + g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8 | |
1408 | + return 0; | |
1409 | +} | |
1410 | + | |
1411 | +char* file_statement(){ | |
1412 | + char* err; | |
1413 | + err=get_value(); | |
1414 | + if (err) return err; | |
1415 | + call_lib_code(LIB_FILE | FUNC_FILE); | |
1416 | + return 0; | |
1417 | +} | |
1418 | + | |
1419 | +char* fclose_statement(){ | |
1420 | + char* err; | |
1421 | + int orgpos=g_srcpos; | |
1422 | + if (endOfStatement()) { | |
1423 | + // If no argument, use 0 | |
1424 | + check_obj_space(1); | |
1425 | + g_object[g_objpos++]=0x24020000; // addiu v0,zero,0 | |
1426 | + } else { | |
1427 | + err=get_value(); | |
1428 | + if (err) return err; | |
1429 | + } | |
1430 | + call_lib_code(LIB_FILE | FUNC_FCLOSE); | |
1431 | + return 0; | |
1432 | +} | |
1433 | + | |
1434 | +char* fget_statement(){ | |
1435 | + return param2_statement(LIB_FILE | FUNC_FGET); | |
1436 | +} | |
1437 | + | |
1438 | +char* fput_statement(){ | |
1439 | + return param2_statement(LIB_FILE | FUNC_FPUT); | |
1440 | +} | |
1441 | + | |
1442 | +char* fseek_statement(){ | |
1443 | + char* err; | |
1444 | + err=get_value(); | |
1445 | + if (err) return err; | |
1446 | + call_lib_code(LIB_FILE | FUNC_FSEEK); | |
1447 | + return 0; | |
1448 | +} | |
1449 | + | |
1450 | +char* fputc_statement(){ | |
1451 | + char* err; | |
1452 | + err=get_value(); | |
1453 | + if (err) return err; | |
1454 | + call_lib_code(LIB_FILE | FUNC_FPUTC); | |
1455 | + return 0; | |
1456 | +} | |
1457 | + | |
1458 | +char* fremove_statement(){ | |
1459 | + char* err; | |
1460 | + err=get_string(); | |
1461 | + if (err) return err; | |
1462 | + call_lib_code(LIB_FILE | FUNC_FREMOVE); | |
1463 | + return 0; | |
1464 | +} | |
1465 | + | |
1466 | +char* usevar_statement(){ | |
1467 | + char* err; | |
1468 | + int i; | |
1469 | + do { | |
1470 | + next_position(); | |
1471 | + i=check_var_name(); | |
1472 | + if (i<65536) return ERR_SYNTAX; | |
1473 | + err=register_var_name(i); | |
1474 | + if (err) return err; | |
1475 | + if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') g_srcpos++; | |
1476 | + next_position(); | |
1477 | + if (g_source[g_srcpos]==',') { | |
1478 | + g_srcpos++; | |
1479 | + } else { | |
1480 | + break; | |
1481 | + } | |
1482 | + } while(1); | |
1483 | + return 0; | |
1484 | +} | |
1485 | + | |
1486 | +char* playwave_statement(){ | |
1487 | + char* err; | |
1488 | + err=get_string(); | |
1489 | + if (err) return err; | |
1490 | + check_obj_space(2); | |
1491 | + g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 | |
1492 | + g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp) | |
1493 | + if (g_source[g_srcpos]==',') { | |
1494 | + g_srcpos++; | |
1495 | + // Get 2nd | |
1496 | + err=get_value(); | |
1497 | + if (err) return err; | |
1498 | + } else { | |
1499 | + // If 2rd parameter is omitted, use 0. | |
1500 | + check_obj_space(1); | |
1501 | + g_object[g_objpos++]=0x24020000; // addiu v0,zero,0 | |
1502 | + } | |
1503 | + call_lib_code(LIB_PLAYWAVE); | |
1504 | + check_obj_space(1); | |
1505 | + g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4 | |
1506 | + return 0; | |
1507 | +} | |
1508 | + | |
1509 | +char* useclass_statement(){ | |
1510 | + char* err; | |
1511 | + int i; | |
1512 | + int* cmpdata; | |
1513 | + do { | |
1514 | + next_position(); | |
1515 | + i=check_var_name(); | |
1516 | + if (i<65536) return ERR_SYNTAX; | |
1517 | + // Check if the class already exists | |
1518 | + cmpdata_reset(); | |
1519 | + while(cmpdata=cmpdata_find(CMPDATA_CLASS)){ | |
1520 | + if (cmpdata[1]==i) { | |
1521 | + // The class was already defined. | |
1522 | + i=0; | |
1523 | + break; | |
1524 | + } | |
1525 | + } | |
1526 | + if (i) { | |
1527 | + // Remove a objects before USECLASS statement | |
1528 | + g_objpos=0; | |
1529 | + // Insert a NOP assembly. This will be replaced by jump statement. | |
1530 | + check_obj_space(1); | |
1531 | + g_object[g_objpos++]=0x00000000; // nop | |
1532 | + // Load new file to define class statement. | |
1533 | + g_class=i; | |
1534 | + return ERR_COMPILE_CLASS; | |
1535 | + } | |
1536 | + if (g_source[g_srcpos]==',') { | |
1537 | + g_srcpos++; | |
1538 | + } else { | |
1539 | + break; | |
1540 | + } | |
1541 | + } while(1); | |
1542 | + return 0; | |
1543 | +} | |
1544 | + | |
1545 | +char* setdir_statement(){ | |
1546 | + char* err; | |
1547 | + err=get_string(); | |
1548 | + if (err) return err; | |
1549 | + call_lib_code(LIB_SETDIR); | |
1550 | + return 0; | |
1551 | +} | |
1552 | + | |
1553 | +char* option_statement(){ | |
1554 | + while(1){ | |
1555 | + next_position(); | |
1556 | + if (nextCodeIs("NOLINENUM")) { | |
1557 | + g_nolinenum=1; | |
1558 | + } else { | |
1559 | + return ERR_SYNTAX; | |
1560 | + } | |
1561 | + next_position(); | |
1562 | + if (g_source[g_srcpos]==',') { | |
1563 | + g_srcpos++; | |
1564 | + } else { | |
1565 | + break; | |
1566 | + } | |
1567 | + } | |
1568 | + return 0; | |
1569 | +} | |
1570 | + | |
1571 | +char* idle_statement(){ | |
1572 | + check_obj_space(2); | |
1573 | + g_object[g_objpos++]=0x42000020; // wait | |
1574 | + return 0; | |
1575 | +} | |
1576 | + | |
1577 | +#ifdef __DEBUG | |
1578 | + char* debug_statement(){ | |
1579 | + call_lib_code(LIB_DEBUG); | |
1580 | + return 0; | |
1581 | + } | |
1582 | +#endif | |
1583 | + | |
1584 | +// Aliases follow | |
1585 | + | |
1586 | +char* poke_statement(){ | |
1587 | + return poke_statement_sub(8); | |
1588 | +} | |
1589 | + | |
1590 | +char* poke16_statement(){ | |
1591 | + return poke_statement_sub(16); | |
1592 | +} | |
1593 | + | |
1594 | +char* poke32_statement(){ | |
1595 | + return poke_statement_sub(32); | |
1596 | +} | |
1597 | + | |
1598 | +char* palette_statement(){ | |
1599 | + return param4_statement(LIB_PALETTE); | |
1600 | +} | |
1601 | + | |
1602 | +char* gpalette_statement(){ | |
1603 | + return param4_statement(LIB_GPALETTE); | |
1604 | +} | |
1605 | + | |
1606 | +char* print_statement(){ | |
1607 | + return print_statement_main(LIB_PRINTSTR,LIB_STRING); | |
1608 | +} | |
1609 | + | |
1610 | +char* pset_statement(){ | |
1611 | + return graphic_statement(FUNC_PSET); | |
1612 | +} | |
1613 | + | |
1614 | +char* line_statement(){ | |
1615 | + return graphic_statement(FUNC_LINE); | |
1616 | +} | |
1617 | + | |
1618 | +char* boxfill_statement(){ | |
1619 | + return graphic_statement(FUNC_BOXFILL); | |
1620 | +} | |
1621 | + | |
1622 | +char* circle_statement(){ | |
1623 | + return graphic_statement(FUNC_CIRCLE); | |
1624 | +} | |
1625 | + | |
1626 | +char* circlefill_statement(){ | |
1627 | + return graphic_statement(FUNC_CIRCLEFILL); | |
1628 | +} | |
1629 | + | |
1630 | +char* gprint_statement(){ | |
1631 | + return graphic_statement(FUNC_GPRINT); | |
1632 | +} | |
1633 | + | |
1634 | +char* putbmp_statement(){ | |
1635 | + return graphic_statement(FUNC_PUTBMP); | |
1636 | +} | |
1637 | + | |
1638 | +char* point_statement(){ | |
1639 | + return graphic_statement(FUNC_POINT); | |
1640 | +} | |
1641 | + | |
1642 | +char* fopen_statement(){ | |
1643 | + return fopen_statement_main(FUNC_FOPENST); | |
1644 | +} | |
1645 | + | |
1646 | +char* fprint_statement(){ | |
1647 | + return print_statement_main(LIB_FILE | FUNC_FPRINTSTR,LIB_FILE | FUNC_FSTRING); | |
1648 | +} | |
1649 | + | |
1650 | +static const void* statement_list[]={ | |
1651 | + "REM",rem_statement, | |
1652 | + "SOUND ",sound_statement, | |
1653 | + "MUSIC ",music_statement, | |
1654 | + "DRAWCOUNT ",drawcount_statement, | |
1655 | + "CURSOR ",cursor_statement, | |
1656 | + "PALETTE ",palette_statement, | |
1657 | + "GPALETTE ",gpalette_statement, | |
1658 | + "BGCOLOR ",bgcolor_statement, | |
1659 | + "CLS",cls_statement, | |
1660 | + "GCLS",gcls_statement, | |
1661 | + "COLOR ",color_statement, | |
1662 | + "GCOLOR ",gcolor_statement, | |
1663 | + "RESTORE ",restore_statement, | |
1664 | + "DATA ",data_statement, | |
1665 | + "CDATA ",cdata_statement, | |
1666 | + "LABEL ",label_statement, | |
1667 | + "DIM ",dim_statement, | |
1668 | + "CLEAR",clear_statement, | |
1669 | + "PRINT",print_statement, | |
1670 | + "IF ",if_statement, | |
1671 | + "ELSEIF ",elseif_statement, | |
1672 | + "ELSE",else_statement, | |
1673 | + "ENDIF",endif_statement, | |
1674 | + "END",end_statement, | |
1675 | + "EXEC ",exec_statement, | |
1676 | + "GOTO ",goto_statement, | |
1677 | + "GOSUB ",gosub_statement, | |
1678 | + "RETURN",return_statement, | |
1679 | + "POKE ",poke_statement, | |
1680 | + "POKE16 ",poke16_statement, | |
1681 | + "POKE32 ",poke32_statement, | |
1682 | + "FOR ",for_statement, | |
1683 | + "NEXT",next_statement, | |
1684 | + "LET ",let_statement, | |
1685 | + "PCG ",pcg_statement, | |
1686 | + "USEPCG",usepcg_statement, | |
1687 | + "SCROLL ",scroll_statement, | |
1688 | + "WAIT ",wait_statement, | |
1689 | + "USEGRAPHIC",usegraphic_statement, | |
1690 | + "PSET ",pset_statement, | |
1691 | + "LINE ",line_statement, | |
1692 | + "BOXFILL ",boxfill_statement, | |
1693 | + "CIRCLE ",circle_statement, | |
1694 | + "CIRCLEFILL ",circlefill_statement, | |
1695 | + "GPRINT ",gprint_statement, | |
1696 | + "PUTBMP ",putbmp_statement, | |
1697 | + "POINT ",point_statement, | |
1698 | + "VAR ",var_statement, | |
1699 | + "DO",do_statement, | |
1700 | + "LOOP",loop_statement, | |
1701 | + "WHILE ",while_statement, | |
1702 | + "WEND",wend_statement, | |
1703 | + "BREAK",break_statement, | |
1704 | + "CONTINUE",continue_statement, | |
1705 | + "SYSTEM",system_statement, | |
1706 | + "WIDTH ",width_statement, | |
1707 | + "FOPEN ",fopen_statement, | |
1708 | + "FILE ",file_statement, | |
1709 | + "FCLOSE",fclose_statement, | |
1710 | + "FPRINT ",fprint_statement, | |
1711 | + "FGET ",fget_statement, | |
1712 | + "FPUT ",fput_statement, | |
1713 | + "FPUTC ",fputc_statement, | |
1714 | + "FSEEK ",fseek_statement, | |
1715 | + "FREMOVE ",fremove_statement, | |
1716 | + "USEVAR ",usevar_statement, | |
1717 | + "PLAYWAVE ",playwave_statement, | |
1718 | + "USECLASS ",useclass_statement, | |
1719 | + "FIELD ",field_statement, | |
1720 | + "METHOD ",method_statement, | |
1721 | + "DELETE ",delete_statement, | |
1722 | + "CALL ",call_statement, | |
1723 | + "STATIC ",static_statement, | |
1724 | + "SETDIR ",setdir_statement, | |
1725 | + "OPTION ",option_statement, | |
1726 | + "USETIMER ",usetimer_statement, | |
1727 | + "TIMER ",timer_statement, | |
1728 | + "INTERRUPT ",interrupt_statement, | |
1729 | + "IDLE",idle_statement, | |
1730 | + // List of additional statements follows | |
1731 | + ADDITIONAL_STATEMENTS | |
1732 | +}; | |
1733 | + | |
1734 | +char* statement(void){ | |
1735 | + char* err; | |
1736 | + int prevpos; | |
1737 | + int i; | |
1738 | + char* (*f)(); | |
1739 | + // Clear flag for temp area usage. | |
1740 | + g_temp_area_used=0; | |
1741 | + // Initialize stack handler used for value | |
1742 | + g_sdepth=g_maxsdepth=0; | |
1743 | + // Allow shifting code object when stack is used. | |
1744 | + // This will be disalloed when CMPDATA_UNSOLVED etc is used. | |
1745 | + g_allow_shift_obj=1; | |
1746 | + // Seek the statement | |
1747 | + for (i=0;i<sizeof(statement_list)/sizeof(statement_list[0]);i+=2){ | |
1748 | + if (nextCodeIs((char*)statement_list[i])) break; | |
1749 | + } | |
1750 | + if (i<sizeof(statement_list)/sizeof(statement_list[0])) { | |
1751 | + // Statement found. Call it. | |
1752 | + f=statement_list[i+1]; | |
1753 | + err=f(); | |
1754 | +#ifdef __DEBUG | |
1755 | + } else if (nextCodeIs("DEBUG")) { | |
1756 | + err=debug_statement(); | |
1757 | +#endif | |
1758 | + } else { | |
1759 | + err=let_statement(); | |
1760 | + } | |
1761 | + if (err) return err; | |
1762 | + // Stack handler must be zero here. | |
1763 | + if (g_sdepth!=0) return ERR_UNKNOWN; | |
1764 | + // Check if temp area is used | |
1765 | + if (g_temp_area_used) { | |
1766 | + // Temp area is used. Insert a garbage collection flag setting routine. | |
1767 | + check_obj_space(1); | |
1768 | + g_object[g_objpos++]=0x7ED6F000;// ext s6,s6,0,31 | |
1769 | + } | |
1770 | + return 0; | |
1771 | +} |
@@ -0,0 +1,237 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +/* | |
13 | + Public functions: | |
14 | + char* get_string(void); | |
15 | + char* simple_string(void); | |
16 | +*/ | |
17 | + | |
18 | +#include "api.h" | |
19 | +#include "compiler.h" | |
20 | + | |
21 | +char* simple_string(void){ | |
22 | + char* err; | |
23 | + unsigned char b1,b2; | |
24 | + int i,j; | |
25 | + next_position(); | |
26 | + b1=g_source[g_srcpos]; | |
27 | + b2=g_source[g_srcpos+1]; | |
28 | + if (b1=='"') { | |
29 | + // Constant string | |
30 | + // Count character number (+1 for \0) | |
31 | + // This may be more than actual character number due to escape sequence. | |
32 | + i=0; | |
33 | + while(1){ | |
34 | + i++; | |
35 | + b1=g_source[g_srcpos+i]; | |
36 | + if (b1=='"') { | |
37 | + break; | |
38 | + } else if (b1=='\\') { | |
39 | + i++; | |
40 | + } else if (b1<0x20) { | |
41 | + // This is an error, that will be detected later again. | |
42 | + break; | |
43 | + } | |
44 | + }; | |
45 | + g_srcpos++; | |
46 | + // Determine required word number | |
47 | + i=(i+3)/4; | |
48 | + // Determine address containing the string | |
49 | + j=(int)(&(g_object[g_objpos+3])); | |
50 | + // Note that using "bgezal zero," must be used to skip some region. | |
51 | + // This is to find embed string in the code. | |
52 | + check_obj_space(2+i); | |
53 | + g_object[g_objpos++]=0x04110000|((i+1)&0x0000FFFF); // bgezal zero,xxxx | |
54 | + g_object[g_objpos++]=0x03E01021; // addu v0,ra,zero | |
55 | + for(j=0;(b1=g_source[g_srcpos++])!='"';j++) { | |
56 | + if (b1=='\\') { | |
57 | + b1=g_source[g_srcpos++]; | |
58 | + if (b1=='x' || b1=='X') { | |
59 | + // Hexadecimal | |
60 | + b1=g_source[g_srcpos++]; | |
61 | + if ('0'<=b1 && b1<='9') b1=b1-'0'; | |
62 | + else if ('A'<=b1 && b1<='F') b1=b1-'A'+10; | |
63 | + else if ('a'<=b1 && b1<='f') b1=b1-'a'+10; | |
64 | + else return ERR_SYNTAX; | |
65 | + b2=g_source[g_srcpos++]; | |
66 | + if ('0'<=b2 && b2<='9') b2=b2-'0'; | |
67 | + else if ('A'<=b2 && b2<='F') b2=b2-'A'+10; | |
68 | + else if ('a'<=b2 && b2<='f') b2=b2-'a'+10; | |
69 | + else return ERR_SYNTAX; | |
70 | + b1=(b1<<4)|b2; | |
71 | + } else if (b1<0x20) { | |
72 | + return ERR_SYNTAX; | |
73 | + } else { | |
74 | + // \\ or \" | |
75 | + } | |
76 | + } else if (b1<0x20) { | |
77 | + return ERR_SYNTAX; | |
78 | + } | |
79 | + ((char*)(&g_object[g_objpos]))[j]=b1; | |
80 | + } | |
81 | + ((char*)(&g_object[g_objpos]))[j]=0x00; | |
82 | + g_objpos+=i; | |
83 | + } else if ('A'<=b1 && b1<='Z') { | |
84 | + i=get_var_number(); | |
85 | + if (i<0) { | |
86 | + // Function | |
87 | + // String would be pointed by $v0 | |
88 | + // Otherwise, it will be assinged in xxx_function() function. | |
89 | + err=str_function(); | |
90 | + if (err) return err; | |
91 | + // Temp area would be used when executing. | |
92 | + g_temp_area_used=1; | |
93 | + return 0; | |
94 | + } | |
95 | + if (g_source[g_srcpos]=='.') { | |
96 | + // This is an object field or method to return string | |
97 | + check_obj_space(1); | |
98 | + g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8) | |
99 | + g_srcpos++; | |
100 | + return string_obj_field(); | |
101 | + } else if (g_source[g_srcpos]=='(') { | |
102 | + // An array element contains pointer to an object. | |
103 | + g_srcpos++; | |
104 | + err=get_dim_value(i); | |
105 | + if (err) return err; | |
106 | + if (g_source[g_srcpos]!='.') return ERR_SYNTAX; | |
107 | + g_srcpos++; | |
108 | + return string_obj_field(); | |
109 | + } | |
110 | + if (g_source[g_srcpos]!='$') return ERR_SYNTAX; | |
111 | + g_srcpos++; | |
112 | + // String variable | |
113 | + next_position(); | |
114 | + if (g_source[g_srcpos]=='(') { | |
115 | + // A part of string | |
116 | + g_srcpos++; | |
117 | + err=get_value(); | |
118 | + if (err) return err; | |
119 | + if (g_source[g_srcpos]==')') { | |
120 | + g_srcpos++; | |
121 | + // Put -1 to $a0 | |
122 | + check_obj_space(1); | |
123 | + g_object[g_objpos++]=0x2404FFFF; // addiu a0,zero,-1 | |
124 | + } else if (g_source[g_srcpos]==',') { | |
125 | + g_srcpos++; | |
126 | + // Store $v0 in stack | |
127 | + g_sdepth+=4; | |
128 | + if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth; | |
129 | + check_obj_space(1); | |
130 | + g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp) | |
131 | + // Get next value | |
132 | + err=get_value(); | |
133 | + if (err) return err; | |
134 | + // Copy $v0 to $a0 and get value from stack to $a0. | |
135 | + check_obj_space(2); | |
136 | + g_object[g_objpos++]=0x00402021; // addu a0,v0,zero | |
137 | + g_object[g_objpos++]=0x8FA20000|g_sdepth; // lw v0,xx(sp) | |
138 | + g_sdepth-=4; | |
139 | + if (g_source[g_srcpos]!=')') return ERR_SYNTAX; | |
140 | + g_srcpos++; | |
141 | + // Temp area will be used when executing. | |
142 | + g_temp_area_used=1; | |
143 | + } else { | |
144 | + return ERR_SYNTAX; | |
145 | + } | |
146 | + // $a1 is var number, $v0 is position, $a0 is length | |
147 | + check_obj_space(1); | |
148 | + g_object[g_objpos++]=0x24050000|(i); // addiu a1,zero,xx | |
149 | + call_lib_code(LIB_MIDSTR); | |
150 | + } else { | |
151 | + // Simple string | |
152 | + check_obj_space(1); | |
153 | + g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8) | |
154 | + // String is pointed by $v0 | |
155 | + } | |
156 | + } else { | |
157 | + return ERR_SYNTAX; | |
158 | + } | |
159 | + return 0; | |
160 | +} | |
161 | + | |
162 | +char* get_string_sub(){ | |
163 | + char* err; | |
164 | + char b1; | |
165 | + // Obtain initial string | |
166 | + err=simple_string(); | |
167 | + if (err) return err; | |
168 | + // Check if connection operator exists | |
169 | + next_position(); | |
170 | + b1=g_source[g_srcpos]; | |
171 | + if (b1!='+' && b1!='&') return 0; // Exit if connection operator does not exist. | |
172 | + g_srcpos++; | |
173 | + // Connection required. | |
174 | + // Prepare one level of stack for handling | |
175 | + g_sdepth+=4; | |
176 | + if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth; | |
177 | + while(1) { | |
178 | + // Store current pointer in stack | |
179 | + check_obj_space(1); | |
180 | + g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp) | |
181 | + // Obtain next string (pointer will be in $v0) | |
182 | + err=simple_string(); | |
183 | + if (err) return err; | |
184 | + // Restore previous pointer from stack in $a0 and copy $v0 to $a1 | |
185 | + // Call library | |
186 | + check_obj_space(2); | |
187 | + g_object[g_objpos++]=0x8FA40000|g_sdepth; // lw a0,xx(sp) | |
188 | + call_lib_code(LIB_CONNECT_STRING); | |
189 | + // Temp area will be used when executing. | |
190 | + g_temp_area_used=1; | |
191 | + // Check if further connection operator exists | |
192 | + next_position(); | |
193 | + b1=g_source[g_srcpos]; | |
194 | + if (b1!='+' && b1!='&') break; | |
195 | + g_srcpos++; | |
196 | + } | |
197 | + g_sdepth-=4; | |
198 | + return 0; | |
199 | +} | |
200 | + | |
201 | +char* get_string(){ | |
202 | + // This is only the public function. | |
203 | + // Note that this can be called recursively. | |
204 | + // String may contain a function with a parameter of value | |
205 | + // that is a function with a parameter of string. | |
206 | + // Result will be in $v0 as a pointer. | |
207 | + char* err; | |
208 | + char b1; | |
209 | + int i,prevpos; | |
210 | + if (g_sdepth==0) { | |
211 | + // Initialize stack handler | |
212 | + g_maxsdepth=0; | |
213 | + prevpos=g_objpos; | |
214 | + // Stack decrement command will be filled later | |
215 | + check_obj_space(1); | |
216 | + g_object[g_objpos++]=0x00000000; // nop (will be replaced by "addiu sp,sp,-xx") | |
217 | + } | |
218 | + err=get_string_sub(); | |
219 | + if (err) return err; | |
220 | + if (g_sdepth==0) { | |
221 | + if (g_maxsdepth==0) { | |
222 | + // Stack was not used. | |
223 | + if (g_allow_shift_obj) { | |
224 | + shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1); | |
225 | + g_objpos--; | |
226 | + } | |
227 | + } else { | |
228 | + // Stack was used. | |
229 | + check_obj_space(1); | |
230 | + g_object[prevpos]=0x27BD0000 | (0-g_maxsdepth) & 0x0000FFFF; // addiu sp,sp,-xx | |
231 | + g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx | |
232 | + } | |
233 | + } | |
234 | + g_lastvar=VAR_STRING; | |
235 | + return 0; | |
236 | +} | |
237 | + |
@@ -0,0 +1,325 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include <xc.h> | |
13 | +#include "compiler.h" | |
14 | +#include "api.h" | |
15 | + | |
16 | +/* | |
17 | + 32 different type interruptions are possible. | |
18 | + See definition in compiler.h like: | |
19 | + #define INTERRUPT_TIMER 0 | |
20 | + extern int g_interrupt_flags; | |
21 | + extern int g_int_vector[]; | |
22 | + #define raise_interrupt_flag(x) do {\ | |
23 | +*/ | |
24 | + | |
25 | +// Timer value that increments every timer event | |
26 | +static int g_timer; | |
27 | + | |
28 | +// Interrupt types | |
29 | +static const void* interrupt_list[]={ | |
30 | + "TIMER", (void*)INTERRUPT_TIMER, | |
31 | + "DRAWCOUNT",(void*)INTERRUPT_DRAWCOUNT, | |
32 | + "KEYS", (void*)INTERRUPT_KEYS, | |
33 | + "INKEY", (void*)INTERRUPT_INKEY, | |
34 | + "MUSIC", (void*)INTERRUPT_MUSIC, | |
35 | + "WAVE", (void*)INTERRUPT_WAVE, | |
36 | + ADDITIONAL_INTERRUPT_FUNCTIONS | |
37 | +}; | |
38 | +#define NUM_INTERRUPT_TYPES ((sizeof(interrupt_list)/sizeof(interrupt_list[0]))/2) | |
39 | +// Flags for interrupt | |
40 | +int g_interrupt_flags; | |
41 | +// Jump address when interrupt | |
42 | +int g_int_vector[NUM_INTERRUPT_TYPES]; | |
43 | + | |
44 | +/* | |
45 | + Initialize and termination | |
46 | +*/ | |
47 | + | |
48 | +void init_timer(){ | |
49 | + int i; | |
50 | + // Stop timer, first | |
51 | + T1CON=0x0000; | |
52 | + IEC0bits.T1IE=0; | |
53 | + TMR1=0; | |
54 | + PR1=0xffff; | |
55 | + g_timer=0; | |
56 | + // Disable interrupt | |
57 | + IEC0bits.CS1IE=0; | |
58 | + for(i=0;i<NUM_INTERRUPT_TYPES;i++) g_int_vector[i]=0; | |
59 | + // CS0 interrupt every 1/60 sec (triggered by Timer2) | |
60 | + IPC0bits.CS0IP=3; | |
61 | + IPC0bits.CS0IS=0; | |
62 | + IFS0bits.CS0IF=0; | |
63 | + IEC0bits.CS0IE=1; | |
64 | +} | |
65 | + | |
66 | +void stop_timer(){ | |
67 | + // Stop timer | |
68 | + T1CON=0x0000; | |
69 | + IEC0bits.T1IE=0; | |
70 | + // Disable interrupt | |
71 | + IEC0bits.CS1IE=0; | |
72 | +} | |
73 | + | |
74 | +/* | |
75 | + Timer interprtation | |
76 | +*/ | |
77 | + | |
78 | +// Interrupt handler | |
79 | +#ifndef __DEBUG | |
80 | + // Timer1 is also used for debug mode | |
81 | + #pragma interrupt T1Handler IPL2SOFT vector 4 | |
82 | +#endif | |
83 | +void T1Handler(void){ | |
84 | + g_timer++; | |
85 | + // Clear Timer1 interrupt flag | |
86 | + IFS0bits.T1IF=0; | |
87 | + // Raise TIMER interrupt flag | |
88 | + raise_interrupt_flag(INTERRUPT_TIMER); | |
89 | +} | |
90 | + | |
91 | +void lib_usetimer(int usec){ | |
92 | + int temppr1; | |
93 | + // Stop timer, first | |
94 | + T1CON=0x0000; | |
95 | + IEC0bits.T1IE=0; | |
96 | + TMR1=0; | |
97 | + PR1=0xffff; | |
98 | + // PR1 setting | |
99 | + // ((CPU_CLOCK_HZ/10000)*usec)< 2147483648, | |
100 | + // therefore, the calculation can be done as 32 bit signed integer | |
101 | + temppr1=((CPU_CLOCK_HZ/10000)*usec)/100; | |
102 | + if (temppr1<=65536) { | |
103 | + // no prescaler | |
104 | + T1CON=0x0000; | |
105 | + PR1=temppr1-1; | |
106 | + } else if ((temppr1>>3)<=65536) { | |
107 | + // 1/8 prescaler | |
108 | + T1CON=0x0010; | |
109 | + PR1=(temppr1>>3)-1; | |
110 | + } else if ((temppr1>>6)<=65536) { | |
111 | + // 1/64 prescaler | |
112 | + T1CON=0x0020; | |
113 | + PR1=(temppr1>>6)-1; | |
114 | + } else if ((temppr1>>8)<=65536) { | |
115 | + // 1/256 prescaler | |
116 | + T1CON=0x0030; | |
117 | + PR1=(temppr1>>8)-1; | |
118 | + } else { | |
119 | + err_invalid_param(); | |
120 | + } | |
121 | + // Timer1 interrupt: priority 2 | |
122 | + IPC1bits.T1IP=2; | |
123 | + IPC1bits.T1IS=0; | |
124 | + IEC0bits.T1IE=1; | |
125 | + // Start timer | |
126 | + T1CONbits.ON=1; | |
127 | +} | |
128 | + | |
129 | +char* usetimer_statement(){ | |
130 | + char* err; | |
131 | + err=get_value(); | |
132 | + if (err) return err; | |
133 | + call_quicklib_code(lib_usetimer,ASM_ADDU_A0_V0_ZERO); | |
134 | + return 0; | |
135 | +} | |
136 | + | |
137 | +char* timer_statement(){ | |
138 | + int i; | |
139 | + char* err; | |
140 | + err=get_value(); | |
141 | + if (err) return err; | |
142 | + i=(int)(&g_timer)+0x8000; | |
143 | + check_obj_space(4); | |
144 | + g_object[g_objpos++]=0x3C030000|((i>>16)&0x0000FFFF); // lui v1,xxxx | |
145 | + g_object[g_objpos++]=0xAC620000|((i-0x8000)&0xFFFF); // sw v0,xxxx(v1) | |
146 | + i=(int)(&TMR1)+0x8000;//0xBF800610 | |
147 | + g_object[g_objpos++]=0x3C030000|((i>>16)&0x0000FFFF); // lui v1,0xbf80 | |
148 | + g_object[g_objpos++]=0xAC600000|((i-0x8000)&0xFFFF); // sw zero,0x0610(v1) | |
149 | + return 0; | |
150 | +} | |
151 | + | |
152 | +char* timer_function(){ | |
153 | + int i; | |
154 | + i=(int)(&g_timer)+0x8000; | |
155 | + check_obj_space(2); | |
156 | + g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx | |
157 | + g_object[g_objpos++]=0x8C420000|((i-0x8000)&0xFFFF); // lw v0,xxxx(v0) | |
158 | + return 0; | |
159 | +} | |
160 | + | |
161 | +/* | |
162 | + Interrupt interprtation | |
163 | + To cause interruption, use raise_interrupt_flag() macro | |
164 | + For example, | |
165 | + raise_interrupt_flag(INTERRUPT_TIMER); | |
166 | + | |
167 | +*/ | |
168 | + | |
169 | +void BasicInt(int addr,void* memory){ | |
170 | + // Note that $s0-$s7 and $fp values must be set again here. | |
171 | + // Set s5 for initial_s5_stack | |
172 | + asm volatile("la $s5,%0"::"i"(&g_initial_s5_stack[2])); | |
173 | + // Set s7 for easy calling call_library() | |
174 | + asm volatile("la $s7,%0"::"i"(&call_library)); | |
175 | + // Set fp and execute BASIC code at $a0 | |
176 | + asm volatile("addu $fp,$zero,$a1"); | |
177 | + asm volatile("jr $a0"); | |
178 | +} | |
179 | +#pragma interrupt CS1Handler IPL1SOFT vector 2 | |
180 | +void CS1Handler(void){ | |
181 | + int i; | |
182 | + // Store s0-s7, fp, and ra in stacks | |
183 | + asm volatile("#":::"s0"); | |
184 | + asm volatile("#":::"s1"); | |
185 | + asm volatile("#":::"s2"); | |
186 | + asm volatile("#":::"s3"); | |
187 | + asm volatile("#":::"s4"); | |
188 | + asm volatile("#":::"s5"); | |
189 | + asm volatile("#":::"s6"); | |
190 | + asm volatile("#":::"s7"); | |
191 | + asm volatile("#":::"fp"); | |
192 | + asm volatile("#":::"ra"); | |
193 | + while(g_interrupt_flags){ | |
194 | + for(i=0;i<NUM_INTERRUPT_TYPES;i++){ | |
195 | + if (g_interrupt_flags & (1<<i)) { | |
196 | + if (g_int_vector[i]) BasicInt(g_int_vector[i],(void*)(&g_var_mem[0])); | |
197 | + g_interrupt_flags &= (1<<i)^0xffff; | |
198 | + } | |
199 | + } | |
200 | + } | |
201 | + IFS0bits.CS1IF=0; | |
202 | +} | |
203 | + | |
204 | +void lib_interrupt_main(int itype, int address){ | |
205 | + // Set address | |
206 | + g_int_vector[itype]=address; | |
207 | + // CS1 interrupt: priority 1 | |
208 | + IPC0bits.CS1IP=1; | |
209 | + IPC0bits.CS1IS=0; | |
210 | + IEC0bits.CS1IE=1; | |
211 | +} | |
212 | + | |
213 | +void lib_interrupt(int itype){ | |
214 | + // $ra contains the address for interrupt | |
215 | + // $ra is 2 word before the interrupt address | |
216 | + asm volatile("addiu $a1,$ra,8"); | |
217 | + asm volatile("j lib_interrupt_main"); | |
218 | +} | |
219 | + | |
220 | +char* interrupt_statement(){ | |
221 | + int itype; | |
222 | + int i,opos; | |
223 | + char* err; | |
224 | + int stop=0; | |
225 | + // Check if STOP | |
226 | + stop=nextCodeIs("STOP "); | |
227 | + // Seek the interrupt | |
228 | + for (i=0;i<NUM_INTERRUPT_TYPES;i++){ | |
229 | + if (nextCodeIs((char*)interrupt_list[i*2])) break; | |
230 | + } | |
231 | + if (i<NUM_INTERRUPT_TYPES) { | |
232 | + // Interrupt found | |
233 | + itype=(int)interrupt_list[i*2+1]; | |
234 | + } else { | |
235 | + // Interrupt not found | |
236 | + return ERR_SYNTAX; | |
237 | + } | |
238 | + // Compile INTERRUPT STOP | |
239 | + if (stop) { | |
240 | + // g_int_vector[itype]=0; | |
241 | + i=(int)(&g_int_vector[itype]); | |
242 | + i-=g_gp; | |
243 | + check_obj_space(1); | |
244 | + g_object[g_objpos++]=0xAF800000|(i&0x0000FFFF); // sw zero,xxxx(gp) | |
245 | + return 0; | |
246 | + } | |
247 | + // Detect ',' | |
248 | + next_position(); | |
249 | + if (g_source[g_srcpos]!=',') return ERR_SYNTAX; | |
250 | + g_srcpos++; | |
251 | + // Store address to call | |
252 | + call_quicklib_code(lib_interrupt,ASM_ORI_A0_ZERO_|itype); | |
253 | + check_obj_space(4); | |
254 | + // Skip the region used for interrupt-calling | |
255 | + opos=g_objpos; | |
256 | + g_object[g_objpos++]=0x10000000; // b xxxxx | |
257 | + g_object[g_objpos++]=0x00000000; // nop | |
258 | + // Begin interrupt-calling region | |
259 | + // Store $ra | |
260 | + g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 | |
261 | + g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp) | |
262 | + // Compile as GOSUB statement | |
263 | + err=gosub_statement(); | |
264 | + if (err) return err; | |
265 | + // Retore $ra and return | |
266 | + check_obj_space(3); | |
267 | + g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp) | |
268 | + g_object[g_objpos++]=0x03E00008; // jr ra | |
269 | + g_object[g_objpos++]=0x08320004; // addiu sp,sp,4 | |
270 | + // End interrupt-calling region | |
271 | + // Complete B assembly | |
272 | + g_object[opos]|=g_objpos-opos-1; | |
273 | + return 0; | |
274 | +} | |
275 | + | |
276 | +/* | |
277 | + CS0 interrupt | |
278 | + IPL3SOFT vector 1 | |
279 | + | |
280 | + This interrupt is always active. Therefore, Do things as few as possible. | |
281 | + 1) Call music function if needed. | |
282 | + MUSIC interrupt is taken by music.c | |
283 | + 2) Check buttons for KEYS interrupt | |
284 | + 3) Check PS/2 for INKEY interrupt | |
285 | + 4) DRAWCOUNT interrupt | |
286 | +*/ | |
287 | + | |
288 | +const int* g_keystatus=(int*)&ps2keystatus[0]; | |
289 | + | |
290 | +#pragma interrupt CS0Handler IPL3SOFT vector 1 | |
291 | +void CS0Handler(void){ | |
292 | + static int s_keys=-1; | |
293 | + static char s_inkey=0; | |
294 | + int i; | |
295 | + IFS0bits.CS0IF=0; | |
296 | + // Call music function | |
297 | + if (g_music_active) musicint(); | |
298 | + // The interrupts are valid only when CS1 is active | |
299 | + if (IEC0bits.CS1IE) { | |
300 | + // Raise DRAWCOUNT interrupt flag | |
301 | + raise_interrupt_flag(INTERRUPT_DRAWCOUNT); | |
302 | + // Check buttons | |
303 | + if (0<=s_keys && s_keys!=(KEYPORT&(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE))) { | |
304 | + // Raise KEYS interrupt flag | |
305 | + raise_interrupt_flag(INTERRUPT_KEYS); | |
306 | + } | |
307 | + s_keys=KEYPORT&(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE); | |
308 | + // Check PS/2 keyboard down | |
309 | + if (g_int_vector[INTERRUPT_INKEY]) { | |
310 | + for(i=0;i<64;i++){ | |
311 | + if (g_keystatus[i]) { | |
312 | + // Raise INKEY interrupt flag | |
313 | + if (!s_inkey) raise_interrupt_flag(INTERRUPT_INKEY); | |
314 | + break; | |
315 | + } | |
316 | + } | |
317 | + s_inkey=(i==64) ? 0:1; | |
318 | + } | |
319 | + } | |
320 | +} | |
321 | +/* | |
322 | + for(i=0;i<256;i++){ | |
323 | + if (ps2keystatus[i]) return i; | |
324 | + } | |
325 | +*/ |
@@ -0,0 +1,295 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +/* | |
13 | + Public function is only get_value(). | |
14 | +*/ | |
15 | + | |
16 | +#include "compiler.h" | |
17 | + | |
18 | +char* get_value(); | |
19 | +char* get_value_sub(int pr); | |
20 | + | |
21 | +char* get_dim_value(int i){ | |
22 | + char* err; | |
23 | + err=get_value_sub(priority(OP_VOID)); | |
24 | + if (err) return err; | |
25 | + check_obj_space(4); | |
26 | + g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2 | |
27 | + g_object[g_objpos++]=0x8FC30000|(i*4); // lw v1,xx(s8) | |
28 | + g_object[g_objpos++]=0x00621821; // addu v1,v1,v0 | |
29 | + g_object[g_objpos++]=0x8C620000; // lw v0,0(v1) | |
30 | + next_position(); | |
31 | + if (g_source[g_srcpos]==','){ | |
32 | + // 2D, 3D or more | |
33 | + // Use a stack | |
34 | + g_sdepth+=4; | |
35 | + if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth; | |
36 | + check_obj_space(1); | |
37 | + do { | |
38 | + g_srcpos++; | |
39 | + g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp) | |
40 | + err=get_value_sub(priority(OP_VOID)); | |
41 | + if (err) return err; | |
42 | + check_obj_space(5); | |
43 | + g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2 | |
44 | + g_object[g_objpos++]=0x8FA30000|g_sdepth; // lw v1,xx(sp) | |
45 | + g_object[g_objpos++]=0x00621821; // addu v1,v1,v0 | |
46 | + g_object[g_objpos++]=0x8C620000; // lw v0,0(v1) | |
47 | + } while (g_source[g_srcpos]==','); | |
48 | + g_sdepth-=4; | |
49 | + } | |
50 | + if (g_source[g_srcpos]!=')') return ERR_SYNTAX; | |
51 | + g_srcpos++; | |
52 | + return 0; | |
53 | +} | |
54 | + | |
55 | +char* get_simple_value(void){ | |
56 | + int i; | |
57 | + char* err; | |
58 | + char b1,b2; | |
59 | + next_position(); | |
60 | + b1=g_source[g_srcpos]; | |
61 | + if (b1=='(') { | |
62 | + // (...) | |
63 | + // Parenthesis | |
64 | + g_srcpos++; | |
65 | + next_position(); | |
66 | + err=get_value_sub(priority(OP_VOID)); | |
67 | + if (err) return err; | |
68 | + next_position(); | |
69 | + if (g_source[g_srcpos]!=')') return ERR_SYNTAX; | |
70 | + g_srcpos++; | |
71 | + } else if (b1=='-') { | |
72 | + // Unary '-' operator | |
73 | + // Note that unary operators ( + and - ) have higher priority than the other operators | |
74 | + g_srcpos++; | |
75 | + err=get_simple_value(); | |
76 | + if (err) return err; | |
77 | + check_obj_space(1); | |
78 | + g_object[g_objpos++]=0x00021023; // subu v0,zero,v0 | |
79 | + g_intconst=-g_intconst; | |
80 | + } else if (b1=='&') { | |
81 | + // '&' operator | |
82 | + g_srcpos++; | |
83 | + i=get_var_number(); | |
84 | + if (i<0) return ERR_SYNTAX; | |
85 | + check_obj_space(1); | |
86 | + g_object[g_objpos++]=0x27C20000|(i*4); // addiu v0,s8,xxxx | |
87 | + } else { | |
88 | + // Main routine of getting value here | |
89 | + if (b1=='+') g_srcpos++; // Ignore unary '+' operator | |
90 | + next_position(); | |
91 | + b1=g_source[g_srcpos]; | |
92 | + b2=g_source[g_srcpos+1]; | |
93 | + if (b1=='0' && b2=='X' || b1=='$') { | |
94 | + // Starts with '0x' or '$' | |
95 | + // Hex number | |
96 | + g_srcpos++; | |
97 | + if (b1=='0') g_srcpos++; | |
98 | + i=0; | |
99 | + while(b1=g_source[g_srcpos]) { | |
100 | + if ('0'<=b1 && b1<='9') { | |
101 | + i*=16; | |
102 | + i+=b1-'0'; | |
103 | + } else if ('A'<=b1 && b1<='F') { | |
104 | + i*=16; | |
105 | + i+=b1-'A'+0x0A; | |
106 | + } else if (b1==' ') { // Skip ' ' | |
107 | + // Avoid "ELSE" statement etc | |
108 | + if ('F'<g_source[g_srcpos+2]) break; | |
109 | + } else { | |
110 | + break; | |
111 | + } | |
112 | + g_srcpos++; | |
113 | + } | |
114 | + g_intconst=i; | |
115 | + if (i&0xFFFF0000) { | |
116 | + // 32 bit | |
117 | + check_obj_space(2); | |
118 | + g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx | |
119 | + g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx | |
120 | + } else { | |
121 | + // 16 bit | |
122 | + check_obj_space(1); | |
123 | + g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx | |
124 | + } | |
125 | + } else if ('0'<=b1 && b1<='9') { | |
126 | + // Starts with 0-9 | |
127 | + // Decimal number | |
128 | + i=0; | |
129 | + while(b1=g_source[g_srcpos]) { | |
130 | + if ('0'<=b1 && b1<='9') { | |
131 | + i*=10; | |
132 | + i+=b1-'0'; | |
133 | + } else if (b1!=' ') { // Skip ' ' | |
134 | + break; | |
135 | + } | |
136 | + g_srcpos++; | |
137 | + } | |
138 | + // The next character should not be '.' or 'E'. | |
139 | + // Or, it must be recognized as a float value. | |
140 | + if (b1=='.') return ERR_SYNTAX; | |
141 | + if (b1=='E') { | |
142 | + b2=g_source[g_srcpos+1]; | |
143 | + if (b2==' ' || '0'<=b2 && b2<='9') return ERR_SYNTAX; | |
144 | + } | |
145 | + g_intconst=i; | |
146 | + if (i&0xFFFF0000) { | |
147 | + // 32 bit | |
148 | + check_obj_space(2); | |
149 | + g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx | |
150 | + g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx | |
151 | + } else { | |
152 | + // 16 bit | |
153 | + check_obj_space(1); | |
154 | + g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx | |
155 | + } | |
156 | + } else { | |
157 | + g_valueisconst=0; | |
158 | + i=get_var_number(); | |
159 | + if (i<0) { | |
160 | + // Must be a function. | |
161 | + return function(); | |
162 | + } | |
163 | + if (g_source[g_srcpos]=='(') { | |
164 | + // Dimension | |
165 | + g_srcpos++; | |
166 | + err=get_dim_value(i); | |
167 | + if (err) return err; | |
168 | + } else { | |
169 | + // Simple value | |
170 | + check_obj_space(1); | |
171 | + g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8) | |
172 | + } | |
173 | + // Check if this is an object | |
174 | + if (g_source[g_srcpos]=='.') { | |
175 | + // This is an object. See the filed of it. | |
176 | + g_srcpos++; | |
177 | + return integer_obj_field(); | |
178 | + } | |
179 | + } | |
180 | + } | |
181 | + // No error | |
182 | + return 0; | |
183 | +} | |
184 | + | |
185 | +char* get_value_sub(int pr){ | |
186 | + char* err; | |
187 | + enum operator op; | |
188 | + char b1,b2,b3; | |
189 | + int prevpos; | |
190 | + // Get a value in $v0. | |
191 | + err=get_simple_value(); | |
192 | + if (err) return err; | |
193 | + while(1){ | |
194 | + // Get the operator in op. If not valid operator, simply return without error. | |
195 | + prevpos=g_srcpos; | |
196 | + err=get_operator(); | |
197 | + if (err) return 0; | |
198 | + op=g_last_op; | |
199 | + // Compair current and previous operators. | |
200 | + // If the previous operator has higher priolity, return. | |
201 | + if (pr>=priority(op)) { | |
202 | + g_srcpos=prevpos; | |
203 | + return 0; | |
204 | + } | |
205 | + // Store $v0 in stack | |
206 | + g_sdepth+=4; | |
207 | + if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth; | |
208 | + check_obj_space(1); | |
209 | + g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp) | |
210 | + // Get next value. | |
211 | + err=get_value_sub(priority(op)); | |
212 | + if (err) return err; | |
213 | + // Get value from stack to $v1. | |
214 | + check_obj_space(1); | |
215 | + g_object[g_objpos++]=0x8FA30000|g_sdepth; // lw v1,xx(sp) | |
216 | + g_sdepth-=4; | |
217 | + // Calculation. Result will be in $v0. | |
218 | + err=calculation(op); | |
219 | + if (err) return err; | |
220 | + } | |
221 | +} | |
222 | + | |
223 | +char* get_value(){ | |
224 | + // This is only the public function. | |
225 | + // Note that this can be called recursively. | |
226 | + // Value may contain function with a parameter of another value. | |
227 | + char* err; | |
228 | + int prevpos; | |
229 | + if (g_sdepth==0) { | |
230 | + // Initialize stack handler | |
231 | + g_maxsdepth=0; | |
232 | + prevpos=g_objpos; | |
233 | + // Stack decrement command will be filled later | |
234 | + check_obj_space(1); | |
235 | + g_object[g_objpos++]=0x00000000; // nop (will be replaced by "addiu sp,sp,-xx") | |
236 | + } | |
237 | + err=get_value_sub(priority(OP_VOID)); | |
238 | + if (err) return err; | |
239 | + if (g_sdepth==0) { | |
240 | + if (g_maxsdepth==0) { | |
241 | + // Stack was not used. | |
242 | + if (g_allow_shift_obj) { | |
243 | + shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1); | |
244 | + g_objpos--; | |
245 | + } | |
246 | + } else { | |
247 | + // Stack was used. | |
248 | + check_obj_space(1); | |
249 | + g_object[prevpos]=0x27BD0000 | (0-g_maxsdepth) & 0x0000FFFF; // addiu sp,sp,-xx | |
250 | + g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx | |
251 | + } | |
252 | + } | |
253 | + g_lastvar=VAR_INTEGER; | |
254 | + return 0; | |
255 | +} | |
256 | + | |
257 | +char* get_floatOrValue(){ | |
258 | + char* err; | |
259 | + char b; | |
260 | + int opos,spos,sdpt; | |
261 | + sdpt=g_sdepth; | |
262 | + opos=g_objpos; | |
263 | + spos=g_srcpos; | |
264 | + // First try integer. | |
265 | + // Integer value has the higher priolity than float value. | |
266 | + err=get_value(); | |
267 | + b=g_source[g_srcpos]; | |
268 | + if (err || b=='#') { | |
269 | + // Value is not integer. Let's try float. | |
270 | + g_sdepth=sdpt; | |
271 | + g_objpos=opos; | |
272 | + g_srcpos=spos; | |
273 | + return get_float(); | |
274 | + } else { | |
275 | + // Value was recognized as an integer. | |
276 | + return 0; | |
277 | + } | |
278 | +} | |
279 | + | |
280 | +char* get_stringFloatOrValue(){ | |
281 | + char* err; | |
282 | + int opos,spos; | |
283 | + opos=g_objpos; | |
284 | + spos=g_srcpos; | |
285 | + // First try string, float, then integer. | |
286 | + err=get_string(); | |
287 | + if (err) { | |
288 | + g_objpos=opos; | |
289 | + g_srcpos=spos; | |
290 | + return get_floatOrValue(); | |
291 | + } else { | |
292 | + return 0; | |
293 | + } | |
294 | +} | |
295 | + |
@@ -0,0 +1,271 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by Katsumi. | |
4 | + http://hp.vector.co.jp/authors/VA016157/ | |
5 | + kmorimatsu@users.sourceforge.jp | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "compiler.h" | |
13 | + | |
14 | +/* | |
15 | + static const int reserved_var_names[]; | |
16 | + This dimension contains var name integers of reserved var names. | |
17 | + To make following structure, execute "reservednames.js" in Windows. | |
18 | +*/ | |
19 | + | |
20 | +static const int reserved_var_names[]={ | |
21 | + 0x000106b8, /*ABS*/ | |
22 | + 0x0001f67c, /*ACOS*/ | |
23 | + 0x0002414c, /*ARGS*/ | |
24 | + 0x0001090c, /*ASC*/ | |
25 | + 0x0002469f, /*ASIN*/ | |
26 | + 0x00024a8f, /*ATAN*/ | |
27 | + 0x002f7c1e, /*ATAN2*/ | |
28 | + 0x0047c31c, /*BREAK*/ | |
29 | + 0x00035869, /*CALL*/ | |
30 | + 0x00575afe, /*CDATA*/ | |
31 | + 0x00036c3d, /*CEIL*/ | |
32 | + 0x000111af, /*CHR*/ | |
33 | + 0x0cb1b682, /*CIRCLE*/ | |
34 | + 0x005d1ea3, /*CLEAR*/ | |
35 | + 0x00011240, /*CLS*/ | |
36 | + 0x005f66cb, /*COLOR*/ | |
37 | + 0x000112ac, /*COS*/ | |
38 | + 0x0003a041, /*COSH*/ | |
39 | + 0x00616415, /*CREAD*/ | |
40 | + 0x0de593fb, /*CURSOR*/ | |
41 | + 0x00040fbe, /*DATA*/ | |
42 | + 0x00011644, /*DEC*/ | |
43 | + 0x0fe19c42, /*DELETE*/ | |
44 | + 0x000116de, /*DIM*/ | |
45 | + 0x000100a8, /*DO*/ | |
46 | + 0x0004fd8e, /*ELSE*/ | |
47 | + 0x1434a177, /*ELSEIF*/ | |
48 | + 0x00011c99, /*END*/ | |
49 | + 0x0091c927, /*ENDIF*/ | |
50 | + 0x00053854, /*EXEC*/ | |
51 | + 0x00011e0d, /*EXP*/ | |
52 | + 0x000579c8, /*FABS*/ | |
53 | + 0x16e3d4be, /*FCLOSE*/ | |
54 | + 0x00058fcf, /*FEOF*/ | |
55 | + 0x00059895, /*FGET*/ | |
56 | + 0x00a67500, /*FGETC*/ | |
57 | + 0x00a7e061, /*FIELD*/ | |
58 | + 0x0005a3a2, /*FILE*/ | |
59 | + 0x177f0ca5, /*FINPUT*/ | |
60 | + 0x0005b1df, /*FLEN*/ | |
61 | + 0x00aa3445, /*FLOAT*/ | |
62 | + 0x00aa363b, /*FLOOR*/ | |
63 | + 0x0005b84d, /*FMOD*/ | |
64 | + 0x00ac5c9f, /*FOPEN*/ | |
65 | + 0x000121db, /*FOR*/ | |
66 | + 0x18352839, /*FPRINT*/ | |
67 | + 0x0005c865, /*FPUT*/ | |
68 | + 0x00ad2e40, /*FPUTC*/ | |
69 | + 0x00aefdec, /*FSEEK*/ | |
70 | + 0x00063b90, /*GCLS*/ | |
71 | + 0x1a808bcb, /*GCOLOR*/ | |
72 | + 0x1ab733b3, /*GETDIR*/ | |
73 | + 0x00c60f03, /*GOSUB*/ | |
74 | + 0x0006796c, /*GOTO*/ | |
75 | + 0x1bcfcc39, /*GPRINT*/ | |
76 | + 0x00012a99, /*HEX*/ | |
77 | + 0x0007ad12, /*IDLE*/ | |
78 | + 0x00010153, /*IF*/ | |
79 | + 0x00f8701a, /*INKEY*/ | |
80 | + 0x00f88ba5, /*INPUT*/ | |
81 | + 0x000130e9, /*INT*/ | |
82 | + 0x00092084, /*KEYS*/ | |
83 | + 0x013be43d, /*LABEL*/ | |
84 | + 0x00013ecf, /*LEN*/ | |
85 | + 0x00013ed5, /*LET*/ | |
86 | + 0x0009e96a, /*LINE*/ | |
87 | + 0x00014030, /*LOG*/ | |
88 | + 0x0145f324, /*LOG10*/ | |
89 | + 0x000a07f9, /*LOOP*/ | |
90 | + 0x000abca3, /*MODF*/ | |
91 | + 0x016418d4, /*MUSIC*/ | |
92 | + 0x000b4321, /*NEXT*/ | |
93 | + 0x000148f8, /*NEW*/ | |
94 | + 0x00014a5d, /*NOT*/ | |
95 | + 0x38a658d7, /*OPTION*/ | |
96 | + 0x000152c0, /*PCG*/ | |
97 | + 0x000cacec, /*PEEK*/ | |
98 | + 0x3b1c6aea, /*PEEK16*/ | |
99 | + 0x3b1c6b2e, /*PEEK32*/ | |
100 | + 0x00010252, /*PI*/ | |
101 | + 0x01ac8479, /*POINT*/ | |
102 | + 0x000ce05e, /*POKE*/ | |
103 | + 0x3c20dc0a, /*POKE16*/ | |
104 | + 0x3c20dc4e, /*POKE32*/ | |
105 | + 0x00015480, /*POW*/ | |
106 | + 0x01aea739, /*PRINT*/ | |
107 | + 0x000cf3d5, /*PSET*/ | |
108 | + 0x3cb45fa4, /*PUBLIC*/ | |
109 | + 0x3cc0fe21, /*PUTBMP*/ | |
110 | + 0x000e18d5, /*READ*/ | |
111 | + 0x00015d2e, /*REM*/ | |
112 | + 0x425c9703, /*RETURN*/ | |
113 | + 0x00015e69, /*RND*/ | |
114 | + 0x45c26d49, /*SCROLL*/ | |
115 | + 0x45f6e3b3, /*SETDIR*/ | |
116 | + 0x00016287, /*SGN*/ | |
117 | + 0x000162cf, /*SIN*/ | |
118 | + 0x000ee52d, /*SINH*/ | |
119 | + 0x01f9a429, /*SOUND*/ | |
120 | + 0x000f0e49, /*SQRT*/ | |
121 | + 0x47f711de, /*SYSTEM*/ | |
122 | + 0x000166bf, /*TAN*/ | |
123 | + 0x000f72ed, /*TANH*/ | |
124 | + 0x020ed5f3, /*TIMER*/ | |
125 | + 0x02182fee, /*TVRAM*/ | |
126 | + 0x022c2a2d, /*UNTIL*/ | |
127 | + 0x4e8887d0, /*USEPCG*/ | |
128 | + 0x4e88a5f3, /*USEVAR*/ | |
129 | + 0x000170dd, /*VAL*/ | |
130 | + 0x000170e3, /*VAR*/ | |
131 | + 0x00119505, /*WAIT*/ | |
132 | + 0x0011a9e9, /*WEND*/ | |
133 | + 0x025aef62, /*WHILE*/ | |
134 | + 0x025b8d75, /*WIDTH*/ | |
135 | + // Additional names follow | |
136 | + ADDITIONAL_RESERVED_VAR_NAMES | |
137 | +}; | |
138 | + | |
139 | +/* | |
140 | + check_var_name(); | |
141 | + This function reads the current position of source code and check if | |
142 | + it contains valid var name, the function returns 0 or plus value. | |
143 | + If not, it returns -1; | |
144 | +*/ | |
145 | + | |
146 | +int check_var_name(){ | |
147 | + char b1; | |
148 | + int j; | |
149 | + int i=0; | |
150 | + int prevpos=g_srcpos; | |
151 | + next_position(); | |
152 | + b1=g_source[g_srcpos]; | |
153 | + if (b1<'A' || 'Z'<b1) return -1; | |
154 | + do { | |
155 | + // First character must be A-Z | |
156 | + // From second, A-Z and 0-9 can be used. | |
157 | + i*=36; | |
158 | + if ('0'<=b1 && b1<='9') { | |
159 | + i+=b1-'0'; | |
160 | + } else if (g_srcpos==prevpos) { | |
161 | + // First character must be A-Z. | |
162 | + // Subtract 9, resulting 1-26 but not 10-35. | |
163 | + // This subtraction is required to maintain | |
164 | + // final number being <0x80000000. | |
165 | + i+=b1-'A'+1; | |
166 | + } else { | |
167 | + i+=b1-'A'+10; | |
168 | + } | |
169 | + g_srcpos++; | |
170 | + b1=g_source[g_srcpos]; | |
171 | + } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z'); | |
172 | + // Length of the label must be between 2 and 6. | |
173 | + if (g_srcpos-prevpos<2) { | |
174 | + // One letter var name, A-Z | |
175 | + return i-1; | |
176 | + } | |
177 | + if (6<g_srcpos-prevpos) { | |
178 | + // Too long. This is not var name. | |
179 | + g_srcpos=prevpos; | |
180 | + return -1; | |
181 | + } | |
182 | + i+=65536; | |
183 | + // Check if this is reserved var name. | |
184 | + for(j=0;j<sizeof reserved_var_names/sizeof reserved_var_names[0];j++){ | |
185 | + if (reserved_var_names[j]==i) { | |
186 | + // This var name is reserved as used for function or statement. | |
187 | + g_srcpos=prevpos; | |
188 | + return -1; | |
189 | + } | |
190 | + } | |
191 | + // Reserved var names table was checked. This must be a long var name. | |
192 | + return i; | |
193 | +} | |
194 | + | |
195 | +/* | |
196 | + int get_var_number(); | |
197 | + This function returns variable number that can be used as the index of $s8 | |
198 | +*/ | |
199 | + | |
200 | +int get_var_number(){ | |
201 | + int i,j,spos; | |
202 | + int* record; | |
203 | + // This must be a short or long var name. | |
204 | + spos=g_srcpos; | |
205 | + i=check_var_name(); | |
206 | + if (i<0) return -1; | |
207 | + // If it is a short name, immediately return. | |
208 | + if (i<26) return i; | |
209 | + // Check if CLASS::STATIC | |
210 | + if (g_source[g_srcpos]==':' && g_source[g_srcpos+1]==':') { | |
211 | + // This is CLASS::STATIC | |
212 | + g_srcpos++; | |
213 | + g_srcpos++; | |
214 | + j=check_var_name(); | |
215 | + if (j<26) return -1; | |
216 | + cmpdata_reset(); | |
217 | + while(record=cmpdata_find(CMPDATA_STATIC)){ | |
218 | + if (record[1]!=i) continue; | |
219 | + if (record[2]!=j) continue; | |
220 | + // Found CLASS::STATIC | |
221 | + i=record[0]&0x0000FFFF; | |
222 | + j=0; | |
223 | + break; | |
224 | + } | |
225 | + if (j) { | |
226 | + // Not found. Maybe a static method | |
227 | + g_srcpos=spos; | |
228 | + return -1; | |
229 | + } | |
230 | + } else { | |
231 | + // Search long var names registered by USEVAR statement. | |
232 | + // If found, returns the value that can be used as the index of $s8 | |
233 | + i=search_var_name(i); | |
234 | + if (i<0) return -1; | |
235 | + } | |
236 | + // This var name is defined by USEVAR statement. | |
237 | + return i+ALLOC_LNV_BLOCK; | |
238 | + | |
239 | +} | |
240 | + | |
241 | +/* | |
242 | + int search_var_name(int nameint); | |
243 | + This function searchs registered long var name in compile data table. | |
244 | + If not found, this function returns -1. | |
245 | + If found, it retunrs var number, beginning 0. | |
246 | +*/ | |
247 | + | |
248 | +int search_var_name(int nameint){ | |
249 | + int* cmpdata; | |
250 | + cmpdata_reset(); | |
251 | + while(cmpdata=cmpdata_find(CMPDATA_USEVAR)){ | |
252 | + if (cmpdata[1]==nameint) return cmpdata[0]&0x0000ffff; | |
253 | + } | |
254 | + return -1; | |
255 | +} | |
256 | + | |
257 | +/* | |
258 | + char* register_var_name(int nameint); | |
259 | + This function is called when compiler detects "USEVAR" statement. | |
260 | + It registers the long file name in compile data table. | |
261 | +*/ | |
262 | + | |
263 | +char* register_var_name(int nameint){ | |
264 | + // Check if registered before. If did, cause error. | |
265 | + if (search_var_name(nameint)!=-1) return ERR_INVALID_VAR_NAME; | |
266 | + // Number of long var name is restricted | |
267 | + if (ALLOC_LNV_NUM<=g_long_name_var_num) return ERR_INVALID_VAR_NAME; | |
268 | + // Register var name as a compile data | |
269 | + g_temp=nameint; | |
270 | + return cmpdata_insert(CMPDATA_USEVAR,g_long_name_var_num++,&g_temp,1); | |
271 | +} |