• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

BASIC compiler/interpreter for PIC32MX/MZ-80K


Commit MetaInfo

Revisão9ba0d2576f981036b8aad97a62b7a0fe4ea9ca88 (tree)
Hora2018-11-02 04:58:32
AutorKatsumi Morimatsu <kmorimatsu@ucda...>
CommiterKatsumi Morimatsu

Mensagem de Log

Add Zoea

Mudança Sumário

Diff

--- /dev/null
+++ b/mips/zoea/App_32MX170F256B.ld
@@ -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 = 0x800) ;
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+
--- /dev/null
+++ b/mips/zoea/MACHIKAN.INI
@@ -0,0 +1,17 @@
1+# MachiKania system
2+# initialization file
3+
4+# Specify the keyboard type
5+# Enable the keyword below
6+
7+106KEY # Japanese Keyboard
8+# 101KEY # US Keyboard
9+
10+
11+# Setup Lock keys' status
12+# Comment out if not lock
13+# the key when initializing
14+
15+NUMLOCK # Num Lock Key
16+CAPSLOCK # Caps Lock Key
17+# SCRLLOCK # Scroll Lock Key
--- /dev/null
+++ b/mips/zoea/SDFSIO.h
@@ -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
--- /dev/null
+++ b/mips/zoea/api.h
@@ -0,0 +1,38 @@
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 "videoout.h"
36+#include "SDFSIO.h"
37+#include "ps2keyboard.h"
38+#include "debug.h"
--- /dev/null
+++ b/mips/zoea/basic.mcp
@@ -0,0 +1,198 @@
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.40\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+[GENERATED_FILES]
66+file_000=no
67+file_001=no
68+file_002=no
69+file_003=no
70+file_004=no
71+file_005=no
72+file_006=no
73+file_007=no
74+file_008=no
75+file_009=no
76+file_010=no
77+file_011=no
78+file_012=no
79+file_013=no
80+file_014=no
81+file_015=no
82+file_016=no
83+file_017=no
84+file_018=no
85+file_019=no
86+file_020=no
87+file_021=no
88+file_022=no
89+file_023=no
90+file_024=no
91+file_025=no
92+file_026=no
93+file_027=no
94+file_028=no
95+file_029=no
96+file_030=no
97+file_031=no
98+file_032=no
99+file_033=no
100+file_034=no
101+file_035=no
102+file_036=no
103+file_037=no
104+[OTHER_FILES]
105+file_000=no
106+file_001=no
107+file_002=no
108+file_003=no
109+file_004=no
110+file_005=no
111+file_006=no
112+file_007=no
113+file_008=no
114+file_009=no
115+file_010=no
116+file_011=no
117+file_012=no
118+file_013=no
119+file_014=no
120+file_015=no
121+file_016=no
122+file_017=no
123+file_018=no
124+file_019=no
125+file_020=no
126+file_021=no
127+file_022=no
128+file_023=no
129+file_024=no
130+file_025=no
131+file_026=no
132+file_027=no
133+file_028=no
134+file_029=no
135+file_030=no
136+file_031=no
137+file_032=no
138+file_033=no
139+file_034=no
140+file_035=yes
141+file_036=yes
142+file_037=yes
143+[FILE_INFO]
144+file_000=compiler.c
145+file_001=editor.c
146+file_002=error.c
147+file_003=exception.c
148+file_004=file.c
149+file_005=float.c
150+file_006=function.c
151+file_007=globalvars.c
152+file_008=keyinput.c
153+file_009=library.c
154+file_010=linker.c
155+file_011=main.c
156+file_012=memory.c
157+file_013=music.c
158+file_014=operator.c
159+file_015=run.c
160+file_016=statement.c
161+file_017=string.c
162+file_018=value.c
163+file_019=debug.c
164+file_020=cmpdata.c
165+file_021=varname.c
166+file_022=api.h
167+file_023=compiler.h
168+file_024=editor.h
169+file_025=keyinput.h
170+file_026=main.h
171+file_027=ps2keyboard.h
172+file_028=SDFSIO.h
173+file_029=videoout.h
174+file_030=debug.h
175+file_031=lib_videoout_machikania.X.a
176+file_032=libsdfsio.a
177+file_033=ps2keyboard.X.a
178+file_034=App_32MX170F256B.ld
179+file_035=help.txt
180+file_036=MACHIKAN.INI
181+file_037=reservednames.js
182+[SUITE_INFO]
183+suite_guid={62D235D8-2DB2-49CD-AF24-5489A6015337}
184+suite_state=
185+[TOOL_SETTINGS]
186+TS{6F324298-6323-4781-8C43-43FA5E6F3646}=-gdwarf-2
187+TS{1F324EFA-C0BA-4A8F-A85A-B21644939CAD}=-g -O1
188+TS{29D3B6CC-DCAB-4659-8011-FFF75BB7F8D7}=-o"$(BINDIR_)$(TARGETBASE).$(TARGETSUFFIX)" -Map="$(BINDIR_)$(TARGETBASE).map"
189+TS{AD4C3FBD-B6BB-4F50-AB4E-35BF132D4D60}=
190+[INSTRUMENTED_TRACE]
191+enable=0
192+transport=0
193+format=0
194+[CUSTOM_BUILD]
195+Pre-Build=
196+Pre-BuildEnabled=1
197+Post-Build=
198+Post-BuildEnabled=1
--- /dev/null
+++ b/mips/zoea/cmpdata.c
@@ -0,0 +1,86 @@
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 "compiler.h"
9+
10+/*
11+ This file provide functions for handling data used when compiling.
12+ The data is inserted between g_objmax and file cache.
13+ Data format (32 bit):
14+ MSB LSB
15+ +----+----+--------+
16+ |type|len | data16 |
17+ +----+----+--------+
18+ where,
19+ type: data type number (unsigned char)
20+ len: length of data area in number of words (unsigned char)
21+ data16: general 16 bit data (short)
22+*/
23+
24+#define g_cmpdata g_objmax
25+
26+static int* g_cmpdata_end;
27+static int* g_cmpdata_point;
28+
29+/*
30+ Initialize routine must be called when starting compiler.
31+*/
32+void cmpdata_init(){
33+ g_cmpdata_end=g_objmax;
34+ g_cmpdata_point=g_objmax;
35+}
36+
37+/*
38+ Function to insert a data. The data must be defined by a pointer to int array.
39+ unsigned char type: Data type number (0-255)
40+ short data16: 16 bit data. If not required, set 0.
41+ int* data: Pointer to data array. If not requird, set 0.
42+ unsigned char num: Length of above data array. If not required, set 0.
43+*/
44+char* cmpdata_insert(unsigned char type, short data16, int* data, unsigned char num){
45+ unsigned char i;
46+ g_cmpdata-=num+1;
47+ if (g_cmpdata<g_object+g_objpos) return ERR_NE_BINARY;
48+ g_cmpdata[0]=(type<<24)|(num+1)<<16|data16;
49+ for(i=0;i<num;i++){
50+ g_cmpdata[i+1]=data[i];
51+ }
52+ return 0;
53+}
54+
55+/*
56+ Reset data point. Next search will be from the beginning.
57+*/
58+
59+void cmpdata_reset(){
60+ g_cmpdata_point=g_cmpdata;
61+}
62+
63+/*
64+ Find the next record with defined type. Return the pointer to the record.
65+*/
66+int* cmpdata_find(unsigned char type){
67+ int* ret;
68+ while(g_cmpdata_point<g_cmpdata_end){
69+ // Remember return value
70+ ret=g_cmpdata_point;
71+ // Move the point to next
72+ g_cmpdata_point+=(ret[0]&0x00ff0000)>>16;
73+ // Check if type is the same. If the same, return.
74+ if ((ret[0]>>24)==type) return ret;
75+ }
76+ return 0;
77+}
78+
79+/*
80+ Find the record from beginning.
81+*/
82+
83+int* cmpdata_findfirst(unsigned char type){
84+ cmpdata_reset();
85+ return cmpdata_find(type);
86+}
--- /dev/null
+++ b/mips/zoea/compiler.c
@@ -0,0 +1,151 @@
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 "compiler.h"
9+
10+void start_program(void* addr, void* memory){
11+ static unsigned int stored_sp;
12+ // Store s0-s7, fp, and ra in stacks
13+ asm volatile("#":::"s0");
14+ asm volatile("#":::"s1");
15+ asm volatile("#":::"s2");
16+ asm volatile("#":::"s3");
17+ asm volatile("#":::"s4");
18+ asm volatile("#":::"s5");
19+ asm volatile("#":::"s6");
20+ asm volatile("#":::"s7");
21+ asm volatile("#":::"fp");
22+ asm volatile("#":::"ra");
23+ // Store sp in stored_sp
24+ asm volatile("la $v0,%0"::"i"(&stored_sp));
25+ asm volatile("sw $sp,0($v0)");
26+ // Shift sp for safety
27+ asm volatile("addiu $sp,$sp,-8");
28+ // Register vector for unexpected NEXT/RETURN
29+ asm volatile("la $v0,%0"::"i"(&err_unexp_next));
30+ asm volatile("sw $v0,4($sp)");
31+ // Store end address in g_end_addr
32+ asm volatile("la $v0,%0"::"i"(&g_end_addr));
33+ asm volatile("la $v1,label");
34+ asm volatile("sw $v1,0($v0)");
35+ // Set s7 for easy calling call_library()
36+ asm volatile("la $s7,%0"::"i"(&call_library));
37+ // Set fp and execute program
38+ asm volatile("addu $fp,$zero,$a1");
39+ asm volatile("jr $a0");
40+ // Restore sp from stored_sp
41+ asm volatile("label:");
42+ asm volatile("la $v0,%0"::"i"(&stored_sp));
43+ asm volatile("lw $sp,0($v0)");
44+ // Restore registers from stack and return
45+ return;
46+}
47+
48+int get_gp(void){
49+ asm volatile("addu $v0,$gp,$zero");
50+}
51+
52+int get_fp(void){
53+ asm volatile("addu $v0,$fp,$zero");
54+}
55+
56+
57+void shift_obj(int* src, int* dst, int len){
58+ int i;
59+ if (dst<src) {
60+ for(i=0;i<len;i++){
61+ dst[i]=src[i];
62+ }
63+ } else if (src<dst) {
64+ for(i=len-1;0<=i;i--){
65+ dst[i]=src[i];
66+ }
67+ }
68+}
69+
70+int strncmp(char* str1, char* str2, int len){
71+ int i;
72+ for (i=0;i<len;i++) {
73+ if (str1[i]>str2[i]) return 1;
74+ if (str1[i]<str2[i]) return -1;
75+ }
76+ return 0;
77+}
78+
79+int nextCodeIs(char* str){
80+ int len;
81+ next_position();
82+ for(len=0;str[len];len++);
83+ if (!strncmp(g_source+g_srcpos,str,len)) {
84+ if ('A'<=str[len-1] && str[len-1]<='Z') {
85+ // When the last character of str is alphabet,
86+ // the next character in source must be space, enter, or ':'.
87+ if (0x20<g_source[g_srcpos+len] && g_source[g_srcpos+len]!=':') return 0;
88+ }
89+ // String matches in the current position in source.
90+ g_srcpos+=len;
91+ return len;
92+ } else {
93+ // String didn't match.
94+ return 0;
95+ }
96+}
97+
98+int endOfStatement(){
99+ unsigned char b;
100+ next_position();
101+ b=g_source[g_srcpos];
102+ return (b<0x20 || b==':') ? 1:0;
103+}
104+
105+char* compile_line(void){
106+ char b1;
107+ char* err;
108+ g_line++;
109+ g_fileline++;
110+ // Check if line number exists
111+ next_position();
112+ b1=g_source[g_srcpos];
113+ if (b1<0x20) {
114+ // The end of line.
115+ // Don't add $s6-setting command.
116+ if (g_source[g_srcpos]==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
117+ g_srcpos++;
118+ return 0;
119+ } else if ('0'<=b1 && b1<='9') {
120+ // Line number exists
121+ err=get_label();
122+ if (err) return err;
123+ g_line=g_label;
124+ }
125+ // Store line number in $s6
126+ if (!(g_line&0xFFFF0000)) {
127+ // Line number must be less than 65536.
128+ // If not, it is invalid number.
129+ // Check existing line with the same number here.
130+ if (search_label(g_line)) {
131+ // Error: duplicate lines
132+ printstr("Line ");
133+ printstr(resolve_label(g_line));
134+ return ERR_MULTIPLE_LABEL;
135+ }
136+ check_obj_space(1);
137+ g_object[g_objpos++]=0x34160000|g_line; //ori s6,zero,xxxx;
138+ }
139+ while(g_source[g_srcpos]!=0x0D && g_source[g_srcpos]!=0x0A){
140+ err=statement();
141+ if (err) return err;
142+ next_position();
143+ if (g_source[g_srcpos]==':') {
144+ g_srcpos++;
145+ next_position();
146+ }
147+ }
148+ if (g_source[g_srcpos]==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
149+ g_srcpos++;
150+ return 0;
151+}
\ No newline at end of file
--- /dev/null
+++ b/mips/zoea/compiler.h
@@ -0,0 +1,371 @@
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+/* Definitions */
9+// Number of variables (including temporary ones)
10+#define ALLOC_VAR_NUM 36
11+// Block # dedicated for PCG
12+#define ALLOC_PCG_BLOCK 36
13+// Block # dedicated for GRAPHIC
14+#define ALLOC_GRAPHIC_BLOCK 37
15+// Start # for long name variables
16+#define ALLOC_LNV_BLOCK 38
17+// Number of long name variables
18+#define ALLOC_LNV_NUM 190
19+// Start # of permanent blocks
20+#define ALLOC_PERM_BLOCK 228
21+// Number of blocks that can be assigned for memory allocation (including all above)
22+#define ALLOC_BLOCK_NUM 238
23+
24+// Persistent RAM bytes used for object, heap and exception data
25+#define PERSISTENT_RAM_SIZE (1024*53)
26+// Exception data area bytes
27+#define EXCEPTION_DATA_SIZE (64)
28+// RAM size used for object and heap
29+#define RAMSIZE (PERSISTENT_RAM_SIZE-EXCEPTION_DATA_SIZE)
30+
31+/* Enums */
32+enum variable{
33+ VAR_INTEGER,
34+ VAR_FLOAT,
35+ VAR_STRING
36+};
37+
38+#define OP_MASK 0x001F
39+enum operator{
40+ OP_VOID=0,
41+ OP_OR =1,
42+ OP_AND =2,
43+ OP_XOR =3,
44+ OP_EQ =4,
45+ OP_NEQ =5,
46+ OP_LT =6,
47+ OP_LTE =7,
48+ OP_MT =8,
49+ OP_MTE =9,
50+ OP_SHL =10,
51+ OP_SHR =11,
52+ OP_ADD =12,
53+ OP_SUB =13,
54+ OP_MUL =14,
55+ OP_DIV =15,
56+ OP_REM =16
57+};
58+
59+#define LIB_MASK 0xFE00
60+#define LIB_STEP 0x0200
61+enum libs{
62+ LIB_SOUND =LIB_STEP*0,
63+ LIB_MUSICFUNC =LIB_STEP*1,
64+ LIB_MUSIC =LIB_STEP*2,
65+ LIB_SETDRAWCOUNT =LIB_STEP*3,
66+ LIB_DRAWCOUNT =LIB_STEP*4,
67+ LIB_PALETTE =LIB_STEP*5,
68+ LIB_GPALETTE =LIB_STEP*6,
69+ LIB_BGCOLOR =LIB_STEP*7,
70+ LIB_CURSOR =LIB_STEP*8,
71+ LIB_CLS =LIB_STEP*9,
72+ LIB_GCLS =LIB_STEP*10,
73+ LIB_COLOR =LIB_STEP*11,
74+ LIB_GCOLOR =LIB_STEP*12,
75+ LIB_KEYS =LIB_STEP*13,
76+ LIB_RESTORE =LIB_STEP*14,
77+ LIB_RESTORE2 =LIB_STEP*15,
78+ LIB_READ =LIB_STEP*16,
79+ LIB_MIDSTR =LIB_STEP*17,
80+ LIB_CLEAR =LIB_STEP*18,
81+ LIB_DIV0 =LIB_STEP*19,
82+ LIB_LETSTR =LIB_STEP*20,
83+ LIB_STRNCMP =LIB_STEP*21,
84+ LIB_RND =LIB_STEP*22,
85+ LIB_DEC =LIB_STEP*23,
86+ LIB_HEX =LIB_STEP*24,
87+ LIB_CHR =LIB_STEP*25,
88+ LIB_CONNECT_STRING =LIB_STEP*26,
89+ LIB_STRING =LIB_STEP*27,
90+ LIB_PRINTSTR =LIB_STEP*28,
91+ LIB_LABEL =LIB_STEP*29,
92+ LIB_DIM =LIB_STEP*30,
93+ LIB_VAL =LIB_STEP*31,
94+ LIB_INPUT =LIB_STEP*32,
95+ LIB_INKEY =LIB_STEP*33,
96+ LIB_USEPCG =LIB_STEP*34,
97+ LIB_PCG =LIB_STEP*35,
98+ LIB_SCROLL =LIB_STEP*36,
99+ LIB_WAIT =LIB_STEP*37,
100+ LIB_VAR_PUSH =LIB_STEP*38,
101+ LIB_VAR_POP =LIB_STEP*39,
102+ LIB_SYSTEM =LIB_STEP*40,
103+ LIB_SPRINTF =LIB_STEP*41,
104+ LIB_FLOAT =LIB_STEP*42,
105+ LIB_FLOATFUNCS =LIB_STEP*43,
106+ LIB_CREAD =LIB_STEP*44,
107+ LIB_USEGRAPHIC =LIB_STEP*45,
108+ LIB_GRAPHIC =LIB_STEP*46,
109+ LIB_WIDTH =LIB_STEP*47,
110+ LIB_FILE =LIB_STEP*48,
111+ LIB_DEBUG =LIB_STEP*127,
112+};
113+
114+// Note: OP_XXXX and FUNC_XXXX cannot be used simultaneously
115+#define FUNC_MASK 0x003F
116+#define FUNC_STEP 0x0001
117+enum functions{
118+ FUNC_FLOAT =FUNC_STEP*0,
119+ FUNC_INT =FUNC_STEP*1,
120+ FUNC_VALSHARP =FUNC_STEP*2,
121+ FUNC_SIN =FUNC_STEP*3,
122+ FUNC_COS =FUNC_STEP*4,
123+ FUNC_TAN =FUNC_STEP*5,
124+ FUNC_ASIN =FUNC_STEP*6,
125+ FUNC_ACOS =FUNC_STEP*7,
126+ FUNC_ATAN =FUNC_STEP*8,
127+ FUNC_ATAN2 =FUNC_STEP*9,
128+ FUNC_SINH =FUNC_STEP*10,
129+ FUNC_COSH =FUNC_STEP*11,
130+ FUNC_TANH =FUNC_STEP*12,
131+ FUNC_EXP =FUNC_STEP*13,
132+ FUNC_LOG =FUNC_STEP*14,
133+ FUNC_LOG10 =FUNC_STEP*15,
134+ FUNC_POW =FUNC_STEP*16,
135+ FUNC_SQRT =FUNC_STEP*17,
136+ FUNC_CEIL =FUNC_STEP*18,
137+ FUNC_FLOOR =FUNC_STEP*19,
138+ FUNC_FABS =FUNC_STEP*20,
139+ FUNC_MODF =FUNC_STEP*21,
140+ FUNC_FMOD =FUNC_STEP*22,
141+ FUNC_PSET =FUNC_STEP*23,
142+ FUNC_LINE =FUNC_STEP*24,
143+ FUNC_BOXFILL =FUNC_STEP*25,
144+ FUNC_CIRCLE =FUNC_STEP*26,
145+ FUNC_CIRCLEFILL =FUNC_STEP*27,
146+ FUNC_GPRINT =FUNC_STEP*28,
147+ FUNC_PUTBMP =FUNC_STEP*29,
148+ FUNC_PUTBMP2 =FUNC_STEP*30,
149+ FUNC_GCOLOR =FUNC_STEP*31,
150+ FUNC_POINT =FUNC_STEP*32,
151+ FUNC_FOPEN =FUNC_STEP*33,
152+ FUNC_FOPENST =FUNC_STEP*34,
153+ FUNC_FILE =FUNC_STEP*35,
154+ FUNC_FCLOSE =FUNC_STEP*36,
155+ FUNC_FINPUT =FUNC_STEP*37,
156+ FUNC_FPRINTSTR =FUNC_STEP*38,
157+ FUNC_FGET =FUNC_STEP*39,
158+ FUNC_FPUT =FUNC_STEP*40,
159+ FUNC_FSEEK =FUNC_STEP*41,
160+ FUNC_FTELL =FUNC_STEP*42,
161+ FUNC_FLEN =FUNC_STEP*43,
162+ FUNC_FSTRING =FUNC_STEP*44,
163+ FUNC_FGETC =FUNC_STEP*45,
164+ FUNC_FPUTC =FUNC_STEP*46,
165+ FUNC_FREMOVE =FUNC_STEP*47,
166+ FUNC_FEOF =FUNC_STEP*48,
167+ FUNC_FINIT =FUNC_STEP*49,
168+ // MAX 63
169+};
170+
171+/* Global vars (see globalvers.c) */
172+extern int g_intconst;
173+extern char g_valueisconst;
174+extern unsigned int g_rnd_seed;
175+extern unsigned int g_label;
176+extern int g_sdepth;
177+extern int g_maxsdepth;
178+extern enum variable g_lastvar;
179+extern char* g_source;
180+extern int g_srcpos;
181+extern int g_line;
182+extern int g_fileline;
183+extern int* g_object;
184+extern int g_objpos;
185+extern int* g_objmax;
186+extern const char* g_err_str[];
187+extern const unsigned char g_priority[];
188+extern enum operator g_last_op;
189+extern int g_end_addr;
190+extern int g_gp;
191+extern int g_s6;
192+extern char RAM[RAMSIZE];
193+extern unsigned int g_ex_data[EXCEPTION_DATA_SIZE/4];
194+extern int g_var_mem[ALLOC_BLOCK_NUM];
195+extern unsigned short g_var_pointer[ALLOC_BLOCK_NUM];
196+extern unsigned short g_var_size[ALLOC_BLOCK_NUM];
197+extern char g_temp_area_used;
198+extern int* g_heap_mem;
199+extern int g_max_mem;
200+extern char g_disable_break;
201+extern unsigned char* g_pcg_font;
202+extern char g_use_graphic;
203+extern unsigned short* g_graphic_area;
204+extern int* g_libparams;
205+extern int g_long_name_var_num;
206+extern int g_temp;
207+
208+/* Prototypes */
209+int get_gp(void);
210+int get_fp(void);
211+void start_program(void* addr, void* memory);
212+void shift_obj(int* src, int* dst, int len);
213+char* compile_line(void);
214+int nextCodeIs(char* str);
215+int endOfStatement();
216+
217+char* init_file(char* buff,char* appname);
218+void close_file();
219+void read_file(int blocklen);
220+char* compile_file();
221+
222+void err_break(void);
223+void err_music(char* str);
224+void err_data_not_found(void);
225+void err_str_complex(void);
226+void err_label_not_found(void);
227+void err_no_mem(void);
228+void err_div_zero(void);
229+void err_unkonwn(void);
230+void err_unexp_next(void);
231+void err_no_block(void);
232+void err_invalid_param(void);
233+char* resolve_label(int s6);
234+
235+void set_sound(unsigned long* data);
236+int musicRemaining(void);
237+void set_music(char* str);
238+void init_music(void);
239+
240+char* statement(void);
241+char* gosub_statement();
242+char* graphic_statement(enum functions func);
243+char* fopen_statement(enum functions func);
244+char* fget_statement();
245+char* fput_statement();
246+char* fputc_statement();
247+char* fremove_statement();
248+
249+char* function(void);
250+char* str_function(void);
251+char* float_function(void);
252+
253+void call_library(void);
254+void reset_dataread();
255+
256+void free_temp_str(char* str);
257+void* alloc_memory(int size, int var_num);
258+void* calloc_memory(int size, int var_num);
259+void move_to_perm_block(int var_num);
260+void move_from_perm_block(int var_num);
261+
262+char* link(void);
263+char* get_label(void);
264+void* search_label(unsigned int label);
265+
266+char* get_string();
267+char* simple_string(void);
268+
269+char* get_operator(void);
270+char* get_floatOperator(void);
271+char* calculation(enum operator op);
272+char* calculation_float(enum operator op);
273+int lib_float(int ia0,int iv0, enum operator a1);
274+
275+int lib_file(enum functions func, int a0, int a1, int v0);
276+
277+char* get_dim_value(int i);
278+char* get_simple_value(void);
279+char* get_value();
280+char* get_floatOrValue();
281+char* get_stringFloatOrValue();
282+
283+void blue_screen(void);
284+
285+char* get_float();
286+
287+void cmpdata_init();
288+char* cmpdata_insert(unsigned char type, short data16, int* data, unsigned char num);
289+void cmpdata_reset();
290+int* cmpdata_find(unsigned char type);
291+int* cmpdata_findfirst(unsigned char type);
292+
293+int check_var_name();
294+int get_var_number();
295+int search_var_name(int nameint);
296+char* register_var_name(int nameint);
297+
298+
299+/* Error messages */
300+#define ERR_SYNTAX (char*)(g_err_str[0])
301+#define ERR_NE_BINARY (char*)(g_err_str[1])
302+#define ERR_NE_MEMORY (char*)(g_err_str[2])
303+#define ERR_DIV_0 (char*)(g_err_str[3])
304+#define ERR_NY_I (char*)(g_err_str[4])
305+#define ERR_LABEL_NF (char*)(g_err_str[5])
306+#define ERR_LABEL_LONG (char*)(g_err_str[6])
307+#define ERR_STR_COMPLEX (char*)(g_err_str[7])
308+#define ERR_DATA_NF (char*)(g_err_str[8])
309+#define ERR_UNKNOWN (char*)(g_err_str[9])
310+#define ERR_MUSIC (char*)(g_err_str[10])
311+#define ERR_MULTIPLE_LABEL (char*)(g_err_str[11])
312+#define ERR_BREAK (char*)(g_err_str[12])
313+#define ERR_UNEXP_NEXT (char*)(g_err_str[13])
314+#define ERR_NO_BLOCK (char*)(g_err_str[14])
315+#define ERR_GOSUB_ASH (char*)(g_err_str[15])
316+#define ERR_INVALID_BREAK (char*)(g_err_str[16])
317+#define ERR_INVALID_ELSEIF (char*)(g_err_str[17])
318+#define ERR_INVALID_PARAM (char*)(g_err_str[18])
319+#define ERR_FILE (char*)(g_err_str[19])
320+#define ERR_INVALID_VAR_NAME (char*)(g_err_str[20])
321+
322+/* comple data type numbers */
323+#define CMPDATA_RESERVED 0
324+#define CMPDATA_USEVAR 1
325+
326+/* Macros */
327+
328+// Skip blanc(s) in source code
329+#define next_position() while(g_source[g_srcpos]==' ') {g_srcpos++;}
330+
331+// Check if object area is not full.
332+#define check_obj_space(x) if (g_objmax<g_object+g_objpos+(x)) return ERR_NE_BINARY
333+
334+// Returns priority of operator
335+#define priority(x) (int)g_priority[(int)(x)]
336+
337+// Insert code for calling library
338+//02E0F809 jalr ra,s7
339+//24070000 addiu a3,zero,0000
340+#define call_lib_code(x) \
341+ check_obj_space(2);\
342+ g_object[g_objpos++]=0x02E0F809;\
343+ g_object[g_objpos++]=0x24070000|((x)&0x0000FFFF)
344+
345+// Division macro for unsigned long
346+// Valid for 31 bits for all cases and 32 bits for some cases
347+#define div32(x,y,z) ((((unsigned long long)((unsigned long)(x)))*((unsigned long long)((unsigned long)(y))))>>(z))
348+
349+// Divide by 9 (valid for 32 bits)
350+#define div9_32(x) div32(x,0xe38e38e4,35)
351+#define rem9_32(x) ((x)-9*div9_32(x))
352+
353+// Divide by 10 (valid for 32 bits)
354+#define div10_32(x) div32(x,0xcccccccd,35)
355+#define rem10_32(x) ((x)-10*div10_32(x))
356+
357+// Divide by 36 (valid for 32 bits)
358+#define div36_32(x) div32(x,0xe38e38e4,37)
359+#define rem36_32(x) (x-36*div36_32(x))
360+
361+// Check break key or buttons when executing BASIC code.
362+// In PS/2 mode, detect ctrl-break.
363+// In button mode, detect pushing four buttons are pushed simultaneously.
364+#define check_break() \
365+ if (g_disable_break==0) {\
366+ if (inPS2MODE()) {\
367+ if (ps2keystatus[0x03]) err_break();\
368+ } else {\
369+ if ((PORTB&0x4c80)==0) err_break();\
370+ }\
371+ }
--- /dev/null
+++ b/mips/zoea/debug.c
@@ -0,0 +1,250 @@
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+
36+static char* readtext;
37+static int filepos;
38+
39+/*
40+ Debug dump
41+ In debugdump.h:
42+ __DEBUGDUMP is defined.
43+ __DEBUGDUMP_FREEAREA is defined as start address of free area (1st argument of set_free_area() function)
44+ const unsigned char dump[] is initialized.
45+*/
46+#ifdef __DEBUGDUMP
47+int debugDump(){
48+ int i;
49+ for(i=0;i<sizeof dump;i++){
50+ RAM[i]=dump[i];
51+ }
52+
53+ g_objpos=(__DEBUGDUMP_FREEAREA-(unsigned int)g_object)/4;
54+
55+ // Initialize parameters
56+ g_pcg_font=0;
57+ g_use_graphic=0;
58+ g_graphic_area=0;
59+ clearscreen();
60+ setcursor(0,0,7);
61+
62+ printstr("BASIC "BASVER"\n");
63+ wait60thsec(15);
64+ // Initialize music
65+ init_music();
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+ set_graphmode(0);
92+ g_use_graphic=0;
93+
94+ return 1;
95+}
96+#else
97+int debugDump(){
98+ return 0;
99+}
100+#endif
101+
102+/*
103+ Override libsdfsio functions.
104+ Here, don't use SD card, but the vertual files
105+ (initext[] and bastext[]) are used.
106+*/
107+
108+FSFILE fsfile;
109+
110+size_t FSfread(void *ptr, size_t size, size_t n, FSFILE *stream){
111+ char b;
112+ size_t ret=0;
113+ if (!readtext) return 0;
114+ while(b=readtext[filepos]){
115+ filepos++;
116+ ((char*)ptr)[ret]=b;
117+ ret++;
118+ if (n<=ret) break;
119+ }
120+ return ret;
121+}
122+FSFILE* FSfopen(const char * fileName, const char *mode){
123+ int i;
124+ for(i=0;i<13;i++){
125+ if (fileName[i]=='.') break;
126+ }
127+ if (i==13) {
128+ // Unknown file name
129+ // Force BAS file
130+ readtext=(char*)&bastext[0];
131+ } else if (fileName[i+1]=='I' && fileName[i+2]=='N' && fileName[i+3]=='I') {
132+ // INI file
133+ readtext=(char*)&initext[0];
134+ } else if (fileName[i+1]=='B' && fileName[i+2]=='A' && fileName[i+3]=='S') {
135+ // BAS file
136+ readtext=(char*)&bastext[0];
137+ // Try debugDump.
138+ if (debugDump()) return 0;
139+ } else {
140+ readtext=0;
141+ return 0;
142+ }
143+ filepos=0;
144+ return &fsfile;
145+}
146+int FSfeof( FSFILE * stream ){
147+ return readtext[filepos]?1:0;
148+}
149+int FSfclose(FSFILE *fo){
150+ return 0;
151+}
152+int FSInit(void){
153+ return 1;
154+}
155+int FSremove (const char * fileName){
156+ return 0;
157+}
158+size_t FSfwrite(const void *ptr, size_t size, size_t n, FSFILE *stream){
159+ return 0;
160+}
161+
162+int FindFirst (const char * fileName, unsigned int attr, SearchRec * rec){
163+ return 0;
164+}
165+int FindNext (SearchRec * rec){
166+ return 0;
167+}
168+int FSmkdir (char * path){
169+ return 0;
170+}
171+char * FSgetcwd (char * path, int numchars){
172+ return 0;
173+}
174+int FSchdir (char * path){
175+ return 0;
176+}
177+long FSftell (FSFILE * fo){
178+ return 0;
179+}
180+int FSfseek(FSFILE *stream, long offset, int whence){
181+ return 0;
182+}
183+/*
184+ ps2init() is not called.
185+ Instead, not_ps2init_but_init_Timer1() is called.
186+ Timer1 is used to update drawcount and drawing gloval variables.
187+*/
188+
189+int not_ps2init_but_init_Timer1(){
190+ PR1=0x0FFF;
191+ TMR1=0;
192+ IFS0bits.T1IF=0;
193+ T1CON=0x8000;
194+ // Timer1 interrupt: priority 4
195+ IPC1bits.T1IP=4;
196+ IPC1bits.T1IS=0;
197+ IEC0bits.T1IE=1;
198+
199+ return 0;
200+}
201+
202+#pragma interrupt timer1Int IPL4SOFT vector 4
203+
204+void timer1Int(){
205+ IFS0bits.T1IF=0;
206+ if (drawing) {
207+ drawing=0;
208+ drawcount++;
209+ } else {
210+ drawing=1;
211+ }
212+}
213+
214+/*
215+ initext[] and bastext[] are vertual files
216+ as "MACHIKAN.INI" and "DEBUG.BAS".
217+*/
218+
219+
220+static const char initext[]=
221+"#PRINT\n"
222+"#PRINT\n";
223+
224+
225+static const char bastext[]=
226+"CLS\n"
227+"DIM S(512)\n"
228+"EXEC 0x8fdd0012, 0x27bd07fc\n"
229+"print s\n"
230+"\n";
231+
232+/*
233+ Test function for constructing assemblies from C codes.
234+*/
235+
236+int _debug_test(int a0, int a1, int a2, int a3, int param4, int param5){
237+// if (a0<0xa0008192) return 0xa0000000;
238+ asm volatile("lw $sp,18($fp)");
239+ asm volatile("addiu $sp,$sp,2044");
240+ return a2+a3;
241+}
242+
243+/*
244+ Break point used for debugging object code.
245+
246+g_object[g_objpos++]=0x0000000d;// break 0x0
247+
248+*/
249+
250+#endif // __DEBUG
--- /dev/null
+++ b/mips/zoea/debug.h
@@ -0,0 +1,25 @@
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+// Pseudo reading config setting for debug mode
11+extern unsigned int g_DEVCFG1;
12+#define DEVCFG1 g_DEVCFG1
13+
14+// Do not use PS/2 keyboard
15+#define ps2init() not_ps2init_but_init_Timer1()
16+int not_ps2init_but_init_Timer1();
17+
18+// Do not use set_graphmode()
19+#define set_graphmode(m) (0)
20+
21+// Do not use asm("wait") but use asm("nop")
22+#undef WAIT
23+#define WAIT "nop"
24+
25+#endif // __DEBUG
--- /dev/null
+++ b/mips/zoea/editor.c
@@ -0,0 +1,2553 @@
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+#include <xc.h>
8+#include "api.h"
9+#include "editor.h"
10+#include "keyinput.h"
11+#include "compiler.h"
12+#include "main.h"
13+
14+struct _TBUF{
15+//リンク付きのテキストバッファ
16+ struct _TBUF *prev;//前方へのリンク。NULLの場合先頭または空き
17+ struct _TBUF *next;//後方へのリンク。NULLの場合最後
18+ unsigned short n;//現在の使用バイト数
19+ unsigned char Buf[TBUFSIZE];//バッファ
20+} ;
21+typedef struct _TBUF _tbuf;
22+
23+//_tbuf TextBuffer[TBUFMAXLINE]; //テキストバッファ
24+_tbuf *TextBuffer; //実体は配列RAM[]の中に確保する
25+
26+_tbuf *TBufstart; //テキストバッファの先頭位置
27+_tbuf *cursorbp; //現在のカーソル位置のテキストバッファ
28+unsigned short cursorix; //現在のカーソル位置のテキストバッファ先頭からの位置
29+_tbuf *disptopbp; //現在表示中画面左上のテキストバッファ
30+unsigned short disptopix; //現在表示中画面左上のテキストバッファ先頭からの位置
31+int num; //現在バッファ内に格納されている文字数
32+int cx,cy; //カーソル座標
33+int cx2; //上下移動時の仮カーソルX座標
34+_tbuf *cursorbp1; //範囲選択時のカーソルスタート位置のテキストバッファ、範囲選択モードでない場合NULL
35+unsigned short cursorix1; //範囲選択時のカーソルスタート位置のテキストバッファ先頭からの位置
36+int cx1,cy1; //範囲選択時のカーソルスタート座標
37+int line_no; //現在のカーソル位置の行
38+int line_no1; //範囲選択時のカーソルスタート位置の行
39+
40+// カーソル関連位置の一時避難用
41+_tbuf *cursorbp_t;
42+unsigned short cursorix_t;
43+_tbuf *disptopbp_t;
44+unsigned short disptopix_t;
45+int cx_t,cy_t,line_no_t;
46+
47+//unsigned char clipboard[WIDTH_X2*EDITWIDTHY]; //クリップボード、最大サイズは編集画面領域と同じ
48+unsigned char *clipboard; //実体は配列RAM[]の中に確保する
49+
50+int clipsize; //現在クリップボードに格納されている文字数
51+int edited; //保存後に変更されたかを表すフラグ
52+
53+//配列RAM[]内にメモリ動的確保するためのポインタ
54+char *editormallocp;
55+
56+//unsigned char filebuf[FILEBUFSIZE]; //ファイルアクセス用バッファ
57+unsigned char *filebuf; //実体は配列RAM[]の中に確保する
58+
59+//unsigned char cwdpath[PATHNAMEMAX]; //現在のディレクトリのパス名
60+unsigned char *cwdpath; //実体は配列RAM[]の中に確保する
61+
62+unsigned char currentfile[13],tempfile[13]; //編集中のファイル名、一時ファイル名
63+
64+//unsigned char filenames[MAXFILENUM][13]; //ロード時のファイル名一覧バッファ
65+unsigned char (*filenames)[13]; //実体は配列RAM[]の中に確保する
66+
67+//unsigned char undobuf[UNDOBUFSIZE]; //アンドゥ用バッファ
68+unsigned char *undobuf; //実体は配列RAM[]の中に確保する
69+unsigned char *undobuf_top; //アンドゥ用バッファの先頭を指すポインタ
70+int undobuf_used; //アンドゥ用バッファ使用量
71+
72+const unsigned char Message1[]="Hit Any Key\n";
73+const unsigned char Message2[]="File System Error\n";
74+const unsigned char Message3[]="Retry:[Enter] / Quit:[ESC]\n";
75+const unsigned char ROOTDIR[]="\\";
76+
77+unsigned char * editormalloc(int size){
78+//配列RAM[]内にサイズsizeの領域を確保し、先頭アドレスを返す
79+//確保できない場合は、エラー表示し動作停止
80+ unsigned char *p;
81+ if(editormallocp+size>RAM+RAMSIZE){
82+ printstr("Cannot allocate memory");
83+ while(1) asm("wait");
84+ }
85+ p=editormallocp;
86+ editormallocp+=size;
87+ return p;
88+}
89+
90+void wait60thsec(unsigned short n){
91+ // 60分のn秒ウェイト(ビデオ画面の最下行信号出力終了まで待つ)
92+ n+=drawcount;
93+ while(drawcount!=n) asm(WAIT);
94+}
95+
96+unsigned int bpixtopos(_tbuf *bp,unsigned int ix){
97+// テキストバッファ上の位置からテキスト全体の先頭から何文字目かを返す
98+// bp:テキストバッファポインタ
99+// ix:bp->Bufの先頭からの文字数
100+ unsigned int pos;
101+ _tbuf *sbp;
102+ pos=0;
103+ sbp=TBufstart;
104+ while(sbp!=bp){
105+ pos+=sbp->n;
106+ sbp=sbp->next;
107+ if(sbp==NULL) return 0; //エラー
108+ }
109+ return pos+ix;
110+}
111+_tbuf * postobpix(int pos,unsigned short *pix){
112+// テキスト全体の先頭からpos文字目のテキストバッファ上の位置を返す
113+// 戻り値 テキストバッファポインタ
114+// *pix(戻り値):戻り値テキストバッファの先頭からの位置(ポインタ渡し)
115+ _tbuf *bp;
116+ bp=TBufstart;
117+ while(pos >= bp->n){
118+ if(bp->next==NULL) break; //全体最後尾の場合
119+ pos-=bp->n;
120+ bp=bp->next;
121+ }
122+ if(pos > bp->n){
123+ // オーバーランエラーの場合先頭を返す
124+ *pix=0;
125+ return TBufstart;
126+ }
127+ *pix=pos;
128+ return bp;
129+}
130+_tbuf * linetobpix(int line,unsigned short *pix){
131+// テキスト全体の先頭からline行目のテキストバッファ上の位置を返す
132+// 戻り値 テキストバッファポインタ
133+// *pix(戻り値):戻り値テキストバッファの先頭からの位置(ポインタ渡し)
134+ _tbuf *bp,*bp2;
135+ int ix,ix2;
136+ bp=TBufstart;
137+ bp2=TBufstart;
138+ ix=0;
139+ ix2=0;
140+ while(line>1){
141+ while(1){
142+ if(ix>=bp->n){
143+ if(bp->next==NULL) break;
144+ bp=bp->next;
145+ ix=0;
146+ continue;
147+ }
148+ if(bp->Buf[ix++] == '\n'){
149+ bp2=bp;
150+ ix2=ix;
151+ break;
152+ }
153+ }
154+ line--;
155+ }
156+ *pix=ix2;
157+ return bp2;
158+}
159+
160+_tbuf * newTBuf(_tbuf *prev){
161+// 新しいテキストバッファ1行を生成
162+// prev:挿入先の行(prevの後ろに追加)
163+// 戻り値 生成したバッファへのポインタ、生成できない場合NULL
164+ _tbuf *bp,*next;
165+
166+ //バッファの先頭から空きをサーチ
167+ bp=TextBuffer;
168+ while(1){
169+ if(bp->prev==NULL && bp!=TBufstart) break;
170+ bp++;
171+ if(bp>=TextBuffer+TBUFMAXLINE) return NULL;//最後まで空きなし
172+ }
173+ next=prev->next;
174+ //行挿入
175+ bp->prev=prev;
176+ bp->next=next;
177+ prev->next=bp;
178+ if(next!=NULL) next->prev=bp;
179+ bp->n=0;
180+ return bp;
181+}
182+
183+_tbuf * deleteTBuf(_tbuf *bp){
184+// テキストバッファの削除
185+// bp:削除する行のポインタ
186+// 戻り値 削除前の次のバッファへのポインタ、ない場合NULL
187+ unsigned short a,b;
188+ _tbuf *prev,*next;
189+ prev=bp->prev;
190+ next=bp->next;
191+ if(prev==NULL){
192+ //先頭行の場合
193+ if(next==NULL) return next; //最後の1行の場合は削除しない
194+ TBufstart=next; //次の行を先頭行設定
195+ }
196+ else prev->next=next; //前を次にリンク(最終行ならNULLがコピーされる)
197+ if(next!=NULL) next->prev=prev; //次があれば次を前にリンク
198+ bp->prev=NULL; //空きフラグ設定
199+ return next;
200+}
201+
202+// アンドゥバッファ
203+/*
204+UNDOBUFSIZEバイトの環状バッファ。テキストバッファに対する変更発生ごとに、
205+変更内容、変更場所をバッファの先頭に記録し、先頭位置を進める。
206+アンドゥ実行が呼び出されると、バッファ先頭から読み出し、テキストバッファに対して
207+元に戻す変更を行う。
208+バッファがいっぱいになると、最後尾から消去(上書き)していく。
209+
210+<バッファ仕様>
211+ 開始位置:テキストバッファトップから何バイト目か(2バイト。下位、上位の順)
212+ 繰り返し数:連続動作の場合の回数(2バイト。下位、上位の順)
213+ バッファの前からも後ろからも削除できるよう、先頭と最後に命令をおく。ただし、
214+ 後ろの命令コードが10以上の場合は削除された文字そのものを意味する。
215+1文字挿入
216+ UNDO_INSERT,開始位置,UNDO_INSERT
217+1文字上書き
218+ UNDO_OVERWRITE,開始位置,消去文字 [,消去文字が0?9の場合さらに0を付加]
219+1文字削除(Delete)
220+ UNDO_DELETE,開始位置,消去文字 [,消去文字が0?9の場合さらに0を付加]
221+1文字削除(BackSpace)
222+ UNDO_BACKSPACE,開始位置,消去文字 [,消去文字が0?9の場合さらに0を付加]
223+連続挿入(Ctrl+Vで貼り付け)
224+ UNDO_CONTINS,開始位置,繰り返し数,UNDO_CONTINS
225+連続削除(領域選択して削除)
226+ UNDO_CONTDEL,繰り返し数,消去文字列,開始位置,繰り返し数,UNDO_CONTDEL
227+*/
228+
229+void pushundomem(unsigned char c){
230+// アンドゥ用メモリの先頭に1バイトを貯める
231+// 空きがなくなった場合、最後尾の1命令分を無効化
232+ unsigned char *p;
233+ int n;
234+
235+ if(undobuf_used>=UNDOBUFSIZE){
236+ //空きがない場合、最後尾のブロックのバイト数分をバッファ利用済み量から減らす
237+ p=undobuf_top-undobuf_used; //最後尾
238+ if(p<undobuf) p+=UNDOBUFSIZE;
239+ switch(*p){
240+ case UNDO_INSERT: //1文字挿入
241+ undobuf_used-=4;
242+ break;
243+ case UNDO_OVERWRITE: //1文字上書き
244+ case UNDO_DELETE: //1文字削除
245+ case UNDO_BACKSPACE: //1文字削除(BS)
246+ undobuf_used-=4;
247+ p+=3;
248+ if(p>=undobuf+UNDOBUFSIZE) p-=UNDOBUFSIZE;
249+ if(*p<10) undobuf_used--; //コード0?9の場合後ろに0が付加されている
250+ break;
251+ case UNDO_CONTINS: //連続挿入
252+ undobuf_used-=6;
253+ break;
254+ case UNDO_CONTDEL: //連続削除
255+ //繰り返し数の読み出し
256+ p++;
257+ if(p>=undobuf+UNDOBUFSIZE) p-=UNDOBUFSIZE;
258+ n=*p++;
259+ if(p>=undobuf+UNDOBUFSIZE) p-=UNDOBUFSIZE;
260+ n+=*p<<8;
261+ undobuf_used-=n+8;
262+ break;
263+ }
264+ }
265+ //アンドゥバッファ先頭に1バイト挿入し、先頭位置を1進める
266+ *undobuf_top++=c;
267+ if(undobuf_top>=undobuf+UNDOBUFSIZE) undobuf_top-=UNDOBUFSIZE;
268+ undobuf_used++;
269+}
270+void pushundomem2(unsigned short w){
271+// アンドゥバッファに2バイト貯める、下位、上位の順
272+ pushundomem((unsigned char)w);
273+ pushundomem(w>>8);
274+}
275+unsigned char popundomem(){
276+// アンドゥバッファから1バイト読み出し、先頭を1つ戻す
277+// 戻り値:読み出したコード
278+ undobuf_top--;
279+ if(undobuf_top<undobuf) undobuf_top+=UNDOBUFSIZE;
280+ undobuf_used--;
281+ return *undobuf_top;
282+}
283+unsigned short popundomem2(){
284+// アンドゥバッファから2バイト読み出し
285+// 戻り値:読み出した2バイトコード
286+ unsigned short w;
287+ w=popundomem()<<8;
288+ w+=popundomem();
289+ return w;
290+}
291+void setundobuf(int com,_tbuf *bp,unsigned short ix,unsigned char c,unsigned short n){
292+//アンドゥバッファにデータをセットする
293+//com:コマンド 1:1文字削除、2:1文字上書き、3:1文字挿入、4:連続削除、5:連続挿入開始
294+//bp,ix:バッファ上の実行場所(カーソル位置)
295+//c:文字(上書き、挿入の場合のみ使用)
296+//n:連続数(連続の場合のみ使用)
297+ unsigned short pos;
298+
299+ pos=bpixtopos(bp,ix); //テキストバッファ先頭から何バイト目かを求める
300+ switch(com){
301+ case UNDO_INSERT: //1文字挿入
302+ pushundomem(com);
303+ pushundomem2(pos);
304+ pushundomem(com);
305+ break;
306+ case UNDO_OVERWRITE: //1文字上書き
307+ case UNDO_DELETE: //1文字削除(Delete)
308+ case UNDO_BACKSPACE: //1文字削除(BackSpace)
309+ pushundomem(com);
310+ pushundomem2(pos);
311+ pushundomem(c);
312+ if(c<10) pushundomem(0); //10未満のコードの場合0を付加
313+ break;
314+ case UNDO_CONTINS: //連続挿入
315+ pushundomem(com);
316+ pushundomem2(pos);
317+ pushundomem2(n);
318+ pushundomem(com);
319+ break;
320+ case UNDO_CONTDEL: //連続削除
321+ pushundomem(com);
322+ pushundomem2(n);
323+ break;
324+ }
325+}
326+
327+int insertchar(_tbuf *bp,unsigned int ix,unsigned char c,int undo){
328+//テキストバッファbpの先頭からixバイトの位置にcを挿入
329+//undo 0:通常(アンドゥバッファに格納する)、1:連続挿入中、2:アンドゥ中
330+//戻り値 成功:0、不正または容量オーバー:-1、空きがあるはずなのに失敗:1
331+ unsigned char *p;
332+
333+ if(ix > bp->n) return -1; //不正指定
334+ if(num >= TBUFMAXSIZE) return -1; //バッファ容量オーバー
335+ if(bp->n < TBUFSIZE){
336+ //ライン内だけで1バイト挿入可能//
337+ for(p=bp->Buf + bp->n ; p > bp->Buf+ix ; p--) *p=*(p-1);
338+ *p=c;
339+ if(!undo) setundobuf(UNDO_INSERT,bp,ix,0,0); //アンドゥバッファ設定
340+ bp->n++;
341+ num++; //バッファ使用量
342+// if(bp->n >= TBUFSIZE && bp->next==NULL) newTBuf(bp); //バッファがいっぱいになったら新たにバッファ生成
343+ return 0;
344+ }
345+ //ラインがあふれる場合
346+ if(bp->next==NULL || bp->next->n >=TBUFSIZE){
347+ // 最終行または次のラインバッファがいっぱいだったら一行挿入
348+ if(newTBuf(bp)==NULL){
349+ // ラインバッファ挿入不可
350+ return 1;
351+ }
352+ }
353+ if(ix==TBUFSIZE){
354+ insertchar(bp->next,0,c,undo);
355+ return 0;
356+ }
357+ p=bp->Buf + TBUFSIZE-1;
358+ insertchar(bp->next,0,*p,1); //次の行の先頭に1文字挿入(必ず空きあり)
359+ for( ; p > bp->Buf+ix ; p--) *p=*(p-1);
360+ *p=c;
361+ if(!undo) setundobuf(UNDO_INSERT,bp,ix,0,0); //アンドゥバッファ設定
362+ return 0;
363+}
364+
365+int overwritechar(_tbuf *bp,unsigned int ix,unsigned char c,int undo){
366+//テキストバッファbpの先頭からixバイトの位置をcで上書き
367+//undo 0:通常(アンドゥバッファに格納する)、1:連続中、2:アンドゥ中
368+//戻り値 成功:0、不正または容量オーバー:-1、空きがあるはずなのに失敗:1
369+
370+ //現在のバッファ位置の文字が終端または改行の場合、挿入モード
371+ if(ix > bp->n) return -1; //不正指定
372+ while(ix >= bp->n){
373+ if(bp->next==NULL){
374+ //テキスト全体最後尾の場合は挿入
375+ return insertchar(bp,ix,c,undo);
376+ }
377+ bp=bp->next;
378+ ix=0;
379+ }
380+ if(bp->Buf[ix]=='\n') return insertchar(bp,ix,c,undo);
381+ if(!undo) setundobuf(UNDO_OVERWRITE,bp,ix,bp->Buf[ix],0); //アンドゥバッファ設定
382+ bp->Buf[ix]=c;
383+ return 0;
384+}
385+
386+void deletechar(_tbuf *bp,unsigned int ix,int undo){
387+//テキストバッファbpの先頭からixバイトの位置の1バイト削除
388+//undo -1:通常BackSpace(アンドゥバッファに格納する)
389+// 0:通常DELETE(アンドゥバッファに格納する)、1:連続中、2:アンドゥ中
390+ unsigned char *p;
391+
392+ if(ix > bp->n) return; //不正指定
393+ if(ix !=bp->n){
394+ //バッファの最後の文字より後ろでない場合
395+
396+ //アンドゥバッファ設定
397+ if(undo==1) pushundomem(bp->Buf[ix]); //連続削除中
398+ else if(undo==-1) setundobuf(UNDO_BACKSPACE,bp,ix,bp->Buf[ix],0); //1文字削除(backspace)
399+ else if(undo==0) setundobuf(UNDO_DELETE,bp,ix,bp->Buf[ix],0); //1文字削除
400+
401+ for(p=bp->Buf+ix ; p< bp->Buf + bp->n-1 ; p++) *p=*(p+1);
402+ bp->n--;
403+ num--; //バッファ使用量
404+ return;
405+ }
406+ //行バッファの現在の最後の場合(削除する文字がない場合)
407+ if(bp->next==NULL) return; //全体の最後の場合、何もしない
408+ deletechar(bp->next,0,undo); //次の行の先頭文字を削除
409+}
410+int gabagecollect1(void){
411+//断片化されたテキストバッファの隙間を埋めるガベージコレクション
412+//カーソルの前と後ろそれぞれ探索して最初の1バイト分のみ実施
413+//戻り値 1バイトでも移動した場合:1、なかった場合:0
414+
415+ _tbuf *bp;
416+ int f=0;
417+ unsigned char *p,*p2;
418+
419+ //カーソルがバッファの先頭にある場合、前のバッファの最後尾に変更
420+ //(ただし前に空きがない場合と先頭バッファの場合を除く)
421+ while(cursorix==0 && cursorbp->prev!=NULL && cursorbp->prev->n <TBUFSIZE){
422+ cursorbp=cursorbp->prev;
423+ cursorix=cursorbp->n;
424+ }
425+ //画面左上位置がバッファの先頭にある場合、前のバッファの最後尾に変更
426+ //(ただし先頭バッファの場合を除く)
427+ while(disptopix==0 && disptopbp->prev!=NULL){
428+ disptopbp=disptopbp->prev;
429+ disptopix=disptopbp->n;
430+ }
431+ //カーソルのあるバッファ以外の空バッファを全て削除
432+ bp=TBufstart;
433+ while(bp!=NULL){
434+ if(bp->n == 0 && bp!=cursorbp){
435+ if(bp==disptopbp) disptopbp=bp->next; //画面左上位置が空バッファ先頭の場合、次にずらす
436+ bp=deleteTBuf(bp); //空きバッファ削除
437+ }
438+ else bp=bp->next;
439+ }
440+
441+ //カーソル位置より前の埋まっていないバッファを先頭からサーチ
442+ bp=TBufstart;
443+ while(bp->n >= TBUFSIZE){
444+ if(bp==cursorbp) break;
445+ bp=bp->next;
446+ }
447+ if(bp!=cursorbp){
448+ //最初に見つけた空き場所に次のバッファから1バイト移動
449+ bp->Buf[bp->n++] = bp->next->Buf[0];
450+ bp=bp->next;
451+ p=bp->Buf;
452+ p2=p+bp->n-1;
453+ for( ; p<p2 ; p++) *p=*(p+1);
454+ bp->n--;
455+ f=1;
456+ if(bp == disptopbp) disptopix--;
457+ if(bp == cursorbp) cursorix--;
458+// else if(bp->n == 0) deleteTBuf(bp);
459+ }
460+ if(cursorbp->next ==NULL) return f; //カーソル位置が最終バッファなら終了
461+ //カーソル位置の次のバッファから埋まっていないバッファをサーチ
462+ bp=cursorbp;
463+ do{
464+ bp=bp->next;
465+ if(bp->next ==NULL) return f; //最終バッファに到達なら終了
466+ } while(bp->n >=TBUFSIZE);
467+
468+ //最初に見つけた空き場所に次のバッファから1バイト移動
469+ bp->Buf[bp->n++] = bp->next->Buf[0];
470+ bp=bp->next;
471+ p=bp->Buf;
472+ p2=p+bp->n-1;
473+ for( ; p<p2 ; p++) *p=*(p+1);
474+ bp->n--;
475+ f=1;
476+ if(bp->n == 0) deleteTBuf(bp);
477+ return f;
478+}
479+void gabagecollect2(void){
480+// 変化がなくなるまで1バイト分のガベージコレクションを呼び出し
481+ while(gabagecollect1()) ;
482+}
483+void inittextbuf(void){
484+// テキストバッファの初期化
485+ _tbuf *bp;
486+ for(bp=TextBuffer;bp<TextBuffer+TBUFMAXLINE;bp++) bp->prev=NULL; //未使用バッファ化
487+ TBufstart=TextBuffer; //リンクの先頭設定
488+ TBufstart->next=NULL;
489+ TBufstart->n=0;
490+ num=0; //バッファ使用量
491+ edited=0; //編集済みフラグクリア
492+ undobuf_top=undobuf;
493+ undobuf_used=0;
494+}
495+void redraw(){
496+//画面の再描画
497+ unsigned char *vp;
498+ _tbuf *bp,*bp1,*bp2;
499+ int ix,ix1,ix2;
500+ int x,y;
501+ unsigned char ch,cl;
502+
503+ vp=TVRAM;
504+ bp=disptopbp;
505+ ix=disptopix;
506+ cl=COLOR_NORMALTEXT;
507+ if(cursorbp1==NULL){
508+ //範囲選択モードでない場合
509+ bp1=NULL;
510+ bp2=NULL;
511+ }
512+ else{
513+ //範囲選択モードの場合、開始位置と終了の前後判断して
514+ //bp1,ix1を開始位置、bp2,ix2を終了位置に設定
515+ if(cy<cy1 || (cy==cy1 && cx<cx1)){
516+ bp1=cursorbp;
517+ ix1=cursorix;
518+ bp2=cursorbp1;
519+ ix2=cursorix1;
520+ }
521+ else{
522+ bp1=cursorbp1;
523+ ix1=cursorix1;
524+ bp2=cursorbp;
525+ ix2=cursorix;
526+ }
527+ }
528+ for(y=0;y<EDITWIDTHY;y++){
529+ if(bp==NULL) break;
530+ for(x=0;x<twidth;x++){
531+ //文字がある位置までサーチ
532+ while(ix>=bp->n){
533+ if(bp==bp1 && ix==ix1) cl=COLOR_AREASELECTTEXT;
534+ if(bp==bp2 && ix==ix2) cl=COLOR_NORMALTEXT;
535+ bp=bp->next;
536+ ix=0;
537+ if(bp==NULL) break;
538+ }
539+ if(bp==NULL) break; //バッファ最終
540+ if(bp==bp1 && ix==ix1) cl=COLOR_AREASELECTTEXT;
541+ if(bp==bp2 && ix==ix2) cl=COLOR_NORMALTEXT;
542+ ch=bp->Buf[ix++];
543+ if(ch=='\n') break;
544+ if(twidth==30) *(vp+ATTROFFSET1)=cl;
545+ else *(vp+ATTROFFSET2)=cl;
546+ *vp++=ch;
547+ }
548+ //改行およびバッファ最終以降の右側表示消去
549+ if(twidth==30){
550+ for(;x<WIDTH_X1;x++){
551+ *(vp+ATTROFFSET1)=0;
552+ *vp++=0;
553+ }
554+ }
555+ else{
556+ for(;x<WIDTH_X2;x++){
557+ *(vp+ATTROFFSET2)=0;
558+ *vp++=0;
559+ }
560+ }
561+ }
562+ //バッファ最終以降の下側表示消去
563+ for(;y<EDITWIDTHY;y++){
564+ if(twidth==30){
565+ for(x=0;x<WIDTH_X1;x++){
566+ *(vp+ATTROFFSET1)=0;
567+ *vp++=0;
568+ }
569+ }
570+ else{
571+ for(x=0;x<WIDTH_X2;x++){
572+ *(vp+ATTROFFSET2)=0;
573+ *vp++=0;
574+ }
575+ }
576+ }
577+}
578+
579+void cursor_left(void){
580+//カーソルを1つ前に移動
581+//出力:下記変数を移動先の値に変更
582+//cursorbp,cursorix バッファ上のカーソル位置
583+//cx,cy 画面上のカーソル位置
584+//cx2 cxと同じ
585+//disptopbp,disptopix 画面左上のバッファ上の位置
586+
587+ _tbuf *bp;
588+ int ix;
589+ int i;
590+ int x;
591+
592+ //バッファ上のカーソル位置を1つ前に移動
593+ if(cursorix!=0) cursorix--;
594+ else while(1) {
595+ //1つ前のバッファの最後尾に移動、ただし空バッファは飛ばす
596+ if(cursorbp->prev==NULL) return; //テキスト全体先頭なので移動しない
597+ cursorbp=cursorbp->prev;
598+ if(cursorbp->n >0){
599+ cursorix=cursorbp->n-1;//バッファ最後尾
600+ break;
601+ }
602+ }
603+
604+ //カーソルおよび画面左上位置の更新
605+ if(cx>0){
606+ //左端でなければカーソルを単純に1つ左に移動して終了
607+ cx--;
608+ cx2=cx;
609+ return;
610+ }
611+ if(cy>0){
612+ //左端だが上端ではない場合
613+ if(cursorbp->Buf[cursorix]!='\n'){
614+ // 移動先が改行コードでない場合、カーソルは1つ上の行の右端に移動
615+ cx=twidth-1;
616+ cx2=cx;
617+ cy--;
618+ return;
619+ }
620+ //画面左上位置から最後尾のX座標をサーチ
621+ bp=disptopbp;
622+ ix=disptopix;
623+ x=0;
624+ while(ix!=cursorix || bp!=cursorbp){
625+ if(bp->n==0){
626+ //空バッファの場合次へ
627+ bp=bp->next;
628+ ix=0;
629+ continue;
630+ }
631+ if(bp->Buf[ix++]=='\n' || x>=twidth-1) x=0;
632+ else x++;
633+ if(ix >= bp->n){
634+ bp=bp->next;
635+ ix=0;
636+ }
637+ }
638+ cx=x;
639+ cx2=cx;
640+ cy--;
641+ line_no--;
642+ return;
643+ }
644+
645+ //左端かつ上端の場合
646+ if(cursorbp->Buf[cursorix]!='\n'){
647+ // 移動先が改行コードでない場合、カーソルは右端に移動
648+ // 画面左上位置は画面横幅分前に移動
649+ cx=twidth-1;
650+ cx2=cx;
651+ }
652+ else{
653+ //移動先が改行コードの場合
654+ //行頭(改行の次の文字またはバッファ先頭)と現在位置の文字数差を
655+ //画面横幅で割った余りがカーソルX座標
656+ bp=cursorbp;
657+ ix=cursorix;
658+ i=0;
659+ while(1){
660+ if(ix==0){
661+ if(bp->prev==NULL) break;
662+ bp=bp->prev;
663+ ix=bp->n;
664+ continue;
665+ }
666+ ix--;
667+ if(bp->Buf[ix]=='\n') break;
668+ i++;
669+ }
670+ cx=i % twidth;
671+ cx2=cx;
672+ line_no--;
673+ }
674+ //画面左上位置は現在位置からX座標分引いたところ
675+ bp=cursorbp;
676+ ix=cursorix;
677+ x=cx;
678+ while(x>0){
679+ if(ix==0){
680+ bp=bp->prev;
681+ ix=bp->n;
682+ continue;
683+ }
684+ ix--;
685+ x--;
686+ }
687+ disptopbp=bp;
688+ disptopix=ix;
689+}
690+void cursor_right(void){
691+//カーソルを1つ後ろに移動
692+//出力:下記変数を移動先の値に変更
693+//cursorbp,cursorix バッファ上のカーソル位置
694+//cx,cy 画面上のカーソル位置
695+//cx2 cxと同じ
696+//disptopbp,disptopix 画面左上のバッファ上の位置
697+
698+ _tbuf *bp;
699+ int ix;
700+ int i;
701+ int x;
702+ unsigned char c;
703+
704+ if(cursorix >= cursorbp->n){
705+ //バッファ最後尾の場合、次の先頭に移動
706+ bp=cursorbp;
707+ while(1) {
708+ //空バッファは飛ばす
709+ if(bp->next==NULL) return; //テキスト全体最後尾なので移動しない
710+ bp=bp->next;
711+ if(bp->n >0) break;
712+ }
713+ cursorbp=bp;
714+ cursorix=0;//バッファ先頭
715+ }
716+ c=cursorbp->Buf[cursorix++]; //バッファ上のカーソル位置のコードを読んで1つ後ろに移動
717+ if(c!='\n' && cx<twidth-1){
718+ //カーソル位置が改行でも右端でもない場合単純に1つ右に移動して終了
719+ cx++;
720+ cx2=cx;
721+ return;
722+ }
723+ cx=0; //カーソルを左端に移動
724+ cx2=cx;
725+ if(c=='\n') line_no++;
726+ if(cy<EDITWIDTHY-1){
727+ //下端でなければカーソルを次行に移動して終了
728+ cy++;
729+ return;
730+ }
731+ //下端の場合
732+ //画面左上位置を更新
733+ //改行コードまたは画面横幅超えるまでサーチ
734+ bp=disptopbp;
735+ ix=disptopix;
736+ x=0;
737+ while(x<twidth){
738+ if(ix >= bp->n){
739+ bp=bp->next;
740+ ix=0;
741+ continue;
742+ }
743+ if(bp->Buf[ix++]=='\n') break;
744+ x++;
745+ }
746+ disptopbp=bp;
747+ disptopix=ix;
748+}
749+void cursor_up(void){
750+//カーソルを1つ上に移動
751+//出力:下記変数を移動先の値に変更
752+//cursorbp,cursorix バッファ上のカーソル位置
753+//cx,cy 画面上のカーソル位置
754+//cx2 移動前のcxと同じ
755+//disptopbp,disptopix 画面左上のバッファ上の位置
756+
757+ _tbuf *bp;
758+ int ix;
759+ int i;
760+ int x;
761+ unsigned char c;
762+
763+ //画面幅分前に戻ったところがバッファ上カーソルの移動先
764+ //途中で改行コードがあれば別の手段で検索
765+ bp=cursorbp;
766+ ix=cursorix;
767+ i=cx2-cx;
768+ while(i<twidth){
769+ if(ix==0){
770+ if(bp->prev==NULL) return; //バッファ先頭までサーチしたら移動なし
771+ bp=bp->prev;
772+ ix=bp->n;
773+ continue;
774+ }
775+ ix--;
776+ if(bp->Buf[ix]=='\n') break;
777+ i++;
778+ }
779+ cursorbp=bp;
780+ cursorix=ix;
781+ //画面幅の間に改行コードがなかった場合
782+ if(i==twidth){
783+ cx=cx2;
784+ //画面上端でなければカーソルを1つ上に移動して終了
785+ if(cy>0){
786+ cy--;
787+ return;
788+ }
789+ //画面上端の場合、カーソル位置からX座標分戻ったところが画面左上位置
790+ x=cx;
791+ while(x>0){
792+ if(ix==0){
793+ bp=bp->prev;
794+ ix=bp->n;
795+ continue;
796+ }
797+ ix--;
798+ x--;
799+ }
800+ disptopbp=bp;
801+ disptopix=ix;
802+ return;
803+ }
804+ //改行が見つかった場合
805+ //行頭(改行の次の文字またはバッファ先頭)と現在位置の文字数差を
806+ //画面横幅で割った余りを求める
807+ line_no--;
808+ i=0;
809+ while(1){
810+ if(ix==0){
811+ if(bp->prev==NULL) break;
812+ bp=bp->prev;
813+ ix=bp->n;
814+ continue;
815+ }
816+ ix--;
817+ if(bp->Buf[ix]=='\n') break;
818+ i++;
819+ }
820+ x=i % twidth; //改行ブロックの最終行の右端
821+ bp=cursorbp;
822+ ix=cursorix;
823+ //バッファ上のカーソル位置は改行ブロックの最終行右端からカーソルX座標分戻る
824+ //最終行右端のほうが小さい場合、その場所をバッファ上のカーソル位置とする
825+ while(x>cx2){
826+ if(ix==0){
827+ bp=bp->prev;
828+ ix=bp->n;
829+ continue;
830+ }
831+ ix--;
832+ x--;
833+ }
834+ cursorbp=bp;
835+ cursorix=ix;
836+ cx=x; //cx2または改行ブロック最終行右端
837+ if(cy>0){
838+ //画面上端でなければカーソルを1つ上に移動して終了
839+ cy--;
840+ return;
841+ }
842+ //画面上端の場合
843+ //画面左上位置は現在位置からX座標分引いたところ
844+ while(x>0){
845+ if(ix==0){
846+ bp=bp->prev;
847+ ix=bp->n;
848+ continue;
849+ }
850+ ix--;
851+ x--;
852+ }
853+ disptopbp=bp;
854+ disptopix=ix;
855+}
856+void cursor_down(void){
857+//カーソルを1つ下に移動
858+//出力:下記変数を移動先の値に変更
859+//cursorbp,cursorix バッファ上のカーソル位置
860+//cx,cy 画面上のカーソル位置
861+//cx2 移動前のcxと同じ
862+//disptopbp,disptopix 画面左上のバッファ上の位置
863+
864+ _tbuf *bp;
865+ int ix;
866+ int x;
867+ unsigned char c;
868+
869+ //次行の先頭サーチ
870+ //カーソル位置から画面右端までの間に改行コードがあれば次の文字が先頭
871+ bp=cursorbp;
872+ ix=cursorix;
873+ x=cx;
874+ while(x<twidth){
875+ if(ix>=bp->n){
876+ if(bp->next==NULL) return; //バッファ最後までサーチしたら移動なし
877+ bp=bp->next;
878+ ix=0;
879+ continue;
880+ }
881+ c=bp->Buf[ix];
882+ ix++;
883+ x++;
884+ if(c=='\n'){
885+ line_no++;
886+ break;
887+ }
888+ }
889+ //次行先頭からcx2文字数分後ろにサーチ
890+ x=0;
891+ while(x<cx2){
892+ if(ix>=bp->n){
893+ if(bp->next==NULL) break; //バッファ最後の場合そこに移動
894+ bp=bp->next;
895+ ix=0;
896+ continue;
897+ }
898+ if(bp->Buf[ix]=='\n') break; //改行コードの場合そこに移動
899+ ix++;
900+ x++;
901+ }
902+ cursorbp=bp;
903+ cursorix=ix;
904+ cx=x;
905+ //画面下端でなければカーソルを1つ下に移動して終了
906+ if(cy<EDITWIDTHY-1){
907+ cy++;
908+ return;
909+ }
910+ //下端の場合
911+ //画面左上位置を更新
912+ //改行コードまたは画面横幅超えるまでサーチ
913+ bp=disptopbp;
914+ ix=disptopix;
915+ x=0;
916+ while(x<twidth){
917+ if(ix >= bp->n){
918+ bp=bp->next;
919+ ix=0;
920+ continue;
921+ }
922+ if(bp->Buf[ix++]=='\n') break;
923+ x++;
924+ }
925+ disptopbp=bp;
926+ disptopix=ix;
927+}
928+void cursor_home(void){
929+//カーソルを行先頭に移動
930+//出力:下記変数を移動先の値に変更
931+//cursorbp,cursorix バッファ上のカーソル位置
932+//cx,cx2 0
933+//cy 変更なし
934+//disptopbp,disptopix 画面左上のバッファ上の位置(変更なし)
935+
936+ //カーソルX座標分前に移動
937+ while(cx>0){
938+ if(cursorix==0){
939+ //空バッファは飛ばす
940+ cursorbp=cursorbp->prev;
941+ cursorix=cursorbp->n;
942+ continue;
943+ }
944+ cursorix--;
945+ cx--;
946+ }
947+ cx2=0;
948+}
949+void cursor_end(void){
950+//カーソルを行末に移動
951+//出力:下記変数を移動先の値に変更
952+//cursorbp,cursorix バッファ上のカーソル位置
953+//cx,cx2 行末
954+//cy 変更なし
955+//disptopbp,disptopix 画面左上のバッファ上の位置(変更なし)
956+
957+ //カーソルX座標を画面幅分後ろに移動
958+ //改行コードまたはバッファ最終があればそこに移動
959+ while(cx<twidth-1){
960+ if(cursorix>=cursorbp->n){
961+ //空バッファは飛ばす
962+ if(cursorbp->next==NULL) break;
963+ cursorbp=cursorbp->next;
964+ cursorix=0;
965+ continue;
966+ }
967+ if(cursorbp->Buf[cursorix]=='\n') break;
968+ cursorix++;
969+ cx++;
970+ }
971+ cx2=cx;
972+}
973+void cursor_pageup(void){
974+//PageUpキー
975+//最上行が最下行になるまでスクロール
976+//出力:下記変数を移動先の値に変更
977+//cursorbp,cursorix バッファ上のカーソル位置
978+//cx,cx2
979+//cy
980+//disptopbp,disptopix 画面左上のバッファ上の位置
981+
982+ _tbuf *bp;
983+ int ix;
984+ int i;
985+ int cy_old;
986+
987+ cy_old=cy;
988+ while(cy>0) cursor_up(); // cy==0になるまでカーソルを上に移動
989+ for(i=0;i<EDITWIDTHY-1;i++){
990+ //画面行数-1行分カーソルを上に移動
991+ bp=disptopbp;
992+ ix=disptopix;
993+ cursor_up();
994+ if(bp==disptopbp && ix==disptopix) break; //最上行で移動できなかった場合抜ける
995+ }
996+ //元のY座標までカーソルを下に移動、1行も動かなかった場合は最上行に留まる
997+ if(i>0) while(cy<cy_old) cursor_down();
998+}
999+void cursor_pagedown(void){
1000+//PageDownキー
1001+//最下行が最上行になるまでスクロール
1002+//出力:下記変数を移動先の値に変更
1003+//cursorbp,cursorix バッファ上のカーソル位置
1004+//cx,cx2
1005+//cy
1006+//disptopbp,disptopix 画面左上のバッファ上の位置
1007+
1008+ _tbuf *bp;
1009+ int ix;
1010+ int i;
1011+ int y;
1012+ int cy_old;
1013+
1014+ cy_old=cy;
1015+ while(cy<EDITWIDTHY-1){
1016+ // cy==EDITWIDTH-1になるまでカーソルを下に移動
1017+ y=cy;
1018+ cursor_down();
1019+ if(y==cy) break;// バッファ最下行で移動できなかった場合抜ける
1020+ }
1021+ for(i=0;i<EDITWIDTHY-1;i++){
1022+ //画面行数-1行分カーソルを下に移動
1023+ bp=disptopbp;
1024+ ix=disptopix;
1025+ cursor_down();
1026+ if(bp==disptopbp && ix==disptopix) break; //最下行で移動できなかった場合抜ける
1027+ }
1028+ //下端からさらに移動した行数分、カーソルを上に移動、1行も動かなかった場合は最下行に留まる
1029+ if(i>0) while(cy>cy_old) cursor_up();
1030+}
1031+void cursor_top(void){
1032+//カーソルをテキストバッファの先頭に移動
1033+ cursorbp=TBufstart;
1034+ cursorix=0;
1035+ cursorbp1=NULL; //範囲選択モード解除
1036+ disptopbp=cursorbp;
1037+ disptopix=cursorix;
1038+ cx=0;
1039+ cx2=0;
1040+ cy=0;
1041+ line_no=1;
1042+}
1043+
1044+int countarea(void){
1045+//テキストバッファの指定範囲の文字数をカウント
1046+//範囲は(cursorbp,cursorix)と(cursorbp1,cursorix1)で指定
1047+//後ろ側の一つ前の文字までをカウント
1048+ _tbuf *bp1,*bp2;
1049+ int ix1,ix2;
1050+ int n;
1051+
1052+ //範囲選択モードの場合、開始位置と終了の前後判断して
1053+ //bp1,ix1を開始位置、bp2,ix2を終了位置に設定
1054+ if(cy<cy1 || (cy==cy1 && cx<cx1)){
1055+ bp1=cursorbp;
1056+ ix1=cursorix;
1057+ bp2=cursorbp1;
1058+ ix2=cursorix1;
1059+ }
1060+ else{
1061+ bp1=cursorbp1;
1062+ ix1=cursorix1;
1063+ bp2=cursorbp;
1064+ ix2=cursorix;
1065+ }
1066+ n=0;
1067+ while(1){
1068+ if(bp1==bp2 && ix1==ix2) return n;
1069+ if(ix1 < bp1->n){
1070+ n++;
1071+ ix1++;
1072+ }
1073+ else{
1074+ bp1=bp1->next;
1075+ ix1=0;
1076+ }
1077+ }
1078+}
1079+void deletearea_len(_tbuf *bp,unsigned int ix,int n,int undo){
1080+//テキストバッファの指定位置から複数文字削除
1081+//bp,ix:削除開始位置
1082+//n:削除する文字数
1083+//undo:0:通常、2:アンドゥ中
1084+ unsigned char *p;
1085+ int i;
1086+
1087+ //選択範囲が最初のバッファの最後まである場合
1088+ if(n>=(bp->n - ix)){
1089+ if(!undo){
1090+ p=bp->Buf+ix;
1091+ for(i=ix;i < bp->n;i++) pushundomem(*p++); //アンドゥバッファに格納
1092+ }
1093+ n -= bp->n - ix; //削除文字数減
1094+ num-=bp->n - ix; //バッファ使用量を減数
1095+ bp->n=ix; //ix以降を削除
1096+ bp=bp->next;
1097+ if(bp==NULL) return;
1098+ ix=0;
1099+ }
1100+ //次のバッファ以降、選択範囲の終了位置が含まれないバッファは削除
1101+ while(n>=bp->n){
1102+ if(!undo){
1103+ p=bp->Buf;
1104+ for(i=0;i < bp->n;i++) pushundomem(*p++); //アンドゥバッファに格納
1105+ }
1106+ n-=bp->n; //削除文字数減
1107+ num-=bp->n; //バッファ使用量を減数
1108+ bp=deleteTBuf(bp); //バッファ削除して次のバッファに進む
1109+ if(bp==NULL) return;
1110+ }
1111+ //選択範囲の終了位置を含む場合、1文字ずつ削除
1112+ if(!undo) undo=1;
1113+ while(n>0){
1114+ deletechar(bp,ix,undo); //バッファから1文字削除(numは関数内で1減される)
1115+ n--;
1116+ }
1117+}
1118+void deletearea(void){
1119+//テキストバッファの指定範囲を削除
1120+//範囲は(cursorbp,cursorix)と(cursorbp1,cursorix1)で指定
1121+//後ろ側の一つ前の文字までを削除
1122+//削除後のカーソル位置は選択範囲の先頭にし、範囲選択モード解除する
1123+
1124+ _tbuf *bp;
1125+ int ix;
1126+ int n;
1127+
1128+ n=countarea(); //選択範囲の文字数カウント
1129+ if(n==0) return;
1130+
1131+ //範囲選択の開始位置と終了位置の前後を判断してカーソルを開始位置に設定
1132+ if(cy>cy1 || (cy==cy1 && cx>cx1)){
1133+ cursorbp=cursorbp1;
1134+ cursorix=cursorix1;
1135+ cx=cx1;
1136+ cy=cy1;
1137+ line_no=line_no1;
1138+ }
1139+ cx2=cx;
1140+ cursorbp1=NULL; //範囲選択モード解除
1141+
1142+ //bp,ixを開始位置に設定
1143+ bp=cursorbp;
1144+ ix=cursorix;
1145+
1146+ setundobuf(UNDO_CONTDEL,bp,ix,0,n); //アンドゥバッファ設定(連続削除開始)
1147+ deletearea_len(bp,ix,n,0); //n文字分削除
1148+ //アンドゥバッファに連続削除終了設定
1149+ pushundomem2(bpixtopos(bp,ix));
1150+ pushundomem2(n);
1151+ pushundomem(UNDO_CONTDEL);
1152+}
1153+void clipcopy(void){
1154+// 選択範囲をクリップボードにコピー
1155+ _tbuf *bp1,*bp2;
1156+ int ix1,ix2;
1157+ char *ps,*pd;
1158+
1159+ //範囲選択モードの場合、開始位置と終了の前後判断して
1160+ //bp1,ix1を開始位置、bp2,ix2を終了位置に設定
1161+ if(cy<cy1 || (cy==cy1 && cx<cx1)){
1162+ bp1=cursorbp;
1163+ ix1=cursorix;
1164+ bp2=cursorbp1;
1165+ ix2=cursorix1;
1166+ }
1167+ else{
1168+ bp1=cursorbp1;
1169+ ix1=cursorix1;
1170+ bp2=cursorbp;
1171+ ix2=cursorix;
1172+ }
1173+ ps=bp1->Buf+ix1;
1174+ pd=clipboard;
1175+ clipsize=0;
1176+ while(bp1!=bp2 || ix1!=ix2){
1177+ if(ix1 < bp1->n){
1178+ *pd++=*ps++;
1179+ clipsize++;
1180+ ix1++;
1181+ }
1182+ else{
1183+ bp1=bp1->next;
1184+ ps=bp1->Buf;
1185+ ix1=0;
1186+ }
1187+ }
1188+}
1189+void clippaste(void){
1190+// クリップボードから貼り付け
1191+ int n,i;
1192+ unsigned char *p;
1193+
1194+ if(clipsize==0 || num+clipsize>TBUFMAXSIZE) return;
1195+ setundobuf(UNDO_CONTINS,cursorbp,cursorix,0,clipsize); //アンドゥバッファ設定
1196+ p=clipboard;
1197+ for(n=clipsize;n>0;n--){
1198+ i=insertchar(cursorbp,cursorix,*p,1);
1199+ if(i>0){
1200+ //バッファ空きがあるのに挿入失敗の場合
1201+ gabagecollect2(); //全体ガベージコレクション
1202+ i=insertchar(cursorbp,cursorix,*p,1);//テキストバッファに1文字挿入
1203+ }
1204+ if(i!=0) break;//挿入失敗
1205+ cursor_right();//画面上、バッファ上のカーソル位置を1つ後ろに移動
1206+ p++;
1207+ }
1208+}
1209+void movecursor(int pos){
1210+// カーソルを現在の位置から任意の位置に移動
1211+// pos:移動したいテキストバッファ先頭からのバイト位置
1212+ int pos2,d;
1213+ pos2=bpixtopos(cursorbp,cursorix);
1214+ d=pos-pos2;
1215+ if(d==0) return;
1216+ if(d>0){
1217+ while(d>0){
1218+ cursor_right();
1219+ d--;
1220+ }
1221+ }
1222+ else{
1223+ while(d<0){
1224+ cursor_left();
1225+ d++;
1226+ }
1227+ }
1228+}
1229+void undoexec(){
1230+//アンドゥ実行
1231+ unsigned char c,c1;
1232+ _tbuf *bp;
1233+ unsigned short n,ix;
1234+ int pos;
1235+
1236+ if(undobuf_used==0) return; //アンドゥバッファ空
1237+ cursorbp1=NULL; //範囲選択解除
1238+ c=popundomem(); //アンドゥバッファ先頭の命令読み出し
1239+ switch(c){
1240+ case UNDO_INSERT: //1文字挿入
1241+ //カーソル移動し1文字削除
1242+ pos=popundomem2();
1243+ movecursor(pos);
1244+ bp=postobpix(pos,&ix);
1245+ deletechar(bp,ix,2);
1246+ popundomem(); //dummy read
1247+ break;
1248+ case UNDO_CONTINS: //連続挿入
1249+ //カーソル移動し連続数分削除
1250+ n=popundomem2();
1251+ pos=popundomem2();
1252+ movecursor(pos);
1253+ bp=postobpix(pos,&ix);
1254+ deletearea_len(bp,ix,n,2);
1255+ popundomem(); //dummy read
1256+ break;
1257+ case UNDO_CONTDEL: //連続削除
1258+ //カーソル移動し連続数分、コードを読み出して挿入
1259+ n=popundomem2();
1260+ pos=popundomem2();
1261+ movecursor(pos);
1262+ bp=postobpix(pos,&ix);
1263+ while(n>0){
1264+ insertchar(bp,ix,popundomem(),2);
1265+ n--;
1266+ }
1267+ popundomem2(); //dummy read
1268+ popundomem(); //dummy read
1269+ break;
1270+ case 0: //0の場合、次の1バイトが実際の有効なコード
1271+ c=popundomem();
1272+ default: //1文字削除(DEL、BS)、1文字上書き
1273+ //カーソル移動し1文字挿入(または上書き)
1274+ pos=popundomem2();
1275+ movecursor(pos);
1276+ bp=postobpix(pos,&ix);
1277+ c1=popundomem();
1278+ if(c1==UNDO_OVERWRITE){
1279+ overwritechar(bp,ix,c,2);
1280+ }
1281+ else{
1282+ insertchar(bp,ix,c,2);
1283+ if(c1==UNDO_BACKSPACE) cursor_right();
1284+ }
1285+ break;
1286+ }
1287+}
1288+
1289+void set_areamode(){
1290+//範囲選択モード開始時のカーソル開始位置グローバル変数設定
1291+ cursorbp1=cursorbp;
1292+ cursorix1=cursorix;
1293+ cx1=cx;
1294+ cy1=cy;
1295+ line_no1=line_no;
1296+}
1297+void save_cursor(void){
1298+//カーソル関連グローバル変数を一時避難
1299+ cursorbp_t=cursorbp;
1300+ cursorix_t=cursorix;
1301+ disptopbp_t=disptopbp;
1302+ disptopix_t=disptopix;
1303+ cx_t=cx;
1304+ cy_t=cy;
1305+ line_no_t=line_no;
1306+}
1307+void restore_cursor(void){
1308+//カーソル関連グローバル変数を一時避難場所から戻す
1309+ cursorbp=cursorbp_t;
1310+ cursorix=cursorix_t;
1311+ disptopbp=disptopbp_t;
1312+ disptopix=disptopix_t;
1313+ cx=cx_t;
1314+ cy=cy_t;
1315+ line_no=line_no_t;
1316+}
1317+
1318+int filesystemretry(){
1319+// SDファイルシステムの再初期化確認と実施
1320+// SDファイルへの保存や読み込み時にファイルエラーが発生した場合に呼び出す
1321+// 戻り値 0:初期化成功、-1:成功することなくEscapeで抜けた
1322+ unsigned short vk;
1323+ while(1){
1324+ setcursorcolor(COLOR_NORMALTEXT);
1325+ printstr((unsigned char *)Message3); //Retry / Quit
1326+ while(1){
1327+ inputchar(); //1文字入力待ち
1328+ vk=vkey & 0xff;
1329+ if(vk==VK_RETURN || vk==VK_SEPARATOR) break;
1330+ if(vk==VK_ESCAPE) return -1;
1331+ }
1332+ //ファイルシステム初期化
1333+ if(FSInit()!=FALSE) return 0; //成功
1334+ //エラーの場合
1335+ setcursorcolor(COLOR_ERRORTEXT);
1336+ printstr((unsigned char *)Message2);//File System Error
1337+ }
1338+}
1339+
1340+int sdfilecopy(char *sourcefile,char *distfile){
1341+// SDカード上のファイルをコピー
1342+// soucefile:コピー元ファイル名
1343+// distfile:コピー先ファイル名
1344+// 戻り値:正常終了 0、エラー終了時エラー番号
1345+ FSFILE *sfp,*dfp;
1346+ int n,er,c;
1347+ er=0;
1348+ sfp=FSfopen(sourcefile,"r");
1349+ if(sfp==NULL) return ERR_CANTFILEOPEN;
1350+ dfp=FSfopen(distfile,"w");
1351+ if(dfp==NULL){
1352+ FSfclose(sfp);
1353+ return ERR_CANTFILEOPEN;
1354+ }
1355+ c=0;
1356+ while(1){
1357+ if(c==0){
1358+ printchar('.');
1359+ c=100;
1360+ }
1361+ c--;
1362+ n=FSfread(filebuf,1,FILEBUFSIZE,sfp);
1363+ if(n==0) break;
1364+ if(FSfwrite(filebuf,1,n,dfp)!=n){
1365+ er=ERR_CANTWRITEFILE;
1366+ break;
1367+ }
1368+ }
1369+ FSfclose(sfp);
1370+ FSfclose(dfp);
1371+ return er;
1372+}
1373+int savetextfile(char *filename){
1374+// テキストバッファをテキストファイルに書き込み
1375+// 書き込み成功で0、失敗でエラーコード(負数)を返す
1376+ FSFILE *fp;
1377+ _tbuf *bp;
1378+ int ix,n,i,er;
1379+ unsigned char *ps,*pd;
1380+ er=0;//エラーコード
1381+ i=-1;
1382+ fp=FSfopen(filename,"w");
1383+ if(fp==NULL) return ERR_CANTFILEOPEN;
1384+ bp=TBufstart;
1385+ ix=0;
1386+ ps=bp->Buf;
1387+ do{
1388+ pd=filebuf;
1389+ n=0;
1390+ while(n<FILEBUFSIZE-1){
1391+ //改行コードが2バイトになることを考慮してバッファサイズ-1までとする
1392+ while(ix>=bp->n){
1393+ bp=bp->next;
1394+ if(bp==NULL){
1395+ break;
1396+ }
1397+ ix=0;
1398+ ps=bp->Buf;
1399+ }
1400+ if(bp==NULL) break;
1401+ if(*ps=='\n'){
1402+ *pd++='\r'; //改行コード0A→0D 0Aにする
1403+ n++;
1404+ }
1405+ *pd++=*ps++;
1406+ ix++;
1407+ n++;
1408+ }
1409+ if(n>0){
1410+ i=FSfwrite(filebuf,1,n,fp);
1411+ if(i!=n) er=ERR_CANTWRITEFILE;
1412+ }
1413+ } while(bp!=NULL && er==0);
1414+ FSfclose(fp);
1415+ return er;
1416+}
1417+int loadtextfile(char *filename){
1418+// テキストファイルをテキストバッファに読み込み
1419+// 読み込み成功で0、失敗でエラーコード(負数)を返す
1420+ FSFILE *fp;
1421+ _tbuf *bp;
1422+ int ix,n,i,er;
1423+ unsigned char *ps,*pd;
1424+ er=0;//エラーコード
1425+ fp=FSfopen(filename,"r");
1426+ if(fp==NULL) return ERR_CANTFILEOPEN;
1427+ inittextbuf();
1428+ bp=TextBuffer;
1429+ ix=0;
1430+ pd=bp->Buf;
1431+ do{
1432+ n=FSfread(filebuf,1,FILEBUFSIZE,fp);
1433+ ps=filebuf;
1434+ for(i=0;i<n;i++){
1435+ if(ix>=TBUFSIZE){
1436+ bp->n=TBUFSIZE;
1437+ bp=newTBuf(bp);
1438+ if(bp==NULL){
1439+ er=ERR_FILETOOBIG;
1440+ break;
1441+ }
1442+ ix=0;
1443+ pd=bp->Buf;
1444+ }
1445+ if(*ps=='\r') ps++; //改行コード0D 0A→0Aにする(単純に0D無視)
1446+ else{
1447+ *pd++=*ps++;
1448+ ix++;
1449+ num++;//バッファ総文字数
1450+ if(num>TBUFMAXSIZE){
1451+ er=ERR_FILETOOBIG;
1452+ break;
1453+ }
1454+ }
1455+ }
1456+ } while(n==FILEBUFSIZE && er==0);
1457+ if(bp!=NULL) bp->n=ix;//最後のバッファの文字数
1458+ FSfclose(fp);
1459+ if(er){
1460+ //エラー発生の場合バッファ、カーソル位置初期化
1461+ inittextbuf();
1462+ cursor_top();
1463+ }
1464+ return er;
1465+}
1466+int overwritecheck(char *fn){
1467+// ファイルの上書き確認
1468+// ファイルの存在をチェックし、存在する場合キーボードから上書き確認する
1469+// fn:ファイル名へのポインタ
1470+// 戻り値 0:存在しないまたは上書き、-1:上書きしない
1471+ SearchRec sr;
1472+ unsigned short vk;
1473+ if(FindFirst(fn,ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE,&sr)) return 0; //ファイルが存在しない
1474+ setcursorcolor(COLOR_ERRORTEXT);
1475+ printstr(fn);
1476+ printstr(": File Exists\n");
1477+ setcursorcolor(COLOR_NORMALTEXT);
1478+ printstr("Ovewrite:[Enter] / Stop:[ESC]\n");
1479+ while(1){
1480+ inputchar(); //1文字入力待ち
1481+ vk=vkey & 0xff;
1482+ if(vk==VK_RETURN || vk==VK_SEPARATOR) return 0;
1483+ if(vk==VK_ESCAPE) return -1;
1484+ }
1485+}
1486+void printfilename(unsigned char x,unsigned char y,int f,int num_dir){
1487+// x,yの位置にファイル名またはディレクトリ名を表示
1488+
1489+ if(f==-2){
1490+ setcursor(x,y,COLOR_ERRORTEXT);
1491+ printchar('<');
1492+ printstr("New FILE");
1493+ printchar('>');
1494+ }
1495+ else if(f==-1){
1496+ setcursor(x,y,COLOR_ERRORTEXT);
1497+ printchar('<');
1498+ printstr("New Dir");
1499+ printchar('>');
1500+ }
1501+ else if(f<num_dir){
1502+ setcursor(x,y,COLOR_DIR);
1503+ printchar('[');
1504+ printstr(filenames[f]);
1505+ printchar(']');
1506+ }
1507+ else{
1508+ setcursor(x,y,COLOR_NORMALTEXT);
1509+ printstr(filenames[f]);
1510+ }
1511+}
1512+int select_dir_file(int filenum,int num_dir, unsigned char* msg){
1513+// filenames[]配列に読み込まれたファイルまたはディレクトリを画面表示しキーボードで選択する
1514+// filenum:ファイル+ディレクトリ数
1515+// num_dir:ディレクトリ数(filenames[]は先頭からnum_dir-1までがディレクトリ)
1516+// msg:画面上部に表示するメッセージ
1517+// 戻り値
1518+// filenames[]の選択されたファイルまたはディレクトリ番号
1519+// -1:新規ディレクトリ作成、tempfile[]にディレクトリ名
1520+// -2:新規ファイル作成、tempfile[]にファイル名
1521+// -3:ESCキーが押された
1522+ int top,f;
1523+ unsigned char *ps,*pd;
1524+ int x,y;
1525+ unsigned char vk;
1526+ //ファイル一覧を画面に表示
1527+ cls();
1528+ setcursor(0,0,COLOR_NORMALTEXT);
1529+ printstr(msg);
1530+ printstr(": ");
1531+ setcursorcolor(4);
1532+ printstr("Select&[Enter] / [ESC]\n");
1533+ for(f=-2;f<filenum;f++){
1534+ x=(f&1)*15+1;
1535+ y=(f+2)/2+1;
1536+ if(y>=WIDTH_Y-1) break;
1537+ printfilename(x,y,f,num_dir);
1538+ }
1539+ top=-2;//画面一番先頭のファイル番号
1540+ f=-2;//現在選択中のファイル番号
1541+ while(1){
1542+ setcursor((f&1)*15,(f-top)/2+1,5);
1543+ printchar(0x1c);// Right Arrow
1544+ cursor--;
1545+ while(1){
1546+ inputchar();
1547+ vk=vkey & 0xff;
1548+ if(vk) break;
1549+ }
1550+ printchar(' ');
1551+ setcursor(0,WIDTH_Y-1,COLOR_NORMALTEXT);
1552+ for(x=0;x<twidth-1;x++) printchar(' '); //最下行のステータス表示を消去
1553+ switch(vk){
1554+ case VK_UP:
1555+ case VK_NUMPAD8:
1556+ //上矢印キー
1557+ if(f>=0){
1558+ f-=2;
1559+ if(f<top){
1560+ //画面最上部の場合、下にスクロールして最上部にファイル名2つ表示
1561+ if(twidth==WIDTH_X1){
1562+ setcursor(WIDTH_X1-1,WIDTH_Y-2,COLOR_NORMALTEXT);
1563+ while(cursor>=TVRAM+WIDTH_X1*2){
1564+ *cursor=*(cursor-WIDTH_X1);
1565+ *(cursor+ATTROFFSET1)=*(cursor+ATTROFFSET1-WIDTH_X1);
1566+ cursor--;
1567+ }
1568+ while(cursor>=TVRAM+WIDTH_X1) *cursor--=' ';
1569+ }
1570+ else{
1571+ setcursor(WIDTH_X2-1,WIDTH_Y-2,COLOR_NORMALTEXT);
1572+ while(cursor>=TVRAM+WIDTH_X2*2){
1573+ *cursor=*(cursor-WIDTH_X2);
1574+ *(cursor+ATTROFFSET2)=*(cursor+ATTROFFSET2-WIDTH_X2);
1575+ cursor--;
1576+ }
1577+ while(cursor>=TVRAM+WIDTH_X2) *cursor--=' ';
1578+ }
1579+ top-=2;
1580+ printfilename(1,1,top,num_dir);
1581+ printfilename(16,1,top+1,num_dir);
1582+ }
1583+ }
1584+ break;
1585+ case VK_DOWN:
1586+ case VK_NUMPAD2:
1587+ //下矢印キー
1588+ if(((f+2)&0xfffe)<filenum){
1589+ f+=2;
1590+ if(f>=filenum) f--;
1591+ if(f-top>=(WIDTH_Y-2)*2){
1592+ //画面最下部の場合、上にスクロールして最下部にファイル名1つor2つ表示
1593+ setcursor(0,1,COLOR_NORMALTEXT);
1594+ if(twidth==WIDTH_X1){
1595+ while(cursor<TVRAM+WIDTH_X1*(WIDTH_Y-2)){
1596+ *cursor=*(cursor+WIDTH_X1);
1597+ *(cursor+ATTROFFSET1)=*(cursor+ATTROFFSET1+WIDTH_X1);
1598+ cursor++;
1599+ }
1600+ while(cursor<TVRAM+WIDTH_X1*(WIDTH_Y-1)) *cursor++=' ';
1601+ }
1602+ else{
1603+ while(cursor<TVRAM+WIDTH_X2*(WIDTH_Y-2)){
1604+ *cursor=*(cursor+WIDTH_X2);
1605+ *(cursor+ATTROFFSET2)=*(cursor+ATTROFFSET2+WIDTH_X2);
1606+ cursor++;
1607+ }
1608+ while(cursor<TVRAM+WIDTH_X2*(WIDTH_Y-1)) *cursor++=' ';
1609+ }
1610+ top+=2;
1611+ printfilename(1,WIDTH_Y-2,f&0xfffe,num_dir);
1612+ if((f|1)<filenum){
1613+ printfilename(16,WIDTH_Y-2,f|1,num_dir);
1614+ }
1615+ }
1616+ }
1617+ break;
1618+ case VK_LEFT:
1619+ case VK_NUMPAD4:
1620+ //左矢印キー
1621+ if(f&1) f--;
1622+ break;
1623+ case VK_RIGHT:
1624+ case VK_NUMPAD6:
1625+ //右矢印キー
1626+ if((f&1)==0 && f+1<filenum) f++;
1627+ break;
1628+ case VK_RETURN: //Enterキー
1629+ case VK_SEPARATOR: //テンキーのEnter
1630+ if(f==-2){
1631+ //新規ファイル
1632+ setcursor(0,WIDTH_Y-1,COLOR_ERRORTEXT);
1633+ printstr("Input File Name: ");
1634+ setcursorcolor(COLOR_NORMALTEXT);
1635+ //ファイル名入力
1636+ *tempfile=0;
1637+ if(lineinput(tempfile,8+1+3)<0) break; //ESCキー
1638+ if(*tempfile==0) break; //ファイル名入力なし
1639+ }
1640+ else if(f==-1){
1641+ //新規ディレクトリ
1642+ setcursor(0,WIDTH_Y-1,COLOR_ERRORTEXT);
1643+ printstr("Input Dir Name: ");
1644+ setcursorcolor(COLOR_NORMALTEXT);
1645+ //ディレクトリ名入力
1646+ *tempfile=0;
1647+ if(lineinput(tempfile,8+1+3)<0) break; //ESCキー
1648+ if(FSmkdir(tempfile)){
1649+ setcursor(0,WIDTH_Y-1,COLOR_ERRORTEXT);
1650+ printstr("Cannot Make Directory ");
1651+ break;
1652+ }
1653+ }
1654+ else{
1655+ //ファイル名またはディレクトリ名をtempfileにコピー
1656+ ps=filenames[f];
1657+ pd=tempfile;
1658+ while(*ps) *pd++=*ps++;
1659+ *pd=0;
1660+ }
1661+ return f;
1662+ case VK_ESCAPE:
1663+ //ESCキー
1664+ return -3;
1665+ }
1666+ }
1667+}
1668+int getfilelist(int *p_num_dir){
1669+// カレントディレクトリでのディレクトリ、.BAS、.TXT、.INIファイル一覧を読み込む
1670+// *p_num_dir:ディレクトリ数を返す
1671+// filenames[]:ファイル名およびディレクトリ名一覧
1672+// 戻り値 ファイル+ディレクトリ数
1673+
1674+ unsigned char *ps,*pd;
1675+ int filenum;
1676+ SearchRec sr;
1677+ filenum=0;
1678+ //ディレクトリのサーチ
1679+ if(FindFirst("*.*",ATTR_DIRECTORY,&sr)==0){
1680+ do{
1681+ //filenames[]にディレクトリ名の一覧を読み込み
1682+ ps=sr.filename;
1683+ pd=filenames[filenum];
1684+ while(*ps!=0) *pd++=*ps++;
1685+ *pd=0;
1686+ filenum++;
1687+ }
1688+ while(!FindNext(&sr) && filenum<MAXFILENUM);
1689+ }
1690+ *p_num_dir=filenum;
1691+ if(filenum>=MAXFILENUM) return filenum;
1692+ //拡張子 BASファイルのサーチ
1693+ if(FindFirst("*.BAS",ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE,&sr)==0){
1694+ do{
1695+ //filenames[]にファイル名の一覧を読み込み
1696+ ps=sr.filename;
1697+ pd=filenames[filenum];
1698+ while(*ps!=0) *pd++=*ps++;
1699+ *pd=0;
1700+ filenum++;
1701+ }
1702+ while(!FindNext(&sr) && filenum<MAXFILENUM);
1703+ }
1704+ if(filenum>=MAXFILENUM) return filenum;
1705+ //拡張子 TXTファイルのサーチ
1706+ if(FindFirst("*.TXT",ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE,&sr)==0){
1707+ do{
1708+ //filenames[]にファイル名の一覧を読み込み
1709+ ps=sr.filename;
1710+ pd=filenames[filenum];
1711+ while(*ps!=0) *pd++=*ps++;
1712+ *pd=0;
1713+ filenum++;
1714+ }
1715+ while(!FindNext(&sr) && filenum<MAXFILENUM);
1716+ }
1717+ if(filenum>=MAXFILENUM) return filenum;
1718+ //拡張子 INIファイルのサーチ
1719+ if(FindFirst("*.INI",ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE,&sr)==0){
1720+ do{
1721+ //filenames[]にファイル名の一覧を読み込み
1722+ ps=sr.filename;
1723+ pd=filenames[filenum];
1724+ while(*ps!=0) *pd++=*ps++;
1725+ *pd=0;
1726+ filenum++;
1727+ }
1728+ while(!FindNext(&sr) && filenum<MAXFILENUM);
1729+ }
1730+ return filenum;
1731+}
1732+void save_as(int ow){
1733+// 現在のテキストバッファの内容をSDカードに保存
1734+// ow 0:名前を付けて保存  1:上書き保存
1735+// ファイル名はグローバル変数currentfile[]
1736+// ファイル名はキーボードから変更可能
1737+// 成功した場合currentfileを更新
1738+
1739+ int er;
1740+ int filenum,num_dir,f;
1741+ unsigned char *ps,*pd;
1742+
1743+ cls();
1744+ setcursor(0,0,COLOR_NORMALTEXT);
1745+ printstr("Save To SD Card\n");
1746+ if(currentfile[0]==0) ow=0; //ファイル名が設定されていない場合名前を付けて保存
1747+
1748+ //currentfileからtempfileにコピー
1749+ ps=currentfile;
1750+ pd=tempfile;
1751+ while(*ps!=0) *pd++=*ps++;
1752+ *pd=0;
1753+
1754+ //カレントディレクトリを変数cwdpathにコピー
1755+ while(1){
1756+ if(FSgetcwd(cwdpath,PATHNAMEMAX)) break;
1757+ setcursorcolor(COLOR_ERRORTEXT);
1758+ printstr("Cannot Get Current Dir\n");
1759+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
1760+ }
1761+ //現在のディレクトリのパスを表示
1762+ setcursorcolor(COLOR_NORMALTEXT);
1763+ printstr("Current Directory is\n");
1764+ printstr(cwdpath);
1765+ printchar('\n');
1766+ while(1){
1767+ if(ow==0){
1768+ printstr("Input File Name + [Enter]\n");
1769+ printstr("[ESC] Select File/Dir or Quit\n");
1770+ //ファイル名入力
1771+ if(lineinput(tempfile,8+1+3)<0){
1772+ //ESCキーが押された場合、ファイル選択、ディレクトリ変更画面または終了
1773+ while(1){
1774+ filenum=getfilelist(&num_dir); //ディレクトリ、ファイル名一覧を読み込み
1775+ f=select_dir_file(filenum,num_dir,"Save"); //ファイルの選択
1776+ cls();
1777+ if(f==-3){
1778+ //終了
1779+ FSchdir(cwdpath);//カレントディレクトリを元に戻す
1780+ return;
1781+ }
1782+ else if(f==-2){
1783+ //新規ファイル
1784+ if(overwritecheck(tempfile)==0) break;//上書きチェック
1785+ }
1786+ else if(f<num_dir){
1787+ //新規ディレクトリまたはディレクトリ変更
1788+ FSchdir(tempfile);//ディレクトリ変更して再度ファイル一覧へ
1789+ }
1790+ else break;
1791+ }
1792+ }
1793+ else{
1794+ if(*tempfile==0) continue; //NULL文字列の場合
1795+ if(overwritecheck(tempfile)) continue;
1796+ }
1797+ }
1798+ printstr("Writing...\n");
1799+ er=savetextfile(tempfile); //ファイル保存、er:エラーコード
1800+ if(er==0){
1801+ printstr("OK");
1802+ FSremove(TEMPFILENAME); //実行時に生成する一時ファイルを削除
1803+ //tempfileからcurrentfileにコピーして終了
1804+ ps=tempfile;
1805+ pd=currentfile;
1806+ while(*ps!=0) *pd++=*ps++;
1807+ *pd=0;
1808+ FSgetcwd(cwdpath,PATHNAMEMAX); //カレントパスを更新
1809+ edited=0; //編集済みフラグクリア
1810+ wait60thsec(60);//1秒待ち
1811+ return;
1812+ }
1813+ setcursorcolor(COLOR_ERRORTEXT);
1814+ if(er==ERR_CANTFILEOPEN) printstr("Bad File Name or File Error\n");
1815+ else printstr("Cannot Write\n");
1816+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
1817+ }
1818+}
1819+
1820+void newtext(void){
1821+// 新規テキスト作成
1822+ unsigned char vk;
1823+ if(edited && num){
1824+ //最終保存後に編集済みの場合、保存の確認
1825+ cls();
1826+ setcursorcolor(COLOR_NORMALTEXT);
1827+ printstr("Save Editing File?\n");
1828+ printstr("Save:[Enter] / Not Save:[ESC]\n");
1829+ while(1){
1830+ inputchar(); //1文字キー入力待ち
1831+ vk=vkey & 0xff;
1832+ if(vk==VK_RETURN || vk==VK_SEPARATOR){
1833+ save_as(0); //名前を付けて保存
1834+ break;
1835+ }
1836+ else if(vk==VK_ESCAPE) break;
1837+ }
1838+ }
1839+ inittextbuf(); //テキストバッファ初期化
1840+ cursor_top(); //カーソルをテキストバッファの先頭に設定
1841+ currentfile[0]=0; //作業中ファイル名クリア
1842+}
1843+
1844+void msra(void){
1845+// Make Self-Running Application (自己実行アプリケーションの作成)
1846+// 最初にソースファイルを名前を付けて保存
1847+// 次にBASICシステムのHEXファイルをソースファイル名の拡張子をHEXにした名前でコピー
1848+
1849+ int er;
1850+ unsigned char *ps,*pd;
1851+ cls();
1852+ setcursor(0,0,COLOR_NORMALTEXT);
1853+ printstr("Make Self-Running Application\n\n");
1854+ printstr("(Work on Root Directory)\n");
1855+
1856+ //カレントディレクトリを変数cwdpathにコピー
1857+ while(1){
1858+ if(FSgetcwd(cwdpath,PATHNAMEMAX)) break;
1859+ setcursorcolor(COLOR_ERRORTEXT);
1860+ printstr("Cannot Get Current Dir\n");
1861+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
1862+ }
1863+ while(1){
1864+ //カレントディレクトリをルートに変更
1865+ if(FSchdir((char *)ROOTDIR)==0) break;
1866+ setcursorcolor(COLOR_ERRORTEXT);
1867+ printstr("Cannot Change To Root Dir\n");
1868+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
1869+ }
1870+ //currentfileからtempfileにコピー
1871+ ps=currentfile;
1872+ pd=tempfile;
1873+ while(*ps!=0) *pd++=*ps++;
1874+ *pd=0;
1875+
1876+ while(1){
1877+ setcursorcolor(COLOR_NORMALTEXT);
1878+ printstr("Input File Name (xxx.BAS)\n");
1879+ if(lineinput(tempfile,8+1+3)<0){
1880+ //ESCキーが押された
1881+ FSchdir(cwdpath); //カレントディレクトリを元に戻す
1882+ return;
1883+ }
1884+ ps=tempfile;
1885+ while(*ps!='.' && *ps!=0) ps++;
1886+ if(ps+4>=tempfile+13 ||
1887+ *ps!='.' ||
1888+ (*(ps+1)!='b' && *(ps+1)!='B') ||
1889+ (*(ps+2)!='a' && *(ps+2)!='A') ||
1890+ (*(ps+3)!='s' && *(ps+3)!='S') ||
1891+ *(ps+4)!=0){
1892+ setcursorcolor(COLOR_ERRORTEXT);
1893+ printstr("File Name Must Be xxx.BAS\n");
1894+ continue;
1895+ }
1896+ if(overwritecheck(tempfile)) continue;
1897+ printstr("Writing BASIC File\n");
1898+ er=savetextfile(tempfile); //ファイル保存、er:エラーコード
1899+ if(er==0) break;
1900+ setcursorcolor(COLOR_ERRORTEXT);
1901+ if(er==ERR_CANTFILEOPEN) printstr("Bad File Name or File Error\n");
1902+ else printstr("Cannot Write\n");
1903+
1904+ //ファイルシステム再初期化、あきらめた場合はreturnする
1905+ if(filesystemretry()){
1906+ if(FSchdir(cwdpath)){
1907+ cwdpath[0]='\\';
1908+ cwdpath[1]=0;
1909+ }
1910+ return;
1911+ }
1912+ }
1913+ printstr("OK\n\n");
1914+ FSremove(TEMPFILENAME); //実行時に生成する一時ファイルを削除
1915+ //tempfileからcurrentfileにコピーして終了
1916+ ps=tempfile;
1917+ pd=currentfile;
1918+ while(*ps!=0) *pd++=*ps++;
1919+ *pd=0;
1920+ edited=0; //編集済みフラグクリア
1921+ // 拡張子をHEXにしてBASICシステムファイルをコピー
1922+ *(ps-3)='H';
1923+ *(ps-2)='E';
1924+ *(ps-1)='X';
1925+ if(overwritecheck(tempfile)) return;
1926+ printstr("Copying\n");
1927+ printstr(HEXFILE);
1928+ printstr(" To ");
1929+ printstr(tempfile);
1930+ printstr("\nWait For A While");
1931+ er=sdfilecopy(HEXFILE,tempfile);
1932+ if(FSchdir(cwdpath)){
1933+ cwdpath[0]='\\';
1934+ cwdpath[1]=0;
1935+ }
1936+ if(er==0){
1937+ printstr("\nDone");
1938+ wait60thsec(120);//2秒待ち
1939+ return;
1940+ }
1941+ setcursorcolor(COLOR_ERRORTEXT);
1942+ if(er==ERR_CANTFILEOPEN){
1943+ printstr(HEXFILE);
1944+ printstr(" Not Found\n");
1945+ }
1946+ else if(er==ERR_CANTWRITEFILE){
1947+ printstr("Write Error\n");
1948+ }
1949+ setcursorcolor(COLOR_NORMALTEXT);
1950+ printstr((unsigned char *)Message1);// Hit Any Key
1951+ inputchar(); //1文字入力待ち
1952+ return;
1953+}
1954+int fileload(void){
1955+// SDカードからファイルを選択して読み込み
1956+// currenfile[]にファイル名を記憶
1957+// 対象ファイル拡張子 BASおよびTXT
1958+// 戻り値 0:読み込みを行った -1:読み込みなし
1959+ int filenum,f,er;
1960+ unsigned char *ps,*pd;
1961+ unsigned char vk;
1962+ int num_dir;//ディレクトリ数
1963+
1964+ //ファイルの一覧をSDカードから読み出し
1965+ cls();
1966+ if(edited && num){
1967+ //最終保存後に編集済みの場合、保存の確認
1968+ setcursorcolor(COLOR_NORMALTEXT);
1969+ printstr("Save Program Before Load?\n");
1970+ printstr("Save:[Enter] / Not Save:[ESC]\n");
1971+ while(1){
1972+ inputchar(); //1文字キー入力待ち
1973+ vk=vkey & 0xff;
1974+ if(vk==VK_RETURN || vk==VK_SEPARATOR){
1975+ save_as(0); //名前を付けて保存
1976+ break;
1977+ }
1978+ else if(vk==VK_ESCAPE) break;
1979+ }
1980+ }
1981+ //カレントディレクトリを変数cwdpathにコピー
1982+ while(1){
1983+ if(FSgetcwd(cwdpath,PATHNAMEMAX)) break;
1984+ setcursorcolor(COLOR_ERRORTEXT);
1985+ printstr("Cannot Get Current Dir\n");
1986+ if(filesystemretry()) return -1; //ファイルシステム再初期化、あきらめた場合はreturnする
1987+ }
1988+ while(1){
1989+ filenum=getfilelist(&num_dir); //ディレクトリ、ファイル名一覧を読み込み
1990+ if(filenum==0){
1991+ setcursorcolor(COLOR_ERRORTEXT);
1992+ printstr(".BAS or .TXT File Not Found\n");
1993+ printstr((unsigned char *)Message1);// Hit Any Key
1994+ inputchar(); //1文字入力待ち
1995+ FSchdir(cwdpath);//カレントディレクトリを元に戻す
1996+ return -1;
1997+ }
1998+ //ファイルの選択
1999+ f=select_dir_file(filenum,num_dir,"Load");
2000+ if(f==-3){
2001+ //読み込まずに終了
2002+ FSchdir(cwdpath);//カレントディレクトリを元に戻す
2003+ return -1;
2004+ }
2005+ else if(f==-2){
2006+ //新規ファイルまたはファイル名を入力して読み込み
2007+ er=loadtextfile(tempfile); //テキストバッファにファイル読み込み
2008+ if(er==ERR_CANTFILEOPEN){
2009+ //ファイルが存在しない場合、新規テキスト
2010+ edited=0;
2011+ newtext();
2012+ }
2013+ else if(er==ERR_FILETOOBIG){
2014+ //ファイルサイズエラーの場合、選択画面に戻る
2015+ setcursor(0,WIDTH_Y-1,COLOR_ERRORTEXT);
2016+ printstr("File Too Big ");
2017+ wait60thsec(60);//1秒待ち
2018+ continue;
2019+ }
2020+ //currenfile[]にファイル名をコピー
2021+ ps=tempfile;
2022+ pd=currentfile;
2023+ while(*ps) *pd++=*ps++;
2024+ *pd=0;
2025+ FSgetcwd(cwdpath,PATHNAMEMAX);//cwdpathをカレントディレクトリのパスに変更
2026+ return 0;
2027+ }
2028+ else if(f<num_dir){
2029+ //新規ディレクトリまたはディレクトリ変更して、再度ファイル一覧画面へ
2030+ FSchdir(tempfile);
2031+ }
2032+ else{
2033+ er=loadtextfile(filenames[f]); //テキストバッファにファイル読み込み
2034+ if(er==0){
2035+ //cwdpath[]、currenfile[]にパス、ファイル名をコピーして終了
2036+ FSgetcwd(cwdpath,PATHNAMEMAX);
2037+ ps=filenames[f];
2038+ pd=currentfile;
2039+ while(*ps!=0) *pd++=*ps++;
2040+ *pd=0;
2041+ return 0;
2042+ }
2043+ setcursor(0,WIDTH_Y-1,COLOR_ERRORTEXT);
2044+ if(er==ERR_CANTFILEOPEN) printstr("Cannot Open File ");
2045+ else if(er=ERR_FILETOOBIG) printstr("File Too Big ");
2046+ wait60thsec(60);//1秒待ち
2047+ }
2048+ }
2049+}
2050+void changewidth(void){
2051+// 30文字モードと40文字モードの切り替え
2052+ if(twidth==WIDTH_X1) set_width(1);
2053+ else set_width(0);
2054+ cursor_top(); //カーソルをテキストバッファの先頭に設定
2055+ redraw(); //再描画
2056+}
2057+void run(int test){
2058+//KM-BASICコンパイル&実行
2059+// test 0:コンパイルと実行、0以外:コンパイルのみで終了
2060+ int er,er2;
2061+ FSFILE *fp;
2062+ unsigned int disptoppos,cursorpos;
2063+ unsigned char widthmode;
2064+ int i,edited1;
2065+ _tbuf *bp;
2066+ unsigned short ix;
2067+ unsigned char *p;
2068+
2069+ cls();
2070+ setcursor(0,0,COLOR_NORMALTEXT);
2071+ while(1){
2072+ //カレントディレクトリをルートに変更
2073+ if(FSchdir((char *)ROOTDIR)){
2074+ setcursorcolor(COLOR_ERRORTEXT);
2075+ printstr("Cannot Change To Root Dir\n");
2076+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
2077+ continue;
2078+ }
2079+ //ルートディレクトリのパス名保存ファイルに実行時パスを保存
2080+ fp=FSfopen(WORKDIRFILE,"w");
2081+ if(fp==NULL){
2082+ setcursorcolor(COLOR_ERRORTEXT);
2083+ printstr("Cannot Open Work Dir File\n");
2084+ if(filesystemretry()){
2085+ //ファイルシステム再初期化、あきらめた場合はカレントディレクトリを戻しreturnする
2086+ FSchdir(cwdpath);
2087+ return;
2088+ }
2089+ continue;
2090+ }
2091+ for(p=cwdpath;*p;p++) ;
2092+ er=FSfwrite(cwdpath,1,p-cwdpath+1,fp);
2093+ FSfclose(fp);
2094+ if(er!=p-cwdpath+1){
2095+ FSremove(WORKDIRFILE);
2096+ setcursorcolor(COLOR_ERRORTEXT);
2097+ printstr("Cannot Write Work Dir File\n");
2098+ if(filesystemretry()){
2099+ //ファイルシステム再初期化、あきらめた場合はカレントディレクトリを戻しreturnする
2100+ FSchdir(cwdpath);
2101+ return;
2102+ }
2103+ continue;
2104+ }
2105+ break;
2106+ }
2107+ while(1){
2108+ //カレントディレクトリを元に戻す
2109+ if(FSchdir(cwdpath)){
2110+ setcursorcolor(COLOR_ERRORTEXT);
2111+ printstr("Cannot Change To CWD\n");
2112+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
2113+ continue;
2114+ }
2115+ //実行用引渡しファイルに保存
2116+ if(savetextfile(TEMPFILENAME)){
2117+ setcursorcolor(COLOR_ERRORTEXT);
2118+ printstr("Cannot Write To SD Card\n");
2119+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
2120+ continue;
2121+ }
2122+ break;
2123+ }
2124+
2125+ //カーソル位置、画面表示位置、画面モードの保存
2126+ disptoppos=bpixtopos(disptopbp,disptopix);
2127+ cursorpos=bpixtopos(cursorbp,cursorix);
2128+ widthmode=twidth;
2129+ edited1=edited; //編集済みフラグの一時退避
2130+ set_width(0);//30文字モードに設定
2131+
2132+ // Enable Break key
2133+ g_disable_break=0;
2134+ //KM-BASIC実行
2135+ er2=runbasic(TEMPFILENAME,test);
2136+
2137+ stopPCG();//システムフォントに戻す
2138+ setcursorcolor(COLOR_NORMALTEXT);
2139+ printchar('\n');
2140+ printstr((unsigned char *)Message1);// Hit Any Key
2141+ do ps2readkey(); //キーバッファが空になるまで読み出し
2142+ while(vkey!=0);
2143+ ps2mode(); //キーボード有効化
2144+ inputchar(); //1文字入力待ち
2145+ init_composite(); //パレット初期化のため画面初期化
2146+ //画面モードを戻す
2147+ if(widthmode==WIDTH_X1) set_width(0);
2148+ else set_width(1);
2149+
2150+ FSgetcwd(cwdpath,PATHNAMEMAX);//カレントディレクトリパス変数を戻す
2151+ while(1){
2152+ //カレントディレクトリをルートに変更
2153+ if(FSchdir((char *)ROOTDIR)){
2154+ setcursorcolor(COLOR_ERRORTEXT);
2155+ printstr("Cannot Change To Root Dir\n");
2156+ filesystemretry(); //ファイルシステム再初期化
2157+ continue;
2158+ }
2159+ //ルートディレクトリのパス名保存ファイルからパス名を読み出し
2160+ fp=FSfopen(WORKDIRFILE,"r");
2161+ if(fp==NULL){
2162+ setcursorcolor(COLOR_ERRORTEXT);
2163+ printstr("Cannot Open Work Dir File\n");
2164+ filesystemretry(); //ファイルシステム再初期化
2165+ continue;
2166+ }
2167+ er=FSfread(cwdpath,1,PATHNAMEMAX,fp);
2168+ FSfclose(fp);
2169+ if(er<=0){
2170+ setcursorcolor(COLOR_ERRORTEXT);
2171+ printstr("Cannot Read Work Dir File\n");
2172+ filesystemretry(); //ファイルシステム再初期化
2173+ continue;
2174+ }
2175+ FSremove(WORKDIRFILE); //パス名保存ファイル削除
2176+ break;
2177+ }
2178+ while(1){
2179+ //カレントディレクトリを元に戻す
2180+ if(FSchdir(cwdpath)){
2181+ setcursorcolor(COLOR_ERRORTEXT);
2182+ printstr("Cannot Change To CWD\n");
2183+ filesystemretry(); //ファイルシステム再初期化
2184+ continue;
2185+ }
2186+ //実行用引渡しファイルから元に戻す
2187+ if(loadtextfile(TEMPFILENAME)){
2188+ setcursorcolor(COLOR_ERRORTEXT);
2189+ printstr("Cannot Load From SD Card\n");
2190+ filesystemretry(); //ファイルシステム再初期化
2191+ continue;
2192+ }
2193+ break;
2194+ }
2195+ if(er2<=0){
2196+ //正常終了またはファイルエラーまたはリンクエラーの場合
2197+ //カーソルを元の位置に設定
2198+ disptopbp=postobpix(disptoppos,&disptopix);
2199+ cursorbp=postobpix(cursorpos,&cursorix);
2200+ }
2201+ else{
2202+ //コンパイルエラーの場合
2203+ //カーソルをエラー行で画面トップに移動
2204+ disptopbp=linetobpix(er2,&disptopix);
2205+ cursorbp=disptopbp;
2206+ cursorix=disptopix;
2207+ cx=0;
2208+ cx2=0;
2209+ cy=0;
2210+ line_no=er2;
2211+ //中央になるようスクロール
2212+ for(i=0;i<EDITWIDTHY/2;i++){
2213+ //画面行数半分カーソルを上に移動
2214+ bp=disptopbp;
2215+ ix=disptopix;
2216+ cursor_up();
2217+ if(bp==disptopbp && ix==disptopix) break; //最上行で移動できなかった場合抜ける
2218+ }
2219+ for(;i>0;i--) cursor_down(); //元のY座標までカーソルを下に移動
2220+ }
2221+ cursorbp1=NULL; //範囲選択モード解除
2222+ clipsize=0; //クリップボードクリア
2223+ edited=edited1;
2224+ FSremove(TEMPFILENAME);
2225+}
2226+void displaybottomline(void){
2227+//エディター画面最下行の表示
2228+ unsigned char *p;
2229+ unsigned char c;
2230+ int t;
2231+ p=cursor; //カーソル位置の退避
2232+ c=cursorcolor;
2233+ setcursor(0,WIDTH_Y-1,COLOR_BOTTOMLINE);
2234+ if(shiftkeys() & CHK_SHIFT){
2235+ printstr("NEW |MSRA|WDTH|TEST|");
2236+ setcursorcolor(COLOR_ERRORTEXT);
2237+ t=TBUFMAXSIZE-num;
2238+ if(t==0) t=1;
2239+ while(t<10000){
2240+ printchar(' ');
2241+ t*=10;
2242+ }
2243+ printstr("LEFT:");
2244+ printnum(TBUFMAXSIZE-num);
2245+ }
2246+ else{
2247+ printstr("LOAD|SAVE| |RUN |");
2248+ setcursorcolor(COLOR_ERRORTEXT);
2249+ t=line_no;
2250+ if(t==0) t=1;
2251+ while(t<10000){
2252+ printchar(' ');
2253+ t*=10;
2254+ }
2255+ printstr("LINE:");
2256+ printnum(line_no);
2257+ }
2258+ cursor=p; //カーソル位置戻し
2259+ cursorcolor=c;
2260+}
2261+void normal_code_process(unsigned char k){
2262+// 通常文字入力処理
2263+// k:入力された文字コード
2264+ int i;
2265+
2266+ edited=1; //編集済みフラグ
2267+ if(insertmode || k=='\n' || cursorbp1!=NULL){ //挿入モード
2268+ if(cursorbp1!=NULL) deletearea();//選択範囲を削除
2269+ i=insertchar(cursorbp,cursorix,k,0);//テキストバッファに1文字挿入
2270+ if(i>0){
2271+ //バッファ空きがあるのに挿入失敗の場合
2272+ gabagecollect2(); //全体ガベージコレクション
2273+ i=insertchar(cursorbp,cursorix,k,0);//テキストバッファに1文字挿入
2274+ }
2275+ if(i==0) cursor_right();//画面上、バッファ上のカーソル位置を1つ後ろに移動
2276+ }
2277+ else{ //上書きモード
2278+ i=overwritechar(cursorbp,cursorix,k,0);//テキストバッファに1文字上書き
2279+ if(i>0){
2280+ //バッファ空きがあるのに上書き(挿入)失敗の場合
2281+ //(行末やバッファ最後尾では挿入)
2282+ gabagecollect2(); //全体ガベージコレクション
2283+ i=overwritechar(cursorbp,cursorix,k,0);//テキストバッファに1文字上書き
2284+ }
2285+ if(i==0) cursor_right();//画面上、バッファ上のカーソル位置を1つ後ろに移動
2286+ }
2287+}
2288+void control_code_process(unsigned char k,unsigned char sh){
2289+// 制御文字入力処理
2290+// k:制御文字の仮想キーコード
2291+// sh:シフト関連キー状態
2292+
2293+ save_cursor(); //カーソル関連変数退避(カーソル移動できなかった場合戻すため)
2294+ switch(k){
2295+ case VK_LEFT:
2296+ case VK_NUMPAD4:
2297+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2298+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD4) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2299+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2300+ if(sh & CHK_CTRL){
2301+ //CTRL+左矢印でHome
2302+ cursor_home();
2303+ break;
2304+ }
2305+ cursor_left();
2306+ if(cursorbp1!=NULL && (disptopbp!=disptopbp_t || disptopix!=disptopix_t)){
2307+ //範囲選択モードで画面スクロールがあった場合
2308+ if(cy1<EDITWIDTHY-1) cy1++; //範囲スタート位置もスクロール
2309+ else restore_cursor(); //カーソル位置を戻す(画面範囲外の範囲選択禁止)
2310+ }
2311+ break;
2312+ case VK_RIGHT:
2313+ case VK_NUMPAD6:
2314+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2315+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD6) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2316+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2317+ if(sh & CHK_CTRL){
2318+ //CTRL+右矢印でEnd
2319+ cursor_end();
2320+ break;
2321+ }
2322+ cursor_right();
2323+ if(cursorbp1!=NULL && (disptopbp!=disptopbp_t || disptopix!=disptopix_t)){
2324+ //範囲選択モードで画面スクロールがあった場合
2325+ if(cy1>0) cy1--; //範囲スタート位置もスクロール
2326+ else restore_cursor(); //カーソル位置を戻す(画面範囲外の範囲選択禁止)
2327+ }
2328+ break;
2329+ case VK_UP:
2330+ case VK_NUMPAD8:
2331+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2332+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD8) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2333+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2334+ cursor_up();
2335+ if(cursorbp1!=NULL && (disptopbp!=disptopbp_t || disptopix!=disptopix_t)){
2336+ //範囲選択モードで画面スクロールがあった場合
2337+ if(cy1<EDITWIDTHY-1) cy1++; //範囲スタート位置もスクロール
2338+ else restore_cursor(); //カーソル位置を戻す(画面範囲外の範囲選択禁止)
2339+ }
2340+ break;
2341+ case VK_DOWN:
2342+ case VK_NUMPAD2:
2343+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2344+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD2) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2345+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2346+ cursor_down();
2347+ if(cursorbp1!=NULL && (disptopbp!=disptopbp_t || disptopix!=disptopix_t)){
2348+ //範囲選択モードで画面スクロールがあった場合
2349+ if(cy1>0) cy1--; //範囲スタート位置もスクロール
2350+ else restore_cursor(); //カーソル位置を戻す(画面範囲外の範囲選択禁止)
2351+ }
2352+ break;
2353+ case VK_HOME:
2354+ case VK_NUMPAD7:
2355+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2356+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD7) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2357+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2358+ cursor_home();
2359+ break;
2360+ case VK_END:
2361+ case VK_NUMPAD1:
2362+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2363+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD1) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2364+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2365+ cursor_end();
2366+ break;
2367+ case VK_PRIOR: // PageUpキー
2368+ case VK_NUMPAD9:
2369+ //シフト+PageUpは無効(NumLock+シフト+「9」除く)
2370+ if((sh & CHK_SHIFT) && ((k!=VK_NUMPAD9) || ((sh & CHK_NUMLK)==0))) break;
2371+ cursorbp1=NULL; //範囲選択モード解除
2372+ cursor_pageup();
2373+ break;
2374+ case VK_NEXT: // PageDownキー
2375+ case VK_NUMPAD3:
2376+ //シフト+PageDownは無効(NumLock+シフト+「3」除く)
2377+ if((sh & CHK_SHIFT) && ((k!=VK_NUMPAD3) || ((sh & CHK_NUMLK)==0))) break;
2378+ cursorbp1=NULL; //範囲選択モード解除
2379+ cursor_pagedown();
2380+ break;
2381+ case VK_DELETE: //Deleteキー
2382+ case VK_DECIMAL: //テンキーの「.」
2383+ edited=1; //編集済みフラグ
2384+ if(cursorbp1!=NULL) deletearea();//選択範囲を削除
2385+ else deletechar(cursorbp,cursorix,0);
2386+ break;
2387+ case VK_BACK: //BackSpaceキー
2388+ edited=1; //編集済みフラグ
2389+ if(cursorbp1!=NULL){
2390+ deletearea();//選択範囲を削除
2391+ break;
2392+ }
2393+ if(cursorix==0 && cursorbp->prev==NULL) break; //バッファ先頭では無視
2394+ cursor_left();
2395+ deletechar(cursorbp,cursorix,-1);
2396+ break;
2397+ case VK_INSERT:
2398+ case VK_NUMPAD0:
2399+ insertmode^=1; //挿入モード、上書きモードを切り替え
2400+ break;
2401+ case 'C':
2402+ //CTRL+C、クリップボードにコピー
2403+ if(cursorbp1!=NULL && (sh & CHK_CTRL)) clipcopy();
2404+ break;
2405+ case 'X':
2406+ //CTRL+X、クリップボードに切り取り
2407+ if(cursorbp1!=NULL && (sh & CHK_CTRL)){
2408+ clipcopy();
2409+ deletearea(); //選択範囲の削除
2410+ edited=1; //編集済みフラグ
2411+ }
2412+ break;
2413+ case 'V':
2414+ //CTRL+V、クリップボードから貼り付け
2415+ if((sh & CHK_CTRL)==0) break;
2416+ if(clipsize==0) break;
2417+ edited=1; //編集済みフラグ
2418+ if(cursorbp1!=NULL){
2419+ //範囲選択している時は削除してから貼り付け
2420+ if(num-countarea()+clipsize<=TBUFMAXSIZE){ //バッファ空き容量チェック
2421+ deletearea();//選択範囲を削除
2422+ clippaste();//クリップボード貼り付け
2423+ }
2424+ }
2425+ else{
2426+ if(num+clipsize<=TBUFMAXSIZE){ //バッファ空き容量チェック
2427+ clippaste();//クリップボード貼り付け
2428+ }
2429+ }
2430+ break;
2431+ case 'S':
2432+ //CTRL+S、SDカードに保存
2433+ if(num==0) break;
2434+ if(sh & CHK_CTRL) save_as(1); //上書き保存
2435+ break;
2436+ case 'O':
2437+ //CTRL+O、ファイル読み込み
2438+ if(sh & CHK_CTRL){
2439+ if(fileload()==0){ //ファイルを選択して読み込み
2440+ //読み込みを行った場合、カーソル位置を先頭に
2441+ cursor_top();
2442+ }
2443+ }
2444+ break;
2445+ case 'N':
2446+ //CTRL+N、新規作成
2447+ if(sh & CHK_CTRL) newtext();
2448+ break;
2449+ case VK_F1: //F1キー
2450+ if(sh & CHK_SHIFT) newtext();//SHIFT+F1キー 新規作成
2451+ else{
2452+ //ファイル読み込み
2453+ if(fileload()==0){ //ファイルを選択して読み込み
2454+ //読み込みを行った場合、カーソル位置を先頭に
2455+ cursor_top();
2456+ }
2457+ }
2458+ break;
2459+ case VK_F2: //F2キー
2460+ if(num==0) break;
2461+ if(sh & CHK_SHIFT) msra(); //create direct running file
2462+ else save_as(0); //ファイル名を付けて保存
2463+ break;
2464+ case VK_F3: //F3キー
2465+ if(sh & CHK_SHIFT) changewidth(); //30文字モード、40文字モード切り替え
2466+ break;
2467+ case VK_F4: //F4キー
2468+ if(num==0) break;
2469+ if(sh & CHK_SHIFT) run(1); //コンパイルテスト
2470+ else run(0); //コンパイル&実行
2471+ break;
2472+ case 'Z':
2473+ //CTRL+Z、アンドゥ
2474+ if(sh & CHK_CTRL) undoexec();
2475+ break;
2476+ }
2477+}
2478+void texteditor(void){
2479+//テキストエディター本体
2480+ unsigned char k1,k2,sh;
2481+ FSFILE *fp;
2482+
2483+ editormallocp=RAM;
2484+ TextBuffer=(_tbuf *)editormalloc(sizeof(_tbuf)*TBUFMAXLINE);
2485+ clipboard=editormalloc(WIDTH_X2*EDITWIDTHY);
2486+ filebuf=editormalloc(FILEBUFSIZE);
2487+ cwdpath=editormalloc(PATHNAMEMAX);
2488+ filenames=(unsigned char (*)[])editormalloc(MAXFILENUM*13);
2489+ undobuf=editormalloc(UNDOBUFSIZE);
2490+
2491+// TextBuffer=(_tbuf *)RAM;
2492+// clipboard=(unsigned char *)TextBuffer+sizeof(_tbuf)*TBUFMAXLINE;
2493+// filebuf=clipboard+WIDTH_X2*EDITWIDTHY;
2494+// cwdpath=filebuf+FILEBUFSIZE;
2495+// filenames=(unsigned char (*)[])(cwdpath+PATHNAMEMAX);
2496+// undobuf=(unsigned char *)filenames+MAXFILENUM*13;
2497+
2498+ inittextbuf(); //テキストバッファ初期化
2499+ currentfile[0]=0; //作業中ファイル名クリア
2500+ cwdpath[0]='\\'; //カレントディレクトリをルートに設定
2501+ cwdpath[1]=0;
2502+
2503+ //実行時生成一時ファイルがあった場合は読み込む
2504+ fp=FSfopen(WORKDIRFILE,"r");
2505+ if(fp!=NULL){
2506+ FSfread(cwdpath,1,PATHNAMEMAX,fp);
2507+ FSfclose(fp);
2508+ FSchdir(cwdpath);
2509+ if(loadtextfile(TEMPFILENAME)==0){
2510+ edited=1;
2511+ setcursorcolor(COLOR_ERRORTEXT);
2512+ printstr("Temporary File Loaded\n");
2513+ printstr("Current Directory is\n");
2514+ setcursorcolor(COLOR_DIR);
2515+ printstr(cwdpath);
2516+ setcursorcolor(COLOR_ERRORTEXT);
2517+ printstr("\nSave To SD Card If Necessary\n");
2518+ setcursorcolor(COLOR_NORMALTEXT);
2519+ printstr((unsigned char *)Message1); //Hit Any Key
2520+ inputchar(); //1文字入力待ち
2521+ }
2522+ else{
2523+ cwdpath[0]='\\'; //カレントディレクトリをルートに設定
2524+ cwdpath[1]=0;
2525+ }
2526+ }
2527+ cursor_top(); //カーソルをテキストバッファの先頭に移動
2528+ insertmode=1; //0:上書き、1:挿入
2529+ clipsize=0; //クリップボードクリア
2530+ blinktimer=0; //カーソル点滅タイマークリア
2531+
2532+ while(1){
2533+ redraw();//画面再描画
2534+ setcursor(cx,cy,COLOR_NORMALTEXT);
2535+ getcursorchar(); //カーソル位置の文字を退避(カーソル点滅用)
2536+ while(1){
2537+ //キー入力待ちループ
2538+ wait60thsec(1); //60分の1秒ウェイト
2539+ blinkcursorchar(); //カーソル点滅させる
2540+ k1=ps2readkey(); //キーバッファから読み込み、k1:通常文字入力の場合ASCIIコード
2541+ displaybottomline(); //画面最下行にファンクションキー機能表示
2542+ if(vkey) break; //キーが押された場合ループから抜ける
2543+ if(cursorbp1==NULL) gabagecollect1(); //1バイトガベージコレクション(範囲選択時はしない)
2544+ }
2545+ resetcursorchar(); //カーソルを元の文字表示に戻す
2546+ k2=(unsigned char)vkey; //k2:仮想キーコード
2547+ sh=vkey>>8; //sh:シフト関連キー状態
2548+ if(k2==VK_RETURN || k2==VK_SEPARATOR) k1='\n'; //Enter押下は単純に改行文字を入力とする
2549+ if(k1) normal_code_process(k1); //通常文字が入力された場合
2550+ else control_code_process(k2,sh); //制御文字が入力された場合
2551+ if(cursorbp1!=NULL && cx==cx1 && cy==cy1) cursorbp1=NULL;//選択範囲の開始と終了が重なったら範囲選択モード解除
2552+ }
2553+}
--- /dev/null
+++ b/mips/zoea/editor.h
@@ -0,0 +1,40 @@
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 26 //エディタ画面縦幅
13+#define COLOR_NORMALTEXT 7 //通常テキスト色
14+#define COLOR_ERRORTEXT 4 //エラーメッセージテキスト色
15+#define COLOR_AREASELECTTEXT 4 //範囲選択テキスト色
16+#define COLOR_BOTTOMLINE 5 //画面最下行の色
17+#define COLOR_DIR 6 //ディレクトリ名表示の色
18+#define FILEBUFSIZE 256 //ファイルアクセス用バッファサイズ
19+#define MAXFILENUM 200 //利用可能ファイル最大数
20+#define PATHNAMEMAX 128 //ワーキングディレクトリパス名の最大値
21+#define UNDOBUFSIZE 2048 //アンドゥ用バッファサイズ
22+
23+#define ERR_FILETOOBIG -1
24+#define ERR_CANTFILEOPEN -2
25+#define ERR_CANTWRITEFILE -3
26+
27+#define TEMPFILENAME "~TEMP.BAS" //実行時ソース保存ファイル名
28+#define WORKDIRFILE "~WORKDIR.TMP" //実行時パス保存ファイル名
29+
30+#define UNDO_INSERT 1
31+#define UNDO_OVERWRITE 2
32+#define UNDO_DELETE 3
33+#define UNDO_BACKSPACE 4
34+#define UNDO_CONTINS 5
35+#define UNDO_CONTDEL 6
36+
37+void texteditor(void); //テキストエディタ本体
38+int runbasic(char *s,int test); //コンパイルして実行
39+extern unsigned char tempfile[13];
40+void wait60thsec(unsigned short n);
--- /dev/null
+++ b/mips/zoea/error.c
@@ -0,0 +1,160 @@
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 "compiler.h"
9+
10+const char* g_err_str[]={
11+ "Syntax error",
12+ "Not enough binary space",
13+ "Not enough memory",
14+ "Divided by zero",
15+ "Not yet implemented",
16+ "Label or line number not found: ",
17+ "Label too long or too short",
18+ "String too complexed",
19+ "Data not found",
20+ "Unknown error:",
21+ "Music syntax error:'",
22+ " found more than twice",
23+ "Break",
24+ "Unexpected NEXT or RETURN statement",
25+ "Cannot assign temporary block",
26+ "GOSUB fuction cannot be used after string-handling",
27+ "Invalid BREAK statement in line ",
28+ "Invalid ELSE/IF statement in line ",
29+ "Invalid parameter(s)",
30+ "File error",
31+ "Invalid variable name",
32+};
33+
34+char* resolve_label(int s6){
35+ static char str[7];
36+ int i,j;
37+ if (s6<65536) {
38+ // Line number
39+ for(i=0;i<5;i++){
40+ str[5-i]='0'+rem10_32(s6);
41+ s6=div10_32(s6);
42+ }
43+ str[6]=0x00;
44+ for(j=1;j<5;j++){
45+ if (str[j]!='0') break;
46+ }
47+ return (char*)(str+j);
48+ } else {
49+ // Label
50+ s6-=65536;
51+ str[6]=0x00;
52+ for(i=5;0<=i;i--){
53+ if (s6<36) {
54+ // First character must be A-Z, corresponding to 1-26 but not 10-35.
55+ // See get_label() for the detail.
56+ str[i]=s6-1+'A';
57+ break;
58+ } else {
59+ // From second, 0-9 corresponds to 0-9 and A-Z corresponds to 10-35.
60+ str[i]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[rem36_32(s6)];
61+ s6=div36_32(s6);
62+ }
63+ }
64+ return (char*)(str+i);
65+ }
66+}
67+
68+void pre_end_addr(int s6){
69+ int i,j;
70+ char str[7];
71+ if (s6<0) s6=s6&0x7fffffff;
72+ g_label=s6;
73+ if (s6<65536) {
74+ // Line number
75+ printstr("\nIn line ");
76+ } else {
77+ // Label
78+ printstr("\nAfter label ");
79+ }
80+ printstr(resolve_label(s6));
81+ asm volatile("la $v0,%0"::"i"(&g_end_addr));
82+ asm volatile("lw $v0,0($v0)");
83+ asm volatile("nop");
84+ asm volatile("jr $v0");
85+}
86+
87+#define end_exec() \
88+ asm volatile("addu $a0,$s6,$zero");\
89+ asm volatile("j pre_end_addr")
90+
91+void err_break(void){
92+ printstr(ERR_BREAK);
93+ end_exec();
94+}
95+
96+void err_data_not_found(void){
97+ printstr(ERR_DATA_NF);
98+ end_exec();
99+}
100+
101+void err_label_not_found(void){
102+ printstr(ERR_LABEL_NF);
103+ printstr(resolve_label(g_label));
104+ printstr("\n");
105+ end_exec();
106+}
107+
108+void err_div_zero(void){
109+ printstr(ERR_DIV_0);
110+ end_exec();
111+}
112+
113+void err_no_mem(void){
114+ printstr(ERR_NE_MEMORY);
115+ end_exec();
116+}
117+
118+void err_str_complex(void){
119+ printstr(ERR_STR_COMPLEX);
120+ end_exec();
121+}
122+
123+void err_unknown(void){
124+ asm volatile("la $v0,%0"::"i"(&g_temp));
125+ asm volatile("sw $ra,0($v0)");
126+ printstr(ERR_UNKNOWN);
127+ printhex32(g_temp);
128+ end_exec();
129+}
130+
131+void err_music(char* str){
132+ printstr(ERR_MUSIC);
133+ printstr(str);
134+ printstr("'\n");
135+ // Restore s6 from g_s6
136+ asm volatile("la $s6,%0"::"i"(&g_s6));
137+ asm volatile("lw $s6,0($s6)");
138+ end_exec();
139+}
140+
141+void err_unexp_next(void){
142+ printstr(ERR_UNEXP_NEXT);
143+ end_exec();
144+}
145+
146+void err_no_block(void){
147+ printstr(ERR_NO_BLOCK);
148+ end_exec();
149+}
150+
151+void err_invalid_param(void){
152+ printstr(ERR_INVALID_PARAM);
153+ end_exec();
154+}
155+
156+void err_file(void){
157+ printstr(ERR_FILE);
158+ end_exec();
159+}
160+
--- /dev/null
+++ b/mips/zoea/exception.c
@@ -0,0 +1,160 @@
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 "main.h"
11+#include "compiler.h"
12+
13+/*
14+ Enable following line if memory dump is needed when exception occurs.
15+*/
16+
17+//#define DUMPFILE "~~MEMORY.DMP"
18+
19+#ifdef DUMPFILE
20+void dumpMemory(){
21+ unsigned int i;
22+ FSFILE *fp;
23+ printstr("\n"DUMPFILE" ");
24+ if(FSInit()==FALSE){
25+ printstr("cannot be created.\n");
26+ return;
27+ }
28+ fp=FSfopen(DUMPFILE,"w");
29+ if(fp==NULL) {
30+ printstr("not saved.\n");
31+ return;
32+ }
33+ for(i=0;i<PERSISTENT_RAM_SIZE;i+=512){
34+ if (FSfwrite(&RAM[i],1,512,fp)<512) break;
35+ }
36+ FSfclose(fp);
37+ printstr("saved.\n");
38+}
39+#else
40+void dumpMemory(){}
41+#endif //ifdef DUMPFILE
42+
43+void _general_exception_handler (void){
44+ int i;
45+ // $v1 is g_ex_data
46+ asm volatile("la $v1,%0"::"i"(&g_ex_data[0]));
47+ // Prepare proper stack area before SoftReset
48+ asm volatile("addiu $sp,$v1,0xfff0");
49+ // g_ex_data[2]=$s6
50+ asm volatile("sw $s6,8($v1)");
51+ // g_ex_data[3]=Cause
52+ asm volatile("mfc0 $v0,$13");
53+ asm volatile("sw $v0,12($v1)");
54+ // g_ex_data[4]=EPC
55+ asm volatile("mfc0 $v0,$14");
56+ asm volatile("sw $v0,16($v1)");
57+ // Exception occured
58+ g_ex_data[0]=1;
59+ // g_s6
60+ g_ex_data[1]=g_s6;
61+ // Clear 2 MLB bits of EPC
62+ g_ex_data[4]&=0xfffffffc;
63+ // If EPC is within RAM, store data in exception area.
64+ if ((int)(&RAM[0])<=g_ex_data[4] && g_ex_data[4] <(int)(&RAM[RAMSIZE])) {
65+ // g_ex_data[5] - g_ex_data[12]: assembly
66+ for(i=-3;i<=3;i++){
67+ g_ex_data[i+8]=((int*)g_ex_data[4])[i];
68+ }
69+ }
70+ // Wait until all buttons are released and reset MachiKania.
71+ #ifdef __DEBUG
72+ asm volatile("j 0xBFC00000");
73+ #else
74+ buttonmode();
75+ for(i=0;i<100000;i++){
76+ if((KEYPORT&(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE))
77+ !=(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE)) i=0;
78+ }
79+ asm volatile("j SoftReset");
80+ #endif
81+}
82+
83+void blue_screen(void){
84+ int i,j,s6,s6g;
85+ unsigned int* opos;
86+ if (RCONbits.POR || RCONbits.EXTR) {
87+ // After power on or reset. Reset flags and return.
88+ RCONbits.POR=0;
89+ RCONbits.EXTR=0;
90+ for(i=0;i<RAMSIZE;i++){
91+ // Reset all RAM area including g_ex_data[]
92+ RAM[i]=0;
93+ }
94+ return;
95+ } else if (g_ex_data[0]==0) {
96+ // No exception found.
97+ return;
98+ }
99+ // Exception occured before SoftReset().
100+ // Prepare data
101+ s6=g_ex_data[2];
102+ s6g=g_ex_data[1];
103+ s6=s6&0x7fffffff;
104+ s6g=s6g&0x7fffffff;
105+ opos=(int*)g_ex_data[4];
106+ //set_bgcolor(255,0,0);
107+ printstr("STOP");
108+ printstr("\nException at ");
109+ printhex32(g_ex_data[4]);
110+ printstr("\n Cause: ");
111+ printhex32(g_ex_data[3]);
112+ printstr("\n ");
113+ switch((g_ex_data[3]>>2)&0x1f){
114+ case 0: printstr("(Interrupt)"); break;
115+ case 1: printstr("(TLB modification)"); break;
116+ case 2: printstr("(TLB load/fetch)"); break;
117+ case 3: printstr("(TLB store)"); break;
118+ case 4: printstr("(Address load/fetch error )"); break;
119+ case 5: printstr("(Address store error)"); break;
120+ case 6: printstr("(Bus fetch error)"); break;
121+ case 7: printstr("(Bus load/store error)"); break;
122+ case 8: printstr("(Syscall)"); break;
123+ case 9: printstr("(Breakpoint)"); break;
124+ case 10: printstr("(Reserved instruction)"); break;
125+ case 11: printstr("(Coprocessor Unusable)"); break;
126+ case 12: printstr("(Integer Overflow)"); break;
127+ case 13: printstr("(Trap)"); break;
128+ case 23: printstr("(Reference to Watch address)"); break;
129+ case 24: printstr("(Machine check)"); break;
130+ default: printstr("(Unknown)"); break;
131+ }
132+ printstr("\n s6: ");
133+ printstr(resolve_label(s6));
134+ printstr("\n g_s6: ");
135+ printstr(resolve_label(s6g));
136+ printstr("\n");
137+ printstr("Reset MachiKania to contine.\n\n");
138+ // Show code where the exception happened.
139+ for(i=-3;i<=3;i++){
140+ printstr("\n ");
141+ printhex32((unsigned int)&opos[i]);
142+ printstr(" ");
143+ if ((unsigned int)&RAM[0]<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<(unsigned int)&RAM[RAMSIZE]) {
144+ // Exception in RAM[RAMSIZE] area
145+ printhex32(g_ex_data[i+8]);
146+ } else if ( 0xA0000000<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<0xA0000000+PIC32MX_RAMSIZE
147+ || 0x9D000000<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<=0x9D000000+PIC32MX_FLASHSIZE) {
148+ // Exception in outside RAM[RAMSIZE] or flash area
149+ printhex32(opos[i]);
150+ } else {
151+ printstr("********");
152+ }
153+ }
154+ printstr("\n");
155+
156+#ifndef __DEBUG
157+ dumpMemory();
158+#endif
159+ while(1) asm("wait");
160+}
--- /dev/null
+++ b/mips/zoea/file.c
@@ -0,0 +1,99 @@
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 "compiler.h"
11+
12+static FSFILE* g_fhandle;
13+static char* g_fbuff;
14+static int g_size;
15+
16+char* init_file(char* buff,char* appname){
17+ // Open file
18+ g_fhandle=FSfopen(appname,"r");
19+ if (!g_fhandle) {
20+ return ERR_UNKNOWN;
21+ }
22+ g_fbuff=buff;
23+ g_line=0;
24+ g_fileline=0;
25+ return 0;
26+}
27+
28+void close_file(){
29+ FSfclose(g_fhandle);
30+}
31+
32+void read_file(int blocklen){
33+ int i;
34+ static char in_string, escape;
35+ // blocklen is either 512 or 256.
36+ if (blocklen==512) {
37+ // This is first read. Initialize parameter(s).
38+ in_string=0;
39+ escape=0;
40+ } else if (g_size<512) {
41+ // Already reached the end of file.
42+ return;
43+ } else {
44+ // Shift buffer and source position 256 bytes.
45+ for(i=0;i<256;i++) g_fbuff[i]=g_fbuff[i+256];
46+ g_srcpos-=256;
47+ }
48+ // Read 512 or 256 bytes from SD card.
49+ g_size=512-blocklen+FSfread((void*)&g_fbuff[512-blocklen],1,blocklen,g_fhandle);
50+ // Some modifications of text for easy compiling.
51+ for(i=512-blocklen;i<512;i++){
52+ if (in_string) {
53+ if (g_fbuff[i]=='\\' && !escape) {
54+ escape=1;
55+ } else {
56+ escape=0;
57+ if (g_fbuff[i]=='"') in_string=0;
58+ }
59+ } else {
60+ // If not in string, all upper cases.
61+ if (g_fbuff[i]=='"') in_string=1;
62+ else if ('a'<=g_fbuff[i] && g_fbuff[i]<='z') g_fbuff[i]+='A'-'a';
63+ // If not in string, tabs will be spaces.
64+ else if ('\t'==g_fbuff[i]) g_fbuff[i]=' ';
65+ }
66+ if (g_fbuff[i]==0x0a || g_fbuff[i]==0x0d) in_string=escape=0;
67+ }
68+ return;
69+}
70+
71+char* compile_file(){
72+ int i;
73+ char* err;
74+ // Read first 512 bytes
75+ read_file(512);
76+ // Compile line by line
77+ while (g_size==512) {
78+ err=compile_line();
79+ if (err) return err;
80+ // Maintain at least 256 characters in cache.
81+ if (256<=g_srcpos) read_file(256);
82+ }
83+ // Return code at the end
84+ g_source[g_size]=0x0d;
85+ // Compile last few lines.
86+ while(g_srcpos<g_size-1){
87+ err=compile_line();
88+ if (err) return err;
89+ }
90+ // Add "DATA 0" and "END" statements.
91+ g_source="DATA 0:END\n";
92+ g_srcpos=0;
93+ err=compile_line();
94+ if (err) return err;
95+ g_srcpos=-1;
96+ // No error occured
97+ return 0;
98+}
99+
--- /dev/null
+++ b/mips/zoea/float.c
@@ -0,0 +1,143 @@
1+#include "./compiler.h"
2+#include "stdlib.h"
3+
4+char* get_float_sub(int pr);
5+
6+char* get_simple_float(void){
7+ int i;
8+ float f;
9+ char* err;
10+ char b1,b2,b3;
11+ next_position();
12+ b1=g_source[g_srcpos];
13+ if (b1=='(') {
14+ // (...)
15+ // Parenthesis
16+ g_srcpos++;
17+ next_position();
18+ err=get_float_sub(priority(OP_VOID));
19+ if (err) return err;
20+ next_position();
21+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
22+ g_srcpos++;
23+ } else if (b1=='-') {
24+ // Unary '-' operator
25+ // Note that unary operators ( + and - ) have higher priority than the other operators
26+ g_srcpos++;
27+ err=get_simple_float();
28+ if (err) return err;
29+ check_obj_space(1);
30+ g_object[g_objpos++]=0x34040000; // ori a0,zero,0
31+ call_lib_code(LIB_FLOAT | OP_SUB);
32+ } else {
33+ // Main routine of getting float value here
34+ if (b1=='+') g_srcpos++; // Ignore unary '+' operator
35+ next_position();
36+ b1=g_source[g_srcpos];
37+ b2=g_source[g_srcpos+1];
38+ b3=g_source[g_srcpos+2];
39+ if ('0'<=b1 && b1<='9') {
40+ f=strtof((const char*)&g_source[g_srcpos],&err);
41+ if (&g_source[g_srcpos]==err) return ERR_SYNTAX;
42+ g_srcpos=err-g_source;
43+ i=((int*)(&f))[0];
44+ if (i&0xFFFF0000) {
45+ // 32 bit
46+ check_obj_space(2);
47+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
48+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
49+ } else {
50+ // 16 bit
51+ check_obj_space(1);
52+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
53+ }
54+ } else {
55+ i=get_var_number();
56+ if (i<0) {
57+ // Must be a function.
58+ return float_function();
59+ }
60+ if (g_source[g_srcpos]!='#') return ERR_SYNTAX;
61+ g_srcpos++;
62+ if (g_source[g_srcpos]=='(') {
63+ // Dimension
64+ g_srcpos++;
65+ return get_dim_value(i);
66+ }
67+ // Simple value
68+ check_obj_space(1);
69+ g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
70+ }
71+ }
72+ // No error
73+ return 0;
74+}
75+
76+char* get_float_sub(int pr){
77+ char* err;
78+ enum operator op;
79+ char b1,b2,b3;
80+ int prevpos;
81+ // Get a value in $v0.
82+ err=get_simple_float();
83+ if (err) return err;
84+ while(1){
85+ // Get the operator in op. If not valid operator, simply return without error.
86+ prevpos=g_srcpos;
87+ err=get_floatOperator();
88+ if (err) return 0;
89+ op=g_last_op;
90+ // Compair current and previous operators.
91+ // If the previous operator has higher priolity, return.
92+ if (pr>=priority(op)) {
93+ g_srcpos=prevpos;
94+ return 0;
95+ }
96+ // Store $v0 in stack
97+ g_sdepth+=4;
98+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
99+ check_obj_space(1);
100+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
101+ // Get next value.
102+ err=get_float_sub(priority(op));
103+ if (err) return err;
104+ // Get value from stack to $a0.
105+ check_obj_space(1);
106+ g_object[g_objpos++]=0x8FA40000|g_sdepth; // lw a0,xx(sp)
107+ g_sdepth-=4;
108+ // Calculation. Result will be in $v0.
109+ err=calculation_float(op);
110+ if (err) return err;
111+ }
112+}
113+
114+char* get_float(){
115+ // Note that this can be called recursively.
116+ // Value may contain function with a parameter of another value.
117+ char* err;
118+ int prevpos;
119+ if (g_sdepth==0) {
120+ // Initialize stack handler
121+ g_maxsdepth=0;
122+ prevpos=g_objpos;
123+ // Stack decrement command will be filled later
124+ check_obj_space(1);
125+ g_objpos++;
126+ }
127+ err=get_float_sub(priority(OP_VOID));
128+ if (err) return err;
129+ if (g_sdepth==0) {
130+ if (g_maxsdepth==0) {
131+ // Stack was not used.
132+ shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
133+ g_objpos--;
134+ } else {
135+ // Stack was used.
136+ check_obj_space(1);
137+ g_object[prevpos]=0x27BD0000 | (0-g_maxsdepth) & 0x0000FFFF; // addiu sp,sp,-xx
138+ g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx
139+ }
140+ }
141+ g_lastvar=VAR_FLOAT;
142+ return 0;
143+}
\ No newline at end of file
--- /dev/null
+++ b/mips/zoea/function.c
@@ -0,0 +1,563 @@
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 "compiler.h"
9+#include "api.h"
10+
11+char* music_function(){
12+ call_lib_code(LIB_MUSICFUNC);
13+ return 0;
14+}
15+
16+char* read_function(){
17+ call_lib_code(LIB_READ);
18+ return 0;
19+}
20+
21+char* cread_function(){
22+ call_lib_code(LIB_CREAD);
23+ return 0;
24+}
25+
26+char* gosub_function(){
27+ // Check if garbage collection has been done.
28+ // This check is required because the used temporary area would be changed
29+ // in sub routine.
30+ if (g_temp_area_used) return ERR_GOSUB_ASH;
31+ return gosub_statement();
32+}
33+char* strncmp_function(){
34+ char* err;
35+ err=get_string();
36+ if (err) return err;
37+ check_obj_space(2);
38+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
39+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
40+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
41+ g_srcpos++;
42+ err=get_string();
43+ if (err) return err;
44+ check_obj_space(1);
45+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
46+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
47+ g_srcpos++;
48+ err=get_value();
49+ if (err) return err;
50+ call_lib_code(LIB_STRNCMP);
51+ check_obj_space(1);
52+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
53+ return 0;
54+}
55+char* len_function(){
56+ char* err;
57+ err=get_string();
58+ if (err) return err;
59+ check_obj_space(5);
60+ g_object[g_objpos++]=0x2443FFFF; // addiu v1,v0,-1
61+ // loop:
62+ g_object[g_objpos++]=0x80640001; // lb a0,1(v1)
63+ g_object[g_objpos++]=0x1480FFFE; // bne a0,zero,loop
64+ g_object[g_objpos++]=0x24630001; // addiu v1,v1,1
65+ g_object[g_objpos++]=0x00621023; // subu v0,v1,v0
66+ return 0;
67+}
68+
69+char* asc_function(){
70+ char* err;
71+ err=get_string();
72+ if (err) return err;
73+ check_obj_space(1);
74+ g_object[g_objpos++]=0x90420000; // lbu v0,0(v0)
75+ return 0;
76+}
77+
78+char* val_function(){
79+ char* err;
80+ err=get_string();
81+ if (err) return err;
82+ call_lib_code(LIB_VAL);
83+ return 0;
84+}
85+
86+char* peek_function(){
87+ char* err;
88+ err=get_value();
89+ if (err) return err;
90+ check_obj_space(1);
91+ g_object[g_objpos++]=0x90420000; // lbu v0,0(v0)
92+ return 0;
93+}
94+
95+char* sgn_function(){
96+ char* err;
97+ err=get_value();
98+ if (err) return err;
99+ check_obj_space(5);
100+ g_object[g_objpos++]=0x10400004; // beq v0,zero,end
101+ g_object[g_objpos++]=0x24030001; // addiu v1,zero,1
102+ g_object[g_objpos++]=0x1C400002; // bgtz v0,end
103+ g_object[g_objpos++]=0x00601021; // addu v0,v1,zero
104+ g_object[g_objpos++]=0x00031023; // subu v0,zero,v1
105+ // end:
106+ return 0;
107+}
108+
109+char* abs_function(){
110+ char* err;
111+ err=get_value();
112+ if (err) return err;
113+ check_obj_space(3);
114+ g_object[g_objpos++]=0x00021FC3; //sra v1,v0,0x1f
115+ g_object[g_objpos++]=0x00621026; //xor v0,v1,v0
116+ g_object[g_objpos++]=0x00431023; //subu v0,v0,v1
117+ return 0;
118+}
119+
120+char* not_function(){
121+ char* err;
122+ err=get_value();
123+ if (err) return err;
124+ check_obj_space(1);
125+ g_object[g_objpos++]=0x2C420001; //sltiu v0,v0,1
126+ return 0;
127+}
128+
129+char* rnd_function(){
130+ call_lib_code(LIB_RND);
131+ return 0;
132+}
133+
134+
135+char* chr_function(void){
136+ char* err;
137+ err=get_value();
138+ if (err) return err;
139+ call_lib_code(LIB_CHR);
140+ return 0;
141+}
142+char* hex_function(void){
143+ char* err;
144+ err=get_value();
145+ if (err) return err;
146+ if (g_source[g_srcpos]==',') {
147+ // Second argument found.
148+ // Get is as $a0.
149+ g_srcpos++;
150+ check_obj_space(2);
151+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
152+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
153+ err=get_value();
154+ if (err) return err;
155+ check_obj_space(3);
156+ g_object[g_objpos++]=0x00022021; //a0,zero,v0
157+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
158+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
159+ } else {
160+ // Second argument not found.
161+ // Set $a0 to 0.
162+ check_obj_space(1);
163+ g_object[g_objpos++]=0x24040000; //addiu a0,zero,0
164+ }
165+ call_lib_code(LIB_HEX);
166+ return 0;
167+}
168+
169+char* dec_function(void){
170+ char* err;
171+ err=get_value();
172+ if (err) return err;
173+ call_lib_code(LIB_DEC);
174+ return 0;
175+}
176+
177+char* keys_function(void){
178+ char* err;
179+ next_position();
180+ if (g_source[g_srcpos]==')') {
181+ check_obj_space(1);
182+ g_object[g_objpos++]=0x3402003F; //ori v0,zero,0x3f
183+ } else {
184+ err=get_value();
185+ if (err) return err;
186+ }
187+ call_lib_code(LIB_KEYS);
188+ return 0;
189+}
190+
191+char* tvram_function(void){
192+ char* err;
193+ int i;
194+ next_position();
195+ if (g_source[g_srcpos]==')') {
196+ i=(int)(&TVRAM[0]);
197+ i-=g_gp;
198+ check_obj_space(1);
199+ g_object[g_objpos++]=0x27820000|(i&0x0000FFFF); // addiu v0,gp,xxxx
200+ } else {
201+ err=get_value();
202+ if (err) return err;
203+ i=(int)(&TVRAM[0]);
204+ i-=g_gp;
205+ check_obj_space(3);
206+ g_object[g_objpos++]=0x27830000|(i&0x0000FFFF); // addiu v1,gp,xxxx
207+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
208+ g_object[g_objpos++]=0x90620000; // lbu v0,0(v1)
209+ }
210+ return 0;
211+}
212+
213+char* drawcount_function(void){
214+ call_lib_code(LIB_DRAWCOUNT);
215+ return 0;
216+}
217+
218+char* input_function(void){
219+ call_lib_code(LIB_INPUT);
220+ return 0;
221+}
222+
223+char* inkey_function(void){
224+ char* err;
225+ next_position();
226+ if (g_source[g_srcpos]==')') {
227+ check_obj_space(1);
228+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x00
229+ } else {
230+ err=get_value();
231+ if (err) return err;
232+ }
233+ call_lib_code(LIB_INKEY);
234+ return 0;
235+}
236+
237+char* args_function(void){
238+ char* err;
239+ int i;
240+ err=get_value();
241+ if (err) return err;
242+ i=g_object[g_objpos-1];
243+ if ((i>>16)==0x3402) {
244+ // Previous object is "ori v0,zero,xxxx".
245+ i&=0xffff;
246+ i=(i+1)<<2;
247+ g_object[g_objpos-1]=0x8EA20000|i; // lw v0,xx(s5)
248+ } else {
249+ check_obj_space(3);
250+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
251+ g_object[g_objpos++]=0x02A21021; // addu v0,s5,v0
252+ g_object[g_objpos++]=0x8C420004; // lw v0,4(v0)
253+ }
254+ return 0;
255+}
256+
257+char* system_function(void){
258+ char* err;
259+ err=get_value();
260+ if (err) return err;
261+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
262+ call_lib_code(LIB_SYSTEM);
263+ return 0;
264+}
265+
266+char* sprintf_function(void){
267+ char* err;
268+ err=get_string();
269+ if (err) return err;
270+ next_position();
271+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
272+ g_srcpos++;
273+ check_obj_space(2);
274+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
275+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
276+ err=get_float();
277+ if (err) return err;
278+ check_obj_space(3);
279+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
280+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
281+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
282+ call_lib_code(LIB_SPRINTF);
283+ return 0;
284+}
285+
286+char* floatstr_function(void){
287+ char* err;
288+ err=get_float();
289+ if (err) return err;
290+ check_obj_space(2);
291+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
292+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x0000
293+ call_lib_code(LIB_SPRINTF);
294+ return 0;
295+}
296+
297+char* floatsharp_function(void){
298+ char* err;
299+ err=get_value();
300+ if (err) return err;
301+ call_lib_code(LIB_FLOATFUNCS | FUNC_FLOAT);
302+ return 0;
303+}
304+
305+char* valsharp_function(void){
306+ char* err;
307+ err=get_string();
308+ if (err) return err;
309+ call_lib_code(LIB_FLOATFUNCS | FUNC_VALSHARP);
310+ return 0;
311+}
312+
313+char* int_function(void){
314+ char* err;
315+ err=get_float();
316+ if (err) return err;
317+ call_lib_code(LIB_FLOATFUNCS | FUNC_INT);
318+ return 0;
319+}
320+
321+char* fseek_function(){
322+ call_lib_code(LIB_FILE | FUNC_FTELL);
323+ return 0;
324+}
325+
326+char* flen_function(){
327+ call_lib_code(LIB_FILE | FUNC_FLEN);
328+ return 0;
329+}
330+
331+char* fgetc_function(){
332+ call_lib_code(LIB_FILE | FUNC_FGETC);
333+ return 0;
334+}
335+
336+char* finput_function(){
337+ char* err;
338+ next_position();
339+ if (g_source[g_srcpos]!=')') {
340+ err=get_value();
341+ if (err) return err;
342+ } else {
343+ // Parameter will be zero if not defined
344+ check_obj_space(1);
345+ g_object[g_objpos++]=0x34020000; // ori v0,zero,0
346+ }
347+ call_lib_code(LIB_FILE | FUNC_FINPUT);
348+ return 0;
349+}
350+
351+char* feof_function(){
352+ call_lib_code(LIB_FILE | FUNC_FEOF);
353+ return 0;
354+}
355+
356+char* float_constant(float val){
357+ volatile int i;
358+ ((float*)(&i))[0]=val;
359+ if (i&0xFFFF0000) {
360+ // 32 bit
361+ check_obj_space(2);
362+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
363+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
364+ } else {
365+ // 16 bit
366+ check_obj_space(1);
367+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
368+ }
369+ return 0;
370+}
371+
372+char* float_1param_function(enum functions func){
373+ char* err;
374+ err=get_float();
375+ if (err) return err;
376+ call_lib_code(LIB_FLOATFUNCS | func);
377+ return 0;
378+}
379+
380+char* float_2param_function(enum functions func){
381+ char* err;
382+ err=get_float();
383+ if (err) return err;
384+ next_position();
385+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
386+ g_srcpos++;
387+ check_obj_space(2);
388+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
389+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
390+ err=get_float();
391+ if (err) return err;
392+ check_obj_space(3);
393+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
394+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
395+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
396+ call_lib_code(LIB_FLOATFUNCS | func);
397+ return 0;
398+}
399+
400+char* float_function(void){
401+ char* err;
402+ if (nextCodeIs("FLOAT#(")) {
403+ err=floatsharp_function();
404+ } else if (nextCodeIs("VAL#(")) {
405+ err=valsharp_function();
406+ } else if (nextCodeIs("SIN#(")) {
407+ err=float_1param_function(FUNC_SIN);
408+ } else if (nextCodeIs("COS#(")) {
409+ err=float_1param_function(FUNC_COS);
410+ } else if (nextCodeIs("TAN#(")) {
411+ err=float_1param_function(FUNC_TAN);
412+ } else if (nextCodeIs("ASIN#(")) {
413+ err=float_1param_function(FUNC_ASIN);
414+ } else if (nextCodeIs("ACOS#(")) {
415+ err=float_1param_function(FUNC_ACOS);
416+ } else if (nextCodeIs("ATAN#(")) {
417+ err=float_1param_function(FUNC_ATAN);
418+ } else if (nextCodeIs("ATAN2#(")) {
419+ err=float_2param_function(FUNC_ATAN2);
420+ } else if (nextCodeIs("SINH#(")) {
421+ err=float_1param_function(FUNC_SINH);
422+ } else if (nextCodeIs("COSH#(")) {
423+ err=float_1param_function(FUNC_COSH);
424+ } else if (nextCodeIs("TANH#(")) {
425+ err=float_1param_function(FUNC_TANH);
426+ } else if (nextCodeIs("EXP#(")) {
427+ err=float_1param_function(FUNC_EXP);
428+ } else if (nextCodeIs("LOG#(")) {
429+ err=float_1param_function(FUNC_LOG);
430+ } else if (nextCodeIs("LOG10#(")) {
431+ err=float_1param_function(FUNC_LOG10);
432+ } else if (nextCodeIs("POW#(")) {
433+ err=float_2param_function(FUNC_POW);
434+ } else if (nextCodeIs("SQRT#(")) {
435+ err=float_1param_function(FUNC_SQRT);
436+ } else if (nextCodeIs("CEIL#(")) {
437+ err=float_1param_function(FUNC_CEIL);
438+ } else if (nextCodeIs("FLOOR#(")) {
439+ err=float_1param_function(FUNC_FLOOR);
440+ } else if (nextCodeIs("FABS#(")) {
441+ err=float_1param_function(FUNC_FABS);
442+ } else if (nextCodeIs("MODF#(")) {
443+ err=float_1param_function(FUNC_MODF);
444+ } else if (nextCodeIs("FMOD#(")) {
445+ err=float_2param_function(FUNC_FMOD);
446+ } else if (nextCodeIs("GOSUB#(")) {
447+ err=gosub_function();
448+ } else if (nextCodeIs("ARGS#(")) {
449+ err=args_function();
450+ } else if (nextCodeIs("PI#")) {
451+ return float_constant(3.141593);
452+ } else {
453+ return ERR_SYNTAX;
454+ }
455+ if (err) return err;
456+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
457+ g_srcpos++;
458+ return 0;
459+}
460+
461+char* str_function(void){
462+ char* err;
463+ if (nextCodeIs("CHR$(")) {
464+ err=chr_function();
465+ } else if (nextCodeIs("HEX$(")) {
466+ err=hex_function();
467+ } else if (nextCodeIs("DEC$(")) {
468+ err=dec_function();
469+ } else if (nextCodeIs("INPUT$(")) {
470+ err=input_function();
471+ } else if (nextCodeIs("GOSUB$(")) {
472+ err=gosub_function();
473+ } else if (nextCodeIs("ARGS$(")) {
474+ err=args_function();
475+ } else if (nextCodeIs("READ$(")) {
476+ err=read_function();
477+ } else if (nextCodeIs("SPRINTF$(")) {
478+ err=sprintf_function();
479+ } else if (nextCodeIs("FLOAT$(")) {
480+ err=floatstr_function();
481+ } else if (nextCodeIs("SYSTEM$(")) {
482+ err=system_function();
483+ } else if (nextCodeIs("FINPUT$(")) {
484+ err=finput_function();
485+ } else {
486+ return ERR_SYNTAX;
487+ }
488+ if (err) return err;
489+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
490+ g_srcpos++;
491+ return 0;
492+}
493+
494+char* function(void){
495+ char* err;
496+ if (nextCodeIs("NOT(")) {
497+ err=not_function();
498+ } else if (nextCodeIs("DRAWCOUNT(")) {
499+ err=drawcount_function();
500+ } else if (nextCodeIs("MUSIC(")) {
501+ err=music_function();
502+ } else if (nextCodeIs("TVRAM(")) {
503+ err=tvram_function();
504+ } else if (nextCodeIs("KEYS(")) {
505+ err=keys_function();
506+ } else if (nextCodeIs("READ(")) {
507+ err=read_function();
508+ } else if (nextCodeIs("CREAD(")) {
509+ err=cread_function();
510+ } else if (nextCodeIs("GOSUB(")) {
511+ err=gosub_function();
512+ } else if (nextCodeIs("STRNCMP(")) {
513+ err=strncmp_function();
514+ } else if (nextCodeIs("PEEK(")) {
515+ err=peek_function();
516+ } else if (nextCodeIs("LEN(")) {
517+ err=len_function();
518+ } else if (nextCodeIs("ASC(")) {
519+ err=asc_function();
520+ } else if (nextCodeIs("SGN(")) {
521+ err=sgn_function();
522+ } else if (nextCodeIs("ABS(")) {
523+ err=abs_function();
524+ } else if (nextCodeIs("RND(")) {
525+ err=rnd_function();
526+ } else if (nextCodeIs("VAL(")) {
527+ err=val_function();
528+ } else if (nextCodeIs("INKEY(")) {
529+ err=inkey_function();
530+ } else if (nextCodeIs("ARGS(")) {
531+ err=args_function();
532+ } else if (nextCodeIs("SYSTEM(")) {
533+ err=system_function();
534+ } else if (nextCodeIs("INT(")) {
535+ err=int_function();
536+ } else if (nextCodeIs("GCOLOR(")) {
537+ err=graphic_statement(FUNC_GCOLOR);
538+ } else if (nextCodeIs("FOPEN(")) {
539+ err=fopen_statement(FUNC_FOPEN);
540+ } else if (nextCodeIs("FSEEK(")) {
541+ err=fseek_function();
542+ } else if (nextCodeIs("FLEN(")) {
543+ err=flen_function();
544+ } else if (nextCodeIs("FGET(")) {
545+ err=fget_statement();
546+ } else if (nextCodeIs("FPUT(")) {
547+ err=fput_statement();
548+ } else if (nextCodeIs("FGETC(")) {
549+ err=fgetc_function();
550+ } else if (nextCodeIs("FPUTC(")) {
551+ err=fputc_statement();
552+ } else if (nextCodeIs("FREMOVE(")) {
553+ err=fremove_statement();
554+ } else if (nextCodeIs("FEOF(")) {
555+ err=feof_function();
556+ } else {
557+ return ERR_SYNTAX;
558+ }
559+ if (err) return err;
560+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
561+ g_srcpos++;
562+ return err;
563+}
--- /dev/null
+++ b/mips/zoea/globalvars.c
@@ -0,0 +1,79 @@
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 "compiler.h"
9+#include "main.h"
10+
11+// Contain the valus of $gp and $s6 (GPR of MIPS32)
12+int g_gp;
13+int g_s6;
14+
15+// Line data when compiling
16+int g_line;
17+int g_fileline;
18+
19+// Contain the address to which return in "END" statement.
20+int g_end_addr;
21+
22+// Following vars are used in value.c and string.c.
23+// These define the depth of stack pointer used for
24+// handling values and strings.
25+int g_sdepth;
26+int g_maxsdepth;
27+
28+// Following var shows what type of variable was defined
29+// in compiling the last code.
30+enum variable g_lastvar;
31+
32+// Vars used for handling constant integer
33+int g_intconst;
34+char g_valueisconst;
35+
36+// Global vars associated to RAM
37+char* g_source;
38+int g_srcpos;
39+int* g_object;
40+int g_objpos;
41+int* g_objmax;
42+char RAM[RAMSIZE] __attribute__((persistent,address(0xA0000000+PIC32MX_RAMSIZE-PERSISTENT_RAM_SIZE)));
43+unsigned int g_ex_data[EXCEPTION_DATA_SIZE/4] __attribute__((persistent,address(0xA0000000+PIC32MX_RAMSIZE-EXCEPTION_DATA_SIZE)));
44+
45+// Global area for vars A-Z and three temporary string pointers
46+int g_var_mem[ALLOC_BLOCK_NUM];
47+unsigned short g_var_pointer[ALLOC_BLOCK_NUM];
48+unsigned short g_var_size[ALLOC_BLOCK_NUM];
49+
50+// Flag to use temporary area when compiling
51+char g_temp_area_used;
52+
53+// Heap area
54+int* g_heap_mem;
55+int g_max_mem;
56+
57+// Random seed
58+unsigned int g_rnd_seed;
59+
60+// Enable/disable Break keys
61+char g_disable_break;
62+
63+// Font data used for PCG
64+unsigned char* g_pcg_font;
65+
66+// Use or do not use graphic
67+char g_use_graphic;
68+
69+// Pointer to graphic RAM
70+unsigned short* g_graphic_area;
71+
72+// Parameter-containing block used for library
73+int* g_libparams;
74+
75+// Number of long name variables
76+int g_long_name_var_num;
77+
78+// General purpose integer used for asigning value with pointer
79+int g_temp;
--- /dev/null
+++ b/mips/zoea/help.txt
@@ -0,0 +1,665 @@
1+<BASIC言語の書式>
2+BASICプログラムの記述は、行番号式、ラベル式、その混合、いずれの方法でも構
3+いません。以下、仕様について述べます。
4+
5+<利用可能な変数型>
6+利用できる変数の型は、32ビット符号付整数(-2147483648 以上 +2147483647 以
7+下)と、文字列型の2種類です。文字列の末端部には0x00が付加されます。
8+
9+A-Zの26個の整数型変数が利用可能です。文字列として扱う場合はA$のように記
10+述します。ただし、A(整数型)とA$(文字列型)を同時に使用することは出来ま
11+せん。
12+
13+整数型の定数は、10進法で記述します。16進法を使う場合、「$1200」のよう
14+に、頭に「$」を付加するか、「0x1200」の様に表記して下さい。
15+
16+文字列型の定数は、「"」で囲って記述してください。「"」を使用する場合は、
17+「CHR$($22)」のように記述することが出来ます。
18+
19+<命令>
20+以下、x, y, z等は整数値を、x$, y$, z$は文字列を、x#, y#, z#は浮動
21+小数点型実数値を指します。xxx, yyy, zzz, www等は任意のステートメントを
22+指します。[ ]は省略可能である事を示します。
23+
24+命令同士を「:」で区切ることにより、一行で複数のコマンドを処理すること
25+が出来ます。
26+
27+BGCOLOR r,g,b
28+ 背景色指定。
29+BREAK
30+ FOR-NEXT, DO-LOOP, WHILE-WENDループから抜け出す。
31+CDATA x[,y[,z[...]]]
32+ データー列を8ビット整数値で指定する。
33+CLEAR
34+ すべての文字列型変数と整数型配列を破棄し、整数値を0とする。また、
35+ PCGの使用をやめ、表示キャラクターをリセットする。
36+CLS
37+ スクリーン消去。
38+COLOR x
39+ テキスト色指定。
40+CONTINUE
41+ FOR-NEXT, DO-LOOP, WHILE-WENDループ中で、以降のコードをスキップす
42+ る。
43+CURSOR x,y
44+ カーソル位置指定。
45+CDATA xxx[,yyy[,zzz[...]]]
46+ データー列を8ビット整数値で指定する。
47+DATA xxx[,yyy[,zzz[...]]]
48+ データー列を整数値もしくは文字列で指定する。
49+DIM xxx [, yyy [, zzz [, ... ]]]
50+ 整数型もしくは浮動小数点型の配列を割り当てる。
51+ xxx,yyy,zzzは、例えば「A(10)」のように記述する。この場合、A(0)から
52+ A(10)までの11個の整数型変数が確保される。浮動小数点型配列の場合は、
53+ 「A#(10)」の様に記述する。多次元配列も、宣言することが出来る。
54+DO WHILE x
55+LOOP
56+ x が0以外の場合、DO文からLOOP文までのステートメントを繰り返し実行する。
57+DO UNTIL x
58+LOOP
59+ x が0の場合、DO文からLOOP文までのステートメントを繰り返し実行する。
60+DO
61+LOOP WHILE x
62+ DO文からLOOP文までのステートメントを実行し、x が0以外の場合、繰り返す。
63+DO
64+LOOP UNTIL x
65+ DO文からLOOP文までのステートメントを実行し、x が0の場合、繰り返す。
66+DRAWCOUNT
67+ DRAWCOUNT値を指定する。DRAWCOUNT値に付いては、DRAWCOUNT()関数を
68+ 参照。
69+END
70+ BASICプログラムを停止する。
71+EXEC x[,y[,z[...]]]
72+ 機械語を実行する。ただし、x,y,zは32ビット整数値。
73+FOR x=yyy TO zzz [ STEP www ]
74+NEXT
75+ yyyで示された計算結果をxに代入し、xの値がzzzになるまで次のNEXT文
76+ までのステートメントを、繰り返し実行する。繰り返しのたび、xの値は
77+ wwwずつ増加する(省略された場合は1ずつ)。「NEXT」の次に何も記述
78+ しないことに注意。
79+GOSUB xxx [, yyy [, zzz [, ... ]]]
80+ 現在の実行位置を記憶し、xxx行目(もしくはラベル)に移動する。yyy, zzz
81+ 等は、サブルーチンに引き継がれる引数(ARGS()関数を参照)。
82+GOTO xxx
83+ xxx行目(もしくはラベル)に移動する。
84+IF xまたはx# THEN yyy [ ELSE zzz ]
85+ xが0以外のとき、yyyを、0のときzzzを実行。yyyおよびzzzは、複数のステート
86+ メントを「:」で挟んで記述可能。
87+IF xまたはx# THEN
88+xxx
89+[ELSEIF yまたはy# THEN
90+yyy]
91+[ELSE
92+zzz]
93+ENDIF
94+ xが0以外の時xxxを、それ以外で且つyが0以外の時(記述された場合)yyyを、
95+ それ以外の場合にzzzを実行。ELSEIFステートメントは、複数記述可。各行で、
96+ THENステートメントの次には何も記入しないことに注意。
97+LABEL xxx
98+ GOTO/GOSUBのジャンプ先を登録する。xxxは、英数字6文字以内の文字列。
99+[LET] x=yyy
100+ yで示された計算結果を、x(整数型変数)に代入する。「LET」は省略可。
101+[LET] x#=yyy
102+ yで示された計算結果を、x(浮動小数点型変数)に代入する。「LET」は省略可。
103+[LET] x$=yyy
104+ yyyで示された文字列(もしくは連結結果;連結演算子は「+」)を、x$に
105+ 代入する。「LET」は省略可。
106+MUSIC x$
107+ BGMを演奏する。詳細は、下記<MUSIC>の項を参照。
108+VAR xxx [, yyy [, zzz [, ... ]]]
109+ サブルーチン内で使う、ローカル変数を指定する。xxx, yyy等は、A-Zの
110+ アルファベットで指定する。
111+USEVAR xxx [, yyy [, zzz [, ... ]]]
112+ 英数字で最大6文字までの変数名を使用できるようにする。
113+ このステートメント以降でxxx, yyy等の長い変数名が使用可能となる。
114+WHILE x
115+WEND
116+ x が0以外の場合、WHILE文からWEND文までのステートメントを繰り返し実行する。
117+PALETTE n,r,g,b
118+ パレット指定。
119+PCG x,y,z
120+ ASCIIコードがxの文字の表示キャラクターを変更する。y,zは、キャラク
121+ ターデーター。詳細は、下記<PCG>の項を参照。
122+POKE x,y
123+ xで示される物理的アドレスに、yで示される値(1バイト値)を書き込む。
124+PRINT [ xまたはx$またはx# [ ,または; [ yまたはy$またはy# [ ... ]]]]
125+ ディスプレイに、整数値または文字列を表示する。「;」を使用した場
126+ 合、次の表示が続けて行われる。「,」を使用した場合、10文字ずつ
127+ に区切って表示される。どちらも使用しない場合、次の表示は行を変え
128+ て行われる。
129+REM xxx
130+ 何も実行しない
131+RESTORE xxx
132+ DATA読み出し開始位置を指定。xxxは行番号もしくはラベル。
133+RETURN
134+ 最後に実行されたGOSUB文の次のステートメントに移動する。戻り値を指
135+ 定することがができる。この場合の戻り値はGOSUB()関数にて取得が可能。
136+SCROLL x,y
137+ 画面を横方向、もしくは縦方向(斜めも可)に動かす。動かす方向と大きさ
138+ は、x, yでそれぞれ、横方向の移動度、縦方向の移動度として指定する。
139+SOUND xxx
140+ 効果音を再生する。詳細は、下記<SOUND>の項を参照。xxxは行番号もしく
141+ はラベル。
142+SYSTEM x , y
143+ 様々なシステム値の設定を行なう。<SYSTEM>の項を参照。
144+USEGRAPHIC [x]
145+ グラフィックディスプレイを使用、もしくは使用停止する。x=0で使用停止、
146+ x=1で使用、x=2で画面とパレットをクリアーして使用、x=3でグラフィック領
147+ 域を確保するが表示はキャラクターディスプレイのまま。ただし、グラフィッ
148+ クディスプレイ未使用の状態でx=0の場合は、領域を確保する。xを省略した場
149+ 合は、x=1と同じ。
150+USEPCG [x]
151+ PCGを使用、もしくは使用停止する。x=0で使用停止、x=1で使用、x=2で
152+ キャラクターをリセットして使用。xを省略した場合は、x=1と同じ。
153+WAIT x
154+ xで示された時間、プログラムの実行を停止する。xが60の場合、約1秒間
155+ 停止。
156+WIDTH x
157+ キャラクターディスプレイの横幅を文字数で指定。xは30もしくは40。
158+
159+<グラフィック関連命令>
160+
161+BOXFILL [x1,y1],x2,y2[,c]
162+ 座標(x1,y1),(x2,y2)を対角線とするカラーcで塗られた長方形を描画。
163+CIRCLE [x,y],r[,c]
164+ 座標(x,y)を中心に、半径r、カラーcの円を描画。
165+CIRCLEFILL [x,y],r[,c]
166+ 座標(x,y)を中心に、半径r、カラーcで塗られた円を描画。
167+GCLS
168+ 画面クリアー。
169+GCOLOR c
170+ それぞれの命令で、cを省略した場合の色を指定。
171+GPALETTE n,r,g,b
172+ パレット指定。
173+GPRINT [x,y],c,bc,s$
174+ 座標(x,y)にカラーcで文字列s$を表示、bc:背景色(負数の場合背景色指定なし)。
175+LINE [x1,y1],x2,y2[,c]
176+ 座標(x1,y1)から(x2,y2)にカラーcで線分を描画。
177+POINT x,y
178+ グラフィック現在位置を、設定する。
179+PSET [x,y][,c]
180+ 座標(x,y)の位置にカラーcで点を描画。
181+PUTBMP [x,y],m,n,bbb
182+ 横m*縦nドットのキャラクター(bbbで指定)を座標(x,y)に表示。
183+ サイズm*nの配列bmpに、単純にカラー番号を並べる。
184+ ただし、カラーが0の部分は透明色として扱う。ただし、bbbはラベル名もし
185+ くは配列へのポインター。
186+(GCOLOR()関数も参照のこと)
187+
188+<ファイル関連命令>
189+FCLOSE [x]
190+ ファイルを閉じる。引数(x)がある場合は、そのファイルハンドルで指定されたファ
191+ イルを閉じる。
192+FGET x,y
193+ バッファー(xに配列として指定)にyバイト読み込む。関数として呼ばれた場合は、
194+ 読み込みに成功したバイト数を返す。
195+FILE x
196+ アクティブなファイルハンドル(1もしくは2)をxに指定する。
197+FOPEN x$,y$[,z]
198+ x$で示される名前のファイルを、y$で示されたモードで開く。同時に開けるファイ
199+ ルの数は、2つまで。関数として呼ばれた場合は、ファイルハンドルを返す。y$と
200+ しては、次のものが有効。
201+ "r" :ファイルを読み込みモードで開く。
202+ "r+" :"r"と同じだが書き込みも可能。
203+ "w" :ファイルを書き込みモードで開く。同名のファイルが在る場合は、
204+ 以前のファイルは消去される。
205+ "w+" :"w"と同じだが、読み込みも可能。
206+ "a" :ファイルを書き込みモードで開く。同名のファイルが在る場合は、
207+ ファイルは消去されず、ファイルの最後尾から書き込まれる。
208+ "a+" :"a"と同じだが、読み込みも可能。
209+ zには、割り当てたいファイルハンドル(1もしくは2)を指定する。省略した場
210+ 合、1が指定される。
211+FPRINT [ xまたはx$またはx# [ ,または; [ yまたはy$またはy# [ ... ]]]]
212+ PRINT命令と同じだが、画面ではなくファイルに情報が書き込まれる。
213+FPUT x,y
214+ バッファー(xに配列として指定)のyバイト分を書き込む。関数として呼ばれた場合
215+ は、書き込みに成功したバイト数を返す。
216+FPUTC x
217+ xで示される1バイトのデーターをファイルに書き込む。関数として呼ばれた場合
218+ は、書き込みに成功したバイト数(1もしくは0)を返す。
219+FREMOVE x$
220+ x$で示される名前のファイルを、SDカードから削除する。関数として呼ばれた場合
221+ は、削除に成功したか(0)、失敗したか(-1)を返す。
222+FSEEK x
223+ xで示されるファイル位置に移動する。
224+(FEOF(), FGETC(), FINPUT$(), FLEN(), FSEEK()関数も参照のこと)
225+
226+
227+<整数型関数>
228+以下、x, y, zは整数値を、x$, y$, z$は文字列を指します。[ ]は省略可能である事
229+を示します。
230+
231+ABS(x)
232+ xの絶対値を返す。
233+ARGS(x)
234+ サブルーチン中で、GOSUBに渡されたx番目の引数を整数値として取り出す。
235+ASC(x$)
236+ 文字列の最初の一文字の、アスキーコードを返す。
237+CREAD()
238+ DATA文の後から、一つずつデーター(8ビット整数値)を読み出す。「READ()」
239+ 関数も参照。
240+DRAWCOUNT()
241+ DRAWCOUNT値を得る。DRAWCOUNTは16ビット整数値で、1/60秒ごとに1ずつ
242+ 増える。
243+FEOF()
244+ FOPENで開いたファイルの現在のファイル位置が、末端に到達しているかどうか
245+ を返す。1で末端に到達、0で未到達。
246+FGETC()
247+ FOPENで開いたファイルから1バイト読み込み、整数値として返す。ファイル
248+ 末端に到達しているなどで読み込みに失敗した場合、-1を返す。
249+FLEN()
250+ FOPENで開いたファイルのファイル長を、バイト数で返す。
251+FSEEK()
252+ FOPENで開いたファイルの、現在のファイル位置を返す。
253+GCOLOR(x,y)
254+ グラフィック座標(x,y)の表示中パレット番号を返す。
255+GOSUB(xxx [, y [, z [, ... ]]])
256+ GOSUB命令と同じだが、戻り値(RETURNを参照)を得ることが出来る。xxxは、
257+ ラベルもしくは行番号。。yyy, zzz 等は、サブルーチンに引き継がれる引数(
258+ ARGS()関数を参照)。
259+INKEY([x])
260+ xを指定しない場合、現在押されているキーのASCII値を返す。押されていな
261+ い場合は、0。ASCII値でxを指定した場合、そのキーが押されているかどう
262+ かを返す。
263+INT(x#)
264+ 実数値x#を整数値に変換して返す。
265+KEYS([x])
266+ キー入力を得る。xの値は以下の通り。xを指定しない場合は、x=63と同じ。
267+ KEYUP: 1
268+ KEYDOWN: 2
269+ KEYLEFT: 4
270+ KEYRIGHT: 8
271+ KEYSTART: 16
272+ KEYFIRE: 32
273+LEN(x$)
274+ 文字列の長さを返す。
275+MUSIC()
276+ BGMの演奏の残り数を返す。
277+NOT(x)
278+ x=0の場合に1を、そうでない場合に0を返す。
279+PEEK(x)
280+ xで示される物理アドレスから1バイト読み取り、返す。
281+READ()
282+ DATA文の後から、一つずつデーター(32ビット整数値)を読み出す。「CREAD()」
283+ 関数も参照。
284+RND()
285+ 0から32767までの擬似乱数を返す。
286+SGN(x)
287+ xの符号(-1, 0, または1)を返す。
288+STRNCMP(x$,y$,z)
289+ 2つの文字列のうちz文字分を比較し、結果を返す。同じ文字列の場合は0。
290+SYSTEM(x)
291+ 様々なシステム値を、整数値で返す。「<システム変数>」の項を参照。
292+TVRAM([x])
293+ ビデオRAMのx番目の内容を、バイト値で返す。xを省略した場合、ビデオ
294+ RAMの開始位置の物理アドレスを返す。
295+VAL(x$)
296+ 10進数もしくは16進数文字列としてのx$の値を、整数値で返す。
297+
298+<浮動小数点型関数>
299+ACOS#(x#)
300+ x# の逆余弦を実数値で返す。
301+ARGS#(x)
302+ サブルーチン中で、GOSUBに渡されたx番目の引数を実数値として取り出す。
303+ASIN#(x#)
304+ x# の逆正弦を実数値で返す。
305+ATAN#(x#)
306+ x# の逆正接を実数値で返す。
307+ATAN2#(y#,x#)
308+ y#/x# の逆正接を実数値で返す。
309+CEIL#(x#)
310+ x# 以上の最小の整数を実数値で返す。
311+COS#(x#)
312+ x# の余弦を実数値で返す。
313+COSH#(x#)
314+ x# の双曲線余弦を実数値で返す。
315+EXP#(x#)
316+ eを底とする x# の指数関数値を実数値で返す。
317+FABS#(x#)
318+ x# の絶対値を実数値で返す。
319+FLOAT#(x)
320+ 整数値 x を浮動小数点型実数値に変換して返す。
321+FLOOR#(x#)
322+ x# 以下の最大の整数を実数値で返す。
323+FMOD#(x#,y#)
324+ x# を y# で割った剰余を実数値で返す。
325+GOSUB#(xxx [, y [, z [, ... ]]])
326+ GOSUB命令と同じだが、戻り値(RETURNを参照)を得ることが出来る。xxxは、
327+ ラベルもしくは行番号。。yyy, zzz 等は、サブルーチンに引き継がれる引数(
328+ ARGS()関数を参照)。
329+LOG#(x#)
330+ x# の自然対数を実数値で返す。
331+LOG10#(x#)
332+ x# の常用対数を実数値で返す。
333+MODF#(x#)
334+ x# の小数部を実数値で返す。
335+PI#
336+ 3.141593を返す。
337+POW#(x#,y#)
338+ x# の y# 乗を実数値で返す。
339+SIN#(x#)
340+ x# の正弦を実数値で返す。
341+SINH#(x#)
342+ x# の双曲線正弦を実数値で返す。
343+SQRT#(x#)
344+ x# の平方根を実数値で返す。
345+TAN#(x#)
346+ x# の正接を実数値で返す。
347+TANH#(x#)
348+ x# の双曲線正接を実数値で返す。
349+VAL#(x$)
350+ 10進数文字列としてのx$の値を、実数値で返す。
351+
352+<文字列型関数>
353+A$(x [,y])など
354+ xの値が0の場合、文字列全体を返す。
355+ xの値が正の場合、xで示される位置より右側の文字列を返す。
356+ xの値が負のとき、文字列の右側x文字を返す。
357+ yが指定された場合、y文字分の文字列を返す。
358+ARGS$(x)
359+ サブルーチン中で、GOSUBに渡されたx番目の引数を文字列として取り出す。
360+CHR$(x)
361+ xをアスキーコードとする文字を返す。
362+DEC$(x)
363+ xの値を、10進数の文字列として返す。
364+FINPUT$([x])
365+ FOPENで開いたファイルから、xで示された長さの文字列を読み込む。xが省略された
366+ 場合は、行の最後まで読み込む(改行コードが含まれる)。
367+FLOAT$(x#)
368+ 実数値x#を、10進数の文字列として返す。
369+GOSUB$(xxx [, y [, z [, ... ]]])
370+ GOSUB命令と同じだが、戻り値(RETURNを参照)を文字列として得ることが出来る。
371+ xxxは、ラベルもしくは行番号。。yyy, zzz 等は、サブルーチンに引き継がれる引数
372+ (ARGS()関数を参照)。
373+HEX$(x [,y])
374+ xの値を、16進数の文字列として返す。yが指定された場合、yバイト長の
375+ 文字列になる。
376+INPUT$()
377+ 文字列入力状態になり、入力が終了すると(Enterが押されると)文字列を返す。
378+SPRINTF$(x$,y#)
379+ x$で示される書式に従って、実数y#の内容を文字列として返す。
380+SYSTEM$(x)
381+ 様々なシステム値を、文字列で返す。「<システム変数>」の項を参照。
382+READ$()
383+ DATA文の後から、一つずつ文字列データーを読み出す。
384+
385+<整数演算子>
386+-x
387+ 符号を反転
388+x + y
389+ 整数加算
390+x - y
391+ 整数減算
392+x * y
393+ 整数乗算
394+x / y
395+ 整数除算
396+x % y
397+ 整数剰余
398+x >> y
399+ xの値をyビット右シフト
400+x << y
401+ xの値をyビット左シフト
402+x = y
403+ 2つの整数値が等しい場合に1、そうでないときに0
404+x != y
405+ 2つの整数値が等しい場合に0、そうでないときに1
406+x < y
407+ xがyより小さい場合に1、そうでないときに0
408+x <= y
409+ xがyより小さいか等しい場合に1、そうでないときに0
410+x > y
411+ xがyより多きい場合に1、そうでないときに0
412+x >= y
413+ xがyより多きいか等しい場合に1、そうでないときに0
414+x AND y
415+ xとyの値のビットごとの AND(論理積でないことに注意)
416+x OR y
417+ xとyの値のビットごとの OR
418+x XOR y
419+ xとyの値のビットごとの XOR
420+
421+なお、整数演算子の優先順位は、優先度が高いものから以下の順です。
422+
423++ - (単項演算子)
424+* / %
425++ - (加算・減算)
426+<< >>
427+< <= > >=
428+= !=
429+XOR
430+AND
431+OR
432+
433+<文字列演算子>
434+x$ + y$
435+ 文字列の連結
436+
437+<浮動小数点型演算子>
438+-x#
439+ 符号を反転
440+x# + y#
441+ 実数加算
442+x# - y#
443+ 実数減算
444+x# * y#
445+ 実数乗算
446+x# / y#
447+ 実数除算
448+x# = y#
449+ 2つの実数値が等しい場合に1、そうでないときに0
450+x# != y#
451+ 2つの実数値が等しい場合に0、そうでないときに1
452+x# < y#
453+ xがyより小さい場合に1、そうでないときに0
454+x# <= y#
455+ xがyより小さいか等しい場合に1、そうでないときに0
456+x# > y#
457+ xがyより多きい場合に1、そうでないときに0
458+x# >= y#
459+ xがyより多きいか等しい場合に1、そうでないときに0
460+x# AND y#
461+ xとyの値の論理積(ビットごとの AND でないことに注意)
462+x# OR y#
463+ xとyの値の論理和(ビットごとの OR でないことに注意)
464+
465+なお、実数演算子の優先順位は、優先度が高いものから以下の順です。
466+
467++ - (単項演算子)
468+* /
469++ - (加算・減算)
470+< <= > >=
471+= !=
472+AND
473+OR
474+
475+<MUSIC>
476+MUSIC命令では、BGM用のデーターを文字列で指定します。文字列の書式は、ABC
477+notationに準拠しています。ただし、すべての記法が使えるわけではありません。
478+なお、キーや速度などのデフォルト設定値は以下の通りです。
479+
480+Q: 1/4=90
481+L: 1/8
482+K: C
483+
484+BGM演奏時に一度に設定できる音の数は、31迄です。これを超えて音楽を再生したい
485+場合は、MUSIC()関数の戻り値を調べ、その値が十分小さくなってから、次のMUSIC命
486+令を実行するようにします。
487+
488+添付のmusic.basに、使い方に関するサンプルがありますので、参考にして下さい。
489+
490+<SOUND>
491+SOUND命令では、DATA列のデーターを、行番号もしくはラベルで指定します。SOUND命
492+令による効果音再生中は、BGMは再生されません。また、前の効果音が終わる前に次
493+のSOUND命令を実行すると、前の効果音の再生は停止し、新しい効果音がすぐに再生
494+されます。
495+
496+DATA列では、32ビット整数値として、交換音を表現します。この整数値の下位16
497+ビットは周波数の指定です。2048が440Hz(ラの音)に対応します。値が大きくなるほ
498+ど、より低い音が出ます。上位16ビットは、音の長さです。1が、1/60秒に相当し
499+ます。最後に、65535以下の値で、効果音の繰り返し回数を指定します。これらのデー
500+ターの数は、32を超えないようにして下さい。
501+
502+添付のsound.basに、使い方に関するサンプルがありますので、参考にして下さい。
503+
504+<PCG>
505+PCG(Programmable Character Generator)を用いると、ASCIIコードごとにフォント
506+を指定して、疑似グラフィックスとして表示させることが出来ます。使用する場合
507+は、まず
508+
509+USEPCG
510+
511+とします。フォントの変更は、PCGステートメントを用いて、
512+
513+PCG 0x80,0x80402010,0x08040201
514+
515+の様に設定します。この例では、ASCIIコード0x80の文字のフォントを設定してい
516+て、バックスラッシュの様な記号(左上から右下に向かう斜め線)が表示されるよう
517+になります。PCGの利用を停止し、オリジナルのフォントに戻す場合は、
518+
519+USEPCG 0
520+
521+とします。再度PCGを使用したい場合は、
522+
523+USEPCG
524+
525+として下さい。先に設定したフォントデーターが、復活します。なお、先に設定し
526+たフォントデーターを破棄してPCGの使用を始めたい場合は、
527+
528+USEPCG 2
529+
530+として下さい。
531+
532+<システム変数>
533+SYSTEM関数及びSYSTEMステートメントを用いて、各種システム情報をやりとりするこ
534+とが出来ます。
535+
536+SYSTEM$(0)
537+ MachiKania バージョン文字列、"Zoea"を返す。
538+SYSTEM$(1)
539+ MachiKania バージョン文字列、"1.0"等を返す。
540+SYSTEM$(2)
541+ BASIC バージョン文字列、"KM-1200"等を返す。
542+SYSTEM$(3)
543+ 現在実行中のHEXファイル名、"ZOEA.HEX"等を返す。
544+SYSTEM(20)
545+ キャラクターディスプレイ横幅を返す。
546+SYSTEM(21)
547+ キャラクターディスプレイ縦幅を返す。
548+SYSTEM(22)
549+ グラフィックディスプレイ横幅を返す。
550+SYSTEM(23)
551+ グラフィックディスプレイ横幅を返す。
552+SYSTEM(24)
553+ キャラクターディスプレイ用の指定色を返す。
554+SYSTEM(25)
555+ グラフィックディスプレイ用の指定色を返す。
556+SYSTEM(26)
557+ キャラクターディスプレイの、現在のX位置を返す。
558+SYSTEM(27)
559+ キャラクターディスプレイの、現在のY位置を返す。
560+SYSTEM(28)
561+ グラフィックディスプレイの、現在のX位置を返す。
562+SYSTEM(29)
563+ グラフィックディスプレイの、現在のY位置を返す。
564+SYSTEM(40)
565+ PS/2キーボードを使用中かどうかを返す。
566+SYSTEM(41)
567+ PS/2キーボード情報、vkeyを返す。
568+SYSTEM(42)
569+ PS/2キーボード情報、lockkeyを返す。
570+SYSTEM(43)
571+ PS/2キーボード情報、keytypeを返す。
572+SYSTEM(100)
573+ 変数格納領域(g_var_mem)へのポインターを返す。
574+SYSTEM(101)
575+ 乱数シードへのポインターを返す。
576+SYSTEM(102)
577+ キャラクターディスプレイ領域(TVRAM)へのポインターを返す。
578+SYSTEM(103)
579+ フォント領域へのポインターを返す。
580+SYSTEM(104)
581+ PCGフォント領域へのポインターを返す。
582+SYSTEM(105)
583+ グラフィックディスプレイ領域へのポインターを返す。
584+SYSTEM 200,x
585+ ディスプレイの表示を停止(xが0のとき)、もしくは開始(xが0以外の時)する。
586+
587+<ヒント>
588+FOR-NEXTループ、WHILE-WENDループ、DO-LOOPループの途中で、GOTO文でループの
589+外に飛んだり、RETURN文を実行したりすると、予期せぬ結果(機器のリセット等)を
590+引き起こします。ただし、GOSUB文でサブルーチンを呼んだり、別のループをネスト
591+して使う事は可能です。
592+
593+ON GOTO分やON GOSUB文はサポートしていません。ただし、例えば次のように記述す
594+ることで、同様の動作をさせることは可能です。
595+ GOSUB 10000+A
596+ ....
597+ 10000 PRINT "A=0" : RETURN
598+ 10001 PRINT "A=1" : RETURN
599+ 10002 PRINT "A=2" : RETURN
600+
601+一行中で連続して文字列を扱うと、"String too complexed"というエラーがでて、
602+停止することがあります。この場合は、文字列を扱う命令を独立した行するか、文
603+字列関連の演算を幾つかのステップに分けて、それぞれ1行ずつの記述にして試し
604+てみて下さい。
605+
606+<バージョン履歴>
607+・KM-1205 2018年2月公開。
608+ 1.スタック容量拡大のため、使用可能RAM容量を53Kバイトに削減。
609+ 2.CLEARステートメントの不具合を修正。
610+・KM-1204 2017年8月公開。
611+ 1.USEVARステートメントを追加。
612+ 2.CLEARステートメント実行でグラフィックモードから抜けるように変更。
613+・KM-1203 2017年1月公開。
614+ 1.ファイル入出力機能を追加。
615+・KM-1202 2016年10月公開。
616+ 1.WIDTHステートメントを追加。
617+ 2.特殊なデーター列・文字列に於ける、リンク時の不具合及びREAD()関数実行時
618+   に於ける不具合を修正。
619+ 3.多次元配列中で演算子を使った場合の不具合を解消。
620+・KM-1201 2016年9月公開。
621+ 1.CONTINUEステートメントを追加。
622+ 2.ATAN2#()関数を追加。
623+ 3.IF-THEN-ELSEステートメントでエラーがでる不具合を修正。
624+ 4.負の実数値の扱いにおける不具合を修正。
625+・KM-1200 2016年8月公開。
626+ 1.グラフィックディスプレイ機能および、関連のステートメント群を追加。
627+ 2.浮動小数点演算機能、及び、算術演算関数群を追加。
628+ 3.VAR, BREAK, SYSTEMステートメントを追加。
629+ 4.DO-LOOP, WHILE-WENDループ構造文を追加。
630+ 5.IF THEN - ELSEIF - ELSE - ENDIFによる、複数行での条件分岐表現を追加。
631+ 6.GOSUBステートメント及びGOSUB()関数に第二以降の引数を指定出来る様にし、
632+   サブルーチン中でARGS()関数により取り出せるようにした。
633+ 7.8ビット整数型を扱うCDATAステートメントとCREAD()関数を追加。
634+ 8.DATAステートメントで文字列を扱える様にし、READ$()で読めるようにした。
635+ 9.多次元配列をサポート。
636+ 10.例外発生時に、情報を表示するようにした。
637+ 11.FOR-NEXTループに於いて、TO値に一致する時だけではなく、値を超えた場合
638+   でもループを抜けるようにした。
639+ 12.MUSICステートメント用のスクリプトにエラーがある際、エラー発生行が正し
640+   く表示されない不具合を修正。
641+ 13.ビットシフト演算子を、追加。
642+
643+・KM-1120 2016年2月公開。
644+ 1.PCG機能を追加。
645+ 2.SCROLL命令を追加。
646+ 3.WAIT命令を追加。
647+ 4.「Ctrl+Break」キーによる実行停止に対応。
648+ 5.FOR無しでNEXTを実行した場合、GOSUB無しでRETURNを実行した場合にエラー
649+   を表示して停止するようにした。
650+
651+・Ver 1.1.0 (KM-1110) 2015年12月公開。
652+ 1.2015年11月21日に変更されたPIC32TVGSの仕様に対応。
653+ 2.PS/2キーボードに対応。
654+ 3.INKEY() INPUT$() VAL() DEC$() の4つの関数を追加。
655+ 4.TVRAM() ASC() PEEK()が、0x80-0xFFの値に関して負の数を返していた不具合
656+   を修正。
657+ 5.DIMステートメントにより配列を定義した際、すべての要素がゼロになるよう
658+   にした。
659+ 6.単項演算子、「-」「+」を追加。
660+ 7.LABEL定義されていない飛び先にGOTOするとリセットされる不具合を修正。
661+ 8.同一のLABELを複数回使用している場合に、コンパイルエラーが出るように修
662+   正。
663+ 9.引数を持たないPRINT文に対応。
664+
665+・Ver 1.0.5 (KM-1100) 最初の正規公開バージョン。
--- /dev/null
+++ b/mips/zoea/keyinput.c
@@ -0,0 +1,203 @@
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+// キー入力、カーソル表示関連機能 by K.Tanaka
7+// PS/2キーボード入力システム、カラーテキスト出力システム利用
8+
9+#include "videoout.h"
10+#include "ps2keyboard.h"
11+#include "keyinput.h"
12+
13+unsigned char lineinputbuf[256]; //lineinput関数用一時バッファ
14+unsigned char blinkchar,blinkcolor;
15+int blinktimer;
16+int insertmode; //挿入モード:1、上書きモード:0
17+
18+void getcursorchar(){
19+// カーソル点滅用に元の文字コードを退避
20+ blinkchar=*cursor;
21+ if(twidth==WIDTH_X1) blinkcolor=*(cursor+ATTROFFSET1);
22+ else blinkcolor=*(cursor+ATTROFFSET2);
23+}
24+void resetcursorchar(){
25+// カーソルを元の文字に戻す
26+ *cursor=blinkchar;
27+ if(twidth==WIDTH_X1) *(cursor+ATTROFFSET1)=blinkcolor;
28+ else *(cursor+ATTROFFSET2)=blinkcolor;
29+}
30+void blinkcursorchar(){
31+// 定期的に呼び出すことでカーソルを点滅表示させる
32+// BLINKTIMEで点滅間隔を設定
33+// 事前にgetcursorchar()を呼び出しておく
34+ blinktimer++;
35+ if(blinktimer>=BLINKTIME*2) blinktimer=0;
36+ if(blinktimer<BLINKTIME){
37+ if(insertmode) *cursor=CURSORCHAR;
38+ else *cursor=CURSORCHAR2;
39+ if(twidth==WIDTH_X1) *(cursor+ATTROFFSET1)=CURSORCOLOR;
40+ else *(cursor+ATTROFFSET2)=CURSORCOLOR;
41+ }
42+ else{
43+ *cursor=blinkchar;
44+ if(twidth==WIDTH_X1) *(cursor+ATTROFFSET1)=blinkcolor;
45+ else *(cursor+ATTROFFSET2)=blinkcolor;
46+ }
47+}
48+
49+unsigned char inputchar(void){
50+// キーボードから1キー入力待ち
51+// 戻り値 通常文字の場合ASCIIコード、その他は0、グローバル変数vkeyに仮想キーコード
52+ unsigned char k;
53+ unsigned short d;
54+ d=drawcount;
55+ while(1){
56+ while(d==drawcount) asm("wait"); //60分の1秒ウェイト
57+ d=drawcount;
58+ k=ps2readkey(); //キーバッファから読み込み、k1:通常文字入力の場合ASCIIコード
59+ if(vkey) return k;
60+ }
61+}
62+
63+unsigned char cursorinputchar(void){
64+// カーソル表示しながらキーボードから1キー入力待ち
65+// 戻り値 通常文字の場合ASCIIコード、その他は0、グローバル変数vkeyに仮想キーコード
66+ unsigned char k;
67+ unsigned short d;
68+ getcursorchar(); //カーソル位置の文字を退避(カーソル点滅用)
69+ d=drawcount;
70+ while(1){
71+ while(d==drawcount) asm("wait"); //60分の1秒ウェイト
72+ d=drawcount;
73+ blinkcursorchar(); //カーソル点滅させる
74+ k=ps2readkey(); //キーバッファから読み込み、k1:通常文字入力の場合ASCIIコード
75+ if(vkey) break; //キーが押された場合ループから抜ける
76+ }
77+ resetcursorchar(); //カーソルを元の文字表示に戻す
78+ return k;
79+}
80+
81+unsigned char printinputchar(void){
82+// カーソル表示しながらキーボードから通常文字キー入力待ちし、入力された文字を表示
83+// 戻り値 入力された文字のASCIIコード、グローバル変数vkeyに最後に押されたキーの仮想キーコード
84+ unsigned char k;
85+ while(1){
86+ k=cursorinputchar();
87+ if(k) break;
88+ }
89+ printchar(k);
90+ return k;
91+}
92+
93+int lineinput(char *s,int n){
94+// キー入力して文字列配列sに格納
95+// sに初期文字列を入れておくと最初に表示して文字列の最後にカーソル移動する
96+// 初期文字列を使用しない場合は*s=0としておく
97+// カーソル位置はsetcursor関数で指定しておく
98+// 最大文字数n、最後に0を格納するのでn+1バイトの領域必要、ただしnの最大値は255
99+// 戻り値 Enterで終了した場合0、ESCで終了時は-1(sは壊さない)
100+//
101+ unsigned char *ps,*pd,*pc;
102+ unsigned char k1,k2;
103+ int i;
104+
105+ if(n>255) return -1;
106+ ps=s;
107+ pd=lineinputbuf;
108+ i=0;
109+ //初期文字列をlineinputbufにコピーし、文字数をiに入れる
110+ while(*ps!=0 && i<n){
111+ *pd++=*ps++;
112+ i++;
113+ }
114+ *pd=0;//バッファ内の文字列最後に0
115+ pc=pd;//現在の文字入力位置ポインタ(最後尾)
116+ if(i>0) printstr(lineinputbuf); //初期文字列表示
117+ while(1){
118+ k1=cursorinputchar(); //カーソル表示しながら1キー入力待ち
119+ k2=(unsigned char)vkey; //k2:仮想キーコード
120+ if(k1){
121+ //通常文字の場合
122+ if(insertmode || *pc==0){
123+ //挿入モードまたは最後尾の場合
124+ if(i==n) continue; //入力文字数最大値の場合無視
125+ for(pd=lineinputbuf+i;pd>=pc;pd--) *(pd+1)=*pd; //1文字分挿入
126+ i++;
127+ }
128+ *pc=k1; //入力文字を追加
129+ printstr(pc); //入力文字以降を表示
130+ pc++;
131+ for(ps=lineinputbuf+i;ps>pc;ps--) cursor--; //カーソル位置戻し
132+ }
133+ else switch(k2){
134+ //制御文字の場合
135+ case VK_LEFT:
136+ case VK_NUMPAD4:
137+ //左矢印キー
138+ if(pc>lineinputbuf){
139+ pc--;
140+ cursor--;
141+ }
142+ break;
143+ case VK_RIGHT:
144+ case VK_NUMPAD6:
145+ //右矢印キー
146+ if(*pc!=0){
147+ pc++;
148+ cursor++;
149+ }
150+ break;
151+ case VK_RETURN: //Enterキー
152+ case VK_SEPARATOR: //テンキーのEnter
153+ //入力用バッファから呼び出し元のバッファにコピーして終了
154+ printchar('\n');
155+ ps=lineinputbuf;
156+ pd=s;
157+ while(*ps!=0) *pd++=*ps++;
158+ *pd=0;
159+ return 0;
160+ case VK_HOME:
161+ case VK_NUMPAD7:
162+ //Homeキー、文字列先頭にカーソル移動
163+ while(pc>lineinputbuf){
164+ pc--;
165+ cursor--;
166+ }
167+ break;
168+ case VK_END:
169+ case VK_NUMPAD1:
170+ //Endキー、文字列最後尾にカーソル移動
171+ while(*pc!=0){
172+ pc++;
173+ cursor++;
174+ }
175+ break;
176+ case VK_BACK:
177+ //Back Spaceキー、1文字左に移動しDelete処理
178+ if(pc==lineinputbuf) break;//カーソルが先頭の場合、無視
179+ pc--;
180+ cursor--;
181+ case VK_DELETE:
182+ case VK_DECIMAL:
183+ //Deleteキー、カーソル位置の1文字削除
184+ if(*pc==0) break;//カーソルが最後尾の場合、無視
185+ for(pd=pc;*(pd+1)!=0;pd++) *pd=*(pd+1);
186+ *pd=0;
187+ i--;
188+ printstr(pc);
189+ printchar(0);//NULL文字表示
190+ for(ps=lineinputbuf+i+1;ps>pc;ps--) cursor--;
191+ break;
192+ case VK_INSERT:
193+ case VK_NUMPAD0:
194+ //Insertキー、挿入モードトグル動作
195+ insertmode^=1;
196+ break;
197+ case VK_ESCAPE:
198+ case VK_CANCEL:
199+ //ESCキーまたはCTRL+Breakキー、-1で終了
200+ return -1;
201+ }
202+ }
203+}
--- /dev/null
+++ b/mips/zoea/keyinput.h
@@ -0,0 +1,45 @@
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+extern unsigned char blinkchar,blinkcolor;
44+extern int blinktimer;
45+extern int insertmode; //挿入モード:1、上書きモード:0
--- /dev/null
+++ b/mips/zoea/library.c
@@ -0,0 +1,1293 @@
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+#include "keyinput.h"
13+#include "stdlib.h"
14+#include "math.h"
15+
16+/*
17+ Local global variables used for graphic
18+ */
19+
20+static int g_gcolor=7;
21+static int g_prev_x=0;
22+static int g_prev_y=0;
23+
24+int lib_read(int mode, unsigned int label){
25+ unsigned int i,code,code2;
26+ static unsigned int pos=0;
27+ static unsigned int in_data=0;
28+ static unsigned char skip=0;
29+ if (label) {
30+ // RESTORE function
31+ switch(mode){
32+ case 0:
33+ // label is label data
34+ i=(int)search_label(label);
35+ if (!i) {
36+ err_data_not_found();
37+ return 0;
38+ }
39+ break;
40+ case 1:
41+ // label is pointer
42+ i=label;
43+ break;
44+ case 2:
45+ default:
46+ // Reset data/read
47+ pos=0;
48+ in_data=0;
49+ skip=0;
50+ return 0;
51+ }
52+ i-=(int)(&g_object[0]);
53+ pos=i/4;
54+ in_data=0;
55+ }
56+ // Get data
57+ if (in_data==0) {
58+ for(i=pos;i<g_objpos;i++){
59+ code=g_object[i];
60+ code2=g_object[i+1];
61+ if ((code&0xFFFF0000)!=0x04110000) continue;
62+ // "bgezal zero," assembly found.
63+ // Check if 0x00000020,0x00000021,0x00000022, or 0x00000023 follows
64+ if ((code2&0xfffffffc)!=0x00000020) {// add/addu/sub/subu zero,zero,zero
65+ // If not, skip following block (it's strig).
66+ i+=code&0x0000FFFF;
67+ continue;
68+ }
69+ // DATA region found.
70+ in_data=(code&0x0000FFFF)-1;
71+ pos=i+2;
72+ skip=code2&0x03;
73+ break;
74+ }
75+ if (g_objpos<=i) {
76+ err_data_not_found();
77+ return 0;
78+ }
79+ }
80+ if (label) {
81+ // RESTORE function. Return pointer.
82+ return ((int)&g_object[pos])+skip;
83+ } else {
84+ switch(mode){
85+ case 0:
86+ // READ() function
87+ in_data--;
88+ return g_object[pos++];
89+ case 1:
90+ default:
91+ // CREAD() function
92+ i=g_object[pos];
93+ i>>=skip*8;
94+ i&=0xff;
95+ if ((++skip)==4) {
96+ skip=0;
97+ in_data--;
98+ pos++;
99+ }
100+ return i;
101+ }
102+ }
103+}
104+
105+void reset_dataread(){
106+ lib_read(2,1);
107+}
108+
109+char* lib_midstr(int var_num, int pos, int len){
110+ int i;
111+ char* str;
112+ char* ret;
113+ if (0<=pos) {
114+ // String after "pos" position.
115+ str=(char*)(g_var_mem[var_num]+pos);
116+ } else {
117+ // String right "pos" characters.
118+ // Determine length
119+ str=(char*)g_var_mem[var_num];
120+ for(i=0;str[i];i++);
121+ if (0<=(i+pos)) {
122+ str=(char*)(g_var_mem[var_num]+i+pos);
123+ }
124+ }
125+ if (len<0) {
126+ // Length is not specified.
127+ // Return the string to the end.
128+ return str;
129+ }
130+ // Length is specified.
131+ // Construct temporary string containing specified number of characters.
132+ ret=alloc_memory((len+1+3)/4,-1);
133+ // Copy string.
134+ for(i=0;(ret[i]=str[i])&&(i<len);i++);
135+ ret[len]=0x00;
136+ return ret;
137+}
138+
139+void lib_clear(void){
140+ int i;
141+ // All variables (including temporary and permanent ones) will be integer 0
142+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
143+ g_var_mem[i]=0;
144+ }
145+ // Clear memory allocation area
146+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
147+ g_var_size[i]=0;
148+ }
149+ // Cancel PCG
150+ stopPCG();
151+ g_pcg_font=0;
152+ // Stop using graphic
153+ set_graphmode(0);
154+ g_use_graphic=0;
155+}
156+
157+void lib_let_str(char* str, int var_num){
158+ int begin,end,size;
159+ // Save pointer
160+ g_var_mem[var_num]=(int)str;
161+ // Determine size
162+ for(size=0;str[size];size++);
163+ // Check if str is in heap area.
164+ begin=(int)str;
165+ end=(int)(&str[size]);
166+ if (begin<(int)(&g_heap_mem[0]) || (int)(&g_heap_mem[g_max_mem])<=end) {
167+ // String is not within allcated block
168+ return;
169+ }
170+ // Str is in heap area. Calculate values stored in heap data dimension
171+ begin-=(int)(&g_heap_mem[0]);
172+ begin>>=2;
173+ end-=(int)(&g_heap_mem[0]);
174+ end>>=2;
175+ size=end-begin+1;
176+ g_var_pointer[var_num]=begin;
177+ g_var_size[var_num]=size;
178+}
179+
180+int lib_rnd(){
181+ int y;
182+ y=g_rnd_seed;
183+ y = y ^ (y << 13);
184+ y = y ^ (y >> 17);
185+ y = y ^ (y << 5);
186+ g_rnd_seed=y;
187+ return y&0x7fff;
188+}
189+
190+char* lib_chr(int num){
191+ char* str;
192+ str=alloc_memory(1,-1);
193+ str[0]=num&0x000000FF;
194+ str[1]=0x00;
195+ return str;
196+}
197+
198+char* lib_dec(int num){
199+ char* str;
200+ int i,j,minus;
201+ char b[12];
202+ b[11]=0x00;
203+ if (num<0) {
204+ minus=1;
205+ num=0-num;
206+ } else {
207+ minus=0;
208+ }
209+ for (i=10;0<i;i--) {
210+ if (num==0 && i<10) break;
211+ b[i]='0'+rem10_32(num);
212+ num=div10_32(num);
213+ }
214+ if (minus) {
215+ b[i]='-';
216+ } else {
217+ i++;
218+ }
219+ str=alloc_memory(3,-1);
220+ for(j=0;str[j]=b[i++];j++);
221+ return str;
222+}
223+
224+char* lib_hex(int num, int width){
225+ char* str;
226+ int i,j,minus;
227+ char b[8];
228+ str=alloc_memory(3,-1);
229+ for(i=0;i<8;i++){
230+ b[i]="0123456789ABCDEF"[(num>>(i<<2))&0x0F];
231+ }
232+ // Width must be between 0 and 8;
233+ if (width<0||8<width) width=8;
234+ if (width==0) {
235+ // Width not asigned. Use minimum width.
236+ for(i=7;0<i;i--){
237+ if ('0'<b[i]) break;
238+ }
239+ } else {
240+ // Constant width
241+ i=width-1;
242+ }
243+ // Copy string to allocated block.
244+ for(j=0;0<=i;i--){
245+ str[j++]=b[i];
246+ }
247+ str[j]=0x00;
248+ return str;
249+}
250+
251+char* lib_connect_string(char* str1, char* str2){
252+ int i,j;
253+ char b;
254+ char* result;
255+ // Determine total length
256+ for(i=0;str1[i];i++);
257+ for(j=0;str2[j];j++);
258+ // Allocate a block for new string
259+ result=alloc_memory((i+j+1+3)/4,-1);
260+ // Create connected strings
261+ for(i=0;b=str1[i];i++) result[i]=b;
262+ for(j=0;b=str2[j];j++) result[i+j]=b;
263+ result[i+j]=0x00;
264+ free_temp_str(str1);
265+ free_temp_str(str2);
266+ return result;
267+}
268+
269+void lib_string(int mode){
270+ int i;
271+ switch(mode){
272+ case 0:
273+ // CR
274+ printchar('\n');
275+ return;
276+ case 1:
277+ // ,
278+#ifdef MEGALOPA
279+ i=rem9_32((unsigned int)(cursor-TVRAM));
280+ printstr(" "+i);
281+#else
282+ i=rem10_32((unsigned int)(cursor-TVRAM));
283+ printstr(" "+i);
284+#endif
285+ return;
286+ default:
287+ return;
288+ }
289+}
290+
291+void* lib_label(unsigned int label){
292+ // This routine is used to jump to address dynamically determined
293+ // in the code; for example: "GOTO 100+I"
294+ unsigned int i,code,search;
295+ void* ret;
296+ if (label&0xFFFF0000) {
297+ // Label is not supported.
298+ // Line number must bs less than 65536.
299+ err_label_not_found();
300+ } else {
301+ // Line number
302+ ret=search_label(label);
303+ if (ret) return ret;
304+ // Line number not found.
305+ err_label_not_found();
306+ }
307+}
308+
309+int lib_keys(int mask){
310+ int keys;
311+ // Enable tact switches
312+ if (inPS2MODE()) {
313+ buttonmode();
314+ }
315+
316+ keys=KEYPORT;
317+ keys=
318+ ((keys&KEYUP)? 0:1)|
319+ ((keys&KEYDOWN)? 0:2)|
320+ ((keys&KEYLEFT)? 0:4)|
321+ ((keys&KEYRIGHT)? 0:8)|
322+ ((keys&KEYSTART)? 0:16)|
323+ ((keys&KEYFIRE)? 0:32);
324+ return mask&keys;
325+}
326+
327+int lib_val(char* str){
328+ int i;
329+ int val=0;
330+ int sign=1;
331+ char b;
332+ // Skip blanc
333+ for(i=0;0<=str[i] && str[i]<0x21;i++);
334+ // Skip '+'
335+ if (str[i]=='+') i++;
336+ // Check '-'
337+ if (str[i]=='-') {
338+ sign=-1;
339+ i++;
340+ }
341+ // Check '0x' or '$'
342+ if (str[i]=='$' || str[i]=='0' && (str[i+1]=='x' || str[i+1]=='X')) {
343+ // Hexadecimal
344+ if (str[i++]=='0') i++;
345+ while(1) {
346+ b=str[i++];
347+ if ('0'<=b && b<='9') {
348+ val<<=4;
349+ val+=b-'0';
350+ } else if ('a'<=b && b<='f') {
351+ val<<=4;
352+ val+=b-'a'+10;
353+ } else if ('A'<=b && b<='F') {
354+ val<<=4;
355+ val+=b-'A'+10;
356+ } else {
357+ break;
358+ }
359+ }
360+ } else {
361+ // Decimal
362+ while(1) {
363+ b=str[i++];
364+ if ('0'<=b && b<='9') {
365+ val*=10;
366+ val+=b-'0';
367+ } else {
368+ break;
369+ }
370+ }
371+ }
372+ return val*sign;
373+}
374+
375+char* lib_input(){
376+ // Allocate memory for strings with 63 characters
377+ char *str=calloc_memory((63+1)/4,-1);
378+ // Enable PS/2 keyboard
379+ if (!inPS2MODE()) {
380+ ps2mode();
381+ ps2init();
382+ }
383+ // Clear key buffer
384+ do ps2readkey();
385+ while(vkey!=0);
386+ // Get string as a line
387+ lineinput(str,63);
388+ check_break();
389+ return str;
390+}
391+
392+unsigned char lib_inkey(int key){
393+ int i;
394+ // Enable PS/2 keyboard
395+ if (!inPS2MODE()) {
396+ ps2mode();
397+ ps2init();
398+ }
399+ if (key) {
400+ return ps2keystatus[key&0xff];
401+ } else {
402+ for(i=0;i<256;i++){
403+ if (ps2keystatus[i]) return i;
404+ }
405+ return 0;
406+ }
407+}
408+
409+void lib_usepcg(int mode){
410+ // Modes; 0: stop PCG, 1: use PCG, 2: reset PCG and use it
411+ switch(mode){
412+ case 0:
413+ // Stop PCG
414+ stopPCG();
415+ break;
416+ case 2:
417+ // Reset PCG and use it
418+ if (g_pcg_font) {
419+ free_temp_str(g_pcg_font);
420+ g_pcg_font=0;
421+ }
422+ // Continue to case 1:
423+ case 1:
424+ default:
425+ // Use PCG
426+ if (g_pcg_font) {
427+ startPCG(g_pcg_font,0);
428+ } else {
429+ g_pcg_font=alloc_memory(256*8/4,ALLOC_PCG_BLOCK);
430+ startPCG(g_pcg_font,1);
431+ }
432+ break;
433+ }
434+}
435+
436+void lib_pcg(unsigned int ascii,unsigned int fontdata1,unsigned int fontdata2){
437+ unsigned int* pcg;
438+ // If USEPCG has not yet executed, do now.
439+ if (!g_pcg_font) lib_usepcg(1);
440+ pcg=(unsigned int*)g_pcg_font;
441+ // 0 <= ascii <= 0xff
442+ ascii&=0xff;
443+ // Update font data
444+ ascii<<=1;
445+ pcg[ascii]=(fontdata1>>24)|((fontdata1&0xff0000)>>8)|((fontdata1&0xff00)<<8)|(fontdata1<<24);
446+ pcg[ascii+1]=(fontdata2>>24)|((fontdata2&0xff0000)>>8)|((fontdata2&0xff00)<<8)|(fontdata2<<24);
447+}
448+
449+void lib_scroll(int x,int y){
450+ int i,j;
451+ int vector=y*WIDTH_X1+x;
452+ if (vector<0) {
453+ // Copy data from upper address to lower address
454+ for(i=0-vector;i<WIDTH_X1*WIDTH_Y;i++){
455+ TVRAM[i+vector]=TVRAM[i];
456+ TVRAM[WIDTH_X1*WIDTH_Y+i+vector]=TVRAM[WIDTH_X1*WIDTH_Y+i];
457+ }
458+ } else if (0<vector) {
459+ // Copy data from lower address to upper address
460+ for(i=WIDTH_X1*WIDTH_Y-vector-1;0<=i;i--){
461+ TVRAM[i+vector]=TVRAM[i];
462+ TVRAM[WIDTH_X1*WIDTH_Y+i+vector]=TVRAM[WIDTH_X1*WIDTH_Y+i];
463+ }
464+ } else {
465+ return;
466+ }
467+ if (x<0) {
468+ // Fill blanc at right
469+ for(i=x;i<0;i++){
470+ for(j=WIDTH_X1+i;j<WIDTH_X1*WIDTH_Y;j+=WIDTH_X1){
471+ TVRAM[j]=0x00;
472+ TVRAM[WIDTH_X1*WIDTH_Y+j]=cursorcolor;
473+ }
474+ }
475+ } else if (0<x) {
476+ // Fill blanc at left
477+ for(i=0;i<x;i++){
478+ for(j=i;j<WIDTH_X1*WIDTH_Y;j+=WIDTH_X1){
479+ TVRAM[j]=0x00;
480+ TVRAM[WIDTH_X1*WIDTH_Y+j]=cursorcolor;
481+ }
482+ }
483+ }
484+ if (y<0) {
485+ // Fill blanc at bottom
486+ for(i=WIDTH_X1*(WIDTH_Y+y);i<WIDTH_X1*WIDTH_Y;i++){
487+ TVRAM[i]=0x00;
488+ TVRAM[WIDTH_X1*WIDTH_Y+i]=cursorcolor;
489+ }
490+ } else if (0<y) {
491+ // Fill blanc at top
492+ for(i=0;i<WIDTH_X1*y;i++){
493+ TVRAM[i]=0x00;
494+ TVRAM[WIDTH_X1*WIDTH_Y+i]=cursorcolor;
495+ }
496+ }
497+}
498+
499+void lib_scroll40(int x,int y){
500+ int i,j;
501+ int vector=y*WIDTH_X2+x;
502+ if (vector<0) {
503+ // Copy data from upper address to lower address
504+ for(i=0-vector;i<WIDTH_X2*WIDTH_Y;i++){
505+ TVRAM[i+vector]=TVRAM[i];
506+ TVRAM[WIDTH_X2*WIDTH_Y+i+vector]=TVRAM[WIDTH_X2*WIDTH_Y+i];
507+ }
508+ } else if (0<vector) {
509+ // Copy data from lower address to upper address
510+ for(i=WIDTH_X2*WIDTH_Y-vector-1;0<=i;i--){
511+ TVRAM[i+vector]=TVRAM[i];
512+ TVRAM[WIDTH_X2*WIDTH_Y+i+vector]=TVRAM[WIDTH_X2*WIDTH_Y+i];
513+ }
514+ } else {
515+ return;
516+ }
517+ if (x<0) {
518+ // Fill blanc at right
519+ for(i=x;i<0;i++){
520+ for(j=WIDTH_X2+i;j<WIDTH_X2*WIDTH_Y;j+=WIDTH_X2){
521+ TVRAM[j]=0x00;
522+ TVRAM[WIDTH_X2*WIDTH_Y+j]=cursorcolor;
523+ }
524+ }
525+ } else if (0<x) {
526+ // Fill blanc at left
527+ for(i=0;i<x;i++){
528+ for(j=i;j<WIDTH_X2*WIDTH_Y;j+=WIDTH_X2){
529+ TVRAM[j]=0x00;
530+ TVRAM[WIDTH_X2*WIDTH_Y+j]=cursorcolor;
531+ }
532+ }
533+ }
534+ if (y<0) {
535+ // Fill blanc at bottom
536+ for(i=WIDTH_X2*(WIDTH_Y+y);i<WIDTH_X2*WIDTH_Y;i++){
537+ TVRAM[i]=0x00;
538+ TVRAM[WIDTH_X2*WIDTH_Y+i]=cursorcolor;
539+ }
540+ } else if (0<y) {
541+ // Fill blanc at top
542+ for(i=0;i<WIDTH_X2*y;i++){
543+ TVRAM[i]=0x00;
544+ TVRAM[WIDTH_X2*WIDTH_Y+i]=cursorcolor;
545+ }
546+ }
547+}
548+
549+void lib_wait(int period){
550+ int i;
551+ unsigned short dcount;
552+ for(i=0;i<period;i++){
553+ dcount=drawcount;
554+ while(dcount==drawcount){
555+ asm (WAIT);
556+ check_break();
557+ }
558+ }
559+}
560+
561+void allocate_graphic_area(){
562+ if (!g_graphic_area) {
563+ // Use this pointer like unsigned short GVRAM[G_H_WORD*G_Y_RES] __attribute__ ((aligned (4)));
564+ g_graphic_area=alloc_memory(G_H_WORD*G_Y_RES/2,ALLOC_GRAPHIC_BLOCK);
565+ // Start graphic and clear screen
566+ init_graphic(g_graphic_area);
567+ // Move current point to (0,0)
568+ g_prev_x=g_prev_y=0;
569+ }
570+}
571+
572+void lib_usegraphic(int mode){
573+ // Modes; 0: stop GRAPHIC, 1: use GRAPHIC, 2: reset GRAPHIC and use it
574+ switch(mode){
575+ case 0:
576+ if (g_use_graphic){
577+ // Stop GRAPHIC if used
578+ set_graphmode(0);
579+ g_use_graphic=0;
580+ // Set timer4 for tempo
581+ PR4=59473; // 3632*262/16-1
582+ } else {
583+ // Prepare GRAPHIC area if not used and not allcated.
584+ allocate_graphic_area();
585+ }
586+ break;
587+ case 2:
588+ // Reset GRAPHIC and use it
589+ g_graphic_area=0;
590+ // Continue to case 1:
591+ case 1:
592+ case 3:
593+ default:
594+ // Use GRAPHIC
595+ allocate_graphic_area();
596+ // Start showing GRAPHIC with mode 1, but not with mode 3
597+ if (mode !=3 && !g_use_graphic){
598+ set_graphmode(1);
599+ g_use_graphic=1;
600+ // Set timer4 for tempo
601+ PR4=55756; // ~=3405*262/16-1(55755.875)
602+ }
603+ break;
604+ }
605+}
606+
607+int lib_graphic(int v0,enum functions func){
608+ unsigned char b;
609+ int x1=g_libparams[1];
610+ int y1=g_libparams[2];
611+ int x2=g_libparams[3];
612+ int y2=g_libparams[4];
613+ // Disable if graphic area is not defined.
614+ if (!g_graphic_area) return;
615+ // If C is omitted in parameters, use current color.
616+ if (v0==-1) {
617+ v0=g_gcolor;
618+ }
619+ // If X1 or Y1 is 0x80000000, use the previous values.
620+ if (x1==0x80000000) x1=g_prev_x;
621+ if (y1==0x80000000) y1=g_prev_y;
622+ switch(func){
623+ case FUNC_POINT:// X1,Y1
624+ g_prev_x=x1;
625+ g_prev_y=y1;
626+ break;
627+ case FUNC_PSET:// X1,Y1[,C]
628+ g_pset(x1,y1,v0&0x0F);
629+ g_prev_x=x1;
630+ g_prev_y=y1;
631+ break;
632+ case FUNC_LINE:// X1,Y1,X2,Y2[,C]
633+ if (y1==y2) g_hline(x1,x2,y1,v0&0x0F);
634+ else g_gline(x1,y1,x2,y2,v0&0x0F);
635+ g_prev_x=x2;
636+ g_prev_y=y2;
637+ break;
638+ case FUNC_BOXFILL:// X1,Y1,X2,Y2[,C]
639+ g_boxfill(x1,y1,x2,y2,v0&0x0F);
640+ g_prev_x=x2;
641+ g_prev_y=y2;
642+ break;
643+ case FUNC_CIRCLE:// X1,Y1,R[,C]
644+ g_circle(x1,y1,x2,v0&0x0F);
645+ g_prev_x=x1;
646+ g_prev_y=y1;
647+ break;
648+ case FUNC_CIRCLEFILL:// X1,Y1,R[,C]
649+ g_circlefill(x1,y1,x2,v0&0x0F);
650+ g_prev_x=x1;
651+ g_prev_y=y1;
652+ break;
653+ case FUNC_GPRINT:// X1,Y1,C,BC,S$
654+ g_printstr(x1,y1,x2,y2,(unsigned char*)v0);
655+ // Move current X,Y according to the string
656+ while(b=((unsigned char*)v0)[0]){
657+ v0++;
658+ if (b==0x0d) {
659+ x1=0;
660+ y1+=8;
661+ } else {
662+ x1+=8;
663+ }
664+ }
665+ g_prev_x=x1;
666+ g_prev_y=y1;
667+ break;
668+ case FUNC_PUTBMP2:// X1,Y1,M,N,BMP(label)
669+ // Search CDATA
670+ // It starts from either 0x00000020,0x00000021,0x00000022, or 0x00000023.
671+ while((((unsigned int*)v0)[0]&0xfffffffc)!=0x00000020) v0+=4;
672+ // CDATA starts from next word.
673+ // MLB 3 bytes show skip byte(s).
674+ v0+=4+(((unsigned int*)v0)[0]&0x03);
675+ // Contunue to FUNC_PUTBMP.
676+ case FUNC_PUTBMP:// X1,Y1,M,N,BMP(pointer)
677+ g_putbmpmn(x1,y1,x2,y2,(const unsigned char*)v0);
678+ g_prev_x=x1;
679+ g_prev_y=y1;
680+ break;
681+ case FUNC_GCOLOR:// (X1,Y1)
682+ v0=g_color(x1,y1);
683+ break;
684+ default:
685+ break;
686+ }
687+ return v0;
688+}
689+
690+void lib_var_push(int a0, int a1, int* sp){
691+ // Note that sp[1] is used for string return address
692+ // sp[2] can be used to store flags
693+ // sp[3] etc can be used to store variable values
694+ int i,params;
695+ unsigned char varnum;
696+ unsigned int strflags=0;
697+ int stack=3;
698+ for(i=0;i<8;i++){
699+ // Prepare parameter
700+ switch(i){
701+ case 0:
702+ params=a0;
703+ break;
704+ case 4:
705+ params=a1;
706+ break;
707+ default:
708+ break;
709+ }
710+ // Get variable number
711+ varnum=params&0xff;
712+ params>>=8;
713+ if (varnum==0) break; // No more variable. End the loop.
714+ varnum--;
715+ sp[stack++]=g_var_mem[varnum];
716+ if (g_var_size[varnum] && g_var_mem[varnum]==(int)(&g_var_pointer[varnum])) {
717+ // strflags change using varnum
718+ strflags|=1<<i;
719+ // Copy to VAR_BLOCK
720+ move_to_perm_block(varnum);
721+ }
722+ // Clear variable
723+ g_var_mem[varnum]=0;
724+ }
725+ // Store string flags
726+ sp[2]=strflags;
727+}
728+
729+void lib_var_pop(int a0, int a1, int* sp){
730+ // Note that sp is 4 bytes larger than that in lib_var_push
731+ // sp[1] was used to store flags
732+ // sp[2] etc can be used to store variable values
733+ int i,params;
734+ unsigned char varnum;
735+ int stack=2;
736+ unsigned int strflags=sp[1];
737+ for(i=0;i<8;i++){
738+ // Prepare parameter
739+ switch(i){
740+ case 0:
741+ params=a0;
742+ break;
743+ case 4:
744+ params=a1;
745+ break;
746+ default:
747+ break;
748+ }
749+ // Get variable number
750+ varnum=params&0xff;
751+ params>>=8;
752+ if (varnum==0) break; // No more variable. End the loop.
753+ varnum--;
754+ g_var_mem[varnum]=sp[stack++];
755+ if (strflags&(1<<i)) {
756+ // Restore from VAR_BLOCK
757+ move_from_perm_block(varnum);
758+ }
759+ }
760+}
761+
762+
763+int lib_system(int a0,int v0){
764+ switch(a0){
765+ // Version info
766+ case 0: return (int)SYSVER1;
767+ case 1: return (int)SYSVER2;
768+ case 2: return (int)BASVER;
769+ case 3: return (int)FILENAME_FLASH_ADDRESS;
770+ // Display info
771+ case 20: return twidth;
772+ case 21: return WIDTH_Y;
773+ case 22: return G_X_RES;
774+ case 23: return G_Y_RES;
775+ case 24: return cursorcolor;
776+ case 25: return g_gcolor;
777+ case 26: return ((int)(cursor-TVRAM))%twidth;
778+ case 27: return ((int)(cursor-TVRAM))/twidth;
779+ case 28: return g_prev_x;
780+ case 29: return g_prev_y;
781+ // Keyboard info
782+ case 40: return (int)inPS2MODE();
783+ case 41: return (int)vkey;
784+ case 42: return (int)lockkey;
785+ case 43: return (int)keytype;
786+ // Pointers to gloval variables
787+ case 100: return (int)&g_var_mem[0];
788+ case 101: return (int)&g_rnd_seed;
789+ case 102: return (int)&TVRAM[0];
790+ case 103: return (int)&FontData[0];
791+ case 104: return (int)g_var_mem[ALLOC_PCG_BLOCK];
792+ case 105: return (int)g_var_mem[ALLOC_GRAPHIC_BLOCK];
793+ // Change system settings
794+ case 200:
795+ // ON/OFF monitor
796+ if (v0) {
797+ start_composite();
798+ } else {
799+ stop_composite();
800+ }
801+ break;
802+ default:
803+ break;
804+ }
805+ return 0;
806+}
807+
808+char* lib_sprintf(char* format, int data){
809+ char* str;
810+ int i;
811+ char temp[4];
812+ if (!format) format="%g";
813+ i=snprintf((char*)(&temp[0]),4,format,data)+1;
814+ str=alloc_memory((i+3)/4,-1);
815+ snprintf(str,i,format,data);
816+ return str;
817+}
818+
819+int lib_floatfuncs(int ia0,int iv0,enum functions a1){
820+ volatile float a0,v0;
821+ ((int*)(&a0))[0]=ia0;
822+ ((int*)(&v0))[0]=iv0;
823+ switch(a1){
824+ case FUNC_FLOAT:
825+ v0=(float)iv0;
826+ break;
827+ case FUNC_INT:
828+ return (int)v0;
829+ case FUNC_VALSHARP:
830+ v0=strtof((const char*)iv0,0);
831+ break;
832+ case FUNC_SIN:
833+ v0=sinf(v0);
834+ break;
835+ case FUNC_COS:
836+ v0=cosf(v0);
837+ break;
838+ case FUNC_TAN:
839+ v0=tanf(v0);
840+ break;
841+ case FUNC_ASIN:
842+ v0=asinf(v0);
843+ break;
844+ case FUNC_ACOS:
845+ v0=acosf(v0);
846+ break;
847+ case FUNC_ATAN:
848+ v0=atanf(v0);
849+ break;
850+ case FUNC_ATAN2:
851+ v0=atan2f(v0,a0);
852+ break;
853+ case FUNC_SINH:
854+ v0=sinhf(v0);
855+ break;
856+ case FUNC_COSH:
857+ v0=coshf(v0);
858+ break;
859+ case FUNC_TANH:
860+ v0=tanhf(v0);
861+ break;
862+ case FUNC_EXP:
863+ v0=expf(v0);
864+ break;
865+ case FUNC_LOG:
866+ v0=logf(v0);
867+ break;
868+ case FUNC_LOG10:
869+ v0=log10f(v0);
870+ break;
871+ case FUNC_POW:
872+ v0=powf(v0,a0);
873+ break;
874+ case FUNC_SQRT:
875+ v0=sqrtf(v0);
876+ break;
877+ case FUNC_CEIL:
878+ v0=ceilf(v0);
879+ break;
880+ case FUNC_FLOOR:
881+ v0=floorf(v0);
882+ break;
883+ case FUNC_FABS:
884+ v0=fabsf(v0);
885+ break;
886+ case FUNC_MODF:
887+ v0=modff(v0,(void*)&a0);
888+ break;
889+ case FUNC_FMOD:
890+ v0=fmodf(v0,a0);
891+ break;
892+ default:
893+ err_unknown();
894+ break;
895+ }
896+ return ((int*)(&v0))[0];
897+};
898+
899+int* lib_dim(int varnum, int argsnum, int* sp){
900+ int i,j;
901+ static int* heap;
902+ // Calculate total length.
903+ int len=0; // Total length
904+ int size=1; // Size of current block
905+ for(i=1;i<=argsnum;i++){
906+ size*=sp[i]+1;
907+ len+=size;
908+ }
909+ // Allocate memory
910+ heap=calloc_memory(len,varnum);
911+ // Construct pointers
912+ len=0;
913+ size=1;
914+ for(i=1;i<argsnum;i++){
915+ size*=sp[i]+1;
916+ for(j=0;j<size;j++){
917+ heap[len+j]=(int)&heap[len+size+(sp[i+1]+1)*j];
918+ }
919+ len+=size;
920+ }
921+ return heap;
922+};
923+
924+void lib_width(int width){
925+#ifdef ZOEA
926+ switch(width){
927+ case 30:
928+ if (twidth!=30) set_width(0);
929+ break;
930+ case 40:
931+ if (twidth!=40) set_width(1);
932+ break;
933+ default:
934+ break;
935+ }
936+#endif // ZOEA
937+}
938+
939+int lib_file_textlen(FSFILE* fhandle){
940+ char buff[128];
941+ int i,textlen,len,seek;
942+ seek=FSftell(fhandle);
943+ len=FSfread(&buff[0],1,128,fhandle);
944+ textlen=0;
945+ for(i=0;i<len-1;i++){ // Read 127 bytes for supporting CRLF
946+ if (buff[i]==0x0d) {
947+ if (i<len && buff[i+1]==0x0a) i++;
948+ break;
949+ } else if (buff[i]==0x0a) {
950+ break;
951+ }
952+ if (i==len-2) {
953+ // reached the end of buffer. Read next 127 bytes
954+ textlen+=127;
955+ buff[0]=buff[127];
956+ len=FSfread(&buff[1],1,127,fhandle);
957+ // Continue with i=0
958+ i=-1;
959+ }
960+ }
961+ // The last return code must be included to caluclate total length.
962+ textlen+=i+1;
963+ // Return to original position
964+ FSfseek(fhandle,seek,SEEK_SET);
965+ return textlen;
966+}
967+
968+int lib_file(enum functions func, int a0, int a1, int v0){
969+ static FSFILE* s_fhandle[2]={0,0};
970+ static char activefhandle=0;
971+ static int numinline=0;
972+ FSFILE* fhandle=0;
973+ int i;
974+ int buff[1];
975+ char* str;
976+ if (activefhandle) fhandle=s_fhandle[activefhandle-1];
977+ switch(func){
978+ case FUNC_FINIT:
979+ // This function is not BASIC statement/function but used from
980+ // running routine.
981+ for(i=0;i<2;i++){
982+ if (s_fhandle[i]) FSfclose(s_fhandle[i]);
983+ s_fhandle[i]=0;
984+ }
985+ activefhandle=0;
986+ numinline=0;
987+ break;
988+ case FUNC_FOPEN: // Return 0 when called as a function.
989+ case FUNC_FOPENST: // Stop with error when called as a statement.
990+ activefhandle=0;
991+ // Check if file handle is free to use, first.
992+ switch(v0){
993+ case 0:
994+ // File handle was not designated
995+ // Force handle=1 and continue to following cases.
996+ v0=1;
997+ case 1:
998+ case 2:
999+ // File handle was designated
1000+ // Check if not used yet.
1001+ if (s_fhandle[v0-1]) {
1002+ // This file handle has been occupied.
1003+ err_file();
1004+ return 0;
1005+ }
1006+ // OK. This file handle can be asigned for new file opened.
1007+ break;
1008+ default:
1009+ err_invalid_param();
1010+ return 0;
1011+ }
1012+ // Open a file
1013+ fhandle=FSfopen ((const char*) a0, (const char*) a1);
1014+ if (!fhandle) {
1015+ if (func==FUNC_FOPENST) err_file();
1016+ return 0;
1017+ }
1018+ // The file is succesfully opened. Asign file handle.
1019+ s_fhandle[v0-1]=fhandle;
1020+ activefhandle=v0;
1021+ return v0;
1022+ case FUNC_FILE:
1023+ switch(v0){
1024+ case 1:
1025+ case 2:
1026+ if (s_fhandle[v0]) {
1027+ activefhandle=v0;
1028+ break;
1029+ }
1030+ default:
1031+ err_invalid_param();
1032+ }
1033+ break;
1034+ case FUNC_FCLOSE:
1035+ switch(v0){
1036+ case 0:
1037+ break;
1038+ case 1:
1039+ case 2:
1040+ if (s_fhandle[v0-1]) activefhandle=v0;
1041+ if (activefhandle) fhandle=s_fhandle[activefhandle-1];
1042+ break;
1043+ default:
1044+ err_invalid_param();
1045+ }
1046+ if (fhandle) {
1047+ FSfclose(fhandle);
1048+ s_fhandle[activefhandle-1]=0;
1049+ }
1050+ activefhandle=0;
1051+ break;
1052+ case FUNC_FINPUT:
1053+ if (fhandle) {
1054+ // Determine text length if called without parameter
1055+ if (v0==0) v0=lib_file_textlen(fhandle);
1056+ // Allocate temporary area for string
1057+ str=alloc_memory((v0+1+3)/4,-1);
1058+ // Read from SD card
1059+ v0=FSfread(str,1,v0,fhandle);
1060+ // Null string at the end.
1061+ str[v0]=0;
1062+ return (int)str;
1063+ } else {
1064+ err_file();
1065+ return (int)"";
1066+ }
1067+ case FUNC_FPRINTSTR:
1068+ // Like lib_printstr()
1069+ for(i=0;((char*)v0)[i];i++);
1070+ if (fhandle) {
1071+ if (!FSfwrite((char*)v0,1,i,fhandle)) err_file();
1072+ } else err_file();
1073+ numinline+=i;
1074+ break;
1075+ case FUNC_FSTRING:
1076+ // Like lib_string()
1077+ switch(v0){
1078+ case 0:
1079+ // CR
1080+ lib_file(FUNC_FPRINTSTR,a0,a1,(int)"\r\n");
1081+ numinline=0;
1082+ break;
1083+ case 1:
1084+ // ,
1085+ i=rem10_32(numinline);
1086+ lib_file(FUNC_FPRINTSTR,a0,a1,(int)(" "+i));
1087+ break;
1088+ default:
1089+ break;
1090+ }
1091+ break;
1092+ case FUNC_FGET:
1093+ if (fhandle) return FSfread((void*)a0,1,v0,fhandle);
1094+ err_file();
1095+ break;
1096+ case FUNC_FPUT:
1097+ if (fhandle) return FSfwrite((void*)a0,1,v0,fhandle);
1098+ err_file();
1099+ break;
1100+ case FUNC_FGETC:
1101+ if (fhandle) {
1102+ // Note: Little endian.
1103+ if (FSfread((void*)&buff[0],1,1,fhandle)) return buff[0]&0xff;
1104+ else return -1;
1105+ }
1106+ err_file();
1107+ break;
1108+ case FUNC_FPUTC:
1109+ if (fhandle) {
1110+ // Note: Little endian.
1111+ buff[0]=v0;
1112+ return FSfwrite((void*)&buff[0],1,1,fhandle);
1113+ }
1114+ err_file();
1115+ break;
1116+ case FUNC_FSEEK:
1117+ if (fhandle) return FSfseek(fhandle,v0,SEEK_SET);
1118+ err_file();
1119+ break;
1120+ case FUNC_FTELL:
1121+ if (fhandle) return FSftell(fhandle);
1122+ err_file();
1123+ break;
1124+ case FUNC_FLEN:
1125+ if (fhandle) return fhandle->size;
1126+ err_file();
1127+ break;
1128+ case FUNC_FEOF:
1129+ if (fhandle) return (fhandle->size<=FSftell(fhandle)) ? 1:0;
1130+ err_file();
1131+ break;
1132+ case FUNC_FREMOVE:
1133+ return FSremove((const char *)v0);
1134+ default:
1135+ err_unknown();
1136+ }
1137+ return v0;
1138+}
1139+
1140+int _call_library(int a0,int a1,int a2,enum libs a3);
1141+
1142+void call_library(void){
1143+ // Store s6 in g_s6
1144+ asm volatile("la $a2,%0"::"i"(&g_s6));
1145+ asm volatile("sw $s6,0($a2)");
1146+ // Copy $v0 to $a2 as 3rd argument of function
1147+ asm volatile("addu $a2,$v0,$zero");
1148+ // Store sp in g_libparams
1149+ asm volatile("la $v0,%0"::"i"(&g_libparams));
1150+ asm volatile("sw $sp,0($v0)");
1151+ // Jump to main routine
1152+ asm volatile("j _call_library");
1153+}
1154+
1155+int _call_library(int a0,int a1,int v0,enum libs a3){
1156+ // usage: call_lib_code(LIB_XXXX);
1157+ // Above code takes 2 words.
1158+ check_break();
1159+ switch(a3 & LIB_MASK){
1160+ case LIB_FLOAT:
1161+ return lib_float(a0,v0,(enum operator)(a3 & OP_MASK)); // see operator.c
1162+ case LIB_FLOATFUNCS:
1163+ return lib_floatfuncs(a0,v0,(enum functions)(a3 & FUNC_MASK));
1164+ case LIB_STRNCMP:
1165+ return strncmp((char*)g_libparams[1],(char*)g_libparams[2],v0);
1166+ case LIB_MIDSTR:
1167+ return (int)lib_midstr(a1,v0,a0);
1168+ case LIB_RND:
1169+ return (int)lib_rnd();
1170+ case LIB_DEC:
1171+ return (int)lib_dec(v0);
1172+ case LIB_HEX:
1173+ return (int)lib_hex(v0,a0);
1174+ case LIB_CHR:
1175+ return (int)lib_chr(v0);
1176+ case LIB_VAL:
1177+ return lib_val((char*)v0);
1178+ case LIB_LETSTR:
1179+ lib_let_str((char*)v0,a0);
1180+ return;
1181+ case LIB_CONNECT_STRING:
1182+ return (int)lib_connect_string((char*)a0, (char*)v0);
1183+ case LIB_STRING:
1184+ lib_string(v0);
1185+ return v0;
1186+ case LIB_PRINTSTR:
1187+ printstr((char*)v0);
1188+ return v0;
1189+ case LIB_GRAPHIC:
1190+ return lib_graphic(v0, (enum functions)(a3 & FUNC_MASK));
1191+ case LIB_SPRINTF:
1192+ return (int)lib_sprintf((char*)v0,a0);
1193+ case LIB_VAR_PUSH:
1194+ lib_var_push(a0,a1,g_libparams);
1195+ return v0;
1196+ case LIB_VAR_POP:
1197+ lib_var_pop(a0,a1,g_libparams);
1198+ return v0;
1199+ case LIB_SCROLL:
1200+ if (twidth==40) lib_scroll40(g_libparams[1],v0);
1201+ else lib_scroll(g_libparams[1],v0);
1202+ return v0;
1203+ case LIB_FILE:
1204+ return lib_file((enum functions)(a3 & FUNC_MASK),g_libparams[1],g_libparams[2],v0);
1205+ case LIB_KEYS:
1206+ return lib_keys(v0);
1207+ case LIB_INKEY:
1208+ return (int)lib_inkey(v0);
1209+ case LIB_CURSOR:
1210+ setcursor(g_libparams[1],v0,cursorcolor);
1211+ return v0;
1212+ case LIB_SOUND:
1213+ set_sound((unsigned long*)v0);
1214+ return v0;
1215+ case LIB_MUSICFUNC:
1216+ return musicRemaining();
1217+ case LIB_MUSIC:
1218+ set_music((char*)v0);
1219+ return v0;
1220+ case LIB_SETDRAWCOUNT:
1221+ drawcount=(v0&0x0000FFFF);
1222+ return v0;
1223+ case LIB_DRAWCOUNT:
1224+ return drawcount;
1225+ case LIB_SYSTEM:
1226+ return lib_system(a0,v0);
1227+ case LIB_RESTORE:
1228+ return lib_read(0,v0);
1229+ case LIB_RESTORE2:
1230+ return lib_read(1,v0);
1231+ case LIB_READ:
1232+ return lib_read(0,0);
1233+ case LIB_CREAD:
1234+ return lib_read(1,0);
1235+ case LIB_LABEL:
1236+ return (int)lib_label(v0);
1237+ case LIB_INPUT:
1238+ return (int)lib_input();
1239+ case LIB_USEGRAPHIC:
1240+ lib_usegraphic(v0);
1241+ return v0;
1242+ case LIB_USEPCG:
1243+ lib_usepcg(v0);
1244+ return v0;
1245+ case LIB_PCG:
1246+ lib_pcg(g_libparams[1],g_libparams[2],v0);
1247+ return v0;
1248+ case LIB_BGCOLOR: // BGCOLOR R,G,B
1249+ set_bgcolor(v0,g_libparams[1],g_libparams[2]); //set_bgcolor(b,r,g);
1250+ return v0;
1251+ case LIB_PALETTE: // PALETTE N,R,G,B
1252+ set_palette(g_libparams[1],v0,g_libparams[2],g_libparams[3]); // set_palette(n,b,r,g);
1253+ return v0;
1254+ case LIB_GPALETTE:// GPALETTE N,R,G,B
1255+ if (g_graphic_area) g_set_palette(g_libparams[1],v0,g_libparams[2],g_libparams[3]); // g_set_palette(n,b,r,g);
1256+ return v0;
1257+ case LIB_CLS:
1258+ clearscreen();
1259+ return v0;
1260+ case LIB_GCLS:
1261+ if (g_graphic_area) g_clearscreen();
1262+ g_prev_x=g_prev_y=0;
1263+ return v0;
1264+ case LIB_WIDTH:
1265+ lib_width(v0);
1266+ return v0;
1267+ case LIB_COLOR:
1268+ setcursorcolor(v0);
1269+ return v0;
1270+ case LIB_GCOLOR:
1271+ g_gcolor=v0;
1272+ return v0;
1273+ case LIB_WAIT:
1274+ lib_wait(v0);
1275+ return v0;
1276+ case LIB_CLEAR:
1277+ lib_clear();
1278+ return v0;
1279+ case LIB_DIM:
1280+ return (int)lib_dim(a0,a1,(int*)v0);
1281+#ifdef __DEBUG
1282+ case LIB_DEBUG:
1283+ asm volatile("nop");
1284+ return v0;
1285+#endif
1286+ case LIB_DIV0:
1287+ err_div_zero();
1288+ return v0;
1289+ default:
1290+ err_unknown();
1291+ return v0;
1292+ }
1293+}
\ No newline at end of file
--- /dev/null
+++ b/mips/zoea/linker.c
@@ -0,0 +1,390 @@
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 "compiler.h"
9+
10+unsigned int g_label;
11+
12+char* get_label(void){
13+ unsigned int i;
14+ char b1;
15+ int prevpos;
16+ next_position();
17+ prevpos=g_srcpos;
18+ i=0;
19+ b1=g_source[g_srcpos];
20+ if ('0'<= b1 && b1<='9') {
21+ // May be line number
22+ do {
23+ i*=10;
24+ i+=b1-'0';
25+ g_srcpos++;
26+ b1=g_source[g_srcpos];
27+ } while ('0'<= b1 && b1<='9');
28+ // Check if end of the statement.
29+ if (i==0 || 65535<i) {
30+ // Line number 0 or more than 65535 is not available
31+ g_srcpos=prevpos;
32+ return ERR_SYNTAX;
33+ } else if (get_operator()) {
34+ // Oparator not found.
35+ g_label=i;
36+ return 0;
37+ } else {
38+ // This is not constant line number.
39+ g_srcpos=prevpos;
40+ g_label=0;
41+ return 0;
42+ }
43+ } else if ('A'<=b1 && b1<='Z') {
44+ // May be label
45+ do {
46+ // First character must be A-Z
47+ // From second, A-Z and 0-9 can be used.
48+ i*=36;
49+ if ('0'<=b1 && b1<='9') {
50+ i+=b1-'0';
51+ } else if (g_srcpos==prevpos) {
52+ // First character must be A-Z.
53+ // Subtract 9, resulting 1-26 but not 10-35.
54+ // This subtraction is required to maintain
55+ // final number being <0x80000000.
56+ i+=b1-'A'+1;
57+ } else {
58+ i+=b1-'A'+10;
59+ }
60+ g_srcpos++;
61+ b1=g_source[g_srcpos];
62+ } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z');
63+ // Length of the label must be between 2 and 6.
64+ if (g_srcpos-prevpos<2 || 6<g_srcpos-prevpos) {
65+ g_srcpos=prevpos;
66+ return ERR_LABEL_LONG;
67+ }
68+ // Must not be a function
69+ next_position();
70+ if (g_source[g_srcpos]=='(') {
71+ g_srcpos=prevpos;
72+ g_label=0;
73+ return 0;
74+ }
75+ g_label=i+65536;
76+ return 0;
77+ } else {
78+ g_label=0;
79+ return 0;
80+ }
81+}
82+
83+void* search_label(unsigned int label){
84+ unsigned int i,code,search1,search2;
85+ if (label&0xFFFF0000) {
86+ // Label
87+ search1=0x3C160000|((label>>16)&0x0000FFFF); //lui s6,yyyy;
88+ search2=0x36D60000|(label&0x0000FFFF); //ori s6,s6,zzzz;
89+ for(i=0;i<g_objpos;i++){
90+ code=g_object[i];
91+ if (code==search1) {
92+ if (g_object[i+1]==search2) {
93+ // Label number found
94+ return &(g_object[i]);
95+ }
96+ }
97+ if (code&0xFFFF0000==0x04110000) {
98+ // "bgezal zero," assembly found. Skip following block (strig).
99+ i+=code&0x0000FFFF;
100+ }
101+ }
102+ // Line number not found.
103+ return 0;
104+ } else {
105+ // Line number
106+ search1=0x34160000|label; //ori s6,zero,xxxx;
107+ for(i=0;i<g_objpos;i++){
108+ code=g_object[i];
109+ if (code==search1) {
110+ // Line number found
111+ return &(g_object[i]);
112+ }
113+ if (code&0xFFFF0000==0x04110000) {
114+ // "bgezal zero," assembly found. Skip following block (strig).
115+ i+=code&0x0000FFFF;
116+ }
117+ }
118+ // Line number not found.
119+ return 0;
120+ }
121+}
122+
123+void* search_breakout(unsigned int start, int* prevcode){
124+ unsigned int pos,code1,depth;
125+ // Start search from start point where BREAK statement is used.
126+ depth=0;
127+ for(pos=start;pos<g_objpos;pos++){
128+ code1=g_object[pos];
129+ switch(code1>>16){
130+ case 0x0411:
131+ // "bgezal zero," assembly found. Skip following block (strig).
132+ pos+=code1&0x0000FFFF;
133+ break;
134+ case 0x0820: // FOR
135+ case 0x0821: // WHILE
136+ case 0x0822: // DO
137+ depth++;
138+ break;
139+ case 0x0830: // NEXT
140+ case 0x0831: // WEND
141+ case 0x0832: // LOOP
142+ if (0<depth) {
143+ depth--;
144+ break;
145+ }
146+ // Destination found.
147+ // Previous code will be also set if required for CONTINUE statement.
148+ if (prevcode) prevcode[0]=g_object[pos-1];
149+ return (void*)&g_object[pos];
150+ default:
151+ break;
152+ }
153+ }
154+ return 0;
155+}
156+
157+void* search_ifout(unsigned int start){
158+ unsigned int pos,code1,depth;
159+ // Start search from start point where BREAK statement is used.
160+ depth=0;
161+ for(pos=start;pos<g_objpos;pos++){
162+ code1=g_object[pos];
163+ switch(code1>>16){
164+ case 0x0411:
165+ // "bgezal zero," assembly found. Skip following block (strig).
166+ pos+=code1&0x0000FFFF;
167+ break;
168+ case 0x3000: // Block marker
169+ if (code1==0x30008000) {
170+ // end block
171+ if (0<depth) {
172+ depth--;
173+ break;
174+ }
175+ // Destination found.
176+ return (void*)&g_object[pos];
177+ } else if (code1==0x30000000) {
178+ // begin block
179+ depth++;
180+ break;
181+ } else {
182+ break;
183+ }
184+ default:
185+ break;
186+ }
187+ }
188+ return 0;
189+}
190+
191+/*
192+ Following codes are dedicated to specific use:
193+ 0x0411xxxx: String/data block
194+ Use 0x0413xxxx (bzegall zero,xxxx) for other cases to get PC to $ra
195+ 0x0810xxxx, 0x0811xxxx: GOTO statement
196+ 0x0812xxxx, 0x0813xxxx: GOSUB statement
197+ 0x0814xxxx, 0x0815xxxx: SOUND etc, for setting v0 as pointer to DATA array.
198+ 0x0816xxxx: BREAK statemant and relatives
199+ 0x08160000: BREAK
200+ 0x08160008: CONTINUE
201+ 0x08160100: Jump to next ELSE, ELSEIF or ENDIF
202+ 0x082xyyyy: Begin block (FOR/DO/WHILE)
203+ 0x083xyyyy: End block (NEXT/LOOP/WEND)
204+ 0x00000020, 0x00000021,
205+ 0x00000022, 0x00000023: Marker for begining the DATA region.
206+ MLB 2 bits show skip byte length in DATA.
207+ 0x30000000: Begin block (IF-THEN-ELSEIF-ELSE-ENDIF)
208+ 0x30008000: End block (IF-THEN-ELSEIF-ELSE-ENDIF)
209+ 0x3000Fxxx: General purpose NOP with value 0x0000-0x0FFF.
210+
211+ IF-THEN-ELSEIF-ELSE-ENDIF is written as follows:
212+ IF-THEN: 0x30000000 0x10400000 0x30000000
213+ ELSEIF-THEN: 0x08160100 0x30008000 (conditional expression) 0x10400000 0x30000000
214+ ELSE: 0x08160100 0x30008000 0x30000000
215+ ENDIF: 0x30008000 0x30008000
216+ , where "0x10400000 0x30000000" and "0x08160100 0x30008000" will be replaced by
217+ codes jumping to next 0x30008000. The 0x30000000 - 0x30008000 blocks will be skipped.
218+*/
219+
220+char* link(void){
221+ int pos;
222+ unsigned int code1,code2,label;
223+ g_fileline=0;
224+ for(pos=0;pos<g_objpos;pos++){
225+ code1=g_object[pos];
226+ switch(code1>>16){
227+ case 0x0411:
228+ // "bgezal zero," assembly found. Skip following block (strig).
229+ pos+=code1&0x0000FFFF;
230+ break;
231+ case 0x3416:
232+ // "ori s6,zero,xxxx" found this is the first word in a line.
233+ g_fileline++;
234+ g_line=code1&0x0000FFFF;
235+ break;
236+ case 0x0810:
237+ // GOTO
238+ code2=g_object[pos+1];
239+ if ((code2&0xFFFF0000)!=0x08110000) continue;
240+ code1&=0x0000FFFF;
241+ code2&=0x0000FFFF;
242+ label=(code1<<16)|code2;
243+ code1=(int)search_label(label);
244+ g_label=label;
245+ if (!code1) return ERR_LABEL_NF;
246+ code1&=0x0FFFFFFF;
247+ code1>>=2;
248+ code1|=0x08000000; // j xxxx
249+ g_object[pos++]=code1;
250+ g_object[pos]=0x00000000; // nop
251+ break;
252+ case 0x0812:
253+ // GOSUB
254+ code2=g_object[pos+1];
255+ if ((code2&0xFFFF0000)!=0x08130000) continue;
256+ code1&=0x0000FFFF;
257+ code2&=0x0000FFFF;
258+ label=(code1<<16)|code2;
259+ code2=(int)search_label(label);
260+ g_label=label;
261+ if (!code2) return ERR_LABEL_NF;
262+ code2&=0x0FFFFFFF;
263+ code2>>=2;
264+ code2|=0x08000000; // j xxxx
265+ g_object[pos++]=0x00000000; // nop
266+ g_object[pos]=code2;
267+ break;
268+ case 0x0814:
269+ // SOUND etc, for setting v0 as pointer to label/line
270+ code2=g_object[pos+1];
271+ if ((code2&0xFFFF0000)!=0x08150000) continue;
272+ code1&=0x0000FFFF;
273+ code2&=0x0000FFFF;
274+ label=(code1<<16)|code2;
275+ code1=(int)search_label(label);
276+ g_label=label;
277+ if (!code1) return ERR_LABEL_NF;
278+ g_object[pos++]=0x3C020000|((code1>>16)&0x0000FFFF); // lui v0,xxxx
279+ g_object[pos] =0x34420000|(code1&0x0000FFFF); // ori v0,v0,xxxx
280+ break;
281+ case 0x0816:
282+ switch(code1&0xFFFF) {
283+ case 0x0000:
284+ // BREAK statement
285+ // Find next the NEXT or WHILE statement and insert jump code after this.
286+ g_label=g_line;
287+ code1=(int)search_breakout(pos,0);
288+ if (!code1) return ERR_INVALID_BREAK;
289+ code1&=0x0FFFFFFF;
290+ code1>>=2;
291+ code1|=0x08000000; // j xxxx
292+ g_object[pos]=code1;
293+ break;
294+ case 0x0008:
295+ // CONTINUE statement
296+ // Find next the NEXT or WHILE statement and insert jump code after this.
297+ g_label=g_line;
298+ code1=(int)search_breakout(pos,&g_temp);
299+ if (!code1) return ERR_INVALID_BREAK;
300+ if (0x3000F000 == (g_temp&0xFFFFF000)) {
301+ // WEND or LOOP statement found
302+ code1-=(g_temp&0x0FFF)<<2;
303+ } else {
304+ // NEXT statement found
305+ code1-=3<<2;
306+ }
307+ code1&=0x0FFFFFFF;
308+ code1>>=2;
309+ code1|=0x08000000; // j xxxx
310+ g_object[pos]=code1;
311+ break;
312+ case 0x0100:
313+ // Jump to next ENDIF
314+ g_label=g_line;
315+ // "pos+2" is for skipping next code (must be 0x30008000)
316+ code1=(int)search_ifout(pos+2);
317+ if (!code1) return ERR_INVALID_ELSEIF;
318+ code1&=0x0FFFFFFF;
319+ code1>>=2;
320+ code1|=0x08000000; // j xxxx
321+ g_object[pos]=code1;
322+ break;
323+ default:
324+ break;
325+ }
326+ break;
327+ case 0x3000:
328+ // Block marker
329+ switch(code1&0xFFFF) {
330+ case 0x0000:
331+ // Begin if block
332+ if (g_object[pos-1]==0x10400000) { // beq v0,zero,xxxx
333+ // IF-THEN or ELSEIF-THEN
334+ // Jump to next ELSE, ELSEIF or ENDIF
335+ g_label=g_line;
336+ // "pos+1" is for skipping current code (0x30000000)
337+ code1=(int)search_ifout(pos+1);
338+ if (!code1) return ERR_INVALID_ELSEIF;
339+ code1-=(int)(&g_object[pos]);
340+ code1>>=2;
341+ code1&=0x0000FFFF;
342+ code1|=0x10400000; // beq v0,zero,xxxx
343+ g_object[pos-1]=code1;
344+ break;
345+ }
346+ break;
347+ default:
348+ break;
349+ }
350+ break;
351+ case 0x0820: // FOR
352+ case 0x0830: // NEXT
353+ case 0x0821: // WHILE
354+ case 0x0831: // WEND
355+ case 0x0822: // DO
356+ case 0x0832: // WHILE
357+ // These are used for detecing the depth of structures.
358+ // Change them to stack increase/decrease commands.
359+ g_object[pos]=0x27BD0000|(code1&0x0000FFFF); //// addiu sp,sp,xx
360+ break;
361+ case 0x2407: // addiu a3,zero,xxxx
362+ if (g_object[pos-1]!=0x02E0F809) break; // jalr ra,s7
363+ // call_lib_code(x)
364+ switch(code1&0x0000FFFF){
365+ case LIB_RESTORE:
366+ // Convert label data to pointer if not dynamic
367+ code1=g_object[pos-3];
368+ code2=g_object[pos-2];
369+ if ((code1>>16)!=0x3C02) break; // lui v0,xxxx
370+ if ((code2>>16)!=0x3442) break; // ori v0,v0,xxxx
371+ label=(code1<<16)|(code2&0x0000FFFF);
372+ code1=(int)search_label(label);
373+ g_label=label;
374+ if (!code1) return ERR_LABEL_NF;
375+ code2=code1&0x0000FFFF;
376+ code1=code1>>16;
377+ g_object[pos-3]=0x3C020000|code1; // lui v0,xxxx
378+ g_object[pos-2]=0x34420000|code2; // ori v0,v0,xxxx
379+ g_object[pos]=0x24070000|LIB_RESTORE2; // addiu a3,zero,xxxx
380+ break;
381+ default:
382+ break;
383+ }
384+ break;
385+ default:
386+ break;
387+ }
388+ }
389+ return 0;
390+}
\ No newline at end of file
--- /dev/null
+++ b/mips/zoea/main.c
@@ -0,0 +1,216 @@
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+
12+// 利用システム
13+// ps2keyboard.X.a : PS/2キーボード入力システムライブラリ
14+// lib_colortext32.a : カラービデオ信号出力システムライブラリ(30×27テキスト版)
15+// libsdfsio.a : SDカードアクセス用ライブラリ
16+
17+#include <xc.h>
18+#include "api.h"
19+#include "compiler.h"
20+#include "editor.h"
21+#include "keyinput.h"
22+#include "main.h"
23+
24+//外付けクリスタル with PLL (16倍)
25+#pragma config PMDL1WAY = OFF, IOL1WAY = OFF
26+#pragma config FPLLIDIV = DIV_1, FPLLMUL = MUL_16, FPLLODIV = DIV_1
27+#pragma config FNOSC = PRIPLL, FSOSCEN = OFF, POSCMOD = XT, OSCIOFNC = OFF
28+#pragma config FPBDIV = DIV_1, FWDTEN = OFF, JTAGEN = OFF, ICESEL = ICS_PGx1
29+#pragma config FCKSM = CSECMD
30+
31+#define mBMXSetRAMKernProgOffset(offset) (BMXDKPBA = (offset))
32+#define mBMXSetRAMUserDataOffset(offset) (BMXDUDBA = (offset))
33+#define mBMXSetRAMUserProgOffset(offset) (BMXDUPBA = (offset))
34+
35+// INIファイル指定キーワード(8文字以内)
36+const char InitKeywords[][9]={
37+ "106KEY","101KEY","NUMLOCK","CAPSLOCK","SCRLLOCK"
38+};
39+
40+void freadline(char *s,FSFILE *fp){
41+// ファイルから1行読み込み、配列sに返す
42+// 最大8文字まで。9文字以上の場合無効
43+// #または0x20以下のコードを見つけた場合、以降は無視
44+// s:9バイト以上の配列
45+// fp:ファイルポインタ
46+ int n;
47+ char c,*p;
48+ n=0;
49+ p=s;
50+ *p=0;
51+ while(n<=8){
52+ if(FSfread(p,1,1,fp)==0 || *p=='\n'){
53+ *p=0;
54+ return;
55+ }
56+ if(*p=='#'){
57+ *p=0;
58+ break;
59+ }
60+ if(*p<=' '){
61+ if(n>0){
62+ *p=0;
63+ break;
64+ }
65+ continue;
66+ }
67+ p++;
68+ n++;
69+ }
70+ if(n>8) *s=0; //9文字以上の文字列の場合は無効
71+ //以降の文字は無視
72+ while(FSfread(&c,1,1,fp) && c!='\n') ;
73+}
74+int searchinittext(char *s){
75+// InitKeywords配列の中から文字列sを探し、位置した場合何番目かを返す
76+// 見つからなかった場合-1を返す
77+ int i;
78+ char *p1;
79+ const char *p2;
80+ for(i=0;i<sizeof(InitKeywords)/sizeof(InitKeywords[0]);i++){
81+ p1=s;
82+ p2=InitKeywords[i];
83+ while(*p1==*p2){
84+ if(*p1==0) return i;
85+ p1++;
86+ p2++;
87+ }
88+ }
89+ return -1;
90+}
91+void readinifile(void){
92+ FSFILE *fp;
93+ char inittext[9];
94+
95+ fp=FSfopen(INIFILE,"r");
96+ if(fp==NULL) return;
97+ printstr("Initialization File Found\n");
98+ lockkey=0; //INIファイルが存在する場合、Lock関連キーはINIファイルに従う
99+ while(1){
100+ if(FSfeof(fp)) break;
101+ freadline(inittext,fp);
102+ switch(searchinittext(inittext)){
103+ case 0:
104+ keytype=0;//日本語キーボード
105+ break;
106+ case 1:
107+ keytype=1;//英語キーボード
108+ break;
109+ case 2:
110+ lockkey|=2;//Num Lock
111+ break;
112+ case 3:
113+ lockkey|=4;//CAPS Lock
114+ break;
115+ case 4:
116+ lockkey|=1;//Scroll Lock
117+ break;
118+ }
119+ }
120+ FSfclose(fp);
121+}
122+
123+void printhex8(unsigned char d){
124+ printchar("0123456789ABCDEF"[d>>4]);
125+ printchar("0123456789ABCDEF"[d&0x0f]);
126+}
127+
128+void printhex16(unsigned short d){
129+ printhex8(d>>8);
130+ printhex8(d&0x00ff);
131+}
132+
133+void printhex32(unsigned int d){
134+ printhex16(d>>16);
135+ printhex16(d&0x0000ffff);
136+}
137+
138+int main(void){
139+ char *appname,*s;
140+
141+ if(DEVCFG1 & 0x8000){
142+ // Set Clock switching enabled and reset
143+ NVMWriteWord(&DEVCFG1,DEVCFG1 & 0xffff7fff);
144+ SoftReset();
145+ }
146+
147+ /* ポートの初期設定 */
148+ TRISA = 0x0000; // PORTA全て出力
149+ ANSELA = 0x0000; // 全てデジタル
150+ TRISB = KEYSTART | KEYFIRE | KEYUP | KEYDOWN | KEYLEFT | KEYRIGHT;// ボタン接続ポート入力設定
151+ ANSELB = 0x0000; // 全てデジタル
152+ CNPUBSET=KEYSTART | KEYFIRE | KEYUP | KEYDOWN | KEYLEFT | KEYRIGHT;// プルアップ設定
153+ ODCB = 0x0300; //RB8,RB9はオープンドレイン
154+
155+ // 周辺機能ピン割り当て
156+ SDI2R=2; //RPA4:SDI2
157+ RPB5R=4; //RPB5:SDO2
158+
159+ // Make RAM executable. See also "char RAM[RAMSIZE]" in globalvars.c
160+ mBMXSetRAMKernProgOffset(PIC32MX_RAMSIZE-RAMSIZE);
161+ mBMXSetRAMUserDataOffset(PIC32MX_RAMSIZE);
162+ mBMXSetRAMUserProgOffset(PIC32MX_RAMSIZE);
163+
164+ ps2mode(); //RA1オン(PS/2有効化マクロ)
165+ init_composite(); // ビデオメモリクリア、割り込み初期化、カラービデオ出力開始
166+ setcursor(0,0,COLOR_NORMALTEXT);
167+
168+ // Show blue screen if exception before soft reset.
169+ blue_screen();
170+
171+ printstr("MachiKania BASIC System\n");
172+ printstr(" Ver "SYSVER1" "SYSVER2" by KENKEN\n");
173+ printstr("BASIC Compiler "BASVER"\n");
174+ printstr(" by Katsumi\n\n");
175+ //SDカードファイルシステム初期化
176+ setcursorcolor(COLOR_NORMALTEXT);
177+ printstr("Init File System...");
178+ // Initialize the File System
179+ if(FSInit()==FALSE){ //ファイルシステム初期化
180+ //エラーの場合停止
181+ setcursorcolor(COLOR_ERRORTEXT);
182+ printstr("\nFile System Error\n");
183+ printstr("Insert Correct Card\n");
184+ printstr("And Reset\n");
185+ while(1) asm("wait");
186+ }
187+ printstr("OK\n");
188+ lockkey=2; // NumLockキーオン
189+ keytype=0; // 日本語キーボード
190+ readinifile(); //INIファイル読み込み
191+ printstr("Init PS/2...");
192+ if(ps2init()){ //PS/2初期化
193+ //キーボードが見つからない場合
194+ printstr("Keyboard Not Found\n");
195+ }
196+ else printstr("OK\n");
197+
198+ wait60thsec(60); //1秒待ち
199+
200+ // 実行中HEXファイル名がHEXFILEと一致した場合はエディタ起動
201+ appname=(char*)FILENAME_FLASH_ADDRESS;
202+ s=HEXFILE;
203+ while(*s++==*appname++) if(*s==0) texteditor(); //テキストエディター呼び出し
204+
205+ // 実行中HEXファイル名の「.HEX」を「.BAS」に置き換えてBASファイルを実行
206+ appname=(char*)FILENAME_FLASH_ADDRESS;
207+ s=tempfile;
208+ while(*appname!='.') *s++=*appname++;
209+ appname=".BAS";
210+ while(*appname!=0) *s++=*appname++;
211+ *s=0;
212+ // buttonmode(); //ボタン有効化
213+ g_disable_break=1; // Breakキー無効化
214+ runbasic(tempfile,0);
215+ while(1) asm(WAIT);
216+}
--- /dev/null
+++ b/mips/zoea/main.h
@@ -0,0 +1,22 @@
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 ZOEA
9+#define SYSVER1 "Zoea"
10+#define SYSVER2 "1.07"
11+#define BASVER "KM-1205"
12+
13+#define INIFILE "MACHIKAZ.INI" // 初期設定ファイル
14+#define HEXFILE "MACHIKAZ.HEX" // 実行中HEXファイル名がこれと一致した場合はエディタ起動
15+
16+#define FILENAME_FLASH_ADDRESS 0x9D005800
17+#define PIC32MX_RAMSIZE 0x10000
18+#define PIC32MX_FLASHSIZE 0x40000
19+
20+void printhex8(unsigned char d);
21+void printhex16(unsigned short d);
22+void printhex32(unsigned int d);
--- /dev/null
+++ b/mips/zoea/memory.c
@@ -0,0 +1,175 @@
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 "compiler.h"
9+
10+/*
11+ ALLOC_VAR_NUM: # of variables used for allocation of memory (string/dimension).
12+ 0 is for A, 1 is for B, ... , and 25 is for Z.
13+ This number also includes temporary area used for string construction etc.
14+ Temporary area is cleared every line of BASIC code in alloc_memory().
15+ ALLOC_BLOCK_NUM: # of blocks that can be used for memory allocation.
16+ This # also includes the ones for ALLOC_VAR_NUM.
17+ After ALLOC_VAR_NUM area, dedicated memory area and permanent area follows.
18+ Currently, only PCG is used for permanent pourpose.
19+ 10 permanant blocks can be used.
20+ Therefore, ALLOC_VAR_NUM+11 == ALLOC_BLOCK_NUM
21+ ALLOC_PERM_BLOCK: Start # of permanent blocks.
22+ The blocks after this number is permanently stored.
23+ Therefore, it must be released when it's not used any more.
24+*/
25+
26+void set_free_area(void* begin, void* end){
27+ int i;
28+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
29+ g_var_size[i]=0;
30+ }
31+ g_heap_mem=(int*)begin;
32+ g_max_mem=(int)((end-begin)/4);
33+}
34+
35+void* calloc_memory(int size, int var_num){
36+ int i;
37+ void* ret;
38+ // Allocate memory
39+ ret=alloc_memory(size,var_num);
40+ // Fill zero in allocated memory
41+ for(i=0;i<size;i++){
42+ ((int*)ret)[i]=0;
43+ }
44+ // return pointer to allocated memory
45+ return ret;
46+}
47+void* alloc_memory(int size, int var_num){
48+ // Remove temporary blocks once a line.
49+ asm volatile("nop");
50+ asm volatile("bltz $s6,_alloc_memory_main"); // Skip if $s6<0
51+ // Following code will be activated after setting $s6 register
52+ // every line and after label statement.
53+ asm volatile("lui $v0,0x8000");
54+ asm volatile("or $s6,$v0,$s6"); // $s6=0x80000000|$s6;
55+ // Remove all temporary blocks
56+ // Note that g_var_size is short integer.
57+ // Note that ALLOC_VAR_NUM is used here (but not ALLOC_BLOC_NUM)
58+ // for(i=26;i<ALLOC_VAR_NUM;i++)g_var_size[i]=0;
59+ asm volatile("addiu $v0,$zero,%0"::"n"((ALLOC_VAR_NUM-26)/2)); // $v0=(ALLOC_VAR_NUM-26)/2
60+ asm volatile("la $v1,%0"::"i"(&g_var_size[0])); // $v1=g_var_size
61+ asm volatile("loop:");
62+ asm volatile("sw $zero,(26*2)($v1)"); // $v1[26]=0, $v1[27]=0
63+ asm volatile("addiu $v0,$v0,-1"); // $v0--
64+ asm volatile("addiu $v1,$v1,4"); // $v1+=2
65+ asm volatile("bne $v0,$zero,loop"); // loop if 0<$v0
66+ asm volatile("b _alloc_memory_main");
67+}
68+void* _alloc_memory_main(int size, int var_num){
69+ int i,j,candidate;
70+ // Assign temp var number
71+ if (var_num<0) {
72+ // Use ALLOC_VAR_NUM here but not ALLOC_BLOCK_NUM
73+ for(i=26;i<ALLOC_VAR_NUM;i++){
74+ if (g_var_size[i]==0) {
75+ var_num=i;
76+ break;
77+ }
78+ }
79+ if (var_num<0) {
80+ err_str_complex();
81+ return 0;
82+ }
83+ }
84+ // Clear var to be assigned.
85+ g_var_size[var_num]=0;
86+ g_var_pointer[var_num]=0;
87+ while(1){
88+ // Try the block after last block
89+ candidate=0;
90+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
91+ if (g_var_size[i]==0) continue;
92+ if (candidate<=g_var_pointer[i]) {
93+ candidate=g_var_pointer[i]+g_var_size[i];
94+ }
95+ }
96+ if (candidate+size<=g_max_mem) break;
97+ // Check between blocks
98+ // Note that there is at least one block with zero pointer and zero size (see above).
99+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
100+ // Candidate is after this block.
101+ candidate=g_var_pointer[i]+g_var_size[i];
102+ // Check if there is an overlap.
103+ for(j=0;j<ALLOC_BLOCK_NUM;j++){
104+ if (g_var_size[j]==0) continue;
105+ if (candidate+size<=g_var_pointer[j]) continue;
106+ if (g_var_pointer[j]+g_var_size[j]<=candidate) continue;
107+ // This block overlaps with the candidate
108+ candidate=-1;
109+ break;
110+ }
111+ if (0<=candidate && candidate+size<=g_max_mem) {
112+ // Available block found
113+ break;
114+ } else {
115+ candidate=-1;
116+ }
117+ }
118+ if (0<=candidate) break;
119+ // New memory block cannot be allocated.
120+ err_no_mem();
121+ return 0;
122+ }
123+ // Available block found.
124+ g_var_pointer[var_num]=candidate;
125+ g_var_size[var_num]=size;
126+ g_var_mem[var_num]=(int)(&(g_heap_mem[candidate]));
127+ return (void*)g_var_mem[var_num];
128+}
129+
130+void free_temp_str(char* str){
131+ int i,pointer;
132+ if (!str) return;
133+ pointer=(int)str-(int)g_heap_mem;
134+ pointer>>=2;
135+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
136+ if (g_var_pointer[i]==pointer) {
137+ g_var_size[i]=0;
138+ break;
139+ }
140+ }
141+}
142+
143+void move_to_perm_block(int var_num){
144+ int i;
145+ // Find available permanent block
146+ for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){
147+ if (g_var_size[i]==0) break;
148+ }
149+ if (ALLOC_BLOCK_NUM<=i) err_no_block(); // Not found
150+ // Available block found.
151+ // Copy value from variable.
152+ g_var_size[i]=g_var_size[var_num];
153+ g_var_pointer[i]=g_var_pointer[var_num];
154+ g_var_mem[i]=g_var_mem[var_num];
155+ // Clear variable
156+ g_var_size[var_num]=0;
157+ g_var_mem[var_num]=0;
158+}
159+
160+void move_from_perm_block(int var_num){
161+ int i,pointer;
162+ pointer=(int)g_var_mem[var_num]-(int)g_heap_mem;
163+ pointer>>=2;
164+ // Find stored block
165+ for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){
166+ if (0<g_var_size[i] && g_var_pointer[i]==pointer) break;
167+ }
168+ if (ALLOC_BLOCK_NUM<=i) err_unknown(); // Not found
169+ // Stored block found.
170+ // Replace pointer
171+ g_var_size[var_num]=g_var_size[i];
172+ g_var_pointer[var_num]=g_var_pointer[i];
173+ // Clear block
174+ g_var_size[i]=0;
175+}
\ No newline at end of file
--- /dev/null
+++ b/mips/zoea/music.c
@@ -0,0 +1,483 @@
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 : 894886.25 Hz
14+ PR3=2047 <-> 437 Hz
15+ Timer4: 1/32 prescaler: 1789772.5 Hz
16+ Timer4 29737 counts: 262 NTSC lines.
17+*/
18+
19+/*
20+ c: 1722
21+ B: 1825
22+ A#: 1933
23+ A: 2048
24+ G#: 2170
25+ G: 2299
26+ F#: 2435
27+ F: 2580
28+ E: 2734
29+ D#: 2896
30+ D: 3067
31+ C#: 3251
32+ C: 3444
33+ Cb: 3650
34+*/
35+
36+const static int g_keys[]={
37+ 1933,1722,3251,2896,2580,2435,2170,// 0 7# C# A#m
38+ 1933,1825,3251,2896,2580,2435,2170,// 7 6# F# D#m
39+ 1933,1825,3251,2896,2734,2435,2170,// 14 5# B G#m
40+ 2048,1825,3251,2896,2734,2435,2170,// 21 4# E C#m
41+ 2048,1825,3251,3067,2734,2435,2170,// 28 3# A F#m
42+ 2048,1825,3251,3067,2734,2435,2299,// 35 2# D Bm
43+ 2048,1825,3444,3067,2734,2435,2299,// 42 1# G Em
44+ 2048,1825,3444,3067,2734,2580,2299,// 49 0 C Am
45+ 2048,1933,3444,3067,2734,2580,2299,// 56 1b F Dm
46+ 2048,1933,3444,3067,2896,2580,2299,// 63 2b Bb Gm
47+ 2170,1933,3444,3067,2896,2580,2299,// 70 3b Eb Cm
48+ 2170,1933,3444,3251,2896,2580,2299,// 77 4b Ab Fm
49+ 2170,1933,3444,3251,2896,2580,2435,// 84 5b Db Bbm
50+ 2170,1933,3650,3251,2896,2580,2435,// 91 6b Gb Ebm
51+ 2170,1933,3650,3251,2896,2734,2435 // 98 7b Cb Abm
52+};
53+
54+/*
55+ 2^(1/12) ~= 69433/(2^16)
56+ 1/(2^(1/12) ~= 1933/(2^11)
57+*/
58+
59+#define toneFlat(x) ((((unsigned long)x)*69433)>>16)
60+#define toneSharp(x) ((((unsigned long)x)*1933)>>11)
61+
62+/* local global vars */
63+static int* g_tones;
64+static int g_qvalue;
65+static int g_lvalue;
66+static int g_mpoint;
67+static char* g_mstr;
68+static int g_mspos;
69+static unsigned short g_music[32];
70+static unsigned short g_sound[32];
71+static unsigned short g_musiclen[32];
72+static unsigned char g_soundlen[32];
73+static int g_musicstart;
74+static int g_musicend;
75+static int g_musicwait;
76+static int g_soundstart;
77+static int g_soundend;
78+static int g_soundwait;
79+static int g_soundrepeat;
80+
81+int musicRemaining(){
82+ return (g_musicend-g_musicstart)&31;
83+}
84+
85+#pragma interrupt timer4int IPL3SOFT vector 16
86+void timer4int(){
87+ unsigned int i;
88+ // This function is called every 1/60 sec.
89+ IFS0CLR=_IFS0_T4IF_MASK; //IFS0bits.T4IF=0;
90+ if (g_soundstart!=g_soundend){
91+ // Start timer & OC4
92+ i=g_sound[g_soundstart];
93+ if (i<0xffff) {
94+ T3CONSET=0x8000;
95+ PR3=i;
96+ if (i<TMR3) TMR3=0;
97+ } else {
98+ T3CONCLR=0x8000;
99+ }
100+ if ((--g_soundwait)<=0) {
101+ g_soundstart++;
102+ if (g_soundstart==g_soundend || 31<g_soundstart) {
103+ g_soundstart=0;
104+ g_soundrepeat--;
105+ if (0<g_soundrepeat) {
106+ g_soundwait=g_soundlen[g_soundstart];
107+ } else {
108+ g_soundend=g_soundrepeat=g_soundwait=0;
109+ }
110+ } else {
111+ g_soundwait=g_soundlen[g_soundstart];
112+ }
113+ }
114+ // Shift music data even though without output.
115+ if (g_musicstart!=g_musicend) {
116+ if ((--g_musicwait)<=0) {
117+ g_musicstart++;
118+ g_musicstart&=31;
119+ g_musicwait=g_musiclen[g_musicstart];
120+ }
121+ }
122+ } else if (g_musicstart!=g_musicend) {
123+ // Start timer & OC4
124+ i=g_music[g_musicstart];
125+ if (i<0xffff) {
126+ T3CONSET=0x8000;
127+ PR3=i;
128+ if (i<TMR3) TMR3=0;
129+ } else {
130+ T3CONCLR=0x8000;
131+ }
132+ if ((--g_musicwait)<=0) {
133+ g_musicstart++;
134+ g_musicstart&=31;
135+ g_musicwait=g_musiclen[g_musicstart];
136+ }
137+ } else {
138+ // Stop timer
139+ T3CONCLR=0x8000;
140+ }
141+}
142+
143+int musicGetNum(){
144+ int i, ret;
145+ char b;
146+ // Skip non number character
147+ for(i=0;(b=g_mstr[g_mspos+i])<'0' && '9'<g_mstr[g_mspos+i];i++);
148+ // Determine the number
149+ ret=0;
150+ while('0'<=b && b<='9'){
151+ ret*=10;
152+ ret+=b-'0';
153+ i++;
154+ b=g_mstr[g_mspos+i];
155+ }
156+ g_mspos+=i;
157+ return ret;
158+}
159+
160+void init_music(){
161+ // Use Timer3 and OC4 for sound.
162+ RPB13R=5; //Use RPB13 for OC4
163+ OC4R=0;
164+ OC4CON=0x000b; // Timer3, toggle mode
165+ OC4CONSET=0x8000;// Start OC4
166+ T3CON=0x0050; // Prescaller: 1:32 (1.8 MHz), not yet started
167+
168+ // Timer4 is used to intterupt every 1/60 sec, just after NTSC view.
169+ T4CON=0x0040; // Prescaller: 1:16
170+ PR4=59473; // 3632*262/16-1
171+ // Timer 4 interruption, IPL3
172+ IPC4bits.T4IP=3;
173+ IPC4bits.T4IS=0;
174+ IFS0bits.T4IF=0;
175+ IEC0bits.T4IE=1;
176+ // Wait until end of NTSC view.
177+ while(!drawing);
178+ while(drawing);
179+ T4CONSET=0x8000; // Start timer 4.
180+
181+ // Initializations for music/sound.
182+ g_qvalue=160; // Q: 1/4=90
183+ g_lvalue=20; // L: 1/8
184+ g_tones=(int*)&(g_keys[49]); // C major
185+ g_musicstart=g_musicend=g_musicwait=g_soundstart=g_soundend=g_soundwait=g_soundrepeat=0;
186+}
187+
188+void musicSetL(){
189+ // Set length of a character.
190+ // Syntax: L:n/m, where n and m are numbers.
191+ int n,m;
192+ n=musicGetNum();
193+ g_mspos++;
194+ m=musicGetNum();
195+ g_lvalue=g_qvalue*n/m;
196+}
197+
198+void musicSetQ(){
199+ int i;
200+ // Syntax: Q:1/4=n, where n is number.
201+ // Skip "1/4="
202+ for(i=0;g_mstr[g_mspos+i]!='=';i++);
203+ g_mspos+=i+1;
204+ i=musicGetNum();
205+ if (i<48) { g_qvalue=320; /* 1/4=45 */ }
206+ else if (i<53) { g_qvalue=288; /* 1/4=50 */ }
207+ else if (i<60) { g_qvalue=256; /* 1/4=56 */ }
208+ else if (i<70) { g_qvalue=224; /* 1/4=64 */ }
209+ else if (i<83) { g_qvalue=192; /* 1/4=75 */ }
210+ else if (i<102) { g_qvalue=160; /* 1/4=90 */ }
211+ else if (i<132) { g_qvalue=128; /* 1/4=113 */ }
212+ else if (i<188) { g_qvalue=96; /* 1/4=150 */ }
213+ else { g_qvalue=64; /* 1/4=225 */ }
214+ g_lvalue=g_qvalue>>3;
215+}
216+
217+void musicSetK(){
218+ // Syntax: K:xxx
219+ if (!strncmp((char*)&(g_mstr[g_mspos]),"A#m",3)) {
220+ g_mspos+=3;
221+ g_tones=(int*)&(g_keys[0]);
222+ return;
223+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"D#m",3)) {
224+ g_mspos+=3;
225+ g_tones=(int*)&(g_keys[7]);
226+ return;
227+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"G#m",3)) {
228+ g_mspos+=3;
229+ g_tones=(int*)&(g_keys[14]);
230+ return;
231+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"C#m",3)) {
232+ g_mspos+=3;
233+ g_tones=(int*)&(g_keys[21]);
234+ return;
235+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"F#m",3)) {
236+ g_mspos+=3;
237+ g_tones=(int*)&(g_keys[28]);
238+ return;
239+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Bbm",3)) {
240+ g_mspos+=3;
241+ g_tones=(int*)&(g_keys[84]);
242+ return;
243+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Ebm",3)) {
244+ g_mspos+=3;
245+ g_tones=(int*)&(g_keys[91]);
246+ return;
247+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Abm",3)) {
248+ g_mspos+=3;
249+ g_tones=(int*)&(g_keys[98]);
250+ return;
251+ }
252+ if (!strncmp((char*)&(g_mstr[g_mspos]),"C#",2)) {
253+ g_mspos+=2;
254+ g_tones=(int*)&(g_keys[0]);
255+ return;
256+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"F#",2)) {
257+ g_mspos+=2;
258+ g_tones=(int*)&(g_keys[7]);
259+ return;
260+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Bm",2)) {
261+ g_mspos+=2;
262+ g_tones=(int*)&(g_keys[35]);
263+ return;
264+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Em",2)) {
265+ g_mspos+=2;
266+ g_tones=(int*)&(g_keys[42]);
267+ return;
268+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Am",2)) {
269+ g_mspos+=2;
270+ g_tones=(int*)&(g_keys[49]);
271+ return;
272+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Dm",2)) {
273+ g_mspos+=2;
274+ g_tones=(int*)&(g_keys[56]);
275+ return;
276+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Gm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Bb",2)) {
277+ g_mspos+=2;
278+ g_tones=(int*)&(g_keys[63]);
279+ return;
280+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Cm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Eb",2)) {
281+ g_mspos+=2;
282+ g_tones=(int*)&(g_keys[70]);
283+ return;
284+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Fm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Ab",2)) {
285+ g_mspos+=2;
286+ g_tones=(int*)&(g_keys[77]);
287+ return;
288+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Db",2)) {
289+ g_mspos+=2;
290+ g_tones=(int*)&(g_keys[84]);
291+ return;
292+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Gb",2)) {
293+ g_mspos+=2;
294+ g_tones=(int*)&(g_keys[91]);
295+ return;
296+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Cb",2)) {
297+ g_mspos+=2;
298+ g_tones=(int*)&(g_keys[98]);
299+ return;
300+ }
301+ switch(g_mstr[g_mspos]){
302+ case 'B':
303+ g_mspos++;
304+ g_tones=(int*)&(g_keys[14]);
305+ return;
306+ case 'E':
307+ g_mspos++;
308+ g_tones=(int*)&(g_keys[21]);
309+ return;
310+ case 'A':
311+ g_mspos++;
312+ g_tones=(int*)&(g_keys[28]);
313+ return;
314+ case 'D':
315+ g_mspos++;
316+ g_tones=(int*)&(g_keys[35]);
317+ return;
318+ case 'G':
319+ g_mspos++;
320+ g_tones=(int*)&(g_keys[42]);
321+ return;
322+ case 'C':
323+ g_mspos++;
324+ g_tones=(int*)&(g_keys[49]);
325+ return;
326+ case 'F':
327+ g_mspos++;
328+ g_tones=(int*)&(g_keys[56]);
329+ return;
330+ default:
331+ err_music(g_mstr);
332+ break;
333+ }
334+}
335+void musicSetM(){
336+ // Currently do nothing
337+ musicGetNum();
338+ musicGetNum();
339+}
340+
341+void set_sound(unsigned long* data){
342+ int sound;
343+ int len;
344+ int pos;
345+ int datalen;
346+ IEC0bits.T4IE=0; // Stop interruption, first.
347+ // Initialize
348+ g_soundrepeat=g_soundstart=g_soundend=0;
349+ pos=0;
350+ do {
351+ while(data[1]!=0x00000020) data++; // Seek DATA statement
352+ datalen=(data[0]&0x00007FFF)-1; // Use bgezal statement containing data length.
353+ data+=2;
354+ while(0<datalen){
355+ datalen--;
356+ len=data[0]>>16;
357+ sound=data[0]&0x0000FFFF;
358+ data++;
359+ if (len) {
360+ // Shift tone if graphic is used
361+ if (g_use_graphic) {
362+ // MUL_15 instead of MUL_16 for CPU clock.
363+ // sound=sound*15/16
364+ sound-=(sound+7)>>4;
365+ }
366+ g_sound[pos]=sound-1;
367+ g_soundlen[pos]=len;
368+ pos++;
369+ if (32<pos) {
370+ err_music("Sound data too long.");
371+ return;
372+ }
373+ } else {
374+ g_soundrepeat=sound;
375+ break;
376+ }
377+ }
378+ } while(len);
379+ g_soundend=pos;
380+ g_soundwait=g_soundlen[0];
381+ IEC0bits.T4IE=1; // Restart interrupt.
382+}
383+
384+void set_music(char* str){
385+ char b;
386+ unsigned long tone,tonenatural;
387+ int len;
388+ g_mstr=str;
389+ g_mspos=0;
390+ while(0<(b=g_mstr[g_mspos])){
391+ if (g_mstr[g_mspos+1]==':') {
392+ // Set property
393+ g_mspos+=2;
394+ switch(b){
395+ case 'L':
396+ musicSetL();
397+ break;
398+ case 'Q':
399+ musicSetQ();
400+ break;
401+ case 'K':
402+ musicSetK();
403+ break;
404+ case 'M':
405+ musicSetM();
406+ break;
407+ default:
408+ err_music(str);
409+ break;
410+ }
411+ } else if ('A'<=b && b<='G' || 'a'<=b && b<='g' || b=='z') {
412+ g_mspos++;
413+ if (b=='z') {
414+ tone=0;
415+ } else if (b<='G') {
416+ tone=g_tones[b-'A'];
417+ tonenatural=g_keys[b-'A'+49];
418+ } else {
419+ tone=g_tones[b-'a']>>1;
420+ tonenatural=g_keys[b-'a'+49]>>1;
421+ }
422+ // Check "'"s
423+ while(g_mstr[g_mspos]=='\''){
424+ g_mspos++;
425+ tone>>=1;
426+ }
427+ // Check ","s
428+ while(g_mstr[g_mspos]==','){
429+ g_mspos++;
430+ tone<<=1;
431+ tonenatural<<=1;
432+ }
433+ // Check "^","=","_"
434+ switch(g_mstr[g_mspos]){
435+ case '^':
436+ g_mspos++;
437+ tone=toneSharp(tone);
438+ break;
439+ case '_':
440+ g_mspos++;
441+ tone=toneFlat(tone);
442+ break;
443+ case '=':
444+ g_mspos++;
445+ tone=tonenatural;
446+ break;
447+ default:
448+ break;
449+ }
450+ // Check number for length
451+ b=g_mstr[g_mspos];
452+ if ('0'<=b && b<='9') {
453+ len=g_lvalue*musicGetNum();
454+ } else {
455+ len=g_lvalue;
456+ }
457+ if (g_mstr[g_mspos]=='/') {
458+ g_mspos++;
459+ len=len/musicGetNum();
460+ }
461+ // Shift tone if graphic is used
462+ if (g_use_graphic) {
463+ // MUL_15 instead of MUL_16 for CPU clock.
464+ // tone=tone*15/16
465+ tone-=(tone+7)>>4;
466+ }
467+ // Update music value array
468+ IEC0bits.T4IE=0; // Stop interruption, first.
469+ if (g_musicstart==g_musicend) {
470+ g_musicwait=len;
471+ }
472+ g_music[g_musicend]=(tone-1)&0x0000FFFF;
473+ g_musiclen[g_musicend]=len;
474+ g_musicend++;
475+ g_musicend&=31;
476+ IEC0bits.T4IE=1; // Restart interruption.
477+ } else {
478+ err_music(str);
479+ }
480+ // Go to next character
481+ while(0<g_mstr[g_mspos] && g_mstr[g_mspos]<=0x20 || g_mstr[g_mspos]=='|') g_mspos++;
482+ }
483+}
\ No newline at end of file
--- /dev/null
+++ b/mips/zoea/operator.c
@@ -0,0 +1,273 @@
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 "compiler.h"
9+
10+/*
11+Operators: (upper ones have higher priority
12+()
13+* / %
14++ -
15+<< >>
16+< <= > >=
17+= !=
18+XOR
19+AND
20+OR
21+*/
22+
23+
24+const unsigned char g_priority[]={
25+ 0, // OP_VOID
26+ 1, // OP_OR
27+ 2, // OP_AND
28+ 3, // OP_XOR
29+ 4,4, // OP_EQ, OP_NEQ
30+ 5,5,5,5, // OP_LT, OP_LTE, OP_MT, OP_MTE
31+ 6,6, // OP_SHL, OP_SHR
32+ 7,7, // OP_ADD, OP_SUB
33+ 8,8,8 // OP_MUL, OP_DIV, OP_REM
34+};
35+
36+enum operator g_last_op;
37+
38+char* get_operator(void){
39+ char b1,b2,b3;
40+ next_position();
41+ b1=g_source[g_srcpos];
42+ b2=g_source[g_srcpos+1];
43+ b3=g_source[g_srcpos+2];
44+ switch(b1){
45+ case '%': g_last_op=OP_REM; break;
46+ case '/': g_last_op=OP_DIV; break;
47+ case '*': g_last_op=OP_MUL; break;
48+ case '-': g_last_op=OP_SUB; break;
49+ case '+': g_last_op=OP_ADD; break;
50+ case '>':
51+ if (b2=='>') {
52+ g_srcpos++;
53+ g_last_op=OP_SHR;
54+ } else if (b2=='=') {
55+ g_srcpos++;
56+ g_last_op=OP_MTE;
57+ } else {
58+ g_last_op=OP_MT;
59+ }
60+ break;
61+ case '<':
62+ if (b2=='<') {
63+ g_srcpos++;
64+ g_last_op=OP_SHL;
65+ } else if (b2=='=') {
66+ g_srcpos++;
67+ g_last_op=OP_LTE;
68+ } else {
69+ g_last_op=OP_LT;
70+ }
71+ break;
72+ case '!':
73+ if (b2!='=') return ERR_SYNTAX;
74+ g_srcpos++;
75+ g_last_op=OP_NEQ;
76+ break;
77+ case '=':
78+ if (b2=='=') g_srcpos++;
79+ g_last_op=OP_EQ;
80+ break;
81+ case 'X':
82+ if (b2!='O') return ERR_SYNTAX;
83+ if (b3!='R') return ERR_SYNTAX;
84+ g_srcpos++;
85+ g_srcpos++;
86+ g_last_op=OP_XOR;
87+ break;
88+ case 'O':
89+ if (b2!='R') return ERR_SYNTAX;
90+ g_srcpos++;
91+ g_last_op=OP_OR;
92+ break;
93+ case 'A':
94+ if (b2!='N') return ERR_SYNTAX;
95+ if (b3!='D') return ERR_SYNTAX;
96+ g_srcpos++;
97+ g_srcpos++;
98+ g_last_op=OP_AND;
99+ break;
100+ default:
101+ return ERR_SYNTAX;
102+ }
103+ g_srcpos++;
104+ return 0;
105+}
106+
107+char* get_floatOperator(void){
108+ char* err;
109+ int spos;
110+ next_position();
111+ spos=g_srcpos;
112+ err=get_operator();
113+ if (err) return err;
114+ switch(g_last_op){
115+ // Following operators cannot be used for float values.
116+ case OP_XOR:
117+ case OP_REM:
118+ case OP_SHR:
119+ case OP_SHL:
120+ g_srcpos=spos;
121+ return ERR_SYNTAX;
122+ default:
123+ return 0;
124+ }
125+}
126+
127+char* calculation(enum operator op){
128+ // $v0 = $v1 <op> $v0;
129+ switch(op){
130+ case OP_OR:
131+ check_obj_space(1);
132+ g_object[g_objpos++]=0x00621025; // or v0,v1,v0
133+ break;
134+ case OP_AND:
135+ check_obj_space(1);
136+ g_object[g_objpos++]=0x00621024; // and v0,v1,v0
137+ break;
138+ case OP_XOR:
139+ check_obj_space(1);
140+ g_object[g_objpos++]=0x00621026; // xor v0,v1,v0
141+ break;
142+ case OP_EQ:
143+ check_obj_space(2);
144+ g_object[g_objpos++]=0x00621026; // xor v0,v1,v0
145+ g_object[g_objpos++]=0x2C420001; // sltiu v0,v0,1
146+ break;
147+ case OP_NEQ:
148+ check_obj_space(2);
149+ g_object[g_objpos++]=0x00621026; // xor v0,v1,v0
150+ g_object[g_objpos++]=0x0002102B; // sltu v0,zero,v0
151+ break;
152+ case OP_LT:
153+ check_obj_space(1);
154+ g_object[g_objpos++]=0x0062102A; // slt v0,v1,v0
155+ break;
156+ case OP_LTE:
157+ check_obj_space(2);
158+ g_object[g_objpos++]=0x0043102A; // slt v0,v0,v1
159+ g_object[g_objpos++]=0x38420001; // xori v0,v0,0x1
160+ break;
161+ case OP_MT:
162+ check_obj_space(1);
163+ g_object[g_objpos++]=0x0043102A; // slt v0,v0,v1
164+ break;
165+ case OP_MTE:
166+ check_obj_space(2);
167+ g_object[g_objpos++]=0x0062102A; // slt v0,v1,v0
168+ g_object[g_objpos++]=0x38420001; // xori v0,v0,0x1
169+ break;
170+ case OP_SHR:
171+ check_obj_space(1);
172+ g_object[g_objpos++]=0x00431006; // srlv v0,v1,v0
173+ break;
174+ case OP_SHL:
175+ check_obj_space(1);
176+ g_object[g_objpos++]=0x00431004; // sllv v0,v1,v0
177+ break;
178+ case OP_ADD:
179+ check_obj_space(1);
180+ g_object[g_objpos++]=0x00621021; // addu v0,v1,v0
181+ break;
182+ case OP_SUB:
183+ check_obj_space(1);
184+ g_object[g_objpos++]=0x00621023; // subu v0,v1,v0
185+ break;
186+ case OP_MUL:
187+ check_obj_space(1);
188+ g_object[g_objpos++]=0x70621002; // mul v0,v1,v0
189+ break;
190+ case OP_DIV:
191+ // Note that intterupt functions do not use mflo and mfhi.
192+ // Probably using div does not cause delay of interrupt.
193+ check_obj_space(5);
194+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label
195+ g_object[g_objpos++]=0x0062001A; // div v1,v0
196+ call_lib_code(LIB_DIV0); // 2 words
197+ // label:
198+ g_object[g_objpos++]=0x00001012; // mflo v0
199+ break;
200+ case OP_REM:
201+ check_obj_space(5);
202+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label
203+ g_object[g_objpos++]=0x0062001A; // div v1,v0
204+ call_lib_code(LIB_DIV0); // 2 words
205+ // label:
206+ g_object[g_objpos++]=0x00001010; // mfhi v0
207+ break;
208+ default:
209+ return ERR_SYNTAX;
210+ }
211+ return 0;
212+}
213+
214+char* calculation_float(enum operator op){
215+ // $v0 = $a0 <op> $v0;
216+ // All the calculations will be done in library code, lib_float function (see below).
217+ call_lib_code(LIB_FLOAT | op);
218+ return 0;
219+}
220+
221+int lib_float(int ia0,int iv0, enum operator a1){
222+ // This function was called from _call_library().
223+ // Variable types must be all int.
224+ // Casting cannot be used.
225+ // Instead, by using pointer, put as int value, get as float value,
226+ // calculate, put as float value, then get as int value for returning.
227+ volatile float a0,v0;
228+ ((int*)(&a0))[0]=ia0;
229+ ((int*)(&v0))[0]=iv0;
230+ switch(a1){
231+ case OP_EQ:
232+ v0= a0==v0?1:0;
233+ break;
234+ case OP_NEQ:
235+ v0= a0!=v0?1:0;
236+ break;
237+ case OP_LT:
238+ v0= a0<v0?1:0;
239+ break;
240+ case OP_LTE:
241+ v0= a0<=v0?1:0;
242+ break;
243+ case OP_MT:
244+ v0= a0>v0?1:0;
245+ break;
246+ case OP_MTE:
247+ v0= a0>=v0?1:0;
248+ break;
249+ case OP_ADD:
250+ v0= a0+v0;
251+ break;
252+ case OP_SUB:
253+ v0= a0-v0;
254+ break;
255+ case OP_MUL:
256+ v0= a0*v0;
257+ break;
258+ case OP_DIV:
259+ if (v0==0) err_div_zero();
260+ v0= a0/v0;
261+ break;
262+ case OP_OR:
263+ v0= a0||v0?1:0;
264+ break;
265+ case OP_AND:
266+ v0= a0&&v0?1:0;
267+ break;
268+ default:
269+ err_unknown();
270+ return 0;
271+ }
272+ return ((int*)(&v0))[0];
273+};
\ No newline at end of file
--- /dev/null
+++ b/mips/zoea/ps2keyboard.h
@@ -0,0 +1,174 @@
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+unsigned char ps2readkey();
166+// 入力された1つのキーのキーコードをグローバル変数vkeyに格納(押されていなければ0を返す)
167+// 下位8ビット:キーコード
168+// 上位8ビット:シフト状態(押下:1)、上位から<0><CAPSLK><NUMLK><SCRLK><Win><ALT><CTRL><SHIFT>
169+// 英数・記号文字の場合、戻り値としてASCIIコード(それ以外は0を返す)
170+
171+// PIC32MX1xx/2xx版のキーボードとボタンの排他利用システムで使用する関数、マクロ
172+void ps2mode(); // PS/2を有効にする
173+void buttonmode(); // ボタンを有効にする
174+#define inPS2MODE() ((LATA&2)>>1) // モード確認用マクロ。PS/2モードの場合1、ボタンモードの場合0を返す
--- /dev/null
+++ b/mips/zoea/run.c
@@ -0,0 +1,148 @@
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 "compiler.h"
11+#include "editor.h"
12+#include "main.h"
13+
14+char* printdec(int num){
15+ char str[11];
16+ int i;
17+ if (num<0) {
18+ printchar('-');
19+ num=0-num;
20+ }
21+ for(i=10;0<i;i--){
22+ if (num==0 && i<10) break;
23+ str[i]='0'+rem10_32(num);
24+ num=div10_32(num);
25+ }
26+ for(i++;i<11;i++) {
27+ printchar(str[i]);
28+ }
29+}
30+
31+int runbasic(char *appname,int test){
32+// BASICソースのコンパイルと実行
33+// appname 実行するBASICソースファイル
34+// test 0:コンパイルと実行、0以外:コンパイルのみで終了
35+//
36+// 戻り値
37+//  0:正常終了
38+//  -1:ファイルエラー
39+//  -2:リンクエラー
40+//  1以上:コンパイルエラーの発生行(行番号ではなくファイル上の何行目か)
41+ int i;
42+ char* buff;
43+ char* err;
44+
45+ // Set grobal pointer
46+ g_gp=get_gp();
47+ // Set source positions
48+ buff=(char*)&(RAM[RAMSIZE-512]);
49+ g_source=(char*)(&buff[0]);
50+ g_srcpos=0;
51+ // Set object positions
52+ g_object=(int*)(&RAM[0]);
53+ g_objpos=0;
54+ g_objmax=g_object+(RAMSIZE-512)/4; // Buffer area excluded.
55+ // Clear object area
56+ for(i=0;i<RAMSIZE/4;i++) g_object[i]=0x00000000;
57+ // Initialize SD card file system
58+ err=init_file(buff,appname);
59+ if (err) {
60+ setcursorcolor(COLOR_ERRORTEXT);
61+ printstr("Can't Open ");
62+ printstr(appname);
63+ printchar('\n');
64+ return -1;
65+ }
66+
67+ // Initialize parameters
68+ g_pcg_font=0;
69+ g_use_graphic=0;
70+ g_graphic_area=0;
71+ clearscreen();
72+ setcursor(0,0,7);
73+ g_long_name_var_num=0;
74+ cmpdata_init();
75+
76+ printstr("BASIC "BASVER"\n");
77+ wait60thsec(15);
78+ // Initialize music
79+ init_music();
80+
81+ printstr("Compiling...");
82+
83+ // Compile the file
84+ err=compile_file();
85+ close_file();
86+ if (err) {
87+ // Compile error
88+ printstr(err);
89+ printstr("\nAround: '");
90+ for(i=0;i<5;i++){
91+ printchar(g_source[g_srcpos-2+i]);
92+ }
93+ printstr("' in line ");
94+ printdec(g_line);
95+ printstr("\n");
96+ for(i=g_srcpos;0x20<=g_source[i];i++);
97+ g_source[i]=0x00;
98+ for(i=g_srcpos;0x20<=g_source[i];i--);
99+ printstr(g_source+i);
100+ return g_fileline;
101+ }
102+
103+ // Link
104+ err=link();
105+ if (err) {
106+ // Link error
107+ printstr(err);
108+ printstr(resolve_label(g_label));
109+ return -2;
110+ }
111+
112+ // All done
113+ printstr("done\n");
114+ if(test) return 0; //コンパイルのみの場合
115+ wait60thsec(15);
116+
117+ // Initialize the other parameters
118+ // Random seed
119+ g_rnd_seed=0x92D68CA2; //2463534242
120+ // Clear variables
121+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
122+ g_var_mem[i]=0;
123+ g_var_size[i]=0;
124+ }
125+ // Clear key input buffer
126+ for(i=0;i<256;i++){
127+ ps2keystatus[i]=0;
128+ }
129+ // Reset data/read.
130+ reset_dataread();
131+ // Initialize file system
132+ lib_file(FUNC_FINIT,0,0,0);
133+
134+ // Assign memory
135+ set_free_area((void*)(g_object+g_objpos),(void*)(&RAM[RAMSIZE]));
136+
137+ // Execute program
138+ // Start program from the beginning of RAM.
139+ // Work area (used for A-Z values) is next to the object code area.
140+ start_program((void*)(&(RAM[0])),(void*)(&g_var_mem[0]));
141+ printstr("\nOK\n");
142+ // Cool down
143+ set_graphmode(0);
144+ g_use_graphic=0;
145+ lib_file(FUNC_FINIT,0,0,0);
146+
147+ return 0;
148+}
--- /dev/null
+++ b/mips/zoea/statement.c
@@ -0,0 +1,1576 @@
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 "api.h"
9+#include "compiler.h"
10+
11+char* rem_statement(){
12+ if (g_source[g_srcpos-4]<0x20) {
13+ // This line contains only "REM" statement
14+ // Delete $s6-setting command if exists.
15+ if ((g_object[g_objpos-1]&0xffff0000)==0x34160000) g_objpos--;
16+ }
17+ while(0x20<=g_source[g_srcpos]){
18+ g_srcpos++;
19+ }
20+ return 0;
21+}
22+
23+char* sound_statement(){
24+ char *err;
25+ err=get_label();
26+ if (err) return err;
27+ if (g_label) {
28+ // Label/number is constant.
29+ // Linker will change following codes later.
30+ // Note that 0x0814xxxx and 0x0815xxxx are specific codes for these.
31+ check_obj_space(2);
32+ g_object[g_objpos++]=0x08140000|((g_label>>16)&0x0000FFFF); // lui v0,xxxx
33+ g_object[g_objpos++]=0x08150000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
34+ } else {
35+ // Label/number will be dynamically set when executing code.
36+ err=get_value();
37+ if (err) return err;
38+ call_lib_code(LIB_LABEL);
39+ }
40+ call_lib_code(LIB_SOUND);
41+ return 0;
42+}
43+char* music_statement(){
44+ char *err;
45+ err=get_string();
46+ call_lib_code(LIB_MUSIC);
47+ return 0;
48+}
49+
50+char* exec_statement(){
51+ char *err;
52+ char b1;
53+ int i,prevpos;
54+ b1=g_source[g_srcpos];
55+ while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){
56+ prevpos=g_objpos;
57+ g_valueisconst=1;
58+ err=get_simple_value();
59+ if (!g_valueisconst) err=ERR_SYNTAX;
60+ if (err) return err;
61+ check_obj_space(1);
62+ g_objpos=prevpos;
63+ g_object[g_objpos++]=g_intconst;
64+ next_position();
65+ b1=g_source[g_srcpos];
66+ if (b1!=',') break;
67+ g_srcpos++;
68+ next_position();
69+ b1=g_source[g_srcpos];
70+ if (b1==0x0d || b1==0x0a) {
71+ // Multiline DATA/EXEC statement
72+ g_line++;
73+ g_fileline++;
74+ if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
75+ g_srcpos++;
76+ // Maintain at least 256 characters in cache.
77+ if (256<=g_srcpos) read_file(256);
78+ next_position();
79+ b1=g_source[g_srcpos];
80+ }
81+ }
82+ return 0;
83+}
84+
85+char* cdata_statement(){
86+ // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero)
87+ // are the sign of data region
88+ int beginpos,prevpos;
89+ char* err;
90+ char b1;
91+ char* cpy;
92+ int shift=0;
93+ int i=0;
94+ beginpos=g_objpos;
95+ check_obj_space(2);
96+ g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx
97+ g_object[g_objpos++]=0x00000020; // add zero,zero,zero
98+ next_position();
99+ b1=g_source[g_srcpos];
100+ while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){
101+ prevpos=g_objpos;
102+ g_valueisconst=1;
103+ err=get_simple_value();
104+ if (!g_valueisconst) err=ERR_SYNTAX;
105+ if (g_intconst<0x00 || 0xff<g_intconst) err=ERR_SYNTAX;
106+ if (err) return err;
107+ g_objpos=prevpos;
108+ i|=g_intconst<<shift;
109+ shift+=8;
110+ if (32<=shift) {
111+ check_obj_space(1);
112+ g_object[g_objpos++]=i;
113+ shift=0;
114+ i=0;
115+ }
116+ next_position();
117+ b1=g_source[g_srcpos];
118+ if (b1!=',') break;
119+ g_srcpos++;
120+ next_position();
121+ b1=g_source[g_srcpos];
122+ if (b1==0x0d || b1==0x0a) {
123+ // Multiline CDATA statement
124+ g_line++;
125+ g_fileline++;
126+ if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
127+ g_srcpos++;
128+ // Maintain at least 256 characters in cache.
129+ if (256<=g_srcpos) read_file(256);
130+ next_position();
131+ b1=g_source[g_srcpos];
132+ }
133+ }
134+ // Write the last 1-3 bytes and shift data if total # is not multipes of 4.
135+ if (0<shift) {
136+ // Convert shift value from bit-shift to data byte-shift.
137+ shift=4-shift/8;
138+ check_obj_space(1);
139+ g_object[g_objpos++]=i;
140+ for(cpy=(char*)&g_object[g_objpos]-1;(char*)&g_object[beginpos+2]<cpy;cpy--){
141+ cpy[0]=cpy[0-shift];
142+ }
143+ }
144+ // Determine the size of data
145+ i=g_objpos-beginpos-1;
146+ g_object[beginpos] =0x04110000|i; // bgezal zero,xxxx
147+ g_object[beginpos+1]=0x00000020|shift; // add zero,zero,zero
148+ return 0;
149+}
150+
151+char* data_statement(){
152+ // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero)
153+ // are the sign of data region
154+ int i,prevpos;
155+ char* err;
156+ while(1){
157+ prevpos=g_objpos;
158+ check_obj_space(2);
159+ g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx
160+ g_object[g_objpos++]=0x00000020; // add zero,zero,zero
161+ next_position();
162+ if (g_source[g_srcpos]=='"') {
163+ // Constant string
164+ // Store pointer to string. This is 3 words bellow of current position
165+ g_object[g_objpos]=(int)(&g_object[g_objpos+3]);
166+ g_objpos++;
167+ g_object[prevpos]=0x04110002; // bgezal zero,xxxx
168+ err=simple_string();
169+ if (err) return err;
170+ next_position();
171+ if (g_source[g_srcpos]==',') {
172+ g_srcpos++;
173+ continue;
174+ }
175+ return 0;
176+ }
177+ err=exec_statement();
178+ if (err) return err;
179+ // Determine the size of data
180+ i=g_objpos-prevpos-1;
181+ g_object[prevpos]=0x04110000|i; // bgezal zero,xxxx
182+ if (g_source[g_srcpos]=='"') {
183+ // Constant string
184+ continue;
185+ }
186+ return 0;
187+ }
188+}
189+
190+char* clear_statement(){
191+ call_lib_code(LIB_CLEAR);
192+ return 0;
193+}
194+
195+char* poke_statement(){
196+ char* err;
197+ err=get_value();
198+ if (err) return err;
199+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
200+ g_srcpos++;
201+ check_obj_space(2);
202+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
203+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
204+ err=get_value();
205+ if (err) return err;
206+ check_obj_space(3);
207+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
208+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
209+ g_object[g_objpos++]=0xA0620000; // sb v0,0(v1)
210+ return 0;
211+}
212+
213+char* dim_statement(){
214+ char* err;
215+ char b1;
216+ int i;
217+ int spos;
218+ int stack;
219+ while(1){
220+ stack=0;
221+ next_position();
222+ i=get_var_number();
223+ if (i<0) return ERR_SYNTAX;
224+ if (g_source[g_srcpos]=='#') g_srcpos++;
225+ next_position();
226+ if (g_source[g_srcpos]!='(') return ERR_SYNTAX;
227+ check_obj_space(1);
228+ spos=g_objpos++; // addiu sp,sp,xxxx
229+ do {
230+ g_srcpos++;
231+ err=get_value();
232+ if (err) return err;
233+ stack+=4;
234+ check_obj_space(1);
235+ g_object[g_objpos++]=0xAFA20000|stack; // sw v0,8(sp)
236+ } while (g_source[g_srcpos]==',');
237+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
238+ g_srcpos++;
239+ check_obj_space(3);
240+ g_object[g_objpos++]=0x24040000|(i); // addiu a0,zero,xx
241+ g_object[g_objpos++]=0x24050000|(stack/4); // addiu a1,zero,xxxx
242+ g_object[g_objpos++]=0x03A01025; // or v0,sp,zero
243+ call_lib_code(LIB_DIM);
244+ // Stack -/+
245+ check_obj_space(1);
246+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xxxx
247+ stack=(0-stack)&0x0000FFFF;
248+ g_object[spos]=0x27BD0000|stack; // addiu sp,sp,xxxx
249+ next_position();
250+ if (g_source[g_srcpos]!=',') break;
251+ g_srcpos++;
252+ }
253+ return 0;
254+}
255+
256+char* label_statement(){
257+ char* err;
258+ char b1;
259+ b1=g_source[g_srcpos];
260+ if (b1<'A' || 'Z'<b1) return ERR_SYNTAX; // Number is not allowed here.
261+ err=get_label();
262+ if (err) return err;
263+ // Check existing label with the same name here.
264+ if (search_label(g_label)) {
265+ // Error: duplicate labels
266+ printstr("Label ");
267+ printstr(resolve_label(g_label));
268+ return ERR_MULTIPLE_LABEL;
269+ }
270+ check_obj_space(2);
271+ g_object[g_objpos++]=0x3C160000|((g_label>>16)&0x0000FFFF); //lui s6,yyyy;
272+ g_object[g_objpos++]=0x36D60000|(g_label&0x0000FFFF); //ori s6,s6,zzzz;
273+ return 0;
274+}
275+
276+char* restore_statement(){
277+ char* err;
278+ err=get_label();
279+ if (err) return err;
280+ if (g_label) {
281+ // Constant label/number
282+ // Use 32 bit mode also for values<65536
283+ // This code will be replaced to code for v0 for pointer in linker.
284+ check_obj_space(2);
285+ g_object[g_objpos++]=0x3C020000|(g_label>>16); // lui v0,xxxx
286+ g_object[g_objpos++]=0x34420000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
287+ } else {
288+ // Dynamic number
289+ err=get_value();
290+ if (err) return err;
291+ }
292+ call_lib_code(LIB_RESTORE);
293+ return 0;
294+}
295+
296+char* gosub_statement_sub(){
297+ char* err;
298+ err=get_label();
299+ if (err) return err;
300+ if (g_label) {
301+ // Label/number is constant.
302+ // Linker will change following codes later.
303+ // Note that 0x0812xxxx and 0x0813xxxx are specific codes for these.
304+ check_obj_space(6);
305+ g_object[g_objpos++]=0x04130003; // bgezall zero,label1
306+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
307+ g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
308+ g_object[g_objpos++]=0x08120000|((g_label>>16)&0x0000FFFF); // nop
309+ // label1:
310+ g_object[g_objpos++]=0x08130000|(g_label&0x0000FFFF); // j xxxx
311+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
312+ // label2:
313+ } else {
314+ // Label/number will be dynamically set when executing code.
315+ err=get_value();
316+ if (err) return err;
317+ call_lib_code(LIB_LABEL);
318+ check_obj_space(6);
319+ g_object[g_objpos++]=0x04130003; // bgezall zero,label1
320+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
321+ g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
322+ g_object[g_objpos++]=0x00000000; // nop
323+ // label1:
324+ g_object[g_objpos++]=0x00400008; // jr v0
325+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
326+ // label2:
327+ }
328+ return 0;
329+}
330+
331+char* gosub_statement(){
332+ char* err;
333+ int opos,spos,stack;
334+ opos=g_objpos;
335+ spos=g_srcpos;
336+ err=gosub_statement_sub();
337+ if (err) return err;
338+ next_position();
339+ // If there is no 2nd argument, return.
340+ if (g_source[g_srcpos]!=',') return 0;
341+
342+ // There is (at least) 2nd argument.
343+ // Rewind object and construct argument-creating routine.
344+ g_objpos=opos;
345+ stack=4;
346+ g_object[g_objpos++]=0x27BD0000; // addiu sp,sp,-xx
347+ do {
348+ g_srcpos++;
349+ stack+=4;
350+ err=get_stringFloatOrValue();
351+ if (err) return err;
352+ check_obj_space(1);
353+ g_object[g_objpos++]=0xAFA20000|stack; // sw v0,xx(sp)
354+ next_position();
355+ } while(g_source[g_srcpos]==',');
356+ check_obj_space(2);
357+ g_object[g_objpos++]=0xAFB50004; // sw s5,4(sp)
358+ g_object[g_objpos++]=0x03A0A821; // addu s5,sp,zero
359+ g_object[opos]|=((0-stack)&0xFFFF); // addiu sp,sp,-xx (See above)
360+ // Rewind source and construct GOSUB routine again.
361+ opos=spos;
362+ spos=g_srcpos;
363+ g_srcpos=opos;
364+ err=gosub_statement_sub();
365+ if (err) return err;
366+ // Remove stack
367+ check_obj_space(2);
368+ g_object[g_objpos++]=0x8FB50004; // lw s5,4(sp)
369+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xx
370+ // All done, go back to wright source position
371+ g_srcpos=spos;
372+ return 0;
373+}
374+
375+char* return_statement(){
376+ char* err;
377+ char b1;
378+ next_position();
379+ b1=g_source[g_srcpos];
380+ if (0x20<b1 && b1!=':') {
381+ // There is a return value.
382+ err=get_stringFloatOrValue();
383+ if (err) return err;
384+ }
385+ check_obj_space(3);
386+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
387+ g_object[g_objpos++]=0x00600008; // jr v1
388+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
389+ return 0;
390+}
391+
392+char* goto_statement(){
393+ char* err;
394+ err=get_label();
395+ if (err) return err;
396+ if (g_label) {
397+ // Label/number is constant.
398+ // Linker will change following codes later.
399+ // Note that 0x0810xxxx and 0x0811xxxx are specific codes for these.
400+ check_obj_space(2);
401+ g_object[g_objpos++]=0x08100000|((g_label>>16)&0x0000FFFF); // j xxxx
402+ g_object[g_objpos++]=0x08110000|(g_label&0x0000FFFF); // nop
403+ } else {
404+ // Label/number will be dynamically set when executing code.
405+ err=get_value();
406+ if (err) return err;
407+ call_lib_code(LIB_LABEL);
408+ check_obj_space(2);
409+ g_object[g_objpos++]=0x00400008; // jr v0
410+ g_object[g_objpos++]=0x00000000; // nop
411+ }
412+ return 0;
413+}
414+
415+char* if_statement(){
416+ char* err;
417+ int prevpos,bpos;
418+ // Get value.
419+ err=get_floatOrValue();
420+ if (err) return err;
421+ // Check "THEN"
422+ if (!nextCodeIs("THEN")) return ERR_SYNTAX;
423+ // Check if statement follows after THEN statement
424+ next_position();
425+ if (nextCodeIs("REM")) {
426+ // If REM statement follows, skip comment words.
427+ rem_statement();
428+ }
429+ if (g_source[g_srcpos]<0x20) {
430+ // End of line.
431+ // Use IF-THEN-ENDIF mode (multiple line mode)
432+ check_obj_space(3);
433+ g_object[g_objpos++]=0x30000000; // nop (see linker)
434+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
435+ g_object[g_objpos++]=0x30000000; // nop (see linker)
436+ return 0;
437+ }
438+ // One line mode
439+ // If $v0=0 then skip.
440+ bpos=g_objpos;
441+ check_obj_space(2);
442+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
443+ g_object[g_objpos++]=0x00000000; // nop
444+ prevpos=g_srcpos;
445+ if (statement()) {
446+ // May be label
447+ g_srcpos=prevpos;
448+ err=goto_statement();
449+ if (err) return err;
450+ } else {
451+ // Must be statement(s)
452+ while(1) {
453+ if (g_source[g_srcpos]!=':') break;
454+ g_srcpos++;
455+ err=statement();
456+ if (err) return err;
457+ }
458+ }
459+ // Check if "ELSE" exists.
460+ if (!nextCodeIs("ELSE ")) {
461+ // "ELSE" not found. This is the end of "IF" statement.
462+ // Previous branch command must jump to this position.
463+ g_object[bpos]=0x10400000|(g_objpos-bpos-1); // beq v0,zero,xxxx
464+ return 0;
465+ }
466+ // Skip after ELSE if required.
467+ check_obj_space(2);
468+ g_object[g_objpos++]=0x10000000; // beq zero,zero,xxxx
469+ g_object[g_objpos++]=0x00000000; // nop
470+ // Previous branch command must jump to this position.
471+ g_object[bpos]=0x10400000|(g_objpos-bpos-1); // beq v0,zero,xxxx
472+ bpos=g_objpos-2;
473+ // Next statement is either label or general statement
474+ prevpos=g_srcpos;
475+ if (statement()) {
476+ // May be label
477+ g_srcpos=prevpos;
478+ err=goto_statement();
479+ if (err) return err;
480+ } else {
481+ // Must be statement(s)
482+ while(1) {
483+ if (g_source[g_srcpos]!=':') break;
484+ g_srcpos++;
485+ err=statement();
486+ if (err) return err;
487+ }
488+ }
489+ // Previous branch command must jump to this position.
490+ g_object[bpos]=0x10000000|(g_objpos-bpos-1); // beq zero,zero,xxxx
491+ return 0;
492+}
493+
494+char* elseif_statement(void){
495+ // Multiple line mode
496+ char* err;
497+ g_object[g_objpos++]=0x08160100; // breakif (see linker)
498+ g_object[g_objpos++]=0x30008000; // nop (see linker)
499+ // Get value.
500+ err=get_floatOrValue();
501+ if (err) return err;
502+ // Check "THEN"
503+ if (!nextCodeIs("THEN")) return ERR_SYNTAX;
504+ // Check if statement follows after THEN statement
505+ if (nextCodeIs("REM")) {
506+ // If REM statement follows, skip comment words.
507+ rem_statement();
508+ }
509+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
510+ // Statement didn't follow after THEM statement (that is correct).
511+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
512+ g_object[g_objpos++]=0x30000000; // nop (see linker)
513+ return 0;
514+
515+}
516+
517+char* else_statement(void){
518+ // Multiple line mode
519+ g_object[g_objpos++]=0x08160100; // breakif (see linker)
520+ g_object[g_objpos++]=0x30008000; // nop (see linker)
521+ g_object[g_objpos++]=0x30000000; // nop (see linker)
522+ // Check if statement follows after THEN statement
523+ if (nextCodeIs("REM")) {
524+ // If REM statement follows, skip comment words.
525+ rem_statement();
526+ }
527+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
528+ // Statement didn't follow after THEM statement (that is correct).
529+ return 0;
530+}
531+
532+char* endif_statement(void){
533+ // Multiple line mode
534+ g_object[g_objpos++]=0x30008000; // nop (see linker)
535+ g_object[g_objpos++]=0x30008000; // nop (see linker)
536+ // Check if statement follows after THEN statement
537+ if (nextCodeIs("REM")) {
538+ // If REM statement follows, skip comment words.
539+ rem_statement();
540+ }
541+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
542+ // Statement didn't follow after THEM statement (that is correct).
543+ return 0;
544+}
545+
546+char* end_statement(void){
547+ int i;
548+ i=(int)&g_end_addr;
549+ i-=g_gp;
550+ check_obj_space(3);
551+ g_object[g_objpos++]=0x8F820000|(i&0x0000FFFF); // lw v0,xxxx(gp)
552+ g_object[g_objpos++]=0x00400008; // jr v0
553+ g_object[g_objpos++]=0x00000000; // nop
554+ return 0;
555+}
556+
557+char* let_dim_sub(int i){
558+ char* err;
559+ g_srcpos++;
560+ err=get_value();
561+ if (err) return err;
562+ check_obj_space(4);
563+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
564+ g_object[g_objpos++]=0x8FC30000|(i*4); // lw v1,xx(s8)
565+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
566+ g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
567+ while(g_source[g_srcpos]==','){
568+ g_srcpos++;
569+ err=get_value();
570+ if (err) return err;
571+ check_obj_space(4);
572+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
573+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
574+ g_object[g_objpos++]=0x8C630000; // lw v1,0(v1)
575+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
576+ g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
577+ }
578+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
579+ g_srcpos++;
580+ return 0;
581+};
582+
583+char* let_statement(){
584+ char* err;
585+ char b2,b3;
586+ int i;
587+ next_position();
588+ i=get_var_number();
589+ if (i<0) return ERR_SYNTAX;
590+ b2=g_source[g_srcpos];
591+ b3=g_source[g_srcpos+1];
592+ if (b2=='#' && b3=='(') {
593+ // Float dimension
594+ g_srcpos++;
595+ check_obj_space(1);
596+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
597+ let_dim_sub(i);
598+ next_position();
599+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
600+ g_srcpos++;
601+ err=get_float();
602+ if (err) return err;
603+ check_obj_space(3);
604+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
605+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
606+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
607+ return 0;
608+ } else if (b2=='#') {
609+ // Float A-Z
610+ g_srcpos++;
611+ next_position();
612+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
613+ g_srcpos++;
614+ err=get_float();
615+ if (err) return err;
616+ check_obj_space(1);
617+ g_object[g_objpos++]=0xAFC20000|(i*4); // sw v0,xxx(s8)
618+ return 0;
619+ } else if (b2=='$') {
620+ // String
621+ g_srcpos++;
622+ next_position();
623+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
624+ g_srcpos++;
625+ err=get_string();
626+ if (err) return err;
627+ check_obj_space(1);
628+ g_object[g_objpos++]=0x24040000|(i); //addiu a0,zero,xx
629+ call_lib_code(LIB_LETSTR);
630+ return 0;
631+ } else if (b2=='(') {
632+ // Dimension
633+ check_obj_space(1);
634+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
635+ let_dim_sub(i);
636+ next_position();
637+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
638+ g_srcpos++;
639+ err=get_value();
640+ if (err) return err;
641+ check_obj_space(3);
642+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
643+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
644+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
645+ return 0;
646+ } else {
647+ // Integer A-Z
648+ next_position();
649+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
650+ g_srcpos++;
651+ err=get_value();
652+ if (err) return err;
653+ check_obj_space(1);
654+ g_object[g_objpos++]=0xAFC20000|(i*4); // sw v0,xxx(s8)
655+ }
656+ return 0;
657+}
658+
659+char* print_statement(enum libs lib_printstr, enum libs lib_string){
660+ char* err;
661+ char b1;
662+ int i;
663+ int status=0;// 1:',' 2:';' 0:none
664+ while(1){
665+ next_position();
666+ if (endOfStatement()) break;
667+ if (!strncmp(g_source+g_srcpos,"ELSE " ,5)) break;
668+ err=get_stringFloatOrValue();
669+ if (err) return err;
670+ switch(g_lastvar){
671+ case VAR_INTEGER:
672+ // Use DEC$() function.
673+ call_lib_code(LIB_DEC);
674+ break;
675+ case VAR_FLOAT:
676+ // Use FLOAT$() function.
677+ check_obj_space(2);
678+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
679+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x0000
680+ call_lib_code(LIB_SPRINTF);
681+ break;
682+ case VAR_STRING:
683+ default:
684+ break;
685+ }
686+ // Call printstr() function
687+ // First argument is the pointer to string
688+ call_lib_code(lib_printstr);
689+ next_position();
690+ b1=g_source[g_srcpos];
691+ if (b1==',') {
692+ status=1;
693+ g_srcpos++;
694+ // Call lib_string() function for comma (,)
695+ check_obj_space(1);
696+ g_object[g_objpos++]=0x34020001; // ori v0,zero,1
697+ call_lib_code(lib_string);
698+ } else if (b1==';') {
699+ status=2;
700+ g_srcpos++;
701+ } else {
702+ status=0;
703+ }
704+ }
705+ if (status==0) {
706+ // Call lib_string() function for CR (\n)
707+ check_obj_space(1);
708+ g_object[g_objpos++]=0x34020000; // ori v0,zero,0
709+ call_lib_code(lib_string);
710+ }
711+ return 0;
712+}
713+
714+char* break_statement(){
715+ check_obj_space(2);
716+ g_object[g_objpos++]=0x08160000; // j xxxx (See link() function)
717+ g_object[g_objpos++]=0x00000000; // nop
718+ return 0;
719+}
720+
721+char* continue_statement(){
722+ check_obj_space(2);
723+ g_object[g_objpos++]=0x08160008; // j xxxx (See link() function)
724+ g_object[g_objpos++]=0x00000000; // nop
725+ return 0;
726+}
727+
728+char* for_statement(){
729+ char* err;
730+// char b1;
731+ int i;
732+ int prepos=g_srcpos;
733+ // Initialization of variable
734+// next_position();
735+// b1=g_source[g_srcpos];
736+ i=get_var_number();
737+// if (b1<'A' || 'Z'<b1) return ERR_SYNTAX;
738+ if (i<0) return ERR_SYNTAX;
739+ g_srcpos=prepos;
740+ err=let_statement();
741+ if (err) return err;
742+ // Check if "TO" exists
743+ if (!nextCodeIs("TO ")) return ERR_SYNTAX;
744+ err=get_value();
745+ if (err) return err;
746+ // Usage of stack:
747+ // 12(sp): "TO" value
748+ // 8(sp): "STEP" value
749+ // 4(sp): Address to return to in "NEXT" statement.
750+ // Store "TO" value in stack
751+ check_obj_space(2);
752+ g_object[g_objpos++]=0x0820FFF4; // addiu sp,sp,-12 (see linker)
753+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
754+ // Check if "STEP" exists
755+ g_valueisconst=1;
756+ if (nextCodeIs("STEP ")) {
757+ // "STEP" exists. Get value
758+ err=get_value();
759+ if (err) return err;
760+ } else {
761+ // "STEP" not exist. Use "1".
762+ check_obj_space(1);
763+ g_object[g_objpos++]=0x24020001; // addiu v0,zero,1
764+ g_intconst=1;
765+ }
766+ check_obj_space(14);
767+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp) (STEP value)
768+ g_object[g_objpos++]=0x04130004; // bgezall zero,check
769+// g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value)
770+ g_object[g_objpos++]=0x8FC40000|(i*4); // lw a0,xx(s8) (current var value)
771+ // After executing "NEXT" statement, process reaches following line.
772+ // Update variable value by adding STEP value
773+ // Note that STEP value is loaded onto $v0 in NEXT statement
774+// g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value)
775+ g_object[g_objpos++]=0x8FC40000|(i*4); // lw a0,xx(s8) (current var value)
776+ g_object[g_objpos++]=0x00822021; // addu a0,a0,v0
777+// g_object[g_objpos++]=0xAFC40000|((b1-'A')*4); // sw a0,xx(s8) (new var value)
778+ g_object[g_objpos++]=0xAFC40000|(i*4); // sw a0,xx(s8) (new var value)
779+ // Value-checking routine and storing ra in stack
780+ // check:
781+ g_object[g_objpos++]=0x8FA3000C; // lw v1,12(sp) (TO value)
782+ g_object[g_objpos++]=0x00641823; // subu v1,v1,a0
783+ g_object[g_objpos++]=0x04420001; // bltzl v0,negative
784+ g_object[g_objpos++]=0x00031823; // subu v1,zero,v1
785+ // negative:
786+ g_object[g_objpos++]=0x04610003; // bgez v1,continue
787+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
788+ break_statement(); // (2 words)
789+ // continue:
790+ return 0;
791+}
792+
793+char* next_statement(){
794+ // Return to address stored in 4($sp)
795+ // while set $v0 to 8($sp) (see for_statement)
796+ // Following assembly must be 4 words.
797+ // If the number of words will be changed, link.c must be reviced for CONTINUE statement.
798+ check_obj_space(4);
799+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
800+ g_object[g_objpos++]=0x03E00008; // jr ra
801+ g_object[g_objpos++]=0x8FA20008; // lw v0,8(sp) (STEP value)
802+ g_object[g_objpos++]=0x0830000C; // addiu sp,sp,12 (see linker)
803+ return 0;
804+}
805+
806+char* do_statement(){
807+ char* err;
808+ // Usage of stack:
809+ // 4(sp): Address to return to in "DO" statement.
810+ check_obj_space(3);
811+ g_object[g_objpos++]=0x04130001;// bgezall zero,label1:
812+ g_object[g_objpos++]=0x0822FFFC;// addiu sp,sp,-4 (see linker)
813+ // label1:
814+ g_object[g_objpos++]=0xAFBF0004;// sw ra,4(sp)
815+ if (nextCodeIs("WHILE ")) {
816+ // DO WHILE
817+ err=get_floatOrValue();
818+ if (err) return err;
819+ check_obj_space(2);
820+ g_object[g_objpos++]=0x14400003; // bne v0,zero,labe2
821+ g_object[g_objpos++]=0x00000000; // nop
822+ return break_statement(); // (2 words)
823+ // label2:
824+
825+ } else if (nextCodeIs("UNTIL ")) {
826+ // DO UNTIL
827+ err=get_floatOrValue();
828+ if (err) return err;
829+ check_obj_space(2);
830+ g_object[g_objpos++]=0x10400003; // beq v0,zero,label2
831+ g_object[g_objpos++]=0x00000000; // nop
832+ return break_statement(); // (2 words)
833+ // label2:
834+ } else {
835+ // DO statement without WHILE/UNTIL
836+ return 0;
837+ }
838+}
839+
840+char* loop_statement(){
841+ char* err;
842+ int opos;
843+ opos=g_objpos;
844+ if (nextCodeIs("WHILE ")) {
845+ // LOOP WHILE
846+ err=get_floatOrValue();
847+ if (err) return err;
848+ check_obj_space(1);
849+ g_object[g_objpos++]=0x10400003; // beq v0,zero,label1
850+ } else if (nextCodeIs("UNTIL ")) {
851+ // LOOP UNTIL
852+ err=get_floatOrValue();
853+ if (err) return err;
854+ check_obj_space(1);
855+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label
856+ } else {
857+ // LOOP statement without WHILE/UNTIL
858+ }
859+ check_obj_space(4);
860+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
861+ g_object[g_objpos++]=0x03E00008; // jr ra
862+ opos=g_objpos+1-opos;
863+ g_object[g_objpos++]=0x3000F000|opos; // nop (See linker, used for CONTINUE statement)
864+ // label1:
865+ g_object[g_objpos++]=0x08320004; // addiu sp,sp,4 (See link() function)
866+ return 0;
867+}
868+
869+char* while_statement(){
870+ char* err;
871+ check_obj_space(3);
872+ g_object[g_objpos++]=0x04130001; // bgezall zero,label1:
873+ g_object[g_objpos++]=0x0821FFFC; // addiu sp,sp,-4 (see linker)
874+ // label1:
875+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
876+ err=get_floatOrValue();
877+ if (err) return err;
878+ check_obj_space(2);
879+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label2
880+ g_object[g_objpos++]=0x00000000; // nop
881+ return break_statement(); // (2 words)
882+ // label2:
883+}
884+
885+char* wend_statement(){
886+ check_obj_space(4);
887+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
888+ g_object[g_objpos++]=0x03E00008; // jr ra
889+ g_object[g_objpos++]=0x3000F003; // nop (See linker, used for CONTINUE statement)
890+ // label1:
891+ g_object[g_objpos++]=0x08310004; // addiu sp,sp,4 (See link() function)
892+ return 0;
893+}
894+
895+char* param4_statement(enum libs lib){
896+ // lib is either LIB_PALETTE or LIB_GPALETTE
897+ // PALETTE N,R,G,B
898+ char* err;
899+ // Get N
900+ err=get_value();
901+ if (err) return err;
902+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
903+ g_srcpos++;
904+ check_obj_space(2);
905+ g_object[g_objpos++]=0x27BDFFF4; // addiu sp,sp,-12
906+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
907+ // Get R
908+ err=get_value();
909+ if (err) return err;
910+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
911+ g_srcpos++;
912+ check_obj_space(1);
913+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
914+ // Get G
915+ err=get_value();
916+ if (err) return err;
917+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
918+ g_srcpos++;
919+ check_obj_space(1);
920+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
921+ // Get B
922+ err=get_value();
923+ if (err) return err;
924+ call_lib_code(lib);
925+ check_obj_space(1);
926+ g_object[g_objpos++]=0x27BD000C; // addiu sp,sp,12
927+ return 0;
928+}
929+
930+char* param3_statement(enum libs lib){
931+ char* err;
932+ // Get 1st parameter
933+ err=get_value();
934+ if (err) return err;
935+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
936+ g_srcpos++;
937+ check_obj_space(2);
938+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
939+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
940+ // Get 2nd parameter
941+ err=get_value();
942+ if (err) return err;
943+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
944+ g_srcpos++;
945+ check_obj_space(1);
946+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
947+ // Get 3rd parameter
948+ err=get_value();
949+ if (err) return err;
950+ call_lib_code(lib);
951+ check_obj_space(1);
952+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
953+ return 0;
954+}
955+
956+char* bgcolor_statement(){
957+ // BGCOLOR R,G,B
958+ return param3_statement(LIB_BGCOLOR);
959+}
960+
961+char* pcg_statement(){
962+ // PCG ASCII,D1,D2
963+ return param3_statement(LIB_PCG);
964+}
965+
966+char* usepcg_statement(){
967+ int objpos=g_objpos;
968+ if (get_value()) {
969+ // Getting integer failed.
970+ // It supporsed to be not parameter
971+ // and same as parameter=1.
972+ g_objpos=objpos;
973+ check_obj_space(1);
974+ g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01
975+ }
976+ call_lib_code(LIB_USEPCG);
977+ return 0;
978+}
979+
980+char* usegraphic_statement(){
981+ int objpos=g_objpos;
982+ if (get_value()) {
983+ // Getting integer failed.
984+ // It supporsed to be not parameter
985+ // and same as parameter=1.
986+ g_objpos=objpos;
987+ check_obj_space(1);
988+ g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01
989+ }
990+ call_lib_code(LIB_USEGRAPHIC);
991+ return 0;
992+}
993+
994+char* cls_statement(){
995+ call_lib_code(LIB_CLS);
996+ return 0;
997+}
998+
999+char* gcls_statement(){
1000+ call_lib_code(LIB_GCLS);
1001+ return 0;
1002+}
1003+
1004+char* color_statement(){
1005+ char* err;
1006+ err=get_value();
1007+ if (err) return err;
1008+ call_lib_code(LIB_COLOR);
1009+ return 0;
1010+}
1011+
1012+char* gcolor_statement(){
1013+ char* err;
1014+ err=get_value();
1015+ if (err) return err;
1016+ call_lib_code(LIB_GCOLOR);
1017+ return 0;
1018+}
1019+
1020+char* param2_statement(enum libs lib){
1021+ char* err;
1022+ // Get 1st
1023+ err=get_value();
1024+ if (err) return err;
1025+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1026+ g_srcpos++;
1027+ check_obj_space(2);
1028+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1029+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1030+ // Get 2nd
1031+ err=get_value();
1032+ if (err) return err;
1033+ call_lib_code(lib);
1034+ check_obj_space(1);
1035+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1036+ return 0;
1037+}
1038+
1039+char* system_statement(){
1040+ // SYSTEM X,Y
1041+ char* err;
1042+ // Get 1st
1043+ err=get_value();
1044+ if (err) return err;
1045+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1046+ g_srcpos++;
1047+ check_obj_space(2);
1048+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1049+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1050+ // Get 2nd
1051+ err=get_value();
1052+ if (err) return err;
1053+ check_obj_space(2);
1054+ g_object[g_objpos++]=0x8FA40004; // lw a0,4(sp)
1055+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1056+ call_lib_code(LIB_SYSTEM);
1057+ return 0;
1058+}
1059+
1060+char* cursor_statement(){
1061+ // CURSOR X,Y
1062+ return param2_statement(LIB_CURSOR);
1063+}
1064+
1065+char* scroll_statement(){
1066+ // SCROLL X,Y
1067+ return param2_statement(LIB_SCROLL);
1068+}
1069+
1070+char* drawcount_statement(){
1071+ char* err;
1072+ err=get_value();
1073+ if (err) return err;
1074+ call_lib_code(LIB_SETDRAWCOUNT);
1075+ return 0;
1076+}
1077+
1078+char* wait_statement(){
1079+ char* err;
1080+ err=get_value();
1081+ if (err) return err;
1082+ call_lib_code(LIB_WAIT);
1083+ return 0;
1084+}
1085+
1086+char* width_statement(){
1087+ char* err;
1088+ err=get_value();
1089+ if (err) return err;
1090+ call_lib_code(LIB_WIDTH);
1091+ return 0;
1092+}
1093+
1094+char* var_statement_sub(int a0, int a1){
1095+ // Construct parameter-setting scripts
1096+ if (a0&0xffff0000) {
1097+ check_obj_space(1);
1098+ g_object[g_objpos++]=0x3C040000|(a0>>16); // lui a0,XXXX
1099+ if (a0&0x0000ffff) {
1100+ check_obj_space(1);
1101+ g_object[g_objpos++]=0x34840000|(a0&0xffff); // ori a0,a0,XXXX
1102+ }
1103+ } else if (a0&0x0000ffff) {
1104+ check_obj_space(1);
1105+ g_object[g_objpos++]=0x34040000|(a0&0xffff); // ori a0,zero,xxxx
1106+ }
1107+ if (a1&0xffff0000) {
1108+ check_obj_space(1);
1109+ g_object[g_objpos++]=0x3C050000|(a1>>16); // lui a1,XXXX
1110+ if (a1&0x0000ffff) {
1111+ check_obj_space(1);
1112+ g_object[g_objpos++]=0x34A50000|(a1&0xffff); // ori a1,a1,XXXX
1113+ }
1114+ } else if (a1&0x0000ffff) {
1115+ check_obj_space(1);
1116+ g_object[g_objpos++]=0x34050000|(a1&0xffff); // ori a1,zero,xxxx
1117+ } else if (a0&0xff000000) {
1118+ // # of variables is 4. Reset $a1 to let lib_var() know that there is no more variables to store.
1119+ check_obj_space(1);
1120+ g_object[g_objpos++]=0x34050000; // ori a1,zero,0
1121+ }
1122+ return 0;
1123+}
1124+
1125+char* var_statement(){
1126+ char* err;
1127+ int i,j,a0,a1;
1128+ static int prevpos;
1129+ short stack;
1130+ do {
1131+ // For stack, 4 bytes are used for return address,
1132+ // 4 bytes are used in lib_var(),
1133+ // and additinal bytes are used for storing variable values.
1134+ stack=8;
1135+ a0=a1=0;
1136+ for (i=0;i<8;i++){
1137+ // Determine the variable number from source code
1138+ j=get_var_number();
1139+ if (j<0) return ERR_SYNTAX;
1140+ stack+=4;
1141+ // Create parameters in $a0, or $a1
1142+ if (i<4) {
1143+ a0=(a0<<8)|(j+1);
1144+ } else {
1145+ a1=(a1<<8)|(j+1);
1146+ }
1147+ // Check remaining variable(s)
1148+ if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') g_srcpos++;
1149+ next_position();
1150+ if (g_source[g_srcpos]!=',') break;
1151+ g_srcpos++;
1152+ }
1153+ // Jump to push routine, first
1154+ check_obj_space(2);
1155+ prevpos=g_objpos;
1156+ g_object[g_objpos++]=0x04130000; // bgezall zero,label1
1157+ g_object[g_objpos++]=0x27BD0000|((0-stack)&0xffff); // addiu sp,sp,-xx
1158+ // Process will be here after RETURN statement
1159+ // Pop routine
1160+ err=var_statement_sub(a0,a1); // Prepare a0, and a1
1161+ if (err) return err;
1162+ call_lib_code(LIB_VAR_POP);
1163+ // Restore stack and return
1164+ check_obj_space(3);
1165+ g_object[g_objpos++]=0x8FA30000|stack; // lw v1,xx(sp)
1166+ g_object[g_objpos++]=0x00600008; // jr v1
1167+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xx
1168+ // Push rotine
1169+ g_object[prevpos]|=g_objpos-prevpos-1; // label1:
1170+ check_obj_space(1);
1171+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
1172+ err=var_statement_sub(a0,a1); // Prepare a0, and a1
1173+ if (err) return err;
1174+ call_lib_code(LIB_VAR_PUSH);
1175+
1176+ } while (g_source[g_srcpos-1]==',');
1177+ return 0;
1178+}
1179+
1180+
1181+char* graphic_statement(enum functions func){
1182+ /*
1183+ PSET X1,Y1[,C]
1184+ LINE X1,Y1,X2,Y2[,C]
1185+ BOXFILL X1,Y1,X2,Y2[,C]
1186+ CIRCLE X1,Y1,R[,C]
1187+ CIRCLEFILL X1,Y1,R[,C]
1188+ GPRINT X1,Y1,C,BC,S$
1189+ PUTBMP X1,Y1,M,N,BMP
1190+ 4(sp): X1
1191+ 8(sp): Y1
1192+ 12(sp): X2/R/M
1193+ 16(sp): Y2/N
1194+ v0: C/S$/BMP
1195+ */
1196+ char* err;
1197+ int paramnum;
1198+ switch(func){
1199+ case FUNC_PSET:// X1,Y1[,C]
1200+ case FUNC_GCOLOR:// X1,Y1
1201+ case FUNC_POINT:// X1,Y1
1202+ paramnum=2;
1203+ break;
1204+ case FUNC_CIRCLE:// X1,Y1,R[,C]
1205+ case FUNC_CIRCLEFILL:// X1,Y1,R[,C]
1206+ paramnum=3;
1207+ break;
1208+ case FUNC_LINE:// X1,Y1,X2,Y2[,C]
1209+ case FUNC_BOXFILL:// X1,Y1,X2,Y2[,C]
1210+ paramnum=4;
1211+ break;
1212+ case FUNC_GPRINT:// X1,Y1,C,BC,S$
1213+ case FUNC_PUTBMP:// X1,Y1,M,N,BMP
1214+ paramnum=5;
1215+ break;
1216+ default:
1217+ return ERR_UNKNOWN;
1218+ }
1219+
1220+ next_position();
1221+ if (g_source[g_srcpos]==',') {
1222+ // X1 and Y1 is omitted. Set 0x80000000 for both.
1223+ check_obj_space(4);
1224+ g_object[g_objpos++]=0x27BDFFF0; // addiu sp,sp,-16
1225+ g_object[g_objpos++]=0x3C028000; // lui v0,0x0080
1226+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1227+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1228+ } else {
1229+ // X1
1230+ err=get_value();
1231+ if (err) return err;
1232+ check_obj_space(2);
1233+ g_object[g_objpos++]=0x27BDFFF0; // addiu sp,sp,-16
1234+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1235+ // Y1
1236+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1237+ g_srcpos++;
1238+ err=get_value();
1239+ if (err) return err;
1240+ check_obj_space(1);
1241+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1242+ }
1243+ if (2<paramnum) {
1244+ // X2, R, or M
1245+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1246+ g_srcpos++;
1247+ err=get_value();
1248+ if (err) return err;
1249+ check_obj_space(1);
1250+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
1251+ if (3<paramnum) {
1252+ // Y2, BC, or N
1253+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1254+ g_srcpos++;
1255+ err=get_value();
1256+ if (err) return err;
1257+ check_obj_space(1);
1258+ g_object[g_objpos++]=0xAFA20010; // sw v0,16(sp)
1259+ }
1260+ }
1261+ if (func==FUNC_GPRINT) {
1262+ // S$
1263+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1264+ g_srcpos++;
1265+ err=get_string();
1266+ if (err) return err;
1267+ } else if (func==FUNC_PUTBMP) {
1268+ // BMP
1269+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1270+ g_srcpos++;
1271+ err=get_label();
1272+ if (g_label && !err) {
1273+ // Label/number is constant.
1274+ // Linker will change following codes later.
1275+ // Note that 0x0814xxxx and 0x0815xxxx are specific codes for these.
1276+ check_obj_space(2);
1277+ g_object[g_objpos++]=0x08140000|((g_label>>16)&0x0000FFFF); // lui v0,xxxx
1278+ g_object[g_objpos++]=0x08150000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
1279+ // Change func to FUNC_PUTBMP2 (label mode).
1280+ func=FUNC_PUTBMP2;
1281+ } else {
1282+ err=get_value();
1283+ if (err) return err;
1284+ }
1285+ } else {
1286+ // [,C]
1287+ if (g_source[g_srcpos]==',') {
1288+ g_srcpos++;
1289+ err=get_value();
1290+ if (err) return err;
1291+ } else {
1292+ // If C is omitted, use -1.
1293+ check_obj_space(1);
1294+ g_object[g_objpos++]=0x2402FFFF; // addiu v0,zero,-1
1295+ }
1296+ }
1297+ // Call library
1298+ call_lib_code(LIB_GRAPHIC | func);
1299+ // Restore stack pointer
1300+ check_obj_space(1);
1301+ g_object[g_objpos++]=0x27BD0010; // addiu sp,sp,16
1302+ return 0;
1303+}
1304+
1305+char* fopen_statement(enum functions func){
1306+ // func is either FUNC_FOPENST or FUNC_FOPEN
1307+ char* err;
1308+ // Get 1st
1309+ err=get_string();
1310+ if (err) return err;
1311+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1312+ g_srcpos++;
1313+ check_obj_space(2);
1314+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
1315+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1316+ // Get 2nd
1317+ err=get_string();
1318+ if (err) return err;
1319+ check_obj_space(1);
1320+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1321+ // Get 3rd
1322+ if (g_source[g_srcpos]==',') {
1323+ g_srcpos++;
1324+ err=get_value();
1325+ if (err) return err;
1326+ } else {
1327+ // If 3rd parameter is omitted, use 0.
1328+ check_obj_space(1);
1329+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1330+ }
1331+ call_lib_code(LIB_FILE | func);
1332+ check_obj_space(1);
1333+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
1334+ return 0;
1335+}
1336+
1337+char* file_statement(){
1338+ char* err;
1339+ err=get_value();
1340+ if (err) return err;
1341+ call_lib_code(LIB_FILE | FUNC_FILE);
1342+ return 0;
1343+}
1344+
1345+char* fclose_statement(){
1346+ char* err;
1347+ int orgpos=g_srcpos;
1348+ if (endOfStatement()) {
1349+ // If no argument, use 0
1350+ check_obj_space(1);
1351+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1352+ } else {
1353+ err=get_value();
1354+ if (err) return err;
1355+ }
1356+ call_lib_code(LIB_FILE | FUNC_FCLOSE);
1357+ return 0;
1358+}
1359+
1360+char* fprint_statement(){
1361+ return print_statement(LIB_FILE | FUNC_FPRINTSTR,LIB_FILE | FUNC_FSTRING);
1362+}
1363+
1364+char* fget_statement(){
1365+ return param2_statement(LIB_FILE | FUNC_FGET);
1366+}
1367+
1368+char* fput_statement(){
1369+ return param2_statement(LIB_FILE | FUNC_FPUT);
1370+}
1371+
1372+char* fseek_statement(){
1373+ char* err;
1374+ err=get_value();
1375+ if (err) return err;
1376+ call_lib_code(LIB_FILE | FUNC_FSEEK);
1377+ return 0;
1378+}
1379+
1380+char* fputc_statement(){
1381+ char* err;
1382+ err=get_value();
1383+ if (err) return err;
1384+ call_lib_code(LIB_FILE | FUNC_FPUTC);
1385+ return 0;
1386+}
1387+
1388+char* fremove_statement(){
1389+ char* err;
1390+ err=get_string();
1391+ if (err) return err;
1392+ call_lib_code(LIB_FILE | FUNC_FREMOVE);
1393+ return 0;
1394+}
1395+
1396+char* usevar_statement(){
1397+ char* err;
1398+ int i;
1399+ do {
1400+ next_position();
1401+ i=check_var_name();
1402+ if (i<65536) return ERR_SYNTAX;
1403+ err=register_var_name(i);
1404+ if (err) return err;
1405+ if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') g_srcpos++;
1406+ next_position();
1407+ if (g_source[g_srcpos]==',') {
1408+ g_srcpos++;
1409+ } else {
1410+ break;
1411+ }
1412+ } while(1);
1413+ return 0;
1414+}
1415+
1416+#ifdef __DEBUG
1417+ char* debug_statement(){
1418+ call_lib_code(LIB_DEBUG);
1419+ return 0;
1420+ }
1421+#endif
1422+
1423+
1424+char* statement(void){
1425+ char* err;
1426+ int prevpos;
1427+ // Clear flag for temp area usage.
1428+ g_temp_area_used=0;
1429+ // Initialize stack handler used for value
1430+ g_sdepth=g_maxsdepth=0;
1431+ if (nextCodeIs("REM")) {
1432+ err=rem_statement();
1433+ } else if (nextCodeIs("SOUND ")) {
1434+ err=sound_statement();
1435+ } else if (nextCodeIs("MUSIC ")) {
1436+ err=music_statement();
1437+ } else if (nextCodeIs("DRAWCOUNT ")) {
1438+ err=drawcount_statement();
1439+ } else if (nextCodeIs("CURSOR ")) {
1440+ err=cursor_statement();
1441+ } else if (nextCodeIs("PALETTE ")) {
1442+ err=param4_statement(LIB_PALETTE);
1443+ } else if (nextCodeIs("GPALETTE ")) {
1444+ err=param4_statement(LIB_GPALETTE);
1445+ } else if (nextCodeIs("BGCOLOR ")) {
1446+ err=bgcolor_statement();
1447+ } else if (nextCodeIs("CLS")) {
1448+ err=cls_statement();
1449+ } else if (nextCodeIs("GCLS")) {
1450+ err=gcls_statement();
1451+ } else if (nextCodeIs("COLOR ")) {
1452+ err=color_statement();
1453+ } else if (nextCodeIs("GCOLOR ")) {
1454+ err=gcolor_statement();
1455+ } else if (nextCodeIs("RESTORE ")) {
1456+ err=restore_statement();
1457+ } else if (nextCodeIs("DATA ")) {
1458+ err=data_statement();
1459+ } else if (nextCodeIs("CDATA ")) {
1460+ err=cdata_statement();
1461+ } else if (nextCodeIs("LABEL ")) {
1462+ err=label_statement();
1463+ } else if (nextCodeIs("DIM ")) {
1464+ err=dim_statement();
1465+ } else if (nextCodeIs("CLEAR")) {
1466+ err=clear_statement();
1467+ } else if (nextCodeIs("PRINT")) {
1468+ err=print_statement(LIB_PRINTSTR,LIB_STRING);
1469+ } else if (nextCodeIs("IF ")) {
1470+ err=if_statement();
1471+ } else if (nextCodeIs("ELSEIF ")) {
1472+ err=elseif_statement();
1473+ } else if (nextCodeIs("ELSE")) {
1474+ err=else_statement();
1475+ } else if (nextCodeIs("ENDIF")) {
1476+ err=endif_statement();
1477+ } else if (nextCodeIs("END")) {
1478+ err=end_statement();
1479+ } else if (nextCodeIs("EXEC ")) {
1480+ err=exec_statement();
1481+ } else if (nextCodeIs("GOTO ")) {
1482+ err=goto_statement();
1483+ } else if (nextCodeIs("GOSUB ")) {
1484+ err=gosub_statement();
1485+ } else if (nextCodeIs("RETURN")) {
1486+ err=return_statement();
1487+ } else if (nextCodeIs("POKE ")) {
1488+ err=poke_statement();
1489+ } else if (nextCodeIs("FOR ")) {
1490+ err=for_statement();
1491+ } else if (nextCodeIs("NEXT")) {
1492+ err=next_statement();
1493+ } else if (nextCodeIs("LET ")) {
1494+ err=let_statement();
1495+ } else if (nextCodeIs("PCG ")) {
1496+ err=pcg_statement();
1497+ } else if (nextCodeIs("USEPCG")) {
1498+ err=usepcg_statement();
1499+ } else if (nextCodeIs("SCROLL ")) {
1500+ err=scroll_statement();
1501+ } else if (nextCodeIs("WAIT ")) {
1502+ err=wait_statement();
1503+ } else if (nextCodeIs("USEGRAPHIC")) {
1504+ err=usegraphic_statement();
1505+ } else if (nextCodeIs("PSET ")) {
1506+ err=graphic_statement(FUNC_PSET);
1507+ } else if (nextCodeIs("LINE ")) {
1508+ err=graphic_statement(FUNC_LINE);
1509+ } else if (nextCodeIs("BOXFILL ")) {
1510+ err=graphic_statement(FUNC_BOXFILL);
1511+ } else if (nextCodeIs("CIRCLE ")) {
1512+ err=graphic_statement(FUNC_CIRCLE);
1513+ } else if (nextCodeIs("CIRCLEFILL ")) {
1514+ err=graphic_statement(FUNC_CIRCLEFILL);
1515+ } else if (nextCodeIs("GPRINT ")) {
1516+ err=graphic_statement(FUNC_GPRINT);
1517+ } else if (nextCodeIs("PUTBMP ")) {
1518+ err=graphic_statement(FUNC_PUTBMP);
1519+ } else if (nextCodeIs("POINT ")) {
1520+ err=graphic_statement(FUNC_POINT);
1521+ } else if (nextCodeIs("VAR ")) {
1522+ err=var_statement();
1523+ } else if (nextCodeIs("DO")) {
1524+ err=do_statement();
1525+ } else if (nextCodeIs("LOOP")) {
1526+ err=loop_statement();
1527+ } else if (nextCodeIs("WHILE ")) {
1528+ err=while_statement();
1529+ } else if (nextCodeIs("WEND")) {
1530+ err=wend_statement();
1531+ } else if (nextCodeIs("BREAK")) {
1532+ err=break_statement();
1533+ } else if (nextCodeIs("CONTINUE")) {
1534+ err=continue_statement();
1535+ } else if (nextCodeIs("SYSTEM")) {
1536+ err=system_statement();
1537+ } else if (nextCodeIs("WIDTH ")) {
1538+ err=width_statement();
1539+ } else if (nextCodeIs("FOPEN ")) {
1540+ err=fopen_statement(FUNC_FOPENST);
1541+ } else if (nextCodeIs("FILE ")) {
1542+ err=file_statement();
1543+ } else if (nextCodeIs("FCLOSE")) {
1544+ err=fclose_statement();
1545+ } else if (nextCodeIs("FPRINT ")) {
1546+ err=fprint_statement();
1547+ } else if (nextCodeIs("FGET ")) {
1548+ err=fget_statement();
1549+ } else if (nextCodeIs("FPUT ")) {
1550+ err=fput_statement();
1551+ } else if (nextCodeIs("FPUTC ")) {
1552+ err=fputc_statement();
1553+ } else if (nextCodeIs("FSEEK ")) {
1554+ err=fseek_statement();
1555+ } else if (nextCodeIs("FREMOVE ")) {
1556+ err=fremove_statement();
1557+ } else if (nextCodeIs("USEVAR ")) {
1558+ err=usevar_statement();
1559+#ifdef __DEBUG
1560+ } else if (nextCodeIs("DEBUG")) {
1561+ err=debug_statement();
1562+#endif
1563+ } else {
1564+ err=let_statement();
1565+ }
1566+ if (err) return err;
1567+ // Stack handler must be zero here.
1568+ if (g_sdepth!=0) return ERR_UNKNOWN;
1569+ // Check if temp area is used
1570+ if (g_temp_area_used) {
1571+ // Temp area is used. Insert a garbage collection flag setting routine.
1572+ check_obj_space(1);
1573+ g_object[g_objpos++]=0x7ED6F000;// ext s6,s6,0,31
1574+ }
1575+ return 0;
1576+}
--- /dev/null
+++ b/mips/zoea/string.c
@@ -0,0 +1,216 @@
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+ Public functions:
10+ char* get_string(void);
11+ char* simple_string(void);
12+*/
13+
14+#include "api.h"
15+#include "compiler.h"
16+
17+char* simple_string(void){
18+ char* err;
19+ unsigned char b1,b2;
20+ int i,j;
21+ next_position();
22+ b1=g_source[g_srcpos];
23+ b2=g_source[g_srcpos+1];
24+ if (b1=='"') {
25+ // Constant string
26+ // Count character number (+1 for \0)
27+ // This may be more than actual character number due to escape sequence.
28+ i=0;
29+ while(1){
30+ i++;
31+ b1=g_source[g_srcpos+i];
32+ if (b1=='"') {
33+ break;
34+ } else if (b1=='\\') {
35+ i++;
36+ } else if (b1<0x20) {
37+ // This is an error, that will be detected later again.
38+ break;
39+ }
40+ };
41+ g_srcpos++;
42+ // Determine required word number
43+ i=(i+3)/4;
44+ // Determine address containing the string
45+ j=(int)(&(g_object[g_objpos+3]));
46+ // Note that using "bgezal zero," must be used to skip some region.
47+ // This is to find embed string in the code.
48+ check_obj_space(2+i);
49+ g_object[g_objpos++]=0x04110000|((i+1)&0x0000FFFF); // bgezal zero,xxxx
50+ g_object[g_objpos++]=0x03E01021; // addu v0,ra,zero
51+ for(j=0;(b1=g_source[g_srcpos++])!='"';j++) {
52+ if (b1=='\\') {
53+ b1=g_source[g_srcpos++];
54+ if (b1=='x' || b1=='X') {
55+ // Hexadecimal
56+ b1=g_source[g_srcpos++];
57+ if ('0'<=b1 && b1<='9') b1=b1-'0';
58+ else if ('A'<=b1 && b1<='F') b1=b1-'A'+10;
59+ else if ('a'<=b1 && b1<='f') b1=b1-'a'+10;
60+ else return ERR_SYNTAX;
61+ b2=g_source[g_srcpos++];
62+ if ('0'<=b2 && b2<='9') b2=b2-'0';
63+ else if ('A'<=b2 && b2<='F') b2=b2-'A'+10;
64+ else if ('a'<=b2 && b2<='f') b2=b2-'a'+10;
65+ else return ERR_SYNTAX;
66+ b1=(b1<<4)|b2;
67+ } else if (b1<0x20) {
68+ return ERR_SYNTAX;
69+ } else {
70+ // \\ or \"
71+ }
72+ } else if (b1<0x20) {
73+ return ERR_SYNTAX;
74+ }
75+ ((char*)(&g_object[g_objpos]))[j]=b1;
76+ }
77+ ((char*)(&g_object[g_objpos]))[j]=0x00;
78+ g_objpos+=i;
79+ } else if ('A'<=b1 && b1<='Z') {
80+ i=get_var_number();
81+ if (i<0) {
82+ // Function
83+ // String would be pointed by $v0
84+ // Otherwise, it will be assinged in xxx_function() function.
85+ err=str_function();
86+ if (err) return err;
87+ // Temp area would be used when executing.
88+ g_temp_area_used=1;
89+ return 0;
90+ }
91+ if (g_source[g_srcpos]!='$') return ERR_SYNTAX;
92+ g_srcpos++;
93+ // String variable
94+ next_position();
95+ if (g_source[g_srcpos]=='(') {
96+ // A part of string
97+ g_srcpos++;
98+ err=get_value();
99+ if (err) return err;
100+ if (g_source[g_srcpos]==')') {
101+ g_srcpos++;
102+ // Put -1 to $a0
103+ check_obj_space(1);
104+ g_object[g_objpos++]=0x2404FFFF; // addiu a0,zero,-1
105+ } else if (g_source[g_srcpos]==',') {
106+ g_srcpos++;
107+ // Store $v0 in stack
108+ g_sdepth+=4;
109+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
110+ check_obj_space(1);
111+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
112+ // Get next value
113+ err=get_value();
114+ if (err) return err;
115+ // Copy $v0 to $a0 and get value from stack to $a0.
116+ check_obj_space(2);
117+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
118+ g_object[g_objpos++]=0x8FA20000|g_sdepth; // lw v0,xx(sp)
119+ g_sdepth-=4;
120+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
121+ g_srcpos++;
122+ // Temp area will be used when executing.
123+ g_temp_area_used=1;
124+ } else {
125+ return ERR_SYNTAX;
126+ }
127+ // $a1 is var number, $v0 is position, $a0 is length
128+ check_obj_space(1);
129+ g_object[g_objpos++]=0x24050000|(i); // addiu a1,zero,xx
130+ call_lib_code(LIB_MIDSTR);
131+ } else {
132+ // Simple string
133+ check_obj_space(1);
134+ g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
135+ // String is pointed by $v0
136+ }
137+ } else {
138+ return ERR_SYNTAX;
139+ }
140+ return 0;
141+}
142+
143+char* get_string_sub(){
144+ char* err;
145+ char b1;
146+ // Obtain initial string
147+ err=simple_string();
148+ if (err) return err;
149+ // Check if connection operator exists
150+ next_position();
151+ b1=g_source[g_srcpos];
152+ if (b1!='+' && b1!='&') return 0; // Exit if connection operator does not exist.
153+ g_srcpos++;
154+ // Connection required.
155+ // Prepare one level of stack for handling
156+ g_sdepth+=4;
157+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
158+ while(1) {
159+ // Store current pointer in stack
160+ check_obj_space(1);
161+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
162+ // Obtain next string (pointer will be in $v0)
163+ err=simple_string();
164+ if (err) return err;
165+ // Restore previous pointer from stack in $a0 and copy $v0 to $a1
166+ // Call library
167+ check_obj_space(2);
168+ g_object[g_objpos++]=0x8FA40000|g_sdepth; // lw a0,xx(sp)
169+ call_lib_code(LIB_CONNECT_STRING);
170+ // Temp area will be used when executing.
171+ g_temp_area_used=1;
172+ // Check if further connection operator exists
173+ next_position();
174+ b1=g_source[g_srcpos];
175+ if (b1!='+' && b1!='&') break;
176+ g_srcpos++;
177+ }
178+ g_sdepth-=4;
179+ return 0;
180+}
181+
182+char* get_string(){
183+ // This is only the public function.
184+ // Note that this can be called recursively.
185+ // String may contain a function with a parameter of value
186+ // that is a function with a parameter of string.
187+ // Result will be in $v0 as a pointer.
188+ char* err;
189+ char b1;
190+ int i,prevpos;
191+ if (g_sdepth==0) {
192+ // Initialize stack handler
193+ g_maxsdepth=0;
194+ prevpos=g_objpos;
195+ // Stack decrement command will be filled later
196+ check_obj_space(1);
197+ g_objpos++;
198+ }
199+ err=get_string_sub();
200+ if (err) return err;
201+ if (g_sdepth==0) {
202+ if (g_maxsdepth==0) {
203+ // Stack was not used.
204+ shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
205+ g_objpos--;
206+ } else {
207+ // Stack was used.
208+ check_obj_space(1);
209+ g_object[prevpos]=0x27BD0000 | (0-g_maxsdepth) & 0x0000FFFF; // addiu sp,sp,-xx
210+ g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx
211+ }
212+ }
213+ g_lastvar=VAR_STRING;
214+ return 0;
215+}
216+
--- /dev/null
+++ b/mips/zoea/value.c
@@ -0,0 +1,267 @@
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+ Public function is only get_value().
10+*/
11+
12+#include "compiler.h"
13+
14+char* get_value();
15+char* get_value_sub(int pr);
16+
17+char* get_dim_value(int i){
18+ char* err;
19+ err=get_value_sub(priority(OP_VOID));
20+ if (err) return err;
21+ check_obj_space(4);
22+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
23+ g_object[g_objpos++]=0x8FC30000|(i*4); // lw v1,xx(s8)
24+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
25+ g_object[g_objpos++]=0x8C620000; // lw v0,0(v1)
26+ next_position();
27+ if (g_source[g_srcpos]==','){
28+ // 2D, 3D or more
29+ // Use a stack
30+ g_sdepth+=4;
31+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
32+ check_obj_space(1);
33+ do {
34+ g_srcpos++;
35+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
36+ err=get_value_sub(priority(OP_VOID));
37+ if (err) return err;
38+ check_obj_space(5);
39+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
40+ g_object[g_objpos++]=0x8FA30000|g_sdepth; // lw v1,xx(sp)
41+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
42+ g_object[g_objpos++]=0x8C620000; // lw v0,0(v1)
43+ } while (g_source[g_srcpos]==',');
44+ g_sdepth-=4;
45+ }
46+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
47+ g_srcpos++;
48+ return 0;
49+}
50+
51+char* get_simple_value(void){
52+ int i;
53+ char* err;
54+ char b1,b2;
55+ next_position();
56+ b1=g_source[g_srcpos];
57+ if (b1=='(') {
58+ // (...)
59+ // Parenthesis
60+ g_srcpos++;
61+ next_position();
62+ err=get_value_sub(priority(OP_VOID));
63+ if (err) return err;
64+ next_position();
65+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
66+ g_srcpos++;
67+ } else if (b1=='-') {
68+ // Unary '-' operator
69+ // Note that unary operators ( + and - ) have higher priority than the other operators
70+ g_srcpos++;
71+ err=get_simple_value();
72+ if (err) return err;
73+ check_obj_space(1);
74+ g_object[g_objpos++]=0x00021023; // subu v0,zero,v0
75+ g_intconst=-g_intconst;
76+ } else {
77+ // Main routine of getting value here
78+ if (b1=='+') g_srcpos++; // Ignore unary '+' operator
79+ next_position();
80+ b1=g_source[g_srcpos];
81+ b2=g_source[g_srcpos+1];
82+ if (b1=='0' && b2=='X' || b1=='$') {
83+ // Starts with '0x' or '$'
84+ // Hex number
85+ g_srcpos++;
86+ if (b1=='0') g_srcpos++;
87+ i=0;
88+ while(b1=g_source[g_srcpos]) {
89+ if ('0'<=b1 && b1<='9') {
90+ i*=16;
91+ i+=b1-'0';
92+ } else if ('A'<=b1 && b1<='F') {
93+ i*=16;
94+ i+=b1-'A'+0x0A;
95+ } else {
96+ break;
97+ }
98+ g_srcpos++;
99+ }
100+ g_intconst=i;
101+ if (i&0xFFFF0000) {
102+ // 32 bit
103+ check_obj_space(2);
104+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
105+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
106+ } else {
107+ // 16 bit
108+ check_obj_space(1);
109+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
110+ }
111+ } else if ('0'<=b1 && b1<='9') {
112+ // Starts with 0-9
113+ // Decimal number
114+ i=0;
115+ while(b1=g_source[g_srcpos]) {
116+ if ('0'<=b1 && b1<='9') {
117+ i*=10;
118+ i+=b1-'0';
119+ } else {
120+ break;
121+ }
122+ g_srcpos++;
123+ }
124+ // The next character should not be '.' or 'E'.
125+ // Or, it must be recognized as a float value.
126+ if (b1=='.' || b1=='E') return ERR_SYNTAX;
127+ g_intconst=i;
128+ if (i&0xFFFF0000) {
129+ // 32 bit
130+ check_obj_space(2);
131+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
132+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
133+ } else {
134+ // 16 bit
135+ check_obj_space(1);
136+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
137+ }
138+ } else {
139+ g_valueisconst=0;
140+ i=get_var_number();
141+ if (i<0) {
142+ // Must be a function.
143+ return function();
144+ }
145+ if (g_source[g_srcpos]=='(') {
146+ // Dimension
147+ g_srcpos++;
148+ return get_dim_value(i);
149+ }
150+ // Simple value
151+ check_obj_space(1);
152+ g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
153+ }
154+ }
155+ // No error
156+ return 0;
157+}
158+
159+char* get_value_sub(int pr){
160+ char* err;
161+ enum operator op;
162+ char b1,b2,b3;
163+ int prevpos;
164+ // Get a value in $v0.
165+ err=get_simple_value();
166+ if (err) return err;
167+ while(1){
168+ // Get the operator in op. If not valid operator, simply return without error.
169+ prevpos=g_srcpos;
170+ err=get_operator();
171+ if (err) return 0;
172+ op=g_last_op;
173+ // Compair current and previous operators.
174+ // If the previous operator has higher priolity, return.
175+ if (pr>=priority(op)) {
176+ g_srcpos=prevpos;
177+ return 0;
178+ }
179+ // Store $v0 in stack
180+ g_sdepth+=4;
181+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
182+ check_obj_space(1);
183+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
184+ // Get next value.
185+ err=get_value_sub(priority(op));
186+ if (err) return err;
187+ // Get value from stack to $v1.
188+ check_obj_space(1);
189+ g_object[g_objpos++]=0x8FA30000|g_sdepth; // lw v1,xx(sp)
190+ g_sdepth-=4;
191+ // Calculation. Result will be in $v0.
192+ err=calculation(op);
193+ if (err) return err;
194+ }
195+}
196+
197+char* get_value(){
198+ // This is only the public function.
199+ // Note that this can be called recursively.
200+ // Value may contain function with a parameter of another value.
201+ char* err;
202+ int prevpos;
203+ if (g_sdepth==0) {
204+ // Initialize stack handler
205+ g_maxsdepth=0;
206+ prevpos=g_objpos;
207+ // Stack decrement command will be filled later
208+ check_obj_space(1);
209+ g_objpos++;
210+ }
211+ err=get_value_sub(priority(OP_VOID));
212+ if (err) return err;
213+ if (g_sdepth==0) {
214+ if (g_maxsdepth==0) {
215+ // Stack was not used.
216+ shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
217+ g_objpos--;
218+ } else {
219+ // Stack was used.
220+ check_obj_space(1);
221+ g_object[prevpos]=0x27BD0000 | (0-g_maxsdepth) & 0x0000FFFF; // addiu sp,sp,-xx
222+ g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx
223+ }
224+ }
225+ g_lastvar=VAR_INTEGER;
226+ return 0;
227+}
228+
229+char* get_floatOrValue(){
230+ char* err;
231+ char b;
232+ int opos,spos,sdpt;
233+ sdpt=g_sdepth;
234+ opos=g_objpos;
235+ spos=g_srcpos;
236+ // First try integer.
237+ // Integer value has the higher priolity than float value.
238+ err=get_value();
239+ b=g_source[g_srcpos];
240+ if (err || b=='#') {
241+ // Value is not integer. Let's try float.
242+ g_sdepth=sdpt;
243+ g_objpos=opos;
244+ g_srcpos=spos;
245+ return get_float();
246+ } else {
247+ // Value was recognized as an integer.
248+ return 0;
249+ }
250+}
251+
252+char* get_stringFloatOrValue(){
253+ char* err;
254+ int opos,spos;
255+ opos=g_objpos;
256+ spos=g_srcpos;
257+ // First try string, float, then integer.
258+ err=get_string();
259+ if (err) {
260+ g_objpos=opos;
261+ g_srcpos=spos;
262+ return get_floatOrValue();
263+ } else {
264+ return 0;
265+ }
266+}
267+
--- /dev/null
+++ b/mips/zoea/varname.c
@@ -0,0 +1,226 @@
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 "compiler.h"
9+
10+/*
11+ static const int reserved_var_names[];
12+ This dimension contains var name integers of reserved var names.
13+ To make following structure, execute "reservednames.js" in Windows.
14+*/
15+
16+static const int reserved_var_names[]={
17+ 0x000106b8, //ABS
18+ 0x0001f67c, //ACOS
19+ 0x0002414c, //ARGS
20+ 0x0001090c, //ASC
21+ 0x0002469f, //ASIN
22+ 0x00024a8f, //ATAN
23+ 0x002f7c1e, //ATAN2
24+ 0x0047c31c, //BREAK
25+ 0x00575afe, //CDATA
26+ 0x00036c3d, //CEIL
27+ 0x000111af, //CHR
28+ 0x0cb1b682, //CIRCLE
29+ 0x005d1ea3, //CLEAR
30+ 0x00011240, //CLS
31+ 0x005f66cb, //COLOR
32+ 0x000112ac, //COS
33+ 0x0003a041, //COSH
34+ 0x00616415, //CREAD
35+ 0x0de593fb, //CURSOR
36+ 0x00040fbe, //DATA
37+ 0x00011644, //DEC
38+ 0x000116de, //DIM
39+ 0x000100a8, //DO
40+ 0x0004fd8e, //ELSE
41+ 0x1434a177, //ELSEIF
42+ 0x00011c99, //END
43+ 0x0091c927, //ENDIF
44+ 0x00053854, //EXEC
45+ 0x00011e0d, //EXP
46+ 0x000579c8, //FABS
47+ 0x16e3d4be, //FCLOSE
48+ 0x00058fcf, //FEOF
49+ 0x00059895, //FGET
50+ 0x00a67500, //FGETC
51+ 0x0005a3a2, //FILE
52+ 0x177f0ca5, //FINPUT
53+ 0x0005b1df, //FLEN
54+ 0x00aa3445, //FLOAT
55+ 0x00aa363b, //FLOOR
56+ 0x0005b84d, //FMOD
57+ 0x00ac5c9f, //FOPEN
58+ 0x000121db, //FOR
59+ 0x18352839, //FPRINT
60+ 0x0005c865, //FPUT
61+ 0x00ad2e40, //FPUTC
62+ 0x00aefdec, //FSEEK
63+ 0x00063b90, //GCLS
64+ 0x1a808bcb, //GCOLOR
65+ 0x00c60f03, //GOSUB
66+ 0x0006796c, //GOTO
67+ 0x1bcfcc39, //GPRINT
68+ 0x00012a99, //HEX
69+ 0x00010153, //IF
70+ 0x00f8701a, //INKEY
71+ 0x00f88ba5, //INPUT
72+ 0x000130e9, //INT
73+ 0x00092084, //KEYS
74+ 0x013be43d, //LABEL
75+ 0x00013ecf, //LEN
76+ 0x00013ed5, //LET
77+ 0x0009e96a, //LINE
78+ 0x00014030, //LOG
79+ 0x0145f324, //LOG10
80+ 0x000a07f9, //LOOP
81+ 0x000abca3, //MODF
82+ 0x016418d4, //MUSIC
83+ 0x000b4321, //NEXT
84+ 0x00014a5d, //NOT
85+ 0x000152c0, //PCG
86+ 0x000cacec, //PEEK
87+ 0x00010252, //PI
88+ 0x01ac8479, //POINT
89+ 0x000ce05e, //POKE
90+ 0x00015480, //POW
91+ 0x01aea739, //PRINT
92+ 0x000cf3d5, //PSET
93+ 0x3cc0fe21, //PUTBMP
94+ 0x000e18d5, //READ
95+ 0x00015d2e, //REM
96+ 0x425c9703, //RETURN
97+ 0x00015e69, //RND
98+ 0x45c26d49, //SCROLL
99+ 0x00016287, //SGN
100+ 0x000162cf, //SIN
101+ 0x000ee52d, //SINH
102+ 0x01f9a429, //SOUND
103+ 0x000f0e49, //SQRT
104+ 0x47f711de, //SYSTEM
105+ 0x000166bf, //TAN
106+ 0x000f72ed, //TANH
107+ 0x02182fee, //TVRAM
108+ 0x022c2a2d, //UNTIL
109+ 0x4e8887d0, //USEPCG
110+ 0x4e88a5f3, //USEVAR
111+ 0x000170dd, //VAL
112+ 0x000170e3, //VAR
113+ 0x00119505, //WAIT
114+ 0x0011a9e9, //WEND
115+ 0x025aef62, //WHILE
116+ 0x025b8d75, //WIDTH
117+};
118+
119+/*
120+ check_var_name();
121+ This function reads the current position of source code and check if
122+ it contains valid var name, the function returns 0 or plus value.
123+ If not, it returns -1;
124+*/
125+
126+int check_var_name(){
127+ char b1;
128+ int j;
129+ int i=0;
130+ int prevpos=g_srcpos;
131+ next_position();
132+ b1=g_source[g_srcpos];
133+ if (b1<'A' || 'Z'<b1) return -1;
134+ do {
135+ // First character must be A-Z
136+ // From second, A-Z and 0-9 can be used.
137+ i*=36;
138+ if ('0'<=b1 && b1<='9') {
139+ i+=b1-'0';
140+ } else if (g_srcpos==prevpos) {
141+ // First character must be A-Z.
142+ // Subtract 9, resulting 1-26 but not 10-35.
143+ // This subtraction is required to maintain
144+ // final number being <0x80000000.
145+ i+=b1-'A'+1;
146+ } else {
147+ i+=b1-'A'+10;
148+ }
149+ g_srcpos++;
150+ b1=g_source[g_srcpos];
151+ } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z');
152+ // Length of the label must be between 2 and 6.
153+ if (g_srcpos-prevpos<2) {
154+ // One letter var name, A-Z
155+ return i-1;
156+ }
157+ if (6<g_srcpos-prevpos) {
158+ // Too long. This is not var name.
159+ g_srcpos=prevpos;
160+ return -1;
161+ }
162+ i+=65536;
163+ // Check if this is reserved var name.
164+ for(j=0;j<sizeof reserved_var_names/sizeof reserved_var_names[0];j++){
165+ if (reserved_var_names[j]==i) {
166+ // This var name is reserved as used for function or statement.
167+ g_srcpos=prevpos;
168+ return -1;
169+ }
170+ }
171+ // Reserved var names table was checked. This must be a long var name.
172+ return i;
173+}
174+
175+/*
176+ int get_var_number();
177+ This function returns variable number that can be used as the index of $s8
178+*/
179+
180+int get_var_number(){
181+ int i;
182+ // This must be a short or long var name.
183+ i=check_var_name();
184+ if (i<0) return -1;
185+ // If it is a short name, immediately return.
186+ if (i<26) return i;
187+ // Search long var names registered by USEVAR statement.
188+ // If found, returns the value that can be used as the index of $s8
189+ i=search_var_name(i);
190+ if (i<0) return -1;
191+ // This var name is defined by USEVAR statement.
192+ return i+ALLOC_LNV_BLOCK;
193+
194+}
195+
196+/*
197+ int search_var_name(int nameint);
198+ This function searchs registered long var name in compile data table.
199+ If not found, this function returns -1.
200+ If found, it retunrs var number, beginning 0.
201+*/
202+
203+int search_var_name(int nameint){
204+ int* cmpdata;
205+ cmpdata_reset();
206+ while(cmpdata=cmpdata_find(CMPDATA_USEVAR)){
207+ if (cmpdata[1]==nameint) return cmpdata[0]&0x0000ffff;
208+ }
209+ return -1;
210+}
211+
212+/*
213+ char* register_var_name(int nameint);
214+ This function is called when compiler detects "USEVAR" statement.
215+ It registers the long file name in compile data table.
216+*/
217+
218+char* register_var_name(int nameint){
219+ // Check if registered before. If did, cause error.
220+ if (search_var_name(nameint)!=-1) return ERR_INVALID_VAR_NAME;
221+ // Number of long var name is restricted
222+ if (ALLOC_LNV_NUM<=g_long_name_var_num) return ERR_INVALID_VAR_NAME;
223+ // Register var name as a compile data
224+ g_temp=nameint;
225+ return cmpdata_insert(CMPDATA_USEVAR,g_long_name_var_num++,&g_temp,1);
226+}
--- /dev/null
+++ b/mips/zoea/videoout.h
@@ -0,0 +1,116 @@
1+//#define WIDTH_X 30 // 横方向文字数
2+#define WIDTH_X1 30 // 横方向文字数1
3+#define WIDTH_X2 40 // 横方向文字数2(6ドットフォント利用時)
4+#define WIDTH_Y 27 // 縦方向文字数
5+//#define ATTROFFSET (WIDTH_X*WIDTH_Y) // VRAM上のカラーパレット格納位置
6+#define ATTROFFSET1 (WIDTH_X1*WIDTH_Y) // VRAM上のカラーパレット格納位置1
7+#define ATTROFFSET2 (WIDTH_X2*WIDTH_Y) // VRAM上のカラーパレット格納位置2
8+
9+#define G_X_RES 256 // 横方向解像度
10+#define G_Y_RES 224 // 縦方向解像度
11+#define G_H_WORD (G_X_RES/4) // 1行当りのワード数(16bit単位)
12+
13+
14+// 入力ボタンのポート、ビット定義
15+#define KEYPORT PORTB
16+#define KEYUP 0x0400
17+#define KEYDOWN 0x0080
18+#define KEYLEFT 0x0100
19+#define KEYRIGHT 0x0200
20+#define KEYSTART 0x0800
21+#define KEYFIRE 0x4000
22+
23+extern volatile char drawing; // 表示期間中は-1
24+extern volatile unsigned short drawcount; // 1画面表示終了ごとに1足す。アプリ側で0にする。
25+ // 最低1回は画面表示したことのチェックと、アプリの処理が何画面期間必要かの確認に利用。
26+extern unsigned char TVRAM[]; //テキストビデオメモリ
27+extern unsigned short *gVRAM; //グラフィックVRAM開始位置のポインタ
28+
29+extern const unsigned char FontData[],FontData2[]; //フォントパターン定義
30+extern unsigned char *cursor;
31+extern unsigned char cursorcolor;
32+extern unsigned char *fontp;
33+extern unsigned char twidth; //テキスト1行文字数(30 or 40)
34+
35+void start_composite(void); //カラーコンポジット出力開始
36+void stop_composite(void); //カラーコンポジット出力停止
37+void init_composite(void); //カラーコンポジット出力初期化
38+void clearscreen(void); //テキスト画面クリア
39+void set_palette(unsigned char n,unsigned char b,unsigned char r,unsigned char g); //テキストパレット設定
40+void set_bgcolor(unsigned char b,unsigned char r,unsigned char g); //バックグランドカラー設定
41+void set_graphmode(unsigned char m); //グラフィックモード変更
42+void init_graphic(unsigned short *gvram); //グラフィック機能利用準備
43+void set_width(unsigned char m); //30文字モード(8ドットフォント)と40文字モード(6ドットフォント)の切り替え
44+
45+void vramscroll(void);
46+ //1行スクロール
47+void vramscrolldown(void);
48+ //1行逆スクロール
49+void setcursor(unsigned char x,unsigned char y,unsigned char c);
50+ //カーソル位置とカラーを設定
51+void setcursorcolor(unsigned char c);
52+ //カーソル位置そのままでカラー番号をcに設定
53+void printchar(unsigned char n);
54+ //カーソル位置にテキストコードnを1文字表示し、カーソルを1文字進める
55+void printstr(unsigned char *s);
56+ //カーソル位置に文字列sを表示
57+void printnum(unsigned int n);
58+ //カーソル位置に符号なし整数nを10進数表示
59+void printnum2(unsigned int n,unsigned char e);
60+ //カーソル位置に符号なし整数nをe桁の10進数表示(前の空き桁部分はスペースで埋める)
61+void cls(void);
62+ //テキスト画面消去し、カーソルを先頭に移動
63+void startPCG(unsigned char *p,int a);
64+ // RAMフォント(PCG)の利用開始、pがフォント格納場所、aが0以外でシステムフォントをコピー
65+void stopPCG(void);
66+ // RAMフォント(PCG)の利用停止
67+
68+void g_clearscreen(void);
69+//グラフィック画面クリア
70+void g_set_palette(unsigned char n,unsigned char b,unsigned char r,unsigned char g);
71+//グラフィック用カラーパレット設定
72+
73+void g_pset(int x,int y,unsigned int c);
74+// (x,y)の位置にカラーcで点を描画
75+
76+void g_putbmpmn(int x,int y,char m,char n,const unsigned char bmp[]);
77+// 横m*縦nドットのキャラクターを座標x,yに表示
78+// unsigned char bmp[m*n]配列に、単純にカラー番号を並べる
79+// カラー番号が0の部分は透明色として扱う
80+
81+void g_clrbmpmn(int x,int y,char m,char n);
82+// 縦m*横nドットのキャラクター消去
83+// カラー0で塗りつぶし
84+
85+void g_gline(int x1,int y1,int x2,int y2,unsigned int c);
86+// (x1,y1)-(x2,y2)にカラーcで線分を描画
87+
88+void g_hline(int x1,int x2,int y,unsigned int c);
89+// (x1,y)-(x2,y)への水平ラインを高速描画
90+
91+void g_circle(int x0,int y0,unsigned int r,unsigned int c);
92+// (x0,y0)を中心に、半径r、カラーcの円を描画
93+
94+void g_boxfill(int x1,int y1,int x2,int y2,unsigned int c);
95+// (x1,y1),(x2,y2)を対角線とするカラーcで塗られた長方形を描画
96+
97+void g_circlefill(int x0,int y0,unsigned int r,unsigned int c);
98+// (x0,y0)を中心に、半径r、カラーcで塗られた円を描画
99+
100+void g_putfont(int x,int y,unsigned int c,int bc,unsigned char n);
101+//8*8ドットのアルファベットフォント表示
102+//座標(x,y)、カラー番号c
103+//bc:バックグランドカラー、負数の場合無視
104+//n:文字番号
105+
106+void g_printstr(int x,int y,unsigned int c,int bc,unsigned char *s);
107+//座標(x,y)からカラー番号cで文字列sを表示、bc:バックグランドカラー
108+
109+void g_printnum(int x,int y,unsigned char c,int bc,unsigned int n);
110+//座標(x,y)にカラー番号cで数値nを表示、bc:バックグランドカラー
111+
112+void g_printnum2(int x,int y,unsigned char c,int bc,unsigned int n,unsigned char e);
113+//座標(x,y)にカラー番号cで数値nを表示、bc:バックグランドカラー、e桁で表示
114+
115+unsigned int g_color(int x,int y);
116+//座標(x,y)のVRAM上の現在のパレット番号を返す、画面外は0を返す