• R/O
  • HTTP
  • SSH
  • HTTPS

提交

標籤
無標籤

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

修訂951d53848130aa0807175aecde0048c7e8ab33a6 (tree)
時間2019-04-10 06:15:53
作者Katsumi <kmorimatsu@sour...>
CommiterKatsumi

Log Message

Start Protozoa Git repository

Change Summary

差異

--- a/mips/classes/STRING/help.txt
+++ b/mips/classes/STRING/help.txt
@@ -12,7 +12,7 @@ BAS
1212 JavaのStringクラス様の文字列を扱うクラス。
1313
1414 <コンストラクター>
15-第一引数は、文字列もしくはCSTRオブジェクト。
15+第一引数は、文字列。
1616
1717 <パブリックフィールド>
1818 STR$
--- /dev/null
+++ b/mips/protozoa/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 = 0x400) ;
60+
61+/*************************************************************************
62+ * Processor-specific object file. Contains SFR definitions.
63+ *************************************************************************/
64+INPUT("processor.o")
65+
66+/*************************************************************************
67+ * Processor-specific peripheral libraries are optional
68+ *************************************************************************/
69+OPTIONAL("libmchp_peripheral.a")
70+OPTIONAL("libmchp_peripheral_32MX150F128B.a")
71+
72+/*************************************************************************
73+ * For interrupt vector handling
74+ *************************************************************************/
75+PROVIDE(_vector_spacing = 0x00000001);
76+_ebase_address = 0x9D006000;
77+
78+/*************************************************************************
79+ * Memory Address Equates
80+ * _RESET_ADDR -- Reset Vector
81+ * _BEV_EXCPT_ADDR -- Boot exception Vector
82+ * _DBG_EXCPT_ADDR -- In-circuit Debugging Exception Vector
83+ * _DBG_CODE_ADDR -- In-circuit Debug Executive address
84+ * _DBG_CODE_SIZE -- In-circuit Debug Executive size
85+ * _GEN_EXCPT_ADDR -- General Exception Vector
86+ *************************************************************************/
87+_RESET_ADDR = (0x9D006000 + 0x1000);
88+_BEV_EXCPT_ADDR = ((0x9D006000 + 0x1000) + 0x380);
89+_DBG_EXCPT_ADDR = ((0x9D006000 + 0x1000) + 0x480);
90+_DBG_CODE_ADDR = 0x9FC00490;
91+_DBG_CODE_SIZE = 0x760 ;
92+_GEN_EXCPT_ADDR = _ebase_address + 0x180;
93+
94+/*************************************************************************
95+ * Memory Regions
96+ *
97+ * Memory regions without attributes cannot be used for orphaned sections.
98+ * Only sections specifically assigned to these regions can be allocated
99+ * into these regions.
100+ *
101+ * The Debug exception vector is located at 0x9FC00480.
102+ * The config_<address> sections are used to locate the config words at
103+ * their absolute addresses.
104+ *************************************************************************/
105+MEMORY
106+{
107+ kseg0_program_mem (rx) : ORIGIN = (0x9D006000 + 0x1000 + 0x490), LENGTH = 0x40000 - (0x6000 + 0x1000 + 0x490) /* All C Files will be located here */
108+ exception_mem : ORIGIN = 0x9D006000, LENGTH = 0x1000 /* Interrupt vector table */
109+ debug_exec_mem : ORIGIN = 0x9FC00490, LENGTH = 0x760
110+ kseg0_boot_mem : ORIGIN = 0x9D006000, LENGTH = 0x0 /* This memory region is dummy */
111+ kseg1_boot_mem : ORIGIN = (0x9D006000 + 0x1000), LENGTH = 0x490 /* C Startup code */
112+ config3 : ORIGIN = 0xBFC00BF0, LENGTH = 0x4
113+ config2 : ORIGIN = 0xBFC00BF4, LENGTH = 0x4
114+ config1 : ORIGIN = 0xBFC00BF8, LENGTH = 0x4
115+ config0 : ORIGIN = 0xBFC00BFC, LENGTH = 0x4
116+ kseg1_data_mem (w!x) : ORIGIN = 0xA0000000, LENGTH = 0x10000
117+ sfrs : ORIGIN = 0xBF800000, LENGTH = 0x100000
118+ configsfrs : ORIGIN = 0xBFC00BF0, LENGTH = 0x10
119+}
120+
121+/*************************************************************************
122+ * Configuration-word sections. Map the config-pragma input sections to
123+ * absolute-address output sections.
124+ *************************************************************************/
125+SECTIONS
126+{
127+ .config_BFC00BF0 : {
128+ KEEP(*(.config_BFC00BF0))
129+ } > config3
130+ .config_BFC00BF4 : {
131+ KEEP(*(.config_BFC00BF4))
132+ } > config2
133+ .config_BFC00BF8 : {
134+ KEEP(*(.config_BFC00BF8))
135+ } > config1
136+ .config_BFC00BFC : {
137+ KEEP(*(.config_BFC00BFC))
138+ } > config0
139+}
140+SECTIONS
141+{
142+ /* Boot Sections */
143+ .reset _RESET_ADDR :
144+ {
145+ KEEP(*(.reset))
146+ KEEP(*(.reset.startup))
147+ } > kseg1_boot_mem
148+ .bev_excpt _BEV_EXCPT_ADDR :
149+ {
150+ KEEP(*(.bev_handler))
151+ } > kseg1_boot_mem
152+ /* Debug exception vector */
153+ .dbg_excpt _DBG_EXCPT_ADDR (NOLOAD) :
154+ {
155+ . += (DEFINED (_DEBUGGER) ? 0x8 : 0x0);
156+ } > kseg1_boot_mem
157+ /* Space reserved for the debug executive */
158+ .dbg_code _DBG_CODE_ADDR (NOLOAD) :
159+ {
160+ . += (DEFINED (_DEBUGGER) ? _DBG_CODE_SIZE : 0x0);
161+ } > debug_exec_mem
162+
163+ .app_excpt _GEN_EXCPT_ADDR :
164+ {
165+ KEEP(*(.gen_handler))
166+ } > exception_mem
167+
168+ .vector_0 _ebase_address + 0x200 + ((_vector_spacing << 5) * 0) :
169+ {
170+ KEEP(*(.vector_0))
171+ } > exception_mem
172+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_0) <= (_vector_spacing << 5), "function at exception vector 0 too large")
173+ .vector_1 _ebase_address + 0x200 + ((_vector_spacing << 5) * 1) :
174+ {
175+ KEEP(*(.vector_1))
176+ } > exception_mem
177+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_1) <= (_vector_spacing << 5), "function at exception vector 1 too large")
178+ .vector_2 _ebase_address + 0x200 + ((_vector_spacing << 5) * 2) :
179+ {
180+ KEEP(*(.vector_2))
181+ } > exception_mem
182+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_2) <= (_vector_spacing << 5), "function at exception vector 2 too large")
183+ .vector_3 _ebase_address + 0x200 + ((_vector_spacing << 5) * 3) :
184+ {
185+ KEEP(*(.vector_3))
186+ } > exception_mem
187+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_3) <= (_vector_spacing << 5), "function at exception vector 3 too large")
188+ .vector_4 _ebase_address + 0x200 + ((_vector_spacing << 5) * 4) :
189+ {
190+ KEEP(*(.vector_4))
191+ } > exception_mem
192+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_4) <= (_vector_spacing << 5), "function at exception vector 4 too large")
193+ .vector_5 _ebase_address + 0x200 + ((_vector_spacing << 5) * 5) :
194+ {
195+ KEEP(*(.vector_5))
196+ } > exception_mem
197+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_5) <= (_vector_spacing << 5), "function at exception vector 5 too large")
198+ .vector_6 _ebase_address + 0x200 + ((_vector_spacing << 5) * 6) :
199+ {
200+ KEEP(*(.vector_6))
201+ } > exception_mem
202+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_6) <= (_vector_spacing << 5), "function at exception vector 6 too large")
203+ .vector_7 _ebase_address + 0x200 + ((_vector_spacing << 5) * 7) :
204+ {
205+ KEEP(*(.vector_7))
206+ } > exception_mem
207+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_7) <= (_vector_spacing << 5), "function at exception vector 7 too large")
208+ .vector_8 _ebase_address + 0x200 + ((_vector_spacing << 5) * 8) :
209+ {
210+ KEEP(*(.vector_8))
211+ } > exception_mem
212+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_8) <= (_vector_spacing << 5), "function at exception vector 8 too large")
213+ .vector_9 _ebase_address + 0x200 + ((_vector_spacing << 5) * 9) :
214+ {
215+ KEEP(*(.vector_9))
216+ } > exception_mem
217+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_9) <= (_vector_spacing << 5), "function at exception vector 9 too large")
218+ .vector_10 _ebase_address + 0x200 + ((_vector_spacing << 5) * 10) :
219+ {
220+ KEEP(*(.vector_10))
221+ } > exception_mem
222+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_10) <= (_vector_spacing << 5), "function at exception vector 10 too large")
223+ .vector_11 _ebase_address + 0x200 + ((_vector_spacing << 5) * 11) :
224+ {
225+ KEEP(*(.vector_11))
226+ } > exception_mem
227+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_11) <= (_vector_spacing << 5), "function at exception vector 11 too large")
228+ .vector_12 _ebase_address + 0x200 + ((_vector_spacing << 5) * 12) :
229+ {
230+ KEEP(*(.vector_12))
231+ } > exception_mem
232+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_12) <= (_vector_spacing << 5), "function at exception vector 12 too large")
233+ .vector_13 _ebase_address + 0x200 + ((_vector_spacing << 5) * 13) :
234+ {
235+ KEEP(*(.vector_13))
236+ } > exception_mem
237+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_13) <= (_vector_spacing << 5), "function at exception vector 13 too large")
238+ .vector_14 _ebase_address + 0x200 + ((_vector_spacing << 5) * 14) :
239+ {
240+ KEEP(*(.vector_14))
241+ } > exception_mem
242+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_14) <= (_vector_spacing << 5), "function at exception vector 14 too large")
243+ .vector_15 _ebase_address + 0x200 + ((_vector_spacing << 5) * 15) :
244+ {
245+ KEEP(*(.vector_15))
246+ } > exception_mem
247+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_15) <= (_vector_spacing << 5), "function at exception vector 15 too large")
248+ .vector_16 _ebase_address + 0x200 + ((_vector_spacing << 5) * 16) :
249+ {
250+ KEEP(*(.vector_16))
251+ } > exception_mem
252+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_16) <= (_vector_spacing << 5), "function at exception vector 16 too large")
253+ .vector_17 _ebase_address + 0x200 + ((_vector_spacing << 5) * 17) :
254+ {
255+ KEEP(*(.vector_17))
256+ } > exception_mem
257+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_17) <= (_vector_spacing << 5), "function at exception vector 17 too large")
258+ .vector_18 _ebase_address + 0x200 + ((_vector_spacing << 5) * 18) :
259+ {
260+ KEEP(*(.vector_18))
261+ } > exception_mem
262+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_18) <= (_vector_spacing << 5), "function at exception vector 18 too large")
263+ .vector_19 _ebase_address + 0x200 + ((_vector_spacing << 5) * 19) :
264+ {
265+ KEEP(*(.vector_19))
266+ } > exception_mem
267+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_19) <= (_vector_spacing << 5), "function at exception vector 19 too large")
268+ .vector_20 _ebase_address + 0x200 + ((_vector_spacing << 5) * 20) :
269+ {
270+ KEEP(*(.vector_20))
271+ } > exception_mem
272+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_20) <= (_vector_spacing << 5), "function at exception vector 20 too large")
273+ .vector_21 _ebase_address + 0x200 + ((_vector_spacing << 5) * 21) :
274+ {
275+ KEEP(*(.vector_21))
276+ } > exception_mem
277+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_21) <= (_vector_spacing << 5), "function at exception vector 21 too large")
278+ .vector_22 _ebase_address + 0x200 + ((_vector_spacing << 5) * 22) :
279+ {
280+ KEEP(*(.vector_22))
281+ } > exception_mem
282+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_22) <= (_vector_spacing << 5), "function at exception vector 22 too large")
283+ .vector_23 _ebase_address + 0x200 + ((_vector_spacing << 5) * 23) :
284+ {
285+ KEEP(*(.vector_23))
286+ } > exception_mem
287+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_23) <= (_vector_spacing << 5), "function at exception vector 23 too large")
288+ .vector_24 _ebase_address + 0x200 + ((_vector_spacing << 5) * 24) :
289+ {
290+ KEEP(*(.vector_24))
291+ } > exception_mem
292+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_24) <= (_vector_spacing << 5), "function at exception vector 24 too large")
293+ .vector_25 _ebase_address + 0x200 + ((_vector_spacing << 5) * 25) :
294+ {
295+ KEEP(*(.vector_25))
296+ } > exception_mem
297+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_25) <= (_vector_spacing << 5), "function at exception vector 25 too large")
298+ .vector_26 _ebase_address + 0x200 + ((_vector_spacing << 5) * 26) :
299+ {
300+ KEEP(*(.vector_26))
301+ } > exception_mem
302+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_26) <= (_vector_spacing << 5), "function at exception vector 26 too large")
303+ .vector_27 _ebase_address + 0x200 + ((_vector_spacing << 5) * 27) :
304+ {
305+ KEEP(*(.vector_27))
306+ } > exception_mem
307+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_27) <= (_vector_spacing << 5), "function at exception vector 27 too large")
308+ .vector_28 _ebase_address + 0x200 + ((_vector_spacing << 5) * 28) :
309+ {
310+ KEEP(*(.vector_28))
311+ } > exception_mem
312+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_28) <= (_vector_spacing << 5), "function at exception vector 28 too large")
313+ .vector_29 _ebase_address + 0x200 + ((_vector_spacing << 5) * 29) :
314+ {
315+ KEEP(*(.vector_29))
316+ } > exception_mem
317+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_29) <= (_vector_spacing << 5), "function at exception vector 29 too large")
318+ .vector_30 _ebase_address + 0x200 + ((_vector_spacing << 5) * 30) :
319+ {
320+ KEEP(*(.vector_30))
321+ } > exception_mem
322+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_30) <= (_vector_spacing << 5), "function at exception vector 30 too large")
323+ .vector_31 _ebase_address + 0x200 + ((_vector_spacing << 5) * 31) :
324+ {
325+ KEEP(*(.vector_31))
326+ } > exception_mem
327+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_31) <= (_vector_spacing << 5), "function at exception vector 31 too large")
328+ .vector_32 _ebase_address + 0x200 + ((_vector_spacing << 5) * 32) :
329+ {
330+ KEEP(*(.vector_32))
331+ } > exception_mem
332+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_32) <= (_vector_spacing << 5), "function at exception vector 32 too large")
333+ .vector_33 _ebase_address + 0x200 + ((_vector_spacing << 5) * 33) :
334+ {
335+ KEEP(*(.vector_33))
336+ } > exception_mem
337+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_33) <= (_vector_spacing << 5), "function at exception vector 33 too large")
338+ .vector_34 _ebase_address + 0x200 + ((_vector_spacing << 5) * 34) :
339+ {
340+ KEEP(*(.vector_34))
341+ } > exception_mem
342+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_34) <= (_vector_spacing << 5), "function at exception vector 34 too large")
343+ .vector_35 _ebase_address + 0x200 + ((_vector_spacing << 5) * 35) :
344+ {
345+ KEEP(*(.vector_35))
346+ } > exception_mem
347+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_35) <= (_vector_spacing << 5), "function at exception vector 35 too large")
348+ .vector_36 _ebase_address + 0x200 + ((_vector_spacing << 5) * 36) :
349+ {
350+ KEEP(*(.vector_36))
351+ } > exception_mem
352+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_36) <= (_vector_spacing << 5), "function at exception vector 36 too large")
353+ .vector_37 _ebase_address + 0x200 + ((_vector_spacing << 5) * 37) :
354+ {
355+ KEEP(*(.vector_37))
356+ } > exception_mem
357+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_37) <= (_vector_spacing << 5), "function at exception vector 37 too large")
358+ .vector_38 _ebase_address + 0x200 + ((_vector_spacing << 5) * 38) :
359+ {
360+ KEEP(*(.vector_38))
361+ } > exception_mem
362+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_38) <= (_vector_spacing << 5), "function at exception vector 38 too large")
363+ .vector_39 _ebase_address + 0x200 + ((_vector_spacing << 5) * 39) :
364+ {
365+ KEEP(*(.vector_39))
366+ } > exception_mem
367+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_39) <= (_vector_spacing << 5), "function at exception vector 39 too large")
368+ .vector_40 _ebase_address + 0x200 + ((_vector_spacing << 5) * 40) :
369+ {
370+ KEEP(*(.vector_40))
371+ } > exception_mem
372+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_40) <= (_vector_spacing << 5), "function at exception vector 40 too large")
373+ .vector_41 _ebase_address + 0x200 + ((_vector_spacing << 5) * 41) :
374+ {
375+ KEEP(*(.vector_41))
376+ } > exception_mem
377+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_41) <= (_vector_spacing << 5), "function at exception vector 41 too large")
378+ .vector_42 _ebase_address + 0x200 + ((_vector_spacing << 5) * 42) :
379+ {
380+ KEEP(*(.vector_42))
381+ } > exception_mem
382+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_42) <= (_vector_spacing << 5), "function at exception vector 42 too large")
383+ .vector_43 _ebase_address + 0x200 + ((_vector_spacing << 5) * 43) :
384+ {
385+ KEEP(*(.vector_43))
386+ } > exception_mem
387+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_43) <= (_vector_spacing << 5), "function at exception vector 43 too large")
388+ .vector_44 _ebase_address + 0x200 + ((_vector_spacing << 5) * 44) :
389+ {
390+ KEEP(*(.vector_44))
391+ } > exception_mem
392+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_44) <= (_vector_spacing << 5), "function at exception vector 44 too large")
393+ .vector_45 _ebase_address + 0x200 + ((_vector_spacing << 5) * 45) :
394+ {
395+ KEEP(*(.vector_45))
396+ } > exception_mem
397+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_45) <= (_vector_spacing << 5), "function at exception vector 45 too large")
398+ .vector_46 _ebase_address + 0x200 + ((_vector_spacing << 5) * 46) :
399+ {
400+ KEEP(*(.vector_46))
401+ } > exception_mem
402+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_46) <= (_vector_spacing << 5), "function at exception vector 46 too large")
403+ .vector_47 _ebase_address + 0x200 + ((_vector_spacing << 5) * 47) :
404+ {
405+ KEEP(*(.vector_47))
406+ } > exception_mem
407+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_47) <= (_vector_spacing << 5), "function at exception vector 47 too large")
408+ .vector_48 _ebase_address + 0x200 + ((_vector_spacing << 5) * 48) :
409+ {
410+ KEEP(*(.vector_48))
411+ } > exception_mem
412+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_48) <= (_vector_spacing << 5), "function at exception vector 48 too large")
413+ .vector_49 _ebase_address + 0x200 + ((_vector_spacing << 5) * 49) :
414+ {
415+ KEEP(*(.vector_49))
416+ } > exception_mem
417+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_49) <= (_vector_spacing << 5), "function at exception vector 49 too large")
418+ .vector_50 _ebase_address + 0x200 + ((_vector_spacing << 5) * 50) :
419+ {
420+ KEEP(*(.vector_50))
421+ } > exception_mem
422+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_50) <= (_vector_spacing << 5), "function at exception vector 50 too large")
423+ .vector_51 _ebase_address + 0x200 + ((_vector_spacing << 5) * 51) :
424+ {
425+ KEEP(*(.vector_51))
426+ } > exception_mem
427+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_51) <= (_vector_spacing << 5), "function at exception vector 51 too large")
428+ .vector_52 _ebase_address + 0x200 + ((_vector_spacing << 5) * 52) :
429+ {
430+ KEEP(*(.vector_52))
431+ } > exception_mem
432+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_52) <= (_vector_spacing << 5), "function at exception vector 52 too large")
433+ .vector_53 _ebase_address + 0x200 + ((_vector_spacing << 5) * 53) :
434+ {
435+ KEEP(*(.vector_53))
436+ } > exception_mem
437+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_53) <= (_vector_spacing << 5), "function at exception vector 53 too large")
438+ .vector_54 _ebase_address + 0x200 + ((_vector_spacing << 5) * 54) :
439+ {
440+ KEEP(*(.vector_54))
441+ } > exception_mem
442+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_54) <= (_vector_spacing << 5), "function at exception vector 54 too large")
443+ .vector_55 _ebase_address + 0x200 + ((_vector_spacing << 5) * 55) :
444+ {
445+ KEEP(*(.vector_55))
446+ } > exception_mem
447+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_55) <= (_vector_spacing << 5), "function at exception vector 55 too large")
448+ .vector_56 _ebase_address + 0x200 + ((_vector_spacing << 5) * 56) :
449+ {
450+ KEEP(*(.vector_56))
451+ } > exception_mem
452+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_56) <= (_vector_spacing << 5), "function at exception vector 56 too large")
453+ .vector_57 _ebase_address + 0x200 + ((_vector_spacing << 5) * 57) :
454+ {
455+ KEEP(*(.vector_57))
456+ } > exception_mem
457+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_57) <= (_vector_spacing << 5), "function at exception vector 57 too large")
458+ .vector_58 _ebase_address + 0x200 + ((_vector_spacing << 5) * 58) :
459+ {
460+ KEEP(*(.vector_58))
461+ } > exception_mem
462+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_58) <= (_vector_spacing << 5), "function at exception vector 58 too large")
463+ .vector_59 _ebase_address + 0x200 + ((_vector_spacing << 5) * 59) :
464+ {
465+ KEEP(*(.vector_59))
466+ } > exception_mem
467+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_59) <= (_vector_spacing << 5), "function at exception vector 59 too large")
468+ .vector_60 _ebase_address + 0x200 + ((_vector_spacing << 5) * 60) :
469+ {
470+ KEEP(*(.vector_60))
471+ } > exception_mem
472+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_60) <= (_vector_spacing << 5), "function at exception vector 60 too large")
473+ .vector_61 _ebase_address + 0x200 + ((_vector_spacing << 5) * 61) :
474+ {
475+ KEEP(*(.vector_61))
476+ } > exception_mem
477+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_61) <= (_vector_spacing << 5), "function at exception vector 61 too large")
478+ .vector_62 _ebase_address + 0x200 + ((_vector_spacing << 5) * 62) :
479+ {
480+ KEEP(*(.vector_62))
481+ } > exception_mem
482+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_62) <= (_vector_spacing << 5), "function at exception vector 62 too large")
483+ .vector_63 _ebase_address + 0x200 + ((_vector_spacing << 5) * 63) :
484+ {
485+ KEEP(*(.vector_63))
486+ } > exception_mem
487+ ASSERT (_vector_spacing == 0 || SIZEOF(.vector_63) <= (_vector_spacing << 5), "function at exception vector 63 too large")
488+
489+ /* The startup code is in the .reset.startup section.
490+ * Keep this here for backwards compatibility with older
491+ * C32 v1.xx releases.
492+ */
493+ .startup ORIGIN(kseg0_boot_mem) :
494+ {
495+ KEEP(*(.startup))
496+ } > kseg0_boot_mem
497+ /* Code Sections - Note that input sections *(.text) and *(.text.*)
498+ ** are not mapped here. The best-fit allocator locates them,
499+ ** so that .text may flow around absolute sections as needed.
500+ */
501+ .text :
502+ {
503+ *(.stub .gnu.linkonce.t.*)
504+ KEEP (*(.text.*personality*))
505+ *(.mips16.fn.*)
506+ *(.mips16.call.*)
507+ *(.gnu.warning)
508+ . = ALIGN(4) ;
509+ } >kseg0_program_mem
510+ /* Global-namespace object initialization */
511+ .init :
512+ {
513+ KEEP (*crti.o(.init))
514+ KEEP (*crtbegin.o(.init))
515+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o *crtn.o ).init))
516+ KEEP (*crtend.o(.init))
517+ KEEP (*crtn.o(.init))
518+ . = ALIGN(4) ;
519+ } >kseg0_program_mem
520+ .fini :
521+ {
522+ KEEP (*(.fini))
523+ . = ALIGN(4) ;
524+ } >kseg0_program_mem
525+ .preinit_array :
526+ {
527+ PROVIDE_HIDDEN (__preinit_array_start = .);
528+ KEEP (*(.preinit_array))
529+ PROVIDE_HIDDEN (__preinit_array_end = .);
530+ . = ALIGN(4) ;
531+ } >kseg0_program_mem
532+ .init_array :
533+ {
534+ PROVIDE_HIDDEN (__init_array_start = .);
535+ KEEP (*(SORT(.init_array.*)))
536+ KEEP (*(.init_array))
537+ PROVIDE_HIDDEN (__init_array_end = .);
538+ . = ALIGN(4) ;
539+ } >kseg0_program_mem
540+ .fini_array :
541+ {
542+ PROVIDE_HIDDEN (__fini_array_start = .);
543+ KEEP (*(SORT(.fini_array.*)))
544+ KEEP (*(.fini_array))
545+ PROVIDE_HIDDEN (__fini_array_end = .);
546+ . = ALIGN(4) ;
547+ } >kseg0_program_mem
548+ .ctors :
549+ {
550+ /* XC32 uses crtbegin.o to find the start of
551+ the constructors, so we make sure it is
552+ first. Because this is a wildcard, it
553+ doesn't matter if the user does not
554+ actually link against crtbegin.o; the
555+ linker won't look for a file to match a
556+ wildcard. The wildcard also means that it
557+ doesn't matter which directory crtbegin.o
558+ is in. */
559+ KEEP (*crtbegin.o(.ctors))
560+ KEEP (*crtbegin?.o(.ctors))
561+ /* We don't want to include the .ctor section from
562+ the crtend.o file until after the sorted ctors.
563+ The .ctor section from the crtend file contains the
564+ end of ctors marker and it must be last */
565+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
566+ KEEP (*(SORT(.ctors.*)))
567+ KEEP (*(.ctors))
568+ . = ALIGN(4) ;
569+ } >kseg0_program_mem
570+ .dtors :
571+ {
572+ KEEP (*crtbegin.o(.dtors))
573+ KEEP (*crtbegin?.o(.dtors))
574+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
575+ KEEP (*(SORT(.dtors.*)))
576+ KEEP (*(.dtors))
577+ . = ALIGN(4) ;
578+ } >kseg0_program_mem
579+ /* Read-only sections */
580+ .rodata :
581+ {
582+ *( .gnu.linkonce.r.*)
583+ *(.rodata1)
584+ . = ALIGN(4) ;
585+ } >kseg0_program_mem
586+ /*
587+ * Small initialized constant global and static data can be placed in the
588+ * .sdata2 section. This is different from .sdata, which contains small
589+ * initialized non-constant global and static data.
590+ */
591+ .sdata2 ALIGN(4) :
592+ {
593+ *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
594+ . = ALIGN(4) ;
595+ } >kseg0_program_mem
596+ /*
597+ * Uninitialized constant global and static data (i.e., variables which will
598+ * always be zero). Again, this is different from .sbss, which contains
599+ * small non-initialized, non-constant global and static data.
600+ */
601+ .sbss2 ALIGN(4) :
602+ {
603+ *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*)
604+ . = ALIGN(4) ;
605+ } >kseg0_program_mem
606+ .eh_frame_hdr :
607+ {
608+ *(.eh_frame_hdr)
609+ } >kseg0_program_mem
610+ . = ALIGN(4) ;
611+ .eh_frame : ONLY_IF_RO
612+ {
613+ KEEP (*(.eh_frame))
614+ } >kseg0_program_mem
615+ . = ALIGN(4) ;
616+ .gcc_except_table : ONLY_IF_RO
617+ {
618+ *(.gcc_except_table .gcc_except_table.*)
619+ } >kseg0_program_mem
620+ . = ALIGN(4) ;
621+ .dbg_data (NOLOAD) :
622+ {
623+ . += (DEFINED (_DEBUGGER) ? 0x200 : 0x0);
624+ } >kseg1_data_mem
625+ .jcr :
626+ {
627+ KEEP (*(.jcr))
628+ . = ALIGN(4) ;
629+ } >kseg1_data_mem
630+ .eh_frame : ONLY_IF_RW
631+ {
632+ KEEP (*(.eh_frame))
633+ } >kseg1_data_mem
634+ . = ALIGN(4) ;
635+ .gcc_except_table : ONLY_IF_RW
636+ {
637+ *(.gcc_except_table .gcc_except_table.*)
638+ } >kseg1_data_mem
639+ . = ALIGN(4) ;
640+ /* Persistent data - Use the new C 'persistent' attribute instead. */
641+ .persist :
642+ {
643+ _persist_begin = .;
644+ *(.persist .persist.*)
645+ *(.pbss .pbss.*)
646+ . = ALIGN(4) ;
647+ _persist_end = .;
648+ } >kseg1_data_mem
649+ /*
650+ * Note that input sections named .data* are not mapped here.
651+ * The best-fit allocator locates them, so that they may flow
652+ * around absolute sections as needed.
653+ */
654+ .data :
655+ {
656+ *( .gnu.linkonce.d.*)
657+ SORT(CONSTRUCTORS)
658+ *(.data1)
659+ . = ALIGN(4) ;
660+ } >kseg1_data_mem
661+ . = .;
662+ _gp = ALIGN(16) + 0x7ff0;
663+ .got ALIGN(4) :
664+ {
665+ *(.got.plt) *(.got)
666+ . = ALIGN(4) ;
667+ } >kseg1_data_mem /* AT>kseg0_program_mem */
668+ /*
669+ * Note that 'small' data sections are still mapped in the linker
670+ * script. This ensures that they are grouped together for
671+ * gp-relative addressing. Absolute sections are allocated after
672+ * the 'small' data sections so small data cannot flow around them.
673+ */
674+ /*
675+ * We want the small data sections together, so single-instruction offsets
676+ * can access them all, and initialized data all before uninitialized, so
677+ * we can shorten the on-disk segment size.
678+ */
679+ .sdata ALIGN(4) :
680+ {
681+ _sdata_begin = . ;
682+ *(.sdata .sdata.* .gnu.linkonce.s.*)
683+ . = ALIGN(4) ;
684+ _sdata_end = . ;
685+ } >kseg1_data_mem
686+ .lit8 :
687+ {
688+ *(.lit8)
689+ } >kseg1_data_mem
690+ .lit4 :
691+ {
692+ *(.lit4)
693+ } >kseg1_data_mem
694+ . = ALIGN (4) ;
695+ _data_end = . ;
696+ _bss_begin = . ;
697+ .sbss ALIGN(4) :
698+ {
699+ _sbss_begin = . ;
700+ *(.dynsbss)
701+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
702+ *(.scommon)
703+ _sbss_end = . ;
704+ . = ALIGN(4) ;
705+ } >kseg1_data_mem
706+ /*
707+ * Align here to ensure that the .bss section occupies space up to
708+ * _end. Align after .bss to ensure correct alignment even if the
709+ * .bss section disappears because there are no input sections.
710+ *
711+ * Note that input sections named .bss* are no longer mapped here.
712+ * The best-fit allocator locates them, so that they may flow
713+ * around absolute sections as needed.
714+ *
715+ */
716+ .bss :
717+ {
718+ *(.dynbss)
719+ *(COMMON)
720+ /* Align here to ensure that the .bss section occupies space up to
721+ _end. Align after .bss to ensure correct alignment even if the
722+ .bss section disappears because there are no input sections. */
723+ . = ALIGN(. != 0 ? 4 : 1);
724+ } >kseg1_data_mem
725+ . = ALIGN(4) ;
726+ _end = . ;
727+ _bss_end = . ;
728+ /*
729+ * The heap and stack are best-fit allocated by the linker after other
730+ * data and bss sections have been allocated.
731+ */
732+ /*
733+ * RAM functions go at the end of our stack and heap allocation.
734+ * Alignment of 2K required by the boundary register (BMXDKPBA).
735+ *
736+ * RAM functions are now allocated by the linker. The linker generates
737+ * _ramfunc_begin and _bmxdkpba_address symbols depending on the
738+ * location of RAM functions.
739+ */
740+ _bmxdudba_address = LENGTH(kseg1_data_mem) ;
741+ _bmxdupba_address = LENGTH(kseg1_data_mem) ;
742+ /* The .pdr section belongs in the absolute section */
743+ /DISCARD/ : { *(.pdr) }
744+ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
745+ .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
746+ .mdebug.abi32 : { KEEP(*(.mdebug.abi32)) }
747+ .mdebug.abiN32 : { KEEP(*(.mdebug.abiN32)) }
748+ .mdebug.abi64 : { KEEP(*(.mdebug.abi64)) }
749+ .mdebug.abiO64 : { KEEP(*(.mdebug.abiO64)) }
750+ .mdebug.eabi32 : { KEEP(*(.mdebug.eabi32)) }
751+ .mdebug.eabi64 : { KEEP(*(.mdebug.eabi64)) }
752+ .gcc_compiled_long32 : { KEEP(*(.gcc_compiled_long32)) }
753+ .gcc_compiled_long64 : { KEEP(*(.gcc_compiled_long64)) }
754+ /* Stabs debugging sections. */
755+ .stab 0 : { *(.stab) }
756+ .stabstr 0 : { *(.stabstr) }
757+ .stab.excl 0 : { *(.stab.excl) }
758+ .stab.exclstr 0 : { *(.stab.exclstr) }
759+ .stab.index 0 : { *(.stab.index) }
760+ .stab.indexstr 0 : { *(.stab.indexstr) }
761+ .comment 0 : { *(.comment) }
762+ /* DWARF debug sections used by MPLAB X for source-level debugging.
763+ Symbols in the DWARF debugging sections are relative to the beginning
764+ of the section so we begin them at 0. */
765+ /* DWARF 1 */
766+ .debug 0 : { *(.debug) }
767+ .line 0 : { *(.line) }
768+ /* GNU DWARF 1 extensions */
769+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
770+ .debug_sfnames 0 : { *(.debug_sfnames) }
771+ /* DWARF 1.1 and DWARF 2 */
772+ .debug_aranges 0 : { *(.debug_aranges) }
773+ .debug_pubnames 0 : { *(.debug_pubnames) }
774+ /* DWARF 2 */
775+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
776+ .debug_abbrev 0 : { *(.debug_abbrev) }
777+ .debug_line 0 : { *(.debug_line) }
778+ .debug_frame 0 : { *(.debug_frame) }
779+ .debug_str 0 : { *(.debug_str) }
780+ .debug_loc 0 : { *(.debug_loc) }
781+ .debug_macinfo 0 : { *(.debug_macinfo) }
782+ /* SGI/MIPS DWARF 2 extensions */
783+ .debug_weaknames 0 : { *(.debug_weaknames) }
784+ .debug_funcnames 0 : { *(.debug_funcnames) }
785+ .debug_typenames 0 : { *(.debug_typenames) }
786+ .debug_varnames 0 : { *(.debug_varnames) }
787+ .debug_pubtypes 0 : { *(.debug_pubtypes) }
788+ .debug_ranges 0 : { *(.debug_ranges) }
789+ /DISCARD/ : { *(.rel.dyn) }
790+ .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
791+ /DISCARD/ : { *(.note.GNU-stack) }
792+ /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.discard) }
793+}
794+
--- /dev/null
+++ b/mips/protozoa/api.h
@@ -0,0 +1,39 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#ifndef BOOL
9+ typedef enum _BOOL { FALSE = 0, TRUE } BOOL;
10+#endif
11+
12+#ifndef BYTE
13+ #define BYTE unsigned char
14+#endif
15+
16+#ifndef WORD
17+ #define WORD unsigned short
18+#endif
19+
20+#ifndef DWORD
21+ #define DWORD unsigned long
22+#endif
23+
24+#ifndef UINT16
25+ #define UINT16 unsigned short
26+#endif
27+
28+#ifndef size_t
29+ #define size_t unsigned int
30+#endif
31+
32+// Used for asm("wait")
33+#define WAIT "wait"
34+
35+#include "interface/videoout.h"
36+#include "interface/SDFSIO.h"
37+#include "interface/ps2keyboard.h"
38+#include "interface/keyinput.h"
39+#include "debug.h"
--- /dev/null
+++ b/mips/protozoa/args.c
@@ -0,0 +1,106 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include "compiler.h"
13+
14+const unsigned int g_initial_s5_stack[3]={
15+ 0, // -8($s5): no object
16+ (unsigned int) &g_initial_s5_stack[2], // -4($s5): previous $s5 (recursive)
17+ 0 // 0($s5): no parameter
18+};
19+
20+static int g_args_stack;
21+/*
22+ See ARGS_SP_XXXX and ARGS_S5_XXXX in compiler.h
23+ At least 4 stacks are needed even without argument
24+ 4($sp) = -12($s5): $sp
25+ 8($sp) = -8($s5): $v0 - pointer to object or previous -8($s5)
26+ 12($sp) = -4($s5): previous $s5
27+ 16($sp) = 0($s5): number of arguments
28+ 20($sp) = 4($s5): first argument
29+ $v0 must be the pointer to an object before comming to this code.
30+ After this code, -12($s5) must be set to $sp: 0xAEBDFFF4 sw sp,-12(s5)
31+*/
32+char* prepare_args_stack(char start_char){
33+ // start_char is either ',' or '('
34+ // When ',' mode, there must be a ',' if argument(s) exist(s).
35+ // When '(' mode, there shouldn't be a '(', because this character has passed.
36+ char* err;
37+ int opos,stack;
38+ stack=0;
39+ opos=g_objpos;
40+ check_obj_space(2);
41+ g_object[g_objpos++]=0x27BD0000; // addiu sp,sp,-xx
42+ // 8(sp) is for $v0, which is pointer to an object
43+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
44+ next_position();
45+ do {
46+ if (!stack) {
47+ // First parameter if exists
48+ stack=16;
49+ if (start_char==','){
50+ if (g_source[g_srcpos]!=',') break;
51+ } else if (start_char=='('){
52+ next_position();
53+ if (g_source[g_srcpos]==')') break;
54+ g_srcpos--;
55+ } else {
56+ return ERR_UNKNOWN;
57+ }
58+ }
59+ g_srcpos++;
60+ stack+=4;
61+ err=get_stringFloatOrValue();
62+ if (err) return err;
63+ check_obj_space(1);
64+ g_object[g_objpos++]=0xAFA20000|stack; // sw v0,xx(sp)
65+ next_position();
66+ } while (g_source[g_srcpos]==',');
67+ // 12(sp) is for $s5, 16(sp) is for # of parameters
68+ check_obj_space(5);
69+ g_object[g_objpos++]=0xAFB5000C; // sw s5,12(sp)
70+ g_object[g_objpos++]=0x34020000|(stack/4-4); // ori v0,zero,xx
71+ g_object[g_objpos++]=0xAFA20010; // sw v0,16(sp)
72+ g_object[g_objpos++]=0x27B50010; // addiu s5,sp,16
73+ g_object[opos]|=((0-stack)&0xFFFF); // addiu sp,sp,-xx (See above)
74+ // All done. Register # of stacks to global var.
75+ g_args_stack=stack;
76+ return 0;
77+}
78+
79+char* remove_args_stack(void){
80+ // Remove stack
81+ check_obj_space(2);
82+ g_object[g_objpos++]=0x8FB5000C; // lw s5,12(sp)
83+ g_object[g_objpos++]=0x27BD0000|g_args_stack; // addiu sp,sp,xx
84+ return 0;
85+}
86+
87+char* args_function_main(void){
88+ char* err;
89+ int i;
90+ err=get_value();
91+ if (err) return err;
92+ i=g_object[g_objpos-1];
93+ if ((i>>16)==0x3402) {
94+ // Previous object is "ori v0,zero,xxxx".
95+ i&=0xffff;
96+ i=i<<2;
97+ g_object[g_objpos-1]=0x8EA20000|i; // lw v0,xx(s5)
98+ } else {
99+ check_obj_space(3);
100+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
101+ g_object[g_objpos++]=0x02A21021; // addu v0,s5,v0
102+ g_object[g_objpos++]=0x8C420000; // lw v0,0(v0)
103+ }
104+ return 0;
105+}
106+
--- /dev/null
+++ b/mips/protozoa/class.c
@@ -0,0 +1,931 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include "compiler.h"
13+
14+static int* g_class_structure;
15+
16+/*
17+ CMPDATA_CLASS structure
18+ type: CMPDATA_CLASS (2)
19+ len: 3
20+ data16: n/a (0)
21+ record[1]: class name as integer
22+ record[2]: pointer to class structure
23+*/
24+
25+/*
26+ CMPDATA_FIELD structure
27+ type: CMPDATA_FIELD (3)
28+ len: 2 or 3 (2: field; 3: method)
29+ data16: field or method
30+ CMPTYPE_PUBLIC_FIELD: 0
31+ CMPTYPE_PRIVATE_FIELD: 1
32+ CMPTYPE_PUBLIC_METHOD: 2
33+ record[1]: field/method name as integer
34+ record[2]: pointer to method
35+*/
36+
37+/*
38+ CMPDATA_STATIC structure
39+ type: CMPDATA_STATIC (4)
40+ len: 3
41+ data16: variable number; add ALLOC_LNV_BLOCK when using
42+ record[1]: class name as integer
43+ record[2]: variable name as integer
44+*/
45+
46+/*
47+ CMPDATA_UNSOLVED structure
48+ type: CMPDATA_UNSOLVED (5)
49+ len: 4
50+ data16: CMPTYPE_NEW_FUNCTION (0)
51+ record[1]: class name as integer
52+ record[2]: address of code for pointer to class structure
53+ record[3]: address of code for size definition
54+
55+ type: CMPDATA_UNSOLVED (5)
56+ len: 4
57+ data16: CMPTYPE_STATIC_METHOD (1)
58+ record[1]: class name as integer
59+ record[2]: method name as integer
60+ record[3]: address of code for pointer to method
61+
62+*/
63+
64+/*
65+ Local prototyping
66+*/
67+char* obj_method(int method);
68+
69+/*
70+ Return code used for calling null method
71+*/
72+static const unsigned int g_return_code[]={
73+ 0x8FA30004, // lw v1,4(sp)
74+ 0x00600008, // jr v1
75+ 0x27BD0004, // addiu sp,sp,4
76+};
77+
78+
79+
80+char* begin_compiling_class(int class){
81+ // Initialize parameters
82+ g_compiling_class=class;
83+ g_class_structure=0;
84+ // Register the class to cmpdata without class structure
85+ return update_class_info(class);
86+}
87+
88+char* end_compiling_class(int class){
89+ char* err;
90+ g_compiling_class=0;
91+ // Construct class structure
92+ err=construct_class_structure(class);
93+ if (err) return err;
94+ // Uppdate class information.
95+ err=update_class_info(class);
96+ if (err) return err;
97+ // Resolve CMPDATA_UNSOLVED.
98+ err=resolve_unresolved(class);
99+ if (err) return err;
100+ // Delete some cmpdata.
101+ delete_cmpdata_for_class(class);
102+ return 0;
103+}
104+
105+void* search_method(int* classdata,int method){
106+ int pos,i;
107+ int nums=classdata[1];
108+
109+ classdata+=2; // exclude first 2 words
110+ classdata+=2*(nums&0xff); // exclude public field
111+ classdata+=2*((nums>>8)&0xff); // exclude private field
112+ nums=(nums>>16)&0xff; // number of methods
113+ for(i=0;i<nums;i++){
114+ if (classdata[0]==method) return (void*)classdata[1];
115+ classdata+=2;
116+ }
117+ return 0; // not found
118+}
119+
120+char* resolve_unresolved(int class){
121+ int* classdata;
122+ int* record;
123+ int* code;
124+ int i;
125+ // Get class structure
126+ cmpdata_reset();
127+ while(record=cmpdata_find(CMPDATA_CLASS)){
128+ if (record[1]==class) break;
129+ }
130+ if (!record) return ERR_UNKNOWN;
131+ classdata=(int*)record[2];
132+ // Explore CMPDATA_UNSOLVED
133+ cmpdata_reset();
134+ while(record=cmpdata_find(CMPDATA_UNSOLVED)){
135+ // Note: don't use cmpdata_find() again in the loop.
136+ // If used, the solved CMPDATA_UNSOLVED must be removed before.
137+ if (record[1]!=class) continue;
138+ switch (record[0]&0xffff) {
139+ case CMPTYPE_NEW_FUNCTION:
140+ // Resolve address of code for pointer to class structure
141+ code=(int*)(record[2]);
142+ code[0]=(code[0]&0xFFFF0000) | (((unsigned int)classdata)>>16);
143+ code[1]=(code[1]&0xFFFF0000) | (((unsigned int)classdata) & 0x0000FFFF);
144+ // Resolve size of object
145+ code=(int*)(record[3]);
146+ code[0]=(code[0]&0xFFFF0000) | (object_size(classdata) & 0x0000FFFF);
147+ // All done
148+ break;
149+ case CMPTYPE_STATIC_METHOD:
150+ // Resolve address of code for pointer to method
151+ // Find method
152+ i=(int)search_method(classdata,record[2]);
153+ if (!i) return ERR_NOT_FIELD;
154+ code=(int*)(record[3]);
155+ code[0]=(code[0]&0xFC000000)|((i&0x0FFFFFFF)>>2);
156+ // All done
157+ break;
158+ default:
159+ return ERR_UNKNOWN;
160+ }
161+ }
162+ return 0;
163+}
164+
165+char* update_class_info(int class){
166+ int* record;
167+ int data[2];
168+ // Update record if exist.
169+ cmpdata_reset();
170+ while(record=cmpdata_find(CMPDATA_CLASS)){
171+ if (record[1]==class) {
172+ record[2]=(int)g_class_structure;
173+ return 0;
174+ }
175+ }
176+ // No record of this class yet. Insert a record.
177+ data[0]=class;
178+ data[1]=(int)g_class_structure;
179+ return cmpdata_insert(CMPDATA_CLASS,0,&data[0],2);
180+}
181+
182+/*
183+ Class structure:
184+ cstruct[0]: class name as integer
185+ cstruct[1]: number of fields and methods:
186+ bit 0-7: # of public fields
187+ bit 8-15: # of private fields
188+ bit 16-23: # of public methods
189+ bit 24-31: reserved
190+ cstruct[x]: public field name
191+ cstruct[x+1]: public field var number
192+ cstruct[y]: private field name
193+ cstruct[y+1]: private field var number
194+ cstruct[z]: public method name
195+ cstruct[z+1]: public method pointer
196+*/
197+
198+/*
199+ Object structure:
200+ object[0]: pointer to class structure
201+ object[1]: field value
202+ ...
203+ object[n]: field value
204+ (according to class structure; public field(s) first, then private field(s))
205+*/
206+
207+char* construct_class_structure(int class){
208+ int* record;
209+ int i;
210+ int num=0;
211+ // Register current address to global var
212+ g_class_structure=&g_object[g_objpos];
213+ // Construct a class structure in object area in following lines
214+ // Class name
215+ check_obj_space(2);
216+ g_object[g_objpos++]=class; // Class name
217+ g_objpos++; // Number of fields/methods
218+ // Public fields
219+ cmpdata_reset();
220+ while(record=cmpdata_find(CMPDATA_FIELD)){
221+ if ((record[0]&0xffff)==CMPTYPE_PUBLIC_FIELD) {
222+ num+=1<<0;
223+ check_obj_space(2);
224+ g_object[g_objpos++]=record[1]; // Field name
225+ g_objpos++; // Var number (see below)
226+ }
227+ }
228+ // Private fields
229+ cmpdata_reset();
230+ while(record=cmpdata_find(CMPDATA_FIELD)){
231+ if ((record[0]&0xffff)==CMPTYPE_PRIVATE_FIELD) {
232+ num+=1<<8;
233+ check_obj_space(2);
234+ g_object[g_objpos++]=record[1]; // Field name
235+ g_objpos++; // Var number (see below)
236+ }
237+ }
238+ // Public methods
239+ cmpdata_reset();
240+ while(record=cmpdata_find(CMPDATA_FIELD)){
241+ if ((record[0]&0xffff)==CMPTYPE_PUBLIC_METHOD) {
242+ num+=1<<16;
243+ check_obj_space(2);
244+ g_object[g_objpos++]=record[1]; // Method name
245+ g_object[g_objpos++]=record[2]; // pointer
246+ }
247+ }
248+ // Update number info
249+ g_class_structure[1]=num;
250+ // Update var numbers of fields
251+ num=((num>>8)&0xff)+(num&0xff);
252+ for(i=1;i<=num;i++){
253+ if ((
254+ g_class_structure[i*2+1]=search_var_name(0x7FFFFFFF & g_class_structure[i*2])+ALLOC_LNV_BLOCK
255+ )<ALLOC_LNV_BLOCK) return ERR_UNKNOWN;
256+ }
257+ return 0;
258+}
259+
260+void delete_cmpdata_for_class(int class){
261+ int* record;
262+ // Delete field/method data
263+ cmpdata_reset();
264+ while(record=cmpdata_find(CMPDATA_FIELD)){
265+ cmpdata_delete(record);
266+ cmpdata_reset();
267+ }
268+ // Delete longvar data
269+ cmpdata_reset();
270+ while(record=cmpdata_find(CMPDATA_USEVAR)){
271+ cmpdata_delete(record);
272+ cmpdata_reset();
273+ }
274+ // Delete solved class codes
275+ cmpdata_reset();
276+ while(record=cmpdata_find(CMPDATA_UNSOLVED)){
277+ if (record[1]!=class) continue;
278+ cmpdata_delete(record);
279+ cmpdata_reset();
280+ }
281+}
282+
283+int object_size(int* classdata){
284+ int nums=classdata[1];
285+ int size=nums&0xff; // public field
286+ size+=(nums>>8)&0xff; // private
287+ // Add 1 for pointer to class data.
288+ return size+1;
289+}
290+
291+char* new_function(){
292+ char* err;
293+ int class,size;
294+ int i,stack, opos;
295+ int* data;
296+ int* classdata;
297+ int record[3];
298+ void* init_method;
299+ // Resolve class name
300+ err=get_label();
301+ if (err) return err;
302+ if (!g_label) return ERR_SYNTAX;
303+ class=g_label;
304+ record[0]=class;
305+ next_position();
306+ // Get class data from cmpdata
307+ // Note that the address of class structure can be resolved
308+ // by using cmpdata when compiling NEW function but not running.
309+ // Therefore, class table is not requred when running.
310+ cmpdata_reset();
311+ while(data=cmpdata_find(CMPDATA_CLASS)){
312+ if (data[1]==class) break;
313+ }
314+ if (!data) return ERR_NO_CLASS;
315+ classdata=(int*)data[2];
316+ if (classdata) {
317+ size=object_size(classdata);
318+ } else {
319+ // Class structure is unsolved.
320+ size=0;
321+ }
322+ // Create object
323+ record[2]=(int)&g_object[g_objpos+3];
324+ call_quicklib_code(lib_calloc_memory,ASM_ORI_A0_ZERO_|size);
325+ // First word of object is pointer to classdata
326+ check_obj_space(3);
327+ record[1]=(int)&g_object[g_objpos];
328+ g_object[g_objpos++]=0x3C080000|(((unsigned int)classdata)>>16); // lui t0,xxxx
329+ g_object[g_objpos++]=0x35080000|(((unsigned int)classdata)&0x0000FFFF); // ori t0,t0,xxxx
330+ g_object[g_objpos++]=0xAC480000; // sw t0,0(v0)
331+ // Check if INIT method exists
332+ if (classdata) {
333+ init_method=search_method(classdata,LABEL_INIT);
334+ } else {
335+ // Class structure is unknown. Use null method.
336+ init_method=(int*)&g_return_code[0];
337+ // Register CMPDATA
338+ cmpdata_insert(CMPDATA_UNSOLVED,CMPTYPE_NEW_FUNCTION,(int*)&record[0],3);
339+ g_allow_shift_obj=0;
340+ }
341+ if (!init_method) {
342+ // All done
343+ // Note that $v0 is address of object here.
344+ // There should not be parameter(s).
345+ if (g_source[g_srcpos]==',') return ERR_NO_INIT;
346+ return 0;
347+ }
348+ // INIT method exists. Note that $v0 is address of object here.
349+ if (g_source[g_srcpos]==',') g_srcpos++;
350+ else if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
351+ check_obj_space(2);
352+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
353+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
354+ err=obj_method(LABEL_INIT);
355+ if (err) return err;
356+ g_srcpos--; // Leave ')' character for detecting end of "new" function
357+ check_obj_space(2);
358+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
359+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
360+ // All done
361+ // Note that $v0 is address of object here.
362+ return 0;
363+}
364+
365+char* field_statement(){
366+ char* err;
367+ int i;
368+ int data[1];
369+ int is_private=0;
370+ // This statement is valid only in class file.
371+ if (!g_compiling_class) return ERR_INVALID_NON_CLASS;
372+ // Check which private or public
373+ next_position();
374+ if (nextCodeIs("PRIVATE ")) {
375+ is_private=1;
376+ } else if (nextCodeIs("PUBLIC ")) {
377+ is_private=0;
378+ }
379+ do {
380+ next_position();
381+ i=check_var_name();
382+ if (i<65536) return ERR_SYNTAX;
383+ // Register varname
384+ err=register_var_name(i);
385+ if (err) return err;
386+ if (g_source[g_srcpos]=='#') {
387+ g_srcpos++;
388+ } else if (g_source[g_srcpos]=='$') {
389+ // String field. Raise 31st bit.
390+ g_srcpos++;
391+ i|=0x80000000;
392+ } else if (g_source[g_srcpos]=='(' && g_source[g_srcpos+1]==')' && is_private) {
393+ // Dimension field (private only). Raise 31st bit.
394+ g_srcpos++;
395+ g_srcpos++;
396+ i|=0x80000000;
397+ }
398+ // Register field
399+ data[0]=i;
400+ if (is_private) {
401+ err=cmpdata_insert(CMPDATA_FIELD,CMPTYPE_PRIVATE_FIELD,(int*)&data[0],1);
402+ } else {
403+ err=cmpdata_insert(CMPDATA_FIELD,CMPTYPE_PUBLIC_FIELD,(int*)&data[0],1);
404+ }
405+ next_position();
406+ if (g_source[g_srcpos]==',') {
407+ g_srcpos++;
408+ } else {
409+ break;
410+ }
411+ } while(1);
412+ return 0;
413+}
414+
415+/*
416+ char* obj_method(int method);
417+ Implementation of access to method of object.
418+*/
419+char* obj_method(int method){
420+ // $v0 contains the address of object.
421+ // Note that '(' has been passed.
422+ char* err;
423+ int stack,opos;
424+ // When method of an object is called from object,
425+ // current variables must be saved to object fields
426+ if (g_compiling_class) {
427+ check_obj_space(1);
428+ g_object[g_objpos++]=0x00402821; // addu a1,v0,zero
429+ call_quicklib_code(lib_save_vars_to_fields,ASM_LW_A0_XXXX_S5|ARGS_S5_V0_OBJ);
430+ }
431+ // Parameters preparation (to $s5) here.
432+ next_position();
433+ opos=g_objpos;
434+ // Begin parameter(s) construction routine
435+ err=prepare_args_stack('(');
436+ if (err) return err;
437+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
438+ g_srcpos++;
439+ // Determine address of method and store fields to local variables.
440+ check_obj_space(3);
441+ g_object[g_objpos++]=0x8FA20000|ARGS_SP_V0_OBJ; // lw v0,8(sp)
442+ g_object[g_objpos++]=0x3C050000|((method>>16)&0x0000FFFF); // lui a1,xxxx
443+ g_object[g_objpos++]=0x34A50000|(method&0x0000FFFF); // ori a1,a1,xxxx
444+ call_quicklib_code(lib_pre_method,ASM_ADDU_A0_V0_ZERO);
445+ // Call method address here. Same routine for GOSUB statement with integer value is used.
446+ check_obj_space(6);
447+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
448+ g_object[g_objpos++]=0x04130003; // bgezall zero,label1
449+ g_object[g_objpos++]=0xAEBD0000|ARGS_S5_SP; // sw sp,-12(s5)
450+ g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
451+ g_object[g_objpos++]=0x00000000; // nop
452+ // label1:
453+ g_object[g_objpos++]=0x00400008; // jr v0
454+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp) // label2:
455+ // Restore fields from local variables.
456+ check_obj_space(3);
457+ g_object[g_objpos++]=0x8FA40008; // lw a0,8(sp)
458+ call_quicklib_code(lib_post_method,ASM_ADDU_A1_V0_ZERO);
459+ // Remove stack
460+ err=remove_args_stack();
461+ if (err) return err;
462+ // When method of an object is called from object,
463+ // current variables must be saved to object fields
464+ if (g_compiling_class) {
465+ check_obj_space(1);
466+ g_object[g_objpos++]=0x00402821; // addu a1,v0,zero
467+ call_quicklib_code(lib_load_vars_from_fields,ASM_LW_A0_XXXX_S5|ARGS_S5_V0_OBJ);
468+ }
469+ return 0;
470+}
471+
472+/*
473+ char* integer_obj_field();
474+ char* string_obj_field();
475+ char* float_obj_field();
476+ Implementation of access to field of object.
477+ This feature is recursive. When an object is applied to the field of another object,
478+ following expression is possible (for example):
479+ obj1.field1.field2
480+
481+*/
482+
483+#define OBJ_FIELD_INTEGER 0
484+#define OBJ_FIELD_STRING '$'
485+#define OBJ_FIELD_FLOAT '#'
486+
487+char* _obj_field(char mode){
488+ // $v0 contains the address of object.
489+ int i;
490+ char* err;
491+ do {
492+ i=check_var_name();
493+ if (i<65536) return ERR_SYNTAX;
494+ if (g_source[g_srcpos]=='(' && mode==OBJ_FIELD_INTEGER) {
495+ // This is a method
496+ g_srcpos++;
497+ return obj_method(i);
498+ } else if (g_source[g_srcpos+1]=='(') {
499+ if (g_source[g_srcpos]==mode) {
500+ // This is a string/float method
501+ g_srcpos++;
502+ g_srcpos++;
503+ return obj_method(i);
504+ }
505+ } else if (g_source[g_srcpos]==mode && mode==OBJ_FIELD_STRING) {
506+ // This is a string field. Raise 31st bit.
507+ i|=0x80000000;
508+ }
509+ check_obj_space(2);
510+ g_object[g_objpos++]=0x3C050000|((i>>16)&0x0000FFFF); // lui a1,xxxx
511+ g_object[g_objpos++]=0x34A50000|(i&0x0000FFFF); // ori a1,a1,xxxx
512+ // First and second arguments are address of object and field name, respectively.
513+ call_quicklib_code(lib_obj_field,ASM_ADDU_A0_V0_ZERO);
514+ // Check if "." follows
515+ if (g_source[g_srcpos]=='.') {
516+ // "." found. $v0 is adress of an object. See the field.
517+ g_srcpos++;
518+ continue;
519+ }
520+ } while(0);
521+ // All done. Check variable type
522+ if (mode==OBJ_FIELD_INTEGER) return 0;
523+ else if (g_source[g_srcpos]==mode) {
524+ g_srcpos++;
525+ return 0;
526+ } else return ERR_SYNTAX;
527+}
528+
529+char* integer_obj_field(){
530+ return _obj_field(OBJ_FIELD_INTEGER);
531+}
532+
533+char* string_obj_field(){
534+ return _obj_field(OBJ_FIELD_STRING);
535+}
536+
537+char* float_obj_field(){
538+ return _obj_field(OBJ_FIELD_FLOAT);
539+}
540+
541+int lib_obj_field(int* object, int fieldname){
542+ int* class;
543+ int i,numfield;
544+ // Check if this is an object (if within the RAM).
545+ if (!withinRAM(object)) err_not_obj();
546+ class=(int*)object[0];
547+ if (!withinRAM(class)) err_not_obj();
548+ // Obtain # of public field
549+ numfield=class[1]&0xff;
550+ for(i=0;i<numfield;i++){
551+ if (class[2+i*2]==fieldname) break;
552+ }
553+ if (i==numfield) err_not_field(fieldname,class[0]);
554+ // Got address of field. Return value as $v0 and address as $v1.
555+ g_temp=(int)(&object[1+i]);
556+ asm volatile("la $v1,%0"::"i"(&g_temp));
557+ asm volatile("lw $v1,0($v1)");
558+ return object[1+i];
559+}
560+
561+/*
562+ Library for letting string field
563+*/
564+
565+void lib_let_str_field(char* prev_str, char* new_str){
566+ int var_num=get_permanent_var_num();
567+ free_perm_str(prev_str);
568+ lib_let_str(new_str,var_num);
569+ return;
570+}
571+
572+/*
573+ Library for calling method statement
574+*/
575+
576+int lib_load_vars_from_fields(int* object, int v0){
577+ // Do nothing if no object
578+ if (object) lib_pre_method(object,LABEL_INIT);
579+ return v0;
580+}
581+
582+int lib_pre_method(int* object, int methodname){
583+ int i,num,nums;
584+ int* class;
585+ // Check if this is an object (if within the RAM).
586+ if (!withinRAM(object)) err_not_obj();
587+ class=(int*)object[0];
588+ if (!withinRAM(class)) err_not_obj();
589+ // Save object field values in local variables in class
590+ nums=class[1];
591+ num=nums&0xff;
592+ for(i=0;i<num;i++){
593+ // Public fields
594+ class+=2;
595+ g_var_mem[class[1]]=object[i+1];
596+ // When string, move from permanent block
597+ if (0x80000000&class[0]) move_from_perm_block_if_exists(class[1]);
598+ }
599+ num+=(nums>>8)&0xff;
600+ for(i=i;i<num;i++){
601+ // Private fields
602+ class+=2;
603+ g_var_mem[class[1]]=object[i+1];
604+ // When string/dimension, move from permanent block
605+ if (0x80000000&class[0]) move_from_perm_block_if_exists(class[1]);
606+ }
607+ // Seek method
608+ num+=(nums>>16)&0xff;
609+ for(i=i;i<num;i++){
610+ class+=2;
611+ if (class[0]==methodname) break;
612+ }
613+ if (i==num) {
614+ // Method not found
615+ if (methodname==LABEL_INIT) {
616+ // INIT method not found
617+ // Call null function
618+ return (int)(&g_return_code[0]);
619+ } else {
620+ class=(int*)object[0];
621+ err_not_field(methodname,class[0]);
622+ }
623+ }
624+ // Method found. return it.
625+ return class[1];
626+}
627+
628+int lib_save_vars_to_fields(int* object,int v0){
629+ int* class;
630+ // Do nothing if no object
631+ if (!object) return;
632+ // Check if this is an object (if within the RAM).
633+ if (!withinRAM(object)) err_not_obj();
634+ class=(int*)object[0];
635+ if (!withinRAM(class)) err_not_obj();
636+ // save vars
637+ lib_post_method(object,0);
638+ return v0;
639+}
640+
641+int lib_post_method(int* object, int v0){
642+ // Note that v0 (a1) contains the return value from a method.
643+ int i,num,nums;
644+ int* class;
645+ // Restore local variables to object field values
646+ class=(int*)object[0];
647+ nums=class[1];
648+ num=nums&0xff;
649+ for(i=0;i<num;i++){
650+ // Public fields
651+ class+=2;
652+ object[i+1]=g_var_mem[class[1]];
653+ // When string, move to permanent block
654+ if (0x80000000&class[0]) {
655+ if (g_var_size[class[1]]) move_to_perm_block(class[1]);
656+ }
657+ }
658+ num+=(nums>>8)&0xff;
659+ for(i=i;i<num;i++){
660+ // Private fields
661+ class+=2;
662+ object[i+1]=g_var_mem[class[1]];
663+ // When string/dimension, move to permanent block
664+ if (0x80000000&class[0]) {
665+ if (g_var_size[class[1]]) move_to_perm_block(class[1]);
666+ }
667+ }
668+ // all done
669+ return v0;
670+}
671+
672+/*
673+ Method statement
674+*/
675+
676+char* method_statement(){
677+ char* err;
678+ int data[2];
679+ int opos=g_objpos;
680+ // This statement is valid only in class file.
681+ if (!g_compiling_class) return ERR_INVALID_NON_CLASS;
682+ // Insert label for setting $s6
683+ err=label_statement();
684+ if (err) return err;
685+ // Register cmpdata
686+ data[0]=g_label;
687+ data[1]=(int)(&g_object[opos]);
688+ return cmpdata_insert(CMPDATA_FIELD,CMPTYPE_PUBLIC_METHOD,(int*)&data[0],2);
689+}
690+
691+/*
692+ Delete statement
693+*/
694+
695+char* delete_statement(){
696+ char* err;
697+ next_position();
698+ g_srcpos--;
699+ do{
700+ g_srcpos++;
701+ err=get_value();
702+ if (err) return err;
703+ call_quicklib_code(lib_delete,ASM_ADDU_A0_V0_ZERO);
704+ next_position();
705+ } while (g_source[g_srcpos]==',');
706+ return 0;
707+}
708+
709+/*
710+ Call statement
711+*/
712+
713+char* call_statement(){
714+ // Just get an integer value. That is it.
715+ return get_value();
716+}
717+
718+/*
719+ Static statement
720+*/
721+
722+char* static_statement(){
723+ char* err;
724+ int* record;
725+ int data[2];
726+ int i;
727+ int is_private=0;
728+ // This statement is valid only in class file.
729+ if (!g_compiling_class) return ERR_INVALID_NON_CLASS;
730+ // Check which private or public
731+ next_position();
732+ if (nextCodeIs("PRIVATE ")) {
733+ is_private=1;
734+ } else if (nextCodeIs("PUBLIC ")) {
735+ is_private=0;
736+ }
737+ do {
738+ next_position();
739+ i=check_var_name();
740+ if (i<65536) return ERR_SYNTAX;
741+ if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') {
742+ g_srcpos++;
743+ }
744+ // Register public static field
745+ if (is_private) {
746+ // This is the same as USEVAR
747+ // Register varname
748+ err=register_var_name(i);
749+ if (err) return err;
750+ } else {
751+ // Check if there is already a CMPDATA record
752+ cmpdata_reset();
753+ while(record=cmpdata_find(CMPDATA_STATIC)){
754+ if (record[1]!=g_compiling_class) continue;
755+ if (record[2]!=i) continue;
756+ break;
757+ }
758+ if (record) {
759+ // There is already a record.
760+ // Do not allocate new number but use the registered number;
761+ i=record[0]&0xffff;
762+ err=cmpdata_insert(CMPDATA_USEVAR,i,&record[2],1);
763+ if (err) return err;
764+ } else {
765+ // Register varname
766+ err=register_var_name(i);
767+ if (err) return err;
768+ // Insert a CMDATA_STATIC record
769+ data[0]=g_compiling_class; // class name as integer
770+ data[1]=i; // static var name as integer
771+ i=search_var_name(i); // var number of this static field
772+ if (i<0) return ERR_UNKNOWN;
773+ err=cmpdata_insert(CMPDATA_STATIC,i,(int*)&data[0],2);
774+ if (err) return err;
775+ }
776+ }
777+ next_position();
778+ if (g_source[g_srcpos]==',') {
779+ g_srcpos++;
780+ } else {
781+ break;
782+ }
783+ } while(1);
784+ return 0;
785+
786+}
787+
788+/*
789+ Static method
790+ Type is either 0, '$', or '#',
791+ for integer, string, or float
792+*/
793+
794+char* static_method(char type){
795+ char* err;
796+ int* data;
797+ int record[3];
798+ int i,opos,method,stack;
799+ next_position();
800+ // Check class name
801+ i=check_var_name();
802+ if (i<65536) return ERR_SYNTAX;
803+ record[0]=i;
804+ // Check if the class exists
805+ cmpdata_reset();
806+ while(data=cmpdata_find(CMPDATA_CLASS)){
807+ if (data[1]==i) {
808+ // The class was already defined.
809+ i=0;
810+ break;
811+ }
812+ }
813+ // Check '::'
814+ if (g_source[g_srcpos]!=':') return ERR_SYNTAX;
815+ g_srcpos++;
816+ if (g_source[g_srcpos]!=':') return ERR_SYNTAX;
817+ g_srcpos++;
818+ if (i) return ERR_NO_CLASS;
819+ data=(int*)data[2];
820+ // Check method
821+ i=check_var_name();
822+ if (i<65536) return ERR_SYNTAX;
823+ if (data) {
824+ method=(int)search_method(data,i);
825+ if (!method) return ERR_NOT_FIELD;
826+ } else {
827+ method=(int)&g_return_code[0];
828+ record[1]=i;
829+ }
830+ // Check type and '('
831+ if (type) {// Either 0, '$', or '#'
832+ if (g_source[g_srcpos]!=type) return ERR_SYNTAX;
833+ g_srcpos++;
834+
835+ }
836+ if (g_source[g_srcpos]!='(') return ERR_SYNTAX;
837+ g_srcpos++;
838+ // Begin parameter(s) construction routine
839+ check_obj_space(1);
840+ g_object[g_objpos++]=0x34020000; // ori v0,zero,0
841+ err=prepare_args_stack('(');
842+ if (err) return err;
843+ // Calling subroutine, which is static method of class
844+ record[2]=(int)&g_object[g_objpos+5];
845+ check_obj_space(7);
846+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
847+ g_object[g_objpos++]=0x04130003; // bgezall zero,label1
848+ g_object[g_objpos++]=0xAEBD0000|ARGS_S5_SP; // sw sp,-12(s5)
849+ g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
850+ g_object[g_objpos++]=0x00000000; // nop
851+ // label1:
852+ g_object[g_objpos++]=0x08000000|((method&0x0FFFFFFF)>>2); // j xxxx
853+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
854+ // label2:
855+ // Register CMPDATA if required.
856+ if (!data) {
857+ cmpdata_insert(CMPDATA_UNSOLVED,CMPTYPE_STATIC_METHOD,(int*)&record[0],3);
858+ g_allow_shift_obj=0;
859+ }
860+ // Remove stack
861+ err=remove_args_stack();
862+ if (err) return err;
863+ return 0;
864+}
865+
866+/*
867+ Let object.field statement
868+*/
869+
870+char* let_object_field(){
871+ char* err;
872+ char b3;
873+ int spos,opos;
874+ // $v0 contains the pointer to object
875+ spos=g_srcpos;
876+ opos=g_objpos;
877+ // Try string field, first
878+ err=string_obj_field();
879+ if (err) {
880+ // Integer or float field
881+ g_srcpos=spos;
882+ g_objpos=opos;
883+ err=integer_obj_field();
884+ if (err) return err;
885+ b3=g_source[g_srcpos];
886+ if (b3=='#') g_srcpos++;
887+ } else {
888+ // String field
889+ b3='$';
890+ }
891+ if (g_source[g_srcpos-1]==')') {
892+ // This is a CALL statement
893+ return 0;
894+ }
895+ // $v1 is address to store value. Save it in stack.
896+ check_obj_space(1);
897+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
898+ g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
899+ if (b3=='$') {
900+ // String field
901+ // Get value
902+ next_position();
903+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
904+ g_srcpos++;
905+ err=get_string();
906+ } else if (b3=='#') {
907+ // Float field
908+ // Get value
909+ next_position();
910+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
911+ g_srcpos++;
912+ err=get_float();
913+ } else {
914+ // Integer field
915+ // Get value
916+ next_position();
917+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
918+ g_srcpos++;
919+ err=get_value();
920+ }
921+ if (err) return err;
922+ // Store in field of object
923+ check_obj_space(4);
924+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
925+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
926+ g_object[g_objpos++]=0x8C640000; // lw a0,0(v1)
927+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
928+ // Handle permanent block for string field
929+ if (b3=='$') call_quicklib_code(lib_let_str_field,ASM_ADDU_A1_V0_ZERO);
930+ return 0;
931+}
\ No newline at end of file
--- /dev/null
+++ b/mips/protozoa/cmpdata.c
@@ -0,0 +1,130 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include "compiler.h"
13+
14+/*
15+ This file provide functions for handling data used when compiling.
16+ The data is inserted between g_objmax and file cache.
17+ Data format (32 bit):
18+ MSB LSB
19+ +----+----+--------+
20+ |type|len | data16 |
21+ +----+----+--------+
22+ where,
23+ type: data type number (unsigned char)
24+ len: length of data area in number of words (unsigned char)
25+ data16: general 16 bit data (short)
26+*/
27+
28+/*
29+ CMPDATA_TEMP structure
30+ type: CMPDATA_TEMP (6)
31+ len: n+1
32+ data16: id
33+ record[1]: any data
34+ record[2]: any data
35+ ...
36+ record[n]: any data
37+*/
38+
39+#define g_cmpdata g_objmax
40+
41+static int* g_cmpdata_end;
42+static int* g_cmpdata_point;
43+static unsigned short g_cmpdata_id;
44+
45+/*
46+ Initialize routine must be called when starting compiler.
47+*/
48+void cmpdata_init(){
49+ g_cmpdata_end=g_objmax;
50+ g_cmpdata_point=g_objmax;
51+ g_cmpdata_id=1;
52+}
53+
54+/*
55+ Returns ID as 16 bit indivisual number
56+*/
57+unsigned short cmpdata_get_id(){
58+ if ((++g_cmpdata_id)==0) printstr("CMPDATA: no more ID!\n");
59+ return g_cmpdata_id;
60+}
61+
62+/*
63+ Function to insert a data. The data must be defined by a pointer to int array.
64+ unsigned char type: Data type number (0-255)
65+ short data16: 16 bit data. If not required, set 0.
66+ int* data: Pointer to data array. If not requird, set 0.
67+ unsigned char num: Length of above data array. If not required, set 0.
68+*/
69+char* cmpdata_insert(unsigned char type, short data16, int* data, unsigned char num){
70+ unsigned char i;
71+ g_cmpdata-=num+1;
72+ if (g_cmpdata<g_object+g_objpos) return ERR_NE_BINARY;
73+ g_cmpdata[0]=(type<<24)|(num+1)<<16|data16;
74+ for(i=0;i<num;i++){
75+ g_cmpdata[i+1]=data[i];
76+ }
77+ return 0;
78+}
79+
80+/*
81+ Reset data point. Next search will be from the beginning.
82+*/
83+
84+void cmpdata_reset(){
85+ g_cmpdata_point=g_cmpdata;
86+}
87+
88+/*
89+ Find the next record with defined type. Return the pointer to the record.
90+*/
91+int* cmpdata_find(unsigned char type){
92+ int* ret;
93+ while(g_cmpdata_point<g_cmpdata_end){
94+ // Remember return value
95+ ret=g_cmpdata_point;
96+ // Move the point to next
97+ g_cmpdata_point+=(ret[0]&0x00ff0000)>>16;
98+ // Check if type is the same. If the same, return.
99+ if ((ret[0]>>24)==type) return ret;
100+ }
101+ return 0;
102+}
103+
104+/*
105+ Find the record from beginning.
106+*/
107+
108+int* cmpdata_findfirst(unsigned char type){
109+ cmpdata_reset();
110+ return cmpdata_find(type);
111+}
112+
113+/*
114+ Delete a record.
115+*/
116+void cmpdata_delete(int* record){
117+ int delnum;
118+ int* data;
119+ // Ignore if invalid record.
120+ if (record<g_cmpdata || g_cmpdata_end<record) return;
121+ // Get number of word to delete.
122+ delnum=(record[0]&0x00ff0000)>>16;
123+ // Delete record by shifting data.
124+ for(data=record-1;g_cmpdata<=data;data--){
125+ data[delnum]=data[0];
126+ }
127+ g_cmpdata+=delnum;
128+ // Reset
129+ cmpdata_reset();
130+}
--- /dev/null
+++ b/mips/protozoa/compiler.c
@@ -0,0 +1,183 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+/*
13+ Usage of MIPS32 registors
14+ $zero: always zero
15+ $at: not used
16+ $v0: return value or result of last calculation
17+ $v1: for calculation (like $v0=$v1*$v0)
18+ $a0-$a2: parameters for calling library ($a2=$v0)
19+ $a3: function # for library
20+ $t0-$t7: used as temporary registors
21+ $s0-$s4: not used
22+ $s5: pointer to parameters list
23+ $s6: line or label number
24+ $s7: address of call_library()
25+ $t8-$t9: used as temporary registors
26+ $k0-$k1: not used
27+ $gp: for accessing global variables by C
28+ $sp: stack pointer
29+ $fp($s8) for accessing variables by BASIC
30+ $ra: contains return address
31+*/
32+
33+#include "compiler.h"
34+
35+void start_program(void* addr, void* memory){
36+ // Note that if usage of $s0-$s7, and $fp is changed,
37+ // revice BasicInt() in timer.c, too.
38+ static unsigned int stored_sp;
39+ // Store s0-s7, fp, and ra in stacks
40+ asm volatile("#":::"s0");
41+ asm volatile("#":::"s1");
42+ asm volatile("#":::"s2");
43+ asm volatile("#":::"s3");
44+ asm volatile("#":::"s4");
45+ asm volatile("#":::"s5");
46+ asm volatile("#":::"s6");
47+ asm volatile("#":::"s7");
48+ asm volatile("#":::"fp");
49+ asm volatile("#":::"ra");
50+ // Store sp in stored_sp
51+ asm volatile("la $v0,%0"::"i"(&stored_sp));
52+ asm volatile("sw $sp,0($v0)");
53+ // Shift sp for safety
54+ asm volatile("addiu $sp,$sp,-8");
55+ // Register vector for unexpected NEXT/RETURN
56+ asm volatile("la $v0,%0"::"i"(&err_unexp_next));
57+ asm volatile("sw $v0,4($sp)");
58+ // Store end address in g_end_addr
59+ asm volatile("la $v0,%0"::"i"(&g_end_addr));
60+ asm volatile("la $v1,label");
61+ asm volatile("sw $v1,0($v0)");
62+ // Set s5 for initial_s5_stack
63+ asm volatile("la $s5,%0"::"i"(&g_initial_s5_stack[2]));
64+ // Set s7 for easy calling call_library()
65+ asm volatile("la $s7,%0"::"i"(&call_library));
66+ // Set fp and execute program
67+ asm volatile("addu $fp,$zero,$a1");
68+ asm volatile("jr $a0");
69+ // Restore sp from stored_sp
70+ asm volatile("label:");
71+ asm volatile("la $v0,%0"::"i"(&stored_sp));
72+ asm volatile("lw $sp,0($v0)");
73+ // Restore registers from stack and return
74+ return;
75+}
76+
77+int get_gp(void){
78+ asm volatile("addu $v0,$gp,$zero");
79+}
80+
81+int get_fp(void){
82+ asm volatile("addu $v0,$fp,$zero");
83+}
84+
85+
86+void shift_obj(int* src, int* dst, int len){
87+ int i;
88+ if (dst<src) {
89+ for(i=0;i<len;i++){
90+ dst[i]=src[i];
91+ }
92+ } else if (src<dst) {
93+ for(i=len-1;0<=i;i--){
94+ dst[i]=src[i];
95+ }
96+ }
97+}
98+
99+int strncmp(char* str1, char* str2, int len){
100+ int i;
101+ for (i=0;i<len;i++) {
102+ if (str1[i]>str2[i]) return 1;
103+ if (str1[i]<str2[i]) return -1;
104+ }
105+ return 0;
106+}
107+
108+int nextCodeIs(char* str){
109+ int len;
110+ next_position();
111+ for(len=0;str[len];len++);
112+ if (!strncmp(g_source+g_srcpos,str,len)) {
113+ if ('A'<=str[len-1] && str[len-1]<='Z') {
114+ // When the last character of str is alphabet,
115+ // the next character in source must be space, enter, ',', or ':'.
116+ if (0x20<g_source[g_srcpos+len] &&
117+ g_source[g_srcpos+len]!=':' && g_source[g_srcpos+len]!=',') return 0;
118+ }
119+ // String matches in the current position in source.
120+ g_srcpos+=len;
121+ return len;
122+ } else {
123+ // String didn't match.
124+ return 0;
125+ }
126+}
127+
128+int endOfStatement(){
129+ unsigned char b;
130+ next_position();
131+ b=g_source[g_srcpos];
132+ return (b<0x20 || b==':') ? 1:0;
133+}
134+
135+char* compile_line(void){
136+ char b1;
137+ char* err;
138+ g_line++;
139+ g_fileline++;
140+ // Check if line number exists
141+ next_position();
142+ b1=g_source[g_srcpos];
143+ if (b1<0x20) {
144+ // The end of line.
145+ // Don't add $s6-setting command.
146+ if (g_source[g_srcpos]==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
147+ g_srcpos++;
148+ return 0;
149+ } else if ('0'<=b1 && b1<='9') {
150+ // Line number exists
151+ err=get_label();
152+ if (err) return err;
153+ g_line=g_label;
154+ }
155+ // Store line number in $s6
156+ if (!(g_line&0xFFFF0000)) {
157+ // Line number must be less than 65536.
158+ // If not, it is invalid number.
159+ // Check existing line with the same number here.
160+ if (search_label(g_line)) {
161+ // Error: duplicate lines
162+ printstr("Line ");
163+ printstr(resolve_label(g_line));
164+ return ERR_MULTIPLE_LABEL;
165+ }
166+ if (!g_nolinenum) {
167+ check_obj_space(1);
168+ g_object[g_objpos++]=0x34160000|g_line; //ori s6,zero,xxxx;
169+ }
170+ }
171+ while(g_source[g_srcpos]!=0x0D && g_source[g_srcpos]!=0x0A){
172+ err=statement();
173+ if (err) return err;
174+ next_position();
175+ if (g_source[g_srcpos]==':') {
176+ g_srcpos++;
177+ next_position();
178+ }
179+ }
180+ if (g_source[g_srcpos]==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
181+ g_srcpos++;
182+ return 0;
183+}
\ No newline at end of file
--- /dev/null
+++ b/mips/protozoa/compiler.h
@@ -0,0 +1,523 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+// Include envilonment specific configurations
13+#include "envspecific.h"
14+
15+/* Definitions */
16+// Number of variables (including temporary ones)
17+#define ALLOC_VAR_NUM 36
18+// Block # dedicated for PCG
19+#define ALLOC_PCG_BLOCK 36
20+// Block # dedicated for GRAPHIC
21+#define ALLOC_GRAPHIC_BLOCK 37
22+// Block # dedicated for PLAYWAVE
23+#define ALLOC_WAVE_BLOCK 38
24+// Start # for long name variables
25+#define ALLOC_LNV_BLOCK 39
26+// Number of long name variables
27+#define ALLOC_LNV_NUM 190
28+// Start # of permanent blocks
29+#define ALLOC_PERM_BLOCK 229
30+// Number of blocks that can be assigned for memory allocation (including all above)
31+#define ALLOC_BLOCK_NUM 329
32+
33+// Persistent RAM bytes used for object, heap and exception data
34+#ifndef PERSISTENT_RAM_SIZE
35+ // This must be defined in envspecific.h
36+ #define PERSISTENT_RAM_SIZE (1024*53)
37+#endif
38+// Exception data area bytes
39+#define EXCEPTION_DATA_SIZE (64)
40+// RAM size used for object and heap
41+#define RAMSIZE (PERSISTENT_RAM_SIZE-EXCEPTION_DATA_SIZE)
42+
43+/* Enums */
44+enum variable{
45+ VAR_INTEGER,
46+ VAR_FLOAT,
47+ VAR_STRING
48+};
49+
50+#define OP_MASK 0x001F
51+enum operator{
52+ OP_VOID=0,
53+ OP_OR =1,
54+ OP_AND =2,
55+ OP_XOR =3,
56+ OP_EQ =4,
57+ OP_NEQ =5,
58+ OP_LT =6,
59+ OP_LTE =7,
60+ OP_MT =8,
61+ OP_MTE =9,
62+ OP_SHL =10,
63+ OP_SHR =11,
64+ OP_ADD =12,
65+ OP_SUB =13,
66+ OP_MUL =14,
67+ OP_DIV =15,
68+ OP_REM =16
69+};
70+
71+#define LIB_MASK 0xFE00
72+#define LIB_STEP 0x0200
73+enum libs{
74+ LIB_SOUND =LIB_STEP*0,
75+ LIB_MUSICFUNC =LIB_STEP*1,
76+ LIB_MUSIC =LIB_STEP*2,
77+ LIB_SETDRAWCOUNT =LIB_STEP*3,
78+ LIB_DRAWCOUNT =LIB_STEP*4,
79+ LIB_PALETTE =LIB_STEP*5,
80+ LIB_GPALETTE =LIB_STEP*6,
81+ LIB_BGCOLOR =LIB_STEP*7,
82+ LIB_CURSOR =LIB_STEP*8,
83+ LIB_CLS =LIB_STEP*9,
84+ LIB_GCLS =LIB_STEP*10,
85+ LIB_COLOR =LIB_STEP*11,
86+ LIB_GCOLOR =LIB_STEP*12,
87+ LIB_KEYS =LIB_STEP*13,
88+ LIB_RESTORE =LIB_STEP*14,
89+ LIB_RESTORE2 =LIB_STEP*15,
90+ LIB_READ =LIB_STEP*16,
91+ LIB_MIDSTR =LIB_STEP*17,
92+ LIB_CLEAR =LIB_STEP*18,
93+ LIB_DIV0 =LIB_STEP*19,
94+ LIB_LETSTR =LIB_STEP*20,
95+ LIB_STRNCMP =LIB_STEP*21,
96+ LIB_RND =LIB_STEP*22,
97+ LIB_DEC =LIB_STEP*23,
98+ LIB_HEX =LIB_STEP*24,
99+ LIB_CHR =LIB_STEP*25,
100+ LIB_CONNECT_STRING =LIB_STEP*26,
101+ LIB_STRING =LIB_STEP*27,
102+ LIB_PRINTSTR =LIB_STEP*28,
103+ LIB_LABEL =LIB_STEP*29,
104+ LIB_DIM =LIB_STEP*30,
105+ LIB_VAL =LIB_STEP*31,
106+ LIB_INPUT =LIB_STEP*32,
107+ LIB_INKEY =LIB_STEP*33,
108+ LIB_USEPCG =LIB_STEP*34,
109+ LIB_PCG =LIB_STEP*35,
110+ LIB_SCROLL =LIB_STEP*36,
111+ LIB_WAIT =LIB_STEP*37,
112+ LIB_VAR_PUSH =LIB_STEP*38,
113+ LIB_VAR_POP =LIB_STEP*39,
114+ LIB_SYSTEM =LIB_STEP*40,
115+ LIB_SPRINTF =LIB_STEP*41,
116+ LIB_FLOAT =LIB_STEP*42,
117+ LIB_FLOATFUNCS =LIB_STEP*43,
118+ LIB_CREAD =LIB_STEP*44,
119+ LIB_USEGRAPHIC =LIB_STEP*45,
120+ LIB_GRAPHIC =LIB_STEP*46,
121+ LIB_WIDTH =LIB_STEP*47,
122+ LIB_FILE =LIB_STEP*48,
123+ LIB_PLAYWAVE =LIB_STEP*49,
124+ LIB_PLAYWAVEFUNC =LIB_STEP*50,
125+ LIB_SETDIR =LIB_STEP*51,
126+ LIB_SETDIRFUNC =LIB_STEP*52,
127+ LIB_GETDIR =LIB_STEP*53,
128+ LIB_DEBUG =LIB_STEP*127,
129+};
130+
131+// Note: OP_XXXX and FUNC_XXXX cannot be used simultaneously
132+#define FUNC_MASK 0x003F
133+#define FUNC_STEP 0x0001
134+enum functions{
135+ FUNC_FLOAT =FUNC_STEP*0,
136+ FUNC_INT =FUNC_STEP*1,
137+ FUNC_VALSHARP =FUNC_STEP*2,
138+ FUNC_SIN =FUNC_STEP*3,
139+ FUNC_COS =FUNC_STEP*4,
140+ FUNC_TAN =FUNC_STEP*5,
141+ FUNC_ASIN =FUNC_STEP*6,
142+ FUNC_ACOS =FUNC_STEP*7,
143+ FUNC_ATAN =FUNC_STEP*8,
144+ FUNC_ATAN2 =FUNC_STEP*9,
145+ FUNC_SINH =FUNC_STEP*10,
146+ FUNC_COSH =FUNC_STEP*11,
147+ FUNC_TANH =FUNC_STEP*12,
148+ FUNC_EXP =FUNC_STEP*13,
149+ FUNC_LOG =FUNC_STEP*14,
150+ FUNC_LOG10 =FUNC_STEP*15,
151+ FUNC_POW =FUNC_STEP*16,
152+ FUNC_SQRT =FUNC_STEP*17,
153+ FUNC_CEIL =FUNC_STEP*18,
154+ FUNC_FLOOR =FUNC_STEP*19,
155+ FUNC_FABS =FUNC_STEP*20,
156+ FUNC_MODF =FUNC_STEP*21,
157+ FUNC_FMOD =FUNC_STEP*22,
158+ FUNC_PSET =FUNC_STEP*23,
159+ FUNC_LINE =FUNC_STEP*24,
160+ FUNC_BOXFILL =FUNC_STEP*25,
161+ FUNC_CIRCLE =FUNC_STEP*26,
162+ FUNC_CIRCLEFILL =FUNC_STEP*27,
163+ FUNC_GPRINT =FUNC_STEP*28,
164+ FUNC_PUTBMP =FUNC_STEP*29,
165+ FUNC_PUTBMP2 =FUNC_STEP*30,
166+ FUNC_GCOLOR =FUNC_STEP*31,
167+ FUNC_POINT =FUNC_STEP*32,
168+ FUNC_FOPEN =FUNC_STEP*33,
169+ FUNC_FOPENST =FUNC_STEP*34,
170+ FUNC_FILE =FUNC_STEP*35,
171+ FUNC_FCLOSE =FUNC_STEP*36,
172+ FUNC_FINPUT =FUNC_STEP*37,
173+ FUNC_FPRINTSTR =FUNC_STEP*38,
174+ FUNC_FGET =FUNC_STEP*39,
175+ FUNC_FPUT =FUNC_STEP*40,
176+ FUNC_FSEEK =FUNC_STEP*41,
177+ FUNC_FTELL =FUNC_STEP*42,
178+ FUNC_FLEN =FUNC_STEP*43,
179+ FUNC_FSTRING =FUNC_STEP*44,
180+ FUNC_FGETC =FUNC_STEP*45,
181+ FUNC_FPUTC =FUNC_STEP*46,
182+ FUNC_FREMOVE =FUNC_STEP*47,
183+ FUNC_FEOF =FUNC_STEP*48,
184+ FUNC_FINIT =FUNC_STEP*49,
185+ // MAX 63
186+};
187+
188+/* Global vars (see globalvers.c) */
189+extern int g_intconst;
190+extern char g_valueisconst;
191+extern unsigned int g_rnd_seed;
192+extern unsigned int g_label;
193+extern int g_sdepth;
194+extern int g_maxsdepth;
195+extern char g_allow_shift_obj;
196+extern enum variable g_lastvar;
197+extern char* g_source;
198+extern int g_srcpos;
199+extern int g_line;
200+extern int g_fileline;
201+extern int* g_object;
202+extern int g_objpos;
203+extern int* g_objmax;
204+extern const char* g_err_str[];
205+extern const unsigned char g_priority[];
206+extern enum operator g_last_op;
207+extern int g_end_addr;
208+extern int g_gp;
209+extern int g_s6;
210+extern char RAM[RAMSIZE];
211+extern unsigned int g_ex_data[EXCEPTION_DATA_SIZE/4];
212+extern int g_var_mem[ALLOC_BLOCK_NUM];
213+extern unsigned short g_var_pointer[ALLOC_BLOCK_NUM];
214+extern unsigned short g_var_size[ALLOC_BLOCK_NUM];
215+extern char g_temp_area_used;
216+extern char g_nolinenum;
217+extern int* g_heap_mem;
218+extern int g_max_mem;
219+extern char g_disable_break;
220+extern unsigned char* g_pcg_font;
221+extern char g_use_graphic;
222+extern unsigned short* g_graphic_area;
223+extern int* g_libparams;
224+extern int g_long_name_var_num;
225+extern char g_music_active;
226+extern int g_class;
227+extern int g_compiling_class;
228+extern int g_temp;
229+
230+/* Prototypes */
231+int get_gp(void);
232+int get_fp(void);
233+void start_program(void* addr, void* memory);
234+void shift_obj(int* src, int* dst, int len);
235+char* compile_line(void);
236+int nextCodeIs(char* str);
237+int endOfStatement();
238+
239+char* init_file(char* buff,char* appname);
240+void close_file();
241+void read_file(int blocklen);
242+char* compile_file();
243+int compile_and_link_file(char* buff,char* appname);
244+int compile_and_link_main_file(char* buff,char* appname);
245+int compile_and_link_class(char* buff,int class);
246+
247+void err_break(void);
248+void err_music(char* str);
249+void err_data_not_found(void);
250+void err_str_complex(void);
251+void err_label_not_found(void);
252+void err_no_mem(void);
253+void err_div_zero(void);
254+void err_unkonwn(void);
255+void err_unexp_next(void);
256+void err_no_block(void);
257+void err_invalid_param(void);
258+void err_file(void);
259+void err_wave(void);
260+void err_not_obj(void);
261+void err_not_field(int fieldname, int classname);
262+void err_str(char* str);
263+char* resolve_label(int s6);
264+
265+void musicint();
266+void set_sound(unsigned long* data, int flagsLR);
267+int musicRemaining(int flagsLR);
268+int waveRemaining(int mode);
269+void set_music(char* str, int flagsLR);
270+void stop_music(void);
271+void init_music(void);
272+void play_wave(char* filename, int start);
273+
274+char* statement(void);
275+char* gosub_statement();
276+char* graphic_statement(enum functions func);
277+char* fopen_statement_main(enum functions func);
278+char* fget_statement();
279+char* fput_statement();
280+char* fputc_statement();
281+char* fremove_statement();
282+char* label_statement();
283+
284+char* function(void);
285+char* str_function(void);
286+char* float_function(void);
287+
288+void call_library(void);
289+void reset_dataread();
290+
291+void free_temp_str(char* str);
292+void free_non_temp_str(char* str);
293+void free_perm_str(char* str);
294+void* alloc_memory(int size, int var_num);
295+void* calloc_memory(int size, int var_num);
296+void move_to_perm_block(int var_num);
297+void move_from_perm_block(int var_num);
298+int move_from_perm_block_if_exists(int var_num);
299+int get_permanent_var_num(void);
300+int get_varnum_from_address(void* address);
301+void* lib_calloc_memory(int size);
302+void lib_delete(int* object);
303+
304+char* link(void);
305+char* get_label(void);
306+void* search_label(unsigned int label);
307+
308+char* get_string();
309+char* simple_string(void);
310+
311+char* get_operator(void);
312+char* get_floatOperator(void);
313+char* calculation(enum operator op);
314+char* calculation_float(enum operator op);
315+int lib_float(int ia0,int iv0, enum operator a1);
316+
317+int lib_file(enum functions func, int a0, int a1, int v0);
318+
319+char* get_dim_value(int i);
320+char* get_simple_value(void);
321+char* get_value();
322+char* get_floatOrValue();
323+char* get_stringFloatOrValue();
324+
325+void blue_screen(void);
326+
327+char* get_float();
328+
329+void cmpdata_init();
330+unsigned short cmpdata_get_id();
331+char* cmpdata_insert(unsigned char type, short data16, int* data, unsigned char num);
332+void cmpdata_reset();
333+int* cmpdata_find(unsigned char type);
334+int* cmpdata_findfirst(unsigned char type);
335+void cmpdata_delete(int* record);
336+
337+int check_var_name();
338+int get_var_number();
339+int search_var_name(int nameint);
340+char* register_var_name(int nameint);
341+
342+char* update_class_info(int class);
343+char* construct_class_structure(int class);
344+void delete_cmpdata_for_class(int class);
345+
346+extern const unsigned int g_initial_s5_stack[3];
347+char* prepare_args_stack(char start_char);
348+char* remove_args_stack(void);
349+char* args_function_main(void);
350+
351+char* begin_compiling_class(int class);
352+char* end_compiling_class(int class);
353+char* new_function();
354+char* field_statement();
355+char* integer_obj_field();
356+char* string_obj_field();
357+char* float_obj_field();
358+int lib_obj_field(int* object, int fieldname);
359+int lib_pre_method(int* object, int methodname);
360+int lib_post_method(int* object, int v0);
361+int lib_save_vars_to_fields(int* object,int v0);
362+int lib_load_vars_from_fields(int* object, int v0);
363+
364+char* method_statement();
365+char* delete_statement();
366+char* call_statement();
367+void lib_let_str_field(char* str, char* prev_str);
368+char* let_object_field();
369+char* static_statement();
370+char* static_method(char type);
371+char* resolve_unresolved(int class);
372+
373+void init_timer();
374+void stop_timer();
375+char* usetimer_statement();
376+char* timer_statement();
377+char* timer_function();
378+char* interrupt_statement();
379+
380+/* Error messages */
381+#define ERR_SYNTAX (char*)(g_err_str[0])
382+#define ERR_NE_BINARY (char*)(g_err_str[1])
383+#define ERR_NE_MEMORY (char*)(g_err_str[2])
384+#define ERR_DIV_0 (char*)(g_err_str[3])
385+#define ERR_NY_I (char*)(g_err_str[4])
386+#define ERR_LABEL_NF (char*)(g_err_str[5])
387+#define ERR_LABEL_LONG (char*)(g_err_str[6])
388+#define ERR_STR_COMPLEX (char*)(g_err_str[7])
389+#define ERR_DATA_NF (char*)(g_err_str[8])
390+#define ERR_UNKNOWN (char*)(g_err_str[9])
391+#define ERR_MUSIC (char*)(g_err_str[10])
392+#define ERR_MULTIPLE_LABEL (char*)(g_err_str[11])
393+#define ERR_BREAK (char*)(g_err_str[12])
394+#define ERR_UNEXP_NEXT (char*)(g_err_str[13])
395+#define ERR_NO_BLOCK (char*)(g_err_str[14])
396+#define ERR_GOSUB_ASH (char*)(g_err_str[15])
397+#define ERR_INVALID_BREAK (char*)(g_err_str[16])
398+#define ERR_INVALID_ELSEIF (char*)(g_err_str[17])
399+#define ERR_INVALID_PARAM (char*)(g_err_str[18])
400+#define ERR_FILE (char*)(g_err_str[19])
401+#define ERR_INVALID_VAR_NAME (char*)(g_err_str[20])
402+#define ERR_WAVE (char*)(g_err_str[21])
403+#define ERR_COMPILE_CLASS (char*)(g_err_str[22])
404+#define ERR_NO_CLASS (char*)(g_err_str[23])
405+#define ERR_NOT_OBJ (char*)(g_err_str[24])
406+#define ERR_NOT_FIELD (char*)(g_err_str[25])
407+#define ERR_INVALID_NON_CLASS (char*)(g_err_str[26])
408+#define ERR_INVALID_CLASS (char*)(g_err_str[27])
409+#define ERR_NO_INIT (char*)(g_err_str[28])
410+
411+/* compile data type numbers */
412+#define CMPDATA_RESERVED 0
413+#define CMPDATA_USEVAR 1
414+#define CMPDATA_CLASS 2
415+#define CMPDATA_FIELD 3
416+#define CMPDATA_STATIC 4
417+#define CMPDATA_UNSOLVED 5
418+#define CMPDATA_TEMP 6
419+// Sub types follow
420+#define CMPTYPE_PUBLIC_FIELD 0
421+#define CMPTYPE_PRIVATE_FIELD 1
422+#define CMPTYPE_PUBLIC_METHOD 2
423+#define CMPTYPE_NEW_FUNCTION 0
424+#define CMPTYPE_STATIC_METHOD 1
425+
426+
427+/* Stack position for values in args.c */
428+#define ARGS_SP_SP 4
429+#define ARGS_SP_V0_OBJ 8
430+#define ARGS_SP_PREV_S5 12
431+#define ARGS_SP_NUM_ARGS 16
432+#define ARGS_S5_SP (-12 & 0xFFFF)
433+#define ARGS_S5_V0_OBJ (-8 & 0xFFFF)
434+#define ARGS_S5_PREV_S5 (-4 & 0xFFFF)
435+#define ARGS_S5_NUM_ARGS (0 & 0xFFFF)
436+
437+/*
438+ Hidden varname 31 bit values
439+ Note that max number of 31 bit value is 0x61504BFF (for ZZZZZZ)
440+*/
441+#define HIDDEN_VAR_THIS_OBJECT 0x7FFF0000
442+
443+/* Macros */
444+
445+// Lables as 31 bit integer
446+#define LABEL_INIT 0x0007df55
447+
448+// Skip blanc(s) in source code
449+#define next_position() while(g_source[g_srcpos]==' ') {g_srcpos++;}
450+
451+// Check if object area is not full.
452+#define check_obj_space(x) if (g_objmax<g_object+g_objpos+(x)) return ERR_NE_BINARY
453+
454+// Returns priority of operator
455+#define priority(x) (int)g_priority[(int)(x)]
456+
457+// Insert code for calling library
458+//02E0F809 jalr ra,s7
459+//24070000 addiu a3,zero,0000
460+#define call_lib_code(x) \
461+ check_obj_space(2);\
462+ g_object[g_objpos++]=0x02E0F809;\
463+ g_object[g_objpos++]=0x24070000|((x)&0x0000FFFF)
464+
465+// Insert code for calling quick library
466+//3C081234 lui t0,0x1234
467+//35085678 ori t0,t0,0x5678
468+//0100F809 jalr ra,t0
469+//00000000 nop
470+#define call_quicklib_code(x,y) do {\
471+ check_obj_space(4);\
472+ g_object[g_objpos++]=0x3C080000|(((unsigned int)(x))>>16);\
473+ g_object[g_objpos++]=0x35080000|(((unsigned int)(x))&0x0000FFFF);\
474+ g_object[g_objpos++]=0x0100F809;\
475+ g_object[g_objpos++]=(y);\
476+ } while (0)
477+
478+#define ASM_NOP 0x00000000
479+#define ASM_ADDU_A0_V0_ZERO 0x00402021
480+#define ASM_ADDU_A1_V0_ZERO 0x00402821
481+#define ASM_ADDU_A2_V0_ZERO 0x00403021
482+#define ASM_ADDU_A3_V0_ZERO 0x00403821
483+#define ASM_ORI_A0_ZERO_ 0x34040000
484+#define ASM_LW_A0_XXXX_S8 0x8FC40000
485+#define ASM_LW_A0_XXXX_S5 0x8EA40000
486+
487+// Interrupt macros
488+// 32 different type interruptions are possible
489+// See also envspecific.h for additional interruptions
490+#define INTERRUPT_TIMER 0
491+#define INTERRUPT_DRAWCOUNT 1
492+#define INTERRUPT_KEYS 2
493+#define INTERRUPT_INKEY 3
494+#define INTERRUPT_MUSIC 4
495+#define INTERRUPT_WAVE 5
496+
497+extern int g_interrupt_flags;
498+extern int g_int_vector[];
499+#define raise_interrupt_flag(x) do {\
500+ if (g_int_vector[x]) {\
501+ IFS0bits.CS1IF=1;\
502+ g_interrupt_flags|=(1<<(x));\
503+ }\
504+} while(0)
505+
506+// Division macro for unsigned long
507+// Valid for 31 bits for all cases and 32 bits for some cases
508+#define div32(x,y,z) ((((unsigned long long)((unsigned long)(x)))*((unsigned long long)((unsigned long)(y))))>>(z))
509+
510+// Divide by 9 (valid for 32 bits)
511+#define div9_32(x) div32(x,0xe38e38e4,35)
512+#define rem9_32(x) ((x)-9*div9_32(x))
513+
514+// Divide by 10 (valid for 32 bits)
515+#define div10_32(x) div32(x,0xcccccccd,35)
516+#define rem10_32(x) ((x)-10*div10_32(x))
517+
518+// Divide by 36 (valid for 32 bits)
519+#define div36_32(x) div32(x,0xe38e38e4,37)
520+#define rem36_32(x) (x-36*div36_32(x))
521+
522+// Check if within RAM
523+#define withinRAM(x) ((&RAM[0])<=((char*)(x)) && ((char*)(x))<(&RAM[RAMSIZE]))
--- /dev/null
+++ b/mips/protozoa/debug.c
@@ -0,0 +1,302 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+#ifdef __DEBUG
9+
10+#include <xc.h>
11+#include "api.h"
12+#include "main.h"
13+#include "compiler.h"
14+
15+/*
16+ Enable following line when debugging binary object.
17+*/
18+//#include "debugdump.h"
19+
20+
21+// Pseudo reading config setting for debug mode
22+unsigned int g_DEVCFG1=0xFF7F4DDB;
23+
24+// Construct jump assembly in boot area.
25+const unsigned int _debug_boot[] __attribute__((address(0xBFC00000))) ={
26+ 0x0B401C00,// j 0x9d007000
27+ 0x00000000,// nop
28+};
29+
30+// Use DEBUG.HEX as file name of this program.
31+const unsigned char _debug_filename[] __attribute__((address(FILENAME_FLASH_ADDRESS))) ="DEBUG.HEX";
32+
33+static const char initext[];
34+static const char bastext[];
35+static const char class1text[];
36+static const char class2text[];
37+
38+static char* readtext;
39+static int filepos;
40+
41+/*
42+ Debug dump
43+ In debugdump.h:
44+ __DEBUGDUMP is defined.
45+ __DEBUGDUMP_FREEAREA is defined as start address of free area (1st argument of set_free_area() function)
46+ const unsigned char dump[] is initialized.
47+*/
48+#ifdef __DEBUGDUMP
49+int debugDump(){
50+ int i;
51+ for(i=0;i<sizeof dump;i++){
52+ RAM[i]=dump[i];
53+ }
54+
55+ g_objpos=(__DEBUGDUMP_FREEAREA-(unsigned int)g_object)/4;
56+
57+ // Initialize parameters
58+ g_pcg_font=0;
59+ g_use_graphic=0;
60+ g_graphic_area=0;
61+ clearscreen();
62+ setcursor(0,0,7);
63+
64+ printstr("BASIC "BASVER"\n");
65+ wait60thsec(15);
66+
67+ printstr("Compiling...");
68+
69+ // Initialize the other parameters
70+ // Random seed
71+ g_rnd_seed=0x92D68CA2; //2463534242
72+ // Clear variables
73+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
74+ g_var_mem[i]=0;
75+ g_var_size[i]=0;
76+ }
77+ // Clear key input buffer
78+ for(i=0;i<256;i++){
79+ ps2keystatus[i]=0;
80+ }
81+ // Reset data/read.
82+ reset_dataread();
83+
84+ // Assign memory
85+ set_free_area((void*)(g_object+g_objpos),(void*)(&RAM[RAMSIZE]));
86+ // Execute program
87+ // Start program from the beginning of RAM.
88+ // Work area (used for A-Z values) is next to the object code area.
89+ start_program((void*)(&(RAM[0])),(void*)(&g_var_mem[0]));
90+ printstr("\nOK\n");
91+ g_use_graphic=0;
92+
93+ return 1;
94+}
95+#else
96+int debugDump(){
97+ return 0;
98+}
99+#endif
100+
101+/*
102+ Override libsdfsio functions.
103+ Here, don't use SD card, but the vertual files
104+ (initext[] and bastext[]) are used.
105+*/
106+
107+FSFILE fsfile;
108+
109+size_t FSfread(void *ptr, size_t size, size_t n, FSFILE *stream){
110+ char b;
111+ size_t ret=0;
112+ if (!readtext) return 0;
113+ while(b=readtext[filepos]){
114+ filepos++;
115+ ((char*)ptr)[ret]=b;
116+ ret++;
117+ if (n<=ret) break;
118+ }
119+ return ret;
120+}
121+FSFILE* FSfopen(const char * fileName, const char *mode){
122+ int i;
123+ for(i=0;i<13;i++){
124+ if (fileName[i]=='.') break;
125+ }
126+ if (i==13) {
127+ // Unknown file name
128+ // Force BAS file
129+ readtext=(char*)&bastext[0];
130+ } else if (fileName[i+1]=='I' && fileName[i+2]=='N' && fileName[i+3]=='I') {
131+ // INI file
132+ readtext=(char*)&initext[0];
133+ } else if (fileName[i+1]=='B' && fileName[i+2]=='A' && fileName[i+3]=='S') {
134+ // Select BAS file
135+ if (fileName[i-6]=='C' && fileName[i-5]=='L' && fileName[i-4]=='A' &&
136+ fileName[i-3]=='S' && fileName[i-2]=='S') {
137+ if (fileName[i-1]=='1') readtext=(char*)&class1text[0];
138+ else if (fileName[i-1]=='2') readtext=(char*)&class2text[0];
139+ else readtext=(char*)&bastext[0];
140+ } else {
141+ readtext=(char*)&bastext[0];
142+ }
143+ // Try debugDump.
144+ if (debugDump()) return 0;
145+ } else {
146+ readtext=0;
147+ return 0;
148+ }
149+ filepos=0;
150+ return &fsfile;
151+}
152+int FSfeof( FSFILE * stream ){
153+ return readtext[filepos]?1:0;
154+}
155+int FSfclose(FSFILE *fo){
156+ return 0;
157+}
158+int FSInit(void){
159+ return 1;
160+}
161+int FSremove (const char * fileName){
162+ return 0;
163+}
164+size_t FSfwrite(const void *ptr, size_t size, size_t n, FSFILE *stream){
165+ return 0;
166+}
167+
168+int FindFirst (const char * fileName, unsigned int attr, SearchRec * rec){
169+ return 0;
170+}
171+int FindNext (SearchRec * rec){
172+ return 0;
173+}
174+int FSmkdir (char * path){
175+ return 0;
176+}
177+char * FSgetcwd (char * path, int numchars){
178+ return 0;
179+}
180+int FSchdir (char * path){
181+ return 0;
182+}
183+long FSftell (FSFILE * fo){
184+ return 0;
185+}
186+int FSfseek(FSFILE *stream, long offset, int whence){
187+ return 0;
188+}
189+/*
190+ ps2init() is not called.
191+ Instead, not_ps2init_but_init_Timer1() is called.
192+ Timer1 is used to update drawcount and drawing gloval variables.
193+*/
194+
195+int not_ps2init_but_init_Timer1(){
196+ PR1=0x0FFF;
197+ TMR1=0;
198+ IFS0bits.T1IF=0;
199+ T1CON=0x8000;
200+ // Timer1 interrupt: priority 4
201+ IPC1bits.T1IP=4;
202+ IPC1bits.T1IS=0;
203+ IEC0bits.T1IE=1;
204+
205+ return 0;
206+}
207+
208+#pragma interrupt timer1Int IPL4SOFT vector 4
209+
210+void timer1Int(){
211+ IFS0bits.T1IF=0;
212+ if (drawing) {
213+ drawing=0;
214+ drawcount++;
215+ } else {
216+ drawing=1;
217+ }
218+}
219+
220+/*
221+ initext[] and bastext[] are vertual files
222+ as "MACHIKAN.INI" and "DEBUG.BAS".
223+*/
224+
225+
226+static const char initext[]=
227+"#PRINT\n"
228+"#PRINT\n";
229+
230+static const char bastext[]=
231+"I=1:WHILE I<=10\n"
232+"I=I+1:WEND\n"
233+"\n"
234+"I=1:DO\n"
235+"I=I+1:LOOP UNTIL I=11\n"
236+"\n"
237+"FOR I=1 TO 10\n"
238+"NEXT\n"
239+"\n"
240+"\n"
241+"\n";
242+
243+static const char class1text[]=
244+"STATIC T1\n"
245+"useclass CLASS2\n"
246+"method T3\n"
247+" return CLASS2::T2\n"
248+"method T5\n"
249+" return T1\n"
250+"\n"
251+"\n";
252+
253+static const char class2text[]=
254+"STATIC T2\n"
255+"useclass CLASS1\n"
256+"method T4\n"
257+" return CLASS1::T1\n"
258+"method T6\n"
259+" return T2\n"
260+"\n"
261+"\n"
262+"\n"
263+"\n";
264+
265+/*
266+ Test function for constructing assemblies from C codes.
267+*/
268+
269+static const void* debugjumptable[]={
270+ FSfread,
271+ FSfopen,
272+};
273+
274+#define for2(x,y,z) for(x=y;x<=z;x++)
275+
276+int _debug_test(int a0, int a1, int a2, int a3, int param4, int param5){
277+ asm volatile(".set noreorder");
278+ asm volatile("addiu $v0,$zero,4772");
279+ asm volatile("loop:");
280+ asm volatile("bne $v0,$zero,loop");
281+ asm volatile("addi $v0,$v0,-1");
282+ asm volatile("wait");
283+ asm volatile("nop");
284+ asm volatile("nop");
285+ asm volatile("nop");
286+ asm volatile("nop");
287+ asm volatile("nop");
288+ asm volatile("nop");
289+ asm volatile("nop");
290+ asm volatile("nop");
291+ a2&=0xFFFFFFFC;
292+ return a2+a3;
293+}
294+
295+/*
296+ Break point used for debugging object code.
297+
298+g_object[g_objpos++]=0x0000000d;// break 0x0
299+
300+*/
301+
302+#endif // __DEBUG
--- /dev/null
+++ b/mips/protozoa/debug.h
@@ -0,0 +1,34 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#ifdef __DEBUG
13+
14+// Pseudo reading config setting for debug mode
15+extern unsigned int g_DEVCFG1;
16+#define DEVCFG1 g_DEVCFG1
17+
18+// Do not use PS/2 keyboard
19+#define ps2init() not_ps2init_but_init_Timer1()
20+int not_ps2init_but_init_Timer1();
21+
22+// Do not use asm("wait") but use asm("nop")
23+#undef WAIT
24+#define WAIT "nop"
25+
26+#endif // __DEBUG
27+
28+// key waiting macro
29+
30+#define debug_wait() lineinput((char*)&g_temp,3)
31+#define debug_wait_char(x) do {\
32+ printchar(x); \
33+ lineinput((char*)&g_temp,3);\
34+ } while(0)
--- /dev/null
+++ b/mips/protozoa/editor.c
@@ -0,0 +1,20 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+#include <xc.h>
9+#include "api.h"
10+#include "editor.h"
11+#include "compiler.h"
12+#include "main.h"
13+
14+unsigned char currentfile[13],tempfile[13]; //編集中のファイル名、一時ファイル名
15+
16+void wait60thsec(unsigned short n){
17+ // 60分のn秒ウェイト(ビデオ画面の最下行信号出力終了まで待つ)
18+ n+=drawcount;
19+ while(drawcount!=n) asm(WAIT);
20+}
--- /dev/null
+++ b/mips/protozoa/editor.h
@@ -0,0 +1,41 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+*/
6+
7+#define TBUFMAXLINE 201 //テキストバッファ数
8+
9+#define TBUFSIZE 200 //テキストバッファ1つのサイズ
10+#define TBUFMAXSIZE (TBUFSIZE*(TBUFMAXLINE-1)) //最大バッファ容量(バッファ1行分空ける)
11+//#define EDITWIDTHX 30 //エディタ画面横幅
12+#define EDITWIDTHY 29 //エディタ画面縦幅
13+//#define EDITWIDTHY 39 //エディタ画面縦幅
14+#define COLOR_NORMALTEXT 7 //通常テキスト色
15+#define COLOR_ERRORTEXT 4 //エラーメッセージテキスト色
16+#define COLOR_AREASELECTTEXT 4 //範囲選択テキスト色
17+#define COLOR_BOTTOMLINE 5 //画面最下行の色
18+#define COLOR_DIR 6 //ディレクトリ名表示の色
19+#define FILEBUFSIZE 256 //ファイルアクセス用バッファサイズ
20+#define MAXFILENUM 200 //利用可能ファイル最大数
21+#define PATHNAMEMAX 128 //ワーキングディレクトリパス名の最大値
22+#define UNDOBUFSIZE 2048 //アンドゥ用バッファサイズ
23+
24+#define ERR_FILETOOBIG -1
25+#define ERR_CANTFILEOPEN -2
26+#define ERR_CANTWRITEFILE -3
27+
28+#define TEMPFILENAME "~TEMP.BAS" //実行時ソース保存ファイル名
29+#define WORKDIRFILE "~WORKDIR.TMP" //実行時パス保存ファイル名
30+
31+#define UNDO_INSERT 1
32+#define UNDO_OVERWRITE 2
33+#define UNDO_DELETE 3
34+#define UNDO_BACKSPACE 4
35+#define UNDO_CONTINS 5
36+#define UNDO_CONTDEL 6
37+
38+void texteditor(void); //テキストエディタ本体
39+int runbasic(char *s,int test); //コンパイルして実行
40+extern unsigned char tempfile[13];
41+void wait60thsec(unsigned short n);
--- /dev/null
+++ b/mips/protozoa/envspecific.c
@@ -0,0 +1,268 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#include <xc.h>
9+#include "main.h"
10+#include "compiler.h"
11+#include "api.h"
12+
13+/*
14+ dymmy imprementations:
15+ ps2keystatus
16+ ps2init
17+*/
18+volatile unsigned char ps2keystatus[256];
19+void g_set_palette(unsigned char n,unsigned char b,unsigned char r,unsigned char g){
20+ set_palette(n,b,r,g);
21+}
22+void ps2init(void){}
23+
24+
25+void pre_run(){
26+ // Currently, do nothing.
27+}
28+
29+void post_run(){
30+ // Cool down
31+}
32+
33+
34+int readbuttons(){
35+ int keys;
36+ LCD_CS_HI;
37+ asm("nop");
38+ KEY_EN;
39+ asm("nop");
40+ TRISBSET=KEYMASK;
41+ asm("nop");
42+ keys=KEYPORT;
43+#if LCD_ALIGNMENT == VERTICAL
44+ keys=
45+ ((keys&KEYUP)? 0:1)|
46+ ((keys&KEYDOWN)? 0:2)|
47+ ((keys&KEYLEFT)? 0:4)|
48+ ((keys&KEYRIGHT)? 0:8)|
49+ ((keys&KEYSTART)? 0:16)|
50+ ((keys&KEYFIRE)? 0:32);
51+#else
52+ keys=
53+ ((keys&KEYRIGHT)? 0:1)|
54+ ((keys&KEYLEFT)? 0:2)|
55+ ((keys&KEYUP)? 0:4)|
56+ ((keys&KEYDOWN)? 0:8)|
57+ ((keys&KEYSTART)? 0:16)|
58+ ((keys&KEYFIRE)? 0:32);
59+#endif
60+ KEY_DS;
61+ asm("nop");
62+ TRISBCLR=KEYMASK;
63+ asm("nop");
64+ LCD_CS_LO;
65+ return keys;
66+}
67+
68+void scroll30(int x,int y){
69+ int i,j;
70+ int vector=y*WIDTH_X1+x;
71+ if (vector<0) {
72+ // Copy data from upper address to lower address
73+ for(i=0-vector;i<WIDTH_X1*WIDTH_Y;i++){
74+ TVRAM[i+vector]=TVRAM[i];
75+ TVRAM[WIDTH_X1*WIDTH_Y+i+vector]=TVRAM[WIDTH_X1*WIDTH_Y+i];
76+ }
77+ } else if (0<vector) {
78+ // Copy data from lower address to upper address
79+ for(i=WIDTH_X1*WIDTH_Y-vector-1;0<=i;i--){
80+ TVRAM[i+vector]=TVRAM[i];
81+ TVRAM[WIDTH_X1*WIDTH_Y+i+vector]=TVRAM[WIDTH_X1*WIDTH_Y+i];
82+ }
83+ } else {
84+ return;
85+ }
86+ if (x<0) {
87+ // Fill blanc at right
88+ for(i=x;i<0;i++){
89+ for(j=WIDTH_X1+i;j<WIDTH_X1*WIDTH_Y;j+=WIDTH_X1){
90+ TVRAM[j]=0x00;
91+ TVRAM[WIDTH_X1*WIDTH_Y+j]=cursorcolor;
92+ }
93+ }
94+ } else if (0<x) {
95+ // Fill blanc at left
96+ for(i=0;i<x;i++){
97+ for(j=i;j<WIDTH_X1*WIDTH_Y;j+=WIDTH_X1){
98+ TVRAM[j]=0x00;
99+ TVRAM[WIDTH_X1*WIDTH_Y+j]=cursorcolor;
100+ }
101+ }
102+ }
103+ if (y<0) {
104+ // Fill blanc at bottom
105+ for(i=WIDTH_X1*(WIDTH_Y+y);i<WIDTH_X1*WIDTH_Y;i++){
106+ TVRAM[i]=0x00;
107+ TVRAM[WIDTH_X1*WIDTH_Y+i]=cursorcolor;
108+ }
109+ } else if (0<y) {
110+ // Fill blanc at top
111+ for(i=0;i<WIDTH_X1*y;i++){
112+ TVRAM[i]=0x00;
113+ TVRAM[WIDTH_X1*WIDTH_Y+i]=cursorcolor;
114+ }
115+ }
116+}
117+
118+void scroll40(int x,int y){
119+ int i,j;
120+ int vector=y*WIDTH_X2+x;
121+ if (vector<0) {
122+ // Copy data from upper address to lower address
123+ for(i=0-vector;i<WIDTH_X2*WIDTH_Y;i++){
124+ TVRAM[i+vector]=TVRAM[i];
125+ TVRAM[WIDTH_X2*WIDTH_Y+i+vector]=TVRAM[WIDTH_X2*WIDTH_Y+i];
126+ }
127+ } else if (0<vector) {
128+ // Copy data from lower address to upper address
129+ for(i=WIDTH_X2*WIDTH_Y-vector-1;0<=i;i--){
130+ TVRAM[i+vector]=TVRAM[i];
131+ TVRAM[WIDTH_X2*WIDTH_Y+i+vector]=TVRAM[WIDTH_X2*WIDTH_Y+i];
132+ }
133+ } else {
134+ return;
135+ }
136+ if (x<0) {
137+ // Fill blanc at right
138+ for(i=x;i<0;i++){
139+ for(j=WIDTH_X2+i;j<WIDTH_X2*WIDTH_Y;j+=WIDTH_X2){
140+ TVRAM[j]=0x00;
141+ TVRAM[WIDTH_X2*WIDTH_Y+j]=cursorcolor;
142+ }
143+ }
144+ } else if (0<x) {
145+ // Fill blanc at left
146+ for(i=0;i<x;i++){
147+ for(j=i;j<WIDTH_X2*WIDTH_Y;j+=WIDTH_X2){
148+ TVRAM[j]=0x00;
149+ TVRAM[WIDTH_X2*WIDTH_Y+j]=cursorcolor;
150+ }
151+ }
152+ }
153+ if (y<0) {
154+ // Fill blanc at bottom
155+ for(i=WIDTH_X2*(WIDTH_Y+y);i<WIDTH_X2*WIDTH_Y;i++){
156+ TVRAM[i]=0x00;
157+ TVRAM[WIDTH_X2*WIDTH_Y+i]=cursorcolor;
158+ }
159+ } else if (0<y) {
160+ // Fill blanc at top
161+ for(i=0;i<WIDTH_X2*y;i++){
162+ TVRAM[i]=0x00;
163+ TVRAM[WIDTH_X2*WIDTH_Y+i]=cursorcolor;
164+ }
165+ }
166+}
167+
168+void scroll(int x, int y){
169+ if (twidth==40) scroll40(x,y);
170+ else scroll30(x,y);
171+}
172+
173+void allocate_graphic_area(){
174+ if (!g_graphic_area) {
175+ // Use this pointer like unsigned short GVRAM[G_H_WORD*G_Y_RES] __attribute__ ((aligned (4)));
176+// g_graphic_area=(unsigned short*)alloc_memory(G_H_WORD*G_Y_RES/2,ALLOC_GRAPHIC_BLOCK);
177+ g_graphic_area=(void *)1;
178+ // Start graphic and clear screen
179+// init_graphic(g_graphic_area);
180+ init_graphic();
181+ // Move current point to (0,0)
182+// g_prev_x=g_prev_y=0;
183+ }
184+}
185+
186+void usegraphic(int mode){
187+ // Modes; 0: stop GRAPHIC, 1: use GRAPHIC, 2: reset GRAPHIC and use it
188+ switch(mode){
189+ case 0:
190+ if (g_use_graphic){
191+ // Stop GRAPHIC if used
192+ set_graphmode(0);
193+ g_use_graphic=0;
194+ // Set timer4 for tempo
195+// PR4=59473; // 3632*262/16-1
196+ } else {
197+ // Prepare GRAPHIC area if not used and not allcated.
198+ allocate_graphic_area();
199+ }
200+ break;
201+ case 2:
202+ // Reset GRAPHIC and use it
203+ g_graphic_area=0;
204+ // Continue to case 1:
205+ case 1:
206+ case 3:
207+ default:
208+ // Use GRAPHIC
209+ allocate_graphic_area();
210+ // Start showing GRAPHIC with mode 1, but not with mode 3
211+ if (mode !=3 && !g_use_graphic){
212+ set_graphmode(1);
213+ g_use_graphic=1;
214+ // Set timer4 for tempo
215+// PR4=55756; // ~=3405*262/16-1(55755.875)
216+ }
217+ break;
218+ }
219+}
220+
221+void videowidth(int width){
222+ // Do nothing
223+}
224+
225+int lib_system(int a0, int a1 ,int v0, int a3, int g_gcolor, int g_prev_x, int g_prev_y){
226+ switch(a0){
227+ // Version info
228+ case 0: return (int)SYSVER1;
229+ case 1: return (int)SYSVER2;
230+ case 2: return (int)BASVER;
231+ case 3: return (int)FILENAME_FLASH_ADDRESS;
232+ // Display info
233+ case 20: return twidth;
234+ case 21: return WIDTH_Y;
235+ case 22: return G_X_RES;
236+ case 23: return G_Y_RES;
237+ case 24: return cursorcolor;
238+ case 25: return g_gcolor;
239+ case 26: return ((int)(cursor-TVRAM))%twidth;
240+ case 27: return ((int)(cursor-TVRAM))/twidth;
241+ case 28: return g_prev_x;
242+ case 29: return g_prev_y;
243+ // Keyboard info
244+ case 40: return 0;//(int)inPS2MODE();
245+ case 41: return 0;//(int)vkey;
246+ case 42: return 0;//(int)lockkey;
247+ case 43: return 0;//(int)keytype;
248+ // Pointers to gloval variables
249+ case 100: return (int)&g_var_mem[0];
250+ case 101: return (int)&g_rnd_seed;
251+ case 102: return (int)&TVRAM[0];
252+ case 103: return (int)&FontData[0];
253+ case 104: return (int)g_var_mem[ALLOC_PCG_BLOCK];
254+ case 105: return (int)g_var_mem[ALLOC_GRAPHIC_BLOCK];
255+ // Change system settings
256+ case 200:
257+ // ON/OFF monitor
258+ if (v0) {
259+// start_composite();
260+ } else {
261+// stop_composite();
262+ }
263+ break;
264+ default:
265+ break;
266+ }
267+ return 0;
268+}
--- /dev/null
+++ b/mips/protozoa/envspecific.h
@@ -0,0 +1,37 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#define CPU_CLOCK_HZ 48000000
9+#define PERSISTENT_RAM_SIZE (1024*53)
10+
11+int readbuttons();
12+void scroll(int x, int y);
13+void usegraphic(int mode);
14+void videowidth(int width);
15+int lib_system(int a0, int a1 ,int v0, int a3, int g_gcolor, int g_prev_x, int g_prev_y);
16+
17+// 30 or 40 characters per line for Zoea
18+#define printcomma() printstr(" "+rem10_32((unsigned int)(cursor-TVRAM)))
19+
20+// Check break key or buttons when executing BASIC code.
21+// In PS/2 mode, detect ctrl-break.
22+// In button mode, detect pushing four buttons are pushed simultaneously.
23+#define check_break() \
24+ if (g_disable_break==0) {\
25+ if (inPS2MODE()) {\
26+ if (ps2keystatus[0x03]) err_break();\
27+ } else {\
28+ if ((PORTB&0x4c80)==0) err_break();\
29+ }\
30+ }
31+
32+// Protozoa specific lists of statements and functions (none defined for Zoea)
33+#define ADDITIONAL_STATEMENTS
34+#define ADDITIONAL_INT_FUNCTIONS
35+#define ADDITIONAL_STR_FUNCTIONS
36+#define ADDITIONAL_RESERVED_VAR_NAMES
37+#define ADDITIONAL_INTERRUPT_FUNCTIONS
--- /dev/null
+++ b/mips/protozoa/error.c
@@ -0,0 +1,198 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include "compiler.h"
13+
14+const char* g_err_str[]={
15+ "Syntax error",
16+ "Not enough binary space",
17+ "Not enough memory",
18+ "Divided by zero",
19+ "Not yet implemented",
20+ "Label or line number not found: ",
21+ "Label too long or too short",
22+ "String too complexed",
23+ "Data not found",
24+ "Unknown error:",
25+ "Music syntax error:'",
26+ " found more than twice",
27+ "Break",
28+ "Unexpected NEXT or RETURN statement",
29+ "Cannot assign temporary block",
30+ "GOSUB fuction cannot be used after string-handling",
31+ "Invalid BREAK statement in line ",
32+ "Invalid ELSE/IF statement in line ",
33+ "Invalid parameter(s)",
34+ "File error",
35+ "Invalid variable name",
36+ "WAVE format error",
37+ "ERR_COMPILE_CLASS",
38+ "Class not found",
39+ "Not an object",
40+ " is not public field/method",
41+ "Valid only in class file",
42+ "Invalid in class file",
43+ "INIT method does not exist",
44+};
45+
46+char* resolve_label(int s6){
47+ static char str[7];
48+ int i,j;
49+ if (s6<65536) {
50+ // Line number
51+ for(i=0;i<5;i++){
52+ str[5-i]='0'+rem10_32(s6);
53+ s6=div10_32(s6);
54+ }
55+ str[6]=0x00;
56+ for(j=1;j<5;j++){
57+ if (str[j]!='0') break;
58+ }
59+ return (char*)(str+j);
60+ } else {
61+ // Label
62+ s6-=65536;
63+ str[6]=0x00;
64+ for(i=5;0<=i;i--){
65+ if (s6<36) {
66+ // First character must be A-Z, corresponding to 1-26 but not 10-35.
67+ // See get_label() for the detail.
68+ str[i]=s6-1+'A';
69+ break;
70+ } else {
71+ // From second, 0-9 corresponds to 0-9 and A-Z corresponds to 10-35.
72+ str[i]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[rem36_32(s6)];
73+ s6=div36_32(s6);
74+ }
75+ }
76+ return (char*)(str+i);
77+ }
78+}
79+
80+void pre_end_addr(int s6){
81+ int i,j;
82+ char str[7];
83+ // Cool down the system
84+ stop_music();
85+ // Resolve line and show it
86+ if (s6<0) s6=s6&0x7fffffff;
87+ g_label=s6;
88+ if (s6<65536) {
89+ // Line number
90+ printstr("\nIn line ");
91+ } else {
92+ // Label
93+ printstr("\nAfter label ");
94+ }
95+ printstr(resolve_label(s6));
96+ asm volatile("la $v0,%0"::"i"(&g_end_addr));
97+ asm volatile("lw $v0,0($v0)");
98+ asm volatile("nop");
99+ asm volatile("jr $v0");
100+}
101+
102+#define end_exec() \
103+ asm volatile("addu $a0,$s6,$zero");\
104+ asm volatile("j pre_end_addr")
105+
106+void err_break(void){
107+ stop_music();
108+ printstr(ERR_BREAK);
109+ end_exec();
110+}
111+
112+void err_data_not_found(void){
113+ printstr(ERR_DATA_NF);
114+ end_exec();
115+}
116+
117+void err_label_not_found(void){
118+ printstr(ERR_LABEL_NF);
119+ printstr(resolve_label(g_label));
120+ printstr("\n");
121+ end_exec();
122+}
123+
124+void err_div_zero(void){
125+ printstr(ERR_DIV_0);
126+ end_exec();
127+}
128+
129+void err_no_mem(void){
130+ printstr(ERR_NE_MEMORY);
131+ end_exec();
132+}
133+
134+void err_str_complex(void){
135+ printstr(ERR_STR_COMPLEX);
136+ end_exec();
137+}
138+
139+void err_unknown(void){
140+ asm volatile("la $v0,%0"::"i"(&g_temp));
141+ asm volatile("sw $ra,0($v0)");
142+ printstr(ERR_UNKNOWN);
143+ printhex32(g_temp);
144+ end_exec();
145+}
146+
147+void err_music(char* str){
148+ printstr(ERR_MUSIC);
149+ printstr(str);
150+ printstr("'\n");
151+ // Restore s6 from g_s6
152+ asm volatile("la $s6,%0"::"i"(&g_s6));
153+ asm volatile("lw $s6,0($s6)");
154+ end_exec();
155+}
156+
157+void err_unexp_next(void){
158+ printstr(ERR_UNEXP_NEXT);
159+ end_exec();
160+}
161+
162+void err_no_block(void){
163+ printstr(ERR_NO_BLOCK);
164+ end_exec();
165+}
166+
167+void err_invalid_param(void){
168+ printstr(ERR_INVALID_PARAM);
169+ end_exec();
170+}
171+
172+void err_file(void){
173+ printstr(ERR_FILE);
174+ end_exec();
175+}
176+
177+void err_wave(void){
178+ printstr(ERR_WAVE);
179+ end_exec();
180+}
181+
182+void err_not_obj(void){
183+ printstr(ERR_NOT_OBJ);
184+ end_exec();
185+}
186+
187+void err_not_field(int fieldname, int classname){
188+ printstr(resolve_label(classname));
189+ printchar('.');
190+ printstr(resolve_label(fieldname & 0x7FFFFFFF));
191+ printstr(ERR_NOT_FIELD);
192+ end_exec();
193+}
194+
195+void err_str(char* str){
196+ printstr(str);
197+ end_exec();
198+}
\ No newline at end of file
--- /dev/null
+++ b/mips/protozoa/exception.c
@@ -0,0 +1,170 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include <xc.h>
13+#include "api.h"
14+#include "main.h"
15+#include "compiler.h"
16+
17+/*
18+ Enable following line if memory dump is needed when exception occurs.
19+*/
20+
21+//#define DUMPFILE "~~MEMORY.DMP"
22+
23+#ifdef DUMPFILE
24+void dumpMemory(){
25+ unsigned int i;
26+ FSFILE *fp;
27+ printstr("\n"DUMPFILE" ");
28+ if(FSInit()==FALSE){
29+ printstr("cannot be created.\n");
30+ return;
31+ }
32+ fp=FSfopen(DUMPFILE,"w");
33+ if(fp==NULL) {
34+ printstr("not saved.\n");
35+ return;
36+ }
37+ for(i=0;i<PERSISTENT_RAM_SIZE;i+=512){
38+ if (FSfwrite(&RAM[i],1,512,fp)<512) break;
39+ }
40+ FSfclose(fp);
41+ printstr("saved.\n");
42+}
43+#else
44+void dumpMemory(){}
45+#endif //ifdef DUMPFILE
46+
47+void _general_exception_handler_main (void);
48+void _general_exception_handler (void){
49+ asm volatile("la $sp,%0"::"i"(&RAM[RAMSIZE-4]));
50+ asm volatile("j _general_exception_handler_main");
51+}
52+void _general_exception_handler_main (void){
53+ int i;
54+ // $v1 is g_ex_data
55+ asm volatile("la $v1,%0"::"i"(&g_ex_data[0]));
56+ // Prepare proper stack area before SoftReset
57+ asm volatile("addiu $sp,$v1,0xfff0");
58+ // g_ex_data[2]=$s6
59+ asm volatile("sw $s6,8($v1)");
60+ // g_ex_data[3]=Cause
61+ asm volatile("mfc0 $v0,$13");
62+ asm volatile("sw $v0,12($v1)");
63+ // g_ex_data[4]=EPC
64+ asm volatile("mfc0 $v0,$14");
65+ asm volatile("sw $v0,16($v1)");
66+ // Exception occured
67+ g_ex_data[0]=1;
68+ // g_s6
69+ g_ex_data[1]=g_s6;
70+ // Clear 2 MLB bits of EPC
71+ g_ex_data[4]&=0xfffffffc;
72+ // If EPC is within RAM, store data in exception area.
73+ if ((int)(&RAM[0])<=g_ex_data[4] && g_ex_data[4] <(int)(&RAM[RAMSIZE])) {
74+ // g_ex_data[5] - g_ex_data[12]: assembly
75+ for(i=-3;i<=3;i++){
76+ g_ex_data[i+8]=((int*)g_ex_data[4])[i];
77+ }
78+ }
79+ // Wait until all buttons are released and reset MachiKania.
80+ #ifdef __DEBUG
81+ asm volatile("j 0xBFC00000");
82+ #else
83+ for(i=0;i<100000;i++){
84+ if((readbuttons()&(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE))
85+ !=(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE)) i=0;
86+ }
87+ RCONbits.POR=0;
88+ RCONbits.EXTR=0;
89+ asm volatile("j 0x9FC00000");
90+ #endif
91+}
92+
93+void blue_screen(void){
94+ int i,j,s6,s6g;
95+ unsigned int* opos;
96+ if (RCONbits.POR || RCONbits.EXTR) {
97+ // After power on or reset. Reset flags and return.
98+ RCONbits.POR=0;
99+ RCONbits.EXTR=0;
100+ for(i=0;i<RAMSIZE;i++){
101+ // Reset all RAM area including g_ex_data[]
102+ RAM[i]=0;
103+ }
104+ return;
105+ } else if (g_ex_data[0]==0) {
106+ // No exception found.
107+ return;
108+ }
109+ // Exception occured before SoftReset().
110+ // Prepare data
111+ s6=g_ex_data[2];
112+ s6g=g_ex_data[1];
113+ s6=s6&0x7fffffff;
114+ s6g=s6g&0x7fffffff;
115+ opos=(int*)g_ex_data[4];
116+ //set_bgcolor(255,0,0);
117+ printstr("STOP");
118+ printstr("\nException at ");
119+ printhex32(g_ex_data[4]);
120+ printstr("\n Cause: ");
121+ printhex32(g_ex_data[3]);
122+ printstr("\n ");
123+ switch((g_ex_data[3]>>2)&0x1f){
124+ case 0: printstr("(Interrupt)"); break;
125+ case 1: printstr("(TLB modification)"); break;
126+ case 2: printstr("(TLB load/fetch)"); break;
127+ case 3: printstr("(TLB store)"); break;
128+ case 4: printstr("(Address load/fetch error )"); break;
129+ case 5: printstr("(Address store error)"); break;
130+ case 6: printstr("(Bus fetch error)"); break;
131+ case 7: printstr("(Bus load/store error)"); break;
132+ case 8: printstr("(Syscall)"); break;
133+ case 9: printstr("(Breakpoint)"); break;
134+ case 10: printstr("(Reserved instruction)"); break;
135+ case 11: printstr("(Coprocessor Unusable)"); break;
136+ case 12: printstr("(Integer Overflow)"); break;
137+ case 13: printstr("(Trap)"); break;
138+ case 23: printstr("(Reference to Watch address)"); break;
139+ case 24: printstr("(Machine check)"); break;
140+ default: printstr("(Unknown)"); break;
141+ }
142+ printstr("\n s6: ");
143+ printstr(resolve_label(s6));
144+ printstr("\n g_s6: ");
145+ printstr(resolve_label(s6g));
146+ printstr("\n");
147+ printstr("Reset MachiKania to contine.\n\n");
148+ // Show code where the exception happened.
149+ for(i=-3;i<=3;i++){
150+ printstr("\n ");
151+ printhex32((unsigned int)&opos[i]);
152+ printstr(" ");
153+ if ((unsigned int)&RAM[0]<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<(unsigned int)&RAM[RAMSIZE]) {
154+ // Exception in RAM[RAMSIZE] area
155+ printhex32(g_ex_data[i+8]);
156+ } else if ( 0xA0000000<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<0xA0000000+PIC32MX_RAMSIZE
157+ || 0x9D000000<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<=0x9D000000+PIC32MX_FLASHSIZE) {
158+ // Exception in outside RAM[RAMSIZE] or flash area
159+ printhex32(opos[i]);
160+ } else {
161+ printstr("********");
162+ }
163+ }
164+ printstr("\n");
165+
166+#ifndef __DEBUG
167+ dumpMemory();
168+#endif
169+ while(1) asm("wait");
170+}
--- /dev/null
+++ b/mips/protozoa/file.c
@@ -0,0 +1,275 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include <xc.h>
13+#include "api.h"
14+#include "compiler.h"
15+
16+static FSFILE* g_fhandle;
17+static char* g_fbuff;
18+static int g_size;
19+
20+char* init_file(char* buff,char* appname){
21+ // Open file
22+ g_fhandle=FSfopen(appname,"r");
23+ if (!g_fhandle) {
24+ return ERR_UNKNOWN;
25+ }
26+ // Initialize parameters
27+ g_fbuff=buff;
28+ g_line=0;
29+ g_fileline=0;
30+ g_source=buff;
31+ g_srcpos=0;
32+ return 0;
33+}
34+
35+void close_file(){
36+ FSfclose(g_fhandle);
37+}
38+
39+void read_file(int blocklen){
40+ int i;
41+ static char in_string, escape;
42+ // blocklen is either 512 or 256.
43+ if (blocklen==512) {
44+ // This is first read. Initialize parameter(s).
45+ in_string=0;
46+ escape=0;
47+ } else if (g_size<512) {
48+ // Already reached the end of file.
49+ return;
50+ } else {
51+ // Shift buffer and source position 256 bytes.
52+ for(i=0;i<256;i++) g_fbuff[i]=g_fbuff[i+256];
53+ g_srcpos-=256;
54+ }
55+ // Read 512 or 256 bytes from SD card.
56+ g_size=512-blocklen+FSfread((void*)&g_fbuff[512-blocklen],1,blocklen,g_fhandle);
57+ // Some modifications of text for easy compiling.
58+ for(i=512-blocklen;i<512;i++){
59+ if (in_string) {
60+ if (g_fbuff[i]=='\\' && !escape) {
61+ escape=1;
62+ } else {
63+ escape=0;
64+ if (g_fbuff[i]=='"') in_string=0;
65+ }
66+ } else {
67+ // If not in string, all upper cases.
68+ if (g_fbuff[i]=='"') in_string=1;
69+ else if ('a'<=g_fbuff[i] && g_fbuff[i]<='z') g_fbuff[i]+='A'-'a';
70+ // If not in string, tabs will be spaces.
71+ else if ('\t'==g_fbuff[i]) g_fbuff[i]=' ';
72+ }
73+ if (g_fbuff[i]==0x0a || g_fbuff[i]==0x0d) in_string=escape=0;
74+ }
75+ return;
76+}
77+
78+char* compile_file(){
79+ int i;
80+ char* err;
81+ // Read first 512 bytes
82+ read_file(512);
83+ // Compile line by line
84+ while (g_size==512) {
85+ err=compile_line();
86+ if (err) return err;
87+ // Maintain at least 256 characters in cache.
88+ if (256<=g_srcpos) read_file(256);
89+ }
90+ // Return code at the end
91+ g_source[g_size]=0x0d;
92+ // Compile last few lines.
93+ while(g_srcpos<g_size-1){
94+ err=compile_line();
95+ if (err) return err;
96+ }
97+ // Add "DATA 0" and "END" statements.
98+ if (g_compiling_class) {
99+ g_source="END\n";
100+ } else {
101+ g_source="DATA 0:END\n";
102+ }
103+ g_srcpos=0;
104+ err=compile_line();
105+ if (err) return err;
106+ g_srcpos=-1;
107+ // No error occured
108+ return 0;
109+}
110+
111+int compile_and_link_file(char* buff,char* appname){
112+ int i,j;
113+ char* err;
114+
115+ while(1){
116+ // Initialize SD card file system
117+ err=init_file(buff,appname);
118+ if (err) {
119+ //setcursorcolor(COLOR_ERRORTEXT);
120+ printstr("Can't Open ");
121+ printstr(appname);
122+ printchar('\n');
123+ return -1;
124+ }
125+
126+ // Option initialization(s)
127+ g_nolinenum=0;
128+
129+ // Compile the file
130+ err=compile_file();
131+ close_file();
132+
133+ // If compiling a class file is required, do it.
134+ if (err==ERR_COMPILE_CLASS) {
135+ j=g_compiling_class;
136+ i=compile_and_link_class(buff, g_class);
137+ g_compiling_class=j;
138+ if (i) return i;
139+ // Continue compiling current file from the beginning.
140+ continue;
141+ }
142+ break;
143+ }
144+
145+ if (err) {
146+ // Compile error
147+ printstr(err);
148+ printstr("\nAround: '");
149+ for(i=0;i<5;i++){
150+ printchar(g_source[g_srcpos-2+i]);
151+ }
152+ printstr("' in line ");
153+ printdec(g_line);
154+ printstr("\n");
155+ for(i=g_srcpos;0x20<=g_source[i];i++);
156+ g_source[i]=0x00;
157+ for(i=g_srcpos;0x20<=g_source[i];i--);
158+ printstr(g_source+i);
159+ return g_fileline;
160+ }
161+
162+ // Link
163+ err=link();
164+ if (err) {
165+ // Link error
166+ printstr(err);
167+ printstr(resolve_label(g_label));
168+ return -2;
169+ }
170+
171+ // All done
172+ return 0;
173+}
174+
175+int compile_and_link_class(char* buff,int class){
176+ int i,j;
177+ char* err;
178+ char* classname;
179+ char classfile[13];
180+ char classdir[11];
181+ int data[2];
182+ unsigned short cwd_id;
183+ int* record;
184+ while(1){
185+ // Begin compiling class
186+ err=begin_compiling_class(class);
187+ if (err) break;
188+ // Determine class file name
189+ classname=resolve_label(class);
190+ for(i=0;classfile[i]=classname[i];i++);
191+ classfile[i++]='.';
192+ classfile[i++]='B';
193+ classfile[i++]='A';
194+ classfile[i++]='S';
195+ classfile[i]=0;
196+ // Check if file exists in current directory
197+ err=init_file(buff,&classfile[0]);
198+ if (!err) {
199+ // Class file found in current directory
200+ close_file();
201+ // Compile it
202+ i=compile_and_link_file(buff,&classfile[0]);
203+ if (i) break;
204+ } else {
205+ // Class file not found in current directory.
206+ // Try library directory, for example, \LIB\CLASS1\CLASS1.BAS
207+ // Store current directory, first
208+ if (!FSgetcwd(buff,256)) break;
209+ for(i=0;buff[i];i++);
210+ cwd_id=cmpdata_get_id();
211+ if (!cwd_id) break;
212+ err=cmpdata_insert(CMPDATA_TEMP,cwd_id,(int*)(&buff[0]),(i+1+3)>>2);
213+ if (err) break;
214+ // Change current directory to class library directory
215+ for(i=0;classdir[i]="\\LIB\\"[i];i++);
216+ for(j=0;classdir[i++]=classname[j];j++);
217+ classdir[i]=0;
218+ FSchdir(classdir);
219+ // Compile class file
220+ i=compile_and_link_file(buff,&classfile[0]);
221+ // Restore current dirctory
222+ cmpdata_reset();
223+ while(record=cmpdata_find(CMPDATA_TEMP)){
224+ if (cwd_id=(record[0]&0xffff)) break;
225+ }
226+ if (!record) break;
227+ FSchdir((char*)(&record[1]));
228+ cmpdata_delete(record);
229+ if (i) break;
230+ }
231+ // End compiling class
232+ err=end_compiling_class(class);
233+ if (err) break;
234+ // Initial assembly is a jump statement to jump to the end of class file
235+ // Note that there is at least a code (set line # to $s6) before reaching here
236+ g_object[0]=0x08000000 | ((((int)(&g_object[g_objpos]))&0x0FFFFFFF)>>2); // j xxxxxxxx
237+ // In the next link, current region of object is ignored.
238+ g_object+=g_objpos;
239+ g_objpos=0;
240+ // All done
241+ return 0;
242+ }
243+ // Error occured
244+ printstr("/nError in class: ");
245+ printstr((char*)&classfile[0]);
246+ printchar('\n');
247+ if (err) printstr(err);
248+ return -2;
249+}
250+
251+int compile_and_link_main_file(char* buff,char* appname){
252+ int i;
253+ g_compiling_class=0;
254+ i=compile_and_link_file(buff,appname);
255+ if (i) return i;
256+ return 0;
257+ /*
258+ After compiling class code, g_object is set to the beginning of next code.
259+ Therefore, after the all, g_object is set toe the beginnig of main code,
260+ and class code(s) is/are excluded. This will affect following features when running:
261+ READ/DATA/RESTORE function/statements
262+ The linker also works withing the g_object dimension. Therefore, the label only works withing the file,
263+ but not in the other file. This feature allows using the same label name in different files without
264+ causing error/misjumping
265+
266+ After compiling class code, following cmpdata are destroyed (see delete_cmpdata_for_class() function):
267+ CMPDATA_FIELD : object field and method information
268+ CMPDATA_USEVAR : long var name information
269+ but following cmpdata remains:
270+ CMPDATA_CLASS : class name and address of class structure
271+ This feature allows compiler to use class information (name and structure) for "NEW" function,
272+ to use the same long var name in different files (note that g_long_name_var_num is not reseted after
273+ compiling each class code).
274+ */
275+}
\ No newline at end of file
--- /dev/null
+++ b/mips/protozoa/float.c
@@ -0,0 +1,171 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include "./compiler.h"
13+#include "stdlib.h"
14+
15+char* get_float_sub(int pr);
16+
17+char* get_simple_float(void){
18+ int i;
19+ float f;
20+ char* err;
21+ char b1,b2,b3;
22+ next_position();
23+ b1=g_source[g_srcpos];
24+ if (b1=='(') {
25+ // (...)
26+ // Parenthesis
27+ g_srcpos++;
28+ next_position();
29+ err=get_float_sub(priority(OP_VOID));
30+ if (err) return err;
31+ next_position();
32+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
33+ g_srcpos++;
34+ } else if (b1=='-') {
35+ // Unary '-' operator
36+ // Note that unary operators ( + and - ) have higher priority than the other operators
37+ g_srcpos++;
38+ err=get_simple_float();
39+ if (err) return err;
40+ check_obj_space(1);
41+ g_object[g_objpos++]=0x34040000; // ori a0,zero,0
42+ call_lib_code(LIB_FLOAT | OP_SUB);
43+ } else {
44+ // Main routine of getting float value here
45+ if (b1=='+') g_srcpos++; // Ignore unary '+' operator
46+ next_position();
47+ b1=g_source[g_srcpos];
48+ b2=g_source[g_srcpos+1];
49+ b3=g_source[g_srcpos+2];
50+ if ('0'<=b1 && b1<='9') {
51+ f=strtof((const char*)&g_source[g_srcpos],&err);
52+ if (&g_source[g_srcpos]==err) return ERR_SYNTAX;
53+ g_srcpos=err-g_source;
54+ i=((int*)(&f))[0];
55+ if (i&0xFFFF0000) {
56+ // 32 bit
57+ check_obj_space(2);
58+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
59+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
60+ } else {
61+ // 16 bit
62+ check_obj_space(1);
63+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
64+ }
65+ } else {
66+ i=get_var_number();
67+ if (i<0) {
68+ // Must be a function.
69+ return float_function();
70+ }
71+ if (g_source[g_srcpos]=='.') {
72+ // This is an object field or method to return string
73+ check_obj_space(1);
74+ g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
75+ g_srcpos++;
76+ return float_obj_field();
77+ } else if (g_source[g_srcpos]=='(') {
78+ // An array element contains pointer to an object.
79+ g_srcpos++;
80+ err=get_dim_value(i);
81+ if (err) return err;
82+ if (g_source[g_srcpos]!='.') return ERR_SYNTAX;
83+ g_srcpos++;
84+ return float_obj_field();
85+ }
86+ if (g_source[g_srcpos]!='#') return ERR_SYNTAX;
87+ g_srcpos++;
88+ if (g_source[g_srcpos]=='(') {
89+ // Dimension
90+ g_srcpos++;
91+ return get_dim_value(i);
92+ }
93+ // Simple value
94+ check_obj_space(1);
95+ g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
96+ }
97+ }
98+ // No error
99+ return 0;
100+}
101+
102+char* get_float_sub(int pr){
103+ char* err;
104+ enum operator op;
105+ char b1,b2,b3;
106+ int prevpos;
107+ // Get a value in $v0.
108+ err=get_simple_float();
109+ if (err) return err;
110+ while(1){
111+ // Get the operator in op. If not valid operator, simply return without error.
112+ prevpos=g_srcpos;
113+ err=get_floatOperator();
114+ if (err) return 0;
115+ op=g_last_op;
116+ // Compair current and previous operators.
117+ // If the previous operator has higher priolity, return.
118+ if (pr>=priority(op)) {
119+ g_srcpos=prevpos;
120+ return 0;
121+ }
122+ // Store $v0 in stack
123+ g_sdepth+=4;
124+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
125+ check_obj_space(1);
126+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
127+ // Get next value.
128+ err=get_float_sub(priority(op));
129+ if (err) return err;
130+ // Get value from stack to $a0.
131+ check_obj_space(1);
132+ g_object[g_objpos++]=0x8FA40000|g_sdepth; // lw a0,xx(sp)
133+ g_sdepth-=4;
134+ // Calculation. Result will be in $v0.
135+ err=calculation_float(op);
136+ if (err) return err;
137+ }
138+}
139+
140+char* get_float(){
141+ // Note that this can be called recursively.
142+ // Value may contain function with a parameter of another value.
143+ char* err;
144+ int prevpos;
145+ if (g_sdepth==0) {
146+ // Initialize stack handler
147+ g_maxsdepth=0;
148+ prevpos=g_objpos;
149+ // Stack decrement command will be filled later
150+ check_obj_space(1);
151+ g_object[g_objpos++]=0x00000000; // nop (will be replaced by "addiu sp,sp,-xx")
152+ }
153+ err=get_float_sub(priority(OP_VOID));
154+ if (err) return err;
155+ if (g_sdepth==0) {
156+ if (g_maxsdepth==0) {
157+ // Stack was not used.
158+ if (g_allow_shift_obj) {
159+ shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
160+ g_objpos--;
161+ }
162+ } else {
163+ // Stack was used.
164+ check_obj_space(1);
165+ g_object[prevpos]=0x27BD0000 | (0-g_maxsdepth) & 0x0000FFFF; // addiu sp,sp,-xx
166+ g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx
167+ }
168+ }
169+ g_lastvar=VAR_FLOAT;
170+ return 0;
171+}
\ No newline at end of file
--- /dev/null
+++ b/mips/protozoa/function.c
@@ -0,0 +1,625 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include "compiler.h"
13+#include "api.h"
14+
15+char* music_function(){
16+ char* err;
17+ next_position();
18+ if (g_source[g_srcpos]==')') {
19+ check_obj_space(1);
20+ g_object[g_objpos++]=0x34020003; //ori v0,zero,0x03
21+ } else {
22+ err=get_value();
23+ if (err) return err;
24+ }
25+ call_lib_code(LIB_MUSICFUNC);
26+ return 0;
27+}
28+
29+char* read_function(){
30+ // This function is not valid in class file.
31+ if (g_compiling_class) return ERR_INVALID_CLASS;
32+ call_lib_code(LIB_READ);
33+ return 0;
34+}
35+
36+char* cread_function(){
37+ call_lib_code(LIB_CREAD);
38+ return 0;
39+}
40+
41+char* gosub_function(){
42+ // Check if garbage collection has been done.
43+ // This check is required because the used temporary area would be changed
44+ // in sub routine.
45+ if (g_temp_area_used) return ERR_GOSUB_ASH;
46+ return gosub_statement();
47+}
48+char* strncmp_function(){
49+ char* err;
50+ err=get_string();
51+ if (err) return err;
52+ check_obj_space(2);
53+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
54+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
55+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
56+ g_srcpos++;
57+ err=get_string();
58+ if (err) return err;
59+ check_obj_space(1);
60+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
61+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
62+ g_srcpos++;
63+ err=get_value();
64+ if (err) return err;
65+ call_lib_code(LIB_STRNCMP);
66+ check_obj_space(1);
67+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
68+ return 0;
69+}
70+char* len_function(){
71+ char* err;
72+ err=get_string();
73+ if (err) return err;
74+ check_obj_space(5);
75+ g_object[g_objpos++]=0x2443FFFF; // addiu v1,v0,-1
76+ // loop:
77+ g_object[g_objpos++]=0x80640001; // lb a0,1(v1)
78+ g_object[g_objpos++]=0x1480FFFE; // bne a0,zero,loop
79+ g_object[g_objpos++]=0x24630001; // addiu v1,v1,1
80+ g_object[g_objpos++]=0x00621023; // subu v0,v1,v0
81+ return 0;
82+}
83+
84+char* asc_function(){
85+ char* err;
86+ err=get_string();
87+ if (err) return err;
88+ check_obj_space(1);
89+ g_object[g_objpos++]=0x90420000; // lbu v0,0(v0)
90+ return 0;
91+}
92+
93+char* val_function(){
94+ char* err;
95+ err=get_string();
96+ if (err) return err;
97+ call_lib_code(LIB_VAL);
98+ return 0;
99+}
100+
101+char* peek_function_sub(int bits){
102+ char* err;
103+ err=get_value();
104+ if (err) return err;
105+ check_obj_space(1);
106+ switch(bits){
107+ case 32:
108+ g_object[g_objpos++]=0x8C420000; // lw v0,0(v0)
109+ break;
110+ case 16:
111+ g_object[g_objpos++]=0x94420000; // lhu v0,0(v0)
112+ break;
113+ case 8:
114+ default:
115+ g_object[g_objpos++]=0x90420000; // lbu v0,0(v0)
116+ break;
117+ }
118+ return 0;
119+}
120+
121+char* sgn_function(){
122+ char* err;
123+ err=get_value();
124+ if (err) return err;
125+ check_obj_space(5);
126+ g_object[g_objpos++]=0x10400004; // beq v0,zero,end
127+ g_object[g_objpos++]=0x24030001; // addiu v1,zero,1
128+ g_object[g_objpos++]=0x1C400002; // bgtz v0,end
129+ g_object[g_objpos++]=0x00601021; // addu v0,v1,zero
130+ g_object[g_objpos++]=0x00031023; // subu v0,zero,v1
131+ // end:
132+ return 0;
133+}
134+
135+char* abs_function(){
136+ char* err;
137+ err=get_value();
138+ if (err) return err;
139+ check_obj_space(3);
140+ g_object[g_objpos++]=0x00021FC3; //sra v1,v0,0x1f
141+ g_object[g_objpos++]=0x00621026; //xor v0,v1,v0
142+ g_object[g_objpos++]=0x00431023; //subu v0,v0,v1
143+ return 0;
144+}
145+
146+char* not_function(){
147+ char* err;
148+ err=get_value();
149+ if (err) return err;
150+ check_obj_space(1);
151+ g_object[g_objpos++]=0x2C420001; //sltiu v0,v0,1
152+ return 0;
153+}
154+
155+char* rnd_function(){
156+ call_lib_code(LIB_RND);
157+ return 0;
158+}
159+
160+char* chr_function(void){
161+ char* err;
162+ err=get_value();
163+ if (err) return err;
164+ call_lib_code(LIB_CHR);
165+ return 0;
166+}
167+char* hex_function(void){
168+ char* err;
169+ err=get_value();
170+ if (err) return err;
171+ if (g_source[g_srcpos]==',') {
172+ // Second argument found.
173+ // Get is as $a0.
174+ g_srcpos++;
175+ check_obj_space(2);
176+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
177+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
178+ err=get_value();
179+ if (err) return err;
180+ check_obj_space(3);
181+ g_object[g_objpos++]=0x00022021; //a0,zero,v0
182+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
183+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
184+ } else {
185+ // Second argument not found.
186+ // Set $a0 to 0.
187+ check_obj_space(1);
188+ g_object[g_objpos++]=0x24040000; //addiu a0,zero,0
189+ }
190+ call_lib_code(LIB_HEX);
191+ return 0;
192+}
193+
194+char* dec_function(void){
195+ char* err;
196+ err=get_value();
197+ if (err) return err;
198+ call_lib_code(LIB_DEC);
199+ return 0;
200+}
201+
202+char* keys_function(void){
203+ char* err;
204+ next_position();
205+ if (g_source[g_srcpos]==')') {
206+ check_obj_space(1);
207+ g_object[g_objpos++]=0x3402003F; //ori v0,zero,0x3f
208+ } else {
209+ err=get_value();
210+ if (err) return err;
211+ }
212+ call_lib_code(LIB_KEYS);
213+ return 0;
214+}
215+
216+char* tvram_function(void){
217+ char* err;
218+ int i;
219+ next_position();
220+ if (g_source[g_srcpos]==')') {
221+ i=(int)(&TVRAM[0]);
222+ i-=g_gp;
223+ check_obj_space(1);
224+ g_object[g_objpos++]=0x27820000|(i&0x0000FFFF); // addiu v0,gp,xxxx
225+ } else {
226+ err=get_value();
227+ if (err) return err;
228+ i=(int)(&TVRAM[0]);
229+ i-=g_gp;
230+ check_obj_space(3);
231+ g_object[g_objpos++]=0x27830000|(i&0x0000FFFF); // addiu v1,gp,xxxx
232+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
233+ g_object[g_objpos++]=0x90620000; // lbu v0,0(v1)
234+ }
235+ return 0;
236+}
237+
238+char* drawcount_function(void){
239+ call_lib_code(LIB_DRAWCOUNT);
240+ return 0;
241+}
242+
243+char* input_function(void){
244+ call_lib_code(LIB_INPUT);
245+ return 0;
246+}
247+
248+char* inkey_function(void){
249+ char* err;
250+ next_position();
251+ if (g_source[g_srcpos]==')') {
252+ check_obj_space(1);
253+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x00
254+ } else {
255+ err=get_value();
256+ if (err) return err;
257+ }
258+ call_lib_code(LIB_INKEY);
259+ return 0;
260+}
261+
262+char* args_function(void){
263+ return args_function_main();
264+}
265+
266+char* system_function(void){
267+ char* err;
268+ err=get_value();
269+ if (err) return err;
270+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
271+ call_lib_code(LIB_SYSTEM);
272+ return 0;
273+}
274+
275+char* sprintf_function(void){
276+ char* err;
277+ err=get_string();
278+ if (err) return err;
279+ next_position();
280+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
281+ g_srcpos++;
282+ check_obj_space(2);
283+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
284+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
285+ err=get_float();
286+ if (err) return err;
287+ check_obj_space(3);
288+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
289+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
290+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
291+ call_lib_code(LIB_SPRINTF);
292+ return 0;
293+}
294+
295+char* floatstr_function(void){
296+ char* err;
297+ err=get_float();
298+ if (err) return err;
299+ check_obj_space(2);
300+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
301+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x0000
302+ call_lib_code(LIB_SPRINTF);
303+ return 0;
304+}
305+
306+char* floatsharp_function(void){
307+ char* err;
308+ err=get_value();
309+ if (err) return err;
310+ call_lib_code(LIB_FLOATFUNCS | FUNC_FLOAT);
311+ return 0;
312+}
313+
314+char* valsharp_function(void){
315+ char* err;
316+ err=get_string();
317+ if (err) return err;
318+ call_lib_code(LIB_FLOATFUNCS | FUNC_VALSHARP);
319+ return 0;
320+}
321+
322+char* int_function(void){
323+ char* err;
324+ err=get_float();
325+ if (err) return err;
326+ call_lib_code(LIB_FLOATFUNCS | FUNC_INT);
327+ return 0;
328+}
329+
330+char* fseek_function(){
331+ call_lib_code(LIB_FILE | FUNC_FTELL);
332+ return 0;
333+}
334+
335+char* flen_function(){
336+ call_lib_code(LIB_FILE | FUNC_FLEN);
337+ return 0;
338+}
339+
340+char* fgetc_function(){
341+ call_lib_code(LIB_FILE | FUNC_FGETC);
342+ return 0;
343+}
344+
345+char* finput_function(){
346+ char* err;
347+ next_position();
348+ if (g_source[g_srcpos]!=')') {
349+ err=get_value();
350+ if (err) return err;
351+ } else {
352+ // Parameter will be zero if not defined
353+ check_obj_space(1);
354+ g_object[g_objpos++]=0x34020000; // ori v0,zero,0
355+ }
356+ call_lib_code(LIB_FILE | FUNC_FINPUT);
357+ return 0;
358+}
359+
360+char* feof_function(){
361+ call_lib_code(LIB_FILE | FUNC_FEOF);
362+ return 0;
363+}
364+
365+char* playwave_function(){
366+ char* err;
367+ next_position();
368+ if (g_source[g_srcpos]!=')') {
369+ // Get param
370+ err=get_value();
371+ if (err) return err;
372+ } else {
373+ // If parameter is omitted, use 0.
374+ check_obj_space(1);
375+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
376+ }
377+ call_lib_code(LIB_PLAYWAVEFUNC);
378+ return 0;
379+}
380+
381+char* setdir_function(){
382+ char* err;
383+ err=get_string();
384+ if (err) return err;
385+ call_lib_code(LIB_SETDIRFUNC);
386+ return 0;
387+}
388+
389+char* getdir_function(){
390+ call_lib_code(LIB_GETDIR);
391+ return 0;
392+}
393+
394+char* float_constant(float val){
395+ volatile int i;
396+ ((float*)(&i))[0]=val;
397+ if (i&0xFFFF0000) {
398+ // 32 bit
399+ check_obj_space(2);
400+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
401+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
402+ } else {
403+ // 16 bit
404+ check_obj_space(1);
405+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
406+ }
407+ return 0;
408+}
409+
410+char* float_1param_function(enum functions func){
411+ char* err;
412+ err=get_float();
413+ if (err) return err;
414+ call_lib_code(LIB_FLOATFUNCS | func);
415+ return 0;
416+}
417+
418+char* float_2param_function(enum functions func){
419+ char* err;
420+ err=get_float();
421+ if (err) return err;
422+ next_position();
423+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
424+ g_srcpos++;
425+ check_obj_space(2);
426+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
427+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
428+ err=get_float();
429+ if (err) return err;
430+ check_obj_space(3);
431+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
432+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
433+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
434+ call_lib_code(LIB_FLOATFUNCS | func);
435+ return 0;
436+}
437+
438+char* float_function(void){
439+ char* err;
440+ if (nextCodeIs("FLOAT#(")) {
441+ err=floatsharp_function();
442+ } else if (nextCodeIs("VAL#(")) {
443+ err=valsharp_function();
444+ } else if (nextCodeIs("SIN#(")) {
445+ err=float_1param_function(FUNC_SIN);
446+ } else if (nextCodeIs("COS#(")) {
447+ err=float_1param_function(FUNC_COS);
448+ } else if (nextCodeIs("TAN#(")) {
449+ err=float_1param_function(FUNC_TAN);
450+ } else if (nextCodeIs("ASIN#(")) {
451+ err=float_1param_function(FUNC_ASIN);
452+ } else if (nextCodeIs("ACOS#(")) {
453+ err=float_1param_function(FUNC_ACOS);
454+ } else if (nextCodeIs("ATAN#(")) {
455+ err=float_1param_function(FUNC_ATAN);
456+ } else if (nextCodeIs("ATAN2#(")) {
457+ err=float_2param_function(FUNC_ATAN2);
458+ } else if (nextCodeIs("SINH#(")) {
459+ err=float_1param_function(FUNC_SINH);
460+ } else if (nextCodeIs("COSH#(")) {
461+ err=float_1param_function(FUNC_COSH);
462+ } else if (nextCodeIs("TANH#(")) {
463+ err=float_1param_function(FUNC_TANH);
464+ } else if (nextCodeIs("EXP#(")) {
465+ err=float_1param_function(FUNC_EXP);
466+ } else if (nextCodeIs("LOG#(")) {
467+ err=float_1param_function(FUNC_LOG);
468+ } else if (nextCodeIs("LOG10#(")) {
469+ err=float_1param_function(FUNC_LOG10);
470+ } else if (nextCodeIs("POW#(")) {
471+ err=float_2param_function(FUNC_POW);
472+ } else if (nextCodeIs("SQRT#(")) {
473+ err=float_1param_function(FUNC_SQRT);
474+ } else if (nextCodeIs("CEIL#(")) {
475+ err=float_1param_function(FUNC_CEIL);
476+ } else if (nextCodeIs("FLOOR#(")) {
477+ err=float_1param_function(FUNC_FLOOR);
478+ } else if (nextCodeIs("FABS#(")) {
479+ err=float_1param_function(FUNC_FABS);
480+ } else if (nextCodeIs("MODF#(")) {
481+ err=float_1param_function(FUNC_MODF);
482+ } else if (nextCodeIs("FMOD#(")) {
483+ err=float_2param_function(FUNC_FMOD);
484+ } else if (nextCodeIs("GOSUB#(")) {
485+ err=gosub_function();
486+ } else if (nextCodeIs("ARGS#(")) {
487+ err=args_function();
488+ } else if (nextCodeIs("PI#")) {
489+ return float_constant(3.141593);
490+ } else {
491+ // Check if static method of a class
492+ err=static_method('#');
493+ //return ERR_SYNTAX;
494+ }
495+ if (err) return err;
496+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
497+ g_srcpos++;
498+ return 0;
499+}
500+
501+static const void* str_func_list[]={
502+ "CHR$(",chr_function,
503+ "HEX$(",hex_function,
504+ "DEC$(",dec_function,
505+ "INPUT$(",input_function,
506+ "GOSUB$(",gosub_function,
507+ "ARGS$(",args_function,
508+ "READ$(",read_function,
509+ "SPRINTF$(",sprintf_function,
510+ "FLOAT$(",floatstr_function,
511+ "SYSTEM$(",system_function,
512+ "FINPUT$(",finput_function,
513+ "GETDIR$(",getdir_function,
514+ // Additional functions follow
515+ ADDITIONAL_STR_FUNCTIONS
516+};
517+
518+char* str_function(void){
519+ char* err;
520+ int i;
521+ char* (*f)();
522+ // Seek the function
523+ for (i=0;i<sizeof(str_func_list)/sizeof(str_func_list[0]);i+=2){
524+ if (nextCodeIs((char*)str_func_list[i])) break;
525+ }
526+ if (i<sizeof(str_func_list)/sizeof(str_func_list[0])) {
527+ // Function found. Call it.
528+ f=str_func_list[i+1];
529+ err=f();
530+ } else {
531+ // Check if static method of a class
532+ err=static_method('$');
533+ //return ERR_SYNTAX;
534+ }
535+ if (err) return err;
536+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
537+ g_srcpos++;
538+ return 0;
539+}
540+
541+// Aliases follow
542+
543+char* peek_function(){
544+ return peek_function_sub(8);
545+}
546+
547+char* peek16_function(){
548+ return peek_function_sub(16);
549+}
550+
551+char* peek32_function(){
552+ return peek_function_sub(32);
553+}
554+
555+char* gcolor_function(){
556+ return graphic_statement(FUNC_GCOLOR);
557+}
558+
559+char* fopen_function(){
560+ return fopen_statement_main(FUNC_FOPEN);
561+}
562+
563+static const void* int_func_list[]={
564+ "NOT(",not_function,
565+ "DRAWCOUNT(",drawcount_function,
566+ "MUSIC(",music_function,
567+ "TVRAM(",tvram_function,
568+ "KEYS(",keys_function,
569+ "READ(",read_function,
570+ "CREAD(",cread_function,
571+ "GOSUB(",gosub_function,
572+ "STRNCMP(",strncmp_function,
573+ "PEEK(",peek_function,
574+ "PEEK16(",peek16_function,
575+ "PEEK32(",peek32_function,
576+ "LEN(",len_function,
577+ "ASC(",asc_function,
578+ "SGN(",sgn_function,
579+ "ABS(",abs_function,
580+ "RND(",rnd_function,
581+ "VAL(",val_function,
582+ "INKEY(",inkey_function,
583+ "ARGS(",args_function,
584+ "SYSTEM(",system_function,
585+ "INT(",int_function,
586+ "GCOLOR(",gcolor_function,
587+ "FOPEN(",fopen_function,
588+ "FSEEK(",fseek_function,
589+ "FLEN(",flen_function,
590+ "FGET(",fget_statement,
591+ "FPUT(",fput_statement,
592+ "FGETC(",fgetc_function,
593+ "FPUTC(",fputc_statement,
594+ "FREMOVE(",fremove_statement,
595+ "FEOF(",feof_function,
596+ "PLAYWAVE(",playwave_function,
597+ "NEW(",new_function,
598+ "SETDIR(",setdir_function,
599+ "TIMER(",timer_function,
600+ // Additional functions follow
601+ ADDITIONAL_INT_FUNCTIONS
602+};
603+
604+char* function(void){
605+ char* err;
606+ int i;
607+ char* (*f)();
608+ // Seek the function
609+ for (i=0;i<sizeof(int_func_list)/sizeof(int_func_list[0]);i+=2){
610+ if (nextCodeIs((char*)int_func_list[i])) break;
611+ }
612+ if (i<sizeof(int_func_list)/sizeof(int_func_list[0])) {
613+ // Function found. Call it.
614+ f=int_func_list[i+1];
615+ err=f();
616+ } else {
617+ // Check if static method of a class
618+ err=static_method(0);
619+ //return ERR_SYNTAX;
620+ }
621+ if (err) return err;
622+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
623+ g_srcpos++;
624+ return 0;
625+}
--- /dev/null
+++ b/mips/protozoa/globalvars.c
@@ -0,0 +1,95 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include "compiler.h"
13+#include "main.h"
14+
15+// Contain the valus of $gp and $s6 (GPR of MIPS32)
16+int g_gp;
17+int g_s6;
18+
19+// Line data when compiling
20+int g_line;
21+int g_fileline;
22+
23+// Contain the address to which return in "END" statement.
24+int g_end_addr;
25+
26+// Following vars are used in value.c and string.c.
27+// These define the depth of stack pointer used for
28+// handling values and strings.
29+int g_sdepth;
30+int g_maxsdepth;
31+char g_allow_shift_obj;
32+
33+// Following var shows what type of variable was defined
34+// in compiling the last code.
35+enum variable g_lastvar;
36+
37+// Vars used for handling constant integer
38+int g_intconst;
39+char g_valueisconst;
40+
41+// Global vars associated to RAM
42+char* g_source;
43+int g_srcpos;
44+int* g_object;
45+int g_objpos;
46+int* g_objmax;
47+char RAM[RAMSIZE] __attribute__((persistent,address(0xA0000000+PIC32MX_RAMSIZE-PERSISTENT_RAM_SIZE)));
48+unsigned int g_ex_data[EXCEPTION_DATA_SIZE/4] __attribute__((persistent,address(0xA0000000+PIC32MX_RAMSIZE-EXCEPTION_DATA_SIZE)));
49+
50+// Global area for vars A-Z and three temporary string pointers
51+int g_var_mem[ALLOC_BLOCK_NUM];
52+unsigned short g_var_pointer[ALLOC_BLOCK_NUM];
53+unsigned short g_var_size[ALLOC_BLOCK_NUM];
54+
55+// Flag to use temporary area when compiling
56+char g_temp_area_used;
57+
58+// Flag to use option nolinenum
59+char g_nolinenum;
60+
61+// Heap area
62+int* g_heap_mem;
63+int g_max_mem;
64+
65+// Random seed
66+unsigned int g_rnd_seed;
67+
68+// Enable/disable Break keys
69+char g_disable_break;
70+
71+// Font data used for PCG
72+unsigned char* g_pcg_font;
73+
74+// Use or do not use graphic
75+char g_use_graphic;
76+
77+// Pointer to graphic RAM
78+unsigned short* g_graphic_area;
79+
80+// Parameter-containing block used for library
81+int* g_libparams;
82+
83+// Number of long name variables
84+int g_long_name_var_num;
85+
86+// Flag for active music/sound/wave function
87+char g_music_active;
88+
89+// Class name being compiled
90+int g_class;
91+// Flag to compile class file
92+int g_compiling_class;
93+
94+// General purpose integer used for asigning value with pointer
95+int g_temp;
--- /dev/null
+++ b/mips/protozoa/interface/LCDdriver.c
@@ -0,0 +1,176 @@
1+/*
2+ * 液晶モジュールドライバ for PIC32MX1xx/2xx
3+ * システムクロック48MHz、周辺クロック48MHz
4+ *
5+ * 液晶モジュールの初期化はブートローダ側で行うため不要
6+ *
7+ * 8bit mode接続
8+ * D8 RB0
9+ * D9 RB1
10+ * D10 RB2
11+ * D11 RB3
12+ * D12 RB4
13+ * D13 RB5
14+ * D14 RB7
15+ * D15 RB8
16+ * RS RB9
17+ * WR RB10
18+ * CS RB11
19+ * RD RB13
20+ * RESET RB14
21+ */
22+
23+#include <plib.h>
24+#include "LCDdriver.h"
25+
26+void inline LCD_set_dat(unsigned char c){
27+ LCD_DATCLR=LCD_DAT_MASK;
28+ LCD_DATSET=((c<<1)&0x180)+(c&0x3f);
29+}
30+unsigned char LCD_get_dat(void){
31+ unsigned short d;
32+ d=PORTB & LCD_DAT_MASK;
33+ return ((d&0x180)>>1)+(d&0x3f);
34+}
35+void LCD_WriteIndex(unsigned char index){
36+// Write Index
37+ LCD_RS_LO;
38+ LCD_set_dat(0);
39+ LCD_WR_LO;
40+ asm("nop");
41+ LCD_WR_HI;
42+ LCD_set_dat(index);
43+ LCD_WR_LO;
44+ asm("nop");
45+ LCD_WR_HI;
46+}
47+
48+void LCD_WriteData(unsigned short data)
49+{
50+// Write Data
51+ LCD_RS_HI;
52+ LCD_set_dat(data>>8);
53+ LCD_WR_LO;
54+ asm("nop");
55+ LCD_WR_HI;
56+ LCD_set_dat((unsigned char)data);
57+ LCD_WR_LO;
58+ asm("nop");
59+ LCD_WR_HI;
60+}
61+unsigned short LCD_ReadData(void)
62+{
63+// Read Data
64+ unsigned short d;
65+ TRISBSET=LCD_DAT_MASK;
66+ LCD_RS_HI;
67+ LCD_RD_LO;
68+ asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
69+ asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
70+ asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
71+ d=LCD_get_dat();
72+ LCD_RD_HI;
73+ asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
74+ asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
75+ LCD_RD_LO;
76+ asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
77+ asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
78+ asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
79+ d=(d<<8)+LCD_get_dat();
80+ LCD_RD_HI;
81+ asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
82+ TRISBCLR=LCD_DAT_MASK;
83+ return d;
84+}
85+void LCD_WriteReg(unsigned char index, unsigned short data)
86+{
87+// Write Index
88+ LCD_WriteIndex(index);
89+
90+// Write Data
91+ LCD_WriteData(data);
92+}
93+unsigned short LCD_ReadReg(unsigned char index)
94+{
95+// Write Index
96+ LCD_WriteIndex(index);
97+
98+// Read Data
99+ return LCD_ReadData();
100+}
101+
102+void LCD_SetCursor(unsigned short x, unsigned short y)
103+{
104+#if LCD_ALIGNMENT == VERTICAL
105+ LCD_WriteReg(0x20, x);
106+ LCD_WriteReg(0x21, y);
107+#elif LCD_ALIGNMENT == HORIZONTAL
108+ LCD_WriteReg(0x20, y);
109+ LCD_WriteReg(0x21, x);
110+#endif
111+}
112+
113+void LCD_continuous_output(unsigned short x,unsigned short y,unsigned short color,int n)
114+{
115+ //High speed continuous output
116+ int i;
117+ unsigned char d1,d2;
118+ LCD_SetCursor(x,y);
119+ LCD_WriteIndex(0x22);
120+ LCD_RS_HI;
121+ d1=color>>8;
122+ d2=(unsigned char)color;
123+ for (i=0; i < n ; i++){
124+ LCD_set_dat(d1);
125+ LCD_WR_LO;
126+ asm("nop");
127+ LCD_WR_HI;
128+ LCD_set_dat(d2);
129+ LCD_WR_LO;
130+ asm("nop");
131+ LCD_WR_HI;
132+ }
133+}
134+void LCD_Clear(unsigned short color)
135+{
136+ LCD_continuous_output(0,0,color,X_RES*Y_RES);
137+}
138+
139+void drawPixel(unsigned short x, unsigned short y, unsigned short color)
140+{
141+ LCD_SetCursor(x,y);
142+ LCD_WriteIndex(0x22);
143+ LCD_WriteData(color);
144+}
145+
146+unsigned short getColor(unsigned short x, unsigned short y)
147+{
148+ unsigned short d;
149+ LCD_SetCursor(x,y);
150+ LCD_WriteIndex(0x22);
151+ LCD_ReadData(); //dummy read
152+ d=LCD_ReadData();
153+ return (d>>11)+(d&0x7e0)+((d&0x1f)<<11); //swap R and B
154+}
155+
156+void LCD_set_Vertical(void){
157+ if(LCD_ReadReg(0)==0x0129){
158+ LCD_WriteReg(0x01, 0x0127);
159+ LCD_WriteReg(0x03, 0x1030);
160+ }
161+ else{
162+ LCD_WriteReg(0x01, 0x0100);
163+ LCD_WriteReg(0x03, 0x1030);
164+ }
165+}
166+
167+void LCD_set_Horizontal(void){
168+ if(LCD_ReadReg(0)==0x0129){
169+ LCD_WriteReg(0x01, 0x0027);
170+ LCD_WriteReg(0x03, 0x1028);
171+ }
172+ else{
173+ LCD_WriteReg(0x01, 0x0000);
174+ LCD_WriteReg(0x03, 0x1028);
175+ }
176+}
--- /dev/null
+++ b/mips/protozoa/interface/LCDdriver.h
@@ -0,0 +1,36 @@
1+#define VERTICAL 0
2+#define HORIZONTAL 1
3+//#define LCD_ALIGNMENT VERTICAL
4+#define LCD_ALIGNMENT HORIZONTAL
5+
6+#if LCD_ALIGNMENT == VERTICAL
7+ #define X_RES 240 // 横方向解像度
8+ #define Y_RES 320 // 縦方向解像度
9+#else
10+ #define X_RES 320 // 横方向解像度
11+ #define Y_RES 240 // 縦方向解像度
12+#endif
13+
14+#define LCD_DAT_MASK 0x01bf
15+#define LCD_DATCLR LATBCLR
16+#define LCD_DATSET LATBSET
17+#define LCD_RS_LO LATBCLR=0x200
18+#define LCD_RS_HI LATBSET=0x200
19+#define LCD_CS_LO LATBCLR=0x800
20+#define LCD_CS_HI LATBSET=0x800
21+#define LCD_WR_LO LATBCLR=0x400
22+#define LCD_WR_HI LATBSET=0x400
23+#define LCD_RD_LO LATBCLR=0x2000
24+#define LCD_RD_HI LATBSET=0x2000
25+#define LCD_RESET_LO LATBCLR=0x4000
26+#define LCD_RESET_HI LATBSET=0x4000
27+
28+void LCD_WriteIndex(unsigned char index);
29+void LCD_WriteData(unsigned short data);
30+unsigned short LCD_ReadData(void);
31+void LCD_Init(void);
32+void LCD_SetCursor(unsigned short x, unsigned short y);
33+void LCD_Clear(unsigned short color);
34+void drawPixel(unsigned short x, unsigned short y, unsigned short color);
35+void LCD_set_Vertical(void);
36+void LCD_set_Horizontal(void);
--- /dev/null
+++ b/mips/protozoa/interface/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/protozoa/interface/graphlib.c
@@ -0,0 +1,894 @@
1+//カラーグラフィックライブラリ
2+
3+#include <plib.h>
4+#include "videoout.h"
5+#include "LCDdriver.h"
6+
7+//unsigned char TVRAM[WIDTH_X*WIDTH_Y*2+1] __attribute__ ((aligned (4)));
8+unsigned char TVRAM[WIDTH_X2*WIDTH_Y*2+1] __attribute__ ((aligned (4)));
9+unsigned char *fontp; //フォント格納アドレス、初期化時はFontData、RAM指定することでPCGを実現
10+unsigned int bgcolor; // バックグランドカラー
11+unsigned char twidth; //テキスト1行文字数(30 or 40)
12+unsigned char graphmode; //テキストモード時 0、グラフィックモード時 0以外
13+
14+unsigned short palette[256];
15+const unsigned char __attribute__((weak)) FontData[256*8]={
16+//フォントデータ、キャラクタコード順に8バイトずつ、上位ビットが左
17+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
18+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
19+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
20+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
21+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
22+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
23+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
24+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
25+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
26+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
27+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
28+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
29+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
30+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
31+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
32+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
33+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
34+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
35+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
36+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
37+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
38+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
39+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
40+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
41+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
42+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
43+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
44+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
45+ 0x00,0x08,0x0C,0xFE,0xFE,0x0C,0x08,0x00,
46+ 0x00,0x20,0x60,0xFE,0xFE,0x60,0x20,0x00,
47+ 0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x00,
48+ 0x00,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,
49+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
50+ 0x30,0x30,0x30,0x30,0x00,0x00,0x30,0x00,
51+ 0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,
52+ 0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00,
53+ 0x18,0x7E,0xD8,0x7E,0x1A,0xFE,0x18,0x00,
54+ 0xE0,0xE6,0x0C,0x18,0x30,0x6E,0xCE,0x00,
55+ 0x78,0xCC,0xD8,0x70,0xDE,0xCC,0x76,0x00,
56+ 0x0C,0x18,0x30,0x00,0x00,0x00,0x00,0x00,
57+ 0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00,
58+ 0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00,
59+ 0xD6,0x7C,0x38,0xFE,0x38,0x7C,0xD6,0x00,
60+ 0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00,
61+ 0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60,
62+ 0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,
63+ 0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x00,
64+ 0x00,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,
65+ 0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,
66+ 0x18,0x38,0x78,0x18,0x18,0x18,0x7E,0x00,
67+ 0x7C,0xC6,0x06,0x1C,0x70,0xC0,0xFE,0x00,
68+ 0x7C,0xC6,0x06,0x3C,0x06,0xC6,0x7C,0x00,
69+ 0x0C,0x1C,0x3C,0x6C,0xFE,0x0C,0x0C,0x00,
70+ 0xFE,0xC0,0xF8,0x0C,0x06,0xCC,0x78,0x00,
71+ 0x3C,0x60,0xC0,0xFC,0xC6,0xC6,0x7C,0x00,
72+ 0xFE,0xC6,0x0C,0x18,0x30,0x30,0x30,0x00,
73+ 0x7C,0xC6,0xC6,0x7C,0xC6,0xC6,0x7C,0x00,
74+ 0x7C,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00,
75+ 0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,
76+ 0x00,0x30,0x00,0x00,0x00,0x30,0x30,0x60,
77+ 0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,
78+ 0x00,0x00,0xFE,0x00,0xFE,0x00,0x00,0x00,
79+ 0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00,
80+ 0x7C,0xC6,0x06,0x1C,0x30,0x00,0x30,0x00,
81+ 0x3C,0x66,0xDE,0xF6,0xDC,0x60,0x3E,0x00,
82+ 0x38,0x6C,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,
83+ 0xFC,0x66,0x66,0x7C,0x66,0x66,0xFC,0x00,
84+ 0x3C,0x66,0xC0,0xC0,0xC0,0x66,0x3C,0x00,
85+ 0xF8,0x6C,0x66,0x66,0x66,0x6C,0xF8,0x00,
86+ 0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xFE,0x00,
87+ 0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xC0,0x00,
88+ 0x3C,0x66,0xC0,0xCE,0xC6,0x66,0x3C,0x00,
89+ 0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,
90+ 0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,
91+ 0x1E,0x0C,0x0C,0x0C,0x0C,0xCC,0x78,0x00,
92+ 0xC6,0xCC,0xD8,0xF0,0xD8,0xCC,0xC6,0x00,
93+ 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFE,0x00,
94+ 0xC6,0xEE,0xFE,0xD6,0xC6,0xC6,0xC6,0x00,
95+ 0xC6,0xE6,0xF6,0xDE,0xCE,0xC6,0xC6,0x00,
96+ 0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x38,0x00,
97+ 0xFC,0xC6,0xC6,0xFC,0xC0,0xC0,0xC0,0x00,
98+ 0x38,0x6C,0xC6,0xC6,0xDE,0x6C,0x3E,0x00,
99+ 0xFC,0xC6,0xC6,0xFC,0xD8,0xCC,0xC6,0x00,
100+ 0x7C,0xC6,0xC0,0x7C,0x06,0xC6,0x7C,0x00,
101+ 0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00,
102+ 0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,
103+ 0xC6,0xC6,0xC6,0x6C,0x6C,0x38,0x38,0x00,
104+ 0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00,
105+ 0xC6,0xC6,0x6C,0x38,0x6C,0xC6,0xC6,0x00,
106+ 0xCC,0xCC,0xCC,0x78,0x30,0x30,0x30,0x00,
107+ 0xFE,0x06,0x0C,0x38,0x60,0xC0,0xFE,0x00,
108+ 0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,
109+ 0xCC,0xCC,0x78,0xFC,0x30,0xFC,0x30,0x00,
110+ 0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,
111+ 0x30,0x78,0xCC,0x00,0x00,0x00,0x00,0x00,
112+ 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,
113+ 0x30,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,
114+ 0x00,0x00,0x7C,0x0C,0x7C,0xCC,0x7E,0x00,
115+ 0xC0,0xC0,0xFC,0xE6,0xC6,0xE6,0xFC,0x00,
116+ 0x00,0x00,0x7C,0xC6,0xC0,0xC6,0x7C,0x00,
117+ 0x06,0x06,0x7E,0xCE,0xC6,0xCE,0x7E,0x00,
118+ 0x00,0x00,0x7C,0xC6,0xFE,0xC0,0x7C,0x00,
119+ 0x1C,0x36,0x30,0xFC,0x30,0x30,0x30,0x00,
120+ 0x00,0x00,0x7E,0xCE,0xCE,0x7E,0x06,0x7C,
121+ 0xC0,0xC0,0xFC,0xE6,0xC6,0xC6,0xC6,0x00,
122+ 0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00,
123+ 0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0xCC,0x78,
124+ 0xC0,0xC0,0xCC,0xD8,0xF0,0xF8,0xCC,0x00,
125+ 0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,
126+ 0x00,0x00,0xFC,0xB6,0xB6,0xB6,0xB6,0x00,
127+ 0x00,0x00,0xFC,0xE6,0xC6,0xC6,0xC6,0x00,
128+ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0x00,
129+ 0x00,0x00,0xFC,0xE6,0xE6,0xFC,0xC0,0xC0,
130+ 0x00,0x00,0x7E,0xCE,0xCE,0x7E,0x06,0x06,
131+ 0x00,0x00,0xDC,0xE6,0xC0,0xC0,0xC0,0x00,
132+ 0x00,0x00,0x7E,0xC0,0x7C,0x06,0xFC,0x00,
133+ 0x30,0x30,0xFC,0x30,0x30,0x36,0x1C,0x00,
134+ 0x00,0x00,0xC6,0xC6,0xC6,0xCE,0x76,0x00,
135+ 0x00,0x00,0xC6,0xC6,0xC6,0x6C,0x38,0x00,
136+ 0x00,0x00,0x86,0xB6,0xB6,0xB6,0xFC,0x00,
137+ 0x00,0x00,0xC6,0x6C,0x38,0x6C,0xC6,0x00,
138+ 0x00,0x00,0xC6,0xC6,0xCE,0x7E,0x06,0x7C,
139+ 0x00,0x00,0xFE,0x0C,0x38,0x60,0xFE,0x00,
140+ 0x3C,0x60,0x60,0xC0,0x60,0x60,0x3C,0x00,
141+ 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,
142+ 0xF0,0x18,0x18,0x0C,0x18,0x18,0xF0,0x00,
143+ 0x60,0xB6,0x1C,0x00,0x00,0x00,0x00,0x00,
144+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
145+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,
146+ 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,
147+ 0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,
148+ 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,
149+ 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,
150+ 0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
151+ 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
152+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
153+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
154+ 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
155+ 0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
156+ 0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,
157+ 0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,
158+ 0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
159+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
160+ 0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,
161+ 0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,
162+ 0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,
163+ 0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,
164+ 0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,
165+ 0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
166+ 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,
167+ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
168+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
169+ 0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,
170+ 0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,
171+ 0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,
172+ 0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,
173+ 0x00,0x00,0x00,0x00,0x07,0x0C,0x18,0x18,
174+ 0x00,0x00,0x00,0x00,0xE0,0x30,0x18,0x18,
175+ 0x18,0x18,0x18,0x0C,0x07,0x00,0x00,0x00,
176+ 0x18,0x18,0x18,0x30,0xE0,0x00,0x00,0x00,
177+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
178+ 0x00,0x00,0x00,0x00,0x78,0x68,0x78,0x00,
179+ 0x78,0x60,0x60,0x60,0x00,0x00,0x00,0x00,
180+ 0x00,0x00,0x00,0x18,0x18,0x18,0x78,0x00,
181+ 0x00,0x00,0x00,0x00,0x60,0x30,0x18,0x00,
182+ 0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,
183+ 0xFE,0x06,0x06,0xFE,0x06,0x0C,0x78,0x00,
184+ 0x00,0x00,0xFC,0x0C,0x38,0x30,0x60,0x00,
185+ 0x00,0x00,0x0C,0x18,0x38,0x78,0x18,0x00,
186+ 0x00,0x00,0x30,0xFC,0xCC,0x0C,0x38,0x00,
187+ 0x00,0x00,0x00,0xFC,0x30,0x30,0xFC,0x00,
188+ 0x00,0x00,0x18,0xFC,0x38,0x78,0xD8,0x00,
189+ 0x00,0x00,0x60,0xFC,0x6C,0x68,0x60,0x00,
190+ 0x00,0x00,0x00,0x78,0x18,0x18,0xFC,0x00,
191+ 0x00,0x00,0x7C,0x0C,0x7C,0x0C,0x7C,0x00,
192+ 0x00,0x00,0x00,0xAC,0xAC,0x0C,0x38,0x00,
193+ 0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,
194+ 0xFE,0x06,0x06,0x34,0x38,0x30,0x60,0x00,
195+ 0x06,0x0C,0x18,0x38,0x78,0xD8,0x18,0x00,
196+ 0x18,0xFE,0xC6,0xC6,0x06,0x0C,0x38,0x00,
197+ 0x00,0x7E,0x18,0x18,0x18,0x18,0x7E,0x00,
198+ 0x18,0xFE,0x18,0x38,0x78,0xD8,0x18,0x00,
199+ 0x30,0xFE,0x36,0x36,0x36,0x36,0x6C,0x00,
200+ 0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,
201+ 0x3E,0x66,0xC6,0x0C,0x18,0x30,0xE0,0x00,
202+ 0x60,0x7E,0xD8,0x18,0x18,0x18,0x30,0x00,
203+ 0x00,0xFE,0x06,0x06,0x06,0x06,0xFE,0x00,
204+ 0x6C,0xFE,0x6C,0x0C,0x0C,0x18,0x30,0x00,
205+ 0x00,0xF0,0x00,0xF6,0x06,0x0C,0xF8,0x00,
206+ 0xFE,0x06,0x0C,0x18,0x38,0x6C,0xC6,0x00,
207+ 0x60,0xFE,0x66,0x6C,0x60,0x60,0x3E,0x00,
208+ 0xC6,0xC6,0x66,0x06,0x0C,0x18,0xF0,0x00,
209+ 0x3E,0x66,0xE6,0x3C,0x18,0x30,0xE0,0x00,
210+ 0x0C,0x78,0x18,0xFE,0x18,0x18,0xF0,0x00,
211+ 0x00,0xD6,0xD6,0xD6,0x0C,0x18,0xF0,0x00,
212+ 0x7C,0x00,0xFE,0x18,0x18,0x30,0x60,0x00,
213+ 0x30,0x30,0x38,0x3C,0x36,0x30,0x30,0x00,
214+ 0x18,0x18,0xFE,0x18,0x18,0x30,0x60,0x00,
215+ 0x00,0x7C,0x00,0x00,0x00,0x00,0xFE,0x00,
216+ 0x00,0x7E,0x06,0x6C,0x18,0x36,0x60,0x00,
217+ 0x18,0x7E,0x0C,0x18,0x3C,0x7E,0x18,0x00,
218+ 0x06,0x06,0x06,0x0C,0x18,0x30,0x60,0x00,
219+ 0x30,0x18,0x0C,0xC6,0xC6,0xC6,0xC6,0x00,
220+ 0xC0,0xC0,0xFE,0xC0,0xC0,0xC0,0x7E,0x00,
221+ 0x00,0xFE,0x06,0x06,0x0C,0x18,0x70,0x00,
222+ 0x00,0x30,0x78,0xCC,0x06,0x06,0x00,0x00,
223+ 0x18,0x18,0xFE,0x18,0xDB,0xDB,0x18,0x00,
224+ 0xFE,0x06,0x06,0x6C,0x38,0x30,0x18,0x00,
225+ 0x00,0x3C,0x00,0x3C,0x00,0x7C,0x06,0x00,
226+ 0x0C,0x18,0x30,0x60,0xCC,0xFC,0x06,0x00,
227+ 0x02,0x36,0x3C,0x18,0x3C,0x6C,0xC0,0x00,
228+ 0x00,0xFE,0x30,0xFE,0x30,0x30,0x3E,0x00,
229+ 0x30,0x30,0xFE,0x36,0x3C,0x30,0x30,0x00,
230+ 0x00,0x78,0x18,0x18,0x18,0x18,0xFE,0x00,
231+ 0xFE,0x06,0x06,0xFE,0x06,0x06,0xFE,0x00,
232+ 0x7C,0x00,0xFE,0x06,0x0C,0x18,0x30,0x00,
233+ 0xC6,0xC6,0xC6,0x06,0x06,0x0C,0x38,0x00,
234+ 0x6C,0x6C,0x6C,0x6E,0x6E,0x6C,0xC8,0x00,
235+ 0x60,0x60,0x60,0x66,0x6C,0x78,0x70,0x00,
236+ 0x00,0xFE,0xC6,0xC6,0xC6,0xC6,0xFE,0x00,
237+ 0x00,0xFE,0xC6,0xC6,0x06,0x0C,0x38,0x00,
238+ 0x00,0xF0,0x06,0x06,0x0C,0x18,0xF0,0x00,
239+ 0x18,0xCC,0x60,0x00,0x00,0x00,0x00,0x00,
240+ 0x70,0xD8,0x70,0x00,0x00,0x00,0x00,0x00,
241+ 0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,
242+ 0x18,0x18,0x1F,0x18,0x18,0x1F,0x18,0x18,
243+ 0x18,0x18,0xFF,0x18,0x18,0xFF,0x18,0x18,
244+ 0x18,0x18,0xF8,0x18,0x18,0xF8,0x18,0x18,
245+ 0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,
246+ 0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,
247+ 0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,
248+ 0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,
249+ 0x10,0x38,0x7C,0xFE,0xFE,0x38,0x7C,0x00,
250+ 0x6C,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,
251+ 0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,
252+ 0x38,0x38,0xFE,0xFE,0xD6,0x10,0x7C,0x00,
253+ 0x00,0x3C,0x7E,0x7E,0x7E,0x7E,0x3C,0x00,
254+ 0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,
255+ 0x03,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,
256+ 0x80,0xC0,0x60,0x30,0x18,0x0C,0x06,0x03,
257+ 0x83,0xC6,0x6C,0x38,0x38,0x6C,0xC6,0x83,
258+ 0xFE,0xB6,0xB6,0xFE,0x86,0x86,0x86,0x00,
259+ 0xC0,0xFE,0xD8,0x7E,0x58,0xFE,0x18,0x00,
260+ 0x7E,0x66,0x7E,0x66,0x7E,0x66,0xC6,0x00,
261+ 0xFE,0xC6,0xC6,0xFE,0xC6,0xC6,0xFE,0x00,
262+ 0x06,0xEF,0xA6,0xFF,0xA2,0xFF,0x0A,0x06,
263+ 0x00,0x38,0x6C,0xC6,0x7C,0x34,0x6C,0x00,
264+ 0xFC,0x6C,0xFE,0x6E,0xF6,0xEC,0x6C,0x78,
265+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
266+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
267+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
268+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
269+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
270+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
271+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
272+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
273+};
274+
275+void set_palette(unsigned char n,unsigned char b,unsigned char r,unsigned char g){
276+//テキスト、グラフィック共用カラーパレット設定
277+ palette[n]=((r>>3)<<11)+((g>>2)<<5)+(b>>3);
278+}
279+
280+void g_pset(int x,int y,unsigned int c)
281+// (x,y)の位置にカラーパレット番号cで点を描画
282+{
283+ if(x>=0 && x<X_RES && y>=0 && y<Y_RES)
284+ drawPixel(x,y,palette[c]);
285+}
286+
287+void g_putbmpmn(int x,int y,char m,char n,const unsigned char bmp[])
288+// 横m*縦nドットのキャラクターを座標x,yに表示
289+// unsigned char bmp[m*n]配列に、単純にカラー番号を並べる
290+// カラー番号が0の部分は透明色として扱う
291+{
292+ int i,j;
293+ int skip;
294+ const unsigned char *p;
295+ if(x<=-m || x>X_RES || y<=-n || y>=Y_RES) return; //画面外
296+ if(y<0){ //画面上部に切れる場合
297+ i=0;
298+ p=bmp-y*m;
299+ }
300+ else{
301+ i=y;
302+ p=bmp;
303+ }
304+ for(;i<y+n;i++){
305+ if(i>=Y_RES) return; //画面下部に切れる場合
306+ if(x<0){ //画面左に切れる場合は残る部分のみ描画
307+ j=0;
308+ p+=-x;
309+ }
310+ else{
311+ j=x;
312+ }
313+ skip=1;
314+ for(;j<x+m;j++){
315+ if(j>=X_RES){ //画面右に切れる場合
316+ p+=x+m-j;
317+ break;
318+ }
319+ if(*p!=0){ //カラー番号が0の場合、透明として処理
320+ if(skip){
321+ LCD_SetCursor(j,i);
322+ LCD_WriteIndex(0x22);
323+ skip=0;
324+ }
325+ LCD_WriteData(palette[*p]);
326+ }
327+ else skip=1;
328+ p++;
329+ }
330+ }
331+}
332+
333+
334+// 縦m*横nドットのキャラクター消去
335+// カラー0で塗りつぶし
336+void g_clrbmpmn(int x,int y,char m,char n)
337+{
338+ int i,j,k;
339+ if(x<=-m || x>X_RES || y<=-n || y>=Y_RES) return; //画面外
340+ if(y<0) i=0; //画面上部に切れる場合
341+ else i=y;
342+ if(x<0) j=0; //画面左に切れる場合は残る部分のみ描画
343+ else j=x;
344+ if(x+m>=X_RES) k=X_RES-j; //画面右に切れる場合
345+ else k=x+m-j;
346+ for(;i<y+n;i++){
347+ if(i>=Y_RES) return; //画面下部に切れる場合
348+ LCD_continuous_output(j,i,0,k);
349+ }
350+}
351+
352+void g_gline(int x1,int y1,int x2,int y2,unsigned int c)
353+// (x1,y1)-(x2,y2)にカラーパレット番号cで線分を描画
354+{
355+ int sx,sy,dx,dy,i;
356+ int e;
357+
358+ if(x2>x1){
359+ dx=x2-x1;
360+ sx=1;
361+ }
362+ else{
363+ dx=x1-x2;
364+ sx=-1;
365+ }
366+ if(y2>y1){
367+ dy=y2-y1;
368+ sy=1;
369+ }
370+ else{
371+ dy=y1-y2;
372+ sy=-1;
373+ }
374+ if(dx>=dy){
375+ e=-dx;
376+ for(i=0;i<=dx;i++){
377+ g_pset(x1,y1,c);
378+ x1+=sx;
379+ e+=dy*2;
380+ if(e>=0){
381+ y1+=sy;
382+ e-=dx*2;
383+ }
384+ }
385+ }
386+ else{
387+ e=-dy;
388+ for(i=0;i<=dy;i++){
389+ g_pset(x1,y1,c);
390+ y1+=sy;
391+ e+=dx*2;
392+ if(e>=0){
393+ x1+=sx;
394+ e-=dy*2;
395+ }
396+ }
397+ }
398+}
399+void g_hline(int x1,int x2,int y,unsigned int c)
400+// (x1,y)-(x2,y)への水平ラインを高速描画
401+{
402+ int temp;
403+ unsigned short d,*ad;
404+
405+ if(y<0 || y>=Y_RES) return;
406+ if(x1>x2){
407+ temp=x1;
408+ x1=x2;
409+ x2=temp;
410+ }
411+ if(x2<0 || x1>=X_RES) return;
412+ if(x1<0) x1=0;
413+ if(x2>=X_RES) x2=X_RES-1;
414+ LCD_continuous_output(x1,y,palette[c],x2-x1+1);
415+}
416+
417+void g_circle(int x0,int y0,unsigned int r,unsigned int c)
418+// (x0,y0)を中心に、半径r、カラーパレット番号cの円を描画
419+{
420+ int x,y,f;
421+ x=r;
422+ y=0;
423+ f=-2*r+3;
424+ while(x>=y){
425+ g_pset(x0-x,y0-y,c);
426+ g_pset(x0-x,y0+y,c);
427+ g_pset(x0+x,y0-y,c);
428+ g_pset(x0+x,y0+y,c);
429+ g_pset(x0-y,y0-x,c);
430+ g_pset(x0-y,y0+x,c);
431+ g_pset(x0+y,y0-x,c);
432+ g_pset(x0+y,y0+x,c);
433+ if(f>=0){
434+ x--;
435+ f-=x*4;
436+ }
437+ y++;
438+ f+=y*4+2;
439+ }
440+}
441+void g_boxfill(int x1,int y1,int x2,int y2,unsigned int c)
442+// (x1,y1),(x2,y2)を対角線とするカラーパレット番号cで塗られた長方形を描画
443+{
444+ int temp;
445+ if(x1>x2){
446+ temp=x1;
447+ x1=x2;
448+ x2=temp;
449+ }
450+ if(x2<0 || x1>=X_RES) return;
451+ if(y1>y2){
452+ temp=y1;
453+ y1=y2;
454+ y2=temp;
455+ }
456+ if(y2<0 || y1>=Y_RES) return;
457+ if(y1<0) y1=0;
458+ if(y2>=Y_RES) y2=Y_RES-1;
459+ while(y1<=y2){
460+ g_hline(x1,x2,y1++,c);
461+ }
462+}
463+void g_circlefill(int x0,int y0,unsigned int r,unsigned int c)
464+// (x0,y0)を中心に、半径r、カラーパレット番号cで塗られた円を描画
465+{
466+ int x,y,f;
467+ x=r;
468+ y=0;
469+ f=-2*r+3;
470+ while(x>=y){
471+ g_hline(x0-x,x0+x,y0-y,c);
472+ g_hline(x0-x,x0+x,y0+y,c);
473+ g_hline(x0-y,x0+y,y0-x,c);
474+ g_hline(x0-y,x0+y,y0+x,c);
475+ if(f>=0){
476+ x--;
477+ f-=x*4;
478+ }
479+ y++;
480+ f+=y*4+2;
481+ }
482+}
483+
484+void g_putfont(int x,int y,unsigned int c,int bc,unsigned char n)
485+//8*8ドットのアルファベットフォント表示
486+//座標(x,y)、カラーパレット番号c
487+//bc:バックグランドカラー、負数の場合無視
488+//n:文字番号
489+{
490+ int i,j;
491+ unsigned char d;
492+ int skip;
493+ unsigned short c1;
494+ const unsigned char *p;
495+ if(x<=-8 || x>=X_RES || y<=-8 || y>=Y_RES) return; //画面外
496+ if(y<0){ //画面上部に切れる場合
497+ i=0;
498+ p=fontp+n*8-y;
499+ }
500+ else{
501+ i=y;
502+ p=fontp+n*8;
503+ }
504+ c1=palette[c];
505+ if(bc>=0) bc=palette[bc];
506+ for(;i<y+8;i++){
507+ if(i>=Y_RES) return; //画面下部に切れる場合
508+ d=*p++;
509+ if(x<0){ //画面左に切れる場合は残る部分のみ描画
510+ j=0;
511+ d<<=-x;
512+ }
513+ else{
514+ j=x;
515+ }
516+ if(bc<0){
517+ skip=1;
518+ for(;j<x+8;j++){
519+ if(j>=X_RES){ //画面右に切れる場合
520+ break;
521+ }
522+ if(d&0x80){
523+ if(skip){
524+ LCD_SetCursor(j,i);
525+ LCD_WriteIndex(0x22);
526+ skip=0;
527+ }
528+ LCD_WriteData(c1);
529+ }
530+ else skip=1;
531+ d<<=1;
532+ }
533+ }
534+ else{
535+ LCD_SetCursor(j,i);
536+ LCD_WriteIndex(0x22);
537+ for(;j<x+8;j++){
538+ if(j>=X_RES){ //画面右に切れる場合
539+ break;
540+ }
541+ if(d&0x80){
542+ LCD_WriteData(c1);
543+ }
544+ else{
545+ LCD_WriteData(bc);
546+ }
547+ d<<=1;
548+ }
549+ }
550+ }
551+}
552+
553+void g_printstr(int x,int y,unsigned int c,unsigned int bc,unsigned char *s){
554+ //座標(x,y)からカラーパレット番号cで文字列sを表示、bc:バックグランドカラー
555+ //bcが負の場合は無視
556+ while(*s){
557+ g_putfont(x,y,c,bc,*s++);
558+ x+=8;
559+ }
560+}
561+void g_printnum(int x,int y,unsigned int c,unsigned int bc,unsigned int n){
562+ //座標(x,y)にカラー番号cで数値nを表示、bc:バックグランドカラー
563+ unsigned int d,e;
564+ d=10;
565+ e=0;
566+ while(n>=d){
567+ e++;
568+ if(e==9) break;
569+ d*=10;
570+ }
571+ x+=e*8;
572+ do{
573+ g_putfont(x,y,c,bc,'0'+n%10);
574+ n/=10;
575+ x-=8;
576+ }while(n!=0);
577+}
578+void g_printnum2(int x,int y,unsigned int c,unsigned int bc,unsigned int n,unsigned char e){
579+ //座標(x,y)にカラー番号cで数値nを表示、bc:バックグランドカラー、e桁で表示
580+ if(e==0) return;
581+ x+=(e-1)*8;
582+ do{
583+ g_putfont(x,y,c,bc,'0'+n%10);
584+ e--;
585+ n/=10;
586+ x-=8;
587+ }while(e!=0 && n!=0);
588+ while(e!=0){
589+ g_putfont(x,y,c,bc,' ');
590+ x-=8;
591+ e--;
592+ }
593+}
594+unsigned int g_color(int x,int y){
595+//座標(x,y)の色情報を返す、画面外は0を返す
596+//パレット番号ではないことに注意
597+ if(x<0 || x>=X_RES || y<0 || y>=Y_RES) return 0;
598+ return getColor(x,y);
599+}
600+
601+// テキスト画面クリア
602+void clearscreen(void)
603+{
604+ unsigned int *vp;
605+ int i;
606+ vp=(unsigned int *)TVRAM;
607+ for(i=0;i<WIDTH_X2*WIDTH_Y*2/4;i++) *vp++=0;
608+ cursor=TVRAM;
609+ LCD_Clear(bgcolor);
610+}
611+
612+// グラフィック画面クリア
613+void g_clearscreen(void)
614+{
615+ LCD_Clear(0);
616+}
617+unsigned char *cursor;
618+unsigned char cursorcolor;
619+
620+void textredraw(void){
621+// テキスト画面再描画
622+// テキストVRAMの内容にしたがって液晶に出力
623+ unsigned char *p;
624+ int i,j;
625+
626+ p=TVRAM;
627+ for(i=0;i<WIDTH_Y;i++){
628+ if(twidth==WIDTH_X1){
629+ for(j=0;j<WIDTH_X1;j++){
630+ g_putfont(j*8,i*8,*(p+ATTROFFSET1),bgcolor,*p);
631+ p++;
632+ }
633+ }
634+ else{
635+ for(j=0;j<WIDTH_X2;j++){
636+ g_putfont(j*6,i*8,*(p+ATTROFFSET2),bgcolor,*p);
637+ p++;
638+ }
639+ }
640+ }
641+}
642+void vramscroll(void){
643+ unsigned short *p1,*p2;
644+
645+ p1=(unsigned short *)TVRAM;
646+ if(twidth==WIDTH_X1){
647+ p2=(unsigned short *)(TVRAM+WIDTH_X1);
648+ while(p2<(unsigned short *)(TVRAM+ATTROFFSET1)){
649+ *(p1+ATTROFFSET1/2)=*(p2+ATTROFFSET1/2);
650+ *p1++=*p2++;
651+ }
652+ while(p1<(unsigned short *)(TVRAM+ATTROFFSET1)){
653+ *(p1+ATTROFFSET1/2)=0;
654+ *p1++=0;
655+ }
656+ }
657+ else{
658+ p2=(unsigned short *)(TVRAM+WIDTH_X2);
659+ while(p2<(unsigned short *)(TVRAM+ATTROFFSET2)){
660+ *(p1+ATTROFFSET2/2)=*(p2+ATTROFFSET2/2);
661+ *p1++=*p2++;
662+ }
663+ while(p1<(unsigned short *)(TVRAM+ATTROFFSET2)){
664+ *(p1+ATTROFFSET2/2)=0;
665+ *p1++=0;
666+ }
667+ }
668+ textredraw();
669+}
670+void vramscrolldown(void){
671+ unsigned short *p1,*p2;
672+
673+ if(twidth==WIDTH_X1){
674+ p1=(unsigned short *)(TVRAM+ATTROFFSET1)-1;
675+ p2=(unsigned short *)(TVRAM+ATTROFFSET1-WIDTH_X1)-1;
676+ while(p2>=(unsigned short *)(TVRAM)){
677+ *(p1+ATTROFFSET1/2)=*(p2+ATTROFFSET1/2);
678+ *p1++=*p2++;
679+ }
680+ while(p1>=(unsigned short *)(TVRAM)){
681+ *(p1+ATTROFFSET1/2)=0;
682+ *p1++=0;
683+ }
684+ }
685+ else{
686+ p1=(unsigned short *)(TVRAM+ATTROFFSET2)-1;
687+ p2=(unsigned short *)(TVRAM+ATTROFFSET2-WIDTH_X2)-1;
688+ while(p2>=(unsigned short *)(TVRAM)){
689+ *(p1+ATTROFFSET2/2)=*(p2+ATTROFFSET2/2);
690+ *p1++=*p2++;
691+ }
692+ while(p1>=(unsigned short *)(TVRAM)){
693+ *(p1+ATTROFFSET2/2)=0;
694+ *p1++=0;
695+ }
696+ }
697+ textredraw();
698+}
699+void setcursor(unsigned char x,unsigned char y,unsigned char c){
700+ //カーソルを座標(x,y)にカラー番号cに設定
701+ if(x>=twidth || y>=WIDTH_Y) return;
702+ cursor=TVRAM+y*twidth+x;
703+ cursorcolor=c;
704+}
705+void setcursorcolor(unsigned char c){
706+ //カーソル位置そのままでカラー番号をcに設定
707+ cursorcolor=c;
708+}
709+void printchar(unsigned char n){
710+ //カーソル位置にテキストコードnを1文字表示し、カーソルを1文字進める
711+ //画面最終文字表示してもスクロールせず、次の文字表示時にスクロールする
712+ if(cursor<TVRAM || cursor>TVRAM+twidth*WIDTH_Y) return;
713+ if(cursor==TVRAM+twidth*WIDTH_Y){
714+ vramscroll();
715+ cursor-=twidth;
716+ }
717+ if(n=='\n'){
718+ //改行
719+ cursor+=twidth-((cursor-TVRAM)%twidth);
720+ } else{
721+ *cursor=n;
722+ if(twidth==WIDTH_X1){
723+ *(cursor+ATTROFFSET1)=cursorcolor;
724+ g_putfont(((cursor-TVRAM)%WIDTH_X1)*8,((cursor-TVRAM)/WIDTH_X1)*8,cursorcolor,bgcolor,n);
725+ }
726+ else{
727+ *(cursor+ATTROFFSET2)=cursorcolor;
728+ g_putfont(((cursor-TVRAM)%WIDTH_X2)*6,((cursor-TVRAM)/WIDTH_X2)*8,cursorcolor,bgcolor,n);
729+ }
730+ cursor++;
731+ }
732+}
733+void printstr(unsigned char *s){
734+ //カーソル位置に文字列sを表示
735+ while(*s){
736+ printchar(*s++);
737+ }
738+}
739+void printnum(unsigned int n){
740+ //カーソル位置に符号なし整数nを10進数表示
741+ unsigned int d,n1;
742+ n1=n/10;
743+ d=1;
744+ while(n1>=d){
745+ d*=10;
746+ }
747+ while(d!=0){
748+ printchar('0'+n/d);
749+ n%=d;
750+ d/=10;
751+ }
752+}
753+void printnum2(unsigned int n,unsigned char e){
754+ //カーソル位置に符号なし整数nをe桁の10進数表示(前の空き桁部分はスペースで埋める)
755+ unsigned int d,n1;
756+ if(e==0) return;
757+ n1=n/10;
758+ d=1;
759+ e--;
760+ while(e>0 && n1>=d){
761+ d*=10;
762+ e--;
763+ }
764+ if(e==0 && n1>d) n%=d*10;
765+ for(;e>0;e--) printchar(' ');
766+ while(d!=0){
767+ printchar('0'+n/d);
768+ n%=d;
769+ d/=10;
770+ }
771+}
772+void cls(void){
773+ //画面消去しカーソルを先頭に移動
774+ clearscreen();
775+}
776+void startPCG(unsigned char *p,int a){
777+// RAMフォント(PCG)の利用開始
778+// p:RAMフォントの格納アドレス(8*256=2048バイト)
779+// a: システムフォントからのコピー指定。0の場合コピーなし、0以外でコピー
780+ int i;
781+ if(a){
782+ if(twidth==WIDTH_X1)
783+ for(i=0;i<8*256;i++) *p++=FontData[i];
784+// else
785+// for(i=0;i<8*256;i++) *p++=FontData2[i];
786+ fontp=p-8*256;
787+ }
788+ else fontp=p;
789+}
790+void stopPCG(void){
791+// RAMフォント(PCG)の利用停止
792+ if(twidth==WIDTH_X1) fontp=(unsigned char *)FontData;
793+// else fontp=(unsigned char *)FontData2;
794+}
795+void set_bgcolor(unsigned char b,unsigned char r,unsigned char g)
796+{
797+ bgcolor=((r>>3)<<11)+((g>>2)<<5)+(b>>3);
798+
799+}
800+void init_textgraph(void){
801+ //テキストモードでのグラフィックLCDライブラリの使用開始
802+ //パレット設定
803+ //LCD縦横設定
804+
805+ int i;
806+ graphmode=0;//テキストモード
807+ fontp=(unsigned char *)FontData;
808+ twidth=WIDTH_X1;//30文字モード
809+ set_bgcolor(0,0,0); //バックグランドカラーは黒
810+ clearscreen();
811+ //カラーパレット初期化
812+ for(i=0;i<8;i++){
813+ set_palette(i,255*(i&1),255*((i>>1)&1),255*(i>>2));
814+ }
815+ for(i=0;i<8;i++){
816+ set_palette(i+8,128*(i&1),128*((i>>1)&1),128*(i>>2));
817+ }
818+ for(i=16;i<256;i++){
819+ set_palette(i,255,255,255);
820+ }
821+ setcursorcolor(7);
822+
823+// LCD_Init(); //ブートローダで初期化するため、アプリ側では初期化しない
824+
825+#if LCD_ALIGNMENT == HORIZONTAL
826+ LCD_set_Horizontal();
827+#endif
828+}
829+
830+void init_graphic(void){
831+ //グラフィックLCDライブラリの使用開始
832+ //パレット設定
833+ //LCD縦横設定
834+
835+ int i;
836+ //カラーパレット初期化
837+ for(i=0;i<8;i++){
838+ set_palette(i,255*(i&1),255*((i>>1)&1),255*(i>>2));
839+ }
840+ for(i=0;i<8;i++){
841+ set_palette(i+8,128*(i&1),128*((i>>1)&1),128*(i>>2));
842+ }
843+ for(i=16;i<256;i++){
844+ set_palette(i,255,255,255);
845+ }
846+
847+// LCD_Init(); //ブートローダで初期化するため、アプリ側では初期化しない
848+
849+#if LCD_ALIGNMENT == HORIZONTAL
850+ LCD_set_Horizontal();
851+#endif
852+ LCD_Clear(0);
853+}
854+volatile unsigned short drawcount;
855+/**********************
856+* Timer2 割り込み処理関数
857+***********************/
858+void __ISR(8, ipl4) T2Handler(void)
859+{
860+ drawcount++;
861+ IFS0bits.T2IF = 0; // T2割り込みフラグクリア
862+ IFS0bits.CS0IF= 1; // CS0割り込み
863+}
864+
865+//30文字モード(8ドットフォント)と40文字モード(6ドットフォント)の切り替え
866+void set_width(unsigned char m){
867+// m:0 30文字モード、1 40文字モード
868+// グラフモード時は無効
869+// PCG使用中はフォント変更しない
870+ if(graphmode) return;
871+ clearscreen();
872+ if(m){
873+// if(fontp<(unsigned char *)0xa0000000) fontp=(unsigned char *)FontData2;
874+ twidth=WIDTH_X2;
875+ }
876+ else{
877+ if(fontp<(unsigned char *)0xa0000000) fontp=(unsigned char *)FontData;
878+ twidth=WIDTH_X1;
879+ }
880+ return;
881+}
882+
883+//テキストモードとグラフィックモードの切り替え
884+void set_graphmode(unsigned char m){
885+// m:0 テキストモード、0以外 グラフィックモード
886+ if(m){
887+ //グラフィックモード開始
888+ graphmode=1;
889+ }
890+ else{
891+ //テキストーモード開始
892+ graphmode=0;
893+ }
894+}
--- /dev/null
+++ b/mips/protozoa/interface/keyinput.c
@@ -0,0 +1,41 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+// キー入力、カーソル表示関連機能 by K.Tanaka
8+// PS/2キーボード入力システム、カラーテキスト出力システム利用
9+
10+#include "videoout.h"
11+#include "ps2keyboard.h"
12+#include "keyinput.h"
13+#include "plib.h"
14+
15+volatile unsigned short vkey; //仮想キーコード
16+unsigned short keystatus,keystatus2,oldkey; //最新のボタン状態と前回のボタン状態
17+
18+int lineinput(char *s,int n){
19+ return 0;
20+}
21+
22+unsigned short readButton(void){
23+ unsigned short k;
24+ LCD_CS_HI;
25+ asm("nop");
26+ KEY_EN;
27+ asm("nop");
28+ TRISBSET=KEYMASK;
29+ asm("nop");
30+ k=~KEYPORT & KEYMASK;
31+ KEY_DS;
32+ asm("nop");
33+ TRISBCLR=KEYMASK;
34+ asm("nop");
35+ LCD_CS_LO;
36+ return k;
37+}
38+
39+unsigned char ps2readkey(){
40+ return 0;
41+}
\ No newline at end of file
--- /dev/null
+++ b/mips/protozoa/interface/keyinput.h
@@ -0,0 +1,48 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+*/
6+
7+#define BLINKTIME 15
8+#define CURSORCHAR 0x87
9+#define CURSORCHAR2 0x80
10+#define CURSORCOLOR 7
11+
12+void getcursorchar();
13+// カーソル点滅用に元の文字コードを退避
14+
15+void resetcursorchar();
16+// カーソルを元の文字に戻す
17+
18+void blinkcursorchar();
19+// 定期的に呼び出すことでカーソルを点滅表示させる
20+// BLINKTIMEで点滅間隔を設定
21+// 事前にgetcursorchar()を呼び出しておく
22+
23+int lineinput(char *s,int n);
24+// キー入力して文字列配列sに格納
25+// sに初期文字列を入れておくと最初に表示して文字列の最後にカーソル移動する
26+// 初期文字列を使用しない場合は*s=0としておく
27+// カーソル位置はsetcursor関数で指定しておく
28+// 最大文字数n、最後に0を格納するのでn+1バイトの領域必要、ただしnの最大値は255
29+// 戻り値 Enterで終了した場合0、ESCで終了時は-1(sは壊さない)
30+
31+unsigned char inputchar(void);
32+// キーボードから1キー入力待ち
33+// 戻り値 通常文字の場合ASCIIコード、その他は0、グローバル変数vkeyに仮想キーコード
34+
35+unsigned char printinputchar(void);
36+// カーソル表示しながらキーボードから通常文字キー入力待ちし、入力された文字を表示
37+// 戻り値 入力された文字のASCIIコード、グローバル変数vkeyに最後に押されたキーの仮想キーコード
38+
39+unsigned char cursorinputchar(void);
40+// カーソル表示しながらキーボードから1キー入力待ち
41+// 戻り値 通常文字の場合ASCIIコード、その他は0、グローバル変数vkeyに仮想キーコード
42+
43+unsigned short readButton(void);
44+
45+extern unsigned char blinkchar,blinkcolor;
46+extern int blinktimer;
47+extern int insertmode; //挿入モード:1、上書きモード:0
48+extern unsigned short keystatus,keystatus2,oldkey; //最新のボタン状態と前回のボタン状態
Binary files /dev/null and b/mips/protozoa/interface/libsdfsio.a differ
--- /dev/null
+++ b/mips/protozoa/interface/ps2keyboard.h
@@ -0,0 +1,178 @@
1+#define CHK_SHIFT 0x01
2+#define CHK_CTRL 0x02
3+#define CHK_ALT 0x04
4+#define CHK_WIN 0x08
5+#define CHK_SCRLK 0x10
6+#define CHK_NUMLK 0x20
7+#define CHK_CAPSLK 0x40
8+#define CHK_SHIFT_L 0x01
9+#define CHK_SHIFT_R 0x02
10+#define CHK_CTRL_L 0x04
11+#define CHK_CTRL_R 0x08
12+#define CHK_ALT_L 0x10
13+#define CHK_ALT_R 0x20
14+#define CHK_WIN_L 0x40
15+#define CHK_WIN_R 0x80
16+#define CHK_SCRLK_A 0x100
17+#define CHK_NUMLK_A 0x200
18+#define CHK_CAPSLK_A 0x400
19+
20+#define VK_LBUTTON 0x01
21+#define VK_RBUTTON 0x02
22+#define VK_CANCEL 0x03
23+#define VK_MBUTTON 0x04
24+#define VK_XBUTTON1 0x05
25+#define VK_XBUTTON2 0x06
26+#define VK_BACK 0x08
27+#define VK_TAB 0x09
28+#define VK_CLEAR 0x0C
29+#define VK_RETURN 0x0D
30+#define VK_SHIFT 0x10
31+#define VK_CONTROL 0x11
32+#define VK_MENU 0x12
33+#define VK_PAUSE 0x13
34+#define VK_CAPITAL 0x14
35+#define VK_KANA 0x15
36+#define VK_HANGUEL 0x15
37+#define VK_HANGUL 0x15
38+#define VK_JUNJA 0x17
39+#define VK_FINAL 0x18
40+#define VK_HANJA 0x19
41+#define VK_KANJI 0x19
42+#define VK_ESCAPE 0x1B
43+#define VK_CONVERT 0x1C
44+#define VK_NONCONVERT 0x1D
45+#define VK_ACCEPT 0x1E
46+#define VK_MODECHANGE 0x1F
47+#define VK_SPACE 0x20
48+#define VK_PRIOR 0x21
49+#define VK_NEXT 0x22
50+#define VK_END 0x23
51+#define VK_HOME 0x24
52+#define VK_LEFT 0x25
53+#define VK_UP 0x26
54+#define VK_RIGHT 0x27
55+#define VK_DOWN 0x28
56+#define VK_SELECT 0x29
57+#define VK_PRINT 0x2A
58+#define VK_EXECUTE 0x2B
59+#define VK_SNAPSHOT 0x2C
60+#define VK_INSERT 0x2D
61+#define VK_DELETE 0x2E
62+#define VK_HELP 0x2F
63+#define VK_LWIN 0x5B
64+#define VK_RWIN 0x5C
65+#define VK_APPS 0x5D
66+#define VK_SLEEP 0x5F
67+#define VK_NUMPAD0 0x60
68+#define VK_NUMPAD1 0x61
69+#define VK_NUMPAD2 0x62
70+#define VK_NUMPAD3 0x63
71+#define VK_NUMPAD4 0x64
72+#define VK_NUMPAD5 0x65
73+#define VK_NUMPAD6 0x66
74+#define VK_NUMPAD7 0x67
75+#define VK_NUMPAD8 0x68
76+#define VK_NUMPAD9 0x69
77+#define VK_MULTIPLY 0x6A
78+#define VK_ADD 0x6B
79+#define VK_SEPARATOR 0x6C
80+#define VK_SUBTRACT 0x6D
81+#define VK_DECIMAL 0x6E
82+#define VK_DIVIDE 0x6F
83+#define VK_F1 0x70
84+#define VK_F2 0x71
85+#define VK_F3 0x72
86+#define VK_F4 0x73
87+#define VK_F5 0x74
88+#define VK_F6 0x75
89+#define VK_F7 0x76
90+#define VK_F8 0x77
91+#define VK_F9 0x78
92+#define VK_F10 0x79
93+#define VK_F11 0x7A
94+#define VK_F12 0x7B
95+#define VK_F13 0x7C
96+#define VK_F14 0x7D
97+#define VK_F15 0x7E
98+#define VK_F16 0x7F
99+#define VK_F17 0x80
100+#define VK_F18 0x81
101+#define VK_F19 0x82
102+#define VK_F20 0x83
103+#define VK_F21 0x84
104+#define VK_F22 0x85
105+#define VK_F23 0x86
106+#define VK_F24 0x87
107+#define VK_NUMLOCK 0x90
108+#define VK_SCROLL 0x91
109+#define VK_LSHIFT 0xA0
110+#define VK_RSHIFT 0xA1
111+#define VK_LCONTROL 0xA2
112+#define VK_RCONTROL 0xA3
113+#define VK_LMENU 0xA4
114+#define VK_RMENU 0xA5
115+#define VK_BROWSER_BACK 0xA6
116+#define VK_BROWSER_FORWARD 0xA7
117+#define VK_BROWSER_REFRESH 0xA8
118+#define VK_BROWSER_STOP 0xA9
119+#define VK_BROWSER_SEARCH 0xAA
120+#define VK_BROWSER_FAVORITES 0xAB
121+#define VK_BROWSER_HOME 0xAC
122+#define VK_VOLUME_MUTE 0xAD
123+#define VK_VOLUME_DOWN 0xAE
124+#define VK_VOLUME_UP 0xAF
125+#define VK_MEDIA_NEXT_TRACK 0xB0
126+#define VK_MEDIA_PREV_TRACK 0xB1
127+#define VK_MEDIA_STOP 0xB2
128+#define VK_MEDIA_PLAY_PAUSE 0xB3
129+#define VK_LAUNCH_MAIL 0xB4
130+#define VK_LAUNCH_MEDIA_SELECT 0xB5
131+#define VK_LAUNCH_APP1 0xB6
132+#define VK_LAUNCH_APP2 0xB7
133+#define VK_OEM_1 0xBA
134+#define VK_OEM_PLUS 0xBB
135+#define VK_OEM_COMMA 0xBC
136+#define VK_OEM_MINUS 0xBD
137+#define VK_OEM_PERIOD 0xBE
138+#define VK_OEM_2 0xBF
139+#define VK_OEM_3 0xC0
140+#define VK_OEM_4 0xDB
141+#define VK_OEM_5 0xDC
142+#define VK_OEM_6 0xDD
143+#define VK_OEM_7 0xDE
144+#define VK_OEM_8 0xDF
145+#define VK_OEM_102 0xE2
146+#define VK_PROCESSKEY 0xE5
147+#define VK_PACKE 0xE7
148+#define VK_ATTN 0xF6
149+#define VK_CRSEL 0xF7
150+#define VK_EXSEL 0xF8
151+#define VK_EREOF 0xF9
152+#define VK_PLAY 0xFA
153+#define VK_ZOOM 0xFB
154+#define VK_NONAME 0xFC
155+#define VK_PA1 0xFD
156+#define VK_OEM_CLEAR 0xFE
157+
158+extern volatile unsigned char ps2keystatus[256]; // 仮想コードに相当するキーの状態(Onの時1)
159+extern volatile unsigned short vkey; //仮想キーコード
160+extern unsigned char lockkey; // 初期化時にLockキーの状態指定。下位3ビットが<CAPSLK><NUMLK><SCRLK>
161+extern unsigned char keytype; // キーボードの種類。0:日本語109キー、1:英語104キー
162+
163+//int ps2init(); // PS/2ライブラリ関連初期化。正常終了0、エラーで-1を返す
164+//unsigned char shiftkeys(); // SHIFT関連キーの押下状態を返す
165+#define shiftkeys() 0 // SHIFT関連キーの押下状態を返す
166+unsigned char ps2readkey();
167+// 入力された1つのキーのキーコードをグローバル変数vkeyに格納(押されていなければ0を返す)
168+// 下位8ビット:キーコード
169+// 上位8ビット:シフト状態(押下:1)、上位から<0><CAPSLK><NUMLK><SCRLK><Win><ALT><CTRL><SHIFT>
170+// 英数・記号文字の場合、戻り値としてASCIIコード(それ以外は0を返す)
171+
172+// PIC32MX1xx/2xx版のキーボードとボタンの排他利用システムで使用する関数、マクロ
173+//void ps2mode(); // PS/2を有効にする
174+#define ps2mode() (0)
175+//void buttonmode(); // ボタンを有効にする
176+#define buttonmode() (0)
177+//#define inPS2MODE() ((LATA&2)>>1) // モード確認用マクロ。PS/2モードの場合1、ボタンモードの場合0を返す
178+#define inPS2MODE() (0)
--- /dev/null
+++ b/mips/protozoa/interface/videoout.h
@@ -0,0 +1,130 @@
1+#include "LCDdriver.h"
2+
3+#if LCD_ALIGNMENT == VERTICAL
4+#define WIDTH_X1 30 // 横方向文字数1
5+#define WIDTH_X2 40 // 横方向文字数2(6ドットフォント利用時)
6+#define WIDTH_Y 40 // 縦方向文字数
7+#define ATTROFFSET1 (WIDTH_X1*WIDTH_Y) // VRAM上のカラーパレット格納位置1
8+#define ATTROFFSET2 (WIDTH_X2*WIDTH_Y) // VRAM上のカラーパレット格納位置2
9+#define G_X_RES 240 // 横方向解像度
10+#define G_Y_RES 320 // 縦方向解像度
11+#else
12+#define WIDTH_X1 40 // 横方向文字数1
13+#define WIDTH_X2 52 // 横方向文字数2(6ドットフォント利用時)
14+#define WIDTH_Y 30 // 縦方向文字数
15+#define ATTROFFSET1 (WIDTH_X1*WIDTH_Y) // VRAM上のカラーパレット格納位置1
16+#define ATTROFFSET2 (WIDTH_X2*WIDTH_Y) // VRAM上のカラーパレット格納位置2
17+#define G_X_RES 320 // 横方向解像度
18+#define G_Y_RES 240 // 縦方向解像度
19+#endif
20+
21+// 入力ボタンのポート、ビット定義
22+#define KEYPORT PORTB
23+#define KEYDOWN 0x0004
24+#define KEYLEFT 0x0008
25+#define KEYRIGHT 0x0010
26+#define KEYUP 0x0020
27+#define KEYSTART 0x0080
28+#define KEYFIRE 0x0100
29+#define KEYMASK (KEYSTART | KEYFIRE | KEYUP | KEYDOWN | KEYLEFT | KEYRIGHT)
30+#define KEY_DS LATASET=0x0008
31+#define KEY_EN LATACLR=0x0008
32+
33+//extern volatile char drawing; // 表示期間中は-1
34+extern volatile unsigned short drawcount; // 1画面表示終了ごとに1足す。アプリ側で0にする。
35+ // 最低1回は画面表示したことのチェックと、アプリの処理が何画面期間必要かの確認に利用。
36+extern unsigned char TVRAM[]; //テキストビデオメモリ
37+//extern unsigned short *gVRAM; //グラフィックVRAM開始位置のポインタ
38+
39+extern const unsigned char FontData[]; //フォントパターン定義
40+//extern const unsigned char FontData[],FontData2[]; //フォントパターン定義
41+extern unsigned char *cursor;
42+extern unsigned char cursorcolor;
43+extern unsigned char *fontp;
44+extern unsigned char twidth; //テキスト1行文字数(30 or 40)
45+extern unsigned int bgcolor; // バックグランドカラー
46+
47+//void start_composite(void); //カラーコンポジット出力開始
48+//void stop_composite(void); //カラーコンポジット出力停止
49+//void init_composite(void); //カラーコンポジット出力初期化
50+void clearscreen(void); //テキスト画面クリア
51+void set_palette(unsigned char n,unsigned char b,unsigned char r,unsigned char g); //テキストパレット設定
52+void set_bgcolor(unsigned char b,unsigned char r,unsigned char g); //バックグランドカラー設定
53+void set_graphmode(unsigned char m); //グラフィックモード変更
54+void init_textgraph(void); //テキスト機能利用準備
55+void init_graphic(void); //グラフィック機能利用準備
56+void set_width(unsigned char m); //30文字モード(8ドットフォント)と40文字モード(6ドットフォント)の切り替え
57+void textredraw(void);
58+ // テキスト画面再描画、テキストVRAMの内容にしたがって液晶に出力
59+void vramscroll(void);
60+ //1行スクロール
61+void vramscrolldown(void);
62+ //1行逆スクロール
63+void setcursor(unsigned char x,unsigned char y,unsigned char c);
64+ //カーソル位置とカラーを設定
65+void setcursorcolor(unsigned char c);
66+ //カーソル位置そのままでカラー番号をcに設定
67+void printchar(unsigned char n);
68+ //カーソル位置にテキストコードnを1文字表示し、カーソルを1文字進める
69+void printstr(unsigned char *s);
70+ //カーソル位置に文字列sを表示
71+void printnum(unsigned int n);
72+ //カーソル位置に符号なし整数nを10進数表示
73+void printnum2(unsigned int n,unsigned char e);
74+ //カーソル位置に符号なし整数nをe桁の10進数表示(前の空き桁部分はスペースで埋める)
75+void cls(void);
76+ //テキスト画面消去し、カーソルを先頭に移動
77+void startPCG(unsigned char *p,int a);
78+ // RAMフォント(PCG)の利用開始、pがフォント格納場所、aが0以外でシステムフォントをコピー
79+void stopPCG(void);
80+ // RAMフォント(PCG)の利用停止
81+
82+void g_clearscreen(void);
83+//グラフィック画面クリア
84+void g_set_palette(unsigned char n,unsigned char b,unsigned char r,unsigned char g);
85+//グラフィック用カラーパレット設定
86+
87+void g_pset(int x,int y,unsigned int c);
88+// (x,y)の位置にカラーcで点を描画
89+
90+void g_putbmpmn(int x,int y,char m,char n,const unsigned char bmp[]);
91+// 横m*縦nドットのキャラクターを座標x,yに表示
92+// unsigned char bmp[m*n]配列に、単純にカラー番号を並べる
93+// カラー番号が0の部分は透明色として扱う
94+
95+void g_clrbmpmn(int x,int y,char m,char n);
96+// 縦m*横nドットのキャラクター消去
97+// カラー0で塗りつぶし
98+
99+void g_gline(int x1,int y1,int x2,int y2,unsigned int c);
100+// (x1,y1)-(x2,y2)にカラーcで線分を描画
101+
102+void g_hline(int x1,int x2,int y,unsigned int c);
103+// (x1,y)-(x2,y)への水平ラインを高速描画
104+
105+void g_circle(int x0,int y0,unsigned int r,unsigned int c);
106+// (x0,y0)を中心に、半径r、カラーcの円を描画
107+
108+void g_boxfill(int x1,int y1,int x2,int y2,unsigned int c);
109+// (x1,y1),(x2,y2)を対角線とするカラーcで塗られた長方形を描画
110+
111+void g_circlefill(int x0,int y0,unsigned int r,unsigned int c);
112+// (x0,y0)を中心に、半径r、カラーcで塗られた円を描画
113+
114+void g_putfont(int x,int y,unsigned int c,int bc,unsigned char n);
115+//8*8ドットのアルファベットフォント表示
116+//座標(x,y)、カラー番号c
117+//bc:バックグランドカラー、負数の場合無視
118+//n:文字番号
119+
120+void g_printstr(int x,int y,unsigned int c,unsigned int bc,unsigned char *s);
121+//座標(x,y)からカラー番号cで文字列sを表示、bc:バックグランドカラー
122+
123+void g_printnum(int x,int y,unsigned int c,unsigned int bc,unsigned int n);
124+//座標(x,y)にカラー番号cで数値nを表示、bc:バックグランドカラー
125+
126+void g_printnum2(int x,int y,unsigned int c,unsigned int bc,unsigned int n,unsigned char e);
127+//座標(x,y)にカラー番号cで数値nを表示、bc:バックグランドカラー、e桁で表示
128+
129+unsigned int g_color(int x,int y);
130+//座標(x,y)のVRAM上の現在のパレット番号を返す、画面外は0を返す
--- /dev/null
+++ b/mips/protozoa/library.c
@@ -0,0 +1,1108 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include <xc.h>
13+#include "main.h"
14+#include "compiler.h"
15+#include "api.h"
16+#include "interface/keyinput.h"
17+#include "stdlib.h"
18+#include "math.h"
19+
20+/*
21+ Local global variables used for graphic
22+ */
23+
24+static int g_gcolor=7;
25+static int g_prev_x=0;
26+static int g_prev_y=0;
27+
28+int lib_setdir(int mode,char* path){
29+ int ret;
30+ ret=FSchdir(path);
31+ if (mode==LIB_SETDIR && ret) err_file();
32+ return ret;
33+}
34+
35+int lib_getdir(){
36+ char* path;
37+ path=calloc_memory(32,-1);
38+ FSgetcwd (path,128);
39+ return (int)path;
40+}
41+
42+int lib_read(int mode, unsigned int label){
43+ unsigned int i,code,code2;
44+ static unsigned int pos=0;
45+ static unsigned int in_data=0;
46+ static unsigned char skip=0;
47+ if (label) {
48+ // RESTORE function
49+ switch(mode){
50+ case 0:
51+ // label is label data
52+ i=(int)search_label(label);
53+ if (!i) {
54+ err_data_not_found();
55+ return 0;
56+ }
57+ break;
58+ case 1:
59+ // label is pointer
60+ i=label;
61+ break;
62+ case 2:
63+ default:
64+ // Reset data/read
65+ pos=0;
66+ in_data=0;
67+ skip=0;
68+ return 0;
69+ }
70+ i-=(int)(&g_object[0]);
71+ pos=i/4;
72+ in_data=0;
73+ }
74+ // Get data
75+ if (in_data==0) {
76+ for(i=pos;i<g_objpos;i++){
77+ code=g_object[i];
78+ code2=g_object[i+1];
79+ if ((code&0xFFFF0000)!=0x04110000) continue;
80+ // "bgezal zero," assembly found.
81+ // Check if 0x00000020,0x00000021,0x00000022, or 0x00000023 follows
82+ if ((code2&0xfffffffc)!=0x00000020) {// add/addu/sub/subu zero,zero,zero
83+ // If not, skip following block (it's strig).
84+ i+=code&0x0000FFFF;
85+ continue;
86+ }
87+ // DATA region found.
88+ in_data=(code&0x0000FFFF)-1;
89+ pos=i+2;
90+ skip=code2&0x03;
91+ break;
92+ }
93+ if (g_objpos<=i) {
94+ err_data_not_found();
95+ return 0;
96+ }
97+ }
98+ if (label) {
99+ // RESTORE function. Return pointer.
100+ return ((int)&g_object[pos])+skip;
101+ } else {
102+ switch(mode){
103+ case 0:
104+ // READ() function
105+ in_data--;
106+ return g_object[pos++];
107+ case 1:
108+ default:
109+ // CREAD() function
110+ i=g_object[pos];
111+ i>>=skip*8;
112+ i&=0xff;
113+ if ((++skip)==4) {
114+ skip=0;
115+ in_data--;
116+ pos++;
117+ }
118+ return i;
119+ }
120+ }
121+}
122+
123+void reset_dataread(){
124+ lib_read(2,1);
125+}
126+
127+char* lib_midstr(int var_num, int pos, int len){
128+ int i;
129+ char* str;
130+ char* ret;
131+ if (0<=pos) {
132+ // String after "pos" position.
133+ str=(char*)(g_var_mem[var_num]+pos);
134+ } else {
135+ // String right "pos" characters.
136+ // Determine length
137+ str=(char*)g_var_mem[var_num];
138+ for(i=0;str[i];i++);
139+ if (0<=(i+pos)) {
140+ str=(char*)(g_var_mem[var_num]+i+pos);
141+ }
142+ }
143+ if (len<0) {
144+ // Length is not specified.
145+ // Return the string to the end.
146+ return str;
147+ }
148+ // Length is specified.
149+ // Construct temporary string containing specified number of characters.
150+ ret=alloc_memory((len+1+3)/4,-1);
151+ // Copy string.
152+ for(i=0;(ret[i]=str[i])&&(i<len);i++);
153+ ret[len]=0x00;
154+ return ret;
155+}
156+
157+void lib_clear(void){
158+ int i;
159+ // All variables (including temporary and permanent ones) will be integer 0
160+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
161+ g_var_mem[i]=0;
162+ }
163+ // Clear memory allocation area
164+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
165+ g_var_size[i]=0;
166+ }
167+ // Cancel PCG
168+ stopPCG();
169+ g_pcg_font=0;
170+ // Stop using graphic
171+ g_use_graphic=1; // Force set_graphmode(0) (see usegraphic() function)
172+ usegraphic(0);
173+}
174+
175+void lib_let_str(char* str, int var_num){
176+ int begin,end,size;
177+ // Save pointer
178+ g_var_mem[var_num]=(int)str;
179+ // Determine size
180+ for(size=0;str[size];size++);
181+ // Check if str is in heap area.
182+ begin=(int)str;
183+ end=(int)(&str[size]);
184+ if (begin<(int)(&g_heap_mem[0]) || (int)(&g_heap_mem[g_max_mem])<=end) {
185+ // String is not within allcated block
186+ return;
187+ }
188+ // Str is in heap area. Calculate values stored in heap data dimension
189+ begin-=(int)(&g_heap_mem[0]);
190+ begin>>=2;
191+ end-=(int)(&g_heap_mem[0]);
192+ end>>=2;
193+ size=end-begin+1;
194+ g_var_pointer[var_num]=begin;
195+ g_var_size[var_num]=size;
196+}
197+
198+int lib_rnd(){
199+ int y;
200+ y=g_rnd_seed;
201+ y = y ^ (y << 13);
202+ y = y ^ (y >> 17);
203+ y = y ^ (y << 5);
204+ g_rnd_seed=y;
205+ return y&0x7fff;
206+}
207+
208+char* lib_chr(int num){
209+ char* str;
210+ str=alloc_memory(1,-1);
211+ str[0]=num&0x000000FF;
212+ str[1]=0x00;
213+ return str;
214+}
215+
216+char* lib_dec(int num){
217+ char* str;
218+ int i,j,minus;
219+ char b[12];
220+ b[11]=0x00;
221+ if (num<0) {
222+ minus=1;
223+ num=0-num;
224+ } else {
225+ minus=0;
226+ }
227+ for (i=10;0<i;i--) {
228+ if (num==0 && i<10) break;
229+ b[i]='0'+rem10_32(num);
230+ num=div10_32(num);
231+ }
232+ if (minus) {
233+ b[i]='-';
234+ } else {
235+ i++;
236+ }
237+ str=alloc_memory(3,-1);
238+ for(j=0;str[j]=b[i++];j++);
239+ return str;
240+}
241+
242+char* lib_hex(int num, int width){
243+ char* str;
244+ int i,j,minus;
245+ char b[8];
246+ str=alloc_memory(3,-1);
247+ for(i=0;i<8;i++){
248+ b[i]="0123456789ABCDEF"[(num>>(i<<2))&0x0F];
249+ }
250+ // Width must be between 0 and 8;
251+ if (width<0||8<width) width=8;
252+ if (width==0) {
253+ // Width not asigned. Use minimum width.
254+ for(i=7;0<i;i--){
255+ if ('0'<b[i]) break;
256+ }
257+ } else {
258+ // Constant width
259+ i=width-1;
260+ }
261+ // Copy string to allocated block.
262+ for(j=0;0<=i;i--){
263+ str[j++]=b[i];
264+ }
265+ str[j]=0x00;
266+ return str;
267+}
268+
269+char* lib_connect_string(char* str1, char* str2){
270+ int i,j;
271+ char b;
272+ char* result;
273+ // Determine total length
274+ for(i=0;str1[i];i++);
275+ for(j=0;str2[j];j++);
276+ // Allocate a block for new string
277+ result=alloc_memory((i+j+1+3)/4,-1);
278+ // Create connected strings
279+ for(i=0;b=str1[i];i++) result[i]=b;
280+ for(j=0;b=str2[j];j++) result[i+j]=b;
281+ result[i+j]=0x00;
282+ free_temp_str(str1);
283+ free_temp_str(str2);
284+ return result;
285+}
286+
287+void lib_string(int mode){
288+ int i;
289+ switch(mode){
290+ case 0:
291+ // CR
292+ printchar('\n');
293+ return;
294+ case 1:
295+ // ,
296+ printcomma();
297+ return;
298+ default:
299+ return;
300+ }
301+}
302+
303+void* lib_label(unsigned int label){
304+ // This routine is used to jump to address dynamically determined
305+ // in the code; for example: "GOTO 100+I"
306+ unsigned int i,code,search;
307+ void* ret;
308+ if (label&0xFFFF0000) {
309+ // Label is not supported.
310+ // Line number must bs less than 65536.
311+ err_label_not_found();
312+ } else {
313+ // Line number
314+ ret=search_label(label);
315+ if (ret) return ret;
316+ // Line number not found.
317+ err_label_not_found();
318+ }
319+}
320+
321+int lib_keys(int mask){
322+ int keys;
323+ keys=readbuttons();
324+ keys=
325+ ((keys&KEYUP)? 0:1)|
326+ ((keys&KEYDOWN)? 0:2)|
327+ ((keys&KEYLEFT)? 0:4)|
328+ ((keys&KEYRIGHT)? 0:8)|
329+ ((keys&KEYSTART)? 0:16)|
330+ ((keys&KEYFIRE)? 0:32);
331+ return mask&keys;
332+}
333+
334+int lib_val(char* str){
335+ int i;
336+ int val=0;
337+ int sign=1;
338+ char b;
339+ // Skip blanc
340+ for(i=0;0<=str[i] && str[i]<0x21;i++);
341+ // Skip '+'
342+ if (str[i]=='+') i++;
343+ // Check '-'
344+ if (str[i]=='-') {
345+ sign=-1;
346+ i++;
347+ }
348+ // Check '0x' or '$'
349+ if (str[i]=='$' || str[i]=='0' && (str[i+1]=='x' || str[i+1]=='X')) {
350+ // Hexadecimal
351+ if (str[i++]=='0') i++;
352+ while(1) {
353+ b=str[i++];
354+ if ('0'<=b && b<='9') {
355+ val<<=4;
356+ val+=b-'0';
357+ } else if ('a'<=b && b<='f') {
358+ val<<=4;
359+ val+=b-'a'+10;
360+ } else if ('A'<=b && b<='F') {
361+ val<<=4;
362+ val+=b-'A'+10;
363+ } else {
364+ break;
365+ }
366+ }
367+ } else {
368+ // Decimal
369+ while(1) {
370+ b=str[i++];
371+ if ('0'<=b && b<='9') {
372+ val*=10;
373+ val+=b-'0';
374+ } else {
375+ break;
376+ }
377+ }
378+ }
379+ return val*sign;
380+}
381+
382+char* lib_input(){
383+ // Allocate memory for strings with 63 characters
384+ char *str=calloc_memory((63+1)/4,-1);
385+ // Enable PS/2 keyboard
386+ if (!inPS2MODE()) {
387+ ps2mode();
388+ ps2init();
389+ }
390+ // Clear key buffer
391+ do ps2readkey();
392+ while(vkey!=0);
393+ // Get string as a line
394+ lineinput(str,63);
395+ check_break();
396+ return str;
397+}
398+
399+unsigned char lib_inkey(int key){
400+ int i;
401+ // Enable PS/2 keyboard
402+ if (!inPS2MODE()) {
403+ ps2mode();
404+ ps2init();
405+ }
406+ if (key) {
407+ return ps2keystatus[key&0xff];
408+ } else {
409+ for(i=0;i<256;i++){
410+ if (ps2keystatus[i]) return i;
411+ }
412+ return 0;
413+ }
414+}
415+
416+void lib_usepcg(int mode){
417+ // Modes; 0: stop PCG, 1: use PCG, 2: reset PCG and use it
418+ switch(mode){
419+ case 0:
420+ // Stop PCG
421+ stopPCG();
422+ break;
423+ case 2:
424+ // Reset PCG and use it
425+ if (g_pcg_font) {
426+ free_non_temp_str(g_pcg_font);
427+ g_pcg_font=0;
428+ }
429+ // Continue to case 1:
430+ case 1:
431+ default:
432+ // Use PCG
433+ if (g_pcg_font) {
434+ startPCG(g_pcg_font,0);
435+ } else {
436+ g_pcg_font=alloc_memory(256*8/4,ALLOC_PCG_BLOCK);
437+ startPCG(g_pcg_font,1);
438+ }
439+ break;
440+ }
441+}
442+
443+void lib_pcg(unsigned int ascii,unsigned int fontdata1,unsigned int fontdata2){
444+ unsigned int* pcg;
445+ // If USEPCG has not yet executed, do now.
446+ if (!g_pcg_font) lib_usepcg(1);
447+ pcg=(unsigned int*)g_pcg_font;
448+ // 0 <= ascii <= 0xff
449+ ascii&=0xff;
450+ // Update font data
451+ ascii<<=1;
452+ pcg[ascii]=(fontdata1>>24)|((fontdata1&0xff0000)>>8)|((fontdata1&0xff00)<<8)|(fontdata1<<24);
453+ pcg[ascii+1]=(fontdata2>>24)|((fontdata2&0xff0000)>>8)|((fontdata2&0xff00)<<8)|(fontdata2<<24);
454+}
455+
456+void lib_usegraphic(int mode){
457+ usegraphic(mode);
458+ // Move current point to (0,0)
459+ g_prev_x=g_prev_y=0;
460+}
461+void lib_wait(int period){
462+ int i;
463+ unsigned short dcount;
464+ for(i=0;i<period;i++){
465+ dcount=drawcount;
466+ while(dcount==drawcount){
467+ asm (WAIT);
468+ check_break();
469+ }
470+ }
471+}
472+
473+int lib_graphic(int v0,enum functions func){
474+ unsigned char b;
475+ int x1=g_libparams[1];
476+ int y1=g_libparams[2];
477+ int x2=g_libparams[3];
478+ int y2=g_libparams[4];
479+ // Disable if graphic area is not defined.
480+ if (!g_graphic_area) return;
481+ // If C is omitted in parameters, use current color.
482+ if (v0==-1) {
483+ v0=g_gcolor;
484+ }
485+ // If X1 or Y1 is 0x80000000, use the previous values.
486+ if (x1==0x80000000) x1=g_prev_x;
487+ if (y1==0x80000000) y1=g_prev_y;
488+ switch(func){
489+ case FUNC_POINT:// X1,Y1
490+ g_prev_x=x1;
491+ g_prev_y=y1;
492+ break;
493+ case FUNC_PSET:// X1,Y1[,C]
494+ g_pset(x1,y1,v0);
495+ g_prev_x=x1;
496+ g_prev_y=y1;
497+ break;
498+ case FUNC_LINE:// X1,Y1,X2,Y2[,C]
499+ if (y1==y2) g_hline(x1,x2,y1,v0);
500+ else g_gline(x1,y1,x2,y2,v0);
501+ g_prev_x=x2;
502+ g_prev_y=y2;
503+ break;
504+ case FUNC_BOXFILL:// X1,Y1,X2,Y2[,C]
505+ g_boxfill(x1,y1,x2,y2,v0);
506+ g_prev_x=x2;
507+ g_prev_y=y2;
508+ break;
509+ case FUNC_CIRCLE:// X1,Y1,R[,C]
510+ g_circle(x1,y1,x2,v0);
511+ g_prev_x=x1;
512+ g_prev_y=y1;
513+ break;
514+ case FUNC_CIRCLEFILL:// X1,Y1,R[,C]
515+ g_circlefill(x1,y1,x2,v0);
516+ g_prev_x=x1;
517+ g_prev_y=y1;
518+ break;
519+ case FUNC_GPRINT:// X1,Y1,C,BC,S$
520+ g_printstr(x1,y1,x2,y2,(unsigned char*)v0);
521+ // Move current X,Y according to the string
522+ while(b=((unsigned char*)v0)[0]){
523+ v0++;
524+ if (b==0x0d) {
525+ x1=0;
526+ y1+=8;
527+ } else {
528+ x1+=8;
529+ }
530+ }
531+ g_prev_x=x1;
532+ g_prev_y=y1;
533+ break;
534+ case FUNC_PUTBMP2:// X1,Y1,M,N,BMP(label)
535+ // Search CDATA
536+ // It starts from either 0x00000020,0x00000021,0x00000022, or 0x00000023.
537+ while((((unsigned int*)v0)[0]&0xfffffffc)!=0x00000020) v0+=4;
538+ // CDATA starts from next word.
539+ // MLB 3 bytes show skip byte(s).
540+ v0+=4+(((unsigned int*)v0)[0]&0x03);
541+ // Contunue to FUNC_PUTBMP.
542+ case FUNC_PUTBMP:// X1,Y1,M,N,BMP(pointer)
543+ g_putbmpmn(x1,y1,x2,y2,(const unsigned char*)v0);
544+ g_prev_x=x1;
545+ g_prev_y=y1;
546+ break;
547+ case FUNC_GCOLOR:// (X1,Y1)
548+ v0=g_color(x1,y1);
549+ break;
550+ default:
551+ break;
552+ }
553+ return v0;
554+}
555+
556+void lib_var_push(int a0, int a1, int* sp){
557+ // Note that sp[1] is used for string return address
558+ // sp[2] can be used to store flags
559+ // sp[3] etc can be used to store variable values
560+ int i,params;
561+ unsigned char varnum;
562+ unsigned int strflags=0;
563+ int stack=3;
564+ for(i=0;i<8;i++){
565+ // Prepare parameter
566+ switch(i){
567+ case 0:
568+ params=a0;
569+ break;
570+ case 4:
571+ params=a1;
572+ break;
573+ default:
574+ break;
575+ }
576+ // Get variable number
577+ varnum=params&0xff;
578+ params>>=8;
579+ if (varnum==0) break; // No more variable. End the loop.
580+ varnum--;
581+ sp[stack++]=g_var_mem[varnum];
582+ if (g_var_size[varnum] && g_var_mem[varnum]==(int)(&g_var_pointer[varnum])) {
583+ // strflags change using varnum
584+ strflags|=1<<i;
585+ // Copy to VAR_BLOCK
586+ move_to_perm_block(varnum);
587+ }
588+ // Clear variable
589+ g_var_mem[varnum]=0;
590+ }
591+ // Store string flags
592+ sp[2]=strflags;
593+}
594+
595+void lib_var_pop(int a0, int a1, int* sp){
596+ // Note that sp is 4 bytes larger than that in lib_var_push
597+ // sp[1] was used to store flags
598+ // sp[2] etc can be used to store variable values
599+ int i,params;
600+ unsigned char varnum;
601+ int stack=2;
602+ unsigned int strflags=sp[1];
603+ for(i=0;i<8;i++){
604+ // Prepare parameter
605+ switch(i){
606+ case 0:
607+ params=a0;
608+ break;
609+ case 4:
610+ params=a1;
611+ break;
612+ default:
613+ break;
614+ }
615+ // Get variable number
616+ varnum=params&0xff;
617+ params>>=8;
618+ if (varnum==0) break; // No more variable. End the loop.
619+ varnum--;
620+ g_var_mem[varnum]=sp[stack++];
621+ if (strflags&(1<<i)) {
622+ // Restore from VAR_BLOCK
623+ move_from_perm_block(varnum);
624+ }
625+ }
626+}
627+
628+
629+char* lib_sprintf(char* format, int data){
630+ char* str;
631+ int i;
632+ char temp[4];
633+ if (!format) format="%g";
634+ i=snprintf((char*)(&temp[0]),4,format,data)+1;
635+ str=alloc_memory((i+3)/4,-1);
636+ snprintf(str,i,format,data);
637+ return str;
638+}
639+
640+int lib_floatfuncs(int ia0,int iv0,enum functions a1){
641+ volatile float a0,v0;
642+ ((int*)(&a0))[0]=ia0;
643+ ((int*)(&v0))[0]=iv0;
644+ switch(a1){
645+ case FUNC_FLOAT:
646+ v0=(float)iv0;
647+ break;
648+ case FUNC_INT:
649+ return (int)v0;
650+ case FUNC_VALSHARP:
651+ v0=strtof((const char*)iv0,0);
652+ break;
653+ case FUNC_SIN:
654+ v0=sinf(v0);
655+ break;
656+ case FUNC_COS:
657+ v0=cosf(v0);
658+ break;
659+ case FUNC_TAN:
660+ v0=tanf(v0);
661+ break;
662+ case FUNC_ASIN:
663+ v0=asinf(v0);
664+ break;
665+ case FUNC_ACOS:
666+ v0=acosf(v0);
667+ break;
668+ case FUNC_ATAN:
669+ v0=atanf(v0);
670+ break;
671+ case FUNC_ATAN2:
672+ v0=atan2f(v0,a0);
673+ break;
674+ case FUNC_SINH:
675+ v0=sinhf(v0);
676+ break;
677+ case FUNC_COSH:
678+ v0=coshf(v0);
679+ break;
680+ case FUNC_TANH:
681+ v0=tanhf(v0);
682+ break;
683+ case FUNC_EXP:
684+ v0=expf(v0);
685+ break;
686+ case FUNC_LOG:
687+ v0=logf(v0);
688+ break;
689+ case FUNC_LOG10:
690+ v0=log10f(v0);
691+ break;
692+ case FUNC_POW:
693+ v0=powf(v0,a0);
694+ break;
695+ case FUNC_SQRT:
696+ v0=sqrtf(v0);
697+ break;
698+ case FUNC_CEIL:
699+ v0=ceilf(v0);
700+ break;
701+ case FUNC_FLOOR:
702+ v0=floorf(v0);
703+ break;
704+ case FUNC_FABS:
705+ v0=fabsf(v0);
706+ break;
707+ case FUNC_MODF:
708+ v0=modff(v0,(void*)&a0);
709+ break;
710+ case FUNC_FMOD:
711+ v0=fmodf(v0,a0);
712+ break;
713+ default:
714+ err_unknown();
715+ break;
716+ }
717+ return ((int*)(&v0))[0];
718+};
719+
720+int* lib_dim(int varnum, int argsnum, int* sp){
721+ int i,j;
722+ static int* heap;
723+ // Calculate total length.
724+ int len=0; // Total length
725+ int size=1; // Size of current block
726+ for(i=1;i<=argsnum;i++){
727+ size*=sp[i]+1;
728+ len+=size;
729+ }
730+ // Allocate memory
731+ heap=calloc_memory(len,varnum);
732+ // Construct pointers
733+ len=0;
734+ size=1;
735+ for(i=1;i<argsnum;i++){
736+ size*=sp[i]+1;
737+ for(j=0;j<size;j++){
738+ heap[len+j]=(int)&heap[len+size+(sp[i+1]+1)*j];
739+ }
740+ len+=size;
741+ }
742+ return heap;
743+};
744+
745+int lib_file_textlen(FSFILE* fhandle){
746+ char buff[128];
747+ int i,textlen,len,seek;
748+ seek=FSftell(fhandle);
749+ len=FSfread(&buff[0],1,128,fhandle);
750+ textlen=0;
751+ for(i=0;i<len-1;i++){ // Read 127 bytes for supporting CRLF
752+ if (buff[i]==0x0d) {
753+ if (i<len && buff[i+1]==0x0a) i++;
754+ break;
755+ } else if (buff[i]==0x0a) {
756+ break;
757+ }
758+ if (i==len-2) {
759+ // reached the end of buffer. Read next 127 bytes
760+ textlen+=127;
761+ buff[0]=buff[127];
762+ len=FSfread(&buff[1],1,127,fhandle);
763+ // Continue with i=0
764+ i=-1;
765+ }
766+ }
767+ // The last return code must be included to caluclate total length.
768+ textlen+=i+1;
769+ // Return to original position
770+ FSfseek(fhandle,seek,SEEK_SET);
771+ return textlen;
772+}
773+
774+int lib_file(enum functions func, int a0, int a1, int v0){
775+ static FSFILE* s_fhandle[2]={0,0};
776+ static char activefhandle=0;
777+ static int numinline=0;
778+ FSFILE* fhandle=0;
779+ int i;
780+ int buff[1];
781+ char* str;
782+ if (activefhandle) fhandle=s_fhandle[activefhandle-1];
783+ switch(func){
784+ case FUNC_FINIT:
785+ // This function is not BASIC statement/function but used from
786+ // running routine.
787+ for(i=0;i<2;i++){
788+ if (s_fhandle[i]) FSfclose(s_fhandle[i]);
789+ s_fhandle[i]=0;
790+ }
791+ activefhandle=0;
792+ numinline=0;
793+ break;
794+ case FUNC_FOPEN: // Return 0 when called as a function.
795+ case FUNC_FOPENST: // Stop with error when called as a statement.
796+ activefhandle=0;
797+ // Check if file handle is free to use, first.
798+ switch(v0){
799+ case 0:
800+ // File handle was not designated
801+ // Force handle=1 and continue to following cases.
802+ v0=1;
803+ case 1:
804+ case 2:
805+ // File handle was designated
806+ // Check if not used yet.
807+ if (s_fhandle[v0-1]) {
808+ // This file handle has been occupied.
809+ err_file();
810+ return 0;
811+ }
812+ // OK. This file handle can be asigned for new file opened.
813+ break;
814+ default:
815+ err_invalid_param();
816+ return 0;
817+ }
818+ // Open a file
819+ fhandle=FSfopen ((const char*) a0, (const char*) a1);
820+ if (!fhandle) {
821+ if (func==FUNC_FOPENST) err_file();
822+ return 0;
823+ }
824+ // The file is succesfully opened. Asign file handle.
825+ s_fhandle[v0-1]=fhandle;
826+ activefhandle=v0;
827+ return v0;
828+ case FUNC_FILE:
829+ switch(v0){
830+ case 1:
831+ case 2:
832+ if (s_fhandle[v0]) {
833+ activefhandle=v0;
834+ break;
835+ }
836+ default:
837+ err_invalid_param();
838+ }
839+ break;
840+ case FUNC_FCLOSE:
841+ switch(v0){
842+ case 0:
843+ break;
844+ case 1:
845+ case 2:
846+ if (s_fhandle[v0-1]) activefhandle=v0;
847+ if (activefhandle) fhandle=s_fhandle[activefhandle-1];
848+ break;
849+ default:
850+ err_invalid_param();
851+ }
852+ if (fhandle) {
853+ FSfclose(fhandle);
854+ s_fhandle[activefhandle-1]=0;
855+ }
856+ activefhandle=0;
857+ break;
858+ case FUNC_FINPUT:
859+ if (fhandle) {
860+ // Determine text length if called without parameter
861+ if (v0==0) v0=lib_file_textlen(fhandle);
862+ // Allocate temporary area for string
863+ str=alloc_memory((v0+1+3)/4,-1);
864+ // Read from SD card
865+ v0=FSfread(str,1,v0,fhandle);
866+ // Null string at the end.
867+ str[v0]=0;
868+ return (int)str;
869+ } else {
870+ err_file();
871+ return (int)"";
872+ }
873+ case FUNC_FPRINTSTR:
874+ // Like lib_printstr()
875+ for(i=0;((char*)v0)[i];i++);
876+ if (fhandle) {
877+ if (!FSfwrite((char*)v0,1,i,fhandle)) err_file();
878+ } else err_file();
879+ numinline+=i;
880+ break;
881+ case FUNC_FSTRING:
882+ // Like lib_string()
883+ switch(v0){
884+ case 0:
885+ // CR
886+ lib_file(FUNC_FPRINTSTR,a0,a1,(int)"\r\n");
887+ numinline=0;
888+ break;
889+ case 1:
890+ // ,
891+ i=rem10_32(numinline);
892+ lib_file(FUNC_FPRINTSTR,a0,a1,(int)(" "+i));
893+ break;
894+ default:
895+ break;
896+ }
897+ break;
898+ case FUNC_FGET:
899+ if (fhandle) return FSfread((void*)a0,1,v0,fhandle);
900+ err_file();
901+ break;
902+ case FUNC_FPUT:
903+ if (fhandle) return FSfwrite((void*)a0,1,v0,fhandle);
904+ err_file();
905+ break;
906+ case FUNC_FGETC:
907+ if (fhandle) {
908+ // Note: Little endian.
909+ if (FSfread((void*)&buff[0],1,1,fhandle)) return buff[0]&0xff;
910+ else return -1;
911+ }
912+ err_file();
913+ break;
914+ case FUNC_FPUTC:
915+ if (fhandle) {
916+ // Note: Little endian.
917+ buff[0]=v0;
918+ return FSfwrite((void*)&buff[0],1,1,fhandle);
919+ }
920+ err_file();
921+ break;
922+ case FUNC_FSEEK:
923+ if (fhandle) return FSfseek(fhandle,v0,SEEK_SET);
924+ err_file();
925+ break;
926+ case FUNC_FTELL:
927+ if (fhandle) return FSftell(fhandle);
928+ err_file();
929+ break;
930+ case FUNC_FLEN:
931+ if (fhandle) return fhandle->size;
932+ err_file();
933+ break;
934+ case FUNC_FEOF:
935+ if (fhandle) return (fhandle->size<=FSftell(fhandle)) ? 1:0;
936+ err_file();
937+ break;
938+ case FUNC_FREMOVE:
939+ return FSremove((const char *)v0);
940+ default:
941+ err_unknown();
942+ }
943+ return v0;
944+}
945+
946+int _call_library(int a0,int a1,int a2,enum libs a3);
947+
948+void call_library(void){
949+ // Store s6 in g_s6
950+ asm volatile("la $a2,%0"::"i"(&g_s6));
951+ asm volatile("sw $s6,0($a2)");
952+ // Copy $v0 to $a2 as 3rd argument of function
953+ asm volatile("addu $a2,$v0,$zero");
954+ // Store sp in g_libparams
955+ asm volatile("la $v0,%0"::"i"(&g_libparams));
956+ asm volatile("sw $sp,0($v0)");
957+ // Jump to main routine
958+ asm volatile("j _call_library");
959+}
960+
961+int _call_library(int a0,int a1,int v0,enum libs a3){
962+ // usage: call_lib_code(LIB_XXXX);
963+ // Above code takes 2 words.
964+ check_break();
965+ switch(a3 & LIB_MASK){
966+ case LIB_FLOAT:
967+ return lib_float(a0,v0,(enum operator)(a3 & OP_MASK)); // see operator.c
968+ case LIB_FLOATFUNCS:
969+ return lib_floatfuncs(a0,v0,(enum functions)(a3 & FUNC_MASK));
970+ case LIB_STRNCMP:
971+ return strncmp((char*)g_libparams[1],(char*)g_libparams[2],v0);
972+ case LIB_MIDSTR:
973+ return (int)lib_midstr(a1,v0,a0);
974+ case LIB_RND:
975+ return (int)lib_rnd();
976+ case LIB_DEC:
977+ return (int)lib_dec(v0);
978+ case LIB_HEX:
979+ return (int)lib_hex(v0,a0);
980+ case LIB_CHR:
981+ return (int)lib_chr(v0);
982+ case LIB_VAL:
983+ return lib_val((char*)v0);
984+ case LIB_LETSTR:
985+ lib_let_str((char*)v0,a0);
986+ return;
987+ case LIB_CONNECT_STRING:
988+ return (int)lib_connect_string((char*)a0, (char*)v0);
989+ case LIB_STRING:
990+ lib_string(v0);
991+ return v0;
992+ case LIB_PRINTSTR:
993+ printstr((char*)v0);
994+ return v0;
995+ case LIB_GRAPHIC:
996+ return lib_graphic(v0, (enum functions)(a3 & FUNC_MASK));
997+ case LIB_SPRINTF:
998+ return (int)lib_sprintf((char*)v0,a0);
999+ case LIB_VAR_PUSH:
1000+ lib_var_push(a0,a1,g_libparams);
1001+ return v0;
1002+ case LIB_VAR_POP:
1003+ lib_var_pop(a0,a1,g_libparams);
1004+ return v0;
1005+ case LIB_SCROLL:
1006+ scroll(g_libparams[1],v0);
1007+ return v0;
1008+ case LIB_FILE:
1009+ return lib_file((enum functions)(a3 & FUNC_MASK),g_libparams[1],g_libparams[2],v0);
1010+ case LIB_KEYS:
1011+ return lib_keys(v0);
1012+ case LIB_INKEY:
1013+ return (int)lib_inkey(v0);
1014+ case LIB_CURSOR:
1015+ setcursor(g_libparams[1],v0,cursorcolor);
1016+ return v0;
1017+ case LIB_SOUND:
1018+ set_sound((unsigned long*)v0,a0);
1019+ return v0;
1020+ case LIB_MUSICFUNC:
1021+ return musicRemaining(a0);
1022+ case LIB_MUSIC:
1023+ set_music((char*)v0,a0);
1024+ return v0;
1025+ case LIB_PLAYWAVE:
1026+ play_wave((char*)g_libparams[1],v0);
1027+ return v0;
1028+ case LIB_PLAYWAVEFUNC:
1029+ return waveRemaining(v0);
1030+ case LIB_SETDRAWCOUNT:
1031+ drawcount=(v0&0x0000FFFF);
1032+ return v0;
1033+ case LIB_GETDIR:
1034+ return lib_getdir();
1035+ case LIB_SETDIRFUNC:
1036+ case LIB_SETDIR:
1037+ return lib_setdir(a3,(char*)v0);
1038+ case LIB_DRAWCOUNT:
1039+ return drawcount;
1040+ case LIB_SYSTEM:
1041+ return lib_system(a0, a1 ,v0, a3, g_gcolor, g_prev_x, g_prev_y);
1042+ case LIB_RESTORE:
1043+ return lib_read(0,v0);
1044+ case LIB_RESTORE2:
1045+ return lib_read(1,v0);
1046+ case LIB_READ:
1047+ return lib_read(0,0);
1048+ case LIB_CREAD:
1049+ return lib_read(1,0);
1050+ case LIB_LABEL:
1051+ return (int)lib_label(v0);
1052+ case LIB_INPUT:
1053+ return (int)lib_input();
1054+ case LIB_USEGRAPHIC:
1055+ lib_usegraphic(v0);
1056+ return v0;
1057+ case LIB_USEPCG:
1058+ lib_usepcg(v0);
1059+ return v0;
1060+ case LIB_PCG:
1061+ lib_pcg(g_libparams[1],g_libparams[2],v0);
1062+ return v0;
1063+ case LIB_BGCOLOR: // BGCOLOR R,G,B
1064+ set_bgcolor(v0,g_libparams[1],g_libparams[2]); //set_bgcolor(b,r,g);
1065+ return v0;
1066+ case LIB_PALETTE: // PALETTE N,R,G,B
1067+ set_palette(g_libparams[1],v0,g_libparams[2],g_libparams[3]); // set_palette(n,b,r,g);
1068+ return v0;
1069+ case LIB_GPALETTE:// GPALETTE N,R,G,B
1070+ if (g_graphic_area) g_set_palette(g_libparams[1],v0,g_libparams[2],g_libparams[3]); // g_set_palette(n,b,r,g);
1071+ return v0;
1072+ case LIB_CLS:
1073+ clearscreen();
1074+ return v0;
1075+ case LIB_GCLS:
1076+ if (g_graphic_area) g_clearscreen();
1077+ g_prev_x=g_prev_y=0;
1078+ return v0;
1079+ case LIB_WIDTH:
1080+ videowidth(v0);
1081+ return v0;
1082+ case LIB_COLOR:
1083+ setcursorcolor(v0);
1084+ return v0;
1085+ case LIB_GCOLOR:
1086+ g_gcolor=v0;
1087+ return v0;
1088+ case LIB_WAIT:
1089+ lib_wait(v0);
1090+ return v0;
1091+ case LIB_CLEAR:
1092+ lib_clear();
1093+ return v0;
1094+ case LIB_DIM:
1095+ return (int)lib_dim(a0,a1,(int*)v0);
1096+#ifdef __DEBUG
1097+ case LIB_DEBUG:
1098+ asm volatile("nop");
1099+ return v0;
1100+#endif
1101+ case LIB_DIV0:
1102+ err_div_zero();
1103+ return v0;
1104+ default:
1105+ err_unknown();
1106+ return v0;
1107+ }
1108+}
\ No newline at end of file
--- /dev/null
+++ b/mips/protozoa/linker.c
@@ -0,0 +1,394 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include "compiler.h"
13+
14+unsigned int g_label;
15+
16+char* get_label(void){
17+ unsigned int i;
18+ char b1;
19+ int prevpos;
20+ next_position();
21+ prevpos=g_srcpos;
22+ i=0;
23+ b1=g_source[g_srcpos];
24+ if ('0'<= b1 && b1<='9') {
25+ // May be line number
26+ do {
27+ i*=10;
28+ i+=b1-'0';
29+ g_srcpos++;
30+ b1=g_source[g_srcpos];
31+ } while ('0'<= b1 && b1<='9');
32+ // Check if end of the statement.
33+ if (i==0 || 65535<i) {
34+ // Line number 0 or more than 65535 is not available
35+ g_srcpos=prevpos;
36+ return ERR_SYNTAX;
37+ } else if (get_operator()) {
38+ // Oparator not found.
39+ g_label=i;
40+ return 0;
41+ } else {
42+ // This is not constant line number.
43+ g_srcpos=prevpos;
44+ g_label=0;
45+ return 0;
46+ }
47+ } else if ('A'<=b1 && b1<='Z') {
48+ // May be label
49+ do {
50+ // First character must be A-Z
51+ // From second, A-Z and 0-9 can be used.
52+ i*=36;
53+ if ('0'<=b1 && b1<='9') {
54+ i+=b1-'0';
55+ } else if (g_srcpos==prevpos) {
56+ // First character must be A-Z.
57+ // Subtract 9, resulting 1-26 but not 10-35.
58+ // This subtraction is required to maintain
59+ // final number being <0x80000000.
60+ i+=b1-'A'+1;
61+ } else {
62+ i+=b1-'A'+10;
63+ }
64+ g_srcpos++;
65+ b1=g_source[g_srcpos];
66+ } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z');
67+ // Length of the label must be between 2 and 6.
68+ if (g_srcpos-prevpos<2 || 6<g_srcpos-prevpos) {
69+ g_srcpos=prevpos;
70+ return ERR_LABEL_LONG;
71+ }
72+ // Must not be a function
73+ next_position();
74+ if (g_source[g_srcpos]=='(') {
75+ g_srcpos=prevpos;
76+ g_label=0;
77+ return 0;
78+ }
79+ g_label=i+65536;
80+ return 0;
81+ } else {
82+ g_label=0;
83+ return 0;
84+ }
85+}
86+
87+void* search_label(unsigned int label){
88+ unsigned int i,code,search1,search2;
89+ if (label&0xFFFF0000) {
90+ // Label
91+ search1=0x3C160000|((label>>16)&0x0000FFFF); //lui s6,yyyy;
92+ search2=0x36D60000|(label&0x0000FFFF); //ori s6,s6,zzzz;
93+ for(i=0;i<g_objpos;i++){
94+ code=g_object[i];
95+ if (code==search1) {
96+ if (g_object[i+1]==search2) {
97+ // Label number found
98+ return &(g_object[i]);
99+ }
100+ }
101+ if (code&0xFFFF0000==0x04110000) {
102+ // "bgezal zero," assembly found. Skip following block (strig).
103+ i+=code&0x0000FFFF;
104+ }
105+ }
106+ // Line number not found.
107+ return 0;
108+ } else {
109+ // Line number
110+ search1=0x34160000|label; //ori s6,zero,xxxx;
111+ for(i=0;i<g_objpos;i++){
112+ code=g_object[i];
113+ if (code==search1) {
114+ // Line number found
115+ return &(g_object[i]);
116+ }
117+ if (code&0xFFFF0000==0x04110000) {
118+ // "bgezal zero," assembly found. Skip following block (strig).
119+ i+=code&0x0000FFFF;
120+ }
121+ }
122+ // Line number not found.
123+ return 0;
124+ }
125+}
126+
127+void* search_breakout(unsigned int start, int* prevcode){
128+ unsigned int pos,code1,depth;
129+ // Start search from start point where BREAK statement is used.
130+ depth=0;
131+ for(pos=start;pos<g_objpos;pos++){
132+ code1=g_object[pos];
133+ switch(code1>>16){
134+ case 0x0411:
135+ // "bgezal zero," assembly found. Skip following block (strig).
136+ pos+=code1&0x0000FFFF;
137+ break;
138+ case 0x0820: // FOR
139+ case 0x0821: // WHILE
140+ case 0x0822: // DO
141+ depth++;
142+ break;
143+ case 0x0830: // NEXT
144+ case 0x0831: // WEND
145+ case 0x0832: // LOOP
146+ if (0<depth) {
147+ depth--;
148+ break;
149+ }
150+ // Destination found.
151+ // Previous code will be also set if required for CONTINUE statement.
152+ if (prevcode) prevcode[0]=g_object[pos-1];
153+ return (void*)&g_object[pos];
154+ default:
155+ break;
156+ }
157+ }
158+ return 0;
159+}
160+
161+void* search_ifout(unsigned int start){
162+ unsigned int pos,code1,depth;
163+ // Start search from start point where BREAK statement is used.
164+ depth=0;
165+ for(pos=start;pos<g_objpos;pos++){
166+ code1=g_object[pos];
167+ switch(code1>>16){
168+ case 0x0411:
169+ // "bgezal zero," assembly found. Skip following block (strig).
170+ pos+=code1&0x0000FFFF;
171+ break;
172+ case 0x3000: // Block marker
173+ if (code1==0x30008000) {
174+ // end block
175+ if (0<depth) {
176+ depth--;
177+ break;
178+ }
179+ // Destination found.
180+ return (void*)&g_object[pos];
181+ } else if (code1==0x30000000) {
182+ // begin block
183+ depth++;
184+ break;
185+ } else {
186+ break;
187+ }
188+ default:
189+ break;
190+ }
191+ }
192+ return 0;
193+}
194+
195+/*
196+ Following codes are dedicated to specific use:
197+ 0x0411xxxx: String/data block
198+ Use 0x0413xxxx (bzegall zero,xxxx) for other cases to get PC to $ra
199+ 0x0810xxxx, 0x0811xxxx: GOTO statement
200+ 0x0812xxxx, 0x0813xxxx: GOSUB statement
201+ 0x0814xxxx, 0x0815xxxx: SOUND etc, for setting v0 as pointer to DATA array.
202+ 0x0816xxxx: BREAK statemant and relatives
203+ 0x08160000: BREAK
204+ 0x08160008: CONTINUE
205+ 0x08160100: Jump to next ELSE, ELSEIF or ENDIF
206+ 0x082xyyyy: Begin block (FOR/DO/WHILE)
207+ 0x083xyyyy: End block (NEXT/LOOP/WEND)
208+ 0x00000020, 0x00000021,
209+ 0x00000022, 0x00000023: Marker for begining the DATA region.
210+ MLB 2 bits show skip byte length in DATA.
211+ 0x30000000: Begin block (IF-THEN-ELSEIF-ELSE-ENDIF)
212+ 0x30008000: End block (IF-THEN-ELSEIF-ELSE-ENDIF)
213+ 0x3000Fxxx: General purpose NOP with value 0x0000-0x0FFF.
214+
215+ IF-THEN-ELSEIF-ELSE-ENDIF is written as follows:
216+ IF-THEN: 0x30000000 0x10400000 0x30000000
217+ ELSEIF-THEN: 0x08160100 0x30008000 (conditional expression) 0x10400000 0x30000000
218+ ELSE: 0x08160100 0x30008000 0x30000000
219+ ENDIF: 0x30008000 0x30008000
220+ , where "0x10400000 0x30000000" and "0x08160100 0x30008000" will be replaced by
221+ codes jumping to next 0x30008000. The 0x30000000 - 0x30008000 blocks will be skipped.
222+*/
223+
224+char* link(void){
225+ int pos;
226+ unsigned int code1,code2,label;
227+ g_fileline=0;
228+ for(pos=0;pos<g_objpos;pos++){
229+ code1=g_object[pos];
230+ switch(code1>>16){
231+ case 0x0411:
232+ // "bgezal zero," assembly found. Skip following block (strig).
233+ pos+=code1&0x0000FFFF;
234+ break;
235+ case 0x3416:
236+ // "ori s6,zero,xxxx" found this is the first word in a line.
237+ g_fileline++;
238+ g_line=code1&0x0000FFFF;
239+ break;
240+ case 0x0810:
241+ // GOTO
242+ code2=g_object[pos+1];
243+ if ((code2&0xFFFF0000)!=0x08110000) continue;
244+ code1&=0x0000FFFF;
245+ code2&=0x0000FFFF;
246+ label=(code1<<16)|code2;
247+ code1=(int)search_label(label);
248+ g_label=label;
249+ if (!code1) return ERR_LABEL_NF;
250+ code1&=0x0FFFFFFF;
251+ code1>>=2;
252+ code1|=0x08000000; // j xxxx
253+ g_object[pos++]=code1;
254+ g_object[pos]=0x00000000; // nop
255+ break;
256+ case 0x0812:
257+ // GOSUB
258+ code2=g_object[pos+1];
259+ if ((code2&0xFFFF0000)!=0x08130000) continue;
260+ code1&=0x0000FFFF;
261+ code2&=0x0000FFFF;
262+ label=(code1<<16)|code2;
263+ code2=(int)search_label(label);
264+ g_label=label;
265+ if (!code2) return ERR_LABEL_NF;
266+ code2&=0x0FFFFFFF;
267+ code2>>=2;
268+ code2|=0x08000000; // j xxxx
269+ g_object[pos++]=0x00000000; // nop
270+ g_object[pos]=code2;
271+ break;
272+ case 0x0814:
273+ // SOUND etc, for setting v0 as pointer to label/line
274+ code2=g_object[pos+1];
275+ if ((code2&0xFFFF0000)!=0x08150000) continue;
276+ code1&=0x0000FFFF;
277+ code2&=0x0000FFFF;
278+ label=(code1<<16)|code2;
279+ code1=(int)search_label(label);
280+ g_label=label;
281+ if (!code1) return ERR_LABEL_NF;
282+ g_object[pos++]=0x3C020000|((code1>>16)&0x0000FFFF); // lui v0,xxxx
283+ g_object[pos] =0x34420000|(code1&0x0000FFFF); // ori v0,v0,xxxx
284+ break;
285+ case 0x0816:
286+ switch(code1&0xFFFF) {
287+ case 0x0000:
288+ // BREAK statement
289+ // Find next the NEXT or WHILE statement and insert jump code after this.
290+ g_label=g_line;
291+ code1=(int)search_breakout(pos,0);
292+ if (!code1) return ERR_INVALID_BREAK;
293+ code1&=0x0FFFFFFF;
294+ code1>>=2;
295+ code1|=0x08000000; // j xxxx
296+ g_object[pos]=code1;
297+ break;
298+ case 0x0008:
299+ // CONTINUE statement
300+ // Find next the NEXT or WHILE statement and insert jump code after this.
301+ g_label=g_line;
302+ code1=(int)search_breakout(pos,&g_temp);
303+ if (!code1) return ERR_INVALID_BREAK;
304+ if (0x3000F000 == (g_temp&0xFFFFF000)) {
305+ // WEND or LOOP statement found
306+ code1-=(g_temp&0x0FFF)<<2;
307+ } else {
308+ // NEXT statement found
309+ code1-=3<<2;
310+ }
311+ code1&=0x0FFFFFFF;
312+ code1>>=2;
313+ code1|=0x08000000; // j xxxx
314+ g_object[pos]=code1;
315+ break;
316+ case 0x0100:
317+ // Jump to next ENDIF
318+ g_label=g_line;
319+ // "pos+2" is for skipping next code (must be 0x30008000)
320+ code1=(int)search_ifout(pos+2);
321+ if (!code1) return ERR_INVALID_ELSEIF;
322+ code1&=0x0FFFFFFF;
323+ code1>>=2;
324+ code1|=0x08000000; // j xxxx
325+ g_object[pos]=code1;
326+ break;
327+ default:
328+ break;
329+ }
330+ break;
331+ case 0x3000:
332+ // Block marker
333+ switch(code1&0xFFFF) {
334+ case 0x0000:
335+ // Begin if block
336+ if (g_object[pos-1]==0x10400000) { // beq v0,zero,xxxx
337+ // IF-THEN or ELSEIF-THEN
338+ // Jump to next ELSE, ELSEIF or ENDIF
339+ g_label=g_line;
340+ // "pos+1" is for skipping current code (0x30000000)
341+ code1=(int)search_ifout(pos+1);
342+ if (!code1) return ERR_INVALID_ELSEIF;
343+ code1-=(int)(&g_object[pos]);
344+ code1>>=2;
345+ code1&=0x0000FFFF;
346+ code1|=0x10400000; // beq v0,zero,xxxx
347+ g_object[pos-1]=code1;
348+ break;
349+ }
350+ break;
351+ default:
352+ break;
353+ }
354+ break;
355+ case 0x0820: // FOR
356+ case 0x0830: // NEXT
357+ case 0x0821: // WHILE
358+ case 0x0831: // WEND
359+ case 0x0822: // DO
360+ case 0x0832: // WHILE
361+ // These are used for detecing the depth of structures.
362+ // Change them to stack increase/decrease commands.
363+ g_object[pos]=0x27BD0000|(code1&0x0000FFFF); //// addiu sp,sp,xx
364+ break;
365+ case 0x2407: // addiu a3,zero,xxxx
366+ if (g_object[pos-1]!=0x02E0F809) break; // jalr ra,s7
367+ // call_lib_code(x)
368+ switch(code1&0x0000FFFF){
369+ case LIB_RESTORE:
370+ // Convert label data to pointer if not dynamic
371+ code1=g_object[pos-3];
372+ code2=g_object[pos-2];
373+ if ((code1>>16)!=0x3C02) break; // lui v0,xxxx
374+ if ((code2>>16)!=0x3442) break; // ori v0,v0,xxxx
375+ label=(code1<<16)|(code2&0x0000FFFF);
376+ code1=(int)search_label(label);
377+ g_label=label;
378+ if (!code1) return ERR_LABEL_NF;
379+ code2=code1&0x0000FFFF;
380+ code1=code1>>16;
381+ g_object[pos-3]=0x3C020000|code1; // lui v0,xxxx
382+ g_object[pos-2]=0x34420000|code2; // ori v0,v0,xxxx
383+ g_object[pos]=0x24070000|LIB_RESTORE2; // addiu a3,zero,xxxx
384+ break;
385+ default:
386+ break;
387+ }
388+ break;
389+ default:
390+ break;
391+ }
392+ }
393+ return 0;
394+}
\ No newline at end of file
--- /dev/null
+++ b/mips/protozoa/main.c
@@ -0,0 +1,272 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+// main.c
9+// MachiKania BASIC System Ver Zoea
10+// KM-BASIC 統合開発実行環境 for PIC32MX170F256B / PIC32MX270F256B by K.Tanaka
11+// LCD出力バージョン(テスト) by K.Tanaka
12+
13+// 利用システム
14+// libsdfsio.a : SDカードアクセス用ライブラリ
15+
16+// System clock :48MHz FRC with PLL (8/2*24/2)
17+// Peripheral clock :48MHz
18+
19+/*
20+ PIC32MX ペリフェラル使用状況
21+
22+ 割り込み
23+ NTSC, Timer2, vector 8, priority 5
24+ MUSIC, CS0, vector 1, priority 2
25+ TIMER, Timer1, vector 4, priority 3
26+ INT, CS1, vector 2, priority 1
27+
28+ タイマー
29+ Timer1 BASIC用タイマー
30+ Timer2 NTSC
31+ Timer3 MUSIC/PWM
32+ Timer4 MUSIC
33+ Timer5 未使用
34+
35+ DMA
36+ DMA0 未使用
37+ DMA1 未使用
38+ DMA2 MUSIC
39+ DMA3 未使用
40+
41+ Output compair
42+ OC1 未使用
43+ OC2 未使用
44+ OC3 未使用
45+ OC4 MUSIC/PWM
46+ OC5 未使用
47+
48+ SPI
49+ SPI1 未使用
50+ SPI2 マルチメディアカード
51+
52+ I2C
53+ I2C1 未使用
54+ I2C2 未使用
55+
56+ ポート使用
57+ A0 MMC
58+ A1 MMC
59+ A2 Audio
60+ A3 LCD/button切換え
61+ A4 MMC
62+ B0 LCD
63+ B1 LCD
64+ B2 LCD/button
65+ B3 LCD/button
66+ B4 LCD/button
67+ B5 LCD/button
68+ B6 未使用
69+ B7 LCD/button
70+ B8 LCD/button
71+ B9 PS2/button
72+ B10 LCD
73+ B11 LCD
74+ B12 未使用
75+ B13 LCD
76+ B14 LCD
77+ B15 MMC
78+*/
79+
80+#include <xc.h>
81+#include "api.h"
82+#include "compiler.h"
83+#include "editor.h"
84+#include "main.h"
85+
86+#define mBMXSetRAMKernProgOffset(offset) (BMXDKPBA = (offset))
87+#define mBMXSetRAMUserDataOffset(offset) (BMXDUDBA = (offset))
88+#define mBMXSetRAMUserProgOffset(offset) (BMXDUPBA = (offset))
89+
90+// INIファイル指定キーワード(8文字以内)
91+const char InitKeywords[][9]={
92+ "106KEY","101KEY","NUMLOCK","CAPSLOCK","SCRLLOCK"
93+};
94+
95+void freadline(char *s,FSFILE *fp){
96+// ファイルから1行読み込み、配列sに返す
97+// 最大8文字まで。9文字以上の場合無効
98+// #または0x20以下のコードを見つけた場合、以降は無視
99+// s:9バイト以上の配列
100+// fp:ファイルポインタ
101+ int n;
102+ char c,*p;
103+ n=0;
104+ p=s;
105+ *p=0;
106+ while(n<=8){
107+ if(FSfread(p,1,1,fp)==0 || *p=='\n'){
108+ *p=0;
109+ return;
110+ }
111+ if(*p=='#'){
112+ *p=0;
113+ break;
114+ }
115+ if(*p<=' '){
116+ if(n>0){
117+ *p=0;
118+ break;
119+ }
120+ continue;
121+ }
122+ p++;
123+ n++;
124+ }
125+ if(n>8) *s=0; //9文字以上の文字列の場合は無効
126+ //以降の文字は無視
127+ while(FSfread(&c,1,1,fp) && c!='\n') ;
128+}
129+int searchinittext(char *s){
130+// InitKeywords配列の中から文字列sを探し、位置した場合何番目かを返す
131+// 見つからなかった場合-1を返す
132+ int i;
133+ char *p1;
134+ const char *p2;
135+ for(i=0;i<sizeof(InitKeywords)/sizeof(InitKeywords[0]);i++){
136+ p1=s;
137+ p2=InitKeywords[i];
138+ while(*p1==*p2){
139+ if(*p1==0) return i;
140+ p1++;
141+ p2++;
142+ }
143+ }
144+ return -1;
145+}
146+void readinifile(void){
147+ FSFILE *fp;
148+ char inittext[9];
149+
150+ fp=FSfopen(INIFILE,"r");
151+ if(fp==NULL) return;
152+ printstr("Initialization File Found\n");
153+// lockkey=0; //INIファイルが存在する場合、Lock関連キーはINIファイルに従う
154+ while(1){
155+ if(FSfeof(fp)) break;
156+ freadline(inittext,fp);
157+ switch(searchinittext(inittext)){
158+ case 0:
159+// keytype=0;//日本語キーボード
160+ break;
161+ case 1:
162+// keytype=1;//英語キーボード
163+ break;
164+ case 2:
165+// lockkey|=2;//Num Lock
166+ break;
167+ case 3:
168+// lockkey|=4;//CAPS Lock
169+ break;
170+ case 4:
171+// lockkey|=1;//Scroll Lock
172+ break;
173+ }
174+ }
175+ FSfclose(fp);
176+}
177+
178+void printhex8(unsigned char d){
179+ printchar("0123456789ABCDEF"[d>>4]);
180+ printchar("0123456789ABCDEF"[d&0x0f]);
181+}
182+
183+void printhex16(unsigned short d){
184+ printhex8(d>>8);
185+ printhex8(d&0x00ff);
186+}
187+
188+void printhex32(unsigned int d){
189+ printhex16(d>>16);
190+ printhex16(d&0x0000ffff);
191+}
192+
193+int main(void){
194+ char *appname,*s;
195+
196+ if(DEVCFG1 & 0x8000){
197+ // Set Clock switching enabled and reset
198+ NVMWriteWord(&DEVCFG1,DEVCFG1 & 0xffff7fff);
199+ SoftReset();
200+ }
201+
202+ /* ポートの初期設定 */
203+ TRISA = 0x0000; // PORTA全て出力
204+ ANSELA = 0x0000; // 全てデジタル
205+ TRISB = 0x0000; // PORTB全て出力(ボタン読み込み時のみ入力に切り替える)
206+ ANSELB = 0x0000; // 全てデジタル
207+ KEY_DS;
208+ LCD_CS_LO;
209+
210+ // 周辺機能ピン割り当て
211+ SDI2R=2; //RPA4:SDI2
212+ RPA1R=4; //RPA1:SDO2
213+
214+ // Make RAM executable. See also "char RAM[RAMSIZE]" in globalvars.c
215+ mBMXSetRAMKernProgOffset(PIC32MX_RAMSIZE-RAMSIZE);
216+ mBMXSetRAMUserDataOffset(PIC32MX_RAMSIZE);
217+ mBMXSetRAMUserProgOffset(PIC32MX_RAMSIZE);
218+
219+ INTEnableSystemMultiVectoredInt();
220+ IPC2bits.T2IP = 4; // 割り込みレベル4
221+ IFS0bits.T2IF = 0;
222+ IEC0bits.T2IE = 1; // タイマ2割り込み有効化
223+ PR2=3125; // 60分の1秒
224+ T2CON = 0x8070; // プリスケーラ1:256、タイマ2開始
225+
226+ init_textgraph();// パレット設定、LCDクリア
227+ setcursor(0,0,COLOR_NORMALTEXT);
228+ keystatus=0;
229+
230+ // Show blue screen if exception before soft reset.
231+ blue_screen();
232+
233+ printstr("MachiKania BASIC System\n");
234+ printstr(" Ver "SYSVER1" "SYSVER2" by KENKEN\n");
235+ printstr("BASIC Compiler "BASVER"\n");
236+ printstr(" by Katsumi\n\n");
237+ //SDカードファイルシステム初期化
238+ setcursorcolor(COLOR_NORMALTEXT);
239+ printstr("Init File System...");
240+ // Initialize the File System
241+ if(FSInit()==FALSE){ //ファイルシステム初期化
242+ //エラーの場合停止
243+ setcursorcolor(COLOR_ERRORTEXT);
244+ printstr("\nFile System Error\n");
245+ printstr("Insert Correct Card\n");
246+ printstr("And Reset\n");
247+ while(1) asm("wait");
248+ }
249+ printstr("OK\n");
250+ readinifile(); //INIファイル読み込み
251+
252+ wait60thsec(60); //1秒待ち
253+
254+/*
255+ // 実行中HEXファイル名がHEXFILEと一致した場合はエディタ起動
256+ appname=(char*)FILENAME_FLASH_ADDRESS;
257+ s=HEXFILE;
258+ while(*s++==*appname++) if(*s==0) texteditor(); //テキストエディター呼び出し
259+*/
260+
261+ // 実行中HEXファイル名の「.HEX」を「.BAS」に置き換えてBASファイルを実行
262+ appname=(char*)FILENAME_FLASH_ADDRESS;
263+ s=tempfile;
264+ while(*appname!='.') *s++=*appname++;
265+ appname=".BAS";
266+ while(*appname!=0) *s++=*appname++;
267+ *s=0;
268+ // buttonmode(); //ボタン有効化
269+ g_disable_break=1; // Breakキー無効化
270+ runbasic(tempfile,0);
271+ while(1) asm(WAIT);
272+}
--- /dev/null
+++ b/mips/protozoa/main.h
@@ -0,0 +1,21 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+#define SYSVER1 "Protozoa"
9+#define SYSVER2 "1.3"
10+#define BASVER "KM-1208"
11+
12+#define INIFILE "MACHILCD.INI" // 初期設定ファイル
13+#define HEXFILE "MACHILCD.HEX" // 実行中HEXファイル名がこれと一致した場合はエディタ起動
14+
15+#define FILENAME_FLASH_ADDRESS 0x9D005800
16+#define PIC32MX_RAMSIZE 0x10000
17+#define PIC32MX_FLASHSIZE 0x40000
18+
19+void printhex8(unsigned char d);
20+void printhex16(unsigned short d);
21+void printhex32(unsigned int d);
--- /dev/null
+++ b/mips/protozoa/memory.c
@@ -0,0 +1,327 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include "compiler.h"
13+
14+/*
15+ ALLOC_VAR_NUM: # of variables used for allocation of memory (string/dimension).
16+ 0 is for A, 1 is for B, ... , and 25 is for Z.
17+ This number also includes temporary area used for string construction etc.
18+ Temporary area is cleared every line of BASIC code in alloc_memory().
19+ ALLOC_BLOCK_NUM: # of blocks that can be used for memory allocation.
20+ This # includes the ones for ALLOC_VAR_NUM, ALLOC_PCG_BLOCK etc, ALLOC_LNV_BLOCK,
21+ ALLOC_PERM_BLOCK.
22+ After ALLOC_VAR_NUM area, dedicated memory area and permanent area follows.
23+ ALLOC_PERM_BLOCK: Start # of permanent blocks.
24+ The blocks after this number is permanently stored.
25+ Therefore, it must be released when it's not used any more.
26+*/
27+
28+static int g_temp_var_num_candidate=ALLOC_PERM_BLOCK;
29+
30+#define DELETE_LIST_SIZE 10
31+static int g_deleted_num;
32+static int g_deleted_pointer[DELETE_LIST_SIZE];
33+static int g_deleted_size[DELETE_LIST_SIZE];
34+
35+void register_deleted_block(int pointer, int size){
36+ // There is maximum
37+ if (DELETE_LIST_SIZE<=g_deleted_num) return;
38+ if (g_deleted_num) {
39+ // Avoid duplication
40+ if (g_deleted_pointer[g_deleted_num-1]==pointer) return;
41+ }
42+ g_deleted_pointer[g_deleted_num]=pointer;
43+ g_deleted_size[g_deleted_num]=size;
44+ g_deleted_num++;
45+}
46+
47+void set_free_area(void* begin, void* end){
48+ // Initialize heap area
49+ int i;
50+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
51+ g_var_size[i]=0;
52+ }
53+ g_heap_mem=(int*)begin;
54+ g_max_mem=(int)((end-begin)/4);
55+ g_deleted_num=0;
56+}
57+
58+void* calloc_memory(int size, int var_num){
59+ int i;
60+ void* ret;
61+ // Allocate memory
62+ ret=alloc_memory(size,var_num);
63+ // Fill zero in allocated memory
64+ for(i=0;i<size;i++){
65+ ((int*)ret)[i]=0;
66+ }
67+ // return pointer to allocated memory
68+ return ret;
69+}
70+void* alloc_memory(int size, int var_num){
71+ // Remove temporary blocks once a line.
72+ asm volatile("nop");
73+ asm volatile("bltz $s6,_alloc_memory_main"); // Skip if $s6<0
74+ // Following code will be activated after setting $s6 register
75+ // every line and after label statement.
76+ asm volatile("lui $v0,0x8000");
77+ asm volatile("or $s6,$v0,$s6"); // $s6=0x80000000|$s6;
78+ // Remove all temporary blocks
79+ // Note that g_var_size is short integer.
80+ // Note that ALLOC_VAR_NUM is used here (but not ALLOC_BLOC_NUM)
81+ // for(i=26;i<ALLOC_VAR_NUM;i++)g_var_size[i]=0;
82+ asm volatile("addiu $v0,$zero,%0"::"n"((ALLOC_VAR_NUM-26)/2)); // $v0=(ALLOC_VAR_NUM-26)/2
83+ asm volatile("la $v1,%0"::"i"(&g_var_size[0])); // $v1=g_var_size
84+ asm volatile("loop:");
85+ asm volatile("sw $zero,(26*2)($v1)"); // $v1[26]=0, $v1[27]=0
86+ asm volatile("addiu $v0,$v0,-1"); // $v0--
87+ asm volatile("addiu $v1,$v1,4"); // $v1+=2
88+ asm volatile("bne $v0,$zero,loop"); // loop if 0<$v0
89+ asm volatile("b _alloc_memory_main");
90+}
91+void* _alloc_memory_main(int size, int var_num){
92+ int i,j,candidate;
93+ // Assign temp var number
94+ if (var_num<0) {
95+ // Use ALLOC_VAR_NUM here but not ALLOC_BLOCK_NUM
96+ for(i=26;i<ALLOC_VAR_NUM;i++){
97+ if (g_var_size[i]==0) {
98+ var_num=i;
99+ break;
100+ }
101+ }
102+ if (var_num<0) {
103+ err_str_complex();
104+ return 0;
105+ }
106+ }
107+ // Clear var to be assigned.
108+ g_var_size[var_num]=0;
109+ g_var_pointer[var_num]=0;
110+ while(1){
111+ // Try the block previously deleted, not for temporary block.
112+ // This is for fast allocation of memory for class object.
113+ if (var_num<26 || ALLOC_VAR_NUM<=var_num) {
114+ candidate=0;
115+ while(g_deleted_num){
116+ // Check if the last deleted block fits
117+ // If not, these cannot be used anymore
118+ g_deleted_num--;
119+ if (size<=g_deleted_size[g_deleted_num]) {
120+ candidate=g_deleted_pointer[g_deleted_num];
121+ break;
122+ }
123+ }
124+ if (candidate || g_deleted_num) {
125+ // Candidate found
126+ break;
127+ }
128+ }
129+ // Try the block after last block
130+ candidate=0;
131+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
132+ if (g_var_size[i]==0) continue;
133+ if (candidate<=g_var_pointer[i]) {
134+ candidate=g_var_pointer[i]+g_var_size[i];
135+ }
136+ }
137+ if (candidate+size<=g_max_mem) {
138+ // Check after deleted block
139+ j=candidate;
140+ for(i=0;i<g_deleted_num;i++){
141+ if (j<g_deleted_pointer[i]+g_deleted_size[i]) {
142+ j=g_deleted_pointer[i]+g_deleted_size[i];
143+ }
144+ }
145+ if (j+size<=g_max_mem) {
146+ // Candidate block found after previously deleted blokcs
147+ candidate=j;
148+ break;
149+ } else {
150+ // Candidate is before previously deleted blocks,
151+ // and there is no candidate block after previously deleted blocks.
152+ // Therefore, use the current candidate, which may invade previously
153+ // deleted blocks. Therefore, erase the previously deleted blocks list.
154+ g_deleted_num=0;
155+ break;
156+ }
157+ }
158+ // Peviously deleted blocks cannot be used any more
159+ g_deleted_num=0;
160+ // Check between blocks
161+ // Note that there is at least one block with zero pointer and zero size (see above).
162+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
163+ // Candidate is after this block.
164+ candidate=g_var_pointer[i]+g_var_size[i];
165+ // Check if there is an overlap.
166+ for(j=0;j<ALLOC_BLOCK_NUM;j++){
167+ if (g_var_size[j]==0) continue;
168+ if (candidate+size<=g_var_pointer[j]) continue;
169+ if (g_var_pointer[j]+g_var_size[j]<=candidate) continue;
170+ // This block overlaps with the candidate
171+ candidate=-1;
172+ break;
173+ }
174+ if (0<=candidate && candidate+size<=g_max_mem) {
175+ // Available block found
176+ break;
177+ } else {
178+ candidate=-1;
179+ }
180+ }
181+ if (0<=candidate) break;
182+ // New memory block cannot be allocated.
183+ err_no_mem();
184+ return 0;
185+ }
186+ // Available block found.
187+ g_var_pointer[var_num]=candidate;
188+ g_var_size[var_num]=size;
189+ g_var_mem[var_num]=(int)(&(g_heap_mem[candidate]));
190+ return (void*)g_var_mem[var_num];
191+}
192+
193+void free_temp_str(char* str){
194+ int i,pointer;
195+ if (!str) return;
196+ pointer=(int)str-(int)g_heap_mem;
197+ pointer>>=2;
198+ for(i=26;i<ALLOC_VAR_NUM;i++){
199+ if (g_var_pointer[i]==pointer) {
200+ if (g_var_size[i] && g_var_mem[i]==(int)str) {
201+ register_deleted_block(pointer,g_var_size[i]);
202+ g_var_size[i]=0;
203+ }
204+ }
205+ }
206+}
207+
208+void free_non_temp_str(char* str){
209+ int i,pointer;
210+ if (!str) return;
211+ pointer=(int)str-(int)g_heap_mem;
212+ pointer>>=2;
213+ for(i=0;i<26;i++){
214+ if (g_var_pointer[i]==pointer) {
215+ if (g_var_size[i] && g_var_mem[i]==(int)str) {
216+ register_deleted_block(pointer,g_var_size[i]);
217+ g_var_size[i]=0;
218+ g_var_mem[i]=0;
219+ }
220+ }
221+ }
222+ for(i=ALLOC_VAR_NUM;i<ALLOC_BLOCK_NUM;i++){
223+ if (g_var_pointer[i]==pointer) {
224+ if (g_var_size[i] && g_var_mem[i]==(int)str) {
225+ register_deleted_block(pointer,g_var_size[i]);
226+ g_var_size[i]=0;
227+ g_var_mem[i]=0;
228+ if (ALLOC_PERM_BLOCK<=i) g_temp_var_num_candidate=i;
229+ }
230+ }
231+ }
232+}
233+
234+void free_perm_str(char* str){
235+ int i,pointer;
236+ if (!str) return;
237+ pointer=(int)str-(int)g_heap_mem;
238+ pointer>>=2;
239+ // Search permanent block and delete a block if found.
240+ for(i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){
241+ if (g_var_pointer[i]==pointer) {
242+ if (g_var_size[i] && g_var_mem[i]==(int)str) {
243+ register_deleted_block(pointer,g_var_size[i]);
244+ g_var_size[i]=0;
245+ g_temp_var_num_candidate=i;
246+ break;
247+ }
248+ }
249+ }
250+}
251+
252+void move_to_perm_block(int var_num){
253+ int i;
254+ // Find available permanent block
255+ i=get_permanent_var_num();
256+ // Available block found.
257+ // Copy value from variable.
258+ g_var_size[i]=g_var_size[var_num];
259+ g_var_pointer[i]=g_var_pointer[var_num];
260+ g_var_mem[i]=g_var_mem[var_num];
261+ // Clear variable
262+ g_var_size[var_num]=0;
263+ g_var_mem[var_num]=0;
264+}
265+
266+int move_from_perm_block_if_exists(int var_num){
267+ int i,pointer;
268+ pointer=(int)g_var_mem[var_num]-(int)g_heap_mem;
269+ pointer>>=2;
270+ // Find stored block
271+ for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){
272+ if (0<g_var_size[i] && g_var_pointer[i]==pointer) break;
273+ }
274+ if (ALLOC_BLOCK_NUM<=i) return 0; // Not found
275+ // Stored block found.
276+ // Replace pointer
277+ g_var_size[var_num]=g_var_size[i];
278+ g_var_pointer[var_num]=g_var_pointer[i];
279+ // Clear block
280+ g_var_size[i]=0;
281+ g_temp_var_num_candidate=i;
282+ return 1;
283+}
284+
285+void move_from_perm_block(int var_num){
286+ if (move_from_perm_block_if_exists(var_num)) return; // Found
287+ err_unknown(); // Not found
288+}
289+
290+int get_permanent_var_num(){
291+ int i;
292+ // Try candidate first
293+ if (!g_var_size[g_temp_var_num_candidate]) {
294+ if (ALLOC_PERM_BLOCK<g_temp_var_num_candidate &&
295+ g_temp_var_num_candidate<ALLOC_BLOCK_NUM) {
296+ return g_temp_var_num_candidate++;
297+ }
298+ }
299+ // Candidate is not available. Seek all.
300+ for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++) {
301+ if (g_var_size[i]==0) {
302+ g_temp_var_num_candidate=i+1;
303+ return i;
304+ }
305+ }
306+ err_no_block();
307+ return 0;
308+}
309+
310+int get_varnum_from_address(void* address){
311+ int i;
312+ for (i=0;i<ALLOC_BLOCK_NUM;i++){
313+ if (g_var_mem[i]==(int)address) return i;
314+ }
315+ // not found
316+ return -1;
317+}
318+
319+void* lib_calloc_memory(int size){
320+ // Allocate memory and return address
321+ return calloc_memory(size,get_permanent_var_num());
322+}
323+
324+void lib_delete(int* object){
325+ // Remove region that fit to object
326+ free_non_temp_str((char*)object);
327+}
--- /dev/null
+++ b/mips/protozoa/music.c
@@ -0,0 +1,644 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#include <xc.h>
9+#include "compiler.h"
10+#include "api.h"
11+
12+/*
13+ Timer3: 1/32 prescaler, toggle mode :750000 Hz
14+ PR3=1704 <-> 440 Hz
15+ Shift tone for 2048 <--> ~440 Hz.
16+ x 1705 / 2048 = 213 / 256 + 1 / 2048
17+
18+*/
19+
20+/*
21+ c: 1434
22+ B: 1519
23+ A#: 1609
24+ A: 1705
25+ G#: 1806
26+ G: 1914
27+ F#: 2028
28+ F: 2148
29+ E: 2276
30+ D#: 2411
31+ D: 2555
32+ C#: 2707
33+ C: 2867
34+ Cb: 3038
35+*/
36+
37+const static int g_keys[]={
38+ 1609,1434,2707,2411,2148,2028,1806,// 0 7# C# A#m
39+ 1609,1519,2707,2411,2148,2028,1806,// 7 6# F# D#m
40+ 1609,1519,2707,2411,2276,2028,1806,// 14 5# B G#m
41+ 1705,1519,2707,2411,2276,2028,1806,// 21 4# E C#m
42+ 1705,1519,2707,2555,2276,2028,1806,// 28 3# A F#m
43+ 1705,1519,2707,2555,2276,2028,1914,// 35 2# D Bm
44+ 1705,1519,2867,2555,2276,2028,1914,// 42 1# G Em
45+ 1705,1519,2867,2555,2276,2148,1914,// 49 0 C Am
46+ 1705,1609,2867,2555,2276,2148,1914,// 56 1b F Dm
47+ 1705,1609,2867,2555,2411,2148,1914,// 63 2b Bb Gm
48+ 1806,1609,2867,2555,2411,2148,1914,// 70 3b Eb Cm
49+ 1806,1609,2867,2707,2411,2148,1914,// 77 4b Ab Fm
50+ 1806,1609,2867,2707,2411,2148,2028,// 84 5b Db Bbm
51+ 1806,1609,3038,2707,2411,2148,2028,// 91 6b Gb Ebm
52+ 1806,1609,3038,2707,2411,2276,2028 // 98 7b Cb Abm
53+};
54+
55+/*
56+ 2^(1/12) ~= 69433/(2^16)
57+ 1/(2^(1/12) ~= 1933/(2^11)
58+*/
59+
60+#define toneFlat(x) ((((unsigned long)(x))*69433)>>16)
61+#define toneSharp(x) ((((unsigned long)(x))*1933)>>11)
62+
63+/* local global vars */
64+static int* g_tones;
65+static int g_qvalue;
66+static int g_lvalue;
67+static int g_mpoint;
68+static char* g_mstr;
69+static int g_mspos;
70+static unsigned short g_music[32];
71+static unsigned short g_sound[32];
72+static unsigned short g_musiclen[32];
73+static unsigned char g_soundlen[32];
74+static int g_musicstart;
75+static int g_musicend;
76+static int g_musicwait;
77+static int g_soundstart;
78+static int g_soundend;
79+static int g_soundwait;
80+static int g_soundrepeat;
81+
82+static char g_sound_mode=0;
83+static FSFILE* g_fhandle=0;
84+static char* g_wavtable=0;
85+
86+#define SOUND_MODE_MUSIC 1
87+#define SOUND_MODE_WAVE 2
88+
89+#define start_dma() T4CONSET=0x8000; DCH2CONSET=0x00000080; g_sound_mode=SOUND_MODE_WAVE
90+#define stop_dma() T4CONCLR=0x8000; DCH2CONCLR=0x00000080; g_sound_mode=SOUND_MODE_MUSIC
91+
92+int waveRemaining(int mode){
93+ if (!g_fhandle) return 0;
94+ switch(mode){
95+ case 1: // current position (header excluded)
96+ return g_fhandle->seek-0x2c;
97+ break;
98+ case 2: // file size (header excluded)
99+ return g_fhandle->size-0x2c;
100+ break;
101+ case 0: // remaining
102+ default:
103+ return g_fhandle->size-g_fhandle->seek;
104+ break;
105+ }
106+}
107+int musicRemaining(int flagsLR){
108+ // flagsLR is ignored
109+ return (g_musicend-g_musicstart)&31;
110+}
111+
112+void musicint(){
113+ unsigned int i;
114+ static unsigned short wavtable_pos;
115+ // This function is called every 1/60 sec.
116+ switch(g_sound_mode){
117+ case SOUND_MODE_MUSIC:
118+ if (g_soundstart!=g_soundend){
119+ // Start timer & OC4
120+ i=g_sound[g_soundstart];
121+ if (i<0xffff) {
122+ T3CONSET=0x8000;
123+ PR3=i;
124+ if (i<TMR3) TMR3=0;
125+ } else {
126+ T3CONCLR=0x8000;
127+ }
128+ if ((--g_soundwait)<=0) {
129+ g_soundstart++;
130+ if (g_soundstart==g_soundend || 31<g_soundstart) {
131+ g_soundstart=0;
132+ g_soundrepeat--;
133+ if (0<g_soundrepeat) {
134+ g_soundwait=g_soundlen[g_soundstart];
135+ } else {
136+ g_soundend=g_soundrepeat=g_soundwait=0;
137+ }
138+ } else {
139+ g_soundwait=g_soundlen[g_soundstart];
140+ }
141+ }
142+ // Shift music data even though without output.
143+ if (g_musicstart!=g_musicend) {
144+ if ((--g_musicwait)<=0) {
145+ g_musicstart++;
146+ g_musicstart&=31;
147+ g_musicwait=g_musiclen[g_musicstart];
148+ }
149+ }
150+ } else if (g_musicstart!=g_musicend) {
151+ // Start timer & OC4
152+ i=g_music[g_musicstart];
153+ if (i<0xffff) {
154+ T3CONSET=0x8000;
155+ PR3=i;
156+ if (i<TMR3) TMR3=0;
157+ } else {
158+ T3CONCLR=0x8000;
159+ }
160+ if ((--g_musicwait)<=0) {
161+ g_musicstart++;
162+ g_musicstart&=31;
163+ g_musicwait=g_musiclen[g_musicstart];
164+ if (((g_musicstart+1)&31)==g_musicend) {
165+ // Raise MUSIC interrupt flag
166+ raise_interrupt_flag(INTERRUPT_MUSIC);
167+ }
168+ }
169+ } else {
170+ // Stop timer
171+ T3CONCLR=0x8000;
172+ }
173+ break;
174+ case SOUND_MODE_WAVE:
175+ // Initialize parameters
176+ if (!T4CONbits.ON){
177+ start_dma();
178+ wavtable_pos=0;
179+ }
180+ wavtable_pos=262-wavtable_pos;
181+ // Read from file
182+ if (0 == FSfread((void*)&g_wavtable[wavtable_pos],1,262,g_fhandle)) {
183+ // End of file.
184+ stop_dma();
185+ FSfclose(g_fhandle);
186+ g_fhandle=0;
187+ g_sound_mode=SOUND_MODE_MUSIC;
188+ stop_music();
189+ // Raise WAVE interrupt flag
190+ raise_interrupt_flag(INTERRUPT_WAVE);
191+ break;
192+ }
193+ break;
194+ default:
195+ break;
196+ }
197+}
198+
199+int musicGetNum(){
200+ int i, ret;
201+ char b;
202+ // Skip non number character
203+ for(i=0;(b=g_mstr[g_mspos+i])<'0' && '9'<g_mstr[g_mspos+i];i++);
204+ // Determine the number
205+ ret=0;
206+ while('0'<=b && b<='9'){
207+ ret*=10;
208+ ret+=b-'0';
209+ i++;
210+ b=g_mstr[g_mspos+i];
211+ }
212+ g_mspos+=i;
213+ return ret;
214+}
215+
216+void stop_music(){
217+ // Initialize normal music mode.
218+
219+ // Use Timer3 and OC4 for sound.
220+ RPA2R=5; //Use RPA2 for OC4
221+ OC4R=0;
222+ OC4CON=0x000b; // Timer3, toggle mode
223+ OC4CONSET=0x8000;// Start OC4
224+ T3CON=0x0050; // Prescaller: 1:32 (1.5 MHz), not yet started
225+
226+ // Initializations for music/sound.
227+ g_musicstart=g_musicend=g_musicwait=g_soundstart=g_soundend=g_soundwait=g_soundrepeat=0;
228+ g_sound_mode=SOUND_MODE_MUSIC;
229+
230+ // Initialize DMA (see also init_dma_music())
231+
232+ // Stop Timer4
233+ T4CON=0x0000; // Not start yet
234+
235+ // Enable DMA, stop DMA2
236+ DMACONSET=0x8000;
237+ DCH2CONCLR=0x0080;
238+
239+ // Close handle if open.
240+ if (g_fhandle) FSfclose(g_fhandle);
241+ g_fhandle=0;
242+
243+ // Inactive music first
244+ g_music_active=0;
245+}
246+
247+void init_music(){
248+ // Initilize music system
249+ stop_music();
250+
251+ // Initializations for music/sound.
252+ g_qvalue=160; // Q: 1/4=90
253+ g_lvalue=20; // L: 1/8
254+ g_tones=(int*)&(g_keys[49]); // C major
255+}
256+
257+void musicSetL(){
258+ // Set length of a character.
259+ // Syntax: L:n/m, where n and m are numbers.
260+ int n,m;
261+ n=musicGetNum();
262+ g_mspos++;
263+ m=musicGetNum();
264+ g_lvalue=g_qvalue*n/m;
265+}
266+
267+void musicSetQ(){
268+ int i;
269+ // Syntax: Q:1/4=n, where n is number.
270+ // Skip "1/4="
271+ for(i=0;g_mstr[g_mspos+i]!='=';i++);
272+ g_mspos+=i+1;
273+ i=musicGetNum();
274+ if (i<48) { g_qvalue=320; /* 1/4=45 */ }
275+ else if (i<53) { g_qvalue=288; /* 1/4=50 */ }
276+ else if (i<60) { g_qvalue=256; /* 1/4=56 */ }
277+ else if (i<70) { g_qvalue=224; /* 1/4=64 */ }
278+ else if (i<83) { g_qvalue=192; /* 1/4=75 */ }
279+ else if (i<102) { g_qvalue=160; /* 1/4=90 */ }
280+ else if (i<132) { g_qvalue=128; /* 1/4=113 */ }
281+ else if (i<188) { g_qvalue=96; /* 1/4=150 */ }
282+ else { g_qvalue=64; /* 1/4=225 */ }
283+ g_lvalue=g_qvalue>>3;
284+}
285+
286+void musicSetK(){
287+ // Syntax: K:xxx
288+ if (!strncmp((char*)&(g_mstr[g_mspos]),"A#m",3)) {
289+ g_mspos+=3;
290+ g_tones=(int*)&(g_keys[0]);
291+ return;
292+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"D#m",3)) {
293+ g_mspos+=3;
294+ g_tones=(int*)&(g_keys[7]);
295+ return;
296+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"G#m",3)) {
297+ g_mspos+=3;
298+ g_tones=(int*)&(g_keys[14]);
299+ return;
300+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"C#m",3)) {
301+ g_mspos+=3;
302+ g_tones=(int*)&(g_keys[21]);
303+ return;
304+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"F#m",3)) {
305+ g_mspos+=3;
306+ g_tones=(int*)&(g_keys[28]);
307+ return;
308+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Bbm",3)) {
309+ g_mspos+=3;
310+ g_tones=(int*)&(g_keys[84]);
311+ return;
312+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Ebm",3)) {
313+ g_mspos+=3;
314+ g_tones=(int*)&(g_keys[91]);
315+ return;
316+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Abm",3)) {
317+ g_mspos+=3;
318+ g_tones=(int*)&(g_keys[98]);
319+ return;
320+ }
321+ if (!strncmp((char*)&(g_mstr[g_mspos]),"C#",2)) {
322+ g_mspos+=2;
323+ g_tones=(int*)&(g_keys[0]);
324+ return;
325+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"F#",2)) {
326+ g_mspos+=2;
327+ g_tones=(int*)&(g_keys[7]);
328+ return;
329+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Bm",2)) {
330+ g_mspos+=2;
331+ g_tones=(int*)&(g_keys[35]);
332+ return;
333+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Em",2)) {
334+ g_mspos+=2;
335+ g_tones=(int*)&(g_keys[42]);
336+ return;
337+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Am",2)) {
338+ g_mspos+=2;
339+ g_tones=(int*)&(g_keys[49]);
340+ return;
341+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Dm",2)) {
342+ g_mspos+=2;
343+ g_tones=(int*)&(g_keys[56]);
344+ return;
345+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Gm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Bb",2)) {
346+ g_mspos+=2;
347+ g_tones=(int*)&(g_keys[63]);
348+ return;
349+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Cm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Eb",2)) {
350+ g_mspos+=2;
351+ g_tones=(int*)&(g_keys[70]);
352+ return;
353+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Fm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Ab",2)) {
354+ g_mspos+=2;
355+ g_tones=(int*)&(g_keys[77]);
356+ return;
357+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Db",2)) {
358+ g_mspos+=2;
359+ g_tones=(int*)&(g_keys[84]);
360+ return;
361+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Gb",2)) {
362+ g_mspos+=2;
363+ g_tones=(int*)&(g_keys[91]);
364+ return;
365+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Cb",2)) {
366+ g_mspos+=2;
367+ g_tones=(int*)&(g_keys[98]);
368+ return;
369+ }
370+ switch(g_mstr[g_mspos]){
371+ case 'B':
372+ g_mspos++;
373+ g_tones=(int*)&(g_keys[14]);
374+ return;
375+ case 'E':
376+ g_mspos++;
377+ g_tones=(int*)&(g_keys[21]);
378+ return;
379+ case 'A':
380+ g_mspos++;
381+ g_tones=(int*)&(g_keys[28]);
382+ return;
383+ case 'D':
384+ g_mspos++;
385+ g_tones=(int*)&(g_keys[35]);
386+ return;
387+ case 'G':
388+ g_mspos++;
389+ g_tones=(int*)&(g_keys[42]);
390+ return;
391+ case 'C':
392+ g_mspos++;
393+ g_tones=(int*)&(g_keys[49]);
394+ return;
395+ case 'F':
396+ g_mspos++;
397+ g_tones=(int*)&(g_keys[56]);
398+ return;
399+ default:
400+ err_music(g_mstr);
401+ break;
402+ }
403+}
404+void musicSetM(){
405+ // Currently do nothing
406+ musicGetNum();
407+ musicGetNum();
408+}
409+
410+void set_sound(unsigned long* data, int flagsLR){
411+ // flagsLR is ignored
412+ int sound;
413+ int len;
414+ int pos;
415+ int datalen;
416+ IEC0bits.T4IE=0; // Stop interruption, first.
417+ // Initialize
418+ g_soundrepeat=g_soundstart=g_soundend=0;
419+ pos=0;
420+ do {
421+ while(data[1]!=0x00000020) data++; // Seek DATA statement
422+ datalen=(data[0]&0x00007FFF)-1; // Use bgezal statement containing data length.
423+ data+=2;
424+ while(0<datalen){
425+ datalen--;
426+ len=data[0]>>16;
427+ sound=data[0]&0x0000FFFF;
428+ data++;
429+ if (len) {
430+ // Shift tone for 2048 <--> ~440 Hz.
431+ // 2048 must be changed to 1705
432+ // x 1705 / 2048 = 213 / 256 + 1 / 2048
433+ sound=213*(sound>>8)+(sound>>11);
434+ g_sound[pos]=sound-1;
435+ g_soundlen[pos]=len;
436+ pos++;
437+ if (32<pos) {
438+ err_music("Sound data too long.");
439+ return;
440+ }
441+ } else {
442+ g_soundrepeat=sound;
443+ break;
444+ }
445+ }
446+ } while(len);
447+ g_soundend=pos;
448+ g_soundwait=g_soundlen[0];
449+ IEC0bits.T4IE=1; // Restart interrupt.
450+ g_music_active=1;// Activate music system
451+}
452+
453+void set_music(char* str, int flagsLR){
454+ // flagsLR is ignored
455+ char b;
456+ unsigned long tone,tonenatural;
457+ int len;
458+ g_mstr=str;
459+ g_mspos=0;
460+ while(0<(b=g_mstr[g_mspos])){
461+ if (g_mstr[g_mspos+1]==':') {
462+ // Set property
463+ g_mspos+=2;
464+ switch(b){
465+ case 'L':
466+ musicSetL();
467+ break;
468+ case 'Q':
469+ musicSetQ();
470+ break;
471+ case 'K':
472+ musicSetK();
473+ break;
474+ case 'M':
475+ musicSetM();
476+ break;
477+ default:
478+ err_music(str);
479+ break;
480+ }
481+ } else if ('A'<=b && b<='G' || 'a'<=b && b<='g' || b=='z') {
482+ g_mspos++;
483+ if (b=='z') {
484+ tone=0;
485+ } else if (b<='G') {
486+ tone=g_tones[b-'A'];
487+ tonenatural=g_keys[b-'A'+49];
488+ } else {
489+ tone=g_tones[b-'a']>>1;
490+ tonenatural=g_keys[b-'a'+49]>>1;
491+ }
492+ // Check "'"s
493+ while(g_mstr[g_mspos]=='\''){
494+ g_mspos++;
495+ tone>>=1;
496+ }
497+ // Check ","s
498+ while(g_mstr[g_mspos]==','){
499+ g_mspos++;
500+ tone<<=1;
501+ tonenatural<<=1;
502+ }
503+ // Check "^","=","_"
504+ switch(g_mstr[g_mspos]){
505+ case '^':
506+ g_mspos++;
507+ tone=toneSharp(tone);
508+ break;
509+ case '_':
510+ g_mspos++;
511+ tone=toneFlat(tone);
512+ break;
513+ case '=':
514+ g_mspos++;
515+ tone=tonenatural;
516+ break;
517+ default:
518+ break;
519+ }
520+ // Check number for length
521+ b=g_mstr[g_mspos];
522+ if ('0'<=b && b<='9') {
523+ len=g_lvalue*musicGetNum();
524+ } else {
525+ len=g_lvalue;
526+ }
527+ if (g_mstr[g_mspos]=='/') {
528+ g_mspos++;
529+ len=len/musicGetNum();
530+ }
531+ // Shift tone if graphic is used
532+ if (g_use_graphic) {
533+ // MUL_15 instead of MUL_16 for CPU clock.
534+ // tone=tone*15/16
535+ tone-=(tone+7)>>4;
536+ }
537+ // Update music value array
538+ IEC0bits.T4IE=0; // Stop interruption, first.
539+ if (g_musicstart==g_musicend) {
540+ g_musicwait=len;
541+ }
542+ g_music[g_musicend]=(tone-1)&0x0000FFFF;
543+ g_musiclen[g_musicend]=len;
544+ g_musicend++;
545+ g_musicend&=31;
546+ IEC0bits.T4IE=1; // Restart interruption.
547+ } else {
548+ err_music(str);
549+ }
550+ // Go to next character
551+ while(0<g_mstr[g_mspos] && g_mstr[g_mspos]<=0x20 || g_mstr[g_mspos]=='|') g_mspos++;
552+ }
553+ g_music_active=1;// Activate music system
554+}
555+
556+/*
557+ PLAYWAVE routines follow
558+*/
559+
560+int checkChars(char* str1, char* str2, int num){
561+ int i;
562+ for(i=0;i<num;i++){
563+ if (str1[i]!=str2[i]) return 1;
564+ }
565+ return 0;
566+}
567+
568+void init_dma_music(){
569+ // Timer4 for 15700 Hz
570+ T4CON=0x0000; // Not start yet
571+ if (g_use_graphic) {
572+ PR4=3405-1;
573+ } else {
574+ PR4=3632-1;
575+ }
576+ TMR4=PR4-1;
577+
578+ // Timer3 for PWM
579+ TMR3=0;
580+ PR3=0x100;
581+ T3CON=0x8000;
582+
583+ // OC4 setting
584+ RPA2R=5; //Use RPA2 for OC4
585+ OC4RS=0x80;
586+ OC4CON=0x000e;
587+ OC4CONSET=0x8000;
588+
589+ //DMA2 settings for OC4
590+ DMACONSET=0x8000;
591+ DCH2CON=0x00000012; // CHBUSY=0, CHCHNS=0, CHEN=0, CHAED=0, CHCHN=0, CHAEN=1, CHEDET=0, CHPRI=b10
592+ DCH2ECON=0x1310; // CHAIRQ=0, CHSIRQ=19, CFORCE=0, CABRT=0, PATEN=0, SIRQEN=1, AIRQEN=0
593+ // CHSIRQ=19: Timer4 interrupt
594+ DCH2SSA=((unsigned int)&(g_wavtable[0]))&0x1fffffff;
595+ DCH2DSA=0x1F803620; // OC4RS
596+ DCH2SSIZ=524;
597+ DCH2DSIZ=1;
598+ DCH2CSIZ=1;
599+ DCH2INTCLR=0x00FF00FF;
600+ DCH2CONSET=0x00000080;
601+}
602+
603+void play_wave(char* filename, int start){
604+ int i;
605+ // Stop the previous play
606+ stop_music();
607+ // Exit function if null filename
608+ if (filename[0]==0x00) {
609+ return;
610+ }
611+ // Alocate 524 byte buffer if not assigned
612+ if (g_var_size[ALLOC_WAVE_BLOCK]==0) {
613+ g_wavtable=(char*)alloc_memory(524/4,ALLOC_WAVE_BLOCK);
614+ }
615+ // Open file
616+ if (g_fhandle) FSfclose(g_fhandle);
617+ g_fhandle=FSfopen(filename,"r");
618+ if (!g_fhandle) err_file();
619+ // Read header and check if monaural 8 bit 16000 Hz.
620+ if (0x2c != FSfread((void*)&g_wavtable[0],1,0x2c,g_fhandle)) err_file();
621+ i=0;
622+ i+=checkChars((char*)&g_wavtable[0],"RIFF",4); // Check RIFF
623+ i+=checkChars((char*)&g_wavtable[8],"WAVEfmt ",8); // Check WAVE and fmt
624+ i+=checkChars((char*)&g_wavtable[16],"\x10\x00\x00\x00\x01\x00",6); // Check if liear PCM
625+ if (!checkChars((char*)&g_wavtable[22],"\x01\x00\x80\x3e\x00\x00\x80\x3e\x00\x00\x01\x00",12)) {
626+ // Monaural 16000 Hz
627+ } else if (!checkChars((char*)&g_wavtable[22],"\x01\x00\x54\x3d\x00\x00\x54\x3d\x00\x00\x01\x00",12)) {
628+ // Monaural 15700 Hz
629+ } else {
630+ i=1;
631+ }
632+ i+=checkChars((char*)&g_wavtable[34],"\x08\x00\x64\x61\x74\x61",6); // Check bit # and data
633+ if (i) err_wave();
634+ // Support defined start position here to skip file pointer here.
635+ FSfseek(g_fhandle, start, SEEK_CUR);
636+ // Read first 262 bytes.
637+ if (262 != FSfread((void*)&g_wavtable[0],1,262,g_fhandle)) err_file();
638+
639+ // Initialize DMA
640+ init_dma_music();
641+ g_sound_mode=SOUND_MODE_WAVE;
642+
643+ g_music_active=1;// Activate music system
644+}
--- /dev/null
+++ b/mips/protozoa/operator.c
@@ -0,0 +1,277 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include "compiler.h"
13+
14+/*
15+Operators: (upper ones have higher priority
16+()
17+* / %
18++ -
19+<< >>
20+< <= > >=
21+= !=
22+XOR
23+AND
24+OR
25+*/
26+
27+
28+const unsigned char g_priority[]={
29+ 0, // OP_VOID
30+ 1, // OP_OR
31+ 2, // OP_AND
32+ 3, // OP_XOR
33+ 4,4, // OP_EQ, OP_NEQ
34+ 5,5,5,5, // OP_LT, OP_LTE, OP_MT, OP_MTE
35+ 6,6, // OP_SHL, OP_SHR
36+ 7,7, // OP_ADD, OP_SUB
37+ 8,8,8 // OP_MUL, OP_DIV, OP_REM
38+};
39+
40+enum operator g_last_op;
41+
42+char* get_operator(void){
43+ char b1,b2,b3;
44+ next_position();
45+ b1=g_source[g_srcpos];
46+ b2=g_source[g_srcpos+1];
47+ b3=g_source[g_srcpos+2];
48+ switch(b1){
49+ case '%': g_last_op=OP_REM; break;
50+ case '/': g_last_op=OP_DIV; break;
51+ case '*': g_last_op=OP_MUL; break;
52+ case '-': g_last_op=OP_SUB; break;
53+ case '+': g_last_op=OP_ADD; break;
54+ case '>':
55+ if (b2=='>') {
56+ g_srcpos++;
57+ g_last_op=OP_SHR;
58+ } else if (b2=='=') {
59+ g_srcpos++;
60+ g_last_op=OP_MTE;
61+ } else {
62+ g_last_op=OP_MT;
63+ }
64+ break;
65+ case '<':
66+ if (b2=='<') {
67+ g_srcpos++;
68+ g_last_op=OP_SHL;
69+ } else if (b2=='=') {
70+ g_srcpos++;
71+ g_last_op=OP_LTE;
72+ } else {
73+ g_last_op=OP_LT;
74+ }
75+ break;
76+ case '!':
77+ if (b2!='=') return ERR_SYNTAX;
78+ g_srcpos++;
79+ g_last_op=OP_NEQ;
80+ break;
81+ case '=':
82+ if (b2=='=') g_srcpos++;
83+ g_last_op=OP_EQ;
84+ break;
85+ case 'X':
86+ if (b2!='O') return ERR_SYNTAX;
87+ if (b3!='R') return ERR_SYNTAX;
88+ g_srcpos++;
89+ g_srcpos++;
90+ g_last_op=OP_XOR;
91+ break;
92+ case 'O':
93+ if (b2!='R') return ERR_SYNTAX;
94+ g_srcpos++;
95+ g_last_op=OP_OR;
96+ break;
97+ case 'A':
98+ if (b2!='N') return ERR_SYNTAX;
99+ if (b3!='D') return ERR_SYNTAX;
100+ g_srcpos++;
101+ g_srcpos++;
102+ g_last_op=OP_AND;
103+ break;
104+ default:
105+ return ERR_SYNTAX;
106+ }
107+ g_srcpos++;
108+ return 0;
109+}
110+
111+char* get_floatOperator(void){
112+ char* err;
113+ int spos;
114+ next_position();
115+ spos=g_srcpos;
116+ err=get_operator();
117+ if (err) return err;
118+ switch(g_last_op){
119+ // Following operators cannot be used for float values.
120+ case OP_XOR:
121+ case OP_REM:
122+ case OP_SHR:
123+ case OP_SHL:
124+ g_srcpos=spos;
125+ return ERR_SYNTAX;
126+ default:
127+ return 0;
128+ }
129+}
130+
131+char* calculation(enum operator op){
132+ // $v0 = $v1 <op> $v0;
133+ switch(op){
134+ case OP_OR:
135+ check_obj_space(1);
136+ g_object[g_objpos++]=0x00621025; // or v0,v1,v0
137+ break;
138+ case OP_AND:
139+ check_obj_space(1);
140+ g_object[g_objpos++]=0x00621024; // and v0,v1,v0
141+ break;
142+ case OP_XOR:
143+ check_obj_space(1);
144+ g_object[g_objpos++]=0x00621026; // xor v0,v1,v0
145+ break;
146+ case OP_EQ:
147+ check_obj_space(2);
148+ g_object[g_objpos++]=0x00621026; // xor v0,v1,v0
149+ g_object[g_objpos++]=0x2C420001; // sltiu v0,v0,1
150+ break;
151+ case OP_NEQ:
152+ check_obj_space(2);
153+ g_object[g_objpos++]=0x00621026; // xor v0,v1,v0
154+ g_object[g_objpos++]=0x0002102B; // sltu v0,zero,v0
155+ break;
156+ case OP_LT:
157+ check_obj_space(1);
158+ g_object[g_objpos++]=0x0062102A; // slt v0,v1,v0
159+ break;
160+ case OP_LTE:
161+ check_obj_space(2);
162+ g_object[g_objpos++]=0x0043102A; // slt v0,v0,v1
163+ g_object[g_objpos++]=0x38420001; // xori v0,v0,0x1
164+ break;
165+ case OP_MT:
166+ check_obj_space(1);
167+ g_object[g_objpos++]=0x0043102A; // slt v0,v0,v1
168+ break;
169+ case OP_MTE:
170+ check_obj_space(2);
171+ g_object[g_objpos++]=0x0062102A; // slt v0,v1,v0
172+ g_object[g_objpos++]=0x38420001; // xori v0,v0,0x1
173+ break;
174+ case OP_SHR:
175+ check_obj_space(1);
176+ g_object[g_objpos++]=0x00431006; // srlv v0,v1,v0
177+ break;
178+ case OP_SHL:
179+ check_obj_space(1);
180+ g_object[g_objpos++]=0x00431004; // sllv v0,v1,v0
181+ break;
182+ case OP_ADD:
183+ check_obj_space(1);
184+ g_object[g_objpos++]=0x00621021; // addu v0,v1,v0
185+ break;
186+ case OP_SUB:
187+ check_obj_space(1);
188+ g_object[g_objpos++]=0x00621023; // subu v0,v1,v0
189+ break;
190+ case OP_MUL:
191+ check_obj_space(1);
192+ g_object[g_objpos++]=0x70621002; // mul v0,v1,v0
193+ break;
194+ case OP_DIV:
195+ // Note that intterupt functions do not use mflo and mfhi.
196+ // Probably using div does not cause delay of interrupt.
197+ check_obj_space(5);
198+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label
199+ g_object[g_objpos++]=0x0062001A; // div v1,v0
200+ call_lib_code(LIB_DIV0); // 2 words
201+ // label:
202+ g_object[g_objpos++]=0x00001012; // mflo v0
203+ break;
204+ case OP_REM:
205+ check_obj_space(5);
206+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label
207+ g_object[g_objpos++]=0x0062001A; // div v1,v0
208+ call_lib_code(LIB_DIV0); // 2 words
209+ // label:
210+ g_object[g_objpos++]=0x00001010; // mfhi v0
211+ break;
212+ default:
213+ return ERR_SYNTAX;
214+ }
215+ return 0;
216+}
217+
218+char* calculation_float(enum operator op){
219+ // $v0 = $a0 <op> $v0;
220+ // All the calculations will be done in library code, lib_float function (see below).
221+ call_lib_code(LIB_FLOAT | op);
222+ return 0;
223+}
224+
225+int lib_float(int ia0,int iv0, enum operator a1){
226+ // This function was called from _call_library().
227+ // Variable types must be all int.
228+ // Casting cannot be used.
229+ // Instead, by using pointer, put as int value, get as float value,
230+ // calculate, put as float value, then get as int value for returning.
231+ volatile float a0,v0;
232+ ((int*)(&a0))[0]=ia0;
233+ ((int*)(&v0))[0]=iv0;
234+ switch(a1){
235+ case OP_EQ:
236+ v0= a0==v0?1:0;
237+ break;
238+ case OP_NEQ:
239+ v0= a0!=v0?1:0;
240+ break;
241+ case OP_LT:
242+ v0= a0<v0?1:0;
243+ break;
244+ case OP_LTE:
245+ v0= a0<=v0?1:0;
246+ break;
247+ case OP_MT:
248+ v0= a0>v0?1:0;
249+ break;
250+ case OP_MTE:
251+ v0= a0>=v0?1:0;
252+ break;
253+ case OP_ADD:
254+ v0= a0+v0;
255+ break;
256+ case OP_SUB:
257+ v0= a0-v0;
258+ break;
259+ case OP_MUL:
260+ v0= a0*v0;
261+ break;
262+ case OP_DIV:
263+ if (v0==0) err_div_zero();
264+ v0= a0/v0;
265+ break;
266+ case OP_OR:
267+ v0= a0||v0?1:0;
268+ break;
269+ case OP_AND:
270+ v0= a0&&v0?1:0;
271+ break;
272+ default:
273+ err_unknown();
274+ return 0;
275+ }
276+ return ((int*)(&v0))[0];
277+};
\ No newline at end of file
--- /dev/null
+++ b/mips/protozoa/protozoa.mcp
@@ -0,0 +1,210 @@
1+[HEADER]
2+magic_cookie={66E99B07-E706-4689-9E80-9B2582898A13}
3+file_version=1.0
4+device=PIC32MX150F128B
5+[PATH_INFO]
6+BuildDirPolicy=BuildDirIsProjectDir
7+dir_src=
8+dir_bin=
9+dir_tmp=
10+dir_sin=
11+dir_inc=
12+dir_lib=C:\Program Files\Microchip\xc32\v1.42\pic32mx\lib
13+dir_lkr=
14+[CAT_FILTERS]
15+filter_src=*.s;*.c
16+filter_inc=*.h;*.inc
17+filter_obj=*.o
18+filter_lib=*.a
19+filter_lkr=*.ld
20+[CAT_SUBFOLDERS]
21+subfolder_src=
22+subfolder_inc=
23+subfolder_obj=
24+subfolder_lib=
25+subfolder_lkr=
26+[FILE_SUBFOLDERS]
27+file_000=.
28+file_001=.
29+file_002=.
30+file_003=.
31+file_004=.
32+file_005=.
33+file_006=.
34+file_007=.
35+file_008=.
36+file_009=.
37+file_010=.
38+file_011=.
39+file_012=.
40+file_013=.
41+file_014=.
42+file_015=.
43+file_016=.
44+file_017=.
45+file_018=.
46+file_019=.
47+file_020=.
48+file_021=.
49+file_022=.
50+file_023=.
51+file_024=.
52+file_025=.
53+file_026=.
54+file_027=.
55+file_028=.
56+file_029=.
57+file_030=.
58+file_031=.
59+file_032=.
60+file_033=.
61+file_034=.
62+file_035=.
63+file_036=.
64+file_037=.
65+file_038=.
66+file_039=.
67+file_040=.
68+[GENERATED_FILES]
69+file_000=no
70+file_001=no
71+file_002=no
72+file_003=no
73+file_004=no
74+file_005=no
75+file_006=no
76+file_007=no
77+file_008=no
78+file_009=no
79+file_010=no
80+file_011=no
81+file_012=no
82+file_013=no
83+file_014=no
84+file_015=no
85+file_016=no
86+file_017=no
87+file_018=no
88+file_019=no
89+file_020=no
90+file_021=no
91+file_022=no
92+file_023=no
93+file_024=no
94+file_025=no
95+file_026=no
96+file_027=no
97+file_028=no
98+file_029=no
99+file_030=no
100+file_031=no
101+file_032=no
102+file_033=no
103+file_034=no
104+file_035=no
105+file_036=no
106+file_037=no
107+file_038=no
108+file_039=no
109+file_040=no
110+[OTHER_FILES]
111+file_000=no
112+file_001=no
113+file_002=no
114+file_003=no
115+file_004=no
116+file_005=no
117+file_006=no
118+file_007=no
119+file_008=no
120+file_009=no
121+file_010=no
122+file_011=no
123+file_012=no
124+file_013=no
125+file_014=no
126+file_015=no
127+file_016=no
128+file_017=no
129+file_018=no
130+file_019=no
131+file_020=no
132+file_021=no
133+file_022=no
134+file_023=no
135+file_024=no
136+file_025=no
137+file_026=no
138+file_027=no
139+file_028=no
140+file_029=no
141+file_030=no
142+file_031=no
143+file_032=no
144+file_033=no
145+file_034=no
146+file_035=no
147+file_036=no
148+file_037=no
149+file_038=no
150+file_039=no
151+file_040=no
152+[FILE_INFO]
153+file_000=args.c
154+file_001=class.c
155+file_002=cmpdata.c
156+file_003=compiler.c
157+file_004=debug.c
158+file_005=editor.c
159+file_006=envspecific.c
160+file_007=error.c
161+file_008=exception.c
162+file_009=file.c
163+file_010=float.c
164+file_011=function.c
165+file_012=globalvars.c
166+file_013=library.c
167+file_014=linker.c
168+file_015=main.c
169+file_016=memory.c
170+file_017=music.c
171+file_018=operator.c
172+file_019=run.c
173+file_020=statement.c
174+file_021=string.c
175+file_022=timer.c
176+file_023=value.c
177+file_024=varname.c
178+file_025=interface\graphlib.c
179+file_026=interface\keyinput.c
180+file_027=interface\LCDdriver.c
181+file_028=api.h
182+file_029=compiler.h
183+file_030=debug.h
184+file_031=editor.h
185+file_032=envspecific.h
186+file_033=main.h
187+file_034=interface\keyinput.h
188+file_035=interface\LCDdriver.h
189+file_036=interface\ps2keyboard.h
190+file_037=interface\SDFSIO.h
191+file_038=interface\videoout.h
192+file_039=interface\libsdfsio.a
193+file_040=App_32MX170F256B.ld
194+[SUITE_INFO]
195+suite_guid={62D235D8-2DB2-49CD-AF24-5489A6015337}
196+suite_state=
197+[TOOL_SETTINGS]
198+TS{6F324298-6323-4781-8C43-43FA5E6F3646}=-gdwarf-2
199+TS{1F324EFA-C0BA-4A8F-A85A-B21644939CAD}=-g -D_SUPPRESS_PLIB_WARNING -O1
200+TS{29D3B6CC-DCAB-4659-8011-FFF75BB7F8D7}=-o"$(BINDIR_)$(TARGETBASE).$(TARGETSUFFIX)" -Map="$(BINDIR_)$(TARGETBASE).map"
201+TS{AD4C3FBD-B6BB-4F50-AB4E-35BF132D4D60}=
202+[INSTRUMENTED_TRACE]
203+enable=0
204+transport=0
205+format=0
206+[CUSTOM_BUILD]
207+Pre-Build=
208+Pre-BuildEnabled=1
209+Post-Build=
210+Post-BuildEnabled=1
--- /dev/null
+++ b/mips/protozoa/run.c
@@ -0,0 +1,133 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include <xc.h>
13+#include "api.h"
14+#include "compiler.h"
15+#include "editor.h"
16+#include "main.h"
17+
18+char* printdec(int num){
19+ char str[11];
20+ int i;
21+ if (num<0) {
22+ printchar('-');
23+ num=0-num;
24+ }
25+ for(i=10;0<i;i--){
26+ if (num==0 && i<10) break;
27+ str[i]='0'+rem10_32(num);
28+ num=div10_32(num);
29+ }
30+ for(i++;i<11;i++) {
31+ printchar(str[i]);
32+ }
33+}
34+
35+int runbasic(char *appname,int test){
36+// BASICソースのコンパイルと実行
37+// appname 実行するBASICソースファイル
38+// test 0:コンパイルと実行、0以外:コンパイルのみで終了
39+//
40+// 戻り値
41+//  0:正常終了
42+//  -1:ファイルエラー
43+//  -2:リンクエラー
44+//  1以上:コンパイルエラーの発生行(行番号ではなくファイル上の何行目か)
45+ int i;
46+ char* buff;
47+ char* err;
48+
49+ // Set grobal pointer
50+ g_gp=get_gp();
51+ // Set buffer positions
52+ buff=(char*)&(RAM[RAMSIZE-512]);
53+ // Set object positions
54+ g_object=(int*)(&RAM[0]);
55+ g_objpos=0;
56+ g_objmax=g_object+(RAMSIZE-512)/4; // Buffer area excluded.
57+ // Clear object area
58+ for(i=0;i<RAMSIZE/4;i++) g_object[i]=0x00000000;
59+
60+ // Check file error
61+ err=init_file(buff,appname);
62+ if (err) {
63+ setcursorcolor(COLOR_ERRORTEXT);
64+ printstr("Can't Open ");
65+ printstr(appname);
66+ printchar('\n');
67+ return -1;
68+ }
69+ close_file();
70+
71+ // Initialize parameters
72+ g_pcg_font=0;
73+ g_use_graphic=0;
74+ g_graphic_area=0;
75+ clearscreen();
76+ setcursor(0,0,7);
77+ g_long_name_var_num=0;
78+ cmpdata_init();
79+
80+ // Initialize music system
81+ init_music();
82+
83+ printstr("BASIC "BASVER"\n");
84+ wait60thsec(15);
85+
86+ printstr("Compiling...");
87+
88+ // Compile the file
89+ i=compile_and_link_main_file(buff,appname);
90+ if (i) return i;
91+
92+ // All done
93+ printstr("done\n");
94+ if(test) return 0; //コンパイルのみの場合
95+ wait60thsec(15);
96+
97+ // Initialize the other parameters
98+ // Random seed
99+ g_rnd_seed=0x92D68CA2; //2463534242
100+ // Clear variables
101+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
102+ g_var_mem[i]=0;
103+ g_var_size[i]=0;
104+ }
105+ // Clear key input buffer
106+ for(i=0;i<256;i++){
107+ ps2keystatus[i]=0;
108+ }
109+ // Reset data/read.
110+ reset_dataread();
111+ // Initialize file system
112+ lib_file(FUNC_FINIT,0,0,0);
113+
114+ // Assign memory
115+ set_free_area((void*)(g_object+g_objpos),(void*)(&RAM[RAMSIZE]));
116+
117+ // Warm up environment
118+ pre_run();
119+ init_timer();
120+
121+ // Execute program
122+ // Start program from the beginning of RAM.
123+ // Work area (used for A-Z values) is next to the object code area.
124+ start_program((void*)(&(RAM[0])),(void*)(&g_var_mem[0]));
125+ printstr("\nOK\n");
126+
127+ // Cool down environment
128+ post_run();
129+ lib_file(FUNC_FINIT,0,0,0);
130+ stop_timer();
131+
132+ return 0;
133+}
--- /dev/null
+++ b/mips/protozoa/statement.c
@@ -0,0 +1,1771 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include "api.h"
13+#include "compiler.h"
14+
15+char* rem_statement(){
16+ if (g_source[g_srcpos-4]<0x20) {
17+ // This line contains only "REM" statement
18+ // Delete $s6-setting command if exists.
19+ if ((g_object[g_objpos-1]&0xffff0000)==0x34160000) g_objpos--;
20+ }
21+ while(0xE0 & g_source[g_srcpos]){
22+ g_srcpos++;
23+ }
24+ return 0;
25+}
26+
27+char* sound_statement(){
28+ char *err;
29+ err=get_label();
30+ if (err) return err;
31+ if (g_label) {
32+ // Label/number is constant.
33+ // Linker will change following codes later.
34+ // Note that 0x0814xxxx and 0x0815xxxx are specific codes for these.
35+ check_obj_space(2);
36+ g_object[g_objpos++]=0x08140000|((g_label>>16)&0x0000FFFF); // lui v0,xxxx
37+ g_object[g_objpos++]=0x08150000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
38+ } else {
39+ // Label/number will be dynamically set when executing code.
40+ err=get_value();
41+ if (err) return err;
42+ call_lib_code(LIB_LABEL);
43+ }
44+ // 2nd param is optional
45+ next_position();
46+ if (g_source[g_srcpos]==',') {
47+ g_srcpos++;
48+ check_obj_space(2);
49+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
50+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
51+ err=get_value();
52+ if (err) return err;
53+ check_obj_space(3);
54+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
55+ g_object[g_objpos++]=0x8FA20004; // lw v0,4(sp)
56+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
57+ } else {
58+ // Set 3 if omitted
59+ check_obj_space(1);
60+ g_object[g_objpos++]=0x24040003; // addiu a0,zero,xx
61+ }
62+ call_lib_code(LIB_SOUND);
63+ return 0;
64+}
65+char* music_statement(){
66+ char *err;
67+ err=get_string();
68+ if (err) return err;
69+ // 2nd param is optional
70+ next_position();
71+ if (g_source[g_srcpos]==',') {
72+ g_srcpos++;
73+ check_obj_space(2);
74+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
75+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
76+ err=get_value();
77+ if (err) return err;
78+ check_obj_space(3);
79+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
80+ g_object[g_objpos++]=0x8FA20004; // lw v0,4(sp)
81+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
82+ } else {
83+ // Set 3 if omitted
84+ check_obj_space(1);
85+ g_object[g_objpos++]=0x24040003; // addiu a0,zero,xx
86+ }
87+ call_lib_code(LIB_MUSIC);
88+ return 0;
89+}
90+
91+char* exec_statement(){
92+ char *err;
93+ char b1;
94+ int i,prevpos;
95+ b1=g_source[g_srcpos];
96+ while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){
97+ prevpos=g_objpos;
98+ g_valueisconst=1;
99+ err=get_simple_value();
100+ if (!g_valueisconst) err=ERR_SYNTAX;
101+ if (err) return err;
102+ check_obj_space(1);
103+ g_objpos=prevpos;
104+ g_object[g_objpos++]=g_intconst;
105+ next_position();
106+ b1=g_source[g_srcpos];
107+ if (b1!=',') break;
108+ g_srcpos++;
109+ next_position();
110+ b1=g_source[g_srcpos];
111+ if (b1==0x0d || b1==0x0a) {
112+ // Multiline DATA/EXEC statement
113+ g_line++;
114+ g_fileline++;
115+ if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
116+ g_srcpos++;
117+ // Maintain at least 256 characters in cache.
118+ if (256<=g_srcpos) read_file(256);
119+ next_position();
120+ b1=g_source[g_srcpos];
121+ }
122+ }
123+ return 0;
124+}
125+
126+char* cdata_statement(){
127+ // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero)
128+ // are the sign of data region
129+ int beginpos,prevpos;
130+ char* err;
131+ char b1;
132+ char* cpy;
133+ int shift=0;
134+ int i=0;
135+ // This statement is not valid in class file.
136+ if (g_compiling_class) return ERR_INVALID_CLASS;
137+ beginpos=g_objpos;
138+ check_obj_space(2);
139+ g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx
140+ g_object[g_objpos++]=0x00000020; // add zero,zero,zero
141+ next_position();
142+ b1=g_source[g_srcpos];
143+ while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){
144+ prevpos=g_objpos;
145+ g_valueisconst=1;
146+ err=get_simple_value();
147+ if (!g_valueisconst) err=ERR_SYNTAX;
148+ if (g_intconst<0x00 || 0xff<g_intconst) err=ERR_SYNTAX;
149+ if (err) return err;
150+ g_objpos=prevpos;
151+ i|=g_intconst<<shift;
152+ shift+=8;
153+ if (32<=shift) {
154+ check_obj_space(1);
155+ g_object[g_objpos++]=i;
156+ shift=0;
157+ i=0;
158+ }
159+ next_position();
160+ b1=g_source[g_srcpos];
161+ if (b1!=',') break;
162+ g_srcpos++;
163+ next_position();
164+ b1=g_source[g_srcpos];
165+ if (b1==0x0d || b1==0x0a) {
166+ // Multiline CDATA statement
167+ g_line++;
168+ g_fileline++;
169+ if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
170+ g_srcpos++;
171+ // Maintain at least 256 characters in cache.
172+ if (256<=g_srcpos) read_file(256);
173+ next_position();
174+ b1=g_source[g_srcpos];
175+ }
176+ }
177+ // Write the last 1-3 bytes and shift data if total # is not multipes of 4.
178+ if (0<shift) {
179+ // Convert shift value from bit-shift to data byte-shift.
180+ shift=4-shift/8;
181+ check_obj_space(1);
182+ g_object[g_objpos++]=i;
183+ for(cpy=(char*)&g_object[g_objpos]-1;(char*)&g_object[beginpos+2]<cpy;cpy--){
184+ cpy[0]=cpy[0-shift];
185+ }
186+ }
187+ // Determine the size of data
188+ i=g_objpos-beginpos-1;
189+ g_object[beginpos] =0x04110000|i; // bgezal zero,xxxx
190+ g_object[beginpos+1]=0x00000020|shift; // add zero,zero,zero
191+ return 0;
192+}
193+
194+char* data_statement(){
195+ // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero)
196+ // are the sign of data region
197+ int i,prevpos;
198+ char* err;
199+ // This statement is not valid in class file.
200+ if (g_compiling_class) return ERR_INVALID_CLASS;
201+ while(1){
202+ prevpos=g_objpos;
203+ check_obj_space(2);
204+ g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx
205+ g_object[g_objpos++]=0x00000020; // add zero,zero,zero
206+ next_position();
207+ if (g_source[g_srcpos]=='"') {
208+ // Constant string
209+ // Store pointer to string. This is 3 words bellow of current position
210+ g_object[g_objpos]=(int)(&g_object[g_objpos+3]);
211+ g_objpos++;
212+ g_object[prevpos]=0x04110002; // bgezal zero,xxxx
213+ err=simple_string();
214+ if (err) return err;
215+ next_position();
216+ if (g_source[g_srcpos]==',') {
217+ g_srcpos++;
218+ continue;
219+ }
220+ return 0;
221+ }
222+ err=exec_statement();
223+ if (err) return err;
224+ // Determine the size of data
225+ i=g_objpos-prevpos-1;
226+ g_object[prevpos]=0x04110000|i; // bgezal zero,xxxx
227+ if (g_source[g_srcpos]=='"') {
228+ // Constant string
229+ continue;
230+ }
231+ return 0;
232+ }
233+}
234+
235+char* clear_statement(){
236+ call_lib_code(LIB_CLEAR);
237+ return 0;
238+}
239+
240+char* poke_statement_sub(int bits){
241+ char* err;
242+ err=get_value();
243+ if (err) return err;
244+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
245+ g_srcpos++;
246+ check_obj_space(2);
247+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
248+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
249+ err=get_value();
250+ if (err) return err;
251+ check_obj_space(3);
252+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
253+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
254+ switch(bits){
255+ case 32:
256+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
257+ break;
258+ case 16:
259+ g_object[g_objpos++]=0xA4620000; // sh v0,0(v1)
260+ break;
261+ case 8:
262+ default:
263+ g_object[g_objpos++]=0xA0620000; // sb v0,0(v1)
264+ break;
265+ }
266+ return 0;
267+}
268+
269+char* dim_statement(){
270+ char* err;
271+ char b1;
272+ int i;
273+ int spos;
274+ int stack;
275+ while(1){
276+ stack=0;
277+ next_position();
278+ i=get_var_number();
279+ if (i<0) return ERR_SYNTAX;
280+ if (g_source[g_srcpos]=='#') g_srcpos++;
281+ next_position();
282+ if (g_source[g_srcpos]!='(') return ERR_SYNTAX;
283+ check_obj_space(1);
284+ spos=g_objpos++; // addiu sp,sp,xxxx
285+ do {
286+ g_srcpos++;
287+ err=get_value();
288+ if (err) return err;
289+ stack+=4;
290+ check_obj_space(1);
291+ g_object[g_objpos++]=0xAFA20000|stack; // sw v0,8(sp)
292+ } while (g_source[g_srcpos]==',');
293+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
294+ g_srcpos++;
295+ check_obj_space(3);
296+ g_object[g_objpos++]=0x24040000|(i); // addiu a0,zero,xx
297+ g_object[g_objpos++]=0x24050000|(stack/4); // addiu a1,zero,xxxx
298+ g_object[g_objpos++]=0x03A01025; // or v0,sp,zero
299+ call_lib_code(LIB_DIM);
300+ // Stack -/+
301+ check_obj_space(1);
302+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xxxx
303+ stack=(0-stack)&0x0000FFFF;
304+ g_object[spos]=0x27BD0000|stack; // addiu sp,sp,xxxx
305+ next_position();
306+ if (g_source[g_srcpos]!=',') break;
307+ g_srcpos++;
308+ }
309+ return 0;
310+}
311+
312+char* label_statement(){
313+ char* err;
314+ char b1;
315+ b1=g_source[g_srcpos];
316+ if (b1<'A' || 'Z'<b1) return ERR_SYNTAX; // Number is not allowed here.
317+ err=get_label();
318+ if (err) return err;
319+ // Check existing label with the same name here.
320+ if (search_label(g_label)) {
321+ // Error: duplicate labels
322+ printstr("Label ");
323+ printstr(resolve_label(g_label));
324+ return ERR_MULTIPLE_LABEL;
325+ }
326+ check_obj_space(2);
327+ g_object[g_objpos++]=0x3C160000|((g_label>>16)&0x0000FFFF); //lui s6,yyyy;
328+ g_object[g_objpos++]=0x36D60000|(g_label&0x0000FFFF); //ori s6,s6,zzzz;
329+ return 0;
330+}
331+
332+char* restore_statement(){
333+ char* err;
334+ // This statement is not valid in class file.
335+ if (g_compiling_class) return ERR_INVALID_CLASS;
336+ err=get_label();
337+ if (err) return err;
338+ if (g_label) {
339+ // Constant label/number
340+ // Use 32 bit mode also for values<65536
341+ // This code will be replaced to code for v0 for pointer in linker.
342+ check_obj_space(2);
343+ g_object[g_objpos++]=0x3C020000|(g_label>>16); // lui v0,xxxx
344+ g_object[g_objpos++]=0x34420000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
345+ } else {
346+ // Dynamic number
347+ err=get_value();
348+ if (err) return err;
349+ }
350+ call_lib_code(LIB_RESTORE);
351+ return 0;
352+}
353+
354+char* gosub_statement_sub(){
355+ char* err;
356+ err=get_label();
357+ if (err) return err;
358+ if (g_label) {
359+ // Label/number is constant.
360+ // Linker will change following codes later.
361+ // Note that 0x0812xxxx and 0x0813xxxx are specific codes for these.
362+ check_obj_space(7);
363+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
364+ g_object[g_objpos++]=0x04130003; // bgezall zero,label1
365+ g_object[g_objpos++]=0xAEBD0000|ARGS_S5_SP; // sw sp,-12(s5)
366+ g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
367+ g_object[g_objpos++]=0x08120000|((g_label>>16)&0x0000FFFF); // nop
368+ // label1:
369+ g_object[g_objpos++]=0x08130000|(g_label&0x0000FFFF); // j xxxx
370+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
371+ // label2:
372+ } else {
373+ // Label/number will be dynamically set when executing code.
374+ err=get_value();
375+ if (err) return err;
376+ call_lib_code(LIB_LABEL);
377+ check_obj_space(7);
378+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
379+ g_object[g_objpos++]=0x04130003; // bgezall zero,label1
380+ g_object[g_objpos++]=0xAEBD0000|ARGS_S5_SP; // sw sp,-12(s5)
381+ g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
382+ g_object[g_objpos++]=0x00000000; // nop
383+ // label1:
384+ g_object[g_objpos++]=0x00400008; // jr v0
385+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
386+ // label2:
387+ }
388+ return 0;
389+}
390+
391+char* gosub_statement(){
392+ char* err;
393+ int opos,spos,stack;
394+ // Skip label first (see below)
395+ opos=g_objpos;
396+ spos=g_srcpos;
397+ err=gosub_statement_sub();
398+ if (err) return err;
399+ next_position();
400+ // Rewind object and construct argument-creating routine.
401+ g_objpos=opos;
402+ // Begin parameter(s) construction routine
403+ g_object[g_objpos++]=0x8EA20000|ARGS_S5_V0_OBJ; // lw v0,-8(s5)
404+ err=prepare_args_stack(',');
405+ if (err) return err;
406+ // Rewind source and construct GOSUB routine again.
407+ opos=spos;
408+ spos=g_srcpos;
409+ g_srcpos=opos;
410+ err=gosub_statement_sub();
411+ if (err) return err;
412+ // Remove stack
413+ err=remove_args_stack();
414+ if (err) return err;
415+ // All done, go back to right source position
416+ g_srcpos=spos;
417+ return 0;
418+}
419+
420+char* return_statement(){
421+ char* err;
422+ char b1;
423+ next_position();
424+ b1=g_source[g_srcpos];
425+ if (0x20<b1 && b1!=':') {
426+ // There is a return value.
427+ err=get_stringFloatOrValue();
428+ if (err) return err;
429+ }
430+ check_obj_space(4);
431+ g_object[g_objpos++]=0x8EBD0000|ARGS_S5_SP; // lw sp,-12(s5)
432+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
433+ g_object[g_objpos++]=0x00600008; // jr v1
434+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
435+ return 0;
436+}
437+
438+char* goto_statement(){
439+ char* err;
440+ err=get_label();
441+ if (err) return err;
442+ if (g_label) {
443+ // Label/number is constant.
444+ // Linker will change following codes later.
445+ // Note that 0x0810xxxx and 0x0811xxxx are specific codes for these.
446+ check_obj_space(2);
447+ g_object[g_objpos++]=0x08100000|((g_label>>16)&0x0000FFFF); // j xxxx
448+ g_object[g_objpos++]=0x08110000|(g_label&0x0000FFFF); // nop
449+ } else {
450+ // Label/number will be dynamically set when executing code.
451+ err=get_value();
452+ if (err) return err;
453+ call_lib_code(LIB_LABEL);
454+ check_obj_space(2);
455+ g_object[g_objpos++]=0x00400008; // jr v0
456+ g_object[g_objpos++]=0x00000000; // nop
457+ }
458+ return 0;
459+}
460+
461+char* if_statement(){
462+ char* err;
463+ int prevpos,bpos;
464+ // Get value.
465+ err=get_floatOrValue();
466+ if (err) return err;
467+ // Check "THEN"
468+ if (!nextCodeIs("THEN")) return ERR_SYNTAX;
469+ // Check if statement follows after THEN statement
470+ next_position();
471+ if (nextCodeIs("REM")) {
472+ // If REM statement follows, skip comment words.
473+ rem_statement();
474+ }
475+ if (g_source[g_srcpos]<0x20) {
476+ // End of line.
477+ // Use IF-THEN-ENDIF mode (multiple line mode)
478+ check_obj_space(3);
479+ g_object[g_objpos++]=0x30000000; // nop (see linker)
480+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
481+ g_object[g_objpos++]=0x30000000; // nop (see linker)
482+ return 0;
483+ }
484+ // One line mode
485+ // If $v0=0 then skip.
486+ bpos=g_objpos;
487+ check_obj_space(2);
488+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
489+ g_object[g_objpos++]=0x00000000; // nop
490+ prevpos=g_srcpos;
491+ if (statement()) {
492+ // May be label
493+ g_srcpos=prevpos;
494+ err=goto_statement();
495+ if (err) return err;
496+ } else {
497+ // Must be statement(s)
498+ while(1) {
499+ if (g_source[g_srcpos]!=':') break;
500+ g_srcpos++;
501+ err=statement();
502+ if (err) return err;
503+ }
504+ }
505+ // Check if "ELSE" exists.
506+ if (!nextCodeIs("ELSE ")) {
507+ // "ELSE" not found. This is the end of "IF" statement.
508+ // Previous branch command must jump to this position.
509+ g_object[bpos]=0x10400000|(g_objpos-bpos-1); // beq v0,zero,xxxx
510+ return 0;
511+ }
512+ // Skip after ELSE if required.
513+ check_obj_space(2);
514+ g_object[g_objpos++]=0x10000000; // beq zero,zero,xxxx
515+ g_object[g_objpos++]=0x00000000; // nop
516+ // Previous branch command must jump to this position.
517+ g_object[bpos]=0x10400000|(g_objpos-bpos-1); // beq v0,zero,xxxx
518+ bpos=g_objpos-2;
519+ // Next statement is either label or general statement
520+ prevpos=g_srcpos;
521+ if (statement()) {
522+ // May be label
523+ g_srcpos=prevpos;
524+ err=goto_statement();
525+ if (err) return err;
526+ } else {
527+ // Must be statement(s)
528+ while(1) {
529+ if (g_source[g_srcpos]!=':') break;
530+ g_srcpos++;
531+ err=statement();
532+ if (err) return err;
533+ }
534+ }
535+ // Previous branch command must jump to this position.
536+ g_object[bpos]=0x10000000|(g_objpos-bpos-1); // beq zero,zero,xxxx
537+ return 0;
538+}
539+
540+char* elseif_statement(void){
541+ // Multiple line mode
542+ char* err;
543+ g_object[g_objpos++]=0x08160100; // breakif (see linker)
544+ g_object[g_objpos++]=0x30008000; // nop (see linker)
545+ // Get value.
546+ err=get_floatOrValue();
547+ if (err) return err;
548+ // Check "THEN"
549+ if (!nextCodeIs("THEN")) return ERR_SYNTAX;
550+ // Check if statement follows after THEN statement
551+ if (nextCodeIs("REM")) {
552+ // If REM statement follows, skip comment words.
553+ rem_statement();
554+ }
555+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
556+ // Statement didn't follow after THEM statement (that is correct).
557+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
558+ g_object[g_objpos++]=0x30000000; // nop (see linker)
559+ return 0;
560+
561+}
562+
563+char* else_statement(void){
564+ // Multiple line mode
565+ g_object[g_objpos++]=0x08160100; // breakif (see linker)
566+ g_object[g_objpos++]=0x30008000; // nop (see linker)
567+ g_object[g_objpos++]=0x30000000; // nop (see linker)
568+ // Check if statement follows after THEN statement
569+ if (nextCodeIs("REM")) {
570+ // If REM statement follows, skip comment words.
571+ rem_statement();
572+ }
573+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
574+ // Statement didn't follow after THEM statement (that is correct).
575+ return 0;
576+}
577+
578+char* endif_statement(void){
579+ // Multiple line mode
580+ g_object[g_objpos++]=0x30008000; // nop (see linker)
581+ g_object[g_objpos++]=0x30008000; // nop (see linker)
582+ // Check if statement follows after THEN statement
583+ if (nextCodeIs("REM")) {
584+ // If REM statement follows, skip comment words.
585+ rem_statement();
586+ }
587+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
588+ // Statement didn't follow after THEM statement (that is correct).
589+ return 0;
590+}
591+
592+char* end_statement(void){
593+ int i;
594+ i=(int)&g_end_addr;
595+ i-=g_gp;
596+ check_obj_space(3);
597+ g_object[g_objpos++]=0x8F820000|(i&0x0000FFFF); // lw v0,xxxx(gp)
598+ g_object[g_objpos++]=0x00400008; // jr v0
599+ g_object[g_objpos++]=0x00000000; // nop
600+ return 0;
601+}
602+
603+char* let_dim_sub(int i){
604+ char* err;
605+ g_srcpos++;
606+ err=get_value();
607+ if (err) return err;
608+ check_obj_space(4);
609+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
610+ g_object[g_objpos++]=0x8FC30000|(i*4); // lw v1,xx(s8)
611+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
612+ g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
613+ while(g_source[g_srcpos]==','){
614+ g_srcpos++;
615+ err=get_value();
616+ if (err) return err;
617+ check_obj_space(4);
618+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
619+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
620+ g_object[g_objpos++]=0x8C630000; // lw v1,0(v1)
621+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
622+ g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
623+ }
624+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
625+ g_srcpos++;
626+ return 0;
627+};
628+
629+char* let_statement(){
630+ char* err;
631+ char b2,b3;
632+ int i,spos,opos;
633+ next_position();
634+ i=get_var_number();
635+ if (i<0) return ERR_SYNTAX;
636+ b2=g_source[g_srcpos];
637+ b3=g_source[g_srcpos+1];
638+ if (b2=='#' && b3=='(') {
639+ // Float dimension
640+ g_srcpos++;
641+ check_obj_space(1);
642+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
643+ let_dim_sub(i);
644+ next_position();
645+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
646+ g_srcpos++;
647+ err=get_float();
648+ if (err) return err;
649+ check_obj_space(3);
650+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
651+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
652+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
653+ return 0;
654+ } else if (b2=='#') {
655+ // Float A-Z
656+ g_srcpos++;
657+ next_position();
658+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
659+ g_srcpos++;
660+ err=get_float();
661+ if (err) return err;
662+ check_obj_space(1);
663+ g_object[g_objpos++]=0xAFC20000|(i*4); // sw v0,xxx(s8)
664+ return 0;
665+ } else if (b2=='$') {
666+ // String
667+ g_srcpos++;
668+ next_position();
669+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
670+ g_srcpos++;
671+ err=get_string();
672+ if (err) return err;
673+ check_obj_space(1);
674+ g_object[g_objpos++]=0x24040000|(i); //addiu a0,zero,xx
675+ call_lib_code(LIB_LETSTR);
676+ return 0;
677+ } else if (b2=='(') {
678+ // Dimension
679+ check_obj_space(1);
680+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
681+ let_dim_sub(i);
682+ if (g_source[g_srcpos]=='.') {
683+ // This is an object. Determine the filed of this object.
684+ // 4(sp) contains the address of dimension value
685+ // The dimension value is the pointer to object
686+ g_srcpos++;
687+ check_obj_space(3);
688+ g_object[g_objpos++]=0x8FA20004; // lw v0,4(sp)
689+ g_object[g_objpos++]=0x8C420000; // lw v0,0(v0) g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
690+ return let_object_field();
691+ }
692+ next_position();
693+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
694+ g_srcpos++;
695+ err=get_value();
696+ if (err) return err;
697+ check_obj_space(3);
698+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
699+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
700+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
701+ return 0;
702+ } else if (b2=='.') {
703+ // Field of object
704+ g_srcpos++;
705+ check_obj_space(1);
706+ g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
707+ return let_object_field();
708+ } else {
709+ // Integer A-Z
710+ next_position();
711+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
712+ g_srcpos++;
713+ err=get_value();
714+ if (err) return err;
715+ check_obj_space(1);
716+ g_object[g_objpos++]=0xAFC20000|(i*4); // sw v0,xxx(s8)
717+ }
718+ return 0;
719+}
720+
721+char* print_statement_main(enum libs lib_printstr, enum libs lib_string){
722+ char* err;
723+ char b1;
724+ int i;
725+ int status=0;// 1:',' 2:';' 0:none
726+ while(1){
727+ next_position();
728+ if (endOfStatement()) break;
729+ if (!strncmp(g_source+g_srcpos,"ELSE " ,5)) break;
730+ err=get_stringFloatOrValue();
731+ if (err) return err;
732+ switch(g_lastvar){
733+ case VAR_INTEGER:
734+ // Use DEC$() function.
735+ call_lib_code(LIB_DEC);
736+ break;
737+ case VAR_FLOAT:
738+ // Use FLOAT$() function.
739+ check_obj_space(2);
740+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
741+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x0000
742+ call_lib_code(LIB_SPRINTF);
743+ break;
744+ case VAR_STRING:
745+ default:
746+ break;
747+ }
748+ // Call printstr() function
749+ // First argument is the pointer to string
750+ call_lib_code(lib_printstr);
751+ next_position();
752+ b1=g_source[g_srcpos];
753+ if (b1==',') {
754+ status=1;
755+ g_srcpos++;
756+ // Call lib_string() function for comma (,)
757+ check_obj_space(1);
758+ g_object[g_objpos++]=0x34020001; // ori v0,zero,1
759+ call_lib_code(lib_string);
760+ } else if (b1==';') {
761+ status=2;
762+ g_srcpos++;
763+ } else {
764+ status=0;
765+ }
766+ }
767+ if (status==0) {
768+ // Call lib_string() function for CR (\n)
769+ check_obj_space(1);
770+ g_object[g_objpos++]=0x34020000; // ori v0,zero,0
771+ call_lib_code(lib_string);
772+ }
773+ return 0;
774+}
775+
776+char* break_statement(){
777+ check_obj_space(2);
778+ g_object[g_objpos++]=0x08160000; // j xxxx (See link() function)
779+ g_object[g_objpos++]=0x00000000; // nop
780+ return 0;
781+}
782+
783+char* continue_statement(){
784+ check_obj_space(2);
785+ g_object[g_objpos++]=0x08160008; // j xxxx (See link() function)
786+ g_object[g_objpos++]=0x00000000; // nop
787+ return 0;
788+}
789+
790+char* for_statement(){
791+ char* err;
792+// char b1;
793+ int i;
794+ int prepos=g_srcpos;
795+ // Initialization of variable
796+// next_position();
797+// b1=g_source[g_srcpos];
798+ i=get_var_number();
799+// if (b1<'A' || 'Z'<b1) return ERR_SYNTAX;
800+ if (i<0) return ERR_SYNTAX;
801+ g_srcpos=prepos;
802+ err=let_statement();
803+ if (err) return err;
804+ // Check if "TO" exists
805+ if (!nextCodeIs("TO ")) return ERR_SYNTAX;
806+ err=get_value();
807+ if (err) return err;
808+ // Usage of stack:
809+ // 12(sp): "TO" value
810+ // 8(sp): "STEP" value
811+ // 4(sp): Address to return to in "NEXT" statement.
812+ // Store "TO" value in stack
813+ check_obj_space(2);
814+ g_object[g_objpos++]=0x0820FFF4; // addiu sp,sp,-12 (see linker)
815+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
816+ // Check if "STEP" exists
817+ g_valueisconst=1;
818+ if (nextCodeIs("STEP ")) {
819+ // "STEP" exists. Get value
820+ err=get_value();
821+ if (err) return err;
822+ } else {
823+ // "STEP" not exist. Use "1".
824+ check_obj_space(1);
825+ g_object[g_objpos++]=0x24020001; // addiu v0,zero,1
826+ g_intconst=1;
827+ }
828+ check_obj_space(14);
829+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp) (STEP value)
830+ g_object[g_objpos++]=0x04130004; // bgezall zero,check
831+// g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value)
832+ g_object[g_objpos++]=0x8FC40000|(i*4); // lw a0,xx(s8) (current var value)
833+ // After executing "NEXT" statement, process reaches following line.
834+ // Update variable value by adding STEP value
835+ // Note that STEP value is loaded onto $v0 in NEXT statement
836+// g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value)
837+ g_object[g_objpos++]=0x8FC40000|(i*4); // lw a0,xx(s8) (current var value)
838+ g_object[g_objpos++]=0x00822021; // addu a0,a0,v0
839+// g_object[g_objpos++]=0xAFC40000|((b1-'A')*4); // sw a0,xx(s8) (new var value)
840+ g_object[g_objpos++]=0xAFC40000|(i*4); // sw a0,xx(s8) (new var value)
841+ // Value-checking routine and storing ra in stack
842+ // check:
843+ g_object[g_objpos++]=0x8FA3000C; // lw v1,12(sp) (TO value)
844+ g_object[g_objpos++]=0x00641823; // subu v1,v1,a0
845+ g_object[g_objpos++]=0x04420001; // bltzl v0,negative
846+ g_object[g_objpos++]=0x00031823; // subu v1,zero,v1
847+ // negative:
848+ g_object[g_objpos++]=0x04610003; // bgez v1,continue
849+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
850+ break_statement(); // (2 words)
851+ // continue:
852+ return 0;
853+}
854+
855+char* next_statement(){
856+ // Return to address stored in 4($sp)
857+ // while set $v0 to 8($sp) (see for_statement)
858+ // Following assembly must be 4 words.
859+ // If the number of words will be changed, link.c must be reviced for CONTINUE statement.
860+ check_obj_space(4);
861+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
862+ g_object[g_objpos++]=0x03E00008; // jr ra
863+ g_object[g_objpos++]=0x8FA20008; // lw v0,8(sp) (STEP value)
864+ g_object[g_objpos++]=0x0830000C; // addiu sp,sp,12 (see linker)
865+ return 0;
866+}
867+
868+char* do_statement(){
869+ char* err;
870+ // Usage of stack:
871+ // 4(sp): Address to return to in "DO" statement.
872+ check_obj_space(3);
873+ g_object[g_objpos++]=0x04130001;// bgezall zero,label1:
874+ g_object[g_objpos++]=0x0822FFFC;// addiu sp,sp,-4 (see linker)
875+ // label1:
876+ g_object[g_objpos++]=0xAFBF0004;// sw ra,4(sp)
877+ if (nextCodeIs("WHILE ")) {
878+ // DO WHILE
879+ err=get_floatOrValue();
880+ if (err) return err;
881+ check_obj_space(2);
882+ g_object[g_objpos++]=0x14400003; // bne v0,zero,labe2
883+ g_object[g_objpos++]=0x00000000; // nop
884+ return break_statement(); // (2 words)
885+ // label2:
886+
887+ } else if (nextCodeIs("UNTIL ")) {
888+ // DO UNTIL
889+ err=get_floatOrValue();
890+ if (err) return err;
891+ check_obj_space(2);
892+ g_object[g_objpos++]=0x10400003; // beq v0,zero,label2
893+ g_object[g_objpos++]=0x00000000; // nop
894+ return break_statement(); // (2 words)
895+ // label2:
896+ } else {
897+ // DO statement without WHILE/UNTIL
898+ return 0;
899+ }
900+}
901+
902+char* loop_statement(){
903+ char* err;
904+ int opos;
905+ opos=g_objpos;
906+ if (nextCodeIs("WHILE ")) {
907+ // LOOP WHILE
908+ err=get_floatOrValue();
909+ if (err) return err;
910+ check_obj_space(1);
911+ g_object[g_objpos++]=0x10400003; // beq v0,zero,label1
912+ } else if (nextCodeIs("UNTIL ")) {
913+ // LOOP UNTIL
914+ err=get_floatOrValue();
915+ if (err) return err;
916+ check_obj_space(1);
917+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label
918+ } else {
919+ // LOOP statement without WHILE/UNTIL
920+ }
921+ check_obj_space(4);
922+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
923+ g_object[g_objpos++]=0x03E00008; // jr ra
924+ opos=g_objpos+1-opos;
925+ g_object[g_objpos++]=0x3000F000|opos; // nop (See linker, used for CONTINUE statement)
926+ // label1:
927+ g_object[g_objpos++]=0x08320004; // addiu sp,sp,4 (See link() function)
928+ return 0;
929+}
930+
931+char* while_statement(){
932+ char* err;
933+ check_obj_space(3);
934+ g_object[g_objpos++]=0x04130001; // bgezall zero,label1:
935+ g_object[g_objpos++]=0x0821FFFC; // addiu sp,sp,-4 (see linker)
936+ // label1:
937+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
938+ err=get_floatOrValue();
939+ if (err) return err;
940+ check_obj_space(2);
941+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label2
942+ g_object[g_objpos++]=0x00000000; // nop
943+ return break_statement(); // (2 words)
944+ // label2:
945+}
946+
947+char* wend_statement(){
948+ check_obj_space(4);
949+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
950+ g_object[g_objpos++]=0x03E00008; // jr ra
951+ g_object[g_objpos++]=0x3000F003; // nop (See linker, used for CONTINUE statement)
952+ // label1:
953+ g_object[g_objpos++]=0x08310004; // addiu sp,sp,4 (See link() function)
954+ return 0;
955+}
956+
957+char* param4_statement(enum libs lib){
958+ // lib is either LIB_PALETTE or LIB_GPALETTE
959+ // PALETTE N,R,G,B
960+ char* err;
961+ // Get N
962+ err=get_value();
963+ if (err) return err;
964+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
965+ g_srcpos++;
966+ check_obj_space(2);
967+ g_object[g_objpos++]=0x27BDFFF4; // addiu sp,sp,-12
968+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
969+ // Get R
970+ err=get_value();
971+ if (err) return err;
972+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
973+ g_srcpos++;
974+ check_obj_space(1);
975+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
976+ // Get G
977+ err=get_value();
978+ if (err) return err;
979+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
980+ g_srcpos++;
981+ check_obj_space(1);
982+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
983+ // Get B
984+ err=get_value();
985+ if (err) return err;
986+ call_lib_code(lib);
987+ check_obj_space(1);
988+ g_object[g_objpos++]=0x27BD000C; // addiu sp,sp,12
989+ return 0;
990+}
991+
992+char* param3_statement(enum libs lib){
993+ char* err;
994+ // Get 1st parameter
995+ err=get_value();
996+ if (err) return err;
997+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
998+ g_srcpos++;
999+ check_obj_space(2);
1000+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
1001+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1002+ // Get 2nd parameter
1003+ err=get_value();
1004+ if (err) return err;
1005+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1006+ g_srcpos++;
1007+ check_obj_space(1);
1008+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1009+ // Get 3rd parameter
1010+ err=get_value();
1011+ if (err) return err;
1012+ call_lib_code(lib);
1013+ check_obj_space(1);
1014+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
1015+ return 0;
1016+}
1017+
1018+char* bgcolor_statement(){
1019+ // BGCOLOR R,G,B
1020+ return param3_statement(LIB_BGCOLOR);
1021+}
1022+
1023+char* pcg_statement(){
1024+ // PCG ASCII,D1,D2
1025+ return param3_statement(LIB_PCG);
1026+}
1027+
1028+char* usepcg_statement(){
1029+ int objpos=g_objpos;
1030+ if (get_value()) {
1031+ // Getting integer failed.
1032+ // It supporsed to be not parameter
1033+ // and same as parameter=1.
1034+ g_objpos=objpos;
1035+ check_obj_space(1);
1036+ g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01
1037+ }
1038+ call_lib_code(LIB_USEPCG);
1039+ return 0;
1040+}
1041+
1042+char* usegraphic_statement(){
1043+ int objpos=g_objpos;
1044+ if (get_value()) {
1045+ // Getting integer failed.
1046+ // It supporsed to be not parameter
1047+ // and same as parameter=1.
1048+ g_objpos=objpos;
1049+ check_obj_space(1);
1050+ g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01
1051+ }
1052+ call_lib_code(LIB_USEGRAPHIC);
1053+ return 0;
1054+}
1055+
1056+char* cls_statement(){
1057+ call_lib_code(LIB_CLS);
1058+ return 0;
1059+}
1060+
1061+char* gcls_statement(){
1062+ call_lib_code(LIB_GCLS);
1063+ return 0;
1064+}
1065+
1066+char* color_statement(){
1067+ char* err;
1068+ err=get_value();
1069+ if (err) return err;
1070+ call_lib_code(LIB_COLOR);
1071+ return 0;
1072+}
1073+
1074+char* gcolor_statement(){
1075+ char* err;
1076+ err=get_value();
1077+ if (err) return err;
1078+ call_lib_code(LIB_GCOLOR);
1079+ return 0;
1080+}
1081+
1082+char* param2_statement(enum libs lib){
1083+ char* err;
1084+ // Get 1st
1085+ err=get_value();
1086+ if (err) return err;
1087+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1088+ g_srcpos++;
1089+ check_obj_space(2);
1090+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1091+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1092+ // Get 2nd
1093+ err=get_value();
1094+ if (err) return err;
1095+ call_lib_code(lib);
1096+ check_obj_space(1);
1097+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1098+ return 0;
1099+}
1100+
1101+char* system_statement(){
1102+ // SYSTEM X,Y
1103+ char* err;
1104+ // Get 1st
1105+ err=get_value();
1106+ if (err) return err;
1107+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1108+ g_srcpos++;
1109+ check_obj_space(2);
1110+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1111+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1112+ // Get 2nd
1113+ err=get_value();
1114+ if (err) return err;
1115+ check_obj_space(2);
1116+ g_object[g_objpos++]=0x8FA40004; // lw a0,4(sp)
1117+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1118+ call_lib_code(LIB_SYSTEM);
1119+ return 0;
1120+}
1121+
1122+char* cursor_statement(){
1123+ // CURSOR X,Y
1124+ return param2_statement(LIB_CURSOR);
1125+}
1126+
1127+char* scroll_statement(){
1128+ // SCROLL X,Y
1129+ return param2_statement(LIB_SCROLL);
1130+}
1131+
1132+char* drawcount_statement(){
1133+ char* err;
1134+ err=get_value();
1135+ if (err) return err;
1136+ call_lib_code(LIB_SETDRAWCOUNT);
1137+ return 0;
1138+}
1139+
1140+char* wait_statement(){
1141+ char* err;
1142+ err=get_value();
1143+ if (err) return err;
1144+ call_lib_code(LIB_WAIT);
1145+ return 0;
1146+}
1147+
1148+char* width_statement(){
1149+ char* err;
1150+ err=get_value();
1151+ if (err) return err;
1152+ call_lib_code(LIB_WIDTH);
1153+ return 0;
1154+}
1155+
1156+char* var_statement_sub(int a0, int a1){
1157+ // Construct parameter-setting scripts
1158+ if (a0&0xffff0000) {
1159+ check_obj_space(1);
1160+ g_object[g_objpos++]=0x3C040000|(a0>>16); // lui a0,XXXX
1161+ if (a0&0x0000ffff) {
1162+ check_obj_space(1);
1163+ g_object[g_objpos++]=0x34840000|(a0&0xffff); // ori a0,a0,XXXX
1164+ }
1165+ } else if (a0&0x0000ffff) {
1166+ check_obj_space(1);
1167+ g_object[g_objpos++]=0x34040000|(a0&0xffff); // ori a0,zero,xxxx
1168+ }
1169+ if (a1&0xffff0000) {
1170+ check_obj_space(1);
1171+ g_object[g_objpos++]=0x3C050000|(a1>>16); // lui a1,XXXX
1172+ if (a1&0x0000ffff) {
1173+ check_obj_space(1);
1174+ g_object[g_objpos++]=0x34A50000|(a1&0xffff); // ori a1,a1,XXXX
1175+ }
1176+ } else if (a1&0x0000ffff) {
1177+ check_obj_space(1);
1178+ g_object[g_objpos++]=0x34050000|(a1&0xffff); // ori a1,zero,xxxx
1179+ } else if (a0&0xff000000) {
1180+ // # of variables is 4. Reset $a1 to let lib_var() know that there is no more variables to store.
1181+ check_obj_space(1);
1182+ g_object[g_objpos++]=0x34050000; // ori a1,zero,0
1183+ }
1184+ return 0;
1185+}
1186+
1187+char* var_statement(){
1188+ char* err;
1189+ int i,j,a0,a1;
1190+ static int prevpos;
1191+ short stack;
1192+ do {
1193+ // For stack, 4 bytes are used for return address,
1194+ // 4 bytes are used in lib_var(),
1195+ // and additinal bytes are used for storing variable values.
1196+ stack=8;
1197+ a0=a1=0;
1198+ for (i=0;i<8;i++){
1199+ // Determine the variable number from source code
1200+ j=get_var_number();
1201+ if (j<0) return ERR_SYNTAX;
1202+ stack+=4;
1203+ // Create parameters in $a0, or $a1
1204+ if (i<4) {
1205+ a0=(a0<<8)|(j+1);
1206+ } else {
1207+ a1=(a1<<8)|(j+1);
1208+ }
1209+ // Check remaining variable(s)
1210+ if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') g_srcpos++;
1211+ next_position();
1212+ if (g_source[g_srcpos]!=',') break;
1213+ g_srcpos++;
1214+ }
1215+ // Jump to push routine, first
1216+ check_obj_space(2);
1217+ prevpos=g_objpos;
1218+ g_object[g_objpos++]=0x04130000; // bgezall zero,label1
1219+ g_object[g_objpos++]=0x27BD0000|((0-stack)&0xffff); // addiu sp,sp,-xx
1220+ // Process will be here after RETURN statement
1221+ // Pop routine
1222+ err=var_statement_sub(a0,a1); // Prepare a0, and a1
1223+ if (err) return err;
1224+ call_lib_code(LIB_VAR_POP);
1225+ // Restore stack and return
1226+ check_obj_space(3);
1227+ g_object[g_objpos++]=0x8FA30000|stack; // lw v1,xx(sp)
1228+ g_object[g_objpos++]=0x00600008; // jr v1
1229+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xx
1230+ // Push rotine
1231+ g_object[prevpos]|=g_objpos-prevpos-1; // label1:
1232+ check_obj_space(1);
1233+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
1234+ err=var_statement_sub(a0,a1); // Prepare a0, and a1
1235+ if (err) return err;
1236+ call_lib_code(LIB_VAR_PUSH);
1237+
1238+ } while (g_source[g_srcpos-1]==',');
1239+ // Renew sp stored in s5 stack.
1240+ check_obj_space(1);
1241+ g_object[g_objpos++]=0xAEBD0000|ARGS_S5_SP; // sw sp,-12(s5)
1242+ return 0;
1243+}
1244+
1245+
1246+char* graphic_statement(enum functions func){
1247+ /*
1248+ PSET X1,Y1[,C]
1249+ LINE X1,Y1,X2,Y2[,C]
1250+ BOXFILL X1,Y1,X2,Y2[,C]
1251+ CIRCLE X1,Y1,R[,C]
1252+ CIRCLEFILL X1,Y1,R[,C]
1253+ GPRINT X1,Y1,C,BC,S$
1254+ PUTBMP X1,Y1,M,N,BMP
1255+ 4(sp): X1
1256+ 8(sp): Y1
1257+ 12(sp): X2/R/M
1258+ 16(sp): Y2/N
1259+ v0: C/S$/BMP
1260+ */
1261+ char* err;
1262+ int spos;
1263+ int paramnum;
1264+ switch(func){
1265+ case FUNC_PSET:// X1,Y1[,C]
1266+ case FUNC_GCOLOR:// X1,Y1
1267+ case FUNC_POINT:// X1,Y1
1268+ paramnum=2;
1269+ break;
1270+ case FUNC_CIRCLE:// X1,Y1,R[,C]
1271+ case FUNC_CIRCLEFILL:// X1,Y1,R[,C]
1272+ paramnum=3;
1273+ break;
1274+ case FUNC_LINE:// X1,Y1,X2,Y2[,C]
1275+ case FUNC_BOXFILL:// X1,Y1,X2,Y2[,C]
1276+ paramnum=4;
1277+ break;
1278+ case FUNC_GPRINT:// X1,Y1,C,BC,S$
1279+ case FUNC_PUTBMP:// X1,Y1,M,N,BMP
1280+ paramnum=5;
1281+ break;
1282+ default:
1283+ return ERR_UNKNOWN;
1284+ }
1285+
1286+ next_position();
1287+ if (g_source[g_srcpos]==',') {
1288+ // X1 and Y1 is omitted. Set 0x80000000 for both.
1289+ check_obj_space(4);
1290+ g_object[g_objpos++]=0x27BDFFF0; // addiu sp,sp,-16
1291+ g_object[g_objpos++]=0x3C028000; // lui v0,0x0080
1292+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1293+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1294+ } else {
1295+ // X1
1296+ err=get_value();
1297+ if (err) return err;
1298+ check_obj_space(2);
1299+ g_object[g_objpos++]=0x27BDFFF0; // addiu sp,sp,-16
1300+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1301+ // Y1
1302+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1303+ g_srcpos++;
1304+ err=get_value();
1305+ if (err) return err;
1306+ check_obj_space(1);
1307+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1308+ }
1309+ if (2<paramnum) {
1310+ // X2, R, or M
1311+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1312+ g_srcpos++;
1313+ err=get_value();
1314+ if (err) return err;
1315+ check_obj_space(1);
1316+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
1317+ if (3<paramnum) {
1318+ // Y2, BC, or N
1319+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1320+ g_srcpos++;
1321+ err=get_value();
1322+ if (err) return err;
1323+ check_obj_space(1);
1324+ g_object[g_objpos++]=0xAFA20010; // sw v0,16(sp)
1325+ }
1326+ }
1327+ if (func==FUNC_GPRINT) {
1328+ // S$
1329+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1330+ g_srcpos++;
1331+ err=get_string();
1332+ if (err) return err;
1333+ } else if (func==FUNC_PUTBMP) {
1334+ // BMP
1335+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1336+ g_srcpos++;
1337+ spos=g_srcpos;
1338+ err=get_label();
1339+ if (g_label && !err) {
1340+ if (search_var_name(g_label)!=-1) {
1341+ // This is a long var name.
1342+ g_label=0;
1343+ g_srcpos=spos;
1344+ }
1345+ }
1346+ if (g_label && !err) {
1347+ // Label/number is constant.
1348+ // Linker will change following codes later.
1349+ // Note that 0x0814xxxx and 0x0815xxxx are specific codes for these.
1350+ check_obj_space(2);
1351+ g_object[g_objpos++]=0x08140000|((g_label>>16)&0x0000FFFF); // lui v0,xxxx
1352+ g_object[g_objpos++]=0x08150000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
1353+ // Change func to FUNC_PUTBMP2 (label mode).
1354+ func=FUNC_PUTBMP2;
1355+ } else {
1356+ err=get_value();
1357+ if (err) return err;
1358+ }
1359+ } else {
1360+ // [,C]
1361+ if (g_source[g_srcpos]==',') {
1362+ g_srcpos++;
1363+ err=get_value();
1364+ if (err) return err;
1365+ } else {
1366+ // If C is omitted, use -1.
1367+ check_obj_space(1);
1368+ g_object[g_objpos++]=0x2402FFFF; // addiu v0,zero,-1
1369+ }
1370+ }
1371+ // Call library
1372+ call_lib_code(LIB_GRAPHIC | func);
1373+ // Restore stack pointer
1374+ check_obj_space(1);
1375+ g_object[g_objpos++]=0x27BD0010; // addiu sp,sp,16
1376+ return 0;
1377+}
1378+
1379+char* fopen_statement_main(enum functions func){
1380+ // func is either FUNC_FOPENST or FUNC_FOPEN
1381+ char* err;
1382+ // Get 1st
1383+ err=get_string();
1384+ if (err) return err;
1385+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1386+ g_srcpos++;
1387+ check_obj_space(2);
1388+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
1389+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1390+ // Get 2nd
1391+ err=get_string();
1392+ if (err) return err;
1393+ check_obj_space(1);
1394+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1395+ // Get 3rd
1396+ if (g_source[g_srcpos]==',') {
1397+ g_srcpos++;
1398+ err=get_value();
1399+ if (err) return err;
1400+ } else {
1401+ // If 3rd parameter is omitted, use 0.
1402+ check_obj_space(1);
1403+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1404+ }
1405+ call_lib_code(LIB_FILE | func);
1406+ check_obj_space(1);
1407+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
1408+ return 0;
1409+}
1410+
1411+char* file_statement(){
1412+ char* err;
1413+ err=get_value();
1414+ if (err) return err;
1415+ call_lib_code(LIB_FILE | FUNC_FILE);
1416+ return 0;
1417+}
1418+
1419+char* fclose_statement(){
1420+ char* err;
1421+ int orgpos=g_srcpos;
1422+ if (endOfStatement()) {
1423+ // If no argument, use 0
1424+ check_obj_space(1);
1425+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1426+ } else {
1427+ err=get_value();
1428+ if (err) return err;
1429+ }
1430+ call_lib_code(LIB_FILE | FUNC_FCLOSE);
1431+ return 0;
1432+}
1433+
1434+char* fget_statement(){
1435+ return param2_statement(LIB_FILE | FUNC_FGET);
1436+}
1437+
1438+char* fput_statement(){
1439+ return param2_statement(LIB_FILE | FUNC_FPUT);
1440+}
1441+
1442+char* fseek_statement(){
1443+ char* err;
1444+ err=get_value();
1445+ if (err) return err;
1446+ call_lib_code(LIB_FILE | FUNC_FSEEK);
1447+ return 0;
1448+}
1449+
1450+char* fputc_statement(){
1451+ char* err;
1452+ err=get_value();
1453+ if (err) return err;
1454+ call_lib_code(LIB_FILE | FUNC_FPUTC);
1455+ return 0;
1456+}
1457+
1458+char* fremove_statement(){
1459+ char* err;
1460+ err=get_string();
1461+ if (err) return err;
1462+ call_lib_code(LIB_FILE | FUNC_FREMOVE);
1463+ return 0;
1464+}
1465+
1466+char* usevar_statement(){
1467+ char* err;
1468+ int i;
1469+ do {
1470+ next_position();
1471+ i=check_var_name();
1472+ if (i<65536) return ERR_SYNTAX;
1473+ err=register_var_name(i);
1474+ if (err) return err;
1475+ if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') g_srcpos++;
1476+ next_position();
1477+ if (g_source[g_srcpos]==',') {
1478+ g_srcpos++;
1479+ } else {
1480+ break;
1481+ }
1482+ } while(1);
1483+ return 0;
1484+}
1485+
1486+char* playwave_statement(){
1487+ char* err;
1488+ err=get_string();
1489+ if (err) return err;
1490+ check_obj_space(2);
1491+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1492+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1493+ if (g_source[g_srcpos]==',') {
1494+ g_srcpos++;
1495+ // Get 2nd
1496+ err=get_value();
1497+ if (err) return err;
1498+ } else {
1499+ // If 2rd parameter is omitted, use 0.
1500+ check_obj_space(1);
1501+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1502+ }
1503+ call_lib_code(LIB_PLAYWAVE);
1504+ check_obj_space(1);
1505+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1506+ return 0;
1507+}
1508+
1509+char* useclass_statement(){
1510+ char* err;
1511+ int i;
1512+ int* cmpdata;
1513+ do {
1514+ next_position();
1515+ i=check_var_name();
1516+ if (i<65536) return ERR_SYNTAX;
1517+ // Check if the class already exists
1518+ cmpdata_reset();
1519+ while(cmpdata=cmpdata_find(CMPDATA_CLASS)){
1520+ if (cmpdata[1]==i) {
1521+ // The class was already defined.
1522+ i=0;
1523+ break;
1524+ }
1525+ }
1526+ if (i) {
1527+ // Remove a objects before USECLASS statement
1528+ g_objpos=0;
1529+ // Insert a NOP assembly. This will be replaced by jump statement.
1530+ check_obj_space(1);
1531+ g_object[g_objpos++]=0x00000000; // nop
1532+ // Load new file to define class statement.
1533+ g_class=i;
1534+ return ERR_COMPILE_CLASS;
1535+ }
1536+ if (g_source[g_srcpos]==',') {
1537+ g_srcpos++;
1538+ } else {
1539+ break;
1540+ }
1541+ } while(1);
1542+ return 0;
1543+}
1544+
1545+char* setdir_statement(){
1546+ char* err;
1547+ err=get_string();
1548+ if (err) return err;
1549+ call_lib_code(LIB_SETDIR);
1550+ return 0;
1551+}
1552+
1553+char* option_statement(){
1554+ while(1){
1555+ next_position();
1556+ if (nextCodeIs("NOLINENUM")) {
1557+ g_nolinenum=1;
1558+ } else {
1559+ return ERR_SYNTAX;
1560+ }
1561+ next_position();
1562+ if (g_source[g_srcpos]==',') {
1563+ g_srcpos++;
1564+ } else {
1565+ break;
1566+ }
1567+ }
1568+ return 0;
1569+}
1570+
1571+char* idle_statement(){
1572+ check_obj_space(2);
1573+ g_object[g_objpos++]=0x42000020; // wait
1574+ return 0;
1575+}
1576+
1577+#ifdef __DEBUG
1578+ char* debug_statement(){
1579+ call_lib_code(LIB_DEBUG);
1580+ return 0;
1581+ }
1582+#endif
1583+
1584+// Aliases follow
1585+
1586+char* poke_statement(){
1587+ return poke_statement_sub(8);
1588+}
1589+
1590+char* poke16_statement(){
1591+ return poke_statement_sub(16);
1592+}
1593+
1594+char* poke32_statement(){
1595+ return poke_statement_sub(32);
1596+}
1597+
1598+char* palette_statement(){
1599+ return param4_statement(LIB_PALETTE);
1600+}
1601+
1602+char* gpalette_statement(){
1603+ return param4_statement(LIB_GPALETTE);
1604+}
1605+
1606+char* print_statement(){
1607+ return print_statement_main(LIB_PRINTSTR,LIB_STRING);
1608+}
1609+
1610+char* pset_statement(){
1611+ return graphic_statement(FUNC_PSET);
1612+}
1613+
1614+char* line_statement(){
1615+ return graphic_statement(FUNC_LINE);
1616+}
1617+
1618+char* boxfill_statement(){
1619+ return graphic_statement(FUNC_BOXFILL);
1620+}
1621+
1622+char* circle_statement(){
1623+ return graphic_statement(FUNC_CIRCLE);
1624+}
1625+
1626+char* circlefill_statement(){
1627+ return graphic_statement(FUNC_CIRCLEFILL);
1628+}
1629+
1630+char* gprint_statement(){
1631+ return graphic_statement(FUNC_GPRINT);
1632+}
1633+
1634+char* putbmp_statement(){
1635+ return graphic_statement(FUNC_PUTBMP);
1636+}
1637+
1638+char* point_statement(){
1639+ return graphic_statement(FUNC_POINT);
1640+}
1641+
1642+char* fopen_statement(){
1643+ return fopen_statement_main(FUNC_FOPENST);
1644+}
1645+
1646+char* fprint_statement(){
1647+ return print_statement_main(LIB_FILE | FUNC_FPRINTSTR,LIB_FILE | FUNC_FSTRING);
1648+}
1649+
1650+static const void* statement_list[]={
1651+ "REM",rem_statement,
1652+ "SOUND ",sound_statement,
1653+ "MUSIC ",music_statement,
1654+ "DRAWCOUNT ",drawcount_statement,
1655+ "CURSOR ",cursor_statement,
1656+ "PALETTE ",palette_statement,
1657+ "GPALETTE ",gpalette_statement,
1658+ "BGCOLOR ",bgcolor_statement,
1659+ "CLS",cls_statement,
1660+ "GCLS",gcls_statement,
1661+ "COLOR ",color_statement,
1662+ "GCOLOR ",gcolor_statement,
1663+ "RESTORE ",restore_statement,
1664+ "DATA ",data_statement,
1665+ "CDATA ",cdata_statement,
1666+ "LABEL ",label_statement,
1667+ "DIM ",dim_statement,
1668+ "CLEAR",clear_statement,
1669+ "PRINT",print_statement,
1670+ "IF ",if_statement,
1671+ "ELSEIF ",elseif_statement,
1672+ "ELSE",else_statement,
1673+ "ENDIF",endif_statement,
1674+ "END",end_statement,
1675+ "EXEC ",exec_statement,
1676+ "GOTO ",goto_statement,
1677+ "GOSUB ",gosub_statement,
1678+ "RETURN",return_statement,
1679+ "POKE ",poke_statement,
1680+ "POKE16 ",poke16_statement,
1681+ "POKE32 ",poke32_statement,
1682+ "FOR ",for_statement,
1683+ "NEXT",next_statement,
1684+ "LET ",let_statement,
1685+ "PCG ",pcg_statement,
1686+ "USEPCG",usepcg_statement,
1687+ "SCROLL ",scroll_statement,
1688+ "WAIT ",wait_statement,
1689+ "USEGRAPHIC",usegraphic_statement,
1690+ "PSET ",pset_statement,
1691+ "LINE ",line_statement,
1692+ "BOXFILL ",boxfill_statement,
1693+ "CIRCLE ",circle_statement,
1694+ "CIRCLEFILL ",circlefill_statement,
1695+ "GPRINT ",gprint_statement,
1696+ "PUTBMP ",putbmp_statement,
1697+ "POINT ",point_statement,
1698+ "VAR ",var_statement,
1699+ "DO",do_statement,
1700+ "LOOP",loop_statement,
1701+ "WHILE ",while_statement,
1702+ "WEND",wend_statement,
1703+ "BREAK",break_statement,
1704+ "CONTINUE",continue_statement,
1705+ "SYSTEM",system_statement,
1706+ "WIDTH ",width_statement,
1707+ "FOPEN ",fopen_statement,
1708+ "FILE ",file_statement,
1709+ "FCLOSE",fclose_statement,
1710+ "FPRINT ",fprint_statement,
1711+ "FGET ",fget_statement,
1712+ "FPUT ",fput_statement,
1713+ "FPUTC ",fputc_statement,
1714+ "FSEEK ",fseek_statement,
1715+ "FREMOVE ",fremove_statement,
1716+ "USEVAR ",usevar_statement,
1717+ "PLAYWAVE ",playwave_statement,
1718+ "USECLASS ",useclass_statement,
1719+ "FIELD ",field_statement,
1720+ "METHOD ",method_statement,
1721+ "DELETE ",delete_statement,
1722+ "CALL ",call_statement,
1723+ "STATIC ",static_statement,
1724+ "SETDIR ",setdir_statement,
1725+ "OPTION ",option_statement,
1726+ "USETIMER ",usetimer_statement,
1727+ "TIMER ",timer_statement,
1728+ "INTERRUPT ",interrupt_statement,
1729+ "IDLE",idle_statement,
1730+ // List of additional statements follows
1731+ ADDITIONAL_STATEMENTS
1732+};
1733+
1734+char* statement(void){
1735+ char* err;
1736+ int prevpos;
1737+ int i;
1738+ char* (*f)();
1739+ // Clear flag for temp area usage.
1740+ g_temp_area_used=0;
1741+ // Initialize stack handler used for value
1742+ g_sdepth=g_maxsdepth=0;
1743+ // Allow shifting code object when stack is used.
1744+ // This will be disalloed when CMPDATA_UNSOLVED etc is used.
1745+ g_allow_shift_obj=1;
1746+ // Seek the statement
1747+ for (i=0;i<sizeof(statement_list)/sizeof(statement_list[0]);i+=2){
1748+ if (nextCodeIs((char*)statement_list[i])) break;
1749+ }
1750+ if (i<sizeof(statement_list)/sizeof(statement_list[0])) {
1751+ // Statement found. Call it.
1752+ f=statement_list[i+1];
1753+ err=f();
1754+#ifdef __DEBUG
1755+ } else if (nextCodeIs("DEBUG")) {
1756+ err=debug_statement();
1757+#endif
1758+ } else {
1759+ err=let_statement();
1760+ }
1761+ if (err) return err;
1762+ // Stack handler must be zero here.
1763+ if (g_sdepth!=0) return ERR_UNKNOWN;
1764+ // Check if temp area is used
1765+ if (g_temp_area_used) {
1766+ // Temp area is used. Insert a garbage collection flag setting routine.
1767+ check_obj_space(1);
1768+ g_object[g_objpos++]=0x7ED6F000;// ext s6,s6,0,31
1769+ }
1770+ return 0;
1771+}
--- /dev/null
+++ b/mips/protozoa/string.c
@@ -0,0 +1,237 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+/*
13+ Public functions:
14+ char* get_string(void);
15+ char* simple_string(void);
16+*/
17+
18+#include "api.h"
19+#include "compiler.h"
20+
21+char* simple_string(void){
22+ char* err;
23+ unsigned char b1,b2;
24+ int i,j;
25+ next_position();
26+ b1=g_source[g_srcpos];
27+ b2=g_source[g_srcpos+1];
28+ if (b1=='"') {
29+ // Constant string
30+ // Count character number (+1 for \0)
31+ // This may be more than actual character number due to escape sequence.
32+ i=0;
33+ while(1){
34+ i++;
35+ b1=g_source[g_srcpos+i];
36+ if (b1=='"') {
37+ break;
38+ } else if (b1=='\\') {
39+ i++;
40+ } else if (b1<0x20) {
41+ // This is an error, that will be detected later again.
42+ break;
43+ }
44+ };
45+ g_srcpos++;
46+ // Determine required word number
47+ i=(i+3)/4;
48+ // Determine address containing the string
49+ j=(int)(&(g_object[g_objpos+3]));
50+ // Note that using "bgezal zero," must be used to skip some region.
51+ // This is to find embed string in the code.
52+ check_obj_space(2+i);
53+ g_object[g_objpos++]=0x04110000|((i+1)&0x0000FFFF); // bgezal zero,xxxx
54+ g_object[g_objpos++]=0x03E01021; // addu v0,ra,zero
55+ for(j=0;(b1=g_source[g_srcpos++])!='"';j++) {
56+ if (b1=='\\') {
57+ b1=g_source[g_srcpos++];
58+ if (b1=='x' || b1=='X') {
59+ // Hexadecimal
60+ b1=g_source[g_srcpos++];
61+ if ('0'<=b1 && b1<='9') b1=b1-'0';
62+ else if ('A'<=b1 && b1<='F') b1=b1-'A'+10;
63+ else if ('a'<=b1 && b1<='f') b1=b1-'a'+10;
64+ else return ERR_SYNTAX;
65+ b2=g_source[g_srcpos++];
66+ if ('0'<=b2 && b2<='9') b2=b2-'0';
67+ else if ('A'<=b2 && b2<='F') b2=b2-'A'+10;
68+ else if ('a'<=b2 && b2<='f') b2=b2-'a'+10;
69+ else return ERR_SYNTAX;
70+ b1=(b1<<4)|b2;
71+ } else if (b1<0x20) {
72+ return ERR_SYNTAX;
73+ } else {
74+ // \\ or \"
75+ }
76+ } else if (b1<0x20) {
77+ return ERR_SYNTAX;
78+ }
79+ ((char*)(&g_object[g_objpos]))[j]=b1;
80+ }
81+ ((char*)(&g_object[g_objpos]))[j]=0x00;
82+ g_objpos+=i;
83+ } else if ('A'<=b1 && b1<='Z') {
84+ i=get_var_number();
85+ if (i<0) {
86+ // Function
87+ // String would be pointed by $v0
88+ // Otherwise, it will be assinged in xxx_function() function.
89+ err=str_function();
90+ if (err) return err;
91+ // Temp area would be used when executing.
92+ g_temp_area_used=1;
93+ return 0;
94+ }
95+ if (g_source[g_srcpos]=='.') {
96+ // This is an object field or method to return string
97+ check_obj_space(1);
98+ g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
99+ g_srcpos++;
100+ return string_obj_field();
101+ } else if (g_source[g_srcpos]=='(') {
102+ // An array element contains pointer to an object.
103+ g_srcpos++;
104+ err=get_dim_value(i);
105+ if (err) return err;
106+ if (g_source[g_srcpos]!='.') return ERR_SYNTAX;
107+ g_srcpos++;
108+ return string_obj_field();
109+ }
110+ if (g_source[g_srcpos]!='$') return ERR_SYNTAX;
111+ g_srcpos++;
112+ // String variable
113+ next_position();
114+ if (g_source[g_srcpos]=='(') {
115+ // A part of string
116+ g_srcpos++;
117+ err=get_value();
118+ if (err) return err;
119+ if (g_source[g_srcpos]==')') {
120+ g_srcpos++;
121+ // Put -1 to $a0
122+ check_obj_space(1);
123+ g_object[g_objpos++]=0x2404FFFF; // addiu a0,zero,-1
124+ } else if (g_source[g_srcpos]==',') {
125+ g_srcpos++;
126+ // Store $v0 in stack
127+ g_sdepth+=4;
128+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
129+ check_obj_space(1);
130+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
131+ // Get next value
132+ err=get_value();
133+ if (err) return err;
134+ // Copy $v0 to $a0 and get value from stack to $a0.
135+ check_obj_space(2);
136+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
137+ g_object[g_objpos++]=0x8FA20000|g_sdepth; // lw v0,xx(sp)
138+ g_sdepth-=4;
139+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
140+ g_srcpos++;
141+ // Temp area will be used when executing.
142+ g_temp_area_used=1;
143+ } else {
144+ return ERR_SYNTAX;
145+ }
146+ // $a1 is var number, $v0 is position, $a0 is length
147+ check_obj_space(1);
148+ g_object[g_objpos++]=0x24050000|(i); // addiu a1,zero,xx
149+ call_lib_code(LIB_MIDSTR);
150+ } else {
151+ // Simple string
152+ check_obj_space(1);
153+ g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
154+ // String is pointed by $v0
155+ }
156+ } else {
157+ return ERR_SYNTAX;
158+ }
159+ return 0;
160+}
161+
162+char* get_string_sub(){
163+ char* err;
164+ char b1;
165+ // Obtain initial string
166+ err=simple_string();
167+ if (err) return err;
168+ // Check if connection operator exists
169+ next_position();
170+ b1=g_source[g_srcpos];
171+ if (b1!='+' && b1!='&') return 0; // Exit if connection operator does not exist.
172+ g_srcpos++;
173+ // Connection required.
174+ // Prepare one level of stack for handling
175+ g_sdepth+=4;
176+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
177+ while(1) {
178+ // Store current pointer in stack
179+ check_obj_space(1);
180+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
181+ // Obtain next string (pointer will be in $v0)
182+ err=simple_string();
183+ if (err) return err;
184+ // Restore previous pointer from stack in $a0 and copy $v0 to $a1
185+ // Call library
186+ check_obj_space(2);
187+ g_object[g_objpos++]=0x8FA40000|g_sdepth; // lw a0,xx(sp)
188+ call_lib_code(LIB_CONNECT_STRING);
189+ // Temp area will be used when executing.
190+ g_temp_area_used=1;
191+ // Check if further connection operator exists
192+ next_position();
193+ b1=g_source[g_srcpos];
194+ if (b1!='+' && b1!='&') break;
195+ g_srcpos++;
196+ }
197+ g_sdepth-=4;
198+ return 0;
199+}
200+
201+char* get_string(){
202+ // This is only the public function.
203+ // Note that this can be called recursively.
204+ // String may contain a function with a parameter of value
205+ // that is a function with a parameter of string.
206+ // Result will be in $v0 as a pointer.
207+ char* err;
208+ char b1;
209+ int i,prevpos;
210+ if (g_sdepth==0) {
211+ // Initialize stack handler
212+ g_maxsdepth=0;
213+ prevpos=g_objpos;
214+ // Stack decrement command will be filled later
215+ check_obj_space(1);
216+ g_object[g_objpos++]=0x00000000; // nop (will be replaced by "addiu sp,sp,-xx")
217+ }
218+ err=get_string_sub();
219+ if (err) return err;
220+ if (g_sdepth==0) {
221+ if (g_maxsdepth==0) {
222+ // Stack was not used.
223+ if (g_allow_shift_obj) {
224+ shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
225+ g_objpos--;
226+ }
227+ } else {
228+ // Stack was used.
229+ check_obj_space(1);
230+ g_object[prevpos]=0x27BD0000 | (0-g_maxsdepth) & 0x0000FFFF; // addiu sp,sp,-xx
231+ g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx
232+ }
233+ }
234+ g_lastvar=VAR_STRING;
235+ return 0;
236+}
237+
--- /dev/null
+++ b/mips/protozoa/timer.c
@@ -0,0 +1,325 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include <xc.h>
13+#include "compiler.h"
14+#include "api.h"
15+
16+/*
17+ 32 different type interruptions are possible.
18+ See definition in compiler.h like:
19+ #define INTERRUPT_TIMER 0
20+ extern int g_interrupt_flags;
21+ extern int g_int_vector[];
22+ #define raise_interrupt_flag(x) do {\
23+*/
24+
25+// Timer value that increments every timer event
26+static int g_timer;
27+
28+// Interrupt types
29+static const void* interrupt_list[]={
30+ "TIMER", (void*)INTERRUPT_TIMER,
31+ "DRAWCOUNT",(void*)INTERRUPT_DRAWCOUNT,
32+ "KEYS", (void*)INTERRUPT_KEYS,
33+ "INKEY", (void*)INTERRUPT_INKEY,
34+ "MUSIC", (void*)INTERRUPT_MUSIC,
35+ "WAVE", (void*)INTERRUPT_WAVE,
36+ ADDITIONAL_INTERRUPT_FUNCTIONS
37+};
38+#define NUM_INTERRUPT_TYPES ((sizeof(interrupt_list)/sizeof(interrupt_list[0]))/2)
39+// Flags for interrupt
40+int g_interrupt_flags;
41+// Jump address when interrupt
42+int g_int_vector[NUM_INTERRUPT_TYPES];
43+
44+/*
45+ Initialize and termination
46+*/
47+
48+void init_timer(){
49+ int i;
50+ // Stop timer, first
51+ T1CON=0x0000;
52+ IEC0bits.T1IE=0;
53+ TMR1=0;
54+ PR1=0xffff;
55+ g_timer=0;
56+ // Disable interrupt
57+ IEC0bits.CS1IE=0;
58+ for(i=0;i<NUM_INTERRUPT_TYPES;i++) g_int_vector[i]=0;
59+ // CS0 interrupt every 1/60 sec (triggered by Timer2)
60+ IPC0bits.CS0IP=3;
61+ IPC0bits.CS0IS=0;
62+ IFS0bits.CS0IF=0;
63+ IEC0bits.CS0IE=1;
64+}
65+
66+void stop_timer(){
67+ // Stop timer
68+ T1CON=0x0000;
69+ IEC0bits.T1IE=0;
70+ // Disable interrupt
71+ IEC0bits.CS1IE=0;
72+}
73+
74+/*
75+ Timer interprtation
76+*/
77+
78+// Interrupt handler
79+#ifndef __DEBUG
80+ // Timer1 is also used for debug mode
81+ #pragma interrupt T1Handler IPL2SOFT vector 4
82+#endif
83+void T1Handler(void){
84+ g_timer++;
85+ // Clear Timer1 interrupt flag
86+ IFS0bits.T1IF=0;
87+ // Raise TIMER interrupt flag
88+ raise_interrupt_flag(INTERRUPT_TIMER);
89+}
90+
91+void lib_usetimer(int usec){
92+ int temppr1;
93+ // Stop timer, first
94+ T1CON=0x0000;
95+ IEC0bits.T1IE=0;
96+ TMR1=0;
97+ PR1=0xffff;
98+ // PR1 setting
99+ // ((CPU_CLOCK_HZ/10000)*usec)< 2147483648,
100+ // therefore, the calculation can be done as 32 bit signed integer
101+ temppr1=((CPU_CLOCK_HZ/10000)*usec)/100;
102+ if (temppr1<=65536) {
103+ // no prescaler
104+ T1CON=0x0000;
105+ PR1=temppr1-1;
106+ } else if ((temppr1>>3)<=65536) {
107+ // 1/8 prescaler
108+ T1CON=0x0010;
109+ PR1=(temppr1>>3)-1;
110+ } else if ((temppr1>>6)<=65536) {
111+ // 1/64 prescaler
112+ T1CON=0x0020;
113+ PR1=(temppr1>>6)-1;
114+ } else if ((temppr1>>8)<=65536) {
115+ // 1/256 prescaler
116+ T1CON=0x0030;
117+ PR1=(temppr1>>8)-1;
118+ } else {
119+ err_invalid_param();
120+ }
121+ // Timer1 interrupt: priority 2
122+ IPC1bits.T1IP=2;
123+ IPC1bits.T1IS=0;
124+ IEC0bits.T1IE=1;
125+ // Start timer
126+ T1CONbits.ON=1;
127+}
128+
129+char* usetimer_statement(){
130+ char* err;
131+ err=get_value();
132+ if (err) return err;
133+ call_quicklib_code(lib_usetimer,ASM_ADDU_A0_V0_ZERO);
134+ return 0;
135+}
136+
137+char* timer_statement(){
138+ int i;
139+ char* err;
140+ err=get_value();
141+ if (err) return err;
142+ i=(int)(&g_timer)+0x8000;
143+ check_obj_space(4);
144+ g_object[g_objpos++]=0x3C030000|((i>>16)&0x0000FFFF); // lui v1,xxxx
145+ g_object[g_objpos++]=0xAC620000|((i-0x8000)&0xFFFF); // sw v0,xxxx(v1)
146+ i=(int)(&TMR1)+0x8000;//0xBF800610
147+ g_object[g_objpos++]=0x3C030000|((i>>16)&0x0000FFFF); // lui v1,0xbf80
148+ g_object[g_objpos++]=0xAC600000|((i-0x8000)&0xFFFF); // sw zero,0x0610(v1)
149+ return 0;
150+}
151+
152+char* timer_function(){
153+ int i;
154+ i=(int)(&g_timer)+0x8000;
155+ check_obj_space(2);
156+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
157+ g_object[g_objpos++]=0x8C420000|((i-0x8000)&0xFFFF); // lw v0,xxxx(v0)
158+ return 0;
159+}
160+
161+/*
162+ Interrupt interprtation
163+ To cause interruption, use raise_interrupt_flag() macro
164+ For example,
165+ raise_interrupt_flag(INTERRUPT_TIMER);
166+
167+*/
168+
169+void BasicInt(int addr,void* memory){
170+ // Note that $s0-$s7 and $fp values must be set again here.
171+ // Set s5 for initial_s5_stack
172+ asm volatile("la $s5,%0"::"i"(&g_initial_s5_stack[2]));
173+ // Set s7 for easy calling call_library()
174+ asm volatile("la $s7,%0"::"i"(&call_library));
175+ // Set fp and execute BASIC code at $a0
176+ asm volatile("addu $fp,$zero,$a1");
177+ asm volatile("jr $a0");
178+}
179+#pragma interrupt CS1Handler IPL1SOFT vector 2
180+void CS1Handler(void){
181+ int i;
182+ // Store s0-s7, fp, and ra in stacks
183+ asm volatile("#":::"s0");
184+ asm volatile("#":::"s1");
185+ asm volatile("#":::"s2");
186+ asm volatile("#":::"s3");
187+ asm volatile("#":::"s4");
188+ asm volatile("#":::"s5");
189+ asm volatile("#":::"s6");
190+ asm volatile("#":::"s7");
191+ asm volatile("#":::"fp");
192+ asm volatile("#":::"ra");
193+ while(g_interrupt_flags){
194+ for(i=0;i<NUM_INTERRUPT_TYPES;i++){
195+ if (g_interrupt_flags & (1<<i)) {
196+ if (g_int_vector[i]) BasicInt(g_int_vector[i],(void*)(&g_var_mem[0]));
197+ g_interrupt_flags &= (1<<i)^0xffff;
198+ }
199+ }
200+ }
201+ IFS0bits.CS1IF=0;
202+}
203+
204+void lib_interrupt_main(int itype, int address){
205+ // Set address
206+ g_int_vector[itype]=address;
207+ // CS1 interrupt: priority 1
208+ IPC0bits.CS1IP=1;
209+ IPC0bits.CS1IS=0;
210+ IEC0bits.CS1IE=1;
211+}
212+
213+void lib_interrupt(int itype){
214+ // $ra contains the address for interrupt
215+ // $ra is 2 word before the interrupt address
216+ asm volatile("addiu $a1,$ra,8");
217+ asm volatile("j lib_interrupt_main");
218+}
219+
220+char* interrupt_statement(){
221+ int itype;
222+ int i,opos;
223+ char* err;
224+ int stop=0;
225+ // Check if STOP
226+ stop=nextCodeIs("STOP ");
227+ // Seek the interrupt
228+ for (i=0;i<NUM_INTERRUPT_TYPES;i++){
229+ if (nextCodeIs((char*)interrupt_list[i*2])) break;
230+ }
231+ if (i<NUM_INTERRUPT_TYPES) {
232+ // Interrupt found
233+ itype=(int)interrupt_list[i*2+1];
234+ } else {
235+ // Interrupt not found
236+ return ERR_SYNTAX;
237+ }
238+ // Compile INTERRUPT STOP
239+ if (stop) {
240+ // g_int_vector[itype]=0;
241+ i=(int)(&g_int_vector[itype]);
242+ i-=g_gp;
243+ check_obj_space(1);
244+ g_object[g_objpos++]=0xAF800000|(i&0x0000FFFF); // sw zero,xxxx(gp)
245+ return 0;
246+ }
247+ // Detect ','
248+ next_position();
249+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
250+ g_srcpos++;
251+ // Store address to call
252+ call_quicklib_code(lib_interrupt,ASM_ORI_A0_ZERO_|itype);
253+ check_obj_space(4);
254+ // Skip the region used for interrupt-calling
255+ opos=g_objpos;
256+ g_object[g_objpos++]=0x10000000; // b xxxxx
257+ g_object[g_objpos++]=0x00000000; // nop
258+ // Begin interrupt-calling region
259+ // Store $ra
260+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
261+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
262+ // Compile as GOSUB statement
263+ err=gosub_statement();
264+ if (err) return err;
265+ // Retore $ra and return
266+ check_obj_space(3);
267+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
268+ g_object[g_objpos++]=0x03E00008; // jr ra
269+ g_object[g_objpos++]=0x08320004; // addiu sp,sp,4
270+ // End interrupt-calling region
271+ // Complete B assembly
272+ g_object[opos]|=g_objpos-opos-1;
273+ return 0;
274+}
275+
276+/*
277+ CS0 interrupt
278+ IPL3SOFT vector 1
279+
280+ This interrupt is always active. Therefore, Do things as few as possible.
281+ 1) Call music function if needed.
282+ MUSIC interrupt is taken by music.c
283+ 2) Check buttons for KEYS interrupt
284+ 3) Check PS/2 for INKEY interrupt
285+ 4) DRAWCOUNT interrupt
286+*/
287+
288+const int* g_keystatus=(int*)&ps2keystatus[0];
289+
290+#pragma interrupt CS0Handler IPL3SOFT vector 1
291+void CS0Handler(void){
292+ static int s_keys=-1;
293+ static char s_inkey=0;
294+ int i;
295+ IFS0bits.CS0IF=0;
296+ // Call music function
297+ if (g_music_active) musicint();
298+ // The interrupts are valid only when CS1 is active
299+ if (IEC0bits.CS1IE) {
300+ // Raise DRAWCOUNT interrupt flag
301+ raise_interrupt_flag(INTERRUPT_DRAWCOUNT);
302+ // Check buttons
303+ if (0<=s_keys && s_keys!=(KEYPORT&(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE))) {
304+ // Raise KEYS interrupt flag
305+ raise_interrupt_flag(INTERRUPT_KEYS);
306+ }
307+ s_keys=KEYPORT&(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE);
308+ // Check PS/2 keyboard down
309+ if (g_int_vector[INTERRUPT_INKEY]) {
310+ for(i=0;i<64;i++){
311+ if (g_keystatus[i]) {
312+ // Raise INKEY interrupt flag
313+ if (!s_inkey) raise_interrupt_flag(INTERRUPT_INKEY);
314+ break;
315+ }
316+ }
317+ s_inkey=(i==64) ? 0:1;
318+ }
319+ }
320+}
321+/*
322+ for(i=0;i<256;i++){
323+ if (ps2keystatus[i]) return i;
324+ }
325+*/
--- /dev/null
+++ b/mips/protozoa/value.c
@@ -0,0 +1,295 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+/*
13+ Public function is only get_value().
14+*/
15+
16+#include "compiler.h"
17+
18+char* get_value();
19+char* get_value_sub(int pr);
20+
21+char* get_dim_value(int i){
22+ char* err;
23+ err=get_value_sub(priority(OP_VOID));
24+ if (err) return err;
25+ check_obj_space(4);
26+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
27+ g_object[g_objpos++]=0x8FC30000|(i*4); // lw v1,xx(s8)
28+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
29+ g_object[g_objpos++]=0x8C620000; // lw v0,0(v1)
30+ next_position();
31+ if (g_source[g_srcpos]==','){
32+ // 2D, 3D or more
33+ // Use a stack
34+ g_sdepth+=4;
35+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
36+ check_obj_space(1);
37+ do {
38+ g_srcpos++;
39+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
40+ err=get_value_sub(priority(OP_VOID));
41+ if (err) return err;
42+ check_obj_space(5);
43+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
44+ g_object[g_objpos++]=0x8FA30000|g_sdepth; // lw v1,xx(sp)
45+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
46+ g_object[g_objpos++]=0x8C620000; // lw v0,0(v1)
47+ } while (g_source[g_srcpos]==',');
48+ g_sdepth-=4;
49+ }
50+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
51+ g_srcpos++;
52+ return 0;
53+}
54+
55+char* get_simple_value(void){
56+ int i;
57+ char* err;
58+ char b1,b2;
59+ next_position();
60+ b1=g_source[g_srcpos];
61+ if (b1=='(') {
62+ // (...)
63+ // Parenthesis
64+ g_srcpos++;
65+ next_position();
66+ err=get_value_sub(priority(OP_VOID));
67+ if (err) return err;
68+ next_position();
69+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
70+ g_srcpos++;
71+ } else if (b1=='-') {
72+ // Unary '-' operator
73+ // Note that unary operators ( + and - ) have higher priority than the other operators
74+ g_srcpos++;
75+ err=get_simple_value();
76+ if (err) return err;
77+ check_obj_space(1);
78+ g_object[g_objpos++]=0x00021023; // subu v0,zero,v0
79+ g_intconst=-g_intconst;
80+ } else if (b1=='&') {
81+ // '&' operator
82+ g_srcpos++;
83+ i=get_var_number();
84+ if (i<0) return ERR_SYNTAX;
85+ check_obj_space(1);
86+ g_object[g_objpos++]=0x27C20000|(i*4); // addiu v0,s8,xxxx
87+ } else {
88+ // Main routine of getting value here
89+ if (b1=='+') g_srcpos++; // Ignore unary '+' operator
90+ next_position();
91+ b1=g_source[g_srcpos];
92+ b2=g_source[g_srcpos+1];
93+ if (b1=='0' && b2=='X' || b1=='$') {
94+ // Starts with '0x' or '$'
95+ // Hex number
96+ g_srcpos++;
97+ if (b1=='0') g_srcpos++;
98+ i=0;
99+ while(b1=g_source[g_srcpos]) {
100+ if ('0'<=b1 && b1<='9') {
101+ i*=16;
102+ i+=b1-'0';
103+ } else if ('A'<=b1 && b1<='F') {
104+ i*=16;
105+ i+=b1-'A'+0x0A;
106+ } else if (b1==' ') { // Skip ' '
107+ // Avoid "ELSE" statement etc
108+ if ('F'<g_source[g_srcpos+2]) break;
109+ } else {
110+ break;
111+ }
112+ g_srcpos++;
113+ }
114+ g_intconst=i;
115+ if (i&0xFFFF0000) {
116+ // 32 bit
117+ check_obj_space(2);
118+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
119+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
120+ } else {
121+ // 16 bit
122+ check_obj_space(1);
123+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
124+ }
125+ } else if ('0'<=b1 && b1<='9') {
126+ // Starts with 0-9
127+ // Decimal number
128+ i=0;
129+ while(b1=g_source[g_srcpos]) {
130+ if ('0'<=b1 && b1<='9') {
131+ i*=10;
132+ i+=b1-'0';
133+ } else if (b1!=' ') { // Skip ' '
134+ break;
135+ }
136+ g_srcpos++;
137+ }
138+ // The next character should not be '.' or 'E'.
139+ // Or, it must be recognized as a float value.
140+ if (b1=='.') return ERR_SYNTAX;
141+ if (b1=='E') {
142+ b2=g_source[g_srcpos+1];
143+ if (b2==' ' || '0'<=b2 && b2<='9') return ERR_SYNTAX;
144+ }
145+ g_intconst=i;
146+ if (i&0xFFFF0000) {
147+ // 32 bit
148+ check_obj_space(2);
149+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
150+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
151+ } else {
152+ // 16 bit
153+ check_obj_space(1);
154+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
155+ }
156+ } else {
157+ g_valueisconst=0;
158+ i=get_var_number();
159+ if (i<0) {
160+ // Must be a function.
161+ return function();
162+ }
163+ if (g_source[g_srcpos]=='(') {
164+ // Dimension
165+ g_srcpos++;
166+ err=get_dim_value(i);
167+ if (err) return err;
168+ } else {
169+ // Simple value
170+ check_obj_space(1);
171+ g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
172+ }
173+ // Check if this is an object
174+ if (g_source[g_srcpos]=='.') {
175+ // This is an object. See the filed of it.
176+ g_srcpos++;
177+ return integer_obj_field();
178+ }
179+ }
180+ }
181+ // No error
182+ return 0;
183+}
184+
185+char* get_value_sub(int pr){
186+ char* err;
187+ enum operator op;
188+ char b1,b2,b3;
189+ int prevpos;
190+ // Get a value in $v0.
191+ err=get_simple_value();
192+ if (err) return err;
193+ while(1){
194+ // Get the operator in op. If not valid operator, simply return without error.
195+ prevpos=g_srcpos;
196+ err=get_operator();
197+ if (err) return 0;
198+ op=g_last_op;
199+ // Compair current and previous operators.
200+ // If the previous operator has higher priolity, return.
201+ if (pr>=priority(op)) {
202+ g_srcpos=prevpos;
203+ return 0;
204+ }
205+ // Store $v0 in stack
206+ g_sdepth+=4;
207+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
208+ check_obj_space(1);
209+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
210+ // Get next value.
211+ err=get_value_sub(priority(op));
212+ if (err) return err;
213+ // Get value from stack to $v1.
214+ check_obj_space(1);
215+ g_object[g_objpos++]=0x8FA30000|g_sdepth; // lw v1,xx(sp)
216+ g_sdepth-=4;
217+ // Calculation. Result will be in $v0.
218+ err=calculation(op);
219+ if (err) return err;
220+ }
221+}
222+
223+char* get_value(){
224+ // This is only the public function.
225+ // Note that this can be called recursively.
226+ // Value may contain function with a parameter of another value.
227+ char* err;
228+ int prevpos;
229+ if (g_sdepth==0) {
230+ // Initialize stack handler
231+ g_maxsdepth=0;
232+ prevpos=g_objpos;
233+ // Stack decrement command will be filled later
234+ check_obj_space(1);
235+ g_object[g_objpos++]=0x00000000; // nop (will be replaced by "addiu sp,sp,-xx")
236+ }
237+ err=get_value_sub(priority(OP_VOID));
238+ if (err) return err;
239+ if (g_sdepth==0) {
240+ if (g_maxsdepth==0) {
241+ // Stack was not used.
242+ if (g_allow_shift_obj) {
243+ shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
244+ g_objpos--;
245+ }
246+ } else {
247+ // Stack was used.
248+ check_obj_space(1);
249+ g_object[prevpos]=0x27BD0000 | (0-g_maxsdepth) & 0x0000FFFF; // addiu sp,sp,-xx
250+ g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx
251+ }
252+ }
253+ g_lastvar=VAR_INTEGER;
254+ return 0;
255+}
256+
257+char* get_floatOrValue(){
258+ char* err;
259+ char b;
260+ int opos,spos,sdpt;
261+ sdpt=g_sdepth;
262+ opos=g_objpos;
263+ spos=g_srcpos;
264+ // First try integer.
265+ // Integer value has the higher priolity than float value.
266+ err=get_value();
267+ b=g_source[g_srcpos];
268+ if (err || b=='#') {
269+ // Value is not integer. Let's try float.
270+ g_sdepth=sdpt;
271+ g_objpos=opos;
272+ g_srcpos=spos;
273+ return get_float();
274+ } else {
275+ // Value was recognized as an integer.
276+ return 0;
277+ }
278+}
279+
280+char* get_stringFloatOrValue(){
281+ char* err;
282+ int opos,spos;
283+ opos=g_objpos;
284+ spos=g_srcpos;
285+ // First try string, float, then integer.
286+ err=get_string();
287+ if (err) {
288+ g_objpos=opos;
289+ g_srcpos=spos;
290+ return get_floatOrValue();
291+ } else {
292+ return 0;
293+ }
294+}
295+
--- /dev/null
+++ b/mips/protozoa/varname.c
@@ -0,0 +1,271 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include "compiler.h"
13+
14+/*
15+ static const int reserved_var_names[];
16+ This dimension contains var name integers of reserved var names.
17+ To make following structure, execute "reservednames.js" in Windows.
18+*/
19+
20+static const int reserved_var_names[]={
21+ 0x000106b8, /*ABS*/
22+ 0x0001f67c, /*ACOS*/
23+ 0x0002414c, /*ARGS*/
24+ 0x0001090c, /*ASC*/
25+ 0x0002469f, /*ASIN*/
26+ 0x00024a8f, /*ATAN*/
27+ 0x002f7c1e, /*ATAN2*/
28+ 0x0047c31c, /*BREAK*/
29+ 0x00035869, /*CALL*/
30+ 0x00575afe, /*CDATA*/
31+ 0x00036c3d, /*CEIL*/
32+ 0x000111af, /*CHR*/
33+ 0x0cb1b682, /*CIRCLE*/
34+ 0x005d1ea3, /*CLEAR*/
35+ 0x00011240, /*CLS*/
36+ 0x005f66cb, /*COLOR*/
37+ 0x000112ac, /*COS*/
38+ 0x0003a041, /*COSH*/
39+ 0x00616415, /*CREAD*/
40+ 0x0de593fb, /*CURSOR*/
41+ 0x00040fbe, /*DATA*/
42+ 0x00011644, /*DEC*/
43+ 0x0fe19c42, /*DELETE*/
44+ 0x000116de, /*DIM*/
45+ 0x000100a8, /*DO*/
46+ 0x0004fd8e, /*ELSE*/
47+ 0x1434a177, /*ELSEIF*/
48+ 0x00011c99, /*END*/
49+ 0x0091c927, /*ENDIF*/
50+ 0x00053854, /*EXEC*/
51+ 0x00011e0d, /*EXP*/
52+ 0x000579c8, /*FABS*/
53+ 0x16e3d4be, /*FCLOSE*/
54+ 0x00058fcf, /*FEOF*/
55+ 0x00059895, /*FGET*/
56+ 0x00a67500, /*FGETC*/
57+ 0x00a7e061, /*FIELD*/
58+ 0x0005a3a2, /*FILE*/
59+ 0x177f0ca5, /*FINPUT*/
60+ 0x0005b1df, /*FLEN*/
61+ 0x00aa3445, /*FLOAT*/
62+ 0x00aa363b, /*FLOOR*/
63+ 0x0005b84d, /*FMOD*/
64+ 0x00ac5c9f, /*FOPEN*/
65+ 0x000121db, /*FOR*/
66+ 0x18352839, /*FPRINT*/
67+ 0x0005c865, /*FPUT*/
68+ 0x00ad2e40, /*FPUTC*/
69+ 0x00aefdec, /*FSEEK*/
70+ 0x00063b90, /*GCLS*/
71+ 0x1a808bcb, /*GCOLOR*/
72+ 0x1ab733b3, /*GETDIR*/
73+ 0x00c60f03, /*GOSUB*/
74+ 0x0006796c, /*GOTO*/
75+ 0x1bcfcc39, /*GPRINT*/
76+ 0x00012a99, /*HEX*/
77+ 0x0007ad12, /*IDLE*/
78+ 0x00010153, /*IF*/
79+ 0x00f8701a, /*INKEY*/
80+ 0x00f88ba5, /*INPUT*/
81+ 0x000130e9, /*INT*/
82+ 0x00092084, /*KEYS*/
83+ 0x013be43d, /*LABEL*/
84+ 0x00013ecf, /*LEN*/
85+ 0x00013ed5, /*LET*/
86+ 0x0009e96a, /*LINE*/
87+ 0x00014030, /*LOG*/
88+ 0x0145f324, /*LOG10*/
89+ 0x000a07f9, /*LOOP*/
90+ 0x000abca3, /*MODF*/
91+ 0x016418d4, /*MUSIC*/
92+ 0x000b4321, /*NEXT*/
93+ 0x000148f8, /*NEW*/
94+ 0x00014a5d, /*NOT*/
95+ 0x38a658d7, /*OPTION*/
96+ 0x000152c0, /*PCG*/
97+ 0x000cacec, /*PEEK*/
98+ 0x3b1c6aea, /*PEEK16*/
99+ 0x3b1c6b2e, /*PEEK32*/
100+ 0x00010252, /*PI*/
101+ 0x01ac8479, /*POINT*/
102+ 0x000ce05e, /*POKE*/
103+ 0x3c20dc0a, /*POKE16*/
104+ 0x3c20dc4e, /*POKE32*/
105+ 0x00015480, /*POW*/
106+ 0x01aea739, /*PRINT*/
107+ 0x000cf3d5, /*PSET*/
108+ 0x3cb45fa4, /*PUBLIC*/
109+ 0x3cc0fe21, /*PUTBMP*/
110+ 0x000e18d5, /*READ*/
111+ 0x00015d2e, /*REM*/
112+ 0x425c9703, /*RETURN*/
113+ 0x00015e69, /*RND*/
114+ 0x45c26d49, /*SCROLL*/
115+ 0x45f6e3b3, /*SETDIR*/
116+ 0x00016287, /*SGN*/
117+ 0x000162cf, /*SIN*/
118+ 0x000ee52d, /*SINH*/
119+ 0x01f9a429, /*SOUND*/
120+ 0x000f0e49, /*SQRT*/
121+ 0x47f711de, /*SYSTEM*/
122+ 0x000166bf, /*TAN*/
123+ 0x000f72ed, /*TANH*/
124+ 0x020ed5f3, /*TIMER*/
125+ 0x02182fee, /*TVRAM*/
126+ 0x022c2a2d, /*UNTIL*/
127+ 0x4e8887d0, /*USEPCG*/
128+ 0x4e88a5f3, /*USEVAR*/
129+ 0x000170dd, /*VAL*/
130+ 0x000170e3, /*VAR*/
131+ 0x00119505, /*WAIT*/
132+ 0x0011a9e9, /*WEND*/
133+ 0x025aef62, /*WHILE*/
134+ 0x025b8d75, /*WIDTH*/
135+ // Additional names follow
136+ ADDITIONAL_RESERVED_VAR_NAMES
137+};
138+
139+/*
140+ check_var_name();
141+ This function reads the current position of source code and check if
142+ it contains valid var name, the function returns 0 or plus value.
143+ If not, it returns -1;
144+*/
145+
146+int check_var_name(){
147+ char b1;
148+ int j;
149+ int i=0;
150+ int prevpos=g_srcpos;
151+ next_position();
152+ b1=g_source[g_srcpos];
153+ if (b1<'A' || 'Z'<b1) return -1;
154+ do {
155+ // First character must be A-Z
156+ // From second, A-Z and 0-9 can be used.
157+ i*=36;
158+ if ('0'<=b1 && b1<='9') {
159+ i+=b1-'0';
160+ } else if (g_srcpos==prevpos) {
161+ // First character must be A-Z.
162+ // Subtract 9, resulting 1-26 but not 10-35.
163+ // This subtraction is required to maintain
164+ // final number being <0x80000000.
165+ i+=b1-'A'+1;
166+ } else {
167+ i+=b1-'A'+10;
168+ }
169+ g_srcpos++;
170+ b1=g_source[g_srcpos];
171+ } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z');
172+ // Length of the label must be between 2 and 6.
173+ if (g_srcpos-prevpos<2) {
174+ // One letter var name, A-Z
175+ return i-1;
176+ }
177+ if (6<g_srcpos-prevpos) {
178+ // Too long. This is not var name.
179+ g_srcpos=prevpos;
180+ return -1;
181+ }
182+ i+=65536;
183+ // Check if this is reserved var name.
184+ for(j=0;j<sizeof reserved_var_names/sizeof reserved_var_names[0];j++){
185+ if (reserved_var_names[j]==i) {
186+ // This var name is reserved as used for function or statement.
187+ g_srcpos=prevpos;
188+ return -1;
189+ }
190+ }
191+ // Reserved var names table was checked. This must be a long var name.
192+ return i;
193+}
194+
195+/*
196+ int get_var_number();
197+ This function returns variable number that can be used as the index of $s8
198+*/
199+
200+int get_var_number(){
201+ int i,j,spos;
202+ int* record;
203+ // This must be a short or long var name.
204+ spos=g_srcpos;
205+ i=check_var_name();
206+ if (i<0) return -1;
207+ // If it is a short name, immediately return.
208+ if (i<26) return i;
209+ // Check if CLASS::STATIC
210+ if (g_source[g_srcpos]==':' && g_source[g_srcpos+1]==':') {
211+ // This is CLASS::STATIC
212+ g_srcpos++;
213+ g_srcpos++;
214+ j=check_var_name();
215+ if (j<26) return -1;
216+ cmpdata_reset();
217+ while(record=cmpdata_find(CMPDATA_STATIC)){
218+ if (record[1]!=i) continue;
219+ if (record[2]!=j) continue;
220+ // Found CLASS::STATIC
221+ i=record[0]&0x0000FFFF;
222+ j=0;
223+ break;
224+ }
225+ if (j) {
226+ // Not found. Maybe a static method
227+ g_srcpos=spos;
228+ return -1;
229+ }
230+ } else {
231+ // Search long var names registered by USEVAR statement.
232+ // If found, returns the value that can be used as the index of $s8
233+ i=search_var_name(i);
234+ if (i<0) return -1;
235+ }
236+ // This var name is defined by USEVAR statement.
237+ return i+ALLOC_LNV_BLOCK;
238+
239+}
240+
241+/*
242+ int search_var_name(int nameint);
243+ This function searchs registered long var name in compile data table.
244+ If not found, this function returns -1.
245+ If found, it retunrs var number, beginning 0.
246+*/
247+
248+int search_var_name(int nameint){
249+ int* cmpdata;
250+ cmpdata_reset();
251+ while(cmpdata=cmpdata_find(CMPDATA_USEVAR)){
252+ if (cmpdata[1]==nameint) return cmpdata[0]&0x0000ffff;
253+ }
254+ return -1;
255+}
256+
257+/*
258+ char* register_var_name(int nameint);
259+ This function is called when compiler detects "USEVAR" statement.
260+ It registers the long file name in compile data table.
261+*/
262+
263+char* register_var_name(int nameint){
264+ // Check if registered before. If did, cause error.
265+ if (search_var_name(nameint)!=-1) return ERR_INVALID_VAR_NAME;
266+ // Number of long var name is restricted
267+ if (ALLOC_LNV_NUM<=g_long_name_var_num) return ERR_INVALID_VAR_NAME;
268+ // Register var name as a compile data
269+ g_temp=nameint;
270+ return cmpdata_insert(CMPDATA_USEVAR,g_long_name_var_num++,&g_temp,1);
271+}