wonbe.c 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716
  1. /* wonbe: WonderWitch Basic Environment */
  2. /* First Created: Nov.3,2000 by Pie Dey Co.,Ltd. */
  3. /* This source code is distributed under GNU General Public License (GPL) */
  4. /* see http://www.gnu.org/ about GPL */
  5. /* This source code is for: */
  6. /* Visual C++ 1.5 (for WW binary) */
  7. /* Visual C++ 6.0 (for Win32 binary) */
  8. /* Turbo C++ 1.0 (for WW binary, by Hirotaka JOE Ohkubo) */
  9. /* GNU Win32 gcc (for Win32 binary, by Hirotaka JOE Ohkubo) */
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #ifdef WIN32
  14. #include <assert.h>
  15. #endif
  16. #ifdef WW
  17. #include <sys/comm.h>
  18. #include <sys/process.h>
  19. #include <sys/fcntl.h>
  20. #include <sys/bios.h>
  21. #include <sys/libwwc.h>
  22. #define assert(x)
  23. #endif
  24. #include "keywords.h"
  25. #ifdef WIN32
  26. #include "win32text.h"
  27. #endif
  28. /* cygwin でなぜか stdarg.h が読み込まれてない & __GNUC__ が効かない... */
  29. #ifdef CYGWIN
  30. #include <stdarg.h>
  31. #endif
  32. char myVersion[] = "0.06";
  33. #ifdef WW
  34. #define NEWLINE "\xa\xd"
  35. #else
  36. #define NEWLINE "\n"
  37. #endif
  38. #ifdef WW
  39. #define MEMMOVE mymemmove
  40. #define FAR far
  41. #else
  42. #define MEMMOVE mymemmove
  43. #define FAR
  44. #endif
  45. #ifdef WIN32
  46. typedef unsigned char BYTE;
  47. #endif
  48. typedef unsigned short WORD;
  49. typedef signed short SHORT;
  50. typedef unsigned long DWORD;
  51. #define EOL (0x0d)
  52. #ifdef WIN32
  53. typedef int BOOL;
  54. #endif
  55. #define FALSE 0
  56. #define TRUE 1
  57. typedef void (*NEARPROC)();
  58. #define WORKAREA_SIZE ((WORD)49152)
  59. #define LINE_SIZE (256)
  60. /* PLAY statement support */
  61. #ifdef WW
  62. #include <il_sound.h>
  63. SoundIL soundIL;
  64. extern BYTE *_heap;
  65. BOOL soundAvailable;
  66. #endif
  67. /* 実行のみのモードで動いているとき (シリアル経由で端末が居ないとき) */
  68. BOOL runtimeOnly;
  69. #ifdef WW
  70. void fatalExit( const char * msg )
  71. {
  72. text_screen_init();
  73. text_put_string( 0, 0, (char*)msg );
  74. text_put_string( 0, 3, "PUSH ANY BUTTON" );
  75. key_wait();
  76. }
  77. #endif
  78. #ifdef WW
  79. BOOL isWonderSwanColor()
  80. {
  81. return wwc_get_hardarch() != HARDARCH_WS;
  82. }
  83. #endif
  84. BOOL commonPrint( FILE FAR * fp, const char * msg,... )
  85. {
  86. #ifdef WW
  87. static
  88. #endif
  89. char buf[256];
  90. vsprintf(buf, msg, (va_list)(&msg+1) );
  91. if( fp != NULL ) {
  92. int r;
  93. r = fprintf( fp, buf );
  94. return r >= 0;
  95. } else {
  96. #ifdef WW
  97. if( runtimeOnly ) {
  98. fatalExit( buf );
  99. } else {
  100. comm_send_string( buf );
  101. }
  102. #else
  103. printf( buf );
  104. #endif
  105. }
  106. return TRUE;
  107. }
  108. void consoleInput( BYTE * buf, WORD len )
  109. {
  110. #ifdef WW
  111. WORD cursor;
  112. if( runtimeOnly ) {
  113. fatalExit("consoleInput not allowed in runtime mode");
  114. } else {
  115. cursor = 0;
  116. while( TRUE ) {
  117. int ch;
  118. ch = comm_receive_char();
  119. if( ch == 0x0d ) { /* CR */
  120. buf[cursor] = '\0';
  121. return;
  122. }
  123. if( ch == 0x09 ) { /* TAB */
  124. goto inputAsChar;
  125. }
  126. if( ch == 0x08 ) { /* BS */
  127. if( cursor > 0 ) {
  128. cursor--;
  129. comm_send_char( (unsigned char)ch );
  130. continue;
  131. }
  132. }
  133. if( ch >= 0 && ch < ' ' ) {
  134. /* ignore it */
  135. continue;
  136. }
  137. if( ch >= ' ' && ch <= 0xfc ) {
  138. inputAsChar:
  139. if( cursor < len-1 ) {
  140. buf[cursor] = ch;
  141. cursor++;
  142. comm_send_char( (unsigned char)ch );
  143. }
  144. }
  145. }
  146. }
  147. #else
  148. gets(buf);
  149. #endif
  150. }
  151. typedef struct {
  152. WORD id;
  153. const BYTE * name;
  154. } KEYWORDITEM;
  155. KEYWORDITEM keywordsA[] = {
  156. { KEYWORD_AND,"and" },
  157. { KEYWORD_ABS,"abs" },
  158. { KEYWORD_AX,"ax"},
  159. { 0,NULL }
  160. };
  161. KEYWORDITEM keywordsB[] = {
  162. { KEYWORD_BREAK,"break" },
  163. { KEYWORD_BX, "bx" },
  164. { 0,NULL }
  165. };
  166. KEYWORDITEM keywordsC[] = {
  167. { KEYWORD_CHR,"chr" },
  168. { KEYWORD_CLS,"cls" },
  169. { KEYWORD_CONT,"cont" },
  170. { KEYWORD_CALL, "call" },
  171. { KEYWORD_CSEG, "cseg" },
  172. { KEYWORD_CX,"cx" },
  173. { KEYWORD_COLORMODE,"colormode" },
  174. { KEYWORD_COLOR,"color" },
  175. { 0,NULL }
  176. };
  177. KEYWORDITEM keywordsD[] = {
  178. { KEYWORD_DEBUG,"debug" },
  179. { KEYWORD_DSEG, "dseg" },
  180. { KEYWORD_DX, "dx" },
  181. { KEYWORD_DI, "di" },
  182. { KEYWORD_DS, "ds" },
  183. { KEYWORD_DEFSEG, "defseg" },
  184. { 0,NULL }
  185. };
  186. KEYWORDITEM keywordsE[] = {
  187. { KEYWORD_END,"end" },
  188. { KEYWORD_EXIT,"exit" },
  189. { KEYWORD_ES, "es" },
  190. { 0,NULL }
  191. };
  192. KEYWORDITEM keywordsF[] = {
  193. { KEYWORD_FOR,"for" },
  194. { KEYWORD_FILES,"files" },
  195. { 0,NULL }
  196. };
  197. KEYWORDITEM keywordsG[] = {
  198. { KEYWORD_GOTO,"goto" },
  199. { KEYWORD_GOSUB,"gosub" },
  200. { 0,NULL }
  201. };
  202. KEYWORDITEM keywordsH[] = {
  203. { KEYWORD_HARDARCH,"hardarch" },
  204. { 0,NULL }
  205. };
  206. KEYWORDITEM keywordsI[] = {
  207. { KEYWORD_IF,"if" },
  208. { KEYWORD_INT, "int" },
  209. { 0,NULL }
  210. };
  211. KEYWORDITEM keywordsL[] = {
  212. { KEYWORD_LOCATE,"locate" },
  213. { KEYWORD_LIST,"list" },
  214. { KEYWORD_LOAD,"load" },
  215. { 0,NULL }
  216. };
  217. KEYWORDITEM keywordsM[] = {
  218. { KEYWORD_MERGE,"merge" },
  219. { 0,NULL }
  220. };
  221. KEYWORDITEM keywordsN[] = {
  222. { KEYWORD_NEXT,"next" },
  223. { KEYWORD_NOT,"not" },
  224. { KEYWORD_NEW,"new" },
  225. { 0,NULL }
  226. };
  227. KEYWORDITEM keywordsO[] = {
  228. { KEYWORD_OR,"or" },
  229. { 0,NULL }
  230. };
  231. KEYWORDITEM keywordsP[] = {
  232. { KEYWORD_PRINT,"print" },
  233. { KEYWORD_PLAY,"play" },
  234. { KEYWORD_PEEK, "peek" },
  235. { KEYWORD_POKE, "poke" },
  236. { KEYWORD_PALETTE, "palette" },
  237. { 0,NULL }
  238. };
  239. KEYWORDITEM keywordsR[] = {
  240. { KEYWORD_REM,"rem" },
  241. { KEYWORD_RETURN,"return" },
  242. { KEYWORD_RND,"rnd" },
  243. { KEYWORD_RUN,"run" },
  244. { KEYWORD_RANDOMIZE,"randomize" },
  245. { 0,NULL }
  246. };
  247. KEYWORDITEM keywordsS[] = {
  248. { KEYWORD_STEP,"step" },
  249. { KEYWORD_SCAN_A,"scan_a" },
  250. { KEYWORD_SCAN_B,"scan_b" },
  251. { KEYWORD_SCAN_X1,"scan_x1" },
  252. { KEYWORD_SCAN_X2,"scan_x2" },
  253. { KEYWORD_SCAN_X3,"scan_x3" },
  254. { KEYWORD_SCAN_X4,"scan_x4" },
  255. { KEYWORD_SCAN_Y1,"scan_y1" },
  256. { KEYWORD_SCAN_Y2,"scan_y2" },
  257. { KEYWORD_SCAN_Y3,"scan_y3" },
  258. { KEYWORD_SCAN_Y4,"scan_y4" },
  259. { KEYWORD_SCAN,"scan" }, /* scanはscna_Xより後になければならない */
  260. { KEYWORD_SAVE,"save" },
  261. { KEYWORD_SSEG, "sseg" },
  262. { KEYWORD_SI, "si" },
  263. { 0,NULL }
  264. };
  265. KEYWORDITEM keywordsT[] = {
  266. { KEYWORD_THEN,"then" },
  267. { KEYWORD_TO,"to" },
  268. { KEYWORD_TICK,"tick" },
  269. { KEYWORD_TRON,"tron" },
  270. { KEYWORD_TROFF,"troff" },
  271. { 0,NULL }
  272. };
  273. KEYWORDITEM keywordsV[] = {
  274. { KEYWORD_VARPTR, "varptr" },
  275. { KEYWORD_VARSEG, "varseg" },
  276. { 0,NULL }
  277. };
  278. KEYWORDITEM keywordsW[] = {
  279. { KEYWORD_WAITVB,"waitvb" },
  280. { KEYWORD_WAIT,"wait" }, // waitはwaitvbより後になければならない
  281. { 0,NULL }
  282. };
  283. KEYWORDITEM keywordsX[] = {
  284. { KEYWORD_XOR,"xor" },
  285. { 0,NULL }
  286. };
  287. KEYWORDITEM * keywordsIndex[26] = {
  288. keywordsA, keywordsB, keywordsC, keywordsD,
  289. keywordsE, keywordsF, keywordsG, keywordsH,
  290. keywordsI, NULL, NULL, keywordsL,
  291. keywordsM, keywordsN, keywordsO, keywordsP,
  292. NULL, keywordsR, keywordsS, keywordsT,
  293. NULL, keywordsV, keywordsW, keywordsX,
  294. NULL, NULL
  295. };
  296. /* インタラクティブモード時の1行バッファ */
  297. BYTE waRawLine[LINE_SIZE];
  298. BYTE waCookedLine[LINE_SIZE];
  299. /* コードとデータを収める領域 */
  300. WORD codeTop;
  301. WORD dataTop;
  302. /*WORD savedPointer; /* breakしたときの実行中位置 */
  303. BYTE wa[WORKAREA_SIZE];
  304. /* グローバル変数領域 */
  305. #define NUMBER_OF_SIMPLE_VARIABLES (26)
  306. SHORT globalVariables[NUMBER_OF_SIMPLE_VARIABLES];
  307. SHORT topLevelVariables[NUMBER_OF_SIMPLE_VARIABLES];
  308. SHORT * localVariables; /* あるスコープで有効なローカル変数領域を持つ */
  309. /* 現在実行中の位置に関する情報 */
  310. /* waかwaCookedLineのどちらかの中を示すかNULL */
  311. BYTE * executionPointer;
  312. /* contコマンドで実行を再開するポイント */
  313. BYTE * resumePointer;
  314. /* 現在処理中の行番号 (0ならダイレクトモード) */
  315. WORD currentLineNumber;
  316. /* gosubとforのためのスタック */
  317. #define STACK_TYPE_GOSUB 1
  318. #define STACK_TYPE_FOR 2
  319. typedef struct {
  320. WORD type; /* 1==GOSUB, 2==FOR */
  321. /* for GOSUB and FOR */
  322. BYTE * returnPointer;
  323. /* for GOSUB */
  324. SHORT * lastLocalVariables;
  325. SHORT simpleVariables[NUMBER_OF_SIMPLE_VARIABLES];
  326. /* for FOR */
  327. SHORT * pvar; /* counter variable */
  328. SHORT limit; /* limit value */
  329. SHORT step; /* step value */
  330. } STACK;
  331. #define STACK_MAX 8
  332. STACK stacks[STACK_MAX];
  333. int stackPointer;
  334. /* インタラクティブモードかインタプリタモードか */
  335. BOOL bInteractive;
  336. /* インタプリタ脱出後の振る舞いのリクエスト */
  337. BOOL bForceToReturnSuper;
  338. int requestNextAction; /* 以下のいずれか */
  339. /* 何もせず現状のまま */
  340. #define REQUEST_NO_ACTION 0
  341. /* 対話モードへ行け */
  342. #define REQUEST_INTERACTIVE 1
  343. /* runLineNumberから実行を開始せよ */
  344. #define REQUEST_RUN_LINENUMBER 2
  345. /* waRawLineに入っている文字列をファイル名としてそれを読み込んで実行せよ */
  346. #define REQUEST_RUN_FILE 3
  347. /* newせよ */
  348. #define REQUEST_NEW 4
  349. /* waRawLineに入っている文字列をファイル名としてそれをロード */
  350. #define REQUEST_LOAD_FILE 5
  351. /* WONBEを終了してOSに戻れ */
  352. #define REQUEST_EXIT_SYSTEM 6
  353. /* waRawLineに入っている文字列をファイル名としてそれをマージ */
  354. #define REQUEST_MERGE_FILE 7
  355. /* REQUEST_RUN_LINENUMBERで実行開始をリクエストする行番号 */
  356. WORD runLineNumber;
  357. // 編集機能が追加専用モードであることを示す
  358. // REQUEST_RUN_FILE or REQUEST_LOAD_FILE経由で処理するときだけTRUEとなる
  359. BOOL appendMode = FALSE;
  360. // Read/Writeされる擬似変数の置き場所
  361. WORD defseg;
  362. WORD registers[KEYWORD_ES-KEYWORD_AX+1];
  363. // トレースモード(tron/troff)
  364. BOOL traceFlag = FALSE;
  365. // マシン語アクセス関連
  366. #ifdef VC15
  367. // VC++1.5のときに使うコード
  368. WORD getdseg()
  369. {
  370. WORD s;
  371. __asm mov s, ds;
  372. return s;
  373. }
  374. WORD getsseg()
  375. {
  376. WORD s;
  377. __asm mov s, ss;
  378. return s;
  379. }
  380. WORD getcseg()
  381. {
  382. WORD s;
  383. __asm mov s, cs;
  384. return s;
  385. }
  386. #else
  387. WORD getdseg()
  388. {
  389. return 0; // DUMMY VALUE
  390. }
  391. WORD getsseg()
  392. {
  393. return 0; // DUMMY VALUE
  394. }
  395. WORD getcseg()
  396. {
  397. return 0; // DUMMY VALUE
  398. }
  399. #endif
  400. /* エラー発生 */
  401. void syntaxError()
  402. {
  403. commonPrint(NULL, "Syntax Error in %d\x7" NEWLINE, currentLineNumber );
  404. bForceToReturnSuper = TRUE;
  405. requestNextAction = REQUEST_INTERACTIVE;
  406. }
  407. void divideByZero()
  408. {
  409. commonPrint(NULL, "Divide by 0 in %d\x7" NEWLINE, currentLineNumber );
  410. bForceToReturnSuper = TRUE;
  411. requestNextAction = REQUEST_INTERACTIVE;
  412. }
  413. void outOfArraySubscription()
  414. {
  415. commonPrint(NULL, "Out of Array Subscription in %d\x7" NEWLINE, currentLineNumber );
  416. bForceToReturnSuper = TRUE;
  417. requestNextAction = REQUEST_INTERACTIVE;
  418. }
  419. void lineNumberNotFound( WORD lineNumber )
  420. {
  421. commonPrint(NULL, "Line Number %d not Found in %d\x7" NEWLINE, lineNumber, currentLineNumber );
  422. bForceToReturnSuper = TRUE;
  423. requestNextAction = REQUEST_INTERACTIVE;
  424. }
  425. void stackOverflow()
  426. {
  427. commonPrint(NULL, "Stack Overflow in %d\x7" NEWLINE, currentLineNumber );
  428. bForceToReturnSuper = TRUE;
  429. requestNextAction = REQUEST_INTERACTIVE;
  430. }
  431. void stackUnderflow()
  432. {
  433. commonPrint(NULL, "Stack Underflow in %d\x7" NEWLINE, currentLineNumber );
  434. bForceToReturnSuper = TRUE;
  435. requestNextAction = REQUEST_INTERACTIVE;
  436. }
  437. void nextWithoutFor()
  438. {
  439. commonPrint(NULL, "Next without For in %d\x7" NEWLINE, currentLineNumber );
  440. bForceToReturnSuper = TRUE;
  441. requestNextAction = REQUEST_INTERACTIVE;
  442. }
  443. void outOfMemory()
  444. {
  445. commonPrint(NULL, "Out of memory in %d\x7" NEWLINE, currentLineNumber );
  446. bForceToReturnSuper = TRUE;
  447. requestNextAction = REQUEST_INTERACTIVE;
  448. }
  449. void loadError()
  450. {
  451. commonPrint(NULL, "File Not Found or Load Error in %d\x7" NEWLINE, currentLineNumber );
  452. bForceToReturnSuper = TRUE;
  453. requestNextAction = REQUEST_INTERACTIVE;
  454. }
  455. void cantContinue()
  456. {
  457. commonPrint(NULL, "Can't Continue in %d\x7" NEWLINE, currentLineNumber );
  458. bForceToReturnSuper = TRUE;
  459. requestNextAction = REQUEST_INTERACTIVE;
  460. }
  461. void saveError()
  462. {
  463. commonPrint(NULL, "Save Error in %d\x7" NEWLINE, currentLineNumber );
  464. bForceToReturnSuper = TRUE;
  465. requestNextAction = REQUEST_INTERACTIVE;
  466. }
  467. void paramError()
  468. {
  469. commonPrint(NULL, "Parameter Error in %d\x7" NEWLINE, currentLineNumber );
  470. bForceToReturnSuper = TRUE;
  471. requestNextAction = REQUEST_INTERACTIVE;
  472. }
  473. void lineNumberZeroError()
  474. {
  475. // このエラーはエディタが出すものなのでランタイムで発生することはあり得ない
  476. // なので現在行番号を報告する意味がない
  477. //commonPrint(NULL, "Invalid Line Number 0 in %d\x7" NEWLINE, currentLineNumber );
  478. commonPrint(NULL, "Invalid Line Number 0\x7" NEWLINE );
  479. bForceToReturnSuper = TRUE;
  480. requestNextAction = REQUEST_INTERACTIVE;
  481. }
  482. /* ユーティリティ関数達 */
  483. void mymemmove( BYTE * dst, const BYTE * src, WORD len )
  484. {
  485. WORD i;
  486. if( dst < src ) {
  487. for( i=0; i<len; i++ ) {
  488. *dst++ = *src++;
  489. }
  490. } else {
  491. dst += len;
  492. src += len;
  493. for( i=0; i<len; i++ ) {
  494. *--dst = *--src;
  495. }
  496. }
  497. }
  498. BYTE * skipToEOL( BYTE * p )
  499. {
  500. while( TRUE ) {
  501. if( *p == EOL ) return p;
  502. switch( *p++ ) {
  503. case 0x01: /* 次にあるのは10進2バイト整数 */
  504. case 0x02: /* 次にあるのは16進2バイト整数 */
  505. p += 2;
  506. break;
  507. case 0x03: /* 次にあるのは可変長文字列 0x00でターミネート */
  508. {
  509. while( TRUE ) {
  510. if( *p++ == '\0' ) break;
  511. }
  512. }
  513. break;
  514. }
  515. }
  516. }
  517. // 短い関数をインライン展開しないコンパイラ向けの最適化としてマクロ化
  518. #define skipToNextLine(p) ( skipToEOL(p+4)+1 )
  519. //BYTE * skipToNextLine( BYTE * p )
  520. //{
  521. // return skipToEOL( p+4 ); // +4は行番号2バイト行長さ2バイト
  522. //}
  523. #if 1
  524. #define mytolower(ch) ((ch >= 'A' && ch <= 'Z')? ch - 'A' + 'a' : ch)
  525. #else
  526. BYTE mytolower( BYTE ch )
  527. {
  528. if( ch >= 'A' && ch <= 'Z' ) {
  529. return ch - 'A' + 'a';
  530. }
  531. return ch;
  532. }
  533. #endif
  534. /* シフトJISの1バイト目かどうか判断。マクロなので副作用に注意 */
  535. #define IsDBCSLeadByte(ch) ((ch >= 0x81 && ch <= 0x9f) || (ch >= 0xe0 && ch <= 0xfc))
  536. /* 実行時情報のクリア (contできなくなる) */
  537. void clearRuntimeInfo()
  538. {
  539. memset( globalVariables, 0, sizeof(globalVariables) );
  540. memset( topLevelVariables, 0, sizeof(topLevelVariables) );
  541. memset( stacks, 0, sizeof(stacks) );
  542. memset( registers, 0, sizeof(registers) );
  543. executionPointer = NULL;
  544. resumePointer = NULL;
  545. currentLineNumber = 0;
  546. localVariables = topLevelVariables;
  547. stackPointer = 0;
  548. defseg = getdseg();
  549. srand(0);
  550. }
  551. /* 行頭の行番号の、実行時の定型処理 */
  552. void processLineHeader()
  553. {
  554. if( !bInteractive ) {
  555. currentLineNumber = *((WORD *)executionPointer);
  556. if( traceFlag ) {
  557. commonPrint( NULL, "[%d]", currentLineNumber );
  558. }
  559. executionPointer += 4; // +4は行番号2バイト行長さ2バイト
  560. } else {
  561. currentLineNumber = 0;
  562. }
  563. }
  564. /* 行番号処理 */
  565. BYTE * getLineReferenceFromLineNumber( WORD lineNumber )
  566. {
  567. BYTE * p;
  568. WORD t;
  569. p = wa;
  570. while( TRUE ) {
  571. t = *((WORD *)p);
  572. if( t == 0 ) {
  573. return NULL;
  574. }
  575. if( lineNumber == t ) {
  576. return p;
  577. }
  578. p += *((WORD *)(p+2));
  579. }
  580. }
  581. BYTE * getInsertionPointFromLineNumber( WORD lineNumber )
  582. {
  583. BYTE * p;
  584. WORD t;
  585. p = wa;
  586. while( TRUE ) {
  587. t = *((WORD *)p);
  588. if( t == 0 ) {
  589. return p;
  590. }
  591. if( lineNumber <= t ) {
  592. return p;
  593. }
  594. p += *((WORD *)(p+2));
  595. }
  596. }
  597. /* 配列管理 */
  598. int availableArrayItems()
  599. {
  600. return (WORKAREA_SIZE-dataTop) >> 1;
  601. }
  602. SHORT * derefArrayItem( int index )
  603. {
  604. if( index < 0 || index >= availableArrayItems() ) {
  605. outOfArraySubscription();
  606. return NULL; /* そのインデックスは使えません */
  607. }
  608. return (SHORT*)(&wa[dataTop+index*2]);
  609. }
  610. /* 物理テキストの管理 */
  611. #define SCREEN_SIZE_X (224/8)
  612. #define SCREEN_SIZE_Y (144/8)
  613. WORD screen[SCREEN_SIZE_X][SCREEN_SIZE_Y];
  614. SHORT xCursor, yCursor;
  615. #define TABSTOP 8
  616. void ptextScrollUp()
  617. {
  618. int x, y;
  619. for( y=0; y<SCREEN_SIZE_Y-1; y++ ) {
  620. for( x=0; x<SCREEN_SIZE_X; x++ ) {
  621. screen[x][y] = screen[x][y+1];
  622. }
  623. }
  624. for( x=0; x<SCREEN_SIZE_X; x++ ) {
  625. screen[x][SCREEN_SIZE_Y-1] = ' ';
  626. }
  627. for( y=0; y<SCREEN_SIZE_Y; y++ ) {
  628. for( x=0; x<SCREEN_SIZE_X; x++ ) {
  629. #ifdef WIN32
  630. drawChar( x, y, screen[x][y] );
  631. #endif
  632. #ifdef WW
  633. text_put_char( x, y, screen[x][y] );
  634. #endif
  635. }
  636. }
  637. }
  638. void ptextNewline()
  639. {
  640. xCursor = 0;
  641. yCursor++;
  642. if( yCursor >= SCREEN_SIZE_Y ) {
  643. ptextScrollUp();
  644. yCursor = SCREEN_SIZE_Y-1;
  645. }
  646. }
  647. void ptextTab()
  648. {
  649. if( xCursor+TABSTOP >= SCREEN_SIZE_X ) {
  650. ptextNewline();
  651. return;
  652. }
  653. xCursor = (xCursor+TABSTOP) / TABSTOP * TABSTOP;
  654. }
  655. void ptextString( const BYTE FAR * msg )
  656. {
  657. while( TRUE ) {
  658. WORD ch;
  659. if( *msg == '\0' ) break;
  660. if( IsDBCSLeadByte(*msg) ) {
  661. ch = (msg[0] << 8) + msg[1];
  662. msg+=2;
  663. } else {
  664. ch = msg[0];
  665. msg++;
  666. }
  667. screen[xCursor][yCursor] = ch;
  668. #ifdef WIN32
  669. drawChar( xCursor, yCursor, ch );
  670. #endif
  671. #ifdef WW
  672. text_put_char( xCursor, yCursor, ch );
  673. #endif
  674. xCursor++;
  675. if( xCursor >= SCREEN_SIZE_X ) {
  676. xCursor = 0;
  677. yCursor++;
  678. if( yCursor >= SCREEN_SIZE_Y ) {
  679. ptextScrollUp();
  680. yCursor = SCREEN_SIZE_Y-1;
  681. }
  682. }
  683. }
  684. }
  685. void ptextLocate( int x, int y )
  686. {
  687. if( x < 0 ) x = 0;
  688. if( x >= SCREEN_SIZE_X ) x = SCREEN_SIZE_X-1;
  689. if( y < 0 ) y = 0;
  690. if( y >= SCREEN_SIZE_Y ) y = SCREEN_SIZE_Y-1;
  691. xCursor = x;
  692. yCursor = y;
  693. }
  694. void ptextCLS()
  695. {
  696. int x,y;
  697. xCursor = 0;
  698. yCursor = 0;
  699. #ifdef WIN32
  700. clearText();
  701. #endif
  702. #ifdef WW
  703. for( y=0; y<SCREEN_SIZE_Y; y++ ) {
  704. text_fill_char(0, y, SCREEN_SIZE_X, ' ' );
  705. }
  706. #endif
  707. for( y=0; y<SCREEN_SIZE_Y; y++ ) {
  708. for( x=0; x<SCREEN_SIZE_X; x++ ) {
  709. screen[x][y] = ' ';
  710. }
  711. }
  712. }
  713. /* 中間コードからソーステキストに戻しながら出力(listとsaveで使う) */
  714. BOOL sourceDump( FILE FAR * fp, WORD from, WORD to )
  715. {
  716. BYTE * p;
  717. BOOL b;
  718. p = getInsertionPointFromLineNumber( from );
  719. while( TRUE ) {
  720. WORD lineNumber;
  721. lineNumber = *((WORD*)p);
  722. if( lineNumber == 0 ) break;
  723. if( lineNumber > to ) break;
  724. p += 4;
  725. b = commonPrint(fp,"%d",lineNumber);
  726. if( b == FALSE ) return FALSE;
  727. while( TRUE ) {
  728. if( *p == EOL ) {
  729. p++;
  730. break;
  731. }
  732. if( *p == 0x01 ) {
  733. WORD n;
  734. p++;
  735. n = *((WORD*)p);
  736. p += 2;
  737. b = commonPrint(fp,"%d",n);
  738. if( b == FALSE ) return FALSE;
  739. } else if( *p == 0x02 ) {
  740. WORD n;
  741. p++;
  742. n = *((WORD*)p);
  743. p += 2;
  744. b = commonPrint(fp,"0x%x",n);
  745. if( b == FALSE ) return FALSE;
  746. } else if( *p == 0x03 ) {
  747. p++;
  748. b = commonPrint(fp,"\"%s\"",p);
  749. if( b == FALSE ) return FALSE;
  750. p += strlen(p)+1;
  751. } else if( *p == '\'' ) { /* コメントのあとはそのまま行末まで転送 */
  752. while( TRUE ) {
  753. if( *p == EOL ) break;
  754. b = commonPrint(fp,"%c",*p);
  755. if( b == FALSE ) return FALSE;
  756. p++;
  757. }
  758. } else if( *p >= 0x80 ) {
  759. int i;
  760. BOOL found;
  761. found = FALSE;
  762. for( i=0; i<26; i++ ) {
  763. KEYWORDITEM * k;
  764. if( found ) break;
  765. k = keywordsIndex[i];
  766. if( k == NULL ) continue;
  767. while( TRUE ) {
  768. if( k->id == 0 ) break;
  769. if( k->id == *p ) {
  770. b = commonPrint(fp, k->name );
  771. if( b == FALSE ) return FALSE;
  772. p++;
  773. if( k->id == KEYWORD_REM ) { /* コメントのあとはそのまま行末まで転送 */
  774. while( TRUE ) {
  775. if( *p == EOL ) break;
  776. b = commonPrint(fp,"%c",*p);
  777. if( b == FALSE ) return FALSE;
  778. p++;
  779. }
  780. }
  781. found = TRUE;
  782. break;
  783. }
  784. k++;
  785. }
  786. }
  787. if( !found ) {
  788. b = commonPrint(fp,"[?%x?]", *p );
  789. if( b == FALSE ) return FALSE;
  790. p++;
  791. }
  792. } else {
  793. b = commonPrint(fp,"%c",*p);
  794. if( b == FALSE ) return FALSE;
  795. p++;
  796. }
  797. }
  798. b = commonPrint(fp,NEWLINE);
  799. if( b == FALSE ) return FALSE;
  800. }
  801. return TRUE;
  802. }
  803. /* 式計算機能 */
  804. SHORT expr(); /* forward decl */
  805. SHORT * getArrayReference()
  806. {
  807. BYTE ch;
  808. int index;
  809. SHORT * pvar;
  810. while( TRUE ) {
  811. ch = *executionPointer++;
  812. if( ch != ' ' && ch != '\t' ) break;
  813. }
  814. if( ch != '(' && ch != '[' ) {
  815. syntaxError();
  816. return NULL;
  817. }
  818. index = expr();
  819. if( bForceToReturnSuper ) return NULL;
  820. pvar = derefArrayItem( index );
  821. if( pvar == NULL ) return NULL;
  822. while( TRUE ) {
  823. ch = *executionPointer++;
  824. if( ch != ' ' && ch != '\t' ) break;
  825. }
  826. if( ch != ')' && ch != ']' ) {
  827. syntaxError();
  828. return NULL;
  829. }
  830. return pvar;
  831. }
  832. SHORT calcValue()
  833. {
  834. BYTE ch;
  835. while( TRUE ) {
  836. ch = *executionPointer++;
  837. if( ch != ' ' && ch != '\t' ) break;
  838. }
  839. if( ch >= 'A' && ch <= 'Z' ) {
  840. return globalVariables[ch-'A'];
  841. }
  842. if( ch >= 'a' && ch <= 'z' ) {
  843. return localVariables[ch-'a'];
  844. }
  845. if( ch == '@' ) {
  846. SHORT * pvar;
  847. pvar = getArrayReference();
  848. if( pvar == NULL ) return -1;
  849. return *pvar;
  850. }
  851. if( ch >= KEYWORD_AX && ch <= KEYWORD_ES ) {
  852. return registers[ch-KEYWORD_AX];
  853. }
  854. switch( ch ) {
  855. case 0x01: /* 次にあるのは10進2バイト整数 */
  856. case 0x02: /* 次にあるのは16進2バイト整数 */
  857. {
  858. SHORT t;
  859. t = *((SHORT *)executionPointer);
  860. executionPointer += 2;
  861. return t;
  862. }
  863. case '(':
  864. {
  865. SHORT t;
  866. t = expr();
  867. while( TRUE ) {
  868. ch = *executionPointer++;
  869. if( ch != ' ' && ch != '\t' ) break;
  870. }
  871. if( ch != ')' ) {
  872. syntaxError();
  873. return -1;
  874. }
  875. return t;
  876. }
  877. case '-':
  878. return -calcValue();
  879. case KEYWORD_NOT:
  880. return ~calcValue();
  881. case KEYWORD_SCAN:
  882. #ifdef WW
  883. return key_press_check();
  884. #else
  885. return win32_scan();
  886. #endif
  887. case KEYWORD_WAIT:
  888. #ifdef WW
  889. return key_wait();
  890. #else
  891. return win32_wait();
  892. #endif
  893. case KEYWORD_RND:
  894. {
  895. SHORT t;
  896. t = calcValue();
  897. return rand() % t;
  898. }
  899. case KEYWORD_ABS:
  900. {
  901. SHORT t;
  902. t = calcValue();
  903. if( t < 0 ) return -t;
  904. return t;
  905. }
  906. case KEYWORD_TICK:
  907. #ifdef WW
  908. return sys_get_tick_count();
  909. #else
  910. return win32_get_tick_count();
  911. #endif
  912. case KEYWORD_SCAN_A:
  913. return 4;
  914. case KEYWORD_SCAN_B:
  915. return 8;
  916. case KEYWORD_SCAN_X1:
  917. return 16;
  918. case KEYWORD_SCAN_X2:
  919. return 32;
  920. case KEYWORD_SCAN_X3:
  921. return 64;
  922. case KEYWORD_SCAN_X4:
  923. return 128;
  924. case KEYWORD_SCAN_Y1:
  925. return 256;
  926. case KEYWORD_SCAN_Y2:
  927. return 512;
  928. case KEYWORD_SCAN_Y3:
  929. return 1024;
  930. case KEYWORD_SCAN_Y4:
  931. return 2048;
  932. case KEYWORD_HARDARCH:
  933. #ifdef WW
  934. return wwc_get_hardarch();
  935. #else
  936. return 0; /* DUMMY VALUE */
  937. #endif
  938. case KEYWORD_DEFSEG:
  939. return defseg;
  940. case KEYWORD_DSEG:
  941. return getdseg();
  942. case KEYWORD_CSEG:
  943. return getcseg();
  944. case KEYWORD_SSEG:
  945. return getsseg();
  946. case KEYWORD_VARPTR:
  947. case KEYWORD_VARSEG:
  948. {
  949. BOOL requestSeg;
  950. SHORT * refer;
  951. requestSeg = (ch == KEYWORD_VARSEG);
  952. while( TRUE ) {
  953. ch = *executionPointer++;
  954. if( ch != ' ' && ch != '\t' ) break;
  955. }
  956. if( ch != '(' ) {
  957. syntaxError();
  958. return -1;
  959. }
  960. while( TRUE ) {
  961. ch = *executionPointer++;
  962. if( ch != ' ' && ch != '\t' ) break;
  963. }
  964. if( ch == '@' ) { /* is it l-value? */
  965. SHORT * pvar;
  966. pvar = getArrayReference();
  967. if( pvar == NULL ) return -1;
  968. refer = pvar;
  969. } else if( ch >= 'A' && ch <= 'Z' ) {
  970. refer = &globalVariables[ch-'A'];
  971. } else if( ch >= 'a' && ch <= 'z' ) {
  972. refer = &localVariables[ch-'a'];
  973. } else if( ch >= KEYWORD_AX && ch <= KEYWORD_ES ) {
  974. refer = &registers[ch-KEYWORD_AX];
  975. } else if( ch == KEYWORD_DEFSEG ) {
  976. refer = &defseg;
  977. } else {
  978. syntaxError();
  979. return -1;
  980. }
  981. while( TRUE ) {
  982. ch = *executionPointer++;
  983. if( ch != ' ' && ch != '\t' ) break;
  984. }
  985. if( ch != ')' ) {
  986. syntaxError();
  987. return -1;
  988. }
  989. #ifdef WW
  990. if( requestSeg ) {
  991. return getdseg();
  992. } else {
  993. return (SHORT)refer;
  994. }
  995. #else
  996. printf("varseg/varptr: %08x\n", refer );
  997. return 0;
  998. #endif
  999. }
  1000. case KEYWORD_PEEK:
  1001. {
  1002. SHORT t;
  1003. BYTE FAR * fulladdr;
  1004. t = calcValue();
  1005. fulladdr = (BYTE FAR *)(((DWORD)defseg << 16) + (WORD)t);
  1006. #ifdef WW
  1007. return *fulladdr;
  1008. #else
  1009. printf("peek: %08x\n", fulladdr );
  1010. return 0;
  1011. #endif
  1012. }
  1013. }
  1014. syntaxError();
  1015. return -1;
  1016. }
  1017. SHORT expr4th()
  1018. {
  1019. SHORT acc;
  1020. acc = calcValue();
  1021. if( bForceToReturnSuper ) return -1;
  1022. while( TRUE ) {
  1023. BYTE ch;
  1024. while( TRUE ) {
  1025. ch = *executionPointer++;
  1026. if( ch != ' ' && ch != '\t' ) break;
  1027. }
  1028. switch( ch ) {
  1029. case '*':
  1030. acc = acc * calcValue();
  1031. break;
  1032. case '/':
  1033. {
  1034. SHORT t;
  1035. t = calcValue();
  1036. if( t == 0 ) {
  1037. divideByZero();
  1038. } else {
  1039. acc = acc / t;
  1040. }
  1041. }
  1042. break;
  1043. default:
  1044. executionPointer--; /* unget it */
  1045. return acc;
  1046. }
  1047. if( bForceToReturnSuper ) return -1;
  1048. }
  1049. }
  1050. SHORT expr3nd()
  1051. {
  1052. SHORT acc;
  1053. acc = expr4th();
  1054. if( bForceToReturnSuper ) return -1;
  1055. while( TRUE ) {
  1056. BYTE ch;
  1057. while( TRUE ) {
  1058. ch = *executionPointer++;
  1059. if( ch != ' ' && ch != '\t' ) break;
  1060. }
  1061. switch( ch ) {
  1062. case '+':
  1063. acc = acc + expr4th();
  1064. break;
  1065. case '-':
  1066. acc = acc - expr4th();
  1067. break;
  1068. default:
  1069. executionPointer--; /* unget it */
  1070. return acc;
  1071. }
  1072. if( bForceToReturnSuper ) return -1;
  1073. }
  1074. }
  1075. SHORT expr2nd()
  1076. {
  1077. SHORT acc;
  1078. acc = expr3nd();
  1079. if( bForceToReturnSuper ) return -1;
  1080. while( TRUE ) {
  1081. BYTE ch;
  1082. while( TRUE ) {
  1083. ch = *executionPointer++;
  1084. if( ch != ' ' && ch != '\t' ) break;
  1085. }
  1086. switch( ch ) {
  1087. case '>':
  1088. {
  1089. BYTE ch2;
  1090. while( TRUE ) {
  1091. ch2 = *executionPointer++;
  1092. if( ch2 != ' ' && ch2 != '\t' ) break;
  1093. }
  1094. if( ch2 == '=' ) {
  1095. acc = (acc >= expr3nd());
  1096. if( acc != 0 ) acc = -1;
  1097. } else {
  1098. executionPointer--;
  1099. acc = (acc > expr3nd());
  1100. if( acc != 0 ) acc = -1;
  1101. }
  1102. }
  1103. break;
  1104. case '<':
  1105. {
  1106. BYTE ch2;
  1107. while( TRUE ) {
  1108. ch2 = *executionPointer++;
  1109. if( ch2 != ' ' && ch2 != '\t' ) break;
  1110. }
  1111. if( ch2 == '=' ) {
  1112. acc = (acc <= expr3nd());
  1113. if( acc != 0 ) acc = -1;
  1114. } else if( ch2 == '>' ) {
  1115. acc = (acc != expr3nd());
  1116. if( acc != 0 ) acc = -1;
  1117. } else {
  1118. executionPointer--;
  1119. acc = (acc < expr3nd());
  1120. if( acc != 0 ) acc = -1;
  1121. }
  1122. }
  1123. break;
  1124. case '=':
  1125. acc = (acc == expr3nd());
  1126. if( acc != 0 ) acc = -1;
  1127. break;
  1128. default:
  1129. executionPointer--; /* unget it */
  1130. return acc;
  1131. }
  1132. if( bForceToReturnSuper ) return -1;
  1133. }
  1134. }
  1135. SHORT expr()
  1136. {
  1137. SHORT acc;
  1138. acc = expr2nd();
  1139. if( bForceToReturnSuper ) return -1;
  1140. while( TRUE ) {
  1141. BYTE ch;
  1142. while( TRUE ) {
  1143. ch = *executionPointer++;
  1144. if( ch != ' ' && ch != '\t' ) break;
  1145. }
  1146. switch( ch ) {
  1147. case KEYWORD_AND:
  1148. acc = acc & expr2nd();
  1149. break;
  1150. case KEYWORD_OR:
  1151. acc = acc | expr2nd();
  1152. break;
  1153. case KEYWORD_XOR:
  1154. acc = acc ^ expr2nd();
  1155. break;
  1156. default:
  1157. executionPointer--; /* unget it */
  1158. return acc;
  1159. }
  1160. if( bForceToReturnSuper ) return -1;
  1161. }
  1162. }
  1163. /* 各ステートメント実行処理メイン */
  1164. void st_assignment( SHORT * pvar ) /* 代入ステートメントだけ例外的に処理する */
  1165. {
  1166. BYTE ch;
  1167. SHORT val;
  1168. while( TRUE ) {
  1169. ch = *executionPointer++;
  1170. if( ch != ' ' && ch != '\t' ) break;
  1171. }
  1172. if( ch != '=' ) {
  1173. syntaxError();
  1174. return;
  1175. }
  1176. val = expr();
  1177. if( bForceToReturnSuper ) return;
  1178. *pvar = val;
  1179. }
  1180. void printOrDebug( BOOL bPrint )
  1181. {
  1182. WORD lastChar;
  1183. BYTE ch;
  1184. lastChar = '\0';
  1185. while( TRUE ) {
  1186. while( TRUE ) {
  1187. ch = *executionPointer++;
  1188. if( ch != ' ' && ch != '\t' ) break;
  1189. }
  1190. if( ch == EOL || ch == ':' || ch == '\'' ) {
  1191. executionPointer--; /* unget it */
  1192. break;
  1193. }
  1194. lastChar = ch;
  1195. switch( ch ) {
  1196. case 0x03:
  1197. if( bPrint ) {
  1198. ptextString( executionPointer );
  1199. } else {
  1200. commonPrint( NULL, executionPointer );
  1201. }
  1202. while( TRUE ) {
  1203. ch = *executionPointer++;
  1204. if( ch == '\0' ) break;
  1205. }
  1206. break;
  1207. case ';':
  1208. break;
  1209. case ',':
  1210. if( bPrint ) {
  1211. ptextTab();
  1212. } else {
  1213. commonPrint( NULL, "\t" );
  1214. }
  1215. break;
  1216. case KEYWORD_CHR:
  1217. {
  1218. WORD val;
  1219. #ifdef WW
  1220. static
  1221. #endif
  1222. BYTE str[3];
  1223. val = expr();
  1224. if( bForceToReturnSuper ) return;
  1225. if( val >= 0x100 ) {
  1226. str[0] = (val >> 8);
  1227. str[1] = (val & 0xff);
  1228. str[2] = '\0';
  1229. } else {
  1230. str[0] = (BYTE)val;
  1231. str[1] = '\0';
  1232. }
  1233. if( bPrint ) {
  1234. ptextString( str );
  1235. } else {
  1236. commonPrint( NULL, str );
  1237. }
  1238. }
  1239. break;
  1240. default:
  1241. {
  1242. SHORT val;
  1243. #ifdef WW
  1244. static
  1245. #endif
  1246. BYTE str[10];
  1247. executionPointer--; /* unget it */
  1248. val = expr();
  1249. if( bForceToReturnSuper ) return;
  1250. sprintf( str, "%d", val );
  1251. if( bPrint ) {
  1252. ptextString( str );
  1253. } else {
  1254. commonPrint( NULL, str );
  1255. }
  1256. }
  1257. break;
  1258. }
  1259. }
  1260. if( lastChar != ';' && lastChar != ',' ) {
  1261. if( bPrint ) {
  1262. ptextNewline();
  1263. } else {
  1264. commonPrint( NULL, NEWLINE );
  1265. }
  1266. }
  1267. }
  1268. void st_print()
  1269. {
  1270. printOrDebug( TRUE );
  1271. }
  1272. void st_debug()
  1273. {
  1274. printOrDebug( FALSE );
  1275. }
  1276. void st_locate()
  1277. {
  1278. SHORT x, y;
  1279. BYTE ch;
  1280. x = expr();
  1281. if( bForceToReturnSuper ) return;
  1282. while( TRUE ) {
  1283. ch = *executionPointer++;
  1284. if( ch != ' ' && ch != '\t' ) break;
  1285. }
  1286. if( ch != ',' ) {
  1287. syntaxError();
  1288. return;
  1289. }
  1290. y = expr();
  1291. if( bForceToReturnSuper ) return;
  1292. ptextLocate( x, y );
  1293. }
  1294. void st_cls()
  1295. {
  1296. ptextCLS();
  1297. }
  1298. void st_goto()
  1299. {
  1300. SHORT val;
  1301. BYTE * t;
  1302. val = expr();
  1303. if( bForceToReturnSuper ) return;
  1304. t = getLineReferenceFromLineNumber( val );
  1305. if( t == NULL ) {
  1306. lineNumberNotFound( val );
  1307. return;
  1308. }
  1309. executionPointer = t;
  1310. bInteractive = FALSE;
  1311. processLineHeader();
  1312. }
  1313. void st_gosub()
  1314. {
  1315. SHORT val;
  1316. BYTE * t;
  1317. val = expr();
  1318. if( bForceToReturnSuper ) return;
  1319. t = getLineReferenceFromLineNumber( val );
  1320. if( t == NULL ) {
  1321. lineNumberNotFound( val );
  1322. return;
  1323. }
  1324. if( stackPointer+1 >= STACK_MAX ) {
  1325. stackOverflow();
  1326. return;
  1327. }
  1328. stacks[stackPointer].type = STACK_TYPE_GOSUB;
  1329. stacks[stackPointer].returnPointer = executionPointer;
  1330. stacks[stackPointer].lastLocalVariables = localVariables;
  1331. localVariables = stacks[stackPointer].simpleVariables;
  1332. stackPointer++;
  1333. executionPointer = t;
  1334. bInteractive = FALSE;
  1335. processLineHeader();
  1336. }
  1337. void st_return()
  1338. {
  1339. while( TRUE ) {
  1340. if( stackPointer == 0 ) {
  1341. stackUnderflow();
  1342. return;
  1343. }
  1344. stackPointer--;
  1345. if( stacks[stackPointer].type == STACK_TYPE_GOSUB ) break;
  1346. }
  1347. executionPointer = stacks[stackPointer].returnPointer;
  1348. if( executionPointer >= waCookedLine && executionPointer < waCookedLine+LINE_SIZE ) {
  1349. bInteractive = TRUE;
  1350. }
  1351. localVariables = stacks[stackPointer].lastLocalVariables;
  1352. }
  1353. void st_if()
  1354. {
  1355. SHORT val;
  1356. BYTE ch;
  1357. val = expr();
  1358. if( bForceToReturnSuper ) return;
  1359. while( TRUE ) {
  1360. ch = *executionPointer++;
  1361. if( ch != ' ' && ch != '\t' ) break;
  1362. }
  1363. if( ch != KEYWORD_THEN ) {
  1364. syntaxError();
  1365. return;
  1366. }
  1367. if( val != 0 ) {
  1368. while( TRUE ) {
  1369. ch = *executionPointer;
  1370. if( ch != ' ' && ch != '\t' ) break;
  1371. executionPointer++;
  1372. }
  1373. if( ch == 0x01 ) {
  1374. // thenのあとに整数が直接書かれた場合は、それにgotoする。
  1375. st_goto();
  1376. return;
  1377. }
  1378. return; /* thenの次から継続実行する */
  1379. }
  1380. /* 条件不成立につき、行末まで読み飛ばす */
  1381. executionPointer = skipToEOL( executionPointer );
  1382. }
  1383. void st_for()
  1384. {
  1385. BYTE ch;
  1386. SHORT from, to, step;
  1387. SHORT * pvar;
  1388. while( TRUE ) {
  1389. ch = *executionPointer++;
  1390. if( ch != ' ' && ch != '\t' ) break;
  1391. }
  1392. if( ch == '@' ) { /* is it l-value? */
  1393. pvar = getArrayReference();
  1394. if( pvar == NULL ) return;
  1395. } else if( ch >= 'A' && ch <= 'Z' ) {
  1396. pvar = &globalVariables[ch-'A'];
  1397. } else if( ch >= 'a' && ch <= 'z' ) {
  1398. pvar = &localVariables[ch-'a'];
  1399. } else {
  1400. syntaxError();
  1401. return;
  1402. }
  1403. while( TRUE ) {
  1404. ch = *executionPointer++;
  1405. if( ch != ' ' && ch != '\t' ) break;
  1406. }
  1407. if( ch != '=' ) {
  1408. syntaxError();
  1409. return;
  1410. }
  1411. from = expr();
  1412. if( bForceToReturnSuper ) return;
  1413. while( TRUE ) {
  1414. ch = *executionPointer++;
  1415. if( ch != ' ' && ch != '\t' ) break;
  1416. }
  1417. if( ch != KEYWORD_TO ) {
  1418. syntaxError();
  1419. return;
  1420. }
  1421. to = expr();
  1422. if( bForceToReturnSuper ) return;
  1423. while( TRUE ) {
  1424. ch = *executionPointer++;
  1425. if( ch != ' ' && ch != '\t' ) break;
  1426. }
  1427. if( ch == KEYWORD_STEP ) {
  1428. step = expr();
  1429. if( bForceToReturnSuper ) return;
  1430. } else {
  1431. step = 1;
  1432. executionPointer--; /* unget it */
  1433. }
  1434. if( stackPointer+1 >= STACK_MAX ) {
  1435. stackOverflow();
  1436. return;
  1437. }
  1438. stacks[stackPointer].type = STACK_TYPE_FOR;
  1439. stacks[stackPointer].returnPointer = executionPointer;
  1440. *pvar = from;
  1441. stacks[stackPointer].pvar = pvar;
  1442. stacks[stackPointer].limit = to;
  1443. stacks[stackPointer].step = step;
  1444. stackPointer++;
  1445. }
  1446. void st_next()
  1447. {
  1448. if( stackPointer == 0 ) {
  1449. nextWithoutFor();
  1450. return;
  1451. }
  1452. if( stacks[stackPointer-1].type != STACK_TYPE_FOR ) {
  1453. nextWithoutFor();
  1454. return;
  1455. }
  1456. if( stacks[stackPointer-1].limit == *(stacks[stackPointer-1].pvar) ) {
  1457. /* loop done */
  1458. stackPointer--;
  1459. return;
  1460. }
  1461. /* count step and loop again */
  1462. *(stacks[stackPointer-1].pvar) += stacks[stackPointer-1].step;
  1463. /* counter overflow? */
  1464. if( stacks[stackPointer-1].step > 0 ) {
  1465. if( stacks[stackPointer-1].limit < *(stacks[stackPointer-1].pvar) ) {
  1466. /* loop done */
  1467. stackPointer--;
  1468. return;
  1469. }
  1470. } else {
  1471. if( stacks[stackPointer-1].limit > *(stacks[stackPointer-1].pvar) ) {
  1472. /* loop done */
  1473. stackPointer--;
  1474. return;
  1475. }
  1476. }
  1477. executionPointer = stacks[stackPointer-1].returnPointer;
  1478. }
  1479. /* endステートメント: 正常な終了 */
  1480. void st_end()
  1481. {
  1482. bForceToReturnSuper = TRUE;
  1483. requestNextAction = REQUEST_INTERACTIVE;
  1484. }
  1485. /* breakステートメント: デバッグ用の中断 */
  1486. void st_break()
  1487. {
  1488. commonPrint(NULL, "Break in %d\x7" NEWLINE, currentLineNumber);
  1489. bForceToReturnSuper = TRUE;
  1490. requestNextAction = REQUEST_INTERACTIVE;
  1491. resumePointer = executionPointer; /* contする場所はbreakの次。breakのみの例外処理 */
  1492. }
  1493. void st_rem()
  1494. {
  1495. executionPointer = skipToEOL( executionPointer );
  1496. }
  1497. void st_new()
  1498. {
  1499. bForceToReturnSuper = TRUE;
  1500. requestNextAction = REQUEST_NEW;
  1501. }
  1502. void st_list()
  1503. {
  1504. WORD from, to;
  1505. BYTE ch;
  1506. while( TRUE ) {
  1507. ch = *executionPointer++;
  1508. if( ch != ' ' && ch != '\t' ) break;
  1509. }
  1510. if( ch == ':' || ch == EOL || ch == '\'' ) {
  1511. executionPointer--; /* unget */
  1512. from = 1;
  1513. to = 32767;
  1514. } else {
  1515. if( ch == 0x01 ) {
  1516. from = *((WORD*)executionPointer);
  1517. executionPointer += 2;
  1518. while( TRUE ) {
  1519. ch = *executionPointer++;
  1520. if( ch != ' ' && ch != '\t' ) break;
  1521. }
  1522. } else {
  1523. from = 1;
  1524. }
  1525. if( ch != '-' ) {
  1526. executionPointer--; /* unget */
  1527. to = from;
  1528. } else {
  1529. while( TRUE ) {
  1530. ch = *executionPointer++;
  1531. if( ch != ' ' && ch != '\t' ) break;
  1532. }
  1533. if( ch == 0x01 ) {
  1534. to = *((WORD*)executionPointer);
  1535. executionPointer += 2;
  1536. } else {
  1537. executionPointer--; /* unget */
  1538. to = 32767;
  1539. }
  1540. }
  1541. }
  1542. sourceDump( NULL, from, to ); /* リスト出力の本体を呼ぶ */
  1543. }
  1544. void st_run()
  1545. {
  1546. BYTE ch;
  1547. while( TRUE ) {
  1548. ch = *executionPointer++;
  1549. if( ch != ' ' && ch != '\t' ) break;
  1550. }
  1551. if( ch == ':' || ch == EOL || ch == '\'' ) {
  1552. bForceToReturnSuper = TRUE;
  1553. requestNextAction = REQUEST_RUN_LINENUMBER;
  1554. runLineNumber = 0;
  1555. } else if( ch == 0x03 ) {
  1556. strcpy( waRawLine, executionPointer );
  1557. bForceToReturnSuper = TRUE;
  1558. requestNextAction = REQUEST_RUN_FILE;
  1559. } else {
  1560. SHORT val;
  1561. executionPointer--; /* unget it */
  1562. val = expr();
  1563. if( bForceToReturnSuper ) return;
  1564. bForceToReturnSuper = TRUE;
  1565. requestNextAction = REQUEST_RUN_LINENUMBER;
  1566. runLineNumber = val;
  1567. }
  1568. }
  1569. void st_cont()
  1570. {
  1571. if( resumePointer == NULL ) {
  1572. cantContinue();
  1573. return;
  1574. }
  1575. executionPointer = resumePointer;
  1576. bInteractive = FALSE;
  1577. }
  1578. void st_save()
  1579. {
  1580. BYTE ch;
  1581. BOOL b;
  1582. FILE FAR * fp;
  1583. while( TRUE ) {
  1584. ch = *executionPointer++;
  1585. if( ch != ' ' && ch != '\t' ) break;
  1586. }
  1587. if( ch != 0x03 ) {
  1588. syntaxError();
  1589. return;
  1590. }
  1591. fp = fopen( executionPointer, "w" );
  1592. if( fp == NULL ) {
  1593. saveError();
  1594. return;
  1595. }
  1596. b = sourceDump( fp, 1, 32767 );
  1597. fclose( fp );
  1598. if( b == FALSE ) {
  1599. saveError();
  1600. remove( executionPointer );
  1601. return;
  1602. }
  1603. executionPointer += strlen(executionPointer)+1;
  1604. }
  1605. void st_load()
  1606. {
  1607. BYTE ch;
  1608. while( TRUE ) {
  1609. ch = *executionPointer++;
  1610. if( ch != ' ' && ch != '\t' ) break;
  1611. }
  1612. if( ch == 0x03 ) {
  1613. strcpy( waRawLine, executionPointer );
  1614. bForceToReturnSuper = TRUE;
  1615. requestNextAction = REQUEST_LOAD_FILE;
  1616. } else {
  1617. syntaxError();
  1618. return;
  1619. }
  1620. }
  1621. void st_merge()
  1622. {
  1623. BYTE ch;
  1624. while( TRUE ) {
  1625. ch = *executionPointer++;
  1626. if( ch != ' ' && ch != '\t' ) break;
  1627. }
  1628. if( ch == 0x03 ) {
  1629. strcpy( waRawLine, executionPointer );
  1630. bForceToReturnSuper = TRUE;
  1631. requestNextAction = REQUEST_MERGE_FILE;
  1632. } else {
  1633. syntaxError();
  1634. return;
  1635. }
  1636. }
  1637. void st_randomize()
  1638. {
  1639. SHORT val;
  1640. val = expr();
  1641. srand( val );
  1642. }
  1643. void st_exit()
  1644. {
  1645. bForceToReturnSuper = TRUE;
  1646. requestNextAction = REQUEST_EXIT_SYSTEM;
  1647. }
  1648. void st_waitvb()
  1649. {
  1650. SHORT val;
  1651. val = expr();
  1652. if( bForceToReturnSuper ) return;
  1653. if( val < 0 || val > 750 ) {
  1654. paramError();
  1655. return;
  1656. }
  1657. #ifdef WW
  1658. sys_wait( val );
  1659. #endif
  1660. #ifdef WIN32
  1661. win32_sys_wait( val );
  1662. #endif
  1663. }
  1664. void st_files()
  1665. {
  1666. #ifdef WIN32
  1667. commonPrint( NULL, "files statement not implemented in Win32\x7" NEWLINE );
  1668. #endif
  1669. #ifdef WW
  1670. int i;
  1671. struct stat statbuf;
  1672. int nent;
  1673. /*chdir("/rom0");*/
  1674. nent = nument(NULL);
  1675. for (i = 0; i < nent; i++) {
  1676. int result = getent(NULL, i, &statbuf);
  1677. if (result == E_FS_SUCCESS) {
  1678. if (statbuf.count != -1) {
  1679. /* Freya OSのバグ? 回避コード */
  1680. int p, q;
  1681. p = 0;
  1682. q = 0;
  1683. waRawLine[p++] = '"';
  1684. while( TRUE ) {
  1685. if( statbuf.name[q] == '\0' ) break;
  1686. waRawLine[p++] = statbuf.name[q++];
  1687. }
  1688. waRawLine[p++] = '"';
  1689. waRawLine[p++] = ',';
  1690. q = 0;
  1691. while( TRUE ) {
  1692. if( statbuf.info[q] == '\0' ) break;
  1693. waRawLine[p++] = statbuf.info[q++];
  1694. }
  1695. waRawLine[p++] = '\0';
  1696. commonPrint( NULL, "%s,%ld,%d" NEWLINE, waRawLine, statbuf.len, statbuf.count );
  1697. }
  1698. } else {
  1699. commonPrint( NULL, "*File Access Error\x7" NEWLINE );
  1700. }
  1701. }
  1702. #endif
  1703. }
  1704. void st_play()
  1705. {
  1706. BYTE ch;
  1707. ch = *executionPointer++;
  1708. while ( ch == ' ' || ch == '\t' ) {
  1709. ch = *executionPointer++;
  1710. }
  1711. if ( ch != 0x03 ) {
  1712. syntaxError();
  1713. return;
  1714. }
  1715. #ifdef WIN32
  1716. win32_play_mml( executionPointer );
  1717. #endif
  1718. #ifdef WW
  1719. if ( soundAvailable ) {
  1720. parse_mml( _heap, executionPointer, 0 );
  1721. bgm_play( _heap, PLAY_SINGLE );
  1722. }
  1723. #endif
  1724. executionPointer += strlen(executionPointer)+1;
  1725. }
  1726. void st_poke()
  1727. {
  1728. SHORT addr, data;
  1729. BYTE ch;
  1730. BYTE FAR * fulladdr;
  1731. addr = expr();
  1732. if( bForceToReturnSuper ) return;
  1733. while( TRUE ) {
  1734. ch = *executionPointer++;
  1735. if( ch != ' ' && ch != '\t' ) break;
  1736. }
  1737. if( ch != ',' ) {
  1738. syntaxError();
  1739. return;
  1740. }
  1741. data = expr();
  1742. if( bForceToReturnSuper ) return;
  1743. fulladdr = (BYTE FAR *)(((DWORD)defseg << 16) + (WORD)addr);
  1744. #ifdef WW
  1745. *fulladdr = data;
  1746. #else
  1747. printf("poke: %08x %02x\n", fulladdr, data );
  1748. #endif
  1749. }
  1750. void st_call()
  1751. {
  1752. SHORT addr;
  1753. BYTE FAR * fulladdr;
  1754. addr = expr();
  1755. if( bForceToReturnSuper ) return;
  1756. fulladdr = (BYTE FAR *)(((DWORD)defseg << 16) + (WORD)addr);
  1757. #ifdef WW
  1758. #ifdef VC15
  1759. // VC++1.5のときに使うコード
  1760. __asm {
  1761. push si
  1762. push di
  1763. push bp
  1764. mov ax,registers[(KEYWORD_AX-KEYWORD_AX)*2]
  1765. mov bx,registers[(KEYWORD_BX-KEYWORD_AX)*2]
  1766. mov cx,registers[(KEYWORD_CX-KEYWORD_AX)*2]
  1767. mov dx,registers[(KEYWORD_DX-KEYWORD_AX)*2]
  1768. mov si,registers[(KEYWORD_SI-KEYWORD_AX)*2]
  1769. mov di,registers[(KEYWORD_DI-KEYWORD_AX)*2]
  1770. mov es,registers[(KEYWORD_ES-KEYWORD_AX)*2]
  1771. push ds
  1772. mov ds,registers[(KEYWORD_DS-KEYWORD_AX)*2]
  1773. call far ptr ss:[fulladdr]
  1774. pop ds
  1775. mov registers[(KEYWORD_AX-KEYWORD_AX)*2],ax
  1776. mov registers[(KEYWORD_BX-KEYWORD_AX)*2],bx
  1777. mov registers[(KEYWORD_CX-KEYWORD_AX)*2],cx
  1778. mov registers[(KEYWORD_DX-KEYWORD_AX)*2],dx
  1779. mov registers[(KEYWORD_SI-KEYWORD_AX)*2],si
  1780. mov registers[(KEYWORD_DI-KEYWORD_AX)*2],di
  1781. mov registers[(KEYWORD_ES-KEYWORD_AX)*2],es
  1782. pop bp
  1783. pop di
  1784. pop si
  1785. }
  1786. #else
  1787. // VC++ 1.5以外の処理系のためのコードは作っていません。欲しい人、自作しましょう
  1788. #endif
  1789. #else
  1790. printf("call: %08x\n", fulladdr );
  1791. #endif
  1792. }
  1793. void st_int()
  1794. {
  1795. SHORT number;
  1796. number = expr();
  1797. if( bForceToReturnSuper ) return;
  1798. #ifdef WW
  1799. #ifdef VC15
  1800. // VC++1.5のときに使うコード
  1801. {
  1802. static BYTE specialIntCallCode[3] = { 0xcd, 0x00, 0xcb };
  1803. DWORD specialPtr;
  1804. specialIntCallCode[1] = (BYTE)number;
  1805. specialPtr = (((DWORD)getdseg() << 16) + (WORD)specialIntCallCode);
  1806. __asm {
  1807. push si
  1808. push di
  1809. push bp
  1810. mov ax,registers[(KEYWORD_AX-KEYWORD_AX)*2]
  1811. mov bx,registers[(KEYWORD_BX-KEYWORD_AX)*2]
  1812. mov cx,registers[(KEYWORD_CX-KEYWORD_AX)*2]
  1813. mov dx,registers[(KEYWORD_DX-KEYWORD_AX)*2]
  1814. mov si,registers[(KEYWORD_SI-KEYWORD_AX)*2]
  1815. mov di,registers[(KEYWORD_DI-KEYWORD_AX)*2]
  1816. mov es,registers[(KEYWORD_ES-KEYWORD_AX)*2]
  1817. push ds
  1818. mov ds,registers[(KEYWORD_DS-KEYWORD_AX)*2]
  1819. call far ptr ss:[specialPtr]
  1820. pop ds
  1821. mov registers[(KEYWORD_AX-KEYWORD_AX)*2],ax
  1822. mov registers[(KEYWORD_BX-KEYWORD_AX)*2],bx
  1823. mov registers[(KEYWORD_CX-KEYWORD_AX)*2],cx
  1824. mov registers[(KEYWORD_DX-KEYWORD_AX)*2],dx
  1825. mov registers[(KEYWORD_SI-KEYWORD_AX)*2],si
  1826. mov registers[(KEYWORD_DI-KEYWORD_AX)*2],di
  1827. mov registers[(KEYWORD_ES-KEYWORD_AX)*2],es
  1828. pop bp
  1829. pop di
  1830. pop si
  1831. }
  1832. }
  1833. #else
  1834. // VC++ 1.5以外の処理系のためのコードは作っていません。欲しい人、自作しましょう
  1835. #endif
  1836. #else
  1837. printf("int: %04x\n", number );
  1838. #endif
  1839. }
  1840. void st_tron()
  1841. {
  1842. traceFlag = TRUE;
  1843. }
  1844. void st_troff()
  1845. {
  1846. traceFlag = FALSE;
  1847. }
  1848. void st_colormode()
  1849. {
  1850. SHORT newmode;
  1851. newmode = expr();
  1852. if( bForceToReturnSuper ) return;
  1853. #ifdef WW
  1854. if( isWonderSwanColor() ) {
  1855. /*SHORT result;*/
  1856. /*result =*/ wwc_set_color_mode( newmode );
  1857. /*if( result != newmode ) {*/
  1858. /* paramError();*/ /* 値の設定に失敗したとき */
  1859. /* return;*/
  1860. /*}*/
  1861. }
  1862. #else
  1863. printf("colormode: %d\n", newmode );
  1864. #endif
  1865. }
  1866. void st_palette()
  1867. {
  1868. SHORT index, r, g, b;
  1869. BYTE ch;
  1870. index = expr();
  1871. if( bForceToReturnSuper ) return;
  1872. while( TRUE ) {
  1873. ch = *executionPointer++;
  1874. if( ch != ' ' && ch != '\t' ) break;
  1875. }
  1876. if( ch != ',' ) {
  1877. syntaxError();
  1878. return;
  1879. }
  1880. r = expr();
  1881. if( bForceToReturnSuper ) return;
  1882. while( TRUE ) {
  1883. ch = *executionPointer++;
  1884. if( ch != ' ' && ch != '\t' ) break;
  1885. }
  1886. if( ch != ',' ) {
  1887. syntaxError();
  1888. return;
  1889. }
  1890. g = expr();
  1891. if( bForceToReturnSuper ) return;
  1892. while( TRUE ) {
  1893. ch = *executionPointer++;
  1894. if( ch != ' ' && ch != '\t' ) break;
  1895. }
  1896. if( ch != ',' ) {
  1897. syntaxError();
  1898. return;
  1899. }
  1900. b = expr();
  1901. if( bForceToReturnSuper ) return;
  1902. #ifdef WW
  1903. if( isWonderSwanColor() ) {
  1904. wwc_palette_set_color(0, index, ((r << 8)&0xf00) | ((g << 4)&0xf0) | (b&0xf) );
  1905. }
  1906. #else
  1907. printf("palette: %d (%d,%d,%d)\n", index, r, g, b );
  1908. #endif
  1909. }
  1910. void st_color()
  1911. {
  1912. SHORT fore, back;
  1913. BYTE ch;
  1914. fore = expr();
  1915. if( bForceToReturnSuper ) return;
  1916. while( TRUE ) {
  1917. ch = *executionPointer++;
  1918. if( ch != ' ' && ch != '\t' ) break;
  1919. }
  1920. if( ch != ',' ) {
  1921. syntaxError();
  1922. return;
  1923. }
  1924. back = expr();
  1925. if( bForceToReturnSuper ) return;
  1926. #ifdef WW
  1927. font_set_color( (fore & 0x03) | ((back << 2) & 0x0c));
  1928. #else
  1929. printf("color: %d %d\n", fore & 3, back & 3 );
  1930. #endif
  1931. }
  1932. /* 行エディタ */
  1933. void editLine()
  1934. {
  1935. WORD wishLineNumber;
  1936. BYTE ch, * p, * target;
  1937. WORD lineNumber;
  1938. // プログラム領域に行を格納する場合は
  1939. // 先頭に2バイトの行番号と2バイトの行長さの情報が格納される
  1940. // 一方、中間言語翻訳の結果は先頭に0x01で始まる10進整数が行番号として入っている
  1941. // このギャップを転送時に解消しなければならない
  1942. // ここに来ているということは、waCookedLine[0]が0x01つまり10進整数である //
  1943. assert( waCookedLine[0] == 0x01 );
  1944. wishLineNumber = *((WORD*)&waCookedLine[1]);
  1945. /* 行番号 0 はだめ */
  1946. if ( wishLineNumber == 0 ) {
  1947. lineNumberZeroError();
  1948. return;
  1949. }
  1950. p = waCookedLine+3;
  1951. //target = getLineReferenceFromLineNumber( wishLineNumber );
  1952. target = getInsertionPointFromLineNumber( wishLineNumber );
  1953. lineNumber = *((WORD*)target);
  1954. while( TRUE ) {
  1955. ch = *p++;
  1956. if( ch != ' ' && ch != '\t' ) break;
  1957. }
  1958. if( ch == EOL ) {
  1959. BYTE * from;
  1960. /* removing the line */
  1961. if( lineNumber == 0 || lineNumber != wishLineNumber ) {
  1962. lineNumberNotFound( wishLineNumber );
  1963. return;
  1964. }
  1965. from = skipToNextLine(target);
  1966. MEMMOVE( target, from, (WORD)(dataTop-(from-wa)) );
  1967. dataTop -= from-target;
  1968. } else {
  1969. WORD len; // プログラム領域上に収めるときのサイズ
  1970. len = skipToEOL(p)-waCookedLine-1+2+1; //-1は0x01の分。+2は長さ情報。+1はEOL
  1971. if( lineNumber == 0 || lineNumber != wishLineNumber ) {
  1972. /* insert new line */
  1973. if( dataTop + len >= WORKAREA_SIZE ) {
  1974. outOfMemory();
  1975. return;
  1976. }
  1977. MEMMOVE( target+len, target, (WORD)(dataTop-(target-wa)) );
  1978. dataTop += len;
  1979. } else {
  1980. /* replace line */
  1981. WORD lost;
  1982. BYTE * nextline;
  1983. int delta;
  1984. nextline = skipToNextLine(target);
  1985. lost = nextline-target;
  1986. delta = len-lost;
  1987. if( dataTop + delta >= WORKAREA_SIZE ) {
  1988. outOfMemory();
  1989. return;
  1990. }
  1991. MEMMOVE( nextline+delta, nextline, (WORD)(dataTop-(nextline-wa)) );
  1992. dataTop += delta;
  1993. }
  1994. // まず行番号をコピーする
  1995. *((WORD*)target) = *((WORD*)&waCookedLine[1]);
  1996. // 行の長さを収める
  1997. *((WORD*)(target+2)) = len;
  1998. // 残りをコピーする
  1999. MEMMOVE( target+4, waCookedLine+3, (WORD)(len-4) );
  2000. }
  2001. }
  2002. /* 追加専門の行エディタ */
  2003. void appendLine()
  2004. {
  2005. BYTE * target;
  2006. WORD len; // プログラム領域上に収めるときのサイズ
  2007. len = skipToEOL(waCookedLine+3)-waCookedLine-1+2+1; //-1は0x01の分。+2は長さ情報。+1はEOL
  2008. if( dataTop + len >= WORKAREA_SIZE ) {
  2009. outOfMemory();
  2010. return;
  2011. }
  2012. target = &wa[dataTop-5]; // -5 is len of last-line-marker
  2013. // まず行番号をコピーする
  2014. *((WORD*)target) = *((WORD*)&waCookedLine[1]);
  2015. // 行の長さを収める
  2016. *((WORD*)(target+2)) = len;
  2017. // 残りをコピーする
  2018. MEMMOVE( target+4, waCookedLine+3, (WORD)(len-4) );
  2019. dataTop += len;
  2020. wa[dataTop-5] = 0;
  2021. wa[dataTop-4] = 0;
  2022. wa[dataTop-3] = 0;
  2023. wa[dataTop-2] = 0;
  2024. wa[dataTop-1] = EOL;
  2025. }
  2026. /* 中間言語に翻訳する */
  2027. BOOL convertInternalCode( BYTE * waCookedLine, const BYTE * waRawLine )
  2028. {
  2029. const BYTE * src = waRawLine;
  2030. BYTE * dst = waCookedLine;
  2031. while( TRUE ) {
  2032. if( *src == '\0' ) break;
  2033. if( *src == '\n' ) break;
  2034. if( *src == '\r' ) break;
  2035. if( *src == ' ' || *src == '\t' ) {
  2036. *dst++ = *src++;
  2037. } else if( *src < 0x20 ) {
  2038. syntaxError();
  2039. return FALSE;
  2040. } else if( *src >= '0' && *src <= '9' ) {
  2041. if( *src == '0' && *(src+1) == 'x' ) {
  2042. WORD acc;
  2043. /* 16進のとき */
  2044. *dst++ = 0x02;
  2045. acc = 0;
  2046. src += 2;
  2047. while( TRUE ) {
  2048. if( *src >= '0' && *src <= '9' ) {
  2049. acc *= 16;
  2050. acc += *src - '0';
  2051. } else if( *src >= 'a' && *src <= 'f' ) {
  2052. acc *= 16;
  2053. acc += *src - 'a' + 10;
  2054. } else if( *src >= 'A' && *src <= 'F' ) {
  2055. acc *= 16;
  2056. acc += *src - 'A' + 10;
  2057. } else {
  2058. break;
  2059. }
  2060. src++;
  2061. }
  2062. *((WORD*)dst) = acc;
  2063. dst += 2;
  2064. } else {
  2065. SHORT acc;
  2066. /* 10進のとき */
  2067. *dst++ = 0x01;
  2068. acc = *src-'0';
  2069. src++;
  2070. while( TRUE ) {
  2071. if( *src < '0' || *src > '9' ) break;
  2072. acc *= 10;
  2073. acc += *src - '0';
  2074. src++;
  2075. if( acc < 0 ) { /* overflow case */
  2076. syntaxError();
  2077. return FALSE;
  2078. }
  2079. }
  2080. *((SHORT*)dst) = acc;
  2081. dst += 2;
  2082. }
  2083. #if 0
  2084. /* 以下のコードは、2項演算子の-を負数と解釈することがあるので使えない */
  2085. } else if( *src == '-' && (*(src+1) >= '0' && *(src+1) <= '9' ) ) {
  2086. WORD acc;
  2087. /* 負数の10進のとき */
  2088. *dst++ = 0x01;
  2089. src++;
  2090. acc = *src-'0';
  2091. src++;
  2092. while( TRUE ) {
  2093. if( *src < '0' || *src > '9' ) break;
  2094. acc *= 10;
  2095. acc += *src - '0';
  2096. src++;
  2097. if( acc > 32768 ) { /* overflow case */
  2098. syntaxError();
  2099. return FALSE;
  2100. }
  2101. }
  2102. *((SHORT*)dst) = -((SHORT)acc);
  2103. dst += 2;
  2104. #endif
  2105. } else if( (*src >= 'a' && *src <= 'z') || (*src >= 'A' && *src <= 'Z') ) {
  2106. BYTE next = *(src+1);
  2107. if( (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z') ) {
  2108. WORD id;
  2109. KEYWORDITEM * p = keywordsIndex[mytolower(*src)-'a'];
  2110. if( p == NULL ) {
  2111. syntaxError();
  2112. return FALSE;
  2113. }
  2114. id = 0;
  2115. while( TRUE ) {
  2116. const BYTE * ps, * pd;
  2117. if( p->id == 0 ) {
  2118. syntaxError();
  2119. return FALSE;
  2120. }
  2121. ps = src;
  2122. pd = p->name;
  2123. while( TRUE ) {
  2124. if( *pd == '\0' ) {
  2125. id = p->id;
  2126. src = ps;
  2127. break;
  2128. }
  2129. if( mytolower(*ps) != mytolower(*pd) ) break;
  2130. ps++;
  2131. pd++;
  2132. }
  2133. if( id != 0 ) break;
  2134. p++;
  2135. }
  2136. *dst++ = (BYTE)id;
  2137. if( id == KEYWORD_REM ) {
  2138. /* コメント文の場合は行末まで何もかもそのままコピーする */
  2139. while( TRUE ) {
  2140. if( *src == '\0' ) break;
  2141. *dst++ = *src++;
  2142. }
  2143. }
  2144. } else {
  2145. *dst++ = *src++;
  2146. }
  2147. } else if( *src == '\'' ) {
  2148. *dst++ = *src++;
  2149. /* コメント文の場合は行末まで何もかもそのままコピーする */
  2150. while( TRUE ) {
  2151. if( *src == '\0' ) break;
  2152. *dst++ = *src++;
  2153. }
  2154. } else if( *src == '"' ) {
  2155. src++;
  2156. *dst++ = 0x03;
  2157. while( TRUE ) {
  2158. if( *src == '\0' ) {
  2159. syntaxError();
  2160. return FALSE;
  2161. }
  2162. if( *src == '"' ) break;
  2163. *dst++ = *src++;
  2164. }
  2165. *dst++ = '\0';
  2166. src++;
  2167. } else {
  2168. *dst++ = *src++;
  2169. }
  2170. }
  2171. *dst = EOL;
  2172. return TRUE;
  2173. }
  2174. /* ステートメント実行処理関数のリスト */
  2175. NEARPROC statements[KEYWORDS_STATEMENT_TO-KEYWORDS_STATEMENT_FROM+1] = {
  2176. st_if,
  2177. st_print,
  2178. st_locate,
  2179. st_cls,
  2180. st_goto,
  2181. st_gosub,
  2182. st_return,
  2183. st_for,
  2184. st_next,
  2185. st_end,
  2186. st_break,
  2187. st_rem,
  2188. st_new,
  2189. st_list,
  2190. st_run,
  2191. st_cont,
  2192. st_save,
  2193. st_load,
  2194. st_merge,
  2195. st_randomize,
  2196. st_exit,
  2197. st_debug,
  2198. st_waitvb,
  2199. st_files,
  2200. st_play,
  2201. st_poke,
  2202. st_call,
  2203. st_int,
  2204. st_tron,
  2205. st_troff,
  2206. st_colormode,
  2207. st_palette,
  2208. st_color
  2209. };
  2210. void interpreterMain()
  2211. {
  2212. WORD keyscan;
  2213. while( TRUE ) {
  2214. /* 行の開始 */
  2215. processLineHeader();
  2216. /* 最後に達してしまった? */
  2217. if( !bInteractive && currentLineNumber == 0 ) {
  2218. bForceToReturnSuper = TRUE;
  2219. requestNextAction = REQUEST_INTERACTIVE;
  2220. return;
  2221. }
  2222. while( TRUE ) {
  2223. BYTE ch;
  2224. if( !bInteractive ) {
  2225. resumePointer = executionPointer; /* contする場所を記憶する */
  2226. }
  2227. #ifdef WW
  2228. keyscan = key_press_check();
  2229. #else
  2230. keyscan = win32_scan();
  2231. #endif
  2232. if( keyscan & 0x02 ) {
  2233. st_break();
  2234. return;
  2235. }
  2236. ch = *executionPointer++;
  2237. if( ch == EOL ) break;
  2238. if( ch == ' ' || ch == '\t' || ch == ':' ) {
  2239. /* nop */
  2240. } else if( ch == '\'' ) { /* comment */
  2241. st_rem();
  2242. } else if( ch == '@' ) { /* is it l-value? */
  2243. SHORT * pvar;
  2244. pvar = getArrayReference();
  2245. if( pvar == NULL ) return;
  2246. st_assignment( pvar );
  2247. } else if( ch >= 'A' && ch <= 'Z' ) {
  2248. st_assignment( &globalVariables[ch-'A'] );
  2249. } else if( ch >= 'a' && ch <= 'z' ) {
  2250. st_assignment( &localVariables[ch-'a'] );
  2251. } else if( ch >= KEYWORD_AX && ch <= KEYWORD_ES ) {
  2252. st_assignment( &registers[ch-KEYWORD_AX] );
  2253. } else if( ch == KEYWORD_DEFSEG ) {
  2254. st_assignment( &defseg );
  2255. } else if( ch >= KEYWORDS_STATEMENT_FROM && ch <= KEYWORDS_STATEMENT_TO ) {
  2256. (*(statements[ch-KEYWORDS_STATEMENT_FROM]))();
  2257. } else if( ch == '?' ) {
  2258. st_debug();
  2259. } else {
  2260. syntaxError();
  2261. }
  2262. if( bForceToReturnSuper ) return;
  2263. }
  2264. if( bInteractive ) return;
  2265. }
  2266. }
  2267. void interactiveMain( FILE FAR * fp )
  2268. {
  2269. if( fp == NULL ) {
  2270. commonPrint(NULL,"OK" NEWLINE);
  2271. }
  2272. while( TRUE ) {
  2273. BOOL b;
  2274. WORD l;
  2275. if( fp == NULL ) {
  2276. consoleInput( waRawLine, LINE_SIZE );
  2277. } else {
  2278. char FAR * r;
  2279. r = fgets( waRawLine, LINE_SIZE, fp );
  2280. if( r == NULL ) break;
  2281. /* ファイル中に LF があると残ってしまうのを消す */
  2282. l = strlen(waRawLine)-1;
  2283. if ( waRawLine[l] == '\x0a' ){
  2284. waRawLine[l] = '\0';
  2285. }
  2286. }
  2287. #ifdef WW
  2288. if( fp == NULL ) {
  2289. commonPrint( NULL, NEWLINE );
  2290. }
  2291. #endif
  2292. /* 中間言語に翻訳する */
  2293. b = convertInternalCode( waCookedLine, waRawLine );
  2294. if( b == FALSE ) {
  2295. bForceToReturnSuper = FALSE;
  2296. continue;
  2297. }
  2298. /* 数値で開始されているか? */
  2299. if( waCookedLine[0] == 0x01 ) {
  2300. /* 行エディタを呼び出す */
  2301. if( appendMode ) {
  2302. appendLine();
  2303. } else {
  2304. editLine();
  2305. }
  2306. if( fp == NULL ) {
  2307. clearRuntimeInfo();
  2308. }
  2309. } else {
  2310. /* その行を実行する */
  2311. executionPointer = waCookedLine;
  2312. interpreterMain();
  2313. }
  2314. if( bForceToReturnSuper ) return;
  2315. }
  2316. }
  2317. /* プログラムの実行開始 */
  2318. void do_run( WORD runLineNumber )
  2319. {
  2320. BYTE * target;
  2321. if( runLineNumber == 0 ) {
  2322. target = &wa[codeTop];
  2323. } else {
  2324. target = getLineReferenceFromLineNumber( runLineNumber );
  2325. if( target == NULL ) {
  2326. lineNumberNotFound( runLineNumber );
  2327. return;
  2328. }
  2329. }
  2330. clearRuntimeInfo();
  2331. bInteractive = FALSE;
  2332. executionPointer = target;
  2333. }
  2334. void do_new()
  2335. {
  2336. clearRuntimeInfo();
  2337. bInteractive = TRUE;
  2338. traceFlag = FALSE;
  2339. codeTop = 0;
  2340. wa[0] = 0;
  2341. wa[1] = 0;
  2342. wa[2] = 0;
  2343. wa[3] = 0;
  2344. wa[4] = EOL;
  2345. dataTop = 5;
  2346. }
  2347. BOOL do_merge( const BYTE * filename )
  2348. {
  2349. FILE FAR * fp;
  2350. fp = fopen( filename, "r" );
  2351. if( fp == NULL ) {
  2352. loadError();
  2353. return FALSE;
  2354. }
  2355. interactiveMain( fp );
  2356. fclose( fp );
  2357. clearRuntimeInfo();
  2358. if( bForceToReturnSuper ) return FALSE;
  2359. return TRUE;
  2360. }
  2361. void superMain()
  2362. {
  2363. while( TRUE ) {
  2364. BOOL b;
  2365. bForceToReturnSuper = FALSE;
  2366. switch( requestNextAction ) {
  2367. case REQUEST_INTERACTIVE:
  2368. bInteractive = TRUE;
  2369. break;
  2370. case REQUEST_RUN_LINENUMBER:
  2371. do_run( runLineNumber );
  2372. break;
  2373. case REQUEST_RUN_FILE:
  2374. do_new();
  2375. appendMode=TRUE;
  2376. b = do_merge( waRawLine );
  2377. appendMode=FALSE;
  2378. if( b ) {
  2379. do_run( 0 );
  2380. }
  2381. break;
  2382. case REQUEST_LOAD_FILE:
  2383. do_new();
  2384. appendMode=TRUE;
  2385. do_merge( waRawLine );
  2386. appendMode=FALSE;
  2387. break;
  2388. case REQUEST_MERGE_FILE:
  2389. do_merge( waRawLine );
  2390. break;
  2391. case REQUEST_NEW:
  2392. do_new();
  2393. break;
  2394. case REQUEST_EXIT_SYSTEM:
  2395. return;
  2396. }
  2397. requestNextAction = REQUEST_NO_ACTION;
  2398. if( bInteractive ) {
  2399. if( runtimeOnly ) return; /* ランタイムモードのときは絶対にインタラクティブモードに行かない */
  2400. interactiveMain( NULL );
  2401. } else {
  2402. interpreterMain();
  2403. }
  2404. bForceToReturnSuper = FALSE;
  2405. }
  2406. }
  2407. #ifdef WW
  2408. BOOL entranceUI()
  2409. {
  2410. #define MAX_ENT 15
  2411. int i;
  2412. struct stat statbuf[MAX_ENT];
  2413. int nent;
  2414. int c, select;
  2415. ptextCLS();
  2416. ptextString( "ワンべぇ V" );
  2417. ptextString( myVersion );
  2418. ptextNewline();
  2419. ptextString( "↑↓Aでファイル選択 Y2で開発環境 STARTで中止" );
  2420. c = 0;
  2421. nent = nument(NULL);
  2422. for (i = 0; i < nent; i++) {
  2423. int result;
  2424. if( c >= MAX_ENT ) break;
  2425. result = getent(NULL, i, &statbuf[c]);
  2426. if (result == E_FS_SUCCESS) {
  2427. if (statbuf[c].count != -1) {
  2428. char FAR * p;
  2429. int l;
  2430. p = statbuf[c].name;
  2431. l = strlen(p);
  2432. if( l >= 3 ) {
  2433. if( p[l-3] == '.' && p[l-2] == 'w' && p[l-1] == 'b' ) {
  2434. ptextLocate(1,c+2);
  2435. ptextString( statbuf[c].info );
  2436. c++;
  2437. }
  2438. }
  2439. }
  2440. }
  2441. }
  2442. /* 選択の開始 */
  2443. select = 0;
  2444. while( TRUE ) {
  2445. int key;
  2446. for( i=0; i<c; i++ ) {
  2447. ptextLocate(0,i+2);
  2448. ptextString( " " );
  2449. }
  2450. if( c > 0 ) {
  2451. ptextLocate(0,select+2);
  2452. ptextString( "→" );
  2453. }
  2454. key = key_wait();
  2455. /* START button */
  2456. if( key & 0x02 ) return FALSE; /* 中止 */
  2457. /* B button */
  2458. if( key & 0x08 ) return FALSE; /* 中止 */
  2459. if( c > 0 ) {
  2460. /* A button */
  2461. if( key & 0x04 ) {
  2462. strcpy( waRawLine, statbuf[select].name );
  2463. requestNextAction = REQUEST_RUN_FILE;
  2464. runtimeOnly = TRUE;
  2465. return TRUE;
  2466. }
  2467. /* X1 or Y1 */
  2468. if( (key & 0x10) != 0 || (key & 0x100) != 0 ) {
  2469. select = select-1;
  2470. if( select < 0 ) {
  2471. select = c-1;
  2472. }
  2473. }
  2474. /* X3 or Y3 */
  2475. if( (key & 0x40) != 0 || (key & 0x400) != 0 ) {
  2476. select = select+1;
  2477. if( select >= c ) {
  2478. select = 0;
  2479. }
  2480. }
  2481. }
  2482. /* Y2 button */
  2483. if( (key & 0x200) != 0 ) {
  2484. return TRUE;
  2485. }
  2486. }
  2487. }
  2488. #endif
  2489. int main( int argc, char *argv[] )
  2490. {
  2491. #ifdef WW
  2492. BOOL b;
  2493. #endif
  2494. runtimeOnly = FALSE;
  2495. requestNextAction = REQUEST_NO_ACTION;
  2496. #ifdef WIN32
  2497. createText();
  2498. #endif
  2499. #ifdef WW
  2500. #ifdef CURRENT_DIR_IS_RAM0
  2501. // シンボルCURRENT_DIR_IS_RAM0を定義してビルドすると
  2502. // カレントディレクトリは/ram0で走る
  2503. // 定義しなければ/rom0で走る
  2504. chdir("/ram0");
  2505. #endif
  2506. text_screen_init();
  2507. b = entranceUI();
  2508. if( b == FALSE ) return 0;
  2509. if( !runtimeOnly ) {
  2510. comm_set_baudrate(1);
  2511. comm_open();
  2512. }
  2513. /* PLAY statement support */
  2514. soundAvailable = FALSE;
  2515. if (open_sound_il(&soundIL) == E_FS_SUCCESS) {
  2516. soundAvailable = TRUE;
  2517. // sounddrv_init(); いらないならわざわざ呼ばない。
  2518. sound_open();
  2519. }
  2520. #endif
  2521. ptextCLS();
  2522. if( requestNextAction == REQUEST_NO_ACTION ) {
  2523. do_new();
  2524. }
  2525. if( !runtimeOnly ) {
  2526. commonPrint(NULL,"ワンべぇ WonderWitch Tiny BASIC Environment Ver %s" NEWLINE,myVersion);
  2527. commonPrint(NULL,"Authors: Pie Dey Co.,Ltd., Hirotaka JOE Ohkubo" NEWLINE);
  2528. commonPrint(NULL,"This program is distributed under GNU General Public License" NEWLINE);
  2529. }
  2530. superMain();
  2531. #ifdef WIN32
  2532. deleteText();
  2533. #endif
  2534. #ifdef WW
  2535. /* PLAY statement support */
  2536. if (soundAvailable) {
  2537. sound_close();
  2538. sounddrv_release();
  2539. }
  2540. if( !runtimeOnly ) {
  2541. comm_close();
  2542. }
  2543. #endif
  2544. return 0;
  2545. }
  2546. /* end of wonbe.c */